From 669fe3fe30832072fc9f08488981029c20081108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A5=9E=E4=BB=99=E9=83=BD=E6=B2=A1=E7=94=A8?= <615206459@qq.com> Date: Thu, 20 Feb 2025 10:51:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/base/views/menu/index.vue | 16 +++--- src/modules/dict/views/list.vue | 23 ++++---- src/plugins/crud/components/select/index.tsx | 60 ++++++++++++++------ src/plugins/crud/plugins/table/toTree.ts | 58 +++++++++++++------ src/plugins/view/components/group.vue | 11 +--- 5 files changed, 101 insertions(+), 67 deletions(-) diff --git a/src/modules/base/views/menu/index.vue b/src/modules/base/views/menu/index.vue index 4dafb7d..597a004 100644 --- a/src/modules/base/views/menu/index.vue +++ b/src/modules/base/views/menu/index.vue @@ -232,13 +232,7 @@ const Table = useTable({ ], plugins: [ Plugins.Table.toTree({ - lazy: true, - async onRefresh() { - return service.base.sys.menu.list().then(res => { - menu.get(); - return res; - }); - } + lazy: true }) ] }); @@ -366,7 +360,13 @@ const Upsert = useUpsert({ // cl-crud const Crud = useCrud( { - service: service.base.sys.menu + service: service.base.sys.menu, + onRefresh(params, { render }) { + service.base.sys.menu.list(params).then(res => { + menu.get(); + render(res); + }); + } }, app => { app.refresh({ diff --git a/src/modules/dict/views/list.vue b/src/modules/dict/views/list.vue index 28fb789..6d2859b 100644 --- a/src/modules/dict/views/list.vue +++ b/src/modules/dict/views/list.vue @@ -245,23 +245,20 @@ const Table = useTable({ ] } ], - plugins: [ - Plugins.Table.toTree({ - async onRefresh(params) { - return service.dict.info.list(params).then(res => { - // 刷新字典 - dict.refresh([ViewGroup.value?.selected?.key]); - - return res; - }); - } - }) - ] + plugins: [Plugins.Table.toTree()] }); // cl-crud const Crud = useCrud({ - service: service.dict.info + service: service.dict.info, + onRefresh(params, { render }) { + service.dict.info.list(params).then(res => { + render(res); + + // 刷新字典 + dict.refresh([ViewGroup.value?.selected?.key]); + }); + } }); // 刷新 diff --git a/src/plugins/crud/components/select/index.tsx b/src/plugins/crud/components/select/index.tsx index 2e1555d..3c04b8f 100644 --- a/src/plugins/crud/components/select/index.tsx +++ b/src/plugins/crud/components/select/index.tsx @@ -1,6 +1,16 @@ -import { useCrud, useForm, } from '@cool-vue/crud'; +import { useCrud, useForm } from '@cool-vue/crud'; import { cloneDeep, isEmpty, isFunction, isString } from 'lodash-es'; -import { computed, defineComponent, onMounted, type PropType, ref, type Ref, toValue, useModel } from 'vue'; +import { + computed, + defineComponent, + onActivated, + onMounted, + type PropType, + ref, + type Ref, + toValue, + useModel +} from 'vue'; import { deepTree, parsePx } from '/@/cool/utils'; import { useI18n } from 'vue-i18n'; import { useCool } from '/@/cool'; @@ -25,8 +35,6 @@ export default defineComponent({ type: String, default: 'value' }, - // 请求接口,如果是字符串,则使用 crud 下的方法 - api: [String, Function], width: [String, Number], // 是否树形 @@ -39,20 +47,28 @@ export default defineComponent({ defaultExpandAll: Boolean, // 顶级标签 topLabel: String, - // 是否选择当前表格数据,如果是,则不能选择自身及其下级 current: Boolean, + + // 请求接口,如果是字符串,则使用 crud 下的方法 + api: [String, Function], + // 值变化刷新 refreshOnChange: { type: Boolean, default: true + }, + // 是否在激活时刷新 + refreshOnActivated: { + type: Boolean, + default: true } }, emits: ['update:modelValue', 'change'], setup(props, { emit, expose }) { - const { refs, setRefs } = useCool(); + const { refs, setRefs, route } = useCool(); const { t } = useI18n(); // cl-crud @@ -65,14 +81,14 @@ export default defineComponent({ const isSearch = computed(() => !Form.value || Form.value?.name === 'search'); // 选项 - const options = ref() + const options = ref(); // 选中值 const value = useModel(props, 'modelValue'); // 列表 const list = computed(() => { - let data: any[] = [] + let data: any[] = []; if (props.current) { data = cloneDeep(toValue(Crud.value?.['cl-table']?.data)); @@ -95,7 +111,6 @@ export default defineComponent({ } deep({ children: data }, false); - } else { data = toValue(options.value || props.options) || []; } @@ -108,10 +123,10 @@ export default defineComponent({ [props.valueKey]: 0, children: data } - ] + ]; } - return data + return data; }); // 获取值 @@ -164,26 +179,36 @@ export default defineComponent({ // 获取选项数据 function refresh() { - let req: Promise | null = null + let req: Promise | null = null; if (isString(props.api)) { - req = Crud.value?.service[props.api]() + req = Crud.value?.service[props.api](); } if (isFunction(props.api)) { - req = props.api() + req = props.api(); } if (req) { req.then(res => { options.value = deepTree(res); - }) + }); } } onMounted(() => { - refresh() - }) + if (props.api) { + refresh(); + + onActivated(() => { + if (props.refreshOnActivated) { + if (!Form.value || Form.value?.name == 'search') { + refresh(); + } + } + }); + } + }); expose({ focus @@ -198,7 +223,6 @@ export default defineComponent({ // 占位符 const placeholder = isSearch.value ? t('全部') : t('请选择'); - // 树形下拉框 const TreeSelect = ( { - const req = options.onRefresh - ? options.onRefresh(params) - : Crud.value?.service.list(params); + // 原 cl-crud 的 onRefresh + const onRefresh = Crud.value.config.onRefresh; - if (req) { - req.then((list) => { - render(onData(list, params.sort)); - }); - } + // 重写 onRefresh + Crud.value.config.onRefresh = async ( + params: Parameters[0], + { render, next, done }: Parameters[1] + ) => { + const req: Promise = new Promise(resolve => { + if (onRefresh) { + const _next = async (params?: any) => { + const res = await next(params); + resolve(res.list); + }; + + const _render = (list: any[]) => { + resolve(list); + }; + + onRefresh(params, { render: _render, next: _next, done }); + } else { + resolve( + options.onRefresh + ? options.onRefresh(params) + : Crud.value?.service[Crud.value.dict.api.list](params) + ); + } + }); + + const list = await req; + + render(onData(list, params.sort)); }; } // 数据处理 - const onData = (list: Item[], sort: "desc" | "asc") => { + const onData = (list: Item[], sort: 'desc' | 'asc') => { const data = deepTree(list, sort); // 递归处理 const deep = (arr: Item[]) => { - arr.forEach((e) => { + arr.forEach(e => { const nodes: { [key: number]: Item[] } = exposed.Table.value?.store.states.lazyTreeNodeMap.value || {}; @@ -69,10 +91,10 @@ export function toTree( // 层级参数 exposed.config.props.lazy = true; - exposed.config.props["row-key"] = "id"; - exposed.config.props["tree-props"] = { - children: "children", - hasChildren: "hasChildren" + exposed.config.props['row-key'] = 'id'; + exposed.config.props['tree-props'] = { + children: 'children', + hasChildren: 'hasChildren' }; // 层级事件 diff --git a/src/plugins/view/components/group.vue b/src/plugins/view/components/group.vue index 7ce5d60..73cca24 100644 --- a/src/plugins/view/components/group.vue +++ b/src/plugins/view/components/group.vue @@ -173,26 +173,17 @@ defineOptions({ import { useI18n } from 'vue-i18n'; import { inject, nextTick, onMounted, reactive, ref, useSlots } from 'vue'; -import { - ArrowLeft, - ArrowRight, - ArrowRightBold, - Refresh as IconRefresh, - Plus, - Search -} from '@element-plus/icons-vue'; +import { Search } from '@element-plus/icons-vue'; import { useBrowser, useCool } from '/@/cool'; import { ContextMenu, useForm } from '@cool-vue/crud'; import { ElMessage, ElMessageBox } from 'element-plus'; import { assign, isEmpty, merge } from 'lodash-es'; import { deepTree } from '/@/cool/utils'; -import { useClipboard } from '@vueuse/core'; const { browser, onScreenChange } = useBrowser(); const slots = useSlots(); const Form = useForm(); const { refs, setRefs } = useCool(); -const { copy } = useClipboard(); const { t } = useI18n(); // 配置