| New file |
| | |
| | | --- |
| | | description: cl-adv-search 组件示例 |
| | | globs: *.tsx, *.ts, *.vue |
| | | --- |
| | | ## 起步 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>base</el-tag> |
| | | <span>起步</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['adv-search/base.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="起步" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!--【很重要】高级搜索组件按钮 --> |
| | | <cl-adv-btn /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!--【很重要】高级搜索组件 --> |
| | | <cl-adv-search ref="AdvSearch" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useAdvSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-adv-search 配置 |
| | | //【很重要】该组件基于 cl-form 故很多示例都可复用 |
| | | const AdvSearch = useAdvSearch({ |
| | | // 配置如 cl-form 一样 |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 自定义 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>custom</el-tag> |
| | | <span>自定义</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['adv-search/custom.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="自定义" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!--【很重要】高级搜索组件按钮 --> |
| | | <cl-adv-btn>更多搜索</cl-adv-btn> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!--【很重要】高级搜索组件 --> |
| | | <cl-adv-search ref="AdvSearch"> |
| | | <!-- 自定义按钮 --> |
| | | <template #slot-btn> |
| | | <el-button @click="toSearch">自定义</el-button> |
| | | </template> |
| | | </cl-adv-search> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useAdvSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-adv-search 配置 |
| | | //【很重要】该组件基于 cl-form 故很多示例都可复用 |
| | | const AdvSearch = useAdvSearch({ |
| | | // 配置如 cl-form 一样 |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | |
| | | title: '更多搜索', |
| | | size: '50%', |
| | | op: ['close', 'search', 'slot-btn'] |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | // 自定义搜索 |
| | | function toSearch() { |
| | | refresh({ page: 1 }); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| New file |
| | |
| | | --- |
| | | description: cl-crud 组件示例 |
| | | globs: *.tsx, *.ts, *.vue |
| | | --- |
| | | ## 完整示例 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>all</el-tag> |
| | | <span>完整示例</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/all.vue']" /> |
| | | |
| | | <cl-dialog v-model="visible" title="完整示例" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!-- 刷新按钮 --> |
| | | <cl-refresh-btn /> |
| | | |
| | | <!-- 新增按钮 --> |
| | | <cl-add-btn /> |
| | | |
| | | <!-- 批量删除按钮 --> |
| | | <cl-multi-delete-btn /> |
| | | |
| | | <!-- 筛选 --> |
| | | <cl-filter label="状态筛选"> |
| | | <!-- 配置prop,选择后会自动过滤列表 --> |
| | | <cl-select :options="options.status" prop="status" :width="120" /> |
| | | </cl-filter> |
| | | |
| | | <!-- 字典 --> |
| | | <cl-filter label="工作(字典)"> |
| | | <cl-select |
| | | tree |
| | | :options="dict.get('occupation')" |
| | | prop="occupation" |
| | | :width="140" |
| | | check-strictly |
| | | /> |
| | | </cl-filter> |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | <!-- 导入 --> |
| | | <cl-import-btn template="/用户导入模版.xlsx" /> |
| | | |
| | | <!-- 导出 --> |
| | | <cl-export-btn :columns="Table?.columns" /> |
| | | |
| | | <!-- 自定义列 --> |
| | | <cl-column-custom |
| | | :ref="setRefs('columnCustom')" |
| | | :columns="Table?.columns" |
| | | /> |
| | | |
| | | <!-- 关键字搜索 --> |
| | | <cl-search-key placeholder="搜索姓名、手机号" :width="250" /> |
| | | |
| | | <!-- 高级搜索按钮 --> |
| | | <cl-adv-btn /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <!-- 表格 --> |
| | | <cl-table |
| | | ref="Table" |
| | | show-summary |
| | | :summary-method="onSummaryMethod" |
| | | :auto-height="false" |
| | | > |
| | | <!-- 展开信息 --> |
| | | <template #column-detail="{ scope }"> |
| | | <div style="padding: 0 10px"> |
| | | <el-descriptions border :column="3"> |
| | | <el-descriptions-item label="ID"> |
| | | {{ scope.row.id }} |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="姓名"> |
| | | {{ scope.row.name }} |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="存款"> |
| | | {{ scope.row.wages }} |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="出生年月"> |
| | | {{ scope.row.createTime }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 自定义列 --> |
| | | <template #column-wages="{ scope }"> |
| | | <span>{{ scope.row.wages }}🤑</span> |
| | | </template> |
| | | </cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | |
| | | <!-- 分页 --> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | |
| | | <!-- 高级搜索 --> |
| | | <cl-adv-search ref="AdvSearch" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="tsx" setup> |
| | | defineOptions({ |
| | | name: 'demo-crud' |
| | | }); |
| | | |
| | | import { useCrud, useUpsert, useTable, useAdvSearch, useSearch } from '@cool-vue/crud'; |
| | | import { useDict } from '/$/dict'; |
| | | import { reactive, ref } from 'vue'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { useCool } from '/@/cool'; |
| | | |
| | | // 基础 |
| | | const { service, refs, setRefs } = useCool(); |
| | | |
| | | // 字典 |
| | | const { dict } = useDict(); |
| | | |
| | | // 选项,统一命名options,存放所有的下拉等其他选项列表数据 |
| | | const options = reactive({ |
| | | status: [ |
| | | { |
| | | label: '启用', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '禁用', |
| | | type: 'danger', |
| | | value: 0 |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // 合计数据 |
| | | const subData = reactive({ |
| | | wages: 0 |
| | | }); |
| | | |
| | | // crud |
| | | const Crud = useCrud( |
| | | { |
| | | // 绑定的服务,如:service.demo.goods、service.base.sys.user |
| | | service: 'test', |
| | | |
| | | // 刷新事件 |
| | | async onRefresh(params, { next }) { |
| | | const res = await next(params); |
| | | Object.assign(subData, res.subData); |
| | | } |
| | | }, |
| | | app => { |
| | | // Crud 加载完,默认刷新一次 |
| | | app.refresh({ |
| | | size: 10 |
| | | // status: 1 // 带额外参数的请求 |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | // 刷新列表,统一调用这个方法去刷新 |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | // 新增、编辑 |
| | | // 插入类型 <Eps.UserInfoEntity>,prop 和 data 会有提示 |
| | | const Upsert = useUpsert<Eps.UserInfoEntity>({ |
| | | items: [ |
| | | // 分组 |
| | | { |
| | | type: 'tabs', |
| | | props: { |
| | | type: 'card', |
| | | labels: [ |
| | | { |
| | | label: '基础信息', |
| | | value: 'base' |
| | | }, |
| | | { |
| | | label: '其他配置', |
| | | value: 'other' |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '头像', |
| | | prop: 'avatarUrl', |
| | | group: 'base', |
| | | component: { |
| | | name: 'cl-upload' |
| | | } |
| | | }, |
| | | { |
| | | label: '账号', |
| | | group: 'base', |
| | | prop: 'account', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | // 动态配置,新增显示、编辑隐藏 |
| | | () => { |
| | | return () => { |
| | | return { |
| | | label: '密码', |
| | | group: 'base', |
| | | prop: 'password', |
| | | hidden: Upsert.value?.mode == 'update', // 通过 mode 参数判断 |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | type: 'password' |
| | | } |
| | | } |
| | | }; |
| | | }; |
| | | }, |
| | | { |
| | | group: 'base', |
| | | prop: 'user', |
| | | component: { |
| | | name: 'cl-form-card', |
| | | props: { |
| | | label: '用户信息(多层级展示)' |
| | | } |
| | | }, |
| | | children: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | required: true, |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '存款', |
| | | prop: 'wages', |
| | | component: { |
| | | name: 'el-input-number' |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | group: 'base', |
| | | prop: 'contact', |
| | | component: { |
| | | name: 'cl-form-card', |
| | | props: { |
| | | label: '联系信息', |
| | | expand: false |
| | | } |
| | | }, |
| | | children: [ |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '省市区', |
| | | prop: 'pca', |
| | | group: 'base', |
| | | component: { |
| | | name: 'cl-distpicker' |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | group: 'other', |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'el-tree-select', |
| | | props: { |
| | | data: dict.get('occupation'), |
| | | checkStrictly: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | group: 'other', |
| | | label: '身份证照片', |
| | | prop: 'idCardPic', |
| | | component: { |
| | | name: 'cl-upload', |
| | | props: { |
| | | isSpace: true, |
| | | size: [200, 300] |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | |
| | | // 详情钩子 |
| | | onInfo(data, { next, done }) { |
| | | // 继续请求 info 接口,可以带其他自定义参数 |
| | | // next({ |
| | | // id: data.id, |
| | | // status: 1 |
| | | // }); |
| | | |
| | | // 使用其他接口 |
| | | // service.demo.goods.info({ id: data.id }).then((res) => { |
| | | // done(res); |
| | | // }); |
| | | |
| | | // 直接取列表的数据返回 |
| | | done(data); |
| | | }, |
| | | |
| | | // 提交钩子 |
| | | onSubmit(data, { next, close, done }) { |
| | | console.log('onSubmit', data); |
| | | // 继续请求 update/add 接口 |
| | | next(data); |
| | | |
| | | // 自定义接口 |
| | | // service.demo.goods |
| | | // .update(data) |
| | | // .then(() => { |
| | | // ElMessage.success("保存成功"); |
| | | |
| | | // // 操作完,刷新列表 |
| | | // refresh(); |
| | | |
| | | // // 关闭窗口 |
| | | // close(); |
| | | // }) |
| | | // .catch((err) => { |
| | | // ElMessage.error(err.message); |
| | | |
| | | // // 关闭加载状态 |
| | | // done(); |
| | | // }); |
| | | }, |
| | | |
| | | // 打开后,数据加载完,onInfo 之后 |
| | | onOpened(data) { |
| | | if (Upsert.value?.mode != 'info') { |
| | | ElMessage.info('编辑中'); |
| | | } |
| | | }, |
| | | |
| | | // 关闭钩子 |
| | | onClose(action, done) { |
| | | if (Upsert.value?.mode == 'update') { |
| | | if (action == 'close') { |
| | | return ElMessageBox.confirm('还没填完,确定关闭不?', '提示', { |
| | | type: 'warning' |
| | | }) |
| | | .then(() => { |
| | | done(); |
| | | ElMessage.info('好吧'); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.success('请继续编辑'); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | done(); |
| | | } |
| | | }); |
| | | |
| | | // 表格 |
| | | const Table = useTable({ |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60 |
| | | }, |
| | | // 展开列 |
| | | { |
| | | label: '展开', |
| | | type: 'expand', |
| | | prop: 'detail', |
| | | width: 60 |
| | | }, |
| | | { |
| | | label: '头像', |
| | | prop: 'avatar', |
| | | width: 100, |
| | | component: { |
| | | name: 'cl-image', |
| | | props: { |
| | | size: 40 |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 120 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140, |
| | | |
| | | // 带搜索组件 |
| | | search: { |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | placeholder: '搜索手机号' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '账号', |
| | | prop: 'account', |
| | | minWidth: 150 |
| | | }, |
| | | { |
| | | label: '存款(元)', |
| | | prop: 'wages', |
| | | minWidth: 150, |
| | | sortable: 'desc' // 默认倒序 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | dictColor: true, |
| | | minWidth: 150, |
| | | dictAllLevels: true, // 显示所有等级 |
| | | |
| | | // 带搜索组件 |
| | | search: { |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | orderNum: 2, |
| | | prop: 'status', |
| | | minWidth: 100, |
| | | component: { |
| | | name: 'cl-switch' |
| | | } |
| | | }, |
| | | { |
| | | label: '出生年月', |
| | | orderNum: 1, |
| | | minWidth: 165, |
| | | prop: 'createTime', |
| | | sortable: 'custom', |
| | | search: { |
| | | component: { |
| | | name: 'cl-date-picker', |
| | | props: { |
| | | type: 'date', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | placeholder: '搜索日期' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | type: 'op', |
| | | width: 340, |
| | | // 静态配置按钮 |
| | | // buttons: ["info", "edit", "delete"], |
| | | // 动态配置按钮 |
| | | buttons({ scope }) { |
| | | return [ |
| | | 'info', |
| | | 'edit', |
| | | 'delete', |
| | | { |
| | | label: '自定义', |
| | | onClick() { |
| | | ElMessage.info(`他是:${scope.row.name}`); |
| | | } |
| | | } |
| | | ]; |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // 合计 |
| | | function onSummaryMethod() { |
| | | // 添加自定义列组件后 |
| | | return ['合计', '', ...refs.columnCustom.summary(subData)]; |
| | | } |
| | | |
| | | // 高级搜索 |
| | | const AdvSearch = useAdvSearch({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | hook: { |
| | | bind: 'string' |
| | | }, |
| | | component: { |
| | | name: 'el-select', |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // 搜索 |
| | | const Search = useSearch({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 起步 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>base</el-tag> |
| | | <span>起步</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/base.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="起步" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-refresh-btn /> |
| | | <cl-add-btn /> |
| | | <cl-multi-delete-btn /> |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | <cl-search-key /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { useCool } from '/@/cool'; |
| | | |
| | | const { service } = useCool(); |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | // test 为测试数据模式,详细说明移步到 service 例子 |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | //【很重要】首次请求,数据一并添加到请求参数中 |
| | | app.refresh({ |
| | | size: 10, |
| | | status: 1 |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | buttons: ['edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 修改文案 / 接口 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>dict</el-tag> |
| | | <span>修改文案 / 接口</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/dict.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="修改文案 / 接口" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-refresh-btn /> |
| | | <cl-add-btn /> |
| | | <cl-multi-delete-btn /> |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | <cl-search-key /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | //【很重要】配置 service,如:service.base.sys.user |
| | | service: 'test', |
| | | |
| | | //【很重要】字典配置,文案和请求方法等 |
| | | dict: { |
| | | // 修改请求 |
| | | // 比如说默认列表请求的是 page 接口,可以修改成 getUserList 等等,这取决于后端有没有这个接口。 |
| | | api: { |
| | | list: 'list', |
| | | add: 'add', |
| | | update: 'update', |
| | | delete: 'delete', |
| | | info: 'info', |
| | | page: 'page' |
| | | }, |
| | | |
| | | // 修改文案 |
| | | label: { |
| | | op: '操作', |
| | | add: '添加', |
| | | delete: '移除', |
| | | multiDelete: '批量移除', |
| | | update: '修改', |
| | | refresh: '刷新', |
| | | info: '详情' |
| | | } |
| | | } |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | buttons: ['edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 事件监听 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>event</el-tag> |
| | | <span>事件监听</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/event.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="事件监听" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-refresh-btn /> |
| | | <cl-add-btn /> |
| | | <cl-multi-delete-btn /> |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | <cl-search-key /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table"> |
| | | <!-- 自定义按钮 --> |
| | | <template #slot-btn="{ scope }"> |
| | | <el-button @click="onEvent(scope.row)">自定义事件</el-button> |
| | | </template> |
| | | </cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { useCool } from '/@/cool'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const { service } = useCool(); |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | // 配置 service |
| | | service: 'test', |
| | | |
| | | //【很重要】监听刷新事件,每次调用 Crud.value.refresh() 会触发 |
| | | onRefresh(params, { next }) { |
| | | // 默认使用 next(params),也可以自己对数据进行处理 |
| | | next({ |
| | | ...params, |
| | | status: 1 |
| | | }); |
| | | }, |
| | | |
| | | // 监听删除事件,点击删除按钮触发 |
| | | onDelete(selection, { next }) { |
| | | // 传入 ids,批量删除多个数据 |
| | | next({ |
| | | ids: selection.map(e => e.id) |
| | | }); |
| | | } |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | width: 300, |
| | | buttons: ['edit', 'delete', 'slot-btn'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // 调用 Crud 方法 |
| | | function onEvent(row: any) { |
| | | ElMessage.info('自定义打开新增'); |
| | | |
| | | // 打开新增表单 |
| | | Crud.value?.rowAdd(); |
| | | |
| | | // 打开编辑表单 |
| | | // Crud.value?.rowEdit(row); |
| | | |
| | | // 打开删除提示框 |
| | | // Crud.value?.rowDelete(row); |
| | | |
| | | // 获取已请求的参数 |
| | | // Crud.value?.getParams(); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 选择表格 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>select-table</el-tag> |
| | | <span>选择表格</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/select-table.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-form ref="Form" /> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2025-02-07</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { useCool } from '/@/cool'; |
| | | import UserSelect from '/$/user/components/user-select.vue'; |
| | | |
| | | const { service } = useCool(); |
| | | const Form = useForm(); |
| | | |
| | | const columns = [ |
| | | { |
| | | label: '头像', |
| | | prop: 'headImg', |
| | | component: { |
| | | name: 'cl-avatar' |
| | | } |
| | | }, |
| | | { |
| | | label: '昵称', |
| | | prop: 'nickName' |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime' |
| | | } |
| | | ]; |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | width: '800px', |
| | | title: '选择表格', |
| | | items: [ |
| | | { |
| | | label: '多选 - default', |
| | | prop: 'a', |
| | | value: [], |
| | | component: { |
| | | vm: UserSelect, |
| | | props: { |
| | | multiple: true |
| | | } |
| | | }, |
| | | span: 12 |
| | | }, |
| | | { |
| | | label: '单选 - default', |
| | | prop: 'b', |
| | | component: { |
| | | name: 'cl-select-table', |
| | | props: { |
| | | pickerType: 'default', |
| | | multiple: false, |
| | | columns, |
| | | service: service.base.sys.user |
| | | } |
| | | }, |
| | | span: 12 |
| | | }, |
| | | { |
| | | label: '多选 - text', |
| | | prop: 'c', |
| | | value: [], |
| | | component: { |
| | | name: 'cl-select-table', |
| | | props: { |
| | | pickerType: 'text', |
| | | multiple: true, |
| | | columns, |
| | | service: service.base.sys.user |
| | | } |
| | | }, |
| | | span: 12 |
| | | }, |
| | | { |
| | | label: '单选 - text', |
| | | prop: 'd', |
| | | component: { |
| | | name: 'cl-select-table', |
| | | props: { |
| | | pickerType: 'text', |
| | | multiple: false, |
| | | columns, |
| | | service: service.base.sys.user |
| | | } |
| | | }, |
| | | span: 12 |
| | | }, |
| | | { |
| | | label: '多选 - table', |
| | | prop: 'e', |
| | | value: [], |
| | | component: { |
| | | name: 'cl-select-table', |
| | | props: { |
| | | pickerType: 'table', |
| | | multiple: true, |
| | | columns, |
| | | service: service.base.sys.user |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## Service 配置 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>service</el-tag> |
| | | <span>Service 配置</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/service.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="Service 配置" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-refresh-btn /> |
| | | <cl-add-btn /> |
| | | <cl-multi-delete-btn /> |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | <cl-search-key /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useCool } from '/@/cool'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | //【很重要】service 是所有请求的集合,是一个对象(刷新页面和保存代码会自动读取后端的所有接口) |
| | | const { service, route } = useCool(); |
| | | console.log('service', service); |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | //【很重要】配置 service,如:service.base.sys.user |
| | | // 不需要到具体的方法,如:service.base.sys.user.page,这是错误的! |
| | | |
| | | // 实际用法 |
| | | // service: service.base.sys.user, |
| | | |
| | | // 测试示例 |
| | | service: 'test' |
| | | |
| | | // 自定义配置1,添加本地 service 文件。 |
| | | // 【很重要】参考 /src/modules/demo/service/test.ts |
| | | // 【很重要】必须放在目录 modules/*/service/ 下,才会自动注入到 service 中 |
| | | // service: service.test |
| | | |
| | | // 自定义配置2,针对一些特殊场景 |
| | | // service: { |
| | | // page(params: any) { |
| | | // // params 请求参数 |
| | | // //【很重要】必须返回一个 Promise 格式 |
| | | // return Promise.resolve({ |
| | | // list: [], |
| | | // pagination: { |
| | | // total: 1, |
| | | // page: 1, |
| | | // size: 20 |
| | | // } |
| | | // }); |
| | | // } |
| | | |
| | | // // add、delete、update、info、list 也是如此配置 |
| | | // } |
| | | }, |
| | | app => { |
| | | // 首次调用刷新接口。在弹窗的情况下可以注释,用 Crud.value?.refresh() 方式手动调用 |
| | | app.refresh(); |
| | | |
| | | // 带参数 |
| | | // app.refresh({ |
| | | // userId: route.query.id |
| | | // }); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | buttons: ['edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 选择成员 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>user-select</el-tag> |
| | | <span>选择成员</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['crud/user-select.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-form ref="Form" /> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2025-02-07</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '选择成员', |
| | | items: [ |
| | | { |
| | | label: '单选', |
| | | prop: 'userId', |
| | | component: { |
| | | name: 'cl-user-select', |
| | | props: { |
| | | multiple: false, |
| | | onChange(val) { |
| | | console.log(val); |
| | | } |
| | | } |
| | | }, |
| | | required: true |
| | | }, |
| | | { |
| | | label: '多选', |
| | | prop: 'userIds', |
| | | component: { |
| | | name: 'cl-user-select', |
| | | props: { |
| | | multiple: true, |
| | | onChange(val) { |
| | | console.log(val); |
| | | } |
| | | } |
| | | }, |
| | | required: true |
| | | } |
| | | ] |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| New file |
| | |
| | | --- |
| | | description: cl-form 组件示例 |
| | | globs: *.tsx, *.ts, *.vue |
| | | --- |
| | | ## 层级显示 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>children</el-tag> |
| | | <span>层级显示</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/children.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '层级显示', |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '年龄', |
| | | prop: 'age', |
| | | value: 18, |
| | | component: { |
| | | name: 'el-input-number' |
| | | } |
| | | }, |
| | | |
| | | // 基础信息 |
| | | { |
| | | component: { |
| | | //【很重要】使用 cl-form-card 组件渲染,也可以使用自定义 |
| | | name: 'cl-form-card', |
| | | props: { |
| | | // 标题 |
| | | label: '基础信息', |
| | | // 是否展开,默认 true |
| | | expand: true |
| | | } |
| | | }, |
| | | children: [ |
| | | { |
| | | label: '账号', |
| | | prop: 'account', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '密码', |
| | | prop: 'password', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | |
| | | // 其他信息 |
| | | { |
| | | component: { |
| | | name: 'cl-form-card', |
| | | props: { |
| | | label: '其他信息', |
| | | expand: false |
| | | } |
| | | }, |
| | | children: [ |
| | | { |
| | | label: '身份证', |
| | | prop: 'idcard', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '学校', |
| | | prop: 'school', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '专业', |
| | | prop: 'major', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 组件渲染 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>component</el-tag> |
| | | <span>组件渲染</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code |
| | | :files="[ |
| | | 'form/component/index.vue', |
| | | 'form/component/select-labels.vue', |
| | | 'form/component/select-status.vue', |
| | | 'form/component/select-work.vue', |
| | | 'form/component/select-work2.vue' |
| | | ]" |
| | | /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"> |
| | | <!-- 年龄插槽 --> |
| | | <template #slot-age="{ scope }"> |
| | | <!-- scope 为表单值 --> |
| | | <el-input-number v-model="scope.age" :min="18" :max="100"></el-input-number> |
| | | </template> |
| | | </cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import SelectWork from './select-work2.vue'; |
| | | import SelectLabels from './select-labels.vue'; |
| | | import SelectStatus from './select-status.vue'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '组件配置', |
| | | |
| | | items: [ |
| | | { |
| | | label: '昵称', |
| | | prop: 'name', |
| | | // 组件配置方式1:标签名(方便,但是不建议组件全局注册) |
| | | value: '神仙', |
| | | component: { |
| | | // 必须是“全局注册”的组件名,如 element-plus 的 el-input、el-date-picker 等 |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | value: '13255022000', |
| | | component: { |
| | | name: 'el-input', |
| | | // 自定义插槽 |
| | | slots: { |
| | | prepend() { |
| | | return '+86'; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '年龄', |
| | | prop: 'age', |
| | | // 组件配置方式2:插槽(万能,就是代码多写点) |
| | | value: 18, |
| | | component: { |
| | | // 必须是 "slot-" 开头 |
| | | name: 'slot-age' |
| | | } |
| | | }, |
| | | // -- start 组件配置方式3:组件实例(不想全局注册,但又想组件化) |
| | | { |
| | | label: '工作', |
| | | prop: 'work', |
| | | value: '设计', |
| | | component: { |
| | | // 双向绑定 |
| | | vm: SelectWork |
| | | } |
| | | }, |
| | | { |
| | | label: '标签', |
| | | prop: 'labels', |
| | | value: ['多金', '深情'], |
| | | component: { |
| | | // scope[prop]绑定 |
| | | vm: SelectLabels |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | prop: 'status', |
| | | value: 1, |
| | | component: { |
| | | // useForm 绑定 |
| | | vm: SelectStatus |
| | | } |
| | | } |
| | | // -- end |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | ElMessage.info( |
| | | `${data.name || '无名'}(${data.age || 18}岁)工作:${data.work || '无'}` |
| | | ); |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## select-labels 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <!--【很重要】直接绑定表单值 scope[prop] --> |
| | | <!-- !符号,只是为了类型提示不错误 --> |
| | | <el-select v-model="scope[prop!]" multiple> |
| | | <el-option |
| | | v-for="(item, index) in list" |
| | | :key="index" |
| | | :label="item.label" |
| | | :value="item.label" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | |
| | | <!--【很重要】必须要有name,避免注册后和其他冲突 --> |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'select-labels' |
| | | }); |
| | | |
| | | import { ref } from 'vue'; |
| | | |
| | | const props = defineProps({ |
| | | scope: null, // 表单值 |
| | | prop: String // 表单项配置的 prop |
| | | }); |
| | | |
| | | // 选项列表 |
| | | const list = ref<{ label: string; value: string }[]>([ |
| | | { |
| | | label: '帅气', |
| | | value: '帅气' // 测试直接使用label,真实情况可能是1,2,3,4或者id |
| | | }, |
| | | { |
| | | label: '多金', |
| | | value: '多金' |
| | | }, |
| | | { |
| | | label: '深情', |
| | | value: '深情' |
| | | } |
| | | ]); |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## select-status 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <!--【很重要】直接绑定status,或者使用 form[prop!] --> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio v-for="(item, index) in list" :key="index" :value="item.value"> |
| | | {{ item.label }} |
| | | </el-radio> |
| | | </el-radio-group> |
| | | </template> |
| | | |
| | | <!--【很重要】必须要有name,避免注册后和其他冲突 --> |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'select-status' |
| | | }); |
| | | |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { computed, ref } from 'vue'; |
| | | |
| | | const props = defineProps({ |
| | | scope: null, // 表单值 |
| | | prop: String // 表单项配置的 prop |
| | | }); |
| | | |
| | | // 使用 useForm,能直接获取到上级的表单实例, |
| | | // 比如操作表单的 Form.value?.submit、Form.value?.close等 |
| | | // 获取表单值,Form.value?.form |
| | | const Form = useForm(); |
| | | |
| | | // 表单值,包一层不会太难受 |
| | | const form = computed(() => Form.value?.form || {}); |
| | | |
| | | // 选项列表 |
| | | const list = ref<{ label: string; value: number }[]>([ |
| | | { |
| | | label: '很好', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '不舒服', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: '要嘎了', |
| | | value: 3 |
| | | } |
| | | ]); |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## select-work 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <el-select v-model="active" @change="onChange"> |
| | | <el-option |
| | | v-for="(item, index) in list" |
| | | :key="index" |
| | | :label="item.label" |
| | | :value="item.label" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | |
| | | <!-- 【很重要】必须要有name,避免注册后和其他冲突 --> |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'select-work' |
| | | }); |
| | | |
| | | import { ref, watch } from 'vue'; |
| | | |
| | | const props = defineProps({ |
| | | modelValue: String |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:modelValue', 'change']); |
| | | |
| | | //【很重要】绑定值 |
| | | // 这种方式虽然麻烦,但是可扩展性高,一些复杂的数据结构可以按这种方式绑定值 |
| | | const active = ref(); |
| | | |
| | | // 选项列表 |
| | | const list = ref<{ label: string; value: string }[]>([ |
| | | { |
| | | label: '倒茶', |
| | | value: '倒茶' // 测试直接使用label,真实情况可能是1,2,3,4或者id |
| | | }, |
| | | { |
| | | label: '设计', |
| | | value: '设计' |
| | | }, |
| | | { |
| | | label: '开发', |
| | | value: '开发' |
| | | } |
| | | ]); |
| | | |
| | | //【很重要】更新绑定值,表单提交才能得到选择后的 |
| | | function onChange(val: string) { |
| | | emit('update:modelValue', val); |
| | | emit('change', val); |
| | | } |
| | | |
| | | //【很重要】使用监听的方式,避免表单打开数据是异步获取的情况 |
| | | watch( |
| | | () => props.modelValue, |
| | | val => { |
| | | // 设置选中的值 |
| | | active.value = val; |
| | | }, |
| | | { |
| | | immediate: true |
| | | } |
| | | ); |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## select-work2 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <el-select v-model="active"> |
| | | <el-option |
| | | v-for="(item, index) in list" |
| | | :key="index" |
| | | :label="item.label" |
| | | :value="item.label" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | |
| | | <!-- 【很重要】必须要有name,避免注册后和其他冲突 --> |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'select-work2' |
| | | }); |
| | | |
| | | import { ref, useModel } from 'vue'; |
| | | |
| | | const props = defineProps({ |
| | | modelValue: String |
| | | }); |
| | | |
| | | //【很重要】绑定值,使用 useModel 的方式双向绑定 |
| | | const active = useModel(props, 'modelValue'); |
| | | |
| | | // 选项列表 |
| | | const list = ref<{ label: string; value: string }[]>([ |
| | | { |
| | | label: '倒茶', |
| | | value: '倒茶' // 测试直接使用label,真实情况可能是1,2,3,4或者id |
| | | }, |
| | | { |
| | | label: '设计', |
| | | value: '设计' |
| | | }, |
| | | { |
| | | label: '开发', |
| | | value: '开发' |
| | | } |
| | | ]); |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 参数配置 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>config</el-tag> |
| | | <span>参数配置</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/config.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"> |
| | | <!-- 按钮插槽 --> |
| | | <template #slot-btns> |
| | | <el-button type="danger">按钮插槽</el-button> |
| | | </template> |
| | | </cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '参数配置', |
| | | |
| | | // 打开是否重置表单 |
| | | isReset: false, |
| | | |
| | | // 默认表单值 |
| | | form: { |
| | | nickName: '神仙都没用' |
| | | }, |
| | | |
| | | // 表单配置 |
| | | props: { |
| | | // 标签宽度 |
| | | labelWidth: '120px', |
| | | |
| | | // 标签位置 |
| | | labelPosition: 'top' |
| | | }, |
| | | |
| | | // 窗口的高。配置后,在窗口内部滚动。默认整个页面滚动 |
| | | height: '60vh', |
| | | |
| | | // 窗口的宽,默认 50% |
| | | width: '60%', |
| | | |
| | | // 窗口设置 |
| | | dialog: { |
| | | // 是否隐藏头部 |
| | | hideHeader: false, |
| | | |
| | | // 顶部操作按钮,默认["fullscreen", "close"] |
| | | // fullscreen 全屏 |
| | | // close 关闭 |
| | | controls: ['close'] |
| | | }, |
| | | |
| | | // 底部操作按钮 |
| | | op: { |
| | | // 默认靠右布局 |
| | | justify: 'flex-end', |
| | | |
| | | // 保存按钮文字 |
| | | saveButtonText: '提交', |
| | | |
| | | // 关闭按钮文字 |
| | | closeButtonText: '关闭', |
| | | |
| | | // 是否隐藏 |
| | | hidden: false, |
| | | |
| | | // 按钮配置 |
| | | buttons: [ |
| | | // 自定义 |
| | | { |
| | | label: '自定义按钮', |
| | | onClick() { |
| | | ElMessage.success('自定义按钮点击'); |
| | | } |
| | | }, |
| | | // close 关闭 |
| | | 'close', |
| | | // save 保存 |
| | | 'save', |
| | | // 插槽使用,配合 template,往上看 cl-form 组件 |
| | | 'slot-btns' |
| | | ] |
| | | }, |
| | | |
| | | // 表单项配置 |
| | | items: [ |
| | | { |
| | | label: '昵称', |
| | | prop: 'nickName', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ], |
| | | |
| | | // 事件 |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 内嵌CRUD 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>crud</el-tag> |
| | | <span>内嵌CRUD</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/crud.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"> |
| | | <template #slot-crud> |
| | | <cl-crud ref="Crud" border> |
| | | <cl-row> |
| | | <!-- 刷新按钮 --> |
| | | <cl-refresh-btn /> |
| | | <!-- 新增按钮 --> |
| | | <cl-add-btn /> |
| | | <!-- 删除按钮 --> |
| | | <cl-multi-delete-btn /> |
| | | <cl-flex1 /> |
| | | <!-- 关键字搜索 --> |
| | | <cl-search-key placeholder="搜索姓名、手机号" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <!-- 数据表格 --> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <!-- 分页控件 --> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </template> |
| | | </cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useForm, useTable, useUpsert } from '@cool-vue/crud'; |
| | | |
| | | // cl-upsert |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | component: { |
| | | name: 'el-date-picker' |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-table |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | type: 'op' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-crud |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh({ |
| | | size: 10 |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '内嵌CRUD', |
| | | props: { |
| | | labelPosition: 'top' |
| | | }, |
| | | dialog: { |
| | | height: '70vh', |
| | | width: '1000px' |
| | | }, |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | placeholder: '请填写姓名' |
| | | } |
| | | }, |
| | | rules: { |
| | | required: true, |
| | | message: '姓名不能为空' |
| | | } |
| | | }, |
| | | { |
| | | label: '内嵌 cl-crud', |
| | | component: { |
| | | name: 'slot-crud' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | submit() { |
| | | Form.value?.close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 组件禁用 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>disabled</el-tag> |
| | | <span>组件禁用</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/disabled.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '组件禁用', |
| | | items: [ |
| | | { |
| | | label: '账号', |
| | | prop: 'account', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | // 设置 boolean 值控制组件的禁用状态(前提是组件支持这个参数,element 的组件几乎都有) |
| | | disabled: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '密码', |
| | | prop: 'password', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | open() { |
| | | // 通用 setProps 方法去设置 disabled, 1.5s后禁用 |
| | | setTimeout(() => { |
| | | Form.value?.setProps('password', { disabled: true }); |
| | | }, 1500); |
| | | }, |
| | | |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 组件事件 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>event</el-tag> |
| | | <span>组件事件</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/event.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '组件事件', |
| | | items: [ |
| | | { |
| | | label: '账号', |
| | | prop: 'account', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | // 组件内 emit 的用 on[name] 接收,如 onChange、onInput、onBlur 等 |
| | | // 前提是组件内有触发事件 |
| | | onBlur() { |
| | | ElMessage.info('账号检查中'); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '是否实名', |
| | | prop: 'status', |
| | | value: 1, |
| | | component: { |
| | | name: 'el-radio-group', |
| | | options: [ |
| | | { |
| | | label: '关闭', |
| | | value: 0 |
| | | }, |
| | | { |
| | | label: '开启', |
| | | value: 1 |
| | | } |
| | | ], |
| | | props: { |
| | | // 值改变事件 |
| | | onChange(val: number) { |
| | | if (val == 1) { |
| | | // 显示表单项 |
| | | Form.value?.showItem('idcard'); |
| | | } else { |
| | | // 隐藏表单项 |
| | | Form.value?.hideItem('idcard'); |
| | | // 清空值 |
| | | Form.value?.setForm('idcard', undefined); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '身份证', |
| | | prop: 'idcard', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 分组显示 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>group</el-tag> |
| | | <span>分组显示</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/group.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '分组显示', |
| | | items: [ |
| | | { |
| | | //【很重要】必须为 tabs |
| | | type: 'tabs', |
| | | props: { |
| | | // 分组样式 |
| | | type: 'card', |
| | | // 分组列表,必须是 { label, value } 的数组格式 |
| | | labels: [ |
| | | { |
| | | label: '基础信息', // 标题 |
| | | value: 'base' // 唯一标识 |
| | | }, |
| | | { |
| | | label: '认证信息', |
| | | value: 'auth' |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | // 基础信息 |
| | | { |
| | | group: 'base', // 标识 |
| | | label: '账号', |
| | | prop: 'account', |
| | | required: true, |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | group: 'base', // 标识 |
| | | label: '密码', |
| | | prop: 'password', |
| | | required: true, |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | |
| | | // 其他信息 group = other |
| | | { |
| | | group: 'auth', // 标识 |
| | | label: '身份证', |
| | | prop: 'idcard', |
| | | required: true, |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | group: 'auth', // 标识 |
| | | label: '学校', |
| | | prop: 'school', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | group: 'auth', // 标识 |
| | | label: '专业', |
| | | prop: 'major', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | //【提示】当第一组验证通过后,会自动切换到下一组展示,直到全部通过才可提交 |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 隐藏/显示 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>hidden</el-tag> |
| | | <span>隐藏/显示</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/hidden.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '隐藏/显示', |
| | | items: [ |
| | | { |
| | | label: '状态', |
| | | prop: 'status', |
| | | value: 0, |
| | | component: { |
| | | name: 'el-radio-group', |
| | | options: [ |
| | | { |
| | | label: '关闭', |
| | | value: 0 |
| | | }, |
| | | { |
| | | label: '开启', |
| | | value: 1 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '账号', |
| | | prop: 'account', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | //【很重要】是否隐藏 |
| | | hidden({ scope }) { |
| | | // scope 为表单值 |
| | | // 返回一个 boolean 来控制当前表单项的隐藏/显示 |
| | | return scope.status != 1; |
| | | }, |
| | | label: '密码', |
| | | prop: 'password', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 布局 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>layout</el-tag> |
| | | <span>布局</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/layout.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '布局', |
| | | items: [ |
| | | { |
| | | //【span】参考文档:https://element-plus.gitee.io/zh-CN/component/layout.html |
| | | // 使用 1/24 分栏,默认 24 |
| | | span: 12, |
| | | label: '昵称', |
| | | prop: 'nickname', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | span: 12, |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | maxlength: 11 |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | //【flex】使宽度不填充满 |
| | | flex: false, |
| | | label: '标签', |
| | | prop: 'label', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | prop: 'status', |
| | | value: 1, |
| | | component: { |
| | | name: 'el-radio-group', |
| | | options: [ |
| | | { |
| | | label: '开启', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '关闭', |
| | | value: 0 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '备注', |
| | | prop: 'remark', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | type: 'textarea', |
| | | rows: 4 |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 起步 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>open</el-tag> |
| | | <span>起步</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/open.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <!--【很重要】ref 一定要对应 useForm 定义的值 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="tsx"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '起步', |
| | | |
| | | items: [ |
| | | { |
| | | label: '昵称', |
| | | // 绑定值的标识,表单提交及回显会自动根据 prop 获取对应的值 |
| | | prop: 'nickname', |
| | | // 组件绑定 |
| | | component: { |
| | | // 必须是“全局注册”的组件名,如 element-plus 的 el-input、el-date-picker 等 |
| | | name: 'el-input', |
| | | |
| | | // 绑定的组件参数配置,如 clearable、placeholder 等 |
| | | // 组件内 emit 的用 on[name] 接收,如 onChange、onInput、onBlur 等 |
| | | props: { |
| | | placeholder: '请输入昵称', |
| | | clearable: true, |
| | | onChange(value: string) {} |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | prop: 'age', |
| | | component: { |
| | | name: 'el-input-number' |
| | | }, |
| | | // 默认值,第一次打开有效 |
| | | value: 18 |
| | | } |
| | | ], |
| | | on: { |
| | | // 打开时触发 |
| | | open() { |
| | | console.log(Form.value?.validateField); |
| | | }, |
| | | |
| | | // 关闭时触发。当配置该方法时,关闭事件会被阻断,使用 done() 关闭窗口 |
| | | close(action, done) { |
| | | // action 为关闭窗口的触发动作 "save" | "close" |
| | | // done 关闭事件 |
| | | done(); |
| | | }, |
| | | |
| | | // 提交时触发 |
| | | submit(data, { done, close }) { |
| | | // data 为表单值 |
| | | // done 关闭加载事件、但不关闭窗口 |
| | | // close 关闭窗口 |
| | | |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 选项框配置 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>options</el-tag> |
| | | <span>选项框配置</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/options.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { computed, reactive } from 'vue'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | // 觉得麻烦就 any,如 { user: [] as any[] } |
| | | const options = reactive<{ [key: string]: { label: string; value: any }[] }>({ |
| | | user: [] |
| | | }); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '选项框配置', |
| | | items: [ |
| | | { |
| | | label: '下拉框', |
| | | prop: 'select', |
| | | component: { |
| | | name: 'el-select', |
| | | props: { |
| | | clearable: true // 可清除 |
| | | }, |
| | | options: [ |
| | | { |
| | | label: 'javascript', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: 'vue', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: 'html', |
| | | value: 3 |
| | | }, |
| | | { |
| | | label: 'css', |
| | | value: 4 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '单选框', |
| | | prop: 'radio', |
| | | value: 1, |
| | | component: { |
| | | name: 'el-radio-group', |
| | | options: [ |
| | | { |
| | | label: '手机', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '电脑', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: '电视', |
| | | value: 3 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '多选框', |
| | | prop: 'checkbox', |
| | | value: [2, 3], |
| | | component: { |
| | | name: 'el-checkbox-group', |
| | | options: [ |
| | | { |
| | | label: '咖啡', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '汉堡', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: '炸鸡', |
| | | value: 3 |
| | | }, |
| | | { |
| | | label: '奶茶', |
| | | value: 4 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '动态配置1', |
| | | prop: 'd1', |
| | | component: { |
| | | name: 'el-select', |
| | | // 动态设置方法1,在 on.open 事件配置 options |
| | | options: [] |
| | | } |
| | | }, |
| | | { |
| | | label: '动态配置2', |
| | | prop: 'd2', |
| | | component: { |
| | | name: 'el-select', |
| | | // 动态设置方法2,使用 computed 更新 options |
| | | options: computed(() => options.user) |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | open() { |
| | | // 模拟 1.5s 后取的数据 |
| | | setTimeout(() => { |
| | | // 动态设置方法1,使用 setOptions 方法设置 |
| | | // d1 为 prop 值 |
| | | Form.value?.setOptions('d1', [ |
| | | { |
| | | label: '😊', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '😭', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: '😘', |
| | | value: 3 |
| | | } |
| | | ]); |
| | | |
| | | // 动态设置方法2,直接设置 options.user,由 computed 更新 |
| | | options.user = [ |
| | | { |
| | | label: '💰', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '🚗', |
| | | value: 2 |
| | | } |
| | | ]; |
| | | }, 1500); |
| | | }, |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 插件的使用 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>plugin</el-tag> |
| | | <span>插件的使用</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open('manager')">管理者</el-button> |
| | | <el-button @click="open('user')">用户</el-button> |
| | | <demo-code :files="['form/plugin/index.vue', 'form/plugin/role.ts']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { setRole } from './role'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open(role: string) { |
| | | Form.value?.open( |
| | | { |
| | | title: '插件的使用', |
| | | |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | required: true, |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | // 自定义参数 role,匹配插件传入的角色 |
| | | role: 'user', |
| | | label: '面试职位', |
| | | prop: 'work', |
| | | value: 1, |
| | | component: { |
| | | name: 'el-radio-group', |
| | | options: [ |
| | | { |
| | | label: '前端开发', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '后端开发', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: 'UI设计', |
| | | value: 3 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | role: 'user', |
| | | label: '期望薪资', |
| | | prop: 'salary', |
| | | value: 5000, |
| | | component: { |
| | | name: 'el-input-number', |
| | | props: { |
| | | min: 2000, |
| | | max: 100000 |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | role: 'manager', |
| | | label: '入职时间', |
| | | prop: 'date', |
| | | component: { |
| | | name: 'el-date-picker' |
| | | } |
| | | }, |
| | | { |
| | | role: 'manager', |
| | | label: '负责人', |
| | | prop: 'head', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { done, close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }, |
| | | [ |
| | | // 自定义插件,角色权限控制 |
| | | setRole(role) |
| | | ] |
| | | ); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 必填项配置 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>required</el-tag> |
| | | <span>必填项配置</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/required.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"></cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '必填项配置', |
| | | items: [ |
| | | { |
| | | label: '昵称', |
| | | prop: 'nickname', |
| | | component: { |
| | | name: 'el-input' |
| | | }, |
| | | // 是否必填,默认判断绑定值是否空 |
| | | required: true |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | maxlength: 11 |
| | | } |
| | | }, |
| | | // 自定义规则 |
| | | // 基础用法可参考:https://element-plus.gitee.io/zh-CN/component/form.html |
| | | // 高级用法可参考:https://github.com/yiminghe/async-validator |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | validator: (rule, value, callback) => { |
| | | if (value === '') { |
| | | callback(new Error('手机号不能为空')); |
| | | } else if (!/^1[3456789]\d{9}$/.test(value)) { |
| | | callback(new Error('手机号格式错误')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 添加/删除表单项 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>rules</el-tag> |
| | | <span>添加/删除表单项</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['form/rules.vue']" /> |
| | | |
| | | <!-- 自定义表单组件 --> |
| | | <cl-form ref="Form"> |
| | | <template #slot-cert="{ scope }"> |
| | | <div class="cert"> |
| | | <!--【很重要】prop、rules 配置格式如下 --> |
| | | <el-form-item |
| | | v-for="(item, index) in scope.cert" |
| | | :key="index" |
| | | :label="`证书${index + 1}`" |
| | | :prop="`cert.${index}.label`" |
| | | :rules="{ |
| | | message: `请填写证书${index + 1}`, |
| | | required: true |
| | | }" |
| | | > |
| | | <div class="row"> |
| | | <!-- 输入框 --> |
| | | <el-input v-model="item.label" placeholder="请填写证书"></el-input> |
| | | |
| | | <!-- 删除行 --> |
| | | <el-icon @click="rowDel(index)"> |
| | | <delete /> |
| | | </el-icon> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | | <!-- 添加行 --> |
| | | <el-row type="flex" justify="end"> |
| | | <el-button @click="rowAdd()">添加证书</el-button> |
| | | </el-row> |
| | | </div> |
| | | </template> |
| | | </cl-form> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useForm } from '@cool-vue/crud'; |
| | | import { Delete } from '@element-plus/icons-vue'; |
| | | |
| | | const Form = useForm(); |
| | | |
| | | function open() { |
| | | Form.value?.open({ |
| | | title: '添加/删除表单项', |
| | | items: [ |
| | | { |
| | | label: '昵称', |
| | | prop: 'nickname', |
| | | component: { |
| | | name: 'el-input' |
| | | }, |
| | | required: true |
| | | }, |
| | | { |
| | | prop: 'cert', |
| | | //【很重要】默认数据格式,以实际业务为主。 |
| | | value: [ |
| | | { |
| | | label: '' |
| | | } |
| | | ], |
| | | component: { |
| | | name: 'slot-cert' |
| | | } |
| | | } |
| | | ], |
| | | on: { |
| | | submit(data, { close }) { |
| | | close(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function rowAdd() { |
| | | Form.value?.form.cert.push({ |
| | | label: '' |
| | | }); |
| | | } |
| | | |
| | | function rowDel(index: number) { |
| | | Form.value?.form.cert.splice(index, 1); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .cert { |
| | | .row { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .el-input { |
| | | flex: 1; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .el-icon { |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | color: red; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | ``` |
| New file |
| | |
| | | --- |
| | | description: module | plugins 模块、插件 |
| | | globs: |
| | | --- |
| | | # 模块/插件开发 |
| | | |
| | | ## 目录结构 |
| | | |
| | | 在 `src/modules` 或 `src/plugins` 下添加一个目录 `demo`: |
| | | |
| | | ```js |
| | | demo |
| | | ├──pages // 页面路由 |
| | | ├──views // 视图路由 |
| | | ├──hooks // 常用函数 |
| | | ├──components // 常用组件 |
| | | ├──directives // 指令 |
| | | ├──static // 静态文件目录 |
| | | ├──store // 状态管理 |
| | | ├──... // 其他自定义文件 |
| | | ├──config.ts // 配置文件 |
| | | └──index.ts // 入口文件 |
| | | ``` |
| | | |
| | | ::: warning |
| | | 约定的目录名称不可修改,但可自行添加或者删除。 |
| | | ::: |
| | | |
| | | ## pages、views |
| | | |
| | | 1. 页面参与权限控制,所以不主动注册目录下的路由,通过 `菜单列表` 中配置注册。或者在 `config.ts` 中手动配置: |
| | | |
| | | ```js |
| | | import { type ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | views: [ |
| | | { |
| | | path: "/demo", |
| | | meta: { |
| | | label: "测试", |
| | | }, |
| | | component: () => import("./views/demo.vue"), |
| | | }, |
| | | ], |
| | | pages: [ |
| | | { |
| | | path: "/demo2", |
| | | meta: { |
| | | label: "测试", |
| | | }, |
| | | component: () => import("./pages/demo.vue"), |
| | | }, |
| | | ], |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | 2. 使页面参与路由缓存,配置 `name` 参数 |
| | | |
| | | :::warning |
| | | |
| | | `path` 与 `name` 的匹配规则: |
| | | |
| | | - /demo/t1 = demo-t1 |
| | | - /demo/t1-det = demo-t1-det |
| | | |
| | | ::: |
| | | |
| | | 方式 1: |
| | | |
| | | ```html |
| | | <script lang="ts" setup> |
| | | defineOptions({ |
| | | name: "demo", |
| | | }); |
| | | </script> |
| | | ``` |
| | | |
| | | 方式 2: |
| | | |
| | | ```html |
| | | <script lang="ts"> |
| | | export default defineComponent({ |
| | | name: "demo", |
| | | }); |
| | | </script> |
| | | ``` |
| | | |
| | | ## components |
| | | |
| | | 目录下的组件,全局注册配置方法如下: |
| | | |
| | | ```js |
| | | import { ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | components: [ |
| | | import("./components/demo.vue"), |
| | | import("./components/demo1.vue"), |
| | | ], |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | ## directives |
| | | |
| | | `directives` 会以目录下的文件名分别注册指令 |
| | | |
| | | ```ts |
| | | // demo/directives/test.ts |
| | | export default { |
| | | created(el, binding) {}, |
| | | mounted() {}, |
| | | ... |
| | | }; |
| | | ``` |
| | | |
| | | 使用 |
| | | |
| | | ```html |
| | | <div v-test></div> |
| | | ``` |
| | | |
| | | ## store |
| | | |
| | | 使用 `pinia` 的推荐写法: |
| | | |
| | | ```ts |
| | | import { defineStore } from "pinia"; |
| | | import { ref } from "vue"; |
| | | |
| | | export const useTestStore = defineStore("test", function () { |
| | | const count = ref(0); |
| | | |
| | | function add() { |
| | | count.value += 1; |
| | | } |
| | | |
| | | return { |
| | | count, |
| | | add, |
| | | }; |
| | | }); |
| | | ``` |
| | | |
| | | 使用 |
| | | |
| | | ```ts |
| | | import { useTestStore } from "/$/demo/store"; |
| | | |
| | | const test = useTestStore(); |
| | | |
| | | test.add(); |
| | | |
| | | console.log(test.count); // 1 |
| | | ``` |
| | | |
| | | ::: tip |
| | | 参考 `base` 模块下 `store` 的导出方式 |
| | | ::: |
| | | |
| | | ## config.ts |
| | | |
| | | 模块的配置,程序运行时会读取该文件。 |
| | | |
| | | - 全局组件、路由的导入 |
| | | |
| | | - 事件钩子 |
| | | |
| | | 输入 `module-config` 关键字,`vscode` 中会自动生成: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | import { Vue } from "vue"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | // 是否启用 |
| | | enable: true, |
| | | |
| | | // 插件名称 |
| | | label: "插件名称", |
| | | |
| | | // 插件描述 |
| | | description: "插件描述", |
| | | |
| | | // 作者 |
| | | author: "作者", |
| | | version: "1.0.0", |
| | | updateTime: "2024-02-02", |
| | | logo: "", |
| | | |
| | | // 忽略 |
| | | ignore: { |
| | | // 忽略进度条的请求 |
| | | NProgress: [ |
| | | "/base/open/eps", |
| | | "/base/comm/person", |
| | | "/base/comm/permmenu", |
| | | "/base/comm/upload", |
| | | "/base/comm/uploadMode", |
| | | ], |
| | | |
| | | // 忽略 token 的路由 |
| | | token: ["/login", "/401", "/403", "/404", "/500", "/502"], |
| | | }, |
| | | |
| | | // 排序 |
| | | order: 0, |
| | | |
| | | // 配置参数 |
| | | options: { |
| | | name: "神仙", |
| | | }, |
| | | |
| | | // 示例页面 |
| | | demo: [ |
| | | { |
| | | name: "基础用法", |
| | | component: () => import("..."), |
| | | }, |
| | | ], |
| | | |
| | | // 注册全局组件 |
| | | components: [], |
| | | |
| | | // 视图路由 |
| | | views: [], |
| | | |
| | | // 页面路由 |
| | | pages: [], |
| | | |
| | | // 顶部工具栏 |
| | | toolbar: { |
| | | order: 1, |
| | | pc: true, // 是否在 pc 端显示 |
| | | h5: true, // 是否在 h5 端显示 |
| | | component: import("./components/index.vue"), |
| | | }, |
| | | |
| | | // 注入全局组件 |
| | | index: { |
| | | component: import("./components/index.vue"), |
| | | }, |
| | | |
| | | // 安装时触发 |
| | | install(app: Vue) {}, |
| | | |
| | | // 加载时触发 |
| | | onLoad(events) {}, |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | - order 模块加载顺序,值越大越先 |
| | | |
| | | - options 提供给外部使用的参数配置: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | options: { |
| | | // 尺寸 |
| | | size: 120, |
| | | // 显示文案 |
| | | text: "选择文件", |
| | | // 限制 |
| | | limit: { |
| | | // 上传最大数量 |
| | | upload: 9, |
| | | // 文件空间选择数 |
| | | select: 9, |
| | | // 上传大小限制 |
| | | size: 100, |
| | | }, |
| | | }, |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | 获取方式: |
| | | |
| | | ```ts |
| | | import { module } from "/@/cool"; |
| | | |
| | | const config = module.config("模块名"); |
| | | ``` |
| | | |
| | | - components 提供全局的组件: |
| | | |
| | | ```ts |
| | | import type { ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | components: [import("./components/test.vue")], |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | 批量导入可以使用 [import.meta.glob](mdc:https:/vitejs.dev/guide/features.html#glob-import) 方法: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | components: Object.values(import.meta.glob("./components/**/*")), |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | - views 全局注册的视图路由,存放在 `/` 中的子路由 `children`: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | views: [ |
| | | { |
| | | path: "/test", |
| | | meta: { |
| | | label: "测试中心", |
| | | }, |
| | | component: () => import("./views/test.vue"), |
| | | }, |
| | | ], |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | - pages 全局注册的页面路由: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | pages: [ |
| | | { |
| | | path: "/test", |
| | | meta: { |
| | | label: "测试中心", |
| | | }, |
| | | component: () => import("./views/test.vue"), |
| | | }, |
| | | ], |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | - install 模块安装时触发。用于预先处理: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | import { Vue } from "vue"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | install(app: Vue) { |
| | | // 注册组件 |
| | | app.component("test", Test); |
| | | |
| | | // 注册指令 |
| | | app.directive("focus", { |
| | | created(el, bind) {}, |
| | | }); |
| | | }, |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | - onLoad 模块安装时触发,预先加载数据,如菜单配置、用户信息: |
| | | |
| | | 1. 使用 `await` 等待加载完成后往下执行 |
| | | |
| | | 2. 可往下模块导出某个方法和变量,如 `hasToken` 验证是否有登陆 |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | import { Vue } from "vue"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | async onLoad() { |
| | | const { user, menu } = useStore(); |
| | | |
| | | if (user.token) { |
| | | // 获取用户信息 |
| | | user.get(); |
| | | // 获取菜单权限 |
| | | await menu.get(); |
| | | } |
| | | |
| | | return { |
| | | async hasToken(cb: () => Promise<any> | void) { |
| | | if (user.token) { |
| | | if (cb) await cb(); |
| | | } |
| | | }, |
| | | }; |
| | | }, |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | 其他模块中接收 `hasToken` 方法: |
| | | |
| | | ```ts |
| | | import { ModuleConfig } from "/@/cool"; |
| | | import { useDict } from "./index"; |
| | | |
| | | export default (): ModuleConfig => { |
| | | return { |
| | | onLoad({ hasToken }) { |
| | | const { dict } = useDict(); |
| | | |
| | | hasToken(() => { |
| | | dict.refresh(); |
| | | }); |
| | | }, |
| | | }; |
| | | }; |
| | | ``` |
| | | |
| | | ## index.ts |
| | | |
| | | 该模块需要对外开放的变量及方法,方便于别人直接使用: |
| | | |
| | | ```ts |
| | | // modules/test/index.ts |
| | | import { useStore } from "./store"; |
| | | |
| | | export function useTest() { |
| | | return { |
| | | // 导出 pinia |
| | | ...useStore(), |
| | | |
| | | // 自定义方法 |
| | | test() {}, |
| | | |
| | | // 自定义变量 |
| | | data: { |
| | | description: "数据描述", |
| | | }, |
| | | }; |
| | | } |
| | | ``` |
| | | |
| | | 导出命名规则 `useBase` `useDemo` `useDict` use + 模块名 |
| | | |
| | | 使用: |
| | | |
| | | ```ts |
| | | import { useTest } from "/$/test"; |
| | | |
| | | const { data, test } = useTest(); |
| | | ``` |
| New file |
| | |
| | | --- |
| | | description: cl-search 组件示例 |
| | | globs: *.tsx, *.ts, *.vue |
| | | --- |
| | | ## 起步 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>base</el-tag> |
| | | <span>起步</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['search/base.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="起步" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!--【很重要】搜索组件 --> |
| | | <cl-search ref="Search" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-search 配置 |
| | | //【很重要】该组件基于 cl-form 故很多示例都可复用 |
| | | const Search = useSearch({ |
| | | // 配置如 cl-form 一样 |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true, |
| | | |
| | | // 值改变的时候刷新列表 |
| | | onChange(val: string) { |
| | | refresh({ |
| | | name: val, |
| | | page: 1 |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | |
| | | onChange(data, prop) { |
| | | console.log(data, prop); |
| | | } |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 折叠 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>collapse</el-tag> |
| | | <span>折叠</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['search/collapse.vue']" /> |
| | | |
| | | <!-- 折叠表格组件 --> |
| | | <cl-dialog v-model="visible" title="折叠" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <!--【collapse】折叠参数,【inline】是否行内 --> |
| | | <cl-search ref="Search" reset-btn collapse :inline="false" /> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-12-26</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { range } from 'lodash-es'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-search 配置 |
| | | const Search = useSearch({ |
| | | items: [ |
| | | ...range(20).map(i => { |
| | | return { |
| | | label: '输入框', |
| | | prop: `T${i + 1}`, |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }; |
| | | }) |
| | | ] |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | x |
| | | |
| | | ``` |
| | | |
| | | ## 自定义 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>custom</el-tag> |
| | | <span>自定义</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['search/custom.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="自定义" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!--【很重要】搜索组件 --> |
| | | <cl-search |
| | | ref="Search" |
| | | :reset-btn="true" |
| | | :on-load="onLoad" |
| | | :on-search="onSearch" |
| | | > |
| | | <!-- 自定义按钮 --> |
| | | <template #buttons="scope"> |
| | | <el-button @click="toSearch(scope)">自定义按钮</el-button> |
| | | </template> |
| | | </cl-search> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-search 配置 |
| | | //【很重要】该组件基于 cl-form 故很多示例都可复用 |
| | | const Search = useSearch({ |
| | | // 配置如 cl-form 一样 |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true, |
| | | |
| | | // 值改变的时候刷新列表 |
| | | onChange(val: string) { |
| | | refresh({ |
| | | name: val, |
| | | page: 1 |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | // cl-search 初始化 |
| | | function onLoad(data: any) { |
| | | data.name = '白小纯'; |
| | | } |
| | | |
| | | // cl-search 配置 onSearch 后,必须使用 next 方法继续请求 |
| | | function onSearch(data: any, { next }: { next: (data: any) => void }) { |
| | | ElMessage.info('开始搜索'); |
| | | // 这边可以处理其他事务 |
| | | next(data); |
| | | } |
| | | |
| | | // 自定义搜索,data 为表单数据 |
| | | function toSearch(data: any) { |
| | | ElMessage.info('自定义搜索'); |
| | | |
| | | refresh({ |
| | | page: 1, |
| | | ...data |
| | | }); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 布局 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>layout</el-tag> |
| | | <span>布局</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['search/layout.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="布局" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <!--【很重要】搜索组件 --> |
| | | <cl-search ref="Search" :reset-btn="true" /> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-search 配置 |
| | | //【很重要】该组件基于 cl-form 故很多示例都可复用 |
| | | const Search = useSearch({ |
| | | // 取消行内表单模式 |
| | | inline: false, |
| | | |
| | | // 表单参数 |
| | | props: { |
| | | labelPosition: 'top' |
| | | }, |
| | | |
| | | // 配置如 cl-form 一样 |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true, |
| | | |
| | | // 值改变的时候刷新列表 |
| | | onChange(val: string) { |
| | | refresh({ |
| | | name: val, |
| | | page: 1 |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | clearable: true |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 使用插件 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>plugin</el-tag> |
| | | <span>使用插件</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['search/layout.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="使用插件" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <!--【很重要】搜索组件 --> |
| | | <cl-search ref="Search" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useSearch, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { Plugins } from '/#/crud'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-search 配置 |
| | | const Search = useSearch({ |
| | | // 【很重要】自动读取 service 下的 search 数据 |
| | | plugins: [ |
| | | Plugins.Search.setAuto({ |
| | | customComponent(field) { |
| | | if (field.propertyName == 'name') { |
| | | return { |
| | | name: 'cl-select', |
| | | props: { |
| | | options: [ |
| | | { |
| | | label: '张三', |
| | | value: '1' |
| | | }, |
| | | { |
| | | label: '李四', |
| | | value: '2' |
| | | } |
| | | ] |
| | | } |
| | | }; |
| | | } |
| | | |
| | | // null 则不操作,按系统默认操作 |
| | | return null; |
| | | } |
| | | }) |
| | | ] |
| | | }); |
| | | |
| | | function refresh(params?: any) { |
| | | Crud.value?.refresh(params); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| New file |
| | |
| | | --- |
| | | description: cl-table 组件示例 |
| | | globs: *.tsx, *.ts, *.vue |
| | | --- |
| | | ## 起步 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>base</el-tag> |
| | | <span>起步</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/base.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="起步" width="80%"> |
| | | <!--【很重要】需要包含在 cl-crud 组件内 --> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!-- 参数文档查看:https://element-plus.org/zh-CN/component/table.html#table-%E5%B1%9E%E6%80%A7 --> |
| | | <cl-table ref="Table" stripe></cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | // 测试数据,移步到 cl-crud 例子查看 |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | // 是否自动计算表格高度,表格高度等于减去上区域和下区域的高度 |
| | | //【很重要】在弹窗或者上级不确定高度中,设置 autoHeight: false,避免显示异常。也可以手动设置最大高度 maxHeight: 500 |
| | | autoHeight: false, |
| | | |
| | | // 右键菜单,移步到右键菜单示例中查看 |
| | | contextMenu: ['refresh'], |
| | | |
| | | // 列配置,点击 columns 查看描述 |
| | | // 更多配置查看 el-table-column 文档,https://element-plus.org/zh-CN/component/table.html#table-column-%E5%B1%9E%E6%80%A7 |
| | | columns: [ |
| | | { |
| | | // 是否为多选框操作列 |
| | | type: 'selection' |
| | | |
| | | // 是否为序号列 |
| | | // type: "index" |
| | | }, |
| | | { |
| | | // 表头标题 |
| | | label: '姓名', |
| | | |
| | | // 绑定值 |
| | | prop: 'name', |
| | | |
| | | // 最小宽度 |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | // 字典匹配,移步到字典示例中查看 |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | // 是否排序,desc, asc |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 多级表头 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>children</el-tag> |
| | | <span>多级表头</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/children.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="多级表头" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '用户信息', |
| | | prop: 'baseInfo', |
| | | minWidth: 250, |
| | | |
| | | // 配置 children 参数 |
| | | children: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 自定义列展示 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>column-custom</el-tag> |
| | | <span>自定义列展示</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/column-custom.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="自定义列展示" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!--【很重要】组件配置,设置为 Table 的 columns,也可以自定义 --> |
| | | <cl-column-custom :columns="Table?.columns" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table"></cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '状态', |
| | | prop: 'status', |
| | | dict: [ |
| | | { |
| | | label: '启用', |
| | | value: 1, |
| | | type: 'success' |
| | | }, |
| | | { |
| | | label: '禁用', |
| | | value: 0, |
| | | type: 'danger' |
| | | } |
| | | ], |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 组件渲染 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>component</el-tag> |
| | | <span>组件渲染</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/component/index.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="组件渲染" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table"></cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import UserInfo from './user-info.vue'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140, |
| | | |
| | | //【很重要】组件实例方式渲染 |
| | | component: { |
| | | vm: UserInfo |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140, |
| | | |
| | | //【很重要】组件名方式渲染 |
| | | component: { |
| | | // 组件名,组件必须全局注册了 |
| | | name: 'el-input', |
| | | |
| | | // 传入参数 |
| | | props: { |
| | | onChange(val) { |
| | | ElMessage.info(val); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## user-info 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="user-info"> |
| | | <cl-avatar :size="36" /> |
| | | |
| | | <div class="det"> |
| | | <p>{{ scope?.name }}</p> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- name 必须填写且唯一 --> |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'user-info' |
| | | }); |
| | | |
| | | const props = defineProps({ |
| | | prop: String, // 列配置的 prop |
| | | scope: null // 列数据 |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .user-info { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .det { |
| | | flex: 1; |
| | | margin-left: 10px; |
| | | text-align: left; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | ``` |
| | | |
| | | ## 右键菜单 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>context-menu</el-tag> |
| | | <span>右键菜单</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/context-menu.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="右键菜单"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table"></cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { EditPen, MoreFilled } from '@element-plus/icons-vue'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | |
| | | // 右键菜单配置,为 [] 时则不显示内容 |
| | | contextMenu: [ |
| | | 'refresh', // 刷新 |
| | | 'check', // 选择行 |
| | | 'edit', // 弹出编辑框 |
| | | 'delete', // 弹出删除提示 |
| | | 'info', // 弹出详情 |
| | | 'order-desc', // 使列倒序 |
| | | 'order-asc', // 使列升序 |
| | | { |
| | | label: '禁用状态', |
| | | disabled: true |
| | | }, |
| | | { |
| | | label: '带图标', |
| | | prefixIcon: EditPen, |
| | | suffixIcon: MoreFilled |
| | | }, |
| | | { |
| | | label: '超出隐藏,看我有很多字非常多', |
| | | ellipsis: true |
| | | }, |
| | | { |
| | | label: '多层级', |
| | | children: [ |
| | | { |
| | | label: 'A', |
| | | children: [ |
| | | { |
| | | label: 'A-1', |
| | | callback(done) { |
| | | ElMessage.success('点击了A-1'); |
| | | done(); |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | label: 'B' |
| | | }, |
| | | { |
| | | label: 'C' |
| | | } |
| | | ] |
| | | }, |
| | | // row 行数据 |
| | | // column 列属性 |
| | | // event 事件对象 |
| | | (row, column, event) => { |
| | | // 必须返回一个对象 |
| | | return { |
| | | label: '自定义2', |
| | | callback(done) { |
| | | ElMessage.info('获取中'); |
| | | |
| | | setTimeout(() => { |
| | | ElMessage.success('Ta 是' + row.name); |
| | | |
| | | // 关闭右键菜单,只有在用到 callback 方法时才需要 |
| | | done(); |
| | | }, 500); |
| | | } |
| | | }; |
| | | } |
| | | ], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置,详细移步到 cl-upsert 示例查看 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 字典匹配 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>dict</el-tag> |
| | | <span>字典匹配</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/dict.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="字典匹配" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { computed, reactive, ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | const options = reactive({ |
| | | occupation: [] as { label: string; value: any }[] |
| | | }); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | |
| | | //【很重要】字典匹配 |
| | | // 使用字典模块的 get 方法绑定,菜单地址 /dict/list |
| | | dict: dict.get('occupation'), |
| | | |
| | | // 是否使用不同颜色区分 |
| | | dictColor: true, |
| | | |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '等级', |
| | | prop: 'occupation', |
| | | |
| | | //【很重要】动态匹配列表的情况,使用 computed |
| | | dict: computed(() => options.occupation), |
| | | |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '状态', |
| | | prop: 'status', |
| | | |
| | | // 自定义匹配列表 |
| | | dict: [ |
| | | { |
| | | label: '启用', |
| | | value: 1, |
| | | type: 'success' |
| | | }, |
| | | { |
| | | label: '禁用', |
| | | value: 0, |
| | | type: 'danger' |
| | | } |
| | | ], |
| | | |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | |
| | | // 模拟接口获取数据 |
| | | setTimeout(() => { |
| | | options.occupation = [ |
| | | { |
| | | label: 'A', |
| | | value: 0 |
| | | }, |
| | | { |
| | | label: 'B', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: 'C', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: 'D', |
| | | value: 3 |
| | | }, |
| | | { |
| | | label: 'E', |
| | | value: 4 |
| | | }, |
| | | { |
| | | label: 'F', |
| | | value: 5 |
| | | } |
| | | ]; |
| | | }, 1500); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 数据格式化 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>formatter</el-tag> |
| | | <span>数据格式化</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/formatter.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="数据格式化" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-09-26</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="tsx"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140, |
| | | formatter(row) { |
| | | return '📱' + row.phone; |
| | | } |
| | | }, |
| | | { |
| | | label: '用户信息', |
| | | minWidth: 200, |
| | | // tsx 方式渲染 |
| | | // 【很重要】使用 tsx 语法时,script 的 lang 一定要设置为 tsx |
| | | formatter(row) { |
| | | // row 为当前行数据 |
| | | return ( |
| | | <el-row> |
| | | <cl-avatar size={30} /> |
| | | <el-text style={{ marginLeft: '10px' }}>{row.name}</el-text> |
| | | </el-row> |
| | | ); |
| | | } |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 隐藏/显示 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>hidden</el-tag> |
| | | <span>隐藏/显示</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/hidden.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="隐藏/显示" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <!--配置一个 tab --> |
| | | <el-tabs v-model="active"> |
| | | <el-tab-pane label="员工" name="user"></el-tab-pane> |
| | | <el-tab-pane label="企业" name="company"></el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <cl-row> |
| | | <!-- 使用方法 showColumn 显示 --> |
| | | <el-button @click="showColumn('account')">显示账号</el-button> |
| | | |
| | | <!-- 使用方法 hideColumn 隐藏 --> |
| | | <el-button @click="hideColumn('account')">隐藏账号</el-button> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table"></cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { computed, ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | // 测试数据,移步到 cl-crud 例子查看 |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | const active = ref('user'); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: 'ID', |
| | | prop: 'id', |
| | | minWidth: 140, |
| | | |
| | | //【很重要】配置 hidden 参数,格式为 boolean 或者 Vue.ComputedRef<boolean> |
| | | hidden: computed(() => { |
| | | return active.value != 'company'; |
| | | }) |
| | | }, |
| | | { |
| | | label: '账号', |
| | | prop: 'account', |
| | | minWidth: 140, |
| | | hidden: true // 默认 false |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | |
| | | function showColumn(prop: string) { |
| | | Table.value?.showColumn(prop); |
| | | } |
| | | |
| | | function hideColumn(prop: string) { |
| | | Table.value?.hideColumn(prop); |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 操作栏 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>op</el-tag> |
| | | <span>操作栏</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/op.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="操作栏" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table"> |
| | | <!-- 插槽的渲染方式 #[component.name] --> |
| | | <template #slot-btns="{ scope }"> |
| | | <el-button |
| | | @click=" |
| | | () => { |
| | | ElMessage.info(scope.row.name); |
| | | } |
| | | " |
| | | >插槽按钮</el-button |
| | | > |
| | | </template> |
| | | </cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!-- 新增、编辑 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | //【很重要】type 必须是 op |
| | | type: 'op', |
| | | |
| | | width: 410, // 宽度 |
| | | |
| | | //【很重要】操作按钮配置,edit 和 info 必须搭配 cl-upsert 实现 |
| | | // edit 编辑,预先获取 service 的 info 接口数据,并带入 cl-upsert 的表单值中 |
| | | // info 详情,cl-upsert 内的组件全部传入 disabled 参数 |
| | | // delete 删除,调用 service 的 delete 接口删除行数据 |
| | | buttons: [ |
| | | { |
| | | label: '编辑', |
| | | type: 'primary', |
| | | onClick({ scope }) { |
| | | ElMessage.info(scope.row.name); |
| | | } |
| | | }, |
| | | { |
| | | label: '删除', |
| | | type: 'danger', |
| | | onClick({ scope }) { |
| | | ElMessage.info(scope.row.name); |
| | | } |
| | | }, |
| | | { |
| | | label: '更多', |
| | | type: 'success', |
| | | children: [ |
| | | { |
| | | label: '查看', |
| | | onClick({ scope }) { |
| | | ElMessage.info(scope.row.name); |
| | | } |
| | | }, |
| | | { |
| | | label: '禁用', |
| | | onClick({ scope }) { |
| | | ElMessage.info(scope.row.name); |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | name: 'slot-btns' |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置,详细移步到 cl-upsert 示例查看 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, // 树形方式选择 |
| | | checkStrictly: true, // 任意层级都能点 |
| | | options: dict.get('occupation') // 使用字典数据 |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 插件的使用 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>plugin</el-tag> |
| | | <span>插件的使用</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/plugin/base.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="插件的使用" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="tsx"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { merge } from 'lodash-es'; |
| | | import { defineComponent } from 'vue'; |
| | | |
| | | // 插件:列标签匹配,方便多个列表公用同一个组件 |
| | | function setColumn(): ClTable.Plugin { |
| | | const columns = { |
| | | UserInfo: { |
| | | label: '用户信息', |
| | | minWidth: 200, |
| | | component: { |
| | | vm: defineComponent({ |
| | | name: 'user-info', |
| | | |
| | | props: { |
| | | scope: null |
| | | }, |
| | | |
| | | setup(props) { |
| | | return () => { |
| | | return ( |
| | | <div> |
| | | <p>{props.scope.name}</p> |
| | | <p>{props.scope.phone}</p> |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } as { [key: string]: DeepPartial<ClTable.Column> }; |
| | | |
| | | return ({ exposed }) => { |
| | | function deep(arr: ClTable.Column[]) { |
| | | arr.forEach(e => { |
| | | if (e.tag) { |
| | | merge(e, columns[e.tag]); |
| | | } |
| | | deep(e.children || []); |
| | | }); |
| | | } |
| | | |
| | | deep(exposed.columns); |
| | | }; |
| | | } |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | tag: 'UserInfo' |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ], |
| | | |
| | | //【很重要】配置插件 |
| | | plugins: [setColumn()] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 行编辑 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>row-edit</el-tag> |
| | | <span>行编辑</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/plugin/row-edit.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="行编辑" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <el-text class="mb-4" tag="p">点击姓名、手机号可以进行编辑</el-text> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { Plugins } from '/#/crud'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140, |
| | | // 【很重要】行编辑,默认 el-input |
| | | edit: true |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140, |
| | | // 【很重要】行编辑,开启、关闭 |
| | | edit: { |
| | | enable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140, |
| | | edit: { |
| | | enable: true, |
| | | // 【很重要】行编辑,组件配置 |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | options: dict.get('occupation'), |
| | | tree: true |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc', |
| | | // 【很重要】行编辑,组件配置 |
| | | edit: { |
| | | enable: true, |
| | | component: { |
| | | name: 'el-date-picker', |
| | | props: { |
| | | type: 'date', |
| | | valueFormat: 'YYYY-MM-DD' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | type: 'op', |
| | | buttons: ['delete'] |
| | | } |
| | | ], |
| | | |
| | | //【很重要】行编辑插件 |
| | | plugins: [Plugins.Table.rowEdit()] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 表头搜索 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>search</el-tag> |
| | | <span>表头搜索</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/search.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="表头搜索" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="tsx"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { Plus } from '@element-plus/icons-vue'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140, |
| | | |
| | | //【很重要】搜索参数配置 |
| | | search: { |
| | | isInput: false, // 默认false,是否输入框模式 |
| | | value: '', // 默认值 |
| | | refreshOnChange: true, // 默认false,搜索时刷新数据,service 的 page 接口请求参数为 { page: 1, [绑定的prop]: 输入值 } |
| | | // 自定义渲染组件 |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | placeholder: '搜索姓名' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140, |
| | | |
| | | //【很重要】搜索参数配置 |
| | | search: { |
| | | // 是否显示搜索图标 |
| | | icon: () => <Plus />, |
| | | |
| | | // 自定义渲染组件 |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | placeholder: '搜索手机号', |
| | | |
| | | // 自定义 change 事件 |
| | | onChange(val) { |
| | | Crud.value?.refresh({ |
| | | page: 1, |
| | | phone: val |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140, |
| | | |
| | | //【很重要】搜索参数配置 |
| | | search: { |
| | | // 是否显示搜索图标 |
| | | icon: () => <cl-svg name="icon-app" size={13} />, |
| | | // 自定义渲染组件 |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | placeholder: '搜索工作', |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 多选框数据 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>selection</el-tag> |
| | | <span>多选框数据</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/selection.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="多选框数据" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <el-button @click="selectRow">选中2行</el-button> |
| | | <el-button :disabled="Table?.selection.length == 0" @click="clear"> |
| | | 取消选择 |
| | | </el-button> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <el-text>已选 {{ Table?.selection.length }} 人</el-text> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh', 'check'], |
| | | |
| | | columns: [ |
| | | { |
| | | type: 'selection' |
| | | }, |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | function selectRow() { |
| | | const [a, b] = Table.value?.data || []; |
| | | |
| | | // 选中2个 |
| | | Table.value?.toggleRowSelection(a); |
| | | Table.value?.toggleRowSelection(b); |
| | | } |
| | | |
| | | function clear() { |
| | | Table.value?.clearSelection(); |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 插槽的使用 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>slot</el-tag> |
| | | <span>插槽的使用</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/slot.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="插槽的使用" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table"> |
| | | <!--【很重要】必须与 prop 名保持一致,格式:column-[prop] --> |
| | | <template #column-name="{ scope }"> |
| | | <cl-row type="flex" align="middle"> |
| | | <cl-avatar :size="36" :style="{ marginRight: '10px' }" /> |
| | | <el-text>{{ scope.row.name }}</el-text> |
| | | </cl-row> |
| | | </template> |
| | | |
| | | <template #column-phone="{ scope }"> 📱{{ scope.row.phone }} </template> |
| | | </cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | headerAlign: 'left', |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 合并行或列 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>span-method</el-tag> |
| | | <span>合并行或列</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/span-method.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="合并行或列" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" :span-method="onSpanMethod" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '存款', |
| | | prop: 'wages', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | interface SpanMethodProps { |
| | | row: any; |
| | | column: any; |
| | | rowIndex: number; |
| | | columnIndex: number; |
| | | } |
| | | |
| | | function onSpanMethod({ row, column, rowIndex, columnIndex }: SpanMethodProps) { |
| | | // 根据实际业务需求调整返回值 { rowspan, colspan } |
| | | if (columnIndex === 0) { |
| | | if (rowIndex % 2 === 0) { |
| | | return { |
| | | rowspan: 2, |
| | | colspan: 1 |
| | | }; |
| | | } else { |
| | | return { |
| | | rowspan: 0, |
| | | colspan: 0 |
| | | }; |
| | | } |
| | | } |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 表尾合计行 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>summary</el-tag> |
| | | <span>表尾合计行</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['table/summary.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="表尾合计行" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <cl-table ref="Table" show-summary :summary-method="getSummaries" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '存款', |
| | | prop: 'wages', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | function getSummaries() { |
| | | return ['合计', '$' + Table.value?.data.reduce((a, b) => a + b.wages, 0)]; |
| | | } |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| New file |
| | |
| | | --- |
| | | description: cl-upsert 组件示例 |
| | | globs: *.tsx, *.ts, *.vue |
| | | --- |
| | | ## 起步 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>base</el-tag> |
| | | <span>起步</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['upsert/base.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="起步" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!-- 打开新增表单的按钮 --> |
| | | <cl-add-btn /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!--【很重要】新增、编辑的表单组件 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | // edit 打开编辑表单 |
| | | buttons: ['edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | //【很重要】该组件基于 cl-form 故很多示例都可复用 |
| | | const Upsert = useUpsert({ |
| | | // 配置如 cl-form 一样 |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 打开、关闭、提交等事件 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>event</el-tag> |
| | | <span>打开、关闭、提交等事件</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['upsert/event.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="事件" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!-- 打开新增表单的按钮 --> |
| | | <cl-add-btn /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!--【很重要】新增、编辑的表单组件 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { useCool } from '/@/cool'; |
| | | |
| | | const { service } = useCool(); |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | // edit 打开编辑表单 |
| | | buttons: ['edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | |
| | | // 以下事件按顺序触发 |
| | | |
| | | // 弹窗打开的事件,这个时候还未有表单数据 |
| | | onOpen() { |
| | | console.log('onOpen'); |
| | | }, |
| | | |
| | | // 获取详情,编辑的时候会触发 |
| | | async onInfo(data, { next, done }) { |
| | | // 不配置 onInfo 的时候默认执行 next(data),调用 service 的 info 接口获取详情 |
| | | // next(data); |
| | | |
| | | // 自定义,需要对请求数据进行处理或者返回处理后的数据 |
| | | const res = await next({ |
| | | id: data.id |
| | | }); |
| | | |
| | | done({ |
| | | ...res, |
| | | name: `[${res.name}]` |
| | | }); |
| | | }, |
| | | |
| | | // 弹窗打开后,已经得到了表单数据 |
| | | onOpened(data) { |
| | | // 判定是否编辑模式 |
| | | if (Upsert.value?.mode == 'update') { |
| | | // 对数据处理 |
| | | data.phone += '000'; |
| | | } |
| | | }, |
| | | |
| | | // 提交事件的钩子 |
| | | // data 表单提交数据 |
| | | // next 继续往下执行 |
| | | // done 关闭加载 |
| | | // close 关闭弹窗 |
| | | async onSubmit(data, { next, done, close }) { |
| | | // 不配置 onSubmit 的时候默认执行 next(data),提交后会去请求 service 的 update/add 接口 |
| | | // next(data); |
| | | |
| | | // 自定义如下 |
| | | // 场景1:提交时对参数额外的处理 |
| | | // next({ |
| | | // ...data, |
| | | // status: 1, |
| | | // createTime: dayjs().format("YYYY-MM-DD") |
| | | // }); |
| | | |
| | | // 场景2:提交前、后的操作 |
| | | // 之前,模拟获取 userId |
| | | const userId = await service.base.sys.user.info({ id: 1 }); |
| | | |
| | | // 返回值 |
| | | const res = await next({ |
| | | userId, |
| | | data |
| | | }); |
| | | |
| | | // 之后 |
| | | // console.log(res); |
| | | }, |
| | | |
| | | // 关闭时触发 |
| | | onClose(action, done) { |
| | | // action 关闭的类型 |
| | | console.log('action,', action); |
| | | |
| | | // 使用 done 关闭窗口 |
| | | done(); |
| | | }, |
| | | |
| | | // 关闭后触发 |
| | | onClosed() { |
| | | console.log('onClosed'); |
| | | } |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## Hook的使用 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>hook</el-tag> |
| | | <span>Hook的使用</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['upsert/hook/index.vue', 'upsert/hook/reg-pca2.ts']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="Hook的使用" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!-- 打开新增表单的按钮 --> |
| | | <cl-add-btn /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!--【很重要】新增、编辑的表单组件 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '省市区', |
| | | prop: 'pca', |
| | | formatter(row) { |
| | | return row.province ? row.province + '-' + row.city + '-' + row.district : '-'; |
| | | }, |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | buttons: ['edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | { |
| | | label: '省市区', |
| | | prop: 'pca2', |
| | | |
| | | //【很重要】hook 参数配置 |
| | | hook: { |
| | | bind(value, { form }) { |
| | | // 将3个参数合并成一个数组,带入级联选择器 |
| | | return [form.province, form.city, form.district]; |
| | | }, |
| | | submit(value, { form, prop }) { |
| | | // 提交的时候将数组拆分成3个字段提交 |
| | | const [province, city, district] = value || []; |
| | | form.province = province; |
| | | form.city = city; |
| | | form.district = district; |
| | | |
| | | // 删除 prop 绑定值 |
| | | form[prop] = undefined; |
| | | } |
| | | }, |
| | | // 注册到全局后可直接使用,注册代码看 ./reg-pca2.ts |
| | | // hook: "pca2", |
| | | |
| | | component: { |
| | | name: 'cl-distpicker' |
| | | } |
| | | }, |
| | | { |
| | | label: '标签', |
| | | prop: 'labels', |
| | | //【很重要】使用内置方法,避免一些辣鸡后端要你这么传给他 |
| | | hook: { |
| | | // labels 的数据为 1,2,3 |
| | | |
| | | // 绑定的时候将 labels 按 , 分割成数组 |
| | | bind: ['split', 'number'], |
| | | |
| | | // 提交的时候将 labels 拼接成字符串 |
| | | submit: ['join'] |
| | | }, |
| | | component: { |
| | | name: 'el-select', |
| | | props: { |
| | | multiple: true |
| | | }, |
| | | options: [ |
| | | { |
| | | label: '帅气', |
| | | value: 1 |
| | | }, |
| | | { |
| | | label: '多金', |
| | | value: 2 |
| | | }, |
| | | { |
| | | label: '有才华', |
| | | value: 3 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 新增、编辑、详情模式 示例 |
| | | |
| | | ```vue |
| | | <template> |
| | | <div class="scope"> |
| | | <div class="h"> |
| | | <el-tag size="small" effect="dark" disable-transitions>mode</el-tag> |
| | | <span>新增、编辑、详情模式</span> |
| | | </div> |
| | | |
| | | <div class="c"> |
| | | <el-button @click="open">预览</el-button> |
| | | <demo-code :files="['upsert/mode.vue']" /> |
| | | |
| | | <!-- 自定义表格组件 --> |
| | | <cl-dialog v-model="visible" title="不同模式" width="80%"> |
| | | <cl-crud ref="Crud"> |
| | | <cl-row> |
| | | <!-- 打开新增表单的按钮 --> |
| | | <cl-add-btn /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <!--【很重要】新增、编辑的表单组件 --> |
| | | <cl-upsert ref="Upsert" /> |
| | | </cl-crud> |
| | | </cl-dialog> |
| | | </div> |
| | | |
| | | <div class="f"> |
| | | <span class="date">2024-01-01</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useCrud, useTable, useUpsert } from '@cool-vue/crud'; |
| | | import { ref } from 'vue'; |
| | | import { useDict } from '/$/dict'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | const { dict } = useDict(); |
| | | |
| | | // cl-crud 配置 |
| | | const Crud = useCrud( |
| | | { |
| | | service: 'test' |
| | | }, |
| | | app => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | // cl-table 配置 |
| | | const Table = useTable({ |
| | | autoHeight: false, |
| | | contextMenu: ['refresh'], |
| | | |
| | | columns: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | dict: dict.get('occupation'), |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | minWidth: 170, |
| | | sortable: 'desc' |
| | | }, |
| | | { |
| | | type: 'op', |
| | | width: 240, |
| | | buttons: ['info', 'edit', 'delete'] |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // cl-upsert 配置 |
| | | const Upsert = useUpsert({ |
| | | items: [ |
| | | { |
| | | label: '姓名', |
| | | prop: 'name', |
| | | component: { |
| | | name: 'el-input' |
| | | } |
| | | }, |
| | | //【很重要】只有返回方法的时候才能使用 Upsert |
| | | () => { |
| | | return { |
| | | label: '手机号', |
| | | prop: 'phone', |
| | | |
| | | // 新增的时候隐藏 |
| | | // hidden: Upsert.value?.mode == "add", |
| | | |
| | | component: { |
| | | name: 'el-input', |
| | | props: { |
| | | // 编辑的时候禁用 |
| | | disabled: Upsert.value?.mode == 'update' |
| | | } |
| | | } |
| | | }; |
| | | }, |
| | | { |
| | | label: '工作', |
| | | prop: 'occupation', |
| | | component: { |
| | | name: 'cl-select', |
| | | props: { |
| | | tree: true, |
| | | checkStrictly: true, |
| | | options: dict.get('occupation') |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | onOpen() { |
| | | ElMessage.info(`当前模式:` + Upsert.value?.mode); |
| | | } |
| | | }); |
| | | |
| | | const visible = ref(false); |
| | | |
| | | function open() { |
| | | visible.value = true; |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| New file |
| | |
| | | # 项目背景 |
| | | |
| | | - 库:typescript、javaScript、scss、vue、tailwind |
| | | - 框架:cool-admin-vue |
| | | - 项目版本:8.x |
| | | |
| | | # 项目目录 |
| | | |
| | | ├── .vscode(代码片段,根据关键字可以快速地生成代码) |
| | | ├── public(静态资源文件) |
| | | ├── packages(源码包:@cool-vue/crud、@cool-vue/vite-plugin) |
| | | ├── build |
| | | │ └── cool() |
| | | │ │ └── eps.json(Eps 配置文件) |
| | | │ │ └── eps.d.ts(Eps 描述文件) |
| | | ├── src |
| | | │ └── cool(核心文件) |
| | | │ └── modules(项目模块) |
| | | │ │ └── base(基础模块) |
| | | │ │ └── demo(示例模块) |
| | | │ │ └── dict(字典模块) |
| | | │ │ └── helper(辅助模块) |
| | | │ │ └── recycle(回收站模块) |
| | | │ │ └── space(cl-upload-space 文件空间模块) |
| | | │ │ └── task(任务模块) |
| | | │ │ └── user(用户模块) |
| | | │ └── plugins(项目插件) |
| | | │ │ └── crud(cl-crud、@cool-vue/crud) |
| | | │ │ └── distpicker(cl-distpicker、省市区选择器) |
| | | │ │ └── echarts(图标) |
| | | │ │ └── editor-preview(编辑器预览组件) |
| | | │ │ └── editor-wange(wang富文本编辑器) |
| | | │ │ └── element-ui(element-plus 组件) |
| | | │ │ └── excel(excel导入、导出组件) |
| | | │ │ └── i18n(多语言) |
| | | │ │ └── iconfont(iconfont 图标) |
| | | │ │ └── theme(cl-theme 主题组件) |
| | | │ │ └── upload(cl-upload 文件上传组件) |
| | | │ │ └── view(cl-view-group、cl-view-head 视图组件) |
| | | │ └── config |
| | | │ │ └── index.ts(默认配置) |
| | | │ │ └── dev.ts(开发环境) |
| | | │ │ └── prod.ts(生产环境) |
| | | │ │ └── proxy.ts(代理配置) |
| | | │ └── App.vue(入口文件) |
| | | │ └── main.ts(入口文件) |
| | | ├── package.json(依赖管理,项目信息) |
| | | └── ... |
| | | |
| | | 模块、插件目录 |
| | | ├── modules/plugins |
| | | │ └── base(模块名) |
| | | │ │ └── components(全局组件) |
| | | │ │ └── directives(全局指令) |
| | | │ │ └── locales(国际化) |
| | | │ │ └── router(路由) |
| | | │ │ └── store(状态管理) |
| | | │ │ └── utils(工具函数) |
| | | │ │ └── views(视图) |
| | | │ │ └── config.ts(必须,模块的配置) |
| | | │ │ └── index.ts(模块导出) |
| | | |
| | | # 其它 |
| | | |
| | | - 文件、组件命名用 - 连接,如:student-info.vue |
| | | - service 的描述类型,查看 build/cool/eps.d.ts 描述文件 |
| | | - 创建模块、插件代码需要读取.cursor/rules的module.mdc,其它的rules根据需要进行参考 |
| | | |
| | | # import 引用别名 |
| | | |
| | | - "/@" 对应 "./src" |
| | | - "/$" 对应 "./src/modules" |
| | | - "/#" 对应 "./src/plugins" |
| | | - "/~" 对应 "./packages" |
| New file |
| | |
| | | node_modules |
| | | .DS_Store |
| | | dist |
| | | dist-ssr |
| | | *.local |
| New file |
| | |
| | | [*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] |
| | | charset = utf-8 |
| | | end_of_line = lf |
| | | indent_style = tab |
| | | indent_size = 4 |
| | | trim_trailing_whitespace = true |
| | | insert_final_newline = true |
| New file |
| | |
| | | # 应用名称 |
| | | VITE_NAME = "COOL-ADMIN" |
| | | |
| | | # 网络超时请求时间 |
| | | VITE_TIMEOUT = 30000 |
| New file |
| | |
| | | *.js text eol=lf |
| | | *.json text eol=lf |
| | | *.ts text eol=lf |
| | | *.vue text eol=lf |
| New file |
| | |
| | | .DS_Store |
| | | node_modules/ |
| | | /dist/ |
| | | dist-ssr/ |
| | | |
| | | # Log files |
| | | npm-debug.log* |
| | | yarn-debug.log* |
| | | yarn-error.log* |
| | | |
| | | # Editor directories and files |
| | | .project |
| | | .idea |
| | | *.suo |
| | | *.ntvs* |
| | | *.njsproj |
| | | *.sln |
| | | *.sw* |
| | | |
| | | vite.config.ts.timestamp* |
| New file |
| | |
| | | { |
| | | "extends": [ |
| | | "development" |
| | | ], |
| | | "hints": { |
| | | "meta-viewport": "off", |
| | | "axe/text-alternatives": [ |
| | | "default", |
| | | { |
| | | "document-title": "off" |
| | | } |
| | | ], |
| | | "disown-opener": "off", |
| | | "css-prefix-order": "off" |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "$schema": "https://json.schemastore.org/prettierrc", |
| | | "semi": true, |
| | | "useTabs": true, |
| | | "tabWidth": 4, |
| | | "printWidth": 100, |
| | | "singleQuote": true, |
| | | "arrowParens": "avoid", |
| | | "trailingComma": "none" |
| | | } |
| New file |
| | |
| | | { |
| | | "module-config": { |
| | | "prefix": "module-config", |
| | | "scope": "typescript", |
| | | "body": [ |
| | | "import { type ModuleConfig } from \"/@/cool\";", |
| | | "", |
| | | "export default (): ModuleConfig => {", |
| | | " return {};", |
| | | "};", |
| | | "" |
| | | ], |
| | | "description": "module config snippets" |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "cl-crud": { |
| | | "prefix": "cl-crud", |
| | | "scope": "vue", |
| | | "body": [ |
| | | "<template>", |
| | | " <cl-crud ref=\"Crud\">", |
| | | " <cl-row>", |
| | | " <!-- 刷新按钮 -->", |
| | | " <cl-refresh-btn />", |
| | | " <!-- 新增按钮 -->", |
| | | " <cl-add-btn />", |
| | | " <!-- 删除按钮 -->", |
| | | " <cl-multi-delete-btn />", |
| | | " <cl-flex1 />", |
| | | " <!-- 条件搜索 -->", |
| | | " <cl-search ref=\"Search\" />", |
| | | " </cl-row>", |
| | | "", |
| | | " <cl-row>", |
| | | " <!-- 数据表格 -->", |
| | | " <cl-table ref=\"Table\" />", |
| | | " </cl-row>", |
| | | "", |
| | | " <cl-row>", |
| | | " <cl-flex1 />", |
| | | " <!-- 分页控件 -->", |
| | | " <cl-pagination />", |
| | | " </cl-row>", |
| | | "", |
| | | " <!-- 新增、编辑 -->", |
| | | " <cl-upsert ref=\"Upsert\" />", |
| | | " </cl-crud>", |
| | | "</template>", |
| | | "", |
| | | "<script lang=\"ts\" setup>", |
| | | "defineOptions({", |
| | | " name: \"$1\"", |
| | | "});", |
| | | "", |
| | | "import { useCrud, useTable, useUpsert, useSearch } from \"@cool-vue/crud\";", |
| | | "import { useCool } from \"/@/cool\";", |
| | | "", |
| | | "const { service } = useCool();", |
| | | "", |
| | | "// cl-upsert", |
| | | "const Upsert = useUpsert({", |
| | | " items: []", |
| | | "});", |
| | | "", |
| | | "// cl-table", |
| | | "const Table = useTable({", |
| | | " columns: []", |
| | | "});", |
| | | "", |
| | | "// cl-search", |
| | | "const Search = useSearch();", |
| | | "", |
| | | "// cl-crud", |
| | | "const Crud = useCrud(", |
| | | " {", |
| | | " service: service$2", |
| | | " },", |
| | | " (app) => {", |
| | | " app.refresh();", |
| | | " }", |
| | | ");", |
| | | "", |
| | | "// 刷新", |
| | | "function refresh(params?: any) {", |
| | | " Crud.value?.refresh(params);", |
| | | "}", |
| | | "</script>", |
| | | "" |
| | | ], |
| | | "description": "cl-crud snippets" |
| | | }, |
| | | "cl-filter": { |
| | | "prefix": "cl-filter", |
| | | "scope": "html", |
| | | "body": [ |
| | | "<cl-filter label=\"\">", |
| | | " <cl-select :options=\"[$1]\" prop=\"\" />", |
| | | "</cl-filter>" |
| | | ], |
| | | "description": "cl-filter snippets" |
| | | }, |
| | | "slot-item": { |
| | | "prefix": "slot item", |
| | | "scope": "html", |
| | | "body": ["<template #slot-$1=\"{ scope }\">", "</template>", ""], |
| | | "description": "slot snippets" |
| | | }, |
| | | "slot-column": { |
| | | "prefix": "slot column", |
| | | "scope": "html", |
| | | "body": ["<template #column-$1=\"{ scope }\">", " ", "</template>", ""], |
| | | "description": "column slot snippets" |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] |
| | | } |
| New file |
| | |
| | | { |
| | | "editor.cursorSmoothCaretAnimation": "on", |
| | | "explorer.fileNesting.enabled": true, |
| | | "explorer.fileNesting.patterns": { |
| | | "tsconfig.json": "tsconfig.*.json, env.d.ts", |
| | | "vite.config.*": "jsconfig*, vitest.config.*, cypress.config.*, playwright.config.*", |
| | | "package.json": "package-lock.json, pnpm*, .yarnrc*, yarn*, .eslint*, eslint*, .prettier*, prettier*, .editorconfig" |
| | | }, |
| | | "editor.codeActionsOnSave": { |
| | | "source.fixAll": "explicit" |
| | | }, |
| | | "editor.formatOnSave": true, |
| | | "editor.defaultFormatter": "esbenp.prettier-vscode", |
| | | "[scss]": { |
| | | "editor.defaultFormatter": "esbenp.prettier-vscode" |
| | | } |
| | | } |
| New file |
| | |
| | | FROM node:lts-alpine |
| | | WORKDIR /build |
| | | # 设置npm镜像 |
| | | RUN npm config set registry https://registry.npmmirror.com |
| | | COPY package.json /build/package.json |
| | | RUN npm install |
| | | COPY ./ /build |
| | | RUN npm run build |
| | | |
| | | FROM nginx |
| | | RUN mkdir /app |
| | | COPY --from=0 /build/dist /app |
| | | COPY --from=0 /build/nginx.conf /etc/nginx/nginx.conf |
| | | EXPOSE 80 |
| New file |
| | |
| | | MIT License |
| | | |
| | | Copyright (c) [2025] [厦门闪酷科技开发有限公司] |
| | | |
| | | Permission is hereby granted, free of charge, to any person obtaining a copy |
| | | of this software and associated documentation files (the "Software"), to deal |
| | | in the Software without restriction, including without limitation the rights |
| | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | | copies of the Software, and to permit persons to whom the Software is |
| | | furnished to do so, subject to the following conditions: |
| | | |
| | | The above copyright notice and this permission notice shall be included in all |
| | | copies or substantial portions of the Software. |
| | | |
| | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| | | SOFTWARE. |
| | | |
| | | --- |
| | | |
| | | MIT 许可证 |
| | | |
| | | 版权所有 (c) [2025] [厦门闪酷科技开发有限公司] |
| | | |
| | | 特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人无限制地处理本软件的权限,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许软件提供给其的人员这样做,但须符合以下条件: |
| | | |
| | | 上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。 |
| | | |
| | | 本软件按“原样”提供,不提供任何明示或暗示的担保,包括但不限于对适销性、特定用途适用性和非侵权的担保。在任何情况下,作者或版权持有人均不对因软件或软件使用或其他交易而产生的任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼或其他诉讼中。 |
| New file |
| | |
| | | declare namespace Eps { |
| | | interface BaseSysDepartmentEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 创建者ID |
| | | */ |
| | | userId?: number; |
| | | |
| | | /** |
| | | * 上级部门ID |
| | | */ |
| | | parentId?: number; |
| | | |
| | | /** |
| | | * 排序 |
| | | */ |
| | | orderNum?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BaseSysLogEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 用户ID |
| | | */ |
| | | userId?: number; |
| | | |
| | | /** |
| | | * 行为 |
| | | */ |
| | | action?: string; |
| | | |
| | | /** |
| | | * ip |
| | | */ |
| | | ip?: string; |
| | | |
| | | /** |
| | | * 参数 |
| | | */ |
| | | params?: any; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 姓名 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BaseSysMenuEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 父菜单ID |
| | | */ |
| | | parentId?: number; |
| | | |
| | | /** |
| | | * 菜单名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 菜单地址 |
| | | */ |
| | | router?: string; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | perms?: string; |
| | | |
| | | /** |
| | | * 类型 0-目录 1-菜单 2-按钮 |
| | | */ |
| | | type?: number; |
| | | |
| | | /** |
| | | * 图标 |
| | | */ |
| | | icon?: string; |
| | | |
| | | /** |
| | | * 排序 |
| | | */ |
| | | orderNum?: number; |
| | | |
| | | /** |
| | | * 视图地址 |
| | | */ |
| | | viewPath?: string; |
| | | |
| | | /** |
| | | * 路由缓存 |
| | | */ |
| | | keepAlive?: boolean; |
| | | |
| | | /** |
| | | * 是否显示 |
| | | */ |
| | | isShow?: boolean; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BaseSysParamEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 键 |
| | | */ |
| | | keyName?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 数据 |
| | | */ |
| | | data?: string; |
| | | |
| | | /** |
| | | * 数据类型 0-字符串 1-富文本 2-文件 |
| | | */ |
| | | dataType?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BaseSysRoleEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 用户ID |
| | | */ |
| | | userId?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 角色标签 |
| | | */ |
| | | label?: string; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 数据权限是否关联上下级 |
| | | */ |
| | | relevance?: boolean; |
| | | |
| | | /** |
| | | * 菜单权限 |
| | | */ |
| | | menuIdList?: any; |
| | | |
| | | /** |
| | | * 部门权限 |
| | | */ |
| | | departmentIdList?: any; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BaseSysUserEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 部门ID |
| | | */ |
| | | departmentId?: number; |
| | | |
| | | /** |
| | | * 创建者ID |
| | | */ |
| | | userId?: number; |
| | | |
| | | /** |
| | | * 姓名 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 用户名 |
| | | */ |
| | | username?: string; |
| | | |
| | | /** |
| | | * 密码 |
| | | */ |
| | | password?: string; |
| | | |
| | | /** |
| | | * 密码版本, 作用是改完密码,让原来的token失效 |
| | | */ |
| | | passwordV?: number; |
| | | |
| | | /** |
| | | * 昵称 |
| | | */ |
| | | nickName?: string; |
| | | |
| | | /** |
| | | * 头像 |
| | | */ |
| | | headImg?: string; |
| | | |
| | | /** |
| | | * 手机 |
| | | */ |
| | | phone?: string; |
| | | |
| | | /** |
| | | * 邮箱 |
| | | */ |
| | | email?: string; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 状态 0-禁用 1-启用 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * socketId |
| | | */ |
| | | socketId?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BasicdataDriverEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 身份证号 |
| | | */ |
| | | businessId?: string; |
| | | |
| | | /** |
| | | * 司机姓名 |
| | | */ |
| | | businessName?: string; |
| | | |
| | | /** |
| | | * 手机号 |
| | | */ |
| | | phone?: string; |
| | | |
| | | /** |
| | | * 驾驶证号 |
| | | */ |
| | | licenseNo?: string; |
| | | |
| | | /** |
| | | * 驾驶证有效期开始 |
| | | */ |
| | | licenseStartDate?: Date; |
| | | |
| | | /** |
| | | * 驾驶证有效期结束 |
| | | */ |
| | | licenseEndDate?: Date; |
| | | |
| | | /** |
| | | * 所属单位 |
| | | */ |
| | | departmentId?: BigInt; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | departmentName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BasicdataIotEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 终端编码 |
| | | */ |
| | | iotCode?: string; |
| | | |
| | | /** |
| | | * 终端名称 |
| | | */ |
| | | iotName?: string; |
| | | |
| | | /** |
| | | * 终端类型 |
| | | */ |
| | | iotTypeCode?: string; |
| | | |
| | | /** |
| | | * 关联业务表 |
| | | */ |
| | | businessType?: string; |
| | | |
| | | /** |
| | | * 业务表ID |
| | | */ |
| | | businessId?: string; |
| | | |
| | | /** |
| | | * 归属单位 |
| | | */ |
| | | departmentId?: number; |
| | | |
| | | /** |
| | | * 终端Key |
| | | */ |
| | | iotKey?: string; |
| | | |
| | | /** |
| | | * 终端Secret |
| | | */ |
| | | iotSecret?: string; |
| | | |
| | | /** |
| | | * 终端上报渠道 |
| | | */ |
| | | iotChanel?: string; |
| | | |
| | | /** |
| | | * 终端通信卡 |
| | | */ |
| | | iotPhone?: string; |
| | | |
| | | /** |
| | | * 通信卡流量包 |
| | | */ |
| | | iotPhonePackage?: string; |
| | | |
| | | /** |
| | | * 安装位置描述 |
| | | */ |
| | | installLocation?: string; |
| | | |
| | | /** |
| | | * 数据格式 |
| | | */ |
| | | dataFormat?: string; |
| | | |
| | | /** |
| | | * 通信协议 |
| | | */ |
| | | protocol?: string; |
| | | |
| | | /** |
| | | * 采集方向 |
| | | */ |
| | | dataDirection?: string; |
| | | |
| | | /** |
| | | * 采集频率 |
| | | */ |
| | | frequency?: string; |
| | | |
| | | /** |
| | | * 数据存储位置 |
| | | */ |
| | | storageLocation?: string; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | departmentName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BasicdataSiteEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 编码 |
| | | */ |
| | | businessId?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | businessName?: string; |
| | | |
| | | /** |
| | | * 归属单位 |
| | | */ |
| | | departmentId?: number; |
| | | |
| | | /** |
| | | * 站点类型 |
| | | */ |
| | | siteType?: string; |
| | | |
| | | /** |
| | | * 地址 |
| | | */ |
| | | address?: string; |
| | | |
| | | /** |
| | | * 负责人 |
| | | */ |
| | | leader?: string; |
| | | |
| | | /** |
| | | * 经度 |
| | | */ |
| | | longitude?: number; |
| | | |
| | | /** |
| | | * 纬度 |
| | | */ |
| | | latitude?: number; |
| | | |
| | | /** |
| | | * 照片 |
| | | */ |
| | | photo?: string; |
| | | |
| | | /** |
| | | * 是否启用 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | departmentName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BasicdataSorterEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 身份证号 |
| | | */ |
| | | businessId?: string; |
| | | |
| | | /** |
| | | * 姓名 |
| | | */ |
| | | businessName?: string; |
| | | |
| | | /** |
| | | * 手机号 |
| | | */ |
| | | phone?: string; |
| | | |
| | | /** |
| | | * 入职日期 |
| | | */ |
| | | hireDate?: Date; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 所属单位 |
| | | */ |
| | | departmentId?: BigInt; |
| | | |
| | | /** |
| | | * 工作站点编码 |
| | | */ |
| | | workSiteId?: string; |
| | | |
| | | /** |
| | | * 身份证正面照 |
| | | */ |
| | | idCardFront?: string; |
| | | |
| | | /** |
| | | * 身份证反面照 |
| | | */ |
| | | idCardBack?: string; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | departmentName?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | workSiteName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BasicdataVehicleEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 车牌号 |
| | | */ |
| | | businessId?: string; |
| | | |
| | | /** |
| | | * 车型 |
| | | */ |
| | | vehicleType?: string; |
| | | |
| | | /** |
| | | * 载重吨数 |
| | | */ |
| | | capacityTon?: number; |
| | | |
| | | /** |
| | | * 默认司机 |
| | | */ |
| | | defaultDriver?: BigInt; |
| | | |
| | | /** |
| | | * 所属单位 |
| | | */ |
| | | departmentId?: BigInt; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | departmentName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BasicdataWastetypeEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 代码 |
| | | */ |
| | | code?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 是否可回收 |
| | | */ |
| | | isRecyclable?: number; |
| | | |
| | | /** |
| | | * 单价 |
| | | */ |
| | | price?: number; |
| | | |
| | | /** |
| | | * 货币 |
| | | */ |
| | | currency?: string; |
| | | |
| | | /** |
| | | * 桶/袋重 |
| | | */ |
| | | packageWeight?: number; |
| | | |
| | | /** |
| | | * 碳减排方向 |
| | | */ |
| | | carbonDirection?: number; |
| | | |
| | | /** |
| | | * 碳减因数 |
| | | */ |
| | | carbonFactor?: number; |
| | | |
| | | /** |
| | | * 因数单位 |
| | | */ |
| | | factorUnit?: string; |
| | | |
| | | /** |
| | | * 公式表达式 |
| | | */ |
| | | formula?: string; |
| | | |
| | | /** |
| | | * 来源标准 |
| | | */ |
| | | sourceStandard?: string; |
| | | |
| | | /** |
| | | * 是否启用 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface DemoGoodsEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 标题 |
| | | */ |
| | | title?: string; |
| | | |
| | | /** |
| | | * 价格 |
| | | */ |
| | | price?: number; |
| | | |
| | | /** |
| | | * 描述 |
| | | */ |
| | | description?: string; |
| | | |
| | | /** |
| | | * 主图 |
| | | */ |
| | | mainImage?: string; |
| | | |
| | | /** |
| | | * 分类 |
| | | */ |
| | | type?: number; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 示例图 |
| | | */ |
| | | exampleImages?: any; |
| | | |
| | | /** |
| | | * 库存 |
| | | */ |
| | | stock?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 昵称 |
| | | */ |
| | | userName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface DictInfoEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 类型ID |
| | | */ |
| | | typeId?: number; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 值 |
| | | */ |
| | | value?: string; |
| | | |
| | | /** |
| | | * 排序 |
| | | */ |
| | | orderNum?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 父ID |
| | | */ |
| | | parentId?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface DictTypeEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 标识 |
| | | */ |
| | | key?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PluginInfoEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 简介 |
| | | */ |
| | | description?: string; |
| | | |
| | | /** |
| | | * Key名 |
| | | */ |
| | | keyName?: string; |
| | | |
| | | /** |
| | | * Hook |
| | | */ |
| | | hook?: string; |
| | | |
| | | /** |
| | | * 描述 |
| | | */ |
| | | readme?: string; |
| | | |
| | | /** |
| | | * 版本 |
| | | */ |
| | | version?: string; |
| | | |
| | | /** |
| | | * Logo(base64) |
| | | */ |
| | | logo?: string; |
| | | |
| | | /** |
| | | * 作者 |
| | | */ |
| | | author?: string; |
| | | |
| | | /** |
| | | * 状态 0-禁用 1-启用 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 内容 |
| | | */ |
| | | content?: any; |
| | | |
| | | /** |
| | | * ts内容 |
| | | */ |
| | | tsContent?: any; |
| | | |
| | | /** |
| | | * 插件的plugin.json |
| | | */ |
| | | pluginJson?: any; |
| | | |
| | | /** |
| | | * 配置 |
| | | */ |
| | | config?: any; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PushAuditlogEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 日志时间 |
| | | */ |
| | | logTime?: Date; |
| | | |
| | | /** |
| | | * 推送类型 |
| | | */ |
| | | pushType?: string; |
| | | |
| | | /** |
| | | * 客户端ID |
| | | */ |
| | | deviceNo?: string; |
| | | |
| | | /** |
| | | * 原始请求内容 |
| | | */ |
| | | requestContent?: string; |
| | | |
| | | /** |
| | | * 错误返回信息 |
| | | */ |
| | | errorMessage?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PushCameraGpsEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 设备序列号 |
| | | */ |
| | | sn?: string; |
| | | |
| | | /** |
| | | * 消息序列号 |
| | | */ |
| | | msgSeq?: string; |
| | | |
| | | /** |
| | | * 消息创建时间 |
| | | */ |
| | | createDate?: Date; |
| | | |
| | | /** |
| | | * GPS定位时间 |
| | | */ |
| | | gpsTime?: Date; |
| | | |
| | | /** |
| | | * 经度 |
| | | */ |
| | | longitude?: number; |
| | | |
| | | /** |
| | | * 纬度 |
| | | */ |
| | | latitude?: number; |
| | | |
| | | /** |
| | | * 速度 |
| | | */ |
| | | speed?: number; |
| | | |
| | | /** |
| | | * 方向角 |
| | | */ |
| | | direction?: number; |
| | | |
| | | /** |
| | | * 海拔高度 |
| | | */ |
| | | elevation?: number; |
| | | |
| | | /** |
| | | * 定位状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PushSiteweightEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 站点编号 |
| | | */ |
| | | businessId?: string; |
| | | |
| | | /** |
| | | * 归属单位 |
| | | */ |
| | | departmentId?: number; |
| | | |
| | | /** |
| | | * 设备号 |
| | | */ |
| | | deviceNo?: string; |
| | | |
| | | /** |
| | | * 上传时间 |
| | | */ |
| | | uploadTime?: Date; |
| | | |
| | | /** |
| | | * 垃圾类型 |
| | | */ |
| | | garbageType?: string; |
| | | |
| | | /** |
| | | * 垃圾重量 |
| | | */ |
| | | weight?: number; |
| | | |
| | | /** |
| | | * 其他数据 |
| | | */ |
| | | extraData?: string; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 部门名称 |
| | | */ |
| | | departmentName?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | garbageName?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | businessName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PushVehicleGpsEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 设备序列号 |
| | | */ |
| | | sn?: string; |
| | | |
| | | /** |
| | | * 消息序列号 |
| | | */ |
| | | msgSeq?: string; |
| | | |
| | | /** |
| | | * 消息创建时间 |
| | | */ |
| | | createDate?: Date; |
| | | |
| | | /** |
| | | * 车牌号 |
| | | */ |
| | | vehicleNo?: string; |
| | | |
| | | /** |
| | | * GPS定位时间 |
| | | */ |
| | | gpsTime?: Date; |
| | | |
| | | /** |
| | | * 经度 |
| | | */ |
| | | longitude?: number; |
| | | |
| | | /** |
| | | * 纬度 |
| | | */ |
| | | latitude?: number; |
| | | |
| | | /** |
| | | * 速度 |
| | | */ |
| | | speed?: number; |
| | | |
| | | /** |
| | | * 方向角 |
| | | */ |
| | | direction?: number; |
| | | |
| | | /** |
| | | * 海拔高度 |
| | | */ |
| | | elevation?: number; |
| | | |
| | | /** |
| | | * 定位状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PushWeightEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 设备号 |
| | | */ |
| | | deviceNo?: string; |
| | | |
| | | /** |
| | | * 上传时间 |
| | | */ |
| | | uploadTime?: Date; |
| | | |
| | | /** |
| | | * 垃圾类型 |
| | | */ |
| | | garbageType?: string; |
| | | |
| | | /** |
| | | * 垃圾重量 |
| | | */ |
| | | weight?: number; |
| | | |
| | | /** |
| | | * 其他数据 |
| | | */ |
| | | extraData?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface RecycleDataEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 表 |
| | | */ |
| | | entityInfo?: any; |
| | | |
| | | /** |
| | | * 操作人 |
| | | */ |
| | | userId?: number; |
| | | |
| | | /** |
| | | * 被删除的数据 |
| | | */ |
| | | data?: any; |
| | | |
| | | /** |
| | | * 请求的接口 |
| | | */ |
| | | url?: string; |
| | | |
| | | /** |
| | | * 请求参数 |
| | | */ |
| | | params?: any; |
| | | |
| | | /** |
| | | * 删除数据条数 |
| | | */ |
| | | count?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 姓名 |
| | | */ |
| | | userName?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface SpaceInfoEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 地址 |
| | | */ |
| | | url?: string; |
| | | |
| | | /** |
| | | * 类型 |
| | | */ |
| | | type?: string; |
| | | |
| | | /** |
| | | * 分类ID |
| | | */ |
| | | classifyId?: number; |
| | | |
| | | /** |
| | | * 文件id |
| | | */ |
| | | fileId?: string; |
| | | |
| | | /** |
| | | * 文件名 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 文件大小 |
| | | */ |
| | | size?: number; |
| | | |
| | | /** |
| | | * 文档版本 |
| | | */ |
| | | version?: number; |
| | | |
| | | /** |
| | | * 文件位置 |
| | | */ |
| | | key?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface SpaceTypeEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 类别名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * 父分类ID |
| | | */ |
| | | parentId?: number; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface TaskInfoEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 任务ID |
| | | */ |
| | | jobId?: string; |
| | | |
| | | /** |
| | | * 任务配置 |
| | | */ |
| | | repeatConf?: string; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | name?: string; |
| | | |
| | | /** |
| | | * cron |
| | | */ |
| | | cron?: string; |
| | | |
| | | /** |
| | | * 最大执行次数 不传为无限次 |
| | | */ |
| | | limit?: number; |
| | | |
| | | /** |
| | | * 每间隔多少毫秒执行一次 如果cron设置了 这项设置就无效 |
| | | */ |
| | | every?: number; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | remark?: string; |
| | | |
| | | /** |
| | | * 状态 0-停止 1-运行 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 开始时间 |
| | | */ |
| | | startDate?: Date; |
| | | |
| | | /** |
| | | * 结束时间 |
| | | */ |
| | | endDate?: Date; |
| | | |
| | | /** |
| | | * 数据 |
| | | */ |
| | | data?: string; |
| | | |
| | | /** |
| | | * 执行的service实例ID |
| | | */ |
| | | service?: string; |
| | | |
| | | /** |
| | | * 状态 0-系统 1-用户 |
| | | */ |
| | | type?: number; |
| | | |
| | | /** |
| | | * 下一次执行时间 |
| | | */ |
| | | nextRunTime?: Date; |
| | | |
| | | /** |
| | | * 状态 0-cron 1-时间间隔 |
| | | */ |
| | | taskType?: number; |
| | | |
| | | /** |
| | | * undefined |
| | | */ |
| | | lastExecuteTime?: Date; |
| | | |
| | | /** |
| | | * undefined |
| | | */ |
| | | lockExpireTime?: Date; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface UserAddressEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 用户ID |
| | | */ |
| | | userId?: number; |
| | | |
| | | /** |
| | | * 联系人 |
| | | */ |
| | | contact?: string; |
| | | |
| | | /** |
| | | * 手机号 |
| | | */ |
| | | phone?: string; |
| | | |
| | | /** |
| | | * 省 |
| | | */ |
| | | province?: string; |
| | | |
| | | /** |
| | | * 市 |
| | | */ |
| | | city?: string; |
| | | |
| | | /** |
| | | * 区 |
| | | */ |
| | | district?: string; |
| | | |
| | | /** |
| | | * 地址 |
| | | */ |
| | | address?: string; |
| | | |
| | | /** |
| | | * 是否默认 |
| | | */ |
| | | isDefault?: boolean; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface UserInfoEntity { |
| | | /** |
| | | * ID |
| | | */ |
| | | id?: number; |
| | | |
| | | /** |
| | | * 登录唯一ID |
| | | */ |
| | | unionid?: string; |
| | | |
| | | /** |
| | | * 头像 |
| | | */ |
| | | avatarUrl?: string; |
| | | |
| | | /** |
| | | * 昵称 |
| | | */ |
| | | nickName?: string; |
| | | |
| | | /** |
| | | * 手机号 |
| | | */ |
| | | phone?: string; |
| | | |
| | | /** |
| | | * 性别 |
| | | */ |
| | | gender?: number; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | status?: number; |
| | | |
| | | /** |
| | | * 登录方式 |
| | | */ |
| | | loginType?: number; |
| | | |
| | | /** |
| | | * 密码 |
| | | */ |
| | | password?: string; |
| | | |
| | | /** |
| | | * 介绍 |
| | | */ |
| | | description?: string; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | createTime?: string; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | updateTime?: string; |
| | | |
| | | /** |
| | | * 任意键值 |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | | |
| | | type json = any; |
| | | |
| | | interface PagePagination { |
| | | size: number; |
| | | page: number; |
| | | total: number; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface PageResponse<T> { |
| | | pagination: PagePagination; |
| | | list: T[]; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface BaseSysLogPageResponse { |
| | | pagination: PagePagination; |
| | | list: BaseSysLogEntity[]; |
| | | } |
| | | |
| | | interface BaseSysMenuPageResponse { |
| | | pagination: PagePagination; |
| | | list: BaseSysMenuEntity[]; |
| | | } |
| | | |
| | | interface BaseSysParamPageResponse { |
| | | pagination: PagePagination; |
| | | list: BaseSysParamEntity[]; |
| | | } |
| | | |
| | | interface BaseSysRolePageResponse { |
| | | pagination: PagePagination; |
| | | list: BaseSysRoleEntity[]; |
| | | } |
| | | |
| | | interface BaseSysUserPageResponse { |
| | | pagination: PagePagination; |
| | | list: BaseSysUserEntity[]; |
| | | } |
| | | |
| | | interface BasicdataDriverPageResponse { |
| | | pagination: PagePagination; |
| | | list: BasicdataDriverEntity[]; |
| | | } |
| | | |
| | | interface BasicdataIotPageResponse { |
| | | pagination: PagePagination; |
| | | list: BasicdataIotEntity[]; |
| | | } |
| | | |
| | | interface BasicdataSitePageResponse { |
| | | pagination: PagePagination; |
| | | list: BasicdataSiteEntity[]; |
| | | } |
| | | |
| | | interface BasicdataSorterPageResponse { |
| | | pagination: PagePagination; |
| | | list: BasicdataSorterEntity[]; |
| | | } |
| | | |
| | | interface BasicdataVehiclePageResponse { |
| | | pagination: PagePagination; |
| | | list: BasicdataVehicleEntity[]; |
| | | } |
| | | |
| | | interface BasicdataWastetypePageResponse { |
| | | pagination: PagePagination; |
| | | list: BasicdataWastetypeEntity[]; |
| | | } |
| | | |
| | | interface DemoGoodsPageResponse { |
| | | pagination: PagePagination; |
| | | list: DemoGoodsEntity[]; |
| | | } |
| | | |
| | | interface DictInfoPageResponse { |
| | | pagination: PagePagination; |
| | | list: DictInfoEntity[]; |
| | | } |
| | | |
| | | interface DictTypePageResponse { |
| | | pagination: PagePagination; |
| | | list: DictTypeEntity[]; |
| | | } |
| | | |
| | | interface PluginInfoPageResponse { |
| | | pagination: PagePagination; |
| | | list: PluginInfoEntity[]; |
| | | } |
| | | |
| | | interface PushAuditlogPageResponse { |
| | | pagination: PagePagination; |
| | | list: PushAuditlogEntity[]; |
| | | } |
| | | |
| | | interface PushSiteweightPageResponse { |
| | | pagination: PagePagination; |
| | | list: PushSiteweightEntity[]; |
| | | } |
| | | |
| | | interface PushWeightPageResponse { |
| | | pagination: PagePagination; |
| | | list: PushWeightEntity[]; |
| | | } |
| | | |
| | | interface PushCameragpsPageResponse { |
| | | pagination: PagePagination; |
| | | list: PushCameraGpsEntity[]; |
| | | } |
| | | |
| | | interface PushVehiclegpsPageResponse { |
| | | pagination: PagePagination; |
| | | list: PushVehicleGpsEntity[]; |
| | | } |
| | | |
| | | interface RecycleDataPageResponse { |
| | | pagination: PagePagination; |
| | | list: RecycleDataEntity[]; |
| | | } |
| | | |
| | | interface SpaceInfoPageResponse { |
| | | pagination: PagePagination; |
| | | list: SpaceInfoEntity[]; |
| | | } |
| | | |
| | | interface SpaceTypePageResponse { |
| | | pagination: PagePagination; |
| | | list: SpaceTypeEntity[]; |
| | | } |
| | | |
| | | interface TaskInfoPageResponse { |
| | | pagination: PagePagination; |
| | | list: TaskInfoEntity[]; |
| | | } |
| | | |
| | | interface UserAddressPageResponse { |
| | | pagination: PagePagination; |
| | | list: UserAddressEntity[]; |
| | | } |
| | | |
| | | interface UserInfoPageResponse { |
| | | pagination: PagePagination; |
| | | list: UserInfoEntity[]; |
| | | } |
| | | |
| | | interface BaseCoding { |
| | | /** |
| | | * 获取模块目录结构 |
| | | */ |
| | | getModuleTree(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 创建代码 |
| | | */ |
| | | createCode(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { getModuleTree: string; createCode: string }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { getModuleTree: boolean; createCode: boolean }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseComm { |
| | | /** |
| | | * 修改个人信息 |
| | | */ |
| | | personUpdate(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 文件上传模式 |
| | | */ |
| | | uploadMode(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限与菜单 |
| | | */ |
| | | permmenu(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 编程 |
| | | */ |
| | | program(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 个人信息 |
| | | */ |
| | | person(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 文件上传 |
| | | */ |
| | | upload(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 退出 |
| | | */ |
| | | logout(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | personUpdate: string; |
| | | uploadMode: string; |
| | | permmenu: string; |
| | | program: string; |
| | | person: string; |
| | | upload: string; |
| | | logout: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | personUpdate: boolean; |
| | | uploadMode: boolean; |
| | | permmenu: boolean; |
| | | program: boolean; |
| | | person: boolean; |
| | | upload: boolean; |
| | | logout: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseOpen { |
| | | /** |
| | | * 刷新token |
| | | */ |
| | | refreshToken(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 验证码 |
| | | */ |
| | | captcha(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 登录 |
| | | */ |
| | | login(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 获得网页内容的参数值 |
| | | */ |
| | | html(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 实体信息与路径 |
| | | */ |
| | | eps(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | refreshToken: string; |
| | | captcha: string; |
| | | login: string; |
| | | html: string; |
| | | eps: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | refreshToken: boolean; |
| | | captcha: boolean; |
| | | login: boolean; |
| | | html: boolean; |
| | | eps: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseSysDepartment { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 排序 |
| | | */ |
| | | order(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BaseSysDepartmentEntity[]>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { delete: string; update: string; order: string; list: string; add: string }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | order: boolean; |
| | | list: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseSysLog { |
| | | /** |
| | | * 日志保存时间 |
| | | */ |
| | | setKeep(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 获得日志保存时间 |
| | | */ |
| | | getKeep(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 清理 |
| | | */ |
| | | clear(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BaseSysLogPageResponse>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { setKeep: string; getKeep: string; clear: string; page: string }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { setKeep: boolean; getKeep: boolean; clear: boolean; page: boolean }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseSysMenu { |
| | | /** |
| | | * 创建代码 |
| | | */ |
| | | create(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 导出 |
| | | */ |
| | | export(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 导入 |
| | | */ |
| | | import(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 解析 |
| | | */ |
| | | parse(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BaseSysMenuEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BaseSysMenuEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BaseSysMenuPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | create: string; |
| | | export: string; |
| | | import: string; |
| | | delete: string; |
| | | update: string; |
| | | parse: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | create: boolean; |
| | | export: boolean; |
| | | import: boolean; |
| | | delete: boolean; |
| | | update: boolean; |
| | | parse: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseSysParam { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 获得网页内容的参数值 |
| | | */ |
| | | html(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BaseSysParamEntity>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BaseSysParamPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | html: string; |
| | | info: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | html: boolean; |
| | | info: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseSysRole { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BaseSysRoleEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BaseSysRoleEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BaseSysRolePageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BaseSysUser { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 移动部门 |
| | | */ |
| | | move(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BaseSysUserEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BaseSysUserEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BaseSysUserPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | move: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | move: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BasicdataDriver { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BasicdataDriverEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BasicdataDriverEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BasicdataDriverPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BasicdataIot { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BasicdataIotEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BasicdataIotEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BasicdataIotPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BasicdataSite { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BasicdataSiteEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BasicdataSiteEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BasicdataSitePageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BasicdataSorter { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BasicdataSorterEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BasicdataSorterEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BasicdataSorterPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BasicdataVehicle { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BasicdataVehicleEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BasicdataVehicleEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BasicdataVehiclePageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface BasicdataWastetype { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<BasicdataWastetypeEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<BasicdataWastetypeEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<BasicdataWastetypePageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface DemoGoods { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<DemoGoodsEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<DemoGoodsEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<DemoGoodsPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface DemoTenant { |
| | | /** |
| | | * 局部不使用多租户 |
| | | */ |
| | | noTenant(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 不使用多租户 |
| | | */ |
| | | noUse(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * use |
| | | */ |
| | | use(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { noTenant: string; noUse: string; use: string }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { noTenant: boolean; noUse: boolean; use: boolean }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface DictInfo { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 获得所有字典类型 |
| | | */ |
| | | types(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 获得字典数据 |
| | | */ |
| | | data(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<DictInfoEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<DictInfoEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<DictInfoPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | types: string; |
| | | data: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | types: boolean; |
| | | data: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface DictType { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<DictTypeEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<DictTypeEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<DictTypePageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface PluginInfo { |
| | | /** |
| | | * 安装插件 |
| | | */ |
| | | install(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<PluginInfoEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<PluginInfoEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<PluginInfoPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | install: string; |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | install: boolean; |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface PushAuditlog { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<PushAuditlogEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<PushAuditlogEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<PushAuditlogPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface PushSiteweight { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<PushSiteweightEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<PushSiteweightEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<PushSiteweightPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface PushWeight { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<PushWeightEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<PushWeightEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<PushWeightPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface PushCameragps { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<PushCameraGpsEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<PushCameraGpsEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<PushCameragpsPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface PushVehiclegps { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<PushVehicleGpsEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<PushVehicleGpsEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<PushVehiclegpsPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface RecycleData { |
| | | /** |
| | | * 恢复数据 |
| | | */ |
| | | restore(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<RecycleDataEntity>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<RecycleDataPageResponse>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { restore: string; info: string; page: string }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { restore: boolean; info: boolean; page: boolean }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface SpaceInfo { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<SpaceInfoEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<SpaceInfoEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<SpaceInfoPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface SpaceType { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<SpaceTypeEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<SpaceTypeEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<SpaceTypePageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface TaskInfo { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 开始 |
| | | */ |
| | | start(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 执行一次 |
| | | */ |
| | | once(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 停止 |
| | | */ |
| | | stop(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<TaskInfoEntity>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<TaskInfoPageResponse>; |
| | | |
| | | /** |
| | | * 日志 |
| | | */ |
| | | log(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | start: string; |
| | | once: string; |
| | | stop: string; |
| | | info: string; |
| | | page: string; |
| | | log: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | start: boolean; |
| | | once: boolean; |
| | | stop: boolean; |
| | | info: boolean; |
| | | page: boolean; |
| | | log: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface UserAddress { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<UserAddressEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<UserAddressEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<UserAddressPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface UserInfo { |
| | | /** |
| | | * 删除 |
| | | */ |
| | | delete(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 修改 |
| | | */ |
| | | update(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 单个信息 |
| | | */ |
| | | info(data?: any): Promise<UserInfoEntity>; |
| | | |
| | | /** |
| | | * 列表查询 |
| | | */ |
| | | list(data?: any): Promise<UserInfoEntity[]>; |
| | | |
| | | /** |
| | | * 分页查询 |
| | | */ |
| | | page(data?: any): Promise<UserInfoPageResponse>; |
| | | |
| | | /** |
| | | * 新增 |
| | | */ |
| | | add(data?: any): Promise<any>; |
| | | |
| | | /** |
| | | * 权限标识 |
| | | */ |
| | | permission: { |
| | | delete: string; |
| | | update: string; |
| | | info: string; |
| | | list: string; |
| | | page: string; |
| | | add: string; |
| | | }; |
| | | |
| | | /** |
| | | * 权限状态 |
| | | */ |
| | | _permission: { |
| | | delete: boolean; |
| | | update: boolean; |
| | | info: boolean; |
| | | list: boolean; |
| | | page: boolean; |
| | | add: boolean; |
| | | }; |
| | | |
| | | request: Request; |
| | | } |
| | | |
| | | interface RequestOptions { |
| | | url: string; |
| | | method?: "OPTIONS" | "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT"; |
| | | data?: any; |
| | | params?: any; |
| | | headers?: any; |
| | | timeout?: number; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | type Request = (options: RequestOptions) => Promise<any>; |
| | | |
| | | type DictKey = |
| | | | "ratedpayload" |
| | | | "iottype" |
| | | | "sitetype" |
| | | | "datachanel" |
| | | | "vehicletype" |
| | | | "businesstype"; |
| | | |
| | | type Service = { |
| | | request: Request; |
| | | |
| | | base: { |
| | | coding: BaseCoding; |
| | | comm: BaseComm; |
| | | open: BaseOpen; |
| | | sys: { |
| | | department: BaseSysDepartment; |
| | | log: BaseSysLog; |
| | | menu: BaseSysMenu; |
| | | param: BaseSysParam; |
| | | role: BaseSysRole; |
| | | user: BaseSysUser; |
| | | }; |
| | | }; |
| | | basicdata: { |
| | | driver: BasicdataDriver; |
| | | iot: BasicdataIot; |
| | | site: BasicdataSite; |
| | | sorter: BasicdataSorter; |
| | | vehicle: BasicdataVehicle; |
| | | wastetype: BasicdataWastetype; |
| | | }; |
| | | demo: { goods: DemoGoods; tenant: DemoTenant }; |
| | | dict: { info: DictInfo; type: DictType }; |
| | | plugin: { info: PluginInfo }; |
| | | push: { |
| | | auditlog: PushAuditlog; |
| | | siteweight: PushSiteweight; |
| | | weight: PushWeight; |
| | | cameragps: PushCameragps; |
| | | vehiclegps: PushVehiclegps; |
| | | }; |
| | | recycle: { data: RecycleData }; |
| | | space: { info: SpaceInfo; type: SpaceType }; |
| | | task: { info: TaskInfo }; |
| | | user: { address: UserAddress; info: UserInfo }; |
| | | }; |
| | | } |
| New file |
| | |
| | | [{"prefix":"/admin/base/coding","name":"","api":[{"method":"get","path":"/getModuleTree"},{"method":"post","path":"/createCode"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/base/comm","name":"","api":[{"method":"post","path":"/personUpdate"},{"method":"get","path":"/uploadMode"},{"method":"get","path":"/permmenu"},{"method":"get","path":"/program"},{"method":"get","path":"/person"},{"method":"post","path":"/upload"},{"method":"post","path":"/logout"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/base/open","name":"","api":[{"method":"get","path":"/refreshToken"},{"method":"get","path":"/captcha"},{"method":"post","path":"/login"},{"method":"get","path":"/html"},{"method":"get","path":"/eps"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/base/sys/department","name":"BaseSysDepartmentEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"post","path":"/order"},{"method":"post","path":"/list"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/base/sys/log","name":"BaseSysLogEntity","api":[{"method":"post","path":"/setKeep"},{"method":"get","path":"/getKeep"},{"method":"post","path":"/clear"},{"method":"post","path":"/page"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"name","type":"string","length":"","comment":"姓名","nullable":true,"source":"b.name"},{"propertyName":"action","type":"string","length":"","comment":"行为","nullable":false,"source":"a.action"},{"propertyName":"ip","type":"string","length":"","comment":"ip","nullable":true,"source":"a.ip"}]}},{"prefix":"/admin/base/sys/menu","name":"BaseSysMenuEntity","api":[{"method":"post","path":"/create"},{"method":"post","path":"/export"},{"method":"post","path":"/import"},{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"post","path":"/parse"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/base/sys/param","name":"BaseSysParamEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/html"},{"method":"get","path":"/info"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"dataType","type":"number","length":"","comment":"数据类型 0-字符串 1-富文本 2-文件 ","nullable":false,"defaultValue":0,"source":"a.dataType"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"name","type":"string","length":"","comment":"名称","nullable":false,"source":"a.name"},{"propertyName":"keyName","type":"string","length":"","comment":"键","nullable":false,"source":"a.keyName"}]}},{"prefix":"/admin/base/sys/role","name":"BaseSysRoleEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"name","type":"string","length":"","comment":"名称","nullable":false,"source":"a.name"},{"propertyName":"label","type":"string","length":"50","comment":"角色标签","nullable":true,"source":"a.label"}]}},{"prefix":"/admin/base/sys/user","name":"BaseSysUserEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"post","path":"/move"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/basicdata/driver","name":"BasicdataDriverEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"departmentId","type":"bigint","length":"","comment":"所属单位","nullable":true,"source":"a.departmentId"},{"propertyName":"status","type":"number","length":"","comment":"状态","nullable":false,"defaultValue":0,"dict":["激活","禁用"],"source":"a.status"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"businessId","type":"string","length":"64","comment":"身份证号","nullable":false,"source":"a.businessId"},{"propertyName":"phone","type":"string","length":"32","comment":"手机号","nullable":true,"source":"a.phone"},{"propertyName":"licenseNo","type":"string","length":"64","comment":"驾驶证号","nullable":true,"source":"a.licenseNo"}]}},{"prefix":"/admin/basicdata/iot","name":"BasicdataIotEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"iotTypeCode","type":"string","length":"","comment":"终端类型","nullable":false,"source":"a.iotTypeCode"},{"propertyName":"status","type":"number","length":"","comment":"状态","nullable":false,"defaultValue":1,"dict":["禁用","启用"],"source":"a.status"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"iotName","type":"string","length":"","comment":"终端名称","nullable":false,"source":"a.iotName"},{"propertyName":"iotCode","type":"string","length":"","comment":"终端编码","nullable":false,"source":"a.iotCode"}]}},{"prefix":"/admin/basicdata/site","name":"BasicdataSiteEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"departmentId","type":"number","length":"","comment":"归属单位","nullable":false,"source":"a.departmentId"},{"propertyName":"siteType","type":"string","length":"","comment":"站点类型","nullable":false,"defaultValue":"收集点","dict":"sitetype","source":"a.siteType"},{"propertyName":"status","type":"number","length":"","comment":"是否启用","nullable":false,"defaultValue":1,"dict":["禁用","启用"],"source":"a.status"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"address","type":"string","length":"","comment":"地址","nullable":false,"source":"a.address"},{"propertyName":"leader","type":"string","length":"","comment":"负责人","nullable":false,"source":"a.leader"}]}},{"prefix":"/admin/basicdata/sorter","name":"BasicdataSorterEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"status","type":"number","length":"","comment":"状态","nullable":false,"defaultValue":0,"dict":["在职","离职","禁用"],"source":"a.status"},{"propertyName":"departmentId","type":"bigint","length":"","comment":"所属单位","nullable":true,"source":"a.departmentId"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"businessName","type":"string","length":"64","comment":"姓名","nullable":false,"source":"a.businessName"},{"propertyName":"businessId","type":"string","length":"32","comment":"身份证号","nullable":true,"source":"a.businessId"},{"propertyName":"phone","type":"string","length":"32","comment":"手机号","nullable":true,"source":"a.phone"}]}},{"prefix":"/admin/basicdata/vehicle","name":"BasicdataVehicleEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"vehicleType","type":"string","length":"","comment":"车型","nullable":false,"defaultValue":"厢式货车","dict":"vehicletype","source":"a.vehicleType"},{"propertyName":"status","type":"number","length":"","comment":"状态","nullable":false,"defaultValue":0,"dict":["启用","禁用"],"source":"a.status"},{"propertyName":"departmentId","type":"bigint","length":"","comment":"所属单位","nullable":true,"source":"a.departmentId"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"businessId","type":"string","length":"32","comment":"车牌号","nullable":false,"source":"a.businessId"},{"propertyName":"defaultDriver","type":"bigint","length":"","comment":"默认司机","nullable":true,"source":"a.defaultDriver"}]}},{"prefix":"/admin/basicdata/wastetype","name":"BasicdataWastetypeEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"isRecyclable","type":"number","length":"","comment":"是否可回收","nullable":false,"defaultValue":0,"dict":["否","是"],"source":"a.isRecyclable"},{"propertyName":"status","type":"number","length":"","comment":"是否启用","nullable":false,"defaultValue":1,"dict":["禁用","启用"],"source":"a.status"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"name","type":"string","length":"","comment":"名称","nullable":false,"source":"a.name"},{"propertyName":"code","type":"string","length":"","comment":"代码","nullable":false,"source":"a.code"}]}},{"prefix":"/admin/demo/goods","name":"DemoGoodsEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"status","type":"number","length":"","comment":"状态","nullable":false,"defaultValue":1,"dict":["禁用","启用"],"source":"a.status"}],"fieldLike":[{"propertyName":"title","type":"string","length":"50","comment":"标题","nullable":false,"source":"a.title"}],"keyWordLikeFields":[{"propertyName":"description","type":"string","length":"","comment":"描述","nullable":true,"source":"a.description"}]}},{"prefix":"/admin/demo/tenant","name":"DemoGoodsEntity","api":[{"method":"post","path":"/noTenant"},{"method":"post","path":"/noUse"},{"method":"post","path":"/use"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/dict/info","name":"DictInfoEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/types"},{"method":"post","path":"/data"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/dict/type","name":"DictTypeEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/plugin/info","name":"PluginInfoEntity","api":[{"method":"post","path":"/install"},{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/push/auditlog","name":"PushAuditlogEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"pushType","type":"string","length":"","comment":"推送类型","nullable":false,"defaultValue":"weight","dict":["weight","health_gps","vehicle_gps","driver_anomaly","others"],"source":"a.pushType"}],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/push/cameragps","name":"PushCameraGpsEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"status","type":"number","length":"","comment":"定位状态","nullable":false,"defaultValue":0,"dict":["有效定位","无效定位"],"source":"a.status"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"sn","type":"string","length":"","comment":"设备序列号","nullable":false,"source":"a.sn"}]}},{"prefix":"/admin/push/siteweight","name":"PushSiteweightEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"deviceNo","type":"string","length":"","comment":"设备号","nullable":false,"source":"a.deviceNo"}],"fieldLike":[{"propertyName":"deviceNo","type":"string","length":"","comment":"设备号","nullable":false,"source":"a.deviceNo"}],"keyWordLikeFields":[]}},{"prefix":"/admin/push/vehiclegps","name":"PushVehicleGpsEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"status","type":"number","length":"","comment":"定位状态","nullable":false,"defaultValue":0,"dict":["有效定位","无效定位"],"source":"a.status"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"sn","type":"string","length":"","comment":"设备序列号","nullable":false,"source":"a.sn"},{"propertyName":"vehicleNo","type":"string","length":"","comment":"车牌号","nullable":true,"source":"a.vehicleNo"}]}},{"prefix":"/admin/push/weight","name":"PushWeightEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"deviceNo","type":"string","length":"","comment":"设备号","nullable":false,"source":"a.deviceNo"},{"propertyName":"garbageType","type":"string","length":"","comment":"垃圾类型","nullable":false,"source":"a.garbageType"}],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/recycle/data","name":"RecycleDataEntity","api":[{"method":"post","path":"/restore"},{"method":"get","path":"/info"},{"method":"post","path":"/page"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"userName","type":"string","length":"","comment":"姓名","nullable":true,"source":"b.name"},{"propertyName":"url","type":"string","length":"","comment":"请求的接口","nullable":true,"source":"a.url"}]}},{"prefix":"/admin/space/info","name":"SpaceInfoEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"type","type":"string","length":"","comment":"类型","nullable":false,"source":"a.type"},{"propertyName":"classifyId","type":"number","length":"","comment":"分类ID","nullable":true,"source":"a.classifyId"}],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/space/type","name":"SpaceTypeEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/task/info","name":"TaskInfoEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"post","path":"/start"},{"method":"post","path":"/once"},{"method":"post","path":"/stop"},{"method":"get","path":"/info"},{"method":"post","path":"/page"},{"method":"get","path":"/log"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"status","type":"number","length":"","comment":"状态 0-停止 1-运行","nullable":false,"defaultValue":1,"source":"a.status"},{"propertyName":"type","type":"number","length":"","comment":"状态 0-系统 1-用户","nullable":false,"defaultValue":0,"source":"a.type"}],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/user/address","name":"UserAddressEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[],"fieldLike":[],"keyWordLikeFields":[]}},{"prefix":"/admin/user/info","name":"UserInfoEntity","api":[{"method":"post","path":"/delete"},{"method":"post","path":"/update"},{"method":"get","path":"/info"},{"method":"post","path":"/list"},{"method":"post","path":"/page"},{"method":"post","path":"/add"}],"search":{"fieldEq":[{"propertyName":"status","type":"number","length":"","comment":"状态","nullable":false,"defaultValue":1,"dict":["禁用","正常","已注销"],"source":"a.status"},{"propertyName":"gender","type":"number","length":"","comment":"性别","nullable":false,"defaultValue":0,"dict":["未知","男","女"],"source":"a.gender"},{"propertyName":"loginType","type":"number","length":"","comment":"登录方式","nullable":false,"defaultValue":0,"dict":["小程序","公众号","H5"],"source":"a.loginType"}],"fieldLike":[],"keyWordLikeFields":[{"propertyName":"nickName","type":"string","length":"","comment":"昵称","nullable":true,"source":"a.nickName"},{"propertyName":"phone","type":"string","length":"","comment":"手机号","nullable":true,"source":"a.phone"}]}}] |
| New file |
| | |
| | | /// <reference types="vite/client" /> |
| | | |
| | | interface ImportMetaEnv { |
| | | readonly VITE_NAME: string; |
| | | readonly VITE_TIMEOUT: number; |
| | | } |
| | | |
| | | interface ImportMeta { |
| | | readonly env: ImportMetaEnv; |
| | | } |
| New file |
| | |
| | | import pluginVue from 'eslint-plugin-vue'; |
| | | import vueTsEslintConfig from '@vue/eslint-config-typescript'; |
| | | import prettier from 'eslint-plugin-prettier'; |
| | | import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'; |
| | | |
| | | export default [ |
| | | { |
| | | name: 'app/files-to-lint', |
| | | files: ['**/*.{ts,mts,tsx,vue}'], |
| | | }, |
| | | |
| | | { |
| | | name: 'app/files-to-ignore', |
| | | ignores: [ |
| | | '**/dist/**', |
| | | '**/dist-ssr/**', |
| | | '**/coverage/**', |
| | | '**/packages/**', |
| | | '**/build/**', |
| | | ], |
| | | }, |
| | | |
| | | ...pluginVue.configs['flat/recommended'], |
| | | ...vueTsEslintConfig(), |
| | | skipFormatting, |
| | | |
| | | { |
| | | languageOptions: { |
| | | parserOptions: { |
| | | ecmaVersion: 2020, |
| | | ecmaFeatures: { |
| | | jsx: true, |
| | | }, |
| | | }, |
| | | }, |
| | | rules: { |
| | | '@typescript-eslint/ban-ts-ignore': 'off', |
| | | '@typescript-eslint/explicit-function-return-type': 'off', |
| | | '@typescript-eslint/no-explicit-any': 'off', |
| | | '@typescript-eslint/no-var-requires': 'off', |
| | | '@typescript-eslint/no-empty-function': 'off', |
| | | '@typescript-eslint/no-use-before-define': 'off', |
| | | '@typescript-eslint/ban-ts-comment': 'off', |
| | | '@typescript-eslint/ban-types': 'off', |
| | | '@typescript-eslint/no-non-null-assertion': 'off', |
| | | '@typescript-eslint/explicit-module-boundary-types': 'off', |
| | | '@typescript-eslint/no-namespace': 'off', |
| | | '@typescript-eslint/no-unused-vars': 'off', |
| | | '@typescript-eslint/no-empty-object-type': 'off', |
| | | 'space-before-function-paren': 'off', |
| | | 'no-unused-vars': 'off', |
| | | 'no-use-before-define': 'off', |
| | | 'no-self-assign': 'off', |
| | | 'vue/no-mutating-props': 'off', |
| | | 'vue/no-template-shadow': 'off', |
| | | 'vue/no-v-html': 'off', |
| | | 'vue/component-name-in-template-casing': ['error', 'kebab-case'], |
| | | 'vue/component-definition-name-casing': ['error', 'kebab-case'], |
| | | 'vue/attributes-order': 'off', |
| | | 'vue/one-component-per-file': 'off', |
| | | 'vue/html-closing-bracket-newline': 'off', |
| | | 'vue/max-attributes-per-line': 'off', |
| | | 'vue/multiline-html-element-content-newline': 'off', |
| | | 'vue/multi-word-component-names': 'off', |
| | | 'vue/singleline-html-element-content-newline': 'off', |
| | | 'vue/attribute-hyphenation': 'off', |
| | | 'vue/html-self-closing': 'off', |
| | | 'vue/require-default-prop': 'off', |
| | | 'vue/v-on-event-hyphenation': 'off', |
| | | 'vue/block-lang': 'off', |
| | | }, |
| | | }, |
| | | ]; |
| New file |
| | |
| | | <!doctype html> |
| | | <html lang="en"> |
| | | <head> |
| | | <meta charset="utf-8" /> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
| | | <meta name="referer" content="never" /> |
| | | <meta name="renderer" content="webkit" /> |
| | | <meta |
| | | name="viewport" |
| | | content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" |
| | | /> |
| | | <title></title> |
| | | <link rel="icon" href="./favicon.ico" /> |
| | | <style> |
| | | html, |
| | | body, |
| | | #app { |
| | | height: 100%; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | * { |
| | | -webkit-font-smoothing: antialiased; |
| | | font-family: |
| | | 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', |
| | | 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; |
| | | } |
| | | |
| | | .preload__wrap { |
| | | display: flex; |
| | | flex-direction: column; |
| | | letter-spacing: 1px; |
| | | background-color: #2f3447; |
| | | position: fixed; |
| | | left: 0; |
| | | top: 0; |
| | | height: 100%; |
| | | width: 100%; |
| | | z-index: 9999; |
| | | transition: all 0.3s ease-in; |
| | | opacity: 1; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .preload__wrap.is-hide { |
| | | opacity: 0; |
| | | } |
| | | |
| | | .preload__container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | width: 100%; |
| | | user-select: none; |
| | | -webkit-user-select: none; |
| | | flex-grow: 1; |
| | | } |
| | | |
| | | .preload__name { |
| | | font-size: 30px; |
| | | color: #fff; |
| | | letter-spacing: 5px; |
| | | font-weight: bold; |
| | | margin-bottom: 30px; |
| | | min-height: 50px; |
| | | } |
| | | |
| | | .preload__title { |
| | | color: #fff; |
| | | font-size: 14px; |
| | | margin: 30px 0 20px 0; |
| | | min-height: 20px; |
| | | } |
| | | |
| | | .preload__sub-title { |
| | | color: #ababab; |
| | | font-size: 12px; |
| | | min-height: 20px; |
| | | } |
| | | |
| | | .preload__name, |
| | | .preload__title, |
| | | .preload__sub-title { |
| | | animation: s 0.5s ease-in; |
| | | } |
| | | |
| | | @keyframes s { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | .preload__loading { |
| | | height: 44px; |
| | | width: 44px; |
| | | border-radius: 30px; |
| | | border: 7px solid currentColor; |
| | | border-bottom-color: #2f3447; |
| | | position: relative; |
| | | animation: |
| | | r 1s infinite cubic-bezier(0.17, 0.67, 0.83, 0.67), |
| | | bc 2s infinite ease-in; |
| | | transform: rotate(0deg); |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | @keyframes r { |
| | | from { |
| | | transform: rotate(0deg); |
| | | } |
| | | |
| | | to { |
| | | transform: rotate(360deg); |
| | | } |
| | | } |
| | | |
| | | .preload__loading::after, |
| | | .preload__loading::before { |
| | | content: ''; |
| | | display: inline-block; |
| | | position: absolute; |
| | | bottom: -2px; |
| | | height: 7px; |
| | | width: 7px; |
| | | border-radius: 10px; |
| | | background-color: currentColor; |
| | | } |
| | | |
| | | .preload__loading::after { |
| | | left: -1px; |
| | | } |
| | | |
| | | .preload__loading::before { |
| | | right: -1px; |
| | | } |
| | | |
| | | @keyframes bc { |
| | | 0% { |
| | | color: #689cc5; |
| | | } |
| | | |
| | | 25% { |
| | | color: #b3b7e2; |
| | | } |
| | | |
| | | 50% { |
| | | color: #93dbe9; |
| | | } |
| | | |
| | | 75% { |
| | | color: #abbd81; |
| | | } |
| | | |
| | | 100% { |
| | | color: #689cc5; |
| | | } |
| | | } |
| | | </style> |
| | | </head> |
| | | |
| | | <body> |
| | | <div class="preload__wrap" id="Loading"> |
| | | <div class="preload__container"> |
| | | <div class="preload__name"></div> |
| | | <div class="preload__loading"></div> |
| | | <div class="preload__title"></div> |
| | | <div class="preload__sub-title"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div id="app"></div> |
| | | <script type="module" src="/src/main.ts"></script> |
| | | </body> |
| | | </html> |
| New file |
| | |
| | | user nginx; |
| | | worker_processes 1; |
| | | error_log /var/log/nginx/error.log warn; |
| | | pid /var/run/nginx.pid; |
| | | events { |
| | | worker_connections 1024; |
| | | } |
| | | http { |
| | | include /etc/nginx/mime.types; |
| | | default_type application/octet-stream; |
| | | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' |
| | | '$status $body_bytes_sent "$http_referer" ' |
| | | '"$http_user_agent" "$http_x_forwarded_for"'; |
| | | access_log /var/log/nginx/access.log main; |
| | | sendfile on; |
| | | keepalive_timeout 65; |
| | | upstream cool { |
| | | server midway:8001; |
| | | } |
| | | |
| | | server { |
| | | listen 80; |
| | | server_name localhost; |
| | | location / { |
| | | root /app; |
| | | index index.html; |
| | | try_files $uri $uri/ /index.html; |
| | | } |
| | | location /api/ { |
| | | proxy_pass http://cool/; |
| | | proxy_set_header Host $host; |
| | | proxy_set_header X-Real-IP $remote_addr; |
| | | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
| | | proxy_set_header REMOTE-HOST $remote_addr; |
| | | |
| | | #缓存相关配置 |
| | | #proxy_cache cache_one; |
| | | #proxy_cache_key $host$request_uri$is_args$args; |
| | | #proxy_cache_valid 200 304 301 302 1h; |
| | | |
| | | #持久化连接相关配置 |
| | | proxy_connect_timeout 3000s; |
| | | proxy_read_timeout 86400s; |
| | | proxy_send_timeout 3000s; |
| | | #proxy_http_version 1.1; |
| | | #proxy_set_header Upgrade $http_upgrade; |
| | | #proxy_set_header Connection "upgrade"; |
| | | |
| | | add_header X-Cache $upstream_cache_status; |
| | | |
| | | #expires 12h; |
| | | } |
| | | |
| | | # socket需额外配置 |
| | | location /socket { |
| | | proxy_pass http://cool/socket; |
| | | proxy_connect_timeout 3600s; #配置点1 |
| | | proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点 |
| | | proxy_send_timeout 3600s; #配置点3 |
| | | proxy_set_header Host $host; |
| | | proxy_set_header X-Real-IP $remote_addr; |
| | | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
| | | proxy_set_header REMOTE-HOST $remote_addr; |
| | | #proxy_bind $remote_addr transparent; |
| | | proxy_http_version 1.1; |
| | | proxy_set_header Upgrade $http_upgrade; |
| | | proxy_set_header Connection "upgrade"; |
| | | rewrite /socket/(.*) /$1 break; |
| | | proxy_redirect off; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "name": "cool-admin-vue", |
| | | "version": "8.0.0", |
| | | "type": "module", |
| | | "scripts": { |
| | | "dev": "vite --host", |
| | | "build": "vite build", |
| | | "build-static": "vite build --mode static", |
| | | "build-demo": "vite build --mode demo", |
| | | "preview": "vite preview", |
| | | "type-check": "vue-tsc --build --force", |
| | | "lint": "eslint . --fix", |
| | | "format": "prettier --write src/" |
| | | }, |
| | | "dependencies": { |
| | | "@cool-vue/crud": "^8.0.6", |
| | | "@element-plus/icons-vue": "^2.3.1", |
| | | "@vueuse/core": "^12.5.0", |
| | | "@wangeditor/editor": "^5.1.23", |
| | | "@wangeditor/editor-for-vue": "^5.1.12", |
| | | "axios": "^1.7.9", |
| | | "chardet": "^2.0.0", |
| | | "core-js": "^3.40.0", |
| | | "dayjs": "^1.11.13", |
| | | "echarts": "^5.6.0", |
| | | "element-plus": "2.10.2", |
| | | "file-saver": "^2.0.5", |
| | | "lodash-es": "^4.17.21", |
| | | "marked": "^14.1.3", |
| | | "mitt": "^3.0.1", |
| | | "nprogress": "^0.2.0", |
| | | "pinia": "^2.3.1", |
| | | "store": "^2.0.12", |
| | | "vue": "^3.5.13", |
| | | "vue-echarts": "^7.0.3", |
| | | "vue-i18n": "^11.0.1", |
| | | "vue-router": "^4.5.0", |
| | | "vuedraggable": "^4.1.0", |
| | | "xlsx": "^0.18.5" |
| | | }, |
| | | "devDependencies": { |
| | | "@cool-vue/vite-plugin": "^8.2.2", |
| | | "@intlify/unplugin-vue-i18n": "^6.0.3", |
| | | "@rushstack/eslint-patch": "^1.10.5", |
| | | "@tsconfig/node20": "^20.1.4", |
| | | "@types/file-saver": "^2.0.7", |
| | | "@types/lodash-es": "^4.17.12", |
| | | "@types/mockjs": "^1.0.10", |
| | | "@types/node": "^20.17.17", |
| | | "@types/nprogress": "^0.2.3", |
| | | "@types/store": "^2.0.5", |
| | | "@vitejs/plugin-vue": "^5.2.1", |
| | | "@vitejs/plugin-vue-jsx": "^4.1.1", |
| | | "@vue/compiler-sfc": "^3.5.13", |
| | | "@vue/eslint-config-prettier": "^10.2.0", |
| | | "@vue/eslint-config-typescript": "^14.3.0", |
| | | "@vue/test-utils": "^2.4.6", |
| | | "@vue/tsconfig": "^0.5.1", |
| | | "autoprefixer": "^10.4.20", |
| | | "eslint": "^9.19.0", |
| | | "eslint-plugin-prettier": "^5.2.3", |
| | | "eslint-plugin-vue": "^9.32.0", |
| | | "postcss": "^8.5.1", |
| | | "prettier": "^3.4.2", |
| | | "rollup-plugin-visualizer": "^5.14.0", |
| | | "sass": "1.81.0", |
| | | "tailwindcss": "^3.4.17", |
| | | "terser": "^5.36.0", |
| | | "typescript": "~5.5.4", |
| | | "vite": "^5.4.14", |
| | | "vite-plugin-compression": "^0.5.1", |
| | | "vite-plugin-vue-devtools": "^7.7.1", |
| | | "vue-tsc": "^2.2.0" |
| | | } |
| | | } |
| New file |
| | |
| | | .DS_Store |
| | | node_modules |
| | | /dist |
| | | |
| | | |
| | | # local env files |
| | | .env.local |
| | | .env.*.local |
| | | |
| | | # Log files |
| | | npm-debug.log* |
| | | yarn-debug.log* |
| | | yarn-error.log* |
| | | pnpm-debug.log* |
| | | |
| | | # Editor directories and files |
| | | .idea |
| | | .vscode |
| | | *.suo |
| | | *.ntvs* |
| | | *.njsproj |
| | | *.sln |
| | | *.sw? |
| New file |
| | |
| | | { |
| | | "tabWidth": 4, |
| | | "useTabs": true, |
| | | "semi": true, |
| | | "jsxBracketSameLine": true, |
| | | "singleQuote": false, |
| | | "printWidth": 100, |
| | | "trailingComma": "none" |
| | | } |
| New file |
| | |
| | | # 介绍 |
| | | |
| | | **cool-admin for vue**是基于[Vue.js](https://v3.cn.vuejs.org)开发。 |
| | | |
| | | [cool-admin 官方文档](https://cool-js.com/) |
| | | |
| | | 尝试 `cool-admin` 最简单的方法就是查看文档及运行示例。 |
| | | |
| | | <img src='https://vue.cool-admin.com/show/admin.png' /> |
| | | |
| | | [Ai极速编码 🔥 在线体验](https://show.cool-admin.com/helper/ai-code) |
| | | |
| | | <img src='https://vue.cool-admin.com/show/code.png' /> |
| | | |
| | | ## 代码仓库 |
| | | |
| | | **cool-admin for vue** 是开源免费的,遵循[MIT](https://baike.baidu.com/item/MIT/10772952)开源协议,意味着您无需支付任何费用,也无需授权,即可将它应用到您的产品中。 |
| | | |
| | | 开源免费,并不意味着您可以将 cool-admin 应用到非法的领域,比如涉及赌博,暴力等方面。如因此产生纠纷等法律问题,`cool-admin`不承担任何责任。 |
| | | |
| | | [https://github.com/cool-team-official/cool-admin-vue](https://github.com/cool-team-official/cool-admin-vue) |
| | | |
| | | ```shell |
| | | git clone https://github.com/cool-team-official/cool-admin-vue.git |
| | | ``` |
| | | |
| | | ## 技术选型 |
| | | |
| | | - [Vue.js](https://v3.cn.vuejs.org),基础框架; |
| | | - [VueRouter](https://router.vuejs.org),Vue.js 官方路由; |
| | | - [Pinia](https://pinia.vuejs.org),轻量级状态管理库; |
| | | - [ElementPlus](https://element-plus.gitee.io/zh-CN),桌面端组件库; |
| | | - [Vite](https://vitejs.cn),构建工具; |
| New file |
| | |
| | | // vue |
| | | declare namespace Vue { |
| | | interface Ref<T = any> { |
| | | value: T; |
| | | } |
| | | |
| | | type Emit = (name: any, ...args: any[]) => void; |
| | | } |
| | | |
| | | // element-plus |
| | | declare namespace ElementPlus { |
| | | type Size = "large" | "default" | "small"; |
| | | type Align = "left" | "center" | "right"; |
| | | |
| | | interface FormProps { |
| | | inline?: boolean; |
| | | labelPosition?: "left" | "right" | "top"; |
| | | labelWidth?: string | number; |
| | | labelSuffix?: string; |
| | | hideRequiredAsterisk?: boolean; |
| | | showMessage?: boolean; |
| | | inlineMessage?: boolean; |
| | | statusIcon?: boolean; |
| | | validateOnRuleChange?: boolean; |
| | | size?: Size; |
| | | disabled?: boolean; |
| | | [key: string]: any; |
| | | } |
| | | } |
| | | |
| | | // mitt |
| | | declare interface Mitt { |
| | | on(name: string, callback: (data: any) => void): void; |
| | | off(name: string, callback: (data: any) => void): void; |
| | | emit(name: string, data?: any): void; |
| | | } |
| | | |
| | | // emitter |
| | | declare interface EmitterItem { |
| | | name: string; |
| | | callback(data: any, events: { refresh(params: any): void; crudList: ClCrud.Ref[] }): void; |
| | | } |
| | | |
| | | declare interface Emitter { |
| | | list: EmitterItem[]; |
| | | init(events: any): void; |
| | | on(name: string, callback: (data: any) => void): void; |
| | | emit(name: string, data?: any): void; |
| | | } |
| | | |
| | | // 方法 |
| | | declare type fn = () => void; |
| | | |
| | | // 对象 |
| | | declare type obj = { |
| | | [key: string]: any; |
| | | }; |
| | | |
| | | // 全部可选 |
| | | declare type DeepPartial<T> = T extends Function |
| | | ? T |
| | | : T extends object |
| | | ? { [P in keyof T]?: DeepPartial<T[P]> } |
| | | : T; |
| | | |
| | | // 合并 |
| | | declare type Merge<A, B> = Omit<A, keyof B> & B; |
| | | |
| | | // 移除 [key] |
| | | declare type RemoveIndex<T> = { |
| | | [P in keyof T as string extends P ? never : number extends P ? never : P]: T[P]; |
| | | }; |
| | | |
| | | // 任用列表 |
| | | declare type List<T> = Array<DeepPartial<T> | (() => DeepPartial<T>)>; |
| | | |
| | | // 获取keys |
| | | declare type PropKey<T> = keyof RemoveIndex<T> | (string & {}); |
| | | |
| | | // 任意字符串 |
| | | declare type AnyString = string & {}; |
| | | |
| | | // 类型或者 Ref 泛型 |
| | | declare type RefData<T = any> = T | Vue.Ref<T>; |
| | | |
| | | // browser |
| | | declare type Browser = { |
| | | screen: string; |
| | | isMini: boolean; |
| | | }; |
| | | |
| | | // 字典选项 |
| | | declare type DictOptions = { |
| | | label?: string; |
| | | value?: any; |
| | | color?: string; |
| | | type?: string; |
| | | [key: string]: any; |
| | | }[]; |
| | | |
| | | // render |
| | | declare namespace Render { |
| | | type OpButton = |
| | | | `slot-${string}` |
| | | | { |
| | | label: string; |
| | | type?: string; |
| | | hidden?: boolean; |
| | | onClick(options: { scope: obj }): void; |
| | | [key: string]: any; |
| | | }; |
| | | |
| | | interface Props { |
| | | onChange?(value: any): void; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Component { |
| | | name?: string; |
| | | options?: RefData<DictOptions>; |
| | | props?: RefData<Props>; |
| | | style?: obj; |
| | | slots?: { |
| | | [key: string]: (data?: any) => any; |
| | | }; |
| | | vm?: any; |
| | | [key: string]: any; |
| | | } |
| | | } |
| | | |
| | | // crud |
| | | declare namespace ClCrud { |
| | | declare interface Field { |
| | | comment: string; |
| | | source: string; |
| | | propertyName: string; |
| | | type: string; |
| | | dict: string | string[]; |
| | | nullable: boolean; |
| | | } |
| | | |
| | | interface Label { |
| | | op: string; |
| | | add: string; |
| | | delete: string; |
| | | multiDelete: string; |
| | | update: string; |
| | | refresh: string; |
| | | info: string; |
| | | search: string; |
| | | reset: string; |
| | | clear: string; |
| | | save: string; |
| | | close: string; |
| | | confirm: string; |
| | | advSearch: string; |
| | | searchKey: string; |
| | | placeholder: string; |
| | | placeholderSelect: string; |
| | | tips: string; |
| | | saveSuccess: string; |
| | | deleteSuccess: string; |
| | | deleteConfirm: string; |
| | | empty: string; |
| | | desc: string; |
| | | asc: string; |
| | | select: string; |
| | | deselect: string; |
| | | seeMore: string; |
| | | hideContent: string; |
| | | nonEmpty: string; |
| | | collapse: string; |
| | | expand: string; |
| | | [key: string]: string; |
| | | } |
| | | |
| | | interface Dict { |
| | | primaryId: string; |
| | | api: { |
| | | list: string; |
| | | add: string; |
| | | update: string; |
| | | delete: string; |
| | | info: string; |
| | | page: string; |
| | | }; |
| | | pagination: { |
| | | page: string; |
| | | size: string; |
| | | }; |
| | | search: { |
| | | keyWord: string; |
| | | query: string; |
| | | }; |
| | | sort: { |
| | | order: string; |
| | | prop: string; |
| | | }; |
| | | label: Label; |
| | | } |
| | | |
| | | interface Permission { |
| | | page?: boolean; |
| | | list?: boolean; |
| | | add?: boolean; |
| | | delete?: boolean; |
| | | update?: boolean; |
| | | info?: boolean; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Params { |
| | | page: { |
| | | page?: number; |
| | | size?: number; |
| | | [key: string]: any; |
| | | }; |
| | | list: obj; |
| | | add: obj; |
| | | delete: { |
| | | ids?: any[]; |
| | | [key: string]: any; |
| | | }; |
| | | update: { |
| | | id?: any; |
| | | [key: string]: any; |
| | | }; |
| | | info: { |
| | | id?: any; |
| | | [key: string]: any; |
| | | }; |
| | | } |
| | | |
| | | interface Response { |
| | | page: { |
| | | list: any[]; |
| | | pagination: { |
| | | total: number; |
| | | page: number; |
| | | size: number; |
| | | [key: string]: any; |
| | | }; |
| | | [key: string]: any; |
| | | }; |
| | | list: any[]; |
| | | add: any; |
| | | update: any; |
| | | info: any; |
| | | delete: any; |
| | | } |
| | | |
| | | interface Service { |
| | | api: { |
| | | page(params?: Params["page"]): Promise<Response["page"]>; |
| | | list(params?: Params["list"]): Promise<Response["list"]>; |
| | | add(params?: Params["add"]): Promise<Response["add"]>; |
| | | update(params?: Params["update"]): Promise<Response["update"]>; |
| | | info(params?: Params["info"]): Promise<Response["info"]>; |
| | | delete(params?: Params["delete"]): Promise<Response["delete"]>; |
| | | permission: Permission; |
| | | search: { |
| | | fieldEq: Field[]; |
| | | fieldLike: Field[]; |
| | | keyWordLikeFields: Field[]; |
| | | }; |
| | | [key: string]: any; |
| | | }; |
| | | } |
| | | |
| | | interface Config { |
| | | name: string; |
| | | service: Service["api"]; |
| | | permission: Permission; |
| | | dict: Dict; |
| | | onRefresh( |
| | | params: obj, |
| | | event: { |
| | | done: fn; |
| | | next: Service["api"]["page"]; |
| | | render: (data: any | any[], pagination?: Response["page"]["pagination"]) => void; |
| | | } |
| | | ): void; |
| | | onDelete( |
| | | selection: obj[], |
| | | event: { |
| | | next: Service["api"]["delete"]; |
| | | } |
| | | ): void; |
| | | } |
| | | |
| | | interface Ref { |
| | | "cl-table": ClTable.Ref; |
| | | "cl-upsert": ClUpsert.Ref; |
| | | id: number; |
| | | mitt: Mitt; |
| | | name: string; |
| | | routePath: string; |
| | | permission: Permission; |
| | | dict: Dict; |
| | | service: Service["api"]; |
| | | loading: boolean; |
| | | params: obj; |
| | | selection: obj[]; |
| | | set(key: "dict" | "style" | "service" | "permission", value: any): void; |
| | | done(): void; |
| | | getParams(): obj; |
| | | setParams(data: obj): void; |
| | | getPermission(key?: string): boolean; |
| | | rowInfo(data: obj): void; |
| | | rowAdd(): void; |
| | | rowEdit(data: obj): void; |
| | | rowAppend(data?: obj): void; |
| | | rowClose(): void; |
| | | rowDelete(...selection: obj[]): void; |
| | | proxy(name: string, data?: any[]): any; |
| | | paramsReplace(params: obj): obj; |
| | | refresh: Service["api"]["page"]; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Options extends DeepPartial<Config> { |
| | | service?: any; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClTable { |
| | | type OpButton = Array<"info" | "edit" | "delete" | AnyString | Render.OpButton>; |
| | | |
| | | type ColumnType = "index" | "selection" | "expand" | "op" | AnyString; |
| | | |
| | | interface Column<T = any> { |
| | | type: ColumnType; |
| | | hidden: RefData<boolean>; |
| | | component: Render.Component; |
| | | search: { |
| | | isInput: boolean; |
| | | value: any; |
| | | icon: () => any; |
| | | refreshOnChange: boolean; |
| | | component: Render.Component; |
| | | }; |
| | | dict: RefData<DictOptions>; |
| | | dictFormatter: (values: DictOptions) => string; |
| | | dictColor: boolean; |
| | | dictSeparator: string; |
| | | dictAllLevels: boolean; |
| | | buttons: OpButton | ((options: { scope: T }) => OpButton); |
| | | align: ElementPlus.Align; |
| | | label: any; |
| | | renderLabel: (options: { column: any; $index: number }) => any; |
| | | className: string; |
| | | prop: PropKey<T>; |
| | | orderNum: number; |
| | | width: RefData<number | string>; |
| | | minWidth: RefData<number | string>; |
| | | renderHeader: (options: { column: any; $index: number }) => any; |
| | | sortable: boolean | "desc" | "descending" | "ascending" | "asc" | "custom"; |
| | | sortMethod: fn; |
| | | sortBy: string | ((row: T, index: number) => any) | any[]; |
| | | resizable: boolean; |
| | | columnKey: string; |
| | | headerAlign: ElementPlus.Align; |
| | | showOverflowTooltip: boolean; |
| | | fixed: boolean | string; |
| | | render: (row: T, column: any, value: any, index: number) => any; |
| | | formatter: (row: T, column: any, value: any, index: number) => any; |
| | | selectable: (row: T, index: number) => boolean; |
| | | reserveSelection: boolean; |
| | | filterMethod: fn; |
| | | filteredValue: unknown[]; |
| | | filters: unknown[]; |
| | | filterPlacement: string; |
| | | filterMultiple: boolean; |
| | | index: ((index: number) => number) | number; |
| | | sortOrders: unknown[]; |
| | | children: Column<T>[]; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | type ContextMenu = Array< |
| | | | ClContextMenu.Item |
| | | | ((row: obj, column: obj, event: PointerEvent) => ClContextMenu.Item) |
| | | | "refresh" |
| | | | "check" |
| | | | "update" |
| | | | "edit" |
| | | | "delete" |
| | | | "info" |
| | | | "order-desc" |
| | | | "order-asc" |
| | | >; |
| | | |
| | | type Plugin = (options: { exposed: Ref }) => void; |
| | | |
| | | interface Config<T = any> { |
| | | columns: Column<T>[]; |
| | | autoHeight: boolean; |
| | | height: any; |
| | | contextMenu: ContextMenu; |
| | | defaultSort: { |
| | | prop: string; |
| | | order: "descending" | "ascending"; |
| | | }; |
| | | sortRefresh: boolean; |
| | | emptyText: string; |
| | | rowKey: string; |
| | | on?: { |
| | | [key: string]: (...args: any[]) => void; |
| | | }; |
| | | props?: { |
| | | [key: string]: any; |
| | | }; |
| | | plugins?: Plugin[]; |
| | | onRowContextmenu?(row: T, column: any, event: any): void; |
| | | } |
| | | |
| | | interface Ref<T = any> { |
| | | Table: any; |
| | | config: obj; |
| | | selection: T[]; |
| | | data: T[]; |
| | | columns: Column<T>[]; |
| | | reBuild(cb?: fn): void; |
| | | calcMaxHeight(): void; |
| | | setData(data: T[]): void; |
| | | setColumns(columns: Column[]): void; |
| | | showColumn(props: PropKey<T> | PropKey<T>[], status?: boolean): void; |
| | | hideColumn(props: PropKey<T> | PropKey<T>[]): void; |
| | | changeSort(prop: PropKey<T>, order: string): void; |
| | | clearSelection(): void; |
| | | getSelectionRows(): any[]; |
| | | toggleRowSelection(row: T, selected?: boolean): void; |
| | | toggleAllSelection(): void; |
| | | toggleRowExpansion(row: T, expanded?: boolean): void; |
| | | setCurrentRow(row: T): void; |
| | | clearSort(): void; |
| | | clearFilter(columnKeys: PropKey<T>[]): void; |
| | | doLayout(): void; |
| | | sort(prop: PropKey<T>, order: string): void; |
| | | scrollTo(position: { top?: number; left?: number }): void; |
| | | setScrollTop(top: number): void; |
| | | setScrollLeft(left: number): void; |
| | | updateKeyChildren(key: string, children: any[]): void; |
| | | } |
| | | |
| | | interface Options<T = any> extends DeepPartial<Config<T>> { |
| | | columns?: List<ClTable.Column<T>>; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClFormTabs { |
| | | type labels = { |
| | | label: string; |
| | | value: string; |
| | | name?: string; |
| | | icon?: any; |
| | | lazy?: boolean; |
| | | [key: string]: any; |
| | | }[]; |
| | | } |
| | | |
| | | declare namespace ClForm { |
| | | type CloseAction = "close" | "save" | AnyString; |
| | | |
| | | interface Rule { |
| | | type?: |
| | | | "string" |
| | | | "number" |
| | | | "boolean" |
| | | | "method" |
| | | | "regexp" |
| | | | "integer" |
| | | | "float" |
| | | | "array" |
| | | | "object" |
| | | | "enum" |
| | | | "date" |
| | | | "url" |
| | | | "hex" |
| | | | "email" |
| | | | "any"; |
| | | required?: boolean; |
| | | message?: string; |
| | | min?: number; |
| | | max?: number; |
| | | trigger?: any; |
| | | validator?(rule: any, value: any, callback: (error?: Error) => void): void; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Hook { |
| | | Fn: (value: any, options: { form: obj; prop: string; method: "submit" | "bind" }) => any; |
| | | Key: |
| | | | "number" |
| | | | "string" |
| | | | "split" |
| | | | "join" |
| | | | "boolean" |
| | | | "booleanNumber" |
| | | | "datetimeRange" |
| | | | "splitJoin" |
| | | | "json" |
| | | | "empty" |
| | | | AnyString; |
| | | Pipe: Hook["Key"] | Hook["Fn"]; |
| | | Event: { |
| | | bind?: Hook["Pipe"] | Hook["Pipe"][]; |
| | | submit?: Hook["Pipe"] | Hook["Pipe"][]; |
| | | reset?: (prop: string) => string[]; |
| | | }; |
| | | } |
| | | |
| | | interface Item<T = any> { |
| | | type?: "tabs"; |
| | | prop?: PropKey<T>; |
| | | props?: { |
| | | labels?: ClFormTabs.labels; |
| | | justify?: "left" | "center" | "right"; |
| | | color?: string; |
| | | mergeProp?: boolean; |
| | | labelWidth?: string; |
| | | error?: string; |
| | | showMessage?: boolean; |
| | | inlineMessage?: boolean; |
| | | size?: "medium" | "default" | "small"; |
| | | [key: string]: any; |
| | | }; |
| | | span?: number; |
| | | col?: { |
| | | span: number; |
| | | offset: number; |
| | | push: number; |
| | | pull: number; |
| | | xs: any; |
| | | sm: any; |
| | | md: any; |
| | | lg: any; |
| | | xl: any; |
| | | tag: string; |
| | | }; |
| | | group?: string; |
| | | collapse?: boolean; |
| | | value?: any; |
| | | label?: string; |
| | | renderLabel?: any; |
| | | flex?: boolean; |
| | | hook?: Hook["Event"] | Hook["Key"]; |
| | | hidden?: boolean | ((options: { scope: obj }) => boolean); |
| | | prepend?: Render.Component; |
| | | component?: Render.Component; |
| | | append?: Render.Component; |
| | | rules?: Rule | Rule[]; |
| | | required?: boolean; |
| | | children?: Item[]; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Config<T = any> { |
| | | title?: any; |
| | | height?: any; |
| | | width?: any; |
| | | props: ElementPlus.FormProps; |
| | | items: Item[]; |
| | | form: obj; |
| | | isReset?: boolean; |
| | | on?: { |
| | | open?(data: T): void; |
| | | close?(action: CloseAction, done: fn): void; |
| | | submit?(data: T, event: { close: fn; done: fn }): void; |
| | | change?(data: T, prop: string): void; |
| | | }; |
| | | op: { |
| | | hidden?: boolean; |
| | | saveButtonText?: string; |
| | | closeButtonText?: string; |
| | | justify?: "flex-start" | "center" | "flex-end"; |
| | | buttons?: Array<CloseAction | Render.OpButton>; |
| | | }; |
| | | dialog: { |
| | | title?: any; |
| | | height?: string; |
| | | width?: string; |
| | | hideHeader?: boolean; |
| | | controls?: Array<"fullscreen" | "close" | AnyString>; |
| | | [key: string]: any; |
| | | }; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | type Plugin = (options: { |
| | | exposed: Ref; |
| | | onOpen(cb: () => void): void; |
| | | onClose(cb: () => void): void; |
| | | onSubmit(cb: (data: obj) => obj): void; |
| | | }) => void; |
| | | |
| | | type Items<T = any> = List<Item<T>>; |
| | | |
| | | interface Ref<T = any> { |
| | | Form: any; |
| | | form: T; |
| | | config: { |
| | | items: Item[]; |
| | | [key: string]: any; |
| | | }; |
| | | open(options: Options<T>, plugins?: Plugin[]): void; |
| | | close(action?: CloseAction): void; |
| | | done(): void; |
| | | clear(): void; |
| | | reset(): void; |
| | | showLoading(): void; |
| | | hideLoading(): void; |
| | | setDisabled(flag?: boolean): void; |
| | | invokeData(data: any): void; |
| | | setData(prop: string, value: any): void; |
| | | bindForm(data: obj): void; |
| | | getForm(prop?: string): any; |
| | | setForm(prop: string, value: any): void; |
| | | setOptions(prop: string, list: DictOptions): void; |
| | | setProps(prop: string, value: any): void; |
| | | setConfig(path: string, value: any): void; |
| | | showItem(props: string[] | string): void; |
| | | hideItem(props: string[] | string): void; |
| | | toggleItem(prop: string, flag?: boolean): void; |
| | | resetFields(): void; |
| | | clearValidate(props?: string[] | string): void; |
| | | validateField( |
| | | props?: string[] | string, |
| | | callback?: (isValid: boolean, invalidFields: any[]) => void |
| | | ): Promise<void>; |
| | | validate(callback: (isValid: boolean, invalidFields: any[]) => void): Promise<void>; |
| | | changeTab(value: any, valid?: boolean): Promise<any>; |
| | | setTitle(value: string): void; |
| | | submit(cb?: (data: obj) => void): void; |
| | | Tabs: { |
| | | active: RefData<string>; |
| | | list: ClFormTabs.labels; |
| | | change(value: any, valid?: boolean): Promise<any>; |
| | | [key: string]: any; |
| | | }; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Options<T = any> extends DeepPartial<Config> { |
| | | items?: Items<T>; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClUpsert { |
| | | interface Config<T = any> { |
| | | sync: boolean; |
| | | items: ClForm.Item[]; |
| | | props: ClForm.Config["props"]; |
| | | op: ClForm.Config["op"]; |
| | | dialog: ClForm.Config["dialog"]; |
| | | onOpen?(): void; |
| | | onOpened?(data: T): void; |
| | | onClose?(action: ClForm.CloseAction, done: fn): void; |
| | | onClosed?(): void; |
| | | onInfo?( |
| | | data: T, |
| | | event: { close: fn; done(data: T): void; next: ClCrud.Service["api"]["info"] } |
| | | ): void; |
| | | onSubmit?( |
| | | data: T, |
| | | event: { close: fn; done: fn; next: ClCrud.Service["api"]["update"] } |
| | | ): void; |
| | | plugins?: ClForm.Plugin[]; |
| | | } |
| | | |
| | | interface Ref<T = any> extends ClForm.Ref<T> { |
| | | mode: "add" | "update" | "info" | AnyString; |
| | | } |
| | | |
| | | interface Options<T = any> extends DeepPartial<Config<T>> { |
| | | items?: ClForm.Items<T>; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClAdvSearch { |
| | | interface Config<T = any> { |
| | | items?: ClForm.Item[]; |
| | | title?: string; |
| | | size?: string | number; |
| | | op?: ("clear" | "reset" | "close" | "search" | `slot-${string}`)[]; |
| | | onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"]; close(): void }): void; |
| | | } |
| | | |
| | | interface Ref<T = any> extends ClForm.Ref<T> {} |
| | | |
| | | interface Options<T = any> extends DeepPartial<Config<T>> { |
| | | items?: ClForm.Items<T>; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClSearch { |
| | | type Plugin = (options: { exposed: Ref }) => void; |
| | | |
| | | interface Config<T = any> { |
| | | inline?: boolean; |
| | | items?: ClForm.Item[]; |
| | | data?: T; |
| | | props?: ElementPlus.FormProps; |
| | | resetBtn?: boolean; |
| | | collapse?: boolean; |
| | | Form?: ClForm.Ref; |
| | | onChange?(data: T, prop: string): void; |
| | | onLoad?(data: T): void; |
| | | onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"] }): void; |
| | | plugins?: Plugin[]; |
| | | } |
| | | |
| | | interface Ref<T = any> extends ClForm.Ref<T> { |
| | | search(params?: obj): void; |
| | | reset(): void; |
| | | } |
| | | |
| | | interface Options<T = any> extends DeepPartial<Config<T>> { |
| | | items?: ClForm.Items<T>; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClContextMenu { |
| | | interface Item { |
| | | label: string; |
| | | prefixIcon?: any; |
| | | suffixIcon?: any; |
| | | ellipsis?: boolean; |
| | | disabled?: boolean; |
| | | hidden?: boolean; |
| | | children?: Item[]; |
| | | showChildren?: boolean; |
| | | callback?(done: fn): void; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Event { |
| | | pageX: number; |
| | | pageY: number; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | interface Options { |
| | | class?: string; |
| | | hover?: |
| | | | boolean |
| | | | { |
| | | target?: string; |
| | | className?: string; |
| | | }; |
| | | list?: Item[]; |
| | | } |
| | | |
| | | interface Ref { |
| | | open(event: Event, options: Options): Exposed; |
| | | close(): void; |
| | | } |
| | | |
| | | interface Exposed { |
| | | close(): void; |
| | | } |
| | | } |
| | | |
| | | declare namespace ClDialog { |
| | | interface Provide { |
| | | visible: Vue.Ref<boolean>; |
| | | fullscreen: Vue.Ref<boolean>; |
| | | } |
| | | } |
| | | |
| | | declare interface Config { |
| | | dict: ClCrud.Dict; |
| | | permission: ClCrud.Permission; |
| | | events: { |
| | | [key: string]: (...args: any[]) => any; |
| | | }; |
| | | style: { |
| | | size: ElementPlus.Size; |
| | | colors: string[]; |
| | | form: { |
| | | labelPosition: ElementPlus.FormProps["labelPosition"]; |
| | | labelWidth: ElementPlus.FormProps["labelWidth"]; |
| | | span: number; |
| | | plugins: ClForm.Plugin[]; |
| | | }; |
| | | table: { |
| | | stripe: boolean; |
| | | border: boolean; |
| | | highlightCurrentRow: boolean; |
| | | resizable: boolean; |
| | | autoHeight: boolean; |
| | | contextMenu: ClTable.ContextMenu; |
| | | column: { |
| | | minWidth: number | string; |
| | | align: ElementPlus.Align; |
| | | headerAlign: ElementPlus.Align; |
| | | opWidth: number | string; |
| | | }; |
| | | plugins: ClTable.Plugin[]; |
| | | }; |
| | | search: { |
| | | plugins: ClSearch.Plugin[]; |
| | | }; |
| | | }; |
| | | } |
| | | |
| | | declare type Options = DeepPartial<Config>; |
| | | |
| | | declare interface CrudOptions { |
| | | options: Options; |
| | | } |
| New file |
| | |
| | | <!doctype html> |
| | | <html lang="en"> |
| | | <head> |
| | | <meta charset="utf-8" /> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
| | | <meta name="referer" content="never" /> |
| | | <meta name="renderer" content="webkit" /> |
| | | <meta |
| | | name="viewport" |
| | | content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" |
| | | /> |
| | | <title></title> |
| | | <link rel="icon" href="./favicon.ico" /> |
| | | </head> |
| | | |
| | | <body> |
| | | <div class="preload__wrap" id="Loading"> |
| | | <div class="preload__container"> |
| | | <p class="preload__name"></p> |
| | | <div class="preload__loading"></div> |
| | | <p class="preload__title"></p> |
| | | <p class="preload__sub-title"></p> |
| | | </div> |
| | | </div> |
| | | |
| | | <div id="app"></div> |
| | | <script type="module" src="/src/main.ts"></script> |
| | | </body> |
| | | </html> |
| New file |
| | |
| | | { |
| | | "name": "@cool-vue/crud", |
| | | "version": "8.0.6", |
| | | "private": false, |
| | | "main": "./dist/index.umd.js", |
| | | "module": "./dist/index.es.js", |
| | | "types": "types/entry.d.ts", |
| | | "type": "module", |
| | | "scripts": { |
| | | "dev": "vite", |
| | | "build": "vue-tsc && vite build", |
| | | "preview": "vite preview" |
| | | }, |
| | | "dependencies": { |
| | | "@vue/runtime-core": "^3.5.13", |
| | | "element-plus": "^2.10.4", |
| | | "lodash-es": "^4.17.21", |
| | | "vue": "^3.5.13" |
| | | }, |
| | | "devDependencies": { |
| | | "@types/node": "^20.11.16", |
| | | "@vitejs/plugin-vue": "^5.2.1", |
| | | "@vitejs/plugin-vue-jsx": "^4.1.1", |
| | | "prettier": "^3.5.1", |
| | | "sass": "^1.85.0", |
| | | "sass-loader": "^16.0.5", |
| | | "typescript": "^5.3.3", |
| | | "vite": "^6.1.0", |
| | | "vite-plugin-dts": "^4.5.0", |
| | | "vue-tsc": "^2.2.2" |
| | | }, |
| | | "files": [ |
| | | "types", |
| | | "dist", |
| | | "index.d.ts", |
| | | "index.ts" |
| | | ] |
| | | } |
| New file |
| | |
| | | lockfileVersion: '9.0' |
| | | |
| | | settings: |
| | | autoInstallPeers: true |
| | | excludeLinksFromLockfile: false |
| | | |
| | | importers: |
| | | |
| | | .: |
| | | dependencies: |
| | | '@vue/runtime-core': |
| | | specifier: ^3.5.13 |
| | | version: 3.5.13 |
| | | element-plus: |
| | | specifier: ^2.9.4 |
| | | version: 2.9.4(vue@3.5.13(typescript@5.7.3)) |
| | | lodash-es: |
| | | specifier: ^4.17.21 |
| | | version: 4.17.21 |
| | | vue: |
| | | specifier: ^3.5.13 |
| | | version: 3.5.13(typescript@5.7.3) |
| | | devDependencies: |
| | | '@types/node': |
| | | specifier: ^20.11.16 |
| | | version: 20.17.19 |
| | | '@vitejs/plugin-vue': |
| | | specifier: ^5.2.1 |
| | | version: 5.2.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3)) |
| | | '@vitejs/plugin-vue-jsx': |
| | | specifier: ^4.1.1 |
| | | version: 4.1.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3)) |
| | | prettier: |
| | | specifier: ^3.5.1 |
| | | version: 3.5.1 |
| | | sass: |
| | | specifier: ^1.85.0 |
| | | version: 1.85.0 |
| | | sass-loader: |
| | | specifier: ^16.0.5 |
| | | version: 16.0.5(sass@1.85.0) |
| | | typescript: |
| | | specifier: ^5.3.3 |
| | | version: 5.7.3 |
| | | vite: |
| | | specifier: ^6.1.0 |
| | | version: 6.1.0(@types/node@20.17.19)(sass@1.85.0) |
| | | vite-plugin-dts: |
| | | specifier: ^4.5.0 |
| | | version: 4.5.0(@types/node@20.17.19)(rollup@4.34.8)(typescript@5.7.3)(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0)) |
| | | vue-tsc: |
| | | specifier: ^2.2.2 |
| | | version: 2.2.2(typescript@5.7.3) |
| | | |
| | | packages: |
| | | |
| | | '@ampproject/remapping@2.3.0': |
| | | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} |
| | | engines: {node: '>=6.0.0'} |
| | | |
| | | '@babel/code-frame@7.26.2': |
| | | resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/compat-data@7.26.8': |
| | | resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/core@7.26.9': |
| | | resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/generator@7.26.9': |
| | | resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-annotate-as-pure@7.25.9': |
| | | resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-compilation-targets@7.26.5': |
| | | resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-create-class-features-plugin@7.26.9': |
| | | resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0 |
| | | |
| | | '@babel/helper-member-expression-to-functions@7.25.9': |
| | | resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-module-imports@7.25.9': |
| | | resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-module-transforms@7.26.0': |
| | | resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0 |
| | | |
| | | '@babel/helper-optimise-call-expression@7.25.9': |
| | | resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-plugin-utils@7.26.5': |
| | | resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-replace-supers@7.26.5': |
| | | resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0 |
| | | |
| | | '@babel/helper-skip-transparent-expression-wrappers@7.25.9': |
| | | resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-string-parser@7.25.9': |
| | | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-validator-identifier@7.25.9': |
| | | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-validator-option@7.25.9': |
| | | resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helpers@7.26.9': |
| | | resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/parser@7.26.9': |
| | | resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} |
| | | engines: {node: '>=6.0.0'} |
| | | hasBin: true |
| | | |
| | | '@babel/plugin-syntax-jsx@7.25.9': |
| | | resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@babel/plugin-syntax-typescript@7.25.9': |
| | | resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@babel/plugin-transform-typescript@7.26.8': |
| | | resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@babel/template@7.26.9': |
| | | resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/traverse@7.26.9': |
| | | resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/types@7.26.9': |
| | | resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@ctrl/tinycolor@3.6.1': |
| | | resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} |
| | | engines: {node: '>=10'} |
| | | |
| | | '@element-plus/icons-vue@2.3.1': |
| | | resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==} |
| | | peerDependencies: |
| | | vue: ^3.2.0 |
| | | |
| | | '@esbuild/aix-ppc64@0.24.2': |
| | | resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} |
| | | engines: {node: '>=18'} |
| | | cpu: [ppc64] |
| | | os: [aix] |
| | | |
| | | '@esbuild/android-arm64@0.24.2': |
| | | resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [android] |
| | | |
| | | '@esbuild/android-arm@0.24.2': |
| | | resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm] |
| | | os: [android] |
| | | |
| | | '@esbuild/android-x64@0.24.2': |
| | | resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [android] |
| | | |
| | | '@esbuild/darwin-arm64@0.24.2': |
| | | resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [darwin] |
| | | |
| | | '@esbuild/darwin-x64@0.24.2': |
| | | resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [darwin] |
| | | |
| | | '@esbuild/freebsd-arm64@0.24.2': |
| | | resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [freebsd] |
| | | |
| | | '@esbuild/freebsd-x64@0.24.2': |
| | | resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [freebsd] |
| | | |
| | | '@esbuild/linux-arm64@0.24.2': |
| | | resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-arm@0.24.2': |
| | | resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-ia32@0.24.2': |
| | | resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [ia32] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-loong64@0.24.2': |
| | | resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} |
| | | engines: {node: '>=18'} |
| | | cpu: [loong64] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-mips64el@0.24.2': |
| | | resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [mips64el] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-ppc64@0.24.2': |
| | | resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [ppc64] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-riscv64@0.24.2': |
| | | resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} |
| | | engines: {node: '>=18'} |
| | | cpu: [riscv64] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-s390x@0.24.2': |
| | | resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [s390x] |
| | | os: [linux] |
| | | |
| | | '@esbuild/linux-x64@0.24.2': |
| | | resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [linux] |
| | | |
| | | '@esbuild/netbsd-arm64@0.24.2': |
| | | resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [netbsd] |
| | | |
| | | '@esbuild/netbsd-x64@0.24.2': |
| | | resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [netbsd] |
| | | |
| | | '@esbuild/openbsd-arm64@0.24.2': |
| | | resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [openbsd] |
| | | |
| | | '@esbuild/openbsd-x64@0.24.2': |
| | | resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [openbsd] |
| | | |
| | | '@esbuild/sunos-x64@0.24.2': |
| | | resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [sunos] |
| | | |
| | | '@esbuild/win32-arm64@0.24.2': |
| | | resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} |
| | | engines: {node: '>=18'} |
| | | cpu: [arm64] |
| | | os: [win32] |
| | | |
| | | '@esbuild/win32-ia32@0.24.2': |
| | | resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} |
| | | engines: {node: '>=18'} |
| | | cpu: [ia32] |
| | | os: [win32] |
| | | |
| | | '@esbuild/win32-x64@0.24.2': |
| | | resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} |
| | | engines: {node: '>=18'} |
| | | cpu: [x64] |
| | | os: [win32] |
| | | |
| | | '@floating-ui/core@1.6.9': |
| | | resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} |
| | | |
| | | '@floating-ui/dom@1.6.13': |
| | | resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} |
| | | |
| | | '@floating-ui/utils@0.2.9': |
| | | resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} |
| | | |
| | | '@jridgewell/gen-mapping@0.3.8': |
| | | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} |
| | | engines: {node: '>=6.0.0'} |
| | | |
| | | '@jridgewell/resolve-uri@3.1.2': |
| | | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} |
| | | engines: {node: '>=6.0.0'} |
| | | |
| | | '@jridgewell/set-array@1.2.1': |
| | | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} |
| | | engines: {node: '>=6.0.0'} |
| | | |
| | | '@jridgewell/sourcemap-codec@1.5.0': |
| | | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} |
| | | |
| | | '@jridgewell/trace-mapping@0.3.25': |
| | | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} |
| | | |
| | | '@microsoft/api-extractor-model@7.30.3': |
| | | resolution: {integrity: sha512-yEAvq0F78MmStXdqz9TTT4PZ05Xu5R8nqgwI5xmUmQjWBQ9E6R2n8HB/iZMRciG4rf9iwI2mtuQwIzDXBvHn1w==} |
| | | |
| | | '@microsoft/api-extractor@7.50.0': |
| | | resolution: {integrity: sha512-Ds/PHTiVzuENQsmXrJKkSdfgNkr/SDG/2rDef0AWl3BchAnXdO7gXaYsAkNx4gWiC4OngNA3fQfd3+BcQxP1DQ==} |
| | | hasBin: true |
| | | |
| | | '@microsoft/tsdoc-config@0.17.1': |
| | | resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==} |
| | | |
| | | '@microsoft/tsdoc@0.15.1': |
| | | resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} |
| | | |
| | | '@parcel/watcher-android-arm64@2.5.1': |
| | | resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm64] |
| | | os: [android] |
| | | |
| | | '@parcel/watcher-darwin-arm64@2.5.1': |
| | | resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm64] |
| | | os: [darwin] |
| | | |
| | | '@parcel/watcher-darwin-x64@2.5.1': |
| | | resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [x64] |
| | | os: [darwin] |
| | | |
| | | '@parcel/watcher-freebsd-x64@2.5.1': |
| | | resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [x64] |
| | | os: [freebsd] |
| | | |
| | | '@parcel/watcher-linux-arm-glibc@2.5.1': |
| | | resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@parcel/watcher-linux-arm-musl@2.5.1': |
| | | resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm] |
| | | os: [linux] |
| | | libc: [musl] |
| | | |
| | | '@parcel/watcher-linux-arm64-glibc@2.5.1': |
| | | resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@parcel/watcher-linux-arm64-musl@2.5.1': |
| | | resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm64] |
| | | os: [linux] |
| | | libc: [musl] |
| | | |
| | | '@parcel/watcher-linux-x64-glibc@2.5.1': |
| | | resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [x64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@parcel/watcher-linux-x64-musl@2.5.1': |
| | | resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [x64] |
| | | os: [linux] |
| | | libc: [musl] |
| | | |
| | | '@parcel/watcher-win32-arm64@2.5.1': |
| | | resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [arm64] |
| | | os: [win32] |
| | | |
| | | '@parcel/watcher-win32-ia32@2.5.1': |
| | | resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [ia32] |
| | | os: [win32] |
| | | |
| | | '@parcel/watcher-win32-x64@2.5.1': |
| | | resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} |
| | | engines: {node: '>= 10.0.0'} |
| | | cpu: [x64] |
| | | os: [win32] |
| | | |
| | | '@parcel/watcher@2.5.1': |
| | | resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} |
| | | engines: {node: '>= 10.0.0'} |
| | | |
| | | '@rollup/pluginutils@5.1.4': |
| | | resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} |
| | | engines: {node: '>=14.0.0'} |
| | | peerDependencies: |
| | | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 |
| | | peerDependenciesMeta: |
| | | rollup: |
| | | optional: true |
| | | |
| | | '@rollup/rollup-android-arm-eabi@4.34.8': |
| | | resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} |
| | | cpu: [arm] |
| | | os: [android] |
| | | |
| | | '@rollup/rollup-android-arm64@4.34.8': |
| | | resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} |
| | | cpu: [arm64] |
| | | os: [android] |
| | | |
| | | '@rollup/rollup-darwin-arm64@4.34.8': |
| | | resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} |
| | | cpu: [arm64] |
| | | os: [darwin] |
| | | |
| | | '@rollup/rollup-darwin-x64@4.34.8': |
| | | resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} |
| | | cpu: [x64] |
| | | os: [darwin] |
| | | |
| | | '@rollup/rollup-freebsd-arm64@4.34.8': |
| | | resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} |
| | | cpu: [arm64] |
| | | os: [freebsd] |
| | | |
| | | '@rollup/rollup-freebsd-x64@4.34.8': |
| | | resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} |
| | | cpu: [x64] |
| | | os: [freebsd] |
| | | |
| | | '@rollup/rollup-linux-arm-gnueabihf@4.34.8': |
| | | resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} |
| | | cpu: [arm] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-arm-musleabihf@4.34.8': |
| | | resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} |
| | | cpu: [arm] |
| | | os: [linux] |
| | | libc: [musl] |
| | | |
| | | '@rollup/rollup-linux-arm64-gnu@4.34.8': |
| | | resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} |
| | | cpu: [arm64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-arm64-musl@4.34.8': |
| | | resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} |
| | | cpu: [arm64] |
| | | os: [linux] |
| | | libc: [musl] |
| | | |
| | | '@rollup/rollup-linux-loongarch64-gnu@4.34.8': |
| | | resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} |
| | | cpu: [loong64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': |
| | | resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} |
| | | cpu: [ppc64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-riscv64-gnu@4.34.8': |
| | | resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} |
| | | cpu: [riscv64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-s390x-gnu@4.34.8': |
| | | resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} |
| | | cpu: [s390x] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-x64-gnu@4.34.8': |
| | | resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} |
| | | cpu: [x64] |
| | | os: [linux] |
| | | libc: [glibc] |
| | | |
| | | '@rollup/rollup-linux-x64-musl@4.34.8': |
| | | resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} |
| | | cpu: [x64] |
| | | os: [linux] |
| | | libc: [musl] |
| | | |
| | | '@rollup/rollup-win32-arm64-msvc@4.34.8': |
| | | resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} |
| | | cpu: [arm64] |
| | | os: [win32] |
| | | |
| | | '@rollup/rollup-win32-ia32-msvc@4.34.8': |
| | | resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} |
| | | cpu: [ia32] |
| | | os: [win32] |
| | | |
| | | '@rollup/rollup-win32-x64-msvc@4.34.8': |
| | | resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} |
| | | cpu: [x64] |
| | | os: [win32] |
| | | |
| | | '@rushstack/node-core-library@5.11.0': |
| | | resolution: {integrity: sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==} |
| | | peerDependencies: |
| | | '@types/node': '*' |
| | | peerDependenciesMeta: |
| | | '@types/node': |
| | | optional: true |
| | | |
| | | '@rushstack/rig-package@0.5.3': |
| | | resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==} |
| | | |
| | | '@rushstack/terminal@0.15.0': |
| | | resolution: {integrity: sha512-vXQPRQ+vJJn4GVqxkwRe+UGgzNxdV8xuJZY2zem46Y0p3tlahucH9/hPmLGj2i9dQnUBFiRnoM9/KW7PYw8F4Q==} |
| | | peerDependencies: |
| | | '@types/node': '*' |
| | | peerDependenciesMeta: |
| | | '@types/node': |
| | | optional: true |
| | | |
| | | '@rushstack/ts-command-line@4.23.5': |
| | | resolution: {integrity: sha512-jg70HfoK44KfSP3MTiL5rxsZH7X1ktX3cZs9Sl8eDu1/LxJSbPsh0MOFRC710lIuYYSgxWjI5AjbCBAl7u3RxA==} |
| | | |
| | | '@sxzz/popperjs-es@2.11.7': |
| | | resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} |
| | | |
| | | '@types/argparse@1.0.38': |
| | | resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} |
| | | |
| | | '@types/estree@1.0.6': |
| | | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} |
| | | |
| | | '@types/lodash-es@4.17.12': |
| | | resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} |
| | | |
| | | '@types/lodash@4.17.15': |
| | | resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} |
| | | |
| | | '@types/node@20.17.19': |
| | | resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} |
| | | |
| | | '@types/web-bluetooth@0.0.16': |
| | | resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} |
| | | |
| | | '@vitejs/plugin-vue-jsx@4.1.1': |
| | | resolution: {integrity: sha512-uMJqv/7u1zz/9NbWAD3XdjaY20tKTf17XVfQ9zq4wY1BjsB/PjpJPMe2xiG39QpP4ZdhYNhm4Hvo66uJrykNLA==} |
| | | engines: {node: ^18.0.0 || >=20.0.0} |
| | | peerDependencies: |
| | | vite: ^5.0.0 || ^6.0.0 |
| | | vue: ^3.0.0 |
| | | |
| | | '@vitejs/plugin-vue@5.2.1': |
| | | resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} |
| | | engines: {node: ^18.0.0 || >=20.0.0} |
| | | peerDependencies: |
| | | vite: ^5.0.0 || ^6.0.0 |
| | | vue: ^3.2.25 |
| | | |
| | | '@volar/language-core@2.4.11': |
| | | resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==} |
| | | |
| | | '@volar/source-map@2.4.11': |
| | | resolution: {integrity: sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==} |
| | | |
| | | '@volar/typescript@2.4.11': |
| | | resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==} |
| | | |
| | | '@vue/babel-helper-vue-transform-on@1.2.5': |
| | | resolution: {integrity: sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==} |
| | | |
| | | '@vue/babel-plugin-jsx@1.2.5': |
| | | resolution: {integrity: sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | peerDependenciesMeta: |
| | | '@babel/core': |
| | | optional: true |
| | | |
| | | '@vue/babel-plugin-resolve-type@1.2.5': |
| | | resolution: {integrity: sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@vue/compiler-core@3.5.13': |
| | | resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} |
| | | |
| | | '@vue/compiler-dom@3.5.13': |
| | | resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} |
| | | |
| | | '@vue/compiler-sfc@3.5.13': |
| | | resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} |
| | | |
| | | '@vue/compiler-ssr@3.5.13': |
| | | resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} |
| | | |
| | | '@vue/compiler-vue2@2.7.16': |
| | | resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} |
| | | |
| | | '@vue/language-core@2.2.0': |
| | | resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} |
| | | peerDependencies: |
| | | typescript: '*' |
| | | peerDependenciesMeta: |
| | | typescript: |
| | | optional: true |
| | | |
| | | '@vue/language-core@2.2.2': |
| | | resolution: {integrity: sha512-QotO41kurE5PLf3vrNgGTk3QswO2PdUFjBwNiOi7zMmGhwb25PSTh9hD1MCgKC06AVv+8sZQvlL3Do4TTVHSiQ==} |
| | | peerDependencies: |
| | | typescript: '*' |
| | | peerDependenciesMeta: |
| | | typescript: |
| | | optional: true |
| | | |
| | | '@vue/reactivity@3.5.13': |
| | | resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} |
| | | |
| | | '@vue/runtime-core@3.5.13': |
| | | resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} |
| | | |
| | | '@vue/runtime-dom@3.5.13': |
| | | resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} |
| | | |
| | | '@vue/server-renderer@3.5.13': |
| | | resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} |
| | | peerDependencies: |
| | | vue: 3.5.13 |
| | | |
| | | '@vue/shared@3.5.13': |
| | | resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} |
| | | |
| | | '@vueuse/core@9.13.0': |
| | | resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} |
| | | |
| | | '@vueuse/metadata@9.13.0': |
| | | resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} |
| | | |
| | | '@vueuse/shared@9.13.0': |
| | | resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} |
| | | |
| | | acorn@8.14.0: |
| | | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} |
| | | engines: {node: '>=0.4.0'} |
| | | hasBin: true |
| | | |
| | | ajv-draft-04@1.0.0: |
| | | resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} |
| | | peerDependencies: |
| | | ajv: ^8.5.0 |
| | | peerDependenciesMeta: |
| | | ajv: |
| | | optional: true |
| | | |
| | | ajv-formats@3.0.1: |
| | | resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} |
| | | peerDependencies: |
| | | ajv: ^8.0.0 |
| | | peerDependenciesMeta: |
| | | ajv: |
| | | optional: true |
| | | |
| | | ajv@8.12.0: |
| | | resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} |
| | | |
| | | ajv@8.13.0: |
| | | resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} |
| | | |
| | | alien-signals@0.4.14: |
| | | resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} |
| | | |
| | | alien-signals@1.0.3: |
| | | resolution: {integrity: sha512-zQOh3wAYK5ujENxvBBR3CFGF/b6afaSzZ/c9yNhJ1ENrGHETvpUuKQsa93Qrclp0+PzTF93MaZ7scVp1uUozhA==} |
| | | |
| | | argparse@1.0.10: |
| | | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} |
| | | |
| | | async-validator@4.2.5: |
| | | resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} |
| | | |
| | | balanced-match@1.0.2: |
| | | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} |
| | | |
| | | brace-expansion@1.1.11: |
| | | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} |
| | | |
| | | brace-expansion@2.0.1: |
| | | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} |
| | | |
| | | braces@3.0.3: |
| | | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} |
| | | engines: {node: '>=8'} |
| | | |
| | | browserslist@4.24.4: |
| | | resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} |
| | | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} |
| | | hasBin: true |
| | | |
| | | caniuse-lite@1.0.30001700: |
| | | resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==} |
| | | |
| | | chokidar@4.0.3: |
| | | resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} |
| | | engines: {node: '>= 14.16.0'} |
| | | |
| | | compare-versions@6.1.1: |
| | | resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} |
| | | |
| | | concat-map@0.0.1: |
| | | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} |
| | | |
| | | confbox@0.1.8: |
| | | resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} |
| | | |
| | | convert-source-map@2.0.0: |
| | | resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} |
| | | |
| | | csstype@3.1.3: |
| | | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} |
| | | |
| | | dayjs@1.11.13: |
| | | resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} |
| | | |
| | | de-indent@1.0.2: |
| | | resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} |
| | | |
| | | debug@4.4.0: |
| | | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} |
| | | engines: {node: '>=6.0'} |
| | | peerDependencies: |
| | | supports-color: '*' |
| | | peerDependenciesMeta: |
| | | supports-color: |
| | | optional: true |
| | | |
| | | detect-libc@1.0.3: |
| | | resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} |
| | | engines: {node: '>=0.10'} |
| | | hasBin: true |
| | | |
| | | electron-to-chromium@1.5.102: |
| | | resolution: {integrity: sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==} |
| | | |
| | | element-plus@2.9.4: |
| | | resolution: {integrity: sha512-sGnW0wd9zf6lEGixXV2gfwx3X6VTMkP52qTkX7zbURJ2oariyslrKTBh2txt1sdn1pUvj2l0KY3OfSXoZGmDOw==} |
| | | peerDependencies: |
| | | vue: ^3.2.0 |
| | | |
| | | entities@4.5.0: |
| | | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} |
| | | engines: {node: '>=0.12'} |
| | | |
| | | esbuild@0.24.2: |
| | | resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} |
| | | engines: {node: '>=18'} |
| | | hasBin: true |
| | | |
| | | escalade@3.2.0: |
| | | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} |
| | | engines: {node: '>=6'} |
| | | |
| | | escape-html@1.0.3: |
| | | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} |
| | | |
| | | estree-walker@2.0.2: |
| | | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} |
| | | |
| | | fast-deep-equal@3.1.3: |
| | | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} |
| | | |
| | | fill-range@7.1.1: |
| | | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} |
| | | engines: {node: '>=8'} |
| | | |
| | | fs-extra@11.3.0: |
| | | resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} |
| | | engines: {node: '>=14.14'} |
| | | |
| | | fsevents@2.3.3: |
| | | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} |
| | | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} |
| | | os: [darwin] |
| | | |
| | | function-bind@1.1.2: |
| | | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} |
| | | |
| | | gensync@1.0.0-beta.2: |
| | | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | globals@11.12.0: |
| | | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} |
| | | engines: {node: '>=4'} |
| | | |
| | | graceful-fs@4.2.11: |
| | | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} |
| | | |
| | | has-flag@4.0.0: |
| | | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} |
| | | engines: {node: '>=8'} |
| | | |
| | | hasown@2.0.2: |
| | | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} |
| | | engines: {node: '>= 0.4'} |
| | | |
| | | he@1.2.0: |
| | | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} |
| | | hasBin: true |
| | | |
| | | html-tags@3.3.1: |
| | | resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} |
| | | engines: {node: '>=8'} |
| | | |
| | | immutable@5.0.3: |
| | | resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} |
| | | |
| | | import-lazy@4.0.0: |
| | | resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} |
| | | engines: {node: '>=8'} |
| | | |
| | | is-core-module@2.16.1: |
| | | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} |
| | | engines: {node: '>= 0.4'} |
| | | |
| | | is-extglob@2.1.1: |
| | | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} |
| | | engines: {node: '>=0.10.0'} |
| | | |
| | | is-glob@4.0.3: |
| | | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} |
| | | engines: {node: '>=0.10.0'} |
| | | |
| | | is-number@7.0.0: |
| | | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} |
| | | engines: {node: '>=0.12.0'} |
| | | |
| | | jju@1.4.0: |
| | | resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} |
| | | |
| | | js-tokens@4.0.0: |
| | | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} |
| | | |
| | | jsesc@3.1.0: |
| | | resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} |
| | | engines: {node: '>=6'} |
| | | hasBin: true |
| | | |
| | | json-schema-traverse@1.0.0: |
| | | resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} |
| | | |
| | | json5@2.2.3: |
| | | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} |
| | | engines: {node: '>=6'} |
| | | hasBin: true |
| | | |
| | | jsonfile@6.1.0: |
| | | resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} |
| | | |
| | | kolorist@1.8.0: |
| | | resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} |
| | | |
| | | local-pkg@0.5.1: |
| | | resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} |
| | | engines: {node: '>=14'} |
| | | |
| | | lodash-es@4.17.21: |
| | | resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} |
| | | |
| | | lodash-unified@1.0.3: |
| | | resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} |
| | | peerDependencies: |
| | | '@types/lodash-es': '*' |
| | | lodash: '*' |
| | | lodash-es: '*' |
| | | |
| | | lodash@4.17.21: |
| | | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} |
| | | |
| | | lru-cache@5.1.1: |
| | | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} |
| | | |
| | | lru-cache@6.0.0: |
| | | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} |
| | | engines: {node: '>=10'} |
| | | |
| | | magic-string@0.30.17: |
| | | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} |
| | | |
| | | memoize-one@6.0.0: |
| | | resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} |
| | | |
| | | micromatch@4.0.8: |
| | | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} |
| | | engines: {node: '>=8.6'} |
| | | |
| | | minimatch@3.0.8: |
| | | resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} |
| | | |
| | | minimatch@9.0.5: |
| | | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} |
| | | engines: {node: '>=16 || 14 >=14.17'} |
| | | |
| | | mlly@1.7.4: |
| | | resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} |
| | | |
| | | ms@2.1.3: |
| | | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} |
| | | |
| | | muggle-string@0.4.1: |
| | | resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} |
| | | |
| | | nanoid@3.3.8: |
| | | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} |
| | | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} |
| | | hasBin: true |
| | | |
| | | neo-async@2.6.2: |
| | | resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} |
| | | |
| | | node-addon-api@7.1.1: |
| | | resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} |
| | | |
| | | node-releases@2.0.19: |
| | | resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} |
| | | |
| | | normalize-wheel-es@1.2.0: |
| | | resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} |
| | | |
| | | path-browserify@1.0.1: |
| | | resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} |
| | | |
| | | path-parse@1.0.7: |
| | | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} |
| | | |
| | | pathe@2.0.3: |
| | | resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} |
| | | |
| | | picocolors@1.1.1: |
| | | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} |
| | | |
| | | picomatch@2.3.1: |
| | | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} |
| | | engines: {node: '>=8.6'} |
| | | |
| | | picomatch@4.0.2: |
| | | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} |
| | | engines: {node: '>=12'} |
| | | |
| | | pkg-types@1.3.1: |
| | | resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} |
| | | |
| | | postcss@8.5.2: |
| | | resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==} |
| | | engines: {node: ^10 || ^12 || >=14} |
| | | |
| | | prettier@3.5.1: |
| | | resolution: {integrity: sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==} |
| | | engines: {node: '>=14'} |
| | | hasBin: true |
| | | |
| | | punycode@2.3.1: |
| | | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} |
| | | engines: {node: '>=6'} |
| | | |
| | | readdirp@4.1.2: |
| | | resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} |
| | | engines: {node: '>= 14.18.0'} |
| | | |
| | | require-from-string@2.0.2: |
| | | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} |
| | | engines: {node: '>=0.10.0'} |
| | | |
| | | resolve@1.22.10: |
| | | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} |
| | | engines: {node: '>= 0.4'} |
| | | hasBin: true |
| | | |
| | | rollup@4.34.8: |
| | | resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} |
| | | engines: {node: '>=18.0.0', npm: '>=8.0.0'} |
| | | hasBin: true |
| | | |
| | | sass-loader@16.0.5: |
| | | resolution: {integrity: sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==} |
| | | engines: {node: '>= 18.12.0'} |
| | | peerDependencies: |
| | | '@rspack/core': 0.x || 1.x |
| | | node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 |
| | | sass: ^1.3.0 |
| | | sass-embedded: '*' |
| | | webpack: ^5.0.0 |
| | | peerDependenciesMeta: |
| | | '@rspack/core': |
| | | optional: true |
| | | node-sass: |
| | | optional: true |
| | | sass: |
| | | optional: true |
| | | sass-embedded: |
| | | optional: true |
| | | webpack: |
| | | optional: true |
| | | |
| | | sass@1.85.0: |
| | | resolution: {integrity: sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==} |
| | | engines: {node: '>=14.0.0'} |
| | | hasBin: true |
| | | |
| | | semver@6.3.1: |
| | | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} |
| | | hasBin: true |
| | | |
| | | semver@7.5.4: |
| | | resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} |
| | | engines: {node: '>=10'} |
| | | hasBin: true |
| | | |
| | | source-map-js@1.2.1: |
| | | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} |
| | | engines: {node: '>=0.10.0'} |
| | | |
| | | source-map@0.6.1: |
| | | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} |
| | | engines: {node: '>=0.10.0'} |
| | | |
| | | sprintf-js@1.0.3: |
| | | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} |
| | | |
| | | string-argv@0.3.2: |
| | | resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} |
| | | engines: {node: '>=0.6.19'} |
| | | |
| | | strip-json-comments@3.1.1: |
| | | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} |
| | | engines: {node: '>=8'} |
| | | |
| | | supports-color@8.1.1: |
| | | resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} |
| | | engines: {node: '>=10'} |
| | | |
| | | supports-preserve-symlinks-flag@1.0.0: |
| | | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} |
| | | engines: {node: '>= 0.4'} |
| | | |
| | | svg-tags@1.0.0: |
| | | resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} |
| | | |
| | | to-regex-range@5.0.1: |
| | | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} |
| | | engines: {node: '>=8.0'} |
| | | |
| | | typescript@5.7.2: |
| | | resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} |
| | | engines: {node: '>=14.17'} |
| | | hasBin: true |
| | | |
| | | typescript@5.7.3: |
| | | resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} |
| | | engines: {node: '>=14.17'} |
| | | hasBin: true |
| | | |
| | | ufo@1.5.4: |
| | | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} |
| | | |
| | | undici-types@6.19.8: |
| | | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} |
| | | |
| | | universalify@2.0.1: |
| | | resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} |
| | | engines: {node: '>= 10.0.0'} |
| | | |
| | | update-browserslist-db@1.1.2: |
| | | resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} |
| | | hasBin: true |
| | | peerDependencies: |
| | | browserslist: '>= 4.21.0' |
| | | |
| | | uri-js@4.4.1: |
| | | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} |
| | | |
| | | vite-plugin-dts@4.5.0: |
| | | resolution: {integrity: sha512-M1lrPTdi7gilLYRZoLmGYnl4fbPryVYsehPN9JgaxjJKTs8/f7tuAlvCCvOLB5gRDQTTKnptBcB0ACsaw2wNLw==} |
| | | peerDependencies: |
| | | typescript: '*' |
| | | vite: '*' |
| | | peerDependenciesMeta: |
| | | vite: |
| | | optional: true |
| | | |
| | | vite@6.1.0: |
| | | resolution: {integrity: sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==} |
| | | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} |
| | | hasBin: true |
| | | peerDependencies: |
| | | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 |
| | | jiti: '>=1.21.0' |
| | | less: '*' |
| | | lightningcss: ^1.21.0 |
| | | sass: '*' |
| | | sass-embedded: '*' |
| | | stylus: '*' |
| | | sugarss: '*' |
| | | terser: ^5.16.0 |
| | | tsx: ^4.8.1 |
| | | yaml: ^2.4.2 |
| | | peerDependenciesMeta: |
| | | '@types/node': |
| | | optional: true |
| | | jiti: |
| | | optional: true |
| | | less: |
| | | optional: true |
| | | lightningcss: |
| | | optional: true |
| | | sass: |
| | | optional: true |
| | | sass-embedded: |
| | | optional: true |
| | | stylus: |
| | | optional: true |
| | | sugarss: |
| | | optional: true |
| | | terser: |
| | | optional: true |
| | | tsx: |
| | | optional: true |
| | | yaml: |
| | | optional: true |
| | | |
| | | vscode-uri@3.1.0: |
| | | resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} |
| | | |
| | | vue-demi@0.14.10: |
| | | resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} |
| | | engines: {node: '>=12'} |
| | | hasBin: true |
| | | peerDependencies: |
| | | '@vue/composition-api': ^1.0.0-rc.1 |
| | | vue: ^3.0.0-0 || ^2.6.0 |
| | | peerDependenciesMeta: |
| | | '@vue/composition-api': |
| | | optional: true |
| | | |
| | | vue-tsc@2.2.2: |
| | | resolution: {integrity: sha512-1icPKkxAA5KTAaSwg0wVWdE48EdsH8fgvcbAiqojP4jXKl6LEM3soiW1aG/zrWrFt8Mw1ncG2vG1PvpZpVfehA==} |
| | | hasBin: true |
| | | peerDependencies: |
| | | typescript: '>=5.0.0' |
| | | |
| | | vue@3.5.13: |
| | | resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} |
| | | peerDependencies: |
| | | typescript: '*' |
| | | peerDependenciesMeta: |
| | | typescript: |
| | | optional: true |
| | | |
| | | yallist@3.1.1: |
| | | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} |
| | | |
| | | yallist@4.0.0: |
| | | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} |
| | | |
| | | snapshots: |
| | | |
| | | '@ampproject/remapping@2.3.0': |
| | | dependencies: |
| | | '@jridgewell/gen-mapping': 0.3.8 |
| | | '@jridgewell/trace-mapping': 0.3.25 |
| | | |
| | | '@babel/code-frame@7.26.2': |
| | | dependencies: |
| | | '@babel/helper-validator-identifier': 7.25.9 |
| | | js-tokens: 4.0.0 |
| | | picocolors: 1.1.1 |
| | | |
| | | '@babel/compat-data@7.26.8': {} |
| | | |
| | | '@babel/core@7.26.9': |
| | | dependencies: |
| | | '@ampproject/remapping': 2.3.0 |
| | | '@babel/code-frame': 7.26.2 |
| | | '@babel/generator': 7.26.9 |
| | | '@babel/helper-compilation-targets': 7.26.5 |
| | | '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) |
| | | '@babel/helpers': 7.26.9 |
| | | '@babel/parser': 7.26.9 |
| | | '@babel/template': 7.26.9 |
| | | '@babel/traverse': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | convert-source-map: 2.0.0 |
| | | debug: 4.4.0 |
| | | gensync: 1.0.0-beta.2 |
| | | json5: 2.2.3 |
| | | semver: 6.3.1 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/generator@7.26.9': |
| | | dependencies: |
| | | '@babel/parser': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | '@jridgewell/gen-mapping': 0.3.8 |
| | | '@jridgewell/trace-mapping': 0.3.25 |
| | | jsesc: 3.1.0 |
| | | |
| | | '@babel/helper-annotate-as-pure@7.25.9': |
| | | dependencies: |
| | | '@babel/types': 7.26.9 |
| | | |
| | | '@babel/helper-compilation-targets@7.26.5': |
| | | dependencies: |
| | | '@babel/compat-data': 7.26.8 |
| | | '@babel/helper-validator-option': 7.25.9 |
| | | browserslist: 4.24.4 |
| | | lru-cache: 5.1.1 |
| | | semver: 6.3.1 |
| | | |
| | | '@babel/helper-create-class-features-plugin@7.26.9(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-annotate-as-pure': 7.25.9 |
| | | '@babel/helper-member-expression-to-functions': 7.25.9 |
| | | '@babel/helper-optimise-call-expression': 7.25.9 |
| | | '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) |
| | | '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 |
| | | '@babel/traverse': 7.26.9 |
| | | semver: 6.3.1 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-member-expression-to-functions@7.25.9': |
| | | dependencies: |
| | | '@babel/traverse': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-module-imports@7.25.9': |
| | | dependencies: |
| | | '@babel/traverse': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-module-imports': 7.25.9 |
| | | '@babel/helper-validator-identifier': 7.25.9 |
| | | '@babel/traverse': 7.26.9 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-optimise-call-expression@7.25.9': |
| | | dependencies: |
| | | '@babel/types': 7.26.9 |
| | | |
| | | '@babel/helper-plugin-utils@7.26.5': {} |
| | | |
| | | '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-member-expression-to-functions': 7.25.9 |
| | | '@babel/helper-optimise-call-expression': 7.25.9 |
| | | '@babel/traverse': 7.26.9 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-skip-transparent-expression-wrappers@7.25.9': |
| | | dependencies: |
| | | '@babel/traverse': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-string-parser@7.25.9': {} |
| | | |
| | | '@babel/helper-validator-identifier@7.25.9': {} |
| | | |
| | | '@babel/helper-validator-option@7.25.9': {} |
| | | |
| | | '@babel/helpers@7.26.9': |
| | | dependencies: |
| | | '@babel/template': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | |
| | | '@babel/parser@7.26.9': |
| | | dependencies: |
| | | '@babel/types': 7.26.9 |
| | | |
| | | '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-plugin-utils': 7.26.5 |
| | | |
| | | '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-plugin-utils': 7.26.5 |
| | | |
| | | '@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-annotate-as-pure': 7.25.9 |
| | | '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) |
| | | '@babel/helper-plugin-utils': 7.26.5 |
| | | '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 |
| | | '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.9) |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/template@7.26.9': |
| | | dependencies: |
| | | '@babel/code-frame': 7.26.2 |
| | | '@babel/parser': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | |
| | | '@babel/traverse@7.26.9': |
| | | dependencies: |
| | | '@babel/code-frame': 7.26.2 |
| | | '@babel/generator': 7.26.9 |
| | | '@babel/parser': 7.26.9 |
| | | '@babel/template': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | debug: 4.4.0 |
| | | globals: 11.12.0 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/types@7.26.9': |
| | | dependencies: |
| | | '@babel/helper-string-parser': 7.25.9 |
| | | '@babel/helper-validator-identifier': 7.25.9 |
| | | |
| | | '@ctrl/tinycolor@3.6.1': {} |
| | | |
| | | '@element-plus/icons-vue@2.3.1(vue@3.5.13(typescript@5.7.3))': |
| | | dependencies: |
| | | vue: 3.5.13(typescript@5.7.3) |
| | | |
| | | '@esbuild/aix-ppc64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/android-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/android-arm@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/android-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/darwin-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/darwin-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/freebsd-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/freebsd-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-arm@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-ia32@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-loong64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-mips64el@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-ppc64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-riscv64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-s390x@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/linux-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/netbsd-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/netbsd-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/openbsd-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/openbsd-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/sunos-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/win32-arm64@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/win32-ia32@0.24.2': |
| | | optional: true |
| | | |
| | | '@esbuild/win32-x64@0.24.2': |
| | | optional: true |
| | | |
| | | '@floating-ui/core@1.6.9': |
| | | dependencies: |
| | | '@floating-ui/utils': 0.2.9 |
| | | |
| | | '@floating-ui/dom@1.6.13': |
| | | dependencies: |
| | | '@floating-ui/core': 1.6.9 |
| | | '@floating-ui/utils': 0.2.9 |
| | | |
| | | '@floating-ui/utils@0.2.9': {} |
| | | |
| | | '@jridgewell/gen-mapping@0.3.8': |
| | | dependencies: |
| | | '@jridgewell/set-array': 1.2.1 |
| | | '@jridgewell/sourcemap-codec': 1.5.0 |
| | | '@jridgewell/trace-mapping': 0.3.25 |
| | | |
| | | '@jridgewell/resolve-uri@3.1.2': {} |
| | | |
| | | '@jridgewell/set-array@1.2.1': {} |
| | | |
| | | '@jridgewell/sourcemap-codec@1.5.0': {} |
| | | |
| | | '@jridgewell/trace-mapping@0.3.25': |
| | | dependencies: |
| | | '@jridgewell/resolve-uri': 3.1.2 |
| | | '@jridgewell/sourcemap-codec': 1.5.0 |
| | | |
| | | '@microsoft/api-extractor-model@7.30.3(@types/node@20.17.19)': |
| | | dependencies: |
| | | '@microsoft/tsdoc': 0.15.1 |
| | | '@microsoft/tsdoc-config': 0.17.1 |
| | | '@rushstack/node-core-library': 5.11.0(@types/node@20.17.19) |
| | | transitivePeerDependencies: |
| | | - '@types/node' |
| | | |
| | | '@microsoft/api-extractor@7.50.0(@types/node@20.17.19)': |
| | | dependencies: |
| | | '@microsoft/api-extractor-model': 7.30.3(@types/node@20.17.19) |
| | | '@microsoft/tsdoc': 0.15.1 |
| | | '@microsoft/tsdoc-config': 0.17.1 |
| | | '@rushstack/node-core-library': 5.11.0(@types/node@20.17.19) |
| | | '@rushstack/rig-package': 0.5.3 |
| | | '@rushstack/terminal': 0.15.0(@types/node@20.17.19) |
| | | '@rushstack/ts-command-line': 4.23.5(@types/node@20.17.19) |
| | | lodash: 4.17.21 |
| | | minimatch: 3.0.8 |
| | | resolve: 1.22.10 |
| | | semver: 7.5.4 |
| | | source-map: 0.6.1 |
| | | typescript: 5.7.2 |
| | | transitivePeerDependencies: |
| | | - '@types/node' |
| | | |
| | | '@microsoft/tsdoc-config@0.17.1': |
| | | dependencies: |
| | | '@microsoft/tsdoc': 0.15.1 |
| | | ajv: 8.12.0 |
| | | jju: 1.4.0 |
| | | resolve: 1.22.10 |
| | | |
| | | '@microsoft/tsdoc@0.15.1': {} |
| | | |
| | | '@parcel/watcher-android-arm64@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-darwin-arm64@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-darwin-x64@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-freebsd-x64@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-linux-arm-glibc@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-linux-arm-musl@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-linux-arm64-glibc@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-linux-arm64-musl@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-linux-x64-glibc@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-linux-x64-musl@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-win32-arm64@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-win32-ia32@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher-win32-x64@2.5.1': |
| | | optional: true |
| | | |
| | | '@parcel/watcher@2.5.1': |
| | | dependencies: |
| | | detect-libc: 1.0.3 |
| | | is-glob: 4.0.3 |
| | | micromatch: 4.0.8 |
| | | node-addon-api: 7.1.1 |
| | | optionalDependencies: |
| | | '@parcel/watcher-android-arm64': 2.5.1 |
| | | '@parcel/watcher-darwin-arm64': 2.5.1 |
| | | '@parcel/watcher-darwin-x64': 2.5.1 |
| | | '@parcel/watcher-freebsd-x64': 2.5.1 |
| | | '@parcel/watcher-linux-arm-glibc': 2.5.1 |
| | | '@parcel/watcher-linux-arm-musl': 2.5.1 |
| | | '@parcel/watcher-linux-arm64-glibc': 2.5.1 |
| | | '@parcel/watcher-linux-arm64-musl': 2.5.1 |
| | | '@parcel/watcher-linux-x64-glibc': 2.5.1 |
| | | '@parcel/watcher-linux-x64-musl': 2.5.1 |
| | | '@parcel/watcher-win32-arm64': 2.5.1 |
| | | '@parcel/watcher-win32-ia32': 2.5.1 |
| | | '@parcel/watcher-win32-x64': 2.5.1 |
| | | optional: true |
| | | |
| | | '@rollup/pluginutils@5.1.4(rollup@4.34.8)': |
| | | dependencies: |
| | | '@types/estree': 1.0.6 |
| | | estree-walker: 2.0.2 |
| | | picomatch: 4.0.2 |
| | | optionalDependencies: |
| | | rollup: 4.34.8 |
| | | |
| | | '@rollup/rollup-android-arm-eabi@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-android-arm64@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-darwin-arm64@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-darwin-x64@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-freebsd-arm64@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-freebsd-x64@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-arm-gnueabihf@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-arm-musleabihf@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-arm64-gnu@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-arm64-musl@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-loongarch64-gnu@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-riscv64-gnu@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-s390x-gnu@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-x64-gnu@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-linux-x64-musl@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-win32-arm64-msvc@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-win32-ia32-msvc@4.34.8': |
| | | optional: true |
| | | |
| | | '@rollup/rollup-win32-x64-msvc@4.34.8': |
| | | optional: true |
| | | |
| | | '@rushstack/node-core-library@5.11.0(@types/node@20.17.19)': |
| | | dependencies: |
| | | ajv: 8.13.0 |
| | | ajv-draft-04: 1.0.0(ajv@8.13.0) |
| | | ajv-formats: 3.0.1(ajv@8.13.0) |
| | | fs-extra: 11.3.0 |
| | | import-lazy: 4.0.0 |
| | | jju: 1.4.0 |
| | | resolve: 1.22.10 |
| | | semver: 7.5.4 |
| | | optionalDependencies: |
| | | '@types/node': 20.17.19 |
| | | |
| | | '@rushstack/rig-package@0.5.3': |
| | | dependencies: |
| | | resolve: 1.22.10 |
| | | strip-json-comments: 3.1.1 |
| | | |
| | | '@rushstack/terminal@0.15.0(@types/node@20.17.19)': |
| | | dependencies: |
| | | '@rushstack/node-core-library': 5.11.0(@types/node@20.17.19) |
| | | supports-color: 8.1.1 |
| | | optionalDependencies: |
| | | '@types/node': 20.17.19 |
| | | |
| | | '@rushstack/ts-command-line@4.23.5(@types/node@20.17.19)': |
| | | dependencies: |
| | | '@rushstack/terminal': 0.15.0(@types/node@20.17.19) |
| | | '@types/argparse': 1.0.38 |
| | | argparse: 1.0.10 |
| | | string-argv: 0.3.2 |
| | | transitivePeerDependencies: |
| | | - '@types/node' |
| | | |
| | | '@sxzz/popperjs-es@2.11.7': {} |
| | | |
| | | '@types/argparse@1.0.38': {} |
| | | |
| | | '@types/estree@1.0.6': {} |
| | | |
| | | '@types/lodash-es@4.17.12': |
| | | dependencies: |
| | | '@types/lodash': 4.17.15 |
| | | |
| | | '@types/lodash@4.17.15': {} |
| | | |
| | | '@types/node@20.17.19': |
| | | dependencies: |
| | | undici-types: 6.19.8 |
| | | |
| | | '@types/web-bluetooth@0.0.16': {} |
| | | |
| | | '@vitejs/plugin-vue-jsx@4.1.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))': |
| | | dependencies: |
| | | '@babel/core': 7.26.9 |
| | | '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.9) |
| | | '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.9) |
| | | vite: 6.1.0(@types/node@20.17.19)(sass@1.85.0) |
| | | vue: 3.5.13(typescript@5.7.3) |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@vitejs/plugin-vue@5.2.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))': |
| | | dependencies: |
| | | vite: 6.1.0(@types/node@20.17.19)(sass@1.85.0) |
| | | vue: 3.5.13(typescript@5.7.3) |
| | | |
| | | '@volar/language-core@2.4.11': |
| | | dependencies: |
| | | '@volar/source-map': 2.4.11 |
| | | |
| | | '@volar/source-map@2.4.11': {} |
| | | |
| | | '@volar/typescript@2.4.11': |
| | | dependencies: |
| | | '@volar/language-core': 2.4.11 |
| | | path-browserify: 1.0.1 |
| | | vscode-uri: 3.1.0 |
| | | |
| | | '@vue/babel-helper-vue-transform-on@1.2.5': {} |
| | | |
| | | '@vue/babel-plugin-jsx@1.2.5(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/helper-module-imports': 7.25.9 |
| | | '@babel/helper-plugin-utils': 7.26.5 |
| | | '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) |
| | | '@babel/template': 7.26.9 |
| | | '@babel/traverse': 7.26.9 |
| | | '@babel/types': 7.26.9 |
| | | '@vue/babel-helper-vue-transform-on': 1.2.5 |
| | | '@vue/babel-plugin-resolve-type': 1.2.5(@babel/core@7.26.9) |
| | | html-tags: 3.3.1 |
| | | svg-tags: 1.0.0 |
| | | optionalDependencies: |
| | | '@babel/core': 7.26.9 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@vue/babel-plugin-resolve-type@1.2.5(@babel/core@7.26.9)': |
| | | dependencies: |
| | | '@babel/code-frame': 7.26.2 |
| | | '@babel/core': 7.26.9 |
| | | '@babel/helper-module-imports': 7.25.9 |
| | | '@babel/helper-plugin-utils': 7.26.5 |
| | | '@babel/parser': 7.26.9 |
| | | '@vue/compiler-sfc': 3.5.13 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@vue/compiler-core@3.5.13': |
| | | dependencies: |
| | | '@babel/parser': 7.26.9 |
| | | '@vue/shared': 3.5.13 |
| | | entities: 4.5.0 |
| | | estree-walker: 2.0.2 |
| | | source-map-js: 1.2.1 |
| | | |
| | | '@vue/compiler-dom@3.5.13': |
| | | dependencies: |
| | | '@vue/compiler-core': 3.5.13 |
| | | '@vue/shared': 3.5.13 |
| | | |
| | | '@vue/compiler-sfc@3.5.13': |
| | | dependencies: |
| | | '@babel/parser': 7.26.9 |
| | | '@vue/compiler-core': 3.5.13 |
| | | '@vue/compiler-dom': 3.5.13 |
| | | '@vue/compiler-ssr': 3.5.13 |
| | | '@vue/shared': 3.5.13 |
| | | estree-walker: 2.0.2 |
| | | magic-string: 0.30.17 |
| | | postcss: 8.5.2 |
| | | source-map-js: 1.2.1 |
| | | |
| | | '@vue/compiler-ssr@3.5.13': |
| | | dependencies: |
| | | '@vue/compiler-dom': 3.5.13 |
| | | '@vue/shared': 3.5.13 |
| | | |
| | | '@vue/compiler-vue2@2.7.16': |
| | | dependencies: |
| | | de-indent: 1.0.2 |
| | | he: 1.2.0 |
| | | |
| | | '@vue/language-core@2.2.0(typescript@5.7.3)': |
| | | dependencies: |
| | | '@volar/language-core': 2.4.11 |
| | | '@vue/compiler-dom': 3.5.13 |
| | | '@vue/compiler-vue2': 2.7.16 |
| | | '@vue/shared': 3.5.13 |
| | | alien-signals: 0.4.14 |
| | | minimatch: 9.0.5 |
| | | muggle-string: 0.4.1 |
| | | path-browserify: 1.0.1 |
| | | optionalDependencies: |
| | | typescript: 5.7.3 |
| | | |
| | | '@vue/language-core@2.2.2(typescript@5.7.3)': |
| | | dependencies: |
| | | '@volar/language-core': 2.4.11 |
| | | '@vue/compiler-dom': 3.5.13 |
| | | '@vue/compiler-vue2': 2.7.16 |
| | | '@vue/shared': 3.5.13 |
| | | alien-signals: 1.0.3 |
| | | minimatch: 9.0.5 |
| | | muggle-string: 0.4.1 |
| | | path-browserify: 1.0.1 |
| | | optionalDependencies: |
| | | typescript: 5.7.3 |
| | | |
| | | '@vue/reactivity@3.5.13': |
| | | dependencies: |
| | | '@vue/shared': 3.5.13 |
| | | |
| | | '@vue/runtime-core@3.5.13': |
| | | dependencies: |
| | | '@vue/reactivity': 3.5.13 |
| | | '@vue/shared': 3.5.13 |
| | | |
| | | '@vue/runtime-dom@3.5.13': |
| | | dependencies: |
| | | '@vue/reactivity': 3.5.13 |
| | | '@vue/runtime-core': 3.5.13 |
| | | '@vue/shared': 3.5.13 |
| | | csstype: 3.1.3 |
| | | |
| | | '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.7.3))': |
| | | dependencies: |
| | | '@vue/compiler-ssr': 3.5.13 |
| | | '@vue/shared': 3.5.13 |
| | | vue: 3.5.13(typescript@5.7.3) |
| | | |
| | | '@vue/shared@3.5.13': {} |
| | | |
| | | '@vueuse/core@9.13.0(vue@3.5.13(typescript@5.7.3))': |
| | | dependencies: |
| | | '@types/web-bluetooth': 0.0.16 |
| | | '@vueuse/metadata': 9.13.0 |
| | | '@vueuse/shared': 9.13.0(vue@3.5.13(typescript@5.7.3)) |
| | | vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3)) |
| | | transitivePeerDependencies: |
| | | - '@vue/composition-api' |
| | | - vue |
| | | |
| | | '@vueuse/metadata@9.13.0': {} |
| | | |
| | | '@vueuse/shared@9.13.0(vue@3.5.13(typescript@5.7.3))': |
| | | dependencies: |
| | | vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3)) |
| | | transitivePeerDependencies: |
| | | - '@vue/composition-api' |
| | | - vue |
| | | |
| | | acorn@8.14.0: {} |
| | | |
| | | ajv-draft-04@1.0.0(ajv@8.13.0): |
| | | optionalDependencies: |
| | | ajv: 8.13.0 |
| | | |
| | | ajv-formats@3.0.1(ajv@8.13.0): |
| | | optionalDependencies: |
| | | ajv: 8.13.0 |
| | | |
| | | ajv@8.12.0: |
| | | dependencies: |
| | | fast-deep-equal: 3.1.3 |
| | | json-schema-traverse: 1.0.0 |
| | | require-from-string: 2.0.2 |
| | | uri-js: 4.4.1 |
| | | |
| | | ajv@8.13.0: |
| | | dependencies: |
| | | fast-deep-equal: 3.1.3 |
| | | json-schema-traverse: 1.0.0 |
| | | require-from-string: 2.0.2 |
| | | uri-js: 4.4.1 |
| | | |
| | | alien-signals@0.4.14: {} |
| | | |
| | | alien-signals@1.0.3: {} |
| | | |
| | | argparse@1.0.10: |
| | | dependencies: |
| | | sprintf-js: 1.0.3 |
| | | |
| | | async-validator@4.2.5: {} |
| | | |
| | | balanced-match@1.0.2: {} |
| | | |
| | | brace-expansion@1.1.11: |
| | | dependencies: |
| | | balanced-match: 1.0.2 |
| | | concat-map: 0.0.1 |
| | | |
| | | brace-expansion@2.0.1: |
| | | dependencies: |
| | | balanced-match: 1.0.2 |
| | | |
| | | braces@3.0.3: |
| | | dependencies: |
| | | fill-range: 7.1.1 |
| | | optional: true |
| | | |
| | | browserslist@4.24.4: |
| | | dependencies: |
| | | caniuse-lite: 1.0.30001700 |
| | | electron-to-chromium: 1.5.102 |
| | | node-releases: 2.0.19 |
| | | update-browserslist-db: 1.1.2(browserslist@4.24.4) |
| | | |
| | | caniuse-lite@1.0.30001700: {} |
| | | |
| | | chokidar@4.0.3: |
| | | dependencies: |
| | | readdirp: 4.1.2 |
| | | |
| | | compare-versions@6.1.1: {} |
| | | |
| | | concat-map@0.0.1: {} |
| | | |
| | | confbox@0.1.8: {} |
| | | |
| | | convert-source-map@2.0.0: {} |
| | | |
| | | csstype@3.1.3: {} |
| | | |
| | | dayjs@1.11.13: {} |
| | | |
| | | de-indent@1.0.2: {} |
| | | |
| | | debug@4.4.0: |
| | | dependencies: |
| | | ms: 2.1.3 |
| | | |
| | | detect-libc@1.0.3: |
| | | optional: true |
| | | |
| | | electron-to-chromium@1.5.102: {} |
| | | |
| | | element-plus@2.9.4(vue@3.5.13(typescript@5.7.3)): |
| | | dependencies: |
| | | '@ctrl/tinycolor': 3.6.1 |
| | | '@element-plus/icons-vue': 2.3.1(vue@3.5.13(typescript@5.7.3)) |
| | | '@floating-ui/dom': 1.6.13 |
| | | '@popperjs/core': '@sxzz/popperjs-es@2.11.7' |
| | | '@types/lodash': 4.17.15 |
| | | '@types/lodash-es': 4.17.12 |
| | | '@vueuse/core': 9.13.0(vue@3.5.13(typescript@5.7.3)) |
| | | async-validator: 4.2.5 |
| | | dayjs: 1.11.13 |
| | | escape-html: 1.0.3 |
| | | lodash: 4.17.21 |
| | | lodash-es: 4.17.21 |
| | | lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) |
| | | memoize-one: 6.0.0 |
| | | normalize-wheel-es: 1.2.0 |
| | | vue: 3.5.13(typescript@5.7.3) |
| | | transitivePeerDependencies: |
| | | - '@vue/composition-api' |
| | | |
| | | entities@4.5.0: {} |
| | | |
| | | esbuild@0.24.2: |
| | | optionalDependencies: |
| | | '@esbuild/aix-ppc64': 0.24.2 |
| | | '@esbuild/android-arm': 0.24.2 |
| | | '@esbuild/android-arm64': 0.24.2 |
| | | '@esbuild/android-x64': 0.24.2 |
| | | '@esbuild/darwin-arm64': 0.24.2 |
| | | '@esbuild/darwin-x64': 0.24.2 |
| | | '@esbuild/freebsd-arm64': 0.24.2 |
| | | '@esbuild/freebsd-x64': 0.24.2 |
| | | '@esbuild/linux-arm': 0.24.2 |
| | | '@esbuild/linux-arm64': 0.24.2 |
| | | '@esbuild/linux-ia32': 0.24.2 |
| | | '@esbuild/linux-loong64': 0.24.2 |
| | | '@esbuild/linux-mips64el': 0.24.2 |
| | | '@esbuild/linux-ppc64': 0.24.2 |
| | | '@esbuild/linux-riscv64': 0.24.2 |
| | | '@esbuild/linux-s390x': 0.24.2 |
| | | '@esbuild/linux-x64': 0.24.2 |
| | | '@esbuild/netbsd-arm64': 0.24.2 |
| | | '@esbuild/netbsd-x64': 0.24.2 |
| | | '@esbuild/openbsd-arm64': 0.24.2 |
| | | '@esbuild/openbsd-x64': 0.24.2 |
| | | '@esbuild/sunos-x64': 0.24.2 |
| | | '@esbuild/win32-arm64': 0.24.2 |
| | | '@esbuild/win32-ia32': 0.24.2 |
| | | '@esbuild/win32-x64': 0.24.2 |
| | | |
| | | escalade@3.2.0: {} |
| | | |
| | | escape-html@1.0.3: {} |
| | | |
| | | estree-walker@2.0.2: {} |
| | | |
| | | fast-deep-equal@3.1.3: {} |
| | | |
| | | fill-range@7.1.1: |
| | | dependencies: |
| | | to-regex-range: 5.0.1 |
| | | optional: true |
| | | |
| | | fs-extra@11.3.0: |
| | | dependencies: |
| | | graceful-fs: 4.2.11 |
| | | jsonfile: 6.1.0 |
| | | universalify: 2.0.1 |
| | | |
| | | fsevents@2.3.3: |
| | | optional: true |
| | | |
| | | function-bind@1.1.2: {} |
| | | |
| | | gensync@1.0.0-beta.2: {} |
| | | |
| | | globals@11.12.0: {} |
| | | |
| | | graceful-fs@4.2.11: {} |
| | | |
| | | has-flag@4.0.0: {} |
| | | |
| | | hasown@2.0.2: |
| | | dependencies: |
| | | function-bind: 1.1.2 |
| | | |
| | | he@1.2.0: {} |
| | | |
| | | html-tags@3.3.1: {} |
| | | |
| | | immutable@5.0.3: {} |
| | | |
| | | import-lazy@4.0.0: {} |
| | | |
| | | is-core-module@2.16.1: |
| | | dependencies: |
| | | hasown: 2.0.2 |
| | | |
| | | is-extglob@2.1.1: |
| | | optional: true |
| | | |
| | | is-glob@4.0.3: |
| | | dependencies: |
| | | is-extglob: 2.1.1 |
| | | optional: true |
| | | |
| | | is-number@7.0.0: |
| | | optional: true |
| | | |
| | | jju@1.4.0: {} |
| | | |
| | | js-tokens@4.0.0: {} |
| | | |
| | | jsesc@3.1.0: {} |
| | | |
| | | json-schema-traverse@1.0.0: {} |
| | | |
| | | json5@2.2.3: {} |
| | | |
| | | jsonfile@6.1.0: |
| | | dependencies: |
| | | universalify: 2.0.1 |
| | | optionalDependencies: |
| | | graceful-fs: 4.2.11 |
| | | |
| | | kolorist@1.8.0: {} |
| | | |
| | | local-pkg@0.5.1: |
| | | dependencies: |
| | | mlly: 1.7.4 |
| | | pkg-types: 1.3.1 |
| | | |
| | | lodash-es@4.17.21: {} |
| | | |
| | | lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): |
| | | dependencies: |
| | | '@types/lodash-es': 4.17.12 |
| | | lodash: 4.17.21 |
| | | lodash-es: 4.17.21 |
| | | |
| | | lodash@4.17.21: {} |
| | | |
| | | lru-cache@5.1.1: |
| | | dependencies: |
| | | yallist: 3.1.1 |
| | | |
| | | lru-cache@6.0.0: |
| | | dependencies: |
| | | yallist: 4.0.0 |
| | | |
| | | magic-string@0.30.17: |
| | | dependencies: |
| | | '@jridgewell/sourcemap-codec': 1.5.0 |
| | | |
| | | memoize-one@6.0.0: {} |
| | | |
| | | micromatch@4.0.8: |
| | | dependencies: |
| | | braces: 3.0.3 |
| | | picomatch: 2.3.1 |
| | | optional: true |
| | | |
| | | minimatch@3.0.8: |
| | | dependencies: |
| | | brace-expansion: 1.1.11 |
| | | |
| | | minimatch@9.0.5: |
| | | dependencies: |
| | | brace-expansion: 2.0.1 |
| | | |
| | | mlly@1.7.4: |
| | | dependencies: |
| | | acorn: 8.14.0 |
| | | pathe: 2.0.3 |
| | | pkg-types: 1.3.1 |
| | | ufo: 1.5.4 |
| | | |
| | | ms@2.1.3: {} |
| | | |
| | | muggle-string@0.4.1: {} |
| | | |
| | | nanoid@3.3.8: {} |
| | | |
| | | neo-async@2.6.2: {} |
| | | |
| | | node-addon-api@7.1.1: |
| | | optional: true |
| | | |
| | | node-releases@2.0.19: {} |
| | | |
| | | normalize-wheel-es@1.2.0: {} |
| | | |
| | | path-browserify@1.0.1: {} |
| | | |
| | | path-parse@1.0.7: {} |
| | | |
| | | pathe@2.0.3: {} |
| | | |
| | | picocolors@1.1.1: {} |
| | | |
| | | picomatch@2.3.1: |
| | | optional: true |
| | | |
| | | picomatch@4.0.2: {} |
| | | |
| | | pkg-types@1.3.1: |
| | | dependencies: |
| | | confbox: 0.1.8 |
| | | mlly: 1.7.4 |
| | | pathe: 2.0.3 |
| | | |
| | | postcss@8.5.2: |
| | | dependencies: |
| | | nanoid: 3.3.8 |
| | | picocolors: 1.1.1 |
| | | source-map-js: 1.2.1 |
| | | |
| | | prettier@3.5.1: {} |
| | | |
| | | punycode@2.3.1: {} |
| | | |
| | | readdirp@4.1.2: {} |
| | | |
| | | require-from-string@2.0.2: {} |
| | | |
| | | resolve@1.22.10: |
| | | dependencies: |
| | | is-core-module: 2.16.1 |
| | | path-parse: 1.0.7 |
| | | supports-preserve-symlinks-flag: 1.0.0 |
| | | |
| | | rollup@4.34.8: |
| | | dependencies: |
| | | '@types/estree': 1.0.6 |
| | | optionalDependencies: |
| | | '@rollup/rollup-android-arm-eabi': 4.34.8 |
| | | '@rollup/rollup-android-arm64': 4.34.8 |
| | | '@rollup/rollup-darwin-arm64': 4.34.8 |
| | | '@rollup/rollup-darwin-x64': 4.34.8 |
| | | '@rollup/rollup-freebsd-arm64': 4.34.8 |
| | | '@rollup/rollup-freebsd-x64': 4.34.8 |
| | | '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 |
| | | '@rollup/rollup-linux-arm-musleabihf': 4.34.8 |
| | | '@rollup/rollup-linux-arm64-gnu': 4.34.8 |
| | | '@rollup/rollup-linux-arm64-musl': 4.34.8 |
| | | '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 |
| | | '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 |
| | | '@rollup/rollup-linux-riscv64-gnu': 4.34.8 |
| | | '@rollup/rollup-linux-s390x-gnu': 4.34.8 |
| | | '@rollup/rollup-linux-x64-gnu': 4.34.8 |
| | | '@rollup/rollup-linux-x64-musl': 4.34.8 |
| | | '@rollup/rollup-win32-arm64-msvc': 4.34.8 |
| | | '@rollup/rollup-win32-ia32-msvc': 4.34.8 |
| | | '@rollup/rollup-win32-x64-msvc': 4.34.8 |
| | | fsevents: 2.3.3 |
| | | |
| | | sass-loader@16.0.5(sass@1.85.0): |
| | | dependencies: |
| | | neo-async: 2.6.2 |
| | | optionalDependencies: |
| | | sass: 1.85.0 |
| | | |
| | | sass@1.85.0: |
| | | dependencies: |
| | | chokidar: 4.0.3 |
| | | immutable: 5.0.3 |
| | | source-map-js: 1.2.1 |
| | | optionalDependencies: |
| | | '@parcel/watcher': 2.5.1 |
| | | |
| | | semver@6.3.1: {} |
| | | |
| | | semver@7.5.4: |
| | | dependencies: |
| | | lru-cache: 6.0.0 |
| | | |
| | | source-map-js@1.2.1: {} |
| | | |
| | | source-map@0.6.1: {} |
| | | |
| | | sprintf-js@1.0.3: {} |
| | | |
| | | string-argv@0.3.2: {} |
| | | |
| | | strip-json-comments@3.1.1: {} |
| | | |
| | | supports-color@8.1.1: |
| | | dependencies: |
| | | has-flag: 4.0.0 |
| | | |
| | | supports-preserve-symlinks-flag@1.0.0: {} |
| | | |
| | | svg-tags@1.0.0: {} |
| | | |
| | | to-regex-range@5.0.1: |
| | | dependencies: |
| | | is-number: 7.0.0 |
| | | optional: true |
| | | |
| | | typescript@5.7.2: {} |
| | | |
| | | typescript@5.7.3: {} |
| | | |
| | | ufo@1.5.4: {} |
| | | |
| | | undici-types@6.19.8: {} |
| | | |
| | | universalify@2.0.1: {} |
| | | |
| | | update-browserslist-db@1.1.2(browserslist@4.24.4): |
| | | dependencies: |
| | | browserslist: 4.24.4 |
| | | escalade: 3.2.0 |
| | | picocolors: 1.1.1 |
| | | |
| | | uri-js@4.4.1: |
| | | dependencies: |
| | | punycode: 2.3.1 |
| | | |
| | | vite-plugin-dts@4.5.0(@types/node@20.17.19)(rollup@4.34.8)(typescript@5.7.3)(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0)): |
| | | dependencies: |
| | | '@microsoft/api-extractor': 7.50.0(@types/node@20.17.19) |
| | | '@rollup/pluginutils': 5.1.4(rollup@4.34.8) |
| | | '@volar/typescript': 2.4.11 |
| | | '@vue/language-core': 2.2.0(typescript@5.7.3) |
| | | compare-versions: 6.1.1 |
| | | debug: 4.4.0 |
| | | kolorist: 1.8.0 |
| | | local-pkg: 0.5.1 |
| | | magic-string: 0.30.17 |
| | | typescript: 5.7.3 |
| | | optionalDependencies: |
| | | vite: 6.1.0(@types/node@20.17.19)(sass@1.85.0) |
| | | transitivePeerDependencies: |
| | | - '@types/node' |
| | | - rollup |
| | | - supports-color |
| | | |
| | | vite@6.1.0(@types/node@20.17.19)(sass@1.85.0): |
| | | dependencies: |
| | | esbuild: 0.24.2 |
| | | postcss: 8.5.2 |
| | | rollup: 4.34.8 |
| | | optionalDependencies: |
| | | '@types/node': 20.17.19 |
| | | fsevents: 2.3.3 |
| | | sass: 1.85.0 |
| | | |
| | | vscode-uri@3.1.0: {} |
| | | |
| | | vue-demi@0.14.10(vue@3.5.13(typescript@5.7.3)): |
| | | dependencies: |
| | | vue: 3.5.13(typescript@5.7.3) |
| | | |
| | | vue-tsc@2.2.2(typescript@5.7.3): |
| | | dependencies: |
| | | '@volar/typescript': 2.4.11 |
| | | '@vue/language-core': 2.2.2(typescript@5.7.3) |
| | | typescript: 5.7.3 |
| | | |
| | | vue@3.5.13(typescript@5.7.3): |
| | | dependencies: |
| | | '@vue/compiler-dom': 3.5.13 |
| | | '@vue/compiler-sfc': 3.5.13 |
| | | '@vue/runtime-dom': 3.5.13 |
| | | '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.7.3)) |
| | | '@vue/shared': 3.5.13 |
| | | optionalDependencies: |
| | | typescript: 5.7.3 |
| | | |
| | | yallist@3.1.1: {} |
| | | |
| | | yallist@4.0.0: {} |
| New file |
| | |
| | | <template> |
| | | <div> |
| | | <div class="title">CRUD DEMO v8</div> |
| | | |
| | | <cl-crud ref="Crud"> |
| | | <div class="search"> |
| | | <cl-search ref="Search" /> |
| | | </div> |
| | | |
| | | <cl-row> |
| | | <cl-add-btn /> |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | <cl-search-key |
| | | field="name" |
| | | :field-list="[ |
| | | { |
| | | label: '昵称', |
| | | value: 'name' |
| | | }, |
| | | { |
| | | label: '手机号', |
| | | value: 'phone' |
| | | } |
| | | ]" |
| | | refreshOnInput |
| | | /> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-table ref="Table" :auto-height="false"></cl-table> |
| | | </cl-row> |
| | | |
| | | <cl-row> |
| | | <cl-flex1 /> |
| | | <cl-pagination /> |
| | | </cl-row> |
| | | |
| | | <cl-upsert ref="Upsert"></cl-upsert> |
| | | <cl-form ref="Form"></cl-form> |
| | | </cl-crud> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="tsx"> |
| | | import { useTable, useForm, useUpsert, useCrud, useSearch } from "./hooks"; |
| | | import { EditPen } from "@element-plus/icons-vue"; |
| | | |
| | | interface Data { |
| | | name?: string; |
| | | age?: number; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | const Upsert = useUpsert<Data>({ |
| | | items: [ |
| | | { |
| | | type: "tabs", |
| | | props: { |
| | | labels: [ |
| | | { |
| | | label: "基础", |
| | | value: "A", |
| | | icon: EditPen |
| | | }, |
| | | { |
| | | label: "高级", |
| | | value: "B" |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | group: "A", |
| | | prop: "age", |
| | | label: "年龄", |
| | | component: { |
| | | name: "el-input" |
| | | } |
| | | }, |
| | | { |
| | | group: "A", |
| | | prop: "name", |
| | | label: "昵称", |
| | | component: { |
| | | name: "el-input" |
| | | }, |
| | | hidden({ scope }) { |
| | | return scope.age < 18; |
| | | } |
| | | }, |
| | | { |
| | | group: "B", |
| | | prop: "phone", |
| | | label: "手机", |
| | | component: { |
| | | name: "el-input" |
| | | }, |
| | | hidden({ scope }) { |
| | | return scope.age < 18; |
| | | } |
| | | }, |
| | | () => { |
| | | return { |
| | | group: "A", |
| | | hidden: Upsert.value?.mode == "add" |
| | | }; |
| | | } |
| | | ], |
| | | onOpened(data) { |
| | | console.log(data); |
| | | Upsert.value?.setForm("age", "18"); |
| | | } |
| | | }); |
| | | |
| | | const Table = useTable<Data>( |
| | | { |
| | | contextMenu: [ |
| | | { |
| | | label: "带图标", |
| | | prefixIcon: EditPen |
| | | }, |
| | | { |
| | | label: "多层级", |
| | | children: [ |
| | | { |
| | | label: "A", |
| | | children: [ |
| | | { |
| | | label: "A-1" |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | label: "B" |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | |
| | | columns: [ |
| | | { |
| | | label: "姓名", |
| | | prop: "name", |
| | | search: { |
| | | component: { |
| | | name: "el-date-picker" |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: "手机号", |
| | | prop: "phone", |
| | | search: { |
| | | component: { |
| | | name: "el-date-picker" |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | type: "op" |
| | | } |
| | | ] |
| | | }, |
| | | (table) => { |
| | | console.log(table); |
| | | } |
| | | ); |
| | | |
| | | const Crud = useCrud( |
| | | { |
| | | service: "test" |
| | | }, |
| | | (app) => { |
| | | app.refresh(); |
| | | } |
| | | ); |
| | | |
| | | const Form = useForm<Data>(); |
| | | |
| | | const Search = useSearch({ |
| | | collapse: true, |
| | | resetBtn: true, |
| | | items: [ |
| | | { |
| | | label: "姓名", |
| | | prop: "name", |
| | | component: { |
| | | name: "el-input" |
| | | }, |
| | | hook: { |
| | | reset() { |
| | | return []; |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .title { |
| | | text-align: center; |
| | | font-size: 14px; |
| | | font-weight: bold; |
| | | } |
| | | </style> |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | import { useConfig, useCore } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-add-btn", |
| | | |
| | | setup(_, { slots }) { |
| | | const { crud } = useCore(); |
| | | const { style } = useConfig(); |
| | | |
| | | return () => { |
| | | return ( |
| | | crud.getPermission("add") && ( |
| | | <el-button type="primary" size={style.size} onClick={crud.rowAdd}> |
| | | {slots.default?.() || crud.dict.label.add} |
| | | </el-button> |
| | | ) |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { useConfig, useCore } from "../../hooks"; |
| | | import { defineComponent } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-adv-btn", |
| | | |
| | | components: { |
| | | Search |
| | | }, |
| | | |
| | | setup(_, { slots }) { |
| | | const { crud, mitt } = useCore(); |
| | | const { style } = useConfig(); |
| | | |
| | | function open() { |
| | | mitt.emit("crud.openAdvSearch"); |
| | | } |
| | | |
| | | return () => { |
| | | return ( |
| | | <el-button size={style.size} onClick={open} class="cl-adv-btn"> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | {slots.default?.() || crud.dict.label.advSearch} |
| | | </el-button> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent, h, inject, mergeProps, nextTick, type PropType, reactive, ref } from "vue"; |
| | | import { Close } from "@element-plus/icons-vue"; |
| | | import { useBrowser, useConfig, useCore } from "../../hooks"; |
| | | import { renderNode } from "../../utils/vnode"; |
| | | import { useApi } from "../form/helper"; |
| | | import { isArray } from "lodash-es"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-adv-search", |
| | | |
| | | components: { |
| | | Close |
| | | }, |
| | | |
| | | props: { |
| | | // 表单项 |
| | | items: { |
| | | type: Array as PropType<ClForm.Item[]>, |
| | | default: () => [] |
| | | }, |
| | | // 标题 |
| | | title: String, |
| | | // 窗体大小 |
| | | size: { |
| | | type: [Number, String], |
| | | default: "30%" |
| | | }, |
| | | // 操作按钮 |
| | | op: { |
| | | type: Array, |
| | | default: () => ["clear", "reset", "close", "search"] |
| | | }, |
| | | // 搜索钩子 |
| | | onSearch: Function |
| | | }, |
| | | |
| | | emits: ["reset", "clear"], |
| | | |
| | | setup(props, { emit, slots, expose }) { |
| | | const { crud, mitt } = useCore(); |
| | | const { style } = useConfig(); |
| | | const browser = useBrowser(); |
| | | |
| | | // 配置 |
| | | const config = reactive<ClAdvSearch.Config>( |
| | | mergeProps(props, inject("useAdvSearch__options") || {}) |
| | | ); |
| | | |
| | | // cl-form |
| | | const Form = ref<ClForm.Ref>(); |
| | | |
| | | // el-drawer |
| | | const Drawer = ref(); |
| | | |
| | | // 是否可见 |
| | | const visible = ref(false); |
| | | |
| | | // 打开 |
| | | function open() { |
| | | visible.value = true; |
| | | |
| | | nextTick(() => { |
| | | Form.value?.open({ |
| | | items: config.items || [], |
| | | op: { |
| | | hidden: true |
| | | }, |
| | | isReset: false |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | // 关闭 |
| | | function close() { |
| | | Drawer.value.handleClose(); |
| | | } |
| | | |
| | | // 重置数据 |
| | | function reset() { |
| | | const d: any = {}; |
| | | |
| | | config.items?.map((e) => { |
| | | if (typeof e.hook != 'string' && e.hook?.reset) { |
| | | const props = e.hook.reset(e.prop!) |
| | | |
| | | if (isArray(props)) { |
| | | props.forEach((prop) => { |
| | | d[prop] = undefined; |
| | | }) |
| | | } |
| | | } |
| | | |
| | | d[e.prop!] = undefined; |
| | | }); |
| | | |
| | | // 重置表单 |
| | | Form.value?.reset(); |
| | | |
| | | // 列表刷新 |
| | | search(); |
| | | |
| | | // 重置事件 |
| | | emit("reset", d); |
| | | } |
| | | |
| | | // 清空数据 |
| | | function clear() { |
| | | Form.value?.clear(); |
| | | emit("clear"); |
| | | } |
| | | |
| | | // 搜素请求 |
| | | function search(params?: any) { |
| | | const form = Form.value?.getForm(); |
| | | |
| | | function next(data: any) { |
| | | Form.value?.done(); |
| | | close(); |
| | | |
| | | return crud.refresh({ |
| | | ...data, |
| | | ...params, |
| | | page: 1 |
| | | }); |
| | | } |
| | | |
| | | if (config.onSearch) { |
| | | config.onSearch(form, { next, close }); |
| | | } else { |
| | | next(form); |
| | | } |
| | | } |
| | | |
| | | // 消息事件 |
| | | mitt.on("crud.openAdvSearch", open); |
| | | |
| | | // 渲染表单 |
| | | function renderForm() { |
| | | return h(<cl-form ref={Form} inner enable-plugin={false} />, {}, slots); |
| | | } |
| | | |
| | | // 渲染底部 |
| | | function renderFooter() { |
| | | const fns = { search, reset, clear, close }; |
| | | |
| | | return config.op?.map((e: string) => { |
| | | switch (e) { |
| | | case "search": |
| | | case "reset": |
| | | case "clear": |
| | | case "close": |
| | | return h( |
| | | <el-button />, |
| | | { |
| | | type: e == "search" ? "primary" : null, |
| | | size: style.size, |
| | | onClick: () => { |
| | | fns[e]() |
| | | } |
| | | }, |
| | | { default: () => crud.dict.label[e] } |
| | | ); |
| | | |
| | | default: |
| | | return renderNode(e, { |
| | | scope: Form.value?.getForm(), |
| | | slots |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | expose({ |
| | | open, |
| | | close, |
| | | clear, |
| | | ...useApi({ Form }), |
| | | reset, |
| | | Form |
| | | }); |
| | | |
| | | return () => { |
| | | return ( |
| | | <el-drawer |
| | | ref={Drawer} |
| | | modal-class="cl-adv-search" |
| | | v-model={visible.value} |
| | | direction="rtl" |
| | | with-header={false} |
| | | size={browser.isMini ? "100%" : config.size}> |
| | | <div class="cl-adv-search__header"> |
| | | <span class="text">{config.title || crud.dict.label.advSearch}</span> |
| | | <el-icon size={20} onClick={close}> |
| | | <Close /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="cl-adv-search__container">{renderForm()}</div> |
| | | <div class="cl-adv-search__footer">{renderFooter()}</div> |
| | | </el-drawer> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { |
| | | defineComponent, |
| | | nextTick, |
| | | onMounted, |
| | | reactive, |
| | | ref, |
| | | h, |
| | | render, |
| | | toRaw, |
| | | type PropType |
| | | } from "vue"; |
| | | import { isString } from "lodash-es"; |
| | | import { addClass, contains, removeClass } from "../../utils"; |
| | | import { useRefs } from "../../hooks"; |
| | | import { ElIcon } from "element-plus"; |
| | | import { ArrowRight } from "@element-plus/icons-vue"; |
| | | |
| | | const ClContextMenu = defineComponent({ |
| | | name: "cl-context-menu", |
| | | |
| | | props: { |
| | | show: Boolean, |
| | | options: { |
| | | type: Object as PropType<ClContextMenu.Options>, |
| | | default: () => ({}) |
| | | }, |
| | | event: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | } |
| | | }, |
| | | |
| | | setup(props, { expose, slots }) { |
| | | const { refs, setRefs } = useRefs(); |
| | | |
| | | // 是否可见 |
| | | const visible = ref(props.show || false); |
| | | |
| | | // 按钮列表 |
| | | const list = ref<ClContextMenu.Item[]>([]); |
| | | |
| | | // 样式 |
| | | const style = reactive({ |
| | | left: "0px", |
| | | top: "0px" |
| | | }); |
| | | |
| | | // 选中值 |
| | | const ids = ref(""); |
| | | |
| | | // 阻止默认事件 |
| | | function stopDefault(e: any) { |
| | | if (e.preventDefault) { |
| | | e.preventDefault(); |
| | | } |
| | | |
| | | if (e.stopPropagation) { |
| | | e.stopPropagation(); |
| | | } |
| | | } |
| | | |
| | | // 解析列表 |
| | | function parseList(list: ClContextMenu.Item[]) { |
| | | function deep(list: ClContextMenu.Item[]) { |
| | | list.forEach((e) => { |
| | | e.showChildren = false; |
| | | |
| | | if (e.children) { |
| | | deep(e.children); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | deep(list); |
| | | |
| | | return list; |
| | | } |
| | | |
| | | // 目标元素 |
| | | let targetEl: any; |
| | | |
| | | // 关闭 |
| | | function close() { |
| | | visible.value = false; |
| | | ids.value = ""; |
| | | |
| | | if (targetEl) { |
| | | removeClass(targetEl, "cl-context-menu__target"); |
| | | } |
| | | } |
| | | |
| | | // 打开 |
| | | function open(event: any, options: ClContextMenu.Options = {}) { |
| | | // 阻止默认事件 |
| | | stopDefault(event); |
| | | |
| | | // 显示 |
| | | visible.value = true; |
| | | |
| | | // 元素 |
| | | const el = refs["context-menu"].querySelector(".cl-context-menu__box") as HTMLElement; |
| | | |
| | | // 点击样式 |
| | | if (options?.hover) { |
| | | const d = options.hover === true ? {} : options.hover; |
| | | targetEl = event.target; |
| | | |
| | | if (targetEl && isString(targetEl.className)) { |
| | | if (d.target) { |
| | | while (!targetEl.className.includes(d.target)) { |
| | | targetEl = targetEl.parentNode; |
| | | } |
| | | } |
| | | |
| | | addClass(targetEl, d.className || "cl-context-menu__target"); |
| | | } |
| | | } |
| | | |
| | | // 自定义样式 |
| | | if (options?.class) { |
| | | addClass(el, options.class); |
| | | } |
| | | |
| | | // 菜单列表 |
| | | if (options?.list) { |
| | | list.value = parseList(options.list); |
| | | } |
| | | |
| | | nextTick(() => { |
| | | // 计算位置 |
| | | let left = event.pageX; |
| | | let top = event.pageY; |
| | | |
| | | // 组件方式用 offset 计算 |
| | | if (!props.show) { |
| | | left = event.offsetX; |
| | | top = event.offsetY; |
| | | } |
| | | |
| | | const { clientHeight: h1, clientWidth: w1 } = event.target?.ownerDocument.body; |
| | | const { clientHeight: h2, clientWidth: w2 } = el; |
| | | |
| | | if (top + h2 > h1) { |
| | | top = h1 - h2 - 5; |
| | | } |
| | | |
| | | if (left + w2 > w1) { |
| | | left = w1 - w2 - 5; |
| | | } |
| | | |
| | | style.left = left + "px"; |
| | | style.top = top + "px"; |
| | | }) |
| | | |
| | | return { |
| | | close |
| | | }; |
| | | } |
| | | |
| | | // 行点击 |
| | | function rowClick(item: ClContextMenu.Item, id: string) { |
| | | ids.value = id; |
| | | |
| | | if (item.disabled) { |
| | | return false; |
| | | } |
| | | |
| | | if (item.callback) { |
| | | return item.callback(close); |
| | | } |
| | | |
| | | if (item.children) { |
| | | item.showChildren = !item.showChildren; |
| | | } else { |
| | | close(); |
| | | } |
| | | } |
| | | |
| | | expose({ |
| | | open, |
| | | close |
| | | }); |
| | | |
| | | onMounted(function () { |
| | | if (visible.value) { |
| | | const { body, documentElement } = props.event.target.ownerDocument; |
| | | |
| | | // 添加到 body 下 |
| | | body.appendChild(refs["context-menu"]); |
| | | // 关闭事件 |
| | | (documentElement || body).addEventListener("mousedown", (e: any) => { |
| | | const el = refs["context-menu"]; |
| | | if (!contains(el, e.target) && el != e.target) { |
| | | close(); |
| | | } |
| | | }); |
| | | |
| | | // 默认打开 |
| | | open(props.event, props?.options); |
| | | } |
| | | }); |
| | | |
| | | return () => { |
| | | function deep(list: ClContextMenu.Item[], pId: string, level: number) { |
| | | return ( |
| | | <div class={["cl-context-menu__box", level > 1 && "is-append"]}> |
| | | {list |
| | | .filter((e) => !e.hidden) |
| | | .map((e, i) => { |
| | | const id = `${pId}-${i}`; |
| | | |
| | | if (!e.suffixIcon) { |
| | | // 默认图标 |
| | | if (e.children) { |
| | | e.suffixIcon = ArrowRight; |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div |
| | | class={{ |
| | | "is-active": ids.value.includes(id), |
| | | "is-ellipsis": e.ellipsis ?? true, |
| | | "is-disabled": e.disabled |
| | | }} |
| | | onClick={(ev: MouseEvent) => { |
| | | rowClick(e, id); |
| | | ev.stopPropagation(); |
| | | }} |
| | | > |
| | | {/* 前缀图标 */} |
| | | {e.prefixIcon && <ElIcon>{h(toRaw(e.prefixIcon))}</ElIcon>} |
| | | |
| | | {/* 标题 */} |
| | | <span> |
| | | {e.label} |
| | | </span> |
| | | |
| | | {/* 后缀图标 */} |
| | | {e.suffixIcon && <ElIcon>{h(toRaw(e.suffixIcon))}</ElIcon>} |
| | | |
| | | {/* 子集 */} |
| | | {e.children && |
| | | e.showChildren && |
| | | deep(e.children, id, level + 1)} |
| | | </div> |
| | | ); |
| | | })} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | return ( |
| | | visible.value && ( |
| | | <div |
| | | class="cl-context-menu" |
| | | ref={setRefs("context-menu")} |
| | | style={style} |
| | | onContextmenu={stopDefault}> |
| | | {slots.default ? slots.default() : deep(list.value, "0", 1)} |
| | | </div> |
| | | ) |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| | | |
| | | export const ContextMenu = { |
| | | open(event: any, options: ClContextMenu.Options) { |
| | | const vm = h(ClContextMenu, { |
| | | show: true, |
| | | event, |
| | | options |
| | | }); |
| | | |
| | | render(vm, event.target.ownerDocument.createElement("div")); |
| | | |
| | | return vm.component?.exposed as ClContextMenu.Exposed; |
| | | } |
| | | }; |
| | | |
| | | export default ClContextMenu; |
| New file |
| | |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import { Mitt } from "../../utils/mitt"; |
| | | import { ref } from "vue"; |
| | | import { assign, isArray, isFunction } from "lodash-es"; |
| | | import { merge } from "../../utils"; |
| | | |
| | | interface Options { |
| | | mitt: Mitt; |
| | | config: ClCrud.Config; |
| | | crud: ClCrud.Ref; |
| | | } |
| | | |
| | | export function useHelper({ config, crud, mitt }: Options) { |
| | | // 刷新随机值,避免脏数据 |
| | | const refreshRd = ref(0); |
| | | |
| | | // 获取权限 |
| | | function getPermission(key: "page" | "list" | "info" | "update" | "add" | "delete"): boolean { |
| | | return Boolean(crud.permission[key]); |
| | | } |
| | | |
| | | // 根据字典替换请求参数 |
| | | function paramsReplace(params: obj) { |
| | | const { pagination, search, sort } = crud.dict; |
| | | |
| | | // 请求参数 |
| | | const a: any = { ...params }; |
| | | |
| | | // 字典 |
| | | const b: any = { ...pagination, ...search, ...sort }; |
| | | |
| | | for (const i in b) { |
| | | if (a[i]) { |
| | | if (i != b[i]) { |
| | | a[`_${b[i]}`] = a[i]; |
| | | |
| | | delete a[i]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (const i in a) { |
| | | if (i[0] === "_") { |
| | | a[i.substr(1)] = a[i]; |
| | | |
| | | delete a[i]; |
| | | } |
| | | } |
| | | |
| | | return a; |
| | | } |
| | | |
| | | // 刷新请求 |
| | | function refresh(params?: obj) { |
| | | const { service, dict } = crud; |
| | | |
| | | return new Promise((success, error) => { |
| | | // 合并请求参数 |
| | | const reqParams = paramsReplace(assign(crud.params, params)); |
| | | |
| | | // Loading |
| | | crud.loading = true; |
| | | |
| | | // 预防脏数据 |
| | | const rd = (refreshRd.value = Math.random()); |
| | | |
| | | // 完成事件 |
| | | function done() { |
| | | crud.loading = false; |
| | | } |
| | | |
| | | // 渲染 |
| | | function render(data: any | any[], pagination?: any) { |
| | | const res = isArray(data) ? { list: data, pagination } : data; |
| | | done(); |
| | | success(res); |
| | | mitt.emit("crud.refresh", res); |
| | | } |
| | | |
| | | // 下一步 |
| | | function next(params: obj): Promise<any> { |
| | | return new Promise(async (resolve, reject) => { |
| | | await service[dict.api.page](params) |
| | | .then((res) => { |
| | | if (rd != refreshRd.value) { |
| | | return false; |
| | | } |
| | | |
| | | if (isArray(res)) { |
| | | res = { |
| | | list: res, |
| | | pagination: { |
| | | total: res.length |
| | | } |
| | | }; |
| | | } |
| | | |
| | | render(res); |
| | | resolve(res); |
| | | }) |
| | | .catch((err) => { |
| | | ElMessage.error(err.message); |
| | | error(err); |
| | | reject(err); |
| | | }); |
| | | |
| | | done(); |
| | | }); |
| | | } |
| | | |
| | | // 刷新钩子 |
| | | if (config.onRefresh) { |
| | | config.onRefresh(reqParams, { next, done, render }); |
| | | } else { |
| | | next(reqParams); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 打开详情 |
| | | function rowInfo(data: any) { |
| | | mitt.emit("crud.proxy", { |
| | | name: "info", |
| | | data: [data] |
| | | }); |
| | | } |
| | | |
| | | // 打开新增 |
| | | function rowAdd() { |
| | | mitt.emit("crud.proxy", { |
| | | name: "add" |
| | | }); |
| | | } |
| | | |
| | | // 打开编辑 |
| | | function rowEdit(data: any) { |
| | | mitt.emit("crud.proxy", { |
| | | name: "edit", |
| | | data: [data] |
| | | }); |
| | | } |
| | | |
| | | // 打开追加 |
| | | function rowAppend(data: any) { |
| | | mitt.emit("crud.proxy", { |
| | | name: "append", |
| | | data: [data] |
| | | }); |
| | | } |
| | | |
| | | // 关闭新增、编辑弹窗 |
| | | function rowClose() { |
| | | mitt.emit("crud.proxy", { |
| | | name: "close" |
| | | }); |
| | | } |
| | | |
| | | // 删除请求 |
| | | function rowDelete(...selection: any[]) { |
| | | const { service, dict } = crud; |
| | | |
| | | // 参数 |
| | | const params = { |
| | | ids: selection.map((e) => e[dict.primaryId]) |
| | | }; |
| | | |
| | | // 下一步 |
| | | async function next(data: obj) { |
| | | return new Promise((resolve, reject) => { |
| | | ElMessageBox({ |
| | | type: "warning", |
| | | title: dict.label.tips, |
| | | message: dict.label.deleteConfirm, |
| | | confirmButtonText: dict.label.confirm, |
| | | cancelButtonText: dict.label.close, |
| | | showCancelButton: true, |
| | | async beforeClose(action, instance, done) { |
| | | if (action === "confirm") { |
| | | instance.confirmButtonLoading = true; |
| | | |
| | | await service[dict.api.delete]({ ...params, ...data }) |
| | | .then((res) => { |
| | | ElMessage.success(dict.label.deleteSuccess); |
| | | |
| | | refresh(); |
| | | resolve(res); |
| | | }) |
| | | .catch((err) => { |
| | | ElMessage.error(err.message); |
| | | reject(err); |
| | | }); |
| | | |
| | | instance.confirmButtonLoading = false; |
| | | } |
| | | |
| | | done(); |
| | | } |
| | | }).catch(() => null); |
| | | }); |
| | | } |
| | | |
| | | // 删除钩子 |
| | | if (config.onDelete) { |
| | | config.onDelete(selection, { next }); |
| | | } else { |
| | | next(params); |
| | | } |
| | | } |
| | | |
| | | // 代理 |
| | | function proxy(name: string, data?: any[]) { |
| | | mitt.emit("crud.proxy", { |
| | | name, |
| | | data |
| | | }); |
| | | } |
| | | |
| | | // 获取请求参数 |
| | | function getParams() { |
| | | return crud.params; |
| | | } |
| | | |
| | | // 替换请求参数 |
| | | function setParams(data: obj) { |
| | | merge(crud.params, data); |
| | | } |
| | | |
| | | // 设置 |
| | | function set(key: string, value: any) { |
| | | if (!value) { |
| | | return false; |
| | | } |
| | | |
| | | switch (key) { |
| | | // 服务 |
| | | case "service": |
| | | Object.assign(crud.service, value); |
| | | crud.service.__proto__ = value.__proto__; |
| | | if (value._permission) { |
| | | for (const i in value._permission) { |
| | | crud.permission[i] = value._permission[i]; |
| | | } |
| | | } |
| | | break; |
| | | |
| | | // 权限 |
| | | case "permission": |
| | | if (isFunction(value)) { |
| | | merge(crud.permission, value(crud)); |
| | | } else { |
| | | merge(crud.permission, value); |
| | | } |
| | | break; |
| | | |
| | | default: |
| | | merge(crud[key], value); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 监听事件 |
| | | function on(name: string, callback: fn) { |
| | | mitt.on(`${name}-${crud.id}`, callback); |
| | | } |
| | | |
| | | // 默认值 |
| | | set("dict", config.dict); |
| | | set("service", config.service); |
| | | set("permission", config.permission); |
| | | |
| | | return { |
| | | proxy, |
| | | set, |
| | | on, |
| | | rowInfo, |
| | | rowAdd, |
| | | rowEdit, |
| | | rowAppend, |
| | | rowDelete, |
| | | rowClose, |
| | | refresh, |
| | | getPermission, |
| | | paramsReplace, |
| | | getParams, |
| | | setParams |
| | | }; |
| | | } |
| New file |
| | |
| | | import { defineComponent, getCurrentInstance, inject, provide, reactive } from "vue"; |
| | | import { cloneDeep } from "lodash-es"; |
| | | import { useHelper } from "./helper"; |
| | | import { Mitt } from "../../utils/mitt"; |
| | | import { mergeConfig, merge } from "../../utils"; |
| | | import { crudList } from "../../emitter"; |
| | | import { useConfig } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-crud", |
| | | |
| | | props: { |
| | | // 组件名 |
| | | name: String, |
| | | // 是否有边框 |
| | | border: Boolean, |
| | | // 内间距 |
| | | padding: { |
| | | type: String, |
| | | default: "10px" |
| | | } |
| | | }, |
| | | |
| | | setup(props, { slots, expose }) { |
| | | // 当前实例 |
| | | const inst = getCurrentInstance(); |
| | | |
| | | // 配置 |
| | | const config = reactive<ClCrud.Config>(mergeConfig(inject("useCrud__options") || {})); |
| | | |
| | | // 事件 |
| | | const mitt = new Mitt(inst?.uid); |
| | | |
| | | // 全局配置 |
| | | const { dict, permission } = useConfig(); |
| | | |
| | | // 参数 |
| | | const crud = reactive( |
| | | merge( |
| | | { |
| | | id: props.name || inst?.uid, |
| | | // 绑定的路由地址 |
| | | routePath: location.pathname || "/", |
| | | // 表格加载状态 |
| | | loading: false, |
| | | // 表格已选列 |
| | | selection: [], |
| | | // 请求参数 |
| | | params: { |
| | | page: 1, |
| | | size: 20 |
| | | }, |
| | | // 请求服务 |
| | | service: {}, |
| | | // 字典 |
| | | dict: {}, |
| | | // 权限 |
| | | permission: {}, |
| | | // 事件 |
| | | mitt, |
| | | // 配置 |
| | | config |
| | | }, |
| | | cloneDeep({ dict, permission }) |
| | | ) |
| | | ); |
| | | |
| | | // 追加参数 |
| | | merge(crud, useHelper({ config, crud, mitt })); |
| | | |
| | | // 集合 |
| | | crudList.push(crud); |
| | | |
| | | // 值穿透 |
| | | provide("crud", crud); |
| | | provide("mitt", mitt); |
| | | |
| | | // 导出 |
| | | expose(crud); |
| | | |
| | | return () => { |
| | | return ( |
| | | <div |
| | | class={["cl-crud", { "is-border": props.border }]} |
| | | style={{ padding: props.padding }}> |
| | | {slots.default?.()} |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent, h, ref, watch, computed, provide } from "vue"; |
| | | import { Close, FullScreen, Minus } from "@element-plus/icons-vue"; |
| | | import { renderNode } from "../../utils/vnode"; |
| | | import { isArray, isBoolean } from "lodash-es"; |
| | | import { useBrowser } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-dialog", |
| | | |
| | | components: { |
| | | Close, |
| | | FullScreen, |
| | | Minus |
| | | }, |
| | | |
| | | props: { |
| | | // 是否可见 |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // Extraneous non-props attributes |
| | | props: Object, |
| | | // 标题 |
| | | title: { |
| | | type: String, |
| | | default: "-" |
| | | }, |
| | | // 高度 |
| | | height: String, |
| | | // 宽度 |
| | | width: { |
| | | type: String, |
| | | default: "50%" |
| | | }, |
| | | // 內间距 |
| | | padding: { |
| | | type: String, |
| | | default: "20px" |
| | | }, |
| | | // 是否缓存 |
| | | keepAlive: Boolean, |
| | | // 是否全屏 |
| | | fullscreen: Boolean, |
| | | // 控制按钮 |
| | | controls: { |
| | | type: Array, |
| | | default: () => ["fullscreen", "close"] |
| | | }, |
| | | // 隐藏头部元素 |
| | | hideHeader: Boolean, |
| | | // 关闭前 |
| | | beforeClose: Function, |
| | | // 是否需要滚动条 |
| | | scrollbar: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 背景透明 |
| | | transparent: Boolean |
| | | }, |
| | | |
| | | emits: ["update:modelValue", "fullscreen-change"], |
| | | |
| | | setup(props, { emit, expose, slots }) { |
| | | const browser = useBrowser(); |
| | | |
| | | // el-dialog |
| | | const Dialog = ref(); |
| | | |
| | | // 是否全屏 |
| | | const fullscreen = ref(false); |
| | | |
| | | // 是否可见 |
| | | const visible = ref(false); |
| | | |
| | | // 缓存数 |
| | | const cacheKey = ref(0); |
| | | |
| | | // 是否全屏 |
| | | const isFullscreen = computed(() => { |
| | | return browser && browser.isMini ? true : fullscreen.value; |
| | | }); |
| | | |
| | | // 监听绑定值 |
| | | watch( |
| | | () => props.modelValue, |
| | | (val) => { |
| | | visible.value = val; |
| | | if (val && !props.keepAlive) { |
| | | cacheKey.value += 1; |
| | | } |
| | | }, |
| | | { |
| | | immediate: true |
| | | } |
| | | ); |
| | | |
| | | // 监听 fullscreen 变化 |
| | | watch( |
| | | () => props.fullscreen, |
| | | (val) => { |
| | | fullscreen.value = val; |
| | | }, |
| | | { |
| | | immediate: true |
| | | } |
| | | ); |
| | | |
| | | // fullscreen-change 回调 |
| | | watch(fullscreen, (val: boolean) => { |
| | | emit("fullscreen-change", val); |
| | | }); |
| | | |
| | | // 提供 |
| | | provide("dialog", { |
| | | visible, |
| | | fullscreen: isFullscreen |
| | | }); |
| | | |
| | | // 打开 |
| | | function open() { |
| | | fullscreen.value = true; |
| | | } |
| | | |
| | | // 关闭 |
| | | function close() { |
| | | function done() { |
| | | onClose(); |
| | | } |
| | | |
| | | if (props.beforeClose) { |
| | | props.beforeClose(done); |
| | | } else { |
| | | done(); |
| | | } |
| | | } |
| | | |
| | | // 关闭后 |
| | | function onClose() { |
| | | emit("update:modelValue", false); |
| | | } |
| | | |
| | | // 切换全屏 |
| | | function changeFullscreen(val?: boolean) { |
| | | fullscreen.value = isBoolean(val) ? Boolean(val) : !fullscreen.value; |
| | | } |
| | | |
| | | // 双击全屏 |
| | | function dblClickFullscreen() { |
| | | if (isArray(props.controls) && props.controls.includes("fullscreen")) { |
| | | changeFullscreen(); |
| | | } |
| | | } |
| | | |
| | | // 渲染头部 |
| | | function renderHeader() { |
| | | return ( |
| | | props.hideHeader || ( |
| | | <div class="cl-dialog__header" onDblclick={dblClickFullscreen}> |
| | | <span class="cl-dialog__title">{props.title}</span> |
| | | |
| | | <div class="cl-dialog__controls"> |
| | | {props.controls.map((e: any) => { |
| | | switch (e) { |
| | | //全屏按钮 |
| | | case "fullscreen": |
| | | if (browser.screen === "xs") { |
| | | return null; |
| | | } |
| | | |
| | | // 是否显示全屏按钮 |
| | | if (isFullscreen.value) { |
| | | return ( |
| | | <button |
| | | type="button" |
| | | class="minimize" |
| | | onClick={() => { |
| | | changeFullscreen(false); |
| | | }}> |
| | | <el-icon> |
| | | <Minus /> |
| | | </el-icon> |
| | | </button> |
| | | ); |
| | | } else { |
| | | return ( |
| | | <button |
| | | type="button" |
| | | class="maximize" |
| | | onClick={() => { |
| | | changeFullscreen(true); |
| | | }}> |
| | | <el-icon> |
| | | <FullScreen /> |
| | | </el-icon> |
| | | </button> |
| | | ); |
| | | } |
| | | |
| | | // 关闭按钮 |
| | | case "close": |
| | | return ( |
| | | <button type="button" class="close" onClick={close}> |
| | | <el-icon> |
| | | <Close /> |
| | | </el-icon> |
| | | </button> |
| | | ); |
| | | |
| | | // 自定义按钮 |
| | | default: |
| | | return renderNode(e, { |
| | | slots |
| | | }); |
| | | } |
| | | })} |
| | | </div> |
| | | </div> |
| | | ) |
| | | ); |
| | | } |
| | | |
| | | expose({ |
| | | Dialog, |
| | | visible, |
| | | isFullscreen, |
| | | open, |
| | | close, |
| | | changeFullscreen |
| | | }); |
| | | |
| | | return () => { |
| | | return h( |
| | | <el-dialog |
| | | ref={Dialog} |
| | | class={["cl-dialog", { 'is-transparent': props.transparent }]} |
| | | width={props.width} |
| | | beforeClose={props.beforeClose} |
| | | show-close={false} |
| | | append-to-body |
| | | fullscreen={isFullscreen.value} |
| | | v-model={visible.value} |
| | | onClose={onClose} |
| | | />, |
| | | {}, |
| | | { |
| | | header() { |
| | | return renderHeader(); |
| | | }, |
| | | default() { |
| | | const height = isFullscreen.value ? "100%" : props.height; |
| | | |
| | | const style = { |
| | | padding: props.padding, |
| | | height |
| | | }; |
| | | |
| | | function content() { |
| | | return ( |
| | | <div class="cl-dialog__default" style={style} key={cacheKey.value}> |
| | | {slots.default?.()} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | if (props.scrollbar) { |
| | | style.height = "auto"; |
| | | |
| | | return <el-scrollbar height={height}>{content()}</el-scrollbar>; |
| | | } else { |
| | | return content(); |
| | | } |
| | | }, |
| | | footer() { |
| | | const d = slots.footer?.(); |
| | | |
| | | if (d && d[0]?.shapeFlag) { |
| | | return <div class="cl-dialog__footer">{d}</div>; |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | } |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-error-message", |
| | | |
| | | props: { |
| | | title: String |
| | | }, |
| | | |
| | | setup(props) { |
| | | return () => { |
| | | return <div class="cl-error-message"> |
| | | {props.title} |
| | | </div>; |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-filter", |
| | | |
| | | props: { |
| | | label: String |
| | | }, |
| | | |
| | | setup(props, { slots }) { |
| | | return () => { |
| | | return ( |
| | | <div class="cl-filter"> |
| | | <span class="cl-filter__label" v-show={props.label}> |
| | | {props.label} |
| | | </span> |
| | | |
| | | {slots.default?.()} |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-flex1", |
| | | |
| | | setup() { |
| | | return () => { |
| | | return <div class="cl-flex1" />; |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent, ref } from "vue"; |
| | | import { ArrowDown, ArrowUp } from "@element-plus/icons-vue"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-form-card", |
| | | |
| | | components: { |
| | | ArrowDown, |
| | | ArrowUp |
| | | }, |
| | | |
| | | props: { |
| | | label: String, |
| | | // 展开状态 |
| | | expand: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 是否能展开、收起 |
| | | isExpand: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | |
| | | setup(props, { slots }) { |
| | | const visible = ref(props.expand); |
| | | |
| | | function toExpand() { |
| | | if (props.isExpand) { |
| | | visible.value = !visible.value; |
| | | } |
| | | } |
| | | |
| | | return () => { |
| | | return ( |
| | | <div class={["cl-form-card", { "is-expand": visible.value }]}> |
| | | <div class="cl-form-card__header" v-show={props.label} onClick={toExpand}> |
| | | <span>{props.label}</span> |
| | | |
| | | <el-icon v-show={props.isExpand}> |
| | | <arrow-down v-show={!visible.value} /> |
| | | <arrow-up v-show={visible.value} /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="cl-form-card__container">{slots.default?.()}</div> |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { |
| | | defineComponent, |
| | | h, |
| | | nextTick, |
| | | onMounted, |
| | | PropType, |
| | | reactive, |
| | | ref, |
| | | toRaw, |
| | | watch |
| | | } from "vue"; |
| | | import { isEmpty } from "lodash-es"; |
| | | import { useRefs, useDialog } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-form-tabs", |
| | | |
| | | props: { |
| | | modelValue: [String, Number], |
| | | labels: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | justify: { |
| | | type: String as PropType< |
| | | "start" | "end" | "left" | "right" | "center" | "justify" | "match-parent" |
| | | >, |
| | | default: "center" |
| | | }, |
| | | type: { |
| | | type: String as PropType<"card" | "default">, |
| | | default: "default" |
| | | } |
| | | }, |
| | | |
| | | emits: ["update:modelValue", "change"], |
| | | |
| | | setup(props, { emit, expose }) { |
| | | const { refs, setRefs } = useRefs(); |
| | | |
| | | // 标识 |
| | | const active = ref(""); |
| | | |
| | | // 切换列表 |
| | | const list = ref<any[]>([]); |
| | | |
| | | // 下划线 |
| | | const line = reactive({ |
| | | width: "", |
| | | offsetLeft: "", |
| | | transform: "", |
| | | backgroundColor: "" |
| | | }); |
| | | |
| | | function update(val: any) { |
| | | if (!val) { |
| | | return false; |
| | | } |
| | | |
| | | nextTick(() => { |
| | | const index = list.value.findIndex((e) => e.value === val); |
| | | const item = refs[`tab-${index}`]; |
| | | |
| | | if (item) { |
| | | // 下划线位置 |
| | | line.width = item.offsetWidth + "px"; |
| | | line.transform = `translateX(${item.offsetLeft}px)`; |
| | | |
| | | // 靠左位置 |
| | | let left = item.offsetLeft + item.clientWidth / 2 - 414 / 2 + 15; |
| | | |
| | | if (left < 0) { |
| | | left = 0; |
| | | } |
| | | |
| | | // 设置滚动距离 |
| | | refs.tabs.scrollLeft = left; |
| | | } |
| | | }); |
| | | |
| | | active.value = val; |
| | | emit("update:modelValue", val); |
| | | } |
| | | |
| | | // 监听绑定值变化 |
| | | watch(() => props.modelValue, update); |
| | | |
| | | // 监听值修改 |
| | | watch( |
| | | () => active.value, |
| | | (val) => { |
| | | emit("change", val); |
| | | } |
| | | ); |
| | | |
| | | useDialog({ |
| | | onFullscreen() { |
| | | update(active.value); |
| | | } |
| | | }); |
| | | |
| | | onMounted(function () { |
| | | if (!isEmpty(props.labels)) { |
| | | list.value = props.labels; |
| | | update(isEmpty(props.modelValue) ? list.value[0].value : props.modelValue); |
| | | } |
| | | }); |
| | | |
| | | expose({ |
| | | active, |
| | | list, |
| | | line, |
| | | update |
| | | }); |
| | | |
| | | return () => { |
| | | return ( |
| | | <div class={["cl-form-tabs", `cl-form-tabs--${props.type}`]}> |
| | | <div |
| | | class="cl-form-tabs__wrap" |
| | | style={{ textAlign: props.justify }} |
| | | ref={setRefs("tabs")}> |
| | | <ul> |
| | | {list.value.map((e, i) => { |
| | | return ( |
| | | <li |
| | | ref={setRefs(`tab-${i}`)} |
| | | class={{ "is-active": e.value === active.value }} |
| | | onClick={() => { |
| | | update(e.value); |
| | | }}> |
| | | {e.icon && <el-icon>{h(toRaw(e.icon))}</el-icon>} |
| | | <span>{e.label}</span> |
| | | </li> |
| | | ); |
| | | })} |
| | | |
| | | {line.width && <div class="cl-form-tabs__line" style={line}></div>} |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { assign } from "lodash-es"; |
| | | import { dataset } from "../../../utils"; |
| | | |
| | | export function useAction({ |
| | | config, |
| | | form, |
| | | Form |
| | | }: { |
| | | config: ClForm.Config; |
| | | form: obj; |
| | | Form: Vue.Ref<any>; |
| | | }) { |
| | | // 设置数据 |
| | | function set( |
| | | { |
| | | prop, |
| | | key, |
| | | path |
| | | }: { prop?: string; key?: "options" | "props" | "hidden" | "hidden-toggle"; path?: string }, |
| | | data?: any |
| | | ) { |
| | | const p: string = path || ""; |
| | | |
| | | if (path) { |
| | | dataset(config, p, data); |
| | | } else { |
| | | let d: any; |
| | | |
| | | if (prop) { |
| | | function deep(arr: ClForm.Item[]) { |
| | | arr.forEach((e) => { |
| | | if (e.prop == prop) { |
| | | d = e; |
| | | } else { |
| | | if (e.children) { |
| | | deep(e.children); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | deep(config.items); |
| | | } |
| | | |
| | | if (d) { |
| | | switch (key) { |
| | | case "options": |
| | | d.component.options = data; |
| | | break; |
| | | |
| | | case "props": |
| | | assign(d.component.props, data); |
| | | break; |
| | | |
| | | case "hidden": |
| | | d.hidden = data; |
| | | break; |
| | | |
| | | case "hidden-toggle": |
| | | d.hidden = data === undefined ? !d.hidden : !data; |
| | | break; |
| | | |
| | | default: |
| | | assign(d, data); |
| | | break; |
| | | } |
| | | } else { |
| | | console.error(`[set] ${prop} is not found`); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 获取表单值 |
| | | function getForm(prop: string) { |
| | | return prop ? form[prop] : form; |
| | | } |
| | | |
| | | // 设置表单值 |
| | | function setForm(prop: string, value: any) { |
| | | form[prop] = value; |
| | | } |
| | | |
| | | // 设置配置 |
| | | function setConfig(path: string, value: any) { |
| | | set({ path }, value); |
| | | } |
| | | |
| | | // 设置数据 |
| | | function setData(prop: string, value: any) { |
| | | set({ prop }, value); |
| | | } |
| | | |
| | | // 设置表单项的下拉数据列表 |
| | | function setOptions(prop: string, value: any[]) { |
| | | set({ prop, key: "options" }, value); |
| | | } |
| | | |
| | | // 设置表单项的组件参数 |
| | | function setProps(prop: string, value: any) { |
| | | set({ prop, key: "props" }, value); |
| | | } |
| | | |
| | | // 切换表单项的显示、隐藏 |
| | | function toggleItem(prop: string, value?: boolean) { |
| | | set({ prop, key: "hidden-toggle" }, value); |
| | | } |
| | | |
| | | // 对部分表单项隐藏 |
| | | function hideItem(...props: string[]) { |
| | | props.forEach((prop) => { |
| | | set({ prop, key: "hidden" }, true); |
| | | }); |
| | | } |
| | | |
| | | // 对部分表单项显示 |
| | | function showItem(...props: string[]) { |
| | | props.forEach((prop) => { |
| | | set({ prop, key: "hidden" }, false); |
| | | }); |
| | | } |
| | | |
| | | // 设置标题 |
| | | function setTitle(value: string) { |
| | | config.title = value; |
| | | } |
| | | |
| | | // 是否展开表单项 |
| | | function collapseItem(e: any) { |
| | | Form.value?.clearValidate(e.prop); |
| | | e.collapse = !e.collapse; |
| | | } |
| | | |
| | | return { |
| | | getForm, |
| | | setForm, |
| | | setData, |
| | | setConfig, |
| | | setOptions, |
| | | setProps, |
| | | toggleItem, |
| | | hideItem, |
| | | showItem, |
| | | setTitle, |
| | | collapseItem |
| | | }; |
| | | } |
| New file |
| | |
| | | import { useElApi } from "../../../hooks"; |
| | | |
| | | export function useApi({ Form }: { Form: Vue.Ref<any> }) { |
| | | return useElApi( |
| | | [ |
| | | "open", |
| | | "close", |
| | | "clear", |
| | | "reset", |
| | | "submit", |
| | | "bindForm", |
| | | "changeTab", |
| | | "setTitle", |
| | | "showLoading", |
| | | "hideLoading", |
| | | "collapseItem", |
| | | "getForm", |
| | | "setForm", |
| | | "invokeData", |
| | | "setData", |
| | | "setConfig", |
| | | "setOptions", |
| | | "setProps", |
| | | "toggleItem", |
| | | "hideItem", |
| | | "showItem", |
| | | "validate", |
| | | "validateField", |
| | | "resetFields", |
| | | "scrollToField", |
| | | "clearValidate", |
| | | "fields" |
| | | ], |
| | | Form |
| | | ); |
| | | } |
| New file |
| | |
| | | import { reactive, ref, watch } from "vue"; |
| | | import { useConfig } from "../../../hooks"; |
| | | import { cloneDeep } from "lodash-es"; |
| | | |
| | | export function useForm() { |
| | | const { dict } = useConfig(); |
| | | |
| | | // 表单配置 |
| | | const config = reactive<ClForm.Config>({ |
| | | title: "-", |
| | | height: undefined, |
| | | width: "50%", |
| | | props: { |
| | | labelWidth: 100 |
| | | }, |
| | | on: {}, |
| | | op: { |
| | | hidden: false, |
| | | saveButtonText: dict.label.save, |
| | | closeButtonText: dict.label.close, |
| | | buttons: ["close", "save"] |
| | | }, |
| | | dialog: { |
| | | closeOnClickModal: false, |
| | | appendToBody: true |
| | | }, |
| | | items: [], |
| | | form: {}, |
| | | _data: {} |
| | | }); |
| | | |
| | | const Form = ref(); |
| | | |
| | | // 表单数据 |
| | | const form = reactive<obj>({}); |
| | | |
| | | // 表单数据备份 |
| | | const oldForm = ref<obj>({}); |
| | | |
| | | // 表单是否可见 |
| | | const visible = ref(false); |
| | | |
| | | // 表单提交保存状态 |
| | | const saving = ref(false); |
| | | |
| | | // 表单加载状态 |
| | | const loading = ref(false); |
| | | |
| | | // 表单禁用状态 |
| | | const disabled = ref(false); |
| | | |
| | | // 监听表单变化 |
| | | watch( |
| | | () => form, |
| | | (val) => { |
| | | if (config.on?.change) { |
| | | for (const i in val) { |
| | | if (form[i] !== oldForm.value[i]) { |
| | | config.on?.change(val, i); |
| | | } |
| | | } |
| | | } |
| | | |
| | | oldForm.value = cloneDeep(val); |
| | | }, |
| | | { |
| | | deep: true |
| | | } |
| | | ); |
| | | |
| | | return { |
| | | Form, |
| | | config, |
| | | form, |
| | | visible, |
| | | saving, |
| | | loading, |
| | | disabled |
| | | }; |
| | | } |
| | | |
| | | export * from "./action"; |
| | | export * from "./api"; |
| | | export * from "./plugins"; |
| | | export * from "./tabs"; |
| New file |
| | |
| | | import { type Ref, type WatchStopHandle, getCurrentInstance, watch } from "vue"; |
| | | import { useConfig } from "../../../hooks"; |
| | | import { uniqueFns } from "../../../utils"; |
| | | |
| | | export function usePlugins(enable: boolean, { visible }: { visible: Ref<boolean> }) { |
| | | const that: any = getCurrentInstance(); |
| | | const { style } = useConfig(); |
| | | |
| | | interface Event { |
| | | onOpen: (() => void)[]; |
| | | onClose: (() => void)[]; |
| | | onSubmit: ((data: obj) => Promise<obj> | obj)[]; |
| | | [key: string]: any; |
| | | } |
| | | |
| | | // 事件 |
| | | const ev: Event = { |
| | | onOpen: [], |
| | | onClose: [], |
| | | onSubmit: [] |
| | | }; |
| | | |
| | | // 监听器 |
| | | let timer: WatchStopHandle | null = null; |
| | | |
| | | // 插件创建 |
| | | function create(plugins: ClForm.Plugin[] = []) { |
| | | if (!enable) { |
| | | return false; |
| | | } |
| | | |
| | | for (const i in ev) { |
| | | ev[i] = []; |
| | | } |
| | | |
| | | // 停止监听 |
| | | if (timer) { |
| | | timer(); |
| | | } |
| | | |
| | | // 执行 |
| | | uniqueFns([...(style.form.plugins || []), ...plugins]).forEach((p) => { |
| | | const d: any = { |
| | | exposed: that.exposed |
| | | }; |
| | | |
| | | for (const i in ev) { |
| | | d[i] = (cb: any) => { |
| | | ev[i].push(cb); |
| | | }; |
| | | } |
| | | |
| | | p(d); |
| | | }); |
| | | |
| | | timer = watch( |
| | | visible, |
| | | (val) => { |
| | | if (val) { |
| | | setTimeout(() => { |
| | | ev.onOpen.forEach((e) => e()); |
| | | }, 10); |
| | | } else { |
| | | ev.onClose.forEach((e) => e()); |
| | | } |
| | | }, |
| | | { |
| | | immediate: true |
| | | } |
| | | ); |
| | | } |
| | | |
| | | // 表单提交 |
| | | async function submit(data: any) { |
| | | let d = data; |
| | | |
| | | for (let i = 0; i < ev.onSubmit.length; i++) { |
| | | const d2 = await ev.onSubmit[i](d); |
| | | |
| | | if (d2) { |
| | | d = d2; |
| | | } |
| | | } |
| | | |
| | | return d; |
| | | } |
| | | |
| | | return { |
| | | create, |
| | | submit |
| | | }; |
| | | } |
| New file |
| | |
| | | import { computed, ref } from "vue"; |
| | | |
| | | export function useTabs({ config, Form }: { config: ClForm.Config; Form: Vue.Ref<any> }) { |
| | | // 选中 |
| | | const active = ref<string | undefined>(); |
| | | |
| | | // 列表 |
| | | const list = computed(() => { |
| | | return get()?.props?.labels || []; |
| | | }); |
| | | |
| | | // 获取选项 |
| | | function getItem(value: any) { |
| | | return list.value.find((e) => e.value == value); |
| | | } |
| | | |
| | | // 是否已加载 |
| | | function isLoaded(value: any) { |
| | | const d = getItem(value); |
| | | return d?.lazy ? d.loaded : true; |
| | | } |
| | | |
| | | // 加载后 |
| | | function onLoad(value: any) { |
| | | const d = getItem(value); |
| | | d!.loaded = true; |
| | | } |
| | | |
| | | // 查找分组 |
| | | function toGroup(opts: { config: ClForm.Config; prop: string; refs: any }) { |
| | | if (active.value) { |
| | | let name; |
| | | |
| | | // 查找标签上绑定的数据 |
| | | const el = opts.refs.form.querySelector(`[data-prop="${opts.prop}"]`); |
| | | |
| | | // 各自判断 |
| | | if (el) { |
| | | name = el?.getAttribute("data-group"); |
| | | } else { |
| | | function deep(d: ClForm.Item) { |
| | | if (d.prop == opts.prop) { |
| | | name = d.group; |
| | | } else { |
| | | if (d.children) { |
| | | d.children.forEach(deep); |
| | | } |
| | | } |
| | | } |
| | | |
| | | config.items.forEach(deep); |
| | | } |
| | | |
| | | if (name) { |
| | | set(name); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 获取参数 |
| | | function get() { |
| | | return config.items.find((e) => e.type === "tabs"); |
| | | } |
| | | |
| | | // 设置参数 |
| | | function set(data: any) { |
| | | active.value = data; |
| | | } |
| | | |
| | | // 清空 |
| | | function clear() { |
| | | // 清空选中 |
| | | active.value = undefined; |
| | | |
| | | // 清空加载状态 |
| | | list.value.forEach((e) => { |
| | | if (e.lazy && e.loaded) { |
| | | e.loaded = undefined; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 切换 |
| | | function change(value: any, isValid = true) { |
| | | return new Promise((resolve: Function, reject: Function) => { |
| | | function next() { |
| | | active.value = value; |
| | | resolve(); |
| | | } |
| | | |
| | | if (isValid) { |
| | | let isError = false; |
| | | |
| | | const arr = config.items |
| | | .filter((e) => e.group == active.value && !e._hidden && e.prop) |
| | | .map((e) => { |
| | | return new Promise((r: Function) => { |
| | | // 验证表单 |
| | | Form.value.validateField(e.prop, (valid: string) => { |
| | | if (valid) { |
| | | isError = true; |
| | | } |
| | | |
| | | r(valid); |
| | | }); |
| | | }); |
| | | }); |
| | | |
| | | Promise.all(arr).then((msg) => { |
| | | if (isError) { |
| | | reject(msg.filter(Boolean)); |
| | | } else { |
| | | next(); |
| | | } |
| | | }); |
| | | } else { |
| | | next(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 合并 |
| | | function mergeProp(item: ClForm.Item) { |
| | | const d = get(); |
| | | |
| | | if (d && d.props) { |
| | | const { mergeProp, labels = [] } = d.props; |
| | | |
| | | if (mergeProp) { |
| | | const t = labels.find((e) => e.value == item.group); |
| | | |
| | | if (t && t.name) { |
| | | item.prop = `${t.name}-${item.prop}`; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return { |
| | | active, |
| | | list, |
| | | isLoaded, |
| | | onLoad, |
| | | get, |
| | | set, |
| | | change, |
| | | clear, |
| | | mergeProp, |
| | | toGroup |
| | | }; |
| | | } |
| New file |
| | |
| | | import { defineComponent, h, nextTick } from "vue"; |
| | | import { assign, cloneDeep, isBoolean, isFunction, keys } from "lodash-es"; |
| | | import { useAction, useForm, usePlugins, useTabs } from "./helper"; |
| | | import { useBrowser, useConfig, useElApi, useRefs } from "../../hooks"; |
| | | import { getValue, merge } from "../../utils"; |
| | | import formHook from "../../utils/form-hook"; |
| | | import { renderNode } from "../../utils/vnode"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-form", |
| | | |
| | | props: { |
| | | name: String, |
| | | inner: Boolean, |
| | | inline: Boolean, |
| | | enablePlugin: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | |
| | | setup(props, { expose, slots }) { |
| | | const { refs, setRefs } = useRefs(); |
| | | const { style, dict } = useConfig(); |
| | | const browser = useBrowser(); |
| | | const { Form, config, form, visible, saving, loading, disabled } = useForm(); |
| | | |
| | | // 关闭的操作类型 |
| | | let closeAction: ClForm.CloseAction = "close"; |
| | | |
| | | // 旧表单数据 |
| | | let defForm: obj | undefined; |
| | | |
| | | // 选项卡 |
| | | const Tabs = useTabs({ config, Form }); |
| | | |
| | | // 操作 |
| | | const Action = useAction({ config, form, Form }); |
| | | |
| | | // 方法 |
| | | const ElFormApi = useElApi( |
| | | [ |
| | | "validate", |
| | | "validateField", |
| | | "resetFields", |
| | | "scrollToField", |
| | | "clearValidate", |
| | | "fields" |
| | | ], |
| | | Form |
| | | ); |
| | | |
| | | // 插件 |
| | | const plugin = usePlugins(props.enablePlugin, { visible }); |
| | | |
| | | // 显示加载中 |
| | | function showLoading() { |
| | | loading.value = true; |
| | | } |
| | | |
| | | // 隐藏加载 |
| | | function hideLoading() { |
| | | loading.value = false; |
| | | } |
| | | |
| | | // 设置是否禁用 |
| | | function setDisabled(val: boolean = true) { |
| | | disabled.value = val; |
| | | } |
| | | |
| | | // 请求表单保存状态 |
| | | function done() { |
| | | saving.value = false; |
| | | } |
| | | |
| | | // 关闭表单 |
| | | function close(action?: ClForm.CloseAction) { |
| | | if (action) { |
| | | closeAction = action; |
| | | } |
| | | |
| | | beforeClose(() => { |
| | | visible.value = false; |
| | | done(); |
| | | }); |
| | | } |
| | | |
| | | // 关闭前 |
| | | function beforeClose(done: fn) { |
| | | if (config.on?.close) { |
| | | config.on.close(closeAction, done); |
| | | } else { |
| | | done(); |
| | | } |
| | | } |
| | | |
| | | // 关闭后 |
| | | function onClosed() { |
| | | Tabs.clear(); |
| | | Form.value?.clearValidate(); |
| | | } |
| | | |
| | | // 清空表单验证 |
| | | function clear() { |
| | | for (const i in form) { |
| | | delete form[i]; |
| | | } |
| | | |
| | | setTimeout(() => { |
| | | Form.value?.clearValidate(); |
| | | }, 0); |
| | | } |
| | | |
| | | // 重置 |
| | | function reset() { |
| | | if (defForm) { |
| | | for (const i in defForm) { |
| | | form[i] = cloneDeep(defForm[i]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 转换表单值,处理多层级等数据 |
| | | function invokeData(d: any) { |
| | | for (const i in d) { |
| | | if (i.includes("-")) { |
| | | // 结构参数 |
| | | const [a, ...arr] = i.split("-"); |
| | | |
| | | // 关键值的key |
| | | const k: string = arr.pop() || ""; |
| | | |
| | | if (!d[a]) { |
| | | d[a] = {}; |
| | | } |
| | | |
| | | let f: any = d[a]; |
| | | |
| | | // 设置默认值 |
| | | arr.forEach((e) => { |
| | | if (!f[e]) { |
| | | f[e] = {}; |
| | | } |
| | | |
| | | f = f[e]; |
| | | }); |
| | | |
| | | // 设置关键值 |
| | | f[k] = d[i]; |
| | | |
| | | delete d[i]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 表单提交 |
| | | function submit(callback?: fn) { |
| | | // 验证表单 |
| | | Form.value.validate(async (valid: boolean, error: any) => { |
| | | if (valid) { |
| | | saving.value = true; |
| | | |
| | | // 拷贝表单值 |
| | | const d = cloneDeep(form); |
| | | |
| | | config.items.forEach((e) => { |
| | | function deep(e: ClForm.Item) { |
| | | if (e.prop) { |
| | | // 过滤隐藏的表单项 |
| | | if (e._hidden) { |
| | | if (e.prop) { |
| | | delete d[e.prop]; |
| | | } |
| | | } |
| | | |
| | | // hook 提交处理 |
| | | if (e.hook) { |
| | | formHook.submit({ |
| | | ...e, |
| | | value: e.prop ? d[e.prop] : undefined, |
| | | form: d |
| | | }); |
| | | } |
| | | } |
| | | |
| | | if (e.children) { |
| | | e.children.forEach(deep); |
| | | } |
| | | } |
| | | |
| | | deep(e); |
| | | }); |
| | | |
| | | // 处理数据 |
| | | invokeData(d); |
| | | |
| | | const submit = callback || config.on?.submit; |
| | | |
| | | // 提交事件 |
| | | if (submit) { |
| | | submit(await plugin.submit(d), { |
| | | close() { |
| | | close("save"); |
| | | }, |
| | | done |
| | | }); |
| | | } else { |
| | | done(); |
| | | } |
| | | } else { |
| | | // 切换到对应的选项卡 |
| | | Tabs.toGroup({ |
| | | refs, |
| | | config, |
| | | prop: keys(error)[0] |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 打开表单 |
| | | function open(options?: ClForm.Options, plugins?: ClForm.Plugin[]) { |
| | | if (!options) { |
| | | return console.error("Options is not null"); |
| | | } |
| | | |
| | | // 清空 |
| | | if (options.isReset !== false) { |
| | | clear(); |
| | | } |
| | | |
| | | // 显示对话框 |
| | | visible.value = true; |
| | | |
| | | // 默认关闭方式 |
| | | closeAction = "close"; |
| | | |
| | | // 合并配置 |
| | | for (const i in config) { |
| | | switch (i) { |
| | | // 表单项 |
| | | case "items": |
| | | function deep(arr: any[]): any[] { |
| | | return arr.map((e) => { |
| | | const d = getValue(e); |
| | | |
| | | return { |
| | | ...d, |
| | | children: d?.children ? deep(d.children) : undefined |
| | | }; |
| | | }); |
| | | } |
| | | |
| | | config.items = deep(options.items || []); |
| | | break; |
| | | // 事件、参数、操作 |
| | | case "on": |
| | | case "op": |
| | | case "props": |
| | | case "dialog": |
| | | case "_data": |
| | | merge(config[i], options[i] || {}); |
| | | break; |
| | | // 其他 |
| | | default: |
| | | config[i] = options[i]; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 预设表单值 |
| | | if (options?.form) { |
| | | for (const i in options.form) { |
| | | form[i] = options.form[i]; |
| | | } |
| | | } |
| | | |
| | | // 设置表单数据 |
| | | config.items.forEach((e) => { |
| | | function deep(e: ClForm.Item) { |
| | | if (e.prop) { |
| | | // 解析 prop |
| | | if (e.prop.includes(".")) { |
| | | e.prop = e.prop.replace(/\./g, "-"); |
| | | } |
| | | |
| | | // prop 合并 |
| | | Tabs.mergeProp(e); |
| | | |
| | | // hook 绑定值 |
| | | formHook.bind({ |
| | | ...e, |
| | | value: form[e.prop] !== undefined ? form[e.prop] : cloneDeep(e.value), |
| | | form |
| | | }); |
| | | |
| | | // 表单验证 |
| | | if (e.required) { |
| | | e.rules = { |
| | | required: true, |
| | | message: dict.label.nonEmpty.replace("{label}", e.label || "") |
| | | }; |
| | | } |
| | | } |
| | | |
| | | // 设置 tabs 默认值 |
| | | if (e.type == "tabs") { |
| | | Tabs.set(e.value); |
| | | } |
| | | |
| | | // 子集 |
| | | if (e.children) { |
| | | e.children.forEach(deep); |
| | | } |
| | | } |
| | | |
| | | deep(e); |
| | | }); |
| | | |
| | | // 设置默认值 |
| | | if (!defForm) { |
| | | defForm = cloneDeep(form); |
| | | } |
| | | |
| | | // 创建插件 |
| | | plugin.create(plugins); |
| | | |
| | | // 打开回调 |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | // 打开事件 |
| | | if (config.on?.open) { |
| | | config.on.open(form); |
| | | } |
| | | }, 10); |
| | | }); |
| | | } |
| | | |
| | | // 绑定表单数据 |
| | | function bindForm(data: any) { |
| | | config.items.forEach((e) => { |
| | | function deep(e: ClForm.Item) { |
| | | formHook.bind({ |
| | | ...e, |
| | | value: e.prop ? data[e.prop] : undefined, |
| | | form: data |
| | | }); |
| | | |
| | | if (e.children) { |
| | | e.children.forEach(deep); |
| | | } |
| | | } |
| | | |
| | | deep(e); |
| | | }); |
| | | |
| | | assign(form, data); |
| | | } |
| | | |
| | | // 渲染表单项 |
| | | function renderFormItem(e: ClForm.Item) { |
| | | const { isDisabled } = config._data; |
| | | |
| | | if (e.type == "tabs") { |
| | | return ( |
| | | <cl-form-tabs v-model={Tabs.active.value} {...e.props} onChange={Tabs.onLoad} /> |
| | | ); |
| | | } |
| | | |
| | | // 是否隐藏 |
| | | e._hidden = parseHidden(e.hidden, { |
| | | scope: form |
| | | }); |
| | | |
| | | // 分组显示 |
| | | const inGroup = e.group ? e.group === Tabs.active.value : true; |
| | | |
| | | // 是否已加载完成 |
| | | const isLoaded = e.component && Tabs.isLoaded(e.group); |
| | | |
| | | // 表单项 |
| | | const FormItem = h( |
| | | <el-form-item |
| | | class={{ |
| | | "no-label": !(e.renderLabel || e.label), |
| | | "has-children": !!e.children |
| | | }} |
| | | key={e.prop} |
| | | data-group={e.group || "-"} |
| | | data-prop={e.prop || "-"} |
| | | label-width={props.inline ? "auto" : ""} |
| | | label={e.label} |
| | | prop={e.prop} |
| | | rules={isDisabled ? null : e.rules} |
| | | required={e._hidden ? false : e.required} |
| | | v-show={inGroup && !e._hidden} |
| | | />, |
| | | e.props, |
| | | { |
| | | label() { |
| | | if (e.renderLabel) { |
| | | return renderNode(e.renderLabel, { |
| | | scope: form, |
| | | render: "slot", |
| | | slots |
| | | }); |
| | | } else { |
| | | return e.label; |
| | | } |
| | | }, |
| | | default() { |
| | | return ( |
| | | <div> |
| | | <div class="cl-form-item"> |
| | | {["prepend", "component", "append"] |
| | | .filter((k) => e[k]) |
| | | .map((name) => { |
| | | const children = e.children && ( |
| | | <div class="cl-form-item__children"> |
| | | <el-row gutter={10}> |
| | | {e.children.map(renderFormItem)} |
| | | </el-row> |
| | | </div> |
| | | ); |
| | | |
| | | const Item = renderNode(e[name], { |
| | | item: e, |
| | | prop: e.prop, |
| | | scope: form, |
| | | slots, |
| | | children, |
| | | _data: { |
| | | isDisabled |
| | | } |
| | | }); |
| | | |
| | | return ( |
| | | <div |
| | | v-show={!e.collapse} |
| | | class={[ |
| | | `cl-form-item__${name}`, |
| | | { |
| | | flex1: e.flex !== false |
| | | } |
| | | ]} |
| | | style={e[name].style}> |
| | | {Item} |
| | | </div> |
| | | ); |
| | | })} |
| | | </div> |
| | | |
| | | {isBoolean(e.collapse) && ( |
| | | <div |
| | | class="cl-form-item__collapse" |
| | | onClick={() => { |
| | | Action.collapseItem(e); |
| | | }}> |
| | | <el-divider content-position="center"> |
| | | {e.collapse |
| | | ? dict.label.seeMore |
| | | : dict.label.hideContent} |
| | | </el-divider> |
| | | </div> |
| | | )} |
| | | </div> |
| | | ); |
| | | } |
| | | } |
| | | ); |
| | | |
| | | let span = e.span || style.form.span; |
| | | |
| | | if (browser.isMini) { |
| | | span = 24; |
| | | } |
| | | |
| | | // 是否行内 |
| | | const Item = props.inline ? ( |
| | | FormItem |
| | | ) : ( |
| | | <el-col span={span} {...e.col} v-show={inGroup && !e._hidden}> |
| | | {FormItem} |
| | | </el-col> |
| | | ); |
| | | |
| | | return isLoaded ? Item : null; |
| | | } |
| | | |
| | | // 渲染表单 |
| | | function renderContainer() { |
| | | // 表单项列表 |
| | | const children = config.items.map(renderFormItem); |
| | | |
| | | // 表单标签位置 |
| | | const labelPosition = |
| | | browser.isMini && !props.inline |
| | | ? "top" |
| | | : config.props.labelPosition || style.form.labelPosition; |
| | | |
| | | return ( |
| | | <div class="cl-form__container" ref={setRefs("form")}> |
| | | {h( |
| | | <el-form |
| | | ref={Form} |
| | | size={style.size} |
| | | label-width={style.form.labelWidth} |
| | | inline={props.inline} |
| | | require-asterisk-position="right" |
| | | disabled={saving.value} |
| | | scroll-to-error |
| | | model={form} |
| | | onSubmit={(e: Event) => { |
| | | submit(); |
| | | e.preventDefault(); |
| | | }} |
| | | />, |
| | | { |
| | | ...config.props, |
| | | labelPosition |
| | | }, |
| | | { |
| | | default: () => { |
| | | const items = [ |
| | | slots.prepend && slots.prepend({ scope: form }), |
| | | children, |
| | | slots.append && slots.append({ scope: form }) |
| | | ]; |
| | | |
| | | return ( |
| | | <div class="cl-form__items" v-loading={loading.value}> |
| | | {props.inline ? ( |
| | | items |
| | | ) : ( |
| | | <el-row gutter={10}>{items}</el-row> |
| | | )} |
| | | </div> |
| | | ); |
| | | } |
| | | } |
| | | )} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // 渲染表单底部按钮 |
| | | function renderFooter() { |
| | | const { hidden, buttons, saveButtonText, closeButtonText, justify } = config.op; |
| | | |
| | | if (hidden) { |
| | | return null; |
| | | } |
| | | |
| | | const Btns = buttons?.map((e: any) => { |
| | | switch (e) { |
| | | case "save": |
| | | return ( |
| | | <el-button |
| | | type="success" |
| | | size={style.size} |
| | | disabled={loading.value} |
| | | loading={saving.value} |
| | | onClick={() => { |
| | | submit(); |
| | | }}> |
| | | {saveButtonText} |
| | | </el-button> |
| | | ); |
| | | case "close": |
| | | return ( |
| | | <el-button |
| | | size={style.size} |
| | | onClick={() => { |
| | | close("close"); |
| | | }}> |
| | | {closeButtonText} |
| | | </el-button> |
| | | ); |
| | | default: |
| | | return renderNode(e, { |
| | | scope: form, |
| | | slots, |
| | | custom() { |
| | | return ( |
| | | <el-button |
| | | type={e.type} |
| | | {...e.props} |
| | | onClick={() => { |
| | | e.onClick({ scope: form }); |
| | | }}> |
| | | {e.label} |
| | | </el-button> |
| | | ); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | return ( |
| | | <div |
| | | class="cl-form__footer" |
| | | style={{ |
| | | justifyContent: justify || "flex-end" |
| | | }}> |
| | | {Btns} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // Tools |
| | | function parseHidden(value: any, { scope }: any) { |
| | | if (isBoolean(value)) { |
| | | return value; |
| | | } else if (isFunction(value)) { |
| | | return value({ scope }); |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | const ctx = { |
| | | name: props.name, |
| | | refs, |
| | | Form, |
| | | visible, |
| | | saving, |
| | | form, |
| | | config, |
| | | loading, |
| | | disabled, |
| | | open, |
| | | close, |
| | | done, |
| | | clear, |
| | | reset, |
| | | submit, |
| | | invokeData, |
| | | bindForm, |
| | | showLoading, |
| | | hideLoading, |
| | | setDisabled, |
| | | Tabs, |
| | | ...Action, |
| | | ...ElFormApi |
| | | }; |
| | | |
| | | expose(ctx); |
| | | |
| | | return () => { |
| | | if (props.inner) { |
| | | return ( |
| | | visible.value && ( |
| | | <div class="cl-form"> |
| | | {renderContainer()} |
| | | {renderFooter()} |
| | | </div> |
| | | ) |
| | | ); |
| | | } else { |
| | | return h( |
| | | <cl-dialog v-model={visible.value} class="cl-form" />, |
| | | { |
| | | title: config.title, |
| | | height: config.height, |
| | | width: config.width, |
| | | ...config.dialog, |
| | | beforeClose, |
| | | onClosed, |
| | | keepAlive: false |
| | | }, |
| | | { |
| | | default() { |
| | | return renderContainer(); |
| | | }, |
| | | footer() { |
| | | return renderFooter(); |
| | | } |
| | | } |
| | | ); |
| | | } |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { App } from "vue"; |
| | | import Crud from "./crud"; |
| | | import AddBtn from "./add-btn"; |
| | | import AdvBtn from "./adv/btn"; |
| | | import AdvSearch from "./adv/search"; |
| | | import Flex from "./flex1"; |
| | | import Form from "./form"; |
| | | import FormTabs from "./form-tabs"; |
| | | import FormCard from "./form-card"; |
| | | import MultiDeleteBtn from "./multi-delete-btn"; |
| | | import Pagination from "./pagination"; |
| | | import RefreshBtn from "./refresh-btn"; |
| | | import SearchKey from "./search-key"; |
| | | import Table from "./table"; |
| | | import Upsert from "./upsert"; |
| | | import Dialog from "./dialog"; |
| | | import Filter from "./filter"; |
| | | import Search from "./search"; |
| | | import ErrorMessage from "./error-message"; |
| | | import Row from "./row"; |
| | | import ContextMenu from "./context-menu"; |
| | | |
| | | export const components: { [key: string]: any } = { |
| | | Crud, |
| | | AddBtn, |
| | | AdvBtn, |
| | | AdvSearch, |
| | | Flex, |
| | | Form, |
| | | FormTabs, |
| | | FormCard, |
| | | MultiDeleteBtn, |
| | | Pagination, |
| | | RefreshBtn, |
| | | SearchKey, |
| | | Table, |
| | | Upsert, |
| | | Dialog, |
| | | Filter, |
| | | Search, |
| | | ErrorMessage, |
| | | Row, |
| | | ContextMenu |
| | | }; |
| | | |
| | | export function useComponent(app: App) { |
| | | for (const i in components) { |
| | | app.component(components[i].name, components[i]); |
| | | } |
| | | } |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | import { useConfig, useCore } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-multi-delete-btn", |
| | | |
| | | setup(_, { slots }) { |
| | | const { crud } = useCore(); |
| | | const { style } = useConfig(); |
| | | |
| | | return () => { |
| | | return ( |
| | | crud.getPermission("delete") && ( |
| | | <el-button |
| | | type="danger" |
| | | size={style.size} |
| | | disabled={crud.selection.length === 0} |
| | | onClick={() => { |
| | | crud.rowDelete(...crud.selection); |
| | | }}> |
| | | {slots.default?.() || crud.dict.label.multiDelete} |
| | | </el-button> |
| | | ) |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent, h, onMounted, onUnmounted, ref } from "vue"; |
| | | import { useBrowser, useConfig, useCore } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-pagination", |
| | | |
| | | setup(_, { expose }) { |
| | | const { crud, mitt } = useCore(); |
| | | const { style } = useConfig(); |
| | | const browser = useBrowser(); |
| | | |
| | | // 总数 |
| | | const total = ref(0); |
| | | |
| | | // 当前页数 |
| | | const currentPage = ref(1); |
| | | |
| | | // 每页大小 |
| | | const pageSize = ref(20); |
| | | |
| | | // 页数发生变化 |
| | | function onCurrentChange(index: number) { |
| | | crud.refresh({ |
| | | page: index |
| | | }); |
| | | } |
| | | |
| | | // 条目发生变化 |
| | | function onSizeChange(size: number) { |
| | | crud.refresh({ |
| | | page: 1, |
| | | size |
| | | }); |
| | | } |
| | | |
| | | // 设置分页信息 |
| | | function setPagination(res: obj) { |
| | | if (res) { |
| | | currentPage.value = res.currentPage || res.page || 1; |
| | | pageSize.value = res.pageSize || res.size || 20; |
| | | total.value = res.total || 0; |
| | | crud.params.size = pageSize.value; |
| | | } |
| | | } |
| | | |
| | | // 数据刷新 |
| | | function onRefresh(res: ClCrud.Response["page"]) { |
| | | setPagination(res.pagination); |
| | | } |
| | | |
| | | // 监听刷新事件 |
| | | onMounted(() => { |
| | | mitt.on("crud.refresh", onRefresh); |
| | | }); |
| | | |
| | | // 移除监听事件 |
| | | onUnmounted(() => { |
| | | mitt.off("crud.refresh", onRefresh); |
| | | }); |
| | | |
| | | expose({ |
| | | total, |
| | | currentPage, |
| | | pageSize, |
| | | setPagination |
| | | }); |
| | | |
| | | return () => { |
| | | return h( |
| | | <el-pagination |
| | | class="cl-pagination" |
| | | size={browser.isMini ? 'small' : style.size} |
| | | background |
| | | page-sizes={[10, 20, 30, 40, 50, 100]} |
| | | pager-count={browser.isMini ? 5 : 7} |
| | | layout={ |
| | | browser.isMini ? "total, pager" : "total, sizes, prev, pager, next, jumper" |
| | | } |
| | | />, |
| | | { |
| | | onSizeChange, |
| | | onCurrentChange, |
| | | total: total.value, |
| | | currentPage: currentPage.value, |
| | | pageSize: pageSize.value |
| | | } |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | import { useConfig, useCore } from "../../hooks"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-refresh-btn", |
| | | |
| | | setup(_, { slots }) { |
| | | const { crud } = useCore(); |
| | | const { style } = useConfig(); |
| | | |
| | | return () => { |
| | | return ( |
| | | <el-button |
| | | size={style.size} |
| | | onClick={() => { |
| | | crud.refresh(); |
| | | }}> |
| | | {slots.default?.() || crud.dict.label.refresh} |
| | | </el-button> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-row", |
| | | |
| | | setup(_, { slots }) { |
| | | return () => { |
| | | return <el-row class="cl-row">{slots.default && slots.default()}</el-row>; |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { defineComponent, ref, computed, type PropType, useModel } from "vue"; |
| | | import { useConfig, useCore } from "../../hooks"; |
| | | import { parsePx } from "../../utils"; |
| | | import { debounce } from "lodash-es"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-search-key", |
| | | |
| | | props: { |
| | | // 绑定值 |
| | | modelValue: String, |
| | | // 选中字段 |
| | | field: { |
| | | type: String, |
| | | default: "keyWord" |
| | | }, |
| | | // 字段列表 |
| | | fieldList: { |
| | | type: Array as PropType<Array<{ label: string; value: string }>>, |
| | | default: () => [] |
| | | }, |
| | | // 搜索时的钩子 |
| | | onSearch: Function, |
| | | // 输入框占位内容 |
| | | placeholder: String, |
| | | // 宽度 |
| | | width: { |
| | | type: [String, Number], |
| | | default: 280 |
| | | }, |
| | | // 是否实时刷新 |
| | | refreshOnInput: Boolean |
| | | }, |
| | | |
| | | emits: ["update:modelValue", "change", "field-change"], |
| | | |
| | | setup(props, { emit, expose }) { |
| | | const { crud } = useCore(); |
| | | const { style } = useConfig(); |
| | | |
| | | // 选中字段 |
| | | const selectField = ref(props.field); |
| | | |
| | | // 加载状态 |
| | | const loading = ref(false); |
| | | |
| | | // 文字提示 |
| | | const placeholder = computed(() => { |
| | | if (props.placeholder) { |
| | | return props.placeholder; |
| | | } else { |
| | | const item = props.fieldList.find((e) => e.value == selectField.value); |
| | | |
| | | if (item) { |
| | | return crud.dict.label.placeholder + item.label; |
| | | } else { |
| | | return crud.dict.label.searchKey; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 搜索内容 |
| | | const value = useModel(props, "modelValue"); |
| | | |
| | | // 锁 |
| | | let lock = false; |
| | | |
| | | // 搜索 |
| | | function search() { |
| | | if (!lock) { |
| | | const params: obj = {}; |
| | | |
| | | props.fieldList.forEach((e) => { |
| | | params[e.value] = undefined; |
| | | }); |
| | | |
| | | async function next(newParams?: obj) { |
| | | loading.value = true; |
| | | |
| | | await crud.refresh({ |
| | | page: 1, |
| | | ...params, |
| | | [selectField.value]: value.value || undefined, |
| | | ...newParams |
| | | }) |
| | | .catch(err => { |
| | | console.error(err); |
| | | }) |
| | | |
| | | loading.value = false; |
| | | } |
| | | |
| | | if (props.onSearch) { |
| | | props.onSearch(params, { next }); |
| | | } else { |
| | | next(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 回车搜索 |
| | | function onKeydown({ key }: KeyboardEvent) { |
| | | if (key === "Enter") { |
| | | search(); |
| | | } |
| | | } |
| | | |
| | | // 监听变化 |
| | | function onChange(val: string) { |
| | | if (!props.refreshOnInput) { |
| | | search(); |
| | | lock = true; |
| | | |
| | | setTimeout(() => { |
| | | lock = false; |
| | | }, 300); |
| | | |
| | | emit("change", val); |
| | | } |
| | | } |
| | | |
| | | // 监听输入 |
| | | const onInput = debounce((val: string) => { |
| | | emit("change", val); |
| | | |
| | | if (props.refreshOnInput) { |
| | | search(); |
| | | } |
| | | }, 300); |
| | | |
| | | // 监听字段选择 |
| | | function onFieldChange() { |
| | | emit("field-change", selectField.value); |
| | | value.value = undefined; |
| | | } |
| | | |
| | | expose({ |
| | | search |
| | | }); |
| | | |
| | | return () => { |
| | | return ( |
| | | <div class="cl-search-key"> |
| | | <el-select |
| | | class="cl-search-key__select" |
| | | size={style.size} |
| | | v-model={selectField.value} |
| | | v-show={props.fieldList.length > 0} |
| | | onChange={onFieldChange}> |
| | | {props.fieldList.map((e, i) => ( |
| | | <el-option key={i} label={e.label} value={e.value} /> |
| | | ))} |
| | | </el-select> |
| | | |
| | | <div class="cl-search-key__wrap" style={{ width: parsePx(props.width) }}> |
| | | <el-input |
| | | v-model={value.value} |
| | | size={style.size} |
| | | placeholder={placeholder.value} |
| | | onKeydown={onKeydown} |
| | | onChange={onChange} |
| | | onInput={onInput} |
| | | clearable |
| | | /> |
| | | |
| | | <el-button |
| | | size={style.size} |
| | | type="primary" |
| | | loading={loading.value} |
| | | onClick={search}> |
| | | {crud.dict.label.search} |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { getCurrentInstance } from "vue"; |
| | | import { useConfig } from "../../../hooks"; |
| | | import { uniqueFns } from "../../../utils"; |
| | | |
| | | export function usePlugins() { |
| | | const that: any = getCurrentInstance(); |
| | | const { style } = useConfig(); |
| | | |
| | | // 插件创建 |
| | | function create(plugins: ClSearch.Plugin[] = []) { |
| | | uniqueFns([...(style.search?.plugins || []), ...plugins]).forEach((p) => { |
| | | p({ |
| | | exposed: that.exposed |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | return { |
| | | create |
| | | }; |
| | | } |
| New file |
| | |
| | | import { useConfig, useCore, useForm, useProxy, useRefs } from "../../hooks"; |
| | | import { |
| | | onMounted, |
| | | PropType, |
| | | defineComponent, |
| | | ref, |
| | | h, |
| | | reactive, |
| | | inject, |
| | | mergeProps, |
| | | nextTick, |
| | | onUnmounted |
| | | } from "vue"; |
| | | import { useApi } from "../form/helper"; |
| | | import { Search, Refresh, Bottom, Top } from "@element-plus/icons-vue"; |
| | | import { mitt } from "../../utils/mitt"; |
| | | import { isArray, isEmpty } from "lodash-es"; |
| | | import { usePlugins } from "./helper/plugins"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-search", |
| | | |
| | | props: { |
| | | // 是否行内 |
| | | inline: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | |
| | | // cl-form 表单配置 |
| | | props: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | |
| | | // 表单值 |
| | | data: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | |
| | | // 列 |
| | | items: { |
| | | type: Array as PropType<ClForm.Item[]>, |
| | | default: () => [] |
| | | }, |
| | | |
| | | // 是否需要重置按钮 |
| | | resetBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | |
| | | // 是否需要折叠 |
| | | collapse: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | |
| | | // 初始化 |
| | | onLoad: Function, |
| | | |
| | | // 搜索时钩子 |
| | | onSearch: Function |
| | | }, |
| | | |
| | | emits: ["reset"], |
| | | |
| | | setup(props, { slots, expose, emit }) { |
| | | const { crud } = useCore(); |
| | | const { refs, setRefs } = useRefs() |
| | | const { style } = useConfig(); |
| | | const plugin = usePlugins() |
| | | |
| | | // 配置 |
| | | const config = reactive<ClSearch.Config>( |
| | | mergeProps(props, inject("useSearch__options") || {}) |
| | | ); |
| | | |
| | | // cl-form |
| | | const Form = useForm(); |
| | | |
| | | // 加载中 |
| | | const loading = ref(false); |
| | | |
| | | // 展开 |
| | | const isExpand = ref(!config.collapse); |
| | | |
| | | // 显示展开、收起按钮 |
| | | const showExpandBtn = ref(false); |
| | | |
| | | // 搜索 |
| | | function search(params?: any) { |
| | | const form = Form.value?.getForm(); |
| | | |
| | | async function next(data?: any) { |
| | | loading.value = true; |
| | | |
| | | const d = { |
| | | page: 1, |
| | | ...form, |
| | | ...data, |
| | | ...params |
| | | }; |
| | | |
| | | for (const i in d) { |
| | | if (d[i] === "") { |
| | | d[i] = undefined; |
| | | } |
| | | } |
| | | |
| | | const res = await crud.refresh(d); |
| | | |
| | | loading.value = false; |
| | | |
| | | return res; |
| | | } |
| | | |
| | | if (config.onSearch) { |
| | | config.onSearch(form, { next }); |
| | | } else { |
| | | next(); |
| | | } |
| | | } |
| | | |
| | | // 重置 |
| | | function reset() { |
| | | const d: any = {}; |
| | | |
| | | config.items?.map((e) => { |
| | | if (typeof e.hook != 'string' && e.hook?.reset) { |
| | | const props = e.hook.reset(e.prop!) |
| | | |
| | | if (isArray(props)) { |
| | | props.forEach((prop) => { |
| | | d[prop] = undefined; |
| | | }) |
| | | } |
| | | } |
| | | |
| | | d[e.prop!] = undefined; |
| | | }); |
| | | |
| | | // 重置表单 |
| | | Form.value?.reset(); |
| | | |
| | | // 列表刷新 |
| | | search(d); |
| | | |
| | | // 重置事件 |
| | | emit("reset", d); |
| | | } |
| | | |
| | | // 收起、展开 |
| | | function expand() { |
| | | isExpand.value = !isExpand.value; |
| | | |
| | | nextTick(() => { |
| | | crud?.["cl-table"].calcMaxHeight() |
| | | }) |
| | | } |
| | | |
| | | // 判断展开状态 |
| | | function onExpand() { |
| | | if (config.collapse) { |
| | | const el = refs.form?.querySelector(".cl-form__items"); |
| | | |
| | | if (el) { |
| | | showExpandBtn.value = el.clientHeight > 84; |
| | | } |
| | | } |
| | | } |
| | | |
| | | function onResize() { |
| | | onExpand(); |
| | | } |
| | | |
| | | const ctx = { |
| | | search, |
| | | reset, |
| | | Form, |
| | | config, |
| | | ...useApi({ Form }) |
| | | }; |
| | | |
| | | useProxy(ctx); |
| | | expose(ctx); |
| | | plugin.create(config.plugins); |
| | | |
| | | onMounted(() => { |
| | | Form.value?.open({ |
| | | op: { |
| | | hidden: true |
| | | }, |
| | | props: { |
| | | labelPosition: 'right', |
| | | ...config.props |
| | | }, |
| | | items: config.items?.map(e => { |
| | | return { |
| | | col: { |
| | | sm: 12, |
| | | md: 8, |
| | | xs: 24, |
| | | lg: 6, |
| | | }, |
| | | ...e, |
| | | } |
| | | }), |
| | | form: config.data, |
| | | on: { |
| | | open(data) { |
| | | config.onLoad?.(data); |
| | | onExpand(); |
| | | }, |
| | | change(data, prop) { |
| | | config.onChange?.(data, prop); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | mitt.on("resize", onResize); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | mitt.off("resize", onResize); |
| | | }) |
| | | |
| | | return () => { |
| | | const btnEl = ( |
| | | <el-form-item label=" " class="cl-search__btns"> |
| | | {/* 重置按钮 */} |
| | | {config.resetBtn && ( |
| | | <el-button size={style.size} icon={Refresh} onClick={reset}> |
| | | {crud.dict.label.reset} |
| | | </el-button> |
| | | )} |
| | | |
| | | {/* 搜索按钮 */} |
| | | <el-button |
| | | type="primary" |
| | | loading={loading.value} |
| | | size={style.size} |
| | | icon={Search} |
| | | onClick={() => { |
| | | search(); |
| | | }}> |
| | | {crud.dict.label.search} |
| | | </el-button> |
| | | |
| | | {/* 自定义按钮 */} |
| | | {slots?.buttons?.(Form.value?.form)} |
| | | </el-form-item> |
| | | ); |
| | | |
| | | return ( |
| | | <div class={["cl-search", isExpand.value ? "is-expand" : "is-fold", { |
| | | 'is-inline': config.inline, |
| | | 'is-collapse': config.collapse, |
| | | }]}> |
| | | <div class="cl-search__form" ref={setRefs("form")}> |
| | | {h( |
| | | <cl-form |
| | | ref={Form} |
| | | inner |
| | | inline={config.inline} |
| | | enable-plugin={false} |
| | | name='search' |
| | | />, |
| | | {}, |
| | | { |
| | | append() { |
| | | return config.collapse ? null : (isEmpty(config.items) || btnEl); |
| | | }, |
| | | ...slots |
| | | } |
| | | )} |
| | | </div> |
| | | |
| | | {config.collapse && ( |
| | | <div class="cl-search__more"> |
| | | {showExpandBtn.value && ( |
| | | <el-button onClick={expand}> |
| | | <span>{isExpand.value ? crud.dict.label.collapse : crud.dict.label.expand}</span> |
| | | <el-icon>{isExpand.value ? <Top /> : <Bottom />}</el-icon> |
| | | </el-button> |
| | | )} |
| | | |
| | | <cl-flex1 /> |
| | | |
| | | {btnEl} |
| | | </div> |
| | | )} |
| | | </div> |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| New file |
| | |
| | | import { nextTick, ref } from "vue"; |
| | | import { useCore } from "../../../hooks"; |
| | | |
| | | export function useData({ config, Table }: { config: ClTable.Config; Table: Vue.Ref<any> }) { |
| | | const { mitt, crud } = useCore(); |
| | | |
| | | // 列表数据 |
| | | const data = ref<obj[]>([]); |
| | | |
| | | // 设置数据 |
| | | function setData(list: obj[]) { |
| | | data.value = list; |
| | | } |
| | | |
| | | // 监听刷新 |
| | | mitt.on("crud.refresh", ({ list }: ClCrud.Response["page"]) => { |
| | | data.value = list; |
| | | |
| | | // 显示选中行 |
| | | nextTick(() => { |
| | | crud.selection.forEach((e) => { |
| | | const d = list.find((a) => a[config.rowKey] == e[config.rowKey]); |
| | | |
| | | if (d) { |
| | | Table.value.toggleRowSelection(d, true); |
| | | } |
| | | }); |
| | | }); |
| | | }); |
| | | |
| | | return { |
| | | data, |
| | | setData |
| | | }; |
| | | } |
| New file |
| | |
| | | import { CloseBold, Search } from "@element-plus/icons-vue"; |
| | | import { h } from "vue"; |
| | | import { useCrud } from "../../../hooks"; |
| | | import { renderNode } from "../../../utils/vnode"; |
| | | |
| | | export function renderHeader(item: ClTable.Column, { scope, slots }: any) { |
| | | const crud = useCrud(); |
| | | |
| | | const slot = slots[`header-${item.prop}`]; |
| | | |
| | | if (slot) { |
| | | return slot({ |
| | | scope |
| | | }); |
| | | } |
| | | |
| | | if (!item.search || !item.search.component) { |
| | | return item.label; |
| | | } |
| | | |
| | | // 显示输入框 |
| | | function show(e: MouseEvent) { |
| | | item.search.isInput = true; |
| | | e.stopPropagation(); |
| | | } |
| | | |
| | | // 隐藏输入框 |
| | | function hide() { |
| | | if (item.search.value !== undefined) { |
| | | item.search.value = undefined; |
| | | refresh(); |
| | | } |
| | | |
| | | item.search.isInput = false; |
| | | } |
| | | |
| | | // 刷新 |
| | | function refresh(params?: any) { |
| | | const { value } = item.search; |
| | | |
| | | crud.value?.refresh({ |
| | | page: 1, |
| | | [item.prop]: value === "" ? undefined : value, |
| | | ...params |
| | | }); |
| | | } |
| | | |
| | | // 文字 |
| | | const text = ( |
| | | <div class="cl-table-header__search-label" onClick={show}> |
| | | <el-icon size={14}>{item.search.icon?.() ?? <Search />}</el-icon> |
| | | |
| | | {item.renderLabel ? item.renderLabel(scope) : item.label} |
| | | </div> |
| | | ); |
| | | |
| | | // 输入框 |
| | | const input = h(renderNode(item.search.component, { prop: item.prop }), { |
| | | clearable: true, |
| | | modelValue: item.search.value, |
| | | onVnodeMounted(vn) { |
| | | // 默认聚焦 |
| | | vn.component?.exposed?.focus?.(); |
| | | }, |
| | | onInput(val: any) { |
| | | item.search.value = val; |
| | | }, |
| | | onChange(val: any) { |
| | | item.search.value = val; |
| | | |
| | | // 更改时刷新列表 |
| | | if (item.search.refreshOnChange) { |
| | | refresh(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return ( |
| | | <div class={["cl-table-header__search", { "is-input": item.search.isInput }]}> |
| | | <div class="cl-table-header__search-inner">{item.search.isInput ? input : text}</div> |
| | | |
| | | {item.search.isInput && ( |
| | | <div class="cl-table-header__search-close" onClick={hide}> |
| | | <el-icon> |
| | | <CloseBold /> |
| | | </el-icon> |
| | | </div> |
| | | )} |
| | | </div> |
| | | ); |
| | | } |
| New file |
| | |
| | | import { debounce, last } from "lodash-es"; |
| | | import { nextTick, onActivated, onMounted, ref } from "vue"; |
| | | import { addClass, removeClass } from "../../../utils"; |
| | | import { mitt } from "../../../utils/mitt"; |
| | | |
| | | // 表格高度 |
| | | export function useHeight({ config, Table }: { Table: Vue.Ref<any>; config: ClTable.Config }) { |
| | | // 最大高度 |
| | | const maxHeight = ref(0); |
| | | |
| | | // 计算表格最大高度 |
| | | const update = debounce(async () => { |
| | | await nextTick(); |
| | | |
| | | let vm = Table.value; |
| | | |
| | | if (vm) { |
| | | while (!vm.$parent?.$el.className?.includes("cl-crud")) { |
| | | vm = vm.$parent; |
| | | } |
| | | |
| | | if (vm) { |
| | | const p = vm.$parent.$el; |
| | | |
| | | await nextTick(); |
| | | |
| | | // 高度 |
| | | let h = 0; |
| | | |
| | | // 表格下间距 |
| | | if (vm.$el.className.includes("cl-row")) { |
| | | h += 10; |
| | | } |
| | | |
| | | // 上高度 |
| | | h += vm.$el.offsetTop; |
| | | |
| | | // 获取下高度 |
| | | let n = vm.$el.nextSibling; |
| | | |
| | | // 集合 |
| | | const arr = [vm.$el]; |
| | | |
| | | while (n) { |
| | | if (n.offsetHeight > 0) { |
| | | h += n.offsetHeight || 0; |
| | | arr.push(n); |
| | | |
| | | if (n.className.includes("cl-row--last")) { |
| | | h += 10; |
| | | } |
| | | } |
| | | |
| | | n = n.nextSibling; |
| | | } |
| | | |
| | | // 移除 cl-row--last |
| | | arr.forEach((e) => { |
| | | removeClass(e, "cl-row--last"); |
| | | }); |
| | | |
| | | // 最后一个可视元素 |
| | | const z = last(arr); |
| | | |
| | | // 去掉 cl-row 下间距高度 |
| | | if (z?.className.includes("cl-row")) { |
| | | addClass(z, "cl-row--last"); |
| | | h -= 10; |
| | | } |
| | | |
| | | // 上间距 |
| | | h += parseInt(window.getComputedStyle(p).paddingTop, 10); |
| | | |
| | | // 设置最大高度 |
| | | if (config.autoHeight) { |
| | | maxHeight.value = p.clientHeight - h; |
| | | } |
| | | } |
| | | } |
| | | }, 100); |
| | | |
| | | // 窗口大小改变事件 |
| | | mitt.on("resize", () => { |
| | | update(); |
| | | }); |
| | | |
| | | onMounted(function () { |
| | | update(); |
| | | }); |
| | | |
| | | onActivated(function () { |
| | | update(); |
| | | }); |
| | | |
| | | return { |
| | | maxHeight, |
| | | calcMaxHeight: update |
| | | }; |
| | | } |
| New file |
| | |
| | | import { inject, reactive, ref } from "vue"; |
| | | import { useConfig } from "../../../hooks"; |
| | | import { getValue, mergeConfig } from "../../../utils"; |
| | | import type { TableInstance } from "element-plus"; |
| | | |
| | | export function useTable(props: any) { |
| | | const { style } = useConfig(); |
| | | |
| | | const Table = ref<TableInstance>(); |
| | | |
| | | // 配置 |
| | | const config = reactive<ClTable.Config>(mergeConfig(props, inject("useTable__options") || {})); |
| | | |
| | | // 列表项动态处理 |
| | | config.columns = (config.columns || []).map((e) => getValue(e)); |
| | | |
| | | // 自动高度 |
| | | config.autoHeight = config.autoHeight ?? style.table.autoHeight; |
| | | |
| | | // 右键菜单 |
| | | config.contextMenu = config.contextMenu ?? style.table.contextMenu; |
| | | |
| | | // 事件 |
| | | if (!config.on) { |
| | | config.on = {}; |
| | | } |
| | | |
| | | // 参数 |
| | | if (!config.props) { |
| | | config.props = {}; |
| | | } |
| | | |
| | | return { Table, config }; |
| | | } |
| | | |
| | | export * from "./data"; |
| | | export * from "./height"; |
| | | export * from "./op"; |
| | | export * from "./render"; |
| | | export * from "./row"; |
| | | export * from "./selection"; |
| | | export * from "./sort"; |
| | | export * from "./header"; |
| New file |
| | |
| | | import { nextTick, ref } from "vue"; |
| | | import { useCore } from "../../../hooks"; |
| | | import { isArray, isBoolean } from "lodash-es"; |
| | | |
| | | export function useOp({ config }: { config: ClTable.Config }) { |
| | | const { mitt } = useCore(); |
| | | |
| | | // 是否可见,用于解决一些显示隐藏的副作用 |
| | | const visible = ref(true); |
| | | |
| | | // 重新构建 |
| | | async function reBuild(cb?: fn) { |
| | | visible.value = false; |
| | | |
| | | await nextTick(); |
| | | |
| | | if (cb) { |
| | | cb(); |
| | | } |
| | | |
| | | visible.value = true; |
| | | |
| | | await nextTick(); |
| | | |
| | | mitt.emit("resize"); |
| | | } |
| | | |
| | | // 显示列 |
| | | function showColumn(prop: string | string[], status?: boolean) { |
| | | const keys = isArray(prop) ? prop : [prop]; |
| | | |
| | | // 多级表头 |
| | | function deep(list: ClTable.Column[]) { |
| | | list.forEach((e) => { |
| | | if (e.prop && keys.includes(e.prop)) { |
| | | e.hidden = isBoolean(status) ? !status : false; |
| | | } |
| | | |
| | | if (e.children) { |
| | | deep(e.children); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | deep(config.columns); |
| | | } |
| | | |
| | | // 隐藏列 |
| | | function hideColumn(prop: string | string[]) { |
| | | showColumn(prop, false); |
| | | } |
| | | |
| | | // 设置列 |
| | | function setColumns(list: ClTable.Column[]) { |
| | | if (list) { |
| | | reBuild(() => { |
| | | config.columns.splice(0, config.columns.length, ...list); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | return { |
| | | visible, |
| | | reBuild, |
| | | showColumn, |
| | | hideColumn, |
| | | setColumns |
| | | }; |
| | | } |
| New file |
| | |
| | | import { getCurrentInstance } from "vue"; |
| | | import { useConfig } from "../../../hooks"; |
| | | import { uniqueFns } from "../../../utils"; |
| | | |
| | | export function usePlugins() { |
| | | const that: any = getCurrentInstance(); |
| | | const { style } = useConfig(); |
| | | |
| | | // 插件创建 |
| | | function create(plugins: ClTable.Plugin[] = []) { |
| | | // 执行 |
| | | uniqueFns([...(style.table.plugins || []), ...plugins]).forEach((p) => { |
| | | p({ |
| | | exposed: that.exposed |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | return { |
| | | create |
| | | }; |
| | | } |
| New file |
| | |
| | | import { h, useSlots } from "vue"; |
| | | import { useCore, useBrowser, useConfig } from "../../../hooks"; |
| | | import { assign, cloneDeep, isArray, isEmpty, isObject, isString, orderBy } from "lodash-es"; |
| | | import { deepFind, getValue } from "../../../utils"; |
| | | import { renderNode } from "../../../utils/vnode"; |
| | | import { renderHeader } from "./header"; |
| | | |
| | | // 渲染 |
| | | export function useRender() { |
| | | const browser = useBrowser(); |
| | | const slots = useSlots(); |
| | | const { crud } = useCore(); |
| | | const { style } = useConfig(); |
| | | |
| | | // 渲染列 |
| | | function renderColumn(columns: ClTable.Column[]) { |
| | | const arr = columns.map((e) => { |
| | | const d = getValue(e); |
| | | |
| | | if (!d.orderNum) { |
| | | d.orderNum = 0; |
| | | } |
| | | |
| | | return d; |
| | | }); |
| | | |
| | | return orderBy(arr, "orderNum", "asc") |
| | | .map((item, index) => { |
| | | if (item.hidden) { |
| | | return null; |
| | | } |
| | | |
| | | const ElTableColumn = ( |
| | | <el-table-column |
| | | key={`cl-table-column__${index}`} |
| | | align={style.table.column.align} |
| | | header-align={style.table.column.headerAlign} |
| | | minWidth={style.table.column.minWidth} |
| | | /> |
| | | ); |
| | | |
| | | // 操作按钮 |
| | | if (item.type === "op") { |
| | | const props = assign( |
| | | { |
| | | label: crud.dict.label.op, |
| | | width: style.table.column.opWidth, |
| | | fixed: browser.isMini ? null : "right" |
| | | }, |
| | | item |
| | | ); |
| | | |
| | | return h(ElTableColumn, props, { |
| | | default: (scope: any) => { |
| | | return ( |
| | | <div class="cl-table__op"> |
| | | {renderOpButtons(item.buttons, { scope })} |
| | | </div> |
| | | ); |
| | | } |
| | | }); |
| | | } |
| | | // 多选,序号 |
| | | else if (["selection", "index"].includes(item.type)) { |
| | | return h(ElTableColumn, item); |
| | | } |
| | | // 默认 |
| | | else { |
| | | function deep(item: ClTable.Column) { |
| | | if (item.hidden) { |
| | | return null; |
| | | } |
| | | |
| | | const props: obj = cloneDeep(item); |
| | | |
| | | // Cannot set property children of #<Element> |
| | | delete props.children; |
| | | |
| | | return h(ElTableColumn, props, { |
| | | header(scope: any) { |
| | | return renderHeader(item, { scope, slots }); |
| | | }, |
| | | default(scope: any) { |
| | | if (item.children) { |
| | | return item.children.map(deep); |
| | | } |
| | | |
| | | // 使用插槽 |
| | | const slot = slots[`column-${item.prop}`]; |
| | | |
| | | if (slot) { |
| | | return slot({ |
| | | scope, |
| | | item |
| | | }); |
| | | } else { |
| | | // 绑定值 |
| | | let value = scope.row[item.prop]; |
| | | |
| | | // 格式化 |
| | | if (item.formatter) { |
| | | value = item.formatter( |
| | | scope.row, |
| | | scope.column, |
| | | value, |
| | | scope.$index |
| | | ); |
| | | |
| | | if (isObject(value)) { |
| | | return value; |
| | | } |
| | | } |
| | | |
| | | // 自定义渲染 |
| | | if (item.render) { |
| | | return item.render( |
| | | scope.row, |
| | | scope.column, |
| | | value, |
| | | scope.$index |
| | | ); |
| | | } |
| | | // 自定义渲染2 |
| | | else if (item.component) { |
| | | return renderNode(item.component, { |
| | | prop: item.prop, |
| | | scope: scope.row, |
| | | _data: { |
| | | column: scope.column, |
| | | index: scope.$index, |
| | | row: scope.row |
| | | } |
| | | }); |
| | | } |
| | | // 字典状态 |
| | | else if (item.dict) { |
| | | return renderDict(value, item); |
| | | } |
| | | // 空数据 |
| | | else if (isEmpty(value)) { |
| | | return scope.emptyText; |
| | | } else { |
| | | return value; |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | return deep(item); |
| | | } |
| | | }) |
| | | .filter(Boolean); |
| | | } |
| | | |
| | | // 渲染操作按钮 |
| | | function renderOpButtons(buttons: any, { scope }: any) { |
| | | const list = getValue(buttons || ["edit", "delete"], { scope }) as ClTable.OpButton; |
| | | |
| | | return list.map((vnode) => { |
| | | if (vnode === "info") { |
| | | return ( |
| | | <el-button |
| | | plain |
| | | size={style.size} |
| | | v-show={crud.getPermission("info")} |
| | | onClick={(e: MouseEvent) => { |
| | | crud.rowInfo(scope.row); |
| | | e.stopPropagation(); |
| | | }}> |
| | | {crud.dict.label?.info} |
| | | </el-button> |
| | | ); |
| | | } else if (vnode === "edit") { |
| | | return ( |
| | | <el-button |
| | | text |
| | | type="primary" |
| | | size={style.size} |
| | | v-show={crud.getPermission("update")} |
| | | onClick={(e: MouseEvent) => { |
| | | crud.rowEdit(scope.row); |
| | | e.stopPropagation(); |
| | | }}> |
| | | {crud.dict.label?.update} |
| | | </el-button> |
| | | ); |
| | | } else if (vnode === "delete") { |
| | | return ( |
| | | <el-button |
| | | text |
| | | type="danger" |
| | | size={style.size} |
| | | v-show={crud.getPermission("delete")} |
| | | onClick={(e: MouseEvent) => { |
| | | crud.rowDelete(scope.row); |
| | | e.stopPropagation(); |
| | | }}> |
| | | {crud.dict.label?.delete} |
| | | </el-button> |
| | | ); |
| | | } else { |
| | | if (typeof vnode === "object") { |
| | | if (vnode.hidden) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | return renderNode(vnode, { |
| | | scope, |
| | | slots, |
| | | custom(vnode) { |
| | | return ( |
| | | <el-button |
| | | text |
| | | type={vnode.type} |
| | | {...vnode?.props} |
| | | onClick={(e: MouseEvent) => { |
| | | vnode.onClick({ scope }); |
| | | e.stopPropagation(); |
| | | }}> |
| | | {vnode.label} |
| | | </el-button> |
| | | ); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 渲染字典 |
| | | function renderDict(value: any, item: ClTable.Column) { |
| | | // 选项列表 |
| | | const list = cloneDeep(item.dict || []) as DictOptions; |
| | | |
| | | // 字符串分隔符 |
| | | const separator = item.dictSeparator === undefined ? "," : item.dictSeparator; |
| | | |
| | | // 设置颜色 |
| | | if (item.dictColor) { |
| | | list.forEach((e, i) => { |
| | | if (!e.color) { |
| | | e.color = style.colors[i]; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 绑定值 |
| | | let values: any[] = []; |
| | | |
| | | // 格式化值 |
| | | if (isArray(value)) { |
| | | values = value; |
| | | } else if (isString(value)) { |
| | | if (separator) { |
| | | values = value.split(separator); |
| | | } else { |
| | | values = [value]; |
| | | } |
| | | } else { |
| | | values = [value]; |
| | | } |
| | | |
| | | // 返回值 |
| | | const result = values |
| | | .filter((e) => e !== undefined && e !== null && e !== "") |
| | | .map((v) => { |
| | | const d = deepFind(v, list, { allLevels: item.dictAllLevels }) || { |
| | | label: v, |
| | | value: v |
| | | }; |
| | | |
| | | return { |
| | | ...d, |
| | | children: [] |
| | | }; |
| | | }); |
| | | |
| | | // 格式化返回 |
| | | if (item.dictFormatter) { |
| | | return item.dictFormatter(result); |
| | | } else { |
| | | // tag 返回 |
| | | return result.map((e) => { |
| | | return h( |
| | | <el-tag disable-transitions style="margin: 2px; border: 0" />, |
| | | { |
| | | type: e.type, |
| | | closable: e.closable, |
| | | hit: e.hit, |
| | | color: e.color, |
| | | size: e.size, |
| | | effect: e.effect || "dark", |
| | | round: e.round |
| | | }, |
| | | { |
| | | default: () => <span>{e.label}</span> |
| | | } |
| | | ); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 插槽 empty |
| | | function renderEmpty(emptyText: string) { |
| | | return ( |
| | | <div class="cl-table__empty"> |
| | | {slots.empty ? ( |
| | | slots.empty() |
| | | ) : ( |
| | | <el-empty image-size={100} description={emptyText}></el-empty> |
| | | )} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // 插槽 append |
| | | function renderAppend() { |
| | | return <div class="cl-table__append">{slots.append && slots.append()}</div>; |
| | | } |
| | | |
| | | return { |
| | | renderColumn, |
| | | renderEmpty, |
| | | renderAppend |
| | | }; |
| | | } |
| New file |
| | |
| | | import { isEmpty, isFunction } from "lodash-es"; |
| | | import { useCore } from "../../../hooks"; |
| | | import { ContextMenu } from "../../context-menu"; |
| | | |
| | | // 单元行事件 |
| | | export function useRow({ |
| | | Table, |
| | | config, |
| | | Sort |
| | | }: { |
| | | Table: Vue.Ref<any>; |
| | | config: ClTable.Config; |
| | | Sort: { |
| | | defaultSort: { |
| | | prop?: string; |
| | | order?: string; |
| | | }; |
| | | changeSort(prop: string, order: string): void; |
| | | }; |
| | | }) { |
| | | const { crud } = useCore(); |
| | | |
| | | // 右键菜单 |
| | | function onRowContextMenu(row: obj, column: obj, event: PointerEvent) { |
| | | // 菜单按钮 |
| | | const buttons = config.contextMenu; |
| | | // 是否开启 |
| | | const enable = !isEmpty(buttons); |
| | | |
| | | if (enable) { |
| | | // 高亮 |
| | | Table.value.setCurrentRow(row); |
| | | |
| | | // 解析按钮 |
| | | const list = buttons |
| | | .map((e) => { |
| | | switch (e) { |
| | | case "refresh": |
| | | return { |
| | | label: crud.dict.label.refresh, |
| | | callback(done: fn) { |
| | | crud.refresh(); |
| | | done(); |
| | | } |
| | | }; |
| | | case "edit": |
| | | case "update": |
| | | return { |
| | | label: crud.dict.label.update, |
| | | hidden: !crud.getPermission("update"), |
| | | callback(done: fn) { |
| | | crud.rowEdit(row); |
| | | done(); |
| | | } |
| | | }; |
| | | case "delete": |
| | | return { |
| | | label: crud.dict.label.delete, |
| | | hidden: !crud.getPermission("delete"), |
| | | callback(done: fn) { |
| | | crud.rowDelete(row); |
| | | done(); |
| | | } |
| | | }; |
| | | case "info": |
| | | return { |
| | | label: crud.dict.label.info, |
| | | hidden: !crud.getPermission("info"), |
| | | callback(done: fn) { |
| | | crud.rowInfo(row); |
| | | done(); |
| | | } |
| | | }; |
| | | case "check": |
| | | return { |
| | | label: crud.selection.find((e) => e.id == row.id) |
| | | ? crud.dict.label.deselect |
| | | : crud.dict.label.select, |
| | | hidden: !config.columns.find((e) => e.type === "selection"), |
| | | callback(done: fn) { |
| | | Table.value.toggleRowSelection(row); |
| | | done(); |
| | | } |
| | | }; |
| | | case "order-desc": |
| | | return { |
| | | label: `${column.label} - ${crud.dict.label.desc}`, |
| | | hidden: !column.sortable, |
| | | callback(done: fn) { |
| | | Sort.changeSort(column.property, "desc"); |
| | | done(); |
| | | } |
| | | }; |
| | | case "order-asc": |
| | | return { |
| | | label: `${column.label} - ${crud.dict.label.asc}`, |
| | | hidden: !column.sortable, |
| | | callback(done: fn) { |
| | | Sort.changeSort(column.property, "asc"); |
| | | done(); |
| | | } |
| | | }; |
| | | default: |
| | | if (isFunction(e)) { |
| | | return e(row, column, event); |
| | | } else { |
| | | return e; |
| | | } |
| | | } |
| | | }) |
| | | .filter((e) => Boolean(e) && !e.hidden); |
| | | |
| | | // 打开菜单 |
| | | if (!isEmpty(list)) { |
| | | ContextMenu.open(event, { |
| | | list |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 回调 |
| | | if (config.onRowContextmenu) { |
| | | config.onRowContextmenu(row, column, event); |
| | | } |
| | | } |
| | | |
| | | return { |
| | | onRowContextMenu |
| | | }; |
| | | } |
| New file |
| | |
| | | import { useCore } from "../../../hooks"; |
| | | |
| | | export function useSelection({ emit }: { emit: Vue.Emit }) { |
| | | const { crud } = useCore(); |
| | | |
| | | // 选择项发生变化 |
| | | function onSelectionChange(selection: any[]) { |
| | | crud.selection.splice(0, crud.selection.length, ...selection); |
| | | emit("selection-change", crud.selection); |
| | | } |
| | | |
| | | return { |
| | | selection: crud.selection, |
| | | onSelectionChange |
| | | }; |
| | | } |
| New file |
| | |
| | | import { useCore } from "../../../hooks"; |
| | | |
| | | // 排序 |
| | | export function useSort({ |
| | | config, |
| | | Table, |
| | | emit |
| | | }: { |
| | | config: ClTable.Config; |
| | | Table: Vue.Ref<any>; |
| | | emit: Vue.Emit; |
| | | }) { |
| | | const { crud } = useCore(); |
| | | |
| | | // 设置默认排序Ï |
| | | const defaultSort = (function () { |
| | | let { prop, order } = config.defaultSort || {}; |
| | | |
| | | const item = config.columns.find((e) => |
| | | ["desc", "asc", "descending", "ascending"].find((a) => a == e.sortable) |
| | | ); |
| | | |
| | | if (item) { |
| | | prop = item.prop; |
| | | order = ["descending", "desc"].find((a) => a == item.sortable) |
| | | ? "descending" |
| | | : "ascending"; |
| | | } |
| | | |
| | | if (order && prop) { |
| | | crud.params.order = ["descending", "desc"].includes(order) ? "desc" : "asc"; |
| | | crud.params.prop = prop; |
| | | |
| | | return { |
| | | prop, |
| | | order |
| | | }; |
| | | } |
| | | |
| | | return {}; |
| | | })(); |
| | | |
| | | // 排序监听 |
| | | function onSortChange({ prop, order }: { prop: string | undefined; order: string }) { |
| | | if (config.sortRefresh) { |
| | | if (order === "descending") { |
| | | order = "desc"; |
| | | } |
| | | |
| | | if (order === "ascending") { |
| | | order = "asc"; |
| | | } |
| | | |
| | | if (!order) { |
| | | prop = undefined; |
| | | } |
| | | |
| | | crud.refresh({ |
| | | prop, |
| | | order, |
| | | page: 1 |
| | | }); |
| | | } |
| | | |
| | | emit("sort-change", { prop, order }); |
| | | } |
| | | |
| | | // 改变排序 |
| | | function changeSort(prop: string, order: string) { |
| | | if (order === "desc") { |
| | | order = "descending"; |
| | | } |
| | | |
| | | if (order === "asc") { |
| | | order = "ascending"; |
| | | } |
| | | |
| | | Table.value?.sort(prop, order); |
| | | } |
| | | |
| | | return { |
| | | defaultSort, |
| | | onSortChange, |
| | | changeSort |
| | | }; |
| | | } |
| New file |
| | |
| | | import { defineComponent, h } from "vue"; |
| | | import { |
| | | useRow, |
| | | useHeight, |
| | | useRender, |
| | | useSort, |
| | | useData, |
| | | useSelection, |
| | | useOp, |
| | | useTable |
| | | } from "./helper"; |
| | | import { useCore, useProxy, useElApi, useConfig } from "../../hooks"; |
| | | import { usePlugins } from "./helper/plugins"; |
| | | |
| | | export default defineComponent({ |
| | | name: "cl-table", |
| | | |
| | | props: { |
| | | // 列配置 |
| | | columns: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | // 是否自动计算高度 |
| | | autoHeight: { |
| | | type: Boolean, |
| | | default: null |
| | | }, |
| | | // 固定高度 |
| | | height: null, |
| | | // 右键菜单 |
| | | contextMenu: { |
| | | type: [Array, Boolean], |
| | | default: null |
| | | }, |
| | | // 默认排序 |
| | | defaultSort: Object, |
| | | // 排序后是否刷新 |
| | | sortRefresh: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 空数据显示文案 |
| | | emptyText: String, |
| | | // 当前行的 key |
| | | rowKey: { |
| | | type: String, |
| | | default: "id" |
| | | } |
| | | }, |
| | | |
| | | emits: ["selection-change", "sort-change"], |
| | | |
| | | setup(props, { emit, expose }) { |
| | | const { crud } = useCore(); |
| | | const { style } = useConfig(); |
| | | const { Table, config } = useTable(props); |
| | | const plugin = usePlugins(); |
| | | |
| | | // 排序 |
| | | const Sort = useSort({ config, emit, Table }); |
| | | |
| | | // 行 |
| | | const Row = useRow({ |
| | | config, |
| | | Table, |
| | | Sort |
| | | }); |
| | | |
| | | // 高度 |
| | | const Height = useHeight({ config, Table }); |
| | | |
| | | // 数据 |
| | | const Data = useData({ config, Table }); |
| | | |
| | | // 多选 |
| | | const Selection = useSelection({ emit }); |
| | | |
| | | // 操作 |
| | | const Op = useOp({ config }); |
| | | |
| | | // 方法 |
| | | const ElTableApi = useElApi( |
| | | [ |
| | | "clearSelection", |
| | | "getSelectionRows", |
| | | "toggleRowSelection", |
| | | "toggleAllSelection", |
| | | "toggleRowExpansion", |
| | | "setCurrentRow", |
| | | "clearSort", |
| | | "clearFilter", |
| | | "doLayout", |
| | | "sort", |
| | | "scrollTo", |
| | | "setScrollTop", |
| | | "setScrollLeft", |
| | | "updateKeyChildren" |
| | | ], |
| | | Table |
| | | ); |
| | | |
| | | const ctx = { |
| | | Table, |
| | | config, |
| | | columns: config.columns, |
| | | ...Selection, |
| | | ...Data, |
| | | ...Sort, |
| | | ...Row, |
| | | ...Height, |
| | | ...Op, |
| | | ...ElTableApi |
| | | }; |
| | | |
| | | useProxy(ctx); |
| | | expose(ctx); |
| | | plugin.create(config.plugins); |
| | | |
| | | return () => { |
| | | const { renderColumn, renderAppend, renderEmpty } = useRender(); |
| | | |
| | | return ( |
| | | ctx.visible.value && |
| | | h( |
| | | <el-table class="cl-table" ref={Table} v-loading={crud.loading} />, |
| | | { |
| | | ...config.on, |
| | | ...config.props, |
| | | |
| | | // config |
| | | maxHeight: config.autoHeight ? ctx.maxHeight.value : null, |
| | | height: config.autoHeight ? config.height : null, |
| | | rowKey: config.rowKey, |
| | | |
| | | // ctx |
| | | defaultSort: ctx.defaultSort, |
| | | data: ctx.data.value, |
| | | onRowContextmenu: ctx.onRowContextMenu, |
| | | onSelectionChange: ctx.onSelectionChange, |
| | | onSortChange: ctx.onSortChange, |
| | | |
| | | // style |
| | | size: style.size, |
| | | border: style.table.border, |
| | | highlightCurrentRow: style.table.highlightCurrentRow, |
| | | resizable: style.table.resizable, |
| | | stripe: style.table.stripe, |
| | | }, |
| | | { |
| | | default() { |
| | | return renderColumn(ctx.columns); |
| | | }, |
| | | empty() { |
| | | return renderEmpty(config.emptyText || crud.dict.label.empty); |
| | | }, |
| | | append() { |
| | | return renderAppend(); |
| | | } |
| | | } |
| | | ) |
| | | ); |
| | | }; |
| | | } |
| | | }); |
| packages/crud/src/components/upsert/index.tsx
packages/crud/src/emitter.ts
packages/crud/src/entry.ts
packages/crud/src/hooks/crud.ts
packages/crud/src/hooks/index.ts
packages/crud/src/index.ts
packages/crud/src/locale/en.ts
packages/crud/src/locale/index.ts
packages/crud/src/locale/ja.ts
packages/crud/src/locale/zh-cn.ts
packages/crud/src/locale/zh-tw.ts
packages/crud/src/main.ts
packages/crud/src/provide.ts
packages/crud/src/static/index.scss
packages/crud/src/test/service.ts
packages/crud/src/utils/form-hook.ts
packages/crud/src/utils/global.ts
packages/crud/src/utils/index.ts
packages/crud/src/utils/mitt.ts
packages/crud/src/utils/parse.tsx
packages/crud/src/utils/vnode.tsx
packages/crud/tsconfig.json
packages/crud/types/components/add-btn/index.d.ts
packages/crud/types/components/adv/btn.d.ts
packages/crud/types/components/adv/search.d.ts
packages/crud/types/components/context-menu/index.d.ts
packages/crud/types/components/crud/helper.d.ts
packages/crud/types/components/crud/index.d.ts
packages/crud/types/components/dialog/index.d.ts
packages/crud/types/components/error-message/index.d.ts
packages/crud/types/components/filter/index.d.ts
packages/crud/types/components/flex1/index.d.ts
packages/crud/types/components/form-card/index.d.ts
packages/crud/types/components/form-tabs/index.d.ts
packages/crud/types/components/form/helper/action.d.ts
packages/crud/types/components/form/helper/api.d.ts
packages/crud/types/components/form/helper/index.d.ts
packages/crud/types/components/form/helper/plugins.d.ts
packages/crud/types/components/form/helper/tabs.d.ts
packages/crud/types/components/form/index.d.ts
packages/crud/types/components/index.d.ts
packages/crud/types/components/multi-delete-btn/index.d.ts
packages/crud/types/components/pagination/index.d.ts
packages/crud/types/components/refresh-btn/index.d.ts
packages/crud/types/components/row/index.d.ts
packages/crud/types/components/search-key/index.d.ts
packages/crud/types/components/search/helper/plugins.d.ts
packages/crud/types/components/search/index.d.ts
packages/crud/types/components/table/helper/data.d.ts
packages/crud/types/components/table/helper/header.d.ts
packages/crud/types/components/table/helper/height.d.ts
packages/crud/types/components/table/helper/index.d.ts
packages/crud/types/components/table/helper/op.d.ts
packages/crud/types/components/table/helper/plugins.d.ts
packages/crud/types/components/table/helper/render.d.ts
packages/crud/types/components/table/helper/row.d.ts
packages/crud/types/components/table/helper/selection.d.ts
packages/crud/types/components/table/helper/sort.d.ts
packages/crud/types/components/table/index.d.ts
packages/crud/types/components/upsert/index.d.ts
packages/crud/types/emitter.d.ts
packages/crud/types/entry.d.ts
packages/crud/types/hooks/crud.d.ts
packages/crud/types/hooks/index.d.ts
packages/crud/types/locale/en.d.ts
packages/crud/types/locale/index.d.ts
packages/crud/types/locale/ja.d.ts
packages/crud/types/locale/zh-cn.d.ts
packages/crud/types/locale/zh-tw.d.ts
packages/crud/types/main.d.ts
packages/crud/types/provide.d.ts
packages/crud/types/test/service.d.ts
packages/crud/types/utils/form-hook.d.ts
packages/crud/types/utils/global.d.ts
packages/crud/types/utils/index.d.ts
packages/crud/types/utils/mitt.d.ts
packages/crud/types/utils/parse.d.ts
packages/crud/types/utils/vnode.d.ts
packages/crud/vite.config.ts
packages/crud/yarn.lock
packages/vite-plugin/.eslintrc.js
packages/vite-plugin/.prettierrc
packages/vite-plugin/client.d.ts
packages/vite-plugin/dist/base.d.ts
packages/vite-plugin/dist/config.d.ts
packages/vite-plugin/dist/ctx/index.d.ts
packages/vite-plugin/dist/demo.d.ts
packages/vite-plugin/dist/eps/flatten.d.ts
packages/vite-plugin/dist/eps/index.d.ts
packages/vite-plugin/dist/file/index.d.ts
packages/vite-plugin/dist/index.d.ts
packages/vite-plugin/dist/index.js
packages/vite-plugin/dist/plugin/index.d.ts
packages/vite-plugin/dist/proxy/index.d.ts
packages/vite-plugin/dist/svg/index.d.ts
packages/vite-plugin/dist/tag/index.d.ts
packages/vite-plugin/dist/test.d.ts
packages/vite-plugin/dist/uniapp-x.d.ts
packages/vite-plugin/dist/uniapp-x/code.d.ts
packages/vite-plugin/dist/uniapp-x/color.d.ts
packages/vite-plugin/dist/uniapp-x/config.d.ts
packages/vite-plugin/dist/uniapp-x/flatten.d.ts
packages/vite-plugin/dist/uniapp-x/index.d.ts
packages/vite-plugin/dist/uniapp-x/tailwind.d.ts
packages/vite-plugin/dist/uniapp-x/utils.d.ts
packages/vite-plugin/dist/utils/index.d.ts
packages/vite-plugin/dist/virtual.d.ts
packages/vite-plugin/package.json
packages/vite-plugin/rollup.config.js
packages/vite-plugin/src/base.ts
packages/vite-plugin/src/config.ts
packages/vite-plugin/src/ctx/index.ts
packages/vite-plugin/src/demo.ts
packages/vite-plugin/src/eps/index.ts
packages/vite-plugin/src/file/index.ts
packages/vite-plugin/src/index.ts
packages/vite-plugin/src/plugin/index.ts
packages/vite-plugin/src/proxy/index.ts
packages/vite-plugin/src/svg/index.ts
packages/vite-plugin/src/tag/index.ts
packages/vite-plugin/src/test.ts
packages/vite-plugin/src/uniapp-x/code.ts
packages/vite-plugin/src/uniapp-x/config.ts
packages/vite-plugin/src/uniapp-x/flatten.ts
packages/vite-plugin/src/uniapp-x/index.ts
packages/vite-plugin/src/uniapp-x/tailwind.ts
packages/vite-plugin/src/uniapp-x/utils.ts
packages/vite-plugin/src/utils/index.ts
packages/vite-plugin/src/virtual.ts
packages/vite-plugin/tsconfig.json
packages/vite-plugin/types/index.d.ts
packages/vite-plugin/yarn.lock
pnpm-lock.yaml
pnpm-workspace.yaml
postcss.config.js
public/favicon.ico
public/logo.png
public/用户导入模版.xlsx
src/App.vue
src/config/dev.ts
src/config/index.ts
src/config/prod.ts
src/config/proxy.ts
src/cool/bootstrap/eps.ts
src/cool/bootstrap/index.ts
src/cool/bootstrap/module.ts
src/cool/hooks/browser.ts
src/cool/hooks/hmr.ts
src/cool/hooks/index.ts
src/cool/hooks/mitt.ts
src/cool/index.ts
src/cool/index.vue
src/cool/module/index.ts
src/cool/router/index.ts
src/cool/service/base.ts
src/cool/service/index.ts
src/cool/service/request.ts
src/cool/service/stream.ts
src/cool/types/index.ts
src/cool/utils/index.ts
src/cool/utils/loading.ts
src/cool/utils/storage.ts
src/main.ts
src/modules/base/components/avatar/index.tsx
src/modules/base/components/code/json.vue
src/modules/base/components/dept/check.vue
src/modules/base/components/dept/select.vue
src/modules/base/components/editor/index.tsx
src/modules/base/components/icon/svg.vue
src/modules/base/components/image/index.vue
src/modules/base/components/link/index.vue
src/modules/base/components/menu/check.vue
src/modules/base/components/menu/file.vue
src/modules/base/components/menu/icon.vue
src/modules/base/components/menu/perms.vue
src/modules/base/components/menu/select.vue
src/modules/base/components/num/index.vue
src/modules/base/config.ts
src/modules/base/directives/permission.ts
src/modules/base/index.ts
src/modules/base/locales/en.json
src/modules/base/locales/zh-cn.json
src/modules/base/locales/zh-tw.json
src/modules/base/pages/error/401.vue
src/modules/base/pages/error/403.vue
src/modules/base/pages/error/404.vue
src/modules/base/pages/error/500.vue
src/modules/base/pages/error/502.vue
src/modules/base/pages/error/components/error-page.vue
src/modules/base/pages/login/components/pic-captcha.vue
src/modules/base/pages/login/index.vue
src/modules/base/pages/login/static/bg.svg
src/modules/base/pages/main/components/amenu.vue
src/modules/base/pages/main/components/bmenu.tsx
src/modules/base/pages/main/components/global.vue
src/modules/base/pages/main/components/process.vue
src/modules/base/pages/main/components/route-nav.vue
src/modules/base/pages/main/components/slider.vue
src/modules/base/pages/main/components/topbar.vue
src/modules/base/pages/main/components/views.vue
src/modules/base/pages/main/index.vue
src/modules/base/static/css/index.scss
src/modules/base/static/svg/amount.svg
src/modules/base/static/svg/back.svg
src/modules/base/static/svg/close-border.svg
src/modules/base/static/svg/close.svg
src/modules/base/static/svg/delete.svg
src/modules/base/static/svg/edit.svg
src/modules/base/static/svg/exit.svg
src/modules/base/static/svg/expand.svg
src/modules/base/static/svg/export.svg
src/modules/base/static/svg/fail.svg
src/modules/base/static/svg/fold.svg
src/modules/base/static/svg/github.svg
src/modules/base/static/svg/home.svg
src/modules/base/static/svg/icon-activity.svg
src/modules/base/static/svg/icon-amount.svg
src/modules/base/static/svg/icon-app.svg
src/modules/base/static/svg/icon-approve.svg
src/modules/base/static/svg/icon-auth.svg
src/modules/base/static/svg/icon-ban.svg
src/modules/base/static/svg/icon-call.svg
src/modules/base/static/svg/icon-camera.svg
src/modules/base/static/svg/icon-card.svg
src/modules/base/static/svg/icon-cart.svg
src/modules/base/static/svg/icon-common.svg
src/modules/base/static/svg/icon-component.svg
src/modules/base/static/svg/icon-count.svg
src/modules/base/static/svg/icon-crown.svg
src/modules/base/static/svg/icon-data.svg
src/modules/base/static/svg/icon-db.svg
src/modules/base/static/svg/icon-delete.svg
src/modules/base/static/svg/icon-dept.svg
src/modules/base/static/svg/icon-design.svg
src/modules/base/static/svg/icon-device.svg
src/modules/base/static/svg/icon-dict.svg
src/modules/base/static/svg/icon-discover.svg
src/modules/base/static/svg/icon-doc.svg
src/modules/base/static/svg/icon-download.svg
src/modules/base/static/svg/icon-emoji.svg
src/modules/base/static/svg/icon-favor.svg
src/modules/base/static/svg/icon-file.svg
src/modules/base/static/svg/icon-folder.svg
src/modules/base/static/svg/icon-goods.svg
src/modules/base/static/svg/icon-home.svg
src/modules/base/static/svg/icon-hot.svg
src/modules/base/static/svg/icon-info.svg
src/modules/base/static/svg/icon-iot.svg
src/modules/base/static/svg/icon-light.svg
src/modules/base/static/svg/icon-like.svg
src/modules/base/static/svg/icon-list.svg
src/modules/base/static/svg/icon-local.svg
src/modules/base/static/svg/icon-log.svg
src/modules/base/static/svg/icon-map.svg
src/modules/base/static/svg/icon-match.svg
src/modules/base/static/svg/icon-menu.svg
src/modules/base/static/svg/icon-monitor.svg
src/modules/base/static/svg/icon-msg.svg
src/modules/base/static/svg/icon-news.svg
src/modules/base/static/svg/icon-notice.svg
src/modules/base/static/svg/icon-params.svg
src/modules/base/static/svg/icon-phone.svg
src/modules/base/static/svg/icon-pic.svg
src/modules/base/static/svg/icon-question.svg
src/modules/base/static/svg/icon-quick.svg
src/modules/base/static/svg/icon-rank.svg
src/modules/base/static/svg/icon-reward.svg
src/modules/base/static/svg/icon-search.svg
src/modules/base/static/svg/icon-set.svg
src/modules/base/static/svg/icon-tag.svg
src/modules/base/static/svg/icon-task.svg
src/modules/base/static/svg/icon-time.svg
src/modules/base/static/svg/icon-tutorial.svg
src/modules/base/static/svg/icon-unlock.svg
src/modules/base/static/svg/icon-user.svg
src/modules/base/static/svg/icon-video.svg
src/modules/base/static/svg/icon-vip.svg
src/modules/base/static/svg/icon-warn.svg
src/modules/base/static/svg/icon-work.svg
src/modules/base/static/svg/icon-workbench.svg
src/modules/base/static/svg/image.svg
src/modules/base/static/svg/import.svg
src/modules/base/static/svg/left.svg
src/modules/base/static/svg/my.svg
src/modules/base/static/svg/order.svg
src/modules/base/static/svg/play.svg
src/modules/base/static/svg/plus-border.svg
src/modules/base/static/svg/plus.svg
src/modules/base/static/svg/refresh.svg
src/modules/base/static/svg/right.svg
src/modules/base/static/svg/screen-full.svg
src/modules/base/static/svg/screen-normal.svg
src/modules/base/static/svg/search.svg
src/modules/base/static/svg/set.svg
src/modules/base/static/svg/sort.svg
src/modules/base/static/svg/stats.svg
src/modules/base/static/svg/success.svg
src/modules/base/static/svg/team.svg
src/modules/base/static/svg/trend.svg
src/modules/base/store/app.ts
src/modules/base/store/index.ts
src/modules/base/store/menu.ts
src/modules/base/store/process.ts
src/modules/base/store/user.ts
src/modules/base/types/index.d.ts
src/modules/base/utils/index.ts
src/modules/base/utils/permission.ts
src/modules/base/views/frame.vue
src/modules/base/views/info.vue
src/modules/base/views/log.vue
src/modules/base/views/menu/components/exp.vue
src/modules/base/views/menu/components/imp.vue
src/modules/base/views/menu/index.vue
src/modules/base/views/param.vue
src/modules/base/views/role.vue
src/modules/base/views/user/components/dept-list.vue
src/modules/base/views/user/components/user-move.vue
src/modules/base/views/user/index.vue
src/modules/basicdata/locales/en.json
src/modules/basicdata/locales/zh-cn.json
src/modules/basicdata/locales/zh-tw.json
src/modules/basicdata/views/driver.vue
src/modules/basicdata/views/iot.vue
src/modules/basicdata/views/site.vue
src/modules/basicdata/views/sorter.vue
src/modules/basicdata/views/vehicle.vue
src/modules/basicdata/views/wastetype.vue
src/modules/demo/config.ts
src/modules/demo/directives/color.ts
src/modules/demo/locales/en.json
src/modules/demo/locales/zh-cn.json
src/modules/demo/locales/zh-tw.json
src/modules/demo/views/crud/components/adv-search/base.vue
src/modules/demo/views/crud/components/adv-search/custom.vue
src/modules/demo/views/crud/components/code.vue
src/modules/demo/views/crud/components/crud/all.vue
src/modules/demo/views/crud/components/crud/base.vue
src/modules/demo/views/crud/components/crud/dict.vue
src/modules/demo/views/crud/components/crud/event.vue
src/modules/demo/views/crud/components/crud/select-table.vue
src/modules/demo/views/crud/components/crud/service.vue
src/modules/demo/views/crud/components/crud/user-select.vue
src/modules/demo/views/crud/components/form/children.vue
src/modules/demo/views/crud/components/form/component/index.vue
src/modules/demo/views/crud/components/form/component/select-labels.vue
src/modules/demo/views/crud/components/form/component/select-status.vue
src/modules/demo/views/crud/components/form/component/select-work.vue
src/modules/demo/views/crud/components/form/component/select-work2.vue
src/modules/demo/views/crud/components/form/config.vue
src/modules/demo/views/crud/components/form/crud.vue
src/modules/demo/views/crud/components/form/disabled.vue
src/modules/demo/views/crud/components/form/event.vue
src/modules/demo/views/crud/components/form/group.vue
src/modules/demo/views/crud/components/form/hidden.vue
src/modules/demo/views/crud/components/form/layout.vue
src/modules/demo/views/crud/components/form/open.vue
src/modules/demo/views/crud/components/form/options.vue
src/modules/demo/views/crud/components/form/plugin/index.vue
src/modules/demo/views/crud/components/form/plugin/role.ts
src/modules/demo/views/crud/components/form/required.vue
src/modules/demo/views/crud/components/form/rules.vue
src/modules/demo/views/crud/components/form/setFocus.vue
src/modules/demo/views/crud/components/other/context-menu.vue
src/modules/demo/views/crud/components/other/tips.vue
src/modules/demo/views/crud/components/other/tsx/index.scss
src/modules/demo/views/crud/components/other/tsx/index.tsx
src/modules/demo/views/crud/components/search/base.vue
src/modules/demo/views/crud/components/search/collapse.vue
src/modules/demo/views/crud/components/search/custom.vue
src/modules/demo/views/crud/components/search/layout.vue
src/modules/demo/views/crud/components/search/plugin.vue
src/modules/demo/views/crud/components/table/base.vue
src/modules/demo/views/crud/components/table/children.vue
src/modules/demo/views/crud/components/table/column-custom.vue
src/modules/demo/views/crud/components/table/component/index.vue
src/modules/demo/views/crud/components/table/component/user-info.vue
src/modules/demo/views/crud/components/table/context-menu.vue
src/modules/demo/views/crud/components/table/dict.vue
src/modules/demo/views/crud/components/table/formatter.vue
src/modules/demo/views/crud/components/table/hidden.vue
src/modules/demo/views/crud/components/table/op.vue
src/modules/demo/views/crud/components/table/plugin/base.vue
src/modules/demo/views/crud/components/table/plugin/row-edit.vue
src/modules/demo/views/crud/components/table/plugin/to-tree.vue
src/modules/demo/views/crud/components/table/search.vue
src/modules/demo/views/crud/components/table/selection.vue
src/modules/demo/views/crud/components/table/slot.vue
src/modules/demo/views/crud/components/table/span-method.vue
src/modules/demo/views/crud/components/table/summary.vue
src/modules/demo/views/crud/components/upsert/base.vue
src/modules/demo/views/crud/components/upsert/event.vue
src/modules/demo/views/crud/components/upsert/hook/index.vue
src/modules/demo/views/crud/components/upsert/hook/reg-pca2.ts
src/modules/demo/views/crud/components/upsert/mode.vue
src/modules/demo/views/crud/index.vue
src/modules/demo/views/home/components/category-ratio.vue
src/modules/demo/views/home/components/count-effect.vue
src/modules/demo/views/home/components/count-paid.vue
src/modules/demo/views/home/components/count-user.vue
src/modules/demo/views/home/components/count-views.vue
src/modules/demo/views/home/components/hot-goods.vue
src/modules/demo/views/home/components/tab-chart.vue
src/modules/demo/views/home/index.vue
src/modules/demo/views/tenant.vue
src/modules/demo/views/test/route.vue
src/modules/dict/config.ts
src/modules/dict/index.ts
src/modules/dict/locales/en.json
src/modules/dict/locales/zh-cn.json
src/modules/dict/locales/zh-tw.json
src/modules/dict/store/dict.ts
src/modules/dict/store/index.ts
src/modules/dict/types/index.d.ts
src/modules/dict/utils/index.ts
src/modules/dict/views/list.vue
src/modules/helper/components/ai-code/btn.vue
src/modules/helper/components/ai-code/dev.vue
src/modules/helper/components/auto-menu.vue
src/modules/helper/components/auto-perms.vue
src/modules/helper/config.ts
src/modules/helper/hooks/index.ts
src/modules/helper/hooks/menu.ts
src/modules/helper/hooks/plugin.ts
src/modules/helper/locales/en.json
src/modules/helper/locales/zh-cn.json
src/modules/helper/locales/zh-tw.json
src/modules/helper/static/index.scss
src/modules/helper/static/svg/icon-vue.svg
src/modules/helper/types/index.d.ts
src/modules/helper/views/ai-code.vue
src/modules/helper/views/plugins.vue
src/modules/push/locales/en.json
src/modules/push/locales/zh-cn.json
src/modules/push/locales/zh-tw.json
src/modules/push/views/auditlog.vue
src/modules/push/views/cameragps.vue
src/modules/push/views/siteweight.vue
src/modules/push/views/vehiclegps.vue
src/modules/push/views/weight.vue
src/modules/recycle/locales/en.json
src/modules/recycle/locales/zh-cn.json
src/modules/recycle/locales/zh-tw.json
src/modules/recycle/views/data.vue
src/modules/space/components/space-inner.vue
src/modules/space/components/space.vue
src/modules/space/config.ts
src/modules/space/hooks/index.ts
src/modules/space/locales/en.json
src/modules/space/locales/zh-cn.json
src/modules/space/locales/zh-tw.json
src/modules/space/views/list.vue
src/modules/task/components/logs.vue
src/modules/task/locales/en.json
src/modules/task/locales/zh-cn.json
src/modules/task/locales/zh-tw.json
src/modules/task/views/list.vue
src/modules/user/components/user-select.vue
src/modules/user/config.ts
src/modules/user/locales/en.json
src/modules/user/locales/zh-cn.json
src/modules/user/locales/zh-tw.json
src/modules/user/views/list.vue
src/plugins/crud/comm/index.ts
src/plugins/crud/components/column-custom/index.vue
src/plugins/crud/components/date/picker.vue
src/plugins/crud/components/date/text.vue
src/plugins/crud/components/dict/index.tsx
src/plugins/crud/components/number/range.vue
src/plugins/crud/components/render/index.tsx
src/plugins/crud/components/select/button.tsx
src/plugins/crud/components/select/index.scss
src/plugins/crud/components/select/index.tsx
src/plugins/crud/components/select/table.vue
src/plugins/crud/components/switch/index.tsx
src/plugins/crud/components/text/index.tsx
src/plugins/crud/components/user/select.vue
src/plugins/crud/config.ts
src/plugins/crud/index.ts
src/plugins/crud/locales/en.json
src/plugins/crud/locales/zh-cn.json
src/plugins/crud/locales/zh-tw.json
src/plugins/crud/plugins/form/index.ts
src/plugins/crud/plugins/form/setFocus.ts
src/plugins/crud/plugins/index.ts
src/plugins/crud/plugins/search/index.ts
src/plugins/crud/plugins/search/setAuto.ts
src/plugins/crud/plugins/table/index.ts
src/plugins/crud/plugins/table/rowEdit.tsx
src/plugins/crud/plugins/table/toTree.ts
src/plugins/dev-tools/components/account.vue
src/plugins/dev-tools/components/dict.vue
src/plugins/dev-tools/components/doc.vue
src/plugins/dev-tools/components/eps.vue
src/plugins/dev-tools/components/index.vue
src/plugins/dev-tools/components/proxy.vue
src/plugins/dev-tools/config.ts
src/plugins/dev-tools/locales/en.json
src/plugins/dev-tools/locales/zh-cn.json
src/plugins/dev-tools/locales/zh-tw.json
src/plugins/dev-tools/static/cool.png
src/plugins/dev-tools/static/echarts.png
src/plugins/dev-tools/static/element-plus.png
src/plugins/dev-tools/static/lodash.png
src/plugins/dev-tools/static/logo.png
src/plugins/dev-tools/static/pinia.png
src/plugins/dev-tools/static/tailwindcss.png
src/plugins/dev-tools/static/vite.png
src/plugins/dev-tools/static/vue.png
src/plugins/dev-tools/utils/index.ts
src/plugins/distpicker/components/index.tsx
src/plugins/distpicker/config.ts
src/plugins/distpicker/data/pca.json
src/plugins/distpicker/demo/base.vue
src/plugins/echarts/config.ts
src/plugins/editor-preview/components/preview.vue
src/plugins/editor-preview/config.ts
src/plugins/editor-preview/demo/base.vue
src/plugins/editor-preview/locales/en.json
src/plugins/editor-preview/locales/zh-cn.json
src/plugins/editor-preview/locales/zh-tw.json
src/plugins/editor-wang/components/wang.vue
src/plugins/editor-wang/config.ts
src/plugins/editor-wang/demo/base.vue
src/plugins/editor-wang/locales/en.json
src/plugins/editor-wang/locales/zh-cn.json
src/plugins/editor-wang/locales/zh-tw.json
src/plugins/element-ui/config.ts
src/plugins/element-ui/css/index.scss
src/plugins/excel/components/export-btn.tsx
src/plugins/excel/components/import-btn.vue
src/plugins/excel/config.ts
src/plugins/excel/demo/base.vue
src/plugins/excel/locales/en.json
src/plugins/excel/locales/zh-cn.json
src/plugins/excel/locales/zh-tw.json
src/plugins/excel/utils/index.ts
src/plugins/github/components/code.vue
src/plugins/github/config.ts
src/plugins/i18n/components/switch.vue
src/plugins/i18n/config.ts
src/plugins/i18n/index.ts
src/plugins/i18n/static/svg/lang.svg
src/plugins/iconfont/config.ts
src/plugins/iconfont/index.ts
src/plugins/iconfont/utils/index.ts
src/plugins/tailwind/config.ts
src/plugins/tailwind/static/index.css
src/plugins/theme/components/theme.vue
src/plugins/theme/config.ts
src/plugins/theme/hooks/index.ts
src/plugins/theme/index.ts
src/plugins/theme/locales/en.json
src/plugins/theme/locales/zh-cn.json
src/plugins/theme/locales/zh-tw.json
src/plugins/theme/static/css/index.scss
src/plugins/theme/static/svg/dark.svg
src/plugins/theme/static/svg/light.svg
src/plugins/theme/static/svg/theme.svg
src/plugins/theme/types/index.d.ts
src/plugins/theme/utils/index.ts
src/plugins/upload/components/upload-item/index.vue
src/plugins/upload/components/upload-item/viewer.vue
src/plugins/upload/components/upload.vue
src/plugins/upload/config.ts
src/plugins/upload/demo/base.vue
src/plugins/upload/demo/check.vue
src/plugins/upload/demo/custom.vue
src/plugins/upload/demo/drag.vue
src/plugins/upload/demo/file.vue
src/plugins/upload/demo/multiple.vue
src/plugins/upload/demo/small.vue
src/plugins/upload/demo/space.vue
src/plugins/upload/hooks/index.ts
src/plugins/upload/index.ts
src/plugins/upload/locales/en.json
src/plugins/upload/locales/zh-cn.json
src/plugins/upload/locales/zh-tw.json
src/plugins/upload/static/svg/audio.svg
src/plugins/upload/static/svg/excel.svg
src/plugins/upload/static/svg/file.svg
src/plugins/upload/static/svg/image.svg
src/plugins/upload/static/svg/pdf.svg
src/plugins/upload/static/svg/ppt.svg
src/plugins/upload/static/svg/rar.svg
src/plugins/upload/static/svg/video.svg
src/plugins/upload/static/svg/word.svg
src/plugins/upload/types/index.d.ts
src/plugins/upload/utils/index.ts
src/plugins/view/components/group.vue
src/plugins/view/components/head.vue
src/plugins/view/config.ts
src/plugins/view/demo/group.vue
src/plugins/view/demo/head.vue
src/plugins/view/hooks/group.ts
src/plugins/view/hooks/index.ts
src/plugins/view/index.ts
src/plugins/view/locales/en.json
src/plugins/view/locales/zh-cn.json
src/plugins/view/locales/zh-tw.json
src/plugins/view/types/index.d.ts
src/shims-vue.d.ts
tailwind.config.js
tsconfig.json
vite.config.ts |