xto-fronted 0.1.2 → 0.1.4

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 (60) hide show
  1. package/.env.development +3 -0
  2. package/.env.production +3 -0
  3. package/bin/cli.js +103 -0
  4. package/index.html +13 -0
  5. package/package.json +16 -3
  6. package/public/vite.svg +10 -0
  7. package/src/App.vue +20 -0
  8. package/src/api/auth.ts +35 -0
  9. package/src/api/menu.ts +13 -0
  10. package/src/api/system.ts +65 -0
  11. package/src/api/user.ts +12 -0
  12. package/src/assets/styles/_dark.scss +407 -0
  13. package/src/assets/styles/_reset.scss +126 -0
  14. package/src/assets/styles/_root.scss +140 -0
  15. package/src/assets/styles/_transition.scss +119 -0
  16. package/src/assets/styles/_variables.scss +45 -0
  17. package/src/assets/styles/index.scss +187 -0
  18. package/src/components/Layout/Footer.vue +17 -0
  19. package/src/components/Layout/Header.vue +335 -0
  20. package/src/components/Layout/Sidebar.vue +213 -0
  21. package/src/components/Layout/Tabs.vue +20 -0
  22. package/src/components/Layout/index.vue +62 -0
  23. package/src/composables/index.ts +9 -0
  24. package/src/composables/useApp.ts +170 -0
  25. package/src/composables/useAuth.ts +70 -0
  26. package/src/composables/useForm.ts +79 -0
  27. package/src/composables/useMenu.ts +141 -0
  28. package/src/composables/useTable.ts +97 -0
  29. package/src/config/index.ts +19 -0
  30. package/src/directives/permission.ts +41 -0
  31. package/src/enums/index.ts +63 -0
  32. package/src/env.d.ts +17 -0
  33. package/src/index.ts +44 -0
  34. package/src/main.ts +34 -0
  35. package/src/router/dynamicRoutes.ts +163 -0
  36. package/src/router/index.ts +71 -0
  37. package/src/router/staticRoutes.ts +43 -0
  38. package/src/stores/app.ts +145 -0
  39. package/src/stores/auth.ts +45 -0
  40. package/src/stores/index.ts +15 -0
  41. package/src/stores/menu.ts +158 -0
  42. package/src/stores/user.ts +41 -0
  43. package/src/types/api.d.ts +103 -0
  44. package/src/types/global.d.ts +45 -0
  45. package/src/types/router.d.ts +48 -0
  46. package/src/types/xto.d.ts +149 -0
  47. package/src/utils/auth.ts +86 -0
  48. package/src/utils/permission.ts +30 -0
  49. package/src/utils/request.ts +126 -0
  50. package/src/utils/storage.ts +72 -0
  51. package/src/views/dashboard/index.vue +32 -0
  52. package/src/views/error/403.vue +57 -0
  53. package/src/views/error/404.vue +57 -0
  54. package/src/views/login/index.vue +141 -0
  55. package/src/views/system/menu/index.vue +32 -0
  56. package/src/views/system/role/index.vue +32 -0
  57. package/src/views/system/user/index.vue +32 -0
  58. package/tsconfig.json +26 -0
  59. package/tsconfig.node.json +11 -0
  60. package/vite.config.ts +139 -0
@@ -0,0 +1,141 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 登录页面
4
+ * 使用统一的 useApp hooks
5
+ */
6
+ import { ref, reactive } from 'vue'
7
+ import { Button } from '@xto/base'
8
+ import { Form, FormItem, Input } from '@xto/form'
9
+ import { useApp } from '@/composables'
10
+
11
+ const { login, loading } = useApp()
12
+
13
+ const formData = reactive({
14
+ uid: '',
15
+ password: ''
16
+ })
17
+
18
+ const rules: Record<string, any[]> = {
19
+ uid: [
20
+ { required: true, message: '请输入账号', trigger: 'blur' }
21
+ ],
22
+ password: [
23
+ { required: true, message: '请输入密码', trigger: 'blur' }
24
+ ]
25
+ }
26
+
27
+ const formRef = ref()
28
+
29
+ // 登录
30
+ const handleLogin = async () => {
31
+ try {
32
+ await formRef.value?.validate()
33
+ await login(formData.uid, formData.password)
34
+ } catch (error) {
35
+ console.error('登录失败', error)
36
+ }
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <div class="login">
42
+ <div class="login__container">
43
+ <div class="login__header">
44
+ <img src="/vite.svg" alt="Logo" class="login__logo" />
45
+ <h1 class="login__title">Analysis Web</h1>
46
+ <p class="login__subtitle">后台管理系统</p>
47
+ </div>
48
+
49
+ <Form
50
+ ref="formRef"
51
+ :model="formData"
52
+ :rules="rules"
53
+ class="login__form"
54
+ label-width="0"
55
+ >
56
+ <FormItem prop="uid">
57
+ <Input
58
+ v-model="formData.uid"
59
+ placeholder="请输入账号"
60
+ size="large"
61
+ />
62
+ </FormItem>
63
+
64
+ <FormItem prop="password">
65
+ <Input
66
+ v-model="formData.password"
67
+ type="password"
68
+ placeholder="请输入密码"
69
+ size="large"
70
+ show-password
71
+ @keyup.enter="handleLogin"
72
+ />
73
+ </FormItem>
74
+
75
+ <FormItem>
76
+ <Button
77
+ type="primary"
78
+ size="large"
79
+ :loading="loading"
80
+ class="login__submit"
81
+ @click="handleLogin"
82
+ >
83
+ 登录
84
+ </Button>
85
+ </FormItem>
86
+ </Form>
87
+ </div>
88
+ </div>
89
+ </template>
90
+
91
+ <style lang="scss" scoped>
92
+ .login {
93
+ width: 100%;
94
+ min-height: 100vh;
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: flex-end;
98
+ padding-right: 15%;
99
+ background: linear-gradient(135deg, var(--color-primary-light-9) 0%, var(--color-primary-light-7) 100%);
100
+
101
+ &__container {
102
+ width: 400px;
103
+ padding: 40px;
104
+ background-color: var(--bg-color);
105
+ border-radius: var(--border-radius-large);
106
+ box-shadow: var(--box-shadow-dark);
107
+ }
108
+
109
+ &__header {
110
+ text-align: center;
111
+ margin-bottom: 30px;
112
+ }
113
+
114
+ &__logo {
115
+ width: 60px;
116
+ height: 60px;
117
+ }
118
+
119
+ &__title {
120
+ font-size: 28px;
121
+ font-weight: 600;
122
+ color: var(--color-primary);
123
+ margin: 15px 0 5px;
124
+ }
125
+
126
+ &__subtitle {
127
+ font-size: 14px;
128
+ color: var(--color-text-secondary);
129
+ }
130
+
131
+ &__form {
132
+ :deep(.t-form-item) {
133
+ margin-bottom: 20px;
134
+ }
135
+ }
136
+
137
+ &__submit {
138
+ width: 100%;
139
+ }
140
+ }
141
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="page">
6
+ <div class="page__placeholder">
7
+ <h2>菜单管理</h2>
8
+ <p>功能开发中...</p>
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <style lang="scss" scoped>
14
+ .page {
15
+ padding: 20px;
16
+ height: 100%;
17
+
18
+ &__placeholder {
19
+ display: flex;
20
+ flex-direction: column;
21
+ align-items: center;
22
+ justify-content: center;
23
+ height: 100%;
24
+ color: var(--color-text-secondary);
25
+
26
+ h2 {
27
+ margin-bottom: 10px;
28
+ color: var(--color-text-primary);
29
+ }
30
+ }
31
+ }
32
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="page">
6
+ <div class="page__placeholder">
7
+ <h2>角色管理</h2>
8
+ <p>功能开发中...</p>
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <style lang="scss" scoped>
14
+ .page {
15
+ padding: 20px;
16
+ height: 100%;
17
+
18
+ &__placeholder {
19
+ display: flex;
20
+ flex-direction: column;
21
+ align-items: center;
22
+ justify-content: center;
23
+ height: 100%;
24
+ color: var(--color-text-secondary);
25
+
26
+ h2 {
27
+ margin-bottom: 10px;
28
+ color: var(--color-text-primary);
29
+ }
30
+ }
31
+ }
32
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="page">
6
+ <div class="page__placeholder">
7
+ <h2>用户管理</h2>
8
+ <p>功能开发中...</p>
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <style lang="scss" scoped>
14
+ .page {
15
+ padding: 20px;
16
+ height: 100%;
17
+
18
+ &__placeholder {
19
+ display: flex;
20
+ flex-direction: column;
21
+ align-items: center;
22
+ justify-content: center;
23
+ height: 100%;
24
+ color: var(--color-text-secondary);
25
+
26
+ h2 {
27
+ margin-bottom: 10px;
28
+ color: var(--color-text-primary);
29
+ }
30
+ }
31
+ }
32
+ </style>
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true,
13
+ "jsx": "preserve",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "baseUrl": ".",
19
+ "paths": {
20
+ "@/*": ["src/*"]
21
+ },
22
+ "types": ["vite/client", "node"]
23
+ },
24
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
25
+ "references": [{ "path": "./tsconfig.node.json" }]
26
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,139 @@
1
+ import { defineConfig, loadEnv } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+ import dts from 'vite-plugin-dts'
4
+ import { resolve } from 'path'
5
+
6
+ export default defineConfig(({ mode }) => {
7
+ const env = loadEnv(mode, process.cwd())
8
+ const isLib = mode === 'lib'
9
+
10
+ return {
11
+ plugins: [
12
+ vue(),
13
+ ...(isLib ? [dts({ insertTypesEntry: true, outDir: 'dist' })] : [])
14
+ ],
15
+ resolve: {
16
+ alias: {
17
+ '@': resolve(__dirname, 'src'),
18
+ '@xto/core': resolve(__dirname, 'node_modules/@xto/core/es/index/index.mjs'),
19
+ '@xto/core/theme': resolve(__dirname, 'node_modules/@xto/core/es/theme/index.mjs'),
20
+ '@xto/core/hooks': resolve(__dirname, 'node_modules/@xto/core/es/hooks/index.mjs'),
21
+ '@xto/core/utils': resolve(__dirname, 'node_modules/@xto/core/es/utils/index.mjs'),
22
+ '@xto/base/es/style.css': resolve(__dirname, 'node_modules/@xto/base/es/style.css'),
23
+ '@xto/form/es/style.css': resolve(__dirname, 'node_modules/@xto/form/es/style.css'),
24
+ '@xto/data/es/style.css': resolve(__dirname, 'node_modules/@xto/data/es/style.css'),
25
+ '@xto/feedback/es/style.css': resolve(__dirname, 'node_modules/@xto/feedback/es/style.css'),
26
+ '@xto/navigation/es/style.css': resolve(__dirname, 'node_modules/@xto/navigation/es/style.css'),
27
+ '@xto/layout/es/style.css': resolve(__dirname, 'node_modules/@xto/layout/es/style.css'),
28
+ '@xto/business/es/style.css': resolve(__dirname, 'node_modules/@xto/business/es/style.css'),
29
+ }
30
+ },
31
+ // 开发模式优化
32
+ optimizeDeps: {
33
+ include: [
34
+ 'vue',
35
+ 'vue-router',
36
+ 'pinia',
37
+ 'axios'
38
+ ],
39
+ exclude: [
40
+ '@xto/core',
41
+ '@xto/base',
42
+ '@xto/form',
43
+ '@xto/data',
44
+ '@xto/feedback',
45
+ '@xto/navigation',
46
+ '@xto/layout',
47
+ '@xto/business'
48
+ ]
49
+ },
50
+ server: {
51
+ host: '0.0.0.0',
52
+ port: 3000,
53
+ open: true,
54
+ proxy: {
55
+ '/user': {
56
+ target: 'https://cloud-api-test.tineco.com',
57
+ changeOrigin: true,
58
+ secure: false
59
+ }
60
+ }
61
+ },
62
+ build: {
63
+ outDir: 'dist',
64
+ sourcemap: false,
65
+ chunkSizeWarningLimit: 1500,
66
+ // 库模式配置
67
+ lib: isLib ? {
68
+ entry: resolve(__dirname, 'src/index.ts'),
69
+ name: 'XtoFronted',
70
+ fileName: (format: string) => `index.${format === 'es' ? 'es.js' : 'umd.js'}`
71
+ } : undefined,
72
+ rollupOptions: {
73
+ // 库模式下排除外部依赖
74
+ external: isLib ? [
75
+ 'vue',
76
+ 'vue-router',
77
+ 'pinia',
78
+ 'axios',
79
+ /^@xto\//
80
+ ] : undefined,
81
+ output: isLib ? {
82
+ globals: {
83
+ vue: 'Vue',
84
+ 'vue-router': 'VueRouter',
85
+ pinia: 'Pinia',
86
+ axios: 'axios'
87
+ },
88
+ exports: 'named'
89
+ } : {
90
+ manualChunks(id) {
91
+ // Vue 全家桶单独打包
92
+ if (id.includes('node_modules/vue/') ||
93
+ id.includes('node_modules/@vue/') ||
94
+ id.includes('node_modules/vue-router/') ||
95
+ id.includes('node_modules/pinia/')) {
96
+ return 'vue-vendor'
97
+ }
98
+ // 组件库按包分割,实现按需加载
99
+ if (id.includes('@xto/core')) {
100
+ return 'xto-core'
101
+ }
102
+ if (id.includes('@xto/base')) {
103
+ return 'xto-base'
104
+ }
105
+ if (id.includes('@xto/form')) {
106
+ return 'xto-form'
107
+ }
108
+ if (id.includes('@xto/data')) {
109
+ return 'xto-data'
110
+ }
111
+ if (id.includes('@xto/feedback')) {
112
+ return 'xto-feedback'
113
+ }
114
+ if (id.includes('@xto/navigation')) {
115
+ return 'xto-navigation'
116
+ }
117
+ if (id.includes('@xto/layout')) {
118
+ return 'xto-layout'
119
+ }
120
+ if (id.includes('@xto/business')) {
121
+ return 'xto-business'
122
+ }
123
+ // 其他第三方库
124
+ if (id.includes('node_modules/')) {
125
+ return 'vendor'
126
+ }
127
+ }
128
+ }
129
+ }
130
+ },
131
+ css: {
132
+ preprocessorOptions: {
133
+ scss: {
134
+ api: 'modern-compiler'
135
+ }
136
+ }
137
+ }
138
+ }
139
+ })