@wp1001/ui 2.9.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.env +6 -0
  2. package/@vant-D4fmGxs6.js +3891 -0
  3. package/index.js +8419 -0
  4. package/package.json +59 -0
  5. package/packages/assets/devtools-detector.js +2 -0
  6. package/packages/components/xarray/index.js +64 -0
  7. package/packages/components/xarray/xarray.vue +57 -0
  8. package/packages/components/xautorows/index.js +35 -0
  9. package/packages/components/xautorows/xautorows.vue +29 -0
  10. package/packages/components/xbutton/mobile.js +3 -0
  11. package/packages/components/xbutton/mobile.vue +9 -0
  12. package/packages/components/xbutton/pc.js +3 -0
  13. package/packages/components/xbutton/pc.vue +9 -0
  14. package/packages/components/xbuttons/mobile.js +51 -0
  15. package/packages/components/xbuttons/mobile.vue +12 -0
  16. package/packages/components/xbuttons/pc.js +51 -0
  17. package/packages/components/xbuttons/pc.vue +16 -0
  18. package/packages/components/xchart/constants.js +58 -0
  19. package/packages/components/xchart/index.js +263 -0
  20. package/packages/components/xchart/utils.js +121 -0
  21. package/packages/components/xchart/xchart.vue +173 -0
  22. package/packages/components/xcheckboxs/mobile.js +58 -0
  23. package/packages/components/xcheckboxs/mobile.vue +38 -0
  24. package/packages/components/xcheckboxs/pc.js +49 -0
  25. package/packages/components/xcheckboxs/pc.vue +42 -0
  26. package/packages/components/xcol/mobile.js +10 -0
  27. package/packages/components/xcol/mobile.vue +9 -0
  28. package/packages/components/xcol/pc.js +10 -0
  29. package/packages/components/xcol/pc.vue +9 -0
  30. package/packages/components/xdatepicker/mobile.js +71 -0
  31. package/packages/components/xdatepicker/mobile.vue +44 -0
  32. package/packages/components/xdatepicker/pc.js +9 -0
  33. package/packages/components/xdatepicker/pc.vue +12 -0
  34. package/packages/components/xdialog/mobile.js +60 -0
  35. package/packages/components/xdialog/mobile.vue +43 -0
  36. package/packages/components/xdialog/pc.js +64 -0
  37. package/packages/components/xdialog/pc.vue +51 -0
  38. package/packages/components/xdict/index.js +47 -0
  39. package/packages/components/xdict/xdict.vue +9 -0
  40. package/packages/components/xdistrictselect/mobile.js +79 -0
  41. package/packages/components/xdistrictselect/mobile.vue +28 -0
  42. package/packages/components/xdistrictselect/pc.js +127 -0
  43. package/packages/components/xdistrictselect/pc.vue +32 -0
  44. package/packages/components/xform/mobile.js +29 -0
  45. package/packages/components/xform/mobile.vue +43 -0
  46. package/packages/components/xform/pc.js +42 -0
  47. package/packages/components/xform/pc.vue +76 -0
  48. package/packages/components/xform/utils.js +95 -0
  49. package/packages/components/xformitem/mobile.js +56 -0
  50. package/packages/components/xformitem/mobile.vue +3 -0
  51. package/packages/components/xformitem/pc.js +72 -0
  52. package/packages/components/xformitem/pc.vue +10 -0
  53. package/packages/components/xformitem/utils.jsx +181 -0
  54. package/packages/components/xicon/mobile.js +35 -0
  55. package/packages/components/xicon/mobile.vue +9 -0
  56. package/packages/components/xicon/pc.js +35 -0
  57. package/packages/components/xicon/pc.vue +11 -0
  58. package/packages/components/xinfo/index.js +100 -0
  59. package/packages/components/xinfo/xinfo.vue +140 -0
  60. package/packages/components/xlooper/index.js +7 -0
  61. package/packages/components/xlooper/xlooper.vue +20 -0
  62. package/packages/components/xpagination/mobile.js +21 -0
  63. package/packages/components/xpagination/mobile.vue +31 -0
  64. package/packages/components/xpagination/pc.js +21 -0
  65. package/packages/components/xpagination/pc.vue +16 -0
  66. package/packages/components/xpicker/index.js +38 -0
  67. package/packages/components/xpicker/xpicker.vue +29 -0
  68. package/packages/components/xradios/mobile.js +40 -0
  69. package/packages/components/xradios/mobile.vue +22 -0
  70. package/packages/components/xradios/pc.js +53 -0
  71. package/packages/components/xradios/pc.vue +43 -0
  72. package/packages/components/xrow/mobile.js +9 -0
  73. package/packages/components/xrow/mobile.vue +23 -0
  74. package/packages/components/xrow/pc.js +9 -0
  75. package/packages/components/xrow/pc.vue +22 -0
  76. package/packages/components/xscan/mobile.js +24 -0
  77. package/packages/components/xscan/mobile.vue +21 -0
  78. package/packages/components/xscan/pc.js +20 -0
  79. package/packages/components/xscan/pc.vue +18 -0
  80. package/packages/components/xsearcher/index.js +198 -0
  81. package/packages/components/xsearcher/xsearcher.vue +170 -0
  82. package/packages/components/xselect/mobile.js +86 -0
  83. package/packages/components/xselect/mobile.vue +24 -0
  84. package/packages/components/xselect/pc.js +114 -0
  85. package/packages/components/xselect/pc.vue +55 -0
  86. package/packages/components/xselect/util.js +66 -0
  87. package/packages/components/xselectv2/index.js +91 -0
  88. package/packages/components/xselectv2/xselectv2.vue +46 -0
  89. package/packages/components/xtable/mobile.js +108 -0
  90. package/packages/components/xtable/mobile.vue +246 -0
  91. package/packages/components/xtable/pc.js +143 -0
  92. package/packages/components/xtable/pc.vue +421 -0
  93. package/packages/components/xtable/searcher.js +477 -0
  94. package/packages/components/xtable/searcher.jsx +330 -0
  95. package/packages/components/xtable/searcher.vue +133 -0
  96. package/packages/components/xtable/settings.js +80 -0
  97. package/packages/components/xtable/settings.vue +77 -0
  98. package/packages/components/xtable/utils.js +692 -0
  99. package/packages/components/xtabletools/mobile.js +25 -0
  100. package/packages/components/xtabletools/mobile.vue +126 -0
  101. package/packages/components/xtabletools/pc.js +18 -0
  102. package/packages/components/xtabletools/pc.vue +135 -0
  103. package/packages/components/xtablev2/index.js +53 -0
  104. package/packages/components/xtablev2/utils.jsx +214 -0
  105. package/packages/components/xtablev2/xtablev2.vue +147 -0
  106. package/packages/components/xtags/mobile.js +17 -0
  107. package/packages/components/xtags/mobile.vue +21 -0
  108. package/packages/components/xtags/pc.js +17 -0
  109. package/packages/components/xtags/pc.vue +22 -0
  110. package/packages/components/xtinymce/index.js +71 -0
  111. package/packages/components/xtinymce/xtinymce.vue +9 -0
  112. package/packages/components/xuploader/xfileuploader.js +48 -0
  113. package/packages/components/xuploader/xfileuploader.vue +54 -0
  114. package/packages/components/xuploader/ximageuploader.js +53 -0
  115. package/packages/components/xuploader/ximageuploader.vue +52 -0
  116. package/packages/comps.js +108 -0
  117. package/packages/controllers/BaseController.js +125 -0
  118. package/packages/controllers/CrudController.js +907 -0
  119. package/packages/controllers/TempCrudController.js +32 -0
  120. package/packages/controllers/index.js +15 -0
  121. package/packages/directives/el-table-infinite-scroll.js +55 -0
  122. package/packages/directives/index.js +5 -0
  123. package/packages/index.js +81 -0
  124. package/packages/index.scss +4 -0
  125. package/packages/layout/breadcrumb/breadcrumb.vue +31 -0
  126. package/packages/layout/breadcrumb/index.js +41 -0
  127. package/packages/layout/header/header.vue +281 -0
  128. package/packages/layout/header/inner.js +11 -0
  129. package/packages/layout/header/inner.vue +3 -0
  130. package/packages/layout/mobile-menu.vue +83 -0
  131. package/packages/layout/mobile-tabs.vue +54 -0
  132. package/packages/layout/pc.vue +85 -0
  133. package/packages/layout/screenlock/index.js +129 -0
  134. package/packages/layout/screenlock/screenlock.vue +85 -0
  135. package/packages/layout/sidebar/item.js +16 -0
  136. package/packages/layout/sidebar/item.vue +16 -0
  137. package/packages/layout/sidebar/menu.js +72 -0
  138. package/packages/layout/sidebar/menu.vue +106 -0
  139. package/packages/layout/sidebar/sidebar.vue +147 -0
  140. package/packages/layout/tagsview/ScrollPane.js +65 -0
  141. package/packages/layout/tagsview/ScrollPane.vue +24 -0
  142. package/packages/layout/tagsview/index.js +169 -0
  143. package/packages/layout/tagsview/index.vue +124 -0
  144. package/packages/plop/actions/make-fill-admin-partials-action.js +95 -0
  145. package/packages/plop/generators/make-admin-page.js +39 -0
  146. package/packages/plop/generators/make-database-admin-pages.js +84 -0
  147. package/packages/plop/generators/make-page-generator.js +52 -0
  148. package/packages/plop/generators/make-simple-page.js +20 -0
  149. package/packages/plop/plopfile.js +24 -0
  150. package/packages/plop/templates/admin_page/controller.js +3 -0
  151. package/packages/plop/templates/admin_page/model.js +24 -0
  152. package/packages/plop/templates/admin_page/{{snakeCase pagename}}-scoped.scss +3 -0
  153. package/packages/plop/templates/admin_page/{{snakeCase pagename}}.vue +11 -0
  154. package/packages/plop/templates/simple_page/controller.js +3 -0
  155. package/packages/plop/templates/simple_page/model.js +6 -0
  156. package/packages/plop/templates/simple_page/{{snakeCase pagename}}-scoped.scss +3 -0
  157. package/packages/plop/templates/simple_page/{{snakeCase pagename}}.vue +7 -0
  158. package/packages/plop/utils/index.js +168 -0
  159. package/packages/plop/utils/plop-utils.js +86 -0
  160. package/packages/styles/common.scss +137 -0
  161. package/packages/styles/element-ui.scss +142 -0
  162. package/packages/styles/vant.scss +133 -0
  163. package/packages/styles/variables.scss +23 -0
  164. package/packages/utils/crypt.js +24 -0
  165. package/packages/utils/decorators.js +67 -0
  166. package/packages/utils/disallowDevtools.js +53 -0
  167. package/packages/utils/effects.js +173 -0
  168. package/packages/utils/funcs.js +78 -0
  169. package/packages/utils/index.js +95 -0
  170. package/packages/utils/message.js +110 -0
  171. package/packages/utils/middlewares.js +86 -0
  172. package/packages/utils/model.js +71 -0
  173. package/packages/utils/modelUtils.js +203 -0
  174. package/packages/utils/request.js +57 -0
  175. package/packages/utils/site.js +33 -0
  176. package/packages/vite-plugins.js +141 -0
  177. package/publish.sh +12 -0
@@ -0,0 +1,32 @@
1
+ import CrudController from './CrudController.js'
2
+
3
+ class TempCrudController extends CrudController {
4
+ handleAdd () {
5
+ const $index = this.table.list.length
6
+ const row = {
7
+ _index: $index + 1,
8
+ isEditing: true
9
+ }
10
+ this.table.list.push(row)
11
+ this.handleEdit({ $index, row })
12
+ }
13
+
14
+ handleDelete ({ $index, row }) {
15
+ this.table.list.splice($index, 1)
16
+ }
17
+
18
+ handleRowEdit ({ row }) {
19
+ row.isEditing = false
20
+ }
21
+
22
+ handleSubmit (params) {
23
+ this.dialog.visible = false
24
+ }
25
+
26
+ handleMultiDelete () {
27
+ const { list, selection } = this.table
28
+ this.table.list = list.filter(ele => !selection.includes(ele))
29
+ }
30
+ }
31
+
32
+ export default TempCrudController
@@ -0,0 +1,15 @@
1
+ import BaseController from './BaseController.js'
2
+ import CrudController from './CrudController.js'
3
+ import TempCrudController from './TempCrudController.js'
4
+
5
+ export {
6
+ BaseController,
7
+ CrudController,
8
+ TempCrudController
9
+ }
10
+
11
+ export default {
12
+ BaseController,
13
+ CrudController,
14
+ TempCrudController
15
+ }
@@ -0,0 +1,55 @@
1
+ const { ElInfiniteScroll } = window.ElementPlus || {}
2
+
3
+ const elTableScrollWrapperClass = '.el-scrollbar__wrap'
4
+
5
+ const syncOptions = (sourceElem, targetElem) => {
6
+ syncAttrs(sourceElem, targetElem, [
7
+ 'infinite-scroll-disabled',
8
+ 'infinite-scroll-delay',
9
+ 'infinite-scroll-immediate',
10
+ 'infinite-scroll-distance',
11
+ ])
12
+ const name = 'infinite-scroll-distance'
13
+ const value = +(sourceElem.getAttribute(name) || 0)
14
+ targetElem.setAttribute(name, (value < 1 ? 1 : value) + '')
15
+ }
16
+
17
+ const syncAttrs = (sourceElem, targetElem, attrsKeys) => {
18
+ let value
19
+ attrsKeys.forEach((name) => {
20
+ value = sourceElem.getAttribute(name)
21
+ if (value !== null) {
22
+ targetElem.setAttribute(name, value)
23
+ } else {
24
+ targetElem.removeAttribute(name)
25
+ }
26
+ })
27
+ }
28
+
29
+ const ElTableInfiniteScroll = {
30
+ name: 'el-table-infinite-scroll',
31
+ mounted(el, binding, VNode, oldVNode) {
32
+ const scrollElem = el.querySelector(elTableScrollWrapperClass)
33
+ if (!scrollElem) {
34
+ throw new Error(`${elTableScrollWrapperClass} element not found.`)
35
+ }
36
+ scrollElem.style.overflowY = 'auto'
37
+ setTimeout(() => {
38
+ if (!el.style.height && !el.style.maxHeight) {
39
+ scrollElem.style.height = '400px'
40
+ console.warn('el-table height required, otherwise will set scrollbar default height: 400px')
41
+ }
42
+ syncOptions(el, scrollElem)
43
+ ElInfiniteScroll.mounted(scrollElem, binding, VNode, oldVNode)
44
+ }, 0)
45
+ },
46
+ updated(el) {
47
+ syncOptions(el, el.querySelector(elTableScrollWrapperClass))
48
+ },
49
+ unmounted(el, ...args) {
50
+ const scrollElem = el.querySelector(elTableScrollWrapperClass)
51
+ ElInfiniteScroll.unmounted(scrollElem, ...args)
52
+ }
53
+ }
54
+
55
+ export default ElTableInfiniteScroll
@@ -0,0 +1,5 @@
1
+ import ElTableInfiniteScroll from './el-table-infinite-scroll.js'
2
+
3
+ export default {
4
+ ElTableInfiniteScroll
5
+ }
@@ -0,0 +1,81 @@
1
+ import { h } from 'vue'
2
+
3
+ import './index.scss'
4
+
5
+ import { initMessageUtils } from './utils/message.js'
6
+ import utils from './utils/index.js'
7
+ import controllers from './controllers/index.js'
8
+ import all from './comps'
9
+ import directives from './directives/index.js'
10
+
11
+ const makePlatformComp = (name) => {
12
+ return {
13
+ name,
14
+ props: {
15
+ platform: {
16
+ type: String,
17
+ default: window.isMobile ? 'mobile' : 'pc'
18
+ }
19
+ },
20
+ data () {
21
+ return { name: '' }
22
+ },
23
+ created () {
24
+ this.name = (this.platform.toLowerCase() === 'pc' ? 'Pc' : 'Mobile') + name
25
+ },
26
+ render () {
27
+ return h(all[this.name], {
28
+ platform: this.platform,
29
+ ...this.$attrs
30
+ }, this.$slots)
31
+ }
32
+ }
33
+ }
34
+
35
+ const components = (() => {
36
+ const names = Object.keys(all)
37
+ const union = [...new Set(names.map(n => n.replace(/(pc|mobile)/i, '')))]
38
+
39
+ const comps = {}
40
+ for (const name of names) {
41
+ if (/(pc|mobile)/i.test(name)) {
42
+ comps[name] = all[name]
43
+ }
44
+ }
45
+ for (const name of union) {
46
+ if (!names.find(n => /(pc|mobile)/i.test(n) && n.toLowerCase().includes(name.toLowerCase()))) {
47
+ comps[name] = all[name]
48
+ } else {
49
+ comps[name] = makePlatformComp(name)
50
+ }
51
+ }
52
+ return comps
53
+ })()
54
+
55
+ const install = (app, options) => {
56
+ initMessageUtils(options)
57
+ for (let key in components) {
58
+ app.component(key, components[key])
59
+ }
60
+ for (let key in directives) {
61
+ app.directive(directives[key].name, directives[key])
62
+ }
63
+ }
64
+
65
+ const StardustUI = {
66
+ version: '2.9.13',
67
+ ...components,
68
+ ...utils,
69
+ ...controllers,
70
+ install
71
+ }
72
+
73
+ export {
74
+ utils,
75
+ controllers
76
+ }
77
+
78
+ export * from './utils/index.js'
79
+ export * from './controllers/index.js'
80
+
81
+ export default StardustUI
@@ -0,0 +1,4 @@
1
+ @import "./styles/variables.scss";
2
+ @import "./styles/element-ui.scss";
3
+ @import "./styles/vant.scss";
4
+ @import "./styles/common.scss";
@@ -0,0 +1,31 @@
1
+ <script>
2
+ export { default } from './index.js'
3
+ </script>
4
+
5
+ <template>
6
+ <el-breadcrumb class="app-breadcrumb" separator="/">
7
+ <transition-group name="breadcrumb">
8
+ <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
9
+ <span v-if="index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
10
+ <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
11
+ </el-breadcrumb-item>
12
+ </transition-group>
13
+ </el-breadcrumb>
14
+ </template>
15
+
16
+ <style lang="scss" scoped>
17
+ .app-breadcrumb.el-breadcrumb {
18
+ display: inline-block;
19
+ font-size: 14px;
20
+ line-height: 50px;
21
+
22
+ .el-breadcrumb__inner a {
23
+ font-weight: 400;
24
+ }
25
+
26
+ .no-redirect {
27
+ color: #97a8be;
28
+ cursor: text;
29
+ }
30
+ }
31
+ </style>
@@ -0,0 +1,41 @@
1
+ import { pathToRegexp } from 'path-to-regexp'
2
+
3
+ export default {
4
+ data() {
5
+ return {
6
+ levelList: null
7
+ }
8
+ },
9
+ watch: {
10
+ $route(route) {
11
+ if (route.path.startsWith('/redirect/')) {
12
+ return
13
+ }
14
+ this.getBreadcrumb()
15
+ }
16
+ },
17
+ created() {
18
+ this.getBreadcrumb()
19
+ },
20
+ methods: {
21
+ getBreadcrumb() {
22
+ let matched = this.$route.matched.filter(item => item.meta?.title)
23
+ const first = matched[0]
24
+
25
+ this.levelList = matched.filter(item => item.meta?.title && item.meta.breadcrumb !== false)
26
+ },
27
+ pathCompile(path) {
28
+ const { params } = this.$route
29
+ var toPath = pathToRegexp(path)
30
+ return toPath(params)
31
+ },
32
+ handleLink(item) {
33
+ const { redirect, path } = item
34
+ if (redirect) {
35
+ this.$router.push(redirect)
36
+ return
37
+ }
38
+ this.$router.push(this.pathCompile(path))
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,281 @@
1
+ <script setup>
2
+ import { reactive, inject, computed, nextTick } from 'vue'
3
+ import store from '@/store'
4
+ import router from '@/router'
5
+
6
+ import Breadcrumb from '../breadcrumb/breadcrumb.vue'
7
+ import Inner from './inner.vue'
8
+
9
+ const { funcs } = StardustJs
10
+ const { storage, fullscreen } = StardustBrowser
11
+
12
+ const { session, local } = storage
13
+ const { app, user } = store
14
+ const { info } = user
15
+
16
+ const model = reactive({
17
+ themeDialogVisible: false,
18
+ colorIndex: -1,
19
+ themeColors: ['#1B5297', '#F5222D', '#FA541C', '#FAAD14', '#13C2C2', '#52C41A', '#1890FF', '#2F54EB', '#722ED1']
20
+ })
21
+
22
+ const handleToggleSidebar = () => {
23
+ app.$patch({
24
+ sidebarToggled: true,
25
+ sidebarCollapse: !app.sidebarCollapse
26
+ })
27
+ }
28
+
29
+ const handleToggleFullscreen = () => {
30
+ const { isOpened, open, exit } = fullscreen
31
+ isOpened() ? exit() : open()
32
+ }
33
+
34
+ const handleClearStorage = () => {
35
+ session.clear()
36
+ local.noClearKeys.add('cacheState')
37
+ local.clear()
38
+ local.noClearKeys.delete('cacheState')
39
+ window.location.reload()
40
+ }
41
+
42
+ const handleLockScreen = () => {
43
+ app.screenLock.isLocked = true
44
+ }
45
+
46
+ const handleSetTheme = () => {
47
+ model.themeDialogVisible = true
48
+ }
49
+
50
+ const handleReset = () => {
51
+ const theme = local.getJson('theme')
52
+ for (let key in theme) {
53
+ theme[key] = ''
54
+ }
55
+ setTheme(theme)
56
+ local.setJson('theme', theme)
57
+ }
58
+
59
+ const handleSetThemeColor = (color) => {
60
+ const root = document.documentElement
61
+ const [r, g, b] = [0, 1, 2].map(n => parseInt(color.slice(1 + n * 2, 1 + n * 2 + 2), 16))
62
+ const avg = (r + g + b) / 3
63
+ const rgb2Hex = (...rgba) => '#' + rgba.map(n => n.toString(16)).join('')
64
+ const theme = {
65
+ color,
66
+ '--x-bg-color': rgb2Hex(r, g, b, 30),
67
+ '--x-sidebar-bg-color': color,
68
+ '--x-sidebar-current-bg-color': rgb2Hex(20, 20, 20, 170),
69
+ '--x-sidebar-hover-bg-color': rgb2Hex(20, 20, 20, 200),
70
+ '--x-sidebar-text-color': avg < 128 ? '#e0eeee' : '#303333',
71
+ '--x-sidebar-current-text-color': avg < 128 ? '#b0bbbb' : '#606666'
72
+ }
73
+ setTheme(theme)
74
+ local.setJson('theme', theme)
75
+ }
76
+
77
+ const setTheme = theme => {
78
+ model.colorIndex = model.themeColors.indexOf(theme.color)
79
+ const root = document.documentElement
80
+ for (let key in theme) {
81
+ if (key === 'color') continue
82
+ root.style.setProperty(key, theme[key])
83
+ }
84
+ }
85
+
86
+ const handleLogout = async () => {
87
+ await router.replace('/login')
88
+ await funcs.sleep(50)
89
+ session.clear()
90
+ local.clear()
91
+ window.location.reload()
92
+ }
93
+
94
+ const config = inject('config')
95
+ const { icons = null } = config?.header || {}
96
+ setTheme(local.getJson('theme', {}))
97
+ </script>
98
+
99
+ <template>
100
+ <div class="header">
101
+ <div class="toggler flex-center" @click="handleToggleSidebar">
102
+ <svg
103
+ viewBox="0 0 1024 1024"
104
+ xmlns="http://www.w3.org/2000/svg"
105
+ width="23"
106
+ height="23"
107
+ :class="{ active: app.sidebarCollapse }"
108
+ >
109
+ <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
110
+ </svg>
111
+ </div>
112
+
113
+ <Breadcrumb v-if="app.breadcrumbVisible" class="breadcrumb" />
114
+
115
+ <Inner />
116
+
117
+ <div class="right flex-center">
118
+ <span class="user flex-center">
119
+ <el-avatar shape="circle" :src="info.avatar" class="avatar">
120
+ {{ info.username[0].toUpperCase() }}
121
+ </el-avatar>
122
+ <span class="name">{{ info.username }}</span>
123
+ </span>
124
+ <el-tooltip
125
+ v-if="!icons || icons.includes('fullscreen')"
126
+ effect="light"
127
+ content="全屏"
128
+ >
129
+ <x-icon
130
+ name="FullScreen"
131
+ class="full"
132
+ @click="handleToggleFullscreen"
133
+ />
134
+ </el-tooltip>
135
+ <el-tooltip
136
+ v-if="!icons || icons.includes('screen_lock')"
137
+ effect="light"
138
+ content="锁屏"
139
+ >
140
+ <x-icon
141
+ name="Lock"
142
+ class="lock"
143
+ @click="handleLockScreen"
144
+ />
145
+ </el-tooltip>
146
+ <el-tooltip
147
+ v-if="!icons || icons.includes('clear_storage')"
148
+ effect="light"
149
+ content="清除缓存"
150
+ >
151
+ <x-icon
152
+ name="Delete"
153
+ class="clear"
154
+ @click="handleClearStorage"
155
+ />
156
+ </el-tooltip>
157
+ <el-tooltip
158
+ v-if="!icons || icons.includes('theme')"
159
+ effect="light"
160
+ content="主题"
161
+ >
162
+ <x-icon
163
+ name="Brush"
164
+ class="theme"
165
+ @click="handleSetTheme"
166
+ />
167
+ </el-tooltip>
168
+ <el-tooltip
169
+ v-if="!icons || icons.includes('logout')"
170
+ effect="light"
171
+ content="退出"
172
+ >
173
+ <x-icon
174
+ :name="app.isMobile ? 'stop-circle-o' : 'SwitchButton'"
175
+ class="logout"
176
+ @click="handleLogout"
177
+ />
178
+ </el-tooltip>
179
+ </div>
180
+
181
+ <x-dialog
182
+ title="主题设置"
183
+ v-model="model.themeDialogVisible"
184
+ drawer
185
+ class="theme-dialog"
186
+ >
187
+ <div class="block">
188
+ <div class="title">主题色</div>
189
+ <div class="theme-colors">
190
+ <div
191
+ v-for="(color, index) in model.themeColors"
192
+ :key="color"
193
+ class="color"
194
+ :class="{ active: index === model.colorIndex }"
195
+ :style="{ backgroundColor: color }"
196
+ @click="handleSetThemeColor(color)"
197
+ />
198
+ </div>
199
+ </div>
200
+ <el-button type="primary" @click="handleReset">恢复默认</el-button>
201
+ </x-dialog>
202
+ </div>
203
+ </template>
204
+
205
+ <style lang="scss" scoped>
206
+ .header {
207
+ padding: 10px 0;
208
+ position: relative;
209
+ box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
210
+ .toggler {
211
+ cursor: pointer;
212
+ width: var(--x-header-height);
213
+ height: var(--x-header-height);
214
+ margin-right: 10px;
215
+ &:hover {
216
+ background-color: #f8f8f8;
217
+ }
218
+ svg {
219
+ transform: rotate(180deg);
220
+ &.active {
221
+ transform: rotate(0);
222
+ }
223
+ }
224
+ }
225
+ .right {
226
+ position: absolute;
227
+ right: 0.1rem;
228
+ top: 50%;
229
+ transform: translateY(-50%);
230
+ font-size: 15px;
231
+ .el-icon {
232
+ font-size: 20px;
233
+ margin-left: 10px;
234
+ cursor: pointer;
235
+ }
236
+ .user {
237
+ color: #626aef;
238
+ display: inline-flex;
239
+ vertical-align: top;
240
+ }
241
+ .avatar {
242
+ margin-right: 10px;
243
+ }
244
+ .el-icon {
245
+ &:hover {
246
+ color: var(--el-color-primary);
247
+ }
248
+ }
249
+ }
250
+ }
251
+ .theme-dialog {
252
+ .block {
253
+ padding-bottom: 10px;
254
+ margin-bottom: 10px;
255
+ border-bottom: 1px solid #e0eeee;
256
+ }
257
+ .title {
258
+ font-size: 16px;
259
+ margin-bottom: 10px;
260
+ }
261
+ .color {
262
+ display: inline-block;
263
+ cursor: pointer;
264
+ width: 25px;
265
+ height: 25px;
266
+ border-radius: 2px;
267
+ margin-right: 5px;
268
+ margin-bottom: 5px;
269
+ position: relative;
270
+ &.active::after {
271
+ content: '✓';
272
+ display: inline-block;
273
+ position: absolute;
274
+ left: 50%;
275
+ top: 50%;
276
+ transform: translate(-50%, -50%);
277
+ color: white;
278
+ }
279
+ }
280
+ }
281
+ </style>
@@ -0,0 +1,11 @@
1
+ import { h } from 'vue'
2
+
3
+ export default {
4
+ name: 'Inner',
5
+ render () {
6
+ const inner = this.HeaderInner
7
+ if (inner) {
8
+ return typeof inner === 'function' ? inner() : h(inner)
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,3 @@
1
+ <script>
2
+ export { default } from './inner.js'
3
+ </script>
@@ -0,0 +1,83 @@
1
+ <script setup>
2
+ import { ref, watch, onMounted } from 'vue'
3
+ import { useRoute } from 'vue-router'
4
+ import store from '@/store'
5
+
6
+ import Sidebar from './sidebar/sidebar.vue'
7
+
8
+ const route = useRoute()
9
+
10
+ const sidebarVisible = ref(false)
11
+
12
+ watch(route, () => sidebarVisible.value = false)
13
+
14
+ onMounted(() => {
15
+ store.app.sidebarCollapse = false
16
+ })
17
+
18
+ const handleToggleSidebar = () => {
19
+ sidebarVisible.value = !sidebarVisible.value
20
+ }
21
+ </script>
22
+
23
+ <template>
24
+ <div class="mobile-menu-layout" :class="{ 'hide-nav-bar': route.meta.hideNavBar }">
25
+ <van-nav-bar
26
+ v-show="!route.meta.hideNavBar"
27
+ :left-text="route.meta.canBack !== false ? '返回' : ''"
28
+ :left-arrow="route.meta.canBack !== false"
29
+ :title="route.meta.title"
30
+ @click-left="$router.go(-1)"
31
+ >
32
+ <template #right>
33
+ <div class="toggler flex-center" @click="handleToggleSidebar">
34
+ <svg
35
+ viewBox="0 0 1024 1024"
36
+ xmlns="http://www.w3.org/2000/svg"
37
+ width="23"
38
+ height="23"
39
+ :class="{ active: sidebarVisible }"
40
+ >
41
+ <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
42
+ </svg>
43
+ </div>
44
+ </template>
45
+ </van-nav-bar>
46
+ <main :class="{ 'has-sidebar': sidebarVisible }">
47
+ <router-view />
48
+ <van-overlay
49
+ v-if="sidebarVisible"
50
+ :show="true"
51
+ @click="handleToggleSidebar"
52
+ >
53
+ <Sidebar />
54
+ </van-overlay>
55
+ </main>
56
+ </div>
57
+ </template>
58
+
59
+ <style lang="scss" scoped>
60
+ svg {
61
+ transform: rotate(180deg);
62
+ &.active {
63
+ transform: rotate(0);
64
+ }
65
+ }
66
+ main {
67
+ height: calc(100vh - var(--van-nav-bar-height));
68
+ overflow-y: auto;
69
+ .sidebar {
70
+ position: absolute;
71
+ left: 0;
72
+ top: 0;
73
+ height: 100%;
74
+ :deep(.arrow-down) {
75
+ top: 0.3rem;
76
+ right: 0.15rem;
77
+ }
78
+ }
79
+ }
80
+ .hide-nav-bar main {
81
+ height: 100%;
82
+ }
83
+ </style>