From 6c6e1d4720fcb2b6c8b5cf4e88398fd8c79fd3eb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 Oct 2025 23:37:05 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E3=80=91=E6=96=87=E7=AB=A0=E5=88=97=E8=A1=A8=EF=BC=88100%=20an?= =?UTF-8?q?td=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/mall/promotion/article/data.ts | 67 ++++++++++++++++--- .../views/mall/promotion/article/index.vue | 20 ++++-- .../mall/promotion/article/modules/form.vue | 4 +- 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/apps/web-antd/src/views/mall/promotion/article/data.ts b/apps/web-antd/src/views/mall/promotion/article/data.ts index e0e184a53..ce26e9c47 100644 --- a/apps/web-antd/src/views/mall/promotion/article/data.ts +++ b/apps/web-antd/src/views/mall/promotion/article/data.ts @@ -1,5 +1,6 @@ import type { VbenFormSchema } from '#/adapter/form'; import type { VxeGridPropTypes } from '#/adapter/vxe-table'; +import type { MallArticleCategoryApi } from '#/api/mall/promotion/articleCategory'; import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; import { getDictOptions } from '@vben/hooks'; @@ -8,12 +9,19 @@ import { z } from '#/adapter/form'; import { getSimpleArticleCategoryList } from '#/api/mall/promotion/articleCategory'; import { getRangePickerDefaultProps } from '#/utils'; +let categoryList: MallArticleCategoryApi.ArticleCategory[] = []; +async function getCategoryData() { + categoryList = await getSimpleArticleCategoryList(); +} + +getCategoryData(); + /** 新增/修改的表单 */ export function useFormSchema(): VbenFormSchema[] { return [ { - component: 'Input', fieldName: 'id', + component: 'Input', dependencies: { triggerFields: [''], show: () => false, @@ -23,6 +31,9 @@ export function useFormSchema(): VbenFormSchema[] { fieldName: 'title', label: '文章标题', component: 'Input', + componentProps: { + placeholder: '请输入文章标题', + }, rules: 'required', }, { @@ -33,6 +44,7 @@ export function useFormSchema(): VbenFormSchema[] { api: getSimpleArticleCategoryList, labelField: 'name', valueField: 'id', + placeholder: '请选择文章分类', }, rules: 'required', }, @@ -40,16 +52,26 @@ export function useFormSchema(): VbenFormSchema[] { fieldName: 'author', label: '文章作者', component: 'Input', + componentProps: { + placeholder: '请输入文章作者', + }, }, { fieldName: 'introduction', label: '文章简介', component: 'Input', + componentProps: { + placeholder: '请输入文章简介', + }, }, { fieldName: 'picUrl', label: '文章封面', component: 'ImageUpload', + formItemClass: 'col-span-2', + componentProps: { + placeholder: '请上传文章封面', + }, rules: 'required', }, { @@ -61,6 +83,8 @@ export function useFormSchema(): VbenFormSchema[] { buttonStyle: 'solid', optionType: 'button', }, + rules: 'required', + defaultValue: true, }, { fieldName: 'recommendBanner', @@ -71,12 +95,18 @@ export function useFormSchema(): VbenFormSchema[] { buttonStyle: 'solid', optionType: 'button', }, + rules: 'required', + defaultValue: true, }, { - // TODO: @xingyu:商品关联 + // TODO: @puhui999:商品关联 fieldName: 'spuId', label: '商品关联', component: 'Input', + formItemClass: 'col-span-2', + componentProps: { + placeholder: '请输入商品 SPU 编号', + }, }, { fieldName: 'sort', @@ -84,9 +114,9 @@ export function useFormSchema(): VbenFormSchema[] { component: 'InputNumber', componentProps: { min: 0, - placeholder: '请输入品牌排序', + placeholder: '请输入排序', }, - rules: z.number().min(0).default(1), + rules: 'required', }, { fieldName: 'status', @@ -100,9 +130,11 @@ export function useFormSchema(): VbenFormSchema[] { rules: z.number().default(CommonStatusEnum.ENABLE), }, { - fieldName: 'description', + fieldName: 'content', label: '文章内容', component: 'RichTextarea', + rules: 'required', + formItemClass: 'col-span-2', }, ]; } @@ -111,19 +143,25 @@ export function useFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] { return [ { - fieldName: 'name', + fieldName: 'categoryId', label: '文章分类', component: 'ApiSelect', componentProps: { api: getSimpleArticleCategoryList, labelField: 'name', valueField: 'id', + placeholder: '请选择文章分类', + allowClear: true, }, }, { fieldName: 'title', label: '文章标题', component: 'Input', + componentProps: { + placeholder: '请输入文章标题', + allowClear: true, + }, }, { fieldName: 'status', @@ -131,6 +169,8 @@ export function useGridFormSchema(): VbenFormSchema[] { component: 'Select', componentProps: { options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, }, }, { @@ -145,21 +185,23 @@ export function useGridFormSchema(): VbenFormSchema[] { ]; } -/** 表格列配置 */ +/** 列表的字段 */ export function useGridColumns(): VxeGridPropTypes.Columns { return [ { field: 'id', title: '编号', - fixed: 'left', + minWidth: 100, }, { field: 'title', title: '标题', + minWidth: 200, }, { field: 'picUrl', title: '封面', + minWidth: 120, cellRender: { name: 'CellImage', }, @@ -167,26 +209,34 @@ export function useGridColumns(): VxeGridPropTypes.Columns { { field: 'categoryId', title: '分类', + minWidth: 100, + formatter: ({ cellValue }) => + categoryList.find((item) => item.id === cellValue)?.name || '-', }, { field: 'browseCount', title: '浏览量', + minWidth: 100, }, { field: 'author', title: '作者', + minWidth: 120, }, { field: 'introduction', title: '文章简介', + minWidth: 250, }, { field: 'sort', title: '排序', + minWidth: 80, }, { field: 'status', title: '状态', + minWidth: 100, cellRender: { name: 'CellDict', props: { type: DICT_TYPE.COMMON_STATUS }, @@ -195,6 +245,7 @@ export function useGridColumns(): VxeGridPropTypes.Columns { { field: 'createTime', title: '创建时间', + minWidth: 180, formatter: 'formatDateTime', }, { diff --git a/apps/web-antd/src/views/mall/promotion/article/index.vue b/apps/web-antd/src/views/mall/promotion/article/index.vue index c38b24868..82c1a89fe 100644 --- a/apps/web-antd/src/views/mall/promotion/article/index.vue +++ b/apps/web-antd/src/views/mall/promotion/article/index.vue @@ -2,7 +2,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { MallArticleApi } from '#/api/mall/promotion/article'; -import { Page, useVbenModal } from '@vben/common-ui'; +import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; import { message } from 'ant-design-vue'; @@ -23,17 +23,17 @@ function handleRefresh() { gridApi.query(); } -/** 创建品牌 */ +/** 创建文章 */ function handleCreate() { formModalApi.setData(null).open(); } -/** 编辑品牌 */ +/** 编辑文章 */ function handleEdit(row: MallArticleApi.Article) { formModalApi.setData(row).open(); } -/** 删除品牌 */ +/** 删除文章 */ async function handleDelete(row: MallArticleApi.Article) { const hideLoading = message.loading({ content: $t('ui.actionMessage.deleting', [row.title]), @@ -41,9 +41,7 @@ async function handleDelete(row: MallArticleApi.Article) { }); try { await deleteArticle(row.id as number); - message.success({ - content: $t('ui.actionMessage.deleteSuccess', [row.title]), - }); + message.success($t('ui.actionMessage.deleteSuccess', [row.title])); handleRefresh(); } finally { hideLoading(); @@ -71,6 +69,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: true, @@ -82,6 +81,13 @@ const [Grid, gridApi] = useVbenVxeGrid({