indexCommon.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. <template>
  2. <div class="common-layout">
  3. <el-container>
  4. <el-header
  5. class="nav"
  6. style="position: sticky; top: 0; left: 0; width: 100%; z-index: 999"
  7. >
  8. <div class="nav-top">
  9. <div>
  10. <img src="@/assets/images/logos.png" /><span
  11. >聚合智慧文档管理系统</span
  12. >
  13. </div>
  14. <div class="search">
  15. <el-input
  16. v-model="searchText"
  17. maxlength="32"
  18. class="w-50 m-2"
  19. size="small"
  20. placeholder="搜索文件"
  21. suffix-icon="Search"
  22. clearable
  23. @change="toSearch"
  24. @@keyup.enter="toSearch"
  25. />
  26. </div>
  27. <div>
  28. <el-dropdown
  29. @command="handleCommand"
  30. class="right-menu-item hover-effect"
  31. trigger="click"
  32. >
  33. <div class="avatar-wrapper">
  34. <img
  35. :src="
  36. userStore.avatar
  37. ? userStore.avatar
  38. : '@/assets/images/profile.png'
  39. "
  40. class="head-img"
  41. /><span>{{ userStore.name }}</span>
  42. </div>
  43. <template #dropdown>
  44. <el-dropdown-menu>
  45. <router-link to="/user/profile">
  46. <el-dropdown-item>个人中心</el-dropdown-item>
  47. </router-link>
  48. <el-dropdown-item divided command="logout">
  49. <span>退出登录</span>
  50. </el-dropdown-item>
  51. </el-dropdown-menu>
  52. </template>
  53. </el-dropdown>
  54. </div>
  55. </div>
  56. </el-header>
  57. <el-container>
  58. <el-aside width="92px" class="asides">
  59. <div class="aside-con">
  60. <router-link
  61. :to="item.path"
  62. v-for="(item, index) in menuList.data"
  63. :key="index"
  64. @click="clickPath(index, item)"
  65. ><div
  66. style="position: relative"
  67. :class="
  68. $route.path == item.path
  69. ? 'acitve-img-style img-style'
  70. : 'img-style'
  71. "
  72. >
  73. <img
  74. :src="$route.path == item.path ? item.beimgs : item.imgs"
  75. />
  76. <div class="text-style" v-if="$route.path != item.path">
  77. {{ item.label }}
  78. </div>
  79. <span
  80. class="yuandian"
  81. v-if="
  82. websoctStore.messOne?.fromId &&
  83. item.path == '/index' &&
  84. $route.path != item.path &&
  85. clickId !== index
  86. "
  87. ></span>
  88. </div> </router-link
  89. ><br />
  90. </div>
  91. </el-aside>
  92. <el-main class="main">
  93. <div class="tab_box">
  94. <el-tabs
  95. v-model="editableTabsValue"
  96. @tab-change="clickTab"
  97. @tab-add="addTab"
  98. type="card"
  99. class="common-tabs"
  100. >
  101. <el-tab-pane
  102. v-for="(item, index) in toRaw(editableTabs)"
  103. :key="item.path"
  104. :label="item.label"
  105. :name="item.path"
  106. :data-item="JSON.stringify(item)"
  107. >
  108. <template #label>
  109. <!-- <div class="tab_pane" @click="paneClick(item)">
  110. <div class="tab_text">{{ item.label }}</div>
  111. <img
  112. src="@/assets/images/close.png"
  113. @click="closeTab(item, index, $event)"
  114. alt=""
  115. />
  116. </div> -->
  117. <router-link
  118. :key="item"
  119. :data-path="item.path"
  120. :to="{
  121. path: item.path,
  122. query: item.clickRowId,
  123. }"
  124. @click="paneClick(item)"
  125. class="tags-view-item"
  126. >
  127. {{item.label}}
  128. </router-link>
  129. </template>
  130. </el-tab-pane>
  131. </el-tabs>
  132. </div>
  133. <router-view v-slot="{ Component }" v-if="isAlive">
  134. <KeepAlive :exclude="['fileEdit','identifyFont']">
  135. <component :is="Component" />
  136. </KeepAlive>
  137. </router-view>
  138. </el-main>
  139. </el-container>
  140. </el-container>
  141. </div>
  142. </template>
  143. <script setup>
  144. import { nextTick, onMounted, provide, ref } from "vue";
  145. import { ElMessageBox } from "element-plus";
  146. import useAppStore from "@/store/modules/app";
  147. import useUserStore from "@/store/modules/user";
  148. import useSettingsStore from "@/store/modules/settings";
  149. import Cookies from "js-cookie";
  150. import chat from "@/assets/images/chat.png";
  151. import bechat from "@/assets/images/bechat.png";
  152. import zuijin from "@/assets/images/zuijin.png";
  153. import bezuijin from "@/assets/images/bezuijin.png";
  154. import colloect from "@/assets/images/colloect.png";
  155. import becolloect from "@/assets/images/becolloect.png";
  156. import system from "@/assets/images/system.png";
  157. import issystem from "@/assets/images/issystem.png";
  158. import my from "@/assets/images/my.png";
  159. import bemy from "@/assets/images/bemy.png";
  160. import bumen from "@/assets/images/bumen.png";
  161. import bebumen from "@/assets/images/bebumen.png";
  162. import common from "@/assets/images/common.png";
  163. import becommon from "@/assets/images/becommon.png";
  164. import chuanshu from "@/assets/images/chuanshu.png";
  165. import bechuanshu from "@/assets/images/bechuanshu.png";
  166. import highsearch from "@/assets/images/highsearch.png";
  167. import behighsearch from "@/assets/images/behighsearch.png";
  168. import manyBody from "@/assets/images/manyBody.png";
  169. import manyBodyFalse from "@/assets/images/manyBodyFalse.png";
  170. import { AppMain, Navbar, Settings, TagsView } from "./components";
  171. import { flieSearch } from "@/api/search/search.js";
  172. import { useRouter, useRoute } from "vue-router";
  173. import useWebsoctStore from "@/store/modules/websocket";
  174. import { toRaw } from "@vue/reactivity";
  175. import iFrame from "@/components/iFrame/index.vue";
  176. const websoctStore = useWebsoctStore();
  177. const router = useRouter(); //注册路由
  178. const route = useRoute();
  179. const appStore = useAppStore();
  180. const userStore = useUserStore();
  181. const settingsStore = useSettingsStore();
  182. const searchText = ref(""); //搜索ipt的值
  183. const selectValue = ref(1); //文档空间类型
  184. const wangzhi = import.meta.env.VITE_APP_BASE_API;
  185. const isAlive = ref(true);
  186. const toFileData = ref();
  187. //--------tabs-----------------
  188. let tabIndex = 2;
  189. const editableTabsValue = ref("/index");
  190. const editableTabs = ref([{ label: "会话消息", path: "/index" }]);
  191. // const removeTab = (targetName) => {
  192. // const tabs = editableTabs.value;
  193. // let activeName = editableTabsValue.value;
  194. // if (activeName === targetName) {
  195. // tabs.forEach((tab, index) => {
  196. // if (tab.name === targetName) {
  197. // const nextTab = tabs[index + 1] || tabs[index - 1];
  198. // if (nextTab) {
  199. // activeName = nextTab.name;
  200. // }
  201. // }
  202. // });
  203. // }
  204. // editableTabsValue.value = activeName;
  205. // editableTabs.value = tabs.filter((tab) => tab.name !== targetName);
  206. // };
  207. //-------------------------
  208. function reload() {
  209. isAlive.value = false;
  210. console.log(11);
  211. nextTick(() => {
  212. isAlive.value = true;
  213. });
  214. }
  215. provide("reload", reload);
  216. function toggleSideBar() {
  217. appStore.toggleSideBar();
  218. }
  219. const logingName = ref("");
  220. onMounted(() => {
  221. logingName.value = Cookies.get("username");
  222. // console.log('router',router)
  223. });
  224. function handleCommand(command) {
  225. switch (command) {
  226. case "setLayout":
  227. setLayout();
  228. break;
  229. case "logout":
  230. logout();
  231. break;
  232. default:
  233. break;
  234. }
  235. }
  236. function logout() {
  237. ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
  238. confirmButtonText: "确定",
  239. cancelButtonText: "取消",
  240. type: "warning",
  241. })
  242. .then(() => {
  243. userStore.logOut().then(() => {
  244. location.href = "/index";
  245. });
  246. })
  247. .catch(() => {});
  248. }
  249. // 跳转到全文搜索
  250. const toSearch = async () => {
  251. if (!searchText.value) return;
  252. // console.log('searchText = ',searchText.value);
  253. const query = {
  254. keyword: searchText.value,
  255. isAsc: "asc",
  256. orderByColumn: "createTime",
  257. pageSize: 3,
  258. pageNum: 1,
  259. };
  260. const res = await flieSearch(query);
  261. // console.log("res", res);
  262. if (res) {
  263. // console.log("res", res);
  264. // console.log("router", route.path);
  265. if (route.path != "/search") {
  266. router.push({
  267. path: "/search",
  268. query: {
  269. searchData: JSON.stringify(res),
  270. searchText: searchText.value,
  271. },
  272. });
  273. } else {
  274. router.replace({
  275. path: "/allback",
  276. query: {
  277. searchData: JSON.stringify(res),
  278. searchText: searchText.value,
  279. },
  280. });
  281. }
  282. }
  283. };
  284. const emits = defineEmits(["setLayout"]);
  285. function setLayout() {
  286. emits("setLayout");
  287. }
  288. const clickId = ref("");
  289. const menuList = reactive({
  290. data: [
  291. {
  292. label: "会话消息",
  293. path: "/index",
  294. imgs: chat,
  295. beimgs: bechat,
  296. },
  297. // {
  298. // label: "接口",
  299. // path: "/swagger",
  300. // imgs: chat,
  301. // beimgs: bechat,
  302. // disabled:true
  303. // },
  304. {
  305. label: "最近文件",
  306. path: "/recent",
  307. imgs: zuijin,
  308. beimgs: bezuijin,
  309. },
  310. {
  311. label: "收藏文件",
  312. path: "/collect",
  313. imgs: colloect,
  314. beimgs: becolloect,
  315. },
  316. {
  317. label: "我的文件",
  318. path: "/myfile",
  319. imgs: my,
  320. beimgs: bemy,
  321. },
  322. {
  323. label: "部门文件",
  324. path: "/department",
  325. imgs: bumen,
  326. beimgs: bebumen,
  327. },
  328. {
  329. label: "公共文件",
  330. path: "/publicment",
  331. imgs: common,
  332. beimgs: becommon,
  333. },
  334. {
  335. label: "高级搜索",
  336. path: "/highsearch",
  337. imgs: highsearch,
  338. beimgs: behighsearch,
  339. },
  340. {
  341. label: "传输列表",
  342. path: "/transFile",
  343. imgs: chuanshu,
  344. beimgs: bechuanshu,
  345. },
  346. {
  347. label: "系统管理",
  348. path: "/admin",
  349. imgs: system,
  350. beimgs: issystem,
  351. },
  352. {
  353. label: "我的协作",
  354. path: "/myjoin",
  355. imgs: manyBody,
  356. beimgs: manyBodyFalse,
  357. },
  358. ],
  359. });
  360. const clickPath = (index, items) => {
  361. items = toRaw(items);
  362. // toFileData.value = null
  363. console.log("clickPathitems", items);
  364. // editableTabs.value = arr;
  365. const arr = toRaw(editableTabs.value);
  366. if (!arr.some((item) => item.label == items.label)) {
  367. editableTabs.value.push({ label: items.label, path: items.path });
  368. //需要jSON去转 否则页面无变化 离谱得很
  369. editableTabs.value = JSON.parse(JSON.stringify(editableTabs.value));
  370. } else {
  371. toFileData.value = null;
  372. clickTab(items.path);
  373. }
  374. editableTabsValue.value = items.path;
  375. // console.log("editableTabs", editableTabs.value);
  376. };
  377. const clickTab = (item) => {
  378. // console.log("item", toRaw(item));
  379. setTimeout(() => {
  380. console.log("toFileData.value", toFileData.value);
  381. if (toFileData.value) {
  382. router.push({
  383. path: toFileData.value.path,
  384. query: {
  385. row: toFileData.value.row,
  386. },
  387. });
  388. // router.push({
  389. // path: toFileData.value.path,
  390. // query: {
  391. // row: toFileData.value.row,
  392. // },
  393. // });
  394. return;
  395. }
  396. let regExp = new RegExp(/^\//);
  397. let regFile = new RegExp(/^tofile/);
  398. if (!regExp.test(toRaw(item))) {
  399. const data = JSON.parse(toRaw(item));
  400. console.log("data", data);
  401. router.push({
  402. path: "/fileEdit" + data.docId,
  403. query: {
  404. clickRowId: data.docId,
  405. // copyRow: JSON.stringify(data),
  406. },
  407. });
  408. } else {
  409. router.push({
  410. path: item,
  411. });
  412. }
  413. }, 500);
  414. };
  415. const paneClick = (item) => {
  416. // 可以拿到当前的标签对象
  417. console.log("paneItem", item);
  418. if (item.row) {
  419. // 判断是菜单还是目录
  420. toFileData.value = item;
  421. } else {
  422. toFileData.value = null;
  423. }
  424. };
  425. //创建tab标签事件
  426. const addTab = (data) => {
  427. console.log("addTab", data);
  428. const arr = toRaw(editableTabs.value);
  429. if (!arr.some((item) => item.label == data.fileName)) {
  430. // editableTabs.value.push({
  431. // label: data.fileName,
  432. // path: JSON.stringify(data),
  433. // });
  434. editableTabs.value.push({
  435. label: data.fileName,
  436. path: JSON.stringify(data),
  437. });
  438. //需要jSON去转 否则页面无变化 离谱得很
  439. editableTabs.value = JSON.parse(JSON.stringify(editableTabs.value));
  440. // editableTabsValue.value = data.path;
  441. }
  442. };
  443. const addFolderAdd = (data) => {
  444. console.log("data", data);
  445. const arr = toRaw(editableTabs.value);
  446. if (!arr.some((item) => item.label == data.row.dirName)) {
  447. editableTabs.value.push({
  448. label: data.name,
  449. path: data.path,
  450. clickRowId: data.row,
  451. });
  452. //需要jSON去转 否则页面无变化 离谱得很
  453. editableTabs.value = JSON.parse(JSON.stringify(editableTabs.value));
  454. }
  455. console.log("editableTabs", editableTabs.value);
  456. };
  457. provide("addTab", addTab);
  458. provide("addFolderAdd", addFolderAdd);
  459. // TODO 删除tab事件
  460. const closeTab = (item, index, e) => {
  461. e.preventDefault();
  462. e.stopPropagation();
  463. editableTabs.value.splice(index, 1);
  464. editableTabs.value = JSON.parse(JSON.stringify(editableTabs.value));
  465. const nextTab =
  466. editableTabs.value[index + 1] || editableTabs.value[index - 1];
  467. clickTab(nextTab.path);
  468. // console.log("item", item);
  469. // console.log("index", index);
  470. // console.log("e", e);
  471. };
  472. </script>
  473. <style lang="scss" scoped>
  474. @import "@/assets/styles/mixin.scss";
  475. @import "@/assets/styles/variables.module.scss";
  476. //整体布局css
  477. .common-layout,
  478. .el-container {
  479. height: 94vh;
  480. }
  481. :deep .el-main {
  482. --el-main-padding: 8px !important;
  483. }
  484. .nav {
  485. background: #06286c;
  486. height: 48px;
  487. .nav-top {
  488. width: 98%;
  489. display: flex;
  490. justify-content: space-between;
  491. & > div:first-child {
  492. font-family: "Inter-SemiBold";
  493. }
  494. & > div:first-child,
  495. & > div:last-child {
  496. display: flex;
  497. align-items: center;
  498. color: #fff;
  499. & > img {
  500. width: 48px;
  501. height: 48px;
  502. }
  503. }
  504. }
  505. .head-img {
  506. border-radius: 12px;
  507. width: 24px;
  508. height: 24px;
  509. margin-right: 10px;
  510. }
  511. .avatar-wrapper {
  512. color: #fff;
  513. display: flex;
  514. align-items: center;
  515. }
  516. .search {
  517. .w-50,
  518. :deep .el-input {
  519. width: 400px;
  520. height: 32px;
  521. border-radius: 4px;
  522. margin-top: 8px;
  523. background: #6f85b5 !important;
  524. --el-input-border-color: #6f85b5;
  525. }
  526. ::v-deep .el-input__inner {
  527. color: #fff !important;
  528. }
  529. }
  530. :deep .el-input__wrapper {
  531. background: #1f3f7e !important;
  532. }
  533. }
  534. .asides {
  535. padding: 8px 10px !important;
  536. font-size: 14px;
  537. color: #000;
  538. background: #fff;
  539. }
  540. .main {
  541. background: #c7cbd8;
  542. }
  543. // tabs标签
  544. .tab_box {
  545. width: 100%;
  546. height: 32px;
  547. border-radius: 4px 4px 4px 4px;
  548. background-color: #fff;
  549. margin-bottom: 8px;
  550. .common-tabs {
  551. height: 32px;
  552. // display: flex;
  553. // align-items: center;
  554. }
  555. .tab_pane {
  556. display: flex;
  557. align-items: center;
  558. justify-content: space-between;
  559. img {
  560. margin-left: 8px;
  561. width: 10px;
  562. height: 10px;
  563. }
  564. }
  565. }
  566. :deep(.common-tabs .el-tabs__item) {
  567. height: 24px !important;
  568. padding: 0px 8px !important;
  569. margin-top: 4px !important;
  570. margin-left: 4px !important;
  571. border: 1px solid #c1cce3 !important;
  572. color: #505870 !important;
  573. font-size: 12px !important;
  574. line-height: 24px;
  575. font-weight: 400 !important;
  576. }
  577. // tag选中颜色
  578. :deep(.common-tabs .el-tabs__item.is-active) {
  579. color: #fff !important;
  580. font-weight: normal;
  581. background-color: #6f85b5;
  582. }
  583. //侧边栏css
  584. .acitve-img-style {
  585. background-color: #f5f7f9;
  586. border-radius: 4px;
  587. }
  588. .img-style {
  589. width: 72px;
  590. height: 72px;
  591. display: flex;
  592. margin-bottom: 8px;
  593. flex-direction: column;
  594. align-items: center;
  595. justify-content: center;
  596. & > img {
  597. width: 40px;
  598. height: 40px;
  599. }
  600. }
  601. .text-style {
  602. text-align: center;
  603. color: #000;
  604. }
  605. </style>
  606. <style lang="scss" scoped>
  607. .el-popper.is-light.type_popper {
  608. background-color: #1f3f7e !important;
  609. border-radius: 4px 4px 4px 4px !important;
  610. border: none !important;
  611. // padding: 0 16px !important;
  612. // box-sizing: border-box !important;
  613. }
  614. .el-popper__arrow::before {
  615. content: none;
  616. }
  617. //鼠标移动上去的选中色
  618. .type_popper {
  619. .el-select-dropdown__item.hover,
  620. .el-select-dropdown__item:hover {
  621. background: #6f85b5 !important;
  622. }
  623. //下拉框的文本颜色
  624. .el-select-dropdown__item {
  625. color: #a4b0d8 !important;
  626. }
  627. //选中之后的颜色
  628. .el-select-dropdown__item.selected {
  629. background: #6f85b5 !important;
  630. color: #fff !important;
  631. }
  632. }
  633. .yuandian {
  634. width: 8px;
  635. height: 8px;
  636. position: absolute;
  637. right: 8px;
  638. top: 6px;
  639. background: #fa5151;
  640. border-radius: 4px;
  641. }
  642. </style>