From 84748363b911c35b9b3a66159cfeeeefd13cc917 Mon Sep 17 00:00:00 2001 From: 马宇豪 <978517621@qq.com> Date: 星期一, 09 十二月 2024 13:12:37 +0800 Subject: [PATCH] 修改导出内容 --- src/views/system/user/index.vue | 4 src/views/safetyReview/expertManage/postEvaluation/components/evaluate.vue | 140 +++++++++++++++++++--- src/views/safetyReview/expertManage/experts/index.vue | 17 +- src/views/safetyReview/expertManage/postEvaluation/components/expertList.vue | 1 public/evaluateFile.docx | 0 src/layout/components/Navbar.vue | 153 +++++++++++++++++++++---- src/views/certificatePdf.vue | 35 +++-- src/assets/images/certBg.jpg | 0 8 files changed, 281 insertions(+), 69 deletions(-) diff --git a/public/evaluateFile.docx b/public/evaluateFile.docx index c1e96e0..c372e2e 100644 --- a/public/evaluateFile.docx +++ b/public/evaluateFile.docx Binary files differ diff --git a/src/assets/images/certBg.jpg b/src/assets/images/certBg.jpg index 3847592..c3ea519 100644 --- a/src/assets/images/certBg.jpg +++ b/src/assets/images/certBg.jpg Binary files differ diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index 4c30253..463aa7e 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -1,41 +1,47 @@ <template> <div class="navbar"> - <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> - <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" /> - <top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" /> + <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" + @toggleClick="toggleSideBar"/> + <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav"/> + <top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav"/> <div class="right-menu"> <template v-if="appStore.device !== 'mobile'"> -<!-- <header-search id="header-search" class="right-menu-item" />--> + <!-- <header-search id="header-search" class="right-menu-item" />--> -<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">--> -<!-- <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />--> -<!-- </el-tooltip>--> + <!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">--> + <!-- <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />--> + <!-- </el-tooltip>--> -<!-- <el-tooltip content="文档地址" effect="dark" placement="bottom">--> -<!-- <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />--> -<!-- </el-tooltip>--> + <!-- <el-tooltip content="文档地址" effect="dark" placement="bottom">--> + <!-- <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />--> + <!-- </el-tooltip>--> -<!-- <screenfull id="screenfull" class="right-menu-item hover-effect" />--> + <!-- <screenfull id="screenfull" class="right-menu-item hover-effect" />--> -<!-- <el-tooltip content="布局大小" effect="dark" placement="bottom">--> -<!-- <size-select id="size-select" class="right-menu-item hover-effect" />--> -<!-- </el-tooltip>--> + <!-- <el-tooltip content="布局大小" effect="dark" placement="bottom">--> + <!-- <size-select id="size-select" class="right-menu-item hover-effect" />--> + <!-- </el-tooltip>--> </template> <div class="avatar-container"> <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click"> <div class="avatar-wrapper"> - <img :src="avator" class="user-avatar" /> - <el-icon><caret-bottom /></el-icon> + <img :src="avator" class="user-avatar"/> + <el-icon> + <caret-bottom/> + </el-icon> </div> <template #dropdown> <el-dropdown-menu> -<!-- <router-link to="/user/profile">--> -<!-- <el-dropdown-item>个人中心</el-dropdown-item>--> -<!-- </router-link>--> -<!-- <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">--> -<!-- <span>布局设置</span>--> -<!-- </el-dropdown-item>--> + <!-- <router-link to="/user/profile">--> + <!-- <el-dropdown-item>个人中心</el-dropdown-item>--> + <!-- </router-link>--> + <!-- <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">--> + <!-- <span>布局设置</span>--> + <!-- </el-dropdown-item>--> + <el-dropdown-item command="password"> + <span>修改密码</span> + </el-dropdown-item> <el-dropdown-item command="logout"> <span>退出登录</span> </el-dropdown-item> @@ -43,15 +49,44 @@ </template> </el-dropdown> </div> + <el-dialog + v-model="pwdDialog" + title="修改密码" + width="550px" + :before-close="handleClose" + > + <el-form :model="form" size="default" ref="pwdRef" :rules="formRules" label-width="110px"> + <el-form-item label="原密码" prop="oldPassword"> + <el-input v-model.trim="form.oldPassword" type="password" show-password + placeholder="请输入原密码"></el-input> + </el-form-item> + <el-form-item label="新密码" prop="newPassword"> + <el-input v-model.trim="form.newPassword" type="password" show-password + placeholder="请输入新密码"></el-input> + </el-form-item> + <el-form-item label="重复密码" prop="confirmPassword"> + <el-input v-model.trim="form.confirmPassword" type="password" show-password + placeholder="请再次输入新密码"></el-input> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> </div> </div> </template> <script setup> -import { ElMessageBox } from 'element-plus' +import {ElMessageBox} from 'element-plus' import Breadcrumb from '@/components/Breadcrumb' import TopNav from '@/components/TopNav' import Hamburger from '@/components/Hamburger' +import {reactive, ref} from 'vue' +import {ElMessage} from "element-plus"; import Screenfull from '@/components/Screenfull' import SizeSelect from '@/components/SizeSelect' import HeaderSearch from '@/components/HeaderSearch' @@ -61,11 +96,72 @@ import useUserStore from '@/store/modules/user' import useSettingsStore from '@/store/modules/settings' import avator from '@/assets/images/avator.png' +import {updateUserPwd} from "@/api/system/user"; +let validatePwd = (rule, value, callback) => { + const regex = /^(?=.*[A-Za-z])(?=.*\d).{8,}$/ + if (value === '') { + callback(new Error('请输入密码')) + } else { + if (!regex.test(value)) { + callback(new Error('密码须包含字母、数字,长度不少于8字符')) + } else { + callback() + } + } +} + +const equalToPassword = (rule, value, callback) => { + if (value === '') { + callback(new Error('请再次确认新密码')) + } else if (form.newPassword !== value) { + callback(new Error("两次输入的密码不一致")) + } else { + callback() + } +}; const appStore = useAppStore() const userStore = useUserStore() const settingsStore = useSettingsStore() + +const pwdDialog = ref(false) +const pwdRef = ref() + +const form = reactive({ + newPassword: '', + oldPassword: '', + confirmPassword: '' +}) + +const formRules = reactive({ + oldPassword: [{required: true, validator: validatePwd, trigger: 'blur'}], + newPassword: [{required: true, validator: validatePwd, trigger: 'blur'}], + confirmPassword: [{required: true, validator: equalToPassword, trigger: 'blur'}] +}) + +const onSubmit = async()=>{ + const valid = await pwdRef.value.validate(); + if(valid){ + const res = await updateUserPwd(form.oldPassword,form.newPassword) + if(res.code == 200){ + ElMessage.success('修改密码成功,请重新登录') + pwdDialog.value = false + logout() + }else{ + ElMessage.warning(res.msg) + } + } +} + +const handleClose = ()=>{ + form.value = { + newPassword: '', + oldPassword: '', + confirmPassword: '' + } + pwdDialog.value = false +} function toggleSideBar() { appStore.toggleSideBar() @@ -78,6 +174,9 @@ break; case "logout": logout(); + break; + case "password": + editPsd(); break; default: break; @@ -93,10 +192,16 @@ userStore.logOut().then(() => { location.href = '/index'; }) - }).catch(() => { }); + }).catch(() => { + }); +} + +function editPsd() { + pwdDialog.value = true } const emits = defineEmits(['setLayout']) + function setLayout() { emits('setLayout'); } diff --git a/src/views/certificatePdf.vue b/src/views/certificatePdf.vue index f67bbc8..dff3884 100644 --- a/src/views/certificatePdf.vue +++ b/src/views/certificatePdf.vue @@ -1,15 +1,16 @@ <template> <div class="form-container"> <div class="certContent" @click="getPdf()"> + <div class="certNo">证书编号:新应急({{ info.bigClassifyName }})- {{info.id?.toString().padStart(5, '0')}}</div> <div class="main-content"> - 兹聘任{{info.name}}同志为自治区应急管理厅专家,聘任期为{{info.employmentDateStart?.substring(0,4)}}年{{info.employmentDateStart?.substring(5,7)}}月至{{info.employmentDateEnd?.substring(0,4)}}年{{info.employmentDateEnd?.substring(5,7)}}月。 + 兹聘任{{info.name}}同志为自治区应急管理厅安全生产{{info.domain}}领域{{info.ratingLevel == 1?'一级':info.ratingLevel == 2?'二级':info.ratingLevel == 3?'三级':''}}专家,聘任期为{{info.employmentDateStart?.substring(0,4)}}年{{info.employmentDateStart?.substring(5,7)}}月至{{info.employmentDateEnd?.substring(0,4)}}年{{info.employmentDateEnd?.substring(5,7)}}月。 </div> <div class="main-content"> 特发此证! </div> <div class="footer-content"> - 自治区应急管理厅<br/> - {{info.updateTime?.substring(0,4)}}年{{info.updateTime?.substring(5,7)}}月 + 新疆维吾尔自治区应急管理厅<br/> + {{info.employmentDateStart?.substring(0,4)}}年{{info.employmentDateStart?.substring(5,7)}}月 </div> </div> </div> @@ -27,6 +28,7 @@ const {info} = toRefs(data) onMounted(()=>{ data.info = route.query + console.log(data.info,'info>>>>>>>>') nextTick(()=>{ getPdf() }) @@ -39,10 +41,6 @@ onMounted(()=>{ -}) - -defineExpose({ - getPdf }) </script> @@ -61,29 +59,36 @@ align-items: center; .certContent{ - width: 1920px; - height: 1280px; + width: calc(1920px * 0.8); + height: calc(1280px * 0.8); background: url("@/assets/images/certBg.jpg") no-repeat center; background-size: contain; display: flex; flex-direction: column; align-items: center; - padding: 550px 380px 80px; - color: #9e0500; + padding: 420px 300px 120px; + color: #333; + position: relative; + + .certNo{ + position: absolute; + left: 235px; + top: 130px; + } .main-content{ width: 100%; - font-size: 50px; + font-size: 2.5rem; text-align: left; line-height: 1.8; - text-indent: 100px; + text-indent: 5rem; letter-spacing: 2px; font-family: 'fangzhengKT'; } .footer-content{ - font-size: 36px; - transform: translate(200px,120px); + font-size: 1.8rem; + transform: translate(250px,50px); text-align: center; line-height: 1.8; } diff --git a/src/views/safetyReview/expertManage/experts/index.vue b/src/views/safetyReview/expertManage/experts/index.vue index c3c9aa3..96e2638 100644 --- a/src/views/safetyReview/expertManage/experts/index.vue +++ b/src/views/safetyReview/expertManage/experts/index.vue @@ -86,12 +86,14 @@ </el-table-column> <el-table-column label="聘书有效时间" align="center" prop=""> <template #default="scope"> - {{scope.row.employmentDateStart}}/{{scope.row.employmentDateEnd}} + <span v-if="scope.row.state == 2">{{scope.row.employmentDateStart}}/{{scope.row.employmentDateEnd}}</span> + <span v-else>--</span> </template> </el-table-column> <el-table-column label="专家聘书" align="center" prop="expertCertificate"> <template #default="scope"> - <el-button type="primary" link @click="viewCert(scope.row)">查看</el-button> + <span v-if="scope.row.state == 2"><el-button type="primary" link @click="viewCert(scope.row)">查看</el-button></span> + <span v-else>--</span> </template> </el-table-column> <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> @@ -254,11 +256,12 @@ } const viewCert=(info)=>{ - const routePath = '/certPdf'; - const resolvedRoute = router.resolve(routePath); - const queryString = new URLSearchParams(info).toString(); - const fullPath = `${resolvedRoute.href}?${queryString}`; - window.open(fullPath, '_blank'); + console.log(info,'info') + const routePath = '/certPdf' + const resolvedRoute = router.resolve(routePath) + const queryString = new URLSearchParams(info).toString() + const fullPath = `${resolvedRoute.href}?${queryString}` + window.open(fullPath, '_blank') } const getSupport =(safety,prevention,emergency)=>{ diff --git a/src/views/safetyReview/expertManage/postEvaluation/components/evaluate.vue b/src/views/safetyReview/expertManage/postEvaluation/components/evaluate.vue index 48be4e5..14bfe9f 100644 --- a/src/views/safetyReview/expertManage/postEvaluation/components/evaluate.vue +++ b/src/views/safetyReview/expertManage/postEvaluation/components/evaluate.vue @@ -115,7 +115,7 @@ <el-table-column prop="content" label="扣分项"/> <el-table-column prop="score" label="分值"> <template #default="scope"> - <el-input v-model.trim="scope.row.score" type="number" :readonly="state.disable"></el-input> + <el-input v-model.trim="scope.row.score" type="number" :readonly="state.disable" placeholder="此处须填写负数"></el-input> </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" > @@ -128,7 +128,7 @@ <div style="margin: 25px 0;font-size: 14px"> <el-form-item label="本项目考评总计" prop="score"> - <el-input v-model.trim="state.form.score" type="number" :readonly="state.disable"><template #append>分</template></el-input> + <el-input v-model.trim="totalScore" type="number" readonly=true><template #append>分</template></el-input> </el-form-item> </div> <el-row> @@ -147,18 +147,51 @@ <el-input v-model="state.form.content" type="textarea" :autosize="{ minRows: 2}" :readonly="state.disable"></el-input> </el-form-item> <el-divider></el-divider> - <el-form-item label="计费标准" prop="freightBasis"> - <el-input v-model.trim="state.form.freightBasis" :readonly="state.disable"></el-input> - </el-form-item> <el-row> <el-col :span="12"> - <el-form-item label="计费时长" prop="billingDuration"> - <el-input v-model.trim="state.form.billingDuration" type="number" :readonly="state.disable"><template #append>天</template></el-input> + <el-form-item label="计费标准" prop="freightBasis"> + <el-input v-model.trim="state.form.freightBasis" :readonly="state.disable"><template #append>天/课时</template></el-input> +<!-- <el-select v-model="state.form.freightBasis" placeholder="计费标准" clearable>--> +<!-- <el-option :key="0" label="前三天600/天" :value="600"/>--> +<!-- <el-option :key="1" label="前三天800/天" :value="800"/>--> +<!-- <el-option :key="1" label="前三天1000/天" :value="1000"/>--> +<!-- <el-option :key="2" label="前三天1200/天" :value="1200"/>--> +<!-- <el-option :key="2" label="前三天1500/天" :value="1500"/>--> +<!-- </el-select>--> </el-form-item> </el-col> <el-col :span="12"> - <el-form-item label="税后金额" prop="afterTaxAmount"> - <el-input v-model.trim="state.form.afterTaxAmount" type="number" :readonly="state.disable"><template #append>元</template></el-input> + <el-form-item label="标准说明" prop="billingInstructions"> + <el-input v-model.trim="state.form.billingInstructions" type="textarea" :autosize="{ minRows: 2}" :readonly="state.disable" placeholder="请具体说明依据的专家费计算标准"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="计费时长" prop="billingDuration"> + <el-input v-model.number.trim="state.form.billingDuration" type="number" :readonly="state.disable"><template #append>天/课时</template></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="税前金额(专家费)" prop="taxExpertFee"> + <el-input v-model="state.form.taxExpertFee" type="number" :readonly="state.disable"><template #append>元</template></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="8"> + <el-form-item label="应纳税所得额"> + <el-input v-model.trim="taxIncome" type="number" readonly><template #append>元</template></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="应缴个税"> + <el-input v-model.trim="taxPay" type="number" readonly><template #append>元</template></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="税后金额"> + <el-input v-model="afterTaxIncome" type="number" readonly><template #append>元</template></el-input> </el-form-item> </el-col> </el-row> @@ -246,7 +279,11 @@ content: '', freightBasis: '', billingDuration: null, + taxExpertFee: null, + billingInstructions: '', afterTaxAmount: null, + taxableIncome: null, + incomeTaxPayable: null, openBank: '', bankCard: '', }, @@ -262,7 +299,7 @@ generalHazards: [{required: true, message: '请输入一般隐患数', trigger: 'blur'}], freightBasis: [{required: true, message: '请输入计费标准', trigger: 'blur'}], billingDuration: [{required: true, message: '请输入计费时长', trigger: 'blur'}], - afterTaxAmount: [{required: true, message: '请输入税后金额', trigger: 'blur'}], + taxExpertFee: [{required: true, message: '请输入税前金额(专家费)', trigger: 'blur'}], openBank: [{required: true, message: '请输入开户行', trigger: 'blur'}], bankCard: [{required: true, message: '请输入卡号', trigger: 'blur'}] }, @@ -294,7 +331,53 @@ }) const totalScore = computed(()=>{ - return Number(addTotal.value) + Number(deductTotal.value) + return 100 + Number(addTotal.value) + Number(deductTotal.value) +}) + +const expertIncome = computed(()=>{ + if(state.form.freightBasis == null || state.form.billingDuration == null){ + return null + } + if(state.form.billingDuration <= 3){ + return (state.form.freightBasis * state.form.billingDuration) + }else{ + return (state.form.freightBasis * 3) + (state.form.freightBasis * 0.5 * (state.form.billingDuration - 3)) + } +}) + +const taxIncome = computed(()=>{ + const expertIncomeValue = state.form.taxExpertFee + if (expertIncomeValue == null || expertIncomeValue === 0 || expertIncomeValue <= 800) { + return 0 + } + if (expertIncomeValue > 800 && expertIncomeValue <= 4000) { + return expertIncomeValue - 800 + } else { + return expertIncomeValue * 0.8 + } +}) + +const taxPay = computed(()=>{ + const taxIncomeValue = taxIncome.value + if (taxIncomeValue == null || taxIncomeValue === 0) { + return 0 + } + if (taxIncomeValue <= 20000) { + return taxIncomeValue * 0.2; + } else if (taxIncomeValue <= 50000) { + return taxIncomeValue * 0.3 - 2000; + } else { + return taxIncomeValue * 0.4 - 7000; + } +}) + +const afterTaxIncome = computed(()=>{ + const expertIncomeValue = state.form.taxExpertFee + const taxPayValue = taxPay.value + if ((expertIncomeValue == null || expertIncomeValue == 0)|| (taxPayValue == null || taxPayValue == 0)) { + return 0 + } + return expertIncomeValue - taxPayValue; }) const openDialog = async (type, value, projectName, projectCheckTime) => { @@ -362,7 +445,6 @@ } const handleClose = () => { - busRef.value.clearValidate(); state.info = { name: '', idCard: '', @@ -386,10 +468,19 @@ content: '', freightBasis: '', billingDuration: null, + taxExpertFee: null, + billingInstructions: '', afterTaxAmount: null, + taxableIncome: null, + incomeTaxPayable: null, openBank: '', bankCard: '', } + totalScore.value = null + taxIncome.value= null + taxPay.value= null + afterTaxIncome.value= null + busRef.value.clearValidate() state.addData = [] state.deductData = [] dialogVisible.value = false; @@ -417,15 +508,22 @@ } const confirmScore = async ()=>{ - state.form.saveData = [...state.addData,...state.deductData] - state.form.delData = state.form.delData.filter((id) => !state.form.saveData.some((item) => item.id === id)) - const res = await projectExpertDetailSave(state.form) - if(res.code == 200){ - ElMessage.success(res.msg) - await handleClose() - emit('getList') - }else{ - ElMessage.warning(res.msg) + const valid = await evaluateRef.value.validate(); + if(valid){ + state.form.saveData = [...state.addData,...state.deductData] + state.form.delData = state.form.delData.filter((id) => !state.form.saveData.some((item) => item.id === id)) + state.form.score = totalScore.value || 0 + state.form.taxableIncome = taxIncome.value || 0 + state.form.incomeTaxPayable = taxPay.value || 0 + state.form.afterTaxAmount = afterTaxIncome.value || 0 + const res = await projectExpertDetailSave(state.form) + if(res.code == 200){ + ElMessage.success(res.msg) + await handleClose() + emit('getList') + }else{ + ElMessage.warning(res.msg) + } } } diff --git a/src/views/safetyReview/expertManage/postEvaluation/components/expertList.vue b/src/views/safetyReview/expertManage/postEvaluation/components/expertList.vue index dc2eed4..be202fb 100644 --- a/src/views/safetyReview/expertManage/postEvaluation/components/expertList.vue +++ b/src/views/safetyReview/expertManage/postEvaluation/components/expertList.vue @@ -128,6 +128,7 @@ outData.name = val.name outData.sex = val.sex == 0?'男':'女' outData.domain = val.domain + outData.jobCategory = res.data.jobCategory?res.data.jobCategory:'暂无' outData.professionalEthics = state.rateList.find(i=>i.value == res.data.professionalEthics)?.label outData.impartialHonest = state.rateList.find(i=>i.value == res.data.impartialHonest)?.label outData.comprehensiveCoordination = state.rateList.find(i=>i.value == res.data.comprehensiveCoordination)?.label diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 28729ae..594df62 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -494,8 +494,8 @@ confirmButtonText: "确定", cancelButtonText: "取消", closeOnClickModal: false, - inputPattern: /^.{5,20}$/, - inputErrorMessage: "用户密码长度必须介于 5 和 20 之间", + inputPattern: /^(?=.*[A-Za-z])(?=.*\d).{8,}$/, + inputErrorMessage: "用户密码须包含字母和数字且长度不少于8个字符", }).then(({ value }) => { resetUserPwd(row.userId, value).then(response => { proxy.$modal.msgSuccess("修改成功,新密码是:" + value); -- Gitblit v1.9.2