YY hace 2 años
padre
commit
97ceec30ca
Se han modificado 47 ficheros con 2876 adiciones y 190 borrados
  1. 13 10
      index.html
  2. BIN
      src/assets/banner.png
  3. 0 74
      src/assets/base.css
  4. 55 0
      src/assets/css/color-dark.css
  5. 4 0
      src/assets/css/icon.css
  6. 177 0
      src/assets/css/main.css
  7. 62 0
      src/assets/css/theme-ele/color-ele.css
  8. BIN
      src/assets/css/theme-ele/fonts/element-icons.ttf
  9. BIN
      src/assets/css/theme-ele/fonts/element-icons.woff
  10. 1 0
      src/assets/css/theme-ele/index.css
  11. 62 0
      src/assets/css/theme-green/color-green.css
  12. BIN
      src/assets/css/theme-green/fonts/element-icons.ttf
  13. BIN
      src/assets/css/theme-green/fonts/element-icons.woff
  14. 1 0
      src/assets/css/theme-green/index.css
  15. 63 0
      src/assets/css/theme-pink/color-pink.css
  16. BIN
      src/assets/css/theme-pink/fonts/element-icons.ttf
  17. BIN
      src/assets/css/theme-pink/fonts/element-icons.woff
  18. 1 0
      src/assets/css/theme-pink/index.css
  19. 62 0
      src/assets/css/theme-red/color-red.css
  20. BIN
      src/assets/css/theme-red/fonts/element-icons.ttf
  21. BIN
      src/assets/css/theme-red/fonts/element-icons.woff
  22. 1 0
      src/assets/css/theme-red/index.css
  23. 191 0
      src/assets/icon/iconfont.css
  24. 1 0
      src/assets/icon/iconfont.js
  25. 317 0
      src/assets/icon/iconfont.json
  26. BIN
      src/assets/icon/iconfont.ttf
  27. BIN
      src/assets/icon/iconfont.woff
  28. BIN
      src/assets/icon/iconfont.woff2
  29. BIN
      src/assets/img/img.jpg
  30. BIN
      src/assets/logo.png
  31. 0 1
      src/assets/logo.svg
  32. 0 35
      src/assets/main.css
  33. BIN
      src/assets/top-1.png
  34. 26 26
      src/components/admin-frame/home.vue
  35. 83 0
      src/components/admin-frame/parts/Header.vue
  36. 202 0
      src/components/admin-frame/parts/Sidebar.vue
  37. 202 0
      src/components/admin-frame/parts/Tags.vue
  38. 23 0
      src/components/admin-frame/parts/breadcrumb.vue
  39. 991 0
      src/layout/menu.ts
  40. 57 36
      src/layout/site.ts
  41. 15 4
      src/main.ts
  42. 54 0
      src/stores/system/role.ts
  43. 6 0
      src/stores/user/mutations.ts
  44. 1 0
      src/stores/user/state.ts
  45. 150 0
      src/util/axios-wrapper.ts
  46. 29 0
      src/util/types.util.ts
  47. 26 4
      tsconfig.json

+ 13 - 10
index.html

@@ -1,13 +1,16 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
-  <head>
-    <meta charset="UTF-8">
-    <link rel="icon" href="/favicon.ico">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Vite App</title>
-  </head>
-  <body>
-    <div id="app"></div>
-    <script type="module" src="/src/main.ts"></script>
-  </body>
+
+<head>
+  <meta charset="UTF-8">
+  <link rel="icon" href="/favicon.ico">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Vite App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+
 </html>
 </html>

BIN
src/assets/banner.png


+ 0 - 74
src/assets/base.css

@@ -1,74 +0,0 @@
-/* color palette from <https://github.com/vuejs/theme> */
-:root {
-  --vt-c-white: #ffffff;
-  --vt-c-white-soft: #f8f8f8;
-  --vt-c-white-mute: #f2f2f2;
-
-  --vt-c-black: #181818;
-  --vt-c-black-soft: #222222;
-  --vt-c-black-mute: #282828;
-
-  --vt-c-indigo: #2c3e50;
-
-  --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
-  --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
-  --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
-  --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
-
-  --vt-c-text-light-1: var(--vt-c-indigo);
-  --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
-  --vt-c-text-dark-1: var(--vt-c-white);
-  --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
-}
-
-/* semantic color variables for this project */
-:root {
-  --color-background: var(--vt-c-white);
-  --color-background-soft: var(--vt-c-white-soft);
-  --color-background-mute: var(--vt-c-white-mute);
-
-  --color-border: var(--vt-c-divider-light-2);
-  --color-border-hover: var(--vt-c-divider-light-1);
-
-  --color-heading: var(--vt-c-text-light-1);
-  --color-text: var(--vt-c-text-light-1);
-
-  --section-gap: 160px;
-}
-
-@media (prefers-color-scheme: dark) {
-  :root {
-    --color-background: var(--vt-c-black);
-    --color-background-soft: var(--vt-c-black-soft);
-    --color-background-mute: var(--vt-c-black-mute);
-
-    --color-border: var(--vt-c-divider-dark-2);
-    --color-border-hover: var(--vt-c-divider-dark-1);
-
-    --color-heading: var(--vt-c-text-dark-1);
-    --color-text: var(--vt-c-text-dark-2);
-  }
-}
-
-*,
-*::before,
-*::after {
-  box-sizing: border-box;
-  margin: 0;
-  position: relative;
-  font-weight: normal;
-}
-
-body {
-  min-height: 100vh;
-  color: var(--color-text);
-  background: var(--color-background);
-  transition: color 0.5s, background-color 0.5s;
-  line-height: 1.6;
-  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
-    Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-  font-size: 15px;
-  text-rendering: optimizeLegibility;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}

+ 55 - 0
src/assets/css/color-dark.css

@@ -0,0 +1,55 @@
+.header {
+  background-color: #242f42 !important;
+}
+.login-wrap {
+  background: #324157;
+}
+.plugins-tips {
+  background: #eef1f6;
+}
+.plugins-tips a {
+  color: #20a0ff;
+}
+.el-upload--text em {
+  color: #20a0ff;
+}
+.pure-button {
+  background: #20a0ff;
+}
+.tags-li.active {
+  border: 1px solid #409eff;
+  background-color: #409eff;
+}
+.message-title {
+  color: #20a0ff;
+}
+.collapse-btn:hover {
+  background: rgb(40, 52, 70);
+}
+
+.sidebar {
+  background-color: #242f42 !important;
+}
+.sidebar-el-menu:not(.el-menu--collapse) {
+  background-color: #242f42 !important;
+}
+.el-menu-item:hover {
+  background-color: #142832 !important;
+}
+.el-menu-item {
+  color: #ffffff;
+  background-color: #242f42 !important;
+}
+.el-menu-item.is-active {
+  background-color: #142832 !important;
+}
+.el-submenu__title *{
+  color: #ffffff;
+}
+.el-submenu__title:hover {
+  background-color: #142832 !important;
+}
+
+.el-submenu__title{
+  background-color: #242f42 !important;
+}

+ 4 - 0
src/assets/css/icon.css

@@ -0,0 +1,4 @@
+
+    [class*=" el-icon-lx"], [class^=el-icon-lx] {
+        font-family: lx-iconfont!important;
+    }

+ 177 - 0
src/assets/css/main.css

@@ -0,0 +1,177 @@
+* {
+    margin: 0;
+    padding: 0;
+}
+
+html,
+body,
+#app,
+.wrapper {
+    width: 100%;
+    height: 100%;
+    overflow-y: auto;
+}
+
+body {
+    font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif;
+}
+
+a {
+    text-decoration: none
+}
+
+
+.content-box {
+    position: absolute;
+    left: 200px;
+    right: 0;
+    top: 60px;
+    bottom: 0;
+    padding-bottom: 30px;
+    -webkit-transition: left .3s ease-in-out;
+    transition: left .3s ease-in-out;
+    background: #f0f0f0;
+}
+
+.content {
+    width: 100%;
+    height: 100%;
+    padding: 10px;
+    overflow-y: scroll;
+    box-sizing: border-box;
+}
+
+.content-collapse {
+    left: 65px;
+}
+
+.container {
+    padding: 30px;
+    background: #fff;
+    border: 1px solid #ddd;
+    border-radius: 5px;
+}
+
+.crumbs {
+    margin: 10px 0;
+}
+
+.el-table th {
+    background-color: #f5f7fa !important;
+}
+
+.pagination {
+    margin: 20px 0;
+    text-align: right;
+}
+
+.plugins-tips {
+    padding: 20px 10px;
+    margin-bottom: 20px;
+}
+
+.el-button+.el-tooltip {
+    margin-left: 10px;
+}
+
+.el-table tr:hover {
+    background: #f6faff;
+}
+
+.mgb20 {
+    margin-bottom: 20px;
+}
+
+.move-enter-active,
+.move-leave-active {
+    transition: opacity .5s;
+}
+
+.move-enter,
+.move-leave {
+    opacity: 0;
+}
+
+/*BaseForm*/
+
+.form-box {
+    width: 600px;
+}
+
+.form-box .line {
+    text-align: center;
+}
+
+.el-time-panel__content::after,
+.el-time-panel__content::before {
+    margin-top: -7px;
+}
+
+.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) {
+    padding-bottom: 0;
+}
+
+/*Upload*/
+
+.pure-button {
+    width: 150px;
+    height: 40px;
+    line-height: 40px;
+    text-align: center;
+    color: #fff;
+    border-radius: 3px;
+}
+
+.g-core-image-corp-container .info-aside {
+    height: 45px;
+}
+
+.el-upload--text {
+    background-color: #fff;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    box-sizing: border-box;
+    width: 360px;
+    height: 180px;
+    text-align: center;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+}
+
+.el-upload--text .el-icon-upload {
+    font-size: 67px;
+    color: #97a8be;
+    margin: 40px 0 16px;
+    line-height: 50px;
+}
+
+.el-upload--text {
+    color: #97a8be;
+    font-size: 14px;
+    text-align: center;
+}
+
+.el-upload--text em {
+    font-style: normal;
+}
+
+/*VueEditor*/
+
+.ql-container {
+    min-height: 400px;
+}
+
+.ql-snow .ql-tooltip {
+    transform: translateX(117.5px) translateY(10px) !important;
+}
+
+.editor-btn {
+    margin-top: 20px;
+}
+
+/*markdown*/
+
+.v-note-wrapper .v-note-panel {
+    min-height: 500px;
+}

+ 62 - 0
src/assets/css/theme-ele/color-ele.css

@@ -0,0 +1,62 @@
+.header {
+  background-color: #409eff !important;
+}
+.login-wrap {
+  background: rgba(56, 157, 170, 0.82);
+}
+.plugins-tips {
+  background: #f2f2f2;
+}
+.plugins-tips a {
+  color: #409eff;
+}
+.el-upload--text em {
+  color: #409eff;
+}
+.pure-button {
+  background: #409eff;
+}
+.pagination > .active > a,
+.pagination > .active > a:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span,
+.pagination > .active > span:hover,
+.pagination > .active > span:focus {
+  background-color: #409eff !important;
+  border-color: #409eff !important;
+}
+.tags-li.active {
+  border: 1px solid #409eff !important;
+  background-color: #409eff !important;
+}
+.collapse-btn:hover {
+  background: #409eff;
+}
+
+.sidebar {
+  background-color: #409eff !important;
+}
+.el-menu {
+  background-color: #409eff !important;
+}
+.el-menu-item.is-active {
+  color: #ffffff;
+  background-color: #403aff !important;
+}
+.el-menu-item:hover {
+  background-color: #403aff !important;
+}
+.sidebar-el-menu:not(.el-menu--collapse) {
+  background-color: #409eff !important;
+}
+.el-submenu__title:hover {
+  background-color: #403aff !important;
+}
+.el-submenu__title {
+  background-color: #409eff !important;
+}
+
+.el-menu-item {
+  background-color: #409eff !important;
+  color: #ffffff;
+}

BIN
src/assets/css/theme-ele/fonts/element-icons.ttf


BIN
src/assets/css/theme-ele/fonts/element-icons.woff


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
src/assets/css/theme-ele/index.css


+ 62 - 0
src/assets/css/theme-green/color-green.css

@@ -0,0 +1,62 @@
+.header {
+  background-color: #07c4a8 !important;
+}
+.login-wrap {
+  background: rgba(56, 157, 170, 0.82);
+}
+.plugins-tips {
+  background: #f2f2f2;
+}
+.plugins-tips a {
+  color: #00d1b2;
+}
+.el-upload--text em {
+  color: #00d1b2;
+}
+.pure-button {
+  background: #00d1b2;
+}
+.pagination > .active > a,
+.pagination > .active > a:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span,
+.pagination > .active > span:hover,
+.pagination > .active > span:focus {
+  background-color: #00d1b2 !important;
+  border-color: #00d1b2 !important;
+}
+.tags-li.active {
+  border: 1px solid #00d1b2 !important;
+  background-color: #00d1b2 !important;
+}
+.collapse-btn:hover {
+  background: #00d1b2;
+}
+
+.sidebar {
+  background-color: #00d1b2 !important;
+}
+.el-menu {
+  background-color: #00d1b2 !important;
+}
+.el-menu-item.is-active {
+  color: #000000;
+  background-color: #00a78e !important;
+}
+.el-menu-item:hover {
+  background-color: #00a78e !important;
+}
+.sidebar-el-menu:not(.el-menu--collapse) {
+  background-color: #00d1b2 !important;
+}
+.el-submenu__title:hover {
+  background-color: #00a78e !important;
+}
+.el-submenu__title {
+  background-color: #07c4a8 !important;
+}
+
+.el-menu-item {
+  background-color: #07c4a8 !important;
+  color: #ffffff;
+}

BIN
src/assets/css/theme-green/fonts/element-icons.ttf


BIN
src/assets/css/theme-green/fonts/element-icons.woff


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
src/assets/css/theme-green/index.css


+ 63 - 0
src/assets/css/theme-pink/color-pink.css

@@ -0,0 +1,63 @@
+.header {
+  background-color: #D23CE6 !important;
+}
+.login-wrap {
+  background: rgba(56, 157, 170, 0.82);
+}
+.plugins-tips {
+  background: #f2f2f2;
+}
+.plugins-tips a {
+  color: #D23CE6;
+}
+.el-upload--text em {
+  color: #D23CE6;
+}
+.pure-button {
+  background: #D23CE6;
+}
+.pagination > .active > a,
+.pagination > .active > a:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span,
+.pagination > .active > span:hover,
+.pagination > .active > span:focus {
+  background-color: #D23CE6 !important;
+  border-color: #D23CE6 !important;
+}
+.tags-li.active {
+  border: 1px solid #D23CE6 !important;
+  background-color: #D23CE6 !important;
+}
+.collapse-btn:hover {
+  background: #D23CE6;
+}
+
+.sidebar {
+  background-color: #D23CE6 !important;
+}
+.el-menu {
+  background-color: #D23CE6 !important;
+}
+.el-menu-item.is-active {
+  color: #ffffff;
+  background-color: #963CE6 !important;
+}
+.el-menu-item:hover{
+   background-color: #963CE6 !important;
+}
+.sidebar-el-menu:not(.el-menu--collapse) {
+  background-color: #D23CE6 !important;
+}
+
+.el-submenu__title:hover {
+  background-color: #D23CE6 !important;
+}
+.el-submenu__title {
+  background-color: #D23CE6 !important;
+}
+
+.el-menu-item {
+  background-color: #D23CE6 !important;
+  color: #ffffff;
+}

BIN
src/assets/css/theme-pink/fonts/element-icons.ttf


BIN
src/assets/css/theme-pink/fonts/element-icons.woff


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
src/assets/css/theme-pink/index.css


+ 62 - 0
src/assets/css/theme-red/color-red.css

@@ -0,0 +1,62 @@
+.header {
+  background-color: #e31d33 !important;
+}
+.login-wrap {
+  background: rgba(56, 157, 170, 0.82);
+}
+.plugins-tips {
+  background: #f2f2f2;
+}
+.plugins-tips a {
+  color: #e31d33;
+}
+.el-upload--text em {
+  color: #e31d33;
+}
+.pure-button {
+  background: #e31d33;
+}
+.pagination > .active > a,
+.pagination > .active > a:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span,
+.pagination > .active > span:hover,
+.pagination > .active > span:focus {
+  background-color: #e31d33 !important;
+  border-color: #e31d33 !important;
+}
+.tags-li.active {
+  border: 1px solid #e31d33 !important;
+  background-color: #e31d33 !important;
+}
+.collapse-btn:hover {
+  background: #e31d33;
+}
+
+.sidebar {
+  background-color: #e31d33 !important;
+}
+.el-menu {
+  background-color: #e31d33 !important;
+}
+.el-menu-item.is-active {
+  color: #ffffff;
+  background-color: #640F33 !important;
+}
+.el-menu-item:hover{
+   background-color: #640F33 !important;
+}
+.sidebar-el-menu:not(.el-menu--collapse) {
+  background-color: #e31d33 !important;
+}
+.el-submenu__title {
+  background-color: #e31d33 !important;
+}
+.el-submenu__title:hover {
+  background-color: #640F33 !important;
+}
+
+.el-menu-item {
+  background-color: #e31d33 !important;
+  color: #ffffff;
+}

BIN
src/assets/css/theme-red/fonts/element-icons.ttf


BIN
src/assets/css/theme-red/fonts/element-icons.woff


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
src/assets/css/theme-red/index.css


+ 191 - 0
src/assets/icon/iconfont.css

@@ -0,0 +1,191 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 1865865 */
+  src: url('iconfont.woff2?t=1650275906057') format('woff2'),
+       url('iconfont.woff?t=1650275906057') format('woff'),
+       url('iconfont.ttf?t=1650275906057') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.iconshijian:before {
+  content: "\e91e";
+}
+
+.iconshenhe:before {
+  content: "\e645";
+}
+
+.iconliebiaoxingshi:before {
+  content: "\e742";
+}
+
+.iconpingfen:before {
+  content: "\e948";
+}
+
+.iconhuishenzhong:before {
+  content: "\e60c";
+}
+
+.iconziliaoku:before {
+  content: "\e62d";
+}
+
+.icondaifabu:before {
+  content: "\e70b";
+}
+
+.iconyifabu:before {
+  content: "\e626";
+}
+
+.iconwenjuan:before {
+  content: "\e636";
+}
+
+.iconinformation-delivery:before {
+  content: "\e657";
+}
+
+.iconshenbao:before {
+  content: "\e6ef";
+}
+
+.iconchengguo:before {
+  content: "\e7af";
+}
+
+.iconyuyuefuwu:before {
+  content: "\e7ce";
+}
+
+.iconzhengji:before {
+  content: "\e6d1";
+}
+
+.iconicon-test1:before {
+  content: "\e6e0";
+}
+
+.iconicon_xinyong_xianxing_jijin-:before {
+  content: "\e60a";
+}
+
+.iconlianxiwomen:before {
+  content: "\e64a";
+}
+
+.icon111:before {
+  content: "\e602";
+}
+
+.iconwenxintishi:before {
+  content: "\e6cc";
+}
+
+.iconkefu:before {
+  content: "\e61a";
+}
+
+.iconicon-test:before {
+  content: "\e627";
+}
+
+.iconjiaoyu:before {
+  content: "\e61b";
+}
+
+.iconjianjie:before {
+  content: "\e616";
+}
+
+.iconzhubanfangrenzheng:before {
+  content: "\e603";
+}
+
+.iconzhubanfang:before {
+  content: "\e60f";
+}
+
+.icongerenzhongxin:before {
+  content: "\e638";
+}
+
+.icondajiangtang:before {
+  content: "\e609";
+}
+
+.iconmaikefeng-tianchong:before {
+  content: "\e64c";
+}
+
+.iconyijianfenxiang:before {
+  content: "\e600";
+}
+
+.iconfenxiang:before {
+  content: "\e63c";
+}
+
+.iconmaikefeng:before {
+  content: "\eb4a";
+}
+
+.iconshexiangtou:before {
+  content: "\e625";
+}
+
+.iconzhuangtai:before {
+  content: "\e655";
+}
+
+.iconfangjian1:before {
+  content: "\e617";
+}
+
+.iconshouye:before {
+  content: "\e615";
+}
+
+.iconfangjian:before {
+  content: "\e613";
+}
+
+.iconyonghu:before {
+  content: "\e608";
+}
+
+.iconzhibo:before {
+  content: "\e60b";
+}
+
+.icontongji:before {
+  content: "\e64b";
+}
+
+.iconquanxian:before {
+  content: "\e7ae";
+}
+
+.iconicon-person:before {
+  content: "\e607";
+}
+
+.iconbangding:before {
+  content: "\e72b";
+}
+
+.iconmima_huaban1:before {
+  content: "\e605";
+}
+
+.iconiconfront-:before {
+  content: "\e621";
+}
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
src/assets/icon/iconfont.js


+ 317 - 0
src/assets/icon/iconfont.json

@@ -0,0 +1,317 @@
+{
+  "id": "1865865",
+  "name": "直播平台",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon",
+  "description": "直播后台",
+  "glyphs": [
+    {
+      "icon_id": "9833351",
+      "name": "时间",
+      "font_class": "shijian",
+      "unicode": "e91e",
+      "unicode_decimal": 59678
+    },
+    {
+      "icon_id": "5064095",
+      "name": "审核",
+      "font_class": "shenhe",
+      "unicode": "e645",
+      "unicode_decimal": 58949
+    },
+    {
+      "icon_id": "577346",
+      "name": "列表形式",
+      "font_class": "liebiaoxingshi",
+      "unicode": "e742",
+      "unicode_decimal": 59202
+    },
+    {
+      "icon_id": "6712377",
+      "name": "评分",
+      "font_class": "pingfen",
+      "unicode": "e948",
+      "unicode_decimal": 59720
+    },
+    {
+      "icon_id": "26503293",
+      "name": "会审中",
+      "font_class": "huishenzhong",
+      "unicode": "e60c",
+      "unicode_decimal": 58892
+    },
+    {
+      "icon_id": "4314088",
+      "name": "资料库",
+      "font_class": "ziliaoku",
+      "unicode": "e62d",
+      "unicode_decimal": 58925
+    },
+    {
+      "icon_id": "7736560",
+      "name": "待发布",
+      "font_class": "daifabu",
+      "unicode": "e70b",
+      "unicode_decimal": 59147
+    },
+    {
+      "icon_id": "10936701",
+      "name": "已发布",
+      "font_class": "yifabu",
+      "unicode": "e626",
+      "unicode_decimal": 58918
+    },
+    {
+      "icon_id": "1048271",
+      "name": "问卷调查",
+      "font_class": "wenjuan",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "2727674",
+      "name": "信息发布",
+      "font_class": "information-delivery",
+      "unicode": "e657",
+      "unicode_decimal": 58967
+    },
+    {
+      "icon_id": "8574234",
+      "name": "申报",
+      "font_class": "shenbao",
+      "unicode": "e6ef",
+      "unicode_decimal": 59119
+    },
+    {
+      "icon_id": "15861741",
+      "name": "成果",
+      "font_class": "chengguo",
+      "unicode": "e7af",
+      "unicode_decimal": 59311
+    },
+    {
+      "icon_id": "16137390",
+      "name": "预约服务",
+      "font_class": "yuyuefuwu",
+      "unicode": "e7ce",
+      "unicode_decimal": 59342
+    },
+    {
+      "icon_id": "16392817",
+      "name": "征集",
+      "font_class": "zhengji",
+      "unicode": "e6d1",
+      "unicode_decimal": 59089
+    },
+    {
+      "icon_id": "1810267",
+      "name": "关闭",
+      "font_class": "icon-test1",
+      "unicode": "e6e0",
+      "unicode_decimal": 59104
+    },
+    {
+      "icon_id": "9696382",
+      "name": "信用信息管理、信息管理类",
+      "font_class": "icon_xinyong_xianxing_jijin-",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "1831603",
+      "name": "联系我们",
+      "font_class": "lianxiwomen",
+      "unicode": "e64a",
+      "unicode_decimal": 58954
+    },
+    {
+      "icon_id": "43407",
+      "name": "专家",
+      "font_class": "111",
+      "unicode": "e602",
+      "unicode_decimal": 58882
+    },
+    {
+      "icon_id": "250687",
+      "name": "温馨提示-",
+      "font_class": "wenxintishi",
+      "unicode": "e6cc",
+      "unicode_decimal": 59084
+    },
+    {
+      "icon_id": "551592",
+      "name": "客服",
+      "font_class": "kefu",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "3745064",
+      "name": "会议",
+      "font_class": "icon-test",
+      "unicode": "e627",
+      "unicode_decimal": 58919
+    },
+    {
+      "icon_id": "8027282",
+      "name": "教育",
+      "font_class": "jiaoyu",
+      "unicode": "e61b",
+      "unicode_decimal": 58907
+    },
+    {
+      "icon_id": "9550452",
+      "name": "简介",
+      "font_class": "jianjie",
+      "unicode": "e616",
+      "unicode_decimal": 58902
+    },
+    {
+      "icon_id": "14893766",
+      "name": "主办方认证",
+      "font_class": "zhubanfangrenzheng",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
+    {
+      "icon_id": "15253802",
+      "name": "主办方",
+      "font_class": "zhubanfang",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "6338139",
+      "name": "个人中心",
+      "font_class": "gerenzhongxin",
+      "unicode": "e638",
+      "unicode_decimal": 58936
+    },
+    {
+      "icon_id": "9606662",
+      "name": "大讲堂",
+      "font_class": "dajiangtang",
+      "unicode": "e609",
+      "unicode_decimal": 58889
+    },
+    {
+      "icon_id": "2570115",
+      "name": "麦克风",
+      "font_class": "maikefeng-tianchong",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "15220134",
+      "name": "一键分享",
+      "font_class": "yijianfenxiang",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "573775",
+      "name": "分享",
+      "font_class": "fenxiang",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    },
+    {
+      "icon_id": "7335647",
+      "name": "麦克风",
+      "font_class": "maikefeng",
+      "unicode": "eb4a",
+      "unicode_decimal": 60234
+    },
+    {
+      "icon_id": "8157938",
+      "name": "摄像头",
+      "font_class": "shexiangtou",
+      "unicode": "e625",
+      "unicode_decimal": 58917
+    },
+    {
+      "icon_id": "5076572",
+      "name": "状态",
+      "font_class": "zhuangtai",
+      "unicode": "e655",
+      "unicode_decimal": 58965
+    },
+    {
+      "icon_id": "5017103",
+      "name": "房间",
+      "font_class": "fangjian1",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "1638357",
+      "name": "首页",
+      "font_class": "shouye",
+      "unicode": "e615",
+      "unicode_decimal": 58901
+    },
+    {
+      "icon_id": "3710184",
+      "name": "房间",
+      "font_class": "fangjian",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "7738015",
+      "name": "用户",
+      "font_class": "yonghu",
+      "unicode": "e608",
+      "unicode_decimal": 58888
+    },
+    {
+      "icon_id": "11800270",
+      "name": "直播",
+      "font_class": "zhibo",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "12837797",
+      "name": "统计1",
+      "font_class": "tongji",
+      "unicode": "e64b",
+      "unicode_decimal": 58955
+    },
+    {
+      "icon_id": "14033570",
+      "name": "权限",
+      "font_class": "quanxian",
+      "unicode": "e7ae",
+      "unicode_decimal": 59310
+    },
+    {
+      "icon_id": "712103",
+      "name": "姓名",
+      "font_class": "icon-person",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
+      "icon_id": "1356727",
+      "name": "绑定",
+      "font_class": "bangding",
+      "unicode": "e72b",
+      "unicode_decimal": 59179
+    },
+    {
+      "icon_id": "14683074",
+      "name": "修改密码",
+      "font_class": "mima_huaban1",
+      "unicode": "e605",
+      "unicode_decimal": 58885
+    },
+    {
+      "icon_id": "8098828",
+      "name": "退出",
+      "font_class": "iconfront-",
+      "unicode": "e621",
+      "unicode_decimal": 58913
+    }
+  ]
+}

BIN
src/assets/icon/iconfont.ttf


BIN
src/assets/icon/iconfont.woff


BIN
src/assets/icon/iconfont.woff2


BIN
src/assets/img/img.jpg


BIN
src/assets/logo.png


+ 0 - 1
src/assets/logo.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

+ 0 - 35
src/assets/main.css

@@ -1,35 +0,0 @@
-@import './base.css';
-
-#app {
-  max-width: 1280px;
-  margin: 0 auto;
-  padding: 2rem;
-
-  font-weight: normal;
-}
-
-a,
-.green {
-  text-decoration: none;
-  color: hsla(160, 100%, 37%, 1);
-  transition: 0.4s;
-}
-
-@media (hover: hover) {
-  a:hover {
-    background-color: hsla(160, 100%, 37%, 0.2);
-  }
-}
-
-@media (min-width: 1024px) {
-  body {
-    display: flex;
-    place-items: center;
-  }
-
-  #app {
-    display: grid;
-    grid-template-columns: 1fr 1fr;
-    padding: 0 2rem;
-  }
-}

BIN
src/assets/top-1.png


+ 26 - 26
src/components/admin-frame/home.vue

@@ -1,40 +1,40 @@
 <template>
 <template>
-  <el-container class="main" :style="{ background: styleInfo.main_bg_color }">
-    <el-header :style="{ background: styleInfo.header_bg_color, 'border-color': styleInfo.aside_border_color }">
-      <component :is="cHeader"></component>
-    </el-header>
+  <el-container class="main">
+    <el-header :style="{ padding: 0 }"> <component :is="cHeader"></component></el-header>
     <el-container>
     <el-container>
-      <el-aside width="200px" :style="{ background: styleInfo.aside_bg_color }">
-        <component :is="cAside"></component>
-      </el-aside>
+      <el-aside width="200px" :style="{ 'background-color': '#242f42' }"><component :is="cAside"></component></el-aside>
       <el-main>
       <el-main>
-        <component :is="breadcrumb"></component>
-        <router-view :style="testInfo"></router-view>
+        <div class="content-box" :class="{ 'content-collapse': collapse }">
+          <component :is="cTags"></component>
+          <el-col :span="24" class="content">
+            <transition name="move" mode="out-in">
+              <el-row>
+                <component :is="cBreadcrumb" :breadcrumbTitle="route.meta.title"></component>
+                <el-col :span="24" class="container" style="padding: 15px"><router-view></router-view></el-col>
+              </el-row>
+            </transition>
+            <el-backtop target=".content"></el-backtop>
+          </el-col>
+        </div>
       </el-main>
       </el-main>
     </el-container>
     </el-container>
   </el-container>
   </el-container>
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-// import { admin_style_Info } from '../../layout/site'
-// import cHeader from './parts/c-header.vue'
-// import cAside from './parts/c-aside.vue'
-// import breadcrumb from './parts/breadcrumb.vue'
-// 基础
+// 组件
+import cHeader from './parts/Header.vue'
+import cAside from './parts/Sidebar.vue'
+import cBreadcrumb from './parts/breadcrumb.vue'
+import cTags from './parts/breadcrumb.vue'
+import { useRoute } from 'vue-router'
 import type { Ref } from 'vue'
 import type { Ref } from 'vue'
-import { onMounted, ref } from 'vue'
+import { ref, toRefs } from 'vue'
 
 
-const styleInfo: Ref<any> = ref(admin_style_Info)
-const testInfo: Ref<any> = ref({
-  height: '86vh',
-  background: '#ffffff',
-  'overflow-x': 'hidden',
-  'overflow-y': 'auto',
-  border: '1px solid #f0f0f0',
-  padding: '10px'
-})
-// 请求
-onMounted(async () => {})
+// 路由
+const route = useRoute()
+let collapse: Ref<any> = ref(false)
+let tagsList: Ref<any> = ref([])
 </script>
 </script>
 <style scoped lang="scss">
 <style scoped lang="scss">
 .main {
 .main {

+ 83 - 0
src/components/admin-frame/parts/Header.vue

@@ -0,0 +1,83 @@
+<template>
+  <div id="Header">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="main header">
+          <el-col :span="24" class="one">
+            <el-col :span="12" class="left">
+              <span @click="collapseChage">
+                <i v-if="!collapse" class="el-icon-s-fold"></i>
+                <i v-else class="el-icon-s-unfold"></i>
+              </span>
+              <span>{{ siteInfo.zhTitle }}-管理中心</span>
+            </el-col>
+            <el-col :span="12" class="right">
+              <i class="el-icon-user-solid"></i>
+              <span>{{ user && user._id ? user.name || user.title || user.expert_name : '游客' }}</span>
+              <el-button type="danger" size="small" @click="logout">退出登录</el-button>
+            </el-col>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { siteInfo } from '../../../layout/site'
+// import store from '@/stores/counter'
+import type { Ref } from 'vue'
+import { ref } from 'vue'
+// import router from '@/router'
+let collapse: Ref<any> = ref(false)
+// let user: Ref<any> = ref(store.state.user)
+let user: Ref<any> = ref({})
+// 侧边栏折叠
+const collapseChage = () => {
+  // collapse.value = !collapse.value
+  // bus.$emit('collapse', collapse.value)
+}
+// 退出登录
+const logout = () => {
+  // sessionStorage.removeItem('token')
+  // router.push('/login')
+}
+</script>
+<style scoped lang="scss">
+.main {
+  background-color: #242f42;
+  .one {
+    height: 60px;
+    border-bottom: 1px solid #f1f1f1;
+    padding: 0 10px;
+    display: flex;
+    .left {
+      line-height: 60px;
+      span {
+        display: inline-block;
+        margin: 0 10px;
+        font-size: 22px;
+        color: #ffffff;
+        font-weight: bold;
+        font-family: cursive;
+      }
+    }
+    .right {
+      text-align: right;
+      line-height: 60px;
+      i {
+        position: relative;
+        top: 5px;
+        margin: 0px 15px;
+        font-size: 30px;
+        color: #fff;
+      }
+      span {
+        color: #fff;
+        font-size: 16px;
+        padding: 0 15px 0 0px;
+      }
+    }
+  }
+}
+</style>

+ 202 - 0
src/components/admin-frame/parts/Sidebar.vue

@@ -0,0 +1,202 @@
+<!-- eslint-disable vue/no-deprecated-slot-attribute -->
+<template>
+  <div id="Sidebar">
+    <el-row class="sidebar">
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="one">
+          <el-menu
+            class="sidebar-el-menu"
+            :default-active="active"
+            :collapse="collapse"
+            unique-opened
+            router
+            :background-color="styleInfo.backColor"
+            :text-color="styleInfo.textColor"
+            :active-text-color="styleInfo.activeColor"
+          >
+            <template v-for="item in items">
+              <!-- 二级菜单 -->
+              <template v-if="item.subs">
+                <el-sub-menu :index="item.index" :key="item.index">
+                  <template v-slot:title>
+                    <i :class="['iconfont', item.icon]"></i>
+                    <span slot="title">{{ item.title }}</span>
+                  </template>
+                  <template v-for="subItem in item.subs">
+                    <!-- 三级菜单 -->
+                    <el-sub-menu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
+                      <template v-slot:title>
+                        <i :class="['iconfont', subItem.icon]"></i>
+                        <span slot="title">{{ subItem.title }}</span>
+                      </template>
+                      <el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
+                        <template v-slot:title>
+                          <i :class="['iconfont', threeItem.icon]"></i>
+                          <span slot="title">{{ threeItem.title }}</span>
+                        </template>
+                      </el-menu-item>
+                    </el-sub-menu>
+                    <el-menu-item v-else :index="subItem.index" :key="`index_${subItem.index}`">
+                      <template v-slot:title>
+                        <i :class="['iconfont', subItem.icon]"></i>
+                        <span slot="title">{{ subItem.title }}</span>
+                      </template>
+                    </el-menu-item>
+                  </template>
+                </el-sub-menu>
+              </template>
+              <!-- 一级菜单 -->
+              <template v-else>
+                <el-menu-item class="first" :index="item.index" :key="item.index">
+                  <i :class="['iconfont', item.icon]"></i>
+                  <span slot="title">{{ item.title }}</span>
+                </el-menu-item>
+              </template>
+            </template>
+          </el-menu>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {
+  system,
+  users,
+  achieveUser,
+  channelUser,
+  trainUser,
+  admin,
+  // 成果评价
+  cgsys,
+  cgadmin,
+  cguser,
+  cgexpert,
+  // 专利市场
+  zlsys,
+  zladmin,
+  zlmech,
+  zluser,
+  zlagent,
+  zlcons
+} from '../../../layout/menu'
+import { menuInfo } from '../../../layout/site'
+import _ from 'lodash'
+import { ElMessage } from 'element-plus'
+import store from '@/stores/counter'
+import type { Ref } from 'vue'
+import { ref, onMounted, watch } from 'vue'
+import { useRoute } from 'vue-router'
+// import { RoleStore } from '@common/src/stores/admin/role' //模块
+// import type { IQueryResult } from '@/util/types.util'
+// const role = RoleStore()
+const useRoutes = useRoute()
+let user: Ref<any> = ref(store.state.user)
+const styleInfo: Ref<any> = ref(menuInfo.info)
+let collapse: Ref<any> = ref(false)
+let items: Ref<any> = ref(admin)
+// 选中
+const active: Ref<any> = ref('')
+onMounted(async () => {
+  onRoutes()
+})
+const onRoutes = () => {
+  active.value = useRoutes.path
+}
+
+const getMenu = async () => {
+  let list = _.cloneDeep(items.value)
+  // if (!_.get(user.value, 'id')) return;
+  let proType = `${import.meta.env.VUE_APP_ROUTER}`
+  if (proType == 'livecms') {
+    if (user.value && user.value.role == '0') {
+      list.push(...admin)
+    } else {
+      // let res: IQueryResult = await role.fetch(user.value.role_id)
+      // if (res && res.errcode == '0') {
+      //   const { menu } = res.data
+      //   if (menu.length > 0) {
+      //     const nmenu = getMenuOptions(admin, menu)
+      //     list.push(...nmenu)
+      //   }
+      // }
+    }
+  } else if (proType == 'liveuser') {
+    // role:3--平台用户,role:4--企业,role:5--专家,role:6--科技成果,role:7--科技频道,role:7--培训问诊
+    if ((user.value && user.value.role == '3') || user.value.role == '4' || user.value.role == '5') list.push(...users)
+    else if (user.value && user.value.role == '6') list.push(...achieveUser)
+    else if (user.value && user.value.role == '7') list.push(...channelUser)
+    else if (user.value && user.value.role == '8') list.push(...trainUser)
+  } else if (proType == 'liveachieve') {
+    // role:1--管理员,role:3--平台用户,role:9--评审专家用户
+    if (user.value && user.value.role == '1') list.push(...cgadmin, ...cgsys)
+    else if (user.value && user.value.role == '3') list.push(...cguser, ...cgsys)
+    else if (user.value && user.value.role == '9') list.push(...cgexpert, ...cgsys)
+  } else if (proType == 'livepatent') {
+    // role:1--管理员,role:2--机构,role:3--平台用户,role:10--代理机构,role:11--咨询师
+    if (user.value && user.value.role == '1') list.push(...zladmin, ...zlsys)
+    else if (user.value && user.value.role == '2') list.push(...zlmech, ...zlsys)
+    else if (user.value && user.value.role == '3') list.push(...zluser, ...zlsys)
+    else if (user.value && user.value.role == '10') list.push(...zlagent, ...zlsys)
+    else if (user.value && user.value.role == '11') list.push(...zlcons, ...zlsys)
+  }
+  items.value = _.uniqBy(list, 'index')
+}
+// 拍平数据
+const getMenuOptions = (allMenu: any, menus: any) => {
+  menus = _.uniq(_.flattenDeep(menus))
+  return getOptions(allMenu, menus) || []
+}
+// 重组,并找到对应菜单
+const getOptions = (allMenu: any, menus: any) => {
+  let res: any = allMenu.map((l: any) => {
+    const r: any = menus.find((f: any) => f == l.num)
+    if (r) {
+      if (l.subs) l.subs = getOptions(l.subs, menus)
+      return l
+    }
+  })
+  res = _.compact(res)
+  return res
+}
+watch(
+  user,
+  (newVal) => {
+    if (newVal && newVal._id) {
+      if (newVal && newVal._id) getMenu()
+      else ElMessage({ message: `暂无用户信息,无法获取菜单信息`, type: 'error' })
+    }
+  },
+  {
+    deep: true
+  }
+)
+</script>
+<style scoped lang="scss">
+.sidebar {
+  display: block;
+  position: absolute;
+  left: 0;
+  top: 60px;
+  bottom: 0;
+  overflow-y: scroll;
+}
+.sidebar::-webkit-scrollbar {
+  width: 0;
+}
+.sidebar-el-menu:not(.el-menu--collapse) {
+  width: 200px;
+}
+.sidebar > ul {
+  height: 100%;
+}
+.main {
+  .one {
+    .iconfont {
+      font-size: 18px;
+      margin: 0 5px 0 0;
+    }
+  }
+}
+</style>

+ 202 - 0
src/components/admin-frame/parts/Tags.vue

@@ -0,0 +1,202 @@
+<!-- eslint-disable vue/no-deprecated-slot-attribute -->
+<template>
+  <div id="Tags">
+    <el-row v-if="showTags">
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="one">
+          <el-col :span="23" class="left">
+            <ul>
+              <li class="tags-li" v-for="(item, index) in tagsList" :class="{ active: isActive(item.path) }" :key="index">
+                <router-link :to="item.path" class="tags-li-title">
+                  {{ item.title }}
+                </router-link>
+                <!-- <span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span> -->
+              </li>
+            </ul>
+          </el-col>
+          <el-col :span="1" class="right">
+            <el-dropdown @command="handleTags">
+              <el-button size="small" type="primary"> 标签选项<i class="el-icon-arrow-down el-icon--right"></i> </el-button>
+              <el-dropdown-menu size="small" slot="dropdown">
+                <el-dropdown-item command="other">关闭其他</el-dropdown-item>
+                <el-dropdown-item command="all">关闭所有</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import bus from './bus'
+import { mapState, createNamespacedHelpers } from 'vuex'
+export default {
+  name: 'Tags',
+  props: {},
+  components: {},
+  data: function () {
+    return {
+      tagsList: []
+    }
+  },
+  created() {
+    this.setTags(this.$route)
+    // 监听关闭当前页面的标签页
+    bus.$on('close_current_tags', () => {
+      for (let i = 0, len = this.tagsList.length; i < len; i++) {
+        const item = this.tagsList[i]
+        if (item.path === this.$route.fullPath) {
+          if (i < len - 1) {
+            this.$router.push(this.tagsList[i + 1].path)
+          } else if (i > 0) {
+            this.$router.push(this.tagsList[i - 1].path)
+          } else {
+            this.$router.push('/')
+          }
+          this.tagsList.splice(i, 1)
+          break
+        }
+      }
+    })
+  },
+  methods: {
+    isActive(path) {
+      return path === this.$route.fullPath
+    },
+    // 打开标签
+    handleTags(command) {
+      command === 'other' ? this.closeOther() : this.closeAll()
+    },
+    // 关闭单个标签
+    closeTags(index) {
+      const delItem = this.tagsList.splice(index, 1)[0]
+      const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1]
+      if (item) {
+        delItem.path === this.$route.fullPath && this.$router.push(item.path)
+      } else {
+        this.$router.push('/adminCenter/homeIndex')
+      }
+    },
+    // 关闭全部标签
+    closeAll() {
+      this.tagsList = []
+      this.$router.push('/adminCenter/homeIndex')
+    },
+    // 关闭其他标签
+    closeOther() {
+      const curItem = this.tagsList.filter((item) => {
+        return item.path === this.$route.fullPath
+      })
+      this.tagsList = curItem
+    },
+    // 设置标签
+    setTags(route) {
+      const isExist = this.tagsList.some((item) => {
+        return item.path === route.fullPath
+      })
+      if (!isExist) {
+        if (this.tagsList.length >= 8) {
+          this.tagsList.shift()
+        }
+        this.tagsList.push({
+          title: route.meta.title,
+          path: route.fullPath,
+          name: route.matched[1].components.default.name
+        })
+      }
+      bus.$emit('tags', this.tagsList)
+    }
+  },
+  computed: {
+    ...mapState(['user']),
+    showTags() {
+      return this.tagsList.length > 0
+    }
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title }
+  },
+  watch: {
+    $route(newValue, oldValue) {
+      let index = this.tagsList.findIndex((i) => i.path == oldValue.path)
+      this.tagsList.splice(index, 1)
+      this.setTags(newValue)
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.main {
+  .one {
+    position: relative;
+    height: 30px;
+    overflow: hidden;
+    background: #fff;
+    padding-right: 120px;
+    box-shadow: 0 5px 10px #ddd;
+    .left {
+      ul {
+        box-sizing: border-box;
+        width: 100%;
+        height: 100%;
+      }
+      .tags-li {
+        float: left;
+        margin: 3px 5px 2px 3px;
+        border-radius: 3px;
+        font-size: 12px;
+        overflow: hidden;
+        cursor: pointer;
+        height: 23px;
+        line-height: 23px;
+        border: 1px solid #e9eaec;
+        background: #fff;
+        padding: 0 5px 0 12px;
+        vertical-align: middle;
+        color: #666;
+        -webkit-transition: all 0.3s ease-in;
+        -moz-transition: all 0.3s ease-in;
+        transition: all 0.3s ease-in;
+      }
+      .tags-li:not(.active):hover {
+        background: #f8f8f8;
+      }
+      .tags-li.active {
+        color: #fff;
+      }
+      .tags-li-title {
+        float: left;
+        // max-width: 80px;
+        // overflow: hidden;
+        // white-space: nowrap;
+        // text-overflow: ellipsis;
+        margin-right: 5px;
+        color: #666;
+      }
+      .tags-li.active .tags-li-title {
+        color: #fff;
+      }
+      .tags-li.active {
+        border: 1px solid #409eff;
+        background-color: #409eff;
+      }
+    }
+    .right {
+      position: absolute;
+      right: 0;
+      top: 0;
+      box-sizing: border-box;
+      padding-top: 1px;
+      text-align: center;
+      width: 110px;
+      height: 30px;
+      background: #fff;
+      box-shadow: -3px 0 15px 3px rgba(0, 0, 0, 0.1);
+      z-index: 10;
+    }
+  }
+}
+</style>

+ 23 - 0
src/components/admin-frame/parts/breadcrumb.vue

@@ -0,0 +1,23 @@
+<template>
+  <div id="breadcrumb">
+    <el-row>
+      <el-col :span="24" class="crumbs">
+        <el-breadcrumb separator="/">
+          <el-breadcrumb-item> <i class="el-icon-s-grid"></i> {{ breadcrumbTitle }} </el-breadcrumb-item>
+        </el-breadcrumb>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { toRefs } from 'vue'
+// #region 参数传递
+const props = defineProps({
+  breadcrumbTitle: { type: String, default: () => '' }
+})
+const { breadcrumbTitle } = toRefs(props)
+
+// #endregion
+</script>
+<style lang="scss" scoped></style>

+ 991 - 0
src/layout/menu.ts

@@ -0,0 +1,991 @@
+export const system = [{ icon: 'iconshouye', index: '/adminCenter/homeIndex', title: '系统首页' }]
+// 管理员
+export const admin = [
+  {
+    icon: 'iconshouye',
+    index: '2',
+    title: '管理账号管理',
+    num: '2',
+    subs: [
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/admin/code',
+      //   title: '邀请码管理',
+      //   num: '2-1',
+      // },
+      {
+        icon: 'iconshouye',
+        index: '/admin/admins',
+        title: '管理用户',
+        num: '2-2'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/admin/mechanism',
+        title: '机构用户',
+        num: '2-3'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/admin/business',
+        title: '业务用户',
+        num: '2-4'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '3',
+    title: '用户管理',
+    num: '3',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/user/personal',
+        title: '个人用户',
+        num: '3-1'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/user/company',
+        title: '企业用户',
+        num: '3-2'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/user/expert',
+        title: '专家用户',
+        num: '3-3'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '/product',
+    title: '产品审核管理',
+    num: '4'
+  },
+  {
+    icon: 'iconshouye',
+    index: '5',
+    title: 'e专利管理',
+    num: '5',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/patent/mess',
+        title: '信息管理',
+        num: '5-1'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/patent/trans',
+        title: '专利交易',
+        num: '5-2'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '6',
+    title: '展会管理',
+    num: '6',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '6-1',
+        title: '科技成果',
+        num: '6-1',
+        subs: [
+          {
+            icon: 'iconshouye',
+            index: '/expo/achieve/live',
+            title: '信息管理',
+            num: '6-1-1'
+          },
+          {
+            icon: 'iconshouye',
+            index: '/expo/achieve/trans',
+            title: '交易审核管理',
+            num: '6-1-2'
+          }
+        ]
+      },
+      {
+        icon: 'iconshouye',
+        index: '6-2',
+        title: '培训问诊',
+        num: '6-2',
+        subs: [
+          {
+            icon: 'iconshouye',
+            index: '/expo/train/live',
+            title: '信息管理',
+            num: '6-2-1'
+          }
+        ]
+      },
+      {
+        icon: 'iconshouye',
+        index: '6-3',
+        title: '科技频道',
+        num: '6-3',
+        subs: [
+          {
+            icon: 'iconshouye',
+            index: '/expo/channel/live',
+            title: '信息管理',
+            num: '6-3-1'
+          }
+        ]
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '7',
+    title: '新闻信息管理',
+    num: '7',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/news/column',
+        title: '栏目管理',
+        num: '7-1'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/news/mess',
+        title: '信息管理',
+        num: '7-2'
+      }
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/news/live',
+      //   title: '科学普及',
+      //   num: '7-1',
+      // },
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/news/live',
+      //   title: '智库视点',
+      //   num: '7-1',
+      // },
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/news/live',
+      //   title: '项目路演',
+      //   num: '7-1',
+      // },
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/news/live',
+      //   title: '嘉宾访谈',
+      //   num: '7-1',
+      // },
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/news/live',
+      //   title: '通知公告',
+      //   num: '7-1',
+      // },
+      // {
+      //   icon: 'iconshouye',
+      //   index: '/news/live',
+      //   title: '科技新闻',
+      //   num: '7-1',
+      // },
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '8',
+    title: '预约服务管理',
+    num: '8',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/subscribe/mess',
+        title: '信息管理',
+        num: '8-1'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '101',
+    title: '系统设置',
+    num: '101',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/system/power',
+        title: '角色设置',
+        num: '101-1'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/system/dictionary',
+        title: '字典表设置',
+        num: '101-2'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/system/uppasswd',
+        title: '修改密码',
+        num: '101-3'
+      }
+    ]
+  }
+]
+// 平台用户
+export const users = [
+  {
+    icon: 'iconshouye',
+    index: '/user/basic',
+    title: '基本信息'
+  },
+  {
+    icon: 'iconshouye',
+    index: '/user/message',
+    title: '消息管理'
+  },
+  {
+    icon: 'iconshouye',
+    index: '/user/product',
+    title: '信息发布'
+  },
+  // {
+  //   icon: 'iconshouye',
+  //   index: '4',
+  //   title: '我的发布',
+  //   subs: [
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/product/stay',
+  //       title: '待发布',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/product/examine',
+  //       title: '审核中',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/product/already',
+  //       title: '已发布',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/product/fail',
+  //       title: '审核拒绝',
+  //     },
+  //   ],
+  // },
+  {
+    icon: 'iconshouye',
+    index: '5',
+    title: '展会管理',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/user/live/next',
+        title: '下期直播'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/user/live/past',
+        title: '已往直播'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '/user/matter',
+    title: '事项管理'
+  },
+  // {
+  //   icon: 'iconshouye',
+  //   index: '6',
+  //   title: '事项管理',
+  //   subs: [
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/matter/cooperation',
+  //       title: '洽谈合作',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/matter/intention',
+  //       title: '达成意向',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/matter/keep',
+  //       title: '交易备案',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/matter/complete',
+  //       title: '交易完成',
+  //     },
+  //     {
+  //       icon: 'iconshouye',
+  //       index: '/user/matter/fail',
+  //       title: '交易失败',
+  //     },
+  //   ],
+  // },
+  {
+    icon: 'iconshouye',
+    index: '/user/uppasswd',
+    title: '修改密码'
+  }
+]
+// 科技成果
+export const achieveUser = [
+  {
+    icon: 'iconshouye',
+    index: '/achieveUser/basic',
+    title: '展会基本信息'
+  },
+  {
+    icon: 'iconshouye',
+    index: '3',
+    title: '展会信息管理',
+    num: '3',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/achieveUser/mess/video',
+        title: '视频信息管理',
+        num: '3-1'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/achieveUser/mess/imgtxt',
+        title: '图文信息管理',
+        num: '3-2'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/achieveUser/mess/guest',
+        title: '嘉宾访谈信息管理',
+        num: '3-3'
+      },
+      {
+        icon: 'iconshouye',
+        index: '/achieveUser/mess/readshow',
+        title: '项目路演信息管理',
+        num: '3-4'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '/achieveUser/apply',
+    title: '展会申请管理'
+  },
+  {
+    icon: 'iconshouye',
+    index: '/achieveUser/trans',
+    title: '交易记录管理'
+  },
+  {
+    icon: 'iconshouye',
+    index: '/achieveUser/census',
+    title: '统计报表'
+  }
+]
+// 科技频道
+export const channelUser = [
+  {
+    icon: 'iconshouye',
+    index: '/channelUser/basic',
+    title: '展会基本信息'
+  },
+  {
+    icon: 'iconshouye',
+    index: '3',
+    title: '展会信息管理',
+    num: '3',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/channelUser/mess/video',
+        title: '视频信息管理',
+        num: '3-1'
+      }
+    ]
+  }
+]
+// 培训问诊
+export const trainUser = [
+  {
+    icon: 'iconshouye',
+    index: '/trainUser/basic',
+    title: '展会基本信息'
+  },
+  {
+    icon: 'iconshouye',
+    index: '3',
+    title: '展会信息管理',
+    num: '3',
+    subs: [
+      {
+        icon: 'iconshouye',
+        index: '/trainUser/mess/video',
+        title: '视频信息管理',
+        num: '3-1'
+      }
+    ]
+  },
+  {
+    icon: 'iconshouye',
+    index: '/trainUser/user',
+    title: '用户管理'
+  }
+]
+
+// 成果评价--liveachieve
+// 系统设置
+export const cgsys = [
+  {
+    icon: 'iconshouye',
+    index: '100',
+    title: '系统设置',
+    subs: [
+      {
+        icon: 'iconicon_xinyong_xianxing_jijin-',
+        index: '/system/basic',
+        title: '基本信息'
+      },
+      {
+        icon: 'iconmima_huaban1',
+        index: '/system/updatepd',
+        title: '修改密码'
+      }
+    ]
+  }
+]
+// 平台用户
+export const cguser = [
+  {
+    icon: 'iconshenbao',
+    index: '3',
+    title: '我的申报',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/user/my/now',
+        title: '申报中'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/my/past',
+        title: '已往申报'
+      }
+    ]
+  },
+  {
+    icon: 'icon111',
+    index: '/user/expertscore',
+    title: '专家评分'
+  },
+  {
+    icon: 'icon111',
+    index: '/user/meeting',
+    title: '专家会审'
+  },
+  {
+    icon: 'iconchengguo',
+    index: '6',
+    title: '证书管理',
+    subs: [
+      {
+        icon: 'iconziliaoku',
+        index: '/user/cert/file',
+        title: '证书制作'
+      },
+      {
+        icon: 'icondaifabu',
+        index: '/user/cert/grant',
+        title: '待发证书'
+      },
+      {
+        icon: 'iconyifabu',
+        index: '/user/cert/issued',
+        title: '证书查看'
+      }
+    ]
+  },
+  {
+    icon: 'iconchengguo',
+    index: '/user/userCertFile',
+    title: '证书资料管理'
+  }
+]
+// 管理用户
+export const cgadmin = [
+  {
+    icon: 'iconyonghu',
+    index: '3',
+    title: '用户管理',
+    subs: [
+      {
+        icon: 'iconyonghu',
+        index: '/admin/personal/user',
+        title: '个人用户'
+      },
+      {
+        icon: 'icon111',
+        index: '/admin/personal/expert',
+        title: '专家用户'
+      },
+      {
+        icon: 'icon111',
+        index: '/admin/personal/psexpert',
+        title: '评审专家'
+      }
+    ]
+  },
+  {
+    icon: 'iconliebiaoxingshi',
+    index: '/admin/shape',
+    title: '形式审查'
+  },
+  {
+    icon: 'iconpingfen',
+    index: '/admin/expertscore',
+    title: '专家评分'
+  },
+  {
+    icon: 'iconhuishenzhong',
+    index: '/admin/meeting',
+    title: '专家会审'
+  },
+  {
+    icon: 'iconchengguo',
+    index: '/admin/perfect',
+    title: '资料完善'
+  },
+  {
+    icon: 'iconchengguo',
+    index: '8',
+    title: '证书管理',
+    subs: [
+      {
+        icon: 'iconziliaoku',
+        index: '/admin/cert/file',
+        title: '证书制作'
+      },
+      {
+        icon: 'icondaifabu',
+        index: '/admin/cert/grant',
+        title: '证书发放'
+      },
+      {
+        icon: 'iconyifabu',
+        index: '/admin/cert/issued',
+        title: '证书归档'
+      }
+    ]
+  },
+  {
+    icon: 'iconchengguo',
+    index: '/admin/adminCertFile',
+    title: '证书单独上传'
+  }
+]
+// 评审专家用户
+export const cgexpert = [
+  {
+    icon: 'iconshenhe',
+    index: '3',
+    title: '审核管理',
+    subs: [
+      {
+        icon: 'icon111',
+        index: '/expert/examine/review',
+        title: '专家初评'
+      },
+      {
+        icon: 'icon111',
+        index: '/expert/examine/meeting',
+        title: '专家会审'
+      }
+    ]
+  }
+]
+
+// 专利市场--livepatent
+// 系统设置
+export const zlsys = [
+  {
+    icon: 'iconshouye',
+    index: '100',
+    title: '系统设置',
+    subs: [
+      {
+        icon: 'iconicon_xinyong_xianxing_jijin-',
+        index: '/system/basic',
+        title: '基本信息'
+      },
+      {
+        icon: 'iconmima_huaban1',
+        index: '/system/updatepd',
+        title: '修改密码'
+      }
+    ]
+  }
+]
+// 管理用户
+export const zladmin = [
+  {
+    icon: 'iconshenbao',
+    index: '3',
+    title: '用户管理',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/admin/user/mech',
+        title: '机构用户'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/user/personal',
+        title: '平台用户'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/user/agent',
+        title: '代理机构'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/user/consulting',
+        title: '咨询师'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '4',
+    title: '专利消息',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/admin/message/notice',
+        title: '通知管理'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/message/problem',
+        title: '问题管理'
+      },
+      // {
+      //   icon: 'iconshenbao',
+      //   index: '/admin/message/examine',
+      //   title: '审核通知',
+      // },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/message/warning',
+        title: '专利预警'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '5',
+    title: '专利审核',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/admin/examine/apply',
+        title: '申请审核'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/examine/gzj',
+        title: '国知局反馈信息'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/examine/search',
+        title: '查新检索'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/patent/assessment',
+        title: '价值评估'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/patent/maintain',
+        title: '专利维权'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '6',
+    title: '专利管理',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/admin/patent/info',
+        title: '专利信息'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/patent/handle',
+        title: '专利信息批量处理'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/patent/trans',
+        title: '专利交易'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/admin/patent/techol',
+        title: '专利需求'
+      }
+    ]
+  }
+]
+// 机构用户
+export const zlmech = [
+  {
+    icon: 'iconshenbao',
+    index: '3',
+    title: '用户管理',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/mech/user/personal',
+        title: '平台用户'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '4',
+    title: '专利消息',
+    subs: [
+      // {
+      //   icon: 'iconshenbao',
+      //   index: '/mech/message/examine',
+      //   title: '审核通知',
+      // },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/message/notice',
+        title: '通知管理'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '5',
+    title: '专利审核',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/mech/examine/apply',
+        title: '申请审核'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/examine/trans',
+        title: '交易审核'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/examine/contract',
+        title: '合同审核'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/examine/file',
+        title: '交易归档'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/examine/complete',
+        title: '完成交易'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '6',
+    title: '专利管理',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/mech/patent/info',
+        title: '专利信息'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/patent/search',
+        title: '专利检索'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/mech/patent/warning',
+        title: '专利预警'
+      }
+    ]
+  }
+]
+// 平台用户
+export const zluser = [
+  {
+    icon: 'iconshenbao',
+    index: '3',
+    title: '我的消息',
+    subs: [
+      // {
+      //   icon: 'iconshenbao',
+      //   index: '/user/message/examine',
+      //   title: '审核消息',
+      // },
+      {
+        icon: 'iconshenbao',
+        index: '/user/message/notcie',
+        title: '通知消息'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/message/chat',
+        title: '咨询服务'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '4',
+    title: '我的申请',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/user/apply/patent',
+        title: '专利申请'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/apply/search',
+        title: '查新检索'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/apply/value',
+        title: '价值评估'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '5',
+    title: '我的专利',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/user/patent/info',
+        title: '专利管理'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/patent/maintain',
+        title: '专利维权'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/patent/warning',
+        title: '专利预警'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/patent/trans',
+        title: '专利交易'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/patent/techol',
+        title: '专利需求'
+      }
+    ]
+  },
+  {
+    icon: 'iconshenbao',
+    index: '6',
+    title: '专利超市',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/user/market/info',
+        title: '专利信息'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/user/market/tans',
+        title: '交易公告'
+      }
+    ]
+  }
+]
+// 代理机构
+export const zlagent = [
+  // {
+  //   icon: 'iconshenbao',
+  //   index: '3',
+  //   title: '专利消息',
+  //   subs: [
+  //     {
+  //       icon: 'iconshenbao',
+  //       index: '/agent/message/examine',
+  //       title: '审核通知',
+  //     },
+  //   ],
+  // },
+  {
+    icon: 'iconshenbao',
+    index: '4',
+    title: '专利审核',
+    subs: [
+      {
+        icon: 'iconshenbao',
+        index: '/agent/examine/apply',
+        title: '申请审核'
+      },
+      {
+        icon: 'iconshenbao',
+        index: '/agent/examine/report',
+        title: '专利上报'
+      }
+    ]
+  }
+  // {
+  //   icon: 'iconshenbao',
+  //   index: '5',
+  //   title: '专利信息',
+  //   subs: [
+  //     {
+  //       icon: 'iconshenbao',
+  //       index: '/agent/patent/apply',
+  //       title: '专利申请',
+  //     },
+  //   ],
+  // },
+]
+// 咨询师
+export const zlcons = [
+  {
+    icon: 'icon111',
+    index: '/cons/problem',
+    title: '问题管理'
+  }
+]

+ 57 - 36
src/layout/site.ts

@@ -1,36 +1,57 @@
-export const system = [{ icon: 'iconshouye', index: '/adminCenter/homeIndex', title: '系统首页' }]
-// 管理员
-export const admin = [
-  {
-    icon: 'iconshouye',
-    index: '2',
-    title: '管理账号管理',
-    num: '2',
-    subs: [
-      // {
-      //   icon: 'iconshouye',
-      //   index: '/admin/code',
-      //   title: '邀请码管理',
-      //   num: '2-1',
-      // },
-      {
-        icon: 'iconshouye',
-        index: '/admin/admins',
-        title: '管理用户',
-        num: '2-2'
-      },
-      {
-        icon: 'iconshouye',
-        index: '/admin/mechanism',
-        title: '机构用户',
-        num: '2-3'
-      },
-      {
-        icon: 'iconshouye',
-        index: '/admin/business',
-        title: '业务用户',
-        num: '2-4'
-      }
-    ]
-  }
-]
+// 网站基本设置
+export const siteInfo = {
+  display: false,
+  zhTitle: '中科在线(长春)'
+  // enTitle: 'Changchun Furui Technology Co., Ltd',
+  // logo_url: require('../../assets/logo.png')
+}
+// 菜单设置
+export const menuInfo = {
+  info: {
+    display: false,
+    mode: 'horizontal',
+    backColor: '#242f42',
+    textColor: '#ffffff'
+    // actColor: '#fe950e',
+    // actColor: '#ffffff',
+  },
+  menuList: [
+    { icon: '', index: '/live', title: '直播大厅' },
+    { icon: '', index: '/channel', title: '科技频道' },
+    { icon: '', index: '/market', title: '科技超市' },
+    { icon: '', index: '/interflow', title: '交流合作' },
+    { icon: '', index: '/service', title: '创新服务' },
+    { icon: '', index: '/universal', title: '科学普及' }
+  ]
+}
+// 轮播图设置
+export const bannerInfo = {
+  info: {
+    display: false,
+    // 轮播高度
+    height: '400px',
+    // 指示器触发方式-默认值:hover,click:点击
+    trigger: '',
+    // 是否自动切换-默认值:true
+    autoplay: true,
+    // 自动切换秒数
+    interval: 3000,
+    // 指示器位置显示-默认值:显示,outside:外部,none:不显示,
+    indicatorpos: '',
+    // 切换箭头-默认值:鼠标滑过时显示,always:一直显示,never:一直隐藏
+    arrow: '',
+    // 轮播类型-card:卡片化
+    type: '',
+    // 是否循环显示:默认值:true
+    loop: true,
+    // 轮播垂直方向显示-默认值:横向,vertical:垂直
+    direction: 'horizontal'
+  },
+  list: []
+}
+// 网站底部信息
+export const footInfo = {
+  display: true,
+  content:
+    '<p>技术运营:长春市福瑞科技有限公司</p><p>技术支持:长春市福瑞科技有限公司</p><p>地址:吉林省长春市朝阳区前进大街1244号电话:12345678901微信:123456邮箱:123456@163.com</p><p>吉ICP备2020007658号-1 Copyright 2019 版权所有 长春市福瑞科技有限公司 All Rights Reserved</p>'
+}

+ 15 - 4
src/main.ts

@@ -1,14 +1,25 @@
 import { createApp } from 'vue'
 import { createApp } from 'vue'
 import { createPinia } from 'pinia'
 import { createPinia } from 'pinia'
-
 import App from './App.vue'
 import App from './App.vue'
 import router from './router'
 import router from './router'
+import ElementPlus from 'element-plus'
 
 
-import './assets/main.css'
+// import 'element-plus/theme-chalk/index.css';
+import '@common/src/assets/css/theme-green/index.css'
+import '@common/src/assets/css/theme-green/color-green.css'
 
 
+import locale from 'element-plus/lib/locale/lang/zh-cn'
+// import moment from 'moment';
+import '@/assets/main.css'
+// import 'animate.css';
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 const app = createApp(App)
 const app = createApp(App)
-
 app.use(createPinia())
 app.use(createPinia())
 app.use(router)
 app.use(router)
-
+app.use(ElementPlus, { locale })
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+  app.component(key, component)
+}
+// app.config.globalProperties.$moment = moment;
+// app.config.globalProperties.$limit = parseInt(import.meta.env.VITE_APP_PAGE_SIZE) || 10;
 app.mount('#app')
 app.mount('#app')

+ 54 - 0
src/stores/system/role.ts

@@ -0,0 +1,54 @@
+import { ref, computed } from 'vue'
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/util/axios-wrapper'
+import _ from 'lodash'
+
+import type { IQueryType, IQueryResult, IQueryParams } from '@/util/types.util'
+const axios = new AxiosWrapper()
+const api = {
+  url: `/zkzx/v2/api/role`
+}
+export const RoleStore = defineStore('role', () => {
+  const count = ref(0)
+  const doubleCount = computed(() => count.value * 2)
+  function increment() {
+    count.value++
+  }
+  const query = async ({ skip = 0, limit = undefined, ...info }: IQueryParams = {}): Promise<IQueryResult> => {
+    let cond: IQueryType = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${api.url}`, cond)
+    return res
+  }
+
+  const fetch = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$get(`${api.url}/${payload}`)
+    return res
+  }
+  const create = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$post(`${api.url}`, payload)
+    return res
+  }
+  const update = async (payload: any): Promise<IQueryResult> => {
+    const id = _.get(payload, 'id', _.get(payload, '_id'))
+    const res = await axios.$post(`${api.url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$delete(`${api.url}/${payload}`)
+    return res
+  }
+  return {
+    count,
+    doubleCount,
+    increment,
+    query,
+
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 6 - 0
src/stores/user/mutations.ts

@@ -0,0 +1,6 @@
+export const setUser = (state: { user: any }, payload: any) => {
+  state.user = payload
+}
+export const setIsInAct = (state: any, payload: any) => {
+  state.isInAct = payload
+}

+ 1 - 0
src/stores/user/state.ts

@@ -0,0 +1 @@
+export const user = {};

+ 150 - 0
src/util/axios-wrapper.ts

@@ -0,0 +1,150 @@
+/* eslint-disable no-console */
+/* eslint-disable no-param-reassign */
+
+import _ from 'lodash';
+import Axios from 'axios';
+import { Util, Error } from 'naf-core';
+// import { Indicator } from 'mint-ui';
+import type { IOptionsType, IQueryType, IRequestResult } from './types.util';
+
+const { trimData, isNullOrUndefined } = Util;
+const { ErrorCode } = Error;
+
+let currentRequests = 0;
+
+// // 参数类型设置
+// type valueType = string | number | object | boolean | Array<any>;
+// type queryType = string | number | boolean;
+
+// export interface IQueryType {
+//   [props: string]: queryType;
+// }
+// export interface IOptionsType {
+//   [props: string]: valueType;
+// }
+
+// export interface IRequestResult {
+//   errcode: string | number;
+//   errmsg: string | number;
+//   details?: string;
+//   [props: string]: any;
+// }
+
+export class AxiosWrapper {
+  constructor({ baseUrl = import.meta.env.VITE_REQUEST_BASE, unwrap = true } = {}) {
+    this.baseUrl = baseUrl;
+    this.unwrap = unwrap;
+  }
+  baseUrl: string;
+  unwrap: boolean;
+
+  // 替换uri中的参数变量
+  static merge(uri: string, query: IQueryType) {
+    if (!uri.includes(':')) {
+      return uri;
+    }
+    const keys = [];
+    const regexp = /\/:([a-z0-9_]+)/gi;
+    let res;
+    // eslint-disable-next-line no-cond-assign
+    while ((res = regexp.exec(uri)) != null) {
+      keys.push(res[1]);
+    }
+    keys.forEach((key) => {
+      const val = _.get(query, key);
+      if (!isNullOrUndefined(val)) {
+        uri = uri.replace(`:${key}`, `${val}`);
+      }
+    });
+    return uri;
+  }
+
+  $get(uri: string, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, undefined, query, options);
+  }
+
+  $post(uri: string, data: object = {}, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, data, query, options);
+  }
+  $delete(uri: string, data: object = {}, query?: IQueryType, options: IOptionsType = {}) {
+    options = { ...options, method: 'delete' };
+    return this.$request(uri, data, query, options);
+  }
+  async $request(uri: string, data?: object, query?: IQueryType, options?: IOptionsType) {
+    if (query && _.isObject(query)) {
+      const keys = Object.keys(query);
+      for (const key of keys) {
+        const val = _.get(query, key);
+        if (val === '') {
+          delete query[key];
+        }
+      }
+    }
+    if (_.isObject(query) && _.isObject(options)) {
+      options = { ...options, params: query, method: 'get' };
+    } else if (_.isObject(query) && !query.params) {
+      options = { params: query };
+    } else if (_.isObject(query) && query.params) {
+      options = query;
+    }
+    if (!options) options = {};
+    if (options.params) options.params = trimData(options.params, null, null);
+    const params = _.get(options, 'params');
+    const url = AxiosWrapper.merge(uri, params as IQueryType);
+    currentRequests += 1;
+    // Indicator.open({
+    //   spinnerType: 'fading-circle',
+    // });
+    try {
+      let returnData: any;
+      const axios = Axios.create({
+        baseURL: this.baseUrl,
+      });
+      // if (util.token && util.token !== null) axios.defaults.headers.common.Authorization = util.token;
+      const token = localStorage.getItem('token');
+      const apiToken = sessionStorage.getItem('apiToken');
+      if (token) axios.defaults.headers.common['token'] = token;
+      if (apiToken) axios.defaults.headers.common['api-token'] = apiToken;
+      const res = await axios.request({
+        method: isNullOrUndefined(data) ? 'get' : 'post',
+        url,
+        data,
+        responseType: 'json',
+        ...options,
+      });
+      const returnRes: IRequestResult = res.data;
+      const { errcode, errmsg, details } = returnRes;
+      if (errcode) {
+        console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`);
+        return returnRes;
+      }
+      // unwrap data
+      if (this.unwrap) {
+        returnData = returnRes;
+      }
+      // 处理apiToken
+      const { apiToken: at, ...others } = returnData;
+      if (at) sessionStorage.setItem('apiToken', at);
+      return others;
+    } catch (err: any) {
+      let errmsg = '接口请求失败,请稍后重试';
+      if (err.response) {
+        const { status } = err.response;
+        if (status === 401) errmsg = '用户认证失败,请重新登录';
+        if (status === 403) errmsg = '当前用户不允许执行该操作';
+      }
+      console.error(
+        `[AxiosWrapper] 接口请求失败: ${err.config && err.config.url} - 
+        ${err.message}`
+      );
+      return { errcode: ErrorCode.SERVICE_FAULT, errmsg, details: err.message };
+    } finally {
+      /* eslint-disable */
+      currentRequests -= 1;
+      if (currentRequests <= 0) {
+        currentRequests = 0;
+        // Indicator.close();
+      }
+    }
+  }
+}

+ 29 - 0
src/util/types.util.ts

@@ -0,0 +1,29 @@
+// 参数类型设置
+type valueType = string | number | Object | boolean | Array<any>;
+type queryType = string | number | boolean;
+
+export interface IQueryType {
+  [props: string]: queryType;
+}
+export interface IOptionsType {
+  [props: string]: valueType;
+}
+
+export interface IRequestResult {
+  errcode: string | number;
+  errmsg: string | number;
+  details?: string;
+  [props: string]: any;
+}
+export interface IQueryResult {
+  errcode?: string | number;
+  errmsg?: string | number;
+  data: valueType;
+  total: number;
+}
+
+export interface IQueryParams {
+  skip?: number;
+  limit?: number;
+  [props: string]: any;
+}

+ 26 - 4
tsconfig.json

@@ -1,13 +1,35 @@
 {
 {
   "extends": "@vue/tsconfig/tsconfig.web.json",
   "extends": "@vue/tsconfig/tsconfig.web.json",
-  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
+  // "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "../common/src/stores/user", "../common/src/stores/user"],
+  "include": [
+    "src/**/*.ts",
+    "src/**/*.d.ts",
+    "src/**/*.tsx",
+    "src/**/*.vue",
+    "src/untils/baiduMap.js",
+    "src/untils/debuonce.js",
+    "**/*.ts",
+    "**/*.tsx"
+  ],
   "compilerOptions": {
   "compilerOptions": {
+    "target": "esnext",
+    "module": "esnext",
+    "strict": false,
+    "jsx": "preserve",
+    "moduleResolution": "node",
     "baseUrl": ".",
     "baseUrl": ".",
     "paths": {
     "paths": {
-      "@/*": ["./src/*"]
-    }
+      "@/*": ["./src/*"],
+      "@common/*": ["../common/*"]
+    },
+    "isolatedModules": false,
+    "suppressImplicitAnyIndexErrors": true,
+    "sourceMap": true,
+    "resolveJsonModule": true,
+    "esModuleInterop": true,
+    "lib": ["es5", "es6", "dom", "dom.iterable"],
+    "allowSyntheticDefaultImports": true
   },
   },
-
   "references": [
   "references": [
     {
     {
       "path": "./tsconfig.node.json"
       "path": "./tsconfig.node.json"