# @yxhl/specter-pui-vtk

> 雅心互联 Vue 3 + Vuetify 3 智能组件库

基于 Vuetify 3 的企业级 Vue 3 组件库，提供丰富的业务组件和工具函数。

## 📋 目录

- [快速开始](#快速开始)
- [安装配置](#安装配置)
- [组件文档](#组件文档)
  - [VtkUpload - 文件上传组件](#vtkupload---文件上传组件)
- [公用方法](#公用方法)
- [配置选项](#配置选项)
- [更新迭代](#更新迭代)
- [常见问题](#常见问题)

---

## 快速开始

### 1. 安装组件库

```bash
npm install @yxhl/specter-pui-vtk
```

### 2. 引入组件库

在 `src/main.js` 或 `src/main.ts` 中：

```javascript
import { createApp } from 'vue'
import App from './App.vue'
import SpecterPuiVtk from '@yxhl/specter-pui-vtk'
import '@yxhl/specter-pui-vtk/dist/specter-pui-vtk.css'

const app = createApp(App)

// 配置组件库（可选）
window.VTK_CONFIG = {
  storageKeys: {
    user: import.meta.env.VITE_MIS_USERS || '_mis_acis_users',
    token: import.meta.env.VITE_MIS_TOKEN || '_mis_acis_token'
  }
}

// 配置 API 地址（可选）
window.VITE_APP_API_URL = import.meta.env.VITE_APP_API_URL

app.use(SpecterPuiVtk)
app.mount('#app')
```

### 3. 使用组件

```vue
<template>
  <VtkStepper :el="currentStep" list="步骤1,步骤2,步骤3" />
  <VtkPage v-model="page" :total="total" />
</template>

<script setup>
import { ref } from 'vue'

const currentStep = ref(1)
const page = ref({ pageno: 1, limit: 10 })
const total = ref(100)
</script>
```

---

## 安装配置

### 环境要求

- Vue 3.x
- Vuetify 3.x
- Node.js >= 16

### 完整配置示例

```javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import SpecterPuiVtk from '@yxhl/specter-pui-vtk'
import '@yxhl/specter-pui-vtk/dist/specter-pui-vtk.css'

const app = createApp(App)

// 1. 配置存储键名（可选）
window.VTK_CONFIG = {
  storageKeys: {
    user: import.meta.env.VITE_MIS_USERS || '_mis_acis_users',
    token: import.meta.env.VITE_MIS_TOKEN || '_mis_acis_token'
  }
}

// 2. 配置 API 基础地址（可选）
window.VITE_APP_API_URL = import.meta.env.VITE_APP_API_URL

// 3. 注册组件库
app.use(SpecterPuiVtk)

// 4. 添加消息组件到模板（必需）
// 在 App.vue 中添加：
// <template>
//   <v-app>
//     <router-view />
//     <vtk-message />
//   </v-app>
// </template>

app.mount('#app')
```

### 环境变量配置

在项目根目录创建 `.env` 文件：

```env
# API 基础地址
VITE_APP_API_URL=https://api.example.com

# 存储键名（可选）
VITE_MIS_USERS=my_user_key
VITE_MIS_TOKEN=my_token_key
```

---

## 组件文档

### 基础组件

#### VtkArea - 地区选择组件

地区选择下拉组件，支持省市区三级联动。

**Props:**
- `modelValue` (String): 绑定值，地区代码
- `placeholder` (String): 占位文本，默认 "请选择地区"

**Events:**
- `update:modelValue`: 值变化时触发
- `change`: 选择变化时触发

**使用示例:**
```vue
<VtkArea v-model="areaCode" placeholder="选择地区" @change="handleChange" />
```

---

#### VtkAreaTabs - 地区选择组件（Tab 版）

带 Tab 切换的地区选择组件，支持多级地区选择。

**Props:**
- `modelValue` (String): 绑定值，地区代码
- `minArea` (Number): 最小地区级别（2=省，4=市，6=区县，9=街镇，12=村社）
- `areaNode` (Number): 显示的地区节点数量

**Events:**
- `update:modelValue`: 值变化时触发
- `change`: 选择变化时触发

**使用示例:**
```vue
<!-- 基础使用 -->
<VtkAreaTabs v-model="areaCode" @change="handleChange" />

<!-- 限制到区县级别 -->
<VtkAreaTabs v-model="areaCode" :min-area="6" />

<!-- 只显示最后2级地区名称 -->
<VtkAreaTabs v-model="areaCode" :area-node="2" />
```

---

#### VtkDept - 人员选择组件

地区-部门-人员三级联动选择组件，支持单选和多选。

**Props:**
- `multiple` (Boolean): 是否多选，默认 false

**Events:**
- `selected`: 选择完成时触发，参数为选中的人员数组

**Methods:**
- `add()`: 打开选择对话框
- `close()`: 关闭选择对话框

**使用示例:**
```vue
<template>
  <VBtn @click="openDept">选择人员</VBtn>
  <VtkDept
    ref="deptRef"
    :multiple="true"
    @selected="handleSelected"
  />
</template>

<script setup>
import { ref } from 'vue'

const deptRef = ref(null)

const openDept = () => {
  deptRef.value?.add()
}

const handleSelected = (persons) => {
  console.log('选中的人员:', persons)
}
</script>
```

---

#### VtkBreadcrumb - 面包屑导航

面包屑导航组件，支持自定义返回路径。

**Props:**
- `items` (Array): 面包屑项数组，格式：`[{ title: '首页', to: '/home' }]`
- `showBack` (Boolean): 是否显示返回按钮，默认 true
- `backTo` (String): 返回路径
- `backText` (String): 返回按钮文本，默认 "返回"

**Events:**
- `back`: 点击返回按钮时触发

**使用示例:**
```vue
<VtkBreadcrumb
  :items="[
    { title: '首页', to: '/home' },
    { title: '用户管理', to: '/users' },
    { title: '用户详情' }
  ]"
  back-to="/home"
  @back="handleBack"
/>
```

---

#### VtkStepper - 步骤条组件

步骤条组件，用于展示多步骤流程。

**Props:**
- `el` (Number): 当前步骤，从 1 开始
- `list` (String): 步骤列表，逗号分隔，如 "步骤1,步骤2,步骤3"

**Slots:**
- `1`, `2`, `3`...: 各步骤的内容插槽

**使用示例:**
```vue
<VtkStepper :el="currentStep" list="基础信息,详细信息,完成">
  <template #1>
    <div>步骤1的内容</div>
  </template>
  <template #2>
    <div>步骤2的内容</div>
  </template>
  <template #3>
    <div>步骤3的内容</div>
  </template>
</VtkStepper>
```

---

#### VtkPage - 分页组件

分页组件，支持页码和每页数量选择。

**Props:**
- `modelValue` (Object): 绑定值，格式：`{ pageno: 1, pageCount: 10, rowCount: 100, limit: 10 }`

**Events:**
- `update:modelValue`: 分页变化时触发
- `change`: 分页变化时触发

**使用示例:**
```vue
<VtkPage v-model="pageData" @change="loadData" />

<script setup>
const pageData = ref({
  pageno: 1,      // 当前页
  pageCount: 10,  // 总页数
  rowCount: 100,  // 总记录数
  limit: 10       // 每页数量
})
</script>
```

---

#### VtkFormItem - 表单项组件

表单项组件，提供标签和帮助文本。

**Props:**
- `label` (String): 标签文本
- `must` (Boolean): 是否必填，显示红色星号
- `left` (Boolean): 标签左对齐
- `help` (String): 帮助文本，支持 HTML

**Slots:**
- `default`: 表单控件插槽

**使用示例:**
```vue
<VtkFormItem
  label="用户名："
  must
  left
  help="请输入4-20位字符"
>
  <VTextField v-model="username" />
</VtkFormItem>
```

---

#### VtkSelect - 下拉选择组件

下拉选择组件，支持字符串格式的选项列表。

**Props:**
- `modelValue`: 绑定值
- `list` (String): 选项列表，格式：`"value1:label1/value2:label2"`
- `placeholder` (String): 占位文本
- 其他 Vuetify VSelect 的 props

**使用示例:**
```vue
<VtkSelect
  v-model="selected"
  list="1:选项1/2:选项2/3:选项3"
  placeholder="请选择"
/>
```

---

#### VtkCheckbox - 复选框组件

复选框组件，支持字符串格式的选项列表。

**Props:**
- `modelValue`: 绑定值
- `list` (String): 选项列表，格式：`"value1:label1/value2:label2"`

**使用示例:**
```vue
<VtkCheckbox
  v-model="selected"
  list="1:选项1/2:选项2/3:选项3"
/>
```

---

#### VtkRadio - 单选框组件

单选框组件，支持字符串格式的选项列表。

**Props:**
- `modelValue`: 绑定值
- `list` (String): 选项列表，格式：`"value1:label1/value2:label2"`

**使用示例:**
```vue
<VtkRadio
  v-model="selected"
  list="1:选项1/2:选项2/3:选项3"
/>
```

---

#### VtkDatePicker - 日期选择器

日期选择器组件。

**Props:**
- `modelValue`: 绑定值
- `placeholder` (String): 占位文本

**使用示例:**
```vue
<VtkDatePicker v-model="date" placeholder="选择日期" />
```

---

#### VtkDateSelector - 高级日期选择器

功能强大的日期选择器组件，支持日期、周、月、年的单选和范围选择，适配 Vuetify 3 主题（亮色/暗色）。

**Props:**
- `modelValue` (String | Array): 绑定值
  - 单选模式：字符串，如 `"2024-01-01"`
  - 范围模式：数组，如 `["2024-01-01", "2024-01-31"]`
- `displayMode` (String): 显示模式，可选值：`'day'` | `'week'` | `'month'` | `'year'`，默认 `'day'`
- `mode` (String): 选择模式，可选值：`'single'` | `'range'`，默认 `'single'`
- `placeholder` (String): 占位文本，默认 `'请选择日期'`
- `disabled` (Boolean): 是否禁用，默认 `false`
- `format` (String): 日期格式，默认 `'YYYY-MM-DD'`
- `separator` (String): 范围分隔符，默认 `' 至 '`
- `inline` (Boolean): 内联模式，直接显示选择器，不需要点击输入框，默认 `false`
- `singlePanel` (Boolean): 单面板模式，范围选择时只显示一个面板，默认 `false`
- `disableFuture` (Boolean): 禁用未来日期，大于当前日期的都置灰不可选，默认 `false`
- `onCancel` (Function): 自定义取消方法
- `onConfirm` (Function): 自定义确认方法
- `disableFuture` (Boolean): 是否禁用超出日期，默认 `false`

**Events:**
- `update:modelValue`: 值变化时触发
- `change`: 选择变化时触发
- `cancel`: 点击取消按钮时触发（未提供 onCancel 时）
- `confirm`: 点击确认按钮时触发（未提供 onConfirm 时）

**使用示例:**

```vue
<template>
  <!-- 基础使用：单选日期 -->
  <VtkDateSelector v-model="date" placeholder="选择日期" />

  <!-- 日期范围选择 -->
  <VtkDateSelector
    v-model="dateRange"
    mode="range"
    displayMode="day"
    placeholder="选择日期范围"
  />

  <!-- 月份范围选择 -->
  <VtkDateSelector
    v-model="monthRange"
    mode="range"
    displayMode="month"
    placeholder="选择月份范围"
  />

  <!-- 年份范围选择 -->
  <VtkDateSelector
    v-model="yearRange"
    mode="range"
    displayMode="year"
    placeholder="选择年份范围"
  />

  <!-- 周范围选择 -->
  <VtkDateSelector
    v-model="weekRange"
    mode="range"
    displayMode="week"
    placeholder="选择周范围"
  />

  <!-- 内联模式：直接显示选择器 -->
  <VtkDateSelector
    v-model="date"
    mode="range"
    displayMode="month"
    inline
  />

  <!-- 单面板模式：范围选择时只显示一个面板 -->
  <VtkDateSelector
    v-model="dateRange"
    mode="range"
    displayMode="day"
    singlePanel
  />

  <!-- 禁用未来日期：只能选择今天及之前的日期 -->
  <VtkDateSelector
    v-model="date"
    displayMode="month"
    :disableFuture="true"
    placeholder="选择月份（不能选未来）"
  />

  <!-- 自定义取消和确认方法 -->
  <VtkDateSelector
    v-model="date"
    :onCancel="handleCancel"
    :onConfirm="handleConfirm"
  />

  <!-- 监听事件 -->
  <VtkDateSelector
    v-model="date"
    @cancel="handleCancel"
    @confirm="handleConfirm"
    @change="handleChange"
  />
</template>

<script setup>
import { ref } from 'vue'

// 单选日期
const date = ref('2024-01-01')

// 日期范围
const dateRange = ref(['2024-01-01', '2024-01-31'])

// 月份范围
const monthRange = ref(['2024-01', '2024-12'])

// 年份范围
const yearRange = ref(['2023', '2024'])

// 周范围
const weekRange = ref(['2024-W01', '2024-W10'])

// 自定义处理方法
const handleCancel = () => {
  console.log('取消选择')
}

const handleConfirm = (value) => {
  console.log('确认选择:', value)
  // 执行自定义逻辑
}

const handleChange = (value) => {
  console.log('值变化:', value)
}
</script>
```

**特性说明:**

1. **多种显示模式**
   - `day`: 日期选择（显示日历）
   - `month`: 月份选择（显示月份网格）
   - `year`: 年份选择（显示年份网格）
   - `week`: 周选择（显示周列表）

2. **单选和范围选择**
   - `single`: 单选模式，返回单个值
   - `range`: 范围模式，返回数组 `[开始, 结束]`

3. **内联模式**
   - 设置 `inline="true"` 后，选择器直接显示，无需点击输入框
   - 选择后立即赋值，无需点击确认按钮
   - 适合嵌入表单或页面中

4. **单面板模式**
   - 设置 `singlePanel="true"` 后，范围选择时只显示一个面板
   - 通过导航按钮切换月份/年份
   - 适合空间受限的场景

5. **主题适配**
   - 自动适配 Vuetify 3 的亮色和暗色主题
   - 使用 Vuetify 主题变量，无需额外配置

6. **禁用未来日期**
   - 设置 `disableFuture="true"` 后，大于当前日期的所有日期、月份、年份都会置灰
   - 禁用的项目无法点击选择
   - 适用于生日选择、历史数据查询等场景

7. **自定义操作**
   - 可通过 `onCancel` 和 `onConfirm` props 自定义取消和确认逻辑
   - 或通过 `@cancel` 和 `@confirm` 事件监听

---

#### VtkImg - 图片组件

图片展示组件，支持预览和列表展示。

**Props:**
- `list` (Array): 图片列表，格式：`[{ url: '', title: '', description: '' }]`

**使用示例:**
```vue
<VtkImg :list="imageList" />
```

---

#### VtkPdf - PDF 查看器

PDF 文件查看组件。

**Props:**
- `list` (Array): PDF 列表，格式：`[{ url: '', title: '', description: '' }]`

**使用示例:**
```vue
<VtkPdf :list="pdfList" />
```

---

#### VtkUpload - 文件上传组件

文件上传组件，参考 Element Plus `el-upload` 设计，支持拖拽上传、多种列表展示模式、图片预览、PDF 新窗口预览、Excel Online 查看器等功能。

**Props:**

| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| `modelValue` | `Array` | `[]` | 文件列表（v-model 双向绑定） |
| `action` | `String` | `''` | 上传接口地址 |
| `accept` | `String` | `''` | 接受的文件类型，同原生 `accept` 属性，如 `image/*`、`.pdf,.xlsx` |
| `multiple` | `Boolean` | `false` | 是否允许多文件同时选择 |
| `limit` | `Number` | `0` | 最大可上传文件数量，`0` 表示不限制 |
| `maxSize` | `Number` | `0` | 单个文件最大体积（MB），`0` 表示不限制 |
| `listType` | `String` | `'text'` | 文件列表展示类型：`text` \| `picture` \| `picture-card` |
| `showFileList` | `Boolean` | `true` | 是否显示文件列表 |
| `autoUpload` | `Boolean` | `true` | 选择文件后是否自动上传 |
| `disabled` | `Boolean` | `false` | 是否禁用 |
| `headers` | `Object` | `{}` | 附加的请求头 |
| `data` | `Object` | `{}` | 上传时附加的表单数据 |
| `name` | `String` | `'file'` | 上传文件的字段名 |
| `tip` | `String` | `''` | 拖拽区底部的提示文字 |
| `beforeUpload` | `Function` | `null` | 上传前的钩子函数，接收 `(rawFile)` 参数，返回 `false` 或 rejected Promise 则停止上传 |
| `beforeRemove` | `Function` | `null` | 移除文件前的钩子函数，接收 `(file, fileList)` 参数，返回 `false` 则阻止移除 |

**Events:**

| 事件 | 参数 | 说明 |
|---|---|---|
| `update:modelValue` | `fileList` | 文件列表变化时触发（v-model） |
| `change` | `(file, fileList)` | 文件添加、上传成功/失败时触发 |
| `success` | `(response, file, fileList)` | 文件上传成功时触发 |
| `error` | `(error, file, fileList)` | 文件上传失败时触发 |
| `remove` | `(file, fileList)` | 文件被移除时触发 |
| `exceed` | `(files, fileList)` | 超出文件数量限制时触发 |
| `preview` | `(file)` | 点击文件预览时触发 |

**Methods（通过 ref 调用）:**

| 方法 | 说明 |
|---|---|
| `submit()` | 手动触发所有 `ready` 状态文件的上传（`autoUpload: false` 时使用） |
| `clearFiles()` | 清空文件列表 |
| `remove(file)` | 手动移除指定文件 |

**文件预览策略:**

| 文件类型 | 有服务端 URL | 仅本地（未上传） |
|---|---|---|
| 图片 | Dialog 内嵌预览 | Dialog 显示 base64 预览 |
| PDF | 新标签页直接打开 | 生成 Blob URL 新标签页打开 |
| xlsx / xls | Microsoft Office Online 查看器（需公网地址） | Dialog 提示无法预览 |
| 其他 | Dialog 内嵌展示 | Dialog 内嵌展示 |

> Office Online 查看器要求文件 URL 必须是**公网可访问的 https 地址**。

**Slots:**

| 插槽 | 说明 |
|---|---|
| `default` | 自定义拖拽区域内容（仅 `text` / `picture` 模式生效） |

**使用示例:**

```vue
<template>
  <!-- 1. 基础文本列表模式 -->
  <VtkUpload
    v-model="files"
    action="/api/upload"
    tip="支持 jpg / png / pdf，单个文件不超过 5MB"
  />

  <!-- 2. 图片缩略图列表模式 -->
  <VtkUpload
    v-model="files"
    action="/api/upload"
    list-type="picture"
    accept="image/*"
    :max-size="2"
  />

  <!-- 3. 图片卡片模式（最多 5 张） -->
  <VtkUpload
    v-model="files"
    action="/api/upload"
    list-type="picture-card"
    accept="image/*"
    :limit="5"
    :max-size="2"
    tip="只能上传 jpg/png，不超过 2MB"
  />

  <!-- 4. 手动上传 -->
  <VtkUpload
    ref="uploadRef"
    v-model="files"
    action="/api/upload"
    :auto-upload="false"
    @change="handleChange"
  />
  <VBtn @click="uploadRef.submit()">开始上传</VBtn>

  <!-- 5. 上传前校验 -->
  <VtkUpload
    v-model="files"
    action="/api/upload"
    :before-upload="beforeUpload"
    :before-remove="beforeRemove"
  />

  <!-- 6. 附加数据 / 自定义请求头 -->
  <VtkUpload
    v-model="files"
    action="/api/upload"
    :data="{ bizType: 'avatar' }"
    :headers="{ 'X-Custom': 'value' }"
  />
</template>

<script setup>
import { ref } from 'vue'

const files = ref([])
const uploadRef = ref(null)

// 上传前校验示例
const beforeUpload = (rawFile) => {
  if (rawFile.size / 1024 / 1024 > 5) {
    alert('文件大小不能超过 5MB')
    return false
  }
  return true
}

// 移除前确认示例
const beforeRemove = (file) => {
  return window.confirm(`确认移除 ${file.name}？`)
}

const handleChange = (file, fileList) => {
  console.log('文件变化:', file, fileList)
}
</script>
```

---

#### VtkEmpty - 空状态组件

空状态展示组件。

**Props:**
- `text` (String): 提示文本，默认 "暂无数据"

**使用示例:**
```vue
<VtkEmpty text="暂无内容" />
```

---

#### VtkFab - 浮动按钮

浮动操作按钮组件。

**使用示例:**
```vue
<VtkFab />
```

---

### 消息组件

#### vtkMessage - 全局消息

全局消息提示组件，需要在 App.vue 中添加 `<vtk-message />` 组件。

**方法:**

```javascript
// 在组件中使用
const { proxy } = getCurrentInstance()

// 成功提示
proxy.$vtk.message.success('操作成功')

// 错误提示
proxy.$vtk.message.error('操作失败')

// 警告提示
proxy.$vtk.message.warning('警告信息')

// 信息提示
proxy.$vtk.message.info('提示信息')

// Toast 提示
proxy.$vtk.message.toast('提示文本', { color: 'primary' })

// 确认对话框
proxy.$vtk.message.confirm({
  title: '提示',
  text: '确认删除吗？',
  onConfirm: () => {
    console.log('确认')
  },
  onCancel: () => {
    console.log('取消')
  }
})

// Alert 对话框
proxy.$vtk.message.alert({
  title: '提示',
  text: '操作成功',
  onConfirm: () => {
    console.log('确认')
  }
})

// Loading 加载
proxy.$vtk.message.loading.show()
proxy.$vtk.message.loading.hide()
```

---

## 公用方法

### 1. Storage - 本地存储

封装的本地存储工具，支持 localStorage 和 sessionStorage。

**使用方式:**

```javascript
import { getCurrentInstance } from 'vue'

const { proxy } = getCurrentInstance()

// 设置值
proxy.$vtk.storage.set('key', 'value')
proxy.$vtk.storage.set('key', { name: 'test' }) // 自动序列化对象

// 获取值
const value = proxy.$vtk.storage.get('key')

// 删除值
proxy.$vtk.storage.remove('key')

// 清空所有
proxy.$vtk.storage.clear()
```

**或者直接导入:**

```javascript
import { storage } from '@yxhl/specter-pui-vtk'

storage.set('key', 'value')
storage.get('key')
storage.remove('key')
storage.clear()
```

---

### 2. Request - HTTP 请求

封装的 Axios 请求工具，自动处理 token 和错误。

**使用方式:**

```javascript
const { proxy } = getCurrentInstance()

// GET 请求（表单格式）
proxy.$vtk.request.getForm('/api/user', { id: 1 })

// POST 请求（表单格式）
proxy.$vtk.request.postForm('/api/user', { name: 'test' })

// GET 请求（JSON 格式）
proxy.$vtk.request.getJson('/api/user', { id: 1 })

// POST 请求（JSON 格式）
proxy.$vtk.request.postJson('/api/user', { name: 'test' })

// 文件上传
proxy.$vtk.request.imp('/api/upload', formData)

// 文件下载
proxy.$vtk.request.exp('/api/download', { id: 1 })

// 自定义请求
proxy.$vtk.request.http(
  '/api/data',
  { key: 'value' },
  'POST',
  { 'content-type': 'application/json' },
  null
)
```

**或者直接导入:**

```javascript
import { request } from '@yxhl/specter-pui-vtk'

request.getForm('/api/user')
request.postJson('/api/user', { name: 'test' })
```

---

### 3. Filters - 过滤器方法

提供常用的数据格式化方法。

**字典过滤:**

```javascript
const { proxy } = getCurrentInstance()

// 字典转换
proxy.$vtk.filters.dict('1', 'status') // 根据字典类型转换值

// 分析类型
proxy.$vtk.filters.analyType('type_code')

// 分析级别
proxy.$vtk.filters.analyLevel('level_code')
```

**脱敏方法:**

```javascript
// 手机号脱敏
proxy.$vtk.filters.mobile('13812345678') // 138****5678

// 身份证脱敏
proxy.$vtk.filters.idcard('110101199001011234') // 110101********1234
```

**格式化方法:**

```javascript
// 日期格式化
proxy.$vtk.filters.date('2024-01-01', 'YYYY-MM-DD')

// 数字格式化
proxy.$vtk.filters.num(1234.56, 2) // 1,234.56

// 年龄计算
proxy.$vtk.filters.age('1990-01-01') // 34

// 文本截取
proxy.$vtk.filters.txt('很长的文本...', 10) // 很长的文本...

// 绝对值
proxy.$vtk.filters.abs(-123) // 123
```

---

### 4. Validation - 表单验证

提供常用的表单验证规则。

**使用方式:**

```javascript
const { proxy } = getCurrentInstance()

// 必填验证
const rules = [
  proxy.$vtk.Validation.required('用户名不能为空')
]

// 邮箱验证
const emailRules = [
  proxy.$vtk.Validation.email('请输入正确的邮箱')
]

// 手机号验证
const mobileRules = [
  proxy.$vtk.Validation.mobile('请输入正确的手机号')
]

// 自定义验证
const customRules = [
  (v) => !!v || '不能为空',
  (v) => v.length >= 6 || '至少6个字符'
]
```

---



## 配置选项

### 存储键名配置

组件库使用 localStorage 存储用户信息和 token，可以通过配置自定义键名。

**配置方式:**

```javascript
// main.js
window.VTK_CONFIG = {
  storageKeys: {
    user: import.meta.env.VITE_MIS_USERS || '_mis_acis_users',
    token: import.meta.env.VITE_MIS_TOKEN || '_mis_acis_token'
  }
}
```

**默认值:**
- `user`: `_mis_acis_users`
- `token`: `_mis_acis_token`

---

### API 基础地址配置

配置 HTTP 请求的基础地址。

**配置方式:**

```javascript
// main.js
window.VITE_APP_API_URL = import.meta.env.VITE_APP_API_URL
```

**或在 .env 文件中:**

```env
VITE_APP_API_URL=https://api.example.com
```

---

## 更新迭代

### 组件库维护者

#### 1. 修改组件

在 `pui-vtks/src/` 目录下修改组件代码。

#### 2. 构建组件库

```bash
cd pui-vtks
npm run build
```

#### 3. 更新版本号

```bash
# 补丁版本 (1.0.0 -> 1.0.1)
npm version patch

# 小版本 (1.0.0 -> 1.1.0)
npm version minor

# 大版本 (1.0.0 -> 2.0.0)
npm version major
```

#### 4. 发布到 npm

```bash
npm config set //registry.npmjs.org/:_authToken=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
npm publish --access public
```

---

### 项目使用者

#### 更新组件库

```bash
# 更新到最新版本
npm update @yxhl/specter-pui-vtk

# 或指定版本
npm install @yxhl/specter-pui-vtk@1.0.5

# 强制重新安装
rm -rf node_modules package-lock.json
npm install
```

#### 查看当前版本

```bash
npm list @yxhl/specter-pui-vtk
```

---

## 常见问题

### 1. 组件未定义

**问题:** 使用组件时提示组件未定义

**解决:**
- 确保在 main.js 中正确引入并注册了组件库
- 确保引入了 CSS 文件

```javascript
import SpecterPuiVtk from '@yxhl/specter-pui-vtk'
import '@yxhl/specter-pui-vtk/dist/specter-pui-vtk.css'

app.use(SpecterPuiVtk)
```

---

### 2. 消息组件不显示

**问题:** 调用 `proxy.$vtk.message` 方法后没有显示

**解决:**
- 确保在 App.vue 中添加了 `<vtk-message />` 组件

```vue
<template>
  <v-app>
    <router-view />
    <vtk-message />
  </v-app>
</template>
```

---

### 3. API 请求 baseURL 为 undefined

**问题:** HTTP 请求的 baseURL 是 undefined

**解决:**
- 在 main.js 中配置 API 地址

```javascript
window.VITE_APP_API_URL = import.meta.env.VITE_APP_API_URL
```

- 或在 .env 文件中配置

```env
VITE_APP_API_URL=https://api.example.com
```

---

### 4. 用户信息获取失败

**问题:** 组件无法获取用户信息

**解决:**
- 确保在 localStorage 中存储了用户信息
- 如果使用自定义键名，需要配置 `window.VTK_CONFIG`

```javascript
window.VTK_CONFIG = {
  storageKeys: {
    user: 'my_custom_user_key'
  }
}
```

---

### 5. 组件样式异常

**问题:** 组件样式显示不正常

**解决:**
- 确保引入了 CSS 文件
- 确保 Vuetify 已正确配置
- 检查是否有样式冲突

```javascript
import '@yxhl/specter-pui-vtk/dist/specter-pui-vtk.css'
```

---

## 版本历史

### v1.0.0
- 初始版本发布
- 包含基础组件和工具函数

---

## 许可证

MIT License

## 作者

yxhl <17363318852@139.com>

## 链接

- [npm 包](https://www.npmjs.com/package/@yxhl/specter-pui-vtk)
- [问题反馈](https://gitee.com/liangthink/specter-core-vue/issues)
