| | |
| | | "core-js": "^3.41.0", |
| | | "element-ui": "^2.15.6", |
| | | "moment": "^2.30.1", |
| | | "dayjs": "^1.11.0", |
| | | "sm-crypto": "^0.3.13", |
| | | "vue": "^2.7.16", |
| | | "vue-router": "^3.6.5", |
| | |
| | | "devDependencies": { |
| | | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", |
| | | "@babel/preset-env": "^7.26.9", |
| | | "@vue/cli-plugin-babel": "~4.5.0",7 |
| | | "@vue/cli-plugin-babel": "~4.5.0", |
| | | "@vue/cli-plugin-eslint": "~4.5.0", |
| | | "@vue/cli-plugin-router": "^4.5.15", |
| | | "@vue/cli-service": "~4.5.0", |
| | | "autoprefixer": "^9.8.8", |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="添加表数据" |
| | | :title="isEdit? '编辑表数据' : '添加表数据'" |
| | | :visible.sync="dialogVisible" |
| | | width="60%" |
| | | :close-on-click-modal="false" |
| | |
| | | componentData = { fileList: component.data }; |
| | | break; |
| | | case 'imageUpload': |
| | | componentData = { imageList: component.data }; |
| | | componentData = { imageList: component.data.map(item=>{ |
| | | return { |
| | | ...item, |
| | | url: getFullUrl(item.url), |
| | | } |
| | | }) }; |
| | | break; |
| | | } |
| | | return { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { customUploadRequest, getFullUrl } from '@/utils/utils' |
| | | import {editSignPicture} from './service' |
| | | export default { |
| | | name: 'SignatureCanvas', |
| | | props: { |
| | |
| | | this.drawDashedBorder() |
| | | }, |
| | | |
| | | // 新增:base64转blob |
| | | dataURLtoBlob(dataurl) { |
| | | const arr = dataurl.split(','); |
| | | const mime = arr[0].match(/:(.*?);/)[1]; |
| | | const bstr = atob(arr[1]); |
| | | let n = bstr.length; |
| | | const u8arr = new Uint8Array(n); |
| | | while (n--) { |
| | | u8arr[n] = bstr.charCodeAt(n); |
| | | } |
| | | return new Blob([u8arr], { type: mime }); |
| | | }, |
| | | |
| | | // 修改:确认签名时上传图片 |
| | | confirmSignature() { |
| | | const canvas = this.$refs.signatureCanvas |
| | | const ctx = this.context |
| | | |
| | | const canvas = this.$refs.signatureCanvas; |
| | | const ctx = this.context; |
| | | // 保存当前画布内容 |
| | | const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) |
| | | |
| | | const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); |
| | | // 先填充背景色 |
| | | ctx.fillStyle = 'rgba(239, 248, 250, 1)' |
| | | ctx.fillRect(0, 0, canvas.width, canvas.height) |
| | | |
| | | ctx.fillStyle = 'rgba(239, 248, 250, 1)'; |
| | | ctx.fillRect(0, 0, canvas.width, canvas.height); |
| | | // 创建一个临时画布来保存签名内容 |
| | | const tempCanvas = document.createElement('canvas') |
| | | tempCanvas.width = canvas.width |
| | | tempCanvas.height = canvas.height |
| | | const tempCtx = tempCanvas.getContext('2d') |
| | | tempCtx.putImageData(imageData, 0, 0) |
| | | |
| | | const tempCanvas = document.createElement('canvas'); |
| | | tempCanvas.width = canvas.width; |
| | | tempCanvas.height = canvas.height; |
| | | const tempCtx = tempCanvas.getContext('2d'); |
| | | tempCtx.putImageData(imageData, 0, 0); |
| | | // 将签名内容绘制到主画布上 |
| | | ctx.drawImage(tempCanvas, 0, 0) |
| | | |
| | | // 导出图片 |
| | | const signatureImage = canvas.toDataURL('image/png') |
| | | this.$emit('confirm', signatureImage) |
| | | ctx.drawImage(tempCanvas, 0, 0); |
| | | // 导出图片为base64 |
| | | const base64Data = canvas.toDataURL('image/png'); |
| | | // base64转blob |
| | | const blob = this.dataURLtoBlob(base64Data); |
| | | // 新增:生成带时间戳的文件名 |
| | | const timestamp = Date.now(); |
| | | const fileName = `signature_${timestamp}.png`; |
| | | const file = new File([blob], fileName, { type: blob.type }); |
| | | // 上传 |
| | | customUploadRequest({ |
| | | file, |
| | | onSuccess: (res) => { |
| | | // 假设返回的图片路径为 res.url |
| | | const url = res.msg || res.data || res |
| | | editSignPicture({signPicture:res.msg}).then(res=>{ |
| | | if(res.code==200){ |
| | | this.$message.success('签名成功'); |
| | | this.$emit('confirm', url); |
| | | } |
| | | }) |
| | | }, |
| | | onError: (err) => { |
| | | this.$message && this.$message.error ? this.$message.error('上传签名失败') : alert('上传签名失败'); |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | beforeDestroy() { |
New file |
| | |
| | | import axios from '@/utils/request'; |
| | | |
| | | // 列表 |
| | | export const editSignPicture = (data) => { |
| | | return axios.post('/api/system/user/editSignPicture', { ...data }) |
| | | } |
| | | export const queryDetail = (data) => { |
| | | return axios.get('/system/user/queryDetail',) |
| | | } |
| | |
| | | import './assets/tailwind.css' |
| | | import './styles/element-variables.less' |
| | | |
| | | import dayjs from "../node_modules/dayjs/dayjs.min.js"; |
| | | import "dayjs/locale/zh-cn"; |
| | | |
| | | dayjs.locale("zh-cn"); |
| | | |
| | | |
| | | |
| | |
| | | keepAlive: true, ------是否缓存 |
| | | } |
| | | */ |
| | | console.log('222222222222222222222',JSON.parse(sessionStorage.getItem('userInfo')).roleType=='5') |
| | | |
| | | const routes = [{ |
| | | path: "/", |
| | |
| | | title: "样品管理", |
| | | keepAlive: true, |
| | | privilege:'sampleManage', |
| | | hide:JSON.parse(sessionStorage.getItem('userInfo')).roleType=='5'?true:false, |
| | | hide:JSON.parse(sessionStorage.getItem('userInfo'))&&JSON.parse(sessionStorage.getItem('userInfo')).roleType=='5'?true:false, |
| | | // privilege:'sampleManage_manage' |
| | | }, |
| | | component: () => import("../views/dataManagement/sampleManage/list.vue"), |
| | |
| | | const submitData = { |
| | | dispatchId: this.selectedScheduling.id, // 实验调度ID |
| | | auditStatus: 1, // 待确认状态 |
| | | confirmSign: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg' || signatureImage, // 签字图片 |
| | | confirmSign: signatureImage, // 签字图片 |
| | | signTime: new Date().toISOString(), // 签字时间 |
| | | testMethodConfirmSheetTerms: this.testItems.map(item => ({ |
| | | id: item.id, // 保留原有ID(编辑时使用) |
| | |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | @open='open' |
| | | class="submit-confirm-dialog" |
| | | > |
| | | <div class="approval-content"> |
| | |
| | | <el-button type="primary" @click="openSignature">签名</el-button> |
| | | </div> |
| | | <div v-if="imgSrc" class="signature-preview"> |
| | | <img :src="imgSrc" alt="签名" /> |
| | | <img :src="getFullUrl(imgSrc)" alt="签名" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | import {queryDetail} from '@/components/service.js' |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | |
| | | |
| | | export default { |
| | | name: "ConfirmDialog", |
| | |
| | | }; |
| | | }, |
| | | methods: { |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | } |
| | | }) |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = ""; |
| | |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | this.imgSrc = imageData; |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | |
| | | this.$emit("confirm", this.imgSrc); |
| | | this.handleClose(); |
| | | }, |
| | | getFullUrl |
| | | }, |
| | | }; |
| | | </script> |
| | |
| | | <template> |
| | | <el-dialog title="审核检测方法确认单" :visible="dialogVisible" width="80%" :close-on-click-modal="false" @close="handleClose" |
| | | <el-dialog title="审核检测方法确认单" :visible="dialogVisible" width="80%" @open='open' :close-on-click-modal="false" @close="handleClose" |
| | | v-loading="loading"> |
| | | <div class="approval-dialog"> |
| | | <div class="approval-content"> |
| | |
| | | <span>签字确认</span> |
| | | <el-button type="primary" class="el-icon-plus" @click="openSignature">签名</el-button> |
| | | </div> |
| | | <img v-if="imgSrc" :src="imgSrc" alt="签名" class="signature-preview" /> |
| | | <img v-if="imgSrc" :src="getFullUrl(imgSrc)" alt="签名" class="signature-preview" /> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer"> |
| | |
| | | <el-button type="primary" @click="handleConfirm" :disabled="!imgSrc" v-if="type === 'review'">确 认</el-button> |
| | | </div> |
| | | |
| | | <SignatureCanvas :visible="signatureDialogVisible" @confirm="handleSignatureConfirm" /> |
| | | <SignatureCanvas :visible="signatureDialogVisible" @close="signatureDialogVisible=false" @confirm="handleSignatureConfirm" /> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | import ApprovalProcess from "@/components/approvalProcess"; |
| | | import { getDetail, sign } from '../service'; |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | import {queryDetail} from '@/components/service.js' |
| | | |
| | | export default { |
| | | name: "ReviewDialog", |
| | |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | methods: {getFullUrl, |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | } |
| | | }) |
| | | }, |
| | | async getDetailData() { |
| | | try { |
| | | this.loading = true; |
| | | const res = await getDetail({ id: this.id }); |
| | | console.log('res', res) |
| | | if (res) { |
| | | this.formData = res |
| | | this.formData = { |
| | | ...res, |
| | | confirmSign: getFullUrl(res.confirmSign) |
| | | } |
| | | // 组装流程数据 |
| | | let processData = []; |
| | | // 提交节点 |
| | |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "提交人:", value: res.createBy || "" }, |
| | | { label: ' ', value: res.confirmSign || "", type: 'img' }, |
| | | { label: ' ', value: getFullUrl(res.confirmSign) || "", type: 'img' }, |
| | | { label: "提交时间:", value: res.createTime || "" }, |
| | | ], |
| | | }); |
| | |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "审核人:", value: res.auditPersonName || "" }, |
| | | { label: ' ', value: res.auditSign || "", type: 'img' }, |
| | | { label: ' ', value: getFullUrl(res.auditSign) || "", type: 'img' }, |
| | | { label: "审核时间:", value: res.auditTime || "" }, |
| | | ], |
| | | }); |
| | |
| | | }, |
| | | handleClose() { |
| | | this.dialogVisible = false; |
| | | this.signatureDialogVisible=false |
| | | this.$emit("close", false); |
| | | this.imgSrc = ""; |
| | | this.formData = { |
| | |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | this.imgSrc = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'; |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | |
| | | :title="dialogTitle" |
| | | :visible.sync="visible" |
| | | width="80%" |
| | | @open='open' |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | :src="getFullUrl(imgSrc)" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | import AIEditor from "@/components/AiEditor"; |
| | | import { getDetailById, sign } from "./service"; |
| | | import {queryDetail} from '@/components/service.js' |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | |
| | | }, |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | console.log('1111111111',getFullUrl(this.imgSrc),res.signPicture) |
| | | } |
| | | }) |
| | | }, |
| | | // 获取详情 |
| | | getDetail(id) { |
| | | getDetailById({ id }) |
| | |
| | | <el-image |
| | | v-for="(url, index) in scope.row.pictures.split(',')" |
| | | :key="index" |
| | | src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" |
| | | :preview-src-list="[url]" |
| | | :src="getFullUrl(url)" |
| | | :preview-src-list="[getFullUrl(url)]" |
| | | style="width: 50px; height: 50px;" |
| | | /> |
| | | </template> |
| | |
| | | import addTime from "./components/addTime.vue"; |
| | | import ReceiveConfirmDialog from "./components/receiveConfirmDialog.vue"; |
| | | import { add, getDetail, update, batchCollectSamples } from "./service"; |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | |
| | | export default { |
| | | name: "AddSample", |
| | |
| | | }, |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | // 获取详情数据 |
| | | async getDetailData(id) { |
| | | try { |
| | | const res = await getDetail({ id }); |
| | | if (res) { |
| | | const detail = res; |
| | | console.log('获取到的详情数据:', detail); |
| | | |
| | | // 设置表单数据 |
| | | this.form = { |
| | | ...this.form, |
| | |
| | | } |
| | | |
| | | // 如果是详情模式,禁用所有输入 |
| | | if (this.pageType == 'detail') { |
| | | this.$nextTick(() => { |
| | | const inputs = document.querySelectorAll('input, textarea, select'); |
| | | inputs.forEach(input => { |
| | | input.disabled = true; |
| | | }); |
| | | }); |
| | | } |
| | | // if (this.pageType == 'detail') { |
| | | // this.$nextTick(() => { |
| | | // const inputs = document.querySelectorAll('input, textarea, select'); |
| | | // inputs.forEach(input => { |
| | | // input.disabled = true; |
| | | // }); |
| | | // }); |
| | | // } |
| | | } |
| | | } catch (error) { |
| | | console.error('获取详情失败:', error); |
| | |
| | | }; |
| | | |
| | | // 打印提交数据 |
| | | console.log('草稿提交数据:', submitData); |
| | | |
| | | let res; |
| | | if (this.pageType == 'edit') { |
| | | // 编辑模式调用update接口 |
| | |
| | | } |
| | | }, |
| | | handlePendingSelectionChange(selection) { |
| | | console.log("pending selection change:", selection); |
| | | console.log("pending samples data:", this.pendingSamples); |
| | | this.selectedSamples = selection; |
| | | // 强制更新视图 |
| | |
| | | }, |
| | | confirmReceive(signature) { |
| | | // 获取选中样品的ID并拼接 |
| | | const recordOperationIds = this.selectedSamples.map(item => item.id).join(','); |
| | | const recordOperationIds = this.selectedSamples.map(item => item.id); |
| | | |
| | | // 调用批量收样接口 |
| | | batchCollectSamples({ |
| | |
| | | |
| | | }, |
| | | isSelectable(row) { |
| | | console.log('isSelectable row:', row); |
| | | console.log('row status:', row.status, typeof row.status); |
| | | const result = String(row.status) == '2'; |
| | | console.log('isSelectable result:', result); |
| | | return result; |
| | | }, |
| | | }, |
| | |
| | | title="接收签字确认" |
| | | :visible.sync="visible" |
| | | width="500px" |
| | | @open="open" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | :src="getFullUrl(imgSrc)" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | |
| | | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | import {queryDetail} from '@/components/service.js' |
| | | |
| | | export default { |
| | | name: "ReceiveConfirmDialog", |
| | |
| | | }; |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | } |
| | | }) |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = ""; |
| | |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | // this.imgSrc = imageData; |
| | | this.imgSrc = 'https://img.yzcdn.cn/vant/ipad.png'; |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | |
| | | <el-image |
| | | v-for="(url, index) in scope.row.pictures.split(',')" |
| | | :key="index" |
| | | :src="url" |
| | | :preview-src-list="[url]" |
| | | :src="getFullUrl(url)" |
| | | :preview-src-list="[getFullUrl(url)]" |
| | | style="width: 50px; height: 50px;" |
| | | /> |
| | | </template> |
| | |
| | | import ConfirmDialog from './components/confirmDialog.vue'; |
| | | import { getDetail, add, update, commitRecord } from './service'; |
| | | import moment from 'moment'; |
| | | import { getFullUrl } from '@/utils/utils' |
| | | |
| | | export default { |
| | | name: "ChangeRecord", |
| | |
| | | } |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | async getDetailData() { |
| | | try { |
| | | const res = await getDetail({ id: this.id }); |
| | |
| | | title="提交确认" |
| | | :visible.sync="visible" |
| | | width="80%" |
| | | @open='open' |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | :src="getFullUrl(imgSrc)" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | import moment from 'moment'; |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | import {queryDetail} from '@/components/service.js' |
| | | |
| | | export default { |
| | | name: "ConfirmDialog", |
| | |
| | | data() { |
| | | return { |
| | | signatureDialogVisible: false, |
| | | imgSrc: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg", |
| | | imgSrc: "", |
| | | showAdditives: true, |
| | | }; |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | } |
| | | }) |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"; |
| | | this.imgSrc = ""; |
| | | }, |
| | | openSignature() { |
| | | this.signatureDialogVisible = true; |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | this.imgSrc = imageData; |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | |
| | | > |
| | | <el-upload |
| | | class="upload-demo" |
| | | action="#" |
| | | :action="uploadUrl" |
| | | :headers="uploadHeaders" |
| | | :file-list="fileList" |
| | | :auto-upload="false" |
| | | :auto-upload="true" |
| | | list-type="picture-card" |
| | | :on-change="handleChange" |
| | | :on-remove="handleRemove" |
| | | :before-upload="beforeUpload" |
| | | :on-change="handleImageChange" |
| | | :on-remove="handleImageRemove" |
| | | :on-success="handleImageSuccess" |
| | | :on-preview="handlePreview" |
| | | multiple |
| | | > |
| | | <i class="el-icon-plus"></i> |
| | |
| | | |
| | | <script> |
| | | import { updateRecordOperation } from '../service' |
| | | import { getFullUrl } from '@/utils/utils'; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | |
| | | export default { |
| | | name: "SampleDialog", |
| | |
| | | { required: true, message: "请输入加水量", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | uploadUrl: apiConfig.imgUrl, |
| | | uploadHeaders: { |
| | | Authorization: sessionStorage.getItem('token') || '' |
| | | }, |
| | | fileList: [], |
| | | defaultImage: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', |
| | | }; |
| | | }; |
| | | }, |
| | | watch: { |
| | | data: { |
| | |
| | | const imageUrls = val.pictures.split(','); |
| | | this.fileList = imageUrls.map((url, index) => ({ |
| | | name: `sample-image-${index + 1}.png`, |
| | | url: url |
| | | url: getFullUrl(url), |
| | | status: 'success', |
| | | })); |
| | | } else { |
| | | this.fileList = []; |
| | | } |
| | | } |
| | | }, |
| | |
| | | this.form = this.$options.data().form; |
| | | this.fileList = []; |
| | | }, |
| | | // 上传前校验 |
| | | beforeUpload(file) { |
| | | const isImage = file.type.startsWith('image/'); |
| | | const isLt2M = file.size / 1024 / 1024 < 2; |
| | | |
| | | if (!isImage) { |
| | | this.$message.error('只能上传图片文件!'); |
| | | return false; |
| | | } |
| | | if (!isLt2M) { |
| | | this.$message.error('图片大小不能超过 2MB!'); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | // 文件状态改变时的钩子 |
| | | handleChange(file, fileList) { |
| | | handleImageChange(file, fileList) { |
| | | this.fileList = fileList; |
| | | |
| | | // 更新pictures字段 |
| | | if (fileList.length === 0) { |
| | | this.form.pictures = this.defaultImage; |
| | | } else { |
| | | const imageUrls = fileList.map(file => file.url || this.defaultImage); |
| | | this.form.pictures = imageUrls.join(','); |
| | | // 只在移除时处理form.pictures,上传成功时在handleImageSuccess处理 |
| | | if (file.status === 'removed') { |
| | | const urls = fileList.map(f => f.url).filter(Boolean); |
| | | this.form.pictures = urls.join(','); |
| | | } |
| | | }, |
| | | // 移除文件时的钩子 |
| | | handleRemove(file, fileList) { |
| | | handleImageSuccess(res, file, fileList) { |
| | | // res.msg为图片url |
| | | const url = res.msg; |
| | | file.url = getFullUrl(url); |
| | | // 更新fileList中对应file的url |
| | | this.fileList = fileList.map(f => { |
| | | if (f.uid === file.uid) { |
| | | return file; |
| | | } |
| | | return f; |
| | | }); |
| | | // 更新form.pictures |
| | | const urls = this.fileList.map(f => f.url).filter(Boolean); |
| | | this.form.pictures = urls.join(','); |
| | | }, |
| | | handleImageRemove(file, fileList) { |
| | | this.fileList = fileList; |
| | | |
| | | // 更新pictures字段 |
| | | if (fileList.length === 0) { |
| | | this.form.pictures = this.defaultImage; |
| | | } else { |
| | | const imageUrls = fileList.map(file => file.url || this.defaultImage); |
| | | this.form.pictures = imageUrls.join(','); |
| | | } |
| | | const urls = fileList.map(f => f.url).filter(Boolean); |
| | | this.form.pictures = urls.join(','); |
| | | }, |
| | | handlePreview(file) { |
| | | this.$alert(`<img src='${file.url}' style='width:100%' />`, '图片预览', { |
| | | dangerouslyUseHTMLString: true |
| | | }); |
| | | }, |
| | | async handleSubmit() { |
| | | this.$refs.form.validate(async (valid) => { |
| | | if (valid) { |
| | | // 处理图片路径为相对路径 |
| | | let pictures = this.form.pictures; |
| | | if (pictures) { |
| | | const prefix = apiConfig.showImgUrl; |
| | | pictures = pictures.split(',').map(url => { |
| | | return url.startsWith(prefix) ? url.substring(prefix.length) : url; |
| | | }).join(','); |
| | | } |
| | | const submitData = { |
| | | ...this.form, |
| | | pictures, |
| | | handlePersonId: JSON.parse(sessionStorage.getItem('userInfo') || '{}').userId || "", |
| | | handlePersonName: JSON.parse(sessionStorage.getItem('userInfo') || '{}').nickName || "", |
| | | fileList: this.fileList, |
| | | }; |
| | | |
| | | try { |
| | | // 先调用updateRecordOperation接口保存数据 |
| | | const res = await updateRecordOperation(submitData); |
| | |
| | | :visible.sync="visible" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | @open='open' |
| | | @close="handleClose" |
| | | > |
| | | <div class="receive-dialog"> |
| | |
| | | <img |
| | | v-if="imgSrc" |
| | | style="width: 200px; height: 100px; margin-left: 25px" |
| | | :src="imgSrc" |
| | | :src="getFullUrl(imgSrc)" |
| | | fit="fit" |
| | | /> |
| | | </div> |
| | |
| | | |
| | | <script> |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue"; |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | import {queryDetail} from '@/components/service.js' |
| | | |
| | | export default { |
| | | name: "ReceiveConfirmDialog", |
| | |
| | | }; |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | } |
| | | }) |
| | | }, |
| | | handleClose() { |
| | | this.$emit("update:visible", false); |
| | | this.imgSrc = ""; |
| | |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureDialogVisible = false; |
| | | // this.imgSrc = imageData; |
| | | this.imgSrc = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'; |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | handleConfirm() { |
| | | if (!this.imgSrc) { |
| | | this.$message.warning("请先完成签名确认"); |
| | | return; |
| | | } |
| | | const defaultSignature = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'; |
| | | this.$emit("confirm", this.imgSrc || defaultSignature); |
| | | this.$emit("confirm", this.imgSrc); |
| | | this.handleClose(); |
| | | }, |
| | | }, |
| | |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getGroupByDispatchId, getParticipantsByDispatchId, getDetail } from "./service"; |
| | | import moment from 'moment'; |
| | | import { add,update } from "./service"; |
| | | import { add,update,updateTester } from "./service"; |
| | | |
| | | export default { |
| | | name: "AddProject", |
| | |
| | | this.userRole=userInfo.roleType || ''; |
| | | // 检查是否为编辑模式 |
| | | if (this.$route.query.type === 'edit' && this.$route.query.id) { |
| | | this.isEdit = true; |
| | | this.isEdit = this.userRole==3?false:true; |
| | | this.editId = this.$route.query.id; |
| | | await this.loadEditData(); |
| | | } |
| | |
| | | formData.experimentMaterial = JSON.stringify(this.form.experimentMaterial); |
| | | |
| | | // 编辑模式下添加id参数 |
| | | if (this.isEdit && this.editId) { |
| | | if (this.editId) { |
| | | formData.id = this.editId; |
| | | } |
| | | |
| | | // 根据是否为编辑模式调用不同接口 |
| | | const apiCall = this.isEdit ? update(formData) : add(formData); |
| | | const apiCall = this.editId ? update(formData) : this.isEdit? updateTester(formData): add(formData); |
| | | |
| | | apiCall.then(res => { |
| | | if (res.code === 200) { |
| | | this.$message.success(status === 1 ? '保存成功' : '草稿保存成功'); |
| | | if (status === 1) { |
| | | this.$router.go(-1); |
| | | } |
| | | this.$router.go(-1); |
| | | } else { |
| | | this.$message.error(res.msg || (status === 1 ? '保存失败' : '草稿保存失败')); |
| | | } |
| | |
| | | // 填充实验调度信息 |
| | | if (data.experimentDispatch?.id) { |
| | | this.form.dispatchId = data.experimentDispatch.id; |
| | | console.log('experimentStepRecord experimentStepRecord',JSON.parse(data.experimentStepRecord)) |
| | | this.groupTableData = [{ ...data.experimentDispatch }]; |
| | | |
| | | // 获取组别信息 |
| | |
| | | } |
| | | |
| | | // 设置动态组件的初始数据 |
| | | if (!this.isEdit) { |
| | | if (this.$refs.materialComponent && this.form.experimentMaterial) { |
| | | this.$refs.materialComponent.setInitialData(this.form.experimentMaterial); |
| | | } |
| | | if (this.$refs.equipmentComponent && this.form.experimentDevice) { |
| | | this.$refs.equipmentComponent.setInitialData(this.form.experimentDevice); |
| | | } |
| | | // if (!this.isEdit) { |
| | | // // if (this.$refs.materialComponent && this.form.experimentMaterial) { |
| | | // // this.$refs.materialComponent.setInitialData(this.form.experimentMaterial); |
| | | // // } |
| | | // // if (this.$refs.equipmentComponent && this.form.experimentDevice) { |
| | | // // this.$refs.equipmentComponent.setInitialData(this.form.experimentDevice); |
| | | // // } |
| | | |
| | | // 设置步骤内容的初始数据 |
| | | this.stepList.forEach((step, index) => { |
| | | const stepContentRef = this.$refs['stepContent' + index]; |
| | | if (stepContentRef && step.content) { |
| | | const editor = Array.isArray(stepContentRef) ? stepContentRef[0] : stepContentRef; |
| | | if (editor?.setInitialData) { |
| | | editor.setInitialData(step.content); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | // // 设置步骤内容的初始数据 |
| | | // this.stepList.forEach((step, index) => { |
| | | // const stepContentRef = this.$refs['stepContent' + index]; |
| | | // if (stepContentRef && step.content) { |
| | | // const editor = Array.isArray(stepContentRef) ? stepContentRef[0] : stepContentRef; |
| | | // if (editor?.setInitialData) { |
| | | // editor.setInitialData(step.content); |
| | | // } |
| | | // } |
| | | // }); |
| | | // } |
| | | }); |
| | | |
| | | } catch (error) { |
| | |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="250"> |
| | | <template slot-scope="scope"> |
| | | <!-- 超级管理员(1)和审批人(2) --> |
| | | <template v-if="userRole == '1' || userRole == '2'"> |
| | | <!-- 草稿箱模式下,只显示编辑和详情 --> |
| | | <template v-if="currentType === 'draft'"> |
| | | <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | |
| | | <!-- 工艺工程师(3) --> |
| | | <template v-if="userRole == '3'"> |
| | | <!-- <el-button type="text" @click="handleEdit(scope.row)" >编辑</el-button> --> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | |
| | | <!-- 实验员(5) --> |
| | | <template v-if="userRole == '5'"> |
| | | <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == 1">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" v-if="scope.row.status == 6">详情</el-button> |
| | | <!-- 非草稿箱,按原有角色逻辑 --> |
| | | <template v-else> |
| | | <!-- 超级管理员(1)和审批人(2) --> |
| | | <template v-if="userRole == '1' || userRole == '2'"> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | <!-- 工艺工程师(3) --> |
| | | <template v-if="userRole == '3'"> |
| | | <el-button type="text" @click="handleDetail(scope.row)">详情</el-button> |
| | | </template> |
| | | <!-- 实验员(5) --> |
| | | <template v-if="userRole == '5'"> |
| | | <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == 1">编辑</el-button> |
| | | <el-button type="text" @click="handleDetail(scope.row)" v-if="scope.row.status == 6">详情</el-button> |
| | | </template> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | return axios.post('/api/t-experiment-scheme/add', { ...data }) |
| | | } |
| | | //修改 |
| | | export const update = (data) => { |
| | | export const updateTester = (data) => { |
| | | return axios.post('/api/t-experiment-scheme/updateTester', { ...data }) |
| | | } |
| | | //修改 |
| | | export const update = (data) => { |
| | | return axios.post('/api/t-experiment-scheme/update', { ...data }) |
| | | } |
| | | //删除 |
| | | export const deleteById = (data) => { |
| | | return axios.delete('/open/t-experiment-scheme/deleteById', { params:data }) |
| | |
| | | </div> |
| | | <img |
| | | v-if="imgSrc" |
| | | :src="imgSrc" |
| | | :src="getFullUrl(imgSrc)" |
| | | alt="签名" |
| | | class="signature-preview" |
| | | /> |
| | |
| | | |
| | | <SignatureCanvas |
| | | :visible="signatureCanvasVisible" |
| | | @close="signatureCanvasVisible=false" |
| | | @confirm="handleSignatureConfirm" |
| | | /> |
| | | </Card> |
| | |
| | | import AiEditor from '@/components/AiEditor' |
| | | import SignatureCanvas from "@/components/SignatureCanvas.vue" |
| | | import { getDetail, applicationTermination } from './service' |
| | | import {queryDetail} from '@/components/service.js' |
| | | import {getFullUrl} from '@/utils/utils.js' |
| | | |
| | | export default { |
| | | name: 'StopExperiment', |
| | |
| | | this.id = this.$route.query.id |
| | | if (this.id) { |
| | | this.getExperimentDetail() |
| | | this.open() |
| | | } else { |
| | | this.$message.error('参数错误,缺少实验ID') |
| | | } |
| | | }, |
| | | methods: { |
| | | getFullUrl, |
| | | open(){ |
| | | queryDetail().then(res=>{ |
| | | if(res){ |
| | | this.imgSrc=res.signPicture |
| | | } |
| | | }) |
| | | }, |
| | | // 获取实验详情 |
| | | async getExperimentDetail() { |
| | | try { |
| | |
| | | this.$message.warning('未获取到实验详情') |
| | | } |
| | | } catch (error) { |
| | | console.error('获取实验详情失败:', error) |
| | | this.$message.error('获取实验详情失败') |
| | | } finally { |
| | | this.loading = false |
| | |
| | | }, |
| | | handleSignatureConfirm(imageData) { |
| | | this.signatureCanvasVisible = false |
| | | // this.imgSrc = imageData |
| | | this.imgSrc = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg' |
| | | this.imgSrc = ""; // 先清空 |
| | | this.$nextTick(() => { |
| | | this.imgSrc = imageData; |
| | | }); |
| | | }, |
| | | async handleConfirm() { |
| | | if (!this.imgSrc) { |
| | |
| | | stopFile: filePaths, // 中止文件路径,多个文件路径通过逗号拼接 |
| | | stopFileName: fileNames // 中止文件名称,多个文件名称通过逗号拼接 |
| | | } |
| | | |
| | | console.log('提交的数据:', formData) |
| | | |
| | | await applicationTermination(formData) |
| | | this.$message.success('提交成功') |
| | | this.handleDialogClose() |
| | | // 提交成功后返回列表页 |
| | | this.$router.go(-1) |
| | | } catch (error) { |
| | | console.error('提交失败:', error) |
| | | this.$message.error('提交失败') |
| | | } finally { |
| | | this.loading = false |