Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/leshan-laboratory
2 文件已重命名
14个文件已修改
46个文件已添加
New file |
| | |
| | | <view class="image-box"> |
| | | <template v-for="(item, index) in banner" :key="index"> |
| | | <!-- 平铺图 --> |
| | | <view v-if="item.position === 3" class="full-row"> |
| | | <image :src="item.fileUrl" mode="widthFix" class="image" /> |
| | | </view> |
| | | |
| | | <!-- 左图 --> |
| | | <view v-else-if="item.position === 1" class="row"> |
| | | <view class="left-half"> |
| | | <image :src="item.fileUrl" mode="widthFix" class="image" /> |
| | | </view> |
| | | <!-- 如果下一个是右图,则显示右图 --> |
| | | <view v-if="index + 1 < banner.length && banner[index + 1].position === 2" class="right-half"> |
| | | <image :src="banner[index + 1].fileUrl" mode="widthFix" class="image" /> |
| | | </view> |
| | | <!-- 如果下一个不是右图,则显示空白 --> |
| | | <view v-else class="right-half empty"></view> |
| | | </view> |
| | | |
| | | <!-- 右图(只有当它不是左图的配对时才显示) --> |
| | | <view v-else-if="item.position === 2 && (index === 0 || banner[index - 1].position !== 1)" class="row"> |
| | | <view class="left-half empty"></view> |
| | | <view class="right-half"> |
| | | <image :src="item.fileUrl" mode="widthFix" class="image" /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <style> |
| | | .image-box { |
| | | width: 100%; |
| | | } |
| | | |
| | | .full-row { |
| | | width: 100%; |
| | | } |
| | | |
| | | .row { |
| | | width: 100%; |
| | | display: flex; |
| | | } |
| | | |
| | | .left-half, .right-half { |
| | | width: 50%; |
| | | } |
| | | |
| | | .left-half { |
| | | padding-right: 5px; |
| | | } |
| | | |
| | | .right-half { |
| | | padding-left: 5px; |
| | | } |
| | | |
| | | .image { |
| | | width: 100%; |
| | | display: block; |
| | | } |
| | | |
| | | .empty { |
| | | background-color: transparent; |
| | | } |
| | | </style> |
| | |
| | | src: url('./SF Compact Display Black.ttf'); |
| | | font-weight: normal; |
| | | font-style: normal; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: 'Source Han Sans CN Normal'; |
| | | src: url('./Source Han Sans CN Normal.ttf'); |
| | | font-weight: normal; |
| | | font-style: normal; |
| | | } |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="新增组件" |
| | | :visible.sync="visible" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | custom-class="add-component-dialog" |
| | | @close="handleClose" |
| | | > |
| | | <div class="component-cards"> |
| | | <div |
| | | v-for="(item, index) in componentTypes" |
| | | :key="index" |
| | | class="component-card" |
| | | :class="{ active: selectedType === item.type }" |
| | | :data-type="item.type" |
| | | @click="handleSelect(item)" |
| | | > |
| | | <div class="card-icon"> |
| | | <img :src="item.icon" :alt="item.title" /> |
| | | </div> |
| | | <div class="card-content"> |
| | | <div class="card-title">{{ item.title }}</div> |
| | | <div class="card-desc">{{ item.description }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取消</el-button> |
| | | <el-button type="primary" @click="handleConfirm">保存</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'AddComponentDialog', |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | selectedType: '', |
| | | componentTypes: [ |
| | | { |
| | | type: 'richText', |
| | | title: '富文本', |
| | | icon: require('@/assets/public/modalImg1.png'), |
| | | description: '富文本组件可以支持文本格式化(如字体、颜色、大小等)、图片插入、链接添加等多种功能。' |
| | | }, |
| | | { |
| | | type: 'customTable', |
| | | title: '自定义表格', |
| | | icon: require('@/assets/public/modalImg2.png'), |
| | | description: '自定义表格组件可以支持自定义表头(包括配置表头类型、默认值、权限等)' |
| | | }, |
| | | { |
| | | type: 'fileUpload', |
| | | title: '文件上传', |
| | | icon: require('@/assets/public/modalImg3.png'), |
| | | description: '支持上传.docx/.pdf/.xlsx/.txt文件' |
| | | }, |
| | | { |
| | | type: 'imageUpload', |
| | | title: '图片上传', |
| | | icon: require('@/assets/public/modalImg4.png'), |
| | | description: '富文本组件可以支持文本格式化(如字体、颜色、大小等)、图片插入、链接添加等多种功能。' |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | handleSelect(item) { |
| | | this.selectedType = item.type |
| | | }, |
| | | handleClose() { |
| | | this.$emit('update:visible', false) |
| | | this.selectedType = '' |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.selectedType) { |
| | | this.$message.warning('请选择要添加的组件类型') |
| | | return |
| | | } |
| | | this.$emit('confirm', this.selectedType) |
| | | this.handleClose() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .add-component-dialog { |
| | | ::v-deep .el-dialog__header { |
| | | border-bottom: 1px solid #e4e7ed; |
| | | padding: 20px; |
| | | margin: 0; |
| | | } |
| | | |
| | | ::v-deep .el-dialog__body { |
| | | padding: 30px; |
| | | } |
| | | |
| | | .component-cards { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); |
| | | gap: 20px; |
| | | padding: 10px; |
| | | |
| | | .component-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | padding: 30px 20px; |
| | | background: #fff; |
| | | border-radius: 10px; |
| | | border: 1px solid #e4e7ed; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | |
| | | &[data-type="richText"] { |
| | | background: linear-gradient(180deg, #FFF1DE 0%, rgba(255,249,241,0) 100%); |
| | | border: 1px solid rgba(249,171,20,0.5); |
| | | } |
| | | |
| | | &[data-type="customTable"] { |
| | | background: linear-gradient(180deg, rgba(5,112,255,0.14) 1%, rgba(234,243,255,0) 100%); |
| | | border: 1px solid rgba(71,145,255,0.5); |
| | | } |
| | | |
| | | &[data-type="fileUpload"] { |
| | | background: linear-gradient(180deg, #E0FAEA 0%, rgba(224,250,234,0) 100%); |
| | | border: 1px solid rgba(87,180,131,0.5); |
| | | } |
| | | |
| | | &[data-type="imageUpload"] { |
| | | background: linear-gradient(180deg, #F5EDFF 0%, rgba(234,243,255,0) 100%); |
| | | border: 1px solid rgba(115,83,247,0.5); |
| | | } |
| | | |
| | | &.active { |
| | | transform: translateY(-4px); |
| | | box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15); |
| | | |
| | | &[data-type="richText"] { |
| | | border-color: rgba(249,171,20,0.8); |
| | | background: linear-gradient(180deg, #FFF1DE 0%, rgba(255,249,241,0.5) 100%); |
| | | } |
| | | |
| | | &[data-type="customTable"] { |
| | | border-color: rgba(71,145,255,0.8); |
| | | background: linear-gradient(180deg, rgba(5,112,255,0.2) 1%, rgba(234,243,255,0.5) 100%); |
| | | } |
| | | |
| | | &[data-type="fileUpload"] { |
| | | border-color: rgba(87,180,131,0.8); |
| | | background: linear-gradient(180deg, #E0FAEA 0%, rgba(224,250,234,0.5) 100%); |
| | | } |
| | | |
| | | &[data-type="imageUpload"] { |
| | | border-color: rgba(115,83,247,0.8); |
| | | background: linear-gradient(180deg, #F5EDFF 0%, rgba(234,243,255,0.5) 100%); |
| | | } |
| | | } |
| | | |
| | | .card-icon { |
| | | width: 92px; |
| | | height: 92px; |
| | | margin-bottom: 16px; |
| | | |
| | | img { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: contain; |
| | | } |
| | | } |
| | | |
| | | .card-content { |
| | | text-align: center; |
| | | |
| | | .card-title { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .card-desc { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | line-height: 1.4; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: center; |
| | | padding-top: 20px; |
| | | |
| | | .el-button { |
| | | min-width: 120px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | watch: { |
| | | value: { |
| | | handler(newVal) { |
| | | if (this.editor && newVal !== this.editor.getContent()) { |
| | | if (this.editor && newVal !== this.editor.getHtml()) { |
| | | this.editor.setContent(newVal) |
| | | } |
| | | }, |
| | |
| | | // 禁用 AI 功能 |
| | | ai: false, |
| | | // 禁用调整大小功能 |
| | | resize: false |
| | | resize: false, |
| | | // 添加唯一标识 |
| | | id: `editor-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` |
| | | } |
| | | |
| | | try { |
| | |
| | | }, |
| | | // 获取编辑器内容 |
| | | getContent() { |
| | | return this.editor ? this.editor.getContent() : '' |
| | | return this.editor ? this.editor.getHtml() : '' |
| | | }, |
| | | // 设置编辑器内容 |
| | | setContent(content) { |
New file |
| | |
| | | <template> |
| | | <div> |
| | | <div class="evaluateTable-header"> |
| | | <el-row> |
| | | <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="18"> |
| | | <el-row style="width: 100%;"> |
| | | <el-col style="color: transparent;cursor: default;" :xs="11" :sm="11" :md="11" :lg="11" |
| | | :xl="11"> |
| | | 占位字 |
| | | </el-col> |
| | | <el-col :offset="1" :xs="12" :sm="12" :md="12" :lg="12" :xl="12"> |
| | | <el-row style="width: 100%;"> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-header-text">良好</div> |
| | | </el-col> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-header-text">正确</div> |
| | | </el-col> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-header-text">失误</div> |
| | | </el-col> |
| | | </el-row> |
| | | </el-col> |
| | | </el-row> |
| | | </el-col> |
| | | <el-col style="color: transparent;cursor: default;" :xs="24" :sm="24" :md="24" :lg="24" :xl="6"> |
| | | 占位字 |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="evaluateTable-body"> |
| | | <el-row> |
| | | <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="18"> |
| | | <div class="evaluateTable-body-left"> |
| | | <div v-for="(item, index) in list" :key="index" class="evaluateTable-body-left-item"> |
| | | <el-row style="width: 100%;"> |
| | | <el-col :xs="11" :sm="11" :md="11" :lg="11" :xl="11"> |
| | | <div class="evaluateTable-body-left-item-text"> |
| | | {{ item }} |
| | | </div> |
| | | </el-col> |
| | | <el-col :offset="1" :xs="12" :sm="12" :md="12" :lg="12" :xl="12"> |
| | | <div class="evaluateTable-body-left-item-score"> |
| | | <el-row v-if="index != 5" style="width: 100%;"> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-body-left-item-score-num" |
| | | :class="yesOrNoActive(sort(2, index)) && 'activeScore'"> |
| | | <img v-if="yesOrNoActive(sort(2, index))" |
| | | src="@/assets/public/active.png" /> |
| | | <img v-else @click="selectNum(index, 2, sort(2, index))" |
| | | src="@/assets/public/noActive.png" /> |
| | | <div>2分</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-body-left-item-score-num" |
| | | :class="yesOrNoActive(sort(1, index)) && 'activeScore'"> |
| | | <img v-if="yesOrNoActive(sort(1, index))" |
| | | src="@/assets/public/active.png" /> |
| | | <img v-else @click="selectNum(index, 1, sort(1, index))" |
| | | src="@/assets/public/noActive.png" /> |
| | | <div>1分</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-body-left-item-score-num" |
| | | :class="yesOrNoActive(sort(0, index)) && 'activeScore'"> |
| | | <img v-if="yesOrNoActive(sort(0, index))" |
| | | src="@/assets/public/active.png" /> |
| | | <img v-else @click="selectNum(index, 0, sort(0, index))" |
| | | src="@/assets/public/noActive.png" /> |
| | | <div>0分</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-else style="width: 100%;"> |
| | | <el-col :xs="16" :sm="16" :md="16" :lg="16" :xl="16"> |
| | | <div class="evaluateTable-body-left-item-score-num" |
| | | :class="yesOrNoActive(sort(2, index)) && 'activeScore'"> |
| | | <img v-if="yesOrNoActive(sort(2, index))" |
| | | src="@/assets/public/active.png" /> |
| | | <img v-else @click="selectNum(index, -3, sort(2, index))" |
| | | src="@/assets/public/noActive.png" /> |
| | | <div>是(-3分)</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8"> |
| | | <div class="evaluateTable-body-left-item-score-num" |
| | | :class="yesOrNoActive(sort(1, index)) && 'activeScore'"> |
| | | <img v-if="yesOrNoActive(sort(1, index))" |
| | | src="@/assets/public/active.png" /> |
| | | <img v-else @click="selectNum(index, 0, sort(1, index))" |
| | | src="@/assets/public/noActive.png" /> |
| | | <div>否(0分)</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="6"> |
| | | <div class="evaluateTable-body-right"> |
| | | <div class="evaluateTable-body-right-title">总分</div> |
| | | <div class="evaluateTable-body-right-num"> |
| | | <div>{{ total != null ? total : '[自动计算]' }}</div> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import store from "../../store"; |
| | | export default { |
| | | props: { |
| | | type: { |
| | | type: Number, |
| | | default: 1 //1 化验师 2 实验员 3 工艺工程师 |
| | | }, |
| | | isReadonly: { |
| | | type: Boolean, |
| | | default: false // 是否只读 |
| | | }, |
| | | viewJson: { |
| | | type: String, |
| | | default: '' //回显 |
| | | } |
| | | }, |
| | | computed: { |
| | | list() { |
| | | if (this.type == 1) return store.state.assay |
| | | if (this.type == 2) return store.state.experiment |
| | | if (this.type == 3) return store.state.craft |
| | | return store.state.assay |
| | | }, |
| | | }, |
| | | watch: { |
| | | activeIndex: { |
| | | handler(newVal, oldVal) { |
| | | this.total = null |
| | | this.activeIndex.map(item => { |
| | | this.total += item.score |
| | | }) |
| | | }, |
| | | deep: true |
| | | }, |
| | | viewJson: { |
| | | handler(newVal, oldVal) { |
| | | console.log("viewJson changed:", newVal) |
| | | if (newVal && this.isReadonly) { |
| | | try { |
| | | const parsedData = JSON.parse(newVal) |
| | | this.activeIndex = parsedData |
| | | console.log("activeIndex updated:", this.activeIndex) |
| | | } catch (e) { |
| | | console.error("Failed to parse viewJson:", e) |
| | | } |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | total: null, |
| | | activeIndex: [ |
| | | { |
| | | num: null, |
| | | score: 0 |
| | | }, |
| | | { |
| | | num: null, |
| | | score: 0 |
| | | }, |
| | | { |
| | | num: null, |
| | | score: 0 |
| | | }, |
| | | { |
| | | num: null, |
| | | score: 0 |
| | | }, |
| | | { |
| | | num: null, |
| | | score: 0 |
| | | }, |
| | | { |
| | | num: null, |
| | | score: 0 |
| | | }, |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | selectNum(index, score, num) { |
| | | if (this.isReadonly) return |
| | | this.activeIndex[index].score = score |
| | | this.activeIndex[index].num = num |
| | | }, |
| | | yesOrNoActive(num) { |
| | | let arr = this.activeIndex.filter(item => item.num == num) |
| | | return arr.length |
| | | }, |
| | | sort(num, index) { |
| | | return (index + 1) * 3 - num |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .evaluateTable-header { |
| | | font-weight: 500; |
| | | font-size: 20px; |
| | | color: #FFFFFF; |
| | | height: 70px; |
| | | background: linear-gradient(270deg, #0ACBCA 0%, #049C9A 100%); |
| | | box-shadow: 0px 6px 10px 0px rgba(4, 156, 154, 0.09); |
| | | border-radius: 10px; |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | padding: 0 23px 0 17px; |
| | | |
| | | &-text { |
| | | line-height: 70px; |
| | | } |
| | | } |
| | | |
| | | .evaluateTable-body { |
| | | background: #FFFFFF; |
| | | box-shadow: 0px 6px 10px 0px rgba(4, 156, 154, 0.09); |
| | | border-radius: 10px; |
| | | margin-top: -10px; |
| | | padding: 0 23px 27px 17px; |
| | | height: 100%; |
| | | |
| | | &-left { |
| | | margin-top: 21px; |
| | | |
| | | &-item { |
| | | background: #D7EFF4; |
| | | box-shadow: 0px 6px 10px 0px rgba(4, 156, 154, 0.09); |
| | | border-radius: 29px; |
| | | margin-bottom: 20px; |
| | | |
| | | &-text { |
| | | flex-shrink: 0; |
| | | line-height: 44px; |
| | | background: radial-gradient(0% 50% at 50% 50%, #0ACBCA 0%, #049C9A 100%); |
| | | box-shadow: 0px 6px 10px 0px rgba(4, 156, 154, 0.09); |
| | | border-radius: 29px; |
| | | text-align: center; |
| | | font-weight: bold; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | letter-spacing: 1px; |
| | | } |
| | | |
| | | &-score { |
| | | line-height: 44px; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .activeScore { |
| | | color: #049C9A; |
| | | } |
| | | |
| | | &-num { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | img { |
| | | width: 16px; |
| | | height: 16px; |
| | | margin-right: 13px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | div { |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | &-item:last-child { |
| | | margin-bottom: unset; |
| | | } |
| | | } |
| | | |
| | | .evaluateTable-body-right { |
| | | margin-top: 21px; |
| | | background: linear-gradient(to top, #0ACBCA 0%, #049C9A 100%); |
| | | border-radius: 10px; |
| | | padding-top: 35px; |
| | | min-height: 329px; |
| | | display: flex; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | margin-left: 16px; |
| | | |
| | | &-title { |
| | | font-family: 'Source Han Sans CN Normal'; |
| | | font-weight: 400; |
| | | font-size: 24px; |
| | | color: #FFFFFF; |
| | | line-height: 24px; |
| | | } |
| | | |
| | | &-num { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | font-family: 'SourceHanSansCN-Medium'; |
| | | font-weight: 500; |
| | | font-size: 44px; |
| | | color: #FFFFFF; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | }, |
| | | total: { |
| | | type: Number, |
| | | default: 20 |
| | | default: 0 |
| | | }, |
| | | queryForm: { |
| | | type: Object, |
| | |
| | | |
| | | } |
| | | |
| | | ::v-deep .el-table__expanded-cell { |
| | | padding: 0; |
| | | } |
| | | |
| | | ::v-deep .el-table .el-table__expand-icon { |
| | | display: none; |
| | | } |
| | | |
| | | .pagination { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | |
| | | </div> |
| | | </template> |
| | | <template v-if="$slots.table"> |
| | | <Table :data="tableData" :total="total" :height="height" :queryForm="queryForm" @currentChange="handleCurrentChange" |
| | | @sizeChange="handleSizeChange"> |
| | | <Table :data="tableData" :total="total" :height="height" :queryForm="queryForm" |
| | | @currentChange="handleCurrentChange" @sizeChange="handleSizeChange"> |
| | | <slot name="table"></slot> |
| | | </Table> |
| | | </template> |
| | | <template v-if="$slots.tableCustom"> |
| | | <slot name="tableCustom"></slot> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | import Card from '@/components/Card/index.vue' |
| | | import ShowDelConfirm from '@/components/showDelConfirm/index.vue' |
| | | import SelectMember from '@/components/SelectMember/index.vue' |
| | | import EvaluateTable from '@/components/EvaluateTable/index.vue' |
| | | import "aieditor/dist/style.css" |
| | | import './assets/tailwind.css' |
| | | import './styles/element-variables.less' |
| | |
| | | Vue.component('Card', Card) |
| | | Vue.component('ShowDelConfirm', ShowDelConfirm) |
| | | Vue.component('SelectMember', SelectMember) |
| | | Vue.component('EvaluateTable', EvaluateTable) |
| | | |
| | | Vue.prototype.msgsuccess = function (msg) { |
| | | this.$message({ |
| | |
| | | component: () => import("../views/dataManagement/confirmation-sheet/components/add.vue"), |
| | | }, |
| | | { |
| | | path: "sampleManage", |
| | | path: "/sampleManage", |
| | | meta: { |
| | | title: "样品管理", |
| | | keepAlive: true, |
| | | // keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleManage/list.vue"), |
| | | component: Parent, |
| | | children: [ |
| | | { |
| | | path: "manage", |
| | | meta: { |
| | | title: "样品管理", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleManage/list.vue"), |
| | | }, |
| | | { |
| | | path: "addSample", |
| | | name: "addPaddSamplelan", |
| | | meta: { |
| | | title: "新增样品", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleManage/addSample"), |
| | | }, { |
| | | path: "record", |
| | | meta: { |
| | | title: "取样操作记录列表", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleRecordList/list.vue"), |
| | | }, |
| | | { |
| | | path: "changeRecord", |
| | | name: "changeRecord", |
| | | meta: { |
| | | title: "填写取样操作记录", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleRecordList/changeRecord"), |
| | | }, { |
| | | path: "submissionList", |
| | | meta: { |
| | | title: "送样单列表", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleSubmissionList/list.vue"), |
| | | }, |
| | | { |
| | | path: "submission", |
| | | name: "submission", |
| | | meta: { |
| | | title: "送样单详情", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleSubmissionList/submission"), |
| | | }, |
| | | ] |
| | | |
| | | }, |
| | | { |
| | | path: "addSample", |
| | | name: "addPaddSamplelan", |
| | | path: "deliveryRecord", |
| | | meta: { |
| | | title: "新增样品", |
| | | title: "取样送样记录", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/SampleDeliveryRecord/list.vue"), |
| | | }, |
| | | { |
| | | path: "delivery", |
| | | name: "delivery", |
| | | meta: { |
| | | title: "送样详情", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleManage/addSample"), |
| | | component: () => import("../views/dataManagement/SampleDeliveryRecord/deliveryRecord"), |
| | | }, |
| | | { |
| | | path: "originalRecordTest", |
| | | meta: { |
| | | title: "原始检验记录", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/originalRecordTest/list.vue"), |
| | | }, |
| | | { |
| | | path: "originalRecordTest/detail", |
| | | name: "OriginalRecordTestDetail", |
| | | meta: { |
| | | title: "原始检验记录详情", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/originalRecordTest/detail.vue"), |
| | | }, |
| | | { |
| | | path: "inspectionReport", |
| | | meta: { |
| | | title: "检验报告管理", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/inspectionReport/list.vue"), |
| | | }, |
| | | { |
| | | path: "inspectionReport/detail", |
| | | name: "inspectionReportDetail", |
| | | meta: { |
| | | title: "检验报告详情", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/inspectionReport/detail.vue"), |
| | | }, |
| | | { |
| | | path: "testResultReport", |
| | | meta: { |
| | | title: "实验结果汇报", |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/testResultReport/list.vue"), |
| | | }, |
| | | { |
| | | path: "testResultReport/detail", |
| | | name: "testResultReportDetail", |
| | | meta: { |
| | | title: "实验结果详情", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/dataManagement/testResultReport/detail.vue"), |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/projectTeamIntegral/detail.vue"), |
| | | }, |
| | | { |
| | | // 超级管理员 |
| | | path: "taskList", |
| | | meta: { |
| | | title: "课题列表", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/taskList"), |
| | | }, |
| | | { |
| | | // 工艺工程师 审批人 实验员 超级管理员 |
| | | path: "restsTask", |
| | | meta: { |
| | | title: "实验员其他任务", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/restsTask"), |
| | | }, |
| | | { |
| | | // 超级管理员 工艺工程师 |
| | | path: "clinicalTrial", |
| | | meta: { |
| | | title: "临床试验积分列表", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/clinicalTrial"), |
| | | }, |
| | | { |
| | | // 化验师 审批人 |
| | | path: "testingAndEvaluation", |
| | | meta: { |
| | | title: "检测项评定列表", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/testingAndEvaluation"), |
| | | }, |
| | | { |
| | | // 化验师 实验员 |
| | | path: "experimentResults", |
| | | meta: { |
| | | title: "实验结果评定", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/experimentResults"), |
| | | }, |
| | | { |
| | | // 化验师 工艺工程师 审批人 |
| | | path: "assayTaskList", |
| | | meta: { |
| | | title: "课题评定列表", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/assayTaskList"), |
| | | }, |
| | | { |
| | | // 工艺工程师 |
| | | path: "processEngineerEvaluate", |
| | | meta: { |
| | | title: "工艺工程师工作评定详情", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/processEngineerEvaluate"), |
| | | }, |
| | | { |
| | | // 工艺工程师 |
| | | path: "testerWorkerEvaluate", |
| | | meta: { |
| | | title: "实验员工作评定", |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/testerWorkerEvaluate"), |
| | | }, |
| | | { |
| | | // 工艺工程师 |
| | | path: "addTesterWorkerEvaluate", |
| | | name: 'AddTesterWorkerEvaluate', |
| | | meta: { |
| | | title: "新增实验员工作评定", |
| | | hide: true, |
| | | keepAlive: true, |
| | | }, |
| | | component: () => import("../views/deliveryAssessment/testerWorkerEvaluate/add"), |
| | | }, |
| | | ] |
| | | } |
| | | ]; |
| | |
| | | keepAliveList: localStorage.getItem('keepAliveList') ? JSON.parse(localStorage.getItem('keepAliveList')) : [],//缓存页面 |
| | | tagList: localStorage.getItem('tagList') ? JSON.parse(localStorage.getItem('tagList')) : [],//标签列表 |
| | | isFold: false,//是否折叠 |
| | | assay: [ |
| | | '检验方法正确', |
| | | '实验检验相关记录完整', |
| | | '检验数据准确', |
| | | '检验过程异常问题的优化处理', |
| | | '检验时效完成度,安全操作', |
| | | '操作失败', |
| | | ],//化验师评定项 |
| | | experiment: [ |
| | | '实验方案熟悉度、设备及材料准备完整度', |
| | | '实验操作、取样、送样准确性', |
| | | '实验记录清晰完整度', |
| | | '实验过程异常问题的优化处理', |
| | | '实验操作时效完成度、安全操作', |
| | | '实验操作失败', |
| | | ],//实验员评定项 |
| | | craft: [ |
| | | '实验工作调度安排完成度', |
| | | '全程实验、化验异常问题处理', |
| | | '实验方案准确度、检验方法准确度', |
| | | '检查实验数据记录准确性', |
| | | '实验分析报告完成度', |
| | | '实验损失与失败', |
| | | ],//工艺工程师评定项 |
| | | }, |
| | | mutations: { |
| | | SET_MENUS(state, data) { |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="发送签字确认" |
| | | :visible.sync="visible" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="receive-dialog"> |
| | | <div class="receive-tip"> |
| | | 您已选中 <span class="sample-count">{{ sampleCount }}</span> 条样品发送,请签字确认 |
| | | </div> |
| | | |
| | | <div class="approval-dialog-approve"> |
| | | <div class="add-group"> |
| | | <div>*</div> |
| | | <span>签字确认</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="openSignature">签名</el-button> |
| | | </div> |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleConfirm" :disabled="!imgSrc"> |
| | | 确认发送 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <SignatureCanvas |
| | | :visible="signatureDialogVisible" |
| | | @confirm="handleSignatureConfirm" |
| | | @close="signatureDialogVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | |
| | | export default { |
| | | name: "ReceiveConfirmDialog", |
| | | components: { |
| | | SignatureCanvas, |
| | | }, |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | sampleCount: { |
| | | type: Number, |
| | | default: 1, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | signatureDialogVisible: false, |
| | | imgSrc: "", |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = ""; |
| | | }, |
| | | openSignature() { |
| | | this.signatureDialogVisible = true; |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | this.imgSrc = imageData; |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | | this.$message.warning("请先完成签名确认"); |
| | | return; |
| | | } |
| | | this.$emit("confirm", this.imgSrc); |
| | | this.handleClose(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | ::v-deep .el-dialog__header { |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .receive-dialog { |
| | | padding: 20px; |
| | | |
| | | .receive-tip { |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-bottom: 20px; |
| | | |
| | | .sample-count { |
| | | color: #409EFF; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .approval-dialog-approve { |
| | | margin-top: 26px; |
| | | |
| | | img { |
| | | border: 2px dashed #049c9a; |
| | | } |
| | | } |
| | | |
| | | .add-group { |
| | | padding-left: 25px; |
| | | margin-top: 14px; |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 19px; |
| | | |
| | | div { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | line-height: 21px; |
| | | margin: 0 32px 0 8px; |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | button { |
| | | width: 150px; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <Table :data="schedulingData" :total="schedulingTotal" :height="null"> |
| | | <template> |
| | | <el-table-column |
| | | prop="planCode" |
| | | 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="notifyTime" label="通知时间"></el-table-column> |
| | | <el-table-column |
| | | prop="startTime" |
| | | label="实验开始时间" |
| | | ></el-table-column> |
| | | <el-table-column prop="endTime" label="实验结束时间"></el-table-column> |
| | | <el-table-column prop="participants" label="参加人员"></el-table-column> |
| | | <el-table-column prop="status" label="状态"></el-table-column> |
| | | </template> |
| | | </Table> |
| | | |
| | | <!-- 送样-收样记录部分 --> |
| | | <div class="sample-record-section"> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>送样-收样记录</span> |
| | | <el-button |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | @click="showAdditives = !showAdditives" |
| | | > |
| | | {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }} |
| | | </el-button> |
| | | </div> |
| | | <div class="sample-code"> |
| | | 取样单编号:{{ form.sampleCode || "DD-25010BS01" }} |
| | | </div> |
| | | <div class="sample-code">待收样列表</div> |
| | | |
| | | <div class="sample-table"> |
| | | <Table |
| | | :data="sampleList" |
| | | :total="sampleTotal" |
| | | :height="null" |
| | | style="width: 100%" |
| | | > |
| | | <template> |
| | | <el-table-column |
| | | prop="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="processTime" |
| | | label="工艺时间间/h" |
| | | width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleName" |
| | | label="取样名称" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleCode" |
| | | label="取样样品编号" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="temperature" |
| | | label="温度" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column prop="ph" label="PH" width="100"></el-table-column> |
| | | <el-table-column |
| | | prop="waterAmount" |
| | | label="加水量" |
| | | width="100" |
| | | ></el-table-column> |
| | | <template v-if="showAdditives"> |
| | | <el-table-column |
| | | prop="additive1" |
| | | label="加辅1" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive2" |
| | | label="加辅2" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive3" |
| | | label="加辅3" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive4" |
| | | label="加辅4" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive5" |
| | | label="加辅5" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive6" |
| | | label="加辅6" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive7" |
| | | label="加辅7" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive8" |
| | | label="加辅8" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive9" |
| | | label="加辅9" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive10" |
| | | label="加辅10" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | </template> |
| | | <el-table-column |
| | | prop="sampleAmount" |
| | | label="取样量" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleTime" |
| | | label="取样时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column prop="photo" label="拍照" width="100"> |
| | | <template slot-scope="scope"> |
| | | <img |
| | | v-if="scope.row.photo" |
| | | :src="scope.row.photo" |
| | | class="sample-photo" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="operator" |
| | | label="操作人" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="status" |
| | | label="状态" |
| | | width="100" |
| | | ></el-table-column> |
| | | </template> |
| | | </Table> |
| | | </div> |
| | | <div class="received-samples"> |
| | | <div style="display: flex; align-items: center"> |
| | | <div class="sample-code">已收样列表</div> |
| | | |
| | | <el-button |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | style="margin-left: 16px" |
| | | @click="showReceivedColumns = !showReceivedColumns" |
| | | > |
| | | {{ showReceivedColumns ? "收起辅料详情" : "展开辅料详情" }} |
| | | </el-button> |
| | | </div> |
| | | <Table |
| | | :data="receivedSamples" |
| | | :total="receivedSamplesTotal" |
| | | :height="null" |
| | | style="width: 100%" |
| | | > |
| | | <template> |
| | | <el-table-column |
| | | prop="index" |
| | | label="序号" |
| | | width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleName" |
| | | label="取样名称" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleCode" |
| | | label="取样样品编号" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="temperature" |
| | | label="温度" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="waterAmount" |
| | | label="加水量" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column prop="ph" label="PH" width="100"></el-table-column> |
| | | <template v-if="showReceivedColumns"> |
| | | <el-table-column |
| | | prop="additive1" |
| | | label="加辅1" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive2" |
| | | label="加辅2" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive3" |
| | | label="加辅3" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive4" |
| | | label="加辅4" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive5" |
| | | label="加辅5" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | </template> |
| | | <el-table-column |
| | | prop="sampleAmount" |
| | | label="取样量" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sendTime" |
| | | label="送样时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sender" |
| | | label="送样人" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="receiveTime" |
| | | label="收样时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="receiver" |
| | | label="收样人" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="status" |
| | | label="状态" |
| | | width="100" |
| | | fixed="right" |
| | | ></el-table-column> |
| | | </template> |
| | | </Table> |
| | | </div> |
| | | </div> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "SampleSubmission", |
| | | data() { |
| | | return { |
| | | showAdditives: true, |
| | | showReceivedColumns: true, |
| | | schedulingData: [ |
| | | { |
| | | planCode: "DD-EX001", |
| | | experimentCode: "DD-EX001", |
| | | experimentName: "名称名称名称", |
| | | notifyTime: "2025-1-2 14:50:19", |
| | | startTime: "2025-02-27", |
| | | endTime: "2025-06-06", |
| | | participants: "张弘, 李天浩, 陈三, 李四", |
| | | status: "已确认", |
| | | }, |
| | | ], |
| | | schedulingTotal: 1, |
| | | form: { |
| | | sampleCode: "DD-25010BS01", |
| | | }, |
| | | sampleList: [ |
| | | { |
| | | index: 1, |
| | | processTime: "2", |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | temperature: "34", |
| | | ph: "34", |
| | | waterAmount: "34", |
| | | additive1: "10g", |
| | | additive2: "5g", |
| | | additive3: "3g", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "34", |
| | | sampleTime: "2025-1-9 15:26:08", |
| | | photo: "@/assets/sample-photos/photo1.jpg", |
| | | operator: "张三", |
| | | status: "待发送", |
| | | }, |
| | | { |
| | | index: 2, |
| | | processTime: "4", |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | temperature: "23", |
| | | ph: "23", |
| | | waterAmount: "23", |
| | | additive1: "8g", |
| | | additive2: "4g", |
| | | additive3: "", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "23", |
| | | sampleTime: "2025-1-9 15:26:08", |
| | | photo: "@/assets/sample-photos/photo2.jpg", |
| | | operator: "李四", |
| | | status: "待接收", |
| | | }, |
| | | { |
| | | index: 3, |
| | | processTime: "8", |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | temperature: "23", |
| | | ph: "23", |
| | | waterAmount: "23", |
| | | additive1: "", |
| | | additive2: "", |
| | | additive3: "", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "23", |
| | | sampleTime: "2025-1-9 15:26:08", |
| | | photo: "@/assets/sample-photos/photo3.jpg", |
| | | operator: "王五", |
| | | status: "已接收", |
| | | }, |
| | | ], |
| | | sampleTotal: 3, |
| | | }; |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin-bottom: 20px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | div, |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | |
| | | div:before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | .el-button { |
| | | margin-left: 16px; |
| | | } |
| | | } |
| | | |
| | | .sample-record-section { |
| | | .sample-code { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.88); |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .table-header { |
| | | margin-bottom: 16px; |
| | | text-align: left; |
| | | } |
| | | |
| | | .sample-photo { |
| | | width: 60px; |
| | | height: 60px; |
| | | object-fit: cover; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="项目课题方案名称:"> |
| | | <el-input v-model="form.planName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建人:"> |
| | | <el-input v-model="form.creator" 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" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</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">待接收样品列表</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column |
| | | prop="planName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column prop="experimentNo" label="实验编号"></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column prop="sampleNo" label="取样单编号"></el-table-column> |
| | | <el-table-column prop="creator" label="创建人"></el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间"></el-table-column> |
| | | <el-table-column |
| | | prop="sampleStatus" |
| | | label="样品总数/待接收/已接收" |
| | | ></el-table-column> |
| | | <el-table-column label="操作" width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleDetail(scope.row)" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | export default { |
| | | name: "ProjectList", |
| | | data() { |
| | | return { |
| | | form: { |
| | | planName: "", |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | }, |
| | | 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", |
| | | }, |
| | | ], |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | this.form = { |
| | | planName: "", |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | | // 实现查询逻辑 |
| | | console.log("查询条件:", this.form); |
| | | this.getTableData(); |
| | | }, |
| | | handleDetail(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/delivery", |
| | | query: { |
| | | id: row.id, |
| | | type: "view", |
| | | }, |
| | | }); |
| | | }, |
| | | getTableData() { |
| | | // 获取列表数据 |
| | | this.tableData = this.mockListData; |
| | | this.total = this.mockListData.length; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tableTitle { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .title { |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049c9a; |
| | | width: unset; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div>一 、实验目的</div> |
| | | </div> |
| | | </div> |
| | | <AiEditor |
| | | ref="purposeEditor" |
| | | v-model="editorContents.purpose" |
| | | height="200px" |
| | | placeholder="请输入实验目的..." |
| | | /> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | |
| | | <div class="item-title"> |
| | | <span>1.实验材料</span> |
| | | </div> |
| | | <AiEditor |
| | | ref="materialEditor" |
| | | v-model="editorContents.material" |
| | | height="200px" |
| | | placeholder="请输入实验材料..." |
| | | /> |
| | | <div class="item-title"> |
| | | <span>2.实验设备</span> |
| | | </div> |
| | | |
| | | <AiEditor |
| | | ref="equipmentEditor" |
| | | v-model="editorContents.equipment" |
| | | height="200px" |
| | | placeholder="请输入实验设备..." |
| | | /> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>三 、检测方法及开发</div> |
| | | </div> |
| | | </div> |
| | | <AiEditor |
| | | ref="methodEditor" |
| | | v-model="editorContents.method" |
| | | height="200px" |
| | | placeholder="请输入检测方法及开发..." |
| | | /> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>四 、实验步骤</div> |
| | | </div> |
| | | </div> |
| | | <AiEditor |
| | | ref="stepsEditor" |
| | | v-model="editorContents.steps" |
| | | height="200px" |
| | | placeholder="请输入实验步骤..." |
| | | /> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>五 、数据采集及分析</div> |
| | | </div> |
| | | </div> |
| | | <AiEditor |
| | | ref="dataAnalysisEditor" |
| | | v-model="editorContents.dataAnalysis" |
| | | height="200px" |
| | | placeholder="请输入数据采集及分析..." |
| | | /> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>六 、结果评估</div> |
| | | </div> |
| | | </div> |
| | | <AiEditor |
| | | ref="evaluationEditor" |
| | | v-model="editorContents.evaluation" |
| | | height="200px" |
| | | placeholder="请输入结果评估..." |
| | | /> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>注意事项</span> |
| | | </div> |
| | | </div> |
| | | <AiEditor |
| | | ref="notesEditor" |
| | | v-model="editorContents.notes" |
| | | height="200px" |
| | | placeholder="请输入注意事项..." |
| | | /> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | <el-button type="primary" class="save-btn" @click="handleSave">保存</el-button> |
| | | <el-button @click="handleSaveDraft">存草稿</el-button> |
| | | </div> |
| | | </template> |
| | | <SelectMember ref="selectMember" /> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import AiEditor from '@/components/AiEditor' |
| | | // import { savePlan, saveDraft } from '@/api/approvalPlan' |
| | | |
| | | export default { |
| | | name: "AddProject", |
| | | components: { |
| | | AiEditor |
| | | }, |
| | | data() { |
| | | return { |
| | | form: {}, |
| | | form: { |
| | | name: '', |
| | | description: '', |
| | | purpose: '', |
| | | material: '', |
| | | equipment: '', |
| | | method: '', |
| | | steps: '', |
| | | dataAnalysis: '', |
| | | evaluation: '', |
| | | notes: '' |
| | | }, |
| | | editorContents: { |
| | | purpose: '', |
| | | material: '', |
| | | equipment: '', |
| | | method: '', |
| | | steps: '', |
| | | dataAnalysis: '', |
| | | evaluation: '', |
| | | notes: '' |
| | | }, |
| | | rules: { |
| | | name: [ |
| | | { required: true, message: "请输入项目组名称", trigger: "blur" }, |
| | |
| | | description: [ |
| | | { required: true, message: "请输入项目组描述", trigger: "blur" }, |
| | | ], |
| | | purpose: [ |
| | | { required: true, message: "请输入实验目的", trigger: "blur" }, |
| | | ], |
| | | material: [ |
| | | { required: true, message: "请输入实验材料", trigger: "blur" }, |
| | | ], |
| | | equipment: [ |
| | | { required: true, message: "请输入实验设备", trigger: "blur" }, |
| | | ], |
| | | method: [ |
| | | { required: true, message: "请输入检测方法及开发", trigger: "blur" }, |
| | | ], |
| | | steps: [ |
| | | { required: true, message: "请输入实验步骤", trigger: "blur" }, |
| | | ], |
| | | dataAnalysis: [ |
| | | { required: true, message: "请输入数据采集及分析", trigger: "blur" }, |
| | | ], |
| | | evaluation: [ |
| | | { required: true, message: "请输入结果评估", trigger: "blur" }, |
| | | ], |
| | | notes: [ |
| | | { required: true, message: "请输入注意事项", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | }; |
| | | }, |
| | | methods: { |
| | | submitForm() { |
| | | // 获取所有编辑器的内容 |
| | | getAllEditorContent() { |
| | | return { |
| | | purpose: this.$refs.purposeEditor.getContent(), |
| | | material: this.$refs.materialEditor.getContent(), |
| | | equipment: this.$refs.equipmentEditor.getContent(), |
| | | method: this.$refs.methodEditor.getContent(), |
| | | steps: this.$refs.stepsEditor.getContent(), |
| | | dataAnalysis: this.$refs.dataAnalysisEditor.getContent(), |
| | | evaluation: this.$refs.evaluationEditor.getContent(), |
| | | notes: this.$refs.notesEditor.getContent() |
| | | } |
| | | }, |
| | | // 保存 |
| | | handleSave() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | console.log("submit!"); |
| | | const formData = { |
| | | ...this.form, |
| | | ...this.getAllEditorContent() |
| | | } |
| | | console.log('保存数据:', formData) |
| | | this.$message.success('保存成功') |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | addMember() { |
| | | this.$refs.selectMember.open(); |
| | | }, |
| | | memberList(i) { |
| | | switch (i) { |
| | | case 1: |
| | | return [1]; |
| | | case 2: |
| | | return [1]; |
| | | case 3: |
| | | return [1, 2, 3, 4, 5, 6, 7, 8]; |
| | | case 4: |
| | | return [1, 2, 3, 4, 5, 6, 7, 8]; |
| | | default: |
| | | break; |
| | | // 保存草稿 |
| | | handleSaveDraft() { |
| | | const formData = { |
| | | ...this.form, |
| | | ...this.getAllEditorContent(), |
| | | status: 'draft' |
| | | } |
| | | console.log('草稿数据:', formData) |
| | | this.$message.success('草稿保存成功') |
| | | }, |
| | | }, |
| | | }; |
| | |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .ai-editor-container { |
| | | width: 75%; |
| | | margin: 20px 0; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | background: #fff; |
| | | } |
| | | </style> |
| | |
| | | } |
| | | |
| | | .header-title:first-child { |
| | | margin-top: 0px; |
| | | .header-title-left { |
| | | margin-top: 0; |
| | | } |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="新增检测数据" |
| | | :visible.sync="dialogVisible" |
| | | width="60%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="sample-dialog"> |
| | | <div class="sample-content"> |
| | | <div class="form-content"> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-position="top" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测样编号" prop="sampleCode"> |
| | | <el-input |
| | | v-model="form.sampleCode" |
| | | placeholder="请输入检测样编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测数据" prop="testData"> |
| | | <el-input |
| | | v-model="form.testData" |
| | | placeholder="请输入检测数据" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="检测类型" prop="testTypes"> |
| | | <el-checkbox-group v-model="form.testTypes"> |
| | | <el-checkbox label="photo">拍照</el-checkbox> |
| | | <el-checkbox label="spectrum">图谱</el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row v-if="showPhotoUpload" :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="检测拍照" prop="photos"> |
| | | <div v-if="isIPad"> |
| | | <el-button type="primary" @click="handleIPadPhoto">拍照</el-button> |
| | | <el-button type="primary" @click="handleIPadUpload">上传</el-button> |
| | | </div> |
| | | <el-upload |
| | | v-else |
| | | class="upload-demo" |
| | | action="#" |
| | | :file-list="photoList" |
| | | :auto-upload="false" |
| | | list-type="picture-card" |
| | | :on-change="handlePhotoChange" |
| | | > |
| | | <i class="el-icon-plus"></i> |
| | | <!-- <div class="el-upload__tip" slot="tip">支持 jpg、png 格式文件</div> --> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row v-if="showSpectrumUpload" :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="检测图谱" prop="spectrums"> |
| | | <div v-if="isIPad"> |
| | | <el-button type="primary" @click="handleIPadSpectrum">选择图谱</el-button> |
| | | </div> |
| | | <el-upload |
| | | v-else |
| | | class="upload-file" |
| | | action="#" |
| | | :file-list="spectrumList" |
| | | :auto-upload="false" |
| | | :on-change="handleSpectrumChange" |
| | | :on-remove="handleSpectrumRemove" |
| | | > |
| | | <el-button type="primary"> |
| | | <i class="el-icon-upload"></i> 选择文件 |
| | | </el-button> |
| | | <div class="el-upload__tip" slot="tip">支持 jpg、png、pdf 格式文件</div> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleSubmit">确 定</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "AddDialog", |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | isIPad: /iPad/i.test(navigator.userAgent), |
| | | form: { |
| | | sampleCode: "", |
| | | testData: "", |
| | | testTypes: ["photo"], // 默认选中拍照 |
| | | photos: [], |
| | | spectrums: [] |
| | | }, |
| | | rules: { |
| | | sampleCode: [ |
| | | { required: true, message: "请输入检测样编号", trigger: "blur" } |
| | | ], |
| | | testData: [ |
| | | { required: true, message: "请输入检测数据", trigger: "blur" } |
| | | ], |
| | | testTypes: [ |
| | | { |
| | | type: 'array', |
| | | required: true, |
| | | message: "请至少选择一种检测类型", |
| | | trigger: "change" |
| | | } |
| | | ], |
| | | photos: [ |
| | | { |
| | | required: true, |
| | | message: "请上传检测照片", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (this.form.testTypes.includes('photo') && (!this.photoList || !this.photoList.length)) { |
| | | callback(new Error('请上传检测照片')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | spectrums: [ |
| | | { |
| | | required: true, |
| | | message: "请上传检测图谱", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (this.form.testTypes.includes('spectrum') && (!this.spectrumList || !this.spectrumList.length)) { |
| | | callback(new Error('请上传检测图谱')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | photoList: [], |
| | | spectrumList: [] |
| | | }; |
| | | }, |
| | | computed: { |
| | | dialogVisible: { |
| | | get() { |
| | | return this.visible; |
| | | }, |
| | | set(val) { |
| | | this.$emit("update:visible", val); |
| | | } |
| | | }, |
| | | showPhotoUpload() { |
| | | return this.form.testTypes.includes('photo'); |
| | | }, |
| | | showSpectrumUpload() { |
| | | return this.form.testTypes.includes('spectrum'); |
| | | } |
| | | }, |
| | | methods: { |
| | | setFormData(data) { |
| | | // 设置基础表单数据 |
| | | this.form.sampleCode = data.sampleCode; |
| | | this.form.testData = data.testData; |
| | | this.form.testTypes = data.testTypes; |
| | | |
| | | // 设置照片列表 |
| | | if (data.photos && data.photos.length) { |
| | | this.photoList = data.photos.map(photo => ({ |
| | | name: photo.name, |
| | | url: photo.url, |
| | | status: 'success' |
| | | })); |
| | | } else { |
| | | this.photoList = []; |
| | | } |
| | | |
| | | // 设置图谱列表 |
| | | if (data.spectrums && data.spectrums.length) { |
| | | this.spectrumList = data.spectrums.map(spectrum => ({ |
| | | name: spectrum.name, |
| | | url: spectrum.url, |
| | | status: 'success' |
| | | })); |
| | | } else { |
| | | this.spectrumList = []; |
| | | } |
| | | |
| | | // 重置表单校验状态 |
| | | this.$nextTick(() => { |
| | | this.$refs.form?.clearValidate(); |
| | | }); |
| | | }, |
| | | handleClose() { |
| | | this.dialogVisible = false; |
| | | this.$refs.form?.resetFields(); |
| | | this.photoList = []; |
| | | this.spectrumList = []; |
| | | this.form = { |
| | | sampleCode: "", |
| | | testData: "", |
| | | testTypes: ["photo"], |
| | | photos: [], |
| | | spectrums: [] |
| | | }; |
| | | }, |
| | | handleSubmit() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | const submitData = { |
| | | ...this.form, |
| | | photos: this.photoList, |
| | | spectrums: this.spectrumList |
| | | }; |
| | | this.$emit("success", submitData); |
| | | } |
| | | }); |
| | | }, |
| | | handlePhotoChange(file, fileList) { |
| | | this.photoList = fileList; |
| | | this.$refs.form.validateField('photos'); |
| | | }, |
| | | handleSpectrumChange(file, fileList) { |
| | | this.spectrumList = fileList; |
| | | this.$refs.form.validateField('spectrums'); |
| | | }, |
| | | handleSpectrumRemove(file) { |
| | | // 处理文件移除逻辑 |
| | | }, |
| | | // iPad 相关方法 |
| | | handleIPadPhoto() { |
| | | // TODO: 调用 iPad 拍照功能 |
| | | console.log('调用 iPad 拍照功能'); |
| | | }, |
| | | handleIPadUpload() { |
| | | // TODO: 调用 iPad 上传功能 |
| | | console.log('调用 iPad 上传功能'); |
| | | }, |
| | | handleIPadSpectrum() { |
| | | // TODO: 调用 iPad 选择图谱功能 |
| | | console.log('调用 iPad 选择图谱功能'); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | ::v-deep .el-dialog__body { |
| | | padding: 0; |
| | | max-height: calc(100vh - 200px); // 设置最大高度 |
| | | } |
| | | |
| | | ::v-deep .el-dialog { |
| | | margin-top: 5vh !important; // 调整弹窗位置 |
| | | max-height: 90vh; // 设置弹窗最大高度 |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-dialog__body { |
| | | flex: 1; |
| | | overflow: hidden; // 防止出现双滚动条 |
| | | } |
| | | } |
| | | |
| | | .sample-dialog { |
| | | height: 100%; |
| | | |
| | | .sample-content { |
| | | background: #ffffff; |
| | | border-radius: 10px; |
| | | padding: 20px; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .form-content { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding: 0 10px; |
| | | max-height: calc(90vh - 250px); // 设置内容区域最大高度 |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: #c0c4cc; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-track { |
| | | background: #f5f7fa; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 15px 20px; |
| | | border-top: 1px solid #e4e7ed; |
| | | margin-top: auto; // 保持在底部 |
| | | |
| | | button { |
| | | width: 150px; |
| | | } |
| | | } |
| | | |
| | | .upload-demo { |
| | | ::v-deep { |
| | | .el-upload--picture-card { |
| | | width: 120px; |
| | | height: 120px; |
| | | line-height: 120px; |
| | | } |
| | | |
| | | .el-upload-list--picture-card { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | |
| | | .el-upload-list__item { |
| | | width: 120px; |
| | | height: 120px; |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | // 让上传按钮始终显示在列表最后 |
| | | .el-upload--picture-card { |
| | | order: 9999; |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | // 包裹容器也使用flex布局 |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .el-row { |
| | | margin-bottom: 20px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; // 最后一行不要margin |
| | | } |
| | | } |
| | | |
| | | ::v-deep .el-form-item--small.el-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | ::v-deep .el-form-item__label { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | // 优化表单布局 |
| | | ::v-deep .el-form { |
| | | .el-form-item { |
| | | margin-bottom: 15px; // 减小表单项间距 |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 优化上传区域布局 |
| | | ::v-deep .el-upload-list--picture-card { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; // 设置图片间距 |
| | | } |
| | | |
| | | .upload-file { |
| | | ::v-deep { |
| | | .el-upload-list { |
| | | margin-top: 10px; |
| | | } |
| | | .el-upload-list__item { |
| | | transition: all .3s; |
| | | &:hover { |
| | | background-color: #f5f7fa; |
| | | } |
| | | } |
| | | .el-upload__tip { |
| | | color: #909399; |
| | | font-size: 12px; |
| | | margin-top: 8px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | > |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <el-button type="primary" class="el-icon-plus" @click="handleAddTask">选择实验调度</el-button> |
| | | </div> |
| | | |
| | | <Table :data="taskTableData" :total="0" :height="null" class="rwuTable"> |
| | | <el-table-column prop="index" label="所属项目课题方案" width="200"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="实验编号"></el-table-column> |
| | | <el-table-column prop="testData" label="实验名称"></el-table-column> |
| | | <el-table-column prop="testData" label="通知时间"></el-table-column> |
| | | <el-table-column prop="testData" label="实验开始时间"></el-table-column> |
| | | <el-table-column prop="testData" label="实验结束时间"></el-table-column> |
| | | <el-table-column prop="testData" label="参加人员"></el-table-column> |
| | | <el-table-column prop="testData" label="状态"></el-table-column> |
| | | </Table> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>本次检验结果总表</div> |
| | | </div> |
| | | </div> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>本次检验结果</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn">发送</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | </el-form> |
| | | <!-- 添加检测数据弹窗 --> |
| | | <add-dialog |
| | | ref="addDialog" |
| | | :visible.sync="dialogVisible" |
| | | @success="handleTaskSubmit" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import AddDialog from './components/addDialog.vue' |
| | | import moment from 'moment' |
| | | |
| | | export default { |
| | | name: "AddProject", |
| | | components: { |
| | | AddDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | isEdit: false, |
| | | currentEditIndex: -1, |
| | | form: { |
| | | recordNo: '', |
| | | testItemName: '', |
| | | testItemNo: '', |
| | | testMethodName: '', |
| | | testMethodNo: '' |
| | | }, |
| | | rules: { |
| | | recordNo: [{ required: true, message: "请输入原始检验记录编号", trigger: "blur" }], |
| | | testItemName: [{ required: true, message: "请输入检测项名字", trigger: "blur" }], |
| | | testItemNo: [{ required: true, message: "请输入检测项编号", trigger: "blur" }], |
| | | testMethodName: [{ required: true, message: "请输入检测方法名字", trigger: "blur" }], |
| | | testMethodNo: [{ required: true, message: "请输入检测方法编号", trigger: "blur" }] |
| | | }, |
| | | taskTableData: [] |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleAddTask() { |
| | | this.isEdit = false; |
| | | this.currentEditIndex = -1; |
| | | this.dialogVisible = true; |
| | | }, |
| | | handleEditTask(row) { |
| | | this.isEdit = true; |
| | | this.currentEditIndex = this.taskTableData.findIndex(item => item === row); |
| | | |
| | | const editData = { |
| | | sampleCode: row.sampleCode, |
| | | testData: row.testData, |
| | | testTypes: [], |
| | | photos: [], |
| | | spectrums: [] |
| | | }; |
| | | |
| | | if (row.photos && row.photos.length > 0) { |
| | | editData.testTypes.push('photo'); |
| | | editData.photos = row.photos.map(photo => ({ |
| | | name: photo.name, |
| | | url: photo.url, |
| | | raw: null |
| | | })); |
| | | } |
| | | if (row.spectrums && row.spectrums.length > 0) { |
| | | editData.testTypes.push('spectrum'); |
| | | editData.spectrums = row.spectrums.map(spectrum => ({ |
| | | name: spectrum.name, |
| | | url: spectrum.url, |
| | | raw: null |
| | | })); |
| | | } |
| | | |
| | | this.$nextTick(() => { |
| | | this.dialogVisible = true; |
| | | this.$refs.addDialog.setFormData(editData); |
| | | }); |
| | | }, |
| | | handleDeleteTask(row) { |
| | | this.$confirm("确认删除该检测数据吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | const index = this.taskTableData.findIndex((item) => item === row); |
| | | if (index > -1) { |
| | | const item = this.taskTableData[index]; |
| | | if (item.photos) { |
| | | item.photos.forEach(photo => { |
| | | if (photo.url.startsWith('blob:')) { |
| | | URL.revokeObjectURL(photo.url); |
| | | } |
| | | }); |
| | | } |
| | | if (item.spectrums) { |
| | | item.spectrums.forEach(spectrum => { |
| | | if (spectrum.url.startsWith('blob:')) { |
| | | URL.revokeObjectURL(spectrum.url); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.taskTableData.splice(index, 1); |
| | | this.$message.success("删除成功"); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | handleTaskSubmit(formData) { |
| | | const photos = formData.photos.map(file => ({ |
| | | name: file.name, |
| | | url: file.url || URL.createObjectURL(file.raw) |
| | | })); |
| | | |
| | | const spectrums = formData.spectrums.map(file => ({ |
| | | name: file.name, |
| | | url: file.url || URL.createObjectURL(file.raw) |
| | | })); |
| | | |
| | | const newData = { |
| | | sampleCode: formData.sampleCode, |
| | | testData: formData.testData, |
| | | testResult: '', |
| | | photos, |
| | | spectrums, |
| | | createTime: this.isEdit ? this.taskTableData[this.currentEditIndex].createTime : moment().format('YYYY-MM-DD HH:mm:ss') |
| | | }; |
| | | |
| | | if (this.isEdit && this.currentEditIndex > -1) { |
| | | const oldData = this.taskTableData[this.currentEditIndex]; |
| | | if (oldData.photos) { |
| | | oldData.photos.forEach(photo => { |
| | | if (photo.url.startsWith('blob:') && !photos.find(p => p.url === photo.url)) { |
| | | URL.revokeObjectURL(photo.url); |
| | | } |
| | | }); |
| | | } |
| | | if (oldData.spectrums) { |
| | | oldData.spectrums.forEach(spectrum => { |
| | | if (spectrum.url.startsWith('blob:') && !spectrums.find(s => s.url === spectrum.url)) { |
| | | URL.revokeObjectURL(spectrum.url); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.taskTableData.splice(this.currentEditIndex, 1, newData); |
| | | this.$message.success('更新成功'); |
| | | } else { |
| | | this.taskTableData.push(newData); |
| | | this.$message.success('添加成功'); |
| | | } |
| | | |
| | | this.dialogVisible = false; |
| | | this.isEdit = false; |
| | | this.currentEditIndex = -1; |
| | | }, |
| | | getPhotoUrls(photos) { |
| | | return photos.map(photo => photo.url); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .el-form--inline .el-form-item { |
| | | margin-right: 83px; |
| | | } |
| | | |
| | | .header-title { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 13px; |
| | | margin-top: 38px; |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .rwuTable { |
| | | width: 85%; |
| | | padding-left: 40px; |
| | | } |
| | | |
| | | .add-project-footer { |
| | | margin-top: 43px; |
| | | |
| | | button { |
| | | width: 220px; |
| | | } |
| | | |
| | | .save-btn { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .image-preview { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-wrap: wrap; |
| | | |
| | | .preview-image { |
| | | width: 50px; |
| | | height: 50px; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .image-slot { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: #f5f7fa; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .spectrum-link { |
| | | display: block; |
| | | margin-bottom: 5px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="项目课题方案名称:"> |
| | | <el-input v-model="form.projectPlan" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="所属实验编号:"> |
| | | <el-input v-model="form.experimentNo" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建人:"> |
| | | <el-input v-model="form.creator" 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" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.experimentName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <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" @click="handleAdd"> |
| | | <div class="flex a-center"> |
| | | <div class="title active">新增检验报告</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="projectPlan" label="所属项目课题方案" ></el-table-column> |
| | | <el-table-column prop="experimentNo" label="所属实验编号" ></el-table-column> |
| | | <el-table-column prop="experimentName" label="实验名称" ></el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间" ></el-table-column> |
| | | <el-table-column prop="creator" label="创建人" ></el-table-column> |
| | | <el-table-column prop="status" label="状态" > |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === '待提交' ? 'warning' : 'success'"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleSubmit(scope.row)">提交</el-button> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import store from '../../../store'; |
| | | export default { |
| | | name: "OriginalRecordTest", |
| | | data() { |
| | | return { |
| | | form: { |
| | | projectPlan: "", |
| | | experimentNo: "", |
| | | creator: "", |
| | | createTime: [], |
| | | experimentName: "" |
| | | }, |
| | | tableData: [ |
| | | { |
| | | id: '1', |
| | | projectPlan: '名称名称名称', |
| | | experimentNo: '31423764', |
| | | experimentName: '名称名称名称', |
| | | creator: '张三', |
| | | createTime: '2024-01-08', |
| | | status: '待提交' |
| | | } |
| | | ], |
| | | total: 5 |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | this.form = { |
| | | projectPlan: "", |
| | | experimentNo: "", |
| | | creator: "", |
| | | createTime: [], |
| | | experimentName: "" |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | | this.getTableData(); |
| | | }, |
| | | handleAdd(){ |
| | | this.$router.push({ |
| | | path: "/dataManagement/inspectionReport/detail", |
| | | query: { |
| | | type: 'add' |
| | | } |
| | | }); |
| | | }, |
| | | handleEdit(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/inspectionReport/detail", |
| | | query: { |
| | | id: row.id, |
| | | type: 'edit' |
| | | } |
| | | }); |
| | | }, |
| | | handleSubmit(row) { |
| | | this.$confirm('确认提交该检验报告?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | // TODO: 调用提交接口 |
| | | this.$message({ |
| | | type: 'success', |
| | | message: '提交成功!' |
| | | }); |
| | | this.getTableData(); |
| | | }).catch(() => { |
| | | this.$message({ |
| | | type: 'info', |
| | | message: '已取消提交' |
| | | }); |
| | | }); |
| | | }, |
| | | getTableData() { |
| | | this.tableData = [ |
| | | { |
| | | id: '1', |
| | | projectPlan: '名称名称名称', |
| | | experimentNo: '31423764', |
| | | experimentName: '名称名称名称', |
| | | creator: '张三', |
| | | createTime: '2024-01-08', |
| | | status: '待提交' |
| | | }, |
| | | { |
| | | id: '2', |
| | | projectPlan: '项目方案2', |
| | | experimentNo: '31423765', |
| | | experimentName: '实验名称2', |
| | | creator: '李四', |
| | | createTime: '2024-01-09', |
| | | status: '已提交' |
| | | } |
| | | ]; |
| | | this.total = this.tableData.length; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .tableTitle { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | cursor: pointer; |
| | | .title { |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | width: unset; |
| | | } |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="新增检测数据" |
| | | :visible.sync="dialogVisible" |
| | | width="60%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="sample-dialog"> |
| | | <div class="sample-content"> |
| | | <div class="form-content"> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-position="top" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测样编号" prop="sampleCode"> |
| | | <el-input |
| | | v-model="form.sampleCode" |
| | | placeholder="请输入检测样编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测数据" prop="testData"> |
| | | <el-input |
| | | v-model="form.testData" |
| | | placeholder="请输入检测数据" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="检测类型" prop="testTypes"> |
| | | <el-checkbox-group v-model="form.testTypes"> |
| | | <el-checkbox label="photo">拍照</el-checkbox> |
| | | <el-checkbox label="spectrum">图谱</el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row v-if="showPhotoUpload" :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="检测拍照" prop="photos"> |
| | | <div v-if="isIPad"> |
| | | <el-button type="primary" @click="handleIPadPhoto">拍照</el-button> |
| | | <el-button type="primary" @click="handleIPadUpload">上传</el-button> |
| | | </div> |
| | | <el-upload |
| | | v-else |
| | | class="upload-demo" |
| | | action="#" |
| | | :file-list="photoList" |
| | | :auto-upload="false" |
| | | list-type="picture-card" |
| | | :on-change="handlePhotoChange" |
| | | > |
| | | <i class="el-icon-plus"></i> |
| | | <!-- <div class="el-upload__tip" slot="tip">支持 jpg、png 格式文件</div> --> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row v-if="showSpectrumUpload" :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="检测图谱" prop="spectrums"> |
| | | <div v-if="isIPad"> |
| | | <el-button type="primary" @click="handleIPadSpectrum">选择图谱</el-button> |
| | | </div> |
| | | <el-upload |
| | | v-else |
| | | class="upload-file" |
| | | action="#" |
| | | :file-list="spectrumList" |
| | | :auto-upload="false" |
| | | :on-change="handleSpectrumChange" |
| | | :on-remove="handleSpectrumRemove" |
| | | > |
| | | <el-button type="primary"> |
| | | <i class="el-icon-upload"></i> 选择文件 |
| | | </el-button> |
| | | <div class="el-upload__tip" slot="tip">支持 jpg、png、pdf 格式文件</div> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleSubmit">确 定</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "AddDialog", |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | isIPad: /iPad/i.test(navigator.userAgent), |
| | | form: { |
| | | sampleCode: "", |
| | | testData: "", |
| | | testTypes: ["photo"], // 默认选中拍照 |
| | | photos: [], |
| | | spectrums: [] |
| | | }, |
| | | rules: { |
| | | sampleCode: [ |
| | | { required: true, message: "请输入检测样编号", trigger: "blur" } |
| | | ], |
| | | testData: [ |
| | | { required: true, message: "请输入检测数据", trigger: "blur" } |
| | | ], |
| | | testTypes: [ |
| | | { |
| | | type: 'array', |
| | | required: true, |
| | | message: "请至少选择一种检测类型", |
| | | trigger: "change" |
| | | } |
| | | ], |
| | | photos: [ |
| | | { |
| | | required: true, |
| | | message: "请上传检测照片", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (this.form.testTypes.includes('photo') && (!this.photoList || !this.photoList.length)) { |
| | | callback(new Error('请上传检测照片')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | spectrums: [ |
| | | { |
| | | required: true, |
| | | message: "请上传检测图谱", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (this.form.testTypes.includes('spectrum') && (!this.spectrumList || !this.spectrumList.length)) { |
| | | callback(new Error('请上传检测图谱')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | photoList: [], |
| | | spectrumList: [] |
| | | }; |
| | | }, |
| | | computed: { |
| | | dialogVisible: { |
| | | get() { |
| | | return this.visible; |
| | | }, |
| | | set(val) { |
| | | this.$emit("update:visible", val); |
| | | } |
| | | }, |
| | | showPhotoUpload() { |
| | | return this.form.testTypes.includes('photo'); |
| | | }, |
| | | showSpectrumUpload() { |
| | | return this.form.testTypes.includes('spectrum'); |
| | | } |
| | | }, |
| | | methods: { |
| | | setFormData(data) { |
| | | // 设置基础表单数据 |
| | | this.form.sampleCode = data.sampleCode; |
| | | this.form.testData = data.testData; |
| | | this.form.testTypes = data.testTypes; |
| | | |
| | | // 设置照片列表 |
| | | if (data.photos && data.photos.length) { |
| | | this.photoList = data.photos.map(photo => ({ |
| | | name: photo.name, |
| | | url: photo.url, |
| | | status: 'success' |
| | | })); |
| | | } else { |
| | | this.photoList = []; |
| | | } |
| | | |
| | | // 设置图谱列表 |
| | | if (data.spectrums && data.spectrums.length) { |
| | | this.spectrumList = data.spectrums.map(spectrum => ({ |
| | | name: spectrum.name, |
| | | url: spectrum.url, |
| | | status: 'success' |
| | | })); |
| | | } else { |
| | | this.spectrumList = []; |
| | | } |
| | | |
| | | // 重置表单校验状态 |
| | | this.$nextTick(() => { |
| | | this.$refs.form?.clearValidate(); |
| | | }); |
| | | }, |
| | | handleClose() { |
| | | this.dialogVisible = false; |
| | | this.$refs.form?.resetFields(); |
| | | this.photoList = []; |
| | | this.spectrumList = []; |
| | | this.form = { |
| | | sampleCode: "", |
| | | testData: "", |
| | | testTypes: ["photo"], |
| | | photos: [], |
| | | spectrums: [] |
| | | }; |
| | | }, |
| | | handleSubmit() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | const submitData = { |
| | | ...this.form, |
| | | photos: this.photoList, |
| | | spectrums: this.spectrumList |
| | | }; |
| | | this.$emit("success", submitData); |
| | | } |
| | | }); |
| | | }, |
| | | handlePhotoChange(file, fileList) { |
| | | this.photoList = fileList; |
| | | this.$refs.form.validateField('photos'); |
| | | }, |
| | | handleSpectrumChange(file, fileList) { |
| | | this.spectrumList = fileList; |
| | | this.$refs.form.validateField('spectrums'); |
| | | }, |
| | | handleSpectrumRemove(file) { |
| | | // 处理文件移除逻辑 |
| | | }, |
| | | // iPad 相关方法 |
| | | handleIPadPhoto() { |
| | | // TODO: 调用 iPad 拍照功能 |
| | | console.log('调用 iPad 拍照功能'); |
| | | }, |
| | | handleIPadUpload() { |
| | | // TODO: 调用 iPad 上传功能 |
| | | console.log('调用 iPad 上传功能'); |
| | | }, |
| | | handleIPadSpectrum() { |
| | | // TODO: 调用 iPad 选择图谱功能 |
| | | console.log('调用 iPad 选择图谱功能'); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | ::v-deep .el-dialog__body { |
| | | padding: 0; |
| | | max-height: calc(100vh - 200px); // 设置最大高度 |
| | | } |
| | | |
| | | ::v-deep .el-dialog { |
| | | margin-top: 5vh !important; // 调整弹窗位置 |
| | | max-height: 90vh; // 设置弹窗最大高度 |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-dialog__body { |
| | | flex: 1; |
| | | overflow: hidden; // 防止出现双滚动条 |
| | | } |
| | | } |
| | | |
| | | .sample-dialog { |
| | | height: 100%; |
| | | |
| | | .sample-content { |
| | | background: #ffffff; |
| | | border-radius: 10px; |
| | | padding: 20px; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .form-content { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding: 0 10px; |
| | | max-height: calc(90vh - 250px); // 设置内容区域最大高度 |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: #c0c4cc; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-track { |
| | | background: #f5f7fa; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 15px 20px; |
| | | border-top: 1px solid #e4e7ed; |
| | | margin-top: auto; // 保持在底部 |
| | | |
| | | button { |
| | | width: 150px; |
| | | } |
| | | } |
| | | |
| | | .upload-demo { |
| | | ::v-deep { |
| | | .el-upload--picture-card { |
| | | width: 120px; |
| | | height: 120px; |
| | | line-height: 120px; |
| | | } |
| | | |
| | | .el-upload-list--picture-card { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | |
| | | .el-upload-list__item { |
| | | width: 120px; |
| | | height: 120px; |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | // 让上传按钮始终显示在列表最后 |
| | | .el-upload--picture-card { |
| | | order: 9999; |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | // 包裹容器也使用flex布局 |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .el-row { |
| | | margin-bottom: 20px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; // 最后一行不要margin |
| | | } |
| | | } |
| | | |
| | | ::v-deep .el-form-item--small.el-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | ::v-deep .el-form-item__label { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | // 优化表单布局 |
| | | ::v-deep .el-form { |
| | | .el-form-item { |
| | | margin-bottom: 15px; // 减小表单项间距 |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 优化上传区域布局 |
| | | ::v-deep .el-upload-list--picture-card { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; // 设置图片间距 |
| | | } |
| | | |
| | | .upload-file { |
| | | ::v-deep { |
| | | .el-upload-list { |
| | | margin-top: 10px; |
| | | } |
| | | .el-upload-list__item { |
| | | transition: all .3s; |
| | | &:hover { |
| | | background-color: #f5f7fa; |
| | | } |
| | | } |
| | | .el-upload__tip { |
| | | color: #909399; |
| | | font-size: 12px; |
| | | margin-top: 8px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | > |
| | | <div style="padding-left: 25px"> |
| | | <el-form-item prop="recordNo" label="原始检验记录编号"> |
| | | <el-input v-model="form.recordNo" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>检测项信息</span> |
| | | </div> |
| | | </div> |
| | | <div style="padding-left: 25px"> |
| | | <el-form-item prop="testItemName" label="检测项名字"> |
| | | <el-input v-model="form.testItemName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item prop="testItemNo" label="检测项编号"> |
| | | <el-input v-model="form.testItemNo" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item prop="testMethodName" label="检测方法名字"> |
| | | <el-input v-model="form.testMethodName" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item prop="testMethodNo" label="检测方法编号"> |
| | | <el-input v-model="form.testMethodNo" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>一 、检测标准</span> |
| | | </div> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>二 、检测仪器</span> |
| | | </div> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>三 、检测试剂</span> |
| | | </div> |
| | | </div> |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>四 、检测步骤</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="header-title" style="margin-bottom: 38px"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>五 、检测数据及参照</span> |
| | | </div> |
| | | <el-button type="primary" class="el-icon-plus" @click="handleAddTask">添加检测数据</el-button> |
| | | </div> |
| | | |
| | | <Table :data="taskTableData" :total="0" :height="null" class="rwuTable"> |
| | | <el-table-column type="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="检测样编号"></el-table-column> |
| | | <el-table-column prop="testData" label="检测数据"></el-table-column> |
| | | <el-table-column label="检测图片" width="200"> |
| | | <template slot-scope="scope"> |
| | | <div class="image-preview" v-if="scope.row.photos && scope.row.photos.length"> |
| | | <el-image |
| | | v-for="(photo, index) in scope.row.photos" |
| | | :key="index" |
| | | :src="photo.url" |
| | | :preview-src-list="getPhotoUrls(scope.row.photos)" |
| | | fit="cover" |
| | | class="preview-image" |
| | | > |
| | | <div slot="error" class="image-slot"> |
| | | <i class="el-icon-picture-outline"></i> |
| | | </div> |
| | | </el-image> |
| | | </div> |
| | | <span v-else>无图片</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="检测图谱" width="200"> |
| | | <template slot-scope="scope"> |
| | | <div v-if="scope.row.spectrums && scope.row.spectrums.length"> |
| | | <el-link |
| | | v-for="(spectrum, index) in scope.row.spectrums" |
| | | :key="index" |
| | | type="primary" |
| | | :href="spectrum.url" |
| | | target="_blank" |
| | | class="spectrum-link" |
| | | > |
| | | {{ spectrum.name }} |
| | | </el-link> |
| | | </div> |
| | | <span v-else>无图谱</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="添加时间" width="180"></el-table-column> |
| | | <el-table-column label="操作" width="150"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEditTask(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDeleteTask(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>六 、检测结果预算</span> |
| | | </div> |
| | | </div> |
| | | <Table :data="taskTableData" :total="0" :height="null" class="rwuTable"> |
| | | <el-table-column type="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="检测样编号"></el-table-column> |
| | | <el-table-column prop="testData" label="检测数据"></el-table-column> |
| | | <el-table-column label="检测结果" > |
| | | <template slot-scope="scope"> |
| | | <el-input v-model="scope.row.testResult" placeholder="请输入检测结果"></el-input> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn">发送</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | </el-form> |
| | | <!-- 添加检测数据弹窗 --> |
| | | <add-dialog |
| | | ref="addDialog" |
| | | :visible.sync="dialogVisible" |
| | | @success="handleTaskSubmit" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import AddDialog from './components/addDialog.vue' |
| | | import moment from 'moment' |
| | | |
| | | export default { |
| | | name: "AddProject", |
| | | components: { |
| | | AddDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | isEdit: false, |
| | | currentEditIndex: -1, |
| | | form: { |
| | | recordNo: '', |
| | | testItemName: '', |
| | | testItemNo: '', |
| | | testMethodName: '', |
| | | testMethodNo: '' |
| | | }, |
| | | rules: { |
| | | recordNo: [{ required: true, message: "请输入原始检验记录编号", trigger: "blur" }], |
| | | testItemName: [{ required: true, message: "请输入检测项名字", trigger: "blur" }], |
| | | testItemNo: [{ required: true, message: "请输入检测项编号", trigger: "blur" }], |
| | | testMethodName: [{ required: true, message: "请输入检测方法名字", trigger: "blur" }], |
| | | testMethodNo: [{ required: true, message: "请输入检测方法编号", trigger: "blur" }] |
| | | }, |
| | | taskTableData: [] |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleAddTask() { |
| | | this.isEdit = false; |
| | | this.currentEditIndex = -1; |
| | | this.dialogVisible = true; |
| | | }, |
| | | handleEditTask(row) { |
| | | this.isEdit = true; |
| | | this.currentEditIndex = this.taskTableData.findIndex(item => item === row); |
| | | |
| | | const editData = { |
| | | sampleCode: row.sampleCode, |
| | | testData: row.testData, |
| | | testTypes: [], |
| | | photos: [], |
| | | spectrums: [] |
| | | }; |
| | | |
| | | if (row.photos && row.photos.length > 0) { |
| | | editData.testTypes.push('photo'); |
| | | editData.photos = row.photos.map(photo => ({ |
| | | name: photo.name, |
| | | url: photo.url, |
| | | raw: null |
| | | })); |
| | | } |
| | | if (row.spectrums && row.spectrums.length > 0) { |
| | | editData.testTypes.push('spectrum'); |
| | | editData.spectrums = row.spectrums.map(spectrum => ({ |
| | | name: spectrum.name, |
| | | url: spectrum.url, |
| | | raw: null |
| | | })); |
| | | } |
| | | |
| | | this.$nextTick(() => { |
| | | this.dialogVisible = true; |
| | | this.$refs.addDialog.setFormData(editData); |
| | | }); |
| | | }, |
| | | handleDeleteTask(row) { |
| | | this.$confirm("确认删除该检测数据吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | const index = this.taskTableData.findIndex((item) => item === row); |
| | | if (index > -1) { |
| | | const item = this.taskTableData[index]; |
| | | if (item.photos) { |
| | | item.photos.forEach(photo => { |
| | | if (photo.url.startsWith('blob:')) { |
| | | URL.revokeObjectURL(photo.url); |
| | | } |
| | | }); |
| | | } |
| | | if (item.spectrums) { |
| | | item.spectrums.forEach(spectrum => { |
| | | if (spectrum.url.startsWith('blob:')) { |
| | | URL.revokeObjectURL(spectrum.url); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.taskTableData.splice(index, 1); |
| | | this.$message.success("删除成功"); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | handleTaskSubmit(formData) { |
| | | const photos = formData.photos.map(file => ({ |
| | | name: file.name, |
| | | url: file.url || URL.createObjectURL(file.raw) |
| | | })); |
| | | |
| | | const spectrums = formData.spectrums.map(file => ({ |
| | | name: file.name, |
| | | url: file.url || URL.createObjectURL(file.raw) |
| | | })); |
| | | |
| | | const newData = { |
| | | sampleCode: formData.sampleCode, |
| | | testData: formData.testData, |
| | | testResult: '', |
| | | photos, |
| | | spectrums, |
| | | createTime: this.isEdit ? this.taskTableData[this.currentEditIndex].createTime : moment().format('YYYY-MM-DD HH:mm:ss') |
| | | }; |
| | | |
| | | if (this.isEdit && this.currentEditIndex > -1) { |
| | | const oldData = this.taskTableData[this.currentEditIndex]; |
| | | if (oldData.photos) { |
| | | oldData.photos.forEach(photo => { |
| | | if (photo.url.startsWith('blob:') && !photos.find(p => p.url === photo.url)) { |
| | | URL.revokeObjectURL(photo.url); |
| | | } |
| | | }); |
| | | } |
| | | if (oldData.spectrums) { |
| | | oldData.spectrums.forEach(spectrum => { |
| | | if (spectrum.url.startsWith('blob:') && !spectrums.find(s => s.url === spectrum.url)) { |
| | | URL.revokeObjectURL(spectrum.url); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.taskTableData.splice(this.currentEditIndex, 1, newData); |
| | | this.$message.success('更新成功'); |
| | | } else { |
| | | this.taskTableData.push(newData); |
| | | this.$message.success('添加成功'); |
| | | } |
| | | |
| | | this.dialogVisible = false; |
| | | this.isEdit = false; |
| | | this.currentEditIndex = -1; |
| | | }, |
| | | getPhotoUrls(photos) { |
| | | return photos.map(photo => photo.url); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .el-form--inline .el-form-item { |
| | | margin-right: 83px; |
| | | } |
| | | |
| | | .header-title { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 13px; |
| | | margin-top: 38px; |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .rwuTable { |
| | | width: 85%; |
| | | padding-left: 40px; |
| | | } |
| | | |
| | | .add-project-footer { |
| | | margin-top: 43px; |
| | | |
| | | button { |
| | | width: 220px; |
| | | } |
| | | |
| | | .save-btn { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .image-preview { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-wrap: wrap; |
| | | |
| | | .preview-image { |
| | | width: 50px; |
| | | height: 50px; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .image-slot { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: #f5f7fa; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .spectrum-link { |
| | | display: block; |
| | | margin-bottom: 5px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="所属实验编号:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建人:"> |
| | | <el-input v-model="form.creator" 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" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="审批人:"> |
| | | <el-input v-model="form.approver" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</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 active">原始记录检测列表</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="projectPlan" label="所属项目课题方案"></el-table-column> |
| | | <el-table-column prop="experimentNo" label="实验编号"></el-table-column> |
| | | <el-table-column prop="experimentName" label="实验名称"></el-table-column> |
| | | <el-table-column prop="creator" label="创建人"></el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间"></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === '已填写' ? 'success' : 'warning'"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="150"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "OriginalRecordTest", |
| | | data() { |
| | | return { |
| | | form: { |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "" |
| | | }, |
| | | tableData: [ |
| | | { |
| | | id: '1', |
| | | projectPlan: 'DD250218-JL01', |
| | | experimentNo: '31423764', |
| | | experimentName: '化学成分分析实验', |
| | | creator: '张三', |
| | | createTime: '2025-1-8 17:56:11', |
| | | status: '未填写' |
| | | }, |
| | | { |
| | | id: '2', |
| | | projectPlan: 'DD250218-JL02', |
| | | experimentNo: '31423765', |
| | | experimentName: '物理性能测试实验', |
| | | creator: '李四', |
| | | createTime: '2025-1-8 18:00:00', |
| | | status: '未填写' |
| | | }, |
| | | { |
| | | id: '3', |
| | | projectPlan: 'DD250218-JL03', |
| | | experimentNo: '31423766', |
| | | experimentName: '材料强度测试', |
| | | creator: '王五', |
| | | createTime: '2025-1-8 18:30:00', |
| | | status: '已填写' |
| | | }, |
| | | { |
| | | id: '4', |
| | | projectPlan: 'DD250218-JL04', |
| | | experimentNo: '31423767', |
| | | experimentName: '耐久性测试实验', |
| | | creator: '赵六', |
| | | createTime: '2025-1-8 19:00:00', |
| | | status: '已填写' |
| | | }, |
| | | { |
| | | id: '5', |
| | | projectPlan: 'DD250218-JL05', |
| | | experimentNo: '31423768', |
| | | experimentName: '环境适应性测试', |
| | | creator: '孙七', |
| | | createTime: '2025-1-8 19:30:00', |
| | | status: '未填写' |
| | | } |
| | | ], |
| | | total: 5 |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | this.form = { |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "" |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | | this.getTableData(); |
| | | }, |
| | | handleEdit(row) { |
| | | console.log("编辑数据:", row); |
| | | }, |
| | | handleDetail(id) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/originalRecordTest/detail", |
| | | query: { id } |
| | | }); |
| | | }, |
| | | getTableData() { |
| | | // TODO: 调用接口获取数据 |
| | | // this.tableData = []; |
| | | // this.total = 0; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .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; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | width: unset; |
| | | } |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | <el-button |
| | | v-if="isEngineer" |
| | | @click="showScheduling = true" |
| | | class="el-icon-plus" |
| | | type="primary" |
| | | > |
| | | 选择实验调度</el-button |
| | | > |
| | | <el-button v-if="isEngineer" @click="showScheduling = true" class="el-icon-plus" type="primary"> |
| | | 选择实验调度</el-button> |
| | | </div> |
| | | <Table :data="schedulingData" :total="schedulingTotal" :height="null"> |
| | | <template> |
| | | <el-table-column |
| | | prop="planCode" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <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="creator" label="状态"></el-table-column> |
| | | </template> |
| | | </Table> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>基础信息</span> |
| | | </div> |
| | | <el-form |
| | | v-if="!isExperimenter" |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | > |
| | | <el-form-item label="取样单编号" prop="sampleCode"> |
| | | <el-input |
| | | v-model="form.sampleCode" |
| | | :disabled="!isExperimenter" |
| | | :placeholder="isExperimenter ? '请输入取样单编号' : '自动生成'" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div v-else class="number">取样单编号:213421241</div> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>取样操作记录</span> |
| | | <el-button |
| | | v-if="isEngineer" |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | @click="showAddTime = true" |
| | | > |
| | | 新增工艺时间 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | @click="showAdditives = !showAdditives" |
| | | > |
| | | {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }} |
| | | </el-button> |
| | | </div> |
| | | <Table :data="sampleData" :total="sampleTotal" :height="null"> |
| | | <template> |
| | | <el-table-column prop="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column |
| | | prop="processTime" |
| | | label="工艺时间" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleName" |
| | | label="取样名称" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleCode" |
| | | label="取样样品编号" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="temperature" |
| | | label="温度" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column prop="ph" label="PH" width="150"></el-table-column> |
| | | <el-table-column |
| | | prop="waterAmount" |
| | | label="加水量" |
| | | width="150" |
| | | ></el-table-column> |
| | | <template v-if="showAdditives"> |
| | | <el-table-column |
| | | prop="additive1" |
| | | label="加辅1" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive2" |
| | | label="加辅2" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive3" |
| | | label="加辅3" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive4" |
| | | label="加辅4" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive5" |
| | | label="加辅5" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive6" |
| | | label="加辅6" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive7" |
| | | label="加辅7" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive8" |
| | | label="加辅8" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive9" |
| | | label="加辅9" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive10" |
| | | label="加辅10" |
| | | width="150" |
| | | ></el-table-column> |
| | | </template> |
| | | <el-table-column |
| | | prop="sampleAmount" |
| | | label="取样量" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleTime" |
| | | label="取样时间" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="remark" |
| | | label="拍照" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="operator" |
| | | label="操作人员" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | v-if="isExperimenter" |
| | | fixed="right" |
| | | label="操作" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEdit(scope.$index, scope.row)" |
| | | >编辑</el-button |
| | | > |
| | | |
| | | <!-- 化验师专用部分 --> |
| | | <div v-if="isAssayer" class="assayer-section"> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>送样-收样记录</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="showPendingColumns = !showPendingColumns"> |
| | | {{ showPendingColumns ? "收起待收样详情" : "展开待收样详情" }} |
| | | </el-button> |
| | | <el-button type="primary" class="el-icon-plus" @click="showReceivedColumns = !showReceivedColumns"> |
| | | {{ showReceivedColumns ? "收起已收样详情" : "展开已收样详情" }} |
| | | </el-button> |
| | | </div> |
| | | <div class="sample-code"> |
| | | 取样单编号:{{ form.sampleCode || "DD-25010BS01" }} |
| | | </div> |
| | | |
| | | <!-- 待收样列表 --> |
| | | <div class="pending-samples"> |
| | | <div class="sub-title">待收样列表</div> |
| | | <el-button type="primary" class="batch-receive" @click="handleBatchReceive">批量接收</el-button> |
| | | <Table :data="pendingSamples" :total="pendingSamplesTotal" :height="null" |
| | | @selection-change="handleSelectionChange"> |
| | | <template> |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column prop="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="sampleName" label="取样名称"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="取样样品编号"></el-table-column> |
| | | <el-table-column prop="ph" label="PH"></el-table-column> |
| | | <el-table-column prop="sampleAmount" label="取样量"></el-table-column> |
| | | <el-table-column prop="sendTime" label="送样时间"></el-table-column> |
| | | <el-table-column prop="sender" label="送样人"></el-table-column> |
| | | <el-table-column prop="status" label="状态"></el-table-column> |
| | | <template v-if="showPendingColumns"> |
| | | <el-table-column prop="temperature" label="温度" width="150"></el-table-column> |
| | | <el-table-column prop="waterAmount" label="加水量" width="150"></el-table-column> |
| | | <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column> |
| | | <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column> |
| | | <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column> |
| | | <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column> |
| | | <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column> |
| | | </template> |
| | | <el-table-column label="操作" width="100" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleReceive(scope.row)">接收</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </Table> |
| | | <div class="remark-section" v-if="isExperimenter"> |
| | | <el-form :model="form" label-position="top"> |
| | | <el-form-item label="备注"> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="form.remark" |
| | | :rows="4" |
| | | placeholder="请输入备注信息" |
| | | ></el-input> |
| | | </Table> |
| | | </div> |
| | | |
| | | <!-- 已收样列表 --> |
| | | <div class="received-samples"> |
| | | <div class="sub-title">已收样列表</div> |
| | | <Table :data="receivedSamples" :total="receivedSamplesTotal" :height="null"> |
| | | <template> |
| | | <el-table-column prop="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="sampleName" label="取样名称"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="取样样品编号"></el-table-column> |
| | | <el-table-column prop="temperature" label="温度" width="150"></el-table-column> |
| | | <el-table-column prop="waterAmount" label="加水量" width="150"></el-table-column> |
| | | <el-table-column prop="ph" label="PH"></el-table-column> |
| | | <template v-if="showReceivedColumns"> |
| | | <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column> |
| | | <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column> |
| | | <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column> |
| | | <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column> |
| | | <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column> |
| | | </template> |
| | | <el-table-column prop="sampleAmount" label="取样量"></el-table-column> |
| | | <el-table-column prop="sendTime" label="送样时间"></el-table-column> |
| | | <el-table-column prop="sender" label="送样人"></el-table-column> |
| | | <el-table-column prop="receiveTime" label="收样时间"></el-table-column> |
| | | <el-table-column prop="receiver" label="收样人"></el-table-column> |
| | | <el-table-column prop="status" label="状态" fixed="right"></el-table-column> |
| | | </template> |
| | | </Table> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 工程师部分 --> |
| | | <div v-if="isEngineer"> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>基础信息</span> |
| | | </div> |
| | | <el-form ref="form" :model="form" :rules="rules" inline label-position="top"> |
| | | <el-form-item label="取样单编号" prop="sampleCode"> |
| | | <el-input v-model="form.sampleCode" :disabled="true" placeholder="自动生成" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>取样操作记录</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="showAddTime = true"> |
| | | 新增工艺时间 |
| | | </el-button> |
| | | <el-button type="primary" class="el-icon-plus" @click="showAdditives = !showAdditives"> |
| | | {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }} |
| | | </el-button> |
| | | </div> |
| | | <Table :data="sampleData" :total="sampleTotal" :height="null"> |
| | | <template> |
| | | <el-table-column prop="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="processTime" label="工艺时间" width="150"></el-table-column> |
| | | <el-table-column prop="sampleName" label="取样名称" width="150"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column> |
| | | <el-table-column prop="temperature" label="温度" width="150"></el-table-column> |
| | | <el-table-column prop="ph" label="PH" width="150"></el-table-column> |
| | | <el-table-column prop="waterAmount" label="加水量" width="150"></el-table-column> |
| | | <template v-if="showAdditives"> |
| | | <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column> |
| | | <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column> |
| | | <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column> |
| | | <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column> |
| | | <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column> |
| | | <el-table-column prop="additive6" label="加辅6" width="150"></el-table-column> |
| | | <el-table-column prop="additive7" label="加辅7" width="150"></el-table-column> |
| | | <el-table-column prop="additive8" label="加辅8" width="150"></el-table-column> |
| | | <el-table-column prop="additive9" label="加辅9" width="150"></el-table-column> |
| | | <el-table-column prop="additive10" label="加辅10" width="150"></el-table-column> |
| | | </template> |
| | | <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column> |
| | | <el-table-column prop="sampleTime" label="取样时间" width="150"></el-table-column> |
| | | <el-table-column prop="remark" label="拍照" width="150"></el-table-column> |
| | | <el-table-column prop="operator" label="操作人员" width="150"></el-table-column> |
| | | </template> |
| | | </Table> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn" @click="handleSave">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn" @click="handleSave">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | |
| | | <experimentalScheduling :show="showScheduling" /> |
| | | <addTime :show.sync="showAddTime" @confirm="handleAddTime" /> |
| | | <sample-dialog |
| | | :visible.sync="showSampleDialog" |
| | | :data="currentSampleData" |
| | | @submit="handleSampleSubmit" |
| | | /> |
| | | <confirm-dialog |
| | | :visible.sync="showConfirmDialog" |
| | | :form-data="form" |
| | | :sample-data="sampleData" |
| | | @confirm="handleConfirm" |
| | | /> |
| | | <receive-confirm-dialog :visible.sync="showReceiveConfirm" :sample-count="selectedSamples.length" |
| | | @confirm="confirmReceive" /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import experimentalScheduling from "./components/experimental-scheduling.vue"; |
| | | import addTime from "./components/addTime.vue"; |
| | | import SampleDialog from "./components/sampleDialog.vue"; |
| | | import ConfirmDialog from './components/confirmDialog.vue'; |
| | | import ReceiveConfirmDialog from "./components/receiveConfirmDialog.vue"; |
| | | |
| | | export default { |
| | | name: "AddConfirmationSheet", |
| | | name: "AddSample", |
| | | components: { |
| | | experimentalScheduling, |
| | | addTime, |
| | | SampleDialog, |
| | | ConfirmDialog, |
| | | ReceiveConfirmDialog, |
| | | }, |
| | | props: {}, |
| | | data() { |
| | | return { |
| | | showScheduling: false, |
| | | showAddTime: false, |
| | | showAdditives: true, |
| | | showSampleDialog: false, |
| | | showConfirmDialog: false, |
| | | currentSampleData: {}, |
| | | currentEditIndex: -1, |
| | | schedulingData: [], // 实验调度表格数据 |
| | | showReceiveConfirm: false, |
| | | showPendingColumns: true, |
| | | showReceivedColumns: true, |
| | | schedulingData: [], |
| | | schedulingTotal: 0, |
| | | sampleData: [ |
| | | { |
| | |
| | | sampleTotal: 2, |
| | | form: { |
| | | sampleCode: "", |
| | | remark: "", |
| | | }, |
| | | rules: { |
| | | sampleCode: [ |
| | | { required: true, message: "请输入取样单编号", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | menu: [], |
| | | userRole: "experimenter", // 用户角色,可以是 'engineer' 或 'experimenter' |
| | | userRole: "assayer", // engineer默认设置为工程师assayer化验师 |
| | | // 化验师相关数据 |
| | | pendingSamples: [ |
| | | { |
| | | index: 1, |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | ph: "5", |
| | | sampleAmount: "34", |
| | | sendTime: "2025-1-9 15:26:08", |
| | | sender: "李四", |
| | | status: "待接收", |
| | | }, |
| | | { |
| | | index: 2, |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | ph: "6", |
| | | sampleAmount: "23", |
| | | sendTime: "2025-1-9 15:26:08", |
| | | sender: "李四", |
| | | status: "待接收", |
| | | }, |
| | | { |
| | | index: 3, |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | ph: "7", |
| | | sampleAmount: "23", |
| | | sendTime: "2025-1-13 16:38:17", |
| | | sender: "李四", |
| | | status: "待接收", |
| | | }, |
| | | ], |
| | | pendingSamplesTotal: 3, |
| | | receivedSamples: [ |
| | | { |
| | | index: 1, |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | ph: "5", |
| | | sampleAmount: "34", |
| | | sendTime: "2025-1-9 15:26:08", |
| | | sender: "李四", |
| | | receiveTime: "2025-1-15 14:00:50", |
| | | receiver: "段向蒙", |
| | | status: "已接收", |
| | | }, |
| | | { |
| | | index: 2, |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | ph: "6", |
| | | sampleAmount: "23", |
| | | sendTime: "2025-1-9 15:26:08", |
| | | sender: "李四", |
| | | receiveTime: "2025-1-15 14:00:50", |
| | | receiver: "傅彦涛", |
| | | status: "已接收", |
| | | }, |
| | | { |
| | | index: 3, |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | ph: "7", |
| | | sampleAmount: "23", |
| | | sendTime: "2025-1-13 16:38:17", |
| | | sender: "李四", |
| | | receiveTime: "2025-1-15 14:00:50", |
| | | receiver: "王乐康", |
| | | status: "已接收", |
| | | }, |
| | | ], |
| | | receivedSamplesTotal: 3, |
| | | selectedSamples: [], |
| | | }; |
| | | }, |
| | | computed: { |
| | | height() { |
| | | return this.$baseTableHeight(); |
| | | }, |
| | | isEngineer() { |
| | | return this.userRole === "engineer"; |
| | | }, |
| | | isExperimenter() { |
| | | return this.userRole === "experimenter"; |
| | | isAssayer() { |
| | | return this.userRole === "assayer"; |
| | | }, |
| | | }, |
| | | watch: {}, |
| | | created() {}, |
| | | mounted() {}, |
| | | methods: { |
| | | setSelectedIds(arr, selectKeyList) { |
| | | function traverse(item) { |
| | | item.selected = selectKeyList.includes(item.menuId); |
| | | if (item.children && item.children.length > 0) { |
| | | item.children.forEach(traverse); |
| | | } |
| | | } |
| | | arr.forEach(traverse); |
| | | return arr; |
| | | }, |
| | | onSubmit() { |
| | | this.$refs["form"].validate((valid) => { |
| | | if (valid) { |
| | | if (this.getSelectedIds(this.menu).length == 0) { |
| | | this.msgwarning("请勾选操作权限"); |
| | | return; |
| | | } |
| | | let obj = { |
| | | ...this.form, |
| | | menuIds: this.getSelectedIds(this.menu), |
| | | }; |
| | | if (this.$route.query && this.$route.query.roleId) { |
| | | obj.roleId = this.$route.query.roleId; |
| | | edit(obj).then(() => { |
| | | this.msgsuccess("保存成功"); |
| | | this.$router.go(-1); |
| | | }); |
| | | } else { |
| | | add(obj).then(() => { |
| | | this.msgsuccess("保存成功"); |
| | | this.form = { |
| | | roleName: "", |
| | | remark: "", |
| | | }; |
| | | this.menu = []; |
| | | this.$router.go(-1); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | getSelectedIds(arr) { |
| | | let result = []; |
| | | function traverse(item) { |
| | | if (item.selected) { |
| | | result.push(item.menuId); |
| | | } |
| | | if (item.children && item.children.length > 0) { |
| | | for (let children of item.children) { |
| | | traverse(children); |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (let item of arr) { |
| | | traverse(item); |
| | | } |
| | | return result; |
| | | }, |
| | | setCheckStatus1(id, status) { |
| | | //点击第1级 |
| | | if (!status) { |
| | | this.menu = this.menu.map((item) => { |
| | | if (item.menuId == id) { |
| | | item.selected = status; |
| | | if (item.children.length > 0) { |
| | | item.children = item.children.map((item1) => { |
| | | item1.selected = status; |
| | | if (item1.children.length > 0) { |
| | | item1.children = item1.children.map((item2) => { |
| | | item2.selected = status; |
| | | return { ...item2 }; |
| | | }); |
| | | } |
| | | return { ...item1 }; |
| | | }); |
| | | } |
| | | } |
| | | return { ...item }; |
| | | }); |
| | | } else { |
| | | this.menu = this.menu.map((item) => { |
| | | if (item.menuId == id) { |
| | | item.selected = true; |
| | | } |
| | | return { ...item }; |
| | | }); |
| | | } |
| | | }, |
| | | setCheckStatus2(id, status, aId) { |
| | | //点击第2级 |
| | | this.menu = this.menu.map((item) => { |
| | | if (item.menuId == aId) { |
| | | item.selected = true; |
| | | if (item.children.length > 0) { |
| | | item.children = item.children.map((item1) => { |
| | | if (item1.menuId == id) { |
| | | item1.selected = status; |
| | | } |
| | | return { ...item1 }; |
| | | }); |
| | | } |
| | | } |
| | | return { ...item }; |
| | | }); |
| | | }, |
| | | setCheckStatus3(id, status, bId, aId) { |
| | | //点击第3级 |
| | | this.menu = this.menu.map((item) => { |
| | | if (item.menuId == aId) { |
| | | item.selected = true; |
| | | if (item.children.length > 0) { |
| | | item.children = item.children.map((item1) => { |
| | | if (item1.menuId == bId) { |
| | | item1.selected = true; |
| | | if (item1.children.length > 0) { |
| | | item1.children = item1.children.map((item2) => { |
| | | if (item2.menuId == id) { |
| | | item2.selected = status; |
| | | } |
| | | return { ...item2 }; |
| | | }); |
| | | } |
| | | } |
| | | return { ...item1 }; |
| | | }); |
| | | } |
| | | } |
| | | return { ...item }; |
| | | }); |
| | | }, |
| | | handleEdit(index, row) { |
| | | this.currentEditIndex = index; |
| | | this.currentSampleData = { ...row }; |
| | | this.showSampleDialog = true; |
| | | }, |
| | | handleSampleSubmit(formData) { |
| | | if (this.currentEditIndex > -1) { |
| | | // 更新表格数据 |
| | | this.$set(this.sampleData, this.currentEditIndex, { |
| | | ...this.sampleData[this.currentEditIndex], |
| | | ...formData, |
| | | }); |
| | | this.currentEditIndex = -1; |
| | | } |
| | | this.showSampleDialog = false; |
| | | }, |
| | | handleDelete(index, row) { |
| | | this.$confirm("确认删除该记录吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | this.sampleData.splice(index, 1); |
| | | // 重新计算序号 |
| | | this.sampleData.forEach((item, i) => { |
| | | item.index = i + 1; |
| | | }); |
| | | this.$message.success("删除成功"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | handleAddTime(processTime) { |
| | | if (!this.isEngineer) return; |
| | | const newRow = { |
| | | index: this.sampleData.length + 1, |
| | | processTime, |
| | |
| | | this.$message.success("添加工艺时间成功"); |
| | | }, |
| | | handleSave() { |
| | | if (this.isExperimenter) { |
| | | this.showConfirmDialog = true; |
| | | } else { |
| | | this.submitForm(); |
| | | } |
| | | this.submitForm(); |
| | | }, |
| | | handleConfirm(signature) { |
| | | this.submitForm(signature); |
| | | }, |
| | | submitForm(signature = null) { |
| | | submitForm() { |
| | | // 在这里实现表单提交逻辑 |
| | | console.log('提交表单数据', { signature }); |
| | | this.$message.success('保存成功'); |
| | | this.showConfirmDialog = false; |
| | | console.log("提交表单数据"); |
| | | this.$message.success("保存成功"); |
| | | }, |
| | | handleSelectionChange(selection) { |
| | | this.selectedSamples = selection; |
| | | }, |
| | | handleReceive(row) { |
| | | this.selectedSamples = [row]; |
| | | this.showReceiveConfirm = true; |
| | | }, |
| | | handleBatchReceive() { |
| | | if (this.selectedSamples.length === 0) { |
| | | this.$message.warning("请先选择要接收的样品"); |
| | | return; |
| | | } |
| | | this.showReceiveConfirm = true; |
| | | }, |
| | | confirmReceive(signature) { |
| | | // 这里处理接收确认逻辑 |
| | | const sampleIds = this.selectedSamples.map((item) => item.id); |
| | | console.log("接收样品", { sampleIds, signature }); |
| | | |
| | | // 模拟接收成功 |
| | | this.$message.success(`成功接收 ${this.selectedSamples.length} 个样品`); |
| | | |
| | | // 更新数据 |
| | | this.selectedSamples.forEach((sample) => { |
| | | const index = this.pendingSamples.findIndex( |
| | | (item) => item.id === sample.id |
| | | ); |
| | | if (index > -1) { |
| | | this.pendingSamples.splice(index, 1); |
| | | this.receivedSamples.unshift({ |
| | | ...sample, |
| | | receiveTime: new Date().toLocaleString(), |
| | | receiver: "当前用户", |
| | | status: "已接收", |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // 清空选择 |
| | | this.selectedSamples = []; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .title_box { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | font-weight: bold; |
| | | |
| | | div:first-child { |
| | | width: 4px; |
| | | height: 16px; |
| | | background: #598dec; |
| | | margin-right: 8px; |
| | | } |
| | | } |
| | | |
| | | .no-data { |
| | | height: 100%; |
| | | background-color: #fff; |
| | | border-radius: 0 0 6px 6px; |
| | | border-left: 1px solid #e8e8e8; |
| | | border-right: 1px solid #e8e8e8; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .add-project-footer { |
| | | margin-top: 43px; |
| | | button { |
| | | width: 220px; |
| | | } |
| | | .save-btn { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .el-checkbox { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .number{ |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0,0,0,0.88); |
| | | } |
| | | |
| | | .row, |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | border: 1px solid #e8e8e8; |
| | | |
| | | .w20 { |
| | | width: 15%; |
| | | padding: 8px 20px; |
| | | } |
| | | |
| | | .sconed { |
| | | flex: 1; |
| | | |
| | | .subpage { |
| | | .title { |
| | | border: 1px solid #e8e8e8; |
| | | border-top: none; |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .two { |
| | | display: flex; |
| | | align-items: center; |
| | | border: 1px solid #e8e8e8; |
| | | border-top: none; |
| | | border-right: none; |
| | | |
| | | .left { |
| | | width: 200px; |
| | | padding: 13px 20px; |
| | | border-right: 1px solid #e8e8e8; |
| | | } |
| | | |
| | | .right { |
| | | display: flex; |
| | | flex: 1; |
| | | |
| | | div { |
| | | padding: 13px 0 13px 20px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .two:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .btns { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 20px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .header { |
| | | border-radius: 16px 16px 0 0; |
| | | background-color: #fafafa; |
| | | color: #909399; |
| | | |
| | | .subpage { |
| | | display: flex; |
| | | } |
| | | |
| | | .title { |
| | | width: 200px; |
| | | padding: 8px 20px; |
| | | } |
| | | } |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | |
| | | } |
| | | } |
| | | |
| | | .remark-section { |
| | | margin-top: 20px; |
| | | .add-project-footer { |
| | | margin-top: 43px; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | button { |
| | | width: 220px; |
| | | } |
| | | |
| | | .el-textarea { |
| | | width: 100%; |
| | | } |
| | | .save-btn { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .signature-section { |
| | | margin-top: 26px; |
| | | } |
| | | |
| | | .add-group { |
| | | padding-left: 25px; |
| | | margin-top: 14px; |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 19px; |
| | | |
| | | div { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | .assayer-section { |
| | | .sample-code { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | line-height: 21px; |
| | | margin: 0 32px 0 8px; |
| | | color: rgba(0, 0, 0, 0.88); |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .sub-title { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin: 20px 0; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .batch-receive { |
| | | float: right; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .pending-samples, |
| | | .received-samples { |
| | | // margin-top: 20px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <span slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleSubmit">确认新增</el-button> |
| | | </span> |
| | |
| | | <el-input type="textarea" v-model="remark" placeholder="请输入审批意见" /> |
| | | </div> |
| | | </div> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleApprove" v-if="type === 'approve'" |
| | | >通过</el-button |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="接收签字确认" |
| | | :visible.sync="visible" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="receive-dialog"> |
| | | <div class="receive-tip"> |
| | | 您已选中 <span class="sample-count">{{ sampleCount }}</span> 条样品接收,请签字确认 |
| | | </div> |
| | | |
| | | <div class="approval-dialog-approve"> |
| | | <div class="add-group"> |
| | | <div>*</div> |
| | | <span>签字确认</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="openSignature">签名</el-button> |
| | | </div> |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleConfirm" :disabled="!imgSrc"> |
| | | 确认接收 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <SignatureCanvas |
| | | :visible="signatureDialogVisible" |
| | | @confirm="handleSignatureConfirm" |
| | | @close="signatureDialogVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | |
| | | export default { |
| | | name: "ReceiveConfirmDialog", |
| | | components: { |
| | | SignatureCanvas, |
| | | }, |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | sampleCount: { |
| | | type: Number, |
| | | default: 1, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | signatureDialogVisible: false, |
| | | imgSrc: "", |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = ""; |
| | | }, |
| | | openSignature() { |
| | | this.signatureDialogVisible = true; |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | this.imgSrc = imageData; |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | | this.$message.warning("请先完成签名确认"); |
| | | return; |
| | | } |
| | | this.$emit("confirm", this.imgSrc); |
| | | this.handleClose(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | ::v-deep .el-dialog__header { |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .receive-dialog { |
| | | padding: 20px; |
| | | |
| | | .receive-tip { |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-bottom: 20px; |
| | | |
| | | .sample-count { |
| | | color: #409EFF; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .approval-dialog-approve { |
| | | margin-top: 26px; |
| | | |
| | | img { |
| | | border: 2px dashed #049c9a; |
| | | } |
| | | } |
| | | |
| | | .add-group { |
| | | padding-left: 25px; |
| | | margin-top: 14px; |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 19px; |
| | | |
| | | div { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | line-height: 21px; |
| | | margin: 0 32px 0 8px; |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | button { |
| | | width: 150px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建人:" v-if="isChemist"> |
| | | <el-input v-model="form.creator" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间:"> |
| | | <el-date-picker |
| | | v-model="form.createTime" |
| | |
| | | value-format="yyyy-MM-dd" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-form-item label="状态:" v-if="!isChemist"> |
| | | <el-input v-model="form.approver" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:" v-if="isChemist"> |
| | | <el-input v-model="form.experimentName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</el-button> |
| | |
| | | </template> |
| | | <template #table> |
| | | <el-table-column |
| | | prop="planCode" |
| | | label="项目课题方案编号" |
| | | v-for="(column, index) in currentColumns" |
| | | :key="index" |
| | | :prop="column.prop" |
| | | :label="column.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="creator" label="创建人"></el-table-column> |
| | | <el-table-column prop="createTime" label="创建日期"></el-table-column> |
| | | <el-table-column prop="status" label="审批状态"> |
| | | <el-table-column label="操作" width="100"> |
| | | <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="approver" label="审批人"></el-table-column> |
| | | <el-table-column prop="approveTime" label="审批时间"></el-table-column> |
| | | <el-table-column label="操作" width="250"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | v-if="scope.row.status === 'pending'" |
| | | type="text" |
| | | @click="handleApprove(scope.row)" |
| | | >审批</el-button |
| | | > |
| | | <el-button |
| | | v-if="scope.row.status === 'approved'" |
| | | type="text" |
| | | @click="handleRevokeApprove(scope.row)" |
| | | >撤销审批</el-button |
| | | > |
| | | <el-button |
| | | v-if="scope.row.status === 'rejected'" |
| | | type="text" |
| | | @click="handleEdit(scope.row)" |
| | | >编辑</el-button |
| | | > |
| | | <el-button |
| | | v-if="scope.row.status === 'rejected'" |
| | | type="text" |
| | | @click="handleDelete(scope.row)" |
| | | >删除</el-button |
| | | > |
| | | <el-button type="text" @click="handleDetail(scope.row)" |
| | | >详情</el-button |
| | | > |
| | | <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | userRole: 'chemist', // 用户角色 |
| | | currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱 |
| | | form: { |
| | | planName: "", |
| | |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | experimentName: "", |
| | | sampleCount: "", |
| | | receivedStatus: "" |
| | | }, |
| | | tableData: [], |
| | | total: 0, |
| | | // 不同角色的表头配置 |
| | | columnConfig: { |
| | | default: [ |
| | | { prop: 'projectPlan', label: '所属项目课题方案' }, |
| | | { prop: 'experimentNo', label: '实验编号' }, |
| | | { prop: 'experimentName', label: '实验名称' }, |
| | | { prop: 'sampleNo', label: '取样单编号' }, |
| | | { prop: 'creator', label: '创建人' }, |
| | | { prop: 'createTime', label: '创建时间' }, |
| | | { prop: 'sendTo', label: '发送对象' }, |
| | | { prop: 'sendTime', label: '发送时间' } |
| | | ], |
| | | chemist: [ |
| | | { prop: 'projectPlan', label: '所属项目课题方案' }, |
| | | { prop: 'experimentNo', label: '实验编号' }, |
| | | { prop: 'experimentName', label: '实验名称' }, |
| | | { prop: 'sampleNo', label: '取样单编号' }, |
| | | { prop: 'creator', label: '创建人' }, |
| | | { prop: 'createTime', label: '创建时间' }, |
| | | { prop: 'sampleCount', label: '样品总数' }, |
| | | { prop: 'receivedCount', label: '待接收' }, |
| | | { prop: 'completedCount', label: '已接收' } |
| | | ] |
| | | }, |
| | | // 模拟数据 |
| | | mockListData: [ |
| | | { |
| | | planCode: 'PLAN-2024-001', |
| | | planName: '2024年度实验室设备升级方案', |
| | | stage: '规划阶段', |
| | | id: '1', |
| | | projectPlan: '2024年度实验室设备性能评估方案', |
| | | experimentNo: 'EXP20240315001', |
| | | experimentName: '设备性能测试实验A', |
| | | sampleNo: 'SAMPLE20240315001', |
| | | creator: '张三', |
| | | createTime: '2024-03-15', |
| | | status: 'pending', |
| | | approver: '李四', |
| | | approveTime: '2024-03-16' |
| | | createTime: '2024-03-15 09:30:00', |
| | | sendTo: '质检部门', |
| | | sendTime: '2024-03-15 10:00:00', |
| | | sampleCount: 5, |
| | | receivedCount: 2, |
| | | completedCount: 3 |
| | | }, |
| | | { |
| | | planCode: 'PLAN-2024-002', |
| | | planName: '实验室安全管理制度更新方案', |
| | | stage: '实施阶段', |
| | | id: '2', |
| | | projectPlan: '新型材料研究项目方案', |
| | | experimentNo: 'EXP20240315002', |
| | | experimentName: '材料强度测试实验', |
| | | sampleNo: 'SAMPLE20240315002', |
| | | creator: '李四', |
| | | createTime: '2024-03-15 11:30:00', |
| | | sendTo: '研发部门', |
| | | sendTime: '2024-03-15 14:00:00', |
| | | sampleCount: 3, |
| | | receivedCount: 1, |
| | | completedCount: 2 |
| | | }, |
| | | { |
| | | id: '3', |
| | | projectPlan: '环境监测系统优化方案', |
| | | experimentNo: 'EXP20240315003', |
| | | experimentName: '空气质量检测实验', |
| | | sampleNo: 'SAMPLE20240315003', |
| | | creator: '王五', |
| | | createTime: '2024-03-14', |
| | | status: 'approved', |
| | | approver: '赵六', |
| | | approveTime: '2024-03-15' |
| | | createTime: '2024-03-15 15:30:00', |
| | | sendTo: '环境监测组', |
| | | sendTime: '2024-03-15 16:00:00' |
| | | }, |
| | | { |
| | | planCode: 'PLAN-2024-003', |
| | | planName: '实验室人员培训计划', |
| | | stage: '准备阶段', |
| | | creator: '孙七', |
| | | createTime: '2024-03-13', |
| | | status: 'rejected', |
| | | approver: '周八', |
| | | approveTime: '2024-03-14' |
| | | id: '4', |
| | | projectPlan: '生物样本分析项目', |
| | | experimentNo: 'EXP20240315004', |
| | | experimentName: '细胞活性测试', |
| | | sampleNo: 'SAMPLE20240315004', |
| | | creator: '赵六', |
| | | createTime: '2024-03-15 16:30:00', |
| | | sendTo: '生物实验室', |
| | | sendTime: '2024-03-15 17:00:00' |
| | | } |
| | | ], |
| | | mockDraftData: [ |
| | | { |
| | | planCode: 'DRAFT-2024-001', |
| | | planName: '实验室设备采购计划(草稿)', |
| | | stage: '规划阶段', |
| | | creator: '张三', |
| | | createTime: '2024-03-16', |
| | | status: 'draft', |
| | | approver: '', |
| | | approveTime: '' |
| | | id: '5', |
| | | projectPlan: '化学反应监测方案', |
| | | experimentNo: 'EXP20240316001', |
| | | experimentName: '催化剂效率测试', |
| | | sampleNo: 'SAMPLE20240316001', |
| | | creator: '孙七', |
| | | createTime: '2024-03-16 09:30:00', |
| | | sendTo: '化学实验室', |
| | | sendTime: '2024-03-16 10:00:00' |
| | | }, |
| | | { |
| | | planCode: 'DRAFT-2024-002', |
| | | planName: '实验室改造方案(草稿)', |
| | | stage: '准备阶段', |
| | | creator: '李四', |
| | | createTime: '2024-03-15', |
| | | status: 'draft', |
| | | approver: '', |
| | | approveTime: '' |
| | | id: '6', |
| | | projectPlan: '药物稳定性研究方案', |
| | | experimentNo: 'EXP20240316002', |
| | | experimentName: '药物降解测试', |
| | | sampleNo: 'SAMPLE20240316002', |
| | | creator: '周八', |
| | | createTime: '2024-03-16 11:30:00', |
| | | sendTo: '药物研究部', |
| | | sendTime: '2024-03-16 14:00:00' |
| | | } |
| | | ], |
| | | approvalDialogVisible: false, |
| | |
| | | currentApprovalData: null, |
| | | }; |
| | | }, |
| | | computed: { |
| | | // 获取当前角色的表头配置 |
| | | currentColumns() { |
| | | return this.columnConfig[this.userRole] || this.columnConfig.default; |
| | | }, |
| | | // 判断是否为化验师角色 |
| | | isChemist() { |
| | | return this.userRole === 'chemist'; |
| | | } |
| | | }, |
| | | created() { |
| | | this.getUserRole(); |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | // 获取用户角色 |
| | | async getUserRole() { |
| | | // TODO: 从用户信息或接口中获取角色 |
| | | // 示例:this.userRole = await getUserRole(); |
| | | this.userRole = 'chemist'; // 临时写死,实际应该从接口获取 |
| | | }, |
| | | resetForm() { |
| | | this.form = { |
| | | planName: "", |
| | |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | experimentName: "", |
| | | sampleCount: "", |
| | | receivedStatus: "" |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | |
| | | }, |
| | | handleAddSample() { |
| | | this.$router.push({ |
| | | path: "/dataManagement/addSample", |
| | | path: "/sampleManage/addSample", |
| | | }); |
| | | }, |
| | | handleApprove(row) { |
| | |
| | | // 实现删除逻辑 |
| | | console.log("删除数据:", row); |
| | | }, |
| | | handleDetail(row) { |
| | | this.currentApprovalData = row; |
| | | this.approvalDialogType = 'view'; |
| | | this.approvalDialogVisible = true; |
| | | handleDetail(id) { |
| | | this.$router.push({ |
| | | path: "/sampleManage/addSample", |
| | | query: { |
| | | id: id |
| | | } |
| | | }); |
| | | }, |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>基础信息</span> |
| | | </div> |
| | | <div class="number">取样单编号:213421241</div> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>取样操作记录</span> |
| | | <el-button |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | @click="showAdditives = !showAdditives" |
| | | > |
| | | {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }} |
| | | </el-button> |
| | | </div> |
| | | <Table :data="sampleData" :total="sampleTotal" :height="null"> |
| | | <template> |
| | | <el-table-column prop="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column |
| | | prop="processTime" |
| | | label="工艺时间" |
| | | width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleName" |
| | | label="取样名称" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleCode" |
| | | label="取样样品编号" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="temperature" |
| | | label="温度" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column prop="ph" label="PH" width="100"></el-table-column> |
| | | <el-table-column |
| | | prop="waterAmount" |
| | | label="加水量" |
| | | width="100" |
| | | ></el-table-column> |
| | | <template v-if="showAdditives"> |
| | | <el-table-column |
| | | prop="additive1" |
| | | label="加辅1" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive2" |
| | | label="加辅2" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive3" |
| | | label="加辅3" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive4" |
| | | label="加辅4" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive5" |
| | | label="加辅5" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive6" |
| | | label="加辅6" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive7" |
| | | label="加辅7" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive8" |
| | | label="加辅8" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive9" |
| | | label="加辅9" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="additive10" |
| | | label="加辅10" |
| | | width="150" |
| | | ></el-table-column> |
| | | </template> |
| | | <el-table-column |
| | | prop="sampleAmount" |
| | | label="取样量" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleTime" |
| | | label="取样时间" |
| | | width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="remark" |
| | | label="拍照" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="operator" |
| | | label="操作人员" |
| | | width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | fixed="right" |
| | | label="操作" |
| | | width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEdit(scope.$index, scope.row)" |
| | | >编辑</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </Table> |
| | | <div class="remark-section"> |
| | | <el-form :model="form" label-position="top"> |
| | | <el-form-item label="备注"> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="form.remark" |
| | | :rows="4" |
| | | placeholder="请输入备注信息" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn" @click="handleSave">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | <sample-dialog |
| | | :visible.sync="showSampleDialog" |
| | | :data="currentSampleData" |
| | | @submit="handleSampleSubmit" |
| | | /> |
| | | <confirm-dialog |
| | | :visible.sync="showConfirmDialog" |
| | | :form-data="form" |
| | | :sample-data="sampleData" |
| | | @confirm="handleConfirm" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import SampleDialog from "./components/sampleDialog.vue"; |
| | | import ConfirmDialog from './components/confirmDialog.vue'; |
| | | |
| | | export default { |
| | | name: "ChangeRecord", |
| | | components: { |
| | | SampleDialog, |
| | | ConfirmDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | showSampleDialog: false, |
| | | showConfirmDialog: false, |
| | | currentSampleData: {}, |
| | | currentEditIndex: -1, |
| | | showAdditives: true, |
| | | sampleData: [ |
| | | { |
| | | index: 1, |
| | | processTime: "2h", |
| | | sampleName: "样品A", |
| | | sampleCode: "SP001", |
| | | temperature: "25℃", |
| | | ph: "7.0", |
| | | waterAmount: "500ml", |
| | | additive1: "10g", |
| | | additive2: "5g", |
| | | additive3: "3g", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "100ml", |
| | | sampleTime: "2024-03-20 10:00:00", |
| | | remark: "", |
| | | operator: "张三" |
| | | }, |
| | | { |
| | | index: 2, |
| | | processTime: "4min", |
| | | sampleName: "样品B", |
| | | sampleCode: "SP002", |
| | | temperature: "30℃", |
| | | ph: "6.5", |
| | | waterAmount: "300ml", |
| | | additive1: "8g", |
| | | additive2: "4g", |
| | | additive3: "", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "50ml", |
| | | sampleTime: "2024-03-20 10:30:00", |
| | | remark: "", |
| | | operator: "李四", |
| | | }, |
| | | ], |
| | | sampleTotal: 2, |
| | | form: { |
| | | remark: "", |
| | | }, |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleEdit(index, row) { |
| | | this.currentEditIndex = index; |
| | | this.currentSampleData = { ...row }; |
| | | this.showSampleDialog = true; |
| | | }, |
| | | handleSampleSubmit(formData) { |
| | | if (this.currentEditIndex > -1) { |
| | | // 更新表格数据 |
| | | this.$set(this.sampleData, this.currentEditIndex, { |
| | | ...this.sampleData[this.currentEditIndex], |
| | | ...formData, |
| | | }); |
| | | this.currentEditIndex = -1; |
| | | } |
| | | this.showSampleDialog = false; |
| | | }, |
| | | handleSave() { |
| | | this.showConfirmDialog = true; |
| | | }, |
| | | handleConfirm(signature) { |
| | | this.submitForm(signature); |
| | | }, |
| | | submitForm(signature = null) { |
| | | // 在这里实现表单提交逻辑 |
| | | console.log('提交表单数据', { signature }); |
| | | this.$message.success('保存成功'); |
| | | this.showConfirmDialog = false; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin-bottom: 20px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | div, span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | |
| | | div:before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | .el-button { |
| | | margin-left: 16px; |
| | | } |
| | | } |
| | | |
| | | .add-project-footer { |
| | | margin-top: 43px; |
| | | button { |
| | | width: 220px; |
| | | } |
| | | .save-btn { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .number { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0,0,0,0.88); |
| | | } |
| | | |
| | | .remark-section { |
| | | margin-top: 20px; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | |
| | | .el-textarea { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | </style> |
File was renamed from src/views/dataManagement/sampleManage/components/confirmDialog.vue |
| | |
| | | /> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer"> |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleConfirm" :disabled="!imgSrc" |
| | | >确 认</el-button |
File was renamed from src/views/dataManagement/sampleManage/components/sampleDialog.vue |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleSubmit" style="margin-left: 20px;">确 定</el-button> |
| | | </div> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.planName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="状态:"> |
| | | <el-input v-model="form.approver" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</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')" |
| | | >{{ type === 'draft' ? '草稿箱' : '取样操作记录列表' }}</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column |
| | | prop="planName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentNo" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleNo" |
| | | label="取样单编号" |
| | | ></el-table-column> |
| | | <el-table-column prop="creator" label="创建人"></el-table-column> |
| | | <el-table-column prop="createTime" 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> |
| | | <el-table-column label="操作" width="150"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | type="text" |
| | | @click="handleEdit(scope.row)" |
| | | >编辑</el-button> |
| | | <el-button |
| | | type="text" |
| | | @click="handleDetail(scope.row)" |
| | | >详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | <!-- 审批弹窗 --> |
| | | <!-- <approval-dialog |
| | | :visible.sync="approvalDialogVisible" |
| | | :type="approvalDialogType" |
| | | :data="currentApprovalData" |
| | | @approve="handleApproveSubmit" |
| | | @reject="handleRejectSubmit" |
| | | /> --> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | // import ApprovalDialog from './components/approvalDialog.vue' |
| | | |
| | | export default { |
| | | name: "ProjectList", |
| | | components: { |
| | | // ApprovalDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | type: 'list', |
| | | currentType: 'list', |
| | | form: { |
| | | planName: "", |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | }, |
| | | tableData: [], |
| | | total: 0, |
| | | // 模拟数据 |
| | | mockListData: [ |
| | | { |
| | | planName: '2024年度实验室设备升级方案', |
| | | experimentNo: '31423764', |
| | | experimentName: '设备性能测试', |
| | | sampleNo: '2024-05-28', |
| | | creator: '刘大大', |
| | | createTime: '2025-1-2 16:27:17', |
| | | status: 'pending' |
| | | } |
| | | ], |
| | | 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: null, |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | this.form = { |
| | | planName: "", |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | | // 实现查询逻辑 |
| | | console.log("查询条件:", this.form); |
| | | }, |
| | | getStatusType(status) { |
| | | const statusMap = { |
| | | pending: "warning", |
| | | rejected: "danger", |
| | | approved: "success", |
| | | archived: "info", |
| | | draft: "info" |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }, |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | | pending: "待审批", |
| | | rejected: "已驳回", |
| | | approved: "已通过", |
| | | archived: "已封存", |
| | | draft: "草稿" |
| | | }; |
| | | return statusMap[status] || "未知"; |
| | | }, |
| | | handleAddSample() { |
| | | this.$router.push({ |
| | | path: "/sampleManage/changeRecord", |
| | | }); |
| | | }, |
| | | handleApprove(row) { |
| | | this.currentApprovalData = row; |
| | | this.approvalDialogType = 'approve'; |
| | | 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(); |
| | | }, |
| | | handleRevokeApprove(row) { |
| | | // 实现撤销审批逻辑 |
| | | console.log("撤销审批数据:", row); |
| | | }, |
| | | handleEdit(row) { |
| | | this.$router.push({ |
| | | path: "/sampleManage/changeRecord", |
| | | query: { |
| | | type: 'edit', |
| | | id: row.id |
| | | } |
| | | }); |
| | | }, |
| | | handleDelete(row) { |
| | | // 实现删除逻辑 |
| | | console.log("删除数据:", row); |
| | | }, |
| | | handleDetail(row) { |
| | | this.$router.push({ |
| | | path: "/sampleManage/changeRecord", |
| | | query: { |
| | | type: 'view', |
| | | id: row.id |
| | | } |
| | | }); |
| | | }, |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
| | | this.type = type; |
| | | this.getTableData(); |
| | | }, |
| | | getTableData() { |
| | | // 根据currentType请求不同的数据 |
| | | if (this.currentType === 'list') { |
| | | this.tableData = this.mockListData; |
| | | this.total = this.mockListData.length; |
| | | } else { |
| | | this.tableData = this.mockDraftData; |
| | | this.total = this.mockDraftData.length; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .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; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | width: unset; |
| | | cursor: pointer; |
| | | } |
| | | .drafts { |
| | | padding: 16px 65px; |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | font-weight: 400; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | margin-left: 16px; |
| | | cursor: pointer; |
| | | } |
| | | .active{ |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="发送签字确认" |
| | | :visible.sync="visible" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="receive-dialog"> |
| | | <div class="receive-tip"> |
| | | 您已选中 <span class="sample-count">{{ sampleCount }}</span> 条样品发送,请签字确认 |
| | | </div> |
| | | |
| | | <div class="approval-dialog-approve"> |
| | | <div class="add-group"> |
| | | <div>*</div> |
| | | <span>签字确认</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="openSignature">签名</el-button> |
| | | </div> |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer select-member-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleConfirm" :disabled="!imgSrc"> |
| | | 确认发送 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <SignatureCanvas |
| | | :visible="signatureDialogVisible" |
| | | @confirm="handleSignatureConfirm" |
| | | @close="signatureDialogVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | |
| | | export default { |
| | | name: "ReceiveConfirmDialog", |
| | | components: { |
| | | SignatureCanvas, |
| | | }, |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | sampleCount: { |
| | | type: Number, |
| | | default: 1, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | signatureDialogVisible: false, |
| | | imgSrc: "", |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = ""; |
| | | }, |
| | | openSignature() { |
| | | this.signatureDialogVisible = true; |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | this.imgSrc = imageData; |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | | this.$message.warning("请先完成签名确认"); |
| | | return; |
| | | } |
| | | this.$emit("confirm", this.imgSrc); |
| | | this.handleClose(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | ::v-deep .el-dialog__header { |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .receive-dialog { |
| | | padding: 20px; |
| | | |
| | | .receive-tip { |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-bottom: 20px; |
| | | |
| | | .sample-count { |
| | | color: #409EFF; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .approval-dialog-approve { |
| | | margin-top: 26px; |
| | | |
| | | img { |
| | | border: 2px dashed #049c9a; |
| | | } |
| | | } |
| | | |
| | | .add-group { |
| | | padding-left: 25px; |
| | | margin-top: 14px; |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 19px; |
| | | |
| | | div { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | line-height: 21px; |
| | | margin: 0 32px 0 8px; |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | button { |
| | | width: 150px; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.planName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input |
| | | v-model="form.planCode" |
| | | placeholder="请输入" |
| | | ></el-input> </el-form-item |
| | | ><el-form-item label="实验名称:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="状态:"> |
| | | <el-input v-model="form.approver" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label=""> |
| | | <el-button type="default" @click="resetForm">重置</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"> |
| | | 取样操作记录列表 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column |
| | | prop="planName" |
| | | label="所属项目课题方案" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentNo" |
| | | label="实验编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleNo" |
| | | label="取样单编号" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="creator" |
| | | label="创建人" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="createTime" |
| | | label="创建时间" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="sampleStatus" |
| | | label="样品总数/待送达/待接收/已接收" |
| | | ></el-table-column> |
| | | <el-table-column label="操作" width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | <!-- 审批弹窗 --> |
| | | <!-- <approval-dialog |
| | | :visible.sync="approvalDialogVisible" |
| | | :type="approvalDialogType" |
| | | :data="currentApprovalData" |
| | | @approve="handleApproveSubmit" |
| | | @reject="handleRejectSubmit" |
| | | /> --> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | // import ApprovalDialog from './components/approvalDialog.vue' |
| | | |
| | | export default { |
| | | name: "ProjectList", |
| | | components: { |
| | | // ApprovalDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | planName: "", |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | }, |
| | | 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", |
| | | }, |
| | | ], |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | this.form = { |
| | | planName: "", |
| | | planCode: "", |
| | | creator: "", |
| | | createTime: [], |
| | | approver: "", |
| | | status: "", |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | | // 实现查询逻辑 |
| | | console.log("查询条件:", this.form); |
| | | this.getTableData(); |
| | | }, |
| | | handleDetail(row) { |
| | | this.$router.push({ |
| | | path: "/sampleManage/submission", |
| | | query: { |
| | | id: row.id, |
| | | type: 'view' |
| | | } |
| | | }); |
| | | }, |
| | | getTableData() { |
| | | // 获取列表数据 |
| | | this.tableData = this.mockListData; |
| | | this.total = this.mockListData.length; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | .flex { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .tableTitle { |
| | | display: flex; |
| | | padding-bottom: 20px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | .title { |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049c9a; |
| | | width: unset; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属实验调度</div> |
| | | </div> |
| | | <Table :data="schedulingData" :total="schedulingTotal" :height="null"> |
| | | <template> |
| | | <el-table-column prop="planCode" label="所属项目课题方案" width="150"></el-table-column> |
| | | <el-table-column prop="experimentCode" label="实验编号" width="150"></el-table-column> |
| | | <el-table-column prop="experimentName" label="实验名称" width="150"></el-table-column> |
| | | <el-table-column prop="notifyTime" label="通知时间" width="150"></el-table-column> |
| | | <el-table-column prop="startTime" label="实验开始时间" width="150"></el-table-column> |
| | | <el-table-column prop="endTime" label="实验结束时间" width="150"></el-table-column> |
| | | <el-table-column prop="participants" label="参加人员" width="150"></el-table-column> |
| | | <el-table-column prop="status" label="状态" width="100"></el-table-column> |
| | | </template> |
| | | </Table> |
| | | |
| | | <!-- 送样-收样记录部分 --> |
| | | <div class="sample-record-section"> |
| | | <div class="header-title-left" style="margin-top: 38px"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>送样-收样记录</span> |
| | | <el-button |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | @click="showAdditives = !showAdditives" |
| | | > |
| | | {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }} |
| | | </el-button> |
| | | </div> |
| | | <div class="sample-code">取样单编号:{{ form.sampleCode || 'DD-25010BS01' }}</div> |
| | | |
| | | <div class="sample-table"> |
| | | <div class="table-header"> |
| | | <el-button type="primary" class="batch-send" @click="handleBatchSend">批量发送</el-button> |
| | | </div> |
| | | <Table :data="sampleList" :total="sampleTotal" :height="null" @selection-change="handleSelectionChange"> |
| | | <template> |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column prop="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column prop="processTime" label="工艺时间间/h" width="120"></el-table-column> |
| | | <el-table-column prop="sampleName" label="取样名称" width="150"></el-table-column> |
| | | <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column> |
| | | <el-table-column prop="temperature" label="温度" width="100"></el-table-column> |
| | | <el-table-column prop="ph" label="PH" width="100"></el-table-column> |
| | | <el-table-column prop="waterAmount" label="加水量" width="100"></el-table-column> |
| | | <template v-if="showAdditives"> |
| | | <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column> |
| | | <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column> |
| | | <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column> |
| | | <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column> |
| | | <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column> |
| | | <el-table-column prop="additive6" label="加辅6" width="150"></el-table-column> |
| | | <el-table-column prop="additive7" label="加辅7" width="150"></el-table-column> |
| | | <el-table-column prop="additive8" label="加辅8" width="150"></el-table-column> |
| | | <el-table-column prop="additive9" label="加辅9" width="150"></el-table-column> |
| | | <el-table-column prop="additive10" label="加辅10" width="150"></el-table-column> |
| | | </template> |
| | | <el-table-column prop="sampleAmount" label="取样量" width="100"></el-table-column> |
| | | <el-table-column prop="sampleTime" label="取样时间" width="150"></el-table-column> |
| | | <el-table-column prop="photo" label="拍照" width="100"> |
| | | <template slot-scope="scope"> |
| | | <img v-if="scope.row.photo" :src="scope.row.photo" class="sample-photo" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="operator" label="操作人" width="100"></el-table-column> |
| | | <el-table-column prop="status" label="状态" width="100"></el-table-column> |
| | | <el-table-column label="操作" width="100" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleSend(scope.row)" v-if="scope.row.status === '待发送'">发送</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </Table> |
| | | </div> |
| | | </div> |
| | | |
| | | <receive-confirm-dialog |
| | | :visible.sync="showReceiveConfirm" |
| | | :sample-count="selectedSamples.length" |
| | | @confirm="confirmSend" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import ReceiveConfirmDialog from './components/receiveConfirmDialog.vue' |
| | | |
| | | export default { |
| | | name: "SampleSubmission", |
| | | components: { |
| | | ReceiveConfirmDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | showReceiveConfirm: false, |
| | | showAdditives: true, |
| | | schedulingData: [{ |
| | | planCode: 'DD-EX001', |
| | | experimentCode: 'DD-EX001', |
| | | experimentName: '名称名称名称', |
| | | notifyTime: '2025-1-2 14:50:19', |
| | | startTime: '2025-02-27', |
| | | endTime: '2025-06-06', |
| | | participants: '张弘, 李天浩, 陈三, 李四', |
| | | status: '已确认' |
| | | }], |
| | | schedulingTotal: 1, |
| | | form: { |
| | | sampleCode: "DD-25010BS01", |
| | | }, |
| | | sampleList: [ |
| | | { |
| | | index: 1, |
| | | processTime: "2", |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | temperature: "34", |
| | | ph: "34", |
| | | waterAmount: "34", |
| | | additive1: "10g", |
| | | additive2: "5g", |
| | | additive3: "3g", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "34", |
| | | sampleTime: "2025-1-9 15:26:08", |
| | | photo: "@/assets/sample-photos/photo1.jpg", |
| | | operator: "张三", |
| | | status: "待发送" |
| | | }, |
| | | { |
| | | index: 2, |
| | | processTime: "4", |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | temperature: "23", |
| | | ph: "23", |
| | | waterAmount: "23", |
| | | additive1: "8g", |
| | | additive2: "4g", |
| | | additive3: "", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "23", |
| | | sampleTime: "2025-1-9 15:26:08", |
| | | photo: "@/assets/sample-photos/photo2.jpg", |
| | | operator: "李四", |
| | | status: "待接收" |
| | | }, |
| | | { |
| | | index: 3, |
| | | processTime: "8", |
| | | sampleName: "名称名称名称", |
| | | sampleCode: "314234321", |
| | | temperature: "23", |
| | | ph: "23", |
| | | waterAmount: "23", |
| | | additive1: "", |
| | | additive2: "", |
| | | additive3: "", |
| | | additive4: "", |
| | | additive5: "", |
| | | additive6: "", |
| | | additive7: "", |
| | | additive8: "", |
| | | additive9: "", |
| | | additive10: "", |
| | | sampleAmount: "23", |
| | | sampleTime: "2025-1-9 15:26:08", |
| | | photo: "@/assets/sample-photos/photo3.jpg", |
| | | operator: "王五", |
| | | status: "已接收" |
| | | } |
| | | ], |
| | | sampleTotal: 3, |
| | | selectedSamples: [] |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleSelectionChange(selection) { |
| | | this.selectedSamples = selection; |
| | | }, |
| | | handleSend(row) { |
| | | this.selectedSamples = [row]; |
| | | this.showReceiveConfirm = true; |
| | | }, |
| | | handleBatchSend() { |
| | | if (this.selectedSamples.length === 0) { |
| | | this.$message.warning('请先选择要发送的样品'); |
| | | return; |
| | | } |
| | | this.showReceiveConfirm = true; |
| | | }, |
| | | confirmSend(signature) { |
| | | // 处理发送确认逻辑 |
| | | const sampleIds = this.selectedSamples.map(item => item.id); |
| | | console.log('发送样品', { sampleIds, signature }); |
| | | |
| | | // 更新状态 |
| | | this.selectedSamples.forEach(sample => { |
| | | const index = this.sampleList.findIndex(item => item.id === sample.id); |
| | | if (index > -1) { |
| | | this.sampleList[index].status = '待接收'; |
| | | } |
| | | }); |
| | | |
| | | this.$message.success(`成功发送 ${this.selectedSamples.length} 个样品`); |
| | | this.selectedSamples = []; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin-bottom: 20px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | div, span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | |
| | | div:before { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | .el-button { |
| | | margin-left: 16px; |
| | | } |
| | | } |
| | | |
| | | .sample-record-section { |
| | | .sample-code { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0,0,0,0.88); |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .table-header { |
| | | margin-bottom: 16px; |
| | | text-align: left; |
| | | } |
| | | |
| | | .sample-photo { |
| | | width: 60px; |
| | | height: 60px; |
| | | object-fit: cover; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="检验数据结果汇总" |
| | | :visible.sync="visible" |
| | | 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"> |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>本次检验结果总表</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>本次检验说明</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </Card> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "CheckoutResult", |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | content: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | ::v-deep .el-dialog__header { |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .approval-dialog { |
| | | display: flex; |
| | | height: 300px; |
| | | |
| | | .approval-content { |
| | | flex: 1; |
| | | margin-right: 20px; |
| | | background: #ffffff; |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | |
| | | .approval-content-card { |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .header-title { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 13px; |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin-top: 38px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | 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:first-child { |
| | | .header-title-left { |
| | | margin-top: 0; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | :visible.sync="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="79.17%" |
| | | @close="handleClose" |
| | | > |
| | | <EvaluateTable ref="evaluateTable" /> |
| | | <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' |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | dialogTitle() { |
| | | return this.type === 'labTechnician' ? '化验师工作评定' : '实验员工作评定'; |
| | | } |
| | | }, |
| | | 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> |
New file |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog title="选择实验调度" :visible.sync="show" width="80%"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null"> |
| | | <template #search> |
| | | <el-form :model="form" label-width="140px" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.planName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.planCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.creator" 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"></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="待确认" value="待确认"></el-option> |
| | | <el-option label="已确认" value="已确认"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="" class="search-btn-box"> |
| | | <el-button type="default" @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <template #table> |
| | | <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> |
| | | </template> |
| | | </TableCustom> |
| | | <span slot="footer" class="select-member-footer"> |
| | | <el-button @click="show = false">取 消</el-button> |
| | | <el-button type="primary" @click="show = false">确 定</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: ['show'], |
| | | data() { |
| | | return { |
| | | form: {}, |
| | | tableData: [], |
| | | total: 0 |
| | | } |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | |
| | | }, |
| | | handleSearch() { |
| | | |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | > |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>一 、所属实验调度</div> |
| | | </div> |
| | | <el-button |
| | | type="primary" |
| | | class="el-icon-plus" |
| | | @click="handleSelectScheduling" |
| | | >选择实验调度</el-button |
| | | > |
| | | </div> |
| | | |
| | | <Table |
| | | :data="[selectedScheduling].filter(Boolean)" |
| | | :total="0" |
| | | :height="null" |
| | | class="rwuTable" |
| | | > |
| | | <el-table-column |
| | | prop="planName" |
| | | label="所属项目课题方案" |
| | | min-width="180" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="planCode" |
| | | label="实验编号" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="noticeTime" |
| | | label="通知时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="startTime" |
| | | label="实验开始时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="endTime" |
| | | label="实验结束时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="participants" |
| | | label="参加人员" |
| | | min-width="180" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="status" |
| | | label="状态" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | </Table> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>一 、实验结果</div> |
| | | </div> |
| | | </div> |
| | | <Table |
| | | :data="experimentResultData" |
| | | :total="0" |
| | | :height="null" |
| | | class="rwuTable" |
| | | > |
| | | <el-table-column |
| | | prop="planName" |
| | | label="所属项目课题方案" |
| | | min-width="180" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="实验编号" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentName" |
| | | label="实验名称" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentDate" |
| | | label="实验日期" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimenter" |
| | | label="实验员" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="createTime" |
| | | label="创建日期" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="creator" |
| | | label="创建人" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="status" |
| | | label="当前状态" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column label="操作" min-width="100" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetail(scope.row)" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>二 、检验结果</div> |
| | | </div> |
| | | </div> |
| | | <Table |
| | | :data="inspectionResultData" |
| | | :total="0" |
| | | :height="null" |
| | | class="rwuTable" |
| | | > |
| | | <el-table-column |
| | | prop="planName" |
| | | label="所属项目课题方案" |
| | | min-width="180" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="experimentCode" |
| | | label="所属实验编号" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="createTime" |
| | | label="创建时间" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="creator" |
| | | label="创建人" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="status" |
| | | label="状态" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column label="操作" min-width="100" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | type="text" |
| | | @click="handleViewInspectionDetail(scope.row)" |
| | | >详情</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>三 、实验数据分析及结论</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>四 、化验师工作评定</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="evaluate-card"> |
| | | <div class="evaluate-card-people"> |
| | | <div |
| | | v-for="technician in labTechnicians" |
| | | :key="technician.id" |
| | | class="evaluate-card-people-item" |
| | | :class="{ 'active-people': selectedLabTechnician?.id === technician.id }" |
| | | @click="handleSelectLabTechnician(technician)" |
| | | > |
| | | {{ technician.name }} |
| | | </div> |
| | | </div> |
| | | <div class="evaluate-card-cotent"> |
| | | <template v-if="selectedLabTechnician"> |
| | | <template v-if="selectedLabTechnician.data"> |
| | | <EvaluateTable |
| | | class="evaluate-table" |
| | | :isReadonly="true" |
| | | :type="1" |
| | | :viewJson="JSON.stringify(selectedLabTechnician.data)" |
| | | /> |
| | | </template> |
| | | <template v-else> |
| | | <div class="no-data">暂未评定</div> |
| | | <div class="to-evaluate" @click="handleEvaluate('labTechnician')">去评价</div> |
| | | </template> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="header-title"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>五 、实验员工作评定</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="evaluate-card"> |
| | | <div class="evaluate-card-people"> |
| | | <div |
| | | v-for="experimenter in experimenters" |
| | | :key="experimenter.id" |
| | | class="evaluate-card-people-item" |
| | | :class="{ 'active-people': selectedExperimenter?.id === experimenter.id }" |
| | | @click="handleSelectExperimenter(experimenter)" |
| | | > |
| | | {{ experimenter.name }} |
| | | </div> |
| | | </div> |
| | | <div class="evaluate-card-cotent"> |
| | | <template v-if="selectedExperimenter"> |
| | | <template v-if="selectedExperimenter.data"> |
| | | <EvaluateTable |
| | | ref="experimenterEvaluateTable" |
| | | class="evaluate-table" |
| | | :isReadonly="true" |
| | | :viewJson="JSON.stringify(selectedExperimenter.data)" |
| | | /> |
| | | </template> |
| | | <template v-else> |
| | | <div class="no-data">暂未评定</div> |
| | | <div class="to-evaluate" @click="handleEvaluate('experimenter')">去评价</div> |
| | | </template> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary" class="save-btn">发送</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | </el-form> |
| | | <!-- 选择实验调度弹窗 --> |
| | | <experimental-scheduling |
| | | :show.sync="schedulingDialogVisible" |
| | | @select="handleSchedulingSelect" |
| | | /> |
| | | <!-- 评价弹窗 --> |
| | | <evaluation-dialog |
| | | :modelValue="evaluationDialogVisible" |
| | | :type="currentEvaluationType" |
| | | @update:modelValue="updateEvaluationDialogVisible" |
| | | @submit="handleEvaluationSubmit" |
| | | /> |
| | | <!-- 检验结果详情弹窗 --> |
| | | <checkout-result |
| | | :visible.sync="checkoutResultVisible" |
| | | :data="currentCheckoutResult" |
| | | /> |
| | | <!-- 新增组件弹窗 --> |
| | | <add-component-dialog |
| | | v-if="showNewDialog" |
| | | :visible.sync="showNewDialog" |
| | | @confirm="handleAddComponent" |
| | | /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import ExperimentalScheduling from "./components/experimental-scheduling.vue"; |
| | | import moment from "moment"; |
| | | import EvaluationDialog from "./components/evaluation-dialog.vue"; |
| | | import CheckoutResult from "./components/checkout-result.vue"; |
| | | import AddComponentDialog from "@/components/AddComponentDialog"; |
| | | |
| | | export default { |
| | | name: "AddProject", |
| | | components: { |
| | | ExperimentalScheduling, |
| | | EvaluationDialog, |
| | | CheckoutResult, |
| | | AddComponentDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | showNewDialog: true, |
| | | dialogVisible: false, |
| | | schedulingDialogVisible: false, |
| | | isEdit: false, |
| | | currentEditIndex: -1, |
| | | selectedScheduling: null, |
| | | form: { |
| | | recordNo: "", |
| | | testItemName: "", |
| | | testItemNo: "", |
| | | testMethodName: "", |
| | | testMethodNo: "", |
| | | }, |
| | | rules: { |
| | | recordNo: [ |
| | | { |
| | | required: true, |
| | | message: "请输入原始检验记录编号", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | testItemName: [ |
| | | { required: true, message: "请输入检测项名字", trigger: "blur" }, |
| | | ], |
| | | testItemNo: [ |
| | | { required: true, message: "请输入检测项编号", trigger: "blur" }, |
| | | ], |
| | | testMethodName: [ |
| | | { required: true, message: "请输入检测方法名字", trigger: "blur" }, |
| | | ], |
| | | testMethodNo: [ |
| | | { required: true, message: "请输入检测方法编号", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | taskTableData: [], |
| | | experimentResultData: [ |
| | | { |
| | | planName: "名称名称名称", |
| | | experimentCode: "3814763", |
| | | experimentName: "名称名称22", |
| | | experimentDate: "2024-05-28", |
| | | experimenter: "刘大大", |
| | | createTime: "2025-1-2 16:27:17", |
| | | creator: "周乐心", |
| | | status: "实验员已提交", |
| | | }, |
| | | ], |
| | | inspectionResultData: [ |
| | | { |
| | | planName: "名称名称名称", |
| | | experimentCode: "31423764", |
| | | createTime: "", |
| | | creator: "", |
| | | status: "已提交", |
| | | }, |
| | | { |
| | | planName: "名称名称名称", |
| | | experimentCode: "31423764", |
| | | createTime: "", |
| | | creator: "", |
| | | status: "已提交", |
| | | }, |
| | | ], |
| | | // 化验师数据 |
| | | labTechnicians: [ |
| | | { |
| | | id: 1, |
| | | name: '张三', |
| | | role: '化验师', |
| | | data: null // 评定数据,null 表示未评定 |
| | | }, |
| | | { |
| | | id: 2, |
| | | name: '李四', |
| | | role: '化验师', |
| | | data: null |
| | | } |
| | | ], |
| | | selectedLabTechnician: null, |
| | | |
| | | // 实验员数据 |
| | | experimenters: [ |
| | | { |
| | | id: 1, |
| | | name: '王五', |
| | | role: '实验员', |
| | | data: null |
| | | }, |
| | | { |
| | | id: 2, |
| | | name: '赵六', |
| | | role: '实验员', |
| | | data: null |
| | | } |
| | | ], |
| | | selectedExperimenter: null, |
| | | |
| | | // 弹窗控制 |
| | | evaluationDialogVisible: false, |
| | | currentEvaluationType: '', |
| | | checkoutResultVisible: false, |
| | | currentCheckoutResult: null |
| | | }; |
| | | }, |
| | | watch: { |
| | | selectedLabTechnician: { |
| | | handler(newVal) { |
| | | console.log("selectedLabTechnician", newVal); |
| | | }, |
| | | }, |
| | | }, |
| | | created() { |
| | | // 默认选中第一个人员 |
| | | this.selectedLabTechnician = this.labTechnicians[0]; |
| | | this.selectedExperimenter = this.experimenters[0]; |
| | | }, |
| | | methods: { |
| | | handleSelectScheduling() { |
| | | this.schedulingDialogVisible = true; |
| | | }, |
| | | handleSchedulingSelect(selectedData) { |
| | | if (selectedData && selectedData.length > 0) { |
| | | this.selectedScheduling = selectedData[0]; |
| | | this.$message.success("选择成功"); |
| | | } |
| | | }, |
| | | handleAddTask() { |
| | | this.isEdit = false; |
| | | this.currentEditIndex = -1; |
| | | this.dialogVisible = true; |
| | | }, |
| | | handleEditTask(row) { |
| | | this.isEdit = true; |
| | | this.currentEditIndex = this.taskTableData.findIndex( |
| | | (item) => item === row |
| | | ); |
| | | |
| | | const editData = { |
| | | sampleCode: row.sampleCode, |
| | | testData: row.testData, |
| | | testTypes: [], |
| | | photos: [], |
| | | spectrums: [], |
| | | }; |
| | | |
| | | if (row.photos && row.photos.length > 0) { |
| | | editData.testTypes.push("photo"); |
| | | editData.photos = row.photos.map((photo) => ({ |
| | | name: photo.name, |
| | | url: photo.url, |
| | | raw: null, |
| | | })); |
| | | } |
| | | if (row.spectrums && row.spectrums.length > 0) { |
| | | editData.testTypes.push("spectrum"); |
| | | editData.spectrums = row.spectrums.map((spectrum) => ({ |
| | | name: spectrum.name, |
| | | url: spectrum.url, |
| | | raw: null, |
| | | })); |
| | | } |
| | | |
| | | this.$nextTick(() => { |
| | | this.dialogVisible = true; |
| | | this.$refs.addDialog.setFormData(editData); |
| | | }); |
| | | }, |
| | | handleDeleteTask(row) { |
| | | this.$confirm("确认删除该检测数据吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | const index = this.taskTableData.findIndex((item) => item === row); |
| | | if (index > -1) { |
| | | const item = this.taskTableData[index]; |
| | | if (item.photos) { |
| | | item.photos.forEach((photo) => { |
| | | if (photo.url.startsWith("blob:")) { |
| | | URL.revokeObjectURL(photo.url); |
| | | } |
| | | }); |
| | | } |
| | | if (item.spectrums) { |
| | | item.spectrums.forEach((spectrum) => { |
| | | if (spectrum.url.startsWith("blob:")) { |
| | | URL.revokeObjectURL(spectrum.url); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.taskTableData.splice(index, 1); |
| | | this.$message.success("删除成功"); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | handleTaskSubmit(formData) { |
| | | const photos = formData.photos.map((file) => ({ |
| | | name: file.name, |
| | | url: file.url || URL.createObjectURL(file.raw), |
| | | })); |
| | | |
| | | const spectrums = formData.spectrums.map((file) => ({ |
| | | name: file.name, |
| | | url: file.url || URL.createObjectURL(file.raw), |
| | | })); |
| | | |
| | | const newData = { |
| | | sampleCode: formData.sampleCode, |
| | | testData: formData.testData, |
| | | testResult: "", |
| | | photos, |
| | | spectrums, |
| | | createTime: this.isEdit |
| | | ? this.taskTableData[this.currentEditIndex].createTime |
| | | : moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | |
| | | if (this.isEdit && this.currentEditIndex > -1) { |
| | | const oldData = this.taskTableData[this.currentEditIndex]; |
| | | if (oldData.photos) { |
| | | oldData.photos.forEach((photo) => { |
| | | if ( |
| | | photo.url.startsWith("blob:") && |
| | | !photos.find((p) => p.url === photo.url) |
| | | ) { |
| | | URL.revokeObjectURL(photo.url); |
| | | } |
| | | }); |
| | | } |
| | | if (oldData.spectrums) { |
| | | oldData.spectrums.forEach((spectrum) => { |
| | | if ( |
| | | spectrum.url.startsWith("blob:") && |
| | | !spectrums.find((s) => s.url === spectrum.url) |
| | | ) { |
| | | URL.revokeObjectURL(spectrum.url); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.taskTableData.splice(this.currentEditIndex, 1, newData); |
| | | this.$message.success("更新成功"); |
| | | } else { |
| | | this.taskTableData.push(newData); |
| | | this.$message.success("添加成功"); |
| | | } |
| | | |
| | | this.dialogVisible = false; |
| | | this.isEdit = false; |
| | | this.currentEditIndex = -1; |
| | | }, |
| | | getPhotoUrls(photos) { |
| | | return photos.map((photo) => photo.url); |
| | | }, |
| | | handleViewDetail(row) { |
| | | console.log("查看详情", row); |
| | | }, |
| | | handleViewInspectionDetail(row) { |
| | | this.currentCheckoutResult = row; |
| | | this.checkoutResultVisible = true; |
| | | }, |
| | | // 选择化验师 |
| | | handleSelectLabTechnician(technician) { |
| | | this.selectedLabTechnician = technician; |
| | | }, |
| | | // 选择实验员 |
| | | handleSelectExperimenter(experimenter) { |
| | | this.selectedExperimenter = experimenter; |
| | | }, |
| | | // 去评价 |
| | | handleEvaluate(type) { |
| | | this.currentEvaluationType = type; |
| | | this.evaluationDialogVisible = true; |
| | | }, |
| | | // 处理评价提交 |
| | | handleEvaluationSubmit(evaluationData) { |
| | | const { type, activeIndex } = evaluationData; |
| | | |
| | | if (type === 'labTechnician') { |
| | | // 更新化验师列表中的数据 |
| | | const labTechnician = this.labTechnicians.find(item => item.id === this.selectedLabTechnician.id); |
| | | if (labTechnician) { |
| | | labTechnician.data = activeIndex; |
| | | // 更新当前选中的化验师数据 |
| | | this.selectedLabTechnician = { ...labTechnician }; |
| | | } |
| | | } else if (type === 'experimenter') { |
| | | // 更新实验员列表中的数据 |
| | | const experimenter = this.experimenters.find(item => item.id === this.selectedExperimenter.id); |
| | | if (experimenter) { |
| | | experimenter.data = activeIndex; |
| | | // 更新当前选中的实验员数据 |
| | | this.selectedExperimenter = { ...experimenter }; |
| | | } |
| | | } |
| | | |
| | | // 这里可以添加数据持久化的逻辑,比如调用API保存到后端 |
| | | // this.saveEvaluationData(type, activeIndex); |
| | | |
| | | this.$message.success('评价提交成功'); |
| | | this.evaluationDialogVisible = false; |
| | | }, |
| | | // 更新弹窗显示状态 |
| | | updateEvaluationDialogVisible(value) { |
| | | this.evaluationDialogVisible = value; |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .el-form--inline .el-form-item { |
| | | margin-right: 83px; |
| | | } |
| | | |
| | | .header-title { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 13px; |
| | | margin-top: 38px; |
| | | margin-bottom: 38px; |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | |
| | | img { |
| | | width: 12px; |
| | | height: 19px; |
| | | } |
| | | |
| | | span { |
| | | flex-shrink: 0; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 27px; |
| | | font-family: "Source Han Sans CN Bold Bold"; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .rwuTable { |
| | | width: 85%; |
| | | padding-left: 40px; |
| | | } |
| | | |
| | | .add-project-footer { |
| | | margin-top: 43px; |
| | | |
| | | button { |
| | | width: 220px; |
| | | } |
| | | |
| | | .save-btn { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .image-preview { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-wrap: wrap; |
| | | |
| | | .preview-image { |
| | | width: 50px; |
| | | height: 50px; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .image-slot { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: #f5f7fa; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .spectrum-link { |
| | | display: block; |
| | | margin-bottom: 5px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .evaluate-card { |
| | | width: calc(95% - 40px); |
| | | background: #eff8fa; |
| | | padding: 30px; |
| | | margin-left: 29px; |
| | | |
| | | .evaluate-card-people { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 16px; |
| | | |
| | | .evaluate-card-people-item { |
| | | width: 125px; |
| | | background: #ffffff; |
| | | border-radius: 6px; |
| | | padding: 10px 5px; |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #333333; |
| | | line-height: 22px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .active-people { |
| | | background: #ebffff; |
| | | border-radius: 6px; |
| | | border: 1px solid #049c9a; |
| | | color: rgba(4, 156, 154, 1); |
| | | } |
| | | } |
| | | .evaluate-card-cotent { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | .no-data { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 500; |
| | | font-size: 20px; |
| | | color: #909399; |
| | | line-height: 28px; |
| | | margin-top: 58px; |
| | | margin-bottom: 30px; |
| | | } |
| | | .to-evaluate { |
| | | width: 65px; |
| | | background: #049c9a; |
| | | border-radius: 4px; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | line-height: 32px; |
| | | text-align: center; |
| | | margin-bottom: 12px; |
| | | } |
| | | .evaluate-table{ |
| | | width: 100%; |
| | | margin-top: 29px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null"> |
| | | <template #search> |
| | | <el-form :model="form" labelWidth="auto" inline> |
| | | <el-form-item label="所属项目课题方案:"> |
| | | <el-input v-model="form.projectPlan" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.experimentNo" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <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="form.createTime" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | value-format="yyyy-MM-dd" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.status" placeholder="请选择"> |
| | | <el-option label="待提交" value="pending"></el-option> |
| | | <el-option label="已提交" value="submitted"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <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" |
| | | :class="{ active: currentType === 'list' }" |
| | | @click="handleTypeChange('list')" |
| | | > |
| | | 实验结果汇报列表 |
| | | </div> |
| | | <div |
| | | class="drafts" |
| | | :class="{ active: currentType === 'draft' }" |
| | | @click="handleTypeChange('draft')" |
| | | > |
| | | 草稿箱 |
| | | </div> |
| | | </div> |
| | | <el-button @click="handleAddResult" class="el-icon-plus" type="primary"> |
| | | 新增实验结果 |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | <template #table> |
| | | <el-table-column prop="projectPlan" label="所属项目课题方案"></el-table-column> |
| | | <el-table-column prop="experimentNo" label="实验编号"></el-table-column> |
| | | <el-table-column prop="experimentName" label="实验名称"></el-table-column> |
| | | <el-table-column prop="engineer" label="工艺工程师"></el-table-column> |
| | | <el-table-column prop="chemist" label="化验师"></el-table-column> |
| | | <el-table-column prop="engineerApproved" label="是否评定"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.engineerApproved === '是' ? 'success' : 'danger'"> |
| | | {{ scope.row.engineerApproved }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="experimenter" label="实验员"></el-table-column> |
| | | <el-table-column prop="experimenterApproved" label="是否评定"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.experimenterApproved === '是' ? 'success' : 'danger'"> |
| | | {{ scope.row.experimenterApproved }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="创建日期"></el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === '已提交' ? 'success' : 'warning'"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="280"> |
| | | <template slot-scope="scope"> |
| | | <template v-if="currentType === 'list'"> |
| | | <!-- 待提交状态 --> |
| | | <template v-if="scope.row.status === '待提交'"> |
| | | <el-button type="text" @click="handleSubmit(scope.row)">提交</el-button> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | <!-- 待评定状态 --> |
| | | <template v-else-if="scope.row.status === '待评定'"> |
| | | <el-button type="text" @click="handleEvaluate(scope.row)">评定</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button> |
| | | </template> |
| | | <!-- 已提交状态 --> |
| | | <template v-else-if="scope.row.status === '已提交'"> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button> |
| | | </template> |
| | | </template> |
| | | <!-- 草稿箱 --> |
| | | <template v-else> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button> |
| | | <el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "TestResultReport", |
| | | data() { |
| | | return { |
| | | currentType: "list", // 当前显示类型:list-列表,draft-草稿箱 |
| | | form: { |
| | | projectPlan: "", |
| | | experimentNo: "", |
| | | experimentName: "", |
| | | createTime: [], |
| | | status: "" |
| | | }, |
| | | tableData: [], |
| | | total: 0, |
| | | // 正式列表数据 |
| | | mockListData: [ |
| | | { |
| | | id: '1', |
| | | projectPlan: '名称名称名称', |
| | | experimentNo: '31423764', |
| | | experimentName: '名称名称名称', |
| | | engineer: '李治悦', |
| | | chemist: '刘大大', |
| | | engineerApproved: '否', |
| | | experimenter: '周乐心; 张瑞瑞', |
| | | experimenterApproved: '否', |
| | | createTime: '2025-1-2 16:27:17', |
| | | status: '待提交' |
| | | }, |
| | | { |
| | | id: '2', |
| | | projectPlan: '高性能材料研究', |
| | | experimentNo: '31423765', |
| | | experimentName: '材料强度测试', |
| | | engineer: '赵雨', |
| | | chemist: '王泽', |
| | | engineerApproved: '是', |
| | | experimenter: '李明; 张华', |
| | | experimenterApproved: '是', |
| | | createTime: '2025-1-2 16:30:17', |
| | | status: '已提交' |
| | | }, |
| | | { |
| | | id: '3', |
| | | projectPlan: '新型合金开发', |
| | | experimentNo: '31423766', |
| | | experimentName: '合金性能分析', |
| | | engineer: '杨静', |
| | | chemist: '陈亮', |
| | | engineerApproved: '是', |
| | | experimenter: '王刚', |
| | | experimenterApproved: '否', |
| | | createTime: '2025-1-2 16:35:17', |
| | | status: '待评定' |
| | | } |
| | | ], |
| | | // 草稿箱数据 |
| | | mockDraftData: [ |
| | | { |
| | | id: '4', |
| | | projectPlan: '环保材料研究', |
| | | experimentNo: '31423767', |
| | | experimentName: '材料降解测试', |
| | | engineer: '张伟', |
| | | chemist: '李强', |
| | | engineerApproved: '否', |
| | | experimenter: '王芳', |
| | | experimenterApproved: '否', |
| | | createTime: '2025-1-2 16:40:17', |
| | | status: '草稿' |
| | | }, |
| | | { |
| | | id: '5', |
| | | projectPlan: '纳米材料开发', |
| | | experimentNo: '31423768', |
| | | experimentName: '纳米结构分析', |
| | | engineer: '刘洋', |
| | | chemist: '周杰', |
| | | engineerApproved: '否', |
| | | experimenter: '孙明', |
| | | experimenterApproved: '否', |
| | | createTime: '2025-1-2 16:45:17', |
| | | status: '草稿' |
| | | } |
| | | ] |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getTableData(); |
| | | }, |
| | | methods: { |
| | | resetForm() { |
| | | this.form = { |
| | | projectPlan: "", |
| | | experimentNo: "", |
| | | experimentName: "", |
| | | createTime: [], |
| | | status: "" |
| | | }; |
| | | }, |
| | | handleSearch() { |
| | | this.getTableData(); |
| | | }, |
| | | handleAddResult() { |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: 'new', |
| | | type: 'add' |
| | | } |
| | | }); |
| | | }, |
| | | handleEdit(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: row.id, |
| | | type: 'edit' |
| | | } |
| | | }); |
| | | }, |
| | | handleDetail(id) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: id, |
| | | type: 'view' |
| | | } |
| | | }); |
| | | }, |
| | | handleSubmit(row) { |
| | | this.$confirm('确认提交该实验结果?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | // TODO: 调用提交接口 |
| | | this.$message.success('提交成功'); |
| | | this.getTableData(); |
| | | }).catch(() => {}); |
| | | }, |
| | | handleDelete(row) { |
| | | this.$confirm('确认删除该实验结果?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | // TODO: 调用删除接口 |
| | | this.$message.success('删除成功'); |
| | | this.getTableData(); |
| | | }).catch(() => {}); |
| | | }, |
| | | handleEvaluate(row) { |
| | | this.$router.push({ |
| | | path: "/dataManagement/testResultReport/detail", |
| | | query: { |
| | | id: row.id, |
| | | type: 'evaluate' |
| | | } |
| | | }); |
| | | }, |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
| | | this.getTableData(); |
| | | }, |
| | | getTableData() { |
| | | // 根据currentType获取不同的数据 |
| | | if (this.currentType === 'list') { |
| | | this.tableData = this.mockListData; |
| | | this.total = this.mockListData.length; |
| | | } else { |
| | | this.tableData = this.mockDraftData; |
| | | this.total = this.mockDraftData.length; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .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; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | width: unset; |
| | | cursor: pointer; |
| | | } |
| | | .drafts { |
| | | padding: 16px 65px; |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | font-weight: 400; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | margin-left: 16px; |
| | | cursor: pointer; |
| | | } |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | </style> |
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" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="content-box"> |
| | | <el-row :gutter="16"> |
| | | <el-col style="margin-top: 5px;" :xs="24" :sm="24" :md="24" :lg="24" :xl="24"> |
| | | <Table :total="0" :height="null" :data="criteriaList" show-summary :summary-method="getSummaries" |
| | | :span-method="arraySpanMethod"> |
| | | <el-table-column type="index" label="序号" width="80" /> |
| | | <el-table-column prop="criteria" label="规程型课题评定标准" /> |
| | | <el-table-column prop="fullScore" label="满分值" width="100" /> |
| | | <el-table-column label="评定分值" prop="score" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-input-number v-model="row.score" :min="0" :max="row.fullScore" :step="1" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="rule" label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、规程型课题评定总分的满分为5分。</div> |
| | | <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="assessed"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范', |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;', |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | ] |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | await this.$refs.formRef.validate(); |
| | | const totalScore = this.criteriaList.reduce((sum, item) => sum + (item.score || 0), 0); |
| | | const assessmentData = { |
| | | ...this.form, |
| | | totalScore, |
| | | criteriaScores: this.criteriaList.map(item => ({ |
| | | criteria: item.criteria, |
| | | score: item.score || 0 |
| | | })) |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | this.handleClose(); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => { |
| | | const value = Number(curr); |
| | | if (!isNaN(value)) { |
| | | return prev + curr; |
| | | } else { |
| | | return prev; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | } else { |
| | | sums[index] = ''; |
| | | } |
| | | }); |
| | | return sums; |
| | | }, |
| | | arraySpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-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> |
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" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="content-box"> |
| | | <el-row :gutter="16"> |
| | | <el-col style="margin-top: 5px;" :xs="24" :sm="24" :md="24" :lg="24" :xl="24"> |
| | | <Table :total="0" :height="null" :data="criteriaList" show-summary :summary-method="getSummaries" |
| | | :span-method="arraySpanMethod"> |
| | | <el-table-column type="index" label="序号" width="80" /> |
| | | <el-table-column prop="criteria" label="创新型课题标准" /> |
| | | <el-table-column prop="fullScore" label="满分值" width="100" /> |
| | | <el-table-column label="评定分值" prop="score" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-input-number v-model="row.score" :min="0" :max="row.fullScore" :step="1" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column 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"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'CraftDialog', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | }, |
| | | 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; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | await this.$refs.formRef.validate(); |
| | | const totalScore = this.criteriaList.reduce((sum, item) => sum + (item.score || 0), 0); |
| | | const assessmentData = { |
| | | ...this.form, |
| | | totalScore, |
| | | criteriaScores: this.criteriaList.map(item => ({ |
| | | criteria: item.criteria, |
| | | score: item.score || 0 |
| | | })) |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | this.handleClose(); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => { |
| | | const value = Number(curr); |
| | | if (!isNaN(value)) { |
| | | return prev + curr; |
| | | } else { |
| | | return prev; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | } else { |
| | | sums[index] = ''; |
| | | } |
| | | }); |
| | | return sums; |
| | | }, |
| | | arraySpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-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> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="课题类型:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="课题名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="提交人:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</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> |
| | | </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="状态"> |
| | | <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">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <!-- 化验师 审批人 --> |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | |
| | | <!-- 工艺工程师 --> |
| | | <CraftDialog :modelValue="craftVisible" :reportData="currentReport" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | import CraftDialog from './components/CraftDialog.vue' |
| | | |
| | | export default { |
| | | name: 'AssayTaskList', |
| | | components: { |
| | | AssessmentDialog, |
| | | CraftDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {}, |
| | | craftVisible: false, |
| | | } |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="新增临床试验" width="50%" @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> |
| | | <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" /> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer select-member-footer"> |
| | | <el-button type="primary">确认</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'Detail', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | textarea: '', |
| | | value1: '', |
| | | score: null, |
| | | fullScore: 3 |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | ], |
| | | }, |
| | | criteriaList: [] |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form = val || {}; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin: 10px 0; |
| | | |
| | | 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'; |
| | | } |
| | | |
| | | |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="任务内容:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <el-button @click="assessmentVisible = true, currentReport = {}" 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="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <Detail :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Detail from './components/detail.vue' |
| | | |
| | | export default { |
| | | name: 'ClinicalTrial', |
| | | components: { |
| | | Detail |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {} |
| | | } |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="化验师工作评定" width="79.17%" @close="handleClose"> |
| | | <EvaluateTable ref="evaluateTable" /> |
| | | <div class="assessed"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'Detail', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | console.log(this.$refs.evaluateTable.total); |
| | | console.log(this.$refs.evaluateTable.activeIndex); |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .assessed { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | gap: 25px; |
| | | margin-top: 20px; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="所属实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </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> |
| | | <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-select> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | </el-form-item> |
| | | </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="是否评定"> |
| | | <template #default="{ row }"> |
| | | <span :style="{ color: ['green', 'red'][row.status - 1] }">{{ ['是', '否'][row.status - 1] |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="创建日期" /> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">评定详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <Detail :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Detail from './components/detail.vue' |
| | | |
| | | export default { |
| | | name: 'ExperimentResults', |
| | | components: { |
| | | Detail |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {} |
| | | } |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="创建日期:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <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> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="assessmentVisible = true">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | export default { |
| | | name: 'ProcessEngineerEvaluate', |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | } |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | |
| | | .table-title { |
| | | width: 220px; |
| | | height: 50px; |
| | | background: #FFFFFF; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049C9A; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049C9A; |
| | | line-height: 27px; |
| | | } |
| | | |
| | | .expand-box { |
| | | padding: 20px; |
| | | background: linear-gradient(180deg, #049C9A 0%, #0ACBCA 100%); |
| | | border-radius: 20px; |
| | | |
| | | &-title { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | line-height: 24px; |
| | | margin-bottom: 20px; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-dialog :visible.sync="dialogVisible" title="其他任务详情" width="70%" @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> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>任务内容</div> |
| | | </div> |
| | | <div>清理</div> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>任务时间</div> |
| | | </div> |
| | | <div>2020-12-31 12:00:00</div> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>评定积分</div> |
| | | </div> |
| | | <div>2</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'Detail', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: {}, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | ], |
| | | }, |
| | | criteriaList: [] |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form = val || {}; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | margin: 10px 0; |
| | | |
| | | 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'; |
| | | } |
| | | |
| | | |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="任务内容:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <!-- 工艺工程师 --> |
| | | <template #setting> |
| | | <el-button @click="assessmentVisible = true, currentReport = {}" 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="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <Detail :modelValue="assessmentVisible" :reportData="currentReport" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Detail from './components/detail.vue' |
| | | |
| | | export default { |
| | | name: 'RestsTask', |
| | | components: { |
| | | Detail |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {} |
| | | } |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
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" 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" /> |
| | | </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"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer select-member-footer"> |
| | | <el-button type="primary" @click="handleSubmit">提交评定结果</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | }, |
| | | 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; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | await this.$refs.formRef.validate(); |
| | | const totalScore = this.criteriaList.reduce((sum, item) => sum + (item.score || 0), 0); |
| | | const assessmentData = { |
| | | ...this.form, |
| | | totalScore, |
| | | criteriaScores: this.criteriaList.map(item => ({ |
| | | criteria: item.criteria, |
| | | score: item.score || 0 |
| | | })) |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | this.handleClose(); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => { |
| | | const value = Number(curr); |
| | | if (!isNaN(value)) { |
| | | return prev + curr; |
| | | } else { |
| | | return prev; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | } else { |
| | | sums[index] = ''; |
| | | } |
| | | }); |
| | | return sums; |
| | | }, |
| | | arraySpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-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> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="课题类型:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="课题名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="提交人:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</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> |
| | | </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="状态"> |
| | | <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">详情</el-button> |
| | | <el-button type="text">评定</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" |
| | | @submit="handleAssessmentSubmit" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | |
| | | export default { |
| | | name: 'TaskList', |
| | | components: { |
| | | AssessmentDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {} |
| | | } |
| | | }, |
| | | methods: { |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <Card> |
| | | <template> |
| | | <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> |
| | | </div> |
| | | <Table :tableData="tableData" :total="total" :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> |
| | | </template> |
| | | </Table> |
| | | <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> |
| | | </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> |
| | | <div class="member-edit" @click="addMember">修改</div> |
| | | </div> |
| | | </div> |
| | | </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" /> |
| | | <div class="add-project-footer"> |
| | | <el-button type="primary">保存</el-button> |
| | | <el-button>存草稿</el-button> |
| | | </div> |
| | | </template> |
| | | <SelectMember ref="selectMember" /> |
| | | <ExperimentalScheduling :show="showScheduling" /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import ExperimentalScheduling from "@/views/dataManagement/confirmation-sheet/components/experimental-scheduling"; |
| | | export default { |
| | | name: 'AddTesterWorkerEvaluate', |
| | | components: { |
| | | ExperimentalScheduling, |
| | | }, |
| | | data() { |
| | | return { |
| | | showScheduling: false, |
| | | } |
| | | }, |
| | | methods: { |
| | | submitForm() { |
| | | }, |
| | | addMember() { |
| | | this.$refs.selectMember.open() |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .el-form--inline .el-form-item { |
| | | margin-right: 83px; |
| | | } |
| | | |
| | | .header-title { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 13px; |
| | | |
| | | .header-title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 13px; |
| | | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .member-list { |
| | | margin-top: 18px; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 28px; |
| | | |
| | | .member-list-card { |
| | | position: relative; |
| | | 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%); |
| | | |
| | | .member-item { |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .member-title { |
| | | margin-top: 20px; |
| | | width: 100%; |
| | | font-family: 'Source Han Sans CN Bold Bold'; |
| | | font-weight: bold; |
| | | font-size: 16px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | line-height: 16px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .member-name-box-2 { |
| | | padding: 0 20px; |
| | | padding-top: 40px; |
| | | display: grid; |
| | | grid-template-columns: repeat(4, 1fr); |
| | | align-items: flex-start; |
| | | flex-wrap: wrap; |
| | | gap: 20px; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .member-name { |
| | | width: 60px; |
| | | height: 60px; |
| | | background: #7D8B79; |
| | | border-radius: 50%; |
| | | text-align: center; |
| | | line-height: 60px; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | .member-edit { |
| | | cursor: pointer; |
| | | position: absolute; |
| | | bottom: 10px; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #FF4D4F; |
| | | line-height: 22px; |
| | | width: 40px; |
| | | background: #FFF1F0; |
| | | border-radius: 4px; |
| | | border: 1px solid #FFCCC7; |
| | | text-align: center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .add-project-footer { |
| | | display: flex; |
| | | gap: 20px; |
| | | margin-top: 43px; |
| | | |
| | | button { |
| | | width: 220px; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="实验编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="实验名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </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> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</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> |
| | | <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="状态"> |
| | | <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> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </TableCustom> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | export default { |
| | | name: 'TesterWorkerEvaluate', |
| | | data() { |
| | | return { |
| | | currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱 |
| | | form: { |
| | | }, |
| | | tableData: [], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | } |
| | | }, |
| | | methods: { |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: '/deliveryAssessment/addTesterWorkerEvaluate' |
| | | }) |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleTypeChange(type) { |
| | | this.currentType = type; |
| | | this.getList(); |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | |
| | | .table-title { |
| | | width: 220px; |
| | | height: 50px; |
| | | background: #FFFFFF; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049C9A; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049C9A; |
| | | line-height: 27px; |
| | | } |
| | | |
| | | .expand-box { |
| | | padding: 20px; |
| | | background: linear-gradient(180deg, #049C9A 0%, #0ACBCA 100%); |
| | | border-radius: 20px; |
| | | |
| | | &-title { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | line-height: 24px; |
| | | margin-bottom: 20px; |
| | | } |
| | | } |
| | | |
| | | .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; |
| | | border: 1px solid #dcdfe6; |
| | | padding: 16px 29px; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | width: unset; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .drafts { |
| | | padding: 16px 65px; |
| | | background: #fafafc; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #dcdfe6; |
| | | font-weight: 400; |
| | | font-size: 18px; |
| | | color: #606266; |
| | | margin-left: 16px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .active { |
| | | color: #049c9a; |
| | | background: #ffffff; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049c9a; |
| | | } |
| | | } |
| | | </style> |
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" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="content-box"> |
| | | <el-row :gutter="16"> |
| | | <el-col style="margin-top: 5px;" :xs="24" :sm="24" :md="24" :lg="24" :xl="24"> |
| | | <Table :total="0" :height="null" :data="criteriaList" show-summary :summary-method="getSummaries" |
| | | :span-method="arraySpanMethod"> |
| | | <el-table-column type="index" label="序号" width="80" /> |
| | | <el-table-column prop="criteria" label="规程型课题评定标准" /> |
| | | <el-table-column prop="fullScore" label="满分值" width="100" /> |
| | | <el-table-column label="评定分值" prop="score" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-input-number v-model="row.score" :min="0" :max="row.fullScore" :step="1" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="rule" label="创新型课题报告评分规则"> |
| | | <template> |
| | | <div> |
| | | <div>1、规程型课题评定总分的满分为5分。</div> |
| | | <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div> |
| | | <div>①有缺项、漏项;</div> |
| | | <div>②或不完整清晰;</div> |
| | | <div>③或工作效率人为拖延。</div> |
| | | <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="assessed"> |
| | | <div>评定时间:2025-2-20 11:08:00</div> |
| | | <div>评定人:张三</div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'AssessmentDialog', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | reportData: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | form: { |
| | | reportNo: '', |
| | | reportName: '', |
| | | }, |
| | | rules: { |
| | | reportName: [ |
| | | { required: true, message: '请输入报告名称', trigger: 'blur' } |
| | | ], |
| | | }, |
| | | criteriaList: [ |
| | | { |
| | | criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范', |
| | | fullScore: 1, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;', |
| | | fullScore: 2, |
| | | score: 0, |
| | | }, |
| | | { |
| | | criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。', |
| | | fullScore: 3, |
| | | score: 0, |
| | | }, |
| | | ] |
| | | } |
| | | }, |
| | | watch: { |
| | | modelValue: { |
| | | handler(val) { |
| | | this.dialogVisible = val; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | reportData: { |
| | | handler(val) { |
| | | if (val) { |
| | | this.form.reportNo = val.reportNo || ''; |
| | | this.form.reportName = val.reportName || ''; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit('update:modelValue', false); |
| | | }, |
| | | async handleSubmit() { |
| | | try { |
| | | await this.$refs.formRef.validate(); |
| | | const totalScore = this.criteriaList.reduce((sum, item) => sum + (item.score || 0), 0); |
| | | const assessmentData = { |
| | | ...this.form, |
| | | totalScore, |
| | | criteriaScores: this.criteriaList.map(item => ({ |
| | | criteria: item.criteria, |
| | | score: item.score || 0 |
| | | })) |
| | | }; |
| | | this.$emit('submit', assessmentData); |
| | | this.handleClose(); |
| | | } catch (error) { |
| | | // 表单验证失败 |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = '合计'; |
| | | return; |
| | | } |
| | | const values = data.map(item => Number(item[column.property])); |
| | | if (!values.every(value => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => { |
| | | const value = Number(curr); |
| | | if (!isNaN(value)) { |
| | | return prev + curr; |
| | | } else { |
| | | return prev; |
| | | } |
| | | }, 0); |
| | | sums[index] += ' 分'; |
| | | } else { |
| | | sums[index] = ''; |
| | | } |
| | | }); |
| | | return sums; |
| | | }, |
| | | arraySpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 4 && rowIndex == 0) { |
| | | return { |
| | | rowspan: 6, |
| | | colspan: 1 |
| | | } |
| | | } else if (rowIndex !== 0 && columnIndex === 4) { |
| | | return [0, 0] |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .content-box { |
| | | |
| | | &-left { |
| | | margin-top: 5px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 8px 8px 0px 0px; |
| | | font-size: 12px; |
| | | |
| | | &-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> |
New file |
| | |
| | | <template> |
| | | <div class="list"> |
| | | <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> |
| | | <el-form-item label="检测项名称:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="检测项编号:"> |
| | | <el-input v-model="form.name" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态:"> |
| | | <el-select v-model="form.name" placeholder="请选择" /> |
| | | </el-form-item> |
| | | <el-form-item class="search-btn-box"> |
| | | <el-button>重置</el-button> |
| | | <el-button type="primary">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | <template #setting> |
| | | <div class="table-title"> |
| | | 项目检查项、检验包 |
| | | </div> |
| | | </template> |
| | | <template #tableCustom> |
| | | <Table :data="tableData" :total="0" @row-click="handleRowClick" row-key="id" |
| | | :expand-row-keys="expandRowKeys"> |
| | | <el-table-column type="expand" width="1"> |
| | | <template #default="{ row }"> |
| | | <div class="expand-box"> |
| | | <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="状态"> |
| | | <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">详情</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="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> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="age" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="assessmentVisible = true">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | </template> |
| | | </TableCustom> |
| | | |
| | | <AssessmentDialog :modelValue="assessmentVisible" :reportData="currentReport" |
| | | @submit="handleAssessmentSubmit" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AssessmentDialog from './components/AssessmentDialog.vue' |
| | | |
| | | export default { |
| | | name: 'TestingAndEvaluation', |
| | | components: { |
| | | AssessmentDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | }, |
| | | tableData: [{ id: 1 }, { id: 2 }], |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1 |
| | | }, |
| | | total: 0, |
| | | assessmentVisible: false, |
| | | currentReport: {}, |
| | | expandRowKeys: [] |
| | | } |
| | | }, |
| | | methods: { |
| | | handleRowClick(row, column, event) { |
| | | if (column.label === '操作') return |
| | | if (this.expandRowKeys.includes(row.id)) { |
| | | this.expandRowKeys = this.expandRowKeys.filter(key => key !== row.id); |
| | | } else { |
| | | this.expandRowKeys.push(row.id); |
| | | } |
| | | }, |
| | | handleCurrentChange(page) { |
| | | this.queryForm.pageNum = page |
| | | this.getList() |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.queryForm.pageSize = size |
| | | this.getList() |
| | | }, |
| | | getList() { |
| | | |
| | | }, |
| | | handleDetail(row) { |
| | | // 处理详情 |
| | | }, |
| | | handleAssessment(row) { |
| | | this.currentReport = row; |
| | | this.assessmentVisible = true; |
| | | }, |
| | | handleAssessmentSubmit(data) { |
| | | console.log('评定提交数据:', data); |
| | | // 处理评定提交 |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .list { |
| | | height: 100%; |
| | | } |
| | | |
| | | .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'; |
| | | font-size: 14px; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | &-num { |
| | | font-family: 'SF Compact Display Black'; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | font-size: 50px; |
| | | color: #049C9A; |
| | | line-height: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tip-warring { |
| | | margin-top: 20px; |
| | | color: rgba(255, 73, 85, 1); |
| | | } |
| | | |
| | | .table-title { |
| | | width: 220px; |
| | | height: 50px; |
| | | background: #FFFFFF; |
| | | border-radius: 8px 8px 0px 0px; |
| | | border: 1px solid #049C9A; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-family: SourceHanSansCN, SourceHanSansCN; |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | color: #049C9A; |
| | | line-height: 27px; |
| | | } |
| | | |
| | | .expand-box { |
| | | padding: 20px; |
| | | background: linear-gradient(180deg, #049C9A 0%, #0ACBCA 100%); |
| | | border-radius: 20px; |
| | | |
| | | &-title { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | line-height: 24px; |
| | | margin-bottom: 20px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | |