gaoluyang
2 天以前 b871888a4ee32d15adfd52fdfabc44c7c674db0e
新疆——新聚lims
1.标准维护预览附件问题
已修改8个文件
133 ■■■■ 文件已修改
.env.development 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.staging 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Onlyoffice/onlyoffice.vue 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Preview/filePreview.vue 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/standard/standardLibrary/index.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -10,5 +10,8 @@
# 本地环境ip+端口
VUE_APP_BASE_URL = 'http://127.0.0.1:8001/lims'
# OnlyOffice 文档服务地址(预览 pdf 用,没有 http:// 前缀会当成相对路径)
VUE_APP_ONLYOFFICE_API = 'http://192.168.21.53:9001'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
.env.production
@@ -9,3 +9,6 @@
# 生产环境ip+端口
VUE_APP_BASE_URL = 'http://192.168.21.53:8001/lims'
# OnlyOffice 文档服务地址(预览 pdf 用,没有 http:// 前缀会当成相对路径)
VUE_APP_ONLYOFFICE_API = 'http://192.168.21.53:9001'
.env.staging
@@ -14,5 +14,8 @@
# 测试环境ip+端口
VUE_APP_BASE_URL = http://127.0.0.1:8001/lims
# OnlyOffice 文档服务地址(预览 pdf 用,没有 http:// 前缀会当成相对路径)
VUE_APP_ONLYOFFICE_API = 'http://192.168.21.53:9001'
# 运行端口
PORT= '80'
public/index.html
@@ -234,9 +234,5 @@
    <script src="<%= BASE_URL %>luckysheet/plugins/js/plugin.js"></script>
    <script src="<%= BASE_URL %>luckysheet/luckysheet.umd.js"></script>
  </body>
  <script
    type="text/javascript"
    src="http://192.168.21.53:9001/web-apps/apps/api/documents/api.js"
  ></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script>
</html>
src/components/Onlyoffice/onlyoffice.vue
@@ -4,6 +4,37 @@
</template>
<script>
// OnlyOffice 文档服务地址,按环境配置;脚本在真正需要预览时才加载
const OFFICE_API_BASE = process.env.VUE_APP_ONLYOFFICE_API || "http://192.168.21.53:9001";
// 多个页面共用编辑器,api.js 只加载一次
let docsApiPromise = null;
function loadDocsApi() {
  if (window.DocsAPI) {
    return Promise.resolve(window.DocsAPI);
  }
  if (!docsApiPromise) {
    docsApiPromise = new Promise((resolve, reject) => {
      const script = document.createElement("script");
      script.src = OFFICE_API_BASE.replace(/\/$/, "") + "/web-apps/apps/api/documents/api.js";
      script.onload = () => {
        if (window.DocsAPI) {
          resolve(window.DocsAPI);
        } else {
          reject(new Error("api.js 加载完成但未注册 DocsAPI"));
        }
      };
      script.onerror = () => reject(new Error("OnlyOffice 文档服务脚本加载失败:" + script.src));
      document.head.appendChild(script);
    });
    // 加载失败后允许下次重试
    docsApiPromise.catch(() => {
      docsApiPromise = null;
    });
  }
  return docsApiPromise;
}
export default {
  name: "VabOnlyOffice",
  props: ['options'],
@@ -50,10 +81,7 @@
    }
  },
  beforeDestroy() {
    if (this.docEditor !== null) {
      this.docEditor.destroyEditor();
      this.docEditor = null;
    }
    this.destroyEditor();
  },
  watch: {
    option: {
@@ -70,10 +98,17 @@
    }
  },
  methods: {
    async setEditor(option) {
    destroyEditor() {
      if (this.docEditor !== null) {
        this.docEditor.destroyEditor();
        this.docEditor = null;
      }
    },
    async setEditor(option) {
      this.destroyEditor();
      // 没有文档地址就不初始化编辑器,避免访问尚未加载的 DocsAPI
      if (!option || !option.url) {
        return;
      }
      this.doctype = this.getFileType(option.fileType);
      let config = {
@@ -116,8 +151,17 @@
        token: option.token || ""
      };
      // eslint-disable-next-line no-undef,no-unused-vars
      this.docEditor = new DocsAPI.DocEditor("vabOnlyOffice", config);
      try {
        await loadDocsApi();
      } catch (error) {
        console.error(error);
        this.$message.error("文档服务暂时不可用,无法预览");
        return;
      }
      if (this._isDestroyed) {
        return;
      }
      this.docEditor = new window.DocsAPI.DocEditor("vabOnlyOffice", config);
    },
    getFileType(fileType) {
      let docType = "";
src/components/Preview/filePreview.vue
@@ -4,10 +4,10 @@
      <img :src="imgUrl" alt="Image Preview" />
    </div>
    <div v-if="isPdf" style="height: 80vh;">
<!--      <object :data="fileUrl" type="application/pdf" width="100%" height="750px">-->
<!--        <p>您的浏览器不支持 PDF 预览。<a :href="fileUrl" style="color: #3a7bfa;" target="_blank">下载 PDF 文件</a></p>-->
<!--      </object>-->
      <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;" />
      <onlyoffice v-if="useOnlyOffice" ref="onlyoffice" :options="option" style="width: 100%;height: 100%;" />
      <iframe v-else-if="pdfUrl" :src="pdfUrl" title="PDF 预览" style="width: 100%;height: 100%;border: none;"></iframe>
      <p v-else-if="pdfError">PDF 预览失败,<a :href="fileUrl" style="color: #3a7bfa;" target="_blank">点此下载查看</a></p>
      <p v-else>正在加载 PDF…</p>
    </div>
    <div v-if="isDoc">
      <p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
@@ -53,6 +53,7 @@
</template>
<script>
import axios from 'axios'
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
@@ -92,7 +93,9 @@
        transformData: (workbookData) => { return workbookData }, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
      },
      csvList: [],//csv文件数据
      imgUrl: ''
      imgUrl: '',
      pdfUrl: '',       //pdf本地预览地址
      pdfError: false,
    }
  },
  computed: {
@@ -134,9 +137,46 @@
    },
    isSupported() {
      return this.isImage || this.isPdf || this.isDoc || this.isZipOrRar || this.isCsv || this.isXls;
    }
    },
    // 调用方传了 OnlyOffice 的配置才走文档服务,否则用浏览器内置阅读器
    useOnlyOffice() {
      return !!(this.option && this.option.url);
    },
  },
  watch: {
    fileUrl: {
      handler() {
        this.loadPdf();
      },
      immediate: true,
    },
  },
  beforeDestroy() {
    this.releasePdfUrl();
  },
  methods: {
    releasePdfUrl() {
      if (this.pdfUrl) {
        URL.revokeObjectURL(this.pdfUrl);
        this.pdfUrl = "";
      }
    },
    async loadPdf() {
      this.releasePdfUrl();
      this.pdfError = false;
      if (!this.isPdf || this.useOnlyOffice) {
        return;
      }
      try {
        const { data } = await axios.get(this.fileUrl, { responseType: "blob" });
        // 后端返回的 Content-Type 不一定带 application/pdf,这里强制指定,
        // 浏览器才会用内置阅读器打开而不是直接下载
        this.pdfUrl = URL.createObjectURL(new Blob([data], { type: "application/pdf" }));
      } catch (error) {
        console.error(error);
        this.pdfError = true;
      }
    },
    renderedHandler() {
      console.log("渲染完成")
      this.isDocShow = true
src/views/standard/standardLibrary/index.vue
@@ -6,8 +6,12 @@
        <pane size="12">
          <el-col>
            <div class="head-container addButton">
              <el-input v-model="search" clearable placeholder="输入关键字进行搜索" size="small" style="margin-bottom: 5px"
              <el-input v-model="search" clearable placeholder="输入关键字进行搜索" size="small"
                        style="margin-bottom: 5px; flex: 1; min-width: 0"
                        suffix-icon="el-icon-search" @keydown.enter.native="searchFilter" @blur="searchFilter" @clear="searchFilter"></el-input>
              <el-button icon="el-icon-refresh" size="small" title="刷新"
                         style="margin-bottom: 5px; margin-left: 8px"
                         @click="selectStandardTreeList"></el-button>
            </div>
            <div class="head-container">
              <el-tree ref="tree" v-loading="treeLoad" :data="list"
@@ -41,7 +45,7 @@
        <pane size="88">
          <el-card v-if="selected.isLeaf" shadow="never" class="template-binding-card">
            <div slot="header"><span>原始记录模板</span><el-button v-if="checkPermi(['standard:standardLibrary:upStandardProduct'])" type="primary" size="mini" style="float:right" @click="saveBindings">保存绑定</el-button></div>
            <p v-if="!templateBindings.length" class="binding-tip">请为当前标准绑定原始记录模板;模板中须使用“检验项”标记。</p>
            <p v-if="!templateBindings.length" class="binding-tip">请为当前标准绑定原始记录模板。</p>
            <el-table :data="templateBindings" border size="small">
              <el-table-column type="index" label="顺序" width="70" /><el-table-column label="模板编号" prop="number" width="180" /><el-table-column label="模板名称" prop="name" /><el-table-column label="检测依据(模板备注)" prop="remark" />
              <el-table-column v-if="checkPermi(['standard:standardLibrary:upStandardProduct'])" label="操作" width="150"><template slot-scope="scope"><el-button type="text" :disabled="scope.$index === 0" @click="moveBinding(scope.$index, -1)">上移</el-button><el-button type="text" :disabled="scope.$index === templateBindings.length - 1" @click="moveBinding(scope.$index, 1)">下移</el-button><el-button type="text" @click="removeBinding(scope.$index)">移除</el-button></template></el-table-column>
vue.config.js
@@ -37,7 +37,7 @@
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        // target: `http://36.213.90.123:9015/lims`,
        target: `http://127.0.0.1:8001/lims`,
        target: `http://192.168.21.53:9001/lims`,
        changeOrigin: true,
        pathRewrite: {
          ["^" + process.env.VUE_APP_BASE_API]: "",