| | |
| | | |
| | | if (this.projectId) { |
| | | params.projectId = this.projectId; |
| | | // TODO: 这里需要替换为新的接口调用 |
| | | // const res = await getProjectUserList(params); |
| | | } else { |
| | | const res = await getUserList(params); |
| | | this.tableData = res.records; |
| | | } |
| | | |
| | | const res = await getUserList(params); |
| | | this.tableData = res.records; |
| | | |
| | | // 数据加载完成后重新应用选中状态 |
| | | this.setSelection(this.selectData) |
| | | this.$nextTick(() => { |
| | | this.tableData.forEach(row => { |
| | | if (this.selectData.some(i => i.userId === row.userId)) { |
| | | this.$refs.memberTable.toggleRowSelection(row, true) |
| | | } |
| | | }) |
| | | }) |
| | | }, |
| | | searchRole() { |
| | | this.search = '' |
| | |
| | | ::-webkit-scrollbar { |
| | | display: none; |
| | | } |
| | | |
| | | .table-container { |
| | | ::-webkit-scrollbar { |
| | | display: block !important; |
| | |
| | | background: #00796b; |
| | | } |
| | | } |
| | | |
| | | html, |
| | | body, |
| | | #app { |
| | |
| | | background-color: #009688 !important; |
| | | border-color: #009688 !important; |
| | | } |
| | | |
| | | .el-radio-button--small.is-active { |
| | | .el-radio-button__inner { |
| | | background-color: #009688 !important; |
| | |
| | | border-radius: 6px; |
| | | border: 1px solid rgba(0, 0, 0, 0.15); |
| | | } |
| | | .el-date-editor{ |
| | | |
| | | .el-date-editor { |
| | | .el-range-separator{ |
| | | width: 22px; |
| | | } |
| | | |
| | | .el-input__inner { |
| | | width: 260px; |
| | | padding: 0 12px 0 30px; |
| | | border-radius: 6px; |
| | | border: 1px solid rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | padding: 0 12px 0 30px; |
| | | border-radius: 6px; |
| | | border: 1px solid rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | .el-input__inner { |
| | | width: 200px; |
| | | } |
| | | .el-pagination__sizes{ |
| | | |
| | | |
| | | .el-pagination__sizes { |
| | | .el-input__inner { |
| | | width: 100px; |
| | | width: 100px; |
| | | } |
| | | } |
| | | } |
| | | .el-pagination__jump{ |
| | | |
| | | .el-pagination__jump { |
| | | .el-input__inner { |
| | | width: 50px; |
| | | } |
| | | width: 50px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | overflow: hidden; |
| | | } |
| | | } |
| | | |
| | | // .pagination{ |
| | | // .el-input__inner { |
| | | // width: unset !important; |
| | |
| | | background-color: #009688; |
| | | } |
| | | |
| | | .el-button + .el-button, |
| | | .el-checkbox.is-bordered + .el-checkbox.is-bordered { |
| | | .el-button+.el-button, |
| | | .el-checkbox.is-bordered+.el-checkbox.is-bordered { |
| | | margin-left: 0; |
| | | } |
| | | |
| | |
| | | type: 'imageUpload', |
| | | title: '图片上传', |
| | | icon: require('@/assets/public/modalImg4.png'), |
| | | description: '富文本组件可以支持文本格式化(如字体、颜色、大小等)、图片插入、链接添加等多种功能。' |
| | | description: '支持上传.png\.jpg文件,上传之后可点击放大预览。' |
| | | } |
| | | ] |
| | | } |
| | |
| | | <div class="image-upload-container"> |
| | | <el-upload v-if="editable" action="#" :file-list="item.data.imageList" |
| | | :on-change="(file, fileList) => handleImageChange(idx, fileList)" |
| | | :on-success="(res, file, fileList) => handleImageSuccess(res, file, fileList, idx)" :auto-upload="true" |
| | | :http-request="() => { }" :before-upload="beforeImageUpload" list-type="picture-card" |
| | | :on-success="(res, file, fileList) => handleImageSuccess(res, file, fileList, idx)" |
| | | :auto-upload="true" |
| | | :http-request="() => { }" |
| | | :before-upload="beforeImageUpload" |
| | | list-type="picture-card" |
| | | :on-preview="(file) => handlePreview(file, idx)" |
| | | class="image-uploader"> |
| | | <i class="el-icon-plus"></i> |
| | | <div class="upload-text">上传图片</div> |
| | | </el-upload> |
| | | <div v-else class="image-preview"> |
| | | <img v-for="image in item.data.imageList" :key="image.uid" :src="image.url" class="preview-image" /> |
| | | <el-image v-for="image in item.data.imageList" |
| | | :key="image.uid" |
| | | :src="image.url" |
| | | :preview-src-list="item.data.imageList.map(img => img.url)" |
| | | class="preview-image" /> |
| | | </div> |
| | | <div class="uploaf-notice">支持.jpg .png格式</div> |
| | | </div> |
| | |
| | | <addTableData :visible.sync="rowDialog.visible" :headerList="rowDialog.headers" |
| | | :editData="rowDialog.form" :isEdit="rowDialog.isEdit" @success="confirmAddRow"> |
| | | </addTableData> |
| | | |
| | | <el-dialog :visible.sync="imagePreviewVisible" width="auto" top="10vh" :show-close="true" v-if="imagePreviewUrl"> |
| | | <img :src="imagePreviewUrl" style="max-width:80vw;max-height:70vh;display:block;margin:auto;" /> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | }, |
| | | headerList: [], |
| | | defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址 |
| | | imagePreviewVisible: false, |
| | | imagePreviewUrl: '', |
| | | }; |
| | | }, |
| | | watch: { |
| | |
| | | } |
| | | return true; |
| | | }, |
| | | handlePreview(file, idx) { |
| | | // 使用el-image的preview-src-list实现预览 |
| | | // 这里直接用Element的图片预览能力,实际上el-upload会自动处理 |
| | | // 但如果你想自定义弹窗,可以用如下代码: |
| | | this.imagePreviewUrl = file.url; |
| | | this.imagePreviewVisible = true; |
| | | }, |
| | | emitUpdate() { |
| | | // 先创建新对象,这有助于触发更新 |
| | | const updatedComponents = JSON.parse(JSON.stringify(this.components)); |
| | |
| | | <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="nickNameOrPhone" placeholder="请输入姓名/手机号" /> |
| | | <el-input clearable v-model="nickNameOrPhone" placeholder="请输入姓名" /> |
| | | <el-button type="primary">搜索</el-button> |
| | | </div> |
| | | </div> |
| | | <Table ref="memberTable" :height="null" :row-key="row => row.userId" :data="tableData" |
| | | :total="0" @selection-change="handleSelectionChange" :row-class-name="tableRowClassName"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column label="角色" prop="roleName" /> |
| | | <el-table-column label="角色" prop="roleType" > |
| | | <template #default="scope"> |
| | | <span v-if="scope.row.roleType == 1">超级管理员</span> |
| | | <span v-if="scope.row.roleType == 2">审批人</span> |
| | | <span v-if="scope.row.roleType == 3">工艺工程师</span> |
| | | <span v-if="scope.row.roleType == 4">化验师</span> |
| | | <span v-if="scope.row.roleType == 5">实验员</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="姓名" prop="nickName" /> |
| | | <el-table-column label="头像" prop="avatar" > |
| | | <template #default="scope"> |
| | | <img :src="scope.row.avatar || require('../../assets/login/img1111.png')" style="width: 50px;height: 50px;border-radius: 50%;" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创建时间" prop="createTime" /> |
| | | </Table> |
| | | </div> |
| | |
| | | }, |
| | | methods: { |
| | | setSelection(selected) { |
| | | this.selectData = selected |
| | | this.$nextTick(() => { |
| | | // 确保 tableData 和 memberTable 都存在 |
| | | if (this.tableData && this.$refs.memberTable) { |
| | | this.selectData = selected; |
| | | // 确保 tableData 和 memberTable 都存在 |
| | | if (this.tableData && this.$refs.memberTable) { |
| | | this.$nextTick(() => { |
| | | // 设置新的选中状态 |
| | | this.tableData.forEach(row => { |
| | | if (selected.some(i => i.userId === row.userId)) { |
| | | this.$refs.memberTable.toggleRowSelection(row, true) |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | const isSelected = selected.some(i => i.userId === row.userId); |
| | | this.$refs.memberTable.toggleRowSelection(row, isSelected); |
| | | }); |
| | | }); |
| | | } |
| | | }, |
| | | openDialog() { |
| | | // 获取角色列表并根据项目组ID进行过滤 |
| | |
| | | <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" |
| | |
| | | <el-table-column label="姓名" prop="nickName" /> |
| | | <el-table-column label="头像" prop="avatar" width="80"> |
| | | <template #default="{ row }"> |
| | | <el-avatar :size="32" :src="row.avatar" /> |
| | | <el-avatar :size="32" :src="row.avatar || require('../../assets/login/img1111.png')" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创建时间" prop="signTime" /> |
| | |
| | | } |
| | | }, |
| | | methods: { |
| | | // toggleRowSelection(row, selected) { |
| | | // this.$refs.elTable.toggleRowSelection(row, selected) |
| | | // this.$forceUpdate() |
| | | // }, |
| | | // clearSelection() { |
| | | // this.$refs.elTable.clearSelection() |
| | | // this.$forceUpdate() |
| | | // }, |
| | | toggleRowSelection(row, selected) { |
| | | this.$refs.elTable.toggleRowSelection(row, selected) |
| | | this.$forceUpdate() |
| | | }, |
| | | clearSelection() { |
| | | this.$refs.elTable.clearSelection() |
| | | this.$forceUpdate() |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.$emit('handleCurrentChange', page) |
| | | }, |
| | |
| | | <div class="flex-over"> |
| | | <div class="people-list" v-for="(member, memberIndex) in group.members" :key="memberIndex"> |
| | | <div class="people-item"> |
| | | <img :src="member.avatar" alt="" class="people-img" /> |
| | | <img :src="member.avatar|| require('../../assets/login/img1111.png')" alt="" class="people-img" /> |
| | | <div class="member-name">{{ member.name }}</div> |
| | | </div> |
| | | <div class="member-status"> |
| | |
| | | left: -10px; |
| | | top: -8px; |
| | | } |
| | | .el-timeline-item__tail{ |
| | | left: 0 !important; |
| | | } |
| | | |
| | | .el-timeline-item__node--primary { |
| | | width: 20px !important; |
| | |
| | | import Vue from "vue"; |
| | | import ElementUI from "element-ui"; |
| | | import "element-ui/lib/theme-chalk/index.css"; |
| | | import Antd from 'ant-design-vue'; |
| | | import {Calendar} from 'ant-design-vue'; |
| | | import 'ant-design-vue/dist/antd.css'; |
| | | import '@/assets/font/font.css' |
| | | import App from "./App.vue"; |
| | |
| | | |
| | | Vue.config.productionTip = false; |
| | | Vue.use(ElementUI, { size: 'small' }) |
| | | Vue.use(Antd) |
| | | Vue.use('Calendar',Calendar) |
| | | Vue.component('Table', Table) |
| | | Vue.component('TableCustom', TableCustom) |
| | | Vue.component('Card', Card) |
| | | Vue.component('ShowDelConfirm', ShowDelConfirm) |
| | | Vue.component('SelectMember', SelectMember) |
| | | Vue.component('EvaluateTable', EvaluateTable) |
| | | // app.use(Button).mount('#app'); |
| | | |
| | | Vue.prototype.msgsuccess = function (msg) { |
| | | this.$message({ |
| | |
| | | console.log('获取详情参数:', { id: this.id }) |
| | | getDetailById({ id: this.id }).then(res => { |
| | | console.log('详情接口返回:', res) |
| | | if (res.code === 200 && res.data) { |
| | | const data = res.data |
| | | if (res) { |
| | | const data = res |
| | | // 设置表单数据 |
| | | this.form = { |
| | | projectName: data.projectName, |
| | |
| | | style="margin-top: 38px" |
| | | > |
| | | <el-form-item prop="projectName" label="项目课题方案名称"> |
| | | <template slot="label"> |
| | | <span class="required-label">项目课题方案名称</span> |
| | | </template> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="请输入" |
| | |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item prop="projectStage" label="项目阶段"> |
| | | <template slot="label"> |
| | | <span class="required-label">项目阶段</span> |
| | | </template> |
| | | <el-select |
| | | v-model="form.projectStage" |
| | | placeholder="请选择" |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item prop="projectCode" label="项目课题方案编号"> |
| | | <template slot="label"> |
| | | <span class="required-label">项目课题方案编号</span> |
| | | </template> |
| | | <el-input |
| | | v-model="form.projectCode" |
| | | placeholder="请输入" |
| | |
| | | </Card> |
| | | </div> |
| | | <!-- 右侧审批流程 --> |
| | | <div class="approval-flow"> |
| | | <div class="approval-flow" v-if="form.auditStatus!=4"> |
| | | <div class="flow-content"> |
| | | <approval-process :processData="form.processData" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="approval-dialog-approve" v-if="type === 'approve'"> |
| | | <div class="approval-dialog-approve" v-if="type === 'approve' "> |
| | | <div class="status"> |
| | | <div class="status-title">审批结果</div> |
| | | <div class="status-content"> |
| | |
| | | <div class="remark"> |
| | | <div class="remark-title">审批意见</div> |
| | | <el-input |
| | | style="width: 400px;" |
| | | type="textarea" |
| | | v-model="remark" |
| | | placeholder="请输入审批意见" |
| | |
| | | style="margin-left: 20px" |
| | | @click="handleApprove" |
| | | v-if="type === 'approve'" |
| | | >通过</el-button |
| | | >确认</el-button |
| | | > |
| | | </div> |
| | | </el-dialog> |
| | |
| | | }, |
| | | computed: { |
| | | dialogTitle() { |
| | | return this.type === "approve" ? "审批" : "审批详情"; |
| | | return this.type === "approve" ? "审批" :this.form.auditStatus!=4 ? "审批详情" : "详情"; |
| | | }, |
| | | }, |
| | | watch: { |
| | |
| | | if (res.code === 200) { |
| | | this.$message.success("审批成功"); |
| | | this.$emit("update:visible", false); |
| | | this.$emit("success"); |
| | | this.$emit("approve"); |
| | | } else { |
| | | this.$message.error(res.msg || "审批失败"); |
| | | } |
| | |
| | | border-radius: 4px; |
| | | margin: 10px 0; |
| | | } |
| | | |
| | | .required-label { |
| | | &::before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="项目课题方案名称:"> |
| | |
| | | <template #setting> |
| | | <div class="table-setting"> |
| | | <div class="flex a-center"> |
| | | <div class="table-title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')"> |
| | | <div class="table-tit" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')"> |
| | | 项目课题方案列表 |
| | | </div> |
| | | <div v-if="isProcessEngineer" class="table-tit drafts" :class="{ active: currentType === 'draft' }" |
| | |
| | | <el-table-column prop="auditTime" label="审批时间"></el-table-column> |
| | | <el-table-column label="操作" width="250"> |
| | | <template slot-scope="scope"> |
| | | <!-- 工艺工程师的按钮 --> |
| | | <template v-if="isProcessEngineer"> |
| | | <el-button v-if="scope.row.auditStatus === 1" type="text" |
| | | @click="handleRevokeApprove(scope.row)">撤销审批</el-button> |
| | | <el-button v-if="scope.row.auditStatus === 3" type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button v-if="scope.row.auditStatus === 3" type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | <el-button v-if="scope.row.auditStatus !== 1" type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | <!-- 草稿箱的按钮 --> |
| | | <template v-if="currentType === 'draft'"> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | <!-- 审批人和超级管理员的按钮 --> |
| | | <!-- 列表的按钮 --> |
| | | <template v-else> |
| | | <el-button v-if="scope.row.auditStatus === 1" type="text" @click="handleApprove(scope.row)">审批</el-button> |
| | | <el-button v-if="scope.row.auditStatus !== 1" type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | <!-- 工艺工程师的按钮 --> |
| | | <template v-if="isProcessEngineer"> |
| | | <el-button v-if="scope.row.auditStatus === 1" type="text" |
| | | @click="handleRevokeApprove(scope.row)">撤销审批</el-button> |
| | | <el-button v-if="scope.row.auditStatus === 3" type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button v-if="scope.row.auditStatus === 3" type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | <el-button v-if="scope.row.auditStatus !== 1" type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | <!-- 审批人和超级管理员的按钮 --> |
| | | <template v-else> |
| | | <el-button v-if="scope.row.auditStatus === 1" type="text" @click="handleApprove(scope.row)">审批</el-button> |
| | | <el-button v-if="scope.row.auditStatus !== 1" type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | }, |
| | | tableData: [], |
| | | total: 0, |
| | | // 模拟数据 |
| | | mockListData: [ |
| | | { |
| | | planCode: "PLAN-2024-001", |
| | | planName: "2024年度实验室设备升级方案", |
| | | stage: "规划阶段", |
| | | creator: "张三", |
| | | createTime: "2024-03-15", |
| | | status: "pending", |
| | | approver: "李四", |
| | | approveTime: "2024-03-16", |
| | | }, |
| | | { |
| | | planCode: "PLAN-2024-002", |
| | | planName: "实验室安全管理制度更新方案", |
| | | stage: "实施阶段", |
| | | creator: "王五", |
| | | createTime: "2024-03-14", |
| | | status: "approved", |
| | | approver: "赵六", |
| | | approveTime: "2024-03-15", |
| | | }, |
| | | { |
| | | planCode: "PLAN-2024-003", |
| | | planName: "实验室人员培训计划", |
| | | stage: "准备阶段", |
| | | creator: "孙七", |
| | | createTime: "2024-03-13", |
| | | status: "rejected", |
| | | approver: "周八", |
| | | approveTime: "2024-03-14", |
| | | }, |
| | | ], |
| | | mockDraftData: [ |
| | | { |
| | | planCode: "DRAFT-2024-001", |
| | | planName: "实验室设备采购计划(草稿)", |
| | | stage: "规划阶段", |
| | | creator: "张三", |
| | | createTime: "2024-03-16", |
| | | status: "draft", |
| | | approver: "", |
| | | approveTime: "", |
| | | }, |
| | | { |
| | | planCode: "DRAFT-2024-002", |
| | | planName: "实验室改造方案(草稿)", |
| | | stage: "准备阶段", |
| | | creator: "李四", |
| | | createTime: "2024-03-15", |
| | | status: "draft", |
| | | approver: "", |
| | | approveTime: "", |
| | | }, |
| | | ], |
| | | approvalDialogVisible: false, |
| | | approvalDialogType: "approve", |
| | | currentApprovalData: [], |
| | | currentApprovalData: {}, // 修改为对象类型 |
| | | // 确认弹窗相关数据 |
| | | changeStatus: false, |
| | | changeStatusTitle: "", |
| | |
| | | this.getTableData(); |
| | | }, |
| | | handleSearch() { |
| | | if (this.form.createTime && this.form.createTime.length === 2) { |
| | | this.form.startTime = this.form.createTime[0]; |
| | | this.form.endTime = this.form.createTime[1]; |
| | | this.updateTimeRange(); |
| | | this.getTableData(); |
| | | }, |
| | | updateTimeRange() { |
| | | if (this.form.createTime?.length === 2) { |
| | | [this.form.startTime, this.form.endTime] = this.form.createTime; |
| | | } else { |
| | | this.form.startTime = ""; |
| | | this.form.endTime = ""; |
| | | } |
| | | this.getTableData(); |
| | | }, |
| | | getStatusType(status) { |
| | | const statusMap = { |
| | |
| | | this.approvalDialogVisible = true; |
| | | }, |
| | | handleApproveSubmit(data) { |
| | | // 处理审批通过 |
| | | console.log("审批通过:", data); |
| | | this.approvalDialogVisible = false; |
| | | this.$message.success("审批通过成功"); |
| | | this.getTableData(); |
| | | }, |
| | | handleRejectSubmit(data) { |
| | | // 处理审批驳回 |
| | | console.log("审批驳回:", data); |
| | | this.approvalDialogVisible = false; |
| | | this.$message.success("审批驳回成功"); |
| | | this.getTableData(); |
| | |
| | | this.currentOperationType = "revoke"; |
| | | this.currentOperationRow = row; |
| | | this.changeStatusTitle = "确认要撤销这条审批吗?"; |
| | | this.changeStatusTip = "撤销后,审批人将无法收到此条审批信息"; // 这里可以根据实际需求修改提示文案 |
| | | this.changeStatusTip = "撤销后,审批人将无法收到此条审批信息"; |
| | | this.changeStatus = true; |
| | | }, |
| | | handleEdit(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/addPlan", |
| | | query: { |
| | | id: row.id |
| | | } |
| | | query: { id: row.id } |
| | | }); |
| | | }, |
| | | handleDelete(row) { |
| | | this.currentOperationType = "delete"; |
| | | this.currentOperationRow = row; |
| | | this.changeStatusTitle = "确认要删除这条信息吗?"; |
| | | this.changeStatusTip = "删除后信息无法找回"; // 这里可以根据实际需求修改提示文案 |
| | | this.changeStatusTip = "删除后信息无法找回"; |
| | | this.changeStatus = true; |
| | | }, |
| | | handleDetail(row) { |
| | |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
| | | this.form.auditStatus = type === "draft" ? -1 : ""; |
| | | this.form.pageNum = 1; // 切换时重置页码 |
| | | this.getTableData(); |
| | | }, |
| | | getTableData() { |
| | | if (this.form.createTime && this.form.createTime.length === 2) { |
| | | this.form.startTime = this.form.createTime[0]; |
| | | this.form.endTime = this.form.createTime[1]; |
| | | } else { |
| | | this.form.startTime = ""; |
| | | this.form.endTime = ""; |
| | | } |
| | | |
| | | // 创建新的请求参数对象,排除createTime |
| | | this.updateTimeRange(); |
| | | const { createTime, ...requestParams } = this.form; |
| | | console.log(requestParams, "requestParams"); |
| | | |
| | | getProposalList(requestParams).then((res) => { |
| | | console.log(res, "请求回来的数据"); |
| | | this.tableData = res.data.records; |
| | | this.total = res.data.total; |
| | | }); |
| | | }, |
| | | handleChangeStatusConfirm() { |
| | | if (this.currentOperationType === "revoke") { |
| | | // 处理撤销审批逻辑 |
| | | upAndDown({ |
| | | id: this.currentOperationRow.id, |
| | | status: 4 // 已撤销状态 |
| | | }).then(() => { |
| | | this.$message.success("撤销审批成功"); |
| | | this.changeStatus = false; |
| | | this.getTableData(); |
| | | }).catch(error => { |
| | | this.$message.error("撤销审批失败"); |
| | | }); |
| | | } else if (this.currentOperationType === "delete") { |
| | | // 处理删除逻辑 |
| | | deleteById({ |
| | | id: this.currentOperationRow.id |
| | | }).then(() => { |
| | | this.$message.success("删除成功"); |
| | | this.changeStatus = false; |
| | | this.getTableData(); |
| | | }).catch(error => { |
| | | this.$message.error("删除失败"); |
| | | }); |
| | | const operationMap = { |
| | | revoke: { |
| | | api: upAndDown, |
| | | params: { id: this.currentOperationRow.id, status: -1 }, |
| | | successMsg: "撤销审批成功", |
| | | errorMsg: "撤销审批失败" |
| | | }, |
| | | delete: { |
| | | api: deleteById, |
| | | params: { id: this.currentOperationRow.id }, |
| | | successMsg: "删除成功", |
| | | errorMsg: "删除失败" |
| | | } |
| | | }; |
| | | |
| | | const operation = operationMap[this.currentOperationType]; |
| | | if (operation) { |
| | | operation.api(operation.params) |
| | | .then(() => { |
| | | this.$message.success(operation.successMsg); |
| | | this.changeStatus = false; |
| | | this.getTableData(); |
| | | }) |
| | | .catch(() => { |
| | | this.$message.error(operation.errorMsg); |
| | | }); |
| | | } |
| | | }, |
| | | }, |
| | |
| | | color: #049c9a; |
| | | line-height: 27px; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &.active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | |
| | | .table-tit { |
| | |
| | | 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; |
| | | &.active { |
| | | color: #049c9a; |
| | | font-weight: bold; |
| | | background: #ffffff; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | |
| | | .el-icon-plus { |
| | |
| | | <el-button type="primary" @click="handleSubmit">提交确认单</el-button> |
| | | <el-button @click="handleSaveDraft">存草稿</el-button> |
| | | </div> |
| | | <experimentalScheduling :show="showScheduling" @close="showScheduling = false" @submit="setSelectedScheduling"/> |
| | | <add-test-item |
| | | :dialogVisible="testItemDialogVisible" |
| | | :editData="currentTestItem" |
| | | @close="handleTestItemDialogClose" |
| | | @confirm="handleTestItemConfirm" |
| | | /> |
| | | <confirm-dialog |
| | | :visible.sync="confirmDialogVisible" |
| | | :formData="confirmFormData" |
| | | :sampleData="testItems" |
| | | @confirm="handleConfirmSubmit" |
| | | /> |
| | | <experimentalScheduling :show="showScheduling" @close="showScheduling = false" @submit="setSelectedScheduling" /> |
| | | <add-test-item :dialogVisible="testItemDialogVisible" :editData="currentTestItem" @close="handleTestItemDialogClose" |
| | | @confirm="handleTestItemConfirm" /> |
| | | <confirm-dialog :visible.sync="confirmDialogVisible" :formData="confirmFormData" :sampleData="testItems" |
| | | @confirm="handleConfirmSubmit" /> |
| | | </Card> |
| | | </template> |
| | | |
| | |
| | | mounted() { }, |
| | | methods: { |
| | | setSelectedScheduling(data) { |
| | | console.log('data',data) |
| | | console.log('data', data) |
| | | if (!data || data.length === 0) return; |
| | | const selectedData = data[0]; // 获取选中的第一条数据 |
| | | this.selectedScheduling = selectedData; |
| | | |
| | | |
| | | // 更新表格数据 |
| | | this.tableData = [{ |
| | | planCode: selectedData.projectName || '', // 所属项目课题方案 |
| | |
| | | status: this.getStatusText(selectedData.status) // 状态 |
| | | }]; |
| | | this.total = this.tableData.length; |
| | | |
| | | |
| | | // 更新确认表单数据 |
| | | this.confirmFormData = { |
| | | planName: selectedData.projectName || '', |
| | |
| | | sampleCode: selectedData.experimentCode || '' // 使用实验编号作为取样单编号 |
| | | }; |
| | | }, |
| | | |
| | | |
| | | // 添加状态转换方法 |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | |
| | | }).then(() => { |
| | | this.testItems.splice(index, 1) |
| | | this.$message.success('删除成功') |
| | | }).catch(() => {}) |
| | | }).catch(() => { }) |
| | | }, |
| | | generateUniqueId() { |
| | | return 'test_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9) |
| | |
| | | const submitData = { |
| | | dispatchId: this.selectedScheduling.id, // 实验调度ID |
| | | auditStatus: 1, // 待确认状态 |
| | | confirmSign:'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'|| signatureImage, // 签字图片 |
| | | confirmSign: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg' || signatureImage, // 签字图片 |
| | | signTime: new Date().toISOString(), // 签字时间 |
| | | testMethodConfirmSheetTerms: this.testItems.map(item => ({ |
| | | id: item.id, // 保留原有ID(编辑时使用) |
| | |
| | | await add(submitData) |
| | | this.$message.success('提交成功') |
| | | } |
| | | |
| | | |
| | | this.confirmDialogVisible = false // 关闭弹窗 |
| | | this.$router.go(-1) |
| | | } catch (error) { |
| | |
| | | await add(draftData) |
| | | this.$message.success('保存草稿成功') |
| | | } |
| | | |
| | | |
| | | this.$router.push('/dataManagement/confirmation-sheet') |
| | | } catch (error) { |
| | | this.$message.error((this.formData.id ? '更新' : '保存') + '草稿失败:' + (error.message || '未知错误')) |
| | |
| | | async getDetailData(id) { |
| | | try { |
| | | const res = await getDetail({ id }) |
| | | if (res.data) { |
| | | if (res) { |
| | | // 设置实验调度数据 |
| | | this.selectedScheduling = { |
| | | id: res.data.dispatchId, |
| | | // ... 其他调度相关字段 |
| | | id: res.dispatchId, |
| | | } |
| | | |
| | | this.tableData = [{ |
| | | // planCode: res.projectName, |
| | | // planName: res.experimentCode, |
| | | // testName: res.experimentName, |
| | | // notifyTime: res.experimentDate, |
| | | |
| | | planCode: res.projectName || '', // 所属项目课题方案 |
| | | planName: res.experimentCode || '', // 实验编号 |
| | | testName: res.experimentName || '', // 实验名称 |
| | | notifyTime: res.experimentDate || '', // 通知时间 |
| | | startTime: res.experimentStartTime || '', // 实验开始时间 |
| | | endTime: res.experimentEndTime || '', // 实验结束时间 |
| | | participants: res.participantsName || '', // 参加人员 |
| | | status: this.getStatusText(res.status) // 状态 |
| | | |
| | | }] |
| | | |
| | | // 设置检测项数据 |
| | | this.testItems = res.data.testMethodConfirmSheetTerms.map(item => ({ |
| | | this.testItems = res.testMethodConfirmSheetTerms.map(item => ({ |
| | | ...item, |
| | | id: item.id // 使用后端返回的ID |
| | | })) |
| | | |
| | | // 设置表单数据 |
| | | this.formData = { |
| | | id: res.data.id, |
| | | dispatchId: res.data.dispatchId, |
| | | auditStatus: res.data.auditStatus, |
| | | confirmSign: res.data.confirmSign, |
| | | signTime: res.data.signTime |
| | | id: res.id, |
| | | dispatchId: res.dispatchId, |
| | | auditStatus: res.auditStatus, |
| | | confirmSign: res.confirmSign, |
| | | signTime: res.signTime |
| | | } |
| | | } |
| | | } catch (error) { |
| | |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.auditStatus" placeholder="请选择"> |
| | | <el-option label="待确认" :value="1"></el-option> |
| | | <el-option label="已通过" :value="2"></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> |
| | |
| | | <div class="flex a-center" style="gap: 16px;"> |
| | | <div class="title pointer" :class="{ active: !isDrafts }" @click="switchToDrafts(false)"> |
| | | 检验方法确认单列表</div> |
| | | <div class="drafts pointer" :class="{ active: isDrafts }" @click="switchToDrafts(true)">草稿箱 |
| | | <div class="drafts pointer" v-if="userRole == '4'" :class="{ active: isDrafts }" @click="switchToDrafts(true)">草稿箱 |
| | | </div> |
| | | </div> |
| | | <el-button @click="handleAddPlan" class="el-icon-plus" type="primary"> |
| | | <el-button v-if="userRole == '4'" @click="handleAddPlan" class="el-icon-plus" type="primary"> |
| | | 新增检测方法确认单</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200"> |
| | | <template slot-scope="scope"> |
| | | <!-- 超级管理员(1)和审批人(2) --> |
| | | <template v-if="userRole == '1' || userRole == '2'"> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | <!-- 草稿箱状态下的操作 --> |
| | | <template v-if="isDrafts"> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | |
| | | <!-- 工艺工程师(3) --> |
| | | <template v-if="userRole == '3'"> |
| | | <el-button type="text" @click="handleReview(scope.row)" |
| | | v-if="scope.row.auditStatus == 1">审核</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" |
| | | v-if="scope.row.auditStatus == 2">详情</el-button> |
| | | </template> |
| | | <!-- 非草稿箱状态下的操作 --> |
| | | <template v-else> |
| | | <!-- 超级管理员(1)和审批人(2) --> |
| | | <template v-if="userRole == '1' || userRole == '2'"> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | |
| | | <!-- 化验师(4) --> |
| | | <template v-if="userRole == '4'"> |
| | | <el-button type="text" @click="handleRevoke(scope.row)" |
| | | v-if="scope.row.auditStatus == 1">撤销</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" |
| | | v-if="scope.row.auditStatus === 2 || scope.row.auditStatus === 3">详情</el-button> |
| | | <el-button type="text" @click="handleEdit(scope.row)" |
| | | v-if="scope.row.auditStatus === 3">编辑</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)" |
| | | v-if="scope.row.auditStatus === 3">删除</el-button> |
| | | <!-- 工艺工程师(3) --> |
| | | <template v-if="userRole == '3'"> |
| | | <el-button type="text" @click="handleReview(scope.row)" |
| | | v-if="scope.row.auditStatus == 1">审核</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" |
| | | v-if="scope.row.auditStatus == 2">详情</el-button> |
| | | </template> |
| | | |
| | | <!-- 化验师(4) --> |
| | | <template v-if="userRole == '4'"> |
| | | <el-button type="text" @click="handleRevoke(scope.row)" |
| | | v-if="scope.row.auditStatus == 1">撤销</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" |
| | | v-if="scope.row.auditStatus == 2 || scope.row.auditStatus == 3">详情</el-button> |
| | | <el-button type="text" @click="handleEdit(scope.row)" |
| | | v-if="scope.row.auditStatus == 3">编辑</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)" |
| | | v-if="scope.row.auditStatus == 3">删除</el-button> |
| | | </template> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | auditStatus: this.isDrafts ? -1 : Number(this.form.auditStatus) || '' |
| | | }; |
| | | const res = await getList(params); |
| | | if (res.code === 200) { |
| | | if (res.code == 200) { |
| | | this.tableData = res.data.records || []; |
| | | this.total = res.data.total || 0; |
| | | } |
| | |
| | | } |
| | | }, |
| | | handleDateChange(val) { |
| | | if (val && val.length === 2) { |
| | | if (val && val.length == 2) { |
| | | this.form.startTime = val[0]; |
| | | this.form.endTime = val[1]; |
| | | } else { |
| | |
| | | }, |
| | | handleEdit(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/confirmation-sheet/edit", |
| | | query: { id: row.id } |
| | | path: "/dataManagement/confirmation-sheet/add", |
| | | query: { |
| | | id: row.id, |
| | | type: 'edit' |
| | | } |
| | | }); |
| | | }, |
| | | handleDelete(row) { |
| | |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | background: #fafafc; |
| | | border: 1px solid #dcdfe6; |
| | |
| | | background: #ffffff; |
| | | border: 1px solid #049c9a !important; |
| | | color: #049c9a; |
| | | font-weight: bold; |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | // 获取实验调度列表 |
| | | export const getDispatchList = (data) => { |
| | | return axios.get('/open/t-experiment-dispatch/chemistSignList', { params:data }) |
| | | return axios.get('/open/t-experiment-dispatch/chemistSignList', { ...data }) |
| | | } |
| | | // 撤销 |
| | | export const revokedSheet = (data) => { |
| | |
| | | import AddGroupDialog from './components/AddGroupDialog' |
| | | import AddTaskDialog from './components/AddTaskDialog' |
| | | import AIEditor from '@/components/AiEditor' |
| | | import { getProposalList, addDispatch, updateDispatch } from './service' |
| | | import { getProposalList, addDispatch, updateDispatch,getDetailById } from './service' |
| | | |
| | | export default { |
| | | name: "AddProject", |
| | |
| | | }).catch(() => {}) |
| | | }, |
| | | handleGroupSubmit(form) { |
| | | const index = this.groupTableData.findIndex(item => item.groupName === form.groupName) |
| | | console.log('11111111',form ,'2222222',this.groupTableData) |
| | | const index = this.groupTableData.findIndex(item => item.id === form.id) |
| | | if (index > -1) { |
| | | this.groupTableData.splice(index, 1, form) |
| | | } else { |
| | |
| | | getDetail() { |
| | | if (this.id) { |
| | | getDetailById({ id: this.id }).then(res => { |
| | | if (res.code === 200 && res.data) { |
| | | const data = res.data |
| | | if (res) { |
| | | const data = res |
| | | // 设置表单数据 |
| | | this.form = { |
| | | projectName: data.projectName, |
| | |
| | | // 设置表格数据 |
| | | this.groupTableData = data.experimentDispatchGroups || [] |
| | | this.taskTableData = data.experimentDispatchTasks || [] |
| | | |
| | | // 处理参与人员数据 |
| | | this.members = { |
| | | processEngineer: data.experimentDispatchParticipants.filter(p => p.roleType === 3) || [], |
| | | experimenter: data.experimentDispatchParticipants.filter(p => p.roleType === 5) || [], |
| | | analyst: data.experimentDispatchParticipants.filter(p => p.roleType === 4) || [] |
| | | }; |
| | | |
| | | // 更新selectMemberData |
| | | this.selectMemberData = [ |
| | | ...this.members.processEngineer, |
| | | ...this.members.experimenter, |
| | | ...this.members.analyst |
| | | ]; |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取详情失败:', err) |
| | |
| | | handleSubmit() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | const eventName = this.isEdit ? "update" : "submit"; |
| | | const eventName = "submit"; |
| | | console.log('this.form',this.form) |
| | | this.$emit(eventName, {...this.form}); |
| | | this.handleClose(); |
| | | } |
| | |
| | | <el-input v-model="form.taskName" placeholder="请输入任务名称" class="custom-input"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="负责人" prop="leader"> |
| | | <el-form-item label="负责人" prop="leader" required> |
| | | <!-- <div class="required-label">负责人</div> --> |
| | | <Table |
| | | ref="table" |
| | | :data="tableData" |
| | | :total="0" |
| | | :height="null" |
| | | :total="0" |
| | | :height="null" |
| | | class="rwuTable" |
| | | @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | |
| | | .custom-input { |
| | | width: 100%; |
| | | } |
| | | |
| | | .required-label { |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-bottom: 8px; |
| | | &::before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .rwuTable { |
| | |
| | | name: item.nickName || "", |
| | | status: item.status === 2 ? "已确认" : "待确认", |
| | | approveTime: item.status === 2 ? item.signTime : "", |
| | | avatar: item.avatar || "", |
| | | avatar: item.avatar, |
| | | })), |
| | | }, |
| | | { |
| | |
| | | name: item.nickName || "", |
| | | status: item.status === 2 ? "已确认" : "待确认", |
| | | approveTime: item.status === 2 ? item.signTime : "", |
| | | avatar: item.avatar || "", |
| | | avatar: item.avatar, |
| | | })), |
| | | }, |
| | | ], |
| | |
| | | this.imgSrc = ''; |
| | | }, |
| | | handleApprove() { |
| | | if(!this.imgSrc){ |
| | | this.$message.error('请先签字在提交'); |
| | | return |
| | | } |
| | | // 组装签名数据 |
| | | const params = { |
| | | dispatchId: this.data.id, // 传递当前调度id |
| | | confirmSign: this.imgSrc, // 签名图片 |
| | | }; |
| | | console.log('params',params) |
| | | sign(params).then(res => { |
| | | if (res && res.code === 200) { |
| | | this.$message.success('签字成功'); |
| | | this.handleClose(); |
| | | this.$emit('update:data') |
| | | } else { |
| | | this.$message.error(res.msg || '签字失败'); |
| | | } |
| | |
| | | <template slot-scope="scope"> |
| | | <!-- 工艺工程师(3) --> |
| | | <template v-if="userRole == '3'"> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | <el-button |
| | | v-if="scope.row.status == 1" |
| | | type="text" |
| | | @click="handleDelete(scope.row)" |
| | | >删除</el-button> |
| | | <template v-if="currentType === 'draft'"> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | <template v-else> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | <el-button |
| | | v-if="scope.row.status == 1" |
| | | type="text" |
| | | @click="handleDelete(scope.row)" |
| | | >删除</el-button> |
| | | </template> |
| | | </template> |
| | | |
| | | <!-- 化验师(4)和实验员(5) --> |
| | |
| | | path: "/dataManagement/addDispatch", |
| | | }); |
| | | }, |
| | | handleEdit(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/addDispatch", |
| | | query: { |
| | | id: row.id, |
| | | type: 'edit' |
| | | } |
| | | }); |
| | | }, |
| | | handleConfirm(row) { |
| | | this.currentApprovalData = row; |
| | | this.approvalDialogType = "approve"; |
| | |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | // font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | width: unset; |
| | |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | font-weight: 400; |
| | | // font-weight: 400; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | margin-left: 16px; |
| | |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | font-weight: bold |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <DynamicComponent :ref="'stepContent' + idx" @submit="(content) => handleStepContentSubmit(idx, content)" |
| | | <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">发送</el-button> |
| | | <el-button @click="handleSaveDraft">存草稿</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> |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | title="实验方案详情" |
| | | :visible="dialogVisible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <el-dialog title="实验方案详情" :visible="dialogVisible" width="80%" :close-on-click-modal="false" @close="handleClose"> |
| | | <div class="approval-dialog"> |
| | | <!-- 左侧审批内容 --> |
| | | <div class="approval-content"> |
| | | <Card class="approval-content-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 class="header-title" style="margin-bottom: 38px"> |
| | | <div style="display: flex; align-items: center; gap: 13px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <el-button @click="handleStopExperiment" type="danger" v-if='form.status != 2 && form.status != 3 && form.status != 4'> |
| | | <el-button @click="handleStopExperiment" type="danger" |
| | | v-if='form.status != 2 && form.status != 3 && form.status != 4 && userRole == 3'> |
| | | 申请终止实验</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | |
| | | <div style="padding-left: 25px;margin-top: 28px;"> |
| | | <el-form-item prop="experimentDate" label="试验日期"> |
| | | <el-date-picker v-model="form.experimentDate" type="datetime" :disabled="true" placeholder="选择日期时间"> |
| | | <el-date-picker v-model="form.experimentDate" type="datetime" :disabled="true" placeholder="选择日期时间"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="content-box"> |
| | | <AiEditor |
| | | ref="purposeEditor" |
| | | :readOnly="true" |
| | | :value="form.experimentObjective" |
| | | height="200px" |
| | | placeholder="请输入实验目的..." |
| | | /> |
| | | <AiEditor ref="purposeEditor" :readOnly="true" :value="form.experimentObjective" height="200px" |
| | | placeholder="请输入实验目的..." /> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="content-box"> |
| | | <AiEditor |
| | | ref="processEditor" |
| | | :readOnly="true" |
| | | :value="form.experimentParamRoute" |
| | | height="200px" |
| | | placeholder="请输入工艺参数及路线..." |
| | | /> |
| | | <AiEditor ref="processEditor" :readOnly="true" :value="form.experimentParamRoute" height="200px" |
| | | placeholder="请输入工艺参数及路线..." /> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | |
| | | <div>三、实验材料及设备</div> |
| | | </div> |
| | | </div> |
| | | <DynamicComponent |
| | | ref="materialComponent" |
| | | title="实验材料" |
| | | :dialogCanEdit="false" |
| | | :dataSource="form.experimentMaterial" |
| | | :editable="false" |
| | | /> |
| | | <DynamicComponent |
| | | ref="equipmentComponent" |
| | | title="实验所用设备" |
| | | :dialogCanEdit="false" |
| | | :dataSource="form.experimentDevice" |
| | | :editable="false" |
| | | /> |
| | | <DynamicComponent ref="materialComponent" title="实验材料" :dialogCanEdit="false" |
| | | :dataSource="form.experimentMaterial" :editable="false" /> |
| | | <DynamicComponent ref="equipmentComponent" title="实验所用设备" :dialogCanEdit="false" |
| | | :dataSource="form.experimentDevice" :editable="false" /> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | |
| | | 步骤{{ idx + 1 }}:{{ item.stepName }} |
| | | </div> |
| | | </div> |
| | | <DynamicComponent |
| | | :dialogCanEdit="false" |
| | | :ref="'stepContent' + idx" |
| | | :dataSource="item.content" |
| | | :editable="false" |
| | | /> |
| | | <DynamicComponent :dialogCanEdit="false" :ref="'stepContent' + idx" :dataSource="item.content" |
| | | :editable="false" /> |
| | | </div> |
| | | </el-form> |
| | | </template> |
| | |
| | | <!-- 右侧审批流程 --> |
| | | <div class="approval-flow" v-if="showApprovalFlow"> |
| | | <div class="flow-content"> |
| | | <approval-process |
| | | :processData="approvalProcessData" |
| | | /> |
| | | <approval-process :processData="approvalProcessData" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <SignatureCanvas |
| | | :visible="signatureDialogVisible" |
| | | @confirm="handleSignatureConfirm" |
| | | /> |
| | | <SignatureCanvas :visible="signatureDialogVisible" @confirm="handleSignatureConfirm" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | selectedParticipants: [], // 实验参与人员 |
| | | showApprovalFlow: false, |
| | | approvalProcessData: [], |
| | | userRole: '', |
| | | }; |
| | | }, |
| | | watch: { |
| | |
| | | if (val && this.data && this.data.id) { |
| | | // 弹窗打开时,确保数据已获取 |
| | | this.getPlanDetail(this.data.id); |
| | | const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}'); |
| | | this.userRole = userInfo.roleType || ''; |
| | | } |
| | | }, |
| | | immediate: true, |
| | |
| | | this.handleClose(); |
| | | return; |
| | | } |
| | | if(res.stopReason){ |
| | | if (res.stopReason) { |
| | | this.showApprovalFlow = true; |
| | | //中止实验申请 |
| | | let processData = []; |
| | | processData.push({ |
| | | type: "primary", |
| | | let processData = []; |
| | | processData.push({ |
| | | type: "primary", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "提交人:", value: res.updateBy || "" }, |
| | | { label: "提交时间:", value: res.createTime || "" }, |
| | | ], |
| | | }); |
| | | if (res.status == 4 || res.status == 3) { |
| | | processData.push({ |
| | | type: 'primary', |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "提交人:", value: res.updateBy || "" }, |
| | | { label: "提交时间:", value: res.createTime || "" }, |
| | | ], |
| | | }); |
| | | if(res.status==4||res.status==3){ |
| | | processData.push({ |
| | | type:'primary', |
| | | mode: "list", |
| | | fields: [ |
| | | { |
| | | label: "审核结果:", |
| | | value: |
| | | res.status ==3 |
| | | ? "通过" |
| | | : res.status ==4 |
| | | { |
| | | label: "审核结果:", |
| | | value: |
| | | res.status == 3 |
| | | ? "通过" |
| | | : res.status == 4 |
| | | ? "驳回" |
| | | : "待审批", |
| | | }, |
| | | { label: "审批意见:", value: res.auditRemark || "" }, |
| | | { label: "审核人:", value: res.auditPersonName || "" }, |
| | | { label: "审核时间:", value: res.auditTime || "" }, |
| | | ], |
| | | }); |
| | | }else{ |
| | | processData.push({ |
| | | type: "warning", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "等待审核"}, |
| | | ], |
| | | }); |
| | | } |
| | | this.approvalProcessData = processData; |
| | | }, |
| | | { label: "审批意见:", value: res.auditRemark || "" }, |
| | | { label: "审核人:", value: res.auditPersonName || "" }, |
| | | { label: "审核时间:", value: res.auditTime || "" }, |
| | | ], |
| | | }); |
| | | } else { |
| | | processData.push({ |
| | | type: "warning", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "等待审核" }, |
| | | ], |
| | | }); |
| | | } |
| | | this.approvalProcessData = processData; |
| | | } |
| | | |
| | | // 填充基本表单数据 |
| | |
| | | experimentObjective: res.experimentObjective || '', |
| | | experimentParamRoute: res.experimentParamRoute || '', |
| | | }; |
| | | |
| | | |
| | | // 构建实验调度数据 |
| | | if (res.experimentDispatch) { |
| | | this.dispatchData = [res.experimentDispatch]; |
| | | } |
| | | |
| | | |
| | | // 填充组别数据 |
| | | if (res.dispatchId) { |
| | | try { |
| | |
| | | console.error('获取组别列表失败:', err); |
| | | } |
| | | } |
| | | |
| | | |
| | | // 填充实验材料和设备 |
| | | if (res.experimentMaterial) { |
| | | try { |
| | |
| | | ? JSON.parse(res.experimentMaterial) |
| | | : res.experimentMaterial; |
| | | this.form.experimentMaterial = materialData; |
| | | |
| | | |
| | | // 为DynamicComponent设置初始数据 |
| | | // this.$nextTick(() => { |
| | | // if (this.$refs.materialComponent) { |
| | |
| | | console.error('解析实验材料数据失败:', err); |
| | | } |
| | | } |
| | | |
| | | |
| | | if (res.experimentDevice) { |
| | | try { |
| | | const deviceData = typeof res.experimentDevice === 'string' |
| | | ? JSON.parse(res.experimentDevice) |
| | | : res.experimentDevice; |
| | | this.form.experimentDevice = deviceData; |
| | | |
| | | |
| | | // 为DynamicComponent设置初始数据 |
| | | this.$nextTick(() => { |
| | | // if (this.$refs.equipmentComponent) { |
| | |
| | | console.error('解析实验设备数据失败:', err); |
| | | } |
| | | } |
| | | |
| | | |
| | | // 填充实验步骤 |
| | | if (res.experimentStepRecord) { |
| | | try { |
| | | const stepsData = typeof res.experimentStepRecord === 'string' |
| | | ? JSON.parse(res.experimentStepRecord) |
| | | : res.experimentStepRecord; |
| | | |
| | | |
| | | this.stepList = (stepsData || []).map(step => ({ |
| | | stepName: step.stepName, |
| | | content: step.content |
| | | })); |
| | | |
| | | |
| | | // 设置步骤内容的初始数据 |
| | | this.$nextTick(() => { |
| | | // this.stepList.forEach((step, index) => { |
| | |
| | | this.stepList = []; |
| | | } |
| | | } |
| | | |
| | | |
| | | // 设置实验人员 |
| | | if (res.experimentSchemePersons) { |
| | | try { |
| | | const participantsData = typeof res.experimentSchemePersons === 'string' |
| | | ? JSON.parse(res.experimentSchemePersons) |
| | | : res.experimentSchemePersons; |
| | | |
| | | |
| | | this.selectedParticipants = participantsData || []; |
| | | } catch (err) { |
| | | console.error('解析实验人员数据失败:', err); |
| | | this.selectedParticipants = []; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | // 更新编辑器内容 |
| | | this.$nextTick(() => { |
| | | if (this.$refs.purposeEditor) { |
| | |
| | | this.$refs.processEditor.setContent(this.form.experimentParamRoute); |
| | | } |
| | | }); |
| | | |
| | | |
| | | } catch (error) { |
| | | console.error("获取方案详情失败:", error); |
| | | this.$message.error("获取方案详情失败"); |
| | |
| | | .approval-dialog { |
| | | display: flex; |
| | | height: 60vh; |
| | | padding:20px; |
| | | padding: 20px; |
| | | overflow: hidden; |
| | | |
| | | @media screen and (max-width: 1200px) { |
| | | flex-direction: column; |
| | | height: auto; |
| | | |
| | | .approval-content, .approval-flow { |
| | | |
| | | .approval-content, |
| | | .approval-flow { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 20px; |
| | |
| | | border: 1px solid #dcdfe6; |
| | | |
| | | &:nth-child(1) { |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(4, 156, 154, 0.2) 0%, |
| | | rgba(5, 242, 194, 0) 70% |
| | | ); |
| | | background: linear-gradient(to bottom, |
| | | rgba(4, 156, 154, 0.2) 0%, |
| | | rgba(5, 242, 194, 0) 70%); |
| | | } |
| | | |
| | | &:nth-child(2) { |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(5, 160, 193, 0.2) 0%, |
| | | rgba(5, 242, 194, 0) 70% |
| | | ); |
| | | background: linear-gradient(to bottom, |
| | | rgba(5, 160, 193, 0.2) 0%, |
| | | rgba(5, 242, 194, 0) 70%); |
| | | } |
| | | |
| | | &:nth-child(3) { |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(255, 77, 79, 0.2) 0%, |
| | | rgba(255, 242, 194, 0) 70% |
| | | ); |
| | | background: linear-gradient(to bottom, |
| | | rgba(255, 77, 79, 0.2) 0%, |
| | | rgba(255, 242, 194, 0) 70%); |
| | | } |
| | | |
| | | &:nth-child(4) { |
| | | background: linear-gradient( |
| | | to bottom, |
| | | rgba(250, 199, 20, 0.21) 0%, |
| | | rgba(255, 242, 194, 0) 70% |
| | | ); |
| | | background: linear-gradient(to bottom, |
| | | rgba(250, 199, 20, 0.21) 0%, |
| | | rgba(255, 242, 194, 0) 70%); |
| | | } |
| | | |
| | | .member-item { |
| | |
| | | .step-list { |
| | | background: #eff8fa; |
| | | padding: 20px; |
| | | |
| | | |
| | | .step-list-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 25px; |
| | | background: #ffffff; |
| | | |
| | | |
| | | .step-list-item-title { |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | |
| | | margin-bottom: 20px; |
| | | width: 65%; |
| | | display: flex; |
| | | |
| | | |
| | | .content-box-left { |
| | | flex: 1; |
| | | |
| | | div { |
| | | padding: 10px 0; |
| | | } |
| | | } |
| | | |
| | | |
| | | .content-box-right { |
| | | flex: 1; |
| | | |
| | | div { |
| | | padding: 10px 0; |
| | | } |
| | |
| | | <el-form-item label="通知时间:"> |
| | | <el-date-picker v-model="form.createTime" type="daterange" range-separator="至" |
| | | start-placeholder="开始日期" end-placeholder="结束日期" |
| | | value-format="yyyy-MM-dd" @change="handleDateChange"></el-date-picker> |
| | | value-format="yyyy-MM-dd" @change="handleDateChange" style="width: 260px;"></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | |
| | | const params = { |
| | | ...this.form |
| | | }; |
| | | console.log('params',params) |
| | | getDispatchList(params).then(res => { |
| | | console.log('222222222222',res) |
| | | if (res.code==200) { |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :height="null" :total="total" @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :height="null" :total="total" |
| | | @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="项目课题方案名称:"> |
| | |
| | | <el-input v-model="form.experimentCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间:"> |
| | | <el-date-picker |
| | | v-model="form.createTime" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | value-format="yyyy-MM-dd" |
| | | @change="handleDateChange" |
| | | ></el-date-picker> |
| | | <el-date-picker v-model="form.createTime" 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="请选择"> |
| | |
| | | <template #setting> |
| | | <div class="tableTitle"> |
| | | <div class="flex a-center flex-wrap"> |
| | | <div |
| | | class="title" |
| | | :class="{active:currentType === 'list'}" |
| | | @click="handleTypeChange('list')" |
| | | >项目课题方案列表</div> |
| | | <div |
| | | v-if="userRole == '3'" |
| | | class="drafts" |
| | | :class="{active:currentType === 'draft'}" |
| | | @click="handleTypeChange('draft')" |
| | | >草稿箱</div> |
| | | <div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">项目课题方案列表</div> |
| | | <div v-if="userRole == '3'" class="drafts" :class="{ active: currentType === 'draft' }" |
| | | @click="handleTypeChange('draft')">草稿箱</div> |
| | | </div> |
| | | <el-button |
| | | v-if="userRole == '3'" |
| | | @click="handleAddPlan" |
| | | class="el-icon-plus" |
| | | type="primary" |
| | | >新增实验方案</el-button> |
| | | <el-button v-if="userRole == '3'" @click="handleAddPlan" class="el-icon-plus" |
| | | type="primary">新增实验方案</el-button> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column |
| | | prop="projectName" |
| | | label="项目课题方案名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | ></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="schemePersonName" label="实验员"></el-table-column> |
| | |
| | | |
| | | <!-- 实验员(5) --> |
| | | <template v-if="userRole == '5'"> |
| | | <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == 1 ">编辑</el-button> |
| | | <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == 1">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" v-if="scope.row.status == 6">详情</el-button> |
| | | </template> |
| | | </template> |
| | |
| | | </template> |
| | | </TableCustom> |
| | | <!-- 审批弹窗 --> |
| | | <approval-dialog |
| | | :visible.sync="approvalDialogVisible" |
| | | :type="approvalDialogType" |
| | | :data="currentApprovalData" |
| | | /> |
| | | <approval-dialog :visible.sync="approvalDialogVisible" :type="approvalDialogType" :data="currentApprovalData" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import ApprovalDialog from './components/approvalDialog.vue' |
| | | import {getList} from './service' |
| | | import { getList } from './service' |
| | | |
| | | export default { |
| | | name: "ProjectList", |
| | |
| | | created() { |
| | | const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}'); |
| | | this.userRole = userInfo.roleType || ''; |
| | | |
| | | if (this.userRole == '4') { |
| | | this.$router.push('/403'); |
| | | return; |
| | | } |
| | | |
| | | |
| | | // if (this.userRole == '4') { |
| | | // this.$router.push('/403'); |
| | | // return; |
| | | // } |
| | | |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | |
| | | '3': "success", |
| | | '4': "danger", |
| | | '5': "info", |
| | | '6':'success' |
| | | '6': 'success' |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }, |
| | | getStatusText(status) { |
| | | if (this.userRole == 5) { |
| | | const statusMap = { |
| | | '-1': "草稿", |
| | | '1': "待提交", |
| | | '2': "申请中止待审核", |
| | | '3': "申请中止已通过", |
| | | '4': "申请中止已驳回", |
| | | '5': "已封存", |
| | | '6': '已提交' |
| | | }; |
| | | return statusMap[status] || "未知"; |
| | | } |
| | | const statusMap = { |
| | | '-1': "草稿", |
| | | '1': "已发送", |
| | |
| | | '3': "申请中止已通过", |
| | | '4': "申请中止已驳回", |
| | | '5': "已封存", |
| | | '6':'实验员已提交' |
| | | '6': '实验员已提交' |
| | | }; |
| | | return statusMap[status] || "未知"; |
| | | }, |
| | |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tableTitle { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .title { |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | |
| | | width: unset; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .drafts { |
| | | padding: 16px 65px; |
| | | background: #fafafc; |
| | |
| | | margin-left: 16px; |
| | | cursor: pointer; |
| | | } |
| | | .active{ |
| | | |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | |
| | | } |
| | | // 获取实验调度列表 |
| | | export const getDispatchList = (data) => { |
| | | return axios.post('/api/t-experiment-dispatch/pageList', { params:data }) |
| | | return axios.post('/api/t-experiment-dispatch/pageList', {...data }) |
| | | } |
| | |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import { Calendar } from 'ant-design-vue'; |
| | | import { loginReq } from './service' |
| | | import HeaderNav from '../../layouts/components/HeaderNav.vue' |
| | | // 引入 Element UI 的日历组件 |
| | |
| | | name: 'Login', |
| | | components: { |
| | | HeaderNav, |
| | | ACalendar: Calendar, |
| | | // ElCalendar // 注册 ElCalendar 组件 |
| | | }, |
| | | |