feat: 新增新闻管理功能,包括新闻的创建、编辑和列表展示,更新相关路由和类型定义
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
"@better-scroll/core": "2.5.1",
|
||||
"@elysiajs/eden": "^1.4.5",
|
||||
"@iconify/vue": "5.0.0",
|
||||
"@riwa/api-types": "http://192.168.1.7:9527/api/riwa-eden-0.0.102.tgz",
|
||||
"@riwa/api-types": "http://192.168.1.7:9527/api/riwa-eden-0.0.107.tgz",
|
||||
"@sa/axios": "workspace:*",
|
||||
"@sa/color": "workspace:*",
|
||||
"@sa/hooks": "workspace:*",
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -18,8 +18,8 @@ importers:
|
||||
specifier: 5.0.0
|
||||
version: 5.0.0(vue@3.5.25(typescript@5.9.3))
|
||||
'@riwa/api-types':
|
||||
specifier: http://192.168.1.7:9527/api/riwa-eden-0.0.102.tgz
|
||||
version: '@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.102.tgz(@elysiajs/eden@1.4.5(elysia@1.4.19(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))'
|
||||
specifier: http://192.168.1.7:9527/api/riwa-eden-0.0.107.tgz
|
||||
version: '@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.107.tgz(@elysiajs/eden@1.4.5(elysia@1.4.19(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))'
|
||||
'@sa/axios':
|
||||
specifier: workspace:*
|
||||
version: link:packages/axios
|
||||
@@ -1083,9 +1083,9 @@ packages:
|
||||
'@quansync/fs@0.1.6':
|
||||
resolution: {integrity: sha512-zoA8SqQO11qH9H8FCBR7NIbowYARIPmBz3nKjgAaOUDi/xPAAu1uAgebtV7KXHTc6CDZJVRZ1u4wIGvY5CWYaw==}
|
||||
|
||||
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.102.tgz':
|
||||
resolution: {tarball: http://192.168.1.7:9527/api/riwa-eden-0.0.102.tgz}
|
||||
version: 0.0.102
|
||||
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.107.tgz':
|
||||
resolution: {tarball: http://192.168.1.7:9527/api/riwa-eden-0.0.107.tgz}
|
||||
version: 0.0.107
|
||||
peerDependencies:
|
||||
'@elysiajs/eden': ^1.4.5
|
||||
|
||||
@@ -5080,7 +5080,7 @@ snapshots:
|
||||
dependencies:
|
||||
quansync: 0.3.0
|
||||
|
||||
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.102.tgz(@elysiajs/eden@1.4.5(elysia@1.4.19(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))':
|
||||
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.107.tgz(@elysiajs/eden@1.4.5(elysia@1.4.19(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))':
|
||||
dependencies:
|
||||
'@elysiajs/eden': 1.4.5(elysia@1.4.19(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3))
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
||||
bank: () => import("@/views/bank/index.vue"),
|
||||
deposit_fiat: () => import("@/views/deposit/fiat/index.vue"),
|
||||
home: () => import("@/views/home/index.vue"),
|
||||
news: () => import("@/views/news/index.vue"),
|
||||
notification: () => import("@/views/notification/index.vue"),
|
||||
rwa_product: () => import("@/views/rwa/product/index.vue"),
|
||||
rwa_producttype: () => import("@/views/rwa/productType/index.vue"),
|
||||
|
||||
@@ -116,6 +116,15 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
hideInMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'news',
|
||||
path: '/news',
|
||||
component: 'layout.base$view.news',
|
||||
meta: {
|
||||
title: 'news',
|
||||
i18nKey: 'route.news'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'notification',
|
||||
path: '/notification',
|
||||
|
||||
@@ -173,6 +173,7 @@ const routeMap: RouteMap = {
|
||||
"home": "/home",
|
||||
"iframe-page": "/iframe-page/:url",
|
||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
||||
"news": "/news",
|
||||
"notification": "/notification",
|
||||
"rwa": "/rwa",
|
||||
"rwa_product": "/rwa/product",
|
||||
|
||||
3
src/typings/elegant-router.d.ts
vendored
3
src/typings/elegant-router.d.ts
vendored
@@ -27,6 +27,7 @@ declare module "@elegant-router/types" {
|
||||
"home": "/home";
|
||||
"iframe-page": "/iframe-page/:url";
|
||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||
"news": "/news";
|
||||
"notification": "/notification";
|
||||
"rwa": "/rwa";
|
||||
"rwa_product": "/rwa/product";
|
||||
@@ -82,6 +83,7 @@ declare module "@elegant-router/types" {
|
||||
| "home"
|
||||
| "iframe-page"
|
||||
| "login"
|
||||
| "news"
|
||||
| "notification"
|
||||
| "rwa"
|
||||
| "tokenization"
|
||||
@@ -113,6 +115,7 @@ declare module "@elegant-router/types" {
|
||||
| "bank"
|
||||
| "deposit_fiat"
|
||||
| "home"
|
||||
| "news"
|
||||
| "notification"
|
||||
| "rwa_product"
|
||||
| "rwa_producttype"
|
||||
|
||||
200
src/views/news/components/add.vue
Normal file
200
src/views/news/components/add.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, h, ref, useTemplateRef } from 'vue';
|
||||
import type { FormInst, FormRules } from 'naive-ui';
|
||||
import { NInput, useDialog } from 'naive-ui';
|
||||
import { client, safeClient } from '@/service/api';
|
||||
import UploadS3 from '@/components/upload/index.vue';
|
||||
|
||||
defineOptions({ name: 'AddNews' });
|
||||
|
||||
type Body = CommonType.TreatyBody<typeof client.api.admin.news.post>;
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'close'): void;
|
||||
}>();
|
||||
|
||||
const formRef = useTemplateRef<FormInst | null>('formRef');
|
||||
const dialog = useDialog();
|
||||
|
||||
const form = ref<Body>({
|
||||
title: '',
|
||||
content: '',
|
||||
categoryId: '',
|
||||
attachmentIds: [],
|
||||
isPinned: false
|
||||
});
|
||||
|
||||
// 获取分类列表
|
||||
const { data: categories, execute: refreshCategories } = safeClient(() =>
|
||||
client.api.admin.news_categories.get({
|
||||
query: {
|
||||
pageIndex: 1,
|
||||
pageSize: 100
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const categoryOptions = computed(
|
||||
() =>
|
||||
categories.value?.data.map(cat => ({
|
||||
label: cat.name,
|
||||
value: cat.id
|
||||
})) || []
|
||||
);
|
||||
|
||||
// 新增分类
|
||||
function handleAddCategory() {
|
||||
const categoryName = ref('');
|
||||
|
||||
dialog.create({
|
||||
title: '新增分类',
|
||||
content: () =>
|
||||
h('div', { class: 'py-4' }, [
|
||||
h('div', { class: 'mb-2 text-14px' }, '分类名称'),
|
||||
h(NInput, {
|
||||
value: categoryName.value,
|
||||
placeholder: '请输入分类名称',
|
||||
'onUpdate:value': (val: string) => {
|
||||
categoryName.value = val;
|
||||
}
|
||||
})
|
||||
]),
|
||||
positiveText: '创建',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (!categoryName.value.trim()) {
|
||||
window.$message?.error('请输入分类名称');
|
||||
return false;
|
||||
}
|
||||
const { data } = await safeClient(() =>
|
||||
client.api.admin.news_categories.post({
|
||||
name: categoryName.value
|
||||
})
|
||||
);
|
||||
if (data) {
|
||||
window.$message?.success('分类创建成功');
|
||||
await refreshCategories();
|
||||
form.value.categoryId = data.value?.id;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const rules: FormRules = {
|
||||
title: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入新闻标题',
|
||||
trigger: ['blur', 'input']
|
||||
},
|
||||
{
|
||||
min: 2,
|
||||
max: 200,
|
||||
message: '标题长度应在2-200个字符之间',
|
||||
trigger: ['blur', 'input']
|
||||
}
|
||||
],
|
||||
content: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入新闻内容',
|
||||
trigger: ['blur', 'input']
|
||||
},
|
||||
{
|
||||
min: 10,
|
||||
message: '内容至少10个字符',
|
||||
trigger: ['blur', 'input']
|
||||
}
|
||||
],
|
||||
categoryId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择新闻分类',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
async function handleSubmit() {
|
||||
formRef.value?.validate(async errors => {
|
||||
if (!errors) {
|
||||
const { data } = await safeClient(() =>
|
||||
client.api.admin.news.post({
|
||||
...form.value
|
||||
})
|
||||
);
|
||||
if (data) {
|
||||
window.$message?.success('新闻创建成功');
|
||||
emit('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NForm
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
>
|
||||
<NFormItem label="新闻标题" path="title">
|
||||
<NInput v-model:value="form.title" placeholder="请输入新闻标题" maxlength="200" show-count />
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="新闻分类" path="categoryId">
|
||||
<NSelect v-model:value="form.categoryId" :options="categoryOptions" placeholder="请选择新闻分类" class="flex-1">
|
||||
<template #action>
|
||||
<div class="px-3 py-2">
|
||||
<NButton size="small" type="primary" block @click.stop="handleAddCategory">
|
||||
<template #icon>
|
||||
<icon-ic-round-plus class="text-icon" />
|
||||
</template>
|
||||
新增分类
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</NSelect>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="新闻内容" path="content">
|
||||
<NInput
|
||||
v-model:value="form.content"
|
||||
type="textarea"
|
||||
placeholder="请输入新闻内容"
|
||||
:rows="10"
|
||||
maxlength="10000"
|
||||
show-count
|
||||
/>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="附件上传" path="attachmentIds">
|
||||
<UploadS3
|
||||
:model-value="form.attachmentIds || []"
|
||||
:max-size="20"
|
||||
:max-files="10"
|
||||
accept="*/*"
|
||||
placeholder="上传附件"
|
||||
:fetch-options="{ businessType: 'other' }"
|
||||
@update:model-value="evt => (form.attachmentIds = evt)"
|
||||
/>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="置顶显示" path="isPinned">
|
||||
<NSwitch v-model:value="form.isPinned">
|
||||
<template #checked>是</template>
|
||||
<template #unchecked>否</template>
|
||||
</NSwitch>
|
||||
</NFormItem>
|
||||
|
||||
<NSpace justify="end" class="mt-4">
|
||||
<NButton @click="$emit('close')">取消</NButton>
|
||||
<NButton type="primary" @click="handleSubmit">创建新闻</NButton>
|
||||
</NSpace>
|
||||
</NForm>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped></style>
|
||||
202
src/views/news/components/edit.vue
Normal file
202
src/views/news/components/edit.vue
Normal file
@@ -0,0 +1,202 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, h, ref, useTemplateRef } from 'vue';
|
||||
import type { FormInst, FormRules } from 'naive-ui';
|
||||
import { NInput, useDialog } from 'naive-ui';
|
||||
import type { Treaty } from '@elysiajs/eden';
|
||||
import { client, safeClient } from '@/service/api';
|
||||
import UploadS3 from '@/components/upload/index.vue';
|
||||
|
||||
defineOptions({ name: 'EditNews' });
|
||||
|
||||
type Data = Treaty.Data<typeof client.api.admin.news.get>['data'][number];
|
||||
type Body = CommonType.TreatyBody<typeof client.api.admin.news.post>;
|
||||
|
||||
const props = defineProps<{
|
||||
data: Data;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'close'): void;
|
||||
}>();
|
||||
|
||||
const formRef = useTemplateRef<FormInst | null>('formRef');
|
||||
const dialog = useDialog();
|
||||
|
||||
const form = ref<Body>({
|
||||
...props.data
|
||||
});
|
||||
|
||||
// 获取分类列表
|
||||
const { data: categories, execute: refreshCategories } = safeClient(() =>
|
||||
client.api.admin.news_categories.get({
|
||||
query: {
|
||||
pageIndex: 1,
|
||||
pageSize: 100
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const categoryOptions = computed(
|
||||
() =>
|
||||
categories.value?.data.map(cat => ({
|
||||
label: cat.name,
|
||||
value: cat.id
|
||||
})) || []
|
||||
);
|
||||
|
||||
// 新增分类
|
||||
function handleAddCategory() {
|
||||
const categoryName = ref('');
|
||||
|
||||
dialog.create({
|
||||
title: '新增分类',
|
||||
content: () =>
|
||||
h('div', { class: 'py-4' }, [
|
||||
h('div', { class: 'mb-2 text-14px' }, '分类名称'),
|
||||
h(NInput, {
|
||||
value: categoryName.value,
|
||||
placeholder: '请输入分类名称',
|
||||
'onUpdate:value': (val: string) => {
|
||||
categoryName.value = val;
|
||||
}
|
||||
})
|
||||
]),
|
||||
positiveText: '创建',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (!categoryName.value.trim()) {
|
||||
window.$message?.error('请输入分类名称');
|
||||
return false;
|
||||
}
|
||||
const { data } = await safeClient(() =>
|
||||
client.api.admin.news_categories.post({
|
||||
name: categoryName.value
|
||||
})
|
||||
);
|
||||
if (data) {
|
||||
window.$message?.success('分类创建成功');
|
||||
await refreshCategories();
|
||||
form.value.categoryId = data.value?.id;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const rules: FormRules = {
|
||||
title: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入新闻标题',
|
||||
trigger: ['blur', 'input']
|
||||
},
|
||||
{
|
||||
min: 2,
|
||||
max: 200,
|
||||
message: '标题长度应在2-200个字符之间',
|
||||
trigger: ['blur', 'input']
|
||||
}
|
||||
],
|
||||
content: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入新闻内容',
|
||||
trigger: ['blur', 'input']
|
||||
},
|
||||
{
|
||||
min: 10,
|
||||
message: '内容至少10个字符',
|
||||
trigger: ['blur', 'input']
|
||||
}
|
||||
],
|
||||
categoryId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择新闻分类',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
async function handleSubmit() {
|
||||
formRef.value?.validate(async errors => {
|
||||
if (!errors) {
|
||||
const { data } = await safeClient(() =>
|
||||
client.api.admin.news({ id: props.data.id }).patch({
|
||||
...form.value
|
||||
})
|
||||
);
|
||||
if (data) {
|
||||
window.$message?.success('新闻更新成功');
|
||||
emit('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NForm
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
>
|
||||
<NFormItem label="新闻标题" path="title">
|
||||
<NInput v-model:value="form.title" placeholder="请输入新闻标题" maxlength="200" show-count />
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="新闻分类" path="categoryId">
|
||||
<NSelect v-model:value="form.categoryId" :options="categoryOptions" placeholder="请选择新闻分类" class="flex-1">
|
||||
<template #action>
|
||||
<div class="px-3 py-2">
|
||||
<NButton size="small" type="primary" block @click.stop="handleAddCategory">
|
||||
<template #icon>
|
||||
<icon-ic-round-plus class="text-icon" />
|
||||
</template>
|
||||
新增分类
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</NSelect>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="新闻内容" path="content">
|
||||
<NInput
|
||||
v-model:value="form.content"
|
||||
type="textarea"
|
||||
placeholder="请输入新闻内容"
|
||||
:rows="10"
|
||||
maxlength="10000"
|
||||
show-count
|
||||
/>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="附件上传" path="attachmentIds">
|
||||
<UploadS3
|
||||
:model-value="form.attachmentIds || []"
|
||||
:max-size="20"
|
||||
:max-files="10"
|
||||
accept="*/*"
|
||||
placeholder="上传附件"
|
||||
:fetch-options="{ businessType: 'news_attachment' }"
|
||||
@update:model-value="evt => (form.attachmentIds = evt)"
|
||||
/>
|
||||
</NFormItem>
|
||||
|
||||
<NFormItem label="置顶显示" path="isPinned">
|
||||
<NSwitch v-model:value="form.isPinned">
|
||||
<template #checked>是</template>
|
||||
<template #unchecked>否</template>
|
||||
</NSwitch>
|
||||
</NFormItem>
|
||||
|
||||
<NSpace justify="end" class="mt-4">
|
||||
<NButton @click="$emit('close')">取消</NButton>
|
||||
<NButton type="primary" @click="handleSubmit">更新新闻</NButton>
|
||||
</NSpace>
|
||||
</NForm>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped></style>
|
||||
191
src/views/news/index.vue
Normal file
191
src/views/news/index.vue
Normal file
@@ -0,0 +1,191 @@
|
||||
<script lang="ts" setup>
|
||||
import { h, useTemplateRef } from 'vue';
|
||||
import { useDateFormat } from '@vueuse/core';
|
||||
import { NButton, NSelect, NSpace, NTag, useDialog } from 'naive-ui';
|
||||
import { client, safeClient } from '@/service/api';
|
||||
import type { TableBaseColumns, TableFetchData, TableFilterColumns, TableInst } from '@/components/table';
|
||||
import Add from './components/add.vue';
|
||||
import Edit from './components/edit.vue';
|
||||
|
||||
const dialog = useDialog();
|
||||
const tableInst = useTemplateRef<TableInst>('tableInst');
|
||||
const { data: categories } = safeClient(
|
||||
client.api.admin.news_categories.get({
|
||||
query: {
|
||||
pageIndex: 1,
|
||||
pageSize: 100
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const fetchData: TableFetchData = ({ pagination, filter }) => {
|
||||
return safeClient(() =>
|
||||
client.api.admin.news.get({
|
||||
query: {
|
||||
...pagination,
|
||||
...filter
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const columns: TableBaseColumns = [
|
||||
{
|
||||
title: '新闻标题',
|
||||
key: 'title',
|
||||
width: 250,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
key: 'category.name',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '内容预览',
|
||||
key: 'content',
|
||||
width: 300,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '附件数',
|
||||
key: 'attachmentIds',
|
||||
width: 100,
|
||||
render: (row: any) => row.attachmentIds?.length || 0
|
||||
},
|
||||
{
|
||||
title: '置顶',
|
||||
key: 'isPinned',
|
||||
width: 80,
|
||||
render: row =>
|
||||
h(
|
||||
NTag,
|
||||
{ type: row.isPinned ? 'warning' : 'default', size: 'small' },
|
||||
{ default: () => (row.isPinned ? '是' : '否') }
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createdAt',
|
||||
width: 180,
|
||||
render: (row: any) => {
|
||||
return useDateFormat(row.createdAt, 'YYYY-MM-DD HH:mm:ss').value;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'operations',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render: (row: any) =>
|
||||
h(
|
||||
NSpace,
|
||||
{ size: 'small' },
|
||||
{
|
||||
default: () => [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: () => handleEdit(row)
|
||||
},
|
||||
{ default: () => '编辑' }
|
||||
),
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'error',
|
||||
text: true,
|
||||
onClick: () => handleDelete(row.id)
|
||||
},
|
||||
{ default: () => '删除' }
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
const filterColumns: TableFilterColumns = [
|
||||
{
|
||||
key: 'isPinned',
|
||||
title: '置顶状态',
|
||||
component: NSelect,
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '已置顶', value: 'true' },
|
||||
{ label: '未置顶', value: 'false' }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function handleAdd() {
|
||||
const dialogInstance = dialog.create({
|
||||
title: '创建新闻',
|
||||
content: () =>
|
||||
h(Add, {
|
||||
onClose: () => {
|
||||
dialogInstance.destroy();
|
||||
tableInst.value?.reload();
|
||||
}
|
||||
}),
|
||||
style: { width: '600px' },
|
||||
showIcon: false
|
||||
});
|
||||
}
|
||||
|
||||
function handleEdit(row: any) {
|
||||
const dialogInstance = dialog.create({
|
||||
title: '编辑新闻',
|
||||
content: () =>
|
||||
h(Edit, {
|
||||
data: row,
|
||||
onClose: () => {
|
||||
dialogInstance.destroy();
|
||||
tableInst.value?.reload();
|
||||
}
|
||||
}),
|
||||
style: { width: '800px' },
|
||||
showIcon: false
|
||||
});
|
||||
}
|
||||
|
||||
function handleDelete(id: string) {
|
||||
dialog.warning({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这条新闻吗?此操作不可恢复。',
|
||||
positiveText: '删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
const { data } = await safeClient(() =>
|
||||
client.api.admin.news({ id }).delete({
|
||||
params: { id }
|
||||
})
|
||||
);
|
||||
if (data) {
|
||||
window.$message?.success('删除成功');
|
||||
tableInst.value?.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableBase
|
||||
ref="tableInst"
|
||||
show-header-operation
|
||||
:columns="columns"
|
||||
:filter-columns="filterColumns"
|
||||
:fetch-data="fetchData"
|
||||
:scroll-x="800"
|
||||
@add="handleAdd"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped></style>
|
||||
Reference in New Issue
Block a user