Browse Source

排序功能

master
npmrun 3 years ago
parent
commit
7310664f7d
  1. 92
      packages/components/tree/better-directory-sort.ts
  2. 25
      packages/components/tree/node.vue
  3. 21
      packages/components/tree/tree.vue
  4. 6
      packages/components/tree/util.ts
  5. 8
      packages/playground/src/dev/tree.vue

92
packages/components/tree/better-directory-sort.ts

@ -0,0 +1,92 @@
function defaultComparator(a, b) {
return a.localeCompare(b, undefined, {
numeric: true,
sensitivity: "base",
});
}
function compareSafe(a, b, comparator) {
if (a == null && b == null) return 0;
if (a != null && b == null) return 1;
if (b != null && a == null) return -1;
return comparator(a, b);
}
type Comparator<T> = (a: T, b: T) => number;
type Entity = {
name: string;
isDirectory: boolean;
};
type Opts = {
comparator?: Comparator<string>;
kinds?: boolean;
};
function createBetterDirectorySort(opts: Opts = {}): Comparator<Entity> {
let comparator = opts.comparator || defaultComparator;
let kinds = opts.kinds || false;
return function betterDirectorySort(a, b) {
// directories should be placed before files
if (a.isDirectory && !b.isDirectory) return -1;
if (b.isDirectory && !a.isDirectory) return 1;
// dotsfiles should be placed before non-dotfiles
let aDot = a.name[0] === ".";
let bDot = b.name[0] === ".";
if (aDot && !bDot) return -1;
if (bDot && !aDot) return 1;
// names will be sorted in period-delimitted parts
let aParts = a.name.split(".");
let bParts = b.name.split(".");
// the first part of the name is the most important part
let aName = aParts.shift();
let bName = bParts.shift();
// final extension is only used when all else is the same
let aExt = aParts.pop();
let bExt = bParts.pop();
let comparedName = compareSafe(aName, bName, comparator);
if (comparedName !== 0) return comparedName;
// "kind" extension is used above other parts
if (kinds) {
let aKind = aParts.pop();
let bKind = bParts.pop();
let comparedKind = compareSafe(aKind, bKind, comparator);
if (comparedKind !== 0) return comparedKind;
}
// loop with an decrementing index
let i = 0;
while (true) {
let aPart = aParts[i];
let bPart = bParts[i];
// if there's no more parts on either name, break
if (aPart == null && bPart == null) break;
// compare the current part, if its the same, continue comparing parts
let comparedPart = compareSafe(aPart, bPart, comparator);
if (comparedPart !== 0) return comparedPart;
i++;
}
// compare the last extension as a final tie-breaker
return compareSafe(aExt, bExt, comparator);
};
}
const betterDirectorySort = createBetterDirectorySort();
// @ts-ignore
betterDirectorySort.custom = createBetterDirectorySort;
// @ts-ignore
betterDirectorySort.defaultComparator = defaultComparator;
export { betterDirectorySort };

25
packages/components/tree/node.vue

@ -33,7 +33,7 @@
]"></div>
</div>
<div class="ps-tree-sub-node" v-if="(opts.justOpen || data.isExpand) && data.children && data.children.length">
<template v-for="(item, index) in data.children" :key="item.key">
<template v-for="(item, index) in sortedList" :key="item.key">
<node
@onDragstart="(e: INiuTreeKey)=>emit('onDragstart', e)"
@onDragend="(e: INiuTreeKey)=>emit('onDragend', e)"
@ -61,11 +61,26 @@
<script lang="ts" setup>
import node from './node.vue'
import { inject, ref, provide, renderSlot, useSlots, watch } from 'vue'
import { inject, ref, provide, renderSlot, useSlots, watch, readonly, computed } from 'vue'
import { isChildOf } from './util'
import renderNode from './renderNode'
import type { INiuTreeData, INiuTreeKey } from './type'
import { ENiuTreeStatus } from './type';
import {betterDirectorySort} from "./better-directory-sort"
const sortedList = computed(()=>{
if(opts.sort){
return props.data.children.sort((a, b) => {
return betterDirectorySort(
{ name: a.title, isDirectory: a.isFolder },
{ name: b.title, isDirectory: b.isFolder },
);
});
}
return props.data.children
})
const props = withDefaults(
defineProps<{
data: INiuTreeData
@ -85,7 +100,8 @@ watch(()=>props.data.isExpand, ()=>{
})
const opts = inject("tree:opts", {
justOpen: false
justOpen: false,
sort: false,
})
const emit = defineEmits<{
(e: 'click', data: INiuTreeData): void
@ -96,8 +112,7 @@ const emit = defineEmits<{
(e: 'onDragover', key: INiuTreeKey): void
(e: 'onDragleave', key: INiuTreeKey): void
}>()
const draggable = ref(true)
const draggable = opts.sort?readonly(ref(false)):ref(true)
const status = ref<ENiuTreeStatus>()
const nodeEL = ref<HTMLDivElement>()
provide("draggable", draggable)

21
packages/components/tree/tree.vue

@ -1,8 +1,8 @@
<template>
<div class="ps-tree component">
<template v-for="(item, index) in list" :key="item.key">
<template v-for="(item, index) in sortedList" :key="item.key">
<node @onDragstart="onDragstart" @expand="onExpand" @onDragEnd="onDragEnd" @onDrop="onDrop" :data-source-key="dataSourceKey"
:data="item" :list="list" :level="level" @click="(item) => clickNode(item)">
:data="item" :list="sortedList" :level="level" @click="(item) => clickNode(item)">
<template
#default="{ data, deep, dataSourceKey, status }: { data: INiuTreeData, deep: number, dataSourceKey: INiuTreeKey, status: ENiuTreeStatus }">
<slot :data="data" :deep="deep" :dataSourceKey="dataSourceKey" :status="status"></slot>
@ -25,12 +25,28 @@ import {
removeByKey,
} from './util'
import {betterDirectorySort} from "./better-directory-sort"
import { computed } from "@vue/reactivity"
const sortedList = computed(()=>{
if(props.sort){
return props.list.sort((a, b) => {
return betterDirectorySort(
{ name: a.title, isDirectory: a.isFolder },
{ name: b.title, isDirectory: b.isFolder },
);
});
}
return props.list
})
const props = withDefaults(
defineProps<{
list: INiuTreeData[]
justOpen?: boolean
autoExpand?: boolean
justOpenOne?: boolean
sort?: boolean
level?: number
dropFn?(status: ENiuTreeStatus, data: INiuTreeData, targetData: INiuTreeData): boolean | Promise<boolean>
}>(),
@ -38,6 +54,7 @@ const props = withDefaults(
justOpenOne: false,
justOpen: false,
autoExpand: false,
sort: false,
level: 0,
}
)

6
packages/components/tree/util.ts

@ -26,6 +26,12 @@ export function convertData<
})
return transformData
}
export function sort(treeData: INiuTreeData[]) {
// 文件夹排前面
// 按文件名排序
}
export function flatTreeData(treeData: INiuTreeData[]): INiuTreeData[] {
let res: INiuTreeData[] = []
treeData.forEach((data) => {

8
packages/playground/src/dev/tree.vue

@ -6,22 +6,22 @@ import "@princess-ui/theme-chalk/dist/ps-tree.css"
const list = ref(convertTreeData([
{
key: 1,
title: "1",
title: "1文件夹",
children: [
{
key: 5,
title: "5",
title: "5文件夹",
children: []
},
]
},
{
key: 2,
title: "2"
title: "2文件"
},
{
key: 3,
title: "3"
title: "3文件"
},
]))
function onExpand(node: INiuTreeData) {

Loading…
Cancel
Save