@cghbcf/xp-ui 1.0.0 → 1.1.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.
- package/README.md +1162 -0
- package/dist/cghbcf-xp-ui.cjs.js +5 -0
- package/dist/cghbcf-xp-ui.es.js +2133 -0
- package/dist/style.css +1 -1
- package/package.json +6 -9
- package/dist/xp-ui.cjs.js +0 -1
- package/dist/xp-ui.es.js +0 -274
package/README.md
ADDED
|
@@ -0,0 +1,1162 @@
|
|
|
1
|
+
# @cghbcf/xp-ui
|
|
2
|
+
|
|
3
|
+
> Vue3 组件库 - 基于 Vue3 + Vite 构建的现代化 UI 组件库
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- ⚡ 基于 Vue3 和 Vite,性能卓越
|
|
8
|
+
- 📦 开箱即用,无需繁琐配置
|
|
9
|
+
- 🎨 现代化设计风格,支持主题定制(浅色 / 暗黑双主题)
|
|
10
|
+
- 🎛️ 可视化主题定制面板 —— 实时修改颜色、一键导出 JSON/CSS
|
|
11
|
+
- 🌈 主色自动派生(-light / -dark / -bg / -border),无需手动配置
|
|
12
|
+
- 🔧 丰富的组件库,覆盖常用场景(Button / Input / Dialog / Card / Icon / Tabs / Empty / Toast / ContextMenu 等 20+ 组件)
|
|
13
|
+
- 💎 完整的 CSS 变量(Design Tokens)系统,便于深度定制
|
|
14
|
+
- 💾 主题配置自动持久化到 localStorage,刷新页面不丢失
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 快速开始
|
|
19
|
+
|
|
20
|
+
### 安装
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# npm
|
|
24
|
+
npm install @cghbcf/xp-ui --save
|
|
25
|
+
|
|
26
|
+
# yarn
|
|
27
|
+
yarn add @cghbcf/xp-ui
|
|
28
|
+
|
|
29
|
+
# pnpm
|
|
30
|
+
pnpm install @cghbcf/xp-ui
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 完整引入
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import { createApp } from 'vue'
|
|
37
|
+
import App from './App.vue'
|
|
38
|
+
import XpUi from '@cghbcf/xp-ui'
|
|
39
|
+
import '@cghbcf/xp-ui/dist/style.css'
|
|
40
|
+
|
|
41
|
+
const app = createApp(App)
|
|
42
|
+
app.use(XpUi)
|
|
43
|
+
app.mount('#app')
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 按需引入
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
import { createApp } from 'vue'
|
|
50
|
+
import App from './App.vue'
|
|
51
|
+
import { XpButton, XpInput, XpDialog, XpCard, XpTabs } from '@cghbcf/xp-ui'
|
|
52
|
+
import '@cghbcf/xp-ui/dist/style.css'
|
|
53
|
+
|
|
54
|
+
const app = createApp(App)
|
|
55
|
+
app.component('XpButton', XpButton)
|
|
56
|
+
app.component('XpInput', XpInput)
|
|
57
|
+
app.mount('#app')
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
也可以直接使用主题 composable:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import { useTheme, applyThemeConfig, setTheme, toggleTheme } from '@cghbcf/xp-ui'
|
|
64
|
+
|
|
65
|
+
const { theme, themeConfig, initTheme, applyThemeConfig, buildCssString } = useTheme()
|
|
66
|
+
initTheme()
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 组件
|
|
72
|
+
|
|
73
|
+
### Icon 图标
|
|
74
|
+
|
|
75
|
+
基于内联 SVG 的图标组件,支持预设/自定义尺寸、颜色、旋转与加载动画。
|
|
76
|
+
|
|
77
|
+
图标文件统一存放在 `src/components/icon/icons/` 目录下,组件在构建时通过 `import.meta.glob` 自动扫描该目录,**新增图标只需放入 `.svg` 文件**,即可用同名 `name` 直接引用(例如 `jiantou.svg` 对应 `name="jiantou"`)。
|
|
78
|
+
|
|
79
|
+
图标内部硬编码的 `fill` / `stroke` 颜色(除 `none` 外)会被自动替换为 `currentColor`,因此 `color` 属性始终生效。当 `name` 不存在时,会展示占位符(`?`)便于排查。
|
|
80
|
+
|
|
81
|
+
#### 基础用法
|
|
82
|
+
|
|
83
|
+
```vue
|
|
84
|
+
<template>
|
|
85
|
+
<!-- 内置图标 -->
|
|
86
|
+
<XpIcon name="jiantou" />
|
|
87
|
+
|
|
88
|
+
<!-- 方向:通过 rotate 或内联样式旋转 -->
|
|
89
|
+
<XpIcon name="jiantou" :rotate="180" />
|
|
90
|
+
|
|
91
|
+
<!-- 预设尺寸 -->
|
|
92
|
+
<XpIcon name="jiantou" size="small" />
|
|
93
|
+
<XpIcon name="jiantou" size="medium" />
|
|
94
|
+
<XpIcon name="jiantou" size="large" />
|
|
95
|
+
|
|
96
|
+
<!-- 自定义尺寸(数字按 px 处理) -->
|
|
97
|
+
<XpIcon name="jiantou" :size="32" />
|
|
98
|
+
|
|
99
|
+
<!-- 自定义颜色 -->
|
|
100
|
+
<XpIcon name="jiantou" color="#67c23a" />
|
|
101
|
+
|
|
102
|
+
<!-- 加载动画 -->
|
|
103
|
+
<XpIcon name="jiantou" spin color="var(--xp-color-primary)" />
|
|
104
|
+
|
|
105
|
+
<!-- name 不存在时显示占位符 -->
|
|
106
|
+
<XpIcon name="not-exist" />
|
|
107
|
+
</template>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
##### Props
|
|
111
|
+
|
|
112
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
113
|
+
|------|------|--------|------|
|
|
114
|
+
| name | string | '' | 图标名称,对应 `icons/` 目录下 `.svg` 文件名(不含后缀) |
|
|
115
|
+
| size | string / number | medium | 尺寸:预设值 `small`(14) / `medium`(18) / `large`(24),或自定义数字(px) / 带单位字符串(如 `48px`) |
|
|
116
|
+
| color | string | '' | 图标颜色,值为任意合法 CSS 颜色 |
|
|
117
|
+
| spin | boolean | false | 是否持续旋转(加载动画) |
|
|
118
|
+
| rotate | number | 0 | 旋转角度(单位:度) |
|
|
119
|
+
|
|
120
|
+
##### Slots
|
|
121
|
+
|
|
122
|
+
| 插槽名 | 说明 |
|
|
123
|
+
|--------|------|
|
|
124
|
+
| default | 自定义图标内容(传入则优先渲染插槽内容,而非 SVG) |
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### Button 按钮
|
|
129
|
+
|
|
130
|
+
按钮用于触发一个操作,如提交表单、打开对话框等。
|
|
131
|
+
|
|
132
|
+
#### 基础用法
|
|
133
|
+
|
|
134
|
+
```vue
|
|
135
|
+
<template>
|
|
136
|
+
<XpButton>Default</XpButton>
|
|
137
|
+
<XpButton type="primary">Primary</XpButton>
|
|
138
|
+
<XpButton type="success">Success</XpButton>
|
|
139
|
+
<XpButton type="warning">Warning</XpButton>
|
|
140
|
+
<XpButton type="danger">Danger</XpButton>
|
|
141
|
+
<XpButton type="info">Info</XpButton>
|
|
142
|
+
|
|
143
|
+
<XpButton type="primary" plain>Plain Primary</XpButton>
|
|
144
|
+
<XpButton type="primary" text>Text Primary</XpButton>
|
|
145
|
+
|
|
146
|
+
<XpButton size="small" type="primary">Small</XpButton>
|
|
147
|
+
<XpButton size="medium" type="primary">Medium</XpButton>
|
|
148
|
+
<XpButton size="large" type="primary">Large</XpButton>
|
|
149
|
+
|
|
150
|
+
<XpButton type="primary" disabled>Disabled</XpButton>
|
|
151
|
+
<XpButton type="primary" loading @click="handleClick">Loading</XpButton>
|
|
152
|
+
</template>
|
|
153
|
+
|
|
154
|
+
<script setup>
|
|
155
|
+
const handleClick = () => {}
|
|
156
|
+
</script>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
##### Props
|
|
160
|
+
|
|
161
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
162
|
+
|------|------|--------|------|
|
|
163
|
+
| type | string | default | 按钮类型,可选值:primary / default / success / warning / danger / info / ghost |
|
|
164
|
+
| size | string | medium | 按钮尺寸,可选值:small / medium / large |
|
|
165
|
+
| plain | boolean | false | 是否朴素按钮 |
|
|
166
|
+
| text | boolean | false | 是否文字按钮 |
|
|
167
|
+
| disabled | boolean | false | 是否禁用按钮 |
|
|
168
|
+
| loading | boolean | false | 是否显示加载状态 |
|
|
169
|
+
|
|
170
|
+
##### Events
|
|
171
|
+
|
|
172
|
+
| 事件名 | 说明 | 回调参数 |
|
|
173
|
+
|--------|------|----------|
|
|
174
|
+
| click | 点击按钮时触发 | event |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### Input 输入框
|
|
179
|
+
|
|
180
|
+
用于收集用户输入信息。
|
|
181
|
+
|
|
182
|
+
#### 基础用法
|
|
183
|
+
|
|
184
|
+
```vue
|
|
185
|
+
<template>
|
|
186
|
+
<XpInput v-model="inputValue" placeholder="请输入内容" showClear />
|
|
187
|
+
|
|
188
|
+
<XpInput placeholder="Small" size="small" />
|
|
189
|
+
<XpInput placeholder="Medium" size="medium" />
|
|
190
|
+
<XpInput placeholder="Large" size="large" />
|
|
191
|
+
|
|
192
|
+
<XpInput placeholder="用户名">
|
|
193
|
+
<template #prefix>👤</template>
|
|
194
|
+
</XpInput>
|
|
195
|
+
|
|
196
|
+
<XpInput placeholder="密码">
|
|
197
|
+
<template #suffix>🔒</template>
|
|
198
|
+
</XpInput>
|
|
199
|
+
|
|
200
|
+
<XpInput placeholder="禁用状态" disabled />
|
|
201
|
+
</template>
|
|
202
|
+
|
|
203
|
+
<script setup>
|
|
204
|
+
import { ref } from 'vue'
|
|
205
|
+
const inputValue = ref('')
|
|
206
|
+
</script>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
##### Props
|
|
210
|
+
|
|
211
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
212
|
+
|------|------|--------|------|
|
|
213
|
+
| modelValue | string / number | '' | 输入框的值,支持 v-model |
|
|
214
|
+
| id | string | '' | 原生 input 的 id,配合 label[for] 使用 |
|
|
215
|
+
| type | string | text | 输入框类型,可选值:text / password / number / email / tel / url |
|
|
216
|
+
| placeholder | string | '' | 占位符文本 |
|
|
217
|
+
| disabled | boolean | false | 是否禁用 |
|
|
218
|
+
| size | string | medium | 输入框尺寸,可选值:small / medium / large |
|
|
219
|
+
| maxlength | string / number | null | 最大输入长度 |
|
|
220
|
+
| showClear | boolean | false | 是否显示清空按钮 |
|
|
221
|
+
|
|
222
|
+
##### Events
|
|
223
|
+
|
|
224
|
+
| 事件名 | 说明 | 回调参数 |
|
|
225
|
+
|--------|------|----------|
|
|
226
|
+
| update:modelValue | 值改变时触发 | value |
|
|
227
|
+
| focus | 获得焦点时触发 | event |
|
|
228
|
+
| blur | 失去焦点时触发 | event |
|
|
229
|
+
| clear | 点击清空按钮时触发 | - |
|
|
230
|
+
|
|
231
|
+
##### Slots
|
|
232
|
+
|
|
233
|
+
| 插槽名 | 说明 |
|
|
234
|
+
|--------|------|
|
|
235
|
+
| prefix | 前缀内容 |
|
|
236
|
+
| suffix | 后缀内容 |
|
|
237
|
+
|
|
238
|
+
##### 实例方法
|
|
239
|
+
|
|
240
|
+
通过模板 ref 可调用内部原生 input 的方法(如自动聚焦 / 全选):
|
|
241
|
+
|
|
242
|
+
```vue
|
|
243
|
+
<template>
|
|
244
|
+
<XpInput ref="inputRef" v-model="value" placeholder="请输入" />
|
|
245
|
+
</template>
|
|
246
|
+
|
|
247
|
+
<script setup>
|
|
248
|
+
import { ref, nextTick } from 'vue'
|
|
249
|
+
const inputRef = ref(null)
|
|
250
|
+
nextTick(() => {
|
|
251
|
+
inputRef.value.focus()
|
|
252
|
+
inputRef.value.select()
|
|
253
|
+
})
|
|
254
|
+
</script>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
| 方法 | 说明 |
|
|
258
|
+
|------|------|
|
|
259
|
+
| focus | 聚焦输入框 |
|
|
260
|
+
| select | 全选输入框内容 |
|
|
261
|
+
| blur | 失焦 |
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### Switch 开关
|
|
266
|
+
|
|
267
|
+
表示两种相互对立的状态间的切换。
|
|
268
|
+
|
|
269
|
+
#### 基础用法
|
|
270
|
+
|
|
271
|
+
```vue
|
|
272
|
+
<template>
|
|
273
|
+
<XpSwitch v-model="value" />
|
|
274
|
+
<XpSwitch v-model="value" size="small" />
|
|
275
|
+
<XpSwitch v-model="value" size="large" />
|
|
276
|
+
<XpSwitch :model-value="true" disabled />
|
|
277
|
+
</template>
|
|
278
|
+
|
|
279
|
+
<script setup>
|
|
280
|
+
import { ref } from 'vue'
|
|
281
|
+
const value = ref(false)
|
|
282
|
+
</script>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
##### Props
|
|
286
|
+
|
|
287
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
288
|
+
|------|------|--------|------|
|
|
289
|
+
| modelValue | boolean | false | 绑定值,支持 v-model |
|
|
290
|
+
| size | string | medium | 尺寸:small / medium / large |
|
|
291
|
+
| disabled | boolean | false | 是否禁用 |
|
|
292
|
+
|
|
293
|
+
##### Events
|
|
294
|
+
|
|
295
|
+
| 事件名 | 说明 | 回调参数 |
|
|
296
|
+
|--------|------|----------|
|
|
297
|
+
| update:modelValue | 值改变时触发 | value |
|
|
298
|
+
| change | 值改变时触发 | value |
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
### Checkbox 多选框
|
|
303
|
+
|
|
304
|
+
一组备选项中进行多选。
|
|
305
|
+
|
|
306
|
+
#### 基础用法
|
|
307
|
+
|
|
308
|
+
```vue
|
|
309
|
+
<template>
|
|
310
|
+
<XpCheckbox v-model="value1">同意协议</XpCheckbox>
|
|
311
|
+
<XpCheckbox v-model="value2">接收邮件</XpCheckbox>
|
|
312
|
+
<XpCheckbox :model-value="true" disabled>已勾选(禁用)</XpCheckbox>
|
|
313
|
+
<XpCheckbox :model-value="false" disabled>未勾选(禁用)</XpCheckbox>
|
|
314
|
+
</template>
|
|
315
|
+
|
|
316
|
+
<script setup>
|
|
317
|
+
import { ref } from 'vue'
|
|
318
|
+
const value1 = ref(true)
|
|
319
|
+
const value2 = ref(false)
|
|
320
|
+
</script>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
##### Props
|
|
324
|
+
|
|
325
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
326
|
+
|------|------|--------|------|
|
|
327
|
+
| modelValue | boolean | false | 绑定值,支持 v-model |
|
|
328
|
+
| disabled | boolean | false | 是否禁用 |
|
|
329
|
+
| indeterminate | boolean | false | 是否半选状态 |
|
|
330
|
+
|
|
331
|
+
##### Events
|
|
332
|
+
|
|
333
|
+
| 事件名 | 说明 | 回调参数 |
|
|
334
|
+
|--------|------|----------|
|
|
335
|
+
| update:modelValue | 值改变时触发 | value |
|
|
336
|
+
| change | 值改变时触发 | value |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
### Radio 单选框
|
|
341
|
+
|
|
342
|
+
在一组备选项中进行单选。
|
|
343
|
+
|
|
344
|
+
#### 基础用法
|
|
345
|
+
|
|
346
|
+
```vue
|
|
347
|
+
<template>
|
|
348
|
+
<XpRadio v-model="value" value="A">选项 A</XpRadio>
|
|
349
|
+
<XpRadio v-model="value" value="B">选项 B</XpRadio>
|
|
350
|
+
<XpRadio v-model="value" value="C">选项 C</XpRadio>
|
|
351
|
+
</template>
|
|
352
|
+
|
|
353
|
+
<script setup>
|
|
354
|
+
import { ref } from 'vue'
|
|
355
|
+
const value = ref('A')
|
|
356
|
+
</script>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
##### Props
|
|
360
|
+
|
|
361
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
362
|
+
|------|------|--------|------|
|
|
363
|
+
| modelValue | string / number / boolean | '' | 绑定值 |
|
|
364
|
+
| value | string / number / boolean | '' | 选项的值 |
|
|
365
|
+
| disabled | boolean | false | 是否禁用 |
|
|
366
|
+
|
|
367
|
+
##### Events
|
|
368
|
+
|
|
369
|
+
| 事件名 | 说明 | 回调参数 |
|
|
370
|
+
|--------|------|----------|
|
|
371
|
+
| update:modelValue | 值改变时触发 | value |
|
|
372
|
+
| change | 值改变时触发 | value |
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### Tag 标签 & Badge 徽标
|
|
377
|
+
|
|
378
|
+
Tag 用于标记和分类;Badge 用于消息数量提示。
|
|
379
|
+
|
|
380
|
+
#### 基础用法
|
|
381
|
+
|
|
382
|
+
```vue
|
|
383
|
+
<template>
|
|
384
|
+
<XpTag>Default</XpTag>
|
|
385
|
+
<XpTag type="primary">Primary</XpTag>
|
|
386
|
+
<XpTag type="success">Success</XpTag>
|
|
387
|
+
<XpTag type="warning">Warning</XpTag>
|
|
388
|
+
<XpTag type="danger">Danger</XpTag>
|
|
389
|
+
<XpTag type="info">Info</XpTag>
|
|
390
|
+
|
|
391
|
+
<XpTag round type="primary">Round</XpTag>
|
|
392
|
+
<XpTag size="small">Small</XpTag>
|
|
393
|
+
<XpTag size="large">Large</XpTag>
|
|
394
|
+
<XpTag closable>Closable</XpTag>
|
|
395
|
+
|
|
396
|
+
<XpBadge value="5">
|
|
397
|
+
<XpButton size="small">消息</XpButton>
|
|
398
|
+
</XpBadge>
|
|
399
|
+
<XpBadge value="120" type="warning">
|
|
400
|
+
<XpButton size="small">通知</XpButton>
|
|
401
|
+
</XpBadge>
|
|
402
|
+
<XpBadge isDot type="danger">
|
|
403
|
+
<XpButton size="small">新消息</XpButton>
|
|
404
|
+
</XpBadge>
|
|
405
|
+
</template>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
##### Tag Props
|
|
409
|
+
|
|
410
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
411
|
+
|------|------|--------|------|
|
|
412
|
+
| type | string | default | 类型:primary / default / success / warning / danger / info |
|
|
413
|
+
| size | string | medium | 尺寸:small / medium / large |
|
|
414
|
+
| color | string | '' | 自定义颜色(#xxx 或 rgb) |
|
|
415
|
+
| plain | boolean | false | 是否朴素样式 |
|
|
416
|
+
| round | boolean | false | 是否圆角 |
|
|
417
|
+
| closable | boolean | false | 是否可关闭 |
|
|
418
|
+
|
|
419
|
+
##### Badge Props
|
|
420
|
+
|
|
421
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
422
|
+
|------|------|--------|------|
|
|
423
|
+
| value | string / number | 0 | 显示值 |
|
|
424
|
+
| max | number | 99 | 最大值,超出显示 {max}+ |
|
|
425
|
+
| type | string | danger | 类型:primary / success / warning / danger / info |
|
|
426
|
+
| isDot | boolean | false | 是否以小圆点显示 |
|
|
427
|
+
| hidden | boolean | false | 是否隐藏徽标 |
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
### Alert 提示
|
|
432
|
+
|
|
433
|
+
用于页面中展示重要的提示信息。
|
|
434
|
+
|
|
435
|
+
#### 基础用法
|
|
436
|
+
|
|
437
|
+
```vue
|
|
438
|
+
<template>
|
|
439
|
+
<XpAlert title="这是一条成功消息" type="success" />
|
|
440
|
+
<XpAlert title="这是一条警告消息" type="warning" />
|
|
441
|
+
<XpAlert title="这是一条错误消息" type="danger" />
|
|
442
|
+
<XpAlert title="这是一条提示消息" type="info" />
|
|
443
|
+
</template>
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
##### Props
|
|
447
|
+
|
|
448
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
449
|
+
|------|------|--------|------|
|
|
450
|
+
| title | string | '' | 标题 |
|
|
451
|
+
| type | string | info | 类型:success / warning / danger / info |
|
|
452
|
+
| effect | string | light | 样式:light / dark / plain |
|
|
453
|
+
| closable | boolean | true | 是否可关闭 |
|
|
454
|
+
| showIcon | boolean | true | 是否显示图标 |
|
|
455
|
+
|
|
456
|
+
##### Events
|
|
457
|
+
|
|
458
|
+
| 事件名 | 说明 | 回调参数 |
|
|
459
|
+
|--------|------|----------|
|
|
460
|
+
| close | 关闭 alert 时触发 | - |
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
### Avatar 头像
|
|
465
|
+
|
|
466
|
+
用图标、图片或者字符展示用户头像。
|
|
467
|
+
|
|
468
|
+
#### 基础用法
|
|
469
|
+
|
|
470
|
+
```vue
|
|
471
|
+
<template>
|
|
472
|
+
<XpAvatar size="small">Xp</XpAvatar>
|
|
473
|
+
<XpAvatar>User</XpAvatar>
|
|
474
|
+
<XpAvatar size="large">Demo</XpAvatar>
|
|
475
|
+
<XpAvatar shape="square">Sq</XpAvatar>
|
|
476
|
+
<XpAvatar shape="square" size="large">UI</XpAvatar>
|
|
477
|
+
<XpAvatar src="https://example.com/avatar.png" alt="Avatar" />
|
|
478
|
+
</template>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
##### Props
|
|
482
|
+
|
|
483
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
484
|
+
|------|------|--------|------|
|
|
485
|
+
| src | string | '' | 图片头像地址 |
|
|
486
|
+
| alt | string | '' | 替代文本 |
|
|
487
|
+
| shape | string | circle | 形状:circle / square |
|
|
488
|
+
| size | string | medium | 尺寸:small / medium / large |
|
|
489
|
+
| icon | string | '' | 图标 |
|
|
490
|
+
|
|
491
|
+
##### Events
|
|
492
|
+
|
|
493
|
+
| 事件名 | 说明 | 回调参数 |
|
|
494
|
+
|--------|------|----------|
|
|
495
|
+
| error | 图片加载失败时触发 | - |
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
### Progress 进度条 & Rate 评分
|
|
500
|
+
|
|
501
|
+
进度条用于展示操作进度;评分用于对事物进行评级操作。
|
|
502
|
+
|
|
503
|
+
#### 基础用法
|
|
504
|
+
|
|
505
|
+
```vue
|
|
506
|
+
<template>
|
|
507
|
+
<XpProgress :percentage="30" style="width:240px" />
|
|
508
|
+
<XpProgress :percentage="60" status="warning" style="width:240px" />
|
|
509
|
+
<XpProgress :percentage="85" status="success" style="width:240px" />
|
|
510
|
+
<XpProgress :percentage="100" status="exception" style="width:240px" />
|
|
511
|
+
|
|
512
|
+
<XpRate v-model="rate" showText />
|
|
513
|
+
</template>
|
|
514
|
+
|
|
515
|
+
<script setup>
|
|
516
|
+
import { ref } from 'vue'
|
|
517
|
+
const rate = ref(3)
|
|
518
|
+
</script>
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
##### Progress Props
|
|
522
|
+
|
|
523
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
524
|
+
|------|------|--------|------|
|
|
525
|
+
| percentage | number | 0 | 百分比(0-100) |
|
|
526
|
+
| color | string | '' | 自定义进度条颜色 |
|
|
527
|
+
| showText | boolean | true | 是否显示百分比文字 |
|
|
528
|
+
| type | string | line | 类型:line / circle |
|
|
529
|
+
| status | string | '' | 状态:success / warning / exception |
|
|
530
|
+
| strokeWidth | number | 8 | line 模式下进度条高度(px),紧凑场景可设小值 |
|
|
531
|
+
|
|
532
|
+
##### Rate Props
|
|
533
|
+
|
|
534
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
535
|
+
|------|------|--------|------|
|
|
536
|
+
| modelValue | number | 0 | 绑定值 |
|
|
537
|
+
| max | number | 5 | 最大分值 |
|
|
538
|
+
| color | string | #f7ba2a | 颜色 |
|
|
539
|
+
| disabled | boolean | false | 是否禁用 |
|
|
540
|
+
| showText | boolean | false | 是否显示文字 |
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
### Tooltip 提示
|
|
545
|
+
|
|
546
|
+
常用于展示鼠标 hover 时的提示信息。
|
|
547
|
+
|
|
548
|
+
#### 基础用法
|
|
549
|
+
|
|
550
|
+
```vue
|
|
551
|
+
<template>
|
|
552
|
+
<XpTooltip content="顶部提示">
|
|
553
|
+
<XpButton type="primary">Top</XpButton>
|
|
554
|
+
</XpTooltip>
|
|
555
|
+
<XpTooltip content="底部提示" placement="bottom">
|
|
556
|
+
<XpButton>Bottom</XpButton>
|
|
557
|
+
</XpTooltip>
|
|
558
|
+
<XpTooltip content="左侧提示" placement="left">
|
|
559
|
+
<XpButton type="success">Left</XpButton>
|
|
560
|
+
</XpTooltip>
|
|
561
|
+
<XpTooltip content="右侧提示" placement="right">
|
|
562
|
+
<XpButton type="warning">Right</XpButton>
|
|
563
|
+
</XpTooltip>
|
|
564
|
+
</template>
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
##### Props
|
|
568
|
+
|
|
569
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
570
|
+
|------|------|--------|------|
|
|
571
|
+
| content | string | '' | 显示的内容 |
|
|
572
|
+
| placement | string | top | 出现位置:top / bottom / left / right |
|
|
573
|
+
| trigger | string | hover | 触发方式:hover / click / manual |
|
|
574
|
+
| disabled | boolean | false | 是否禁用 |
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
### Dropdown 下拉菜单
|
|
579
|
+
|
|
580
|
+
将动作或菜单折叠到下拉菜单中。
|
|
581
|
+
|
|
582
|
+
#### 基础用法
|
|
583
|
+
|
|
584
|
+
```vue
|
|
585
|
+
<template>
|
|
586
|
+
<XpDropdown :items="items" @select="handleSelect">
|
|
587
|
+
<XpButton type="primary">下拉菜单 ▾</XpButton>
|
|
588
|
+
</XpDropdown>
|
|
589
|
+
</template>
|
|
590
|
+
|
|
591
|
+
<script setup>
|
|
592
|
+
const items = [
|
|
593
|
+
{ label: '选项一', command: 'a' },
|
|
594
|
+
{ label: '选项二', command: 'b' },
|
|
595
|
+
{ label: '选项三(禁用)', command: 'c', disabled: true },
|
|
596
|
+
{ divider: true },
|
|
597
|
+
{ label: '选项四', command: 'd' }
|
|
598
|
+
]
|
|
599
|
+
const handleSelect = (item) => {
|
|
600
|
+
console.log('选中:', item)
|
|
601
|
+
}
|
|
602
|
+
</script>
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
##### Props
|
|
606
|
+
|
|
607
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
608
|
+
|------|------|--------|------|
|
|
609
|
+
| items | Array | [] | 菜单项:{ label, command, disabled, divider } |
|
|
610
|
+
| disabled | boolean | false | 是否禁用 |
|
|
611
|
+
|
|
612
|
+
##### Events
|
|
613
|
+
|
|
614
|
+
| 事件名 | 说明 | 回调参数 |
|
|
615
|
+
|--------|------|----------|
|
|
616
|
+
| select | 点击菜单项时触发 | item |
|
|
617
|
+
| command | 点击菜单项时触发(传 command) | command, item |
|
|
618
|
+
| open | 菜单打开时触发 | - |
|
|
619
|
+
| close | 菜单关闭时触发 | - |
|
|
620
|
+
|
|
621
|
+
---
|
|
622
|
+
|
|
623
|
+
### Card 卡片
|
|
624
|
+
|
|
625
|
+
将信息聚合在卡片容器中展示。
|
|
626
|
+
|
|
627
|
+
#### 基础用法
|
|
628
|
+
|
|
629
|
+
```vue
|
|
630
|
+
<template>
|
|
631
|
+
<XpCard title="卡片标题">
|
|
632
|
+
<p>这是卡片内容</p>
|
|
633
|
+
</XpCard>
|
|
634
|
+
|
|
635
|
+
<XpCard title="卡片标题">
|
|
636
|
+
<p>卡片内容区域</p>
|
|
637
|
+
<template #footer>
|
|
638
|
+
<div style="display:flex;justify-content:flex-end;gap:8px">
|
|
639
|
+
<XpButton size="small">取消</XpButton>
|
|
640
|
+
<XpButton size="small" type="primary">确定</XpButton>
|
|
641
|
+
</div>
|
|
642
|
+
</template>
|
|
643
|
+
</XpCard>
|
|
644
|
+
|
|
645
|
+
<XpCard title="卡片标题" shadow="hover">
|
|
646
|
+
<p>悬停出现阴影</p>
|
|
647
|
+
</XpCard>
|
|
648
|
+
</template>
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
##### Props
|
|
652
|
+
|
|
653
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
654
|
+
|------|------|--------|------|
|
|
655
|
+
| title | string | '' | 卡片标题 |
|
|
656
|
+
| shadow | string | always | 阴影效果:always / hover / never |
|
|
657
|
+
| bordered | boolean | true | 是否显示边框 |
|
|
658
|
+
| hover | boolean | false | 是否 hover 时上移 |
|
|
659
|
+
|
|
660
|
+
##### Slots
|
|
661
|
+
|
|
662
|
+
| 插槽名 | 说明 |
|
|
663
|
+
|--------|------|
|
|
664
|
+
| header | 自定义头部内容 |
|
|
665
|
+
| default | 卡片主体内容 |
|
|
666
|
+
| footer | 底部内容 |
|
|
667
|
+
| extra | 头部右侧内容 |
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
### Tabs 标签页
|
|
672
|
+
|
|
673
|
+
分隔内容上有关联但属于不同类别的数据集合。
|
|
674
|
+
|
|
675
|
+
#### 基础用法
|
|
676
|
+
|
|
677
|
+
```vue
|
|
678
|
+
<template>
|
|
679
|
+
<XpTabs v-model="active">
|
|
680
|
+
<XpTabPane name="tab1" title="选项一">
|
|
681
|
+
<p>这是选项一的内容。</p>
|
|
682
|
+
</XpTabPane>
|
|
683
|
+
<XpTabPane name="tab2" title="选项二">
|
|
684
|
+
<p>这是选项二的内容。</p>
|
|
685
|
+
</XpTabPane>
|
|
686
|
+
<XpTabPane name="tab3" title="选项三">
|
|
687
|
+
<p>这是选项三的内容。</p>
|
|
688
|
+
</XpTabPane>
|
|
689
|
+
</XpTabs>
|
|
690
|
+
</template>
|
|
691
|
+
|
|
692
|
+
<script setup>
|
|
693
|
+
import { ref } from 'vue'
|
|
694
|
+
const active = ref('tab1')
|
|
695
|
+
</script>
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
##### Tabs Props
|
|
699
|
+
|
|
700
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
701
|
+
|------|------|--------|------|
|
|
702
|
+
| modelValue | string / number | null | 当前激活的 name,支持 v-model |
|
|
703
|
+
|
|
704
|
+
##### TabPane Props
|
|
705
|
+
|
|
706
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
707
|
+
|------|------|--------|------|
|
|
708
|
+
| name | string / number | - | 必填,唯一标识 |
|
|
709
|
+
| title | string | '' | 标签标题 |
|
|
710
|
+
| disabled | boolean | false | 是否禁用 |
|
|
711
|
+
|
|
712
|
+
##### Tabs Events
|
|
713
|
+
|
|
714
|
+
| 事件名 | 说明 | 回调参数 |
|
|
715
|
+
|--------|------|----------|
|
|
716
|
+
| update:modelValue | 切换时触发 | name |
|
|
717
|
+
| change | 切换时触发 | name |
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
### Dialog 对话框
|
|
722
|
+
|
|
723
|
+
在保留当前页面状态的情况下,告知用户并承载相关操作。
|
|
724
|
+
|
|
725
|
+
#### 基础用法
|
|
726
|
+
|
|
727
|
+
```vue
|
|
728
|
+
<template>
|
|
729
|
+
<XpButton type="primary" @click="visible = true">打开对话框</XpButton>
|
|
730
|
+
<XpDialog
|
|
731
|
+
v-model:visible="visible"
|
|
732
|
+
title="提示"
|
|
733
|
+
@confirm="handleConfirm"
|
|
734
|
+
@cancel="handleCancel"
|
|
735
|
+
>
|
|
736
|
+
<p>这是一段弹窗内容</p>
|
|
737
|
+
</XpDialog>
|
|
738
|
+
</template>
|
|
739
|
+
|
|
740
|
+
<script setup>
|
|
741
|
+
import { ref } from 'vue'
|
|
742
|
+
const visible = ref(false)
|
|
743
|
+
const handleConfirm = () => { visible.value = false }
|
|
744
|
+
const handleCancel = () => { visible.value = false }
|
|
745
|
+
</script>
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
#### 自定义宽度
|
|
749
|
+
|
|
750
|
+
```vue
|
|
751
|
+
<template>
|
|
752
|
+
<XpDialog
|
|
753
|
+
v-model:visible="visible"
|
|
754
|
+
title="宽弹窗"
|
|
755
|
+
width="700px"
|
|
756
|
+
>
|
|
757
|
+
<p>弹窗内容</p>
|
|
758
|
+
</XpDialog>
|
|
759
|
+
</template>
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
#### 自定义按钮文字
|
|
763
|
+
|
|
764
|
+
```vue
|
|
765
|
+
<template>
|
|
766
|
+
<XpDialog
|
|
767
|
+
v-model:visible="visible"
|
|
768
|
+
title="确认删除"
|
|
769
|
+
confirm-button-text="删除"
|
|
770
|
+
cancel-button-text="我再想想"
|
|
771
|
+
>
|
|
772
|
+
<p>确定要删除这条记录吗?</p>
|
|
773
|
+
</XpDialog>
|
|
774
|
+
</template>
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
##### Props
|
|
778
|
+
|
|
779
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
780
|
+
|------|------|--------|------|
|
|
781
|
+
| visible | boolean | false | 是否显示,支持 v-model |
|
|
782
|
+
| title | string | '' | 弹窗标题 |
|
|
783
|
+
| width | string | 500px | 弹窗宽度 |
|
|
784
|
+
| confirmButtonText | string | 确定 | 确认按钮文字 |
|
|
785
|
+
| cancelButtonText | string | 取消 | 取消按钮文字 |
|
|
786
|
+
| closeOnClickModal | boolean | true | 点击遮罩层是否关闭弹窗 |
|
|
787
|
+
| showDefaultFooter | boolean | true | 是否显示默认底部按钮 |
|
|
788
|
+
|
|
789
|
+
##### Events
|
|
790
|
+
|
|
791
|
+
| 事件名 | 说明 | 回调参数 |
|
|
792
|
+
|--------|------|----------|
|
|
793
|
+
| confirm | 点击确认按钮时触发 | - |
|
|
794
|
+
| cancel | 点击取消按钮时触发 | - |
|
|
795
|
+
| close | 关闭弹窗时触发 | - |
|
|
796
|
+
| update:visible | 可见性改变时触发 | visible |
|
|
797
|
+
|
|
798
|
+
##### Slots
|
|
799
|
+
|
|
800
|
+
| 插槽名 | 说明 |
|
|
801
|
+
|--------|------|
|
|
802
|
+
| default | 弹窗主体内容 |
|
|
803
|
+
| footer | 自定义底部按钮区域 |
|
|
804
|
+
|
|
805
|
+
> 按 Esc 键同样可以关闭弹窗。
|
|
806
|
+
|
|
807
|
+
---
|
|
808
|
+
|
|
809
|
+
### Empty 空状态
|
|
810
|
+
|
|
811
|
+
用于列表、目录等数据为空时的占位展示。
|
|
812
|
+
|
|
813
|
+
#### 基础用法
|
|
814
|
+
|
|
815
|
+
```vue
|
|
816
|
+
<template>
|
|
817
|
+
<XpEmpty title="目录为空" hint="拖入文件或点击工具栏上传" />
|
|
818
|
+
</template>
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
#### 自定义图标与操作
|
|
822
|
+
|
|
823
|
+
```vue
|
|
824
|
+
<template>
|
|
825
|
+
<XpEmpty title="连接失败" hint="无法连接到服务器,请检查网络后重试">
|
|
826
|
+
<template #icon>
|
|
827
|
+
<div class="my-icon" />
|
|
828
|
+
</template>
|
|
829
|
+
<XpButton type="primary" size="small">重新加载</XpButton>
|
|
830
|
+
</XpEmpty>
|
|
831
|
+
</template>
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
##### Props
|
|
835
|
+
|
|
836
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
837
|
+
|------|------|--------|------|
|
|
838
|
+
| title | string | 暂无内容 | 主文案 |
|
|
839
|
+
| hint | string | '' | 辅助说明文案 |
|
|
840
|
+
|
|
841
|
+
##### Slots
|
|
842
|
+
|
|
843
|
+
| 插槽名 | 说明 |
|
|
844
|
+
|--------|------|
|
|
845
|
+
| icon | 自定义图标(默认是一个文件占位图形) |
|
|
846
|
+
| default | 底部操作区(如重试按钮) |
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
### FileIcon 文件图标
|
|
851
|
+
|
|
852
|
+
按文件类型展示对应的矢量图标,内置文件夹与常见文件类型,适用于文件管理器等场景。
|
|
853
|
+
|
|
854
|
+
#### 基础用法
|
|
855
|
+
|
|
856
|
+
```vue
|
|
857
|
+
<template>
|
|
858
|
+
<XpFileIcon type="folder" :size="34" />
|
|
859
|
+
<XpFileIcon type="pdf" :size="34" />
|
|
860
|
+
<XpFileIcon type="code" :size="20" />
|
|
861
|
+
</template>
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
##### Props
|
|
865
|
+
|
|
866
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
867
|
+
|------|------|--------|------|
|
|
868
|
+
| type | string | file | 类型:folder / image / video / audio / pdf / doc / sheet / slide / archive / code / text / file |
|
|
869
|
+
| size | number | 20 | 图标边长(px) |
|
|
870
|
+
|
|
871
|
+
---
|
|
872
|
+
|
|
873
|
+
### ContextMenu 右键菜单
|
|
874
|
+
|
|
875
|
+
在指定屏幕坐标位置弹出的菜单,常用于右键 / 长按等交互场景。
|
|
876
|
+
|
|
877
|
+
#### 基础用法
|
|
878
|
+
|
|
879
|
+
```vue
|
|
880
|
+
<template>
|
|
881
|
+
<div @contextmenu.prevent="openMenu($event, items)">右键点击此区域</div>
|
|
882
|
+
<XpContextMenu :visible="menu.visible" :x="menu.x" :y="menu.y" :items="menu.items" @close="menu.visible = false" />
|
|
883
|
+
</template>
|
|
884
|
+
|
|
885
|
+
<script setup>
|
|
886
|
+
import { reactive } from 'vue'
|
|
887
|
+
const menu = reactive({ visible: false, x: 0, y: 0, items: [] })
|
|
888
|
+
const openMenu = (e, items) => {
|
|
889
|
+
menu.x = e.clientX
|
|
890
|
+
menu.y = e.clientY
|
|
891
|
+
menu.items = items
|
|
892
|
+
menu.visible = true
|
|
893
|
+
}
|
|
894
|
+
const items = [
|
|
895
|
+
{ label: '打开', command: 'open' },
|
|
896
|
+
{ label: '禁用项', disabled: true },
|
|
897
|
+
{ divider: true },
|
|
898
|
+
{ label: '删除', command: 'delete', danger: true }
|
|
899
|
+
]
|
|
900
|
+
</script>
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
> 菜单会自动进行视口边界校正;点击菜单项、遮罩或按 Esc 均会关闭菜单。
|
|
904
|
+
|
|
905
|
+
##### Props
|
|
906
|
+
|
|
907
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
908
|
+
|------|------|--------|------|
|
|
909
|
+
| visible | boolean | false | 是否显示 |
|
|
910
|
+
| x | number | 0 | 菜单左上角 x 坐标(px) |
|
|
911
|
+
| y | number | 0 | 菜单左上角 y 坐标(px) |
|
|
912
|
+
| items | Array | [] | 菜单项:{ label, icon?, command?, danger?, disabled?, divider?, onClick? } |
|
|
913
|
+
|
|
914
|
+
##### Events
|
|
915
|
+
|
|
916
|
+
| 事件名 | 说明 | 回调参数 |
|
|
917
|
+
|--------|------|----------|
|
|
918
|
+
| select | 点击菜单项时触发 | item |
|
|
919
|
+
| command | 点击菜单项时触发(传 command) | command, item |
|
|
920
|
+
| close | 菜单关闭时触发 | - |
|
|
921
|
+
|
|
922
|
+
> 兼容用法:菜单项里直接传 `onClick` 函数也会在点击时被调用。
|
|
923
|
+
|
|
924
|
+
---
|
|
925
|
+
|
|
926
|
+
### Toast 轻提示
|
|
927
|
+
|
|
928
|
+
轻量级的全局消息提示,需要配合 `useToast()` 组合式函数使用。
|
|
929
|
+
|
|
930
|
+
#### 基础用法
|
|
931
|
+
|
|
932
|
+
```vue
|
|
933
|
+
<template>
|
|
934
|
+
<!-- 在应用根节点挂载一次即可 -->
|
|
935
|
+
<XpToast />
|
|
936
|
+
</template>
|
|
937
|
+
|
|
938
|
+
<script setup>
|
|
939
|
+
import { useToast } from '@cghbcf/xp-ui'
|
|
940
|
+
const { toast, success, error, warn, info } = useToast()
|
|
941
|
+
|
|
942
|
+
success('操作成功')
|
|
943
|
+
error('操作失败')
|
|
944
|
+
warn('请注意该操作的后果')
|
|
945
|
+
info('这是一条普通提示')
|
|
946
|
+
</script>
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
##### useToast API
|
|
950
|
+
|
|
951
|
+
| 方法 | 说明 | 参数 |
|
|
952
|
+
|------|------|------|
|
|
953
|
+
| toast | 触发提示,可自定义类型与时长 | (message, type?, duration?) |
|
|
954
|
+
| success | 成功提示(2200ms) | message |
|
|
955
|
+
| error | 错误提示(3600ms) | message |
|
|
956
|
+
| warn | 警告提示(2800ms) | message |
|
|
957
|
+
| info | 信息提示(2600ms) | message |
|
|
958
|
+
| toasts | 响应式提示列表(ref) | - |
|
|
959
|
+
|
|
960
|
+
toast 的 `type` 可选值:`info` / `success` / `error` / `warn`。
|
|
961
|
+
|
|
962
|
+
---
|
|
963
|
+
|
|
964
|
+
## 主题定制
|
|
965
|
+
|
|
966
|
+
Xp UI 内置完整的 **浅色 / 暗黑双主题** 系统,并支持 **可视化颜色定制**、**配置导入导出**,可在任意项目中按需使用。
|
|
967
|
+
|
|
968
|
+
### 主题色(Design Tokens)
|
|
969
|
+
|
|
970
|
+
组件库的所有颜色都通过 **CSS 变量** 控制,你可以在浏览器开发者工具中实时查看和调试:
|
|
971
|
+
|
|
972
|
+
| 变量名 | 说明 |
|
|
973
|
+
|--------|------|
|
|
974
|
+
| `--xp-color-primary` | 主色(品牌色) |
|
|
975
|
+
| `--xp-color-success` | 成功色 |
|
|
976
|
+
| `--xp-color-warning` | 警告色 |
|
|
977
|
+
| `--xp-color-danger` | 危险色 |
|
|
978
|
+
| `--xp-color-info` | 信息色 |
|
|
979
|
+
| `--xp-text-color-primary` | 主要文字色 |
|
|
980
|
+
| `--xp-text-color-regular` | 常规文字色 |
|
|
981
|
+
| `--xp-border-color` | 边框色 |
|
|
982
|
+
| `--xp-bg-color` | 背景色 |
|
|
983
|
+
| `--xp-fill-color` | 填充色 |
|
|
984
|
+
| `--xp-shadow-sm` / `--xp-shadow-md` / `--xp-shadow-lg` | 阴影 |
|
|
985
|
+
|
|
986
|
+
> 每个主题色还自动派生出 `-light`(30% 浅色)、`-dark`(20% 深色)、`-bg`(背景色)、`-border`(边框色),无需手动配置。
|
|
987
|
+
|
|
988
|
+
### 浅色 / 暗黑模式切换
|
|
989
|
+
|
|
990
|
+
在入口文件中调用 `initTheme()` 即可自动初始化主题(读取 localStorage 或跟随系统偏好):
|
|
991
|
+
|
|
992
|
+
```js
|
|
993
|
+
import { useTheme } from '@cghbcf/xp-ui'
|
|
994
|
+
|
|
995
|
+
const { initTheme, toggleTheme, setTheme, theme } = useTheme()
|
|
996
|
+
|
|
997
|
+
// 1. 页面加载时初始化主题(读取 localStorage)
|
|
998
|
+
initTheme()
|
|
999
|
+
|
|
1000
|
+
// 2. 切换主题按钮
|
|
1001
|
+
const handleToggle = () => toggleTheme()
|
|
1002
|
+
|
|
1003
|
+
// 3. 强制切换到指定主题
|
|
1004
|
+
setTheme('dark') // 或 'light'
|
|
1005
|
+
|
|
1006
|
+
// 4. 响应式读取当前主题
|
|
1007
|
+
console.log(theme.value) // 'light' | 'dark'
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
Vue 组件中的示例用法:
|
|
1011
|
+
|
|
1012
|
+
```vue
|
|
1013
|
+
<template>
|
|
1014
|
+
<button @click="toggleTheme">
|
|
1015
|
+
当前主题:{{ theme === 'dark' ? '🌙 暗黑' : '☀️ 浅色' }}
|
|
1016
|
+
</button>
|
|
1017
|
+
</template>
|
|
1018
|
+
|
|
1019
|
+
<script setup>
|
|
1020
|
+
import { useTheme } from '@cghbcf/xp-ui'
|
|
1021
|
+
const { theme, toggleTheme, initTheme } = useTheme()
|
|
1022
|
+
initTheme() // 在页面挂载时调用
|
|
1023
|
+
</script>
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
### 自定义主题色(applyThemeConfig)
|
|
1027
|
+
|
|
1028
|
+
通过 `applyThemeConfig` 可以一次性替换所有颜色变量,支持:
|
|
1029
|
+
- 修改主色系(primary / success / warning / danger / info)
|
|
1030
|
+
- 分别定制浅色和暗黑两套文本、边框、背景、填充、阴影
|
|
1031
|
+
|
|
1032
|
+
```js
|
|
1033
|
+
import { applyThemeConfig } from '@cghbcf/xp-ui'
|
|
1034
|
+
|
|
1035
|
+
// 修改主色为绿色 —— 只需一个颜色值,其他衍生色自动生成
|
|
1036
|
+
applyThemeConfig({
|
|
1037
|
+
primary: {
|
|
1038
|
+
primary: '#22c55e', // 绿色主色
|
|
1039
|
+
success: '#67c23a',
|
|
1040
|
+
warning: '#e6a23c',
|
|
1041
|
+
danger: '#f56c6c',
|
|
1042
|
+
info: '#909399'
|
|
1043
|
+
}
|
|
1044
|
+
})
|
|
1045
|
+
|
|
1046
|
+
// 完整配置:浅色 + 暗黑各一套
|
|
1047
|
+
applyThemeConfig({
|
|
1048
|
+
primary: {
|
|
1049
|
+
primary: '#22c55e',
|
|
1050
|
+
success: '#67c23a',
|
|
1051
|
+
warning: '#e6a23c',
|
|
1052
|
+
danger: '#f56c6c',
|
|
1053
|
+
info: '#909399'
|
|
1054
|
+
},
|
|
1055
|
+
light: {
|
|
1056
|
+
text: { primary: '#303133', regular: '#606266', secondary: '#909399', placeholder: '#c0c4cc' },
|
|
1057
|
+
border: { base: '#dcdfe6', light: '#ebeef5', lighter: '#f2f6fc' },
|
|
1058
|
+
bg: { base: '#ffffff', page: '#f2f3f5', soft: '#f5f7fa', overlay: 'rgba(0, 0, 0, 0.5)' },
|
|
1059
|
+
fill: { base: '#f0f2f5', light: '#f5f7fa', lighter: '#fafafa' },
|
|
1060
|
+
shadow: { sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)', md: '0 2px 12px 0 rgba(0, 0, 0, 0.1)', lg: '0 4px 20px 0 rgba(0, 0, 0, 0.15)', overlay: '0 8px 24px 0 rgba(0, 0, 0, 0.2)' }
|
|
1061
|
+
},
|
|
1062
|
+
dark: {
|
|
1063
|
+
text: { primary: '#e5eaf3', regular: '#cfd3dc', secondary: '#a3a6ad', placeholder: '#8d9095' },
|
|
1064
|
+
border: { base: '#4c4d4f', light: '#414243', lighter: '#363637' },
|
|
1065
|
+
bg: { base: '#1d1e1f', page: '#141414', soft: '#2a2b2c', overlay: 'rgba(0, 0, 0, 0.7)' },
|
|
1066
|
+
fill: { base: '#303030', light: '#262727', lighter: '#1d1d1d' },
|
|
1067
|
+
shadow: { sm: '0 1px 2px 0 rgba(0, 0, 0, 0.4)', md: '0 2px 12px 0 rgba(0, 0, 0, 0.45)', lg: '0 4px 20px 0 rgba(0, 0, 0, 0.5)', overlay: '0 8px 24px 0 rgba(0, 0, 0, 0.6)' }
|
|
1068
|
+
}
|
|
1069
|
+
})
|
|
1070
|
+
```
|
|
1071
|
+
|
|
1072
|
+
> 注意:`applyThemeConfig` 会自动做**深合并**——你只需传入要修改的部分,未传的部分保持默认。
|
|
1073
|
+
|
|
1074
|
+
### 导出主题配置(buildCssString)
|
|
1075
|
+
|
|
1076
|
+
可以将当前的主题配置导出为完整的 CSS 文件,放到其他项目(非 Vue 项目也可使用):
|
|
1077
|
+
|
|
1078
|
+
```js
|
|
1079
|
+
import { buildCssString, applyThemeConfig, getDefaultThemeConfig } from '@cghbcf/xp-ui'
|
|
1080
|
+
|
|
1081
|
+
// 1. 先应用你的自定义主题
|
|
1082
|
+
applyThemeConfig({ primary: { primary: '#22c55e' } })
|
|
1083
|
+
|
|
1084
|
+
// 2. 生成 CSS(包含 :root 和 [data-theme="dark"] 两套规则)
|
|
1085
|
+
const css = buildCssString({
|
|
1086
|
+
primary: { primary: '#22c55e' },
|
|
1087
|
+
light: { text: { primary: '#303133' } },
|
|
1088
|
+
dark: { text: { primary: '#e5eaf3' } }
|
|
1089
|
+
})
|
|
1090
|
+
|
|
1091
|
+
// 3. 写入文件(Node / Vite 构建时使用)
|
|
1092
|
+
// fs.writeFileSync('dist/xp-ui-theme.css', css)
|
|
1093
|
+
console.log(css)
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
也可以直接读取 `themeConfig` 响应式对象:
|
|
1097
|
+
|
|
1098
|
+
```js
|
|
1099
|
+
const { themeConfig } = useTheme()
|
|
1100
|
+
console.log(JSON.stringify(themeConfig.value, null, 2))
|
|
1101
|
+
// 输出完整的主题配置,供导入/导出
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
### 导出 JSON 配置文件
|
|
1105
|
+
|
|
1106
|
+
导出 JSON 后可以保存到项目配置文件中,下次启动时重新导入:
|
|
1107
|
+
|
|
1108
|
+
```js
|
|
1109
|
+
import { useTheme } from '@cghbcf/xp-ui'
|
|
1110
|
+
|
|
1111
|
+
const { themeConfig, applyThemeConfig, resetThemeConfig } = useTheme()
|
|
1112
|
+
|
|
1113
|
+
// 导出
|
|
1114
|
+
const json = JSON.stringify(themeConfig.value, null, 2)
|
|
1115
|
+
// 可以保存到 localStorage 或上传到服务器
|
|
1116
|
+
|
|
1117
|
+
// 导入(从文件 / localStorage / API 读取)
|
|
1118
|
+
applyThemeConfig(JSON.parse(json))
|
|
1119
|
+
|
|
1120
|
+
// 恢复默认
|
|
1121
|
+
resetThemeConfig()
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
### 主题 API 汇总
|
|
1125
|
+
|
|
1126
|
+
```js
|
|
1127
|
+
import { useTheme } from '@cghbcf/xp-ui'
|
|
1128
|
+
|
|
1129
|
+
const {
|
|
1130
|
+
theme, // 响应式 ref: 当前主题 ('light' | 'dark')
|
|
1131
|
+
themeConfig, // 响应式 ref: 完整主题配置对象
|
|
1132
|
+
setTheme, // 设置主题: setTheme('dark' | 'light')
|
|
1133
|
+
toggleTheme, // 在 light/dark 之间切换
|
|
1134
|
+
initTheme, // 初始化:读取 localStorage + 跟随系统偏好
|
|
1135
|
+
applyThemeConfig, // 应用自定义主题配置(CSS 变量会立即更新)
|
|
1136
|
+
resetThemeConfig, // 恢复默认配置
|
|
1137
|
+
getDefaultThemeConfig, // 获取默认配置对象
|
|
1138
|
+
buildCssString, // 根据配置生成 CSS 字符串
|
|
1139
|
+
buildCssVars // 根据配置生成 { '--xp-color-xxx': value } 映射
|
|
1140
|
+
} = useTheme()
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
### 主题持久化
|
|
1144
|
+
|
|
1145
|
+
`initTheme()` 和 `applyThemeConfig()` 都会自动将设置写入 `localStorage`(键名 `xp-ui-theme` 和 `xp-ui-theme-config`),下次访问时自动恢复,无需额外处理。
|
|
1146
|
+
|
|
1147
|
+
---
|
|
1148
|
+
|
|
1149
|
+
## 浏览器支持
|
|
1150
|
+
|
|
1151
|
+
支持所有现代浏览器:
|
|
1152
|
+
|
|
1153
|
+
- Chrome(推荐)
|
|
1154
|
+
- Firefox
|
|
1155
|
+
- Safari
|
|
1156
|
+
- Edge
|
|
1157
|
+
|
|
1158
|
+
---
|
|
1159
|
+
|
|
1160
|
+
## License
|
|
1161
|
+
|
|
1162
|
+
MIT
|