浏览代码

Merge branch 'liuqiang' into v3

liuQiang 1 年之前
父节点
当前提交
1f929046a1

+ 24 - 0
src/api/upload/upload.js

@@ -0,0 +1,24 @@
+import request from "../../../src/utils/request-file"
+// 上传文件
+function uploadFile(data) {
+    return request({
+        url: `/biz/info/upload`,
+        method: "post",
+        data,
+        headers: {
+            'Content-Type': 'multipart/form-data'
+        },
+    })
+}
+// 上传多文件
+function uploadFileMany(data) {
+    return request({
+        url: `/biz/info/uploadFiles`,
+        method: "post",
+        data,
+    })
+}
+export default {
+    uploadFile,
+    uploadFileMany,
+}

+ 13 - 0
src/layout/iframe.vue

@@ -0,0 +1,13 @@
+<template>
+    <div>
+
+    </div>
+</template>
+
+<script setup>
+
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 155 - 23
src/layout/indexCommon.vue

@@ -104,6 +104,7 @@
               type="card"
               class="common-tabs"
             >
+              <el-tab-pane label="首页"> </el-tab-pane>
               <el-tab-pane
                 v-for="(item, index) in toRaw(editableTabs)"
                 :key="item.path"
@@ -120,27 +121,47 @@
                       alt=""
                     />
                   </div>
-                  <!-- <router-link
-                    :key="item"
-                    :data-path="item.path"
-                    :to="{
-                      path: item.path,
-                      query: {row:item.row},
-                    }"
-                    @click="paneClick(item)"
-                    class="tags-view-item"
-                  >
-                  {{item.label}}
-                  </router-link> -->
                 </template>
               </el-tab-pane>
+              <!-- 文件的iframe -->
+              <div v-for="item in iFrameData" :key="item.id">
+                <el-tab-pane :label="item.name" v-if="item.src">
+                  <template #label>
+                    <div class="tab_pane" @click="filePaneClick(item)">
+                      <div class="tab_text">{{ item.name }}</div>
+                      <img
+                        src="@/assets/images/close.png"
+                        @click="closeFileTab(item, index, $event)"
+                        alt=""
+                      />
+                    </div>
+                  </template>
+                </el-tab-pane>
+              </div>
             </el-tabs>
           </div>
-          <router-view v-slot="{ Component }" v-if="isAlive">
-            <KeepAlive :exclude="['identifyFont']">
-              <component :is="Component" />
-            </KeepAlive>
-          </router-view>
+          <div v-show="isAlive">
+            <router-view v-slot="{ Component }">
+              <KeepAlive :exclude="['identifyFont', 'allback', 'search']">
+                <component :is="Component" />
+              </KeepAlive>
+            </router-view>
+          </div>
+          <div v-show="!isAlive" style="width: 100%">
+            <div v-for="item in iFrameData" :key="item.id">
+              <div style="width: 100%" v-show="item.show">
+                <iframe
+                  :src="item.src"
+                  frameborder="0"
+                  :id="`iframe${item.id}`"
+                  width="100%"
+                  height="1000px"
+                  class="iframeBox"
+                  v-show="item.show"
+                ></iframe>
+              </div>
+            </div>
+          </div>
         </el-main>
       </el-container>
     </el-container>
@@ -149,7 +170,7 @@
 
 <script setup>
 import { nextTick, onMounted, provide, ref } from "vue";
-import { ElMessageBox } from "element-plus";
+import { ElMessageBox, ElMessage } from "element-plus";
 import useAppStore from "@/store/modules/app";
 import useUserStore from "@/store/modules/user";
 import useSettingsStore from "@/store/modules/settings";
@@ -191,10 +212,38 @@ const selectValue = ref(1); //文档空间类型
 const wangzhi = import.meta.env.VITE_APP_BASE_API;
 const isAlive = ref(true);
 const toFileData = ref();
+const uid = useUserStore().uid;
+const iFrameData = ref([
+  {
+    id: 1,
+    src: `http://192.168.1.9:81/fileEdit?clickRowId=1197`,
+    show: false,
+    name: "file1",
+  },
+  {
+    id: 2,
+    src: ``,
+    // src: `http://192.168.1.9:81/fileEdit?clickRowId=1198`,
+    show: false,
+    name: "file2",
+  },
+  {
+    id: 3,
+    src: ``,
+    show: false,
+    name: "",
+  },
+  {
+    id: 4,
+    src: ``,
+    show: false,
+    name: "",
+  },
+]);
 //--------tabs-----------------
 let tabIndex = 2;
 const editableTabsValue = ref("/index");
-const editableTabs = ref([{ label: "会话消息", path: "/index" }]);
+const editableTabs = ref([]);
 
 // const removeTab = (targetName) => {
 //   const tabs = editableTabs.value;
@@ -393,7 +442,10 @@ const clickTab = (item) => {
   setTimeout(() => {
     console.log("toFileData.value", toFileData.value);
     if (toFileData.value) {
-      console.log('tofolder',JSON.stringify(toRaw(toFileData.value.clickRowId)));
+      console.log(
+        "tofolder",
+        JSON.stringify(toRaw(toFileData.value.clickRowId))
+      );
       router.push({
         path: toFileData.value.path,
         query: {
@@ -414,7 +466,8 @@ const clickTab = (item) => {
       const data = JSON.parse(toRaw(item));
       console.log("data", data);
       router.push({
-        path: "/fileEdit" + data.docId,
+        // path: "/fileEdit" + data.docId,
+        path: "/fileEdit",
         query: {
           clickRowId: data.docId,
           // row:JSON.stringify(toFileData.value)
@@ -430,6 +483,7 @@ const clickTab = (item) => {
 };
 const paneClick = (item) => {
   // 可以拿到当前的标签对象
+  isAlive.value = true;
   console.log("paneItem", item);
   if (item.clickRowId) {
     // 判断是菜单还是目录
@@ -437,7 +491,58 @@ const paneClick = (item) => {
   } else {
     toFileData.value = null;
   }
-    clickTab(item.path)
+  clickTab(item.path);
+  console.log("isAlive", isAlive.value);
+};
+// 点击文件标签
+const filePaneClick = (item) => {
+  console.log("filePaneClickitem", item);
+  const row = toRaw(item);
+  const arr = iFrameData.value.map((par) => {
+    if (par.id === row.id) {
+      par.show = true;
+      // document.getElementById('iframe'+par.id).window.document.iframe[0]
+      const outIframe = document.getElementById("iframe" + par.id);
+      const inIframe =
+        outIframe.contentDocument.getElementsByTagName("iframe")[0];
+      setTimeout(() => {
+        inIframe.style.height = outIframe.style.height =
+          outIframe.parentElement.offsetHeight + "px";
+        inIframe.style.width = outIframe.style.width =
+          outIframe.parentElement.offsetWidth + "px";
+
+        // console.log('dom',outIframe.parentElement.offsetWidth);
+        // console.log('inIframe',inIframe);
+      }, 500);
+    } else {
+      par.show = false;
+    }
+    return toRaw(par);
+  });
+  iFrameData.value = arr;
+  // console.log("Clicknewfilearr", iFrameData.value);
+  isAlive.value = false;
+  // console.log("isAlive", isAlive.value);
+};
+// 创建文件的标签
+const addFileTab = (data) => {
+  console.log("fileTabdata", data);
+  const thisData = toRaw(data);
+  const oldIFrameData = iFrameData.value;
+  const canAdd = oldIFrameData.some((par) => par.src == "");
+  if (!canAdd) return ElMessage.error("已到最大数量,请先关闭其他文件!");
+  const arr = oldIFrameData.map((par) => {
+    if (!par.src) {
+      if (thisData.docId) {
+        par.src = `http://192.168.1.9:81/fileEdit?clickRowId=${thisData.docId}`;
+        par.name = data.fileName;
+        thisData.docId = "";
+      }
+    }
+    return toRaw(par);
+  });
+  iFrameData.value = arr;
+  console.log("addFileTab", arr);
 };
 //创建tab标签事件
 const addTab = (data) => {
@@ -473,6 +578,7 @@ const addFolderAdd = (data) => {
 };
 provide("addTab", addTab);
 provide("addFolderAdd", addFolderAdd);
+provide("addFileTab", addFileTab);
 // TODO 删除tab事件
 const closeTab = (item, index, e) => {
   e.preventDefault();
@@ -486,6 +592,24 @@ const closeTab = (item, index, e) => {
   // console.log("index", index);
   // console.log("e", e);
 };
+// TODO 删除tab事件
+const closeFileTab = (item, index, e) => {
+  e.preventDefault();
+  e.stopPropagation();
+  const data = toRaw(item);
+  console.log("closeFileTab", data);
+  const arr = iFrameData.value.map((par) => {
+    if (par.id === data.id) {
+      par.src = "";
+      par.show = false;
+      par.name = "";
+    }
+    return toRaw(par);
+  });
+  iFrameData.value = arr;
+  // console.log("index", index);
+  // console.log("e", e);
+};
 </script>
 
 <style lang="scss" scoped>
@@ -519,7 +643,7 @@ const closeTab = (item, index, e) => {
         height: 48px;
       }
     }
-    .logoImg{
+    .logoImg {
       width: 150px !important;
       height: 100%;
       margin-right: 10px;
@@ -663,4 +787,12 @@ const closeTab = (item, index, e) => {
   background: #fa5151;
   border-radius: 4px;
 }
+::v-deep .qualityManual-container-office {
+  width: 1000px !important;
+  height: 1000px !important;
+  iframe {
+    width: 1000px !important;
+    height: 1000px !important;
+  }
+}
 </style>

+ 21 - 12
src/router/index.js

@@ -57,6 +57,20 @@ export const constantRoutes = [{
 		path: '/401',
 		component: () => import('@/views/error/401'),
 		hidden: true
+	},{
+		path: "/fileEdit",
+		name: "fileEdit",
+		// component: common,
+		component: () => import("@/views/myfile/components/FileEdit.vue"),
+		// children: [{
+		// 	path: '/fileEdit:docId(\\d+)',
+		// 	component: () => import("@/views/myfile/components/FileEdit.vue"),
+		// 	name: 'fileEdit',
+		// 	meta: {
+		// 		title: '文件预览',
+		// 		activeMenu: '/fileEdit'
+		// 	}
+		// }]
 	},
 	{
 		path: '',
@@ -182,18 +196,13 @@ export const constantRoutes = [{
 					icon: "department"
 				}
 			},{
-				path: "/fileEdit",
-				name: "fileEdit",
-				component: common,
-				children: [{
-					path: '/fileEdit:docId(\\d+)',
-					component: () => import("@/views/myfile/components/FileEdit.vue"),
-					name: 'fileEdit',
-					meta: {
-						title: '文件预览',
-						activeMenu: '/fileEdit'
-					}
-				}]
+				path: "/iframe/*",
+				component: () => import("@/layout/iframe.vue"),
+				name: "iframe",
+				meta: {
+					title: "iframe",
+					icon: "department"
+				}
 			},{
 				path: "/allback",
 				component: () => import("@/views/highSearch/SupplierAllBack.vue"),

+ 152 - 0
src/utils/request-file.js

@@ -0,0 +1,152 @@
+import axios from 'axios'
+import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { tansParams, blobValidate } from '@/utils/ruoyi'
+import cache from '@/plugins/cache'
+import { saveAs } from 'file-saver'
+import useUserStore from '@/store/modules/user'
+
+let downloadLoadingInstance;
+// 是否显示重新登录
+export let isRelogin = { show: false };
+
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+// 创建axios实例
+const service = axios.create({
+  // axios中请求配置有baseURL选项,表示请求URL公共部分
+  baseURL: import.meta.env.VITE_APP_BASE_API,
+  // 超时
+  timeout: 600000
+})
+
+// request拦截器
+service.interceptors.request.use(config => {
+  // 是否需要设置 token
+  const isToken = (config.headers || {}).isToken === false
+  // 是否需要防止数据重复提交
+  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
+  if (getToken() && !isToken) {
+    config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+  }
+  // get请求映射params参数
+  if (config.method === 'get' && config.params) {
+    let url = config.url + '?' + tansParams(config.params);
+    url = url.slice(0, -1);
+    config.params = {};
+    config.url = url;
+  }
+  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+    const requestObj = {
+      url: config.url,
+      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+      time: new Date().getTime()
+    }
+    const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
+    const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
+    if (requestSize >= limitSize) {
+      console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
+      return config;
+    }
+    const sessionObj = cache.session.getJSON('sessionObj')
+    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
+      cache.session.setJSON('sessionObj', requestObj)
+    } else {
+      const s_url = sessionObj.url;                // 请求地址
+      const s_data = sessionObj.data;              // 请求数据
+      const s_time = sessionObj.time;              // 请求时间
+      const interval = 1000;                       // 间隔时间(ms),小于此时间视为重复提交
+      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
+        const message = '数据正在处理,请勿重复提交';
+        console.warn(`[${s_url}]: ` + message)
+        return Promise.reject(new Error(message))
+      } else {
+        cache.session.setJSON('sessionObj', requestObj)
+      }
+    }
+  }
+  return config
+}, error => {
+  console.log(error)
+  Promise.reject(error)
+})
+
+// 响应拦截器
+service.interceptors.response.use(res => {
+  // 未设置状态码则默认成功状态
+  const code = res.data.code || 200;
+  // 获取错误信息
+  const msg = errorCode[code] || res.data.msg || errorCode['default']
+  // 二进制数据则直接返回
+  if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
+    return res.data
+  }
+  if (code === 401) {
+    if (!isRelogin.show) {
+      isRelogin.show = true;
+      ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
+        isRelogin.show = false;
+        useUserStore().logOut().then(() => {
+          location.href = '/index';
+        })
+      }).catch(() => {
+        isRelogin.show = false;
+      });
+    }
+    return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
+  } else if (code === 500) {
+    ElMessage({ message: msg, type: 'error' })
+    return Promise.reject(new Error(msg))
+  } else if (code === 601) {
+    ElMessage({ message: msg, type: 'warning' })
+    return Promise.reject(new Error(msg))
+  } else if (code !== 200) {
+    ElNotification.error({ title: msg })
+    return Promise.reject('error')
+  } else {
+    return Promise.resolve(res.data)
+  }
+},
+  error => {
+    console.log('err' + error)
+    let { message } = error;
+    if (message == "Network Error") {
+      message = "后端接口连接异常";
+    } else if (message.includes("timeout")) {
+      message = "系统接口请求超时";
+    } else if (message.includes("Request failed with status code")) {
+      message = "系统接口" + message.substr(message.length - 3) + "异常";
+    }
+    ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
+    return Promise.reject(error)
+  }
+)
+
+// 通用下载方法
+export function download(url, params, filename, config) {
+  downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
+  return service.post(url, params, {
+    transformRequest: [(params) => { return tansParams(params) }],
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    responseType: 'blob',
+    ...config
+  }).then(async (data) => {
+    const isBlob = blobValidate(data);
+    if (isBlob) {
+      const blob = new Blob([data])
+      saveAs(blob, filename)
+    } else {
+      const resText = await data.text();
+      const rspObj = JSON.parse(resText);
+      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+      ElMessage.error(errMsg);
+    }
+    downloadLoadingInstance.close();
+  }).catch((r) => {
+    console.error(r)
+    ElMessage.error('下载文件出现错误,请联系管理员!')
+    downloadLoadingInstance.close();
+  })
+}
+
+export default service

+ 2 - 2
src/views/login.vue

@@ -238,7 +238,7 @@ async function handleLogin() {
     if (valid) {
       // console.log('loginvalid',valid);
       loading.value = true;
-      // console.log("pass",loginForm.value.password);
+      // console.log("pass",loginForm.value
       // console.log("sm3",sm3('123456'));
       // 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
       Cookies.set("pass", sm3(loginForm.value.password), {
@@ -262,7 +262,7 @@ async function handleLogin() {
         //如果登录的和记录的用户不是同一个, 或者同一个用户但是重新输入了密码,那就需要sm3加密
         query.password = sm3(query.password);
       }
-        console.log("query", query);
+        // console.log("query", query);
       userStore
         .login(query)
         .then(async (res) => {

+ 21 - 9
src/views/myfile/MyFile.vue

@@ -385,6 +385,7 @@
 <script>
 import { ref, toRaw, onMounted ,inject,onActivated} from 'vue'
 import myfile from '../../api/myfile/myfile'
+import uploadApi from '../../api/upload/upload'
 import { delFavorite } from '@/api/biz/favorite.js'
 import documents from '../../api/document/document'
 import fileCount from '../../api/fileCount/fileCount'
@@ -399,7 +400,7 @@ import SpaceBig from './modalComponebts/SpaceBig.vue'
 import PlaceGridFolder from './components/PlaceGridFolder.vue'
 import PalaceGridFile from './components/PalaceGridFile.vue'
 import ImgFile from "./jsComponents/ImgFile"
-import { Search } from '@element-plus/icons-vue'
+import { Refresh, Search } from '@element-plus/icons-vue'
 import blueLeft from '../../assets/images/blueLeft.png'
 import grayRight from "../../assets/images/grayRight.png"
 import sort from '../../assets/images/sort.png'
@@ -615,6 +616,7 @@ export default {
         const chooseNum = ref()
         const loadingPreview = ref(false)
         const addTab = inject("addTab");
+        const addFileTab = inject("addFileTab");
         const addFolderAdd = inject("addFolderAdd");
         // 获取文件夹,中栏,文件
         function getAllTop() {
@@ -673,6 +675,7 @@ export default {
             addFolderAdd(addData)
             thisFolder.value = row
             console.log('row2',row);
+            topPath.value = row.dirPath
             if(row.isEncrypt === "Y"){
                 getLeveldetailFn(row.encryptLevel)
             }else{
@@ -846,7 +849,8 @@ export default {
                             type: "success",
                             message: "删除成功"
                         })
-                        getAllTop()
+                        // getAllTop()
+                         refreshFile()
                     }
                 })
             }
@@ -873,7 +877,7 @@ export default {
                 // const filePreview = canPreviewFile(copyFileType.value)
                 // if (filePreview) {
                      loadingPreview.value = false
-                    addTab(clickRow.value);
+                    addFileTab(clickRow.value);
                     onlyView.value = false
                     // editOnline.value = false
                     cliCC.value = false
@@ -915,7 +919,7 @@ export default {
                 const filePreview = canPreviewFile(copyFileType.value)
                 if (filePreview) {
                      loadingPreview.value = false
-                    addTab(clickRow.value);
+                    addFileTab(clickRow.value);
                     //    const addData = {
                     //     path:"/fileEdit" + clickRow.value.docId,
                     //     name:clickRow.value.fileName,
@@ -971,7 +975,7 @@ export default {
         function sureUpload() {
             if (fileArr.value.length > 0) {
                 for (var i = 1; i <= fileArr.value.length; i++) {
-                    myfile.uploadFile({
+                    uploadApi.uploadFile({
                         spaceId: newSpaceId.value - 0,
                         dirId: newDirId.value - 0,
                         file: fileArr.value[i - 1]
@@ -981,7 +985,8 @@ export default {
                                 message: "上传文件成功",
                                 type: "success"
                             })
-                            getAllTop()
+                            // getAllTop()
+                            refreshFile()
                             uploadModal.value = false
                             fileArr.value = []
                         }
@@ -1075,7 +1080,8 @@ export default {
                                 message: "删除成功",
                                 type: "success"
                             })
-                            getAllTop()
+                            // getAllTop()
+                             refreshFile()
                         } else {
                             ElMessage({
                                 message: "删除失败,目录应不为空",
@@ -1091,11 +1097,16 @@ export default {
                                 message: "删除成功",
                                 type: "success"
                             })
-                            getAllTop()
+                            // getAllTop()
+                             refreshFile()
                         }
                     })
                 }
             }
+            if (row.name == '分享给') {
+                workOrEdit.value = num
+                thanks.value = true
+            } 
         }
         function delName(row, num) {
             documents.delDocument(row.dirId).then(res => {
@@ -1729,7 +1740,8 @@ export default {
             loadingPreview,
             downLoadfile,
             addTab,
-            addFolderAdd
+            addFolderAdd,
+            addFileTab
         }
     },
     watch: {

+ 0 - 4
src/views/myfile/components/PlaceGridFolder.vue

@@ -19,10 +19,6 @@
                 <!-- 右键唤出的菜单 -->
                 <div class="rightList" v-if="folderVisible"
                     :style="{ left: folderleft + 30 + 'px', top: foldertop - 50 + 'px' }">
-                    <div class="menu_item" @click="fatherOpen(null, null)">
-                        <img src="@/assets/images/trash.png" alt="" />
-                        <span>打开</span>
-                    </div>
                     <div class="menu_item" @click="fatherRest(null, null)">
                         <img src="@/assets/images/textbox.png" alt="" />
                         <span>重命名</span>

+ 1 - 1
src/views/myfile/modalComponebts/CreateFloder.vue

@@ -1,7 +1,7 @@
 <template>
     <div>
         <div>
-            <el-dialog v-model="addBoser" title="修改密码" width="30%" @close="diClose">
+            <el-dialog v-model="addBoser" title="新建目录" width="30%" @close="diClose">
                 <el-form :model="boserForm" label-width="120px">
                     <el-form-item label="目录名称">
                         <el-input v-model="boserForm.dirName" />

+ 5 - 1
src/views/search/index.vue

@@ -138,7 +138,7 @@
 import { onMounted, ref, toRaw, inject } from "vue";
 import { search } from "@/api/search/search.js";
 import { flieSearch } from "@/api/search/search.js";
-import { useRoute, useRouter } from "vue-router";
+import { useRoute, useRouter,onBeforeRouteUpdate } from "vue-router";
 import Pagination from "@/components/Pagination/index.vue";
 //---------------导入图片--------------------------
 import file_DOC from "@/assets/images/fileType/file_DOC.png";
@@ -328,6 +328,10 @@ function formatFileSize(fileSize) {
     return fileSize + "B";
   }
 }
+onBeforeRouteUpdate((to,from)=>{
+      console.log('to',to);
+      console.log('from',from);
+    })
 </script>
 
 <style lang="scss" scoped>