UNPKG

@ithinkdt/naive

Version:

iThinkDT Naive UI

173 lines (151 loc) 4.89 kB
import { ref, isRef, computed, watch, nextTick } from 'vue' import { NFlex, NButton } from 'ithinkdt-ui' import { walkTree } from '@ithinkdt/common' import { useModal } from '@ithinkdt/core' import { DtModuleTree } from './Tree' export function useModuleSelect( modules, { title, onRefresh, treeProps = {}, modalProps = {}, loading = ref(false), includeParents }, ) { const _selection = ref([]) const outIdSets = [] const modulePathsMap = new Map() const moduleIdSet = new Set() let init const $init = new Promise((resolve) => (init = resolve)) watch( modules, (tree) => { modulePathsMap.clear() moduleIdSet.clear() if (!Array.isArray(tree)) return if (tree.length > 0) { nextTick(init) walkTree( tree, (it, _i, parents) => { moduleIdSet.add(it.id) if (!it.children?.length) { modulePathsMap.set(it.id, [...parents.map((it) => it.id), it.id]) } }, { parentPaths: true }, ) } }, { immediate: true }, ) const renderModuleSelect = (showSubmitBtn = false, submiting, onSubmit) => { return ( <DtModuleTree data={modules.value} treeProps={treeProps} loading={loading.value} selectable showSubmitBtn={showSubmitBtn} submiting={submiting} v-model:selection={_selection.value} onSubmit={() => onSubmit(getIds())} onRefresh={onRefresh} /> ) } const saving = ref(false) let resolve, reject const ret = useModal({ type: 'drawer', width: 520, ...modalProps, title, closable: computed(() => !saving.value), onClose: () => reject(), content: { default: () => <div style="padding-left: 16px">{renderModuleSelect(false)}</div>, footer: () => ( <NFlex> <NButton onClick={() => reject()} disabled={saving.value || loading.value}> 取 消 </NButton> <NButton type="primary" onClick={() => resolve()} loading={saving.value || loading.value}> 保 存 </NButton> </NFlex> ), }, }) const setSelection = async (selection) => { outIdSets.length = 0 _selection.value = [] if (selection.length === 0) { return } await $init const data = [] for (const it of selection) { if (modulePathsMap.has(it)) data.push(it) if (!moduleIdSet.has(it)) { outIdSets.push(it) } } _selection.value = data } let last const handleSelection = async (selection) => { last?.() if (isRef(selection)) { last = watch( selection, (data) => { setSelection(Array.isArray(data) ? [...data] : []) }, { immediate: true }, ) } else { if (selection instanceof Promise) { selection = await selection } setSelection(Array.isArray(selection) ? [...selection] : []) } } const getIds = () => { let ids = [..._selection.value] if (includeParents) { ids = [ ...new Set( ids.flatMap((key) => { return modulePathsMap.get(key) ?? [] }), ), ].filter((it) => !it.startsWith('app-')) } return [...ids, ...outIdSets] } return { open: async (selection, then) => { ret.show() await handleSelection(selection) return new Promise((_resolve, _reject) => { resolve = _resolve reject = _reject }) .then(() => { saving.value = true Promise.resolve(then(getIds())) .then((v) => { if (false !== v) ret.close() }) .finally(() => { saving.value = false }) }) .catch(() => { ret.close() }) }, close: ret.close, modulePathsMap, renderModuleSelect, setSelection: handleSelection, getSelection: getIds, } }