xto-fronted 0.1.0 → 0.1.1

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 (54) hide show
  1. package/.env.development +4 -0
  2. package/.env.production +4 -0
  3. package/index.html +13 -0
  4. package/package.json +18 -10
  5. package/public/vite.svg +10 -0
  6. package/src/App.vue +20 -0
  7. package/src/api/auth.ts +26 -0
  8. package/src/api/system.ts +65 -0
  9. package/src/api/user.ts +46 -0
  10. package/src/assets/styles/_dark.scss +407 -0
  11. package/src/assets/styles/_reset.scss +126 -0
  12. package/src/assets/styles/_root.scss +140 -0
  13. package/src/assets/styles/_transition.scss +119 -0
  14. package/src/assets/styles/_variables.scss +45 -0
  15. package/src/assets/styles/index.scss +187 -0
  16. package/src/components/Layout/Footer.vue +17 -0
  17. package/src/components/Layout/Header.vue +390 -0
  18. package/src/components/Layout/Sidebar.vue +297 -0
  19. package/src/components/Layout/Tabs.vue +134 -0
  20. package/src/components/Layout/index.vue +62 -0
  21. package/src/composables/useAuth.ts +45 -0
  22. package/src/composables/useForm.ts +79 -0
  23. package/src/composables/useTable.ts +97 -0
  24. package/src/directives/permission.ts +38 -0
  25. package/src/enums/index.ts +63 -0
  26. package/src/env.d.ts +17 -0
  27. package/src/index.ts +39 -0
  28. package/src/main.ts +34 -0
  29. package/src/router/dynamicRoutes.ts +163 -0
  30. package/src/router/index.ts +81 -0
  31. package/src/router/staticRoutes.ts +43 -0
  32. package/src/stores/app.ts +145 -0
  33. package/src/stores/auth.ts +32 -0
  34. package/src/stores/index.ts +15 -0
  35. package/src/stores/menu.ts +80 -0
  36. package/src/stores/user.ts +73 -0
  37. package/src/types/api.d.ts +84 -0
  38. package/src/types/global.d.ts +45 -0
  39. package/src/types/router.d.ts +48 -0
  40. package/src/types/xto.d.ts +149 -0
  41. package/src/utils/auth.ts +62 -0
  42. package/src/utils/permission.ts +42 -0
  43. package/src/utils/request.ts +126 -0
  44. package/src/utils/storage.ts +63 -0
  45. package/src/views/dashboard/index.vue +284 -0
  46. package/src/views/error/403.vue +57 -0
  47. package/src/views/error/404.vue +57 -0
  48. package/src/views/login/index.vue +248 -0
  49. package/src/views/system/menu/index.vue +381 -0
  50. package/src/views/system/role/index.vue +304 -0
  51. package/src/views/system/user/index.vue +327 -0
  52. package/tsconfig.json +26 -0
  53. package/tsconfig.node.json +11 -0
  54. package/vite.config.ts +139 -0
@@ -0,0 +1,126 @@
1
+ // ==============================================
2
+ // CSS Reset - 样式重置
3
+ // ==============================================
4
+
5
+ *,
6
+ *::before,
7
+ *::after {
8
+ box-sizing: border-box;
9
+ margin: 0;
10
+ padding: 0;
11
+ }
12
+
13
+ html {
14
+ width: 100%;
15
+ height: 100%;
16
+ font-size: var(--font-size-base);
17
+ -webkit-text-size-adjust: 100%;
18
+ -webkit-tap-highlight-color: transparent;
19
+ text-rendering: optimizeLegibility;
20
+ -webkit-font-smoothing: antialiased;
21
+ -moz-osx-font-smoothing: grayscale;
22
+ }
23
+
24
+ body {
25
+ width: 100%;
26
+ height: 100%;
27
+ font-family: var(--font-family);
28
+ font-size: var(--font-size-base);
29
+ line-height: 1.5;
30
+ color: var(--color-text-primary);
31
+ background-color: var(--bg-color-page);
32
+ }
33
+
34
+ #app {
35
+ width: 100%;
36
+ height: 100%;
37
+ }
38
+
39
+ a {
40
+ color: var(--color-primary);
41
+ text-decoration: none;
42
+ cursor: pointer;
43
+ transition: color var(--transition-duration-fast);
44
+
45
+ &:hover {
46
+ color: var(--color-primary-light-3);
47
+ }
48
+ }
49
+
50
+ ul,
51
+ ol {
52
+ list-style: none;
53
+ }
54
+
55
+ img {
56
+ max-width: 100%;
57
+ height: auto;
58
+ vertical-align: middle;
59
+ }
60
+
61
+ button {
62
+ cursor: pointer;
63
+ font-family: inherit;
64
+ font-size: inherit;
65
+ border: none;
66
+ background: none;
67
+ outline: none;
68
+
69
+ &:disabled {
70
+ cursor: not-allowed;
71
+ }
72
+ }
73
+
74
+ input,
75
+ textarea,
76
+ select {
77
+ font-family: inherit;
78
+ font-size: inherit;
79
+ outline: none;
80
+ }
81
+
82
+ table {
83
+ border-collapse: collapse;
84
+ border-spacing: 0;
85
+ }
86
+
87
+ h1,
88
+ h2,
89
+ h3,
90
+ h4,
91
+ h5,
92
+ h6 {
93
+ margin: 0;
94
+ font-weight: 500;
95
+ color: var(--color-text-primary);
96
+ }
97
+
98
+ p {
99
+ margin: 0;
100
+ }
101
+
102
+ // 滚动条样式
103
+ ::-webkit-scrollbar {
104
+ width: 6px;
105
+ height: 6px;
106
+ }
107
+
108
+ ::-webkit-scrollbar-track {
109
+ background-color: var(--color-fill-light);
110
+ border-radius: 3px;
111
+ }
112
+
113
+ ::-webkit-scrollbar-thumb {
114
+ background-color: var(--color-border);
115
+ border-radius: 3px;
116
+
117
+ &:hover {
118
+ background-color: var(--color-text-secondary);
119
+ }
120
+ }
121
+
122
+ // 选中文本样式
123
+ ::selection {
124
+ background-color: var(--color-primary-light-8);
125
+ color: var(--color-primary);
126
+ }
@@ -0,0 +1,140 @@
1
+ // ==============================================
2
+ // CSS Variables - 主题变量
3
+ // ==============================================
4
+
5
+ :root {
6
+ // 主题色
7
+ --color-primary: #409eff;
8
+ --color-primary-light-3: #79bbff;
9
+ --color-primary-light-5: #a0cfff;
10
+ --color-primary-light-7: #c6e2ff;
11
+ --color-primary-light-8: #d9ecff;
12
+ --color-primary-light-9: #ecf5ff;
13
+ --color-primary-dark-2: #337ecc;
14
+
15
+ // 功能色
16
+ --color-success: #67c23a;
17
+ --color-success-light: #e1f3d8;
18
+ --color-success-dark: #529b2e;
19
+
20
+ --color-warning: #e6a23c;
21
+ --color-warning-light: #fdf6ec;
22
+ --color-warning-dark: #b88230;
23
+
24
+ --color-danger: #f56c6c;
25
+ --color-danger-light: #fde2e2;
26
+ --color-danger-dark: #c45656;
27
+
28
+ --color-info: #909399;
29
+ --color-info-light: #f4f4f5;
30
+ --color-info-dark: #73767a;
31
+
32
+ // 文字颜色
33
+ --color-text-primary: #303133;
34
+ --color-text-regular: #606266;
35
+ --color-text-secondary: #909399;
36
+ --color-text-placeholder: #a8abb2;
37
+ --color-text-disabled: #c0c4cc;
38
+
39
+ // 边框颜色
40
+ --color-border: #dcdfe6;
41
+ --color-border-light: #e4e7ed;
42
+ --color-border-lighter: #ebeef5;
43
+ --color-border-extra-light: #f2f6fc;
44
+ --color-border-dark: #d4d7de;
45
+
46
+ // 填充颜色
47
+ --color-fill: #f5f7fa;
48
+ --color-fill-light: #fafafa;
49
+ --color-fill-lighter: #fafcff;
50
+ --color-fill-blank: #ffffff;
51
+
52
+ // 背景颜色
53
+ --bg-color: #ffffff;
54
+ --bg-color-page: #f2f3f5;
55
+ --bg-color-overlay: #ffffff;
56
+
57
+ // 盒子阴影
58
+ --box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
59
+ --box-shadow-light: 0 2px 8px 0 rgba(0, 0, 0, 0.06);
60
+ --box-shadow-lighter: 0 1px 4px 0 rgba(0, 0, 0, 0.04);
61
+ --box-shadow-dark: 0 4px 16px 0 rgba(0, 0, 0, 0.12);
62
+
63
+ // 字体
64
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
65
+ 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
66
+ 'Noto Color Emoji';
67
+ --font-size-base: 14px;
68
+ --font-size-small: 12px;
69
+ --font-size-large: 16px;
70
+ --font-size-extra-large: 18px;
71
+
72
+ // 圆角
73
+ --border-radius-base: 4px;
74
+ --border-radius-small: 2px;
75
+ --border-radius-large: 8px;
76
+ --border-radius-round: 20px;
77
+ --border-radius-circle: 50%;
78
+
79
+ // 间距
80
+ --spacing-xs: 4px;
81
+ --spacing-sm: 8px;
82
+ --spacing-md: 16px;
83
+ --spacing-lg: 24px;
84
+ --spacing-xl: 32px;
85
+
86
+ // 尺寸
87
+ --component-size-large: 40px;
88
+ --component-size-default: 32px;
89
+ --component-size-small: 24px;
90
+
91
+ // 过渡时间
92
+ --transition-duration: 0.3s;
93
+ --transition-duration-fast: 0.2s;
94
+ --transition-duration-slow: 0.5s;
95
+
96
+ // z-index
97
+ --z-index-dropdown: 1000;
98
+ --z-index-sticky: 1020;
99
+ --z-index-fixed: 1030;
100
+ --z-index-modal-backdrop: 1040;
101
+ --z-index-modal: 1050;
102
+ --z-index-popover: 1060;
103
+ --z-index-tooltip: 1070;
104
+
105
+ // 布局
106
+ --sidebar-width: 210px;
107
+ --sidebar-collapsed-width: 64px;
108
+ --header-height: 50px;
109
+ --tabs-height: 40px;
110
+ --footer-height: 30px;
111
+ }
112
+
113
+ // 暗色主题
114
+ .dark {
115
+ --color-text-primary: #e5eaf3;
116
+ --color-text-regular: #cfd3dc;
117
+ --color-text-secondary: #a3a6ad;
118
+ --color-text-placeholder: #8d9095;
119
+ --color-text-disabled: #6c6e72;
120
+
121
+ --color-border: #4c4d4f;
122
+ --color-border-light: #414243;
123
+ --color-border-lighter: #363637;
124
+ --color-border-extra-light: #2b2b2c;
125
+ --color-border-dark: #58585b;
126
+
127
+ --color-fill: #303030;
128
+ --color-fill-light: #262727;
129
+ --color-fill-lighter: #1d1d1d;
130
+ --color-fill-blank: #141414;
131
+
132
+ --bg-color: #1d1e1f;
133
+ --bg-color-page: #0a0a0a;
134
+ --bg-color-overlay: #1d1e1f;
135
+
136
+ --box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
137
+ --box-shadow-light: 0 2px 8px 0 rgba(0, 0, 0, 0.24);
138
+ --box-shadow-lighter: 0 1px 4px 0 rgba(0, 0, 0, 0.2);
139
+ --box-shadow-dark: 0 4px 16px 0 rgba(0, 0, 0, 0.36);
140
+ }
@@ -0,0 +1,119 @@
1
+ // ==============================================
2
+ // Transitions - 过渡动画
3
+ // ==============================================
4
+
5
+ // 淡入淡出
6
+ .fade-enter-active,
7
+ .fade-leave-active {
8
+ transition: opacity var(--transition-duration);
9
+ }
10
+
11
+ .fade-enter-from,
12
+ .fade-leave-to {
13
+ opacity: 0;
14
+ }
15
+
16
+ // 淡入淡出 + 缩放
17
+ .fade-scale-enter-active,
18
+ .fade-scale-leave-active {
19
+ transition: all var(--transition-duration);
20
+ }
21
+
22
+ .fade-scale-enter-from,
23
+ .fade-scale-leave-to {
24
+ opacity: 0;
25
+ transform: scale(0.9);
26
+ }
27
+
28
+ // 淡入淡出 + 滑动
29
+ .fade-transform-enter-active,
30
+ .fade-transform-leave-active {
31
+ transition: all var(--transition-duration-fast);
32
+ }
33
+
34
+ .fade-transform-enter-from {
35
+ opacity: 0;
36
+ transform: translateX(-10px);
37
+ }
38
+
39
+ .fade-transform-leave-to {
40
+ opacity: 0;
41
+ transform: translateX(10px);
42
+ }
43
+
44
+ // 向下滑入
45
+ .slide-down-enter-active,
46
+ .slide-down-leave-active {
47
+ transition: all var(--transition-duration);
48
+ }
49
+
50
+ .slide-down-enter-from,
51
+ .slide-down-leave-to {
52
+ opacity: 0;
53
+ transform: translateY(-20px);
54
+ }
55
+
56
+ // 向上滑入
57
+ .slide-up-enter-active,
58
+ .slide-up-leave-active {
59
+ transition: all var(--transition-duration);
60
+ }
61
+
62
+ .slide-up-enter-from,
63
+ .slide-up-leave-to {
64
+ opacity: 0;
65
+ transform: translateY(20px);
66
+ }
67
+
68
+ // 向左滑入
69
+ .slide-left-enter-active,
70
+ .slide-left-leave-active {
71
+ transition: all var(--transition-duration);
72
+ }
73
+
74
+ .slide-left-enter-from,
75
+ .slide-left-leave-to {
76
+ opacity: 0;
77
+ transform: translateX(20px);
78
+ }
79
+
80
+ // 向右滑入
81
+ .slide-right-enter-active,
82
+ .slide-right-leave-active {
83
+ transition: all var(--transition-duration);
84
+ }
85
+
86
+ .slide-right-enter-from,
87
+ .slide-right-leave-to {
88
+ opacity: 0;
89
+ transform: translateX(-20px);
90
+ }
91
+
92
+ // 缩放
93
+ .zoom-enter-active,
94
+ .zoom-leave-active {
95
+ transition: all var(--transition-duration);
96
+ }
97
+
98
+ .zoom-enter-from,
99
+ .zoom-leave-to {
100
+ opacity: 0;
101
+ transform: scale(0.5);
102
+ }
103
+
104
+ // 列表动画
105
+ .list-enter-active,
106
+ .list-leave-active {
107
+ transition: all var(--transition-duration);
108
+ }
109
+
110
+ .list-enter-from,
111
+ .list-leave-to {
112
+ opacity: 0;
113
+ transform: translateY(30px);
114
+ }
115
+
116
+ // 侧边栏折叠动画
117
+ .collapse-transition {
118
+ transition: width var(--transition-duration), padding var(--transition-duration);
119
+ }
@@ -0,0 +1,45 @@
1
+ // ==============================================
2
+ // SCSS Variables - 用于样式计算
3
+ // ==============================================
4
+
5
+ // 主题色
6
+ $color-primary: #409eff;
7
+ $color-success: #67c23a;
8
+ $color-warning: #e6a23c;
9
+ $color-danger: #f56c6c;
10
+ $color-info: #909399;
11
+
12
+ // 文字颜色
13
+ $color-text-primary: #303133;
14
+ $color-text-regular: #606266;
15
+ $color-text-secondary: #909399;
16
+
17
+ // 边框颜色
18
+ $color-border: #dcdfe6;
19
+ $color-border-light: #e4e7ed;
20
+ $color-border-lighter: #ebeef5;
21
+
22
+ // 背景颜色
23
+ $bg-color: #ffffff;
24
+ $bg-color-page: #f2f3f5;
25
+
26
+ // 字体
27
+ $font-size-base: 14px;
28
+ $font-size-small: 12px;
29
+
30
+ // 圆角
31
+ $border-radius-base: 4px;
32
+ $border-radius-large: 8px;
33
+
34
+ // 间距
35
+ $spacing-xs: 4px;
36
+ $spacing-sm: 8px;
37
+ $spacing-md: 16px;
38
+ $spacing-lg: 24px;
39
+
40
+ // 布局
41
+ $sidebar-width: 210px;
42
+ $sidebar-collapsed-width: 64px;
43
+ $header-height: 50px;
44
+ $tabs-height: 40px;
45
+ $footer-height: 30px;
@@ -0,0 +1,187 @@
1
+ // ==============================================
2
+ // 全局样式入口
3
+ // ==============================================
4
+
5
+ // CSS 变量(根选择器)
6
+ @use 'root';
7
+
8
+ // Reset
9
+ @use 'reset';
10
+
11
+ // Transitions
12
+ @use 'transition';
13
+
14
+ // Dark Theme Override
15
+ @use 'dark';
16
+
17
+ // ==============================================
18
+ // 全局通用样式
19
+ // ==============================================
20
+
21
+ // 文字截断
22
+ .text-ellipsis {
23
+ overflow: hidden;
24
+ text-overflow: ellipsis;
25
+ white-space: nowrap;
26
+ }
27
+
28
+ // 多行截断
29
+ .text-ellipsis-2 {
30
+ display: -webkit-box;
31
+ -webkit-line-clamp: 2;
32
+ -webkit-box-orient: vertical;
33
+ overflow: hidden;
34
+ }
35
+
36
+ // Flex 布局
37
+ .flex {
38
+ display: flex;
39
+ }
40
+
41
+ .flex-center {
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ }
46
+
47
+ .flex-between {
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: space-between;
51
+ }
52
+
53
+ .flex-wrap {
54
+ flex-wrap: wrap;
55
+ }
56
+
57
+ .flex-1 {
58
+ flex: 1;
59
+ }
60
+
61
+ // 文字对齐
62
+ .text-left {
63
+ text-align: left;
64
+ }
65
+
66
+ .text-center {
67
+ text-align: center;
68
+ }
69
+
70
+ .text-right {
71
+ text-align: right;
72
+ }
73
+
74
+ // 颜色
75
+ .text-primary {
76
+ color: var(--color-primary);
77
+ }
78
+
79
+ .text-success {
80
+ color: var(--color-success);
81
+ }
82
+
83
+ .text-warning {
84
+ color: var(--color-warning);
85
+ }
86
+
87
+ .text-danger {
88
+ color: var(--color-danger);
89
+ }
90
+
91
+ .text-info {
92
+ color: var(--color-info);
93
+ }
94
+
95
+ // 背景
96
+ .bg-primary {
97
+ background-color: var(--color-primary);
98
+ }
99
+
100
+ .bg-success {
101
+ background-color: var(--color-success);
102
+ }
103
+
104
+ .bg-warning {
105
+ background-color: var(--color-warning);
106
+ }
107
+
108
+ .bg-danger {
109
+ background-color: var(--color-danger);
110
+ }
111
+
112
+ // 间距
113
+ .mt-10 {
114
+ margin-top: 10px;
115
+ }
116
+
117
+ .mt-20 {
118
+ margin-top: 20px;
119
+ }
120
+
121
+ .mb-10 {
122
+ margin-bottom: 10px;
123
+ }
124
+
125
+ .mb-20 {
126
+ margin-bottom: 20px;
127
+ }
128
+
129
+ .ml-10 {
130
+ margin-left: 10px;
131
+ }
132
+
133
+ .mr-10 {
134
+ margin-right: 10px;
135
+ }
136
+
137
+ .p-10 {
138
+ padding: 10px;
139
+ }
140
+
141
+ .p-20 {
142
+ padding: 20px;
143
+ }
144
+
145
+ // 卡片容器
146
+ .card {
147
+ background-color: var(--bg-color);
148
+ border-radius: var(--border-radius-base);
149
+ box-shadow: var(--box-shadow-light);
150
+ padding: var(--spacing-md);
151
+ }
152
+
153
+ // 页面容器
154
+ .page-container {
155
+ padding: var(--spacing-md);
156
+ min-height: 100%;
157
+ }
158
+
159
+ // 搜索栏
160
+ .search-bar {
161
+ display: flex;
162
+ flex-wrap: wrap;
163
+ gap: var(--spacing-sm);
164
+ margin-bottom: var(--spacing-md);
165
+ }
166
+
167
+ // 工具栏
168
+ .toolbar {
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: space-between;
172
+ margin-bottom: var(--spacing-md);
173
+ }
174
+
175
+ // 表格容器
176
+ .table-container {
177
+ background-color: var(--bg-color);
178
+ border-radius: var(--border-radius-base);
179
+ padding: var(--spacing-md);
180
+ }
181
+
182
+ // 分页容器
183
+ .pagination-container {
184
+ display: flex;
185
+ justify-content: flex-end;
186
+ margin-top: var(--spacing-md);
187
+ }
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="footer">
6
+ <span>Copyright © 2024 Xto Demo. All Rights Reserved.</span>
7
+ </div>
8
+ </template>
9
+
10
+ <style lang="scss" scoped>
11
+ .footer {
12
+ width: 100%;
13
+ text-align: center;
14
+ font-size: 12px;
15
+ color: var(--color-text-secondary);
16
+ }
17
+ </style>