董国庆
8 小时以前 fe6509e66e6852f6b5d740385bdae4fd0a11da77
修改问题
13个文件已修改
562 ■■■■ 已修改文件
laboratory/src/components/AiEditor/index.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/utils/utils.js 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/pilotAndProduction/components/approval/index.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/productApproval/add.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/productApproval/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/projectTesting/components/approval/index.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/rawMaterials/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/deliveryAssessment/testingAndEvaluation/components/approval/index.vue 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/feasibilityReport/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/feasibilityStudy/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/processDevelopment/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/projectProposalLibrary/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/verificationRelease/components/approval/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/components/AiEditor/index.vue
@@ -57,7 +57,8 @@
    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
@@ -78,18 +79,91 @@
    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')
@@ -205,6 +279,7 @@
      }
      console.log('this.addIpToContent(this.value)',this.addIpToContent(this.value))
      try {
        this.editor = new AiEditor(options)
      } catch (error) {
@@ -217,14 +292,17 @@
        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);
      }
    },
    // 清空编辑器内容
laboratory/src/utils/utils.js
@@ -51,11 +51,10 @@
 * @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) {
@@ -79,7 +78,19 @@
  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;
}
laboratory/src/views/chemistQa/pilotAndProduction/components/approval/index.vue
@@ -108,7 +108,7 @@
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",
@@ -172,13 +172,23 @@
  },
  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);
        }
      }
    },
laboratory/src/views/chemistQa/productApproval/add.vue
@@ -77,7 +77,7 @@
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';
@@ -136,14 +136,24 @@
  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() {
laboratory/src/views/chemistQa/productApproval/components/approval/index.vue
@@ -112,7 +112,7 @@
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",
@@ -176,14 +176,24 @@
    },
    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() {
laboratory/src/views/chemistQa/projectTesting/components/approval/index.vue
@@ -1,12 +1,19 @@
<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>
@@ -23,12 +30,21 @@
                            </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" />
@@ -38,29 +54,35 @@
                                </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" /> -->
@@ -79,10 +101,18 @@
                    <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>
@@ -91,32 +121,36 @@
                <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: {
@@ -154,17 +188,19 @@
    },
    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,
@@ -173,34 +209,48 @@
    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 = [];
@@ -241,25 +291,23 @@
                        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");
@@ -267,21 +315,23 @@
            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 || '审核失败');
            });
        },
@@ -461,7 +511,7 @@
            line-height: 32px;
            display: flex;
            align-items: center;
            justify-content: center
      justify-content: center;
        }
        .reject {
@@ -475,7 +525,7 @@
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center
      justify-content: center;
        }
        .activeStatus {
laboratory/src/views/chemistQa/rawMaterials/components/approval/index.vue
@@ -109,7 +109,7 @@
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",
@@ -173,14 +173,24 @@
  },
  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() {
laboratory/src/views/deliveryAssessment/testingAndEvaluation/components/approval/index.vue
@@ -1,12 +1,18 @@
<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>
@@ -23,12 +29,21 @@
                            </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" />
@@ -38,29 +53,35 @@
                                </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" /> -->
@@ -79,10 +100,18 @@
                    <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>
@@ -91,31 +120,35 @@
                <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: {
@@ -160,10 +193,10 @@
        visible: {
            handler(val) {
                if (val && this.data.id) {
                    this.getDetailInfo()
          this.getDetailInfo();
                }
                if (val && this.data.itemId) {
                    this.getDetail()
          this.getDetail();
                }
            },
            immediate: true,
@@ -171,30 +204,44 @@
    },
    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 = [];
@@ -235,25 +282,23 @@
                        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");
@@ -268,15 +313,17 @@
            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() {
@@ -453,7 +500,7 @@
            line-height: 32px;
            display: flex;
            align-items: center;
            justify-content: center
      justify-content: center;
        }
        .reject {
@@ -467,7 +514,7 @@
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center
      justify-content: center;
        }
        .activeStatus {
laboratory/src/views/reportLibrary/feasibilityReport/components/approval/index.vue
@@ -111,7 +111,7 @@
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",
@@ -168,14 +168,24 @@
  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() {
laboratory/src/views/reportLibrary/feasibilityStudy/components/approval/index.vue
@@ -109,7 +109,7 @@
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 {
@@ -167,14 +167,24 @@
  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() {
laboratory/src/views/reportLibrary/processDevelopment/components/approval/index.vue
@@ -115,7 +115,7 @@
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';
@@ -174,14 +174,24 @@
    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() {
laboratory/src/views/reportLibrary/projectProposalLibrary/components/approval/index.vue
@@ -116,7 +116,7 @@
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';
@@ -175,14 +175,24 @@
    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() {
laboratory/src/views/reportLibrary/verificationRelease/components/approval/index.vue
@@ -114,7 +114,7 @@
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';
@@ -173,14 +173,24 @@
    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() {