top.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <template>
  2. <a-layout class="layout-top">
  3. <a-layout-header class="m-layout-header">
  4. <div>
  5. <img src="../assets/images/logoHeader.png" />
  6. <span>深圳市多元世纪信息技术股份有限公司</span>
  7. </div>
  8. <div class="m-layout-header-right">
  9. <div @click="openDrawer">
  10. <span>{{ username }},您好!</span>
  11. </div>
  12. <div class="relative">
  13. <!-- <a-input-search ref="userNameInput"
  14. class="searchInput"
  15. readonly
  16. placeholder="请输入代码/名称"
  17. @pressEnter="search">
  18. </a-input-search> -->
  19. <!-- <a-icon type="search" /> -->
  20. </div>
  21. <div class="news-container">
  22. <a-badge @click="openNotice">
  23. <svg class="icon svg-icon" aria-hidden="true">
  24. <use xlink:href="#icon-xiaoxi"></use>
  25. </svg>
  26. </a-badge>
  27. </div>
  28. <div>
  29. <a-popover v-model:visible="visible" trigger="click" placement="bottomRight">
  30. <template #content>
  31. <div v-for="item in setMenu" @click="chooseSetMenu(item.path)" :key="item.path">{{ item.name }}</div>
  32. </template>
  33. <a-avatar :size="24">
  34. <template #icon>
  35. <UserOutlined />
  36. </template>
  37. </a-avatar>
  38. </a-popover>
  39. <Setting />
  40. </div>
  41. </div>
  42. </a-layout-header>
  43. <a-layout class="middleLayout">
  44. <a-layout-sider class="m-layout-left" width="180" v-model:collapsed="collapsed" @collapse="collapse" collapsible>
  45. <a-menu theme="dark" mode="inline" class="left-menu" v-model:selectedKeys="selectedKeys" v-model:openKeys="openKeys" @click="menuClick">
  46. <a-sub-menu v-for="item in menuList" :key="item.code">
  47. <template #title>
  48. <span>
  49. <svg class="icon svg-icon" aria-hidden="true">
  50. <use :xlink:href="fontIcon(item.code)"></use>
  51. </svg>
  52. <span class="menu-item_title" v-show="!collapsed">{{ item.title }}</span>
  53. </span>
  54. </template>
  55. <a-menu-item :key="subItem.code" v-for="subItem in item.children">
  56. <span>{{ subItem.title }}</span>
  57. </a-menu-item>
  58. </a-sub-menu>
  59. </a-menu>
  60. </a-layout-sider>
  61. <a-layout-content :style="{ background: '#0E0E0F', flex: 1 }">
  62. <Drawer :title="'挂牌'" :visible="visible"></Drawer>
  63. <!-- <Main /> -->
  64. <router-view />
  65. </a-layout-content>
  66. </a-layout>
  67. </a-layout>
  68. </template>
  69. <script lang="ts">
  70. import { UserOutlined } from '@ant-design/icons-vue';
  71. import { defineComponent, ref, provide, unref } from 'vue';
  72. import Setting from '@/views/setting/index.vue';
  73. import CapitalInfo from '@/common/components/capitalInfo/index.vue';
  74. import SecondMenu from '@/common/components/secondeMenu/index.vue';
  75. import APP from '@/services';
  76. import { initData } from '@/common/methods';
  77. import { useRouter } from 'vue-router';
  78. import { openModal } from '@/common/setup/modal/index';
  79. import Drawer from '@/common/components/drawer/index.vue';
  80. import Main from './main.vue';
  81. // 菜单栏
  82. const handleMenu = () => {
  83. const collapsed = ref<boolean>(false);
  84. const selectedKeys = ref<string[]>(['1-1']);
  85. const openKeys = ref<string[]>(['1']);
  86. const preOpenKeys = ref<string[]>(['1']);
  87. const menuList = APP.getRef('menus');
  88. // const menuList = [
  89. // {
  90. // key: '1',
  91. // title: '市场',
  92. // code: 'market',
  93. // children: [
  94. // {
  95. // key: '1-1',
  96. // title: '现货贸易',
  97. // code: ''
  98. // },
  99. // ],
  100. // },
  101. // {
  102. // key: '2',
  103. // title: '查询',
  104. // code: 'search',
  105. // children: [
  106. // {
  107. // key: '2-1',
  108. // title: '单据记录',
  109. // code: ''
  110. // },
  111. // {
  112. // key: '2-2',
  113. // title: '资金流水',
  114. // code: ''
  115. // },
  116. // {
  117. // key: '2-3',
  118. // title: '出入库',
  119. // code: ''
  120. // },
  121. // {
  122. // key: '2-4',
  123. // title: '登录日志',
  124. // code: ''
  125. // },
  126. // ],
  127. // },
  128. // {
  129. // key: '3',
  130. // title: '报表',
  131. // code: 'report'
  132. // },
  133. // ];
  134. const router = useRouter();
  135. // 控制菜单是否隐藏
  136. function collapse(collapsed: boolean) {
  137. if (collapsed) {
  138. preOpenKeys.value = openKeys.value;
  139. openKeys.value = [];
  140. } else {
  141. openKeys.value = preOpenKeys.value;
  142. }
  143. }
  144. // 配置是否显示下半部分
  145. function setShowBottomPart(code: string): boolean {
  146. // 显示下半部分 这里保存的是市场对应的 code
  147. const show: string[] = [''];
  148. return show.includes(code);
  149. }
  150. function menuClick(value: any) {
  151. console.log('菜单: ', value);
  152. const key = value.key;
  153. setShowBottomPart(key);
  154. router.push({ name: key });
  155. }
  156. // 一级菜单图标
  157. function fontIcon(code: string): string {
  158. let result = 'icon-jinrongfenxi';
  159. switch (code) {
  160. case 'market':
  161. result = 'icon-jinrongfenxi';
  162. break;
  163. case 'info':
  164. result = 'icon-zhangdan';
  165. break;
  166. case 'business':
  167. result = 'icon-renwu';
  168. break;
  169. case 'manage':
  170. result = 'icon-quanxian';
  171. break;
  172. case 'search':
  173. result = 'icon-chazhaojilu';
  174. break;
  175. case 'report':
  176. result = 'icon-bingtu';
  177. break;
  178. }
  179. return '#' + result;
  180. }
  181. return { collapsed, selectedKeys, menuList, openKeys, collapse, menuClick, setShowBottomPart, fontIcon };
  182. };
  183. function testAction() {
  184. const { openAction } = openModal('drawer');
  185. return { openDrawer: openAction };
  186. }
  187. // 设置
  188. const setFn = () => {
  189. const visible = ref<boolean>(false);
  190. const chooseSetupItem = ref<string>('');
  191. provide('ControlModal', chooseSetupItem);
  192. const setMenu = [
  193. // { name: '修改密码', path: 'password' },
  194. // { name: '收货地址', path: 'addresss' },
  195. // // {name: '发票', path: 'setup-password'},
  196. // { name: '手机号码绑定/解绑', path: 'phone' },
  197. // { name: '关于我们', path: 'aboutUs' },
  198. { name: '退出', path: 'logout' },
  199. ];
  200. const { openAction } = openModal('logout');
  201. function chooseSetMenu(path: string) {
  202. // chooseSetupItem.value = path;
  203. openAction();
  204. console.log(path);
  205. visible.value = false;
  206. }
  207. return { visible, setMenu, chooseSetMenu };
  208. };
  209. // 搜索
  210. const onSearch = () => {
  211. function search(value: string) {
  212. console.log(value);
  213. }
  214. return { search };
  215. };
  216. // 控制消息弹窗
  217. function controlNotice() {
  218. const { openAction } = openModal('notice');
  219. return { openNotice: openAction };
  220. }
  221. export default defineComponent({
  222. name: 'layout-top',
  223. components: {
  224. Setting,
  225. UserOutlined,
  226. CapitalInfo,
  227. SecondMenu,
  228. Drawer,
  229. Main,
  230. },
  231. setup(props, context) {
  232. const { collapsed, selectedKeys, openKeys, menuList, collapse, menuClick, setShowBottomPart, fontIcon } = handleMenu();
  233. const router = useRouter();
  234. // 控制消息弹窗
  235. const { openNotice } = controlNotice();
  236. initData(() => {
  237. // 处理路由跳转到菜单栏里第一个对应的页面
  238. const list = unref(menuList);
  239. if (list.length && list[0].children && list[0].children.length) {
  240. // 处理修改具体某个菜单栏,主要处理页面刷新
  241. let firstIndex = 0,
  242. secondeIndex = 0;
  243. for (let i = 0; i < list.length; i++) {
  244. for (let j = 0; j < list[i].children.length; j++) {
  245. if (window.location.hash.includes(list[i].children[j].code)) {
  246. firstIndex = i;
  247. secondeIndex = j;
  248. break;
  249. }
  250. }
  251. }
  252. const code = list[firstIndex].children[secondeIndex].code;
  253. // selectedKeys.value.length = 0;
  254. // selectedKeys.value.push(code);
  255. // openKeys.value.length = 0;
  256. // openKeys.value.push(list[firstIndex].code);
  257. selectedKeys.value = [code];
  258. openKeys.value = [list[firstIndex].code];
  259. context.emit('chooseMenu', setShowBottomPart(code));
  260. // 处理页面刷新时候 引发路由乱跳的bug
  261. if (router.currentRoute.value.fullPath === '/home') {
  262. router.push(code);
  263. } else {
  264. }
  265. }
  266. });
  267. const { openDrawer } = testAction();
  268. const { visible, setMenu, chooseSetMenu } = setFn();
  269. const username = APP.get('username');
  270. const { search } = onSearch();
  271. const searchName = ref<string[]>(['']);
  272. return {
  273. collapsed,
  274. collapse,
  275. selectedKeys,
  276. openKeys,
  277. menuClick,
  278. username,
  279. menuList,
  280. visible,
  281. setMenu,
  282. chooseSetMenu,
  283. fontIcon,
  284. openNotice,
  285. openDrawer,
  286. };
  287. },
  288. });
  289. </script>
  290. <style lang="less">
  291. .layout-top {
  292. .flex;
  293. width: 100%;
  294. height: 100%;
  295. flex-direction: column;
  296. .m-layout-header {
  297. width: 100%;
  298. height: 40px;
  299. line-height: 40px;
  300. background: @m-grey0;
  301. color: @m-grey1;
  302. padding: 0 20px;
  303. .flex();
  304. justify-content: space-between;
  305. img {
  306. margin-right: 16px;
  307. width: 20px;
  308. height: 20px;
  309. }
  310. .searchInput.ant-input-affix-wrapper {
  311. width: 240px;
  312. height: 30px;
  313. line-height: 30px;
  314. font-size: 14px;
  315. background: @m-grey9;
  316. border: 0;
  317. vertical-align: middle;
  318. padding-left: 40px;
  319. position: relative;
  320. .rounded-corners(15px);
  321. .ant-input {
  322. background: @m-grey9;
  323. color: @m-white0;
  324. }
  325. .ant-input-suffix {
  326. margin-left: -215px;
  327. .ant-input-search-icon {
  328. color: @m-grey10;
  329. }
  330. }
  331. }
  332. // .relative {
  333. // position: relative;
  334. // .a-icon {
  335. // font-size: 14px;
  336. // .position(absolute, 50%, auto, auto, 10px);
  337. // margin-top: -7px;
  338. // color: @m-grey10;
  339. // z-index: 10;
  340. // }
  341. // }
  342. .m-layout-header-right {
  343. .flex();
  344. .news-container {
  345. padding-left: 10px;
  346. padding-right: 16px;
  347. .ant-badge {
  348. margin-top: 7px;
  349. cursor: pointer;
  350. > svg {
  351. font-size: 24px;
  352. }
  353. .ant-badge-dot {
  354. box-shadow: 0 0 0 1px @m-red0;
  355. }
  356. }
  357. }
  358. .ant-avatar-icon {
  359. margin-top: -3px;
  360. }
  361. }
  362. }
  363. .middleLayout {
  364. flex: 1;
  365. width: 100%;
  366. .inlineflex;
  367. border-bottom: 1px solid @m-black2;
  368. .m-layout-left {
  369. height: 100%;
  370. background: @m-black4;
  371. .ant-layout-sider-children {
  372. ul.ant-menu.ant-menu-inline {
  373. li.ant-menu-submenu {
  374. padding-bottom: 0;
  375. .ant-menu-submenu-title {
  376. color: @m-grey2;
  377. font-size: 16px;
  378. height: 60px;
  379. line-height: 60px;
  380. margin-top: 0;
  381. margin-bottom: 0;
  382. padding: 5px 0;
  383. .icon {
  384. font-size: 20px;
  385. }
  386. .menu-item_title {
  387. display: inline-block;
  388. font-size: 16px;
  389. margin-left: 15px;
  390. }
  391. }
  392. .ant-menu-sub {
  393. .ant-menu-item {
  394. padding-left: 60px !important;
  395. margin-top: 5px;
  396. margin-bottom: 5px;
  397. }
  398. }
  399. }
  400. li.ant-menu-submenu-open {
  401. .ant-menu-submenu-title {
  402. color: @m-white0;
  403. .icon {
  404. color: @m-white0;
  405. }
  406. }
  407. .ant-menu-sub {
  408. .ant-menu-item.ant-menu-item-selected {
  409. background-color: @m-blue0;
  410. }
  411. }
  412. }
  413. }
  414. }
  415. .ant-layout-sider-trigger {
  416. width: 100%;
  417. height: 40px;
  418. line-height: 40px;
  419. background: @m-black0;
  420. position: absolute;
  421. }
  422. }
  423. .ant-menu-vertical {
  424. .ant-menu-submenu-vertical {
  425. height: 60px;
  426. line-height: 60px;
  427. padding: 5px 0;
  428. .ant-menu-submenu-title {
  429. height: 50px;
  430. line-height: 50px;
  431. .icon {
  432. font-size: 20px;
  433. }
  434. }
  435. }
  436. .ant-menu-submenu {
  437. .ant-menu-submenu-title {
  438. .menu-item_title {
  439. display: none;
  440. }
  441. }
  442. }
  443. }
  444. }
  445. .bottomLayout {
  446. width: 100%;
  447. flex: none;
  448. height: @bottomHeight;
  449. .inlineflex;
  450. }
  451. }
  452. </style>