| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="课题评定详情" width="70%" @close="handleClose"> |
| | | <el-form :model="form" inline label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> |
| | | <el-form-item label="报告编号" prop="reportNo" required> |
| | | <el-input v-model="form.reportNo" disabled placeholder="自动生成" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> |
| | | <el-form-item label="报告名称" prop="reportName"> |
| | | <el-input v-model="form.reportName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="content-box"> |
| | | <el-row :gutter="16"> |
| | | <el-col style="margin-top: 5px;" :xs="24" :sm="24" :md="24" :lg="24" :xl="24"> |
| | | <Table :total="0" :height="null" :data="criteriaList" show-summary :summary-method="getSummaries" |
| | | :span-method="arraySpanMethod"> |
| | | <el-table-column type="index" label="序号" width="80" /> |
| | | <el-table-column prop="criteria" label="规程型课题评定标准" /> |
| | | <el-table-column prop="fullScore" label="满分值" width="100" /> |
| | | <el-table-column label="评定分值" prop="score" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-input-number v-model="row.score" :min="0" :max="row.fullScore" :step="1" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、规程型课题评定总分的满分为5分。</div> |
| | | <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <span class="select-member-footer"> |
| | | <el-button type="primary">提交评定结果</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <el-dialog |
| | | :visible.sync="dialogVisible" |
| | | :title="type === 'detail' ? '课题评定详情' : '课题评定'" |
| | | width="70%" |
| | | @close="handleClose" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | inline |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> |
| | | <el-form-item label="报告编号" prop="reportNo" required> |
| | | <el-input v-model="form.reportNo" disabled placeholder="自动生成" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> |
| | | <el-form-item label="报告名称" prop="reportName"> |
| | | <el-input v-model="form.reportName" disabled placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="content-box"> |
| | | <el-row :gutter="16"> |
| | | <el-col |
| | | style="margin-top: 5px" |
| | | :xs="24" |
| | | :sm="24" |
| | | :md="24" |
| | | :lg="24" |
| | | :xl="24" |
| | | > |
| | | <Table |
| | | :total="0" |
| | | :height="null" |
| | | :data="criteriaList" |
| | | show-summary |
| | | :summary-method="getSummaries" |
| | | :span-method="arraySpanMethod" |
| | | > |
| | | <el-table-column type="index" label="序号" width="80" /> |
| | | <el-table-column prop="criteria" label="规程型课题评定标准" /> |
| | | <el-table-column prop="fullScore" label="满分值" width="100" /> |
| | | <el-table-column label="评定分值" prop="score" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-input-number |
| | | v-model="row.score" |
| | | :min="0" |
| | | :max="row.fullScore" |
| | | :step="1" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、规程型课题评定总分的满分为5分。</div> |
| | | <div> |
| | | 2、某分项工作完成,但出现以下三种错误中的1种,则减1分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div> |
| | | 3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="assessed" style="display:flex" v-if="evaluateInfo.status == 3"> |
| | | <div style="margin-right: 20px">评定时间:{{ evaluateInfo.evaluateTime }}</div> |
| | | <div>评定人:{{ evaluateInfo.evaluatePersonName }}</div> |
| | | </div> |
| | | <template #footer v-if="evaluateInfo.status === 2 && type=='approve'"> |
| | | <span class="select-member-footer"> |
| | | <el-button type="primary" @click="handleSubmit">提交评定结果</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDetailById, evaluate } from "../service.js"; |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | name: "AssessmentDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | data() { |
| | | id: { |
| | | type: String, |
| | | // required: true, |
| | | default: () => "", |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: "detail", // 'detail' 或 'evaluate' |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: "", |
| | | reportName: "", |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: "请输入报告名称", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: "文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范", |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: |
| | | "专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: |
| | | "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | ], |
| | | evaluateInfo: {}, |
| | | }; |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | if (val) { |
| | | this.fetchDataById(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | id: { |
| | | handler(val) { |
| | | if (this.dialogVisible && val) { |
| | | this.fetchDataById(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | type: { |
| | | handler(val) { |
| | | // 可根据type切换详情/评定模式 |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | }, |
| | | methods: { |
| | | async fetchDataById() { |
| | | try { |
| | | const res = await getDetailById({id:this.id}); |
| | | const data = res || {}; |
| | | this.form.reportNo = data.reportCode || ""; |
| | | this.form.reportName = data.reportTitle || ""; |
| | | this.evaluateInfo = { ...data }; |
| | | // 评定分数 |
| | | if (data.evaluateScore) { |
| | | const scores = data.evaluateScore.split(",").map(Number); |
| | | this.criteriaList.forEach((item, idx) => { |
| | | item.score = scores[idx] || 0; |
| | | }); |
| | | } else { |
| | | this.criteriaList.forEach((item) => (item.score = 0)); |
| | | } |
| | | } catch (e) { |
| | | // 错误处理 |
| | | } |
| | | }, |
| | | handleClose() { |
| | | this.$emit("close", false); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | await this.$refs.formRef.validate(); |
| | | const totalScore = this.criteriaList.reduce( |
| | | (sum, item) => sum + (item.score || 0), |
| | | 0 |
| | | ); |
| | | const assessmentData = { |
| | | id: this.evaluateInfo.id, |
| | | evaluateScore: this.criteriaList |
| | | .map((item) => item.score || 0) |
| | | .join(","), |
| | | }; |
| | | // 这里可以调用evaluate接口 |
| | | evaluate(assessmentData).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("提交成功"); |
| | | this.handleClose(); |
| | | }else{ |
| | | this.$message.error(res.message) |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "合计"; |
| | | return; |
| | | } |
| | | const values = data.map((item) => Number(item[column.property])); |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => { |
| | | const value = Number(curr); |
| | | if (!isNaN(value)) { |
| | | return prev + curr; |
| | | } else { |
| | | return prev; |
| | | } |
| | | }, 0); |
| | | sums[index] += " 分"; |
| | | } else { |
| | | sums[index] = ""; |
| | | } |
| | | }); |
| | | return sums; |
| | | }, |
| | | arraySpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范', |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;', |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | ] |
| | | } |
| | | rowspan: 6, |
| | | colspan: 1, |
| | | }; |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0]; |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | await this.$refs.formRef.validate(); |
| | | const totalScore = this.criteriaList.reduce((sum, item) => sum + (item.score || 0), 0); |
| | | const assessmentData = { |
| | | ...this.form, |
| | | totalScore, |
| | | criteriaScores: this.criteriaList.map(item => ({ |
| | | criteria: item.criteria, |
| | | score: item.score || 0 |
| | | })) |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | this.handleClose(); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => { |
| | | const value = Number(curr); |
| | | if (!isNaN(value)) { |
| | | return prev + curr; |
| | | } else { |
| | | return prev; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | } else { |
| | | sums[index] = ''; |
| | | } |
| | | }); |
| | | return sums; |
| | | }, |
| | | arraySpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #FAFAFA !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &-body { |
| | | padding: 0 10px; |
| | | line-height: 23px; |
| | | } |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #fafafa !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &-body { |
| | | padding: 0 10px; |
| | | line-height: 23px; |
| | | } |
| | | } |
| | | } |
| | | </style> |