import { computed, reactive, Ref } from "vue"; import { PropertyDescribes } from "../html-mount/propertys"; import { installGlobalVar } from "./use-global-vars"; import { inRevise, mergeFuns } from "@/utils/shared"; import { useStore } from "../store"; import { ShapeType } from "../components"; import { ui18n } from "@/lang"; export const useGlobalDescribes = installGlobalVar(() => { const shapesDescribes: Record = reactive({}); const shapesSetCount: Record = {}; const data: Record = reactive({}); return { set(item: { id: string }, descs: PropertyDescribes) { if (item.id in shapesSetCount) { shapesSetCount[item.id]++; } else { shapesSetCount[item.id] = 1; } shapesDescribes[item.id] = descs; data[item.id] = item; }, del(id: string) { if (id in shapesSetCount) { shapesSetCount[id]--; } if (shapesSetCount[id] === 0) { delete shapesDescribes[id]; delete shapesSetCount[id]; delete data[id]; } }, get(id: string) { return ( shapesDescribes[id] && { desc: shapesDescribes[id], data: data[id] } ); }, }; }); export const useComponentsDescribes = (ids: Ref) => { const gdesc = useGlobalDescribes(); const store = useStore(); const excludeKeys = ["length", "name"]; const groups = computed(() => { return ids.value .map((id) => gdesc.get(id)) .filter((item) => !!item) .map((item) => ({ ...item, type: store.getType(item.data.id) })); }); const similars = [ ["rectangle", "circle", "triangle", "polygon"], ] as ShapeType[][]; const shareDescribes = computed(() => { if (groups.value.length === 0) { return {}; } const types = [ ...new Set(groups.value.map((item) => item.type)), ] as ShapeType[]; if (types.length > 1) { if ( !similars.some((similar) => types.every((t) => similar.includes(t))) ) { return; } } const shareDescribes: Record< string, { desc: PropertyDescribes[string][]; data: { id: string }[] } > = {}; const shareKeys: string[] = Object.keys(groups.value[0].desc); for (const item of groups.value) { const keys = Object.keys(item.desc); for (const key of keys) { if (shareKeys.includes(key)) { if (!shareDescribes[key]) { shareDescribes[key] = { desc: [], data: [] }; } else { const temp = shareDescribes[key].desc[0]; if (inRevise(temp.props, item.desc[key].props)) { delete shareDescribes[key]; shareKeys.splice(shareKeys.indexOf(key), 1); continue; } } shareDescribes[key].desc.push(item.desc[key]); shareDescribes[key].data.push(item.data); } } for (let i = 0; i < shareKeys.length; i++) { if (!keys.includes(shareKeys[i])) { delete shareDescribes[shareKeys[i]]; shareKeys.splice(i--, 1); } } } return shareDescribes; }); const stopWatchs: (() => void)[] = []; const mergeDesc = computed(() => { mergeFuns(stopWatchs)(); stopWatchs.length = 0; const mergeDesc: Record< string, PropertyDescribes[string] & { joins: { id: string }[] } > = {}; for (const key in shareDescribes.value) { if (excludeKeys.includes(key)) continue; const { desc: descs, data } = shareDescribes.value[key]; mergeDesc[key] = { ...descs[0], joins: data, }; let value = descs[0].value; let i = 1; for (; i < descs.length; i++) { if (descs[i].value !== value) { break; } } if (i !== descs.length) { mergeDesc[key].label = mergeDesc[key].label + `(${ui18n.t("sys.sys.more")})`; value = undefined; } Object.defineProperty(mergeDesc[key], "value", { get() { return value; }, set(val) { for (const desc of descs) { desc.value = val; } return true; }, }); delete mergeDesc[key].default; } return mergeDesc; }); return mergeDesc; };