|
@@ -1,623 +0,0 @@
|
|
|
-<script setup lang="ts" generic="T=any">
|
|
|
-import type { TableProps } from 'ant-design-vue'
|
|
|
-import type { Key } from 'ant-design-vue/es/_util/type'
|
|
|
-import type { FilterValue } from 'ant-design-vue/es/table/interface'
|
|
|
-import type { SorterResult, TablePaginationConfig } from 'ant-design-vue/lib/table/interface'
|
|
|
-import type { ComputedRef, Ref } from 'vue'
|
|
|
-import type { RouteParams } from 'vue-router'
|
|
|
-import type { GetListResponse, Pagination } from '@/api/curd'
|
|
|
-import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/types'
|
|
|
-import type { Column } from '@/components/StdDesign/types'
|
|
|
-import { HolderOutlined } from '@ant-design/icons-vue'
|
|
|
-import { message } from 'ant-design-vue'
|
|
|
-import { debounce } from 'lodash'
|
|
|
-import { getPithyColumns } from '@/components/StdDesign/StdDataDisplay/methods/columns'
|
|
|
-import useSortable from '@/components/StdDesign/StdDataDisplay/methods/sortable'
|
|
|
-import StdBulkActions from '@/components/StdDesign/StdDataDisplay/StdBulkActions.vue'
|
|
|
-import StdDataEntry, { labelRender } from '@/components/StdDesign/StdDataEntry'
|
|
|
-import StdPagination from './StdPagination.vue'
|
|
|
-
|
|
|
-const props = withDefaults(defineProps<StdTableProps<T>>(), {
|
|
|
- rowKey: 'id',
|
|
|
-})
|
|
|
-
|
|
|
-const emit = defineEmits([
|
|
|
- 'clickEdit',
|
|
|
- 'clickView',
|
|
|
- 'clickBatchModify',
|
|
|
-])
|
|
|
-
|
|
|
-const selectedRowKeys = defineModel<(number | string)[]>('selectedRowKeys', {
|
|
|
- default: () => reactive([]),
|
|
|
-})
|
|
|
-
|
|
|
-const selectedRows = defineModel<T[]>('selectedRows', {
|
|
|
- default: () => reactive([]),
|
|
|
-})
|
|
|
-
|
|
|
-const route = useRoute()
|
|
|
-
|
|
|
-const dataSource: Ref<T[]> = ref([])
|
|
|
-const expandKeysList: Ref<Key[]> = ref([])
|
|
|
-
|
|
|
-watch(dataSource, () => {
|
|
|
- if (!props.expandAll)
|
|
|
- return
|
|
|
-
|
|
|
- const res: Key[] = []
|
|
|
-
|
|
|
- function buildKeysList(record) {
|
|
|
- record.children?.forEach(v => {
|
|
|
- buildKeysList(v)
|
|
|
- })
|
|
|
- res.push(record[props.rowKey])
|
|
|
- }
|
|
|
-
|
|
|
- dataSource.value.forEach(v => {
|
|
|
- buildKeysList(v)
|
|
|
- })
|
|
|
-
|
|
|
- expandKeysList.value = res
|
|
|
-})
|
|
|
-
|
|
|
-// eslint-disable-next-line ts/no-explicit-any
|
|
|
-const rowsKeyIndexMap: Ref<Record<number, any>> = ref({})
|
|
|
-const loading = ref(true)
|
|
|
-// eslint-disable-next-line ts/no-explicit-any
|
|
|
-const selectedRecords: Ref<Record<any, any>> = ref({})
|
|
|
-
|
|
|
-// This can be useful if there are more than one StdTable in the same page.
|
|
|
-// eslint-disable-next-line sonarjs/pseudo-random
|
|
|
-const randomId = ref(Math.random().toString(36).substring(2, 8))
|
|
|
-const updateFilter = ref(0)
|
|
|
-const init = ref(false)
|
|
|
-
|
|
|
-const pagination: Pagination = reactive({
|
|
|
- total: 1,
|
|
|
- per_page: 10,
|
|
|
- current_page: 1,
|
|
|
- total_pages: 1,
|
|
|
-})
|
|
|
-
|
|
|
-const filterParams = ref({})
|
|
|
-
|
|
|
-const paginationParams = ref({
|
|
|
- page: 1,
|
|
|
- page_size: 20,
|
|
|
-})
|
|
|
-
|
|
|
-const sortParams = ref({
|
|
|
- order: 'desc' as 'desc' | 'asc' | undefined,
|
|
|
- sort_by: '' as Key | readonly Key[] | undefined,
|
|
|
-})
|
|
|
-
|
|
|
-const params = computed(() => {
|
|
|
- return {
|
|
|
- ...filterParams.value,
|
|
|
- ...sortParams.value,
|
|
|
- ...props.getParams,
|
|
|
- ...props.overwriteParams,
|
|
|
- trash: props.inTrash,
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- selectedRows.value.forEach(v => {
|
|
|
- selectedRecords.value[v[props.rowKey]] = v
|
|
|
- })
|
|
|
-})
|
|
|
-
|
|
|
-const searchColumns = computed(() => {
|
|
|
- const _searchColumns: Column[] = []
|
|
|
-
|
|
|
- props.columns.forEach((column: Column) => {
|
|
|
- if (column.search) {
|
|
|
- if (typeof column.search === 'object') {
|
|
|
- _searchColumns.push({
|
|
|
- ...column,
|
|
|
- edit: column.search,
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- else {
|
|
|
- _searchColumns.push({ ...column })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- return _searchColumns
|
|
|
-})
|
|
|
-
|
|
|
-const pithyColumns = computed<Column[]>(() => {
|
|
|
- if (props.pithy)
|
|
|
- return getPithyColumns(props.columns)
|
|
|
-
|
|
|
- return props.columns?.filter(c => {
|
|
|
- return !c.hiddenInTable
|
|
|
- })
|
|
|
-})
|
|
|
-
|
|
|
-const batchColumns = computed(() => {
|
|
|
- return props.columns?.filter(column => column.batch) || []
|
|
|
-})
|
|
|
-
|
|
|
-const radioColumns = computed(() => {
|
|
|
- return props.columns?.filter(column => column.radio) || []
|
|
|
-})
|
|
|
-
|
|
|
-const get_list = debounce(_get_list, 100, {
|
|
|
- leading: false,
|
|
|
- trailing: true,
|
|
|
-})
|
|
|
-
|
|
|
-onMounted(async () => {
|
|
|
- if (!props.disableQueryParams) {
|
|
|
- filterParams.value = {
|
|
|
- ...route.query,
|
|
|
- ...props.getParams,
|
|
|
- }
|
|
|
- paginationParams.value.page = Number(route.query.page) || 1
|
|
|
- paginationParams.value.page_size = Number(route.query.page_size) || 20
|
|
|
- }
|
|
|
-
|
|
|
- await nextTick()
|
|
|
-
|
|
|
- get_list()
|
|
|
-
|
|
|
- if (props.sortable)
|
|
|
- initSortable()
|
|
|
-
|
|
|
- init.value = true
|
|
|
-})
|
|
|
-
|
|
|
-defineExpose({
|
|
|
- get_list,
|
|
|
- pagination,
|
|
|
- resetSelection,
|
|
|
- loading,
|
|
|
-})
|
|
|
-
|
|
|
-function destroy(id: number | string) {
|
|
|
- props.api!.destroy(id, { permanent: props.inTrash }).then(() => {
|
|
|
- get_list()
|
|
|
- message.success($gettext('Deleted successfully'))
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-function recover(id: number | string) {
|
|
|
- props.api.recover(id).then(() => {
|
|
|
- message.success($gettext('Recovered Successfully'))
|
|
|
- get_list()
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// eslint-disable-next-line ts/no-explicit-any
|
|
|
-function buildIndexMap(data: any, level: number = 0, index: number = 0, total: number[] = []) {
|
|
|
- if (data && data.length > 0) {
|
|
|
- // eslint-disable-next-line ts/no-explicit-any
|
|
|
- data.forEach((v: any) => {
|
|
|
- v.level = level
|
|
|
-
|
|
|
- const current_indexes = [...total, index++]
|
|
|
-
|
|
|
- rowsKeyIndexMap.value[v.id] = current_indexes
|
|
|
- if (v.children)
|
|
|
- buildIndexMap(v.children, level + 1, 0, current_indexes)
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-async function _get_list() {
|
|
|
- dataSource.value = []
|
|
|
- loading.value = true
|
|
|
-
|
|
|
- // eslint-disable-next-line ts/no-explicit-any
|
|
|
- await props.api?.get_list({ ...params.value, ...paginationParams.value }).then(async (r: GetListResponse<any>) => {
|
|
|
- dataSource.value = r.data
|
|
|
- rowsKeyIndexMap.value = {}
|
|
|
- if (props.sortable)
|
|
|
- buildIndexMap(r.data)
|
|
|
-
|
|
|
- if (r.pagination)
|
|
|
- Object.assign(pagination, r.pagination)
|
|
|
- })
|
|
|
-
|
|
|
- loading.value = false
|
|
|
-}
|
|
|
-
|
|
|
-// eslint-disable-next-line ts/no-explicit-any
|
|
|
-function onTableChange(_pagination: TablePaginationConfig, filters: Record<string, FilterValue>, sorter: SorterResult | SorterResult<any>[]) {
|
|
|
- if (sorter) {
|
|
|
- sorter = sorter as SorterResult
|
|
|
- selectedRowKeys.value = []
|
|
|
- sortParams.value.sort_by = sorter.field
|
|
|
- switch (sorter.order) {
|
|
|
- case 'ascend':
|
|
|
- sortParams.value.order = 'asc'
|
|
|
- break
|
|
|
- case 'descend':
|
|
|
- sortParams.value.order = 'desc'
|
|
|
- break
|
|
|
- default:
|
|
|
- sortParams.value.order = undefined
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if (filters) {
|
|
|
- Object.keys(filters).forEach((v: string) => {
|
|
|
- params[v] = filters[v]
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- if (_pagination)
|
|
|
- selectedRowKeys.value = []
|
|
|
-}
|
|
|
-
|
|
|
-function expandedTable(keys: Key[]) {
|
|
|
- expandKeysList.value = keys
|
|
|
-}
|
|
|
-
|
|
|
-// eslint-disable-next-line ts/no-explicit-any
|
|
|
-async function onSelect(record: any, selected: boolean, _selectedRows: any[]) {
|
|
|
- // console.log('onSelect', record, selected, _selectedRows)
|
|
|
- if (props.selectionType === 'checkbox' || props.exportExcel || batchColumns.value.length > 0 || props.bulkActions) {
|
|
|
- if (selected) {
|
|
|
- _selectedRows.forEach(v => {
|
|
|
- if (v) {
|
|
|
- if (selectedRecords.value[v[props.rowKey]] === undefined)
|
|
|
- selectedRowKeys.value.push(v[props.rowKey])
|
|
|
-
|
|
|
- selectedRecords.value[v[props.rowKey]] = v
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- else {
|
|
|
- selectedRowKeys.value.splice(selectedRowKeys.value.indexOf(record[props.rowKey]), 1)
|
|
|
- delete selectedRecords.value[record[props.rowKey]]
|
|
|
- }
|
|
|
- await nextTick()
|
|
|
- selectedRows.value = [...selectedRowKeys.value.map(v => selectedRecords.value[v])]
|
|
|
- }
|
|
|
- else if (selected) {
|
|
|
- selectedRowKeys.value = record[props.rowKey]
|
|
|
- selectedRows.value = [record]
|
|
|
- }
|
|
|
- else {
|
|
|
- selectedRowKeys.value = []
|
|
|
- selectedRows.value = []
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// eslint-disable-next-line ts/no-explicit-any
|
|
|
-async function onSelectAll(selected: boolean, _selectedRows: any[], changeRows: any[]) {
|
|
|
- // console.log('onSelectAll', selected, selectedRows, changeRows)
|
|
|
- // eslint-disable-next-line ts/no-explicit-any
|
|
|
- changeRows.forEach((v: any) => {
|
|
|
- if (v) {
|
|
|
- if (selected) {
|
|
|
- selectedRowKeys.value.push(v[props.rowKey])
|
|
|
- selectedRecords.value[v[props.rowKey]] = v
|
|
|
- }
|
|
|
- else {
|
|
|
- delete selectedRecords.value[v[props.rowKey]]
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- if (!selected) {
|
|
|
- selectedRowKeys.value.splice(0, selectedRowKeys.value.length, ...selectedRowKeys.value.filter(v => selectedRecords.value[v]))
|
|
|
- }
|
|
|
-
|
|
|
- // console.log(selectedRowKeysBuffer.value, selectedRecords.value)
|
|
|
-
|
|
|
- await nextTick()
|
|
|
- selectedRows.value.splice(0, selectedRows.value.length, ...selectedRowKeys.value.map(v => selectedRecords.value[v]))
|
|
|
-}
|
|
|
-
|
|
|
-function resetSelection() {
|
|
|
- selectedRowKeys.value = reactive([])
|
|
|
- selectedRows.value = reactive([])
|
|
|
- selectedRecords.value = reactive({})
|
|
|
-}
|
|
|
-
|
|
|
-const router = useRouter()
|
|
|
-
|
|
|
-async function resetSearch() {
|
|
|
- filterParams.value = {}
|
|
|
- updateFilter.value++
|
|
|
-}
|
|
|
-
|
|
|
-watch(params, async v => {
|
|
|
- if (!init.value)
|
|
|
- return
|
|
|
-
|
|
|
- paginationParams.value = {
|
|
|
- page: 1,
|
|
|
- page_size: paginationParams.value.page_size,
|
|
|
- }
|
|
|
-
|
|
|
- await nextTick()
|
|
|
-
|
|
|
- if (!props.disableQueryParams)
|
|
|
- await router.push({ query: { ...v as unknown as RouteParams, ...paginationParams.value } })
|
|
|
- else
|
|
|
- get_list()
|
|
|
-}, { deep: true })
|
|
|
-
|
|
|
-watch(() => route.query, () => {
|
|
|
- if (init.value)
|
|
|
- get_list()
|
|
|
-})
|
|
|
-
|
|
|
-const rowSelection = computed(() => {
|
|
|
- if (batchColumns.value.length > 0 || props.selectionType || props.exportExcel || props.bulkActions) {
|
|
|
- return {
|
|
|
- selectedRowKeys: unref(selectedRowKeys),
|
|
|
- onSelect,
|
|
|
- onSelectAll,
|
|
|
- getCheckboxProps: props?.getCheckboxProps,
|
|
|
- type: (batchColumns.value.length > 0 || props.exportExcel || props.bulkActions) ? 'checkbox' : props.selectionType,
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- return null
|
|
|
- }
|
|
|
-}) as ComputedRef<TableProps['rowSelection']>
|
|
|
-
|
|
|
-const hasSelectedRow = computed(() => {
|
|
|
- return batchColumns.value.length > 0 && selectedRowKeys.value.length > 0
|
|
|
-})
|
|
|
-
|
|
|
-function clickBatchEdit() {
|
|
|
- emit('clickBatchModify', batchColumns.value, selectedRowKeys.value, selectedRows.value)
|
|
|
-}
|
|
|
-
|
|
|
-function initSortable() {
|
|
|
- useSortable(props, randomId, dataSource, rowsKeyIndexMap, expandKeysList)
|
|
|
-}
|
|
|
-
|
|
|
-async function changePage(page: number, page_size: number) {
|
|
|
- if (page) {
|
|
|
- paginationParams.value = {
|
|
|
- page,
|
|
|
- page_size,
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- paginationParams.value = {
|
|
|
- page: 1,
|
|
|
- page_size,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- await nextTick()
|
|
|
-
|
|
|
- if (!props.disableQueryParams)
|
|
|
- await router.push({ query: { ...route.query, ...paginationParams.value } })
|
|
|
-
|
|
|
- get_list()
|
|
|
-}
|
|
|
-
|
|
|
-const paginationSize = computed(() => {
|
|
|
- if (props.size === 'small')
|
|
|
- return 'small'
|
|
|
- else
|
|
|
- return 'default'
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<template>
|
|
|
- <div class="std-table">
|
|
|
- <div v-if="radioColumns.length">
|
|
|
- <AFormItem
|
|
|
- v-for="column in radioColumns"
|
|
|
- :key="column.dataIndex as PropertyKey"
|
|
|
- :label="labelRender(column.title)"
|
|
|
- >
|
|
|
- <ARadioGroup v-model:value="params[column.dataIndex as string]">
|
|
|
- <ARadioButton :value="undefined">
|
|
|
- {{ $gettext('All') }}
|
|
|
- </ARadioButton>
|
|
|
- <ARadioButton
|
|
|
- v-for="(value, key) in column.mask"
|
|
|
- :key
|
|
|
- :value="key"
|
|
|
- >
|
|
|
- {{ labelRender(value) }}
|
|
|
- </ARadioButton>
|
|
|
- </ARadioGroup>
|
|
|
- </AFormItem>
|
|
|
- </div>
|
|
|
- <StdDataEntry
|
|
|
- v-if="!disableSearch && searchColumns.length"
|
|
|
- :key="updateFilter"
|
|
|
- :data-list="searchColumns"
|
|
|
- :data-source="filterParams"
|
|
|
- type="search"
|
|
|
- layout="inline"
|
|
|
- >
|
|
|
- <template #action>
|
|
|
- <ASpace class="action-btn">
|
|
|
- <AButton @click="resetSearch">
|
|
|
- {{ $gettext('Reset') }}
|
|
|
- </AButton>
|
|
|
- <AButton
|
|
|
- v-if="hasSelectedRow"
|
|
|
- @click="clickBatchEdit"
|
|
|
- >
|
|
|
- {{ $gettext('Batch Modify') }}
|
|
|
- </AButton>
|
|
|
- <slot name="append-search" />
|
|
|
- </ASpace>
|
|
|
- </template>
|
|
|
- </StdDataEntry>
|
|
|
- <StdBulkActions
|
|
|
- v-if="bulkActions"
|
|
|
- v-model:selected-row-keys="selectedRowKeys"
|
|
|
- :api
|
|
|
- :in-trash="inTrash"
|
|
|
- :actions="bulkActions"
|
|
|
- @on-success="() => { resetSelection(); get_list() }"
|
|
|
- />
|
|
|
- <ATable
|
|
|
- :id="`std-table-${randomId}`"
|
|
|
- :columns="pithyColumns"
|
|
|
- :data-source="dataSource"
|
|
|
- :loading="loading"
|
|
|
- :pagination="false"
|
|
|
- :row-key="rowKey"
|
|
|
- :row-selection="rowSelection"
|
|
|
- :scroll="{ x: scrollX ?? true }"
|
|
|
- :size="size as any"
|
|
|
- :expanded-row-keys="expandKeysList"
|
|
|
- @change="onTableChange"
|
|
|
- @expanded-rows-change="expandedTable"
|
|
|
- >
|
|
|
- <template #bodyCell="{ text, record, column }: {text: any, record: Record<string, any>, column: any}">
|
|
|
- <template v-if="column.handle === true">
|
|
|
- <span class="ant-table-drag-icon"><HolderOutlined /></span>
|
|
|
- {{ text }}
|
|
|
- </template>
|
|
|
- <div v-if="column.dataIndex === 'action'" class="action">
|
|
|
- <template v-if="!props.disableView && !inTrash">
|
|
|
- <AButton
|
|
|
- type="link"
|
|
|
- size="small"
|
|
|
- @click="$emit('clickView', record[props.rowKey], record)"
|
|
|
- >
|
|
|
- {{ $gettext('View') }}
|
|
|
- </AButton>
|
|
|
- </template>
|
|
|
-
|
|
|
- <template v-if="!props.disableModify && !inTrash">
|
|
|
- <AButton
|
|
|
- type="link"
|
|
|
- size="small"
|
|
|
- @click="$emit('clickEdit', record[props.rowKey], record)"
|
|
|
- >
|
|
|
- {{ $gettext('Modify') }}
|
|
|
- </AButton>
|
|
|
- </template>
|
|
|
-
|
|
|
- <slot
|
|
|
- name="actions"
|
|
|
- :record="record"
|
|
|
- />
|
|
|
-
|
|
|
- <template v-if="!props.disableDelete">
|
|
|
- <APopconfirm
|
|
|
- v-if="!inTrash"
|
|
|
- :cancel-text="$gettext('No')"
|
|
|
- :ok-text="$gettext('Ok')"
|
|
|
- :title="$gettext('Are you sure you want to delete this item?')"
|
|
|
- @confirm="destroy(record[rowKey])"
|
|
|
- >
|
|
|
- <AButton
|
|
|
- type="link"
|
|
|
- size="small"
|
|
|
- >
|
|
|
- {{ $gettext('Delete') }}
|
|
|
- </AButton>
|
|
|
- </APopconfirm>
|
|
|
- <APopconfirm
|
|
|
- v-else
|
|
|
- :cancel-text="$gettext('No')"
|
|
|
- :ok-text="$gettext('Ok')"
|
|
|
- :title="$gettext('Are you sure you want to recover this item?')"
|
|
|
- @confirm="recover(record[rowKey])"
|
|
|
- >
|
|
|
- <AButton
|
|
|
- type="link"
|
|
|
- size="small"
|
|
|
- >
|
|
|
- {{ $gettext('Recover') }}
|
|
|
- </AButton>
|
|
|
- </APopconfirm>
|
|
|
- <APopconfirm
|
|
|
- v-if="inTrash"
|
|
|
- :cancel-text="$gettext('No')"
|
|
|
- :ok-text="$gettext('Ok')"
|
|
|
- :title="$gettext('Are you sure you want to delete this item permanently?')"
|
|
|
- @confirm="destroy(record[rowKey])"
|
|
|
- >
|
|
|
- <AButton
|
|
|
- type="link"
|
|
|
- size="small"
|
|
|
- >
|
|
|
- {{ $gettext('Delete Permanently') }}
|
|
|
- </AButton>
|
|
|
- </APopconfirm>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </ATable>
|
|
|
- <StdPagination
|
|
|
- :size="paginationSize"
|
|
|
- :loading="loading"
|
|
|
- :pagination="pagination"
|
|
|
- @change="changePage"
|
|
|
- @change-page-size="onTableChange"
|
|
|
- />
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<style lang="less">
|
|
|
-.ant-table-scroll {
|
|
|
- .ant-table-body {
|
|
|
- overflow-x: auto !important;
|
|
|
- overflow-y: hidden !important;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.std-table {
|
|
|
- overflow-x: hidden !important;
|
|
|
- overflow-y: hidden !important;
|
|
|
-}
|
|
|
-</style>
|
|
|
-
|
|
|
-<style lang="less" scoped>
|
|
|
-.ant-form {
|
|
|
- margin: 10px 0 20px 0;
|
|
|
-}
|
|
|
-
|
|
|
-.ant-slider {
|
|
|
- min-width: 90px;
|
|
|
-}
|
|
|
-
|
|
|
-.action-btn {
|
|
|
- // min-height: 50px;
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- align-items: flex-start;
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.ant-form-inline .ant-form-item) {
|
|
|
- margin-bottom: 10px;
|
|
|
-}
|
|
|
-
|
|
|
-.ant-divider {
|
|
|
- &:last-child {
|
|
|
- display: none;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.action {
|
|
|
- @media (max-width: 768px) {
|
|
|
- .ant-divider-vertical {
|
|
|
- display: none;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|
|
|
-
|
|
|
-<style lang="less">
|
|
|
-.ant-table-drag-icon {
|
|
|
- float: left;
|
|
|
- margin-right: 16px;
|
|
|
- cursor: grab;
|
|
|
-}
|
|
|
-
|
|
|
-.sortable-ghost *, .sortable-chosen * {
|
|
|
- cursor: grabbing !important;
|
|
|
-}
|
|
|
-</style>
|