This commit is contained in:
神仙都没用 2025-02-20 10:51:34 +08:00
parent 6e38a2bbb7
commit 669fe3fe30
5 changed files with 101 additions and 67 deletions

View File

@ -232,13 +232,7 @@ const Table = useTable({
], ],
plugins: [ plugins: [
Plugins.Table.toTree({ Plugins.Table.toTree({
lazy: true, lazy: true
async onRefresh() {
return service.base.sys.menu.list().then(res => {
menu.get();
return res;
});
}
}) })
] ]
}); });
@ -366,7 +360,13 @@ const Upsert = useUpsert({
// cl-crud // cl-crud
const Crud = useCrud( 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 => {
app.refresh({ app.refresh({

View File

@ -245,23 +245,20 @@ const Table = useTable({
] ]
} }
], ],
plugins: [ plugins: [Plugins.Table.toTree()]
Plugins.Table.toTree({
async onRefresh(params) {
return service.dict.info.list(params).then(res => {
//
dict.refresh([ViewGroup.value?.selected?.key]);
return res;
});
}
})
]
}); });
// cl-crud // cl-crud
const Crud = useCrud({ 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]);
});
}
}); });
// //

View File

@ -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 { 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 { deepTree, parsePx } from '/@/cool/utils';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useCool } from '/@/cool'; import { useCool } from '/@/cool';
@ -25,8 +35,6 @@ export default defineComponent({
type: String, type: String,
default: 'value' default: 'value'
}, },
// 请求接口,如果是字符串,则使用 crud 下的方法
api: [String, Function],
width: [String, Number], width: [String, Number],
// 是否树形 // 是否树形
@ -39,20 +47,28 @@ export default defineComponent({
defaultExpandAll: Boolean, defaultExpandAll: Boolean,
// 顶级标签 // 顶级标签
topLabel: String, topLabel: String,
// 是否选择当前表格数据,如果是,则不能选择自身及其下级 // 是否选择当前表格数据,如果是,则不能选择自身及其下级
current: Boolean, current: Boolean,
// 请求接口,如果是字符串,则使用 crud 下的方法
api: [String, Function],
// 值变化刷新 // 值变化刷新
refreshOnChange: { refreshOnChange: {
type: Boolean, type: Boolean,
default: true default: true
},
// 是否在激活时刷新
refreshOnActivated: {
type: Boolean,
default: true
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup(props, { emit, expose }) { setup(props, { emit, expose }) {
const { refs, setRefs } = useCool(); const { refs, setRefs, route } = useCool();
const { t } = useI18n(); const { t } = useI18n();
// cl-crud // cl-crud
@ -65,14 +81,14 @@ export default defineComponent({
const isSearch = computed(() => !Form.value || Form.value?.name === 'search'); const isSearch = computed(() => !Form.value || Form.value?.name === 'search');
// 选项 // 选项
const options = ref<Dict.Item[]>() const options = ref<Dict.Item[]>();
// 选中值 // 选中值
const value = useModel(props, 'modelValue'); const value = useModel(props, 'modelValue');
// 列表 // 列表
const list = computed(() => { const list = computed(() => {
let data: any[] = [] let data: any[] = [];
if (props.current) { if (props.current) {
data = cloneDeep(toValue(Crud.value?.['cl-table']?.data)); data = cloneDeep(toValue(Crud.value?.['cl-table']?.data));
@ -95,7 +111,6 @@ export default defineComponent({
} }
deep({ children: data }, false); deep({ children: data }, false);
} else { } else {
data = toValue(options.value || props.options) || []; data = toValue(options.value || props.options) || [];
} }
@ -108,10 +123,10 @@ export default defineComponent({
[props.valueKey]: 0, [props.valueKey]: 0,
children: data children: data
} }
] ];
} }
return data return data;
}); });
// 获取值 // 获取值
@ -164,26 +179,36 @@ export default defineComponent({
// 获取选项数据 // 获取选项数据
function refresh() { function refresh() {
let req: Promise<any> | null = null let req: Promise<any> | null = null;
if (isString(props.api)) { if (isString(props.api)) {
req = Crud.value?.service[props.api]() req = Crud.value?.service[props.api]();
} }
if (isFunction(props.api)) { if (isFunction(props.api)) {
req = props.api() req = props.api();
} }
if (req) { if (req) {
req.then(res => { req.then(res => {
options.value = deepTree(res); options.value = deepTree(res);
}) });
} }
} }
onMounted(() => { onMounted(() => {
refresh() if (props.api) {
}) refresh();
onActivated(() => {
if (props.refreshOnActivated) {
if (!Form.value || Form.value?.name == 'search') {
refresh();
}
}
});
}
});
expose({ expose({
focus focus
@ -198,7 +223,6 @@ export default defineComponent({
// 占位符 // 占位符
const placeholder = isSearch.value ? t('全部') : t('请选择'); const placeholder = isSearch.value ? t('全部') : t('请选择');
// 树形下拉框 // 树形下拉框
const TreeSelect = ( const TreeSelect = (
<el-tree-select <el-tree-select

View File

@ -1,6 +1,6 @@
import { useCrud } from "@cool-vue/crud"; import { useCrud } from '@cool-vue/crud';
import { deepTree } from "/@/cool/utils"; import { deepTree } from '/@/cool/utils';
import { isEmpty } from "lodash-es"; import { isEmpty } from 'lodash-es';
interface Item extends Eps.BaseSysMenuEntity { interface Item extends Eps.BaseSysMenuEntity {
children?: Item[]; children?: Item[];
@ -22,26 +22,48 @@ export function toTree(
// 设置刷新方法 // 设置刷新方法
if (Crud.value) { if (Crud.value) {
Crud.value.config.onRefresh = (params: any, { render }: any) => { // 原 cl-crud 的 onRefresh
const req = options.onRefresh const onRefresh = Crud.value.config.onRefresh;
? options.onRefresh(params)
: Crud.value?.service.list(params);
if (req) { // 重写 onRefresh
req.then((list) => { Crud.value.config.onRefresh = async (
render(onData(list, params.sort)); params: Parameters<ClCrud.Config['onRefresh']>[0],
}); { render, next, done }: Parameters<ClCrud.Config['onRefresh']>[1]
} ) => {
const req: Promise<any[]> = 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 data = deepTree(list, sort);
// 递归处理 // 递归处理
const deep = (arr: Item[]) => { const deep = (arr: Item[]) => {
arr.forEach((e) => { arr.forEach(e => {
const nodes: { [key: number]: Item[] } = const nodes: { [key: number]: Item[] } =
exposed.Table.value?.store.states.lazyTreeNodeMap.value || {}; exposed.Table.value?.store.states.lazyTreeNodeMap.value || {};
@ -69,10 +91,10 @@ export function toTree(
// 层级参数 // 层级参数
exposed.config.props.lazy = true; exposed.config.props.lazy = true;
exposed.config.props["row-key"] = "id"; exposed.config.props['row-key'] = 'id';
exposed.config.props["tree-props"] = { exposed.config.props['tree-props'] = {
children: "children", children: 'children',
hasChildren: "hasChildren" hasChildren: 'hasChildren'
}; };
// 层级事件 // 层级事件

View File

@ -173,26 +173,17 @@ defineOptions({
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { inject, nextTick, onMounted, reactive, ref, useSlots } from 'vue'; import { inject, nextTick, onMounted, reactive, ref, useSlots } from 'vue';
import { import { Search } from '@element-plus/icons-vue';
ArrowLeft,
ArrowRight,
ArrowRightBold,
Refresh as IconRefresh,
Plus,
Search
} from '@element-plus/icons-vue';
import { useBrowser, useCool } from '/@/cool'; import { useBrowser, useCool } from '/@/cool';
import { ContextMenu, useForm } from '@cool-vue/crud'; import { ContextMenu, useForm } from '@cool-vue/crud';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { assign, isEmpty, merge } from 'lodash-es'; import { assign, isEmpty, merge } from 'lodash-es';
import { deepTree } from '/@/cool/utils'; import { deepTree } from '/@/cool/utils';
import { useClipboard } from '@vueuse/core';
const { browser, onScreenChange } = useBrowser(); const { browser, onScreenChange } = useBrowser();
const slots = useSlots(); const slots = useSlots();
const Form = useForm(); const Form = useForm();
const { refs, setRefs } = useCool(); const { refs, setRefs } = useCool();
const { copy } = useClipboard();
const { t } = useI18n(); const { t } = useI18n();
// //