indexCommon.vue 16 KB

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