wip: crud table

This commit is contained in:
张传龙
2022-09-01 14:53:18 +08:00
parent 9ea8ffd7fd
commit f2e2fc6819
4 changed files with 330 additions and 98 deletions

View File

@@ -5,8 +5,12 @@
</n-space>
<div flex-shrink-0>
<n-button secondary type="primary">重置</n-button>
<n-button ml-20 type="primary">搜索</n-button>
<n-button secondary type="primary" @click="emit('reset')">重置</n-button>
<n-button ml-20 type="primary" @click="emit('search')">搜索</n-button>
</div>
</div>
</template>
<script setup>
const emit = defineEmits(['search', 'reset'])
</script>

View File

@@ -1,16 +1,106 @@
<template>
<QueryBar v-if="$slots.queryBar" mb-30>
<QueryBar v-if="$slots.queryBar" mb-30 @search="handleSearch" @reset="handleReset">
<slot name="queryBar" />
</QueryBar>
<slot />
<n-data-table
:remote="remote"
:loading="loading"
:scroll-x="scrollX"
:columns="columns"
:data="tableData"
:row-key="(row) => row[rowKey]"
:pagination="isPagination ? pagination : false"
@update:checked-row-keys="onChecked"
@update:page="onPageChange"
/>
</template>
<script setup>
const props = defineProps({
/**
* @remote true: 后端分页 false 前端分页
*/
remote: {
type: Boolean,
default: true,
},
/**
* @remote 是否分页
*/
isPagination: {
type: Boolean,
default: true,
},
scrollX: {
type: Number,
default: 1200,
},
rowKey: {
type: String,
default: 'id',
},
columns: {
type: Array,
required: true,
},
queryForm: {
type: Object,
required: true,
},
getData: {
type: Function,
required: true,
},
})
const emit = defineEmits(['update:queryForm', 'onChecked'])
const loading = ref(false)
const initQuery = { ...props.queryForm }
const tableData = ref([])
const showModal = ref(true)
const segmented = {
content: 'soft',
footer: 'soft',
const pagination = reactive({ page: 1, pageSize: 10, itemCount: 100 })
async function handleQuery(extraParams = {}) {
try {
loading.value = true
const res = await props.getData(
{ ...props.queryForm, ...extraParams },
{ pageNo: pagination.page, pageSize: pagination.pageSize }
)
tableData.value = res?.pageData || res
pagination.itemCount = res.total ?? res.length
} catch (error) {
tableData.value = []
pagination.itemCount = 0
$message.error(error.message)
} finally {
loading.value = false
}
}
function handleSearch() {
pagination.page = 1
handleQuery()
}
async function handleReset() {
emit('update:queryForm', { ...initQuery })
await nextTick()
pagination.page = 1
handleQuery()
}
function onChecked(rowKeys) {
if (props.columns.some((item) => item.type === 'selection')) {
emit('onChecked', rowKeys)
}
}
function onPageChange(currentPage) {
pagination.page = currentPage
if (props.remote) {
handleQuery()
}
}
defineExpose({
handleSearch,
handleReset,
})
</script>

View File

@@ -6,51 +6,172 @@
</n-button>
</template>
<CrudTable>
<CrudTable
ref="$table"
v-model:query-form="queryForm"
:scroll-x="1600"
:columns="columns"
:get-data="getTableData"
@on-checked="onChecked"
>
<template #queryBar>
<QueryBarItem label="标题" :label-width="50">
<n-input v-model:value="queryForm.title" type="text" placeholder="请输入标题" />
</QueryBarItem>
</template>
<n-data-table
:loading="loading"
:scroll-x="1600"
:data="tableData.filter((item) => item.title.includes(queryForm.title))"
:columns="columns"
:pagination="pagination"
:row-key="(row) => row.id"
@update:checked-row-keys="handleCheck"
/>
<!-- 新增/编辑/查看 -->
<CrudModal v-model:visible="modalVisible" :title="modalTitle" @on-save="handleSave"> 内容 </CrudModal>
</CrudTable>
<!-- 新增/编辑/查看 -->
<CrudModal v-model:visible="modalVisible" :title="modalTitle" @on-save="handleSave"> 内容 </CrudModal>
</CommonPage>
</template>
<script setup>
import { usePostTable } from './usePostTable'
import { NButton, NSwitch } from 'naive-ui'
import { formatDateTime } from '@/utils'
import { renderIcon } from '@/utils/icon'
import api from './api'
const queryForm = reactive({
const $table = ref(null)
const queryForm = ref({
title: '',
})
async function getTableData(query = {}, pagination = {}) {
const { pageSize = 10, pageNo = 1 } = pagination
try {
// * 参数可自定义,如不需要后端分页则可以不传 pagination 相关参数
const res = await api.getPosts({ ...query, pageSize, pageNo })
if (res.code === 0) {
return Promise.resolve(res.data)
}
} catch (error) {
return Promise.reject(error)
}
}
// 选中事件
function onChecked(rowKeys) {
if (rowKeys.length) $message.info(`选中${rowKeys.join(' ')}`)
}
const columns = [
{ type: 'selection' },
{ title: '标题', key: 'title', width: 150, ellipsis: { tooltip: true } },
{ title: '分类', key: 'category', width: 80, ellipsis: { tooltip: true } },
{
title: '描述',
key: 'description',
width: 200,
ellipsis: { tooltip: true },
},
{ title: '创建人', key: 'author', width: 80 },
{
title: '创建时间',
key: 'createDate',
width: 150,
render(row) {
return h('span', formatDateTime(row['createDate']))
},
},
{
title: '最后更新时间',
key: 'updateDate',
width: 150,
render(row) {
return h('span', formatDateTime(row['updateDate']))
},
},
{
title: '推荐',
key: 'isRecommend',
width: 120,
align: 'center',
fixed: 'right',
render(row) {
return h(NSwitch, {
size: 'small',
value: row['isRecommend'],
rubberBand: false,
loading: !!row.recommending,
onUpdateValue: () => handleRecommend(row),
})
},
},
{
title: '发布',
key: 'isPublish',
width: 120,
align: 'center',
fixed: 'right',
render(row) {
return h(NSwitch, {
size: 'small',
rubberBand: false,
value: row['isPublish'],
loading: !!row.publishing,
onUpdateValue: () => handlePublish(row),
})
},
},
{
title: '操作',
key: 'actions',
width: 200,
align: 'center',
fixed: 'right',
render(row) {
return [
h(
NButton,
{
size: 'small',
type: 'primary',
onClick: () => handleEdit(row),
},
{ default: () => '编辑', icon: renderIcon('material-symbols:edit-outline', { size: 14 }) }
),
h(
NButton,
{
size: 'small',
type: 'error',
style: 'margin-left: 15px;',
onClick: () => handleDelete(row),
},
{ default: () => '删除', icon: renderIcon('material-symbols:delete-outline', { size: 14 }) }
),
]
},
},
]
onMounted(() => {
$table.value?.handleSearch()
})
const modalVisible = ref(false)
const modalTitle = ref('新增文章')
const pagination = reactive({ pageSize: 10 })
const { loading, columns, tableData, initColumns, initTableData } = usePostTable()
function handleDelete(row) {
if (row && row.id) {
$dialog.confirm({
content: '确定删除?',
confirm() {
$message.success('删除成功')
initTableData()
},
cancel() {
$message.success('已取消')
},
})
}
}
onBeforeMount(() => {
initColumns()
initTableData()
})
function handleEdit(row) {
modalTitle.value = '编辑文章'
modalVisible.value = true
}
function handleSave() {
modalVisible.value = false
}
function handleCheck(rowKeys) {
if (rowKeys.length) $message.info(`选中${rowKeys.join(' ')}`)
}
</script>