# blt-re-zhongkong
**Repository Path**: zhejiang_blandu_smart_energy/blt-re-zhongkong
## Basic Information
- **Project Name**: blt-re-zhongkong
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-12
- **Last Updated**: 2026-04-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 🚀 开发
```bash
# 配置
1. 一键安装 .vscode 目录中推荐的插件
2. node 版本 18.x 或 20+
3. pnpm 版本 8.x 或最新版
# 安装依赖
pnpm i
# 初始化 Husky(首次安装后执行)
pnpm prepare
# 启动服务
pnpm dev
```
## ⚠️ 常见问题
### Husky / ESLint 在 Git 提交时不生效
如果首次安装依赖后,git commit 时没有触发代码检查和格式化,请按以下步骤排查:
```bash
# 1. 手动初始化 husky
pnpm prepare
# 2. 检查 .husky/pre-commit 文件是否存在且可执行
# Windows 用户需要确保文件以 LF(而不是 CRLF)作为行尾符
# 3. 测试 lint-staged 是否正常工作
npx lint-staged
# 4. 如果还不行,重新初始化 git hooks
rm -rf .git/hooks
pnpm prepare
```
## ✔️ 预览
```bash
# 预览预发布环境
pnpm preview:stage
# 预览正式环境
pnpm preview:prod
```
## 📦️ 多环境打包
```bash
# 构建预发布环境
pnpm build:stage
# 构建正式环境
pnpm build:prod
```
## 🔧 代码检查
```bash
# 代码格式化
pnpm lint
# 单元测试
pnpm test
```
## Git 提交规范参考
- `feat` 增加新的业务功能
- `fix` 修复业务问题/BUG
- `perf` 优化性能
- `style` 更改代码风格, 不影响运行结果
- `refactor` 重构代码
- `revert` 撤销更改
- `test` 测试相关, 不涉及业务代码的更改
- `docs` 文档和注释相关
- `chore` 更新依赖/修改脚手架配置等琐事
- `workflow` 工作流改进
- `ci` 持续集成相关
- `types` 类型定义文件更改
- `wip` 开发中
## 部分公共样式
普通蓝色背景颜色
el组件直接使用primary
```css
background:var(--el-color-primary); //背景色
color: var(--v3-primary-text-color); // 文字蓝
```
table
```js
import { useTable } from "@/composables/useTable"
// 初始化表格相关数据和方法
const { queryParams, loading, total, list, resetQuery, setFetchData, loadData } = useTable({
initParams: {
name: ""
}
})
const getList = async () => {}
// 注册数据加载函数
setFetchData(getList)
onMounted(() => {
loadData()
})
```
普通卡片统一样式
```css
.m-12-28-block {
margin: 0 28px 12px 12px;
background: var(--v3-body-main-bg-color);
border-radius: 8px;
}
```
普通详情头部
```html
```
普通搜索头部
```html
```
普通表格外框
```html
```
# CommonSearch 使用示例
## 示例 1: 基础单项搜索
最简单的单项搜索配置:
```vue
```
## 示例 2: 带接口数据的 Select
使用 `useFetchSelect` 动态获取选项:
```vue
```
## 示例 3: 日期范围搜索(多项模式)
使用多项模式实现日期范围搜索,支持展开/收起功能:
```vue
```
**多项模式特性:**
- 每个搜索条件独占一行,清晰展示
- 带序号标识(1、2、3...)
- 当有多个条件时,自动显示"展开/收起"按钮
- 收起状态下只显示第一个条件,便于节省空间
- 点击圆形 ➕ 按钮添加新条件
- 点击圆形 ➖ 按钮删除当前条件
## 示例 4: 带统计信息的搜索
使用插槽添加统计信息:
```vue
总设备
{{ statistics.total }}
在线
{{ statistics.online }}
离线
{{ statistics.offline }}
```
## 示例 5: 切换搜索模式
动态切换单项和多项模式:
```vue
```
## 示例 6: 与表格联动
完整的搜索+表格示例:
```vue
```
# useFetchSelect Hook 使用说明
一个灵活的 Hook,用于从接口获取数据并转换为 Select 组件需要的选项格式。
## 基础用法
### 场景 1: 标准格式接口
接口返回数据已经是标准的 `{ label, value }` 格式:
```javascript
// 接口返回:
{
code: 200,
data: [
{ label: "选项1", value: "1" },
{ label: "选项2", value: "2" }
]
}
```
```vue
```
### 场景 2: 非标准格式 - 简单映射
接口返回的数据字段名不是 `label` 和 `value`:
```javascript
// 接口返回:
{
code: 200,
data: [
{ name: "分类1", id: "1" },
{ name: "分类2", id: "2" }
]
}
```
```vue
```
### 场景 3: 嵌套数据路径
数据在深层嵌套的路径中:
```javascript
// 接口返回:
{
code: 200,
data: {
list: [
{ categoryName: "分类1", categoryId: "1" },
{ categoryName: "分类2", categoryId: "2" }
],
total: 100
}
}
```
```vue
```
### 场景 4: 更深层的嵌套
```javascript
// 接口返回:
{
code: 200,
data: {
data: [
{ categoryName: "分类1", categoryId: "1" },
{ categoryName: "分类2", categoryId: "2" }
]
}
}
```
```vue
```
### 场景 5: 带禁用状态
```javascript
// 接口返回:
{
code: 200,
data: [
{ name: "分类1", id: "1", isDisabled: false },
{ name: "分类2", id: "2", isDisabled: true }
]
}
```
```vue
```
### 场景 6: 自定义转换函数
对于复杂的数据格式,可以使用自定义转换函数:
```javascript
// 接口返回:
{
code: 200,
data: {
categories: [
{
info: { name: "分类1", code: "C001" },
status: 1
},
{
info: { name: "分类2", code: "C002" },
status: 0
}
]
}
}
```
```vue
```
### 场景 7: 手动刷新数据
```vue
刷新
```
### 场景 8: 延迟加载
不在组件挂载时自动加载数据:
```vue
```
## API 参数说明
| 参数 | 说明 | 类型 | 默认值 | 必填 |
| ------------- | ---------------------- | -------- | ------- | ---- |
| api | API 函数 | Function | - | 是 |
| params | API 参数 | Object | - | 否 |
| dataPath | 数据路径,支持点号分隔 | String | "data" | 否 |
| labelField | label 字段名 | String | "label" | 否 |
| valueField | value 字段名 | String | "value" | 否 |
| disabledField | disabled 字段名 | String | - | 否 |
| transform | 自定义转换函数 | Function | - | 否 |
| immediate | 是否立即加载 | Boolean | true | 否 |
## 返回值
| 属性 | 说明 | 类型 |
| -------- | ------------ | --------------------- |
| options | 选项数组 | Ref |
| loading | 加载状态 | Ref |
| value | 当前选中值 | Ref |
| loadData | 加载数据方法 | Function |
| refresh | 刷新数据方法 | Function |
## 常见问题
### Q1: 如何知道我的接口数据在哪个路径?
在浏览器控制台查看接口返回,然后用点号连接路径。例如:
- `res.data` → `dataPath: "data"`
- `res.data.list` → `dataPath: "data.list"`
- `res.data.data` → `dataPath: "data.data"`
### Q2: 我的接口返回数据很复杂,怎么办?
使用 `transform` 自定义转换函数,可以处理任何复杂的数据格式。
## 完整示例
```vue
提交
刷新选项
```
## 迁移指南
### 从旧版迁移到新版
**旧版写法:**
```javascript
const { options } = useFetchSelect(
{
api: getList,
params: { page: 1, limit: 1000 }
},
true,
"id",
"name"
)
```
**新版写法:**
```javascript
const { options } = useFetchSelect({
api: getList,
params: { page: 1, limit: 1000 },
dataPath: "data.data",
labelField: "name",
valueField: "id"
})
```
# 自定义表头 使用示例
一个功能强大的表格列自定义组件,支持列的显示/隐藏、拖拽排序、固定列等功能,配置自动保存到后端。
## ✨ 功能特性
- 🎯 **列选择** - 自由选择需要显示的列
- 🔄 **拖拽排序** - 支持拖拽调整列的显示顺序
- 📌 **固定列** - 部分列可设置为固定不可删除
- 💾 **配置保存** - 自动保存到后端,刷新页面后配置保持
- 🎨 **美观界面** - 现代化的 UI 设计,操作直观
## 📦 快速开始
### 第一步:在 useTable 中获取表头功能
```javascript
import { useTable } from "@/composables/useTable"
const {
// ... 其他功能
// 表头配置相关
availableColumns, // 当前显示的列(用于 el-table-column 渲染)
selectedProps, // 选中的列的 prop 数组
fixedProps, // 固定的列的 prop 数组
tableKey, // 表格 key(用于强制刷新)
setTableHeader, // 保存表头配置
getTableHeader, // 获取表头配置
initTableColumns // 初始化表格列
} = useTable({
/* ... */
})
```
### 第二步:定义默认配置
```javascript
// 定义默认表头配置
const defaultColumnConfig = {
columnOptions: [
{ label: "主体名称", prop: "name" },
{ label: "用户名称", prop: "customerName" },
{ label: "详细地址", prop: "address" },
{ label: "负责人数量", prop: "userNumber" },
{ label: "服务到期时间", prop: "expireTime" },
{ label: "创建时间", prop: "createTime", width: 160 }
],
// 默认显示的列
selectedProps: ["name", "customerName", "address", "userNumber", "expireTime", "createTime"],
// 固定不可删除的列
fixedProps: ["name", "customerName"]
}
```
### 第三步:使用组件
```vue
{{ row[item.prop] }}
操作
```
## 📖 详细说明
### columnOptions 配置项
每个列配置对象支持以下属性:
| 属性 | 说明 | 类型 | 必填 | 示例 |
| ------------- | ------------ | ------- | ---- | ---------------- |
| label | 列标题 | String | 是 | "用户名称" |
| prop | 列字段名 | String | 是 | "userName" |
| width | 列宽度 | Number | 否 | 160 |
| fixed | 固定列位置 | String | 否 | "left" / "right" |
| sortable | 是否可排序 | Boolean | 否 | true |
| needAutoWidth | 是否自动宽度 | Boolean | 否 | true |
```javascript
const columnOptions = [
{
label: "序号",
prop: "index",
fixed: "left",
needAutoWidth: false,
width: 50
},
{
label: "设备名称",
prop: "devName",
needAutoWidth: true,
width: 150
},
{
label: "总用量",
prop: "totalUsage",
width: 110,
sortable: true
}
]
```
### API 方法说明
#### getTableHeader(menu, tableId, config, columnSettingRef)
获取表头配置(首次加载时调用)
**参数:**
- `menu` (String) - 菜单标识,用于区分不同页面
- `tableId` (String) - 表格ID,用于区分同一页面的不同表格
- `config` (Object) - 默认配置对象
- `columnOptions` - 所有可选列配置
- `selectedProps` - 默认选中的列
- `fixedProps` - 固定的列
- `columnSettingRef` (Ref) - 列设置组件引用(可选)
**示例:**
```javascript
onMounted(() => {
getTableHeader("deviceManage", "deviceTable", defaultColumnConfig, columnSetting)
})
```
#### setTableHeader(newColumns, menu, tableId, tableRef, columnSettingRef)
保存表头配置(用户修改后调用)
**参数:**
- `newColumns` (Object) - 新的列配置(由 ColumnSetting 组件传出)
- `menu` (String) - 菜单标识
- `tableId` (String) - 表格ID
- `tableRef` (Ref) - 表格引用(可选,用于刷新布局)
- `columnSettingRef` (Ref) - 列设置组件引用(可选)
**示例:**
```javascript
const handleUpdate = (newColumns) => {
setTableHeader(newColumns, "deviceManage", "deviceTable", tableRef, columnSetting)
}
```
## 🎯 完整示例
```vue
新增
{{ row.status === 1 ? "启用" : "禁用" }}
{{ formatDate(row.createTime) }}
{{ row[item.prop] }}
操作
编辑
删除
```
## 💡 使用技巧
### 1. 同一页面多个表格
```javascript
// 表格1
getTableHeader("userManage", "mainTable", config1, columnSetting1)
// 表格2
getTableHeader("userManage", "subTable", config2, columnSetting2)
```
### 2. 动态更新可选列
```javascript
// 根据不同条件显示不同的列
const getColumnOptions = computed(() => {
if (userType.value === "admin") {
return [
{ label: "用户ID", prop: "userId" },
{ label: "权限", prop: "permission" } // 管理员专属
// ...
]
} else {
return [
{ label: "用户ID", prop: "userId" },
{ label: "姓名", prop: "name" }
// ...
]
}
})
```
### 3. 自定义列内容渲染
```vue
{{ getStatusText(row.status) }}
¥{{ row.amount.toFixed(2) }}
{{ row[item.prop] }}
```
## ⚠️ 注意事项
1. **菜单标识和表格ID** - `menu` 和 `tableId` 的组合必须唯一,用于区分不同表格的配置
2. **固定列限制** - `fixedProps` 中指定的列无法在列设置中删除
3. **表格刷新** - 修改配置后会自动刷新表格布局,无需手动处理
4. **配置持久化** - 配置会自动保存到后端,刷新页面后仍然保持
5. **列宽度** - 如果设置了 `width`,列将使用固定宽度;否则使用默认宽度
## 🐛 常见问题
### Q1: 列设置弹窗不显示?
确保正确初始化了列数据:
```javascript
const showColumnSetting = () => {
columnSetting.value?.initColumnData() // 先初始化
columnSetting.value?.show() // 再显示
}
```
### Q2: 配置保存后表格不更新?
确保传递了 `tableRef` 参数:
```javascript
setTableHeader(newColumns, "menu", "tableId", tableRef, columnSetting)
```
### Q3: 如何重置到默认配置?
在列设置弹窗中点击"重置"按钮,或者清空后端保存的配置。
### Q4: 列顺序如何保存?
列的顺序通过 `availableColumns` 自动保存,支持拖拽调整顺序。
# UploadImg 图片上传组件
一个基于 Element Plus Upload 组件封装的图片上传公共组件。
## 功能特性
- ✅ 支持图片预览
- ✅ 支持上传数量限制
- ✅ 支持自定义提示文本
- ✅ 自动处理上传成功/失败状态
- ✅ 达到限制数量后自动隐藏上传按钮
- ✅ 完整的事件回调机制
## 基础使用
```vue
```
## 完整示例(参考 configuration/add.vue)
```vue
系统图片
本地图片
```
## Props
| 参数 | 说明 | 类型 | 默认值 | 必填 |
| ------------ | ------------ | ------ | ------------------------------- | ---- |
| uploadApiUrl | 上传接口地址 | String | - | 是 |
| fileList | 文件列表 | Array | [] | 否 |
| limit | 最大上传数量 | Number | 1 | 否 |
| tip | 提示文本 | String | "建议上传60\*60px大小的png图片" | 否 |
| uploadText | 上传按钮文本 | String | "点击上传" | 否 |
## Events
| 事件名 | 说明 | 回调参数 |
| ------- | -------------- | --------------------------------------------- |
| success | 上传成功时触发 | { url: string, file: File, response: Object } |
| error | 上传失败时触发 | error: Error \| Object |
| remove | 删除文件时触发 | uploadFile: Object |
## 注意事项
1. **fileList 的管理**:组件本身不维护 fileList 状态,需要父组件通过 @success 和 @remove 事件来维护
2. **上传接口格式**:组件期望上传接口返回格式为:
```json
{
"status": 200,
"data": {
"link": "图片链接地址"
},
"msg": "上传成功"
}
```
3. **表单验证**:如果需要清除表单验证,可以在 success 回调中手动调用:
```javascript
formRef.value?.clearValidate("fieldName")
```
4. **编辑时回显图片**:需要构造符合 Element Plus Upload 组件的 fileList 格式:
```javascript
// 如果有已上传的图片URL
if (form.groupIcon) {
imageFile.value = [
{
name: "image",
url: form.groupIcon
}
]
}
```
## 样式定制
组件已包含基础样式,如需定制可以通过以下方式:
```vue
```
# SvgIcon 图标组件
一个支持多种图标类型的 Vue3 图标组件,支持本地 Symbol、在线 URL、以及自动识别本地图片流的场景。
## 功能特性
- ✅ 支持本地 Symbol 图标(iconfont)
- ✅ 支持在线 URL 图片
- ✅ 支持颜色遮罩(mask)方式渲染
- ✅ **自动识别并获取本地图片流**(包含 `/uploadFile/` 的路径)
- ✅ 自动处理加载状态
- ✅ 响应式更新
## 使用场景
### 1. 本地 Symbol 图标(默认)
适用于 iconfont 等 SVG symbol 图标。
```vue
```
### 2. 在线 URL 图片
适用于 CDN 或完整 URL 路径的图片。
```vue
```
### 3. 本地图片流(自动识别)⭐
组件会**自动识别**包含 `/uploadFile/` 的路径,并通过 `getImageStream` 获取本地存储的图片。
```vue
```
## Props
| 参数 | 说明 | 类型 | 默认值 | 必填 |
| ------- | ---------------------------------- | ------- | ------ | ---- |
| prefix | Symbol 图标前缀 | String | "icon" | 否 |
| name | 图标名称或 URL | String | - | 是 |
| useMask | 是否使用颜色遮罩(适用于单色 SVG) | Boolean | false | 否 |
## 自动判断逻辑
组件会按以下优先级自动判断图标类型:
1. **在线 URL + Mask**:`name` 以 `http://` 或 `https://` 开头,且 `useMask = true`
- 使用 `` + CSS mask 渲染,支持颜色修改
2. **在线 URL**:`name` 以 `http://` 或 `https://` 开头
- 使用 `
![]()
` 标签渲染,性能更好
3. **本地图片流**:`name` 包含 `/uploadFile/` ⭐
- 自动调用 `getImageStream` 获取图片 URL
- 显示加载动画
- 使用 `
![]()
` 标签渲染
4. **本地 Symbol**:其他情况
- 使用 `