Skip to content

Commit

Permalink
Add tree structure function.
Browse files Browse the repository at this point in the history
  • Loading branch information
gudaoxuri committed Dec 6, 2023
1 parent 3a159a9 commit 5e0643f
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 131 deletions.
37 changes: 19 additions & 18 deletions docs/TableDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import type { TableCellDictItem, TableColumnProps, TableDataSliceReq, TableLayou
import { AggregateKind, DATA_DICT_POSTFIX, DataKind, LayoutKind } from '../src/components/props'
import { getRandomInt } from '../src/utils/basic'
const columns = [{ name: 'no', dataKind: DataKind.NUMBER, dataEditable: false }, { name: 'name', useDict: true, dictEditable: true }, { name: 'phone' }, { name: 'stats', useDict: true, dictEditable: true, multiValue: true }, { name: 'addr' }, { name: 'time', dataKind: DataKind.DATETIME }]
const columns = [{ name: 'no', dataKind: DataKind.NUMBER, dataEditable: false }, { name: 'pno', dataKind: DataKind.NUMBER, dataEditable: false }, { name: 'name', useDict: true, dictEditable: true }, { name: 'phone' }, { name: 'stats', useDict: true, dictEditable: true, multiValue: true }, { name: 'addr' }, { name: 'time', dataKind: DataKind.DATETIME }]
const layouts = [{
id: 'hi',
title: 'HI',
layoutKind: LayoutKind.LIST,
columns: [{
name: 'no',
width: 80,
}, {
name: 'name',
}, {
name: 'stats',
}, {
name: 'no',
width: 80,
}, {
name: 'addr',
}, {
Expand Down Expand Up @@ -51,10 +51,11 @@ const events = {
resolve(attachDict(data.map((d) => {
d.no = getRandomInt(1000, 2000)
d.name = 'xy'
d.stats = ['init']
d.phone = '!Phone2'
d.addr = '!Addr2'
d.time = '2023-10-24'
d.stats = []
d.phone = ''
d.addr = ''
d.time = ''
d.pno = data[0].pno
return d
})))
}
Expand Down Expand Up @@ -246,26 +247,26 @@ const resp1 = {
const data2 = [
{ no: 1, name: 'xh', stats: ['init'], phone: 'Phone1', addr: 'Addr1 Addr1 Addr1 Addr1 Addr1 Addr1', time: '2023-10-23' },
{ no: 2, name: 'xh', stats: ['init'], phone: 'Phone2', addr: 'Addr2', time: '2023-10-24' },
{ no: 3, name: 'xh', stats: ['progress', 'risk'], phone: 'Phone3', addr: 'Addr3', time: '2023-10-25' },
{ no: 4, name: 'xh', stats: ['init'], phone: 'Phone4', addr: 'Addr4', time: '2023-10-26' },
{ no: 5, name: 'xh', stats: ['init'], phone: 'Phone5', addr: 'Addr5', time: '2023-10-27' },
{ no: 3, pno: 1, name: 'xh', stats: ['progress', 'risk'], phone: 'Phone3', addr: 'Addr3', time: '2023-10-25' },
{ no: 4, pno: 1, name: 'xh', stats: ['init'], phone: 'Phone4', addr: 'Addr4', time: '2023-10-26' },
{ no: 5, pno: 1, name: 'xh', stats: ['init'], phone: 'Phone5', addr: 'Addr5', time: '2023-10-27' },
{ no: 6, name: 'xh', stats: ['init'], phone: 'Phone6', addr: 'Addr6', time: '2023-10-28' },
{ no: 7, name: 'xh', stats: ['init'], phone: 'Phone7', addr: 'Addr7', time: '2023-10-29' },
{ no: 8, name: 'xh', stats: ['init'], phone: 'Phone8', addr: 'Addr8', time: '2023-10-30' },
{ no: 9, name: 'xh', stats: ['init'], phone: 'Phone9', addr: 'Addr9', time: '2023-10-31' },
{ no: 10, name: 'xh', stats: ['close'], phone: 'Phone10', addr: 'Addr10', time: '2023-11-1' },
{ no: 8, pno: 4, name: 'xh', stats: ['init'], phone: 'Phone8', addr: 'Addr8', time: '2023-10-30' },
{ no: 9, pno: 4, name: 'xh', stats: ['init'], phone: 'Phone9', addr: 'Addr9', time: '2023-10-31' },
{ no: 10, pno: 8, name: 'xh', stats: ['close'], phone: 'Phone10', addr: 'Addr10', time: '2023-11-1' },
{ no: 11, name: 'xh', stats: ['close'], phone: 'Phone11', addr: 'Addr11', time: '2023-11-2' },
{ no: 12, name: 'xh', stats: ['close'], phone: 'Phone12', addr: 'Addr12', time: '2023-11-3' },
{ no: 13, name: 'xh', stats: ['close'], phone: 'Phone13', addr: 'Addr13', time: '2023-11-4' },
{ no: 14, name: 'xh', stats: ['close'], phone: 'Phone14', addr: 'Addr14', time: '2023-11-5' },
{ no: 15, name: 'xh', stats: ['close'], phone: 'Phone15', addr: 'Addr15', time: '2023-11-6' },
{ no: 16, name: 'xh', stats: ['close'], phone: 'Phone16', addr: 'Addr16', time: '2023-11-7' },
{ no: 16, pno: 8, name: 'xh', stats: ['close'], phone: 'Phone16', addr: 'Addr16', time: '2023-11-7' },
{ no: 17, name: 'xh', stats: ['finish'], phone: 'Phone17', addr: 'Addr17', time: '2023-11-8' },
{ no: 18, name: 'xh', stats: ['finish'], phone: 'Phone18', addr: 'Addr18', time: '2023-11-9' },
{ no: 19, name: 'xh', stats: ['finish'], phone: 'Phone19', addr: 'Addr19', time: '2023-11-10' },
{ no: 20, name: 'xh', stats: ['finish'], phone: 'Phone20', addr: 'Addr20', time: '2023-11-11' },
{ no: 21, name: 'xh', stats: ['finish'], phone: 'Phone21', addr: 'Addr21', time: '2023-11-12' },
{ no: 22, name: 'xh', stats: ['finish'], phone: 'Phone22', addr: 'Addr22', time: '2023-11-13' },
{ no: 22, pno: 1, name: 'xh', stats: ['finish'], phone: 'Phone22', addr: 'Addr22', time: '2023-11-13' },
{ no: 23, name: 'xh', stats: ['finish'], phone: 'Phone23', addr: 'Addr23', time: '2023-11-14' },
{ no: 24, name: 'xh', stats: ['progress', 'risk'], phone: 'Phone24', addr: 'Addr24', time: '2023-11-15' },
{ no: 25, name: 'xh', stats: ['close'], phone: 'Phone25', addr: 'Addr25', time: '2023-11-16' },
Expand All @@ -283,7 +284,7 @@ const data3 = [
{ no: 114, name: 'xy', stats: ['init'], phone: 'Phone14', addr: 'Addr14', time: '2023-11-5' },
{ no: 115, name: 'xy', stats: ['init'], phone: 'Phone15', addr: 'Addr15', time: '2023-11-6' },
{ no: 116, name: 'xy', stats: ['init'], phone: 'Phone16', addr: 'Addr16', time: '2023-11-7' },
{ no: 117, name: 'xy', stats: ['init'], phone: 'Phone17', addr: 'Addr17', time: '2023-11-8' },
{ no: 117, pno: 210, name: 'xy', stats: ['init'], phone: 'Phone17', addr: 'Addr17', time: '2023-11-8' },
{ no: 118, name: 'xy', stats: ['init'], phone: 'Phone18', addr: 'Addr18', time: '2023-11-9' },
{ no: 119, name: 'xy', stats: ['init'], phone: 'Phone19', addr: 'Addr19', time: '2023-11-10' },
{ no: 210, name: 'xy', stats: ['init'], phone: 'Phone20', addr: 'Addr20', time: '2023-11-11' },
Expand Down Expand Up @@ -345,7 +346,7 @@ const resp2 = [
<div style="height: 600px">
<!-- <iw-task-table pk-column-name="no" :columns="columns" :events="events" :layouts="layouts"></iw-task-table> -->
<iw-task-table
pk-column-name="no" :columns="columns" :events="events" :layouts="layouts"
pk-column-name="no" parent-pk-column-name="pno" :columns="columns" :events="events" :layouts="layouts"
:group="group"
/>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/assets/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ export const TRASH = 'octicon-trash-24'
export const DICT = 'octicon-book-24'
export const PIN = 'octicon-pin-24'
export const WRAP = 'octicon-move-to-end-24'
export const EXPAND = 'octicon-triangle-right-24'
export const SHRINK = 'octicon-triangle-down-24'
4 changes: 2 additions & 2 deletions src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@
"titlePlaceholder": "New name",
"submit": "Add"
},
"rowAdd": {
"new": "New row"
"rowNew": {
"newTitle": "New row"
},
"rowCopyPaste": {
"copyTitle": "Copy row(s)",
Expand Down
4 changes: 2 additions & 2 deletions src/assets/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@
"titlePlaceholder": "新的字典项名称",
"submit": "添加"
},
"rowAdd": {
"new": "新增行"
"rowNew": {
"newTitle": "新增行"
},
"rowCopyPaste": {
"copyTitle": "复制行",
Expand Down
129 changes: 95 additions & 34 deletions src/components/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { InjectionKey, Ref } from 'vue'
import { toRaw } from 'vue'
import type { TableBasicConf, TableColumnConf, TableLayoutColumnConf, TableLayoutConf, TableStyleConf } from './conf'
import { getDefaultValueByDataKind } from './conf'
import { sortByTree } from './function/RowTree.vue'
import type { TableCellDictItem, TableCellDictItemResp, TableDataResp, TableDataSliceReq, TableEventProps, TableLayoutModifyReq } from './props'
import { DATA_DICT_POSTFIX, OperatorKind } from './props'

Expand Down Expand Up @@ -30,6 +31,10 @@ export async function loadData(layoutId?: string, moreForGroupedValue?: any) {
if (layout.filters)
filters = toRaw(layout.filters)

const slice = {
offsetNumber: 0,
fetchNumber: layout.fetchDataNumber,
}
if (moreForGroupedValue) {
const groupFilter = {
items: [
Expand All @@ -45,6 +50,15 @@ export async function loadData(layoutId?: string, moreForGroupedValue?: any) {
filters.push(groupFilter)
else
filters = [groupFilter]
if (layout.data && Array.isArray(layout.data)) {
const curGroupData = layout.data.find(d => d.groupValue === moreForGroupedValue)
if (curGroupData !== undefined)
slice.offsetNumber = curGroupData.records.length
}
}
else {
if (layout.data && !Array.isArray(layout.data))
slice.offsetNumber = layout.data.records.length
}
let sorts
if (layout.sorts)
Expand All @@ -58,12 +72,11 @@ export async function loadData(layoutId?: string, moreForGroupedValue?: any) {
if (layout.aggs)
aggs = toRaw(layout.aggs)

let slice
if (layout.slice)
slice = toRaw(layout.slice)

const resp = await events.loadData(filters, sorts, group, aggs, slice)
if (Array.isArray(resp)) {
resp.forEach((groupData) => {
groupData.records = sortByTree(groupData.records, tableBasicConf.pkColumnName, tableBasicConf.parentPkColumnName)
})
// (Re)group query
if (layout.data && Array.isArray(layout.data))
layout.data.splice(0, layout.data.length, ...resp)
Expand All @@ -76,65 +89,71 @@ export async function loadData(layoutId?: string, moreForGroupedValue?: any) {
const groupData = layout.data.find(d => d.groupValue === moreForGroupedValue)
if (groupData) {
groupData.records.push(...resp.records)
groupData.records = sortByTree(groupData.records, tableBasicConf.pkColumnName, tableBasicConf.parentPkColumnName)
groupData.aggs = resp.aggs
groupData.totalNumber = resp.totalNumber
}
}
else {
resp.records = sortByTree(resp.records, tableBasicConf.pkColumnName, tableBasicConf.parentPkColumnName)
layout.data = resp
}
}
else {
// Query without grouping
resp.records = sortByTree(resp.records, tableBasicConf.pkColumnName, tableBasicConf.parentPkColumnName)
layout.data = resp
}
}

export const FUN_ADD_DATA_TYPE = Symbol('FUN_ADD_DATA_TYPE') as InjectionKey<(newRecords: { [key: string]: any }[], afterPk?: any, groupValue?: any, reFilter?: boolean, reSort?: boolean, reLoad?: boolean) => Promise<boolean>>
export async function addData(newRecords: { [key: string]: any }[], afterPk?: any, groupValue?: any, reFilter?: boolean, reSort?: boolean, reLoad?: boolean): Promise<boolean> {
export const FUN_ADD_DATA_TYPE = Symbol('FUN_ADD_DATA_TYPE') as InjectionKey<(newRecords: { [key: string]: any }[], afterPk: any, reFilter?: boolean, reSort?: boolean, reLoad?: boolean) => Promise<boolean>>
export async function addData(newRecords: { [key: string]: any }[], afterPk: any, reFilter?: boolean, reSort?: boolean, reLoad?: boolean): Promise<boolean> {
const layout = tableLayoutsConf.find(layout => layout.id === currentLayoutId.value)!

if (Array.isArray(layout.data) && afterPk === undefined && groupValue === undefined)
return false

if (!events.saveData)
return false

if (tableBasicConf.parentPkColumnName) {
if (Array.isArray(layout.data)) {
for (const groupData of layout.data) {
const afterRecord = groupData.records.find(record => record[tableBasicConf.pkColumnName] === afterPk)
if (afterRecord) {
newRecords.forEach((record) => {
record[tableBasicConf.parentPkColumnName!] = afterRecord[tableBasicConf.parentPkColumnName!]
})
break
}
}
}
else if (layout.data && !Array.isArray(layout.data)) {
const afterRecord = layout.data.records.find(record => record[tableBasicConf.pkColumnName] === afterPk)
if (afterRecord) {
newRecords.forEach((record) => {
record[tableBasicConf.parentPkColumnName!] = afterRecord[tableBasicConf.parentPkColumnName!]
})
}
}
}

const savedRecords = await events.saveData(newRecords)
if (reLoad) {
await loadData()
return true
}

if (Array.isArray(layout.data)) {
if (groupValue) {
const data = layout.data.find(d => d.groupValue === groupValue)!
if (afterPk !== undefined) {
const idx = data.records.findIndex(r => r[tableBasicConf.pkColumnName] === afterPk)
data.records.splice(idx + 1, 0, ...savedRecords)
}
else {
data.records.splice(data.records.length, 0, ...savedRecords)
layout.data.forEach((groupData) => {
const idx = groupData.records.findIndex(r => r[tableBasicConf.pkColumnName] === afterPk)
if (idx !== -1) {
groupData.records.splice(idx + 1, 0, ...savedRecords)
groupData.records = sortByTree(groupData.records, tableBasicConf.pkColumnName, tableBasicConf.parentPkColumnName)
}
}
else {
layout.data.forEach((groupData) => {
if (afterPk !== undefined) {
const idx = groupData.records.findIndex(r => r[tableBasicConf.pkColumnName] === afterPk)
if (idx !== -1)
groupData.records.splice(idx + 1, 0, ...savedRecords)
}
})
}
})
}
else if (layout.data && !Array.isArray(layout.data)) {
if (afterPk !== undefined) {
const idx = layout.data.records.findIndex(r => r[tableBasicConf.pkColumnName] === afterPk)
layout.data.records.splice(idx + 1, 0, ...savedRecords)
}
else {
layout.data.records.splice(layout.data.records.length, 0, ...savedRecords)
}
const idx = layout.data.records.findIndex(r => r[tableBasicConf.pkColumnName] === afterPk)
layout.data.records.splice(idx + 1, 0, ...savedRecords)
layout.data.records = sortByTree(layout.data, tableBasicConf.pkColumnName, tableBasicConf.parentPkColumnName)
}
else {
// Empty,unreachable
Expand Down Expand Up @@ -192,10 +211,12 @@ export async function deleteData(deletedPks: any[], reFilter?: boolean, reSort?:
}
if (Array.isArray(layout.data)) {
layout.data.forEach((d) => {
deletedPks = filterTreeDataPks(deletedPks, d.records)
d.records = d.records.filter(item => !deletedPks.includes(item[tableBasicConf.pkColumnName]))
})
}
else if (layout.data && !Array.isArray(layout.data)) {
deletedPks = filterTreeDataPks(deletedPks, layout.data.records)
layout.data.records = layout.data.records.filter(item => !deletedPks.includes(item[tableBasicConf.pkColumnName]))
}
else {
Expand All @@ -205,6 +226,22 @@ export async function deleteData(deletedPks: any[], reFilter?: boolean, reSort?:
// TODO agg清空,重新计算
}

function filterTreeDataPks(filterPks: any[], records: { [key: string]: any }[]): any[] {
if (tableBasicConf.parentPkColumnName === undefined)
return filterPks

const pksWithChildren: any[] = filterPks.slice()

pksWithChildren.forEach((pk) => {
const childrenPks = records.filter(record => record[tableBasicConf.parentPkColumnName!] === pk).map(record => record[tableBasicConf.pkColumnName])
if (childrenPks.length > 0) {
pksWithChildren.push(...childrenPks)
pksWithChildren.push(...filterTreeDataPks(childrenPks, records))
}
})
return pksWithChildren
}

export const FUN_LOAD_CELL_DICT_ITEMS_TYPE = Symbol('FUN_LOAD_CELL_DICT_ITEMS_TYPE') as InjectionKey<(columnName: string, filterValue?: any, slice?: TableDataSliceReq) => Promise<TableCellDictItemResp>>
export async function loadCellDictItems(columnName: string, filterValue?: any, slice?: TableDataSliceReq): Promise<TableCellDictItemResp> {
if (events.loadCellDictItems) { return await events.loadCellDictItems(columnName, filterValue, slice) }
Expand Down Expand Up @@ -434,6 +471,8 @@ export async function newLayout(newLayoutConf: TableLayoutConf, reFilter?: boole
sorts: newLayoutConf.sorts,
group: newLayoutConf.group,
aggs: newLayoutConf.aggs,
expandDataPks: newLayoutConf.expandDataPks,
fetchDataNumber: newLayoutConf.fetchDataNumber,
}))) {
if (reLoad) {
await loadData()
Expand Down Expand Up @@ -466,6 +505,28 @@ export async function modifyLayout(changedLayoutReq: TableLayoutModifyReq, reFil
changedLayoutReq.sorts && (layout.sorts = changedLayoutReq.sorts)
changedLayoutReq.group && (layout.group = changedLayoutReq.group)
changedLayoutReq.aggs && (layout.aggs = changedLayoutReq.aggs)
if (changedLayoutReq.newExpandDataPk) {
const idx = layout.expandDataPks.indexOf(changedLayoutReq.newExpandDataPk)
if (idx === -1)
layout.expandDataPks.push(changedLayoutReq.newExpandDataPk)
}
if (changedLayoutReq.deleteExpandDataPk) {
let deleteExpandDataPks = []
if (Array.isArray(layout.data)) {
layout.data.forEach((groupData) => {
deleteExpandDataPks.push(...filterTreeDataPks([changedLayoutReq.deleteExpandDataPk], groupData.records))
})
}
else {
deleteExpandDataPks = filterTreeDataPks([changedLayoutReq.deleteExpandDataPk], (layout.data as TableDataResp).records)
}
deleteExpandDataPks.forEach((deleteExpandDataPk) => {
const idx = layout.expandDataPks.indexOf(deleteExpandDataPk)
if (idx !== -1)
layout.expandDataPks.splice(idx, 1)
})
}
changedLayoutReq.fetchDataNumber && (layout.fetchDataNumber = changedLayoutReq.fetchDataNumber)
if (changedLayoutReq.deletedColumnName) {
const oldLayoutColumnIdx = layout.columns.findIndex(column => column.name === changedLayoutReq.deletedColumnName)
layout.columns.splice(oldLayoutColumnIdx, 1)
Expand Down
Loading

0 comments on commit 5e0643f

Please sign in to comment.