1个文件已删除
10个文件已添加
38个文件已修改
| | |
| | | <template> |
| | | <el-dialog @open="openDialog" class="select-member" :visible.sync="visible" width="53.33%" |
| | | :close-on-click-modal="false" :show-close="false"> |
| | | <el-dialog |
| | | @open="openDialog" |
| | | class="select-member" |
| | | :visible.sync="visible" |
| | | width="53.33%" |
| | | :close-on-click-modal="false" |
| | | :show-close="false" |
| | | > |
| | | <template #title> |
| | | <div>选择实验人员</div> |
| | | <div>{{ roleType==4 ? "选择化验师" : "选择实验人员" }}</div> |
| | | </template> |
| | | <div class="select-member-content"> |
| | | <div class="select-member-content-right"> |
| | | <div class="select-member-content-right-header"> |
| | | <div class="select-member-content-right-header-text">人员列表</div> |
| | | <div class="select-member-content-right-header-search"> |
| | | <el-input clearable v-model="searchKeyword" placeholder="请输入姓名" /> |
| | | <el-input |
| | | clearable |
| | | v-model="searchKeyword" |
| | | placeholder="请输入姓名" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <Table ref="memberTable" :height="null" :row-key="row => row.userId" :data="filteredTableData" |
| | | :total="0" @selection-change="handleSelectionChange" :row-class-name="tableRowClassName"> |
| | | <Table |
| | | ref="memberTable" |
| | | :height="null" |
| | | :row-key="(row) => row.userId" |
| | | :data="filteredTableData" |
| | | :total="0" |
| | | @selection-change="handleSelectionChange" |
| | | :row-class-name="tableRowClassName" |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column label="角色" prop="roleType" > |
| | | <template #default="{ row }"> |
| | | {{ row.roleType === 3 ? '工艺工程师' : row.roleType === 4 ? '化验师' : '实验员' }} |
| | | {{ |
| | | row.roleType === 3 |
| | | ? "工艺工程师" |
| | | : row.roleType === 4 |
| | | ? "化验师" |
| | | : "实验员" |
| | | }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="姓名" prop="nickName" /> |
| | | <el-table-column label="头像" prop="avatar" width="80"> |
| | | <template #default="{ row }"> |
| | | <el-avatar :size="32" :src="row.avatar || require('../../assets/login/img1111.png')" /> |
| | | <el-avatar |
| | | :size="32" |
| | | :src="row.avatar || require('../../assets/login/img1111.png')" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创建时间" prop="signTime" /> |
| | | <el-table-column label="创建时间" prop="createTime" /> |
| | | </Table> |
| | | </div> |
| | | </div> |
| | |
| | | props: { |
| | | memberList: { |
| | | type: Array, |
| | | default: () => [] |
| | | } |
| | | default: () => [], |
| | | }, |
| | | roleType: { |
| | | type: String, |
| | | default: () => "", |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | visible: false, |
| | | searchKeyword: '', |
| | | searchKeyword: "", |
| | | selectData: [], |
| | | defaultSelected: [] // 默认选中的行 |
| | | } |
| | | defaultSelected: [], // 默认选中的行 |
| | | }; |
| | | }, |
| | | computed: { |
| | | filteredTableData() { |
| | |
| | | return this.memberList; |
| | | } |
| | | const keyword = this.searchKeyword.toLowerCase(); |
| | | return this.memberList.filter(item => |
| | | return this.memberList.filter( |
| | | (item) => |
| | | (item.nickName && item.nickName.toLowerCase().includes(keyword)) || |
| | | (item.phone && item.phone.includes(keyword)) |
| | | ); |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | setSelection(selected) { |
| | | this.selectData = selected |
| | | this.selectData = selected; |
| | | this.$nextTick(() => { |
| | | // 设置新选中 |
| | | this.memberList.forEach(row => { |
| | | if (selected.some(i => i.userId === row.userId)) { |
| | | this.$refs.memberTable.toggleRowSelection(row, true) |
| | | this.memberList.forEach((row) => { |
| | | if (selected.some((i) => i.userId === row.userId)) { |
| | | this.$refs.memberTable.toggleRowSelection(row, true); |
| | | } |
| | | }) |
| | | }) |
| | | }); |
| | | }); |
| | | }, |
| | | openDialog() { |
| | | this.setSelection(this.selectData); |
| | | }, |
| | | handleSelectionChange(val) { |
| | | this.selectData = val |
| | | this.selectData = val; |
| | | }, |
| | | open(data = [], defaultSelected = []) { |
| | | this.memberList = data |
| | | this.visible = true |
| | | this.defaultSelected = defaultSelected |
| | | this.memberList = data; |
| | | this.visible = true; |
| | | this.defaultSelected = defaultSelected; |
| | | // 在下一个tick中设置选中状态,确保表格已经渲染完成 |
| | | this.$nextTick(() => { |
| | | this.setDefaultSelection(); |
| | | }); |
| | | }, |
| | | close() { |
| | | this.visible = false |
| | | this.visible = false; |
| | | }, |
| | | submit() { |
| | | this.$emit('submit', this.selectData) |
| | | if (this.roleType) { |
| | | if (this.selectData.length == 1) { |
| | | this.$emit("submit", this.selectData); |
| | | } else { |
| | | this.$message.error( |
| | | `请选择一个${this.roleType == 4 ? "化验师" : "实验员"}!` |
| | | ); |
| | | } |
| | | }else{ |
| | | this.$emit("submit", this.selectData); |
| | | } |
| | | |
| | | }, |
| | | tableRowClassName({ row, rowIndex }) { |
| | | if (this.selectData.findIndex(item => item.userId === row.userId) != -1) { |
| | | return 'select-row'; |
| | | if ( |
| | | this.selectData.findIndex((item) => item.userId === row.userId) != -1 |
| | | ) { |
| | | return "select-row"; |
| | | } |
| | | return ''; |
| | | return ""; |
| | | }, |
| | | setDefaultSelection() { |
| | | if (this.defaultSelected && this.defaultSelected.length > 0) { |
| | | this.defaultSelected.forEach(row => { |
| | | const targetRow = this.memberList.find(item => item.userId === row.userId); |
| | | this.defaultSelected.forEach((row) => { |
| | | const targetRow = this.memberList.find( |
| | | (item) => item.userId === row.userId |
| | | ); |
| | | if (targetRow) { |
| | | this.$refs.memberTable.toggleRowSelection(targetRow, true); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | font-size: 16px; |
| | | line-height: 16px; |
| | | color: #222222; |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | margin-right: 20px; |
| | | } |
| | | |
| | |
| | | component: () => import("../views/deliveryAssessment/restsTask"), |
| | | }, |
| | | { |
| | | // 工艺工程师 审批人 |
| | | path: "processEngineerEvaluate", |
| | | meta: { |
| | | title: "工艺工程师工作评定", |
| | | privilege:'deliveryAssessment_processEngineerEvaluate' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/processEngineerEvaluate"), |
| | | }, |
| | | { |
| | | // 审批人 |
| | | path: "reportEvaluation", |
| | | name: 'ReportEvaluation', |
| | | meta: { |
| | | title: "专业报告库评定", |
| | | keepAlive: true, |
| | | privilege:'deliveryAssessment_reportEvaluation' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/reportEvaluation"), |
| | | }, |
| | | { |
| | | // 超级管理员 工艺工程师 审批人 |
| | | path: "clinicalTrial", |
| | | meta: { |
| | |
| | | privilege:'deliveryAssessment_clinicalTrial' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/clinicalTrial"), |
| | | }, |
| | | { |
| | | // 审批人 |
| | | path: "technicianJobEvaluation", |
| | | name: 'TechnicianJobEvaluation', |
| | | meta: { |
| | | title: "化验师工作评定详情", |
| | | keepAlive: true, |
| | | privilege:'deliveryAssessment_technicianJobEvaluation' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/technicianJobEvaluation"), |
| | | }, |
| | | { |
| | | // 化验师 审批人 工艺工程师 |
| | |
| | | title: "课题评定列表", |
| | | privilege:'deliveryAssessment_assayTaskList' |
| | | }, |
| | | // component: () => import("../views/deliveryAssessment/taskList"), |
| | | component: () => import("../views/deliveryAssessment/assayTaskList"), |
| | | }, |
| | | { |
| | | // 工艺工程师 审批人 |
| | | path: "processEngineerEvaluate", |
| | | meta: { |
| | | title: "工艺工程师工作评定详情", |
| | | privilege:'deliveryAssessment_processEngineerEvaluate' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/processEngineerEvaluate"), |
| | | }, |
| | | |
| | | { |
| | | // 工艺工程师 |
| | | path: "testerWorkerEvaluate", |
| | |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/experimenterJobEvaluation"), |
| | | }, |
| | | { |
| | | // 审批人 |
| | | path: "technicianJobEvaluation", |
| | | name: 'TechnicianJobEvaluation', |
| | | meta: { |
| | | title: "化验师工作评定详情", |
| | | keepAlive: true, |
| | | privilege:'deliveryAssessment_technicianJobEvaluation' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/technicianJobEvaluation"), |
| | | }, |
| | | { |
| | | // 审批人 |
| | | path: "reportEvaluation", |
| | | name: 'ReportEvaluation', |
| | | meta: { |
| | | title: "专业报告库评定", |
| | | keepAlive: true, |
| | | privilege:'deliveryAssessment_reportEvaluation' |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/reportEvaluation"), |
| | | }, |
| | | |
| | | |
| | | ] |
| | | } |
| | | ]; |
| | |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | console.log('1111111111',getFullUrl(this.imgSrc),res.signPicture) |
| | | } |
| | | }) |
| | | }, |
| | |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | // 模拟上传签名图片,实际应调用上传接口,成功后回显图片链接 |
| | | // TODO: 替换为实际上传接口 |
| | | // uploadSignature(imageData).then(url => { this.imgSrc = url }) |
| | | this.imgSrc = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'; // 默认图片链接 |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | |
| | | <template> |
| | | <Card> |
| | | <template style="position: relative"> |
| | | <el-form ref="form" :model="form" :rules="rules" inline label-position="top"> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | > |
| | | <div v-if="!isEdit"> |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div style="display: flex; align-items: center; gap: 13px"> |
| | |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <el-button @click="showScheduling = true" class="el-icon-plus" type="primary"> |
| | | 选择实验调度</el-button> |
| | | <el-button |
| | | @click="showScheduling = true" |
| | | class="el-icon-plus" |
| | | type="primary" |
| | | > |
| | | 选择实验调度</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | <!-- //换到详情弹窗 --> |
| | | <!-- <el-button @click="handleStopExperiment" type="danger"> |
| | | 申请终止实验</el-button> --> |
| | | <Table :data="groupTableData" :total="0" :height="null" class="groupTable"> |
| | | <el-table-column type="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="projectName" label="所属项目课题方案"></el-table-column> |
| | | <el-table-column prop="experimentCode" label="实验编号"></el-table-column> |
| | | <el-table-column prop="experimentName" label="实验名称"></el-table-column> |
| | | <el-table-column prop="experimentDate" label="通知时间"></el-table-column> |
| | | <el-table-column prop="experimentStartTime" label="实验开始时间"></el-table-column> |
| | | <el-table-column prop="experimentEndTime" label="实验结束时间"></el-table-column> |
| | | <el-table-column prop="participantsName" label="参加人员"></el-table-column> |
| | | <Table |
| | | :data="groupTableData" |
| | | :total="0" |
| | | :height="null" |
| | | class="groupTable" |
| | | > |
| | | <el-table-column |
| | | type="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="projectName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentDate" |
| | | label="通知时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentStartTime" |
| | | label="实验开始时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentEndTime" |
| | | label="实验结束时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="participantsName" |
| | | label="参加人员" |
| | | ></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | |
| | | <span>组别列表</span> |
| | | </div> |
| | | |
| | | <Table :data="groupData" :total="0" :height="null" class="groupTable"> |
| | | <el-table-column type="index" label="序号" width="80"></el-table-column> |
| | | <Table |
| | | :data="groupData" |
| | | :total="0" |
| | | :height="null" |
| | | class="groupTable" |
| | | > |
| | | <el-table-column |
| | | type="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column prop="groupName" label="组别"></el-table-column> |
| | | <el-table-column prop="remark" label="备注"></el-table-column> |
| | | </Table> |
| | | </template> |
| | | |
| | | <div style="padding-left: 25px;margin-top: 28px;"> |
| | | <div style="padding-left: 25px; margin-top: 28px"> |
| | | <el-form-item prop="experimentDate" label="试验日期"> |
| | | |
| | | <el-date-picker v-model="form.experimentDate" type="datetime" :disabled="isEdit" placeholder="选择日期时间"> |
| | | <el-date-picker |
| | | v-model="form.experimentDate" |
| | | type="datetime" |
| | | :disabled="isEdit" |
| | | placeholder="选择日期时间" |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </div> |
| | |
| | | </div> |
| | | <div class="content-box"> |
| | | <div class="content-box-left"> |
| | | <div>项目课题方案名称:{{ groupTableData && groupTableData.length > 0 ? groupTableData[0].projectName : '' }}</div> |
| | | <div>实验编号:{{ groupTableData && groupTableData.length > 0 ? groupTableData[0].experimentCode : '' }}</div> |
| | | <div> |
| | | 项目课题方案名称:{{ |
| | | groupTableData && groupTableData.length > 0 |
| | | ? groupTableData[0].projectName |
| | | : "" |
| | | }} |
| | | </div> |
| | | <div> |
| | | 实验编号:{{ |
| | | groupTableData && groupTableData.length > 0 |
| | | ? groupTableData[0].experimentCode |
| | | : "" |
| | | }} |
| | | </div> |
| | | </div> |
| | | <div class="content-box-right"> |
| | | <div>项目课题方案编号: {{ groupTableData && groupTableData.length > 0 ? groupTableData[0].projectCode : '' }}</div> |
| | | <div>实验名称: {{ groupTableData && groupTableData.length > 0 ? groupTableData[0].experimentName : '' }}</div> |
| | | <div> |
| | | 项目课题方案编号: |
| | | {{ |
| | | groupTableData && groupTableData.length > 0 |
| | | ? groupTableData[0].projectCode |
| | | : "" |
| | | }} |
| | | </div> |
| | | <div> |
| | | 实验名称: |
| | | {{ |
| | | groupTableData && groupTableData.length > 0 |
| | | ? groupTableData[0].experimentName |
| | | : "" |
| | | }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="add-group" v-if="!isEdit"> |
| | | <div>*</div> |
| | | <span>参加人员</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="addMember" >选择参加人员</el-button> |
| | | <el-button type="primary" class="el-icon-plus" @click="addMember" |
| | | >选择参加人员</el-button |
| | | > |
| | | </div> |
| | | <div class="add-group" v-else><span>实验人员</span> </div> |
| | | <div class="member-list"> |
| | |
| | | <div class="member-title">实验员</div> |
| | | <div class="flex"> |
| | | <div class="member-name-box-2"> |
| | | <div v-for="i in selectedParticipants" :key="i.id" class="member-name"> |
| | | <div |
| | | v-for="i in selectedParticipants" |
| | | :key="i.id" |
| | | class="member-name" |
| | | > |
| | | {{ i.nickName }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="member-change"> |
| | | <div class="member-change-btn" @click="handleEditMember" v-if="!isEdit">修改</div> |
| | | <div |
| | | class="member-change-btn" |
| | | @click="handleEditMember" |
| | | v-if="!isEdit" |
| | | > |
| | | 修改 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | |
| | | <Table :data="groupData" :total="0" :height="null" class="groupTable"> |
| | | <el-table-column type="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column |
| | | type="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column prop="groupName" label="组别"></el-table-column> |
| | | <el-table-column prop="remark" label="备注"></el-table-column> |
| | | </Table> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="content-box"> |
| | | <AiEditor ref="purposeEditor" :readOnly="isEdit" :value="editorContents.purpose" height="200px" |
| | | placeholder="请输入实验目的..." /> |
| | | <AiEditor |
| | | ref="purposeEditor" |
| | | :readOnly="isEdit" |
| | | :value="editorContents.purpose" |
| | | height="200px" |
| | | placeholder="请输入实验目的..." |
| | | /> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="content-box"> |
| | | <AiEditor ref="processEditor" :readOnly="isEdit" :value="editorContents.process" height="200px" |
| | | placeholder="请输入工艺参数及路线..." /> |
| | | <AiEditor |
| | | ref="processEditor" |
| | | :readOnly="isEdit" |
| | | :value="editorContents.process" |
| | | height="200px" |
| | | placeholder="请输入工艺参数及路线..." |
| | | /> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | |
| | | <div>三、实验材料及设备</div> |
| | | </div> |
| | | </div> |
| | | <DynamicComponent ref="materialComponent" title="实验材料" :participants="participantsData" |
| | | @submit="handleMaterialSubmit" :dataSource="form.experimentMaterial" :editable="!isEdit" /> |
| | | <DynamicComponent ref="equipmentComponent" title="实验所用设备" :participants="participantsData" |
| | | @submit="handleEquipmentSubmit" :dataSource="form.experimentDevice" :editable="!isEdit" /> |
| | | <DynamicComponent |
| | | ref="materialComponent" |
| | | title="实验材料" |
| | | :participants="participantsData" |
| | | @submit="handleMaterialSubmit" |
| | | :dataSource="form.experimentMaterial" |
| | | :editable="!isEdit" |
| | | /> |
| | | <DynamicComponent |
| | | ref="equipmentComponent" |
| | | title="实验所用设备" |
| | | :participants="participantsData" |
| | | @submit="handleEquipmentSubmit" |
| | | :dataSource="form.experimentDevice" |
| | | :editable="!isEdit" |
| | | /> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>四、实验操作步骤记录</div> |
| | | </div> |
| | | <el-button @click="handleAddStep" class="el-icon-plus" type="primary" v-if="!isEdit"> |
| | | 添加步骤</el-button> |
| | | <el-button |
| | | @click="handleAddStep" |
| | | class="el-icon-plus" |
| | | type="primary" |
| | | v-if="!isEdit" |
| | | > |
| | | 添加步骤</el-button |
| | | > |
| | | </div> |
| | | |
| | | <div class="step-list" v-for="(item, idx) in stepList" :key="idx"> |
| | |
| | | 步骤{{ idx + 1 }}:{{ item.stepName }} |
| | | </div> |
| | | <div class="step-list-item-control"> |
| | | <div class="controlBtn edit" @click="handleEditStep(idx)" v-if="!isEdit"> |
| | | <img src="@/assets/public/edit.png" alt="编辑" class="edit-icon" /> |
| | | <div |
| | | class="controlBtn edit" |
| | | @click="handleEditStep(idx)" |
| | | v-if="!isEdit" |
| | | > |
| | | <img |
| | | src="@/assets/public/edit.png" |
| | | alt="编辑" |
| | | class="edit-icon" |
| | | /> |
| | | 编辑 |
| | | </div> |
| | | <div class="controlBtn delete" @click="handleDeleteStep(idx)" v-if="!isEdit"> |
| | | <img src="@/assets/public/delete.png" alt="删除" class="delete-icon" /> |
| | | <div |
| | | class="controlBtn delete" |
| | | @click="handleDeleteStep(idx)" |
| | | v-if="!isEdit" |
| | | > |
| | | <img |
| | | src="@/assets/public/delete.png" |
| | | alt="删除" |
| | | class="delete-icon" |
| | | /> |
| | | 删除 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <DynamicComponent :participants="participantsData" :ref="'stepContent' + idx" @submit="(content) => handleStepContentSubmit(idx, content)" |
| | | :dataSource="item.content" :editable="!isEdit" /> |
| | | <DynamicComponent |
| | | :participants="participantsData" |
| | | :ref="'stepContent' + idx" |
| | | @submit="(content) => handleStepContentSubmit(idx, content)" |
| | | :dataSource="item.content" |
| | | :editable="!isEdit" |
| | | /> |
| | | </div> |
| | | |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn" @click="handleSave">{{userRole == 3 ? '发送' : '提交'}}</el-button> |
| | | <el-button @click="handleSaveDraft" v-if="userRole == 3">存草稿</el-button> |
| | | <el-button type="primary" class="save-btn" @click="handleSave">{{ |
| | | userRole == 3 ? "发送" : "提交" |
| | | }}</el-button> |
| | | <el-button @click="handleSaveDraft" v-if="userRole == 3" |
| | | >存草稿</el-button |
| | | > |
| | | </div> |
| | | </el-form> |
| | | </template> |
| | | <SelectMemberSimple ref="selectMember" @submit="handleMemberSubmit" /> |
| | | <experimentalScheduling :show="showScheduling" @submit="handleSchedulingSubmit" @close="handleSchedulingClose" /> |
| | | <experimentalScheduling |
| | | :show="showScheduling" |
| | | @submit="handleSchedulingSubmit" |
| | | @close="handleSchedulingClose" |
| | | /> |
| | | <AddStep ref="addStepDialog" @submit="handleStepSubmit" /> |
| | | </Card> |
| | | </template> |
| | |
| | | import DynamicComponent from "@/components/DynamicComponent"; |
| | | import AddStep from "./components/add-step.vue"; |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getGroupByDispatchId, getParticipantsByDispatchId, getDetail } from "./service"; |
| | | import moment from 'moment'; |
| | | import { |
| | | getGroupByDispatchId, |
| | | getParticipantsByDispatchId, |
| | | getDetail, |
| | | } from "./service"; |
| | | import moment from "moment"; |
| | | import { add,update,updateTester } from "./service"; |
| | | |
| | | export default { |
| | |
| | | return { |
| | | showScheduling: false, |
| | | form: { |
| | | experimentDate: '', // 实验日期 |
| | | experimentDate: "", // 实验日期 |
| | | experimentMaterial: null, |
| | | experimentDevice: null, |
| | | experimentObjective: '', // 实验目的 |
| | | experimentParamRoute: '', // 工艺参数及路线 |
| | | experimentObjective: "", // 实验目的 |
| | | experimentParamRoute: "", // 工艺参数及路线 |
| | | experimentStepRecord: [], // 实验步骤记录 |
| | | experimentSchemePersons: [], // 实验方案人员 |
| | | dispatchId: '', // 实验调度id |
| | | dispatchId: "", // 实验调度id |
| | | status: -1, // 状态:-1=草稿箱 1=已发送 |
| | | commitTime: '', // 提交时间 |
| | | commitTime: "", // 提交时间 |
| | | }, |
| | | editorContents: { |
| | | purpose: "", |
| | |
| | | { required: true, message: "请添加实验设备", trigger: "change" }, |
| | | ], |
| | | }, |
| | | userRole:'', |
| | | userRole: "", |
| | | groupTableData: [], |
| | | groupData: [], |
| | | taskTableData: [], |
| | |
| | | // 状态映射表 |
| | | statusTypeMap: { |
| | | "-1": "info", |
| | | "1": "warning", |
| | | "2": "success", |
| | | "3": "info" |
| | | 1: "warning", |
| | | 2: "success", |
| | | 3: "info", |
| | | }, |
| | | statusTextMap: { |
| | | "-1": "草稿箱", |
| | | "1": "待确认", |
| | | "2": "已确认", |
| | | "3": "已封存" |
| | | } |
| | | 1: "待确认", |
| | | 2: "已确认", |
| | | 3: "已封存", |
| | | }, |
| | | }; |
| | | }, |
| | | async created() { |
| | | const userInfo=JSON.parse(sessionStorage.getItem('userInfo') || '{}'); |
| | | this.userRole=userInfo.roleType || ''; |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | this.userRole = userInfo.roleType || ""; |
| | | // 检查是否为编辑模式 |
| | | if (this.$route.query.type === 'edit' && this.$route.query.id) { |
| | | if (this.$route.query.type === "edit" && this.$route.query.id) { |
| | | this.isEdit = this.userRole==3?false:true; |
| | | this.editId = this.$route.query.id; |
| | | await this.loadEditData(); |
| | |
| | | this.$refs.selectMember.close(); |
| | | }, |
| | | handleEditMember() { |
| | | this.$refs.selectMember.open(this.participantsData, this.selectedParticipants); |
| | | this.$refs.selectMember.open( |
| | | this.participantsData, |
| | | this.selectedParticipants |
| | | ); |
| | | }, |
| | | |
| | | // ===== 步骤相关方法 ===== |
| | |
| | | |
| | | // 获取所有步骤内容 |
| | | const stepContentRefs = Object.keys(this.$refs) |
| | | .filter(key => key.startsWith('stepContent')) |
| | | .map(key => this.$refs[key]); |
| | | .filter((key) => key.startsWith("stepContent")) |
| | | .map((key) => this.$refs[key]); |
| | | |
| | | stepContentRefs.forEach((ref) => { |
| | | const editor = Array.isArray(ref) ? ref[0] : ref; |
| | | if (editor && typeof editor.submit === 'function') { |
| | | if (editor && typeof editor.submit === "function") { |
| | | editor.submit(); |
| | | } |
| | | }); |
| | |
| | | const experimentParamRoute = this.$refs.processEditor.getContent(); |
| | | |
| | | // 构建实验步骤记录数据 |
| | | const experimentStepRecord = this.stepList.map(step => ({ |
| | | const experimentStepRecord = this.stepList.map((step) => ({ |
| | | stepName: step.stepName, |
| | | content: step.content |
| | | content: step.content, |
| | | })); |
| | | |
| | | // 构建提交数据 |
| | | const formData = { |
| | | ...this.form, |
| | | experimentDate: moment(this.form.experimentDate).format('YYYY-MM-DD HH:mm:ss'), |
| | | dispatchId: this.groupTableData && this.groupTableData.length > 0 ? this.groupTableData[0]?.id : '', |
| | | experimentDate: moment(this.form.experimentDate).format( |
| | | "YYYY-MM-DD HH:mm:ss" |
| | | ), |
| | | dispatchId: |
| | | this.groupTableData && this.groupTableData.length > 0 |
| | | ? this.groupTableData[0]?.id |
| | | : "", |
| | | experimentObjective, |
| | | experimentParamRoute, |
| | | experimentSchemePersons: this.selectedParticipants.map(person => ({ |
| | | experimentSchemePersons: this.selectedParticipants.map( |
| | | (person) => ({ |
| | | userId: person.userId, |
| | | nickName: person.nickName, |
| | | roleType: person.roleType, |
| | | commitTime: moment().format('YYYY-MM-DD HH:mm:ss'), |
| | | })), |
| | | commitTime: moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | }) |
| | | ), |
| | | status, |
| | | commitTime: moment().format('YYYY-MM-DD HH:mm:ss'), |
| | | commitTime: moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | |
| | | // 统一转换JSON字符串 |
| | | formData.experimentStepRecord = JSON.stringify(experimentStepRecord); |
| | | formData.experimentDevice = JSON.stringify(this.form.experimentDevice); |
| | | formData.experimentMaterial = JSON.stringify(this.form.experimentMaterial); |
| | | formData.experimentDevice = JSON.stringify( |
| | | this.form.experimentDevice |
| | | ); |
| | | formData.experimentMaterial = JSON.stringify( |
| | | this.form.experimentMaterial |
| | | ); |
| | | |
| | | // 编辑模式下添加id参数 |
| | | if (this.editId) { |
| | |
| | | } |
| | | |
| | | // 根据是否为编辑模式调用不同接口 |
| | | const apiCall = this.editId ? update(formData) : this.isEdit? updateTester(formData): add(formData); |
| | | const apiCall = this.editId |
| | | ? update(formData) |
| | | : this.isEdit |
| | | ? updateTester(formData) |
| | | : add(formData); |
| | | |
| | | apiCall.then(res => { |
| | | apiCall |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | this.$message.success(status === 1 ? '保存成功' : '草稿保存成功'); |
| | | this.$message.success( |
| | | status === 1 ? "保存成功" : "草稿保存成功" |
| | | ); |
| | | this.$router.go(-1); |
| | | } else { |
| | | this.$message.error(res.msg || (status === 1 ? '保存失败' : '草稿保存失败')); |
| | | this.$message.error( |
| | | res.msg || (status === 1 ? "保存失败" : "草稿保存失败") |
| | | ); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error(status === 1 ? '保存失败' : '草稿保存失败'); |
| | | console.error(status === 1 ? '保存失败:' : '草稿保存失败:', err); |
| | | }) |
| | | .catch((err) => { |
| | | this.$message.error(status === 1 ? "保存失败" : "草稿保存失败"); |
| | | console.error(status === 1 ? "保存失败:" : "草稿保存失败:", err); |
| | | }); |
| | | } else { |
| | | // 获取第一个错误字段并滚动到该位置 |
| | | const firstError = this.$refs.form.fields.find(field => field.validateState === 'error'); |
| | | const firstError = this.$refs.form.fields.find( |
| | | (field) => field.validateState === "error" |
| | | ); |
| | | if (firstError) { |
| | | this.$nextTick(() => { |
| | | firstError.$el.scrollIntoView({ behavior: 'smooth', block: 'center' }); |
| | | firstError.$el.scrollIntoView({ |
| | | behavior: "smooth", |
| | | block: "center", |
| | | }); |
| | | }); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | // 校验参与人员 |
| | | if (!this.selectedParticipants || this.selectedParticipants.length === 0) { |
| | | if ( |
| | | !this.selectedParticipants || |
| | | this.selectedParticipants.length === 0 |
| | | ) { |
| | | this.$message.error("请选择参与人员"); |
| | | return false; |
| | | } |
| | | |
| | | // 校验实验目的 |
| | | const purpose = this.$refs.purposeEditor.getContent(); |
| | | if (!purpose || purpose === '<p></p>' || purpose.trim() === '<p></p>') { |
| | | if (!purpose || purpose === "<p></p>" || purpose.trim() === "<p></p>") { |
| | | this.$message.error("请填写实验目的"); |
| | | return false; |
| | | } |
| | | |
| | | // 校验工艺参数及路线 |
| | | const process = this.$refs.processEditor.getContent(); |
| | | if (!process || process === '<p></p>' || process.trim() === '<p></p>') { |
| | | if (!process || process === "<p></p>" || process.trim() === "<p></p>") { |
| | | this.$message.error("请填写工艺参数及路线"); |
| | | return false; |
| | | } |
| | |
| | | } |
| | | |
| | | // 校验每个步骤是否都有内容 |
| | | const invalidStep = this.stepList.findIndex(step => !step.content); |
| | | const invalidStep = this.stepList.findIndex((step) => !step.content); |
| | | if (invalidStep !== -1) { |
| | | this.$message.error(`请完善第${invalidStep + 1}个步骤的内容`); |
| | | return false; |
| | |
| | | handleSchedulingSubmit(data) { |
| | | this.groupTableData = data || []; |
| | | if (data && data.length > 0 && data[0].id) { |
| | | getGroupByDispatchId({ dispatchId: data[0].id }).then(res => { |
| | | getGroupByDispatchId({ dispatchId: data[0].id }) |
| | | .then((res) => { |
| | | if (res) { |
| | | this.groupData = res || []; |
| | | } else { |
| | | this.$message.error(res.msg || '获取组别列表失败'); |
| | | this.$message.error(res.msg || "获取组别列表失败"); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('获取组别列表失败'); |
| | | console.error('获取组别列表失败:', err); |
| | | }) |
| | | .catch((err) => { |
| | | this.$message.error("获取组别列表失败"); |
| | | console.error("获取组别列表失败:", err); |
| | | }); |
| | | getParticipantsByDispatchId({ dispatchId: data[0].id }).then(res => { |
| | | getParticipantsByDispatchId({ dispatchId: data[0].id }) |
| | | .then((res) => { |
| | | console.log("获取参加人员列表:", res); |
| | | if (res) { |
| | | this.participantsData = res || []; |
| | | } else { |
| | | this.$message.error(res.msg || '获取参加人员列表失败'); |
| | | this.$message.error(res.msg || "获取参加人员列表失败"); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('获取参加人员列表失败'); |
| | | console.error('获取参加人员列表失败:', err); |
| | | }) |
| | | .catch((err) => { |
| | | this.$message.error("获取参加人员列表失败"); |
| | | console.error("获取参加人员列表失败:", err); |
| | | }); |
| | | } |
| | | }, |
| | |
| | | try { |
| | | const res = await getDetail({ id: this.editId }); |
| | | if (!res) { |
| | | this.$message.error('获取详情失败'); |
| | | this.$message.error("获取详情失败"); |
| | | return; |
| | | } |
| | | |
| | | console.log('编辑数据', res); |
| | | console.log("编辑数据", res); |
| | | const data = res; |
| | | |
| | | // 填充基本表单数据 |
| | |
| | | // 填充实验调度信息 |
| | | if (data.experimentDispatch?.id) { |
| | | this.form.dispatchId = data.experimentDispatch.id; |
| | | console.log('experimentStepRecord experimentStepRecord',JSON.parse(data.experimentStepRecord)) |
| | | console.log( |
| | | "experimentStepRecord experimentStepRecord", |
| | | JSON.parse(data.experimentStepRecord) |
| | | ); |
| | | this.groupTableData = [{ ...data.experimentDispatch }]; |
| | | |
| | | // 获取组别信息 |
| | | try { |
| | | const groupRes = await getGroupByDispatchId({ dispatchId: data.experimentDispatch.id }); |
| | | const groupRes = await getGroupByDispatchId({ |
| | | dispatchId: data.experimentDispatch.id, |
| | | }); |
| | | this.groupData = groupRes || []; |
| | | } catch (err) { |
| | | console.error('获取组别列表失败:', err); |
| | | console.error("获取组别列表失败:", err); |
| | | } |
| | | } |
| | | |
| | | // 填充参与人员 |
| | | this.selectedParticipants = Array.isArray(data.experimentSchemePersons) |
| | | ? data.experimentSchemePersons |
| | | : JSON.parse(data.experimentSchemePersons || '[]'); |
| | | : JSON.parse(data.experimentSchemePersons || "[]"); |
| | | |
| | | // 填充富文本编辑器内容 |
| | | this.editorContents.purpose = data.experimentObjective || ''; |
| | | this.editorContents.process = data.experimentParamRoute || ''; |
| | | this.editorContents.purpose = data.experimentObjective || ""; |
| | | this.editorContents.process = data.experimentParamRoute || ""; |
| | | |
| | | // 填充实验材料和设备 |
| | | try { |
| | | this.form.experimentMaterial = typeof data.experimentMaterial === 'string' |
| | | this.form.experimentMaterial = |
| | | typeof data.experimentMaterial === "string" |
| | | ? JSON.parse(data.experimentMaterial) |
| | | : data.experimentMaterial; |
| | | } catch (err) { |
| | | console.error('解析实验材料数据失败:', err); |
| | | console.error("解析实验材料数据失败:", err); |
| | | this.form.experimentMaterial = []; |
| | | } |
| | | |
| | | try { |
| | | this.form.experimentDevice = typeof data.experimentDevice === 'string' |
| | | this.form.experimentDevice = |
| | | typeof data.experimentDevice === "string" |
| | | ? JSON.parse(data.experimentDevice) |
| | | : data.experimentDevice; |
| | | } catch (err) { |
| | | console.error('解析实验设备数据失败:', err); |
| | | console.error("解析实验设备数据失败:", err); |
| | | this.form.experimentDevice = []; |
| | | } |
| | | |
| | | // 填充实验步骤 |
| | | try { |
| | | const stepsData = typeof data.experimentStepRecord === 'string' |
| | | const stepsData = |
| | | typeof data.experimentStepRecord === "string" |
| | | ? JSON.parse(data.experimentStepRecord) |
| | | : data.experimentStepRecord; |
| | | |
| | | this.stepList = (stepsData || []).map(step => ({ |
| | | this.stepList = (stepsData || []).map((step) => ({ |
| | | stepName: step.stepName, |
| | | content: step.content |
| | | content: step.content, |
| | | })); |
| | | } catch (err) { |
| | | console.error('解析实验步骤数据失败:', err); |
| | | console.error("解析实验步骤数据失败:", err); |
| | | this.stepList = []; |
| | | } |
| | | |
| | |
| | | // }); |
| | | // } |
| | | }); |
| | | |
| | | } catch (error) { |
| | | this.$message.error('获取详情失败'); |
| | | console.error('获取详情失败:', error); |
| | | this.$message.error("获取详情失败"); |
| | | console.error("获取详情失败:", error); |
| | | } |
| | | }, |
| | | // 转换数据格式为ViewDynamicComponent需要的格式 |
| | | convertToViewFormat(data) { |
| | | if (!data || !Array.isArray(data)) return []; |
| | | |
| | | return data.map(item => ({ |
| | | return data.map((item) => ({ |
| | | id: item.id || Math.random().toString(36).substr(2, 9), |
| | | type: item.type, |
| | | data: item.data |
| | | data: item.data, |
| | | })); |
| | | }, |
| | | }, |
| | |
| | | border: 1px solid #dcdfe6; |
| | | |
| | | &:nth-child(1) { |
| | | background: linear-gradient(to bottom, |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(4, 156, 154, 0.2) 0%, |
| | | rgba(5, 242, 194, 0) 70%); |
| | | rgba(5, 242, 194, 0) 70% |
| | | ); |
| | | } |
| | | |
| | | &:nth-child(2) { |
| | | background: linear-gradient(to bottom, |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(5, 160, 193, 0.2) 0%, |
| | | rgba(5, 242, 194, 0) 70%); |
| | | rgba(5, 242, 194, 0) 70% |
| | | ); |
| | | } |
| | | |
| | | &:nth-child(3) { |
| | | background: linear-gradient(to bottom, |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(255, 77, 79, 0.2) 0%, |
| | | rgba(255, 242, 194, 0) 70%); |
| | | rgba(255, 242, 194, 0) 70% |
| | | ); |
| | | } |
| | | |
| | | &:nth-child(4) { |
| | | background: linear-gradient(to bottom, |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(250, 199, 20, 0.21) 0%, |
| | | rgba(255, 242, 194, 0) 70%); |
| | | rgba(255, 242, 194, 0) 70% |
| | | ); |
| | | } |
| | | |
| | | .member-item { |
| | |
| | | </template> |
| | | <template v-else> |
| | | <div class="no-data">暂未评定</div> |
| | | <!-- <div v-if="canEvaluate" class="to-evaluate" >去评价</div> --> |
| | | <div v-if="canEvaluate" class="to-evaluate" @click="handleEvaluate('processEngineer')">去评价</div> |
| | | </template> |
| | | </template> |
| | | </div> |
| | |
| | | <el-button type="primary" class="save-btn" @click="handleSubmit(1)">提交</el-button> |
| | | <el-button @click="handleSubmit(-1)">存草稿</el-button> |
| | | </div> |
| | | <div class="add-project-footer" v-if="isView && form.status == 2"> |
| | | <div class="add-project-footer" v-if="isView && form.status == 2 &&(userRole==1 || userRole==2)"> |
| | | <el-button type="primary" class="save-btn" @click="handleEvaluate('processEngineer')">工艺工程师评定</el-button> |
| | | <!-- <el-button @click="handleSubmit(-1)">存草稿</el-button> --> |
| | | </div> |
| | |
| | | "3": "已封存" |
| | | }, |
| | | currentEvaluationData: null, // 添加当前评价数据 |
| | | userRole:'', |
| | | }; |
| | | }, |
| | | watch: { |
| | |
| | | if (id) { |
| | | this.getDetailData(id); |
| | | } |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo")); |
| | | console.log('userInfo',userInfo) |
| | | this.userRole = userInfo.roleType || ''; |
| | | }, |
| | | methods: { |
| | | handleAddTask() { |
| | |
| | | }, |
| | | // 去评价 |
| | | handleEvaluate(type) { |
| | | if(this.$route.query.type == 'view' || type !='processEngineer'){ |
| | | if(this.$route.query.type == 'view' && type !='processEngineer'){ |
| | | this.$message.warning('当前为查看模式,无法进行评价'); |
| | | return; |
| | | } |
| | |
| | | // 处理评价提交 |
| | | handleEvaluationSubmit(evaluationData) { |
| | | const { activeIndex } = evaluationData; |
| | | |
| | | // 将评分数据转换为后端需要的格式 |
| | | const evaluateData = { |
| | | evaluateType: 1, // 1=工艺工程师 |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="课题评定详情" width="70%" @close="handleClose"> |
| | | <el-form :model="form" inline label-position="top" :rules="rules" ref="formRef"> |
| | | <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-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-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-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" /> |
| | | <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> |
| | | 2、某分项工作完成,但出现以下三种错误中的1种,则减1分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | <div> |
| | | 3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <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">提交评定结果</el-button> |
| | | <el-button type="primary" @click="handleSubmit">提交评定结果</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDetailById, evaluate } from "../service.js"; |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | name: "AssessmentDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | id: { |
| | | type: String, |
| | | // required: true, |
| | | default: () => "", |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: "detail", // 'detail' 或 'evaluate' |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | reportNo: "", |
| | | reportName: "", |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | { required: true, message: "请输入报告名称", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范', |
| | | criteria: "文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范", |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;', |
| | | criteria: |
| | | "专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | criteria: |
| | | "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | ] |
| | | } |
| | | ], |
| | | evaluateInfo: {}, |
| | | }; |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | this.fetchDataById(); |
| | | } |
| | | }, |
| | | immediate: true |
| | | 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('update:modelValue', false); |
| | | 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 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 |
| | | })) |
| | | id: this.evaluateInfo.id, |
| | | evaluateScore: this.criteriaList |
| | | .map((item) => item.score || 0) |
| | | .join(","), |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | // 这里可以调用evaluate接口 |
| | | evaluate(assessmentData).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("提交成功"); |
| | | this.handleClose(); |
| | | }else{ |
| | | this.$message.error(res.message) |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | sums[index] = "合计"; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | 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; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | sums[index] += " 分"; |
| | | } else { |
| | | sums[index] = ''; |
| | | sums[index] = ""; |
| | | } |
| | | }); |
| | | return sums; |
| | |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | colspan: 1, |
| | | }; |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | return [0, 0]; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #FAFAFA !important; |
| | | background: #fafafa !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="queryForm" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="所属项目组:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="项目组名称:"> |
| | | <el-input v-model="form.teamName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="检测项名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="报告名称:"> |
| | | <el-input v-model="form.reportTitle" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="检测项编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="报告编号:"> |
| | | <el-input v-model="form.reportCode" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="报告内容:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="课题类型:"> |
| | | <el-select v-model="form.reportType" placeholder="请选择"> |
| | | <el-option label="中试" :value="1" /> |
| | | <el-option label="辅料" :value="2" /> |
| | | <el-option label="产品报告" :value="3" /> |
| | | <!-- <el-option label="验证与发布" :value="4" /> reportType integer 报告类型 1=中试 2=辅料 3=产品报告--> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="草稿箱" :value="-1" /> |
| | | <el-option label="待审核" :value="1" /> |
| | | <el-option label="待评定" :value="2" /> |
| | | <el-option label="已评定" :value="3" /> |
| | | <el-option label="已驳回" :value="4" /> |
| | | <el-option label="已撤回" :value="5" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="tableTitle"> |
| | | <div class="title active"> |
| | | 化验师QA专题报告列表</div> |
| | | <div class="title active">化验师QA专题报告列表</div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="报告类型" /> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="报告名称" /> |
| | | <el-table-column prop="age" label="报告编号" /> |
| | | <el-table-column prop="age" label="制定人" /> |
| | | <el-table-column prop="age" label="制定日期" /> |
| | | <el-table-column prop="age" label="评定人" /> |
| | | <el-table-column prop="age" label="评定时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <el-table-column prop="reportType" label="报告类型"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | <span v-if="row.reportType == 1">中试</span> |
| | | <span v-else-if="row.reportType == 2">辅料</span> |
| | | <span v-else-if="row.reportType == 3">产品报告</span> |
| | | <span v-else>--</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="teamName" label="所属项目组" /> |
| | | <el-table-column prop="reportTitle" label="报告名称" /> |
| | | <el-table-column prop="reportCode" label="报告编号" /> |
| | | <el-table-column prop="developPerson" label="制定人" /> |
| | | <el-table-column prop="developDate" label="制定日期" /> |
| | | <el-table-column prop="evaluatePersonName" label="评定人" /> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 3" type="info" color="#fff" |
| | | >已评定</el-tag |
| | | > |
| | | <el-tag v-else-if="row.status == 2" type="success">待评定</el-tag> |
| | | <el-tag v-else-if="row.status == 1" type="warning">待审核</el-tag> |
| | | <el-tag v-else-if="row.status == 4" type="danger">已驳回</el-tag> |
| | | <el-tag v-else-if="row.status == 5" type="info">已撤回</el-tag> |
| | | <el-tag v-else type="default">草稿箱</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-button type="text" v-if="row.status == 3" @click="handleDetail(row)">详情</el-button> |
| | | <el-button v-if="row.status == 2" type="text" @click="handleAssessment(row)">评定</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <!-- 工艺工程师 --> |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | <AssessmentDialog |
| | | :modelValue="assessmentVisible" |
| | | :id="currentReport.id" |
| | | :type="currentType" |
| | | @close="closeAssessmentDialog" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | import AssessmentDialog from "./components/AssessmentDialog.vue"; |
| | | import { evaluateList } from "./service.js"; |
| | | |
| | | export default { |
| | | name: 'QAList', |
| | | name: "QAList", |
| | | components: { |
| | | AssessmentDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | form: {}, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | pageNum: 1, |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: true, |
| | | assessmentVisible: false, |
| | | currentType: "", |
| | | currentReport: {}, |
| | | } |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | this.queryForm.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | this.queryForm.pageSize = size; |
| | | this.getList(); |
| | | }, |
| | | getList() { |
| | | |
| | | async getList() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await evaluateList(params); |
| | | if (res && res.data) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } |
| | | }, |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | handleReset() { |
| | | this.form = {}; |
| | | this.queryForm = { pageSize: 10, pageNum: 1 }; |
| | | this.getList(); |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | this.currentReport = row; |
| | | this.currentType = "detail"; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.currentType = "approve"; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | } |
| | | } |
| | | } |
| | | closeAssessmentDialog() { |
| | | this.assessmentVisible = false; |
| | | this.currentReport = {}; |
| | | this.currentType = ""; |
| | | this.getList(); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.getList(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | background: #e8faf6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | font-family: "SF Compact Display Black"; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 60px; |
| | | } |
| | | } |
New file |
| | |
| | | |
| | | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 获取中试、生产验证分析报告;辅料;产品报告管理评定列表 |
| | | export function evaluateList(data) { |
| | | return axios.post('/api/t-qa-produce-report/evaluateList', { ...data }) |
| | | } |
| | | // 获取中试、生产验证分析报告;辅料;产品报告管理评定列表 |
| | | export function evaluateCount(data) { |
| | | return axios.post('/api/t-qa-produce-report/evaluateCount', { ...data }) |
| | | } |
| | | // 查看中试、生产验证分析报告;辅料;产品报告管理详情 |
| | | export function getDetailById(data) { |
| | | return axios.get('/open/t-qa-produce-report/getDetailById', { params:data }) |
| | | } |
| | | export function evaluate(data) { |
| | | return axios.post(`/api/t-qa-produce-report/evaluate`, { ...data }) |
| | | } |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="课题评定详情" width="70%" @close="handleClose"> |
| | | <el-form :model="form" inline label-position="top" :rules="rules" ref="formRef"> |
| | | <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-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-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-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" /> |
| | | <el-input-number |
| | | v-model="row.score" |
| | | :min="0" |
| | | :max="row.fullScore" |
| | | :step="1" |
| | | disabled |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="rule" label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、规程型课题评定总分的满分为5分。</div> |
| | | <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div> |
| | | <div> |
| | | 2、某分项工作完成,但出现以下三种错误中的1种,则减1分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | <div> |
| | | 3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="assessed"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | <div class="assessed" v-if="evaluateInfo.status == 3"> |
| | | <div>评定时间:{{ evaluateInfo.evaluateTime || "" }}</div> |
| | | <div>评定人:{{ evaluateInfo.evaluatePersonName || "" }}</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDetailById, evaluate } from "../service.js"; |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | name: "AssessmentDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | id: { |
| | | type: [String, Number], |
| | | default: "", |
| | | // required: true, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | reportNo: "", |
| | | reportName: "", |
| | | }, |
| | | evaluateInfo: {}, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | { required: true, message: "请输入报告名称", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范', |
| | | criteria: "文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范", |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;', |
| | | criteria: |
| | | "专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | criteria: |
| | | "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。", |
| | | fullScore: 3, |
| | | score: 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 || ''; |
| | | if (val && this.id) { |
| | | this.fetchDetail(); |
| | | } |
| | | }, |
| | | immediate: true |
| | | immediate: true, |
| | | }, |
| | | id(val) { |
| | | if (this.modelValue && val) { |
| | | this.fetchDetail(); |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | async handleSubmit() { |
| | | async fetchDetail() { |
| | | 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) { |
| | | // 表单验证失败 |
| | | const res = await getDetailById({ id: this.id }); |
| | | if (res) { |
| | | this.evaluateInfo = { ...res }; |
| | | this.form.reportNo = res.reportCode || ""; |
| | | this.form.reportName = res.reportName || ""; |
| | | // 详情回显分数 |
| | | if (res.evaluateScore) { |
| | | if ( |
| | | this.type === "detail" && |
| | | typeof res.evaluateScore === "string" |
| | | ) { |
| | | const scoreArr = res.evaluateScore |
| | | .split(",") |
| | | .map((s) => Number(s)); |
| | | this.criteriaList.forEach((item, idx) => { |
| | | item.score = scoreArr[idx] || 0; |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } catch (e) { |
| | | this.$message && this.$message.error("获取详情失败"); |
| | | } |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:modelValue", false); |
| | | this.$emit("close"); |
| | | }, |
| | | |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | sums[index] = "合计"; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | 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; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | sums[index] += " 分"; |
| | | } else { |
| | | sums[index] = ''; |
| | | sums[index] = ""; |
| | | } |
| | | }); |
| | | return sums; |
| | |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | colspan: 1, |
| | | }; |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | return [0, 0]; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #FAFAFA !important; |
| | | background: #fafafa !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="queryForm" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="项目组名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.teamName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="课题类型:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-select v-model="form.reportType" placeholder="请选择"> |
| | | <el-option label="中试" :value="1" /> |
| | | <el-option label="辅料" :value="2" /> |
| | | <el-option label="产品报告" :value="3" /> |
| | | <!-- <el-option label="验证与发布" :value="4" /> reportType integer 报告类型 1=中试 2=辅料 3=产品报告--> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="课题名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="报告名称:"> |
| | | <el-input v-model="form.reportTitle" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="提交人:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.staffNames" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="草稿箱" :value="-1" /> |
| | | <el-option label="待审核" :value="1" /> |
| | | <el-option label="待评定" :value="2" /> |
| | | <el-option label="已评定" :value="3" /> |
| | | <el-option label="已驳回" :value="4" /> |
| | | <el-option label="已撤回" :value="5" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="top-box-integral"> |
| | | <!-- <div class="top-box-integral"> |
| | | <div style="background-color:rgba(232, 250, 246, 1)" v-for="item in 3" :key="item" |
| | | class="top-box-integral-card"> |
| | | <div class="top-box-integral-card-title">{{ ['课题合计数量', '待评定', '已评定'][item - 1] }}</div> |
| | | <div style="color:rgba(4, 156, 154, 1)" class="top-box-integral-card-num">99.9</div> |
| | | </div> |
| | | </div> --> |
| | | <div class="top-box-integral"> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">课题合计数量</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.totalCount || 0 }} |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">待评定</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.toEvaluatedCount || 0 }} |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">已评定</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.evaluatedCount || 0 }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="课题类型" /> |
| | | <el-table-column prop="age" label="报告编号" /> |
| | | <el-table-column prop="age" label="报告名称" /> |
| | | <el-table-column prop="age" label="提交人" /> |
| | | <el-table-column prop="age" label="评定结果" /> |
| | | <el-table-column prop="age" label="累积分值" /> |
| | | <el-table-column prop="age" label="评定时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <el-table-column prop="teamName" label="所属项目组" /> |
| | | <el-table-column prop="reportType" label="课题类型"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | <span v-if="row.reportType == 1">中试</span> |
| | | <span v-else-if="row.reportType == 2">辅料</span> |
| | | <span v-else-if="row.reportType == 3">产品报告</span> |
| | | <span v-else>--</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <el-table-column prop="reportCode" label="报告编号" /> |
| | | <el-table-column prop="reportTitle" label="报告名称" /> |
| | | <el-table-column prop="createBy" label="提交人" /> |
| | | <!-- <el-table-column prop="evaluatePersonName" label="评定人员" /> --> |
| | | <el-table-column prop="evaluateScore" label="评定结果" /> |
| | | <el-table-column prop="totalScore" label="累积分值" /> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-tag v-if="row.status == 3" type="info" color="#fff" |
| | | >已评定</el-tag |
| | | > |
| | | <el-tag v-else-if="row.status == 2" type="success">待评定</el-tag> |
| | | <el-tag v-else-if="row.status == 1" type="warning">待审核</el-tag> |
| | | <el-tag v-else-if="row.status == 4" type="danger">已驳回</el-tag> |
| | | <el-tag v-else-if="row.status == 5" type="info">已撤回</el-tag> |
| | | <el-tag v-else type="default">草稿箱</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleDetail(row)">详情</el-button> |
| | | <!-- <el-button |
| | | type="text" |
| | | @click="handleAssessment(row)" |
| | | v-if="row.status == 2" |
| | | >评定</el-button |
| | | > --> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <!-- 化验师 审批人 --> |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | <AssessmentDialog |
| | | :modelValue="assessmentVisible" |
| | | :id="currentReport.id" |
| | | @close="closeAssessmentDialog" |
| | | /> |
| | | |
| | | <!-- 工艺工程师 --> |
| | | <CraftDialog :modelValue="craftVisible" :reportData="currentReport" /> |
| | | <!-- <CraftDialog :modelValue="craftVisible" :reportData="currentReport" /> --> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | import CraftDialog from './components/CraftDialog.vue' |
| | | import AssessmentDialog from "./components/AssessmentDialog.vue"; |
| | | // import CraftDialog from "./components/CraftDialog.vue"; |
| | | import { evaluateList, evaluateCount } from "./service.js"; |
| | | |
| | | export default { |
| | | name: 'AssayTaskList', |
| | | name: "AssayTaskList", |
| | | components: { |
| | | AssessmentDialog, |
| | | CraftDialog |
| | | // CraftDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | form: {}, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | pageNum: 1, |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {}, |
| | | craftVisible: false, |
| | | } |
| | | statistics: { |
| | | totalCount: 0, |
| | | toEvaluatedCount: 0, |
| | | evaluatedCount: 0, |
| | | }, |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | this.queryForm.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | this.queryForm.pageSize = size; |
| | | this.getList(); |
| | | }, |
| | | getList() { |
| | | |
| | | async getList() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await evaluateList(params); |
| | | if (res && res.data) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } |
| | | }, |
| | | async getStatistics() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await evaluateCount(params); |
| | | if (res && res.data) { |
| | | this.statistics = res.data; |
| | | } |
| | | }, |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | handleReset() { |
| | | this.form = {}; |
| | | this.queryForm = { pageSize: 10, pageNum: 1 }; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | closeAssessmentDialog(){ |
| | | this.assessmentVisible = false; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | background: #e8faf6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | font-family: "SF Compact Display Black"; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | |
| | | export function evaluateList(data) { |
| | | return axios.post('/api/t-qa-produce-report/evaluateList', { ...data }) |
| | | } |
| | | |
| | | // 获取中试、生产验证分析报告;辅料;产品报告管理评定列表 |
| | | export function evaluateCount(data) { |
| | | return axios.post('/api/t-qa-produce-report/evaluateCount', { ...data }) |
| | | } |
| | | // 查看中试、生产验证分析报告;辅料;产品报告管理详情 |
| | | export function getDetailById(data) { |
| | | return axios.post('/open/t-qa-produce-report/getDetailById', { ...data }) |
| | | return axios.get('/open/t-qa-produce-report/getDetailById', { params:data }) |
| | | } |
| | |
| | | <template> |
| | | <Card> |
| | | <template> |
| | | <div class="header-title" style="margin-bottom: 18px;"> |
| | | <div class="header-title" style="margin-bottom: 18px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <el-button class="el-icon-plus" type="primary" @click="showScheduling = true"> 选择实验调度</el-button> |
| | | <el-button |
| | | class="el-icon-plus" |
| | | type="primary" |
| | | v-if="isEdit" |
| | | @click="showScheduling = true" |
| | | > |
| | | 选择实验调度</el-button |
| | | > |
| | | </div> |
| | | <Table :tableData="tableData" :total="total" :height="null"> |
| | | <Table :data="tableData" :total="0" :height="null"> |
| | | <template> |
| | | <el-table-column prop="planCode" label="所属项目课题方案"></el-table-column> |
| | | <el-table-column prop="planName" label="实验编号"></el-table-column> |
| | | <el-table-column prop="planName" label="实验名称"></el-table-column> |
| | | <el-table-column prop="stage" label="通知时间"></el-table-column> |
| | | <el-table-column prop="stage" label="实验开始时间"></el-table-column> |
| | | <el-table-column prop="stage" label="实验结束时间"></el-table-column> |
| | | <el-table-column prop="stage" label="参加人员"></el-table-column> |
| | | <el-table-column prop="creator" label="状态"></el-table-column> |
| | | <el-table-column |
| | | type="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="projectName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentDate" |
| | | label="通知时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentStartTime" |
| | | label="实验开始时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentEndTime" |
| | | label="实验结束时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="participantsName" |
| | | label="参加人员" |
| | | ></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </Table> |
| | | <div class="header-title" style="margin-top: 60px;"> |
| | | <div class="header-title" style="margin-top: 60px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>被评定化验师</div> |
| | | </div> |
| | | <el-button class="el-icon-plus" type="primary" @click="addMember"> 选择化验师</el-button> |
| | | <el-button class="el-icon-plus" v-if="isEdit" type="primary" @click="addMember"> |
| | | 选择化验师</el-button |
| | | > |
| | | </div> |
| | | <div class="member-list"> |
| | | <div class="member-list-card"> |
| | | <div class="member-item"> |
| | | <div class="member-title">化验师</div> |
| | | <div class="member-name-box-2"> |
| | | <div v-for="i in [1, 2, 3, 4, 5, 6, 7, 8]" :key="i" class="member-name">张三</div> |
| | | <div |
| | | v-for="i in selectedParticipants" |
| | | :key="i.id" |
| | | class="member-name" |
| | | > |
| | | {{ i.nickName }} |
| | | </div> |
| | | <div class="member-edit" @click="addMember">修改</div> |
| | | </div> |
| | | <div class="member-edit" @click="handleEditMember" v-if="isEdit"> |
| | | 修改 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 18px;margin-top: 60px;"> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 18px; margin-top: 60px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>工作标准评定</div> |
| | | </div> |
| | | </div> |
| | | <EvaluateTable :type="1" /> |
| | | <EvaluateTable :type="1" ref="evaluateTable" /> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | <el-button type="primary" @click="submitForm()">保存</el-button> |
| | | <!-- <el-button>存草稿</el-button> --> |
| | | </div> |
| | | </template> |
| | | <SelectMember ref="selectMember" /> |
| | | <ExperimentalScheduling :show="showScheduling" /> |
| | | <SelectMemberSimple ref="selectMember" @submit="handleMemberSubmit" roleType="4" /> |
| | | <ExperimentalScheduling |
| | | :show="showScheduling" |
| | | @submit="handleSchedulingSubmit" |
| | | @close="handleSchedulingClose" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import ExperimentalScheduling from "@/views/dataManagement/confirmation-sheet/components/experimental-scheduling"; |
| | | import SelectMemberSimple from "@/components/SelectMemberSimple/index.vue"; |
| | | import ExperimentalScheduling from "@/views/dataManagement/schemeManagement/components/experimental-scheduling"; |
| | | import { getEvaluateChemist, add } from "./service.js"; |
| | | import moment from "moment"; |
| | | export default { |
| | | name: 'AddchemistEvaluate', |
| | | name: "AddchemistEvaluate", |
| | | components: { |
| | | ExperimentalScheduling, |
| | | SelectMemberSimple, |
| | | }, |
| | | data() { |
| | | return { |
| | | showScheduling: false, |
| | | participantsData: [], |
| | | selectedParticipants: [], |
| | | tableData: [], |
| | | isEdit: true, // 是否为编辑模式 |
| | | // 状态映射表 |
| | | statusTypeMap: { |
| | | "-1": "info", |
| | | 1: "warning", |
| | | 2: "success", |
| | | 3: "info", |
| | | }, |
| | | statusTextMap: { |
| | | "-1": "草稿箱", |
| | | 1: "待确认", |
| | | 2: "已确认", |
| | | 3: "已封存", |
| | | }, |
| | | }; |
| | | }, |
| | | async created() { |
| | | // const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | // this.userRole = userInfo.roleType || ""; |
| | | // 检查是否为编辑模式 |
| | | this.participantsData = []; |
| | | this.selectedParticipants = []; |
| | | this.tableData = []; |
| | | this.isEdit = true; // 是否为编辑模式 |
| | | if (this.$route.query.id) { |
| | | this.isEdit = this.$route.query.type === "view" ? false : true; |
| | | this.editId = this.$route.query.id; |
| | | await this.loadEditData(); |
| | | } |
| | | }, |
| | | methods: { |
| | | submitForm() { |
| | | handleSchedulingClose() { |
| | | this.showScheduling = false; |
| | | }, |
| | | handleSchedulingSubmit(data) { |
| | | console.log("data data", data); |
| | | this.tableData = data || []; |
| | | if (data && data.length > 0 && data[0].id) { |
| | | getEvaluateChemist({ dispatchId: data[0].id }) |
| | | .then((res) => { |
| | | console.log("获取参加人员列表:", res); |
| | | if (res) { |
| | | this.participantsData = res.map(item=>{ |
| | | return { |
| | | ...item,roleType:4 |
| | | } |
| | | }); |
| | | } else { |
| | | this.$message.error(res.msg || "获取参加人员列表失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | this.$message.error("获取参加人员列表失败"); |
| | | console.error("获取参加人员列表失败:", err); |
| | | }); |
| | | } |
| | | }, |
| | | getStatusType(status) { |
| | | return this.statusTypeMap[status] || "info"; |
| | | }, |
| | | getStatusText(status) { |
| | | return this.statusTextMap[status] || "未知"; |
| | | }, |
| | | handleEditMember() { |
| | | this.$refs.selectMember.open( |
| | | this.participantsData, |
| | | this.selectedParticipants |
| | | ); |
| | | }, |
| | | // ===== 人员相关方法 ===== |
| | | addMember() { |
| | | this.$refs.selectMember.open() |
| | | if (this.tableData.length == 0) { |
| | | this.$message.error("请先选择所属实验调度"); |
| | | return; |
| | | } |
| | | this.$refs.selectMember.open(this.participantsData, []); |
| | | }, |
| | | handleMemberSubmit(selectedMembers) { |
| | | this.selectedParticipants = selectedMembers; |
| | | this.$refs.selectMember.close(); |
| | | }, |
| | | // 将分数转换为评定值 |
| | | getEvaluateValue(score) { |
| | | // 2分 = 良好(1), 1分 = 正确(2), 0分 = 失误(3) |
| | | const scoreMap = { |
| | | 2: 1, // 良好 |
| | | 1: 2, // 正确 |
| | | 0: 3, // 失误 |
| | | }; |
| | | return scoreMap[score] || 3; // 默认返回失误 |
| | | }, |
| | | submitForm() { |
| | | const evaluateTable = this.$refs.evaluateTable; |
| | | if (!evaluateTable) { |
| | | this.$message.warning("评价表格未加载完成"); |
| | | return; |
| | | } |
| | | const activeIndex = evaluateTable.activeIndex; |
| | | |
| | | const evaluateData = { |
| | | evaluateOne: this.getEvaluateValue(activeIndex[0].score), |
| | | evaluateTwo: this.getEvaluateValue(activeIndex[1].score), |
| | | evaluateThree: this.getEvaluateValue(activeIndex[2].score), |
| | | evaluateFour: this.getEvaluateValue(activeIndex[3].score), |
| | | evaluateFive: this.getEvaluateValue(activeIndex[4].score), |
| | | evaluateSix: this.getEvaluateValue(activeIndex[5].score), |
| | | evaluateTime: moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | resultEvaluateJson: JSON.stringify(activeIndex), |
| | | dispatchId: this.tableData[0]?.id, |
| | | evaluateType:2, |
| | | userId: this.selectedParticipants[0].userId, |
| | | dispatchId:this.tableData[0]?.id, |
| | | status: 1 |
| | | }; |
| | | |
| | | |
| | | console.log("11111111111", evaluateTable.activeIndex); |
| | | console.log("2222222222222222", evaluateData); |
| | | add(evaluateData).then(res=>{ |
| | | if(res.code==200){ |
| | | this.$message.success("保存成功"); |
| | | this.$router.back(); |
| | | }else{ |
| | | this.$message.error(res.msg||"保存失败"); |
| | | } |
| | | }) |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | |
| | | &:before { |
| | | content: '*'; |
| | | color: #F56C6C; |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | |
| | | width: 340px; |
| | | height: 400px; |
| | | border-radius: 8px; |
| | | border: 1px solid #DCDFE6; |
| | | background: linear-gradient(to bottom, rgba(255, 77, 79, 0.20) 0%, rgba(255, 242, 194, 0) 70%); |
| | | border: 1px solid #dcdfe6; |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(255, 77, 79, 0.2) 0%, |
| | | rgba(255, 242, 194, 0) 70% |
| | | ); |
| | | |
| | | .member-item { |
| | | height: 100%; |
| | |
| | | .member-title { |
| | | margin-top: 20px; |
| | | width: 100%; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | font-weight: bold; |
| | | font-size: 16px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | |
| | | .member-name { |
| | | width: 60px; |
| | | height: 60px; |
| | | background: #7D8B79; |
| | | background: #7d8b79; |
| | | border-radius: 50%; |
| | | text-align: center; |
| | | line-height: 60px; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .member-edit { |
| | |
| | | transform: translateX(-50%); |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #FF4D4F; |
| | | color: #ff4d4f; |
| | | line-height: 22px; |
| | | width: 40px; |
| | | background: #FFF1F0; |
| | | background: #fff1f0; |
| | | border-radius: 4px; |
| | | border: 1px solid #FFCCC7; |
| | | border: 1px solid #ffccc7; |
| | | text-align: center; |
| | | } |
| | | } |
| | |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.projectName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.experimentNo" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.experimentName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="评定时间:"> |
| | | <el-date-picker v-model="value1" type="daterange" range-separator="至" start-placeholder="开始日期" |
| | | <el-date-picker v-model="form.dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" |
| | | end-placeholder="结束日期"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="tableTitle"> |
| | | <div class="flex a-center"> |
| | | <div class="title" :class="{ active: currentType === 'list' }" |
| | | @click="handleTypeChange('list')"> |
| | | <div class="title active"> |
| | | 化验师工作评定列表</div> |
| | | <div class="drafts" :class="{ active: currentType === 'draft' }" |
| | | @click="handleTypeChange('draft')">草稿箱</div> |
| | | </div> |
| | | <el-button @click="handleAdd" class="el-icon-plus" type="primary"> |
| | | 新增化验师工作评定</el-button> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="检测项名称" /> |
| | | <el-table-column prop="age" label="检测项编号" /> |
| | | <el-table-column prop="age" label="备注" /> |
| | | <el-table-column prop="age" label="创建人" /> |
| | | <el-table-column prop="age" label="创建时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <el-table-column prop="teamName" label="所属项目课题方案" /> |
| | | <el-table-column prop="experimentCode" label="实验编号" /> |
| | | <el-table-column prop="experimentName" label="实验名称" /> |
| | | <el-table-column prop="chemistName" label="被评定化验师" /> |
| | | <el-table-column prop="chemistIntegral" label="评定分数" /> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column label="操作" width="180"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="assessmentVisible = true">详情</el-button> |
| | | <el-button type="text" style="color: #1890ff" @click="handleDetail(row)">详情</el-button> |
| | | <el-button type="text" style="color: #1890ff" @click="handleEdit(row)">编辑</el-button> |
| | | <el-button type="text" style="color: #1890ff" @click="handleDelete(row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { chemistEvaluateList } from './service' |
| | | |
| | | export default { |
| | | name: 'TesterWorkerEvaluate', |
| | | name: 'ChemistEvaluate', |
| | | data() { |
| | | return { |
| | | currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱 |
| | | form: { |
| | | projectName: '', |
| | | experimentNo: '', |
| | | experimentName: '', |
| | | dateRange: [] |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | loading: false |
| | | } |
| | | }, |
| | | methods: { |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: '/deliveryAssessment/addTesterWorkerEvaluate' |
| | | async getList() { |
| | | this.loading = true |
| | | const params = { |
| | | ...this.queryForm, |
| | | projectName: this.form.projectName, |
| | | experimentNo: this.form.experimentNo, |
| | | experimentName: this.form.experimentName, |
| | | startTime: this.form.dateRange && this.form.dateRange[0] ? this.form.dateRange[0] : '', |
| | | endTime: this.form.dateRange && this.form.dateRange[1] ? this.form.dateRange[1] : '' |
| | | } |
| | | try { |
| | | const res = await chemistEvaluateList(params) |
| | | this.tableData = (res.data?.records || []).map(item => { |
| | | let score = ''; |
| | | try { |
| | | const json = typeof item.resultEvaluateJson === 'string' |
| | | ? JSON.parse(item.resultEvaluateJson) |
| | | : item.resultEvaluateJson; |
| | | score = json?.score || ''; |
| | | } catch (e) {} |
| | | return { ...item, score }; |
| | | }) |
| | | this.total = res.data?.total || 0 |
| | | } finally { |
| | | this.loading = false |
| | | } |
| | | }, |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1 |
| | | this.getList() |
| | | }, |
| | | handleReset() { |
| | | this.form = { |
| | | projectName: '', |
| | | experimentNo: '', |
| | | experimentName: '', |
| | | dateRange: [] |
| | | } |
| | | this.queryForm.pageNum = 1 |
| | | this.getList() |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: '/deliveryAssessment/addchemistEvaluate' |
| | | }) |
| | | }, |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
| | | this.getList(); |
| | | handleDetail(row) { |
| | | // 详情逻辑后续补充 |
| | | }, |
| | | handleEdit(row) { |
| | | // 编辑逻辑后续补充 |
| | | }, |
| | | handleDelete(row) { |
| | | // 删除逻辑后续补充 |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getList() |
| | | } |
| | | } |
| | | </script> |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 获取化验师工作评定分页列表 |
| | | export const chemistEvaluateList = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/chemistEvaluateList', { ...data }) |
| | | } |
| | | |
| | | export const add = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/add', { ...data }) |
| | | } |
| | | |
| | | export const getEvaluateChemist = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getEvaluateChemist', { params:data }) |
| | | } |
| | | |
| | | // export const getEvaluateChemist = (data) => { |
| | | // return axios.get('/open/t-result-work-evaluate/getEvaluateTester', { params:data }) |
| | | // } |
| | | |
| | | // export const update = (data) => { |
| | | // return axios.post('/api/t-tester-other-task/update', { ...data }) |
| | | // } |
| | | // export const deleteById = (data) => { |
| | | // return axios.delete('/open/t-tester-other-task/deleteById', { params:data }) |
| | | // } |
| | | // export const deleteByIds = (data) => { |
| | | // return axios.delete('/open/t-tester-other-task/deleteByIds', { params:data }) |
| | | // } |
| | | |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="新增临床试验" width="50%" @close="handleClose"> |
| | | <el-dialog |
| | | :visible.sync="dialogVisible" |
| | | :title="type === 'add' ? '新增临床试验' : '临床试验详情'" |
| | | width="50%" |
| | | @open='open' |
| | | @close="handleClose" |
| | | > |
| | | <div class="content-box"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属项目组</div> |
| | | </div> |
| | | <Table :data="criteriaList" :height="null"> |
| | | <el-table-column prop="name" label="项目组名称" /> |
| | | <el-table-column prop="name" label="项目负责人" /> |
| | | <el-table-column prop="name" label="项目组成员" /> |
| | | <el-table-column prop="name" label="创建时间" /> |
| | | <Table :data="projectTeamList" :height="null"> |
| | | <el-table-column prop="teamName" label="项目组名称" /> |
| | | <el-table-column prop="personCharge" label="项目负责人" /> |
| | | <el-table-column prop="staffName" label="项目组成员" /> |
| | | <el-table-column prop="createTime" label="创建时间" /> |
| | | </Table> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>临床试验内容</div> |
| | | </div> |
| | | <el-input type="textarea" :rows="4" placeholder="请输入" v-model="form.textarea" /> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>临床试验时间</div> |
| | | </div> |
| | | <el-date-picker v-model="form.value1" type="datetime" placeholder="请选择" /> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>评定积分</div> |
| | | </div> |
| | | <el-input-number placeholder="请输入" v-model="form.score" :min="0" :max="form.fullScore" :precision="1" |
| | | :step="1" /> |
| | | <el-row> |
| | | <el-col :span="2"> </el-col> |
| | | <el-col :span="12" :offset="1"> |
| | | <el-form |
| | | :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="100px" |
| | | :span="12" |
| | | label-position="top" |
| | | style="margin-top: 20px" |
| | | > |
| | | <el-form-item label="临床试验内容" prop="trialContent" required> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="form.trialContent" |
| | | placeholder="请输入" |
| | | :disabled="type === 'detail'" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="临床试验时间" prop="trialTime" required> |
| | | <el-date-picker |
| | | v-model="form.trialTime" |
| | | type="datetime" |
| | | placeholder="请选择" |
| | | style="width: 100%" |
| | | :disabled="type === 'detail'" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="评定积分" prop="evaluateScore" required> |
| | | <el-input |
| | | type="number" |
| | | v-model="form.evaluateScore" |
| | | placeholder="请输入" |
| | | :disabled="type === 'detail'" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer select-member-footer"> |
| | | <el-button type="primary">确认</el-button> |
| | | <el-button v-if="!isDetail" type="primary" @click="handleConfirm" |
| | | >确认</el-button |
| | | > |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDetailById, add, getDetailByUserId } from "../service.js"; |
| | | import moment from "moment"; |
| | | export default { |
| | | name: 'Detail', |
| | | name: "Detail", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | type: { |
| | | type: String, |
| | | default: "add", |
| | | }, |
| | | id: { |
| | | type: [String, Number], |
| | | default: "", |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | textarea: '', |
| | | value1: '', |
| | | score: null, |
| | | fullScore: 3 |
| | | trialContent: "", |
| | | trialTime: "", |
| | | evaluateScore: null, |
| | | processEngineerId: "", |
| | | // fullScore: 3, |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | |
| | | trialContent: [ |
| | | { required: true, message: "请输入任务内容", trigger: "blur" }, |
| | | ], |
| | | trialTime: [ |
| | | { required: true, message: "请选择任务时间", trigger: "change" }, |
| | | ], |
| | | evaluateScore: [{ required: true, message: "请输入评定积分", trigger: "blur" }], |
| | | }, |
| | | criteriaList: [] |
| | | } |
| | | projectTeamList: [], |
| | | isDetail: false, |
| | | }; |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | if (val) this.initForm(); |
| | | }, |
| | | immediate: true |
| | | immediate: true, |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form = val || {}; |
| | | } |
| | | type: { |
| | | handler() { |
| | | this.initForm(); |
| | | }, |
| | | immediate: true |
| | | } |
| | | immediate: true, |
| | | }, |
| | | id: { |
| | | handler() { |
| | | this.initForm(); |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | open() { |
| | | const teamRes = getDetailByUserId(); |
| | | this.projectTeamList = [{ ...teamRes }]; |
| | | }, |
| | | async initForm() { |
| | | this.isDetail = this.type === "detail"; |
| | | // 获取项目组信息 |
| | | |
| | | if (this.type === "add") { |
| | | // 新增,清空表单 |
| | | this.form = { |
| | | trialContent: "", |
| | | trialTime: "", |
| | | evaluateScore: null, |
| | | fullScore: 3, |
| | | }; |
| | | } else if (this.type === "detail" && this.id) { |
| | | // 详情,查详情接口 |
| | | const res = await getDetailById({ id: this.id }); |
| | | if (res && res.data) { |
| | | this.form = { |
| | | ...res.data, |
| | | fullScore: 3, |
| | | }; |
| | | } |
| | | } |
| | | }, |
| | | handleClose() { |
| | | this.$emit("close"); |
| | | }, |
| | | async handleConfirm() { |
| | | let processEngineer = this.projectTeamList[0]?.staffs?.filter( |
| | | (item) => item.roleType == 3 |
| | | ); |
| | | // 新增提交 |
| | | const params = { |
| | | trialContent: this.form.trialContent, |
| | | trialTime: moment(this.form.trialTime).format("YYYY-MM-DD HH:mm:ss"), |
| | | evaluateScore: this.form.evaluateScore, |
| | | processEngineerId: |
| | | processEngineer.length > 0 ? processEngineer[0].userId : "", |
| | | teamId: this.projectTeamList[0]?.id || "", |
| | | }; |
| | | await add(params); |
| | | this.$emit("close"); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | |
| | | |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :height='null' :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="项目组名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.teamName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="任务内容:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="试验内容:"> |
| | | <el-input v-model="form.trialContent" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <el-button @click="assessmentVisible = true, currentReport = {}" class="el-icon-plus" type="primary"> |
| | | <el-button v-if="roleType==2" @click="handleAssessment" class="el-icon-plus" type="primary"> |
| | | 新增临床试验</el-button> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="临床试验内容" /> |
| | | <el-table-column prop="age" label=" 临床试验时间" /> |
| | | <el-table-column prop="age" label="添加人" /> |
| | | <el-table-column prop="age" label="评定积分" /> |
| | | <el-table-column prop="age" label="累计分数" /> |
| | | <el-table-column prop="age" label="评定时间" /> |
| | | <el-table-column prop="age" label="操作"> |
| | | <el-table-column prop="projectTeam" label="所属项目组" > |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-tag v-if="row.teamName" type="info">{{ row.teamName }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="trialContent" label="临床试验内容" /> |
| | | <el-table-column prop="trialTime" label="临床试验时间" /> |
| | | <el-table-column prop="createBy" label="添加人" /> |
| | | <el-table-column prop="evaluateScore" label="评定积分" /> |
| | | <el-table-column prop="totalScore" label="累计分数" /> |
| | | <el-table-column prop="createTime" label="评定时间" /> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleDetail(row)">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <Detail :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | <Detail :modelValue="assessmentVisible" :type="dialogType" :id="currentId" @close="closeDetail" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Detail from './components/detail.vue' |
| | | import { pageList, getDetailByUserId } from './service.js' |
| | | |
| | | export default { |
| | | name: 'ClinicalTrial', |
| | |
| | | data() { |
| | | return { |
| | | form: { |
| | | teamName: '', |
| | | trialContent: '' |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {} |
| | | dialogType: '', |
| | | roleType: '', |
| | | currentId: '', |
| | | } |
| | | }, |
| | | mounted() { |
| | | const userInfo = JSON.parse(sessionStorage.getItem('userInfo')); |
| | | this.roleType = userInfo?.roleType; |
| | | this.getList(); |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | const params = { ...this.form, ...this.queryForm } |
| | | pageList(params).then(res => { |
| | | if(res && res.data) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } |
| | | }) |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | handleReset() { |
| | | this.form = { name: '', content: '' }; |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | async openDialog(type, id = '') { |
| | | this.dialogType = type; |
| | | this.currentId = id; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleDetail(row) { |
| | | this.openDialog('detail', row.id); |
| | | }, |
| | | handleAssessment() { |
| | | this.openDialog('add'); |
| | | }, |
| | | closeDetail() { |
| | | this.assessmentVisible = false; |
| | | this.getList(); |
| | | }, |
| | | }, |
| | | watch: { |
| | | assessmentVisible(val) { |
| | | if (!val) { |
| | | this.dialogType = ''; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 项目组总积分分页列表 |
| | | // 列表 |
| | | export const pageList = (data) => { |
| | | return axios.post('/api/t-clinical-trial-points/pageList', { ...data }) |
| | | } |
| | |
| | | export const getDetailById = (data) => { |
| | | return axios.get('/open/t-clinical-trial-points/getDetailById', { params:data }) |
| | | } |
| | | |
| | | //查询项目组信息 |
| | | export const getDetailByUserId = (data) => { |
| | | return axios.get('/open/t-project-team/getDetailByUserId', { params:data }) |
| | | } |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 获取实验结果汇报评定列表-审批人使用 |
| | | export const evaluatePageList = (data) => { |
| | | return axios.post('/api/t-experiment-result-report/evaluatePageList', { ...data }) |
| | | // 查询化验师评定列表-化验师使用 |
| | | export const getEvaluateChemistPageList = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/getEvaluateChemistPageList', { ...data }) |
| | | } |
| | | // 查询实验员评定列表-实验员使用 |
| | | export const getEvaluateTesterPageList = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/getEvaluateTesterPageList', { ...data }) |
| | | } |
| | | |
| | | export const add = (data) => { |
| | | return axios.post('/api/t-tester-other-task/add', { ...data }) |
| | | } |
| | | export const update = (data) => { |
| | | return axios.post('/api/t-tester-other-task/update', { ...data }) |
| | | } |
| | | export const deleteById = (data) => { |
| | | return axios.delete('/open/t-tester-other-task/deleteById', { params:data }) |
| | | } |
| | | export const deleteByIds = (data) => { |
| | | return axios.delete('/open/t-tester-other-task/deleteByIds', { params:data }) |
| | | } |
| | | export const getDetailById = (data) => { |
| | | return axios.get('/open/t-tester-other-task/getDetailById', { params:data }) |
| | | } |
| | | // export const add = (data) => { |
| | | // return axios.post('/api/t-result-work-evaluate/add', { ...data }) |
| | | // } |
| | | |
| | | // export const getEvaluateChemist = (data) => { |
| | | // return axios.get('/open/t-result-work-evaluate/getEvaluateChemist', { params:data }) |
| | | // } |
| | | |
| | | // export const update = (data) => { |
| | | // return axios.post('/api/t-tester-other-task/update', { ...data }) |
| | | // } |
| | | // export const deleteById = (data) => { |
| | | // return axios.delete('/open/t-tester-other-task/deleteById', { params:data }) |
| | | // } |
| | | // export const deleteByIds = (data) => { |
| | | // return axios.delete('/open/t-tester-other-task/deleteByIds', { params:data }) |
| | | // } |
| | | |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="form" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | :height="null" |
| | | @handlePageChange="handlePageChange" |
| | | @handleSizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input |
| | | v-model="form.experimentCode" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间:"> |
| | | <el-date-picker v-model="value1" type="daterange" range-separator="至" start-placeholder="开始日期" |
| | | end-placeholder="结束日期"> |
| | | </el-date-picker> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input |
| | | v-model="form.experimentName" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建日期:"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | value-format="yyyy-MM-dd" |
| | | @change="handleDateChange" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="是" value="1"></el-option> |
| | | <el-option label="否" value="0"></el-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="待提交" :value="1"></el-option> |
| | | <el-option label="待评定" :value="2"></el-option> |
| | | <el-option label="已评定" :value="3"></el-option> |
| | | <el-option label="已封存" :value="4"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</el-button> |
| | | <el-button |
| | | type="primary" |
| | | style="margin-left: 10px" |
| | | @click="handleSearch" |
| | | >查询</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="tableTitle"> |
| | | <div class="flex a-center"> |
| | | <div |
| | | class="title active" |
| | | > |
| | | 实验结果汇报列表 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目课题方案" /> |
| | | <el-table-column prop="age" label="实验编号" /> |
| | | <el-table-column prop="age" label="工艺工程师" /> |
| | | <el-table-column prop="age" label="化验师" /> |
| | | <el-table-column prop="age" label="实验员" /> |
| | | <el-table-column prop="age" label="创建日期" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <template #default="{ row }"> |
| | | <span :style="{ color: ['green', 'red'][row.status - 1] }">{{ ['是', '否'][row.status - 1] |
| | | }}</span> |
| | | <el-table-column |
| | | prop="projectName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="processEngineerName" |
| | | label="工艺工程师" |
| | | ></el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="laboratoryChemistName" |
| | | label="化验师" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimenterName" |
| | | label="实验员" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="createTime" |
| | | label="创建日期" |
| | | width="180" |
| | | ></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-button type="text">评定</el-button> |
| | | <el-table-column label="操作" width="180"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { getList} from "./service"; |
| | | |
| | | export default { |
| | | name: 'ExperimenterJobEvaluation', |
| | | components: { |
| | | }, |
| | | name: "TestResultReport", |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | projectName: "", |
| | | experimentCode: "", |
| | | experimentName: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | status: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | dateRange: [], |
| | | tableData: [], |
| | | total: 0, |
| | | } |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | resetForm() { |
| | | this.form = { |
| | | projectName: "", |
| | | experimentCode: "", |
| | | experimentName: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | status: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }; |
| | | this.dateRange = []; |
| | | this.getTableData(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | handleSearch() { |
| | | this.getTableData(); |
| | | }, |
| | | getList() { |
| | | |
| | | handleDetail(id) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: id, |
| | | type: "view", |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }); |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | getTableData() { |
| | | const params = { |
| | | ...this.form, |
| | | }; |
| | | getList(params) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } else { |
| | | this.$message.error(res.msg || "获取数据失败"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | this.$message.error("获取数据失败"); |
| | | }); |
| | | }, |
| | | handleDateChange(val) { |
| | | if (val) { |
| | | this.form.startTime = val[0]; |
| | | this.form.endTime = val[1]; |
| | | } else { |
| | | this.form.startTime = ""; |
| | | this.form.endTime = ""; |
| | | } |
| | | }, |
| | | getStatusType(status) { |
| | | const statusMap = { |
| | | "-1": "info", |
| | | 1: "warning", |
| | | 2: "warning", |
| | | 3: "success", |
| | | 4: "info", |
| | | 5: "warning", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }, |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | | "-1": "草稿箱", |
| | | 1: "待提交", |
| | | 2: "待评定", |
| | | 3: "已评定", |
| | | 4: "已封存", |
| | | 5: "已解封", |
| | | }; |
| | | return statusMap[status] || "未知"; |
| | | }, |
| | | handlePageChange(pageNum) { |
| | | this.form.pageNum = pageNum; |
| | | this.getTableData(); |
| | | }, |
| | | handleSizeChange(pageSize) { |
| | | this.form.pageSize = pageSize; |
| | | this.getTableData(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .top-box-integral { |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .tableTitle { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | gap: 28px; |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | align-items: center; |
| | | .title, |
| | | .drafts { |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | cursor: pointer; |
| | | font-weight: 400; |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | .title { |
| | | padding: 16px 29px; |
| | | } |
| | | .drafts { |
| | | padding: 16px 65px; |
| | | margin-left: 16px; |
| | | } |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 列表 |
| | | export const getList = (data) => { |
| | | return axios.post('/api/t-experiment-result-report/pageList', { ...data }) |
| | | } |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | :visible.sync="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="79.17%" |
| | | @close="handleClose" |
| | | > |
| | | <EvaluateTable ref="evaluateTable" :viewJson="viewJson" /> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit" class="submit-btn">确认评定结果</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | const EVALUATION_TYPES = ['labTechnician', 'experimenter']; |
| | | |
| | | export default { |
| | | name: "EvaluationDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: 'labTechnician' |
| | | }, |
| | | viewJson: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | dialogTitle() { |
| | | return this.type === 'labTechnician' ? '化验师工作评定' : this.type === 'experimenter' ? '实验员工作评定' : '工艺工程师工作评定'; |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | dialogVisible(val) { |
| | | if (!val) { |
| | | this.$emit('update:modelValue', false); |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | handleSubmit() { |
| | | const evaluateTable = this.$refs.evaluateTable; |
| | | if (!evaluateTable) { |
| | | this.$message.warning('评价表格未加载完成'); |
| | | return; |
| | | } |
| | | |
| | | const evaluateData = { |
| | | type: this.type, |
| | | activeIndex: evaluateTable.activeIndex |
| | | }; |
| | | |
| | | this.$emit('submit', evaluateData); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .dialog-footer { |
| | | padding: 20px; |
| | | border-top: 1px solid #eee; |
| | | |
| | | .submit-btn { |
| | | min-width: 80px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="queryForm" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.projectName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.experimentCode" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.experimentName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="创建日期:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.createTime" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="待提交" :value="1"></el-option> |
| | | <el-option label="待评定" :value="2"></el-option> |
| | | <el-option label="已评定" :value="3"></el-option> |
| | | <el-option label="已封存" :value="4"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="table-title"> |
| | | 实验结果汇报列表 |
| | | </div> |
| | | <div class="table-title">实验结果汇报列表</div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目课题方案" /> |
| | | <el-table-column prop="age" label="实验编号" /> |
| | | <el-table-column prop="age" label="工艺工程师" /> |
| | | <el-table-column prop="age" label="化验师" /> |
| | | <el-table-column prop="age" label="实验员" /> |
| | | <el-table-column prop="age" label="创建日期" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | <el-table-column prop="projectName" label="所属项目课题方案" /> |
| | | <el-table-column prop="experimentCode" label="实验编号" /> |
| | | <el-table-column prop="experimentName" label="实验名称" /> |
| | | <el-table-column prop="processEngineerName" label="工艺工程师" /> |
| | | <el-table-column prop="laboratoryChemistName" label="化验师" /> |
| | | <el-table-column prop="experimenterName" label="实验员" /> |
| | | <el-table-column prop="createTime" label="创建日期" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <el-table-column prop="operation" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="assessmentVisible = true">详情</el-button> |
| | | <el-button type="text" @click="handleDetail(row)">详情</el-button> |
| | | <el-button |
| | | v-if="row.status === 2" |
| | | type="text" |
| | | @click="handleEvaluate(row)" |
| | | >评定</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | <evaluation-dialog |
| | | :modelValue="evaluationDialogVisible" |
| | | :type="'processEngineer'" |
| | | :viewJson="currentEvaluationData" |
| | | @update:modelValue="updateEvaluationDialogVisible" |
| | | @submit="handleEvaluationSubmit" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import EvaluationDialog from "./components/evaluation-dialog.vue"; |
| | | import { evaluatePageList,evaluateProcess } from './service.js'; |
| | | |
| | | export default { |
| | | name: 'ProcessEngineerEvaluate', |
| | | name: "ProcessEngineerEvaluate", |
| | | components: { |
| | | EvaluationDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | projectName: '', |
| | | experimentCode: '', |
| | | experimentName: '', |
| | | createTime: '', |
| | | status: '', |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | pageNum: 1, |
| | | }, |
| | | total: 0, |
| | | } |
| | | evaluationDialogVisible: false, |
| | | currentEvaluationData: null, |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getList(); |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | this.queryForm.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | this.queryForm.pageSize = size; |
| | | this.getList(); |
| | | }, |
| | | getList() { |
| | | |
| | | const params = { |
| | | ...this.form, |
| | | pageNum: this.queryForm.pageNum, |
| | | pageSize: this.queryForm.pageSize, |
| | | }; |
| | | evaluatePageList(params).then(res => { |
| | | if (res && res.code === 200) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } else { |
| | | this.$message.error(res.msg || '获取数据失败'); |
| | | } |
| | | }).catch(() => { |
| | | this.$message.error('获取数据失败'); |
| | | }); |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: row.id, |
| | | type: "view", |
| | | }, |
| | | }); |
| | | }, |
| | | handleEvaluate(row) { |
| | | this.currentEvaluationData = row; // 可根据实际需要传递数据 |
| | | this.evaluationDialogVisible = true; |
| | | }, |
| | | updateEvaluationDialogVisible(val) { |
| | | this.evaluationDialogVisible = val; |
| | | if (!val) this.currentEvaluationData = null; |
| | | }, |
| | | // 处理评价提交 |
| | | handleEvaluationSubmit(evaluationData) { |
| | | const { activeIndex } = evaluationData; |
| | | // 将评分数据转换为后端需要的格式 |
| | | const evaluateData = { |
| | | evaluateType: 1, // 1=工艺工程师 |
| | | evaluateOne: this.getEvaluateValue(activeIndex[0].score), |
| | | evaluateTwo: this.getEvaluateValue(activeIndex[1].score), |
| | | evaluateThree: this.getEvaluateValue(activeIndex[2].score), |
| | | evaluateFour: this.getEvaluateValue(activeIndex[3].score), |
| | | evaluateFive: this.getEvaluateValue(activeIndex[4].score), |
| | | evaluateSix: this.getEvaluateValue(activeIndex[5].score), |
| | | evaluateTime: moment().format('YYYY-MM-DD HH:mm:ss'), |
| | | resultEvaluateJson: JSON.stringify(activeIndex), |
| | | resultReportId: this.currentOperationRow.id, |
| | | dispatchId: this.currentOperationRow.dispatchId, |
| | | status: 1 |
| | | }; |
| | | console.log('evaluateData',evaluateData) |
| | | |
| | | evaluateProcess(evaluateData).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('评定成功'); |
| | | this.evaluationDialogVisible = false; |
| | | this.getList(); // 重新获取列表数据 |
| | | } else { |
| | | this.$message.error(res.msg || '评定失败'); |
| | | } |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('评定失败'); |
| | | }); |
| | | }, |
| | | resetForm() { |
| | | this.form = { |
| | | projectName: '', |
| | | experimentCode: '', |
| | | experimentName: '', |
| | | createTime: '', |
| | | status: '', |
| | | }; |
| | | this.getList(); |
| | | }, |
| | | handleSearch() { |
| | | this.getList(); |
| | | }, |
| | | getStatusType(status) { |
| | | const statusMap = { |
| | | '-1': 'info', |
| | | '1': 'warning', |
| | | '2': 'warning', |
| | | '3': 'success', |
| | | '4': 'info', |
| | | '5': 'warning' |
| | | }; |
| | | return statusMap[status] || 'info'; |
| | | }, |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | | '-1': '草稿箱', |
| | | '1': '待提交', |
| | | '2': '待评定', |
| | | '3': '已评定', |
| | | '4': '已封存', |
| | | '5': '已解封' |
| | | }; |
| | | return statusMap[status] || '未知'; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | background: #e8faf6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | font-family: "SF Compact Display Black"; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | |
| | | .table-title { |
| | | width: 220px; |
| | | height: 50px; |
| | | background: #FFFFFF; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049C9A; |
| | | border: 1px solid #049c9a; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 27px; |
| | | } |
| | | |
| | | .expand-box { |
| | | padding: 20px; |
| | | background: linear-gradient(180deg, #049C9A 0%, #0ACBCA 100%); |
| | | background: linear-gradient(180deg, #049c9a 0%, #0acbca 100%); |
| | | border-radius: 20px; |
| | | |
| | | &-title { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | color: #ffffff; |
| | | line-height: 24px; |
| | | margin-bottom: 20px; |
| | | } |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 获取实验结果汇报评定列表-审批人使用 |
| | | export const evaluatePageList = (data) => { |
| | | return axios.post('/api/t-experiment-result-report/evaluatePageList', { ...data }) |
| | | } |
| | | // 评定工艺工程师实验 |
| | | export const evaluateProcess = (data) => { |
| | | return axios.post('/api/t-experiment-result-report/evaluateProcess', { ...data }) |
| | | } |
| | |
| | | <div class="top-box-header-title"> |
| | | <div>项目组总积分表</div> |
| | | <div class="top-box-header-time"> |
| | | <div>评定开始时间:2024-02-09</div> |
| | | <div>评定结束始时间:2024-02-09</div> |
| | | <div>评定开始时间:{{ topData.startTime || '-' }}</div> |
| | | <div>评定结束时间:{{ topData.endTime || '-' }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="top-box-integral"> |
| | | <div :style="{ backgroundColor: ['rgba(232, 250, 246, 1)', 'rgba(255, 243, 213, 1)', 'rgba(254, 237, 220, 1)', 'rgba(239, 248, 255, 1)', 'rgba(255, 237, 238, 1)'][item - 1] }" |
| | | v-for="item in 5" :key="item" class="top-box-integral-card"> |
| | | v-for="(item,index) in 5" :key="index" class="top-box-integral-card"> |
| | | <div class="top-box-integral-card-title">{{ ['项目组总积分', '工艺工程师积分', '化验师积分', '实验员积分', '实验终止次数'][item - |
| | | 1] }}</div> |
| | | <div :style="{ color: ['rgba(4, 156, 154, 1)', 'rgba(255, 197, 61, 1)', 'rgba(255, 147, 0, 1)', 'rgba(23, 119, 213, 1)', 'rgba(255, 73, 85, 1)'][item - 1] }" |
| | | class="top-box-integral-card-num">99.9</div> |
| | | class="top-box-integral-card-num">{{ |
| | | [ |
| | | topData.teamIntegral ?? '0', |
| | | topData.engineerIntegral ?? '0', |
| | | topData.chemistIntegral ?? '0', |
| | | topData.testerIntegral ?? '0', |
| | | topData.termination ?? '0' |
| | | ][item - 1] |
| | | }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="integral-content"> |
| | | <div class="integral-content-box"> |
| | | <div class="integral-content-box-left"> |
| | | <div @click="changeActiveItem(item)" class="integral-content-box-left-item" |
| | | :class="actionsLeftTab == item && 'activeItem'" v-for="item in 3" :key="item"> |
| | | <div>{{ ['工艺工程师', '化验师', '实验员'][item - 1] }}</div> |
| | | <div @click="changeActiveItem(item.value)" class="integral-content-box-left-item" |
| | | :class="actionsLeftTab == item.value && 'activeItem'" v-for="item in leftTabs" :key="item.value"> |
| | | <div>{{ item.label }}</div> |
| | | <div>工作内容评定</div> |
| | | </div> |
| | | </div> |
| | | <div class="integral-content-box-right"> |
| | | <div v-show="actionsLeftTab != 1" @wheel.prevent="handleWheel" class="integral-content-box-right-nameTab"> |
| | | <div v-show="actionsLeftTab == 2" @wheel.prevent="handleWheel" class="integral-content-box-right-nameTab"> |
| | | <div |
| | | v-for="(item, idx) in chemistTabList" |
| | | :key="item.userName || idx" |
| | | @click="changeActiveName(idx)" |
| | | :class="activeNameTab == idx && 'activeName'" |
| | | class="integral-content-box-right-nameTab-name" |
| | | > |
| | | {{ item.userName }} |
| | | </div> |
| | | </div> |
| | | <!-- <div v-show="actionsLeftTab != 1 && actionsLeftTab != 2" @wheel.prevent="handleWheel" class="integral-content-box-right-nameTab"> |
| | | <div @click="changeActiveName(item)" :class="activeNameTab == item && 'activeName'" class="integral-content-box-right-nameTab-name" v-for="item in 8" :key="item">张三</div> |
| | | </div> --> |
| | | <div v-show="actionsLeftTab == 3" @wheel.prevent="handleWheel" class="integral-content-box-right-nameTab"> |
| | | <div |
| | | v-for="(item, idx) in testerTabList" |
| | | :key="item.userName || idx" |
| | | @click="changeActiveName(idx)" |
| | | :class="activeNameTab == idx && 'activeName'" |
| | | class="integral-content-box-right-nameTab-name" |
| | | > |
| | | {{ item.userName }} |
| | | </div> |
| | | </div> |
| | | <div class="integral-content-box-right-thead"> |
| | | <div>评定项</div> |
| | | <div>评定情况</div> |
| | | <div>开始时间</div> |
| | | <div>结束时间</div> |
| | | <div>操作</div> |
| | | <div v-if="roleType == 1 || roleType == 2">操作</div> |
| | | </div> |
| | | <div class="integral-content-box-right-body"> |
| | | <div v-for="item in itemList" :key="item" class="integral-content-box-right-body-item"> |
| | | <div v-for="(item, idx) in itemList" :key="item.id || idx" class="integral-content-box-right-body-item"> |
| | | <div>{{ item.gainer }}</div> |
| | | <div> |
| | | <div v-if="item.situationOne">{{ item.situationOne }}</div> |
| | | <div v-if="item.situationTwo">{{ item.situationTwo }}</div> |
| | | </div> |
| | | <div></div> |
| | | <div></div> |
| | | <div v-if="item.startTime">{{item.startTime}}</div> |
| | | <div v-if="item.endTime">{{item.endTime}}</div> |
| | | <div> |
| | | <el-button type="text">修改</el-button> |
| | | <el-button type="text" v-if="roleType == 1 || roleType == 2" @click.stop='toChange(item.url)'>{{item.url? '修改':''}}</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | getDetailById, |
| | | getDetailByIdLeftOne, |
| | | getDetailByIdLeftTwo, |
| | | getDetailByIdLeftThree, |
| | | } from "./service"; |
| | | export default { |
| | | data() { |
| | | return { |
| | | actionsLeftTab: 1, |
| | | activeNameTab: 1, |
| | | actionspPersonnel: null, |
| | | roleType: null, |
| | | leftTabs: [], |
| | | detailId: null, |
| | | topData: {}, |
| | | tabData: [], |
| | | chemistTabList: [], // 化验师tab的人员列表 |
| | | testerTabList: [], // 实验员tab的人员列表 |
| | | craftList: [ |
| | | { |
| | | gainer: '1、项目可研报告', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "1、项目可研报告", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '2、项目可行报告', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "2、项目可行报告", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '3、项目实验室开发阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "3、项目实验室开发阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '4、项目中试试验阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "4、项目中试试验阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '5、项目生产验证试验阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "5、项目生产验证试验阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '6、工艺开发工具', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "6、工艺开发工具", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '7、验证与开发', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "7、验证与开发", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '8、立项报告', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "8、立项报告", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '9、临床实验积分', |
| | | situationTwo: '积分数:', |
| | | gainer: "9、临床实验积分", |
| | | situationTwo: "积分数:", |
| | | url:'/deliveryAssessment/clinicalTrial' |
| | | }, |
| | | ],//工艺工程师-工作内容评定 |
| | | assayList: [ |
| | | { |
| | | gainer: '1、项目开发阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "1、项目开发阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '2、项目中试试验阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "2、项目中试试验阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '3、项目生产验证试验阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "3、项目生产验证试验阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '4、项目检测项、检验包评定', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "4、项目检测项、检验包评定", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '5、中试、生产验证试验检验分析报告评定', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "5、中试、生产验证试验检验分析报告评定", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '6、原辅料、包材、竞品检验分析报告评定', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "6、原辅料、包材、竞品检验分析报告评定", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '7、产品报批及项目工作总结报告评定', |
| | | situationOne: '课题数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "7、产品报批及项目工作总结报告评定", |
| | | situationOne: "课题数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | ],//化验师-工作内容评定 |
| | | experimentList: [ |
| | | { |
| | | gainer: '1、项目实验室开发阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "1、项目实验室开发阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '2、项目中试试验阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "2、项目中试试验阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '3、项目生产验证试验阶段', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "3、项目生产验证试验阶段", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | }, |
| | | { |
| | | gainer: '4、其他任务', |
| | | situationOne: '实验数:', |
| | | situationTwo: '积分数:', |
| | | gainer: "4、其他任务", |
| | | situationOne: "实验数:", |
| | | situationTwo: "积分数:", |
| | | url:'/deliveryAssessment/restsTask' |
| | | }, |
| | | ],//实验员-工作内容评定 |
| | | } |
| | | }; |
| | | }, |
| | | computed: { |
| | | itemList() { |
| | | switch (this.actionsLeftTab) { |
| | | case 1: |
| | | return this.craftList |
| | | case 2: |
| | | return this.assayList |
| | | case 3: |
| | | return this.experimentList |
| | | default: |
| | | return this.craftList |
| | | } |
| | | } |
| | | return this.tabData || []; |
| | | }, |
| | | }, |
| | | created() { |
| | | |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | this.roleType = userInfo.roleType; |
| | | this.initTabs(); |
| | | this.detailId = this.$route.query.id || this.$route.params.id; |
| | | this.fetchTopData(); |
| | | this.fetchTabData(this.actionsLeftTab); |
| | | }, |
| | | methods: { |
| | | changeActiveItem(item) { |
| | | this.actionsLeftTab = item |
| | | initTabs() { |
| | | if (this.roleType == 3) { |
| | | // 工艺工程师 |
| | | this.leftTabs = [ |
| | | { label: "工艺工程师", value: 1 }, |
| | | { label: "化验师", value: 2 }, |
| | | { label: "实验员", value: 3 }, |
| | | ]; |
| | | } else if (this.roleType == 4) { |
| | | // 化验师 |
| | | this.leftTabs = [{ label: "化验师", value: 2 }]; |
| | | this.actionsLeftTab = 2; |
| | | } else if (this.roleType == 5) { |
| | | // 实验员 |
| | | this.leftTabs = [{ label: "实验员", value: 3 }]; |
| | | this.actionsLeftTab = 3; |
| | | } else { |
| | | // 超级管理员、审批人或其他 |
| | | this.leftTabs = [ |
| | | { label: "工艺工程师", value: 1 }, |
| | | { label: "化验师", value: 2 }, |
| | | { label: "实验员", value: 3 }, |
| | | ]; |
| | | this.actionsLeftTab = 1; |
| | | } |
| | | }, |
| | | changeActiveName(item) { |
| | | this.activeNameTab = item |
| | | fetchTopData() { |
| | | if (!this.detailId) return; |
| | | getDetailById({ id: this.detailId }).then((res) => { |
| | | if (res && res.data) { |
| | | this.topData = res.data; |
| | | } |
| | | }); |
| | | }, |
| | | fetchTabData(tabType) { |
| | | if (!this.detailId) return; |
| | | let api; |
| | | if (tabType == 1) api = getDetailByIdLeftOne; |
| | | else if (tabType == 2) api = getDetailByIdLeftTwo; |
| | | else if (tabType == 3) api = getDetailByIdLeftThree; |
| | | else return; |
| | | api({ id: this.detailId }).then((res) => { |
| | | if (res) { |
| | | if (tabType == 1) { |
| | | const list = res.engineerList || []; |
| | | this.craftList = this.craftList.map((item, idx) => { |
| | | const apiItem = list[idx] || {}; |
| | | let label = |
| | | item.situationOne && item.situationOne.includes("课题") |
| | | ? "课题数:" |
| | | : "实验数:"; |
| | | return { |
| | | ...item, |
| | | situationOne: label + (apiItem.count ?? "0"), |
| | | situationTwo: "积分数:" + (apiItem.integral ?? "0"), |
| | | startTime: apiItem.startTime || "-", |
| | | endTime: apiItem.endTime || "-", |
| | | }; |
| | | }); |
| | | console.log("craftList craftList", this.craftList); |
| | | this.tabData = this.craftList; |
| | | } else if (tabType == 2) { |
| | | // 化验师 |
| | | const chemistList = res.chemistList || []; |
| | | this.chemistTabList = chemistList; |
| | | this.activeNameTab = 0; |
| | | this.updateAssayListByChemist(0); |
| | | } else if (tabType == 3) { |
| | | const testerList = res.testerList || []; |
| | | this.testerTabList = testerList; |
| | | this.activeNameTab = 0; |
| | | this.updateExperimentListByTester(0); |
| | | } |
| | | // 其他tab后续再做 |
| | | } |
| | | }); |
| | | }, |
| | | updateAssayListByChemist(idx) { |
| | | const chemist = this.chemistTabList[idx]; |
| | | if (!chemist) { |
| | | this.tabData = []; |
| | | return; |
| | | } |
| | | const list = chemist.list || []; |
| | | this.tabData = this.assayList.map((item, i) => { |
| | | const apiItem = list[i] || {}; |
| | | let label = item.situationOne && item.situationOne.includes("课题") ? "课题数:" : "实验数:"; |
| | | return { |
| | | ...item, |
| | | situationOne: label + (apiItem.count ?? "0"), |
| | | situationTwo: "积分数:" + (apiItem.integral ?? "0"), |
| | | startTime: apiItem.startTime || "-", |
| | | endTime: apiItem.endTime || "-", |
| | | }; |
| | | }); |
| | | }, |
| | | updateExperimentListByTester(idx) { |
| | | const tester = this.testerTabList[idx]; |
| | | if (!tester) { |
| | | this.tabData = []; |
| | | return; |
| | | } |
| | | const list = tester.list || []; |
| | | this.tabData = this.experimentList.map((item, i) => { |
| | | const apiItem = list[i] || {}; |
| | | let label = item.situationOne && item.situationOne.includes("课题") ? "课题数:" : "实验数:"; |
| | | return { |
| | | ...item, |
| | | situationOne: label + (apiItem.count ?? "0"), |
| | | situationTwo: "积分数:" + (apiItem.integral ?? "0"), |
| | | startTime: apiItem.startTime || "-", |
| | | endTime: apiItem.endTime || "-", |
| | | }; |
| | | }); |
| | | }, |
| | | changeActiveItem(item) { |
| | | this.actionsLeftTab = item; |
| | | this.fetchTabData(item); |
| | | }, |
| | | changeActiveName(idx) { |
| | | this.activeNameTab = idx; |
| | | if (this.actionsLeftTab == 2) { |
| | | this.updateAssayListByChemist(idx); |
| | | } else if (this.actionsLeftTab == 3) { |
| | | this.updateExperimentListByTester(idx); |
| | | } |
| | | }, |
| | | handleWheel(e) { |
| | | if (this.scrollTimer) { |
| | |
| | | }; |
| | | |
| | | this.scrollTimer = setTimeout(scroll, 8); // 减少延迟时间 |
| | | }, |
| | | toChange(url){ |
| | | if(url){ |
| | | this.$router.push(url) |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scope lang="less"> |
| | | .top-box-header { |
| | | &-title { |
| | | color: #FFFFFF; |
| | | color: #ffffff; |
| | | padding: 0 20px; |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | min-height: 58px; |
| | | padding-bottom: 12px; |
| | | font-size: 20px; |
| | | background: linear-gradient(180deg, #05A0C1 0%, #05F2C2 100%); |
| | | background: linear-gradient(180deg, #05a0c1 0%, #05f2c2 100%); |
| | | border-radius: 16px 16px 0px 0px; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | |
| | | &-time { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 16px; |
| | | |
| | | div:first-child { |
| | |
| | | .top-box-integral { |
| | | padding: 42px 30px 38px 30px; |
| | | margin-top: -12px; |
| | | background: linear-gradient(180deg, #FFFFFF 0%, rgba(255, 255, 255, 0.2) 100%); |
| | | background: linear-gradient( |
| | | 180deg, |
| | | #ffffff 0%, |
| | | rgba(255, 255, 255, 0.2) 100% |
| | | ); |
| | | box-shadow: 0px 10px 19px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 16px; |
| | | border: 4px solid #FFFFFF; |
| | | border: 4px solid #ffffff; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | background: #e8faf6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | font-family: "SF Compact Display Black"; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | |
| | | background: rgba(255, 255, 255, 0.8); |
| | | box-shadow: 0px 10px 19px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 16px; |
| | | border: 4px solid #FFFFFF; |
| | | border: 4px solid #ffffff; |
| | | |
| | | &-box { |
| | | display: flex; |
| | |
| | | margin-top: 50px; |
| | | |
| | | .activeItem { |
| | | background: linear-gradient(180deg, rgba(5, 160, 193, 0.4) 0%, rgba(5, 242, 194, 0) 100%); |
| | | border-image: linear-gradient(180deg, rgba(10, 203, 202, 1), rgba(4, 156, 154, 0.2)) 1 1; |
| | | background: linear-gradient( |
| | | 180deg, |
| | | rgba(5, 160, 193, 0.4) 0%, |
| | | rgba(5, 242, 194, 0) 100% |
| | | ); |
| | | border-image: linear-gradient( |
| | | 180deg, |
| | | rgba(10, 203, 202, 1), |
| | | rgba(4, 156, 154, 0.2) |
| | | ) |
| | | 1 1; |
| | | clip-path: inset(0 round 10px); |
| | | filter: hue-rotate(360deg); |
| | | } |
| | |
| | | cursor: pointer; |
| | | width: 160px; |
| | | height: 170px; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | font-weight: bold; |
| | | font-size: 20px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | display: flex; |
| | | text-align: center; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | line-height: 30px; |
| | | background: #EFF8FA; |
| | | background: #eff8fa; |
| | | border-radius: 10px; |
| | | border: 1px solid; |
| | | clip-path: inset(0px round 10px); |
| | | filter: hue-rotate(360deg); |
| | | border-image: linear-gradient(180deg, rgba(220, 223, 230, 1), rgba(220, 223, 230, 1)) 1 1; |
| | | border-image: linear-gradient( |
| | | 180deg, |
| | | rgba(220, 223, 230, 1), |
| | | rgba(220, 223, 230, 1) |
| | | ) |
| | | 1 1; |
| | | |
| | | &:hover { |
| | | background: linear-gradient(180deg, rgba(5, 160, 193, 0.4) 0%, rgba(5, 242, 194, 0) 100%); |
| | | border-image: linear-gradient(180deg, rgba(10, 203, 202, 1), rgba(4, 156, 154, 0.2)) 1 1; |
| | | background: linear-gradient( |
| | | 180deg, |
| | | rgba(5, 160, 193, 0.4) 0%, |
| | | rgba(5, 242, 194, 0) 100% |
| | | ); |
| | | border-image: linear-gradient( |
| | | 180deg, |
| | | rgba(10, 203, 202, 1), |
| | | rgba(4, 156, 154, 0.2) |
| | | ) |
| | | 1 1; |
| | | clip-path: inset(0 round 10px); |
| | | filter: hue-rotate(360deg); |
| | | } |
| | |
| | | font-weight: 400; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | background: #FAFAFC; |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #DCDFE6; |
| | | border: 1px solid #dcdfe6; |
| | | line-height: 50px; |
| | | min-width: 94px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .activeName { |
| | | border: 1px solid #049C9A; |
| | | background: #FFFFFF; |
| | | border: 1px solid #049c9a; |
| | | background: #ffffff; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | } |
| | | } |
| | | |
| | |
| | | flex-wrap: wrap; |
| | | |
| | | div { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-weight: 500; |
| | | font-size: 20px; |
| | | color: #FFFFFF; |
| | | color: #ffffff; |
| | | text-align: center; |
| | | line-height: 40px; |
| | | flex: 1; |
| | | background: linear-gradient(270deg, #0ACBCA 0%, #049C9A 100%); |
| | | background: linear-gradient(270deg, #0acbca 0%, #049c9a 100%); |
| | | box-shadow: 0px 6px 10px 0px rgba(4, 156, 154, 0.09); |
| | | border-radius: 10px; |
| | | } |
| | |
| | | |
| | | &>div { |
| | | padding-left: 23px; |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | flex: 1; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | min-height: 50px; |
| | | background: #D7EFF4; |
| | | background: #d7eff4; |
| | | box-shadow: 0px 6px 10px 0px rgba(4, 156, 154, 0.09); |
| | | border-radius: 10px; |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | |
| | | </el-form> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="项目组名称" /> |
| | | <el-table-column prop="age" label="项目组总积分" /> |
| | | <el-table-column prop="age" label="工艺工程师积分" /> |
| | | <el-table-column prop="age" label="化验师积分" /> |
| | | <el-table-column prop="age" label="实验员积分" /> |
| | | <el-table-column prop="age" label="评定开始时间" /> |
| | | <el-table-column prop="age" label="评定结束时间" /> |
| | | <el-table-column prop="age" label="状态" /> |
| | | <el-table-column prop="age" label="操作"> |
| | | <el-table-column prop="teamName" label="项目组名称" /> |
| | | <el-table-column prop="teamIntegral" label="项目组总积分" /> |
| | | <el-table-column prop="engineerIntegral" label="工艺工程师积分" /> |
| | | <el-table-column prop="chemistIntegral" label="化验师积分" /> |
| | | <el-table-column prop="testerIntegral" label="实验员积分" /> |
| | | <el-table-column prop="startTime" label="评定开始时间" /> |
| | | <el-table-column prop="endTime" label="评定结束时间" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-button @click="goDetail" type="text">详情</el-button> |
| | | <span>{{ formatStatus(row.status) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button @click="goDetail(row)" type="text">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | |
| | | } |
| | | }, |
| | | methods: { |
| | | goDetail() { |
| | | goDetail(row) { |
| | | this.$router.push({ |
| | | path: '/deliveryAssessment/projectTeamIntegral-detail' |
| | | path: '/deliveryAssessment/projectTeamIntegral-detail', |
| | | query: { id: row.id } |
| | | }) |
| | | }, |
| | | handleCurrentChange(page) { |
| | |
| | | params.startTime = this.value1[0] |
| | | params.endTime = this.value1[1] |
| | | } else { |
| | | params.startTime = undefined |
| | | params.endTime = undefined |
| | | params.startTime = '' |
| | | params.endTime = '' |
| | | } |
| | | try { |
| | | const res = await pageList(params) |
| | | this.tableData = res.records || [] |
| | | this.total = res.total || 0 |
| | | this.tableData = res.data.records || [] |
| | | this.total = res.data.total || 0 |
| | | } catch (e) { |
| | | this.tableData = [] |
| | | this.total = 0 |
| | | } |
| | | }, |
| | | formatStatus(status) { |
| | | if (status === -1) return '草稿箱' |
| | | if (status === 1) return '已提交' |
| | | return '全部' |
| | | } |
| | | }, |
| | | mounted() { |
| | |
| | | export const pageList = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/pageList', { ...data }) |
| | | } |
| | | // 项查看详情-顶部数据 |
| | | export const getDetailById = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getDetailById', { params:data }) |
| | | } |
| | | // 查看详情-左侧数据-工艺工程师工作内容评定 |
| | | export const getDetailByIdLeftOne = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getDetailByIdLeftOne', { params:data }) |
| | | } |
| | | // 查看详情-左侧数据-化验师工作内容评定 |
| | | export const getDetailByIdLeftTwo = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getDetailByIdLeftTwo', { params:data }) |
| | | } |
| | | // 查看详情-左侧数据-实验员工作内容评定 |
| | | export const getDetailByIdLeftThree = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getDetailByIdLeftThree', { params:data }) |
| | | } |
| | | // 查询可评定的化验师 |
| | | export const getEvaluateChemist = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getEvaluateChemist', { params:data }) |
| | | } |
| | | // 查询可评定的实验员 |
| | | export const getEvaluateTester = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getEvaluateTester', { params:data }) |
| | | } |
New file |
| | |
| | | <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" disabled placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="content-box"> |
| | | <el-row :gutter="16"> |
| | | <el-col :xs="24" :sm="24" :md="4" :lg="4" :xl="4"> |
| | | <div class="content-box-left"> |
| | | <div class="content-box-left-th">设立课题规则</div> |
| | | <div |
| | | class="content-box-left-body" |
| | | :style="{ height: `calc(${$baseTableHeight()}px - 40px)` }" |
| | | > |
| | | 1、根据可研报告、产品构思设计的工艺研究路线,一条工艺路线设立一个课题。如果一个课题中有多个化合物需要开发研究,则每个化合物作为一个分题;分题归集到该课题中,最终形成课题报告。不同课题报告中的分题不能重复使用。 |
| | | 2、在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题 |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col |
| | | style="margin-top: 5px" |
| | | :xs="24" |
| | | :sm="24" |
| | | :md="20" |
| | | :lg="20" |
| | | :xl="20" |
| | | > |
| | | <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" |
| | | :disabled="type === 'detail'" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="rule" label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、各分项评满分,应满足以下四项要求:</div> |
| | | <div>①分项内容:清晰、系统、完整,结构逻辑清晰,无缺项;</div> |
| | | <div>②团队工作运行顺畅、计划时间高效。</div> |
| | | <div>③工作结果完成度高。</div> |
| | | <div>④课题文档报告完成度高。</div> |
| | | <div> |
| | | 2、某分项工作完成,但出现以下三种错误中的1种,则减1分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div> |
| | | 3、某分项工作基本完成,但出现三种错误中的2-3种,则减2分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div> |
| | | 4、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="assessed" v-if="evaluateInfo.status == 3"> |
| | | <div>评定时间:{{ evaluateInfo.evaluateTime || "" }}</div> |
| | | <div>评定人:{{ evaluateInfo.evaluatePersonName || "" }}</div> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer select-member-footer" v-if="type !== 'detail'"> |
| | | <el-button type="primary" @click="handleSubmit">提交评定结果</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { evaluateDetail, evaluate } from "../service.js"; |
| | | export default { |
| | | name: "AssessmentDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | id: { |
| | | type: [String, Number], |
| | | // required: true, |
| | | default: () => "", |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: "assessment", |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: "", |
| | | reportName: "", |
| | | }, |
| | | evaluateInfo: {}, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: "请输入报告名称", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: |
| | | "课题名称依准确性、报告内容完整性:研究目标是否完整、是否研究工作内容合理性、是否围绕目标展开开、是否具有逻辑性和条理性", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: "文献资料调查:全面性、系统性编辑逻辑顺畅,表达规范", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: |
| | | "专业/技术路线与方法:合理性、可行性;实验设计科学、能完成研究目标、方法完整、完整、可靠;", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: |
| | | "实验验证工作可行性强,团队工作调度支持实验设备、材料等条件的准备良好,时间计划合理,能效按时完成", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: |
| | | "实验设计合理性:①对照设置,重复次数,样本量足够。②变量控制:自变量控制,因变量测量,干扰因素分析识别;确保结果的准确性③验证结果解释分析:符合科学原理、逻辑严密、不存在漏洞。具有实际应用价值,解决了实际问题或实现了研究目的。", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: |
| | | "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | ], |
| | | }; |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | if (val && this.id) { |
| | | this.fetchDetail(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | id(val) { |
| | | if (this.modelValue && val) { |
| | | this.fetchDetail(); |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | async fetchDetail() { |
| | | try { |
| | | const res = await evaluateDetail({ id: this.id }); |
| | | if (res) { |
| | | this.evaluateInfo = { ...res }; |
| | | this.form.reportNo = res.reportCode || ""; |
| | | this.form.reportName = res.reportName || ""; |
| | | // 详情回显分数 |
| | | if (res.evaluateScore) { |
| | | if ( |
| | | this.type === "detail" && |
| | | typeof res.evaluateScore === "string" |
| | | ) { |
| | | const scoreArr = res.evaluateScore |
| | | .split(",") |
| | | .map((s) => Number(s)); |
| | | this.criteriaList.forEach((item, idx) => { |
| | | item.score = scoreArr[idx] || 0; |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } catch (e) { |
| | | this.$message && this.$message.error("获取详情失败"); |
| | | } |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:modelValue", false); |
| | | this.$emit("close"); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | // 拼接分数 |
| | | const evaluateScore = this.criteriaList |
| | | .map((item) => item.score) |
| | | .join(","); |
| | | const params = { |
| | | id: this.id, |
| | | evaluateScore, |
| | | }; |
| | | evaluate(params).then((res) => { |
| | | if (res) { |
| | | this.$message && this.$message.success("评定成功"); |
| | | this.handleClose(); |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | this.$message && this.$message.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; |
| | | |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #fafafa !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &-body { |
| | | padding: 0 10px; |
| | | line-height: 23px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .assessed { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | gap: 25px; |
| | | margin-top: 20px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="queryForm" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="项目组名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.teamName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="课题类型:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-select v-model="form.reportType" placeholder="请选择"> |
| | | <el-option label="可研报告" :value="1" /> |
| | | <el-option label="可行报告" :value="2" /> |
| | | <el-option label="工艺开发工具" :value="3" /> |
| | | <el-option label="验证与发布" :value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="课题名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="报告名称:"> |
| | | <el-input v-model="form.reportName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="提交人:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.staffNames" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="草稿箱" :value="-1" /> |
| | | <el-option label="待审核" :value="1" /> |
| | | <el-option label="待评定" :value="2" /> |
| | | <el-option label="已评定" :value="3" /> |
| | | <el-option label="已驳回" :value="4" /> |
| | | <el-option label="已撤回" :value="5" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="top-box-integral"> |
| | | <div style="background-color:rgba(232, 250, 246, 1)" v-for="item in 3" :key="item" |
| | | class="top-box-integral-card"> |
| | | <div class="top-box-integral-card-title">{{ ['课题合计数量', '待评定', '已评定'][item - 1] }}</div> |
| | | <div style="color:rgba(4, 156, 154, 1)" class="top-box-integral-card-num">99.9</div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">课题合计数量</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.totalCount || 0 }} |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">待评定</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.toEvaluatedCount || 0 }} |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">已评定</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.evaluatedCount || 0 }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="tip-warring"> |
| | | <div>【注意】每个课题交付评分标准:</div> |
| | | <div> |
| | | 1、课题由工程师/化验师设定,并清晰完整完成课题目标,评优秀3分; |
| | | </div> |
| | | <div> |
| | | 2、课题由工程师/化验师设定,并清晰完整完成课题目标,评优秀3分; |
| | | </div> |
| | | <div> |
| | | 3、课题由上级设定,工程师/化验师清晰完整完成课题目标,评正常2分; |
| | | </div> |
| | | <div> |
| | | 4、课题由上级设定,工程师/化验师只能阐述课题内容,无法延伸工作思路,无开发思维的运行能力、创新能力,无法实现专题目标,评失误0分; |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="课题类型" /> |
| | | <el-table-column prop="age" label="报告编号" /> |
| | | <el-table-column prop="age" label="报告名称" /> |
| | | <el-table-column prop="age" label="提交人" /> |
| | | <el-table-column prop="age" label="评定结果" /> |
| | | <el-table-column prop="age" label="累积分值" /> |
| | | <el-table-column prop="age" label="评定时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <el-table-column prop="teamName" label="所属项目组" /> |
| | | <el-table-column prop="reportType" label="课题类型"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | <span v-if="row.reportType == 1">可研报告</span> |
| | | <span v-else-if="row.reportType == 2">可行报告</span> |
| | | <span v-else-if="row.reportType == 3">工艺开发工具</span> |
| | | <span v-else-if="row.reportType == 4">验证与发布</span> |
| | | <span v-else>--</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <el-table-column prop="reportCode" label="报告编号" /> |
| | | <el-table-column prop="reportName" label="报告名称" /> |
| | | <el-table-column prop="createBy" label="提交人" /> |
| | | <el-table-column prop="evaluatePersonName" label="评定人员" /> |
| | | <el-table-column prop="evaluateScore" label="评定分数" /> |
| | | <el-table-column prop="totalScore" label="累积分值" /> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-button type="text">评定</el-button> |
| | | <el-tag v-if="row.status == 3" type="info" color="#fff" |
| | | >已评定</el-tag |
| | | > |
| | | <el-tag v-else-if="row.status == 2" type="success">待评定</el-tag> |
| | | <el-tag v-else-if="row.status == 1" type="warning">待审核</el-tag> |
| | | <el-tag v-else-if="row.status == 4" type="danger">已驳回</el-tag> |
| | | <el-tag v-else-if="row.status == 5" type="info">已撤回</el-tag> |
| | | <el-tag v-else type="default">草稿箱</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleDetail(row)">详情</el-button> |
| | | <el-button |
| | | type="text" |
| | | @click="handleAssessment(row)" |
| | | v-if="row.status == 2" |
| | | >评定</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <!-- 审批人 --> |
| | | <CraftDialog :modelValue="craftVisible" :reportData="currentReport" /> |
| | | <AssessmentDialog |
| | | :modelValue="assessmentVisible" |
| | | :id="currentId" |
| | | :type="dialogType" |
| | | @close="handleAssessmentSubmit" |
| | | @submit="handleAssessmentSubmit" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import CraftDialog from './components/CraftDialog.vue' |
| | | import AssessmentDialog from "./components/AssessmentDialog.vue"; |
| | | import { pageList, evaluateCount, evaluateDetail } from "./service.js"; |
| | | |
| | | export default { |
| | | name: 'ReportEvaluation', |
| | | name: "TaskList", |
| | | components: { |
| | | CraftDialog |
| | | AssessmentDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | form: {}, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | pageNum: 1, |
| | | }, |
| | | total: 0, |
| | | currentReport: {}, |
| | | craftVisible: false, |
| | | } |
| | | assessmentVisible: false, |
| | | currentId: null, |
| | | dialogType: '', |
| | | statistics: { |
| | | totalCount: 0, |
| | | toEvaluatedCount: 0, |
| | | evaluatedCount: 0, |
| | | }, |
| | | }; |
| | | }, |
| | | methods: { |
| | | async getList() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await pageList(params); |
| | | if (res && res.data) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } |
| | | }, |
| | | async getStatistics() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await evaluateCount(params); |
| | | if (res && res.data) { |
| | | this.statistics = res.data; |
| | | } |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | this.queryForm.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | this.queryForm.pageSize = size; |
| | | this.getList(); |
| | | }, |
| | | getList() { |
| | | |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | handleReset() { |
| | | this.form = {}; |
| | | this.queryForm = { pageSize: 10, pageNum: 1 }; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | this.currentId = row.id; |
| | | this.dialogType = 'detail'; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.currentId = row.id; |
| | | this.dialogType = 'assessment'; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | } |
| | | } |
| | | } |
| | | this.assessmentVisible=false; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | background: #e8faf6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | font-family: "SF Compact Display Black"; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 项目组总积分分页列表 |
| | | export const pageList = (data) => { |
| | | return axios.post('/api/t-feasibility-study-report/pageList', { ...data }) |
| | | } |
| | | // 评定 |
| | | export const evaluate = (data) => { |
| | | return axios.put(`/open/t-feasibility-study-report/evaluate?id=${data.id}&evaluateScore=${data.evaluateScore}`, { params:data }) |
| | | } |
| | | // 查看详情 |
| | | export const evaluateDetail = (data) => { |
| | | return axios.get('/open/t-feasibility-study-report/evaluateDetail', { params:data }) |
| | | } |
| | | // 统计 |
| | | export const evaluateCount = (data) => { |
| | | return axios.post('/api/t-feasibility-study-report/evaluateCount', {...data }) |
| | | } |
| | |
| | | :visible.sync="dialogVisible" |
| | | :title="type === 'add' ? '新增其他任务' : '其他任务详情'" |
| | | width="70%" |
| | | @open='open' |
| | | @close="handleClose" |
| | | > |
| | | <div class="content-box"> |
| | |
| | | <div>所属项目组</div> |
| | | </div> |
| | | <Table :data="criteriaList" :height="null"> |
| | | <el-table-column prop="name" label="项目组名称" /> |
| | | <el-table-column prop="name" label="项目负责人" /> |
| | | <el-table-column prop="name" label="项目组成员" /> |
| | | <el-table-column prop="name" label="创建时间" /> |
| | | <el-table-column prop="teamName" label="项目组名称" /> |
| | | <el-table-column prop="personCharge" label="项目负责人" /> |
| | | <el-table-column prop="staffName" label="项目组成员" /> |
| | | <el-table-column prop="createTime" label="创建时间" /> |
| | | </Table> |
| | | |
| | | <el-row> |
| | |
| | | > |
| | | <el-option |
| | | v-for="member in memberList" |
| | | :key="member.id" |
| | | :label="member.name" |
| | | :value="member.id" |
| | | :key="member.userId" |
| | | :label="member.nickName" |
| | | :value="member.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="任务内容" prop="taskContent" required> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="form.taskContent" |
| | | placeholder="请输入" |
| | | :disabled="type === 'detail'" |
| | |
| | | </el-form-item> |
| | | <el-form-item label="评定积分" prop="score" required> |
| | | <el-input |
| | | type="number" |
| | | v-model="form.score" |
| | | placeholder="请输入" |
| | | :disabled="type === 'detail'" |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template v-slot:footer> |
| | | <el-button v-if="type === 'add'" type="primary" @click="handleSave">确认</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import {getDetailByUserId, add, update, getDetailById} from '../service.js' |
| | | import moment from 'moment' |
| | | export default { |
| | | name: "Detail", |
| | | props: { |
| | |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | id: { |
| | | type: String, |
| | | default: () => (''), |
| | | }, |
| | | type: { |
| | | type: String, |
| | |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | assignee: "", |
| | | id: '', |
| | | teamId: '', |
| | | assignee: "", // 实际为 testerId |
| | | taskContent: "", |
| | | taskTime: "", |
| | | score: "", |
| | | score: "", // 实际为 evaluateScore |
| | | }, |
| | | rules: { |
| | | assignee: [ |
| | |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form = { |
| | | assignee: val.assignee || "", |
| | | taskContent: val.taskContent || "", |
| | | taskTime: val.taskTime || "", |
| | | score: val.score || "", |
| | | }; |
| | | this.memberList = val.memberList || []; |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | }, |
| | | methods: { |
| | | open(){ |
| | | getDetailByUserId().then(res=>{ |
| | | this.criteriaList=[{...res}] |
| | | this.memberList=res.staffs.filter(item => item.roleType == '5') || [] |
| | | this.form.teamId = res.id || '' |
| | | }) |
| | | // 如果是详情,获取详情数据 |
| | | if(this.type === 'detail' && this.id){ |
| | | getDetailById({id: this.id}).then(res => { |
| | | if(res && res){ |
| | | this.form = { |
| | | id: res.id || '', |
| | | teamId: res.teamId || '', |
| | | assignee: res.testerId || '', |
| | | taskContent: res.taskContent || '', |
| | | taskTime: res.taskTime || '', |
| | | score: res.evaluateScore || '', |
| | | } |
| | | } |
| | | }) |
| | | } else if(this.type === 'add') { |
| | | // 新增时清空表单 |
| | | this.form = { |
| | | id: '', |
| | | teamId: this.form.teamId, |
| | | assignee: '', |
| | | taskContent: '', |
| | | taskTime: '', |
| | | score: '', |
| | | } |
| | | } |
| | | }, |
| | | handleSave() { |
| | | this.$refs.formRef.validate(valid => { |
| | | if (!valid) return; |
| | | const params = { |
| | | id: this.form.id, |
| | | teamId: this.form.teamId, |
| | | taskContent: this.form.taskContent, |
| | | taskTime: this.form.taskTime ? moment(this.form.taskTime).format('YYYY-MM-DD HH:mm:ss') : '', |
| | | testerId: this.form.assignee, |
| | | evaluateScore: this.form.score, |
| | | }; |
| | | const api = this.type === 'add' ? add : update; |
| | | api(params).then(res => { |
| | | if(res && res.code === 200){ |
| | | this.$message.success('保存成功'); |
| | | this.$emit('close'); |
| | | this.$emit('update:modelValue', false); |
| | | } |
| | | }) |
| | | }) |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:modelValue", false); |
| | | }, |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" :loading="loading" :height='null' @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="项目组名称:"> |
| | | <el-input v-model="form.groupName" placeholder="请输入" /> |
| | | <el-input v-model="form.teamName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="任务内容:"> |
| | | <el-input v-model="form.taskContent" placeholder="请输入" /> |
| | |
| | | <el-button v-if="roleType==3" @click="handleAdd" class="el-icon-plus" type="primary">新增其他任务</el-button> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column :prop="'projectTeam.teamName'" label="所属项目组" /> |
| | | <el-table-column prop="projectTeam" label="所属项目组" > |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.teamName" type="info">{{ row.teamName }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="taskContent" label="任务内容" /> |
| | | <el-table-column prop="taskTime" label="任务时间" /> |
| | | <el-table-column prop="testerName" label="添加人" /> |
| | | <el-table-column prop="createBy" label="添加人" /> |
| | | <el-table-column prop="evaluateScore" label="评定积分" /> |
| | | <el-table-column label="累计分数"> |
| | | <template #default> |
| | | <!-- 累计分数接口未返回,留空或后端补充 --> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column prop="createTime" label="评定时间" /> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleDetail(row)">详情</el-button> |
| | |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <Detail :modelValue="assessmentVisible" :reportData="currentReport" :type="detailType" @close="assessmentVisible = false" /> |
| | | <Detail :modelValue="assessmentVisible" :type="detailType" :id="currentId" @close="closeDetail" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Detail from './components/detail.vue' |
| | | import { pageList, getDetailById } from './service.js' |
| | | import { pageList } from './service.js' |
| | | |
| | | export default { |
| | | name: 'RestsTask', |
| | |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {}, |
| | | detailType: 'detail', |
| | | detailType: '', |
| | | currentId: null, |
| | | loading: false, |
| | | roleType:'', |
| | | } |
| | |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | closeDetail() { |
| | | this.assessmentVisible = false; |
| | | this.getList(); |
| | | }, |
| | | handleAdd() { |
| | | this.currentReport = { |
| | | assignee: '', |
| | | taskContent: '', |
| | | taskTime: '', |
| | | score: '', |
| | | memberList: [] // 这里需要你根据实际情况传入项目组成员 |
| | | }; |
| | | this.detailType = 'add'; |
| | | this.currentId = null; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleDetail(row) { |
| | | if (!row || !row.id) return; |
| | | getDetailById({ id: row.id }).then(res => { |
| | | if (res && res.data) { |
| | | this.currentReport = res.data; |
| | | this.detailType = 'detail'; |
| | | this.assessmentVisible = true; |
| | | } |
| | | }); |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.currentId = row.id; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | } |
| | |
| | | export const getDetailById = (data) => { |
| | | return axios.get('/open/t-tester-other-task/getDetailById', { params:data }) |
| | | } |
| | | //查询项目组信息 |
| | | export const getDetailByUserId = (data) => { |
| | | return axios.get('/open/t-project-team/getDetailByUserId', { params:data }) |
| | | } |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="课题评定详情" width="70%" @close="handleClose"> |
| | | <el-form :model="form" inline label-position="top" :rules="rules" ref="formRef"> |
| | | <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-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-input v-model="form.reportName" disabled placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-col :xs="24" :sm="24" :md="4" :lg="4" :xl="4"> |
| | | <div class="content-box-left"> |
| | | <div class="content-box-left-th">设立课题规则</div> |
| | | <div class="content-box-left-body" :style="{ height: `calc(${$baseTableHeight()}px - 40px)` }"> |
| | | <div |
| | | class="content-box-left-body" |
| | | :style="{ height: `calc(${$baseTableHeight()}px - 40px)` }" |
| | | > |
| | | 1、根据可研报告、产品构思设计的工艺研究路线,一条工艺路线设立一个课题。如果一个课题中有多个化合物需要开发研究,则每个化合物作为一个分题;分题归集到该课题中,最终形成课题报告。不同课题报告中的分题不能重复使用。 |
| | | 2、在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题</div> |
| | | 2、在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题 |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col style="margin-top: 5px;" :xs="24" :sm="24" :md="20" :lg="20" :xl="20"> |
| | | <Table :total="0" :height="null" :data="criteriaList" show-summary :summary-method="getSummaries" |
| | | :span-method="arraySpanMethod"> |
| | | <el-col |
| | | style="margin-top: 5px" |
| | | :xs="24" |
| | | :sm="24" |
| | | :md="20" |
| | | :lg="20" |
| | | :xl="20" |
| | | > |
| | | <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" /> |
| | | <el-input-number |
| | | v-model="row.score" |
| | | :min="0" |
| | | :max="row.fullScore" |
| | | :step="1" |
| | | :disabled="type === 'detail'" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="rule" label="创新型课题报告评分规则"> |
| | |
| | | <div>②团队工作运行顺畅、计划时间高效。</div> |
| | | <div>③工作结果完成度高。</div> |
| | | <div>④课题文档报告完成度高。</div> |
| | | <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div> |
| | | <div> |
| | | 2、某分项工作完成,但出现以下三种错误中的1种,则减1分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、某分项工作基本完成,但出现三种错误中的2-3种,则减2分:</div> |
| | | <div> |
| | | 3、某分项工作基本完成,但出现三种错误中的2-3种,则减2分: |
| | | </div> |
| | | <div> ①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>4、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | <div> |
| | | 4、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="assessed"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | <div class="assessed" v-if="evaluateInfo.status == 3"> |
| | | <div>评定时间:{{ evaluateInfo.evaluateTime || "" }}</div> |
| | | <div>评定人:{{ evaluateInfo.evaluatePersonName || "" }}</div> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer select-member-footer"> |
| | | <span class="dialog-footer select-member-footer" v-if="type !== 'detail'"> |
| | | <el-button type="primary" @click="handleSubmit">提交评定结果</el-button> |
| | | </span> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { evaluateDetail, evaluate } from "../service.js"; |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | name: "AssessmentDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | id: { |
| | | type: [String, Number], |
| | | required: true, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: "assessment", |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | reportNo: "", |
| | | reportName: "", |
| | | }, |
| | | evaluateInfo: {}, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | { required: true, message: "请输入报告名称", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '课题名称依准确性、报告内容完整性:研究目标是否完整、是否研究工作内容合理性、是否围绕目标展开开、是否具有逻辑性和条理性', |
| | | criteria: |
| | | "课题名称依准确性、报告内容完整性:研究目标是否完整、是否研究工作内容合理性、是否围绕目标展开开、是否具有逻辑性和条理性", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '文献资料调查:全面性、系统性编辑逻辑顺畅,表达规范', |
| | | criteria: "文献资料调查:全面性、系统性编辑逻辑顺畅,表达规范", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能完成研究目标、方法完整、完整、可靠;', |
| | | criteria: |
| | | "专业/技术路线与方法:合理性、可行性;实验设计科学、能完成研究目标、方法完整、完整、可靠;", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '实验验证工作可行性强,团队工作调度支持实验设备、材料等条件的准备良好,时间计划合理,能效按时完成', |
| | | criteria: |
| | | "实验验证工作可行性强,团队工作调度支持实验设备、材料等条件的准备良好,时间计划合理,能效按时完成", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '实验设计合理性:①对照设置,重复次数,样本量足够。②变量控制:自变量控制,因变量测量,干扰因素分析识别;确保结果的准确性③验证结果解释分析:符合科学原理、逻辑严密、不存在漏洞。具有实际应用价值,解决了实际问题或实现了研究目的。', |
| | | criteria: |
| | | "实验设计合理性:①对照设置,重复次数,样本量足够。②变量控制:自变量控制,因变量测量,干扰因素分析识别;确保结果的准确性③验证结果解释分析:符合科学原理、逻辑严密、不存在漏洞。具有实际应用价值,解决了实际问题或实现了研究目的。", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | criteria: |
| | | "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。", |
| | | fullScore: 2, |
| | | score: 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 || ''; |
| | | if (val && this.id) { |
| | | this.fetchDetail(); |
| | | } |
| | | }, |
| | | immediate: true |
| | | immediate: true, |
| | | }, |
| | | id(val) { |
| | | if (this.modelValue && val) { |
| | | this.fetchDetail(); |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | async fetchDetail() { |
| | | try { |
| | | const res = await evaluateDetail({ id: this.id }); |
| | | if (res) { |
| | | this.evaluateInfo = { ...res }; |
| | | this.form.reportNo = res.reportCode || ""; |
| | | this.form.reportName = res.reportName || ""; |
| | | // 详情回显分数 |
| | | if (res.evaluateScore) { |
| | | if ( |
| | | this.type === "detail" && |
| | | typeof res.evaluateScore === "string" |
| | | ) { |
| | | const scoreArr = res.evaluateScore |
| | | .split(",") |
| | | .map((s) => Number(s)); |
| | | this.criteriaList.forEach((item, idx) => { |
| | | item.score = scoreArr[idx] || 0; |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } catch (e) { |
| | | this.$message && this.$message.error("获取详情失败"); |
| | | } |
| | | }, |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | this.$emit("update:modelValue", false); |
| | | this.$emit("close"); |
| | | }, |
| | | 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 |
| | | })) |
| | | // 拼接分数 |
| | | const evaluateScore = this.criteriaList |
| | | .map((item) => item.score) |
| | | .join(","); |
| | | const params = { |
| | | id: this.id, |
| | | evaluateScore, |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | evaluate(params).then((res) => { |
| | | if (res) { |
| | | this.$message && this.$message.success("评定成功"); |
| | | this.handleClose(); |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | this.$message && this.$message.error("评定失败"); |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | sums[index] = "合计"; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | 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; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | sums[index] += " 分"; |
| | | } else { |
| | | sums[index] = ''; |
| | | sums[index] = ""; |
| | | } |
| | | }); |
| | | return sums; |
| | |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | colspan: 1, |
| | | }; |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | return [0, 0]; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #FAFAFA !important; |
| | | background: #fafafa !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="queryForm" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="项目组名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.teamName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="课题类型:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-select v-model="form.reportType" placeholder="请选择"> |
| | | <el-option label="可研报告" :value="1" /> |
| | | <el-option label="可行报告" :value="2" /> |
| | | <el-option label="工艺开发工具" :value="3" /> |
| | | <el-option label="验证与发布" :value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="课题名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-form-item label="报告名称:"> |
| | | <el-input v-model="form.reportName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="提交人:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.staffNames" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="草稿箱" :value="-1" /> |
| | | <el-option label="待审核" :value="1" /> |
| | | <el-option label="待评定" :value="2" /> |
| | | <el-option label="已评定" :value="3" /> |
| | | <el-option label="已驳回" :value="4" /> |
| | | <el-option label="已撤回" :value="5" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="top-box-integral"> |
| | | <div style="background-color:rgba(232, 250, 246, 1)" v-for="item in 3" :key="item" |
| | | class="top-box-integral-card"> |
| | | <div class="top-box-integral-card-title">{{ ['课题合计数量', '待评定', '已评定'][item - 1] }}</div> |
| | | <div style="color:rgba(4, 156, 154, 1)" class="top-box-integral-card-num">99.9</div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">课题合计数量</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.totalCount || 0 }} |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">待评定</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.toEvaluatedCount || 0 }} |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="background-color: rgba(232, 250, 246, 1)" |
| | | class="top-box-integral-card" |
| | | > |
| | | <div class="top-box-integral-card-title">已评定</div> |
| | | <div |
| | | style="color: rgba(4, 156, 154, 1)" |
| | | class="top-box-integral-card-num" |
| | | > |
| | | {{ statistics.evaluatedCount || 0 }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="tip-warring"> |
| | | <div> |
| | | 【注意】每个课题交付评分标准: |
| | | </div> |
| | | <div>【注意】每个课题交付评分标准:</div> |
| | | <div> |
| | | 1、课题由工程师/化验师设定,并清晰完整完成课题目标,评优秀3分; |
| | | </div> |
| | |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="课题类型" /> |
| | | <el-table-column prop="age" label="报告编号" /> |
| | | <el-table-column prop="age" label="报告名称" /> |
| | | <el-table-column prop="age" label="提交人" /> |
| | | <el-table-column prop="age" label="评定结果" /> |
| | | <el-table-column prop="age" label="累积分值" /> |
| | | <el-table-column prop="age" label="评定时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <el-table-column prop="teamName" label="所属项目组" /> |
| | | <el-table-column prop="reportType" label="课题类型"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | <span v-if="row.reportType == 1">可研报告</span> |
| | | <span v-else-if="row.reportType == 2">可行报告</span> |
| | | <span v-else-if="row.reportType == 3">工艺开发工具</span> |
| | | <span v-else-if="row.reportType == 4">验证与发布</span> |
| | | <span v-else>--</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <el-table-column prop="reportCode" label="报告编号" /> |
| | | <el-table-column prop="reportName" label="报告名称" /> |
| | | <el-table-column prop="createBy" label="提交人" /> |
| | | <el-table-column prop="evaluatePersonName" label="评定人员" /> |
| | | <el-table-column prop="evaluateScore" label="评定分数" /> |
| | | <el-table-column prop="totalScore" label="累积分值" /> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-button type="text">评定</el-button> |
| | | <el-tag v-if="row.status == 3" type="info" color="#fff" |
| | | >已评定</el-tag |
| | | > |
| | | <el-tag v-else-if="row.status == 2" type="success">待评定</el-tag> |
| | | <el-tag v-else-if="row.status == 1" type="warning">待审核</el-tag> |
| | | <el-tag v-else-if="row.status == 4" type="danger">已驳回</el-tag> |
| | | <el-tag v-else-if="row.status == 5" type="info">已撤回</el-tag> |
| | | <el-tag v-else type="default">草稿箱</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleDetail(row)">详情</el-button> |
| | | <el-button |
| | | type="text" |
| | | @click="handleAssessment(row)" |
| | | v-if="row.status == 2" |
| | | >评定</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" |
| | | @submit="handleAssessmentSubmit" /> |
| | | <AssessmentDialog |
| | | :modelValue="assessmentVisible" |
| | | :id="currentId" |
| | | :type="dialogType" |
| | | @close="handleAssessmentSubmit" |
| | | @submit="handleAssessmentSubmit" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | import AssessmentDialog from "./components/AssessmentDialog.vue"; |
| | | import { pageList, evaluateCount, evaluateDetail } from "./service.js"; |
| | | |
| | | export default { |
| | | name: 'TaskList', |
| | | name: "TaskList", |
| | | components: { |
| | | AssessmentDialog |
| | | AssessmentDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | form: {}, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | pageNum: 1, |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {} |
| | | } |
| | | currentId: null, |
| | | dialogType: '', |
| | | statistics: { |
| | | totalCount: 0, |
| | | toEvaluatedCount: 0, |
| | | evaluatedCount: 0, |
| | | }, |
| | | }; |
| | | }, |
| | | methods: { |
| | | async getList() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await pageList(params); |
| | | if (res && res.data) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } |
| | | }, |
| | | async getStatistics() { |
| | | const params = { ...this.queryForm, ...this.form }; |
| | | const res = await evaluateCount(params); |
| | | if (res && res.data) { |
| | | this.statistics = res.data; |
| | | } |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | this.queryForm.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | this.queryForm.pageSize = size; |
| | | this.getList(); |
| | | }, |
| | | getList() { |
| | | |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | handleReset() { |
| | | this.form = {}; |
| | | this.queryForm = { pageSize: 10, pageNum: 1 }; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | this.currentId = row.id; |
| | | this.dialogType = 'detail'; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.currentId = row.id; |
| | | this.dialogType = 'assessment'; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | } |
| | | } |
| | | } |
| | | this.assessmentVisible=false; |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.getList(); |
| | | this.getStatistics(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | background: #e8faf6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | font-family: "SF Compact Display Black"; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | color: #049c9a; |
| | | line-height: 60px; |
| | | } |
| | | } |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 项目组总积分分页列表 |
| | | export const pageList = (data) => { |
| | | return axios.post('/api/t-feasibility-study-report/pageList', { ...data }) |
| | | } |
| | | // 评定 |
| | | export const evaluate = (data) => { |
| | | return axios.put(`/open/t-feasibility-study-report/evaluate?id=${data.id}&evaluateScore=${data.evaluateScore}`, { params:data }) |
| | | } |
| | | // 查看详情 |
| | | export const evaluateDetail = (data) => { |
| | | return axios.get('/open/t-feasibility-study-report/evaluateDetail', { params:data }) |
| | | } |
| | | // 统计 |
| | | export const evaluateCount = (data) => { |
| | | return axios.post('/api/t-feasibility-study-report/evaluateCount', {...data }) |
| | | } |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="form" |
| | | :tableData="tableData" |
| | | :total="total" |
| | | :height="null" |
| | | @handlePageChange="handlePageChange" |
| | | @handleSizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input |
| | | v-model="form.experimentCode" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间:"> |
| | | <el-date-picker v-model="value1" type="daterange" range-separator="至" start-placeholder="开始日期" |
| | | end-placeholder="结束日期"> |
| | | </el-date-picker> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input |
| | | v-model="form.experimentName" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建日期:"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | value-format="yyyy-MM-dd" |
| | | @change="handleDateChange" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="是" value="1"></el-option> |
| | | <el-option label="否" value="0"></el-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="待提交" :value="1"></el-option> |
| | | <el-option label="待评定" :value="2"></el-option> |
| | | <el-option label="已评定" :value="3"></el-option> |
| | | <el-option label="已封存" :value="4"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</el-button> |
| | | <el-button |
| | | type="primary" |
| | | style="margin-left: 10px" |
| | | @click="handleSearch" |
| | | >查询</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="tableTitle"> |
| | | <div class="flex a-center"> |
| | | <div |
| | | class="title active"> |
| | | 实验结果汇报列表 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目课题方案" /> |
| | | <el-table-column prop="age" label="实验编号" /> |
| | | <el-table-column prop="age" label="工艺工程师" /> |
| | | <el-table-column prop="age" label="化验师" /> |
| | | <el-table-column prop="age" label="实验员" /> |
| | | <el-table-column prop="age" label="创建日期" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <template #default="{ row }"> |
| | | <span :style="{ color: ['green', 'red'][row.status - 1] }">{{ ['是', '否'][row.status - 1] |
| | | }}</span> |
| | | <el-table-column |
| | | prop="projectName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="processEngineerName" |
| | | label="工艺工程师" |
| | | ></el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="laboratoryChemistName" |
| | | label="化验师" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimenterName" |
| | | label="实验员" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="createTime" |
| | | label="创建日期" |
| | | width="180" |
| | | ></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-button type="text">评定</el-button> |
| | | <el-table-column label="操作" width="180"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { getList} from "./service"; |
| | | |
| | | export default { |
| | | name: 'TechnicianJobEvaluation', |
| | | components: { |
| | | }, |
| | | name: "TestResultReport", |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | projectName: "", |
| | | experimentCode: "", |
| | | experimentName: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | status: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | dateRange: [], |
| | | tableData: [], |
| | | total: 0, |
| | | } |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | resetForm() { |
| | | this.form = { |
| | | projectName: "", |
| | | experimentCode: "", |
| | | experimentName: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | status: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }; |
| | | this.dateRange = []; |
| | | this.getTableData(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | handleSearch() { |
| | | this.getTableData(); |
| | | }, |
| | | getList() { |
| | | |
| | | handleDetail(id) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: id, |
| | | type: "view", |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }); |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | getTableData() { |
| | | const params = { |
| | | ...this.form, |
| | | }; |
| | | getList(params) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } else { |
| | | this.$message.error(res.msg || "获取数据失败"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | this.$message.error("获取数据失败"); |
| | | }); |
| | | }, |
| | | handleDateChange(val) { |
| | | if (val) { |
| | | this.form.startTime = val[0]; |
| | | this.form.endTime = val[1]; |
| | | } else { |
| | | this.form.startTime = ""; |
| | | this.form.endTime = ""; |
| | | } |
| | | }, |
| | | getStatusType(status) { |
| | | const statusMap = { |
| | | "-1": "info", |
| | | 1: "warning", |
| | | 2: "warning", |
| | | 3: "success", |
| | | 4: "info", |
| | | 5: "warning", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }, |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | | "-1": "草稿箱", |
| | | 1: "待提交", |
| | | 2: "待评定", |
| | | 3: "已评定", |
| | | 4: "已封存", |
| | | 5: "已解封", |
| | | }; |
| | | return statusMap[status] || "未知"; |
| | | }, |
| | | handlePageChange(pageNum) { |
| | | this.form.pageNum = pageNum; |
| | | this.getTableData(); |
| | | }, |
| | | handleSizeChange(pageSize) { |
| | | this.form.pageSize = pageSize; |
| | | this.getTableData(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .top-box-integral { |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .tableTitle { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | gap: 28px; |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | align-items: center; |
| | | .title, |
| | | .drafts { |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | cursor: pointer; |
| | | font-weight: 400; |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | .title { |
| | | padding: 16px 29px; |
| | | } |
| | | .drafts { |
| | | padding: 16px 65px; |
| | | margin-left: 16px; |
| | | } |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 列表 |
| | | export const getList = (data) => { |
| | | return axios.post('/api/t-experiment-result-report/pageList', { ...data }) |
| | | } |
| | |
| | | <template> |
| | | <Card> |
| | | <template> |
| | | <div class="header-title" style="margin-bottom: 18px;"> |
| | | <div class="header-title" style="margin-bottom: 18px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <el-button class="el-icon-plus" type="primary" @click="showScheduling = true"> 选择实验调度</el-button> |
| | | <el-button |
| | | class="el-icon-plus" |
| | | type="primary" |
| | | v-if="isEdit" |
| | | @click="showScheduling = true" |
| | | > |
| | | 选择实验调度</el-button |
| | | > |
| | | </div> |
| | | <Table :tableData="tableData" :total="total" :height="null"> |
| | | <Table :data="tableData" :total="0" :height="null"> |
| | | <template> |
| | | <el-table-column prop="planCode" label="所属项目课题方案"></el-table-column> |
| | | <el-table-column prop="planName" label="实验编号"></el-table-column> |
| | | <el-table-column prop="planName" label="实验名称"></el-table-column> |
| | | <el-table-column prop="stage" label="通知时间"></el-table-column> |
| | | <el-table-column prop="stage" label="实验开始时间"></el-table-column> |
| | | <el-table-column prop="stage" label="实验结束时间"></el-table-column> |
| | | <el-table-column prop="stage" label="参加人员"></el-table-column> |
| | | <el-table-column prop="creator" label="状态"></el-table-column> |
| | | <el-table-column |
| | | type="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="projectName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentDate" |
| | | label="通知时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentStartTime" |
| | | label="实验开始时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentEndTime" |
| | | label="实验结束时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="participantsName" |
| | | label="参加人员" |
| | | ></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </Table> |
| | | <div class="header-title" style="margin-top: 60px;"> |
| | | <div class="header-title" style="margin-top: 60px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>被评定实验员</div> |
| | | </div> |
| | | <el-button class="el-icon-plus" type="primary" @click="addMember"> 选择实验员</el-button> |
| | | <el-button |
| | | class="el-icon-plus" |
| | | v-if="isEdit" |
| | | type="primary" |
| | | @click="addMember" |
| | | > |
| | | 选择实验员</el-button |
| | | > |
| | | </div> |
| | | <div class="member-list"> |
| | | <div class="member-list-card"> |
| | | <div class="member-item"> |
| | | <div class="member-title">实验员</div> |
| | | <div class="member-name-box-2"> |
| | | <div v-for="i in [1, 2, 3, 4, 5, 6, 7, 8]" :key="i" class="member-name">张三</div> |
| | | <div |
| | | v-for="i in selectedParticipants" |
| | | :key="i.id" |
| | | class="member-name" |
| | | > |
| | | {{ i.nickName }} |
| | | </div> |
| | | <div class="member-edit" @click="addMember">修改</div> |
| | | </div> |
| | | <div class="member-edit" @click="handleEditMember" v-if="isEdit"> |
| | | 修改 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 18px;margin-top: 60px;"> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 18px; margin-top: 60px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>工作标准评定</div> |
| | | </div> |
| | | </div> |
| | | <EvaluateTable :type="2" /> |
| | | <EvaluateTable :type="2" ref="evaluateTable" /> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | <el-button type="primary" @click="submitForm()">保存</el-button> |
| | | <!-- <el-button>存草稿</el-button> --> |
| | | </div> |
| | | </template> |
| | | <SelectMember ref="selectMember" /> |
| | | <ExperimentalScheduling :show="showScheduling" /> |
| | | <SelectMemberSimple |
| | | ref="selectMember" |
| | | @submit="handleMemberSubmit" |
| | | roleType="5" |
| | | /> |
| | | <ExperimentalScheduling |
| | | :show="showScheduling" |
| | | @submit="handleSchedulingSubmit" |
| | | @close="handleSchedulingClose" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import ExperimentalScheduling from "@/views/dataManagement/confirmation-sheet/components/experimental-scheduling"; |
| | | import SelectMemberSimple from "@/components/SelectMemberSimple/index.vue"; |
| | | import ExperimentalScheduling from "@/views/dataManagement/schemeManagement/components/experimental-scheduling"; |
| | | import { getEvaluateChemist, add } from "./service.js"; |
| | | import moment from "moment"; |
| | | |
| | | export default { |
| | | name: 'AddTesterWorkerEvaluate', |
| | | name: "AddTesterWorkerEvaluate", |
| | | components: { |
| | | ExperimentalScheduling, |
| | | SelectMemberSimple, |
| | | }, |
| | | data() { |
| | | return { |
| | | showScheduling: false, |
| | | participantsData: [], |
| | | selectedParticipants: [], |
| | | tableData: [], |
| | | isEdit: true, // 是否为编辑模式 |
| | | // 状态映射表 |
| | | statusTypeMap: { |
| | | "-1": "info", |
| | | 1: "warning", |
| | | 2: "success", |
| | | 3: "info", |
| | | }, |
| | | statusTextMap: { |
| | | "-1": "草稿箱", |
| | | 1: "待确认", |
| | | 2: "已确认", |
| | | 3: "已封存", |
| | | }, |
| | | }; |
| | | }, |
| | | async created() { |
| | | // const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | // this.userRole = userInfo.roleType || ""; |
| | | // 检查是否为编辑模式 |
| | | this.participantsData = []; |
| | | this.selectedParticipants = []; |
| | | this.tableData = []; |
| | | this.isEdit = true; // 是否为编辑模式 |
| | | |
| | | if (this.$route.query.id) { |
| | | this.isEdit = this.$route.query.type === "view" ? false : true; |
| | | this.editId = this.$route.query.id; |
| | | await this.loadEditData(); |
| | | } |
| | | }, |
| | | methods: { |
| | | submitForm() { |
| | | handleSchedulingClose() { |
| | | this.showScheduling = false; |
| | | }, |
| | | handleSchedulingSubmit(data) { |
| | | console.log("data data", data); |
| | | this.tableData = data || []; |
| | | if (data && data.length > 0 && data[0].id) { |
| | | getEvaluateChemist({ dispatchId: data[0].id }) |
| | | .then((res) => { |
| | | console.log("获取参加人员列表:", res); |
| | | if (res) { |
| | | this.participantsData = res.map((item) => { |
| | | return { |
| | | ...item, |
| | | roleType: 5, |
| | | }; |
| | | }); |
| | | } else { |
| | | this.$message.error(res.msg || "获取参加人员列表失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | this.$message.error("获取参加人员列表失败"); |
| | | console.error("获取参加人员列表失败:", err); |
| | | }); |
| | | } |
| | | }, |
| | | getStatusType(status) { |
| | | return this.statusTypeMap[status] || "info"; |
| | | }, |
| | | getStatusText(status) { |
| | | return this.statusTextMap[status] || "未知"; |
| | | }, |
| | | handleEditMember() { |
| | | this.$refs.selectMember.open( |
| | | this.participantsData, |
| | | this.selectedParticipants |
| | | ); |
| | | }, |
| | | // ===== 人员相关方法 ===== |
| | | addMember() { |
| | | this.$refs.selectMember.open() |
| | | if (this.tableData.length == 0) { |
| | | this.$message.error("请先选择所属实验调度"); |
| | | return; |
| | | } |
| | | this.$refs.selectMember.open(this.participantsData, []); |
| | | }, |
| | | handleMemberSubmit(selectedMembers) { |
| | | this.selectedParticipants = selectedMembers; |
| | | this.$refs.selectMember.close(); |
| | | }, |
| | | // 将分数转换为评定值 |
| | | getEvaluateValue(score) { |
| | | // 2分 = 良好(1), 1分 = 正确(2), 0分 = 失误(3) |
| | | const scoreMap = { |
| | | 2: 1, // 良好 |
| | | 1: 2, // 正确 |
| | | 0: 3, // 失误 |
| | | }; |
| | | return scoreMap[score] || 3; // 默认返回失误 |
| | | }, |
| | | submitForm() { |
| | | const evaluateTable = this.$refs.evaluateTable; |
| | | if (!evaluateTable) { |
| | | this.$message.warning("评价表格未加载完成"); |
| | | return; |
| | | } |
| | | const activeIndex = evaluateTable.activeIndex; |
| | | |
| | | const evaluateData = { |
| | | evaluateOne: this.getEvaluateValue(activeIndex[0].score), |
| | | evaluateTwo: this.getEvaluateValue(activeIndex[1].score), |
| | | evaluateThree: this.getEvaluateValue(activeIndex[2].score), |
| | | evaluateFour: this.getEvaluateValue(activeIndex[3].score), |
| | | evaluateFive: this.getEvaluateValue(activeIndex[4].score), |
| | | evaluateSix: this.getEvaluateValue(activeIndex[5].score), |
| | | evaluateTime: moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | resultEvaluateJson: JSON.stringify(activeIndex), |
| | | dispatchId: this.tableData[0]?.id, |
| | | evaluateType: 3, |
| | | userId: this.selectedParticipants[0].userId, |
| | | dispatchId: this.tableData[0]?.id, |
| | | status: 1, |
| | | }; |
| | | |
| | | console.log("11111111111", evaluateTable.activeIndex); |
| | | console.log("2222222222222222", evaluateData); |
| | | add(evaluateData).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("保存成功"); |
| | | this.$router.back(); |
| | | } else { |
| | | this.$message.error(res.msg || "保存失败"); |
| | | } |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | |
| | | &:before { |
| | | content: '*'; |
| | | color: #F56C6C; |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | |
| | | width: 340px; |
| | | height: 400px; |
| | | border-radius: 8px; |
| | | border: 1px solid #DCDFE6; |
| | | background: linear-gradient(to bottom, rgba(255, 77, 79, 0.20) 0%, rgba(255, 242, 194, 0) 70%); |
| | | border: 1px solid #dcdfe6; |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(255, 77, 79, 0.2) 0%, |
| | | rgba(255, 242, 194, 0) 70% |
| | | ); |
| | | |
| | | .member-item { |
| | | height: 100%; |
| | |
| | | .member-title { |
| | | margin-top: 20px; |
| | | width: 100%; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | font-weight: bold; |
| | | font-size: 16px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | |
| | | .member-name { |
| | | width: 60px; |
| | | height: 60px; |
| | | background: #7D8B79; |
| | | background: #7d8b79; |
| | | border-radius: 50%; |
| | | text-align: center; |
| | | line-height: 60px; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .member-edit { |
| | |
| | | transform: translateX(-50%); |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #FF4D4F; |
| | | color: #ff4d4f; |
| | | line-height: 22px; |
| | | width: 40px; |
| | | background: #FFF1F0; |
| | | background: #fff1f0; |
| | | border-radius: 4px; |
| | | border: 1px solid #FFCCC7; |
| | | border: 1px solid #ffccc7; |
| | | text-align: center; |
| | | } |
| | | } |
| | |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.projectName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.experimentNo" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.experimentName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="评定时间:"> |
| | | <el-date-picker v-model="value1" type="daterange" range-separator="至" start-placeholder="开始日期" |
| | | <el-date-picker v-model="form.dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" |
| | | end-placeholder="结束日期"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="tableTitle"> |
| | | <div class="flex a-center"> |
| | | <div class="title" :class="{ active: currentType === 'list' }" |
| | | @click="handleTypeChange('list')"> |
| | | <div class="title active" > |
| | | 实验员工作评定列表</div> |
| | | <div class="drafts" :class="{ active: currentType === 'draft' }" |
| | | @click="handleTypeChange('draft')">草稿箱</div> |
| | | |
| | | </div> |
| | | <el-button @click="handleAdd" class="el-icon-plus" type="primary"> |
| | | 新增实验员工作评定</el-button> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="检测项名称" /> |
| | | <el-table-column prop="age" label="检测项编号" /> |
| | | <el-table-column prop="age" label="备注" /> |
| | | <el-table-column prop="age" label="创建人" /> |
| | | <el-table-column prop="age" label="创建时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <el-table-column prop="teamName" label="所属项目课题方案" /> |
| | | <el-table-column prop="experimentCode" label="实验编号" /> |
| | | <el-table-column prop="experimentName" label="实验名称" /> |
| | | <el-table-column prop="chemistName" label="被评定实验员" /> |
| | | <el-table-column prop="chemistIntegral" label="评定分数" /> |
| | | <el-table-column prop="evaluateTime" label="评定时间" /> |
| | | <el-table-column label="操作" width="180"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="assessmentVisible = true">详情</el-button> |
| | | <el-button type="text" style="color: #1890ff" @click="handleDetail(row)">详情</el-button> |
| | | <el-button type="text" style="color: #1890ff" @click="handleEdit(row)">编辑</el-button> |
| | | <el-button type="text" style="color: #1890ff" @click="handleDelete(row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import { chemistEvaluateList } from './service' |
| | | export default { |
| | | name: 'TesterWorkerEvaluate', |
| | | data() { |
| | | return { |
| | | currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱 |
| | | form: { |
| | | projectName: '', |
| | | experimentNo: '', |
| | | experimentName: '', |
| | | dateRange: [] |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | loading: false |
| | | } |
| | | }, |
| | | methods: { |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: '/deliveryAssessment/addTesterWorkerEvaluate' |
| | | async getList() { |
| | | this.loading = true |
| | | const params = { |
| | | ...this.queryForm, |
| | | projectName: this.form.projectName, |
| | | experimentNo: this.form.experimentNo, |
| | | experimentName: this.form.experimentName, |
| | | startTime: this.form.dateRange && this.form.dateRange[0] ? this.form.dateRange[0] : '', |
| | | endTime: this.form.dateRange && this.form.dateRange[1] ? this.form.dateRange[1] : '' |
| | | } |
| | | try { |
| | | const res = await chemistEvaluateList(params) |
| | | this.tableData = (res.data?.records || []).map(item => { |
| | | let score = ''; |
| | | try { |
| | | const json = typeof item.resultEvaluateJson === 'string' |
| | | ? JSON.parse(item.resultEvaluateJson) |
| | | : item.resultEvaluateJson; |
| | | score = json?.score || ''; |
| | | } catch (e) {} |
| | | return { ...item, score }; |
| | | }) |
| | | this.total = res.data?.total || 0 |
| | | } finally { |
| | | this.loading = false |
| | | } |
| | | }, |
| | | handleSearch() { |
| | | this.queryForm.pageNum = 1 |
| | | this.getList() |
| | | }, |
| | | handleReset() { |
| | | this.form = { |
| | | projectName: '', |
| | | experimentNo: '', |
| | | experimentName: '', |
| | | dateRange: [] |
| | | } |
| | | this.queryForm.pageNum = 1 |
| | | this.getList() |
| | | }, |
| | | |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: '/deliveryAssessment/addTesterWorkerEvaluate' |
| | | }) |
| | | }, |
| | | handleDetail(row) { |
| | | // 详情逻辑后续补充 |
| | | }, |
| | | handleEdit(row) { |
| | | // 编辑逻辑后续补充 |
| | | }, |
| | | handleDelete(row) { |
| | | // 删除逻辑后续补充 |
| | | } |
| | | |
| | | }, |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
| | | this.getList(); |
| | | }, |
| | | mounted() { |
| | | this.getList() |
| | | } |
| | | } |
| | | </script> |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 项目组总积分分页列表 |
| | | export const pageList = (data) => { |
| | | // 获取化验师工作评定分页列表 |
| | | export const chemistEvaluateList = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/testerEvaluateList', { ...data }) |
| | | } |
| | | |
| | | export const add = (data) => { |
| | | return axios.post('/api/t-result-work-evaluate/add', { ...data }) |
| | | } |
| | | export const update = (data) => { |
| | | return axios.post('/api/t-tester-other-task/update', { ...data }) |
| | | |
| | | export const getEvaluateChemist = (data) => { |
| | | return axios.get('/open/t-result-work-evaluate/getEvaluateTester', { params:data }) |
| | | } |
| | | export const deleteById = (data) => { |
| | | return axios.delete('/open/t-tester-other-task/deleteById', { params:data }) |
| | | } |
| | | export const deleteByIds = (data) => { |
| | | return axios.delete('/open/t-tester-other-task/deleteByIds', { params:data }) |
| | | } |
| | | export const getDetailById = (data) => { |
| | | return axios.delete('/open/t-tester-other-task/getDetailById', { params:data }) |
| | | } |
| | | |
| | | // export const getEvaluateChemist = (data) => { |
| | | // return axios.get('/open/t-result-work-evaluate/getEvaluateTester', { params:data }) |
| | | // } |
| | | |
| | | // export const update = (data) => { |
| | | // return axios.post('/api/t-tester-other-task/update', { ...data }) |
| | | // } |
| | | // export const deleteById = (data) => { |
| | | // return axios.delete('/open/t-tester-other-task/deleteById', { params:data }) |
| | | // } |
| | | // export const deleteByIds = (data) => { |
| | | // return axios.delete('/open/t-tester-other-task/deleteByIds', { params:data }) |
| | | // } |
| | | |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="检测项评定详情" width="70%" @close="handleClose"> |
| | | <el-form :model="form" inline label-position="top" :rules="rules" ref="formRef"> |
| | | <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-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-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-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" /> |
| | | <el-input-number |
| | | v-model="row.score" |
| | | :min="0" |
| | | :max="row.fullScore" |
| | | :step="1" |
| | | :disabled="type === 'detail'" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="rule" label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、规程型课题评定总分的满分为5分。</div> |
| | | <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div> |
| | | <div> |
| | | 2、某分项工作完成,但出现以下三种错误中的1种,则减1分: |
| | | </div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | <div> |
| | | 3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </el-row> |
| | | </div> |
| | | <!-- 化验师 审批人 --> |
| | | <div class="assessed"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | <div class="assessed" v-if="evaluateInfo.status == 3"> |
| | | <div>评定时间:{{ evaluateInfo.evaluateTime }}</div> |
| | | <div>评定人:{{ evaluateInfo.evaluatePersonName }}</div> |
| | | </div> |
| | | <!-- 工艺工程师 --> |
| | | <!-- <template #footer> |
| | | <template #footer v-if="evaluateInfo.status === 2 && type=='approve'"> |
| | | <span class="select-member-footer"> |
| | | <el-button type="primary">提交评定结果</el-button> |
| | | <el-button type="primary" @click="handleSubmit">提交评定结果</el-button> |
| | | </span> |
| | | </template> --> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDetail, evaluate } from "../service.js"; |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | name: "AssessmentDialog", |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | default: () => {}, |
| | | }, |
| | | id: { |
| | | type: [String, Number], |
| | | required: true, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: "detail", // 'detail' 或 'evaluate' |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | reportNo: "", |
| | | reportName: "", |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | { required: true, message: "请输入报告名称", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范', |
| | | criteria: "文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范", |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;', |
| | | criteria: |
| | | "专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;", |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | criteria: |
| | | "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。", |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | ] |
| | | } |
| | | ], |
| | | evaluateInfo: {}, |
| | | }; |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | this.fetchDataById(); |
| | | } |
| | | }, |
| | | immediate: true |
| | | 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 getDetail(this.id); |
| | | const data = res || {}; |
| | | this.form.reportNo = data.itemCode || ""; |
| | | this.form.reportName = data.itemName || ""; |
| | | 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('update:modelValue', false); |
| | | 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 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 |
| | | })) |
| | | id: this.evaluateInfo.id, |
| | | evaluateScore: this.criteriaList |
| | | .map((item) => item.score || 0) |
| | | .join(","), |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | // 这里可以调用evaluate接口 |
| | | evaluate(assessmentData).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("提交成功"); |
| | | this.handleClose(); |
| | | }else{ |
| | | this.$message.error(res.message) |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | sums[index] = "合计"; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | 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; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | sums[index] += " 分"; |
| | | } else { |
| | | sums[index] = ''; |
| | | sums[index] = ""; |
| | | } |
| | | }); |
| | | return sums; |
| | |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | colspan: 1, |
| | | }; |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | return [0, 0]; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-th { |
| | | line-height: 40px; |
| | | background: #FAFAFA !important; |
| | | background: #fafafa !important; |
| | | color: #909399; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
New file |
| | |
| | | <template> |
| | | <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" po :close-on-click-modal="false" |
| | | @close="handleClose"> |
| | | <div class="approval-dialog"> |
| | | <!-- 左侧审批内容 --> |
| | | <div class="approval-content"> |
| | | <Card class="approval-content-card"> |
| | | <template style="position: relative"> |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属检测项</div> |
| | | </div> |
| | | </div> |
| | | <Table :height="null" :total="0" :data="tableData"> |
| | | <template> |
| | | <el-table-column prop="teamName" label="所属项目组" /> |
| | | <el-table-column prop="itemName" label="检测项名称" /> |
| | | <el-table-column prop="itemCode" label="检测项编号" /> |
| | | <el-table-column prop="remark" label="备注" /> |
| | | <el-table-column prop="createBy" label="创建人" /> |
| | | <el-table-column prop="createTime" label="创建时间" /> |
| | | </template> |
| | | </Table> |
| | | |
| | | |
| | | <el-form ref="form" :model="form" :rules="rules" inline label-position="top" |
| | | style="margin-top: 18px"> |
| | | <el-form-item prop="name" label="报告内容"> |
| | | <el-select v-model="form.reportContent" style="width: 100%;" disabled |
| | | placeholder="请选择报告内容"> |
| | | <el-option label="国家标准" :value="1" /> |
| | | <el-option label="分析方法开发" :value="2" /> |
| | | <el-option label="方法验证报告" :value="3" /> |
| | | <el-option label="方法确认" :value="4" /> |
| | | <el-option label="操作规程" :value="5" /> |
| | | <el-option label="方法转移记录清单" :value="6" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>报告正文</div> |
| | | </div> |
| | | </div> |
| | | <el-form-item prop="name" style="margin-top: 18px"> |
| | | <ai-editor :value="form.reportText" :readOnly="true" style="width: 100%;" |
| | | placeholder="请输入报告编号" /> |
| | | </el-form-item> |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>附件</span> |
| | | </div> |
| | | </div> |
| | | <el-form-item prop="name" style="margin-top: 18px"> |
| | | <el-upload action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList"> |
| | | <!-- <el-button size="small" type="primary">点击上传</el-button> --> |
| | | </el-upload> |
| | | </el-form-item> |
| | | |
| | | </el-form> |
| | | </template> |
| | | <!-- <SelectMember ref="selectMember" /> --> |
| | | </Card> |
| | | </div> |
| | | <!-- 右侧审批流程 --> |
| | | <div class="approval-flow"> |
| | | <div class="flow-content"> |
| | | <approval-process :processData="form.processData" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="approval-dialog-approve" v-if="type === 'approve'"> |
| | | <el-row :span="24"> |
| | | <el-col :span="12"> |
| | | <div class="status"> |
| | | <div class="status-title">审批结果</div> |
| | | <div class="status-content"> |
| | | <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1"> |
| | | 通过 |
| | | </div> |
| | | <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2"> |
| | | 驳回 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="remark"> |
| | | <div class="remark-title">审批意见</div> |
| | | <el-input type="textarea" v-model="remark" placeholder="请输入审批意见" /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | </div> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleApprove" v-if="type === 'approve'">确认</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import ApprovalProcess from '@/components/approvalProcess' |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetailInfo, getDetail, detailAuditReport } from '../../service' |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | | components: { |
| | | ApprovalProcess, |
| | | AiEditor |
| | | }, |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: "approve", // approve-审批,view-查看 |
| | | }, |
| | | data: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | id: { |
| | | type: String, |
| | | default: "", |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | reportText: "", |
| | | reportContent: "", |
| | | qaReportFiles: [], |
| | | processData: [], |
| | | }, |
| | | tableData: [], |
| | | fileList: [], |
| | | radio1: 1, |
| | | rules: {}, |
| | | status: "1", |
| | | remark: "", |
| | | }; |
| | | }, |
| | | computed: { |
| | | dialogTitle() { |
| | | return this.type === "approve" ? "方法验证报告审批" : "方法验证报告详情"; |
| | | }, |
| | | }, |
| | | watch: { |
| | | visible: { |
| | | handler(val) { |
| | | if (val && this.data.id) { |
| | | this.getDetailInfo() |
| | | } |
| | | if (val && this.data.itemId) { |
| | | this.getDetail() |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | }, |
| | | methods: { |
| | | getDetailInfo() { |
| | | getDetailInfo({ id: this.data.id }).then(res => { |
| | | if (res) { |
| | | this.form = { ...res, reportContent: Number(res.reportContent), processData: [] } |
| | | if (res.qaReportFileList && res.qaReportFileList.length > 0) { |
| | | this.fileList = res.qaReportFileList.map(file => ({ |
| | | name: file.fileName, |
| | | url: getFullUrl(file.fileUrl), |
| | | uid: file.id |
| | | })) |
| | | this.form.qaReportFileList = res.fileList |
| | | } else { |
| | | this.fileList = [] |
| | | this.form.qaReportFileList = [] |
| | | } |
| | | // 组装流程数据 |
| | | let processData = []; |
| | | // 提交节点 |
| | | processData.push({ |
| | | type: "primary", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "提交人:", value: res.updateBy || "" }, |
| | | { label: "提交时间:", value: res.createTime || "" }, |
| | | ], |
| | | }); |
| | | if (res.status == 2 || res.status == 3) { |
| | | processData.push({ |
| | | type: |
| | | res.status === 2 |
| | | ? "primary" |
| | | : res.status === 3 |
| | | ? "danger" |
| | | : "warning", |
| | | mode: "list", |
| | | fields: [ |
| | | { |
| | | label: "审核结果:", |
| | | value: |
| | | res.status === 2 |
| | | ? "通过" |
| | | : res.status === 3 |
| | | ? "驳回" |
| | | : "待审批", |
| | | }, |
| | | { label: "审批意见:", value: res.auditRemark || "" }, |
| | | { label: "审核人:", value: res.auditPersonName || "" }, |
| | | { label: "审核时间:", value: res.auditTime || "" }, |
| | | ], |
| | | }); |
| | | } else { |
| | | processData.push({ |
| | | type: "warning", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "等待审核" }, |
| | | ], |
| | | }); |
| | | } |
| | | // 如有卡片模式,按前述结构 push |
| | | |
| | | this.$nextTick(() => { |
| | | this.form.processData = processData; |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | getDetail() { |
| | | getDetail(this.data.itemId).then(res => { |
| | | if (res) { |
| | | this.tableData = [{ ...res, teamName: res.projectTeamVO.teamName }] |
| | | } |
| | | }) |
| | | }, |
| | | handleClose() { |
| | | this.$emit("close"); |
| | | |
| | | this.form.approvalComment = ""; |
| | | }, |
| | | handleApprove() { |
| | | if (!this.remark) { |
| | | this.$message.warning("请输入审批意见"); |
| | | return; |
| | | } |
| | | const params = { |
| | | id: this.data.id, |
| | | auditRemark: this.remark, |
| | | auditStatus: this.status === '1' ? 2 : 3 |
| | | }; |
| | | detailAuditReport(params).then(res => { |
| | | if (res) { |
| | | this.$message.success('审核成功'); |
| | | this.$emit("close"); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error(err.message || '审核失败'); |
| | | }); |
| | | }, |
| | | handleReject() { |
| | | if (!this.form.approvalComment) { |
| | | this.$message.warning("请输入审批意见"); |
| | | return; |
| | | } |
| | | this.$emit("reject", { |
| | | ...this.form, |
| | | status: "rejected", |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | ::v-deep .el-dialog__header { |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .approval-dialog { |
| | | display: flex; |
| | | height: 40vh; |
| | | |
| | | .approval-content { |
| | | flex: 3; |
| | | margin-right: 20px; |
| | | background: #ffffff; |
| | | box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08); |
| | | border-radius: 10px; |
| | | } |
| | | |
| | | .approval-flow { |
| | | padding: 40px 20px; |
| | | // width: 405px; |
| | | flex: 2; |
| | | background: #ffffff; |
| | | box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08); |
| | | border-radius: 10px; |
| | | |
| | | .flow-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | margin-bottom: 20px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .flow-content { |
| | | height: calc(100% - 40px); |
| | | overflow-y: auto; |
| | | |
| | | .el-form--inline .el-form-item { |
| | | margin-right: 83px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .approval-content-card { |
| | | height: calc(100% - 100px) !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .header-title { |
| | | // display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | margin-bottom: 20px; |
| | | gap: 13px; |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin-top: 18px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | div { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | |
| | | &:before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | } |
| | | |
| | | .header-title-left :first-child { |
| | | margin-top: 0; |
| | | } |
| | | } |
| | | |
| | | .header-title:first-child { |
| | | .header-title-left { |
| | | margin-top: 0; |
| | | } |
| | | } |
| | | |
| | | .item-title { |
| | | padding-left: 25px; |
| | | |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | margin: 18px 0; |
| | | |
| | | &:before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .approval-dialog-approve { |
| | | padding: 18px 20px; |
| | | // display: flex; |
| | | align-content: center; |
| | | |
| | | .status { |
| | | margin-right: 40px; |
| | | max-width: 60%; |
| | | } |
| | | |
| | | // align-items: center; |
| | | .status-title { |
| | | color: #222222; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | line-height: 14px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .status-content { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100%; |
| | | gap: 16px; |
| | | background: #ffffff; |
| | | border-radius: 10px; |
| | | border: 1px solid rgba(4, 156, 154, 0.5); |
| | | |
| | | .resolve { |
| | | border-radius: 10px; |
| | | flex: 1; |
| | | font-size: 16px; |
| | | // padding: 5px 55px; |
| | | font-weight: 400; |
| | | color: #333333; |
| | | cursor: pointer; |
| | | line-height: 32px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center |
| | | } |
| | | |
| | | .reject { |
| | | flex: 1; |
| | | border-radius: 10px; |
| | | font-size: 16px; |
| | | line-height: 32px; |
| | | // padding: 5px 55px; |
| | | font-weight: 400; |
| | | color: #333333; |
| | | cursor: pointer; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center |
| | | } |
| | | |
| | | .activeStatus { |
| | | background: #ebfefd; |
| | | color: #049c9a; |
| | | box-shadow: 0px 0px 6px 0px rgba(10, 109, 108, 0.25); |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | |
| | | .remark-title { |
| | | color: #222222; |
| | | font-family: "SourceHanSansCN-Medium"; |
| | | line-height: 14px; |
| | | margin-bottom: 16px; |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | gap: 20px; |
| | | |
| | | button { |
| | | width: 150px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <TableCustom |
| | | :queryForm="queryForm" |
| | | :height="0" |
| | | :total="total" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | > |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form |
| | | ref="searchForm" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="auto" |
| | | inline |
| | | > |
| | | <el-form-item label="所属项目组:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.teamName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="检测项名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.itemName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="检测项编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | <el-input v-model="form.itemCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="报告内容:"> |
| | | <el-select v-model="form.reportContent" placeholder="请选择"> |
| | | <el-option label="国家标准" value="1"></el-option> |
| | | <el-option label="分析方法开发" value="2"></el-option> |
| | | <el-option label="方法验证报告" value="3"></el-option> |
| | | <el-option label="方法确认" value="4"></el-option> |
| | | <el-option label="操作规程" value="5"></el-option> |
| | | <el-option label="方法转移记录清单" value="6"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="草稿箱" value="-1"></el-option> |
| | | <el-option label="已提交" value="1"></el-option> |
| | | <el-option label="待评定" value="2"></el-option> |
| | | <el-option label="已评定" value="3"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | <el-form-item label="" style="margin-left: 63px"> |
| | | <el-button |
| | | type="default" |
| | | style="margin-right: 10px" |
| | | @click="handleReset" |
| | | >重置</el-button |
| | | > |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="table-title"> |
| | | 项目检查项、检验包 |
| | | <div class="table-setting"> |
| | | <div class="flex a-center"> |
| | | <div class="table-title active">项目检测项、检验包列表</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #tableCustom> |
| | | <Table :data="tableData" :total="0" @row-click="handleRowClick" row-key="id" |
| | | :expand-row-keys="expandRowKeys"> |
| | | <Table |
| | | :data="tableData" |
| | | :total="total" |
| | | @row-click="handleRowClick" |
| | | row-key="id" |
| | | :height="null" |
| | | @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange" |
| | | :expand-row-keys="expandRowKeys" |
| | | > |
| | | <el-table-column type="expand" width="1"> |
| | | <template #default="{ row }"> |
| | | <div class="expand-box"> |
| | | <div style="display: flex; align-items: center"> |
| | | <div class="expand-box-title">报告列表</div> |
| | | <Table :total="0" :height="null"> |
| | | <el-table-column prop="name" label="报告内容" /> |
| | | <el-table-column prop="name" label="制订人" /> |
| | | <el-table-column prop="name" label="制订日期" /> |
| | | <el-table-column prop="name" label="检测项编号" /> |
| | | <el-table-column prop="name" label="审批人" /> |
| | | <el-table-column prop="name" label="审批时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | </div> |
| | | <Table |
| | | :data="reportList[row.id] || []" |
| | | :total="0" |
| | | :height="null" |
| | | > |
| | | <el-table-column prop="reportContent" label="报告内容"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已通过</el-tag> |
| | | <el-tag v-else type="success">未通过</el-tag> |
| | | <span>{{ getReportContentText(row.reportContent) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="developPerson" label="制订人" /> |
| | | <el-table-column prop="createTime" label="制订日期" /> |
| | | <el-table-column prop="auditPersonName" label="审批人" /> |
| | | <el-table-column prop="auditTime" label="审批时间" /> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff" |
| | | >待审核</el-tag |
| | | > |
| | | <el-tag v-if="row.status == 2" type="success" color="#fff" |
| | | >已通过</el-tag |
| | | > |
| | | <el-tag v-if="row.status == 3" type="danger" |
| | | >已驳回</el-tag |
| | | > |
| | | <el-tag v-if="row.status == 4" type="danger" |
| | | >已撤销</el-tag |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | <el-button type="text" v-if="row.status == 2" @click="handleApprove(row)" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="name" label="所属项目组" /> |
| | | <el-table-column prop="age" label="检测项名称" /> |
| | | <el-table-column prop="age" label="检测项编号" /> |
| | | <el-table-column prop="age" label="备注" /> |
| | | <el-table-column prop="age" label="创建人" /> |
| | | <el-table-column prop="age" label="创建时间" /> |
| | | <el-table-column prop="teamName" label="所属项目组" /> |
| | | <el-table-column prop="itemName" label="检测项名称" /> |
| | | <el-table-column prop="itemCode" label="检测项编号" /> |
| | | <el-table-column prop="remark" label="备注" /> |
| | | <el-table-column prop="createBy" label="创建人" /> |
| | | <el-table-column prop="createTime" label="创建时间" /> |
| | | <el-table-column prop="age" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-tag v-if="row.status == 1" type="info" color="#fff">已评定</el-tag> |
| | | <el-tag v-else type="success">待评定</el-tag> |
| | | <el-tag v-if="row.status == -1" type="info" color="#fff" |
| | | >草稿箱</el-tag |
| | | > |
| | | <el-tag v-else-if="row.status == 1" type="warning">已提交</el-tag> |
| | | <el-tag v-else-if="row.status == 2" type="primary">待评定</el-tag> |
| | | <el-tag v-else-if="row.status == 3" type="success">已评定</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <!-- 工艺工程师 --> |
| | | <!-- <el-button type="text" @click="assessmentVisible = true">评定</el-button> --> |
| | | <el-button type="text" @click="assessmentVisible = true">详情</el-button> |
| | | <template> |
| | | <el-button |
| | | v-if="row.status == 2 && isProcessEngineer" |
| | | type="text" |
| | | @click="handleReportDetail(row, 'approve')" |
| | | >评定</el-button |
| | | > |
| | | <el-button |
| | | v-else |
| | | type="text" |
| | | @click="handleReportDetail(row, 'detail')" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" |
| | | @submit="handleAssessmentSubmit" /> |
| | | <Approval |
| | | :visible="showApproval" |
| | | @close="closeApproval" |
| | | :data="rowData" |
| | | :type="approvalType" |
| | | /> |
| | | <AssessmentDialog |
| | | :modelValue="showAssessmentDialog" |
| | | :reportData="assessmentDialogData" |
| | | :id="assessmentDialogId" |
| | | :type="assessmentDialogType" |
| | | @close="handleCloseAssessmentDialog" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | import Approval from "./components/approval"; |
| | | import AssessmentDialog from "./components/AssessmentDialog.vue"; |
| | | import { getDataList, getListByItemId } from "./service"; |
| | | |
| | | export default { |
| | | name: 'TestingAndEvaluation', |
| | | name: "ProjectList", |
| | | components: { |
| | | AssessmentDialog |
| | | Approval, |
| | | AssessmentDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | itemCode: "", // 检测项编号 |
| | | itemName: "", // 检测项名称 |
| | | reportContent: "", // 报告内容 |
| | | status: "", // 状态,默认为空字符串表示全部 |
| | | teamName: "", // 项目组名称 |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }, |
| | | tableData: [{ id: 1 }, { id: 2 }], |
| | | rules: { |
| | | itemCode: [ |
| | | { max: 50, message: "检测项编号不能超过50个字符", trigger: "blur" }, |
| | | ], |
| | | itemName: [ |
| | | { max: 100, message: "检测项名称不能超过100个字符", trigger: "blur" }, |
| | | ], |
| | | teamName: [ |
| | | { max: 100, message: "项目组名称不能超过100个字符", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | showSubmitConfirm: false, |
| | | showDelConfirm: false, |
| | | confirmTitle: "", // 确认框标题 |
| | | confirmTip: "", // 确认框提示 |
| | | confirmType: "", // 确认框类型:'deleteReport'-删除报告, 'deleteItem'-删除检测项, 'revoke'-撤销审批 |
| | | rowId: "", |
| | | showApproval: false, |
| | | approvalType: "", // 新增:审批类型 |
| | | submitTitle: "", // 新增:提交评定确认框标题 |
| | | submitTip: "", // 新增:提交评定确认框提示 |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | pageNum: 1, |
| | | }, |
| | | tableData: [], |
| | | expandRowKeys: [], |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {}, |
| | | expandRowKeys: [] |
| | | } |
| | | rowData: {}, |
| | | reportList: {}, // 修改为对象,用行ID作为key |
| | | currentRow: null, |
| | | currentAction: "", |
| | | showItemApproval: false, |
| | | loading: false, |
| | | showAssessmentDialog: false, |
| | | assessmentDialogData: {}, |
| | | assessmentDialogId: "", |
| | | assessmentDialogType: "detail", |
| | | }; |
| | | }, |
| | | computed: { |
| | | isChemist() { |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | return userInfo.roleType == 4; // 2是化验师 |
| | | }, |
| | | isProcessEngineer() { |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | return userInfo.roleType == 3; // 3是工艺工程师 |
| | | }, |
| | | isApprovaler() { |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | return userInfo.roleType == 2; // 2是审批人 |
| | | }, |
| | | }, |
| | | methods: { |
| | | handleRowClick(row, column, event) { |
| | | if (column.label === '操作') return |
| | | if (this.expandRowKeys.includes(row.id)) { |
| | | this.expandRowKeys = this.expandRowKeys.filter(key => key !== row.id); |
| | | closeApproval() { |
| | | this.showApproval = false; |
| | | this.rowData = {}; |
| | | this.approvalType = ""; |
| | | this.getList(); |
| | | }, |
| | | handleCloseAssessmentDialog(){ |
| | | this.showAssessmentDialog = false; |
| | | this.assessmentDialogData = {}; |
| | | this.assessmentDialogId = ''; |
| | | this.assessmentDialogType = ''; // 或 'evaluate',根据业务调整 |
| | | this.getList(); |
| | | }, |
| | | async handleRowClick(row, column, event) { |
| | | if (column.label == "操作") return; |
| | | const currentOpenId = this.expandRowKeys[0]; |
| | | if (currentOpenId === row.id) { |
| | | // 如果点的是当前已展开的,关闭它 |
| | | this.expandRowKeys = []; |
| | | delete this.reportList[row.id]; |
| | | } else { |
| | | this.expandRowKeys = [row.id]; |
| | | // 如果有其他已展开的,先关闭 |
| | | if (currentOpenId) { |
| | | this.expandRowKeys = []; |
| | | delete this.reportList[currentOpenId]; |
| | | } |
| | | // 展开新行 |
| | | this.expandRowKeys = [row.id]; |
| | | try { |
| | | const res = await getListByItemId({ id: row.id }); |
| | | if (res) { |
| | | this.$set(this.reportList, row.id, res || []); |
| | | } else { |
| | | this.msgError(res.msg || "获取报告列表失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取报告列表失败:", error); |
| | | this.msgError("获取报告列表失败"); |
| | | } |
| | | } |
| | | }, |
| | | handleApprove(row) { |
| | | this.showApproval = true; |
| | | this.rowId = row.id; |
| | | this.rowData = row; |
| | | this.approvalType = "detail"; |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | this.queryForm.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | this.queryForm.pageSize = size; |
| | | this.getList(); |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | async getList() { |
| | | if (this.loading) return; |
| | | try { |
| | | this.loading = true; |
| | | const params = { |
| | | ...this.form, |
| | | pageNum: this.queryForm.pageNum, |
| | | pageSize: this.queryForm.pageSize, |
| | | }; |
| | | let res; |
| | | res = await getDataList(params); |
| | | if (res.code === 200) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } else { |
| | | this.$message.error(res.msg || "获取列表失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取列表失败:", error); |
| | | this.$message.error("获取列表失败,请重试"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | // 打开评定弹窗 |
| | | handleReportDetail(row, type) { |
| | | this.assessmentDialogData = row; |
| | | this.assessmentDialogId = row.id; |
| | | this.assessmentDialogType = type; // 或 'evaluate',根据业务调整 |
| | | this.showAssessmentDialog = true; |
| | | }, |
| | | getReportContentText(value) { |
| | | const contentMap = { |
| | | 1: "国家标准", |
| | | 2: "分析方法开发", |
| | | 3: "方法验证报告", |
| | | 4: "方法确认", |
| | | 5: "操作规程", |
| | | 6: "方法转移记录清单", |
| | | }; |
| | | return contentMap[value] || value; |
| | | }, |
| | | async handleSearch() { |
| | | try { |
| | | console.log("111111111"); |
| | | // this.loading = true; |
| | | await this.$refs.searchForm.validate(); |
| | | this.queryForm.pageNum = 1; |
| | | await this.getList(); |
| | | } catch (error) { |
| | | // 如果是校验失败,error会是false,此时不做任何处理,因为el-form会展示错误信息 |
| | | if (error !== false) { |
| | | this.$message.error("查询失败,请重试"); |
| | | } |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | async handleReset() { |
| | | try { |
| | | // this.loading = true; |
| | | this.$refs.searchForm.resetFields(); |
| | | // resetFields会把status也置为初始值'',需要根据当前tab重新设置 |
| | | this.form = { |
| | | itemCode: "", |
| | | itemName: "", |
| | | reportContent: "", |
| | | status: "", |
| | | teamName: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }; |
| | | this.queryForm.pageNum = 1; |
| | | await this.getList(); |
| | | } catch (error) { |
| | | this.$message.error("重置失败,请重试"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.getList(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | .el-icon-plus { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .top-box-integral { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | gap: 28px; |
| | | |
| | | &-card { |
| | | flex: 1; |
| | | background: #E8FAF6; |
| | | box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.06); |
| | | border-radius: 10px; |
| | | padding: 21px 20px; |
| | | |
| | | &-title { |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | .header-content { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | color: rgba(0, 0, 0, 0.88); |
| | | margin-left: 30px; |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | .box-title { |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | .header-icon { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .header-box { |
| | | border-radius: 16px; |
| | | margin-bottom: 30px; |
| | | } |
| | | |
| | | .table-setting { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .table-title { |
| | | width: 220px; |
| | | height: 50px; |
| | | background: #FFFFFF; |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049C9A; |
| | | border: 1px solid #dcdfe6; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049C9A; |
| | | color: #606266; |
| | | line-height: 27px; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &.active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | |
| | | .table-tit { |
| | | width: 166px; |
| | | height: 50px; |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | line-height: 27px; |
| | | margin-left: 16px; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &.active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .expand-box { |
| | | padding: 20px; |
| | | background: linear-gradient(180deg, #049C9A 0%, #0ACBCA 100%); |
| | | background: linear-gradient(180deg, #049c9a 0%, #0acbca 100%); |
| | | border-radius: 20px; |
| | | |
| | | &-title { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | color: #ffffff; |
| | | line-height: 24px; |
| | | margin-bottom: 20px; |
| | | } |
| | |
| | | |
| | | // 查询列表 |
| | | export function getDataList(data) { |
| | | return axios.post('/api/t-qa-test-item/pageList', { ...data }) |
| | | return axios.post('/api/t-qa-test-item/evaluateList', { ...data }) |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | //评定QA检测项管理 |
| | | export function evaluate(data) { |
| | | return axios.put(`/api/t-qa-test-item/evaluate`, { ...data }) |
| | | return axios.post(`/api/t-qa-test-item/evaluate`, { ...data }) |
| | | } |
| | | |
| | | |
| | |
| | | <div class="title">待办事项</div> |
| | | <!-- 待办事项列表将放置在这里 --> |
| | | <div class="todo-list"> |
| | | <div class="todo-item" v-for="i in 6" :key="i"> |
| | | <div class="todo-item" v-for="(item,index) in list" :key="index" @click.stop="toDetail(item)"> |
| | | <div class="todo-details"> |
| | | <div class="notice-card"> |
| | | <div class="todo-icon"></div> |
| | | <div class="red-notice"></div> |
| | | <div class="red-notice" v-if="item.isRead==0"></div> |
| | | </div> |
| | | |
| | | <span class="todo-title">您有 [1] 条 【项目课题方案】 等待审批</span> |
| | | <span class="todo-title" :title="item.content || ''">{{item.content||''}}</span> |
| | | </div> |
| | | <div class="todo-meta"> |
| | | <div class="me"></div> |
| | | <span class="todo-submitter">提交人: 王晓晓</span> |
| | | <span class="todo-submitter">提交人: {{item.commitName||''}}</span> |
| | | <div class="time"></div> |
| | | <span class="todo-submitter">2023.12.10 08:00</span> |
| | | <span class="todo-submitter">{{item.commitTime||''}}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | <script> |
| | | import { Calendar } from "ant-design-vue"; |
| | | import { loginReq } from "./service"; |
| | | import { getList,read } from "./service"; |
| | | import HeaderNav from "../../layouts/components/HeaderNav.vue"; |
| | | import zhCN from "ant-design-vue/lib/locale-provider/zh_CN"; |
| | | // 引入 Element UI 的日历组件 |
| | |
| | | date: new Date(), |
| | | viewWidth: "", |
| | | scale: 1, |
| | | list:[], |
| | | // 审批人 |
| | | moduleList2: [ |
| | | { |
| | |
| | | created() { |
| | | // 初始化时检查窗口大小 |
| | | this.handleResize(); |
| | | getList().then(res=>{ |
| | | console.log('22222222',res) |
| | | this.list = res |
| | | |
| | | }) |
| | | }, |
| | | mounted() { |
| | | // 监听窗口大小变化 |
| | |
| | | }); |
| | | } |
| | | }, |
| | | toDetail(item){ |
| | | console.log('item item',item) |
| | | read({id:item.id}).then(res=>{ |
| | | console.log('res',res) |
| | | |
| | | }) |
| | | |
| | | } |
| | | }, |
| | | computed: { |
| | | currentModuleList() { |
| | |
| | | .todo-list { |
| | | flex: 1; |
| | | height: 100%; |
| | | max-height: 264px; |
| | | overflow: auto; |
| | | } |
| | | |
| | |
| | | font-size: 14px; |
| | | color: #303133; |
| | | line-height: 24px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | max-width: 400px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .todo-meta { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | min-width:260px; |
| | | } |
| | | |
| | | .time { |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 登录 |
| | | export const loginReq = (data) => { |
| | | return axios.post('/login', { ...data }) |
| | | export const getList = (data) => { |
| | | return axios.get('/open/t-notice/list', { ...data }) |
| | | } |
| | | export const read = (data) => { |
| | | return axios.get(`/open/t-notice/read?id=${data.id}`, { ...data }) |
| | | } |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <!-- <template #setting> |
| | | <el-button icon="el-icon-plus" @click="add" type="primary">添加角色</el-button> |
| | | </template> |
| | | </template> --> |
| | | <template #table> |
| | | <el-table-column type="index" width="55" label="序号"></el-table-column> |
| | | <el-table-column prop="roleName" label="角色名称"></el-table-column> |