|
@@ -1,98 +1,100 @@
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
-import gettext from '@/gettext'
|
|
|
|
-import StdDataEntry from '@/components/StdDataEntry'
|
|
|
|
-import StdPagination from './StdPagination.vue'
|
|
|
|
-import {computed, onMounted, reactive, ref, watch} from 'vue'
|
|
|
|
-import {useRoute, useRouter} from 'vue-router'
|
|
|
|
-import {message} from 'ant-design-vue'
|
|
|
|
-import {downloadCsv} from '@/lib/helper'
|
|
|
|
|
|
+import { computed, onMounted, reactive, ref, toRaw, watch } from 'vue'
|
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
|
+import { message } from 'ant-design-vue'
|
|
import dayjs from 'dayjs'
|
|
import dayjs from 'dayjs'
|
|
import Sortable from 'sortablejs'
|
|
import Sortable from 'sortablejs'
|
|
-import {HolderOutlined} from '@ant-design/icons-vue'
|
|
|
|
-import {toRaw} from '@vue/reactivity'
|
|
|
|
-
|
|
|
|
-const {$gettext, interpolate} = gettext
|
|
|
|
-
|
|
|
|
-const emit = defineEmits(['onSelected', 'onSelectedRecord', 'clickEdit', 'update:selectedRowKeys', 'clickBatchModify'])
|
|
|
|
|
|
+import { HolderOutlined } from '@ant-design/icons-vue'
|
|
|
|
+import _ from 'lodash'
|
|
|
|
+import StdPagination from './StdPagination.vue'
|
|
|
|
+import { downloadCsv } from '@/lib/helper'
|
|
|
|
+import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
|
|
|
+import gettext from '@/gettext'
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
api: Object,
|
|
api: Object,
|
|
columns: Array,
|
|
columns: Array,
|
|
data_key: {
|
|
data_key: {
|
|
type: String,
|
|
type: String,
|
|
- default: 'data'
|
|
|
|
|
|
+ default: 'data',
|
|
},
|
|
},
|
|
disable_search: {
|
|
disable_search: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: false
|
|
|
|
|
|
+ default: false,
|
|
},
|
|
},
|
|
disable_query_params: {
|
|
disable_query_params: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: false
|
|
|
|
|
|
+ default: false,
|
|
},
|
|
},
|
|
disable_add: {
|
|
disable_add: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: false
|
|
|
|
|
|
+ default: false,
|
|
},
|
|
},
|
|
edit_text: String,
|
|
edit_text: String,
|
|
deletable: {
|
|
deletable: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: true
|
|
|
|
|
|
+ default: true,
|
|
},
|
|
},
|
|
get_params: {
|
|
get_params: {
|
|
type: Object,
|
|
type: Object,
|
|
default() {
|
|
default() {
|
|
return {}
|
|
return {}
|
|
- }
|
|
|
|
|
|
+ },
|
|
},
|
|
},
|
|
editable: {
|
|
editable: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: true
|
|
|
|
|
|
+ default: true,
|
|
},
|
|
},
|
|
selectionType: {
|
|
selectionType: {
|
|
type: String,
|
|
type: String,
|
|
- validator: function (value: string) {
|
|
|
|
- return ['checkbox', 'radio'].indexOf(value) !== -1
|
|
|
|
- }
|
|
|
|
|
|
+ validator(value: string) {
|
|
|
|
+ return ['checkbox', 'radio'].includes(value)
|
|
|
|
+ },
|
|
},
|
|
},
|
|
pithy: {
|
|
pithy: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: false
|
|
|
|
|
|
+ default: false,
|
|
},
|
|
},
|
|
scrollX: {
|
|
scrollX: {
|
|
type: [Number, Boolean],
|
|
type: [Number, Boolean],
|
|
- default: true
|
|
|
|
|
|
+ default: true,
|
|
},
|
|
},
|
|
rowKey: {
|
|
rowKey: {
|
|
type: String,
|
|
type: String,
|
|
- default: 'id'
|
|
|
|
|
|
+ default: 'id',
|
|
},
|
|
},
|
|
exportCsv: {
|
|
exportCsv: {
|
|
type: Boolean,
|
|
type: Boolean,
|
|
- default: false
|
|
|
|
|
|
+ default: false,
|
|
},
|
|
},
|
|
size: String,
|
|
size: String,
|
|
selectedRowKeys: {
|
|
selectedRowKeys: {
|
|
- type: Array
|
|
|
|
|
|
+ type: Array,
|
|
},
|
|
},
|
|
- useSortable: Boolean
|
|
|
|
|
|
+ useSortable: Boolean,
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+const emit = defineEmits(['onSelected', 'onSelectedRecord', 'clickEdit', 'update:selectedRowKeys', 'clickBatchModify'])
|
|
|
|
+
|
|
|
|
+const { $gettext, interpolate } = gettext
|
|
|
|
+
|
|
const data_source: any = ref([])
|
|
const data_source: any = ref([])
|
|
const expand_keys_list: any = ref([])
|
|
const expand_keys_list: any = ref([])
|
|
const rows_key_index_map: any = ref({})
|
|
const rows_key_index_map: any = ref({})
|
|
|
|
|
|
const loading = ref(true)
|
|
const loading = ref(true)
|
|
|
|
+
|
|
const pagination = reactive({
|
|
const pagination = reactive({
|
|
total: 1,
|
|
total: 1,
|
|
per_page: 10,
|
|
per_page: 10,
|
|
current_page: 1,
|
|
current_page: 1,
|
|
- total_pages: 1
|
|
|
|
|
|
+ total_pages: 1,
|
|
})
|
|
})
|
|
|
|
|
|
const route = useRoute()
|
|
const route = useRoute()
|
|
|
|
+
|
|
const params = reactive({
|
|
const params = reactive({
|
|
- ...props.get_params
|
|
|
|
|
|
+ ...props.get_params,
|
|
})
|
|
})
|
|
|
|
|
|
const selectedKeysLocalBuffer: any = ref([])
|
|
const selectedKeysLocalBuffer: any = ref([])
|
|
@@ -104,7 +106,7 @@ const selectedRowKeysBuffer = computed({
|
|
set(v) {
|
|
set(v) {
|
|
selectedKeysLocalBuffer.value = v
|
|
selectedKeysLocalBuffer.value = v
|
|
emit('update:selectedRowKeys', v)
|
|
emit('update:selectedRowKeys', v)
|
|
- }
|
|
|
|
|
|
+ },
|
|
})
|
|
})
|
|
|
|
|
|
const searchColumns = getSearchColumns()
|
|
const searchColumns = getSearchColumns()
|
|
@@ -112,24 +114,23 @@ const pithyColumns = getPithyColumns()
|
|
const batchColumns = getBatchEditColumns()
|
|
const batchColumns = getBatchEditColumns()
|
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
- if (!props.disable_query_params) {
|
|
|
|
|
|
+ if (!props.disable_query_params)
|
|
Object.assign(params, route.query)
|
|
Object.assign(params, route.query)
|
|
- }
|
|
|
|
|
|
+
|
|
get_list()
|
|
get_list()
|
|
|
|
|
|
- if (props.useSortable) {
|
|
|
|
|
|
+ if (props.useSortable)
|
|
initSortable()
|
|
initSortable()
|
|
- }
|
|
|
|
})
|
|
})
|
|
|
|
|
|
defineExpose({
|
|
defineExpose({
|
|
- get_list
|
|
|
|
|
|
+ get_list,
|
|
})
|
|
})
|
|
|
|
|
|
function destroy(id: any) {
|
|
function destroy(id: any) {
|
|
props.api!.destroy(id).then(() => {
|
|
props.api!.destroy(id).then(() => {
|
|
get_list()
|
|
get_list()
|
|
- message.success(interpolate($gettext('Delete ID: %{id}'), {id: id}))
|
|
|
|
|
|
+ message.success(interpolate($gettext('Delete ID: %{id}'), { id }))
|
|
}).catch((e: any) => {
|
|
}).catch((e: any) => {
|
|
message.error($gettext(e?.message ?? 'Server error'))
|
|
message.error($gettext(e?.message ?? 'Server error'))
|
|
})
|
|
})
|
|
@@ -138,8 +139,8 @@ function destroy(id: any) {
|
|
function get_list(page_num = null, page_size = 20) {
|
|
function get_list(page_num = null, page_size = 20) {
|
|
loading.value = true
|
|
loading.value = true
|
|
if (page_num) {
|
|
if (page_num) {
|
|
- params['page'] = page_num
|
|
|
|
- params['page_size'] = page_size
|
|
|
|
|
|
+ params.page = page_num
|
|
|
|
+ params.page_size = page_size
|
|
}
|
|
}
|
|
props.api!.get_list(params).then(async (r: any) => {
|
|
props.api!.get_list(params).then(async (r: any) => {
|
|
data_source.value = r.data
|
|
data_source.value = r.data
|
|
@@ -149,9 +150,12 @@ function get_list(page_num = null, page_size = 20) {
|
|
if (data && data.length > 0) {
|
|
if (data && data.length > 0) {
|
|
data.forEach((v: any) => {
|
|
data.forEach((v: any) => {
|
|
v.level = level
|
|
v.level = level
|
|
- let current_index = [...total, index++]
|
|
|
|
|
|
+
|
|
|
|
+ const current_index = [...total, index++]
|
|
|
|
+
|
|
rows_key_index_map.value[v.id] = current_index
|
|
rows_key_index_map.value[v.id] = current_index
|
|
- if (v.children) buildIndexMap(v.children, level + 1, 0, current_index)
|
|
|
|
|
|
+ if (v.children)
|
|
|
|
+ buildIndexMap(v.children, level + 1, 0, current_index)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -159,9 +163,8 @@ function get_list(page_num = null, page_size = 20) {
|
|
buildIndexMap(r.data)
|
|
buildIndexMap(r.data)
|
|
}
|
|
}
|
|
|
|
|
|
- if (r.pagination !== undefined) {
|
|
|
|
|
|
+ if (r.pagination !== undefined)
|
|
Object.assign(pagination, r.pagination)
|
|
Object.assign(pagination, r.pagination)
|
|
- }
|
|
|
|
|
|
|
|
loading.value = false
|
|
loading.value = false
|
|
}).catch((e: any) => {
|
|
}).catch((e: any) => {
|
|
@@ -172,23 +175,22 @@ function get_list(page_num = null, page_size = 20) {
|
|
function stdChange(pagination: any, filters: any, sorter: any) {
|
|
function stdChange(pagination: any, filters: any, sorter: any) {
|
|
if (sorter) {
|
|
if (sorter) {
|
|
selectedRowKeysBuffer.value = []
|
|
selectedRowKeysBuffer.value = []
|
|
- params['order_by'] = sorter.field
|
|
|
|
- params['sort'] = sorter.order === 'ascend' ? 'asc' : 'desc'
|
|
|
|
|
|
+ params.order_by = sorter.field
|
|
|
|
+ params.sort = sorter.order === 'ascend' ? 'asc' : 'desc'
|
|
switch (sorter.order) {
|
|
switch (sorter.order) {
|
|
case 'ascend':
|
|
case 'ascend':
|
|
- params['sort'] = 'asc'
|
|
|
|
|
|
+ params.sort = 'asc'
|
|
break
|
|
break
|
|
case 'descend':
|
|
case 'descend':
|
|
- params['sort'] = 'desc'
|
|
|
|
|
|
+ params.sort = 'desc'
|
|
break
|
|
break
|
|
default:
|
|
default:
|
|
- params['sort'] = null
|
|
|
|
|
|
+ params.sort = null
|
|
break
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (pagination) {
|
|
|
|
|
|
+ if (pagination)
|
|
selectedRowKeysBuffer.value = []
|
|
selectedRowKeysBuffer.value = []
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
function expandedTable(keys: any) {
|
|
function expandedTable(keys: any) {
|
|
@@ -196,22 +198,24 @@ function expandedTable(keys: any) {
|
|
}
|
|
}
|
|
|
|
|
|
function getSearchColumns() {
|
|
function getSearchColumns() {
|
|
- let searchColumns: any = []
|
|
|
|
|
|
+ const searchColumns: any = []
|
|
|
|
+
|
|
props.columns!.forEach((column: any) => {
|
|
props.columns!.forEach((column: any) => {
|
|
- if (column.search) {
|
|
|
|
|
|
+ if (column.search)
|
|
searchColumns.push(column)
|
|
searchColumns.push(column)
|
|
- }
|
|
|
|
})
|
|
})
|
|
|
|
+
|
|
return searchColumns
|
|
return searchColumns
|
|
}
|
|
}
|
|
|
|
|
|
function getBatchEditColumns() {
|
|
function getBatchEditColumns() {
|
|
- let batch: any = []
|
|
|
|
|
|
+ const batch: any = []
|
|
|
|
+
|
|
props.columns!.forEach((column: any) => {
|
|
props.columns!.forEach((column: any) => {
|
|
- if (column.batch) {
|
|
|
|
|
|
+ if (column.batch)
|
|
batch.push(column)
|
|
batch.push(column)
|
|
- }
|
|
|
|
})
|
|
})
|
|
|
|
+
|
|
return batch
|
|
return batch
|
|
}
|
|
}
|
|
|
|
|
|
@@ -221,6 +225,7 @@ function getPithyColumns() {
|
|
return c.pithy === true && c.display !== false
|
|
return c.pithy === true && c.display !== false
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
+
|
|
return props.columns!.filter((c: any, index: any, columns: any) => {
|
|
return props.columns!.filter((c: any, index: any, columns: any) => {
|
|
return c.display !== false
|
|
return c.display !== false
|
|
})
|
|
})
|
|
@@ -241,10 +246,14 @@ async function onSelectChange(_selectedRowKeys: any) {
|
|
Object.keys(crossPageSelect).forEach(v => {
|
|
Object.keys(crossPageSelect).forEach(v => {
|
|
t.push(...crossPageSelect[v])
|
|
t.push(...crossPageSelect[v])
|
|
})
|
|
})
|
|
|
|
+
|
|
const n: any = [..._selectedRowKeys]
|
|
const n: any = [..._selectedRowKeys]
|
|
|
|
+
|
|
t = await t.concat(n)
|
|
t = await t.concat(n)
|
|
|
|
+
|
|
// console.log(crossPageSelect)
|
|
// console.log(crossPageSelect)
|
|
const set = new Set(t)
|
|
const set = new Set(t)
|
|
|
|
+
|
|
selectedRowKeysBuffer.value = Array.from(set)
|
|
selectedRowKeysBuffer.value = Array.from(set)
|
|
emit('onSelected', selectedRowKeysBuffer.value)
|
|
emit('onSelected', selectedRowKeysBuffer.value)
|
|
}
|
|
}
|
|
@@ -261,66 +270,58 @@ const reset_search = async () => {
|
|
})
|
|
})
|
|
|
|
|
|
Object.assign(params, {
|
|
Object.assign(params, {
|
|
- ...props.get_params
|
|
|
|
|
|
+ ...props.get_params,
|
|
})
|
|
})
|
|
|
|
|
|
- router.push({query: {}}).catch(() => {
|
|
|
|
|
|
+ router.push({ query: {} }).catch(() => {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
watch(params, () => {
|
|
watch(params, () => {
|
|
- if (!props.disable_query_params) {
|
|
|
|
- router.push({query: params})
|
|
|
|
- }
|
|
|
|
|
|
+ if (!props.disable_query_params)
|
|
|
|
+ router.push({ query: params })
|
|
|
|
+
|
|
get_list()
|
|
get_list()
|
|
})
|
|
})
|
|
|
|
|
|
const rowSelection = computed(() => {
|
|
const rowSelection = computed(() => {
|
|
if (batchColumns.length > 0 || props.selectionType) {
|
|
if (batchColumns.length > 0 || props.selectionType) {
|
|
return {
|
|
return {
|
|
- selectedRowKeys: selectedRowKeysBuffer.value, onChange: onSelectChange,
|
|
|
|
- onSelect: onSelect, type: batchColumns.length > 0 ? 'checkbox' : props.selectionType
|
|
|
|
|
|
+ selectedRowKeys: selectedRowKeysBuffer.value,
|
|
|
|
+ onChange: onSelectChange,
|
|
|
|
+ onSelect,
|
|
|
|
+ type: batchColumns.length > 0 ? 'checkbox' : props.selectionType,
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
return null
|
|
return null
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
|
|
-function fn(obj: Object, desc: string) {
|
|
|
|
- const arr: string[] = desc.split('.')
|
|
|
|
- while (arr.length) {
|
|
|
|
- // @ts-ignore
|
|
|
|
- const top = obj[arr.shift()]
|
|
|
|
- if (top === undefined) {
|
|
|
|
- return null
|
|
|
|
- }
|
|
|
|
- obj = top
|
|
|
|
- }
|
|
|
|
- return obj
|
|
|
|
-}
|
|
|
|
|
|
+const fn = _.get
|
|
|
|
|
|
async function export_csv() {
|
|
async function export_csv() {
|
|
- let header = []
|
|
|
|
- let headerKeys: any[] = []
|
|
|
|
|
|
+ const header = []
|
|
|
|
+ const headerKeys: any[] = []
|
|
const showColumnsMap: any = {}
|
|
const showColumnsMap: any = {}
|
|
- // @ts-ignore
|
|
|
|
- for (let showColumnsKey in pithyColumns) {
|
|
|
|
- // @ts-ignore
|
|
|
|
- if (pithyColumns[showColumnsKey].dataIndex === 'action') continue
|
|
|
|
- // @ts-ignore
|
|
|
|
|
|
+
|
|
|
|
+ for (const showColumnsKey in pithyColumns) {
|
|
|
|
+ if (pithyColumns[showColumnsKey].dataIndex === 'action')
|
|
|
|
+ continue
|
|
|
|
+
|
|
let t = pithyColumns[showColumnsKey].title
|
|
let t = pithyColumns[showColumnsKey].title
|
|
|
|
|
|
- if (typeof t === 'function') {
|
|
|
|
|
|
+ if (typeof t === 'function')
|
|
t = t()
|
|
t = t()
|
|
- }
|
|
|
|
|
|
+
|
|
header.push({
|
|
header.push({
|
|
title: t,
|
|
title: t,
|
|
- // @ts-ignore
|
|
|
|
- key: pithyColumns[showColumnsKey].dataIndex
|
|
|
|
|
|
+
|
|
|
|
+ key: pithyColumns[showColumnsKey].dataIndex,
|
|
})
|
|
})
|
|
- // @ts-ignore
|
|
|
|
|
|
+
|
|
headerKeys.push(pithyColumns[showColumnsKey].dataIndex)
|
|
headerKeys.push(pithyColumns[showColumnsKey].dataIndex)
|
|
- // @ts-ignore
|
|
|
|
|
|
+
|
|
showColumnsMap[pithyColumns[showColumnsKey].dataIndex] = pithyColumns[showColumnsKey]
|
|
showColumnsMap[pithyColumns[showColumnsKey].dataIndex] = pithyColumns[showColumnsKey]
|
|
}
|
|
}
|
|
|
|
|
|
@@ -329,30 +330,32 @@ async function export_csv() {
|
|
let page = 1
|
|
let page = 1
|
|
while (hasMore) {
|
|
while (hasMore) {
|
|
// 准备 DataSource
|
|
// 准备 DataSource
|
|
- await props.api!.get_list({page}).then((response: any) => {
|
|
|
|
|
|
+ await props.api!.get_list({ page }).then((response: any) => {
|
|
if (response.data.length === 0) {
|
|
if (response.data.length === 0) {
|
|
hasMore = false
|
|
hasMore = false
|
|
|
|
+
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- if (response[props.data_key] === undefined) {
|
|
|
|
|
|
+ if (response[props.data_key] === undefined)
|
|
dataSource = dataSource.concat(...response.data)
|
|
dataSource = dataSource.concat(...response.data)
|
|
- } else {
|
|
|
|
|
|
+ else
|
|
dataSource = dataSource.concat(...response[props.data_key])
|
|
dataSource = dataSource.concat(...response[props.data_key])
|
|
- }
|
|
|
|
}).catch((e: any) => {
|
|
}).catch((e: any) => {
|
|
message.error(e.message ?? $gettext('Server error'))
|
|
message.error(e.message ?? $gettext('Server error'))
|
|
hasMore = false
|
|
hasMore = false
|
|
- return
|
|
|
|
})
|
|
})
|
|
page += 1
|
|
page += 1
|
|
}
|
|
}
|
|
const data: any[] = []
|
|
const data: any[] = []
|
|
|
|
+
|
|
dataSource.forEach((row: Object) => {
|
|
dataSource.forEach((row: Object) => {
|
|
- let obj: any = {}
|
|
|
|
|
|
+ const obj: any = {}
|
|
|
|
+
|
|
headerKeys.forEach(key => {
|
|
headerKeys.forEach(key => {
|
|
let data = fn(row, key)
|
|
let data = fn(row, key)
|
|
const c = showColumnsMap[key]
|
|
const c = showColumnsMap[key]
|
|
- data = c?.customRender?.({text: data}) ?? data
|
|
|
|
|
|
+
|
|
|
|
+ data = c?.customRender?.({ text: data }) ?? data
|
|
obj[c.dataIndex] = data
|
|
obj[c.dataIndex] = data
|
|
})
|
|
})
|
|
data.push(obj)
|
|
data.push(obj)
|
|
@@ -375,61 +378,65 @@ function getLeastIndex(index: number) {
|
|
}
|
|
}
|
|
|
|
|
|
function getTargetData(data: any, indexList: number[]): any {
|
|
function getTargetData(data: any, indexList: number[]): any {
|
|
- let target: any = {children: data}
|
|
|
|
|
|
+ let target: any = { children: data }
|
|
indexList.forEach((index: number) => {
|
|
indexList.forEach((index: number) => {
|
|
target.children[index].parent = target
|
|
target.children[index].parent = target
|
|
target = target.children[index]
|
|
target = target.children[index]
|
|
})
|
|
})
|
|
|
|
+
|
|
return target
|
|
return target
|
|
}
|
|
}
|
|
|
|
|
|
function initSortable() {
|
|
function initSortable() {
|
|
const table: any = document.querySelector('#std-table tbody')
|
|
const table: any = document.querySelector('#std-table tbody')
|
|
|
|
+
|
|
new Sortable(table, {
|
|
new Sortable(table, {
|
|
handle: '.ant-table-drag-icon',
|
|
handle: '.ant-table-drag-icon',
|
|
animation: 150,
|
|
animation: 150,
|
|
sort: true,
|
|
sort: true,
|
|
forceFallback: true,
|
|
forceFallback: true,
|
|
- setData: function (dataTransfer) {
|
|
|
|
|
|
+ setData(dataTransfer) {
|
|
dataTransfer.setData('Text', '')
|
|
dataTransfer.setData('Text', '')
|
|
},
|
|
},
|
|
- onStart({item}) {
|
|
|
|
- let targetRowKey = Number(item.dataset.rowKey)
|
|
|
|
- if (targetRowKey) {
|
|
|
|
|
|
+ onStart({ item }) {
|
|
|
|
+ const targetRowKey = Number(item.dataset.rowKey)
|
|
|
|
+ if (targetRowKey)
|
|
expand_keys_list.value = expand_keys_list.value.filter((item: number) => item !== targetRowKey)
|
|
expand_keys_list.value = expand_keys_list.value.filter((item: number) => item !== targetRowKey)
|
|
- }
|
|
|
|
},
|
|
},
|
|
- onMove({dragged, related}) {
|
|
|
|
|
|
+ onMove({ dragged, related }) {
|
|
const oldRow: number[] = rows_key_index_map.value?.[Number(dragged.dataset.rowKey)]
|
|
const oldRow: number[] = rows_key_index_map.value?.[Number(dragged.dataset.rowKey)]
|
|
const newRow: number[] = rows_key_index_map.value?.[Number(related.dataset.rowKey)]
|
|
const newRow: number[] = rows_key_index_map.value?.[Number(related.dataset.rowKey)]
|
|
- if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] != newRow[newRow.length - 2]) {
|
|
|
|
|
|
+ if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] != newRow[newRow.length - 2])
|
|
return false
|
|
return false
|
|
- }
|
|
|
|
},
|
|
},
|
|
- async onEnd({item, newIndex, oldIndex}) {
|
|
|
|
- if (newIndex === oldIndex) return
|
|
|
|
|
|
+ async onEnd({ item, newIndex, oldIndex }) {
|
|
|
|
+ if (newIndex === oldIndex)
|
|
|
|
+ return
|
|
|
|
|
|
const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
|
const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
|
const direction: number = indexDelta > 0 ? +1 : -1
|
|
const direction: number = indexDelta > 0 ? +1 : -1
|
|
|
|
|
|
- let rowIndex: number[] = rows_key_index_map.value?.[Number(item.dataset.rowKey)]
|
|
|
|
|
|
+ const rowIndex: number[] = rows_key_index_map.value?.[Number(item.dataset.rowKey)]
|
|
const newRow = getTargetData(data_source.value, rowIndex)
|
|
const newRow = getTargetData(data_source.value, rowIndex)
|
|
const newRowParent = newRow.parent
|
|
const newRowParent = newRow.parent
|
|
const level: number = newRow.level
|
|
const level: number = newRow.level
|
|
|
|
|
|
- let currentRowIndex: number[] = [...rows_key_index_map.value?.
|
|
|
|
|
|
+ const currentRowIndex: number[] = [...rows_key_index_map.value?.
|
|
[Number(table.children[Number(newIndex) + direction].dataset.rowKey)]]
|
|
[Number(table.children[Number(newIndex) + direction].dataset.rowKey)]]
|
|
- let currentRow: any = getTargetData(data_source.value, currentRowIndex)
|
|
|
|
|
|
+
|
|
|
|
+ const currentRow: any = getTargetData(data_source.value, currentRowIndex)
|
|
|
|
+
|
|
// Reset parent
|
|
// Reset parent
|
|
currentRow.parent = newRow.parent = null
|
|
currentRow.parent = newRow.parent = null
|
|
newRowParent.children.splice(rowIndex[level], 1)
|
|
newRowParent.children.splice(rowIndex[level], 1)
|
|
newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
|
newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
|
|
|
|
|
- let changeIds: number[] = []
|
|
|
|
|
|
+ const changeIds: number[] = []
|
|
|
|
|
|
function processChanges(row: any, children: boolean = false, newIndex: number | undefined = undefined) {
|
|
function processChanges(row: any, children: boolean = false, newIndex: number | undefined = undefined) {
|
|
// Build changes ID list expect new row
|
|
// Build changes ID list expect new row
|
|
- if (children || newIndex === undefined) changeIds.push(row.id)
|
|
|
|
|
|
+ if (children || newIndex === undefined)
|
|
|
|
+ changeIds.push(row.id)
|
|
|
|
|
|
if (newIndex !== undefined)
|
|
if (newIndex !== undefined)
|
|
rows_key_index_map.value[row.id][level] = newIndex
|
|
rows_key_index_map.value[row.id][level] = newIndex
|
|
@@ -437,16 +444,17 @@ function initSortable() {
|
|
rows_key_index_map.value[row.id][level] += direction
|
|
rows_key_index_map.value[row.id][level] += direction
|
|
|
|
|
|
row.parent = null
|
|
row.parent = null
|
|
- if (row.children) {
|
|
|
|
|
|
+ if (row.children)
|
|
row.children.forEach((v: any) => processChanges(v, true, newIndex))
|
|
row.children.forEach((v: any) => processChanges(v, true, newIndex))
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// Replace row index for new row
|
|
// Replace row index for new row
|
|
processChanges(newRow, false, currentRowIndex[level])
|
|
processChanges(newRow, false, currentRowIndex[level])
|
|
|
|
+
|
|
// Rebuild row index maps for changes row
|
|
// Rebuild row index maps for changes row
|
|
for (let i = Number(oldIndex); i != newIndex; i -= direction) {
|
|
for (let i = Number(oldIndex); i != newIndex; i -= direction) {
|
|
- let rowIndex: number[] = rows_key_index_map.value?.[table.children[i].dataset.rowKey]
|
|
|
|
|
|
+ const rowIndex: number[] = rows_key_index_map.value?.[table.children[i].dataset.rowKey]
|
|
|
|
+
|
|
rowIndex[level] += direction
|
|
rowIndex[level] += direction
|
|
processChanges(getTargetData(data_source.value, rowIndex))
|
|
processChanges(getTargetData(data_source.value, rowIndex))
|
|
}
|
|
}
|
|
@@ -455,83 +463,106 @@ function initSortable() {
|
|
|
|
|
|
props.api!.update_order({
|
|
props.api!.update_order({
|
|
target_id: newRow.id,
|
|
target_id: newRow.id,
|
|
- direction: direction,
|
|
|
|
- affected_ids: changeIds
|
|
|
|
|
|
+ direction,
|
|
|
|
+ affected_ids: changeIds,
|
|
}).then(() => {
|
|
}).then(() => {
|
|
message.success($gettext('Updated successfully'))
|
|
message.success($gettext('Updated successfully'))
|
|
}).catch((e: any) => {
|
|
}).catch((e: any) => {
|
|
message.error(e?.message ?? $gettext('Server error'))
|
|
message.error(e?.message ?? $gettext('Server error'))
|
|
})
|
|
})
|
|
- }
|
|
|
|
|
|
+ },
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<template>
|
|
<template>
|
|
<div class="std-table">
|
|
<div class="std-table">
|
|
- <std-data-entry
|
|
|
|
|
|
+ <StdDataEntry
|
|
v-if="!disable_search && searchColumns.length"
|
|
v-if="!disable_search && searchColumns.length"
|
|
:data-list="searchColumns"
|
|
:data-list="searchColumns"
|
|
:data-source="params"
|
|
:data-source="params"
|
|
layout="inline"
|
|
layout="inline"
|
|
>
|
|
>
|
|
<template #action>
|
|
<template #action>
|
|
- <a-space class="action-btn">
|
|
|
|
- <a-button v-if="exportCsv" @click="export_csv" type="primary" ghost>
|
|
|
|
|
|
+ <ASpace class="action-btn">
|
|
|
|
+ <AButton
|
|
|
|
+ v-if="exportCsv"
|
|
|
|
+ type="primary"
|
|
|
|
+ ghost
|
|
|
|
+ @click="export_csv"
|
|
|
|
+ >
|
|
{{ $gettext('Export') }}
|
|
{{ $gettext('Export') }}
|
|
- </a-button>
|
|
|
|
- <a-button @click="reset_search">
|
|
|
|
|
|
+ </AButton>
|
|
|
|
+ <AButton @click="reset_search">
|
|
{{ $gettext('Reset') }}
|
|
{{ $gettext('Reset') }}
|
|
- </a-button>
|
|
|
|
- <a-button v-if="hasSelectedRow" @click="click_batch_edit">
|
|
|
|
|
|
+ </AButton>
|
|
|
|
+ <AButton
|
|
|
|
+ v-if="hasSelectedRow"
|
|
|
|
+ @click="click_batch_edit"
|
|
|
|
+ >
|
|
{{ $gettext('Batch Modify') }}
|
|
{{ $gettext('Batch Modify') }}
|
|
- </a-button>
|
|
|
|
- </a-space>
|
|
|
|
|
|
+ </AButton>
|
|
|
|
+ </ASpace>
|
|
</template>
|
|
</template>
|
|
- </std-data-entry>
|
|
|
|
- <a-table
|
|
|
|
|
|
+ </StdDataEntry>
|
|
|
|
+ <ATable
|
|
|
|
+ id="std-table"
|
|
:columns="pithyColumns"
|
|
:columns="pithyColumns"
|
|
:data-source="data_source"
|
|
:data-source="data_source"
|
|
:loading="loading"
|
|
:loading="loading"
|
|
:pagination="false"
|
|
:pagination="false"
|
|
:row-key="rowKey"
|
|
:row-key="rowKey"
|
|
- :rowSelection="rowSelection"
|
|
|
|
- @change="stdChange"
|
|
|
|
|
|
+ :row-selection="rowSelection"
|
|
:scroll="{ x: scrollX }"
|
|
:scroll="{ x: scrollX }"
|
|
:size="size"
|
|
:size="size"
|
|
- id="std-table"
|
|
|
|
|
|
+ :expanded-row-keys="expand_keys_list"
|
|
|
|
+ @change="stdChange"
|
|
@expandedRowsChange="expandedTable"
|
|
@expandedRowsChange="expandedTable"
|
|
- :expandedRowKeys="expand_keys_list"
|
|
|
|
>
|
|
>
|
|
- <template
|
|
|
|
- v-slot:bodyCell="{text, record, index, column}"
|
|
|
|
- >
|
|
|
|
|
|
+ <template #bodyCell="{ text, record, index, column }">
|
|
<template v-if="column.handle === true">
|
|
<template v-if="column.handle === true">
|
|
- <span class="ant-table-drag-icon"><HolderOutlined/></span>
|
|
|
|
|
|
+ <span class="ant-table-drag-icon"><HolderOutlined /></span>
|
|
{{ text }}
|
|
{{ text }}
|
|
</template>
|
|
</template>
|
|
<template v-if="column.dataIndex === 'action'">
|
|
<template v-if="column.dataIndex === 'action'">
|
|
- <a-button type="link" size="small" v-if="props.editable"
|
|
|
|
- @click="$emit('clickEdit', record[props.rowKey], record)">
|
|
|
|
|
|
+ <AButton
|
|
|
|
+ v-if="props.editable"
|
|
|
|
+ type="link"
|
|
|
|
+ size="small"
|
|
|
|
+ @click="$emit('clickEdit', record[props.rowKey], record)"
|
|
|
|
+ >
|
|
{{ props.edit_text || $gettext('Modify') }}
|
|
{{ props.edit_text || $gettext('Modify') }}
|
|
- </a-button>
|
|
|
|
- <slot name="actions" :record="record"/>
|
|
|
|
|
|
+ </AButton>
|
|
|
|
+ <slot
|
|
|
|
+ name="actions"
|
|
|
|
+ :record="record"
|
|
|
|
+ />
|
|
<template v-if="props.deletable">
|
|
<template v-if="props.deletable">
|
|
- <a-divider type="vertical"/>
|
|
|
|
- <a-popconfirm
|
|
|
|
- :cancelText="$gettext('No')"
|
|
|
|
- :okText="$gettext('OK')"
|
|
|
|
|
|
+ <ADivider type="vertical" />
|
|
|
|
+ <APopconfirm
|
|
|
|
+ :cancel-text="$gettext('No')"
|
|
|
|
+ :ok-text="$gettext('OK')"
|
|
:title="$gettext('Are you sure you want to delete?')"
|
|
:title="$gettext('Are you sure you want to delete?')"
|
|
- @confirm="destroy(record[rowKey])">
|
|
|
|
- <a-button type="link" size="small">{{ $gettext('Delete') }}</a-button>
|
|
|
|
- </a-popconfirm>
|
|
|
|
|
|
+ @confirm="destroy(record[rowKey])"
|
|
|
|
+ >
|
|
|
|
+ <AButton
|
|
|
|
+ type="link"
|
|
|
|
+ size="small"
|
|
|
|
+ >
|
|
|
|
+ {{ $gettext('Delete') }}
|
|
|
|
+ </AButton>
|
|
|
|
+ </APopconfirm>
|
|
</template>
|
|
</template>
|
|
</template>
|
|
</template>
|
|
</template>
|
|
</template>
|
|
- </a-table>
|
|
|
|
- <std-pagination :size="size" :pagination="pagination" @change="get_list" @changePageSize="stdChange"/>
|
|
|
|
|
|
+ </ATable>
|
|
|
|
+ <StdPagination
|
|
|
|
+ :size="size"
|
|
|
|
+ :pagination="pagination"
|
|
|
|
+ @change="get_list"
|
|
|
|
+ @changePageSize="stdChange"
|
|
|
|
+ />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|