From 68f8603c75cda12f209cbb4fcd8f5ec7212e276d Mon Sep 17 00:00:00 2001 From: "meilin.huang" <954537473@qq.com> Date: Sat, 16 Dec 2023 17:41:15 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20PageTable=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mayfly_go_web/package.json | 10 +- .../SearchForm/components/SearchFormItem.vue | 20 +- .../src/components/SearchForm/index.ts | 189 ++++++++++++++++-- .../src/components/pagetable/PageTable.vue | 148 ++++++++++---- mayfly_go_web/src/theme/app.scss | 4 +- mayfly_go_web/src/views/ops/component/tag.ts | 20 ++ mayfly_go_web/src/views/ops/db/DbList.vue | 17 +- .../src/views/ops/db/DbSqlExecLog.vue | 2 +- .../src/views/ops/db/InstanceList.vue | 2 +- .../ops/db/component/table/DbTableData.vue | 5 + .../src/views/ops/machine/MachineList.vue | 18 +- .../ops/machine/authcert/AuthCertList.vue | 2 +- .../ops/machine/cronjob/CronJobExecList.vue | 5 +- .../views/ops/machine/cronjob/CronJobList.vue | 2 +- .../src/views/ops/mongo/MongoList.vue | 19 +- .../src/views/ops/redis/RedisList.vue | 20 +- mayfly_go_web/src/views/ops/tag/TeamList.vue | 4 +- .../src/views/system/account/AccountList.vue | 2 +- .../src/views/system/role/RoleList.vue | 2 +- .../src/views/system/syslog/SyslogList.vue | 5 +- mayfly_go_web/yarn.lock | 92 ++------- 21 files changed, 372 insertions(+), 216 deletions(-) diff --git a/mayfly_go_web/package.json b/mayfly_go_web/package.json index 8aaa34fc..e27f4511 100644 --- a/mayfly_go_web/package.json +++ b/mayfly_go_web/package.json @@ -11,13 +11,13 @@ "dependencies": { "@element-plus/icons-vue": "^2.1.0", "@vueuse/core": "^10.7.0", - "asciinema-player": "^3.6.2", + "asciinema-player": "^3.6.3", "axios": "^1.6.2", "clipboard": "^2.0.11", "countup.js": "^2.7.0", "cropperjs": "^1.5.11", "echarts": "^5.4.3", - "element-plus": "^2.4.3", + "element-plus": "^2.4.4", "js-base64": "^3.7.5", "jsencrypt": "^3.3.2", "lodash": "^4.17.21", @@ -47,15 +47,15 @@ "@types/sortablejs": "^1.15.3", "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", - "@vitejs/plugin-vue": "^4.5.1", - "@vue/compiler-sfc": "^3.3.10", + "@vitejs/plugin-vue": "^4.5.2", + "@vue/compiler-sfc": "^3.3.11", "dotenv": "^16.3.1", "eslint": "^8.35.0", "eslint-plugin-vue": "^9.19.2", "prettier": "^3.1.0", "sass": "^1.69.0", "typescript": "^5.3.2", - "vite": "^5.0.7", + "vite": "^5.0.10", "vue-eslint-parser": "^9.3.2" }, "browserslist": [ diff --git a/mayfly_go_web/src/components/SearchForm/components/SearchFormItem.vue b/mayfly_go_web/src/components/SearchForm/components/SearchFormItem.vue index 3cd275df..55400de8 100644 --- a/mayfly_go_web/src/components/SearchForm/components/SearchFormItem.vue +++ b/mayfly_go_web/src/components/SearchForm/components/SearchFormItem.vue @@ -2,6 +2,7 @@ { }; }); -// 接收 enumMap (el 为 select-v2 需单独处理 enumData) -// const enumMap = inject('enumMap', ref(new Map())); -// const columnEnum = computed(() => { -// let enumData = enumMap.value.get(props.item.prop); -// if (!enumData) return []; -// if (props.item?.type === 'select-v2' && props.item.fieldNames) { -// enumData = enumData.map((item: { [key: string]: any }) => { -// return { ...item, label: item[fieldNames.value.label], value: item[fieldNames.value.value] }; -// }); -// } -// return enumData; -// }); - // 处理透传的 searchProps (type 为 tree-select、cascader 的时候需要给下默认 label && value && children) const handleSearchProps = computed(() => { const label = fieldNames.value.label; @@ -77,6 +65,12 @@ const handleSearchProps = computed(() => { return searchProps; }); +// 处理透传的 事件 +const handleEvents = computed(() => { + let itemEvents = props.item?.props ?? {}; + return itemEvents; +}); + // 处理默认 placeholder const placeholder = computed(() => { const search = props.item; diff --git a/mayfly_go_web/src/components/SearchForm/index.ts b/mayfly_go_web/src/components/SearchForm/index.ts index 99a6a329..cc8276c2 100644 --- a/mayfly_go_web/src/components/SearchForm/index.ts +++ b/mayfly_go_web/src/components/SearchForm/index.ts @@ -1,4 +1,5 @@ -import { VNode } from 'vue'; +import Api from '@/common/Api'; +import { VNode, ref, toValue } from 'vue'; export type FieldNamesProps = { label: string; @@ -19,6 +20,78 @@ export type SearchItemType = | 'switch' | 'slider'; +/** + * 表单组件可选项的api信息 + */ +export class OptionsApi { + /** + * 请求获取options的api + */ + api: Api; + + /** + * 请求参数 + */ + params: any; + + /** + * 是否立即执行,否则在组件focus事件中获取 + */ + immediate: boolean = false; + + /** + * 是否只获取一次,即若以获取则不继续调用该api + */ + once: boolean = true; + + /** + * 转换函数,主要用于将响应的api结果转换为满足组件options的结构 + */ + convertFn: (apiResp: any) => any; + + withConvertFn(fn: (apiResp: any) => any) { + this.convertFn = fn; + return this; + } + + /** + * 立即获取该可选值 + * @returns + */ + withImmediate() { + this.immediate = true; + return this; + } + + /** + * 设为非一次性api,即每次组件focus获取的时候都允许重新获取options + * @returns this + */ + withNoOnce() { + this.once = false; + return this; + } + + /** + * 调用api获取组件可选项 + * @returns 组件可选项信息 + */ + async getOptions() { + let res = await this.api.request(toValue(this.params)); + if (this.convertFn) { + res = this.convertFn(res); + } + return res; + } + + static new(api: Api, params: any): OptionsApi { + const oa = new OptionsApi(); + oa.api = api; + oa.params = params; + return oa; + } +} + /** * 搜索项 */ @@ -43,22 +116,50 @@ export class SearchItem { */ options: any; + /** + * 获取可选项的api信息 + */ + optionsApi: OptionsApi; + /** * 插槽名 */ slot: string; - props?: any; // 搜索项参数,根据 element plus 官方文档来传递,该属性所有值会透传到组件 + /** + * 搜索项参数,根据 element plus 官方文档来传递,该属性所有值会透传到组件 + */ + props?: any; - tooltip?: string; // 搜索提示 + /** + * 搜索项事件,根据 element plus 官方文档来传递,该属性所有值会透传到组件 + */ + events?: any; - span?: number; // 搜索项所占用的列数,默认为 1 列 + /** + * 搜索提示 + */ + tooltip?: string; - offset?: number; // 搜索字段左侧偏移列数 + /** + * 搜索项所占用的列数,默认为 1 列 + */ + span?: number; - fieldNames: FieldNamesProps; // 指定 label && value && children 的 key 值,用于select等类型组件 + /** + * 搜索字段左侧偏移列数 + */ + offset?: number; - render?: (scope: any) => VNode; // 自定义搜索内容渲染(tsx语法) + /** + * 指定 label && value && children 的 key 值,用于select等类型组件 + */ + fieldNames: FieldNamesProps; + + /** + * 自定义搜索内容渲染(tsx语法) + */ + render?: (scope: any) => VNode; constructor(prop: string, label: string) { this.prop = prop; @@ -69,7 +170,7 @@ export class SearchItem { return new SearchItem(prop, label); } - static text(prop: string, label: string): SearchItem { + static input(prop: string, label: string): SearchItem { const tq = new SearchItem(prop, label); tq.type = 'input'; return tq; @@ -78,10 +179,11 @@ export class SearchItem { static select(prop: string, label: string): SearchItem { const tq = new SearchItem(prop, label); tq.type = 'select'; + tq.withOneProps('filterable', true); return tq; } - static date(prop: string, label: string): SearchItem { + static datePicker(prop: string, label: string): SearchItem { const tq = new SearchItem(prop, label); tq.type = 'date-picker'; return tq; @@ -93,8 +195,40 @@ export class SearchItem { return tq; } - withSpan(span: number): SearchItem { - this.span = span; + /** + * 为组件设置一个props属性 + * @param propsKey 属性key + * @param propsValue 属性value + * @returns + */ + withOneProps(propsKey: string, propsValue: any): SearchItem { + if (!this.props) { + this.props = {}; + } + this.props[propsKey] = propsValue; + return this; + } + + /** + * 为组件传递组件自身的props属性 (根据 element plus 官方文档来传递,该属性所有值会透传到组件) + * @returns this + */ + withProps(props: any = {}): SearchItem { + this.props = props; + return this; + } + + /** + * 为组件传递组件自身事件函数 + * @param event 事件名称 + * @param fn 事件处理函数 + * @returns + */ + bindEvent(event: string, eventFn: any): SearchItem { + if (!this.events) { + this.events = {}; + } + this.props[event] = eventFn; return this; } @@ -108,7 +242,38 @@ export class SearchItem { return this; } - setOptions(options: any): SearchItem { + /** + * 设置获取组件options可选项值的api配置 + * @param optionsApi 可选项api配置 + * @returns this + */ + withOptionsApi(optionsApi: OptionsApi): SearchItem { + this.optionsApi = optionsApi; + // 使用api获取组件可选项需要将options转为响应式,否则组件无法响应式获取组件可选项 + this.options = ref(null); + + // 立即执行,则直接调用api获取并赋值options + if (this.optionsApi.immediate) { + this.optionsApi.getOptions().then((res) => { + this.options.value = res; + }); + } else { + // 注册focus事件,在触发focus时赋值options + this.bindEvent('focus', async () => { + if (!toValue(this.options) || !optionsApi.once) { + this.options.value = await this.optionsApi.getOptions(); + } + }); + } + return this; + } + + withSpan(span: number): SearchItem { + this.span = span; + return this; + } + + withOptions(options: any): SearchItem { this.options = options; return this; } diff --git a/mayfly_go_web/src/components/pagetable/PageTable.vue b/mayfly_go_web/src/components/pagetable/PageTable.vue index 7c2f8036..b6a64d4a 100644 --- a/mayfly_go_web/src/components/pagetable/PageTable.vue +++ b/mayfly_go_web/src/components/pagetable/PageTable.vue @@ -2,7 +2,7 @@
- +