| | |
| | | value: { |
| | | handler(newVal) { |
| | | if (this.editor && newVal !== this.editor.getHtml()) { |
| | | this.editor.setContent(newVal) |
| | | const contentWithIp = this.addIpToContent(newVal); |
| | | this.editor.setContent(contentWithIp) |
| | | } |
| | | }, |
| | | immediate: true |
| | |
| | | this.destroyEditor() |
| | | }, |
| | | methods: { |
| | | // 去除内容中的IP地址,只保留相对路径 |
| | | removeIpFromContent(content) { |
| | | if (!content || typeof content !== 'string') return content; |
| | | |
| | | // 获取当前IP地址 |
| | | const currentIp = getAllocateIp(); |
| | | |
| | | // 使用正则表达式匹配并替换所有包含当前IP的URL |
| | | const ipRegex = new RegExp(currentIp.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'); |
| | | return content.replace(ipRegex, ''); |
| | | }, |
| | | |
| | | // 为内容中的相对路径添加IP地址,并处理已包含IP的绝对路径 |
| | | addIpToContent(content) { |
| | | if (!content || typeof content !== 'string') return content; |
| | | |
| | | // 获取当前IP地址 |
| | | const currentIp = getAllocateIp(); |
| | | |
| | | // 匹配所有src、href、poster属性 |
| | | const pathRegex = /(src|href|poster)="([^"]+)"/g; |
| | | |
| | | return content.replace(pathRegex, (match, attr, path) => { |
| | | // 如果路径是相对路径(不以http开头),则添加当前IP地址 |
| | | if (!path.startsWith('http')) { |
| | | // 检查路径是否已经以/images/开头,避免重复添加 |
| | | if (path.startsWith('/images/')) { |
| | | // 如果currentIp已经以/images/结尾,则去掉路径开头的/ |
| | | if (currentIp.endsWith('/images/')) { |
| | | return `${attr}="${currentIp}${path.substring(1)}"`; |
| | | } else { |
| | | return `${attr}="${currentIp}${path}"`; |
| | | } |
| | | } else { |
| | | return `${attr}="${currentIp}${path}"`; |
| | | } |
| | | } |
| | | |
| | | // 如果路径已经包含当前IP地址,直接返回 |
| | | if (path.startsWith(currentIp)) { |
| | | return match; |
| | | } |
| | | |
| | | // 如果路径是绝对路径,提取路径部分并替换为当前IP地址 |
| | | // 匹配形如 http://192.168.1.100:8080/xxx 的路径 |
| | | const absolutePathRegex = /^https?:\/\/[^\/]+(\/.*)$/; |
| | | const matchResult = path.match(absolutePathRegex); |
| | | |
| | | if (matchResult) { |
| | | // 提取路径部分,替换为当前IP地址 |
| | | let pathPart = matchResult[1]; |
| | | |
| | | // 如果currentIp已经以/images/结尾,且pathPart以/images/开头,则去掉pathPart开头的/images/ |
| | | if (currentIp.endsWith('/images/') && pathPart.startsWith('/images/')) { |
| | | pathPart = pathPart.substring(7); // 去掉开头的 '/images/' |
| | | // 如果pathPart以/开头,则去掉开头的/ |
| | | if (pathPart.startsWith('/')) { |
| | | pathPart = pathPart.substring(1); |
| | | } |
| | | } |
| | | |
| | | return `${attr}="${currentIp}${pathPart}"`; |
| | | } |
| | | |
| | | // 其他情况(如外部链接)保持不变 |
| | | |
| | | return match; |
| | | }); |
| | | }, |
| | | |
| | | initEditor() { |
| | | const options = { |
| | | element: this.$refs.editorRef, |
| | | placeholder: this.placeholder, |
| | | content: this.value, |
| | | content: this.addIpToContent(this.value), |
| | | editable: !this.readOnly, |
| | | toolbar: this.toolbar, |
| | | toolbarExcludeKeys: ["ai"], |
| | | draggable: false, |
| | | onChange: (content) => { |
| | | this.$emit('input', content) |
| | | this.$emit('change', content) |
| | | // 确保content是字符串类型 |
| | | const contentStr = typeof content === 'string' ? content : String(content || ''); |
| | | const contentWithoutIp = this.removeIpFromContent(contentStr); |
| | | this.$emit('input', contentWithoutIp) |
| | | this.$emit('change', contentWithoutIp) |
| | | }, |
| | | onFocus: () => { |
| | | this.$emit('focus') |
| | |
| | | |
| | | } |
| | | |
| | | console.log('this.addIpToContent(this.value)',this.addIpToContent(this.value)) |
| | | try { |
| | | this.editor = new AiEditor(options) |
| | | } catch (error) { |
| | |
| | | this.editor = null |
| | | } |
| | | }, |
| | | // 获取编辑器内容 |
| | | // 获取编辑器内容(去除IP地址,只保留相对路径) |
| | | getContent() { |
| | | return this.editor ? this.editor.getHtml() : '' |
| | | if (!this.editor) return ''; |
| | | const content = this.editor.getHtml(); |
| | | return this.removeIpFromContent(content); |
| | | }, |
| | | // 设置编辑器内容 |
| | | // 设置编辑器内容(为相对路径添加IP地址) |
| | | setContent(content) { |
| | | if (this.editor) { |
| | | this.editor.setContent(content) |
| | | const contentWithIp = this.addIpToContent(content); |
| | | this.editor.setContent(contentWithIp); |
| | | } |
| | | }, |
| | | // 清空编辑器内容 |
| | |
| | | * @param {string} name 下载保存的文件名(可选) |
| | | */ |
| | | export function downloadFileByUrl(url, name) { |
| | | console.log("22222222222222222222", url); |
| | | if (!url) return; |
| | | // 处理相对路径 |
| | | const fullUrl = getFullUrl(url); |
| | | console.log("fullUrl fullUrl", fullUrl); |
| | | console.log("下载文件地址", fullUrl); |
| | | const a = document.createElement("a"); |
| | | a.href = fullUrl; |
| | | if (name) { |
| | |
| | | window.open(fullUrl, "_blank"); |
| | | } |
| | | |
| | | /** |
| | | * 判断文件是否为图片 |
| | | * @param {string} url 文件URL |
| | | * @returns {boolean} 是否为图片文件 |
| | | */ |
| | | export function isImageFile(url) { |
| | | if (!url) return false; |
| | | const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg']; |
| | | const lowerUrl = url.toLowerCase(); |
| | | return imageExtensions.some(ext => lowerUrl.includes(ext)); |
| | | } |
| | | |
| | | export function getAllocateIp() { |
| | | const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}"); |
| | | return userInfo.allocateIp ? userInfo.allocateIp +'/images/' : apiConfig.showImgUrl; |
| | | return userInfo.allocateIp ? 'http://'+userInfo.allocateIp +':11222/images/' : apiConfig.showImgUrl; |
| | | } |
| | |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getDetail, audit } from "../../service"; |
| | | import apiConfig from "@/utils/baseurl"; |
| | | import { getAllocateIp } from "@/utils/utils"; |
| | | import { getAllocateIp, downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | |
| | | }, |
| | | methods: { |
| | | handlePreview(file) { |
| | | console.log("url", file); |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | window.open(file.url, "_blank"); |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | window.open(newUrl, "_blank"); |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import chooseProject from "@/components/chooseProject"; |
| | | import { addData, getDetail, editData } from "./service"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp } from "@/utils/utils"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp , downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | import { mapState } from "vuex"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | |
| | |
| | | |
| | | methods: { |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | getDetail() { |
| | |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetail, audit } from '../../service' |
| | | import apiConfig from '@/utils/baseurl'; |
| | | import { getAllocateIp } from '@/utils/utils' |
| | | import { getAllocateIp, downloadFileByUrl, isImageFile } from '@/utils/utils' |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | |
| | | }, |
| | | methods: { |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | getDetail() { |
| | |
| | | <template> |
| | | <el-dialog :title="dialogTitle" :visible.sync="visible" width="90%" top="5vh" @open="open" |
| | | :close-on-click-modal="false" @close="handleClose"> |
| | | <el-dialog |
| | | :title="dialogTitle" |
| | | :visible.sync="visible" |
| | | width="90%" |
| | | top="5vh" |
| | | @open="open" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="approval-dialog"> |
| | | <!-- 左侧审批内容 --> |
| | | <div class="approval-content"> |
| | | <Card class="approval-content-card"> |
| | | <template style="position: relative"> |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属检测项</div> |
| | |
| | | </template> |
| | | </Table> |
| | | |
| | | |
| | | <el-form ref="form" :model="form" :rules="rules" inline label-position="top" |
| | | style="margin-top: 18px"> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | style="margin-top: 18px" |
| | | > |
| | | <el-form-item prop="name" label="报告内容"> |
| | | <el-select v-model="form.reportContent" style="width: 100%;" disabled |
| | | placeholder="请选择报告内容"> |
| | | <el-select |
| | | v-model="form.reportContent" |
| | | style="width: 100%" |
| | | disabled |
| | | placeholder="请选择报告内容" |
| | | > |
| | | <el-option label="国家标准" :value="1" /> |
| | | <el-option label="分析方法开发" :value="2" /> |
| | | <el-option label="方法验证报告" :value="3" /> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>报告正文</div> |
| | | </div> |
| | | </div> |
| | | <el-form-item prop="name" style="margin-top: 18px"> |
| | | <ai-editor :value="form.reportText" :readOnly="true" style="width: 100%;" |
| | | placeholder="请输入报告编号" /> |
| | | <ai-editor |
| | | :value="form.reportText" |
| | | :readOnly="true" |
| | | style="width: 100%" |
| | | placeholder="请输入报告编号" |
| | | /> |
| | | </el-form-item> |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>附件</span> |
| | | </div> |
| | | </div> |
| | | <el-form-item prop="name" style="margin-top: 18px"> |
| | | <el-upload action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList" |
| | | :on-preview="handlePreview"> |
| | | <el-upload |
| | | action="https://jsonplaceholder.typicode.com/posts/" |
| | | :file-list="fileList" |
| | | :on-preview="handlePreview" |
| | | > |
| | | <!-- <el-button size="small" type="primary">点击上传</el-button> --> |
| | | </el-upload> |
| | | </el-form-item> |
| | | |
| | | </el-form> |
| | | </template> |
| | | <!-- <SelectMember ref="selectMember" /> --> |
| | |
| | | <div class="status"> |
| | | <div class="status-title">审批结果</div> |
| | | <div class="status-content"> |
| | | <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1"> |
| | | <div |
| | | class="resolve" |
| | | :class="status == '1' && 'activeStatus'" |
| | | @click.stop="status = 1" |
| | | > |
| | | 通过 |
| | | </div> |
| | | <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2"> |
| | | <div |
| | | class="reject" |
| | | :class="status == '2' && 'activeStatus'" |
| | | @click.stop="status = 2" |
| | | > |
| | | 驳回 |
| | | </div> |
| | | </div> |
| | |
| | | <el-col :span="12"> |
| | | <div class="remark"> |
| | | <div class="remark-title">审批意见</div> |
| | | <el-input type="textarea" v-model="remark" placeholder="请输入审批意见" /> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="remark" |
| | | placeholder="请输入审批意见" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | </div> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleApprove" v-if="type == 'approve'">确认</el-button> |
| | | <el-button type="primary" @click="handleApprove" v-if="type == 'approve'" |
| | | >确认</el-button |
| | | > |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import ApprovalProcess from '@/components/approvalProcess' |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetailInfo, getDetail, detailAuditReport } from '../../service' |
| | | import { getFullUrl, getAllocateIp } from '@/utils/utils' |
| | | import apiConfig from '@/utils/baseurl'; |
| | | import ApprovalProcess from "@/components/approvalProcess"; |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getDetailInfo, getDetail, detailAuditReport } from "../../service"; |
| | | import { getFullUrl, getAllocateIp, downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | import apiConfig from "@/utils/baseurl"; |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | | components: { |
| | | ApprovalProcess, |
| | | AiEditor |
| | | AiEditor, |
| | | }, |
| | | props: { |
| | | visible: { |
| | |
| | | }, |
| | | computed: { |
| | | dialogTitle() { |
| | | return this.type == "approve" ? "审核项目检测项、检验包" : "项目检测项、检验包详情"; |
| | | return this.type == "approve" |
| | | ? "审核项目检测项、检验包" |
| | | : "项目检测项、检验包详情"; |
| | | }, |
| | | }, |
| | | watch: { |
| | | visible: { |
| | | handler(val) { |
| | | if (val && this.data.id) { |
| | | this.getDetailInfo() |
| | | this.getDetailInfo(); |
| | | } |
| | | if (val && this.data.itemId) { |
| | | this.getDetail() |
| | | this.getDetail(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | |
| | | methods: { |
| | | getFullUrl, |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | window.open(file.url, '_blank'); |
| | | console.log("图片链接", file.url); |
| | | window.open(file.url, "_blank"); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | window.open(newUrl, '_blank'); |
| | | console.log("图片链接", newUrl); |
| | | window.open(newUrl, "_blank"); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | open() { |
| | | this.status = 1; |
| | | this.remark = '' |
| | | this.remark = ""; |
| | | }, |
| | | getDetailInfo() { |
| | | getDetailInfo({ id: this.data.id }).then(res => { |
| | | getDetailInfo({ id: this.data.id }).then((res) => { |
| | | if (res) { |
| | | this.form = { ...res, reportContent: Number(res.reportContent), processData: [] } |
| | | this.form = { |
| | | ...res, |
| | | reportContent: Number(res.reportContent), |
| | | processData: [], |
| | | }; |
| | | if (res.qaReportFileList && res.qaReportFileList.length > 0) { |
| | | this.fileList = res.qaReportFileList.map(file => ({ |
| | | this.fileList = res.qaReportFileList.map((file) => ({ |
| | | name: file.fileName, |
| | | url: getFullUrl(file.fileUrl), |
| | | uid: file.id |
| | | })) |
| | | this.form.qaReportFileList = res.fileList |
| | | uid: file.id, |
| | | })); |
| | | this.form.qaReportFileList = res.fileList; |
| | | } else { |
| | | this.fileList = [] |
| | | this.form.qaReportFileList = [] |
| | | this.fileList = []; |
| | | this.form.qaReportFileList = []; |
| | | } |
| | | // 组装流程数据 |
| | | let processData = []; |
| | |
| | | processData.push({ |
| | | type: "warning", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "等待审核" }, |
| | | ], |
| | | fields: [{ label: "等待审核" }], |
| | | }); |
| | | } |
| | | // 如有卡片模式,按前述结构 push |
| | | |
| | | this.$nextTick(() => { |
| | | this.form.processData = processData; |
| | | }) |
| | | }); |
| | | } |
| | | }) |
| | | }); |
| | | }, |
| | | getDetail() { |
| | | getDetail(this.data.itemId).then(res => { |
| | | getDetail(this.data.itemId).then((res) => { |
| | | if (res) { |
| | | this.tableData = [{ ...res, teamName: res.projectTeamVO.teamName }] |
| | | this.tableData = [{ ...res, teamName: res.projectTeamVO.teamName }]; |
| | | } |
| | | }) |
| | | }); |
| | | }, |
| | | handleClose() { |
| | | this.$emit("close"); |
| | |
| | | this.form.approvalComment = ""; |
| | | }, |
| | | handleApprove() { |
| | | if (!this.remark && this.status == '2') { |
| | | if (!this.remark && this.status == "2") { |
| | | this.$message.warning("请输入审批意见"); |
| | | return; |
| | | } |
| | | const params = { |
| | | id: this.data.id, |
| | | auditRemark: this.remark, |
| | | auditStatus: this.status == '1' ? 2 : 3 |
| | | auditStatus: this.status == "1" ? 2 : 3, |
| | | }; |
| | | detailAuditReport(params).then(res => { |
| | | detailAuditReport(params) |
| | | .then((res) => { |
| | | if (res) { |
| | | this.$message.success('审核成功'); |
| | | this.$message.success("审核成功"); |
| | | this.$emit("close"); |
| | | } |
| | | }).catch(err => { |
| | | }) |
| | | .catch((err) => { |
| | | // this.$message.error(err.message || '审核失败'); |
| | | }); |
| | | }, |
| | |
| | | line-height: 32px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center |
| | | justify-content: center; |
| | | } |
| | | |
| | | .reject { |
| | |
| | | cursor: pointer; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center |
| | | justify-content: center; |
| | | } |
| | | |
| | | .activeStatus { |
| | |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getDetail, audit } from "../../service"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | import { getAllocateIp } from '@/utils/utils' |
| | | import { getAllocateIp, downloadFileByUrl, isImageFile } from '@/utils/utils' |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | |
| | | }, |
| | | methods: { |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | getDetail() { |
| | |
| | | <template> |
| | | <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" po :close-on-click-modal="false" |
| | | @close="handleClose"> |
| | | <el-dialog |
| | | :title="dialogTitle" |
| | | :visible.sync="visible" |
| | | width="80%" |
| | | po |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="approval-dialog"> |
| | | <!-- 左侧审批内容 --> |
| | | <div class="approval-content"> |
| | | <Card class="approval-content-card"> |
| | | <template style="position: relative"> |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>所属检测项</div> |
| | |
| | | </template> |
| | | </Table> |
| | | |
| | | |
| | | <el-form ref="form" :model="form" :rules="rules" inline label-position="top" |
| | | style="margin-top: 18px"> |
| | | <el-form |
| | | ref="form" |
| | | :model="form" |
| | | :rules="rules" |
| | | inline |
| | | label-position="top" |
| | | style="margin-top: 18px" |
| | | > |
| | | <el-form-item prop="name" label="报告内容"> |
| | | <el-select v-model="form.reportContent" style="width: 100%;" disabled |
| | | placeholder="请选择报告内容"> |
| | | <el-select |
| | | v-model="form.reportContent" |
| | | style="width: 100%" |
| | | disabled |
| | | placeholder="请选择报告内容" |
| | | > |
| | | <el-option label="国家标准" :value="1" /> |
| | | <el-option label="分析方法开发" :value="2" /> |
| | | <el-option label="方法验证报告" :value="3" /> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>报告正文</div> |
| | | </div> |
| | | </div> |
| | | <el-form-item prop="name" style="margin-top: 18px"> |
| | | <ai-editor :value="form.reportText" :readOnly="true" style="width: 100%;" |
| | | placeholder="请输入报告编号" /> |
| | | <ai-editor |
| | | :value="form.reportText" |
| | | :readOnly="true" |
| | | style="width: 100%" |
| | | placeholder="请输入报告编号" |
| | | /> |
| | | </el-form-item> |
| | | <div class="header-title" style="width: 100%;"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <span>附件</span> |
| | | </div> |
| | | </div> |
| | | <el-form-item prop="name" style="margin-top: 18px"> |
| | | <el-upload :on-preview="handlePreview" |
| | | action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList"> |
| | | <el-upload |
| | | :on-preview="handlePreview" |
| | | action="https://jsonplaceholder.typicode.com/posts/" |
| | | :file-list="fileList" |
| | | > |
| | | <!-- <el-button size="small" type="primary">点击上传</el-button> --> |
| | | </el-upload> |
| | | </el-form-item> |
| | | |
| | | </el-form> |
| | | </template> |
| | | <!-- <SelectMember ref="selectMember" /> --> |
| | |
| | | <div class="status"> |
| | | <div class="status-title">审批结果</div> |
| | | <div class="status-content"> |
| | | <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1"> |
| | | <div |
| | | class="resolve" |
| | | :class="status == '1' && 'activeStatus'" |
| | | @click.stop="status = 1" |
| | | > |
| | | 通过 |
| | | </div> |
| | | <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2"> |
| | | <div |
| | | class="reject" |
| | | :class="status == '2' && 'activeStatus'" |
| | | @click.stop="status = 2" |
| | | > |
| | | 驳回 |
| | | </div> |
| | | </div> |
| | |
| | | <el-col :span="12"> |
| | | <div class="remark"> |
| | | <div class="remark-title">审批意见</div> |
| | | <el-input type="textarea" v-model="remark" placeholder="请输入审批意见" /> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="remark" |
| | | placeholder="请输入审批意见" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | </div> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button type="primary" @click="handleApprove" v-if="type === 'approve'">确认</el-button> |
| | | <el-button type="primary" @click="handleApprove" v-if="type === 'approve'" |
| | | >确认</el-button |
| | | > |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import ApprovalProcess from '@/components/approvalProcess' |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetailInfo, getDetail, detailAuditReport } from '../../service' |
| | | import apiConfig from '@/utils/baseurl'; |
| | | import { getAllocateIp } from '@/utils/utils' |
| | | import ApprovalProcess from "@/components/approvalProcess"; |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getDetailInfo, getDetail, detailAuditReport } from "../../service"; |
| | | import apiConfig from "@/utils/baseurl"; |
| | | import { getAllocateIp, downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | export default { |
| | | name: "ApprovalDialog", |
| | | components: { |
| | | ApprovalProcess, |
| | | AiEditor |
| | | AiEditor, |
| | | }, |
| | | props: { |
| | | visible: { |
| | |
| | | visible: { |
| | | handler(val) { |
| | | if (val && this.data.id) { |
| | | this.getDetailInfo() |
| | | this.getDetailInfo(); |
| | | } |
| | | if (val && this.data.itemId) { |
| | | this.getDetail() |
| | | this.getDetail(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | |
| | | }, |
| | | methods: { |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | window.open(file.url, '_blank'); |
| | | console.log("图片链接", file.url); |
| | | window.open(file.url, "_blank"); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | window.open(newUrl, '_blank'); |
| | | console.log("图片链接", newUrl); |
| | | window.open(newUrl, "_blank"); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | getDetailInfo() { |
| | | getDetailInfo({ id: this.data.id }).then(res => { |
| | | getDetailInfo({ id: this.data.id }).then((res) => { |
| | | if (res) { |
| | | this.form = { ...res, reportContent: Number(res.reportContent), processData: [] } |
| | | this.form = { |
| | | ...res, |
| | | reportContent: Number(res.reportContent), |
| | | processData: [], |
| | | }; |
| | | if (res.qaReportFileList && res.qaReportFileList.length > 0) { |
| | | this.fileList = res.qaReportFileList.map(file => ({ |
| | | this.fileList = res.qaReportFileList.map((file) => ({ |
| | | name: file.fileName, |
| | | url: getFullUrl(file.fileUrl), |
| | | uid: file.id |
| | | })) |
| | | this.form.qaReportFileList = res.fileList |
| | | uid: file.id, |
| | | })); |
| | | this.form.qaReportFileList = res.fileList; |
| | | } else { |
| | | this.fileList = [] |
| | | this.form.qaReportFileList = [] |
| | | this.fileList = []; |
| | | this.form.qaReportFileList = []; |
| | | } |
| | | // 组装流程数据 |
| | | let processData = []; |
| | |
| | | processData.push({ |
| | | type: "warning", |
| | | mode: "list", |
| | | fields: [ |
| | | { label: "等待审核" }, |
| | | ], |
| | | fields: [{ label: "等待审核" }], |
| | | }); |
| | | } |
| | | // 如有卡片模式,按前述结构 push |
| | | |
| | | this.$nextTick(() => { |
| | | this.form.processData = processData; |
| | | }) |
| | | }); |
| | | } |
| | | }) |
| | | }); |
| | | }, |
| | | getDetail() { |
| | | getDetail(this.data.itemId).then(res => { |
| | | getDetail(this.data.itemId).then((res) => { |
| | | if (res) { |
| | | this.tableData = [{ ...res, teamName: res.projectTeamVO.teamName }] |
| | | this.tableData = [{ ...res, teamName: res.projectTeamVO.teamName }]; |
| | | } |
| | | }) |
| | | }); |
| | | }, |
| | | handleClose() { |
| | | this.$emit("close"); |
| | |
| | | const params = { |
| | | id: this.data.id, |
| | | auditRemark: this.remark, |
| | | auditStatus: this.status === '1' ? 2 : 3 |
| | | auditStatus: this.status === "1" ? 2 : 3, |
| | | }; |
| | | detailAuditReport(params).then(res => { |
| | | detailAuditReport(params) |
| | | .then((res) => { |
| | | if (res) { |
| | | this.$message.success('审核成功'); |
| | | this.$message.success("审核成功"); |
| | | this.$emit("close"); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error(err.message || '审核失败'); |
| | | }) |
| | | .catch((err) => { |
| | | this.$message.error(err.message || "审核失败"); |
| | | }); |
| | | }, |
| | | handleReject() { |
| | |
| | | line-height: 32px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center |
| | | justify-content: center; |
| | | } |
| | | |
| | | .reject { |
| | |
| | | cursor: pointer; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center |
| | | justify-content: center; |
| | | } |
| | | |
| | | .activeStatus { |
| | |
| | | import { getDetail } from "../../service"; |
| | | import { customUploadRequest, getFullUrl } from "@/utils/utils"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | import { getAllocateIp } from '@/utils/utils' |
| | | import { getAllocateIp, downloadFileByUrl, isImageFile } from '@/utils/utils' |
| | | |
| | | export default { |
| | | name: "ApprovalDialog", |
| | |
| | | methods: { |
| | | getFullUrl, |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | open() { |
| | |
| | | import ApprovalProcess from "@/components/approvalProcess"; |
| | | import AiEditor from "@/components/AiEditor"; |
| | | import { getDetail } from "../../service"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp } from "@/utils/utils"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp, downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | |
| | | export default { |
| | |
| | | methods: { |
| | | getFullUrl, |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | open() { |
| | |
| | | import ApprovalProcess from '@/components/approvalProcess' |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetail } from '../../service'; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp } from "@/utils/utils"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp , downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | |
| | | |
| | |
| | | methods: { |
| | | getFullUrl, |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | open() { |
| | |
| | | import ApprovalProcess from '@/components/approvalProcess' |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetail } from '../../service'; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp } from "@/utils/utils"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp , downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | |
| | | |
| | |
| | | methods: { |
| | | getFullUrl, |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | open() { |
| | |
| | | import ApprovalProcess from '@/components/approvalProcess' |
| | | import AiEditor from '@/components/AiEditor' |
| | | import { getDetail } from '../../service'; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp } from "@/utils/utils"; |
| | | import { customUploadRequest, getFullUrl, getAllocateIp , downloadFileByUrl, isImageFile } from "@/utils/utils"; |
| | | import apiConfig from '@/utils/baseurl'; |
| | | |
| | | |
| | |
| | | methods: { |
| | | getFullUrl, |
| | | handlePreview(file) { |
| | | console.log('url', file) |
| | | if (file && file.url) { |
| | | // 判断是否为图片文件 |
| | | const isImage = isImageFile(file.url); |
| | | |
| | | if (isImage) { |
| | | // 图片文件:使用 window.open 预览 |
| | | if (file.url && file.url.startsWith(getAllocateIp())) { |
| | | console.log('图片链接', file.url) |
| | | window.open(file.url, '_blank'); |
| | | } else { |
| | | let newUrl = getAllocateIp() + file.url; |
| | | console.log('图片链接', newUrl) |
| | | window.open(newUrl, '_blank'); |
| | | } |
| | | } else { |
| | | // 非图片文件:使用下载方式 |
| | | downloadFileByUrl(file.url, file.name); |
| | | } |
| | | } |
| | | }, |
| | | open() { |