# 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 ``` ## 示例 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 ``` ## 📖 详细说明 ### 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 ``` ## 💡 使用技巧 ### 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 ``` ## ⚠️ 注意事项 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**:其他情况 - 使用 `` 渲染 ## 实际应用示例 ### 菜单配置表格 ```vue ``` ### 项目列表卡片 ```vue

{{ project.name }}

{{ project.description }}

``` ## 注意事项 1. **自动识别规则**: - 包含 `/uploadFile/` 的路径会自动获取本地图片流 - 例如:`/uploadFile/logo.png`、`path/uploadFile/icon.jpg` 等 2. **性能优化**: - 本地图片流获取会发起异步请求 - 建议结合虚拟滚动或分页使用大列表 - 组件会自动缓存已加载的图片 3. **图片路径格式**: - 本地流:必须包含 `/uploadFile/`,例如 `/uploadFile/abc.png` - 在线 URL:以 `http://` 或 `https://` 开头 - Symbol 图标:其他格式,例如 `menu_icon` 4. **加载状态**: - 组件内置加载动画,无需额外处理 - 加载失败时不会显示任何内容 5. **Symbol 图标前缀**: - 默认使用 `icon` 作为前缀 - 如果你的 Symbol 图标有其他前缀,请使用 `prefix` prop ## 样式定制 ```vue ``` ## TypeScript 支持 组件使用 TypeScript 编写,提供完整的类型支持: ```typescript interface Props { prefix?: string // Symbol 图标前缀 name: string // 图标名称或 URL(必填) useMask?: boolean // 是否使用颜色遮罩 } ``` ## 识别规则总结 | name 格式 | 识别为 | 渲染方式 | | ----------------------------- | ----------- | ----------------------------- | | `http://...` 或 `https://...` | 在线 URL | `` 或 `
` (mask) | | 包含 `/uploadFile/` | 本地图片流 | `` (通过 getImageStream) | | 其他 | Symbol 图标 | `` | # 数据格式转换 ### 输入格式(Router dynamicRoutes) ```typescript { path: "/device-manage", component: Layouts, name: "Device-Manage", meta: { title: "设备管理", groupTitle: "物联网平台", svgIcon: "menu_sbgl" }, children: [ { path: "product", component: () => import("@/views/device-manage/product/index.vue"), name: "Product", meta: { title: "产品", keepAlive: true, hidden: false } }, { path: "add-product", component: () => import("@/views/device-manage/product/add-product/index.vue"), name: "AddProduct", meta: { title: "创建产品", activeMenu: "/device-manage/product", hidden: true } } ] } ``` ### 输出格式(menuTemplateList) ```javascript ;[ { id: 1, menuTitle: "产品", menuName: "Product", menuPath: "product", menuComponent: "device-manage/product/index.vue", menuHidden: 0, menuActive: "", menuProps: "", sortId: 0, nameApp: "", pathApp: "/device-manage/product", menuApp: "" }, { id: 2, menuTitle: "创建产品", menuName: "AddProduct", menuPath: "add-product", menuComponent: "device-manage/product/add-product/index.vue", menuHidden: 1, menuActive: "/device-manage/product", menuProps: "", sortId: 0, nameApp: "", pathApp: "/device-manage/add-product", menuApp: "" } ] ```