xto-fronted 0.2.5 → 0.2.7

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 (107) hide show
  1. package/.env.development +4 -0
  2. package/.env.production +4 -0
  3. package/README.md +94 -196
  4. package/dist/{components/Layout/TopMenu.vue.d.ts → App.vue.d.ts} +1 -1
  5. package/dist/api/auth.d.ts +8 -10
  6. package/dist/api/system.d.ts +11 -12
  7. package/dist/api/user.d.ts +12 -3
  8. package/dist/components/Layout/Footer.vue.d.ts +1 -1
  9. package/dist/components/Layout/Header.vue.d.ts +3 -14
  10. package/dist/components/Layout/Sidebar.vue.d.ts +1 -1
  11. package/dist/components/Layout/Tabs.vue.d.ts +1 -1
  12. package/dist/components/Layout/index.vue.d.ts +1 -1
  13. package/dist/composables/useAuth.d.ts +4 -19
  14. package/dist/directives/permission.d.ts +0 -1
  15. package/dist/index-CWRs4WMN.js +372 -0
  16. package/dist/index-CpxpXTQX.js +1462 -0
  17. package/dist/index-Cu3Z2-PY.js +345 -0
  18. package/dist/index-DPEVEyik.js +475 -0
  19. package/dist/index-DYnXaqYf.js +142 -0
  20. package/dist/index.d.ts +12 -25
  21. package/dist/index.es.js +76 -1521
  22. package/dist/index.umd.js +1 -20
  23. package/dist/main.d.ts +0 -1
  24. package/dist/router/dynamicRoutes.d.ts +33 -17
  25. package/dist/router/index.d.ts +4 -26
  26. package/dist/router/layoutRoute.d.ts +18 -0
  27. package/dist/router/staticRoutes.d.ts +2 -18
  28. package/dist/setup.d.ts +17 -0
  29. package/dist/stores/app.d.ts +15 -9
  30. package/dist/stores/auth.d.ts +48 -62
  31. package/dist/stores/index.d.ts +3 -1
  32. package/dist/stores/menu.d.ts +29 -47
  33. package/dist/stores/user.d.ts +84 -64
  34. package/dist/style.css +1 -1
  35. package/dist/utils/auth.d.ts +10 -10
  36. package/dist/utils/permission.d.ts +10 -1
  37. package/dist/utils/request.d.ts +7 -23
  38. package/dist/{components/Layout/Breadcrumb.vue.d.ts → views/dashboard/index.vue.d.ts} +1 -1
  39. package/dist/{components/Error → views/error}/403.vue.d.ts +1 -1
  40. package/dist/{components/Error → views/error}/404.vue.d.ts +1 -1
  41. package/dist/views/login/index.vue.d.ts +4 -0
  42. package/dist/views/system/menu/index.vue.d.ts +4 -0
  43. package/dist/views/system/role/index.vue.d.ts +4 -0
  44. package/dist/views/system/user/index.vue.d.ts +4 -0
  45. package/dist/vite.svg +9 -9
  46. package/index.html +13 -0
  47. package/package.json +27 -31
  48. package/public/vite.svg +10 -0
  49. package/src/App.vue +20 -0
  50. package/src/api/auth.ts +26 -0
  51. package/src/api/system.ts +65 -0
  52. package/src/api/user.ts +46 -0
  53. package/src/assets/styles/_dark.scss +407 -0
  54. package/src/assets/styles/_reset.scss +126 -0
  55. package/src/assets/styles/_root.scss +140 -0
  56. package/src/assets/styles/_transition.scss +119 -0
  57. package/src/assets/styles/_variables.scss +45 -0
  58. package/src/assets/styles/index.scss +187 -0
  59. package/src/components/Layout/Footer.vue +17 -0
  60. package/src/components/Layout/Header.vue +390 -0
  61. package/src/components/Layout/Sidebar.vue +297 -0
  62. package/src/components/Layout/Tabs.vue +134 -0
  63. package/src/components/Layout/index.vue +62 -0
  64. package/src/composables/useAuth.ts +45 -0
  65. package/src/composables/useForm.ts +79 -0
  66. package/src/composables/useTable.ts +97 -0
  67. package/src/directives/permission.ts +38 -0
  68. package/src/enums/index.ts +63 -0
  69. package/src/env.d.ts +17 -0
  70. package/src/index.ts +48 -0
  71. package/src/main.ts +34 -0
  72. package/src/router/dynamicRoutes.ts +163 -0
  73. package/src/router/index.ts +81 -0
  74. package/src/router/layoutRoute.ts +45 -0
  75. package/src/router/staticRoutes.ts +43 -0
  76. package/src/setup.ts +54 -0
  77. package/src/stores/app.ts +163 -0
  78. package/src/stores/auth.ts +66 -0
  79. package/src/stores/index.ts +15 -0
  80. package/src/stores/menu.ts +80 -0
  81. package/src/stores/user.ts +73 -0
  82. package/src/style.css +11 -0
  83. package/src/types/api.d.ts +84 -0
  84. package/src/types/global.d.ts +45 -0
  85. package/src/types/router.d.ts +48 -0
  86. package/src/types/xto.d.ts +149 -0
  87. package/src/utils/auth.ts +62 -0
  88. package/src/utils/permission.ts +42 -0
  89. package/src/utils/request.ts +124 -0
  90. package/src/utils/storage.ts +63 -0
  91. package/src/views/dashboard/index.vue +284 -0
  92. package/src/views/error/403.vue +57 -0
  93. package/src/views/error/404.vue +57 -0
  94. package/src/views/login/index.vue +248 -0
  95. package/src/views/system/menu/index.vue +381 -0
  96. package/src/views/system/role/index.vue +304 -0
  97. package/src/views/system/user/index.vue +327 -0
  98. package/tsconfig.json +26 -0
  99. package/tsconfig.node.json +11 -0
  100. package/vite.config.ts +140 -0
  101. package/dist/api/menu.d.ts +0 -4
  102. package/dist/components/Login/index.vue.d.ts +0 -25
  103. package/dist/components/SettingDrawer/index.vue.d.ts +0 -19
  104. package/dist/composables/index.d.ts +0 -8
  105. package/dist/composables/useApp.d.ts +0 -65
  106. package/dist/composables/useMenu.d.ts +0 -34
  107. package/dist/config/index.d.ts +0 -31
@@ -0,0 +1,284 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { Card, Tag, Progress } from '@xto/data'
4
+
5
+ const stats = ref([
6
+ { title: '用户总数', value: 1234, icon: '👥', color: '#409eff' },
7
+ { title: '今日访问', value: 567, icon: '👀', color: '#67c23a' },
8
+ { title: '订单数量', value: 890, icon: '📦', color: '#e6a23c' },
9
+ { title: '销售金额', value: 123456, icon: '💰', color: '#f56c6c' }
10
+ ])
11
+
12
+ const activities = ref([
13
+ { user: '张三', action: '登录系统', time: '2分钟前', type: 'success' },
14
+ { user: '李四', action: '修改了用户信息', time: '5分钟前', type: 'warning' },
15
+ { user: '王五', action: '创建了新订单', time: '10分钟前', type: 'info' },
16
+ { user: '赵六', action: '删除了测试数据', time: '30分钟前', type: 'danger' },
17
+ { user: '钱七', action: '更新了系统配置', time: '1小时前', type: 'primary' }
18
+ ])
19
+
20
+ const quickLinks = ref([
21
+ { title: '用户管理', path: '/system/user', icon: '👤' },
22
+ { title: '角色管理', path: '/system/role', icon: '👥' },
23
+ { title: '菜单管理', path: '/system/menu', icon: '📋' },
24
+ { title: '系统设置', path: '/system', icon: '⚙️' }
25
+ ])
26
+ </script>
27
+
28
+ <template>
29
+ <div class="dashboard">
30
+ <!-- 统计卡片 -->
31
+ <div class="dashboard__stats">
32
+ <Card v-for="stat in stats" :key="stat.title" class="stat-card">
33
+ <div class="stat-card__content">
34
+ <div class="stat-card__icon" :style="{ backgroundColor: stat.color + '20' }">
35
+ {{ stat.icon }}
36
+ </div>
37
+ <div class="stat-card__info">
38
+ <div class="stat-card__title">{{ stat.title }}</div>
39
+ <div class="stat-card__value" :style="{ color: stat.color }">
40
+ {{ stat.value.toLocaleString() }}
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </Card>
45
+ </div>
46
+
47
+ <!-- 主体内容 -->
48
+ <div class="dashboard__main">
49
+ <!-- 快捷入口 -->
50
+ <Card class="dashboard__quick">
51
+ <template #header>
52
+ <span class="card-title">快捷入口</span>
53
+ </template>
54
+ <div class="quick-links">
55
+ <router-link
56
+ v-for="link in quickLinks"
57
+ :key="link.path"
58
+ :to="link.path"
59
+ class="quick-link"
60
+ >
61
+ <span class="quick-link__icon">{{ link.icon }}</span>
62
+ <span class="quick-link__title">{{ link.title }}</span>
63
+ </router-link>
64
+ </div>
65
+ </Card>
66
+
67
+ <!-- 最近活动 -->
68
+ <Card class="dashboard__activity">
69
+ <template #header>
70
+ <span class="card-title">最近活动</span>
71
+ </template>
72
+ <div class="activity-list">
73
+ <div v-for="(activity, index) in activities" :key="index" class="activity-item">
74
+ <Tag :type="activity.type as any" size="small">{{ activity.user }}</Tag>
75
+ <span class="activity-item__action">{{ activity.action }}</span>
76
+ <span class="activity-item__time">{{ activity.time }}</span>
77
+ </div>
78
+ </div>
79
+ </Card>
80
+ </div>
81
+
82
+ <!-- 系统信息 -->
83
+ <Card class="dashboard__system">
84
+ <template #header>
85
+ <span class="card-title">系统信息</span>
86
+ </template>
87
+ <div class="system-info">
88
+ <div class="system-info__item">
89
+ <span class="system-info__label">系统版本</span>
90
+ <span class="system-info__value">v1.0.0</span>
91
+ </div>
92
+ <div class="system-info__item">
93
+ <span class="system-info__label">Vue 版本</span>
94
+ <span class="system-info__value">3.4.21</span>
95
+ </div>
96
+ <div class="system-info__item">
97
+ <span class="system-info__label">构建工具</span>
98
+ <span class="system-info__value">Vite 5</span>
99
+ </div>
100
+ <div class="system-info__item">
101
+ <span class="system-info__label">UI 组件库</span>
102
+ <span class="system-info__value">xto</span>
103
+ </div>
104
+ <div class="system-info__item">
105
+ <span class="system-info__label">服务器状态</span>
106
+ <Progress :percentage="75" status="success" />
107
+ </div>
108
+ <div class="system-info__item">
109
+ <span class="system-info__label">内存使用</span>
110
+ <Progress :percentage="45" />
111
+ </div>
112
+ </div>
113
+ </Card>
114
+ </div>
115
+ </template>
116
+
117
+ <style lang="scss" scoped>
118
+ .dashboard {
119
+ padding: 20px;
120
+
121
+ &__stats {
122
+ display: grid;
123
+ grid-template-columns: repeat(4, 1fr);
124
+ gap: 20px;
125
+ margin-bottom: 20px;
126
+
127
+ @media (max-width: 1200px) {
128
+ grid-template-columns: repeat(2, 1fr);
129
+ }
130
+
131
+ @media (max-width: 768px) {
132
+ grid-template-columns: 1fr;
133
+ }
134
+ }
135
+
136
+ &__main {
137
+ display: grid;
138
+ grid-template-columns: repeat(2, 1fr);
139
+ gap: 20px;
140
+ margin-bottom: 20px;
141
+
142
+ @media (max-width: 992px) {
143
+ grid-template-columns: 1fr;
144
+ }
145
+ }
146
+
147
+ &__quick,
148
+ &__activity {
149
+ min-height: 300px;
150
+ }
151
+ }
152
+
153
+ .card-title {
154
+ font-size: 16px;
155
+ font-weight: 500;
156
+ }
157
+
158
+ .stat-card {
159
+ &__content {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 15px;
163
+ }
164
+
165
+ &__icon {
166
+ width: 50px;
167
+ height: 50px;
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ font-size: 24px;
172
+ border-radius: var(--border-radius-base);
173
+ }
174
+
175
+ &__info {
176
+ flex: 1;
177
+ }
178
+
179
+ &__title {
180
+ font-size: 14px;
181
+ color: var(--color-text-secondary);
182
+ margin-bottom: 5px;
183
+ }
184
+
185
+ &__value {
186
+ font-size: 24px;
187
+ font-weight: 600;
188
+ }
189
+ }
190
+
191
+ .quick-links {
192
+ display: grid;
193
+ grid-template-columns: repeat(4, 1fr);
194
+ gap: 15px;
195
+
196
+ @media (max-width: 768px) {
197
+ grid-template-columns: repeat(2, 1fr);
198
+ }
199
+ }
200
+
201
+ .quick-link {
202
+ display: flex;
203
+ flex-direction: column;
204
+ align-items: center;
205
+ justify-content: center;
206
+ padding: 20px;
207
+ border-radius: var(--border-radius-base);
208
+ background-color: var(--color-fill);
209
+ text-decoration: none;
210
+ transition: all var(--transition-duration-fast);
211
+
212
+ &:hover {
213
+ background-color: var(--color-primary-light-9);
214
+ transform: translateY(-2px);
215
+ }
216
+
217
+ &__icon {
218
+ font-size: 28px;
219
+ margin-bottom: 10px;
220
+ }
221
+
222
+ &__title {
223
+ font-size: 14px;
224
+ color: var(--color-text-primary);
225
+ }
226
+ }
227
+
228
+ .activity-list {
229
+ display: flex;
230
+ flex-direction: column;
231
+ gap: 15px;
232
+ }
233
+
234
+ .activity-item {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 10px;
238
+ padding-bottom: 15px;
239
+ border-bottom: 1px solid var(--color-border-lighter);
240
+
241
+ &:last-child {
242
+ border-bottom: none;
243
+ padding-bottom: 0;
244
+ }
245
+
246
+ &__action {
247
+ flex: 1;
248
+ font-size: 14px;
249
+ color: var(--color-text-regular);
250
+ }
251
+
252
+ &__time {
253
+ font-size: 12px;
254
+ color: var(--color-text-placeholder);
255
+ }
256
+ }
257
+
258
+ .system-info {
259
+ display: grid;
260
+ grid-template-columns: repeat(2, 1fr);
261
+ gap: 20px;
262
+
263
+ @media (max-width: 768px) {
264
+ grid-template-columns: 1fr;
265
+ }
266
+
267
+ &__item {
268
+ display: flex;
269
+ align-items: center;
270
+ gap: 10px;
271
+ }
272
+
273
+ &__label {
274
+ font-size: 14px;
275
+ color: var(--color-text-secondary);
276
+ min-width: 80px;
277
+ }
278
+
279
+ &__value {
280
+ font-size: 14px;
281
+ color: var(--color-text-primary);
282
+ }
283
+ }
284
+ </style>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import { useRouter } from 'vue-router'
3
+ import { Button } from '@xto/base'
4
+
5
+ const router = useRouter()
6
+
7
+ const goBack = () => {
8
+ router.push('/')
9
+ }
10
+ </script>
11
+
12
+ <template>
13
+ <div class="error-page">
14
+ <div class="error-page__content">
15
+ <div class="error-page__code">403</div>
16
+ <div class="error-page__title">无访问权限</div>
17
+ <div class="error-page__desc">抱歉,您没有权限访问此页面</div>
18
+ <Button type="primary" @click="goBack">返回首页</Button>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <style lang="scss" scoped>
24
+ .error-page {
25
+ width: 100%;
26
+ height: 100vh;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ background-color: var(--bg-color-page);
31
+
32
+ &__content {
33
+ text-align: center;
34
+ }
35
+
36
+ &__code {
37
+ font-size: 120px;
38
+ font-weight: 600;
39
+ color: var(--color-warning);
40
+ line-height: 1;
41
+ margin-bottom: 20px;
42
+ }
43
+
44
+ &__title {
45
+ font-size: 24px;
46
+ font-weight: 500;
47
+ color: var(--color-text-primary);
48
+ margin-bottom: 10px;
49
+ }
50
+
51
+ &__desc {
52
+ font-size: 14px;
53
+ color: var(--color-text-secondary);
54
+ margin-bottom: 30px;
55
+ }
56
+ }
57
+ </style>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import { useRouter } from 'vue-router'
3
+ import { Button } from '@xto/base'
4
+
5
+ const router = useRouter()
6
+
7
+ const goBack = () => {
8
+ router.push('/')
9
+ }
10
+ </script>
11
+
12
+ <template>
13
+ <div class="error-page">
14
+ <div class="error-page__content">
15
+ <div class="error-page__code">404</div>
16
+ <div class="error-page__title">页面不存在</div>
17
+ <div class="error-page__desc">抱歉,您访问的页面不存在或已被删除</div>
18
+ <Button type="primary" @click="goBack">返回首页</Button>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <style lang="scss" scoped>
24
+ .error-page {
25
+ width: 100%;
26
+ height: 100vh;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ background-color: var(--bg-color-page);
31
+
32
+ &__content {
33
+ text-align: center;
34
+ }
35
+
36
+ &__code {
37
+ font-size: 120px;
38
+ font-weight: 600;
39
+ color: var(--color-primary);
40
+ line-height: 1;
41
+ margin-bottom: 20px;
42
+ }
43
+
44
+ &__title {
45
+ font-size: 24px;
46
+ font-weight: 500;
47
+ color: var(--color-text-primary);
48
+ margin-bottom: 10px;
49
+ }
50
+
51
+ &__desc {
52
+ font-size: 14px;
53
+ color: var(--color-text-secondary);
54
+ margin-bottom: 30px;
55
+ }
56
+ }
57
+ </style>
@@ -0,0 +1,248 @@
1
+ <script setup lang="ts">
2
+ import { ref, reactive } from 'vue'
3
+ import { useRouter } from 'vue-router'
4
+ import { Button } from '@xto/base'
5
+ import { Form, FormItem, Input, Checkbox } from '@xto/form'
6
+ import { Message } from '@xto/feedback'
7
+ import { useAuthStore } from '@/stores/auth'
8
+ import { useUserStore } from '@/stores/user'
9
+ import { useMenuStore } from '@/stores/menu'
10
+
11
+ const router = useRouter()
12
+ const authStore = useAuthStore()
13
+ const userStore = useUserStore()
14
+ const menuStore = useMenuStore()
15
+
16
+ const loading = ref(false)
17
+ const rememberMe = ref(false)
18
+
19
+ const formData = reactive({
20
+ username: 'admin',
21
+ password: '123456'
22
+ })
23
+
24
+ const rules: Record<string, any[]> = {
25
+ username: [
26
+ { required: true, message: '请输入用户名', trigger: 'blur' }
27
+ ],
28
+ password: [
29
+ { required: true, message: '请输入密码', trigger: 'blur' },
30
+ { min: 6, message: '密码长度至少6位', trigger: 'blur' }
31
+ ]
32
+ }
33
+
34
+ const formRef = ref()
35
+
36
+ // 登录
37
+ const handleLogin = async () => {
38
+ try {
39
+ await formRef.value?.validate()
40
+ loading.value = true
41
+
42
+ // Mock 登录
43
+ setTimeout(() => {
44
+ // 设置 token
45
+ authStore.login({
46
+ token: 'mock_token_' + Date.now(),
47
+ refreshToken: 'mock_refresh_token',
48
+ expireTime: Date.now() + 7 * 24 * 60 * 60 * 1000
49
+ })
50
+
51
+ // 设置用户信息
52
+ userStore.setUserInfo({
53
+ id: 1,
54
+ username: formData.username,
55
+ nickname: '管理员',
56
+ avatar: '',
57
+ email: 'admin@example.com',
58
+ phone: '13800138000',
59
+ status: 1,
60
+ roles: ['admin'],
61
+ permissions: ['*'],
62
+ createTime: new Date().toISOString()
63
+ })
64
+
65
+ // 设置菜单
66
+ menuStore.setMenuList([
67
+ {
68
+ id: 1,
69
+ name: 'Dashboard',
70
+ path: '/dashboard',
71
+ component: 'dashboard/index',
72
+ icon: 'dashboard',
73
+ title: '仪表盘',
74
+ keepAlive: true,
75
+ affix: true
76
+ },
77
+ {
78
+ id: 2,
79
+ name: 'System',
80
+ path: '/system',
81
+ redirect: '/system/user',
82
+ icon: 'setting',
83
+ title: '系统管理',
84
+ children: [
85
+ {
86
+ id: 21,
87
+ name: 'SystemUser',
88
+ path: '/system/user',
89
+ component: 'system/user/index',
90
+ icon: 'user',
91
+ title: '用户管理',
92
+ keepAlive: true
93
+ },
94
+ {
95
+ id: 22,
96
+ name: 'SystemRole',
97
+ path: '/system/role',
98
+ component: 'system/role/index',
99
+ icon: 'role',
100
+ title: '角色管理',
101
+ keepAlive: true
102
+ },
103
+ {
104
+ id: 23,
105
+ name: 'SystemMenu',
106
+ path: '/system/menu',
107
+ component: 'system/menu/index',
108
+ icon: 'menu',
109
+ title: '菜单管理',
110
+ keepAlive: true
111
+ }
112
+ ]
113
+ }
114
+ ])
115
+
116
+ Message.success('登录成功')
117
+ router.push('/')
118
+ loading.value = false
119
+ }, 1000)
120
+ } catch (error) {
121
+ loading.value = false
122
+ }
123
+ }
124
+ </script>
125
+
126
+ <template>
127
+ <div class="login">
128
+ <div class="login__container">
129
+ <div class="login__header">
130
+ <img src="/vite.svg" alt="Logo" class="login__logo" />
131
+ <h1 class="login__title">Xto Demo</h1>
132
+ <p class="login__subtitle">后台管理系统</p>
133
+ </div>
134
+
135
+ <Form
136
+ ref="formRef"
137
+ :model="formData"
138
+ :rules="rules"
139
+ class="login__form"
140
+ label-width="0"
141
+ >
142
+ <FormItem prop="username">
143
+ <Input
144
+ v-model="formData.username"
145
+ placeholder="用户名"
146
+ prefix-icon="👤"
147
+ size="large"
148
+ />
149
+ </FormItem>
150
+
151
+ <FormItem prop="password">
152
+ <Input
153
+ v-model="formData.password"
154
+ type="password"
155
+ placeholder="密码"
156
+ prefix-icon="🔒"
157
+ size="large"
158
+ show-password
159
+ @keyup.enter="handleLogin"
160
+ />
161
+ </FormItem>
162
+
163
+ <FormItem>
164
+ <Checkbox v-model="rememberMe">记住我</Checkbox>
165
+ </FormItem>
166
+
167
+ <FormItem>
168
+ <Button
169
+ type="primary"
170
+ size="large"
171
+ :loading="loading"
172
+ class="login__submit"
173
+ @click="handleLogin"
174
+ >
175
+ 登录
176
+ </Button>
177
+ </FormItem>
178
+ </Form>
179
+
180
+ <div class="login__footer">
181
+ <p>提示: 任意用户名密码即可登录 (Mock 模式)</p>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </template>
186
+
187
+ <style lang="scss" scoped>
188
+ .login {
189
+ width: 100%;
190
+ min-height: 100vh;
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: flex-end;
194
+ padding-right: 15%;
195
+ background: linear-gradient(135deg, var(--color-primary-light-9) 0%, var(--color-primary-light-7) 100%);
196
+
197
+ &__container {
198
+ width: 400px;
199
+ padding: 40px;
200
+ background-color: var(--bg-color);
201
+ border-radius: var(--border-radius-large);
202
+ box-shadow: var(--box-shadow-dark);
203
+ }
204
+
205
+ &__header {
206
+ text-align: center;
207
+ margin-bottom: 30px;
208
+ }
209
+
210
+ &__logo {
211
+ width: 60px;
212
+ height: 60px;
213
+ }
214
+
215
+ &__title {
216
+ font-size: 28px;
217
+ font-weight: 600;
218
+ color: var(--color-primary);
219
+ margin: 15px 0 5px;
220
+ }
221
+
222
+ &__subtitle {
223
+ font-size: 14px;
224
+ color: var(--color-text-secondary);
225
+ }
226
+
227
+ &__form {
228
+ :deep(.t-form-item) {
229
+ margin-bottom: 20px;
230
+ }
231
+
232
+ :deep(.x-input__prefix) {
233
+ margin-right: 8px;
234
+ }
235
+ }
236
+
237
+ &__submit {
238
+ width: 100%;
239
+ }
240
+
241
+ &__footer {
242
+ text-align: center;
243
+ margin-top: 20px;
244
+ font-size: 12px;
245
+ color: var(--color-text-placeholder);
246
+ }
247
+ }
248
+ </style>