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> </div>
<div class="ps-tree-sub-node" v-if="(opts.justOpen || data.isExpand) && data.children && data.children.length"> <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 <node
@onDragstart="(e: INiuTreeKey)=>emit('onDragstart', e)" @onDragstart="(e: INiuTreeKey)=>emit('onDragstart', e)"
@onDragend="(e: INiuTreeKey)=>emit('onDragend', e)" @onDragend="(e: INiuTreeKey)=>emit('onDragend', e)"
@ -61,11 +61,26 @@
<script lang="ts" setup> <script lang="ts" setup>
import node from './node.vue' 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 { isChildOf } from './util'
import renderNode from './renderNode' import renderNode from './renderNode'
import type { INiuTreeData, INiuTreeKey } from './type' import type { INiuTreeData, INiuTreeKey } from './type'
import { ENiuTreeStatus } 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( const props = withDefaults(
defineProps<{ defineProps<{
data: INiuTreeData data: INiuTreeData
@ -85,7 +100,8 @@ watch(()=>props.data.isExpand, ()=>{
}) })
const opts = inject("tree:opts", { const opts = inject("tree:opts", {
justOpen: false justOpen: false,
sort: false,
}) })
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'click', data: INiuTreeData): void (e: 'click', data: INiuTreeData): void
@ -96,8 +112,7 @@ const emit = defineEmits<{
(e: 'onDragover', key: INiuTreeKey): void (e: 'onDragover', key: INiuTreeKey): void
(e: 'onDragleave', key: INiuTreeKey): void (e: 'onDragleave', key: INiuTreeKey): void
}>() }>()
const draggable = opts.sort?readonly(ref(false)):ref(true)
const draggable = ref(true)
const status = ref<ENiuTreeStatus>() const status = ref<ENiuTreeStatus>()
const nodeEL = ref<HTMLDivElement>() const nodeEL = ref<HTMLDivElement>()
provide("draggable", draggable) provide("draggable", draggable)

21
packages/components/tree/tree.vue

@ -1,8 +1,8 @@
<template> <template>
<div class="ps-tree component"> <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" <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 <template
#default="{ data, deep, dataSourceKey, status }: { data: INiuTreeData, deep: number, dataSourceKey: INiuTreeKey, status: ENiuTreeStatus }"> #default="{ data, deep, dataSourceKey, status }: { data: INiuTreeData, deep: number, dataSourceKey: INiuTreeKey, status: ENiuTreeStatus }">
<slot :data="data" :deep="deep" :dataSourceKey="dataSourceKey" :status="status"></slot> <slot :data="data" :deep="deep" :dataSourceKey="dataSourceKey" :status="status"></slot>
@ -25,12 +25,28 @@ import {
removeByKey, removeByKey,
} from './util' } 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( const props = withDefaults(
defineProps<{ defineProps<{
list: INiuTreeData[] list: INiuTreeData[]
justOpen?: boolean justOpen?: boolean
autoExpand?: boolean autoExpand?: boolean
justOpenOne?: boolean justOpenOne?: boolean
sort?: boolean
level?: number level?: number
dropFn?(status: ENiuTreeStatus, data: INiuTreeData, targetData: INiuTreeData): boolean | Promise<boolean> dropFn?(status: ENiuTreeStatus, data: INiuTreeData, targetData: INiuTreeData): boolean | Promise<boolean>
}>(), }>(),
@ -38,6 +54,7 @@ const props = withDefaults(
justOpenOne: false, justOpenOne: false,
justOpen: false, justOpen: false,
autoExpand: false, autoExpand: false,
sort: false,
level: 0, level: 0,
} }
) )

6
packages/components/tree/util.ts

@ -26,6 +26,12 @@ export function convertData<
}) })
return transformData return transformData
} }
export function sort(treeData: INiuTreeData[]) {
// 文件夹排前面
// 按文件名排序
}
export function flatTreeData(treeData: INiuTreeData[]): INiuTreeData[] { export function flatTreeData(treeData: INiuTreeData[]): INiuTreeData[] {
let res: INiuTreeData[] = [] let res: INiuTreeData[] = []
treeData.forEach((data) => { 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([ const list = ref(convertTreeData([
{ {
key: 1, key: 1,
title: "1", title: "1文件夹",
children: [ children: [
{ {
key: 5, key: 5,
title: "5", title: "5文件夹",
children: [] children: []
}, },
] ]
}, },
{ {
key: 2, key: 2,
title: "2" title: "2文件"
}, },
{ {
key: 3, key: 3,
title: "3" title: "3文件"
}, },
])) ]))
function onExpand(node: INiuTreeData) { function onExpand(node: INiuTreeData) {

Loading…
Cancel
Save