weike-multi-cascader
Version:
A multiple cascader component for antd
263 lines (262 loc) • 8.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.conactAllName = exports.findNodeByValue = exports.shallowEqualArray = exports.transformValue = exports.sortByTree = exports.reconcile = exports.sinkTreeState = exports.liftTreeState = exports.removeAllDescendanceValue = exports.matchAllLeafValue = exports.hasParentChecked = exports.hasChildChecked = exports.flattenTree = void 0;
const index_1 = require("../index");
// 平铺树结构,方便根据 value(字符串) 获取到所有的 NodeItem 节点
// 添加 parent 链接到父节点
function flattenTree(root) {
const res = [];
function dfs(nodes, parent = null) {
if (!nodes) {
return;
}
const newChildren = [];
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
const { children } = node;
const newNode = Object.assign(Object.assign({}, node), { parent });
res.push(newNode);
newChildren.push(newNode);
if (children) {
dfs(children, newNode);
}
}
if (parent) {
// eslint-disable-next-line no-param-reassign
parent.children = newChildren;
}
}
dfs(root);
return res;
}
exports.flattenTree = flattenTree;
// 是否有子节点(包括自己)被选中
function hasChildChecked(item, curValue) {
function dfs(node) {
if (!node) {
return false;
}
const { value, children } = node;
if (curValue.includes(value)) {
return true;
}
if (!children) {
return false;
}
return children.some((child) => dfs(child));
}
return dfs(item);
}
exports.hasChildChecked = hasChildChecked;
// 是否有父节点(包括自己)被选中
function hasParentChecked(item, value) {
let tmp = item;
while (tmp) {
if (value.includes(tmp.value)) {
return true;
}
tmp = tmp.parent;
}
return false;
}
exports.hasParentChecked = hasParentChecked;
function matchAllLeafValue(value, roots) {
const res = [];
function dfs(nodes, needed) {
if (!nodes) {
return;
}
nodes.forEach((node) => {
const { value: nodeValue, children } = node;
if (needed || value.includes(nodeValue)) {
if (!children) {
// 叶子节点
res.push(nodeValue);
}
else {
dfs(children, true);
}
}
else {
dfs(children, needed);
}
});
}
dfs(roots, false);
return Array.from(new Set(res));
}
exports.matchAllLeafValue = matchAllLeafValue;
// 删除所有子孙节点的 value, 不包括自己
// 输入可能是 dirty
function removeAllDescendanceValue(root, value) {
const allChildrenValue = [];
function dfs(node) {
if (node.children) {
node.children.forEach((item) => {
allChildrenValue.push(item.value);
dfs(item);
});
}
}
dfs(root);
return value.filter((val) => !allChildrenValue.includes(val));
}
exports.removeAllDescendanceValue = removeAllDescendanceValue;
// 状态提升
function liftTreeState(item, curVal) {
var _a;
const { value } = item;
// 加入当前节点 value
const nextValue = curVal.concat(value);
let last = item;
// eslint-disable-next-line no-constant-condition
while (true) {
// 如果父节点的所有子节点都已经 checked, 添加该节点 value,继续尝试提升
if ((_a = last === null || last === void 0 ? void 0 : last.parent) === null || _a === void 0 ? void 0 : _a.children.every((child) => nextValue.includes(child.value))) {
nextValue.push(last.parent.value);
last = last.parent;
}
else {
break;
}
}
// 移除最后一个满足 checked 的父节点的所有子孙节点 value
return removeAllDescendanceValue(last, nextValue);
}
exports.liftTreeState = liftTreeState;
// 状态下沉
function sinkTreeState(root, value) {
const parentValues = [];
const subTreeValues = [];
function getCheckedParent(node) {
if (!node) {
return null;
}
parentValues.push(node.value);
if (value.includes(node.value)) {
return node;
}
return getCheckedParent(node.parent);
}
const checkedParent = getCheckedParent(root);
if (!checkedParent) {
return value;
}
function dfs(node) {
if (!node.children || node.value === root.value) {
return;
}
node.children.forEach((item) => {
if (item.value !== root.value) {
if (parentValues.includes(item.value)) {
dfs(item);
}
else {
subTreeValues.push(item.value);
}
}
});
}
dfs(checkedParent);
// 替换 checkedParent 下子树的值
const nextValue = removeAllDescendanceValue(checkedParent, value).filter((item) => item !== checkedParent.value);
return Array.from(new Set(nextValue.concat(subTreeValues)));
}
exports.sinkTreeState = sinkTreeState;
// checked, unchecked 时重新计算
function reconcile(item, checked, value) {
if (checked) {
// 如果已经有父节点被 checked, 再进行 checked 没有意义,直接忽略
// 主要是用在避免初始化时传入的 value 结构不合理
if (hasParentChecked(item, value)) {
return value;
}
return liftTreeState(item, value);
}
return sinkTreeState(item, value);
}
exports.reconcile = reconcile;
// 按树的 dfs 前序排
function sortByTree(value, flattenData) {
// 按照树结构前顺排序
const map = flattenData.reduce((cur, node, index) => {
cur[node.value] = index;
return cur;
}, {});
return value.sort((a, b) => map[a] - map[b] || 0);
}
exports.sortByTree = sortByTree;
// 过滤非法数据,排序
function transformValue(value, flattenData) {
let nextValue = [];
if (value.some((v) => v === index_1.All)) {
return [index_1.All];
}
for (let i = 0; i < value.length; i++) {
const node = flattenData.find((item) => item.value === value[i]);
if (node) {
nextValue = reconcile(node, true, nextValue);
}
else {
nextValue.push(value[i]);
}
}
return sortByTree(nextValue, flattenData);
}
exports.transformValue = transformValue;
function shallowEqualArray(arrA, arrB) {
if (arrA === arrB) {
return true;
}
if (!arrA || !arrB) {
return false;
}
var len = arrA.length;
if (arrB.length !== len) {
return false;
}
for (var i = 0; i < len; i++) {
if (arrA[i] !== arrB[i]) {
return false;
}
}
return true;
}
exports.shallowEqualArray = shallowEqualArray;
// 通过 value 查找树节点
function findNodeByValue(value, tree) {
function findParent(nodes) {
if (!nodes) {
return undefined;
}
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (value === node.value) {
return node;
}
if (node.children) {
const foundInChildren = findParent(node.children);
if (foundInChildren) {
return foundInChildren;
}
}
}
}
return findParent(tree);
}
exports.findNodeByValue = findNodeByValue;
function conactAllName(initData, init, flag) {
const newData = Object.assign({}, initData);
if (newData.parent && newData.parent.title !== 'All') {
const title = init ? `${newData.title}-${init}` : newData.title;
newData.title = conactAllName(newData.parent, title, flag);
return newData.title;
}
else if (newData.parent && newData.parent.title === 'All' && flag) {
return init ? `${newData.title}-${init}-全部` : `${newData.title}-全部`;
}
else {
return init ? `${newData.title}-${init}` : newData.title;
}
}
exports.conactAllName = conactAllName;