@yyp92-cli/template-vue-pc 1.2.0

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 (113) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +15 -0
  3. package/template/.env.development +2 -0
  4. package/template/.env.production +2 -0
  5. package/template/.env.test +2 -0
  6. package/template/README.md +30 -0
  7. package/template/auto-imports.d.ts +11 -0
  8. package/template/components.d.ts +67 -0
  9. package/template/index.html +16 -0
  10. package/template/package.json +43 -0
  11. package/template/pnpm-lock.yaml +2830 -0
  12. package/template/public/vite.svg +1 -0
  13. package/template/src/App.vue +26 -0
  14. package/template/src/assets/img/login-bg.jpg +0 -0
  15. package/template/src/assets/img/logo.svg +15 -0
  16. package/template/src/components/layout/header-crumb/index.vue +38 -0
  17. package/template/src/components/layout/header-info/index.vue +181 -0
  18. package/template/src/components/layout/index.vue +83 -0
  19. package/template/src/components/layout/main-header/index.vue +85 -0
  20. package/template/src/components/layout/main-menu/index.vue +166 -0
  21. package/template/src/components/layout-horizontal/header-crumb/index.vue +38 -0
  22. package/template/src/components/layout-horizontal/header-info/index.vue +185 -0
  23. package/template/src/components/layout-horizontal/index.vue +55 -0
  24. package/template/src/components/layout-horizontal/main-header/index.vue +86 -0
  25. package/template/src/components/layout-horizontal/main-menu/index.vue +135 -0
  26. package/template/src/global/constants.ts +4 -0
  27. package/template/src/global/register-icons.ts +10 -0
  28. package/template/src/main.ts +16 -0
  29. package/template/src/mock/index.ts +8 -0
  30. package/template/src/mock/login.ts +5 -0
  31. package/template/src/mock/userDepartmentList.ts +85 -0
  32. package/template/src/mock/userInfoMock.ts +24 -0
  33. package/template/src/mock/userList.ts +115 -0
  34. package/template/src/mock/userListDelete.ts +1 -0
  35. package/template/src/mock/userMenuList.ts +466 -0
  36. package/template/src/mock/userMenus.ts +374 -0
  37. package/template/src/mock/userRoleList.ts +1846 -0
  38. package/template/src/router/index.ts +41 -0
  39. package/template/src/router/routes.ts +189 -0
  40. package/template/src/service/api/index.ts +90 -0
  41. package/template/src/service/request/index.ts +268 -0
  42. package/template/src/service/request/type.ts +5 -0
  43. package/template/src/store/counter.ts +19 -0
  44. package/template/src/store/index.ts +14 -0
  45. package/template/src/store/login/index.ts +142 -0
  46. package/template/src/store/main/index.ts +54 -0
  47. package/template/src/store/main/system/index.ts +88 -0
  48. package/template/src/store/main/system/type.ts +19 -0
  49. package/template/src/styles/global.scss +33 -0
  50. package/template/src/styles/index.scss +4 -0
  51. package/template/src/styles/reset.scss +17 -0
  52. package/template/src/theme/darkTheme.scss +51 -0
  53. package/template/src/theme/lightTheme.scss +53 -0
  54. package/template/src/types/index.ts +1 -0
  55. package/template/src/types/login.ts +4 -0
  56. package/template/src/utils/cache.ts +44 -0
  57. package/template/src/utils/download.ts +27 -0
  58. package/template/src/utils/format.ts +10 -0
  59. package/template/src/utils/index.ts +14 -0
  60. package/template/src/utils/map-menus.ts +174 -0
  61. package/template/src/views/403/index.vue +22 -0
  62. package/template/src/views/login/component/login-panel.vue +138 -0
  63. package/template/src/views/login/component/panel-account.vue +138 -0
  64. package/template/src/views/login/component/panel-phone.vue +56 -0
  65. package/template/src/views/login/index.vue +28 -0
  66. package/template/src/views/main/analysis/dashboard/index.vue +19 -0
  67. package/template/src/views/main/analysis/overview/index.vue +25 -0
  68. package/template/src/views/main/detail/index.vue +19 -0
  69. package/template/src/views/main/fullScreen/images/bg.png +0 -0
  70. package/template/src/views/main/fullScreen/images/contrast-bg.png +0 -0
  71. package/template/src/views/main/fullScreen/images/dataScreen-alarm.png +0 -0
  72. package/template/src/views/main/fullScreen/images/dataScreen-header-btn-bg-l.png +0 -0
  73. package/template/src/views/main/fullScreen/images/dataScreen-header-btn-bg-r.png +0 -0
  74. package/template/src/views/main/fullScreen/images/dataScreen-header-center-bg.png +0 -0
  75. package/template/src/views/main/fullScreen/images/dataScreen-header-left-bg.png +0 -0
  76. package/template/src/views/main/fullScreen/images/dataScreen-header-right-bg.png +0 -0
  77. package/template/src/views/main/fullScreen/images/dataScreen-header-warn-bg.png +0 -0
  78. package/template/src/views/main/fullScreen/images/dataScreen-main-cb.png +0 -0
  79. package/template/src/views/main/fullScreen/images/dataScreen-main-lb.png +0 -0
  80. package/template/src/views/main/fullScreen/images/dataScreen-main-lc.png +0 -0
  81. package/template/src/views/main/fullScreen/images/dataScreen-main-lt.png +0 -0
  82. package/template/src/views/main/fullScreen/images/dataScreen-main-rb.png +0 -0
  83. package/template/src/views/main/fullScreen/images/dataScreen-main-rc.png +0 -0
  84. package/template/src/views/main/fullScreen/images/dataScreen-main-rt.png +0 -0
  85. package/template/src/views/main/fullScreen/images/dataScreen-title.png +0 -0
  86. package/template/src/views/main/fullScreen/images/dataScreen-warn-bg.png +0 -0
  87. package/template/src/views/main/fullScreen/images/line-bg.png +0 -0
  88. package/template/src/views/main/fullScreen/images/man-bg.png +0 -0
  89. package/template/src/views/main/fullScreen/images/man.png +0 -0
  90. package/template/src/views/main/fullScreen/images/map-title-bg.png +0 -0
  91. package/template/src/views/main/fullScreen/images/rankingChart-bg.png +0 -0
  92. package/template/src/views/main/fullScreen/images/total.png +0 -0
  93. package/template/src/views/main/fullScreen/images/woman-bg.png +0 -0
  94. package/template/src/views/main/fullScreen/images/woman.png +0 -0
  95. package/template/src/views/main/fullScreen/index.vue +33 -0
  96. package/template/src/views/main/index.vue +24 -0
  97. package/template/src/views/main/product/category/index.vue +19 -0
  98. package/template/src/views/main/product/goods/index.vue +19 -0
  99. package/template/src/views/main/story/chat/index.vue +70 -0
  100. package/template/src/views/main/story/list/index.vue +19 -0
  101. package/template/src/views/main/system/department/index.vue +20 -0
  102. package/template/src/views/main/system/menu/index.vue +19 -0
  103. package/template/src/views/main/system/role/index.vue +20 -0
  104. package/template/src/views/main/system/user/index.vue +141 -0
  105. package/template/src/views/main/system/user/user-comp/UserContent.vue +211 -0
  106. package/template/src/views/main/system/user/user-comp/UserModal.vue +225 -0
  107. package/template/src/views/main/system/user/user-comp/UserSearch.vue +147 -0
  108. package/template/src/views/not-found/index.vue +22 -0
  109. package/template/src/vite-env.d.ts +9 -0
  110. package/template/tsconfig.app.json +26 -0
  111. package/template/tsconfig.json +7 -0
  112. package/template/tsconfig.node.json +25 -0
  113. package/template/vite.config.ts +66 -0
@@ -0,0 +1,174 @@
1
+ import {routes} from '@/router/routes'
2
+ import useLoginStore from "@/store/login"
3
+
4
+ export let localRoutes: any[] = []
5
+
6
+ export function mapMenusToRoutes() {
7
+ const {permissions} = useLoginStore()
8
+ const newRoutes: any = []
9
+ const newLocalRoutes: any = [];
10
+
11
+ (routes as any)[0].children.forEach((group: any) => {
12
+ const {
13
+ path,
14
+ name,
15
+ meta,
16
+ children = []
17
+ } = group ?? {}
18
+ const {
19
+ title,
20
+ hideMenu,
21
+ icon,
22
+ showFullScreen
23
+ } = meta ?? {}
24
+ newLocalRoutes.push(path)
25
+
26
+ if (!hideMenu && permissions.includes(path)) {
27
+ const newChildren:any = []
28
+ children.forEach((item: any) => {
29
+ if (permissions.includes(item.path) && !item.meta.hideMenu) {
30
+ newChildren.push({
31
+ path: item.path,
32
+ name: item.name,
33
+ title: item.meta.title
34
+ })
35
+ }
36
+ newLocalRoutes.push(item.path)
37
+ })
38
+
39
+ newRoutes.push({
40
+ path,
41
+ name,
42
+ title,
43
+ icon,
44
+ showFullScreen: !!showFullScreen,
45
+ children: newChildren?.length ? newChildren : null
46
+ })
47
+ }
48
+ else {
49
+ const list = children.map((item: any) => item.path)
50
+ newLocalRoutes.push(...list)
51
+ }
52
+ })
53
+
54
+ localRoutes = newLocalRoutes
55
+
56
+ return newRoutes
57
+ }
58
+
59
+ // * 获取菜单的重定向
60
+ export const getMenusRedirect = (menus: any[], targetUrl: string) => {
61
+ let url = ''
62
+
63
+ menus.forEach((item: any) => {
64
+ if (item.path === targetUrl && item?.children?.length) {
65
+ url = item.children[0].path
66
+ }
67
+ })
68
+
69
+ return url
70
+ }
71
+
72
+ // * / 重定向
73
+ export let getFirstMenu = (menus: any[]) => {
74
+ const firstItem = menus[0]
75
+ if (!firstItem.children.length) {
76
+ return firstItem.path
77
+ }
78
+
79
+ return firstItem.children[0].path
80
+ }
81
+
82
+ /**
83
+ * 根据路径去匹配需要显示的菜单
84
+ * @param path 需要匹配的路径
85
+ * @param userMenus 所有的菜单
86
+ */
87
+ export function mapPathToMenu(path: string, userMenus: any[]) {
88
+ for (const menu of userMenus) {
89
+ if (menu?.children) {
90
+ for (const submenu of menu.children) {
91
+ if (submenu.path === path) {
92
+ return submenu
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ /**
100
+ * 根据路径去匹配需要显示的菜单, 生成面包屑
101
+ * @param path 需要匹配的路径
102
+ * @param userMenus 所有的菜单
103
+ */
104
+ interface Breadcrumbs {
105
+ name: string
106
+ path?: string
107
+ }
108
+ export function mapPathToBreadcrumbs(path: string, userMenus: any[]) {
109
+ const breadcrumbs: Breadcrumbs[] = []
110
+
111
+ for (const menu of userMenus) {
112
+ if (menu?.children) {
113
+ for (const submenu of menu.children) {
114
+ if (submenu.path === path) {
115
+ breadcrumbs.push({
116
+ name: menu.title,
117
+ path: menu.path
118
+ })
119
+ breadcrumbs.push({
120
+ name: submenu.title,
121
+ path: submenu.path
122
+ })
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ return breadcrumbs
129
+ }
130
+
131
+ /**
132
+ * 菜单映射到 id 的列表
133
+ * @param menulist
134
+ */
135
+ export function mapMenulistToIds(menulist: any[]) {
136
+ const ids: number[] = []
137
+
138
+ function recurseGetId(menus: any[]) {
139
+ for (const item of menus) {
140
+ if (item?.children) {
141
+ recurseGetId(item.children)
142
+ }
143
+ else {
144
+ ids.push(item.id)
145
+ }
146
+ }
147
+ }
148
+ recurseGetId(menulist)
149
+
150
+ return ids
151
+ }
152
+
153
+ /**
154
+ * 从菜单映射到按钮的权限
155
+ * @param menuList 菜单列表
156
+ * @returns 权限的数组(字符串数组)
157
+ */
158
+ export function mapMenusToPermissions(menuList: any[]) {
159
+ const permissions: string[] = []
160
+
161
+ function recurseGetPermission(menus: any[]) {
162
+ for (const item of menus) {
163
+ if (item.type === 3) {
164
+ permissions.push(item.permission)
165
+ }
166
+ else {
167
+ recurseGetPermission(item?.children ?? [])
168
+ }
169
+ }
170
+ }
171
+ recurseGetPermission(menuList)
172
+
173
+ return permissions
174
+ }
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <div class="not-found-wraper">
3
+ <el-result
4
+ icon="error"
5
+ title="403"
6
+ sub-title="你没有权限访问该页面!"
7
+ ></el-result>
8
+ </div>
9
+ </template>
10
+
11
+ <script
12
+ setup
13
+ lang="ts"
14
+ name="NoAuth"
15
+ >
16
+ </script>
17
+
18
+ <style
19
+ scoped
20
+ lang="scss"
21
+ >
22
+ </style>
@@ -0,0 +1,138 @@
1
+ <template>
2
+ <div class="login-panel">
3
+ <h1 class="title">后台管理系统</h1>
4
+
5
+ <div class="tabs">
6
+ <el-tabs
7
+ type="border-card"
8
+ stretch
9
+ v-model="activeName"
10
+ >
11
+ <el-tab-pane
12
+ name="account"
13
+ >
14
+ <template #label>
15
+ <div class="label">
16
+ <el-icon>
17
+ <UserFilled />
18
+ </el-icon>
19
+
20
+ <span class="text">账号登录</span>
21
+ </div>
22
+ </template>
23
+
24
+ <PanelAccount ref="accountRef"/>
25
+ </el-tab-pane>
26
+
27
+ <el-tab-pane
28
+ name="phone"
29
+ >
30
+ <template #label>
31
+ <div class="label">
32
+ <el-icon>
33
+ <Cellphone />
34
+ </el-icon>
35
+
36
+ <span class="text">手机登录</span>
37
+ </div>
38
+ </template>
39
+
40
+ <PanelPhone />
41
+ </el-tab-pane>
42
+ </el-tabs>
43
+ </div>
44
+
45
+ <div class="controls">
46
+ <el-checkbox
47
+ v-model="isRememberPassword"
48
+ label="记住密码"
49
+ size="large"
50
+ />
51
+
52
+ <el-link
53
+ type="primary"
54
+ >忘记密码</el-link>
55
+ </div>
56
+
57
+ <el-button
58
+ class="login-btn"
59
+ type="primary"
60
+ size="large"
61
+ @click="handleLoginAction"
62
+ :loading="activeName === 'account' ? accountRef?.loginLoading : false"
63
+ >立即登录</el-button>
64
+ </div>
65
+ </template>
66
+
67
+ <script
68
+ setup
69
+ lang="ts"
70
+ name="LoginPanel"
71
+ >
72
+ import {ref, watch} from 'vue'
73
+ import PanelAccount from './panel-account.vue'
74
+ import PanelPhone from './panel-phone.vue'
75
+ import { localCache } from '@/utils/cache'
76
+
77
+ const CHACHE_IS_REMEMBER_PASSWORD = 'isRememberPassword'
78
+ const activeName = ref('account')
79
+ const isRememberPassword = ref(localCache.getCache(CHACHE_IS_REMEMBER_PASSWORD) ?? false)
80
+ const accountRef = ref<InstanceType<typeof PanelAccount>>()
81
+
82
+ // 保留记住密码的状态
83
+ watch(isRememberPassword, (value) => {
84
+ localCache.setCache(CHACHE_IS_REMEMBER_PASSWORD, value)
85
+ })
86
+
87
+ const handleLoginAction = () => {
88
+ if (activeName.value === 'account') {
89
+ accountRef.value?.loginAction(isRememberPassword.value)
90
+
91
+ return
92
+ }
93
+
94
+ console.log('用户进行手机登录')
95
+ }
96
+ </script>
97
+
98
+ <style
99
+ scoped
100
+ lang="scss"
101
+ >
102
+ h1 {
103
+ margin: 0;
104
+ }
105
+
106
+ .login-panel {
107
+ width: 330px;
108
+ background: #fff;
109
+ border-radius: 8px;
110
+ padding: 16px 24px;
111
+ }
112
+
113
+ .title {
114
+ text-align: center;
115
+ margin-bottom: 15px;
116
+ }
117
+
118
+ .label {
119
+ display: flex;
120
+ justify-content: space-between;
121
+ align-items: center;
122
+
123
+ .text {
124
+ margin-left: 5px;
125
+ }
126
+ }
127
+
128
+ .controls {
129
+ display: flex;
130
+ justify-content: space-between;
131
+ align-items: center;
132
+ }
133
+
134
+ .login-btn {
135
+ width: 100%;
136
+ margin-top: 10px;
137
+ }
138
+ </style>
@@ -0,0 +1,138 @@
1
+ <template>
2
+ <div class="panel-account">
3
+ <el-form
4
+ label-width="60px"
5
+ size="large"
6
+ :model="account"
7
+ :rules="accountRules"
8
+ ref="formRef"
9
+ >
10
+ <el-form-item
11
+ label="账号"
12
+ prop="name"
13
+ >
14
+ <el-input
15
+ v-model="account.name"
16
+ />
17
+ </el-form-item>
18
+
19
+ <el-form-item
20
+ label="密码"
21
+ prop="password"
22
+ >
23
+ <el-input
24
+ show-password
25
+ v-model="account.password"
26
+ />
27
+ </el-form-item>
28
+ </el-form>
29
+ </div>
30
+ </template>
31
+
32
+ <script
33
+ setup
34
+ lang="ts"
35
+ name="PanelAccount"
36
+ >
37
+ import {reactive, ref} from 'vue'
38
+ import {ElMessage} from 'element-plus'
39
+ import {useRouter, useRoute} from 'vue-router'
40
+ import type {FormRules, ElForm} from 'element-plus'
41
+ import useLoginStore from '@/store/login'
42
+ import type {IAccount} from '@/types'
43
+ import { localCache } from '@/utils/cache'
44
+
45
+ const CHACHE_NAME = 'name'
46
+ const CHACHE_PASSWORD = 'password'
47
+
48
+ const router = useRouter()
49
+ const route = useRoute()
50
+ const loginStore = useLoginStore()
51
+ const account = reactive<IAccount>({
52
+ name: localCache.getCache(CHACHE_NAME) ?? '',
53
+ password: localCache.getCache(CHACHE_PASSWORD) ?? ''
54
+ })
55
+ const loginLoading = ref(false)
56
+ const formRef = ref<InstanceType<typeof ElForm>>()
57
+
58
+
59
+ // 检验规则
60
+ const accountRules: FormRules = {
61
+ name: [
62
+ {
63
+ required: true,
64
+ message: '必须输入账号信息',
65
+ trigger: 'blur'
66
+ },
67
+ {
68
+ pattern: /^[a-zA-Z0-9]{6,20}$/,
69
+ message: '必须6~20位数字和字母组成',
70
+ trigger: 'blur'
71
+ }
72
+ ],
73
+ password: [
74
+ {
75
+ required: true,
76
+ message: '必须输入密码信息',
77
+ trigger: 'blur'
78
+ },
79
+ {
80
+ pattern: /^[a-zA-Z0-9]{3,}$/,
81
+ message: '必须3位以上数字和字母组成',
82
+ trigger: 'blur'
83
+ }
84
+ ]
85
+ }
86
+
87
+ function loginAction(isRememberPassword: boolean) {
88
+ formRef.value?.validate((valid) => {
89
+ if (valid) {
90
+ const name = account.name
91
+ const password = account.password
92
+
93
+ loginLoading.value = true
94
+ loginStore.loginAccountAction({
95
+ name,
96
+ password
97
+ })
98
+ .then((res) => {
99
+ // 记住密码
100
+ if (isRememberPassword) {
101
+ localCache.setCache(CHACHE_NAME, name)
102
+ localCache.setCache(CHACHE_PASSWORD, password)
103
+ }
104
+ else {
105
+ localCache.removeCache(CHACHE_NAME)
106
+ localCache.removeCache(CHACHE_PASSWORD)
107
+ }
108
+
109
+ console.log('-----res', res)
110
+
111
+ if (res === 'ok') {
112
+ // 判断登录的时候,路由路径当中是否有query参数,如果有就往query参数跳转,没有跳转到首页
113
+ const redirect: any = route.query.redirect
114
+ router.push({path: redirect || '/'})
115
+ }
116
+ })
117
+ .finally(() => {
118
+ loginLoading.value = false
119
+ })
120
+ }
121
+ else {
122
+ ElMessage.error('请您输入正确的格式后再操作')
123
+ }
124
+ })
125
+ }
126
+
127
+ defineExpose({
128
+ loginAction,
129
+ loginLoading
130
+ })
131
+ </script>
132
+
133
+ <style
134
+ scoped
135
+ lang="scss"
136
+ >
137
+ .panel-account {}
138
+ </style>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div class="panel-phone">
3
+ <el-form
4
+ label-width="60px"
5
+ size="large"
6
+ ref="formRef"
7
+ >
8
+ <el-form-item
9
+ label="手机号"
10
+ prop=""
11
+ >
12
+ <el-input />
13
+ </el-form-item>
14
+
15
+ <el-form-item
16
+ label="验证码"
17
+ prop="password"
18
+ >
19
+ <div class="verify-code">
20
+ <el-input
21
+ show-password
22
+ />
23
+ <el-button
24
+ class="get-btn"
25
+ type="primary"
26
+ >
27
+ 获取验证码
28
+ </el-button>
29
+ </div>
30
+ </el-form-item>
31
+ </el-form>
32
+ </div>
33
+ </template>
34
+
35
+ <script
36
+ setup
37
+ lang="ts"
38
+ name="PanelPhone"
39
+ >
40
+ </script>
41
+
42
+ <style
43
+ scoped
44
+ lang="scss"
45
+ >
46
+ .panel-phone {
47
+ .verify-code {
48
+ display: flex;
49
+ align-items: center;
50
+
51
+ .get-btn {
52
+ margin-left: 8px;
53
+ }
54
+ }
55
+ }
56
+ </style>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <div class="login-wraper">
3
+ <LoginPanel />
4
+ </div>
5
+ </template>
6
+
7
+ <script
8
+ setup
9
+ lang="ts"
10
+ name="Login"
11
+ >
12
+ import LoginPanel from './component/login-panel.vue'
13
+ </script>
14
+
15
+ <style
16
+ scoped
17
+ lang="scss"
18
+ >
19
+ .login-wraper {
20
+ width: 100%;
21
+ height: 100%;
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
+ background: url('../../assets/img/login-bg.jpg') center center no-repeat;
26
+ background-size: 100% 100%;
27
+ }
28
+ </style>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <div class="dashboard">
3
+ <h2>dashboard</h2>
4
+ </div>
5
+ </template>
6
+
7
+ <script
8
+ setup
9
+ lang="ts"
10
+ name="Dashboard"
11
+ >
12
+ </script>
13
+
14
+ <style
15
+ scoped
16
+ lang="scss"
17
+ >
18
+ .dashboard {}
19
+ </style>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <div class="overview">
3
+ <h2>overview</h2>
4
+
5
+ <div @click="handleJump">跳转详情</div>
6
+ </div>
7
+ </template>
8
+
9
+ <script
10
+ setup
11
+ lang="ts"
12
+ name="Overview"
13
+ >
14
+ import router from '@/router'
15
+ function handleJump() {
16
+ router.push('/detail')
17
+ }
18
+ </script>
19
+
20
+ <style
21
+ scoped
22
+ lang="scss"
23
+ >
24
+ .overview {}
25
+ </style>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <div class="detail">
3
+ <h2>detail</h2>
4
+ </div>
5
+ </template>
6
+
7
+ <script
8
+ setup
9
+ lang="ts"
10
+ name="Detail"
11
+ >
12
+ </script>
13
+
14
+ <style
15
+ scoped
16
+ lang="scss"
17
+ >
18
+ .detail {}
19
+ </style>