From 84caccaf058a65679b17b42c4769b3efb6329670 Mon Sep 17 00:00:00 2001 From: lq Date: Mon, 19 May 2025 16:52:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=95=86=E9=93=BA=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E3=80=81=E5=95=86=E5=93=81=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- apps/web-antd/src/api/request.ts | 20 ++ .../form/components/upload-image.vue | 86 ++++++--- apps/web-antd/src/util/json/filedType.json | 2 +- apps/web-antd/src/util/json/formType.json | 8 + .../product-classification/api/index.ts | 66 +++++++ .../components/modal.vue | 71 +++++++ .../product-classification/config/form.ts | 46 +++++ .../product-classification/config/search.ts | 30 +++ .../product-classification/config/table.ts | 70 +++++++ .../my-gen/product-classification/index.vue | 128 +++++++++++++ .../views/my-gen/product-image/api/index.ts | 42 ++++ .../my-gen/product-image/components/modal.vue | 68 +++++++ .../views/my-gen/product-image/config/form.ts | 40 ++++ .../my-gen/product-image/config/search.ts | 30 +++ .../my-gen/product-image/config/table.ts | 69 +++++++ .../src/views/my-gen/product-image/index.vue | 128 +++++++++++++ .../views/my-gen/product-label/api/index.ts | 42 ++++ .../my-gen/product-label/components/modal.vue | 68 +++++++ .../views/my-gen/product-label/config/form.ts | 34 ++++ .../my-gen/product-label/config/search.ts | 25 +++ .../my-gen/product-label/config/table.ts | 68 +++++++ .../src/views/my-gen/product-label/index.vue | 128 +++++++++++++ .../src/views/my-gen/product/api/index.ts | 42 ++++ .../views/my-gen/product/components/modal.vue | 63 ++++++ .../src/views/my-gen/product/config/form.ts | 89 +++++++++ .../src/views/my-gen/product/config/search.ts | 35 ++++ .../src/views/my-gen/product/config/table.ts | 76 ++++++++ .../src/views/my-gen/product/index.vue | 149 +++++++++++++++ .../my-gen/store-classification/api/index.ts | 49 +++++ .../store-classification/components/modal.vue | 71 +++++++ .../store-classification/config/form.ts | 40 ++++ .../store-classification/config/search.ts | 30 +++ .../store-classification/config/table.ts | 69 +++++++ .../my-gen/store-classification/index.vue | 128 +++++++++++++ .../src/views/my-gen/store/api/index.ts | 42 ++++ .../views/my-gen/store/components/modal.vue | 66 +++++++ .../src/views/my-gen/store/config/form.ts | 179 ++++++++++++++++++ .../src/views/my-gen/store/config/search.ts | 55 ++++++ .../src/views/my-gen/store/config/table.ts | 82 ++++++++ .../web-antd/src/views/my-gen/store/index.vue | 128 +++++++++++++ apps/web-antd/vite.config.mts | 4 +- docs/.vitepress/config/en.mts | 2 +- 43 files changed, 2639 insertions(+), 31 deletions(-) create mode 100644 apps/web-antd/src/views/my-gen/product-classification/api/index.ts create mode 100644 apps/web-antd/src/views/my-gen/product-classification/components/modal.vue create mode 100644 apps/web-antd/src/views/my-gen/product-classification/config/form.ts create mode 100644 apps/web-antd/src/views/my-gen/product-classification/config/search.ts create mode 100644 apps/web-antd/src/views/my-gen/product-classification/config/table.ts create mode 100644 apps/web-antd/src/views/my-gen/product-classification/index.vue create mode 100644 apps/web-antd/src/views/my-gen/product-image/api/index.ts create mode 100644 apps/web-antd/src/views/my-gen/product-image/components/modal.vue create mode 100644 apps/web-antd/src/views/my-gen/product-image/config/form.ts create mode 100644 apps/web-antd/src/views/my-gen/product-image/config/search.ts create mode 100644 apps/web-antd/src/views/my-gen/product-image/config/table.ts create mode 100644 apps/web-antd/src/views/my-gen/product-image/index.vue create mode 100644 apps/web-antd/src/views/my-gen/product-label/api/index.ts create mode 100644 apps/web-antd/src/views/my-gen/product-label/components/modal.vue create mode 100644 apps/web-antd/src/views/my-gen/product-label/config/form.ts create mode 100644 apps/web-antd/src/views/my-gen/product-label/config/search.ts create mode 100644 apps/web-antd/src/views/my-gen/product-label/config/table.ts create mode 100644 apps/web-antd/src/views/my-gen/product-label/index.vue create mode 100644 apps/web-antd/src/views/my-gen/product/api/index.ts create mode 100644 apps/web-antd/src/views/my-gen/product/components/modal.vue create mode 100644 apps/web-antd/src/views/my-gen/product/config/form.ts create mode 100644 apps/web-antd/src/views/my-gen/product/config/search.ts create mode 100644 apps/web-antd/src/views/my-gen/product/config/table.ts create mode 100644 apps/web-antd/src/views/my-gen/product/index.vue create mode 100644 apps/web-antd/src/views/my-gen/store-classification/api/index.ts create mode 100644 apps/web-antd/src/views/my-gen/store-classification/components/modal.vue create mode 100644 apps/web-antd/src/views/my-gen/store-classification/config/form.ts create mode 100644 apps/web-antd/src/views/my-gen/store-classification/config/search.ts create mode 100644 apps/web-antd/src/views/my-gen/store-classification/config/table.ts create mode 100644 apps/web-antd/src/views/my-gen/store-classification/index.vue create mode 100644 apps/web-antd/src/views/my-gen/store/api/index.ts create mode 100644 apps/web-antd/src/views/my-gen/store/components/modal.vue create mode 100644 apps/web-antd/src/views/my-gen/store/config/form.ts create mode 100644 apps/web-antd/src/views/my-gen/store/config/search.ts create mode 100644 apps/web-antd/src/views/my-gen/store/config/table.ts create mode 100644 apps/web-antd/src/views/my-gen/store/index.vue diff --git a/README.md b/README.md index e027949a..facaa2d6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ **English** | [中文](./README.zh-CN.md) | [日本語](./README.ja-JP.md) -## Introduction +## Vue Vben Admin is a free and open source middle and back-end template. Using the latest `vue3`, `vite`, `TypeScript` and other mainstream technology development, the out-of-the-box middle and back-end front-end solutions can also be used for learning reference. diff --git a/apps/web-antd/src/api/request.ts b/apps/web-antd/src/api/request.ts index c5f04432..1d321f11 100644 --- a/apps/web-antd/src/api/request.ts +++ b/apps/web-antd/src/api/request.ts @@ -91,6 +91,26 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { }), ); + // 通用的错误处理 + client.addResponseInterceptor( + errorMessageResponseInterceptor((msg: string, error) => { + const responseData = error?.response?.data ?? {}; + const errorCode = responseData?.code ?? -1; + const errorMessage = responseData?.error ?? responseData?.message ?? msg; + + // 处理登录过期 + if (errorCode === 401) { + message.error('登录状态已过期,请重新登录'); + const authStore = useAuthStore(); + authStore.logout(); + return; + } + + // 其他错误处理 + message.error(errorMessage); + }), + ); + // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 client.addResponseInterceptor( errorMessageResponseInterceptor((msg: string, error) => { diff --git a/apps/web-antd/src/components/form/components/upload-image.vue b/apps/web-antd/src/components/form/components/upload-image.vue index b8a96811..b99d6fbf 100644 --- a/apps/web-antd/src/components/form/components/upload-image.vue +++ b/apps/web-antd/src/components/form/components/upload-image.vue @@ -1,5 +1,5 @@ + diff --git a/apps/web-antd/src/views/my-gen/product-classification/config/form.ts b/apps/web-antd/src/views/my-gen/product-classification/config/form.ts new file mode 100644 index 00000000..967ec57a --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-classification/config/form.ts @@ -0,0 +1,46 @@ +import type { VbenFormProps } from '#/adapter/form'; + +export const modalFormProps: VbenFormProps = { + wrapperClass: 'grid-cols-12', // 24栅格, + commonConfig: { + formItemClass: 'col-span-12', + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + // handleSubmit: onSubmit, + layout: 'horizontal', + schema: [ + { + component: 'VbenInput', + fieldName: 'id', + label: 'ID', + formItemClass: 'col-span-6', + dependencies: { + show: false, + triggerFields: ['id'], + }, + }, + // 生成的表单字段 + { + fieldName: 'name', + label: '分类名称', + component: 'VbenInput', + rules: 'required', + }, + { + fieldName: 'cover', + label: '分类图片', + component: 'Avatar', + rules: 'required', + }, + { + fieldName: 'pid', + label: '父级分类', + component: 'VbenInput', + rules: 'required', + }, + ], + showDefaultActions: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-classification/config/search.ts b/apps/web-antd/src/views/my-gen/product-classification/config/search.ts new file mode 100644 index 00000000..0efc5718 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-classification/config/search.ts @@ -0,0 +1,30 @@ +import type { VbenFormProps } from '#/adapter/form'; + +// import dayjs from 'dayjs'; + +export const formOptions: VbenFormProps = { + // 默认展开 + collapsed: false, + schema: [ + // 生成的搜索字段 + { + fieldName: 'name', + label: '分类名称', + component: 'VbenInput', + }, + { + fieldName: 'pid', + label: '父级分类', + component: 'VbenInput', + }, + ], + // 控制表单是否显示折叠按钮 + showCollapseButton: true, + submitButtonOptions: { + content: '查询', + }, + // 是否在字段值改变时提交表单 + submitOnChange: true, + // 按下回车时是否提交表单 + submitOnEnter: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-classification/config/table.ts b/apps/web-antd/src/views/my-gen/product-classification/config/table.ts new file mode 100644 index 00000000..1af1ae37 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-classification/config/table.ts @@ -0,0 +1,70 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { getProductClassificationListApi } from '../api'; + +interface RowType { + id: string; + name: string; + logo: string; + introduce: string; + created_at: string; +} + +export const gridOptions: VxeGridProps = { + checkboxConfig: { + highlight: true, + labelField: '', + }, + columnConfig: { + useKey: true, + }, + rowConfig: { + useKey: true, + }, + columns: [ + { type: 'checkbox', width: 60 }, + { field: 'id', align: 'left', title: 'ID', width: 100 }, + // 生成的列表字段 + { field: 'name', title: '分类名称' }, + { field: 'cover', title: '分类图片', slots: { default: 'cover' } }, + { field: 'pid', title: '父级分类' }, + + { field: 'created_at', title: '创建时间' }, + { field: 'updated_at', title: '编辑时间' }, + { type: 'html', title: '操作', slots: { default: 'action' } }, + ], + keepSource: true, + pagerConfig: {}, + proxyConfig: { + ajax: { + // 请求后端接口方法 + query: async ({ page }, formValues) => { + return await getProductClassificationListApi({ + page: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, + }, + height: 'auto', + border: false, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + refresh: true, // 刷新 + print: false, // 打印 + export: false, // 导出 + // custom: true, // 自定义列 + zoom: true, // 最大化最小化 + slots: { + buttons: 'toolbar-buttons', + }, + custom: { + // 自定义列-图标 + icon: 'vxe-icon-menu', + }, + }, + showOverflow: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-classification/index.vue b/apps/web-antd/src/views/my-gen/product-classification/index.vue new file mode 100644 index 00000000..7b7d175c --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-classification/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-antd/src/views/my-gen/product-image/api/index.ts b/apps/web-antd/src/views/my-gen/product-image/api/index.ts new file mode 100644 index 00000000..f1fc05ee --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-image/api/index.ts @@ -0,0 +1,42 @@ +import { requestClient } from '#/api/request'; + +const prefix = 'product-image/'; +/** + * 分页查询商品图片列表 + * @param data + */ +export async function getProductImageListApi(data: any) { + return requestClient.get(`${prefix}list`, { params: data }); +} + +/** + * 获取商品图片详情 + * @param id + */ +export async function getProductImageInfoApi(id: number) { + return requestClient.get(`${prefix}detail`, { params: { id } }); +} + +/** + * 新增商品图片 + * @param data + */ +export async function createProductImageApi(data: Record) { + return requestClient.post(`${prefix}create`, data); +} + +/** + * 编辑商品图片 + * @param data + */ +export async function updateProductImageApi(data: Record) { + return requestClient.post(`${prefix}update`, data); +} + +/** + * 删除商品图片 + * @param data + */ +export async function deleteProductImageApi(data: Record) { + return requestClient.post(`${prefix}delete`, data); +} diff --git a/apps/web-antd/src/views/my-gen/product-image/components/modal.vue b/apps/web-antd/src/views/my-gen/product-image/components/modal.vue new file mode 100644 index 00000000..310d8419 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-image/components/modal.vue @@ -0,0 +1,68 @@ + + diff --git a/apps/web-antd/src/views/my-gen/product-image/config/form.ts b/apps/web-antd/src/views/my-gen/product-image/config/form.ts new file mode 100644 index 00000000..c1aac2b3 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-image/config/form.ts @@ -0,0 +1,40 @@ +import type { VbenFormProps } from '#/adapter/form'; + +export const modalFormProps: VbenFormProps = { + wrapperClass: 'grid-cols-12', // 24栅格, + commonConfig: { + formItemClass: 'col-span-12', + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + // handleSubmit: onSubmit, + layout: 'horizontal', + schema: [ + { + component: 'VbenInput', + fieldName: 'id', + label: 'ID', + formItemClass: 'col-span-6', + dependencies: { + show: false, + triggerFields: ['id'], + }, + }, + // 生成的表单字段 + { + fieldName: 'url', + label: '商品地址', + component: 'Avatar', + rules: 'required', + }, + { + fieldName: 'product_id', + label: '商品ID', + component: 'VbenInput', + rules: 'required', + }, + ], + showDefaultActions: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-image/config/search.ts b/apps/web-antd/src/views/my-gen/product-image/config/search.ts new file mode 100644 index 00000000..6bcb40c7 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-image/config/search.ts @@ -0,0 +1,30 @@ +import type { VbenFormProps } from '#/adapter/form'; + +// import dayjs from 'dayjs'; + +export const formOptions: VbenFormProps = { + // 默认展开 + collapsed: false, + schema: [ + // 生成的搜索字段 + { + fieldName: 'url', + label: '商品地址', + component: 'VbenInput', + }, + { + fieldName: 'product_id', + label: '商品ID', + component: 'VbenInput', + }, + ], + // 控制表单是否显示折叠按钮 + showCollapseButton: true, + submitButtonOptions: { + content: '查询', + }, + // 是否在字段值改变时提交表单 + submitOnChange: true, + // 按下回车时是否提交表单 + submitOnEnter: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-image/config/table.ts b/apps/web-antd/src/views/my-gen/product-image/config/table.ts new file mode 100644 index 00000000..33b925da --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-image/config/table.ts @@ -0,0 +1,69 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { getProductImageListApi } from '../api'; + +interface RowType { + id: string; + name: string; + logo: string; + introduce: string; + created_at: string; +} + +export const gridOptions: VxeGridProps = { + checkboxConfig: { + highlight: true, + labelField: '', + }, + columnConfig: { + useKey: true, + }, + rowConfig: { + useKey: true, + }, + columns: [ + { type: 'checkbox', width: 60 }, + { field: 'id', align: 'left', title: 'ID', width: 100 }, + // 生成的列表字段 + { field: 'url', title: '商品地址' }, + { field: 'product_id', title: '商品ID' }, + + { field: 'created_at', title: '创建时间' }, + { field: 'updated_at', title: '编辑时间' }, + { type: 'html', title: '操作', slots: { default: 'action' } }, + ], + keepSource: true, + pagerConfig: {}, + proxyConfig: { + ajax: { + // 请求后端接口方法 + query: async ({ page }, formValues) => { + return await getProductImageListApi({ + page: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, + }, + height: 'auto', + border: false, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + refresh: true, // 刷新 + print: false, // 打印 + export: false, // 导出 + // custom: true, // 自定义列 + zoom: true, // 最大化最小化 + slots: { + buttons: 'toolbar-buttons', + }, + custom: { + // 自定义列-图标 + icon: 'vxe-icon-menu', + }, + }, + showOverflow: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-image/index.vue b/apps/web-antd/src/views/my-gen/product-image/index.vue new file mode 100644 index 00000000..99f5bb69 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-image/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-antd/src/views/my-gen/product-label/api/index.ts b/apps/web-antd/src/views/my-gen/product-label/api/index.ts new file mode 100644 index 00000000..985fda00 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-label/api/index.ts @@ -0,0 +1,42 @@ +import { requestClient } from '#/api/request'; + +const prefix = 'product-label/'; +/** + * 分页查询商品标签列表 + * @param data + */ +export async function getProductLabelListApi(data: any) { + return requestClient.get(`${prefix}list`, { params: data }); +} + +/** + * 获取商品标签详情 + * @param id + */ +export async function getProductLabelInfoApi(id: number) { + return requestClient.get(`${prefix}detail`, { params: { id } }); +} + +/** + * 新增商品标签 + * @param data + */ +export async function createProductLabelApi(data: Record) { + return requestClient.post(`${prefix}create`, data); +} + +/** + * 编辑商品标签 + * @param data + */ +export async function updateProductLabelApi(data: Record) { + return requestClient.post(`${prefix}update`, data); +} + +/** + * 删除商品标签 + * @param data + */ +export async function deleteProductLabelApi(data: Record) { + return requestClient.post(`${prefix}delete`, data); +} diff --git a/apps/web-antd/src/views/my-gen/product-label/components/modal.vue b/apps/web-antd/src/views/my-gen/product-label/components/modal.vue new file mode 100644 index 00000000..37e5c800 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-label/components/modal.vue @@ -0,0 +1,68 @@ + + diff --git a/apps/web-antd/src/views/my-gen/product-label/config/form.ts b/apps/web-antd/src/views/my-gen/product-label/config/form.ts new file mode 100644 index 00000000..1224f2cc --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-label/config/form.ts @@ -0,0 +1,34 @@ +import type { VbenFormProps } from '#/adapter/form'; + +export const modalFormProps: VbenFormProps = { + wrapperClass: 'grid-cols-12', // 24栅格, + commonConfig: { + formItemClass: 'col-span-12', + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + // handleSubmit: onSubmit, + layout: 'horizontal', + schema: [ + { + component: 'VbenInput', + fieldName: 'id', + label: 'ID', + formItemClass: 'col-span-6', + dependencies: { + show: false, + triggerFields: ['id'], + }, + }, + // 生成的表单字段 + { + fieldName: 'name', + label: '标签名称', + component: 'VbenInput', + rules: 'required', + }, + ], + showDefaultActions: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-label/config/search.ts b/apps/web-antd/src/views/my-gen/product-label/config/search.ts new file mode 100644 index 00000000..680d5544 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-label/config/search.ts @@ -0,0 +1,25 @@ +import type { VbenFormProps } from '#/adapter/form'; + +// import dayjs from 'dayjs'; + +export const formOptions: VbenFormProps = { + // 默认展开 + collapsed: false, + schema: [ + // 生成的搜索字段 + { + fieldName: 'name', + label: '标签名称', + component: 'VbenInput', + }, + ], + // 控制表单是否显示折叠按钮 + showCollapseButton: true, + submitButtonOptions: { + content: '查询', + }, + // 是否在字段值改变时提交表单 + submitOnChange: true, + // 按下回车时是否提交表单 + submitOnEnter: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-label/config/table.ts b/apps/web-antd/src/views/my-gen/product-label/config/table.ts new file mode 100644 index 00000000..59d32b2a --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-label/config/table.ts @@ -0,0 +1,68 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { getProductLabelListApi } from '../api'; + +interface RowType { + id: string; + name: string; + logo: string; + introduce: string; + created_at: string; +} + +export const gridOptions: VxeGridProps = { + checkboxConfig: { + highlight: true, + labelField: '', + }, + columnConfig: { + useKey: true, + }, + rowConfig: { + useKey: true, + }, + columns: [ + { type: 'checkbox', width: 60 }, + { field: 'id', align: 'left', title: 'ID', width: 100 }, + // 生成的列表字段 + { field: 'name', title: '标签名称' }, + + { field: 'created_at', title: '创建时间' }, + { field: 'updated_at', title: '编辑时间' }, + { type: 'html', title: '操作', slots: { default: 'action' } }, + ], + keepSource: true, + pagerConfig: {}, + proxyConfig: { + ajax: { + // 请求后端接口方法 + query: async ({ page }, formValues) => { + return await getProductLabelListApi({ + page: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, + }, + height: 'auto', + border: false, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + refresh: true, // 刷新 + print: false, // 打印 + export: false, // 导出 + // custom: true, // 自定义列 + zoom: true, // 最大化最小化 + slots: { + buttons: 'toolbar-buttons', + }, + custom: { + // 自定义列-图标 + icon: 'vxe-icon-menu', + }, + }, + showOverflow: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product-label/index.vue b/apps/web-antd/src/views/my-gen/product-label/index.vue new file mode 100644 index 00000000..27fef407 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product-label/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-antd/src/views/my-gen/product/api/index.ts b/apps/web-antd/src/views/my-gen/product/api/index.ts new file mode 100644 index 00000000..f8df2540 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product/api/index.ts @@ -0,0 +1,42 @@ +import { requestClient } from '#/api/request'; + +const prefix = 'product/'; +/** + * 分页查询产品列表 + * @param data + */ +export async function getProductListApi(data: any) { + return requestClient.get(`${prefix}list`, { params: data }); +} + +/** + * 获取产品详情 + * @param id + */ +export async function getProductInfoApi(id: number) { + return requestClient.get(`${prefix}detail`, { params: { id } }); +} + +/** + * 新增产品 + * @param data + */ +export async function createProductApi(data: Record) { + return requestClient.post(`${prefix}create`, data); +} + +/** + * 编辑产品 + * @param data + */ +export async function updateProductApi(data: Record) { + return requestClient.post(`${prefix}update`, data); +} + +/** + * 删除产品 + * @param data + */ +export async function deleteProductApi(data: Record) { + return requestClient.post(`${prefix}delete`, data); +} diff --git a/apps/web-antd/src/views/my-gen/product/components/modal.vue b/apps/web-antd/src/views/my-gen/product/components/modal.vue new file mode 100644 index 00000000..0ee1c3da --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product/components/modal.vue @@ -0,0 +1,63 @@ + + diff --git a/apps/web-antd/src/views/my-gen/product/config/form.ts b/apps/web-antd/src/views/my-gen/product/config/form.ts new file mode 100644 index 00000000..8aa1ba32 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product/config/form.ts @@ -0,0 +1,89 @@ +import type { VbenFormProps } from '#/adapter/form'; + +import { getProductClassificationTreeOptionApi } from '#/views/my-gen/product-classification/api'; + +export const modalFormProps: VbenFormProps = { + wrapperClass: 'grid-cols-12', // 24栅格, + commonConfig: { + formItemClass: 'col-span-12', + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + // handleSubmit: onSubmit, + layout: 'horizontal', + schema: [ + { + component: 'VbenInput', + fieldName: 'id', + label: 'ID', + formItemClass: 'col-span-6', + dependencies: { + show: false, + triggerFields: ['id'], + }, + }, + // 生成的表单字段 + { + fieldName: 'title', + label: '商品名称', + component: 'VbenInput', + rules: 'required', + }, + { + fieldName: 'cover', + label: '封面图', + component: 'Avatar', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'price', + label: '价格', + component: 'VbenInput', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'classification_id', + label: '产品分类', + component: 'ApiTreeSelect', + componentProps: { + api: getProductClassificationTreeOptionApi, + filterOption: (input: string, option: any) => { + // 自定义过滤逻辑,确保可以根据 name 进行搜索 + return option?.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; + }, + showSearch: true, + // 菜单接口转options格式 + afterFetch: (data: { id: number; name: string }[]) => { + return data.map((item: any) => ({ + label: item.name, + value: item.id, + })); + }, + }, + rules: 'required', + }, + { + fieldName: 'images', + label: '产品图片', + component: 'UploadImage', + rules: 'required', + }, + { + fieldName: 'introduction', + label: '简介', + component: 'Textarea', + rules: 'required', + }, + { + fieldName: 'description', + label: '详细说明', + component: 'VbenInput', + rules: 'required', + }, + ], + showDefaultActions: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product/config/search.ts b/apps/web-antd/src/views/my-gen/product/config/search.ts new file mode 100644 index 00000000..8b776941 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product/config/search.ts @@ -0,0 +1,35 @@ +import type { VbenFormProps } from '#/adapter/form'; + +// import dayjs from 'dayjs'; + +export const formOptions: VbenFormProps = { + // 默认展开 + collapsed: false, + schema: [ + // 生成的搜索字段 + { + fieldName: 'title', + label: '商品名称', + component: 'VbenInput', + }, + { + fieldName: 'mall_id', + label: '商家ID', + component: 'VbenInput', + }, + { + fieldName: 'classification_id', + label: '产品分类', + component: 'VbenInput', + }, + ], + // 控制表单是否显示折叠按钮 + showCollapseButton: true, + submitButtonOptions: { + content: '查询', + }, + // 是否在字段值改变时提交表单 + submitOnChange: true, + // 按下回车时是否提交表单 + submitOnEnter: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product/config/table.ts b/apps/web-antd/src/views/my-gen/product/config/table.ts new file mode 100644 index 00000000..dec13000 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product/config/table.ts @@ -0,0 +1,76 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { getProductListApi } from '../api'; + +interface RowType { + id: string; + name: string; + logo: string; + introduce: string; + created_at: string; +} + +export const gridOptions: VxeGridProps = { + checkboxConfig: { + highlight: true, + labelField: '', + }, + columnConfig: { + useKey: true, + }, + rowConfig: { + useKey: true, + }, + columns: [ + { type: 'checkbox', width: 60 }, + { field: 'id', align: 'left', title: 'ID', width: 100 }, + // 生成的列表字段 + { field: 'title', title: '商品名称' }, + { field: 'mall_id', title: '商家ID' }, + { field: 'user_id', title: '上传用户ID' }, + { field: 'introduction', title: '简介' }, + { field: 'cover', title: '封面图', slots: { default: 'cover' } }, + { field: 'images', title: '商品图册', slots: { default: 'images' } }, + { field: 'description', title: '详细说明' }, + { field: 'price', title: '价格' }, + { field: 'classification_id', title: '产品分类' }, + + { field: 'created_at', title: '创建时间' }, + { field: 'updated_at', title: '编辑时间' }, + { type: 'html', title: '操作', slots: { default: 'action' } }, + ], + keepSource: true, + pagerConfig: {}, + proxyConfig: { + ajax: { + // 请求后端接口方法 + query: async ({ page }, formValues) => { + return await getProductListApi({ + page: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, + }, + height: 'auto', + border: false, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + refresh: true, // 刷新 + print: false, // 打印 + export: false, // 导出 + // custom: true, // 自定义列 + zoom: true, // 最大化最小化 + slots: { + buttons: 'toolbar-buttons', + }, + custom: { + // 自定义列-图标 + icon: 'vxe-icon-menu', + }, + }, + showOverflow: false, +}; diff --git a/apps/web-antd/src/views/my-gen/product/index.vue b/apps/web-antd/src/views/my-gen/product/index.vue new file mode 100644 index 00000000..7d5eccf0 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/product/index.vue @@ -0,0 +1,149 @@ + + + diff --git a/apps/web-antd/src/views/my-gen/store-classification/api/index.ts b/apps/web-antd/src/views/my-gen/store-classification/api/index.ts new file mode 100644 index 00000000..f28f237a --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store-classification/api/index.ts @@ -0,0 +1,49 @@ +import { requestClient } from '#/api/request'; + +const prefix = 'store-classification/'; +/** + * 分页查询店铺行业列表 + * @param data + */ +export async function getStoreClassificationListApi(data: any) { + return requestClient.get(`${prefix}list`, { params: data }); +} + +/** + * 获取店铺行业详情 + */ +export async function getStoreClassificationOptionApi() { + return requestClient.get(`${prefix}option`); +} + +/** + * 获取店铺行业详情 + * @param id + */ +export async function getStoreClassificationInfoApi(id: number) { + return requestClient.get(`${prefix}detail`, { params: { id } }); +} + +/** + * 新增店铺行业 + * @param data + */ +export async function createStoreClassificationApi(data: Record) { + return requestClient.post(`${prefix}create`, data); +} + +/** + * 编辑店铺行业 + * @param data + */ +export async function updateStoreClassificationApi(data: Record) { + return requestClient.post(`${prefix}update`, data); +} + +/** + * 删除店铺行业 + * @param data + */ +export async function deleteStoreClassificationApi(data: Record) { + return requestClient.post(`${prefix}delete`, data); +} diff --git a/apps/web-antd/src/views/my-gen/store-classification/components/modal.vue b/apps/web-antd/src/views/my-gen/store-classification/components/modal.vue new file mode 100644 index 00000000..4e2f99d6 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store-classification/components/modal.vue @@ -0,0 +1,71 @@ + + diff --git a/apps/web-antd/src/views/my-gen/store-classification/config/form.ts b/apps/web-antd/src/views/my-gen/store-classification/config/form.ts new file mode 100644 index 00000000..2fd3c40d --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store-classification/config/form.ts @@ -0,0 +1,40 @@ +import type { VbenFormProps } from '#/adapter/form'; + +export const modalFormProps: VbenFormProps = { + wrapperClass: 'grid-cols-12', // 24栅格, + commonConfig: { + formItemClass: 'col-span-12', + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + // handleSubmit: onSubmit, + layout: 'horizontal', + schema: [ + { + component: 'VbenInput', + fieldName: 'id', + label: 'ID', + formItemClass: 'col-span-6', + dependencies: { + show: false, + triggerFields: ['id'], + }, + }, + // 生成的表单字段 + { + fieldName: 'name', + label: '行业名称', + component: 'VbenInput', + rules: 'required', + }, + { + fieldName: 'pid', + label: '父级ID', + component: 'VbenInput', + rules: 'required', + }, + ], + showDefaultActions: false, +}; diff --git a/apps/web-antd/src/views/my-gen/store-classification/config/search.ts b/apps/web-antd/src/views/my-gen/store-classification/config/search.ts new file mode 100644 index 00000000..34650415 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store-classification/config/search.ts @@ -0,0 +1,30 @@ +import type { VbenFormProps } from '#/adapter/form'; + +// import dayjs from 'dayjs'; + +export const formOptions: VbenFormProps = { + // 默认展开 + collapsed: false, + schema: [ + // 生成的搜索字段 + { + fieldName: 'name', + label: '行业名称', + component: 'VbenInput', + }, + { + fieldName: 'pid', + label: '父级ID', + component: 'VbenInput', + }, + ], + // 控制表单是否显示折叠按钮 + showCollapseButton: true, + submitButtonOptions: { + content: '查询', + }, + // 是否在字段值改变时提交表单 + submitOnChange: true, + // 按下回车时是否提交表单 + submitOnEnter: false, +}; diff --git a/apps/web-antd/src/views/my-gen/store-classification/config/table.ts b/apps/web-antd/src/views/my-gen/store-classification/config/table.ts new file mode 100644 index 00000000..3a8f6e46 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store-classification/config/table.ts @@ -0,0 +1,69 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { getStoreClassificationListApi } from '../api'; + +interface RowType { + id: string; + name: string; + logo: string; + introduce: string; + created_at: string; +} + +export const gridOptions: VxeGridProps = { + checkboxConfig: { + highlight: true, + labelField: '', + }, + columnConfig: { + useKey: true, + }, + rowConfig: { + useKey: true, + }, + columns: [ + { type: 'checkbox', width: 60 }, + { field: 'id', align: 'left', title: 'ID', width: 100 }, + // 生成的列表字段 + { field: 'name', title: '行业名称' }, + { field: 'pid', title: '父级ID' }, + + { field: 'created_at', title: '创建时间' }, + { field: 'updated_at', title: '编辑时间' }, + { type: 'html', title: '操作', slots: { default: 'action' } }, + ], + keepSource: true, + pagerConfig: {}, + proxyConfig: { + ajax: { + // 请求后端接口方法 + query: async ({ page }, formValues) => { + return await getStoreClassificationListApi({ + page: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, + }, + height: 'auto', + border: false, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + refresh: true, // 刷新 + print: false, // 打印 + export: false, // 导出 + // custom: true, // 自定义列 + zoom: true, // 最大化最小化 + slots: { + buttons: 'toolbar-buttons', + }, + custom: { + // 自定义列-图标 + icon: 'vxe-icon-menu', + }, + }, + showOverflow: false, +}; diff --git a/apps/web-antd/src/views/my-gen/store-classification/index.vue b/apps/web-antd/src/views/my-gen/store-classification/index.vue new file mode 100644 index 00000000..ba46ad9a --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store-classification/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-antd/src/views/my-gen/store/api/index.ts b/apps/web-antd/src/views/my-gen/store/api/index.ts new file mode 100644 index 00000000..930c7b0c --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store/api/index.ts @@ -0,0 +1,42 @@ +import { requestClient } from '#/api/request'; + +const prefix = 'store/'; +/** + * 分页查询店铺管理列表 + * @param data + */ +export async function getStoreListApi(data: any) { + return requestClient.get(`${prefix}list`, { params: data }); +} + +/** + * 获取店铺管理详情 + * @param id + */ +export async function getStoreInfoApi(id: number) { + return requestClient.get(`${prefix}detail`, { params: { id } }); +} + +/** + * 新增店铺管理 + * @param data + */ +export async function createStoreApi(data: Record) { + return requestClient.post(`${prefix}create`, data); +} + +/** + * 编辑店铺管理 + * @param data + */ +export async function updateStoreApi(data: Record) { + return requestClient.post(`${prefix}update`, data); +} + +/** + * 删除店铺管理 + * @param data + */ +export async function deleteStoreApi(data: Record) { + return requestClient.post(`${prefix}delete`, data); +} diff --git a/apps/web-antd/src/views/my-gen/store/components/modal.vue b/apps/web-antd/src/views/my-gen/store/components/modal.vue new file mode 100644 index 00000000..a5af86f8 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store/components/modal.vue @@ -0,0 +1,66 @@ + + diff --git a/apps/web-antd/src/views/my-gen/store/config/form.ts b/apps/web-antd/src/views/my-gen/store/config/form.ts new file mode 100644 index 00000000..37e484a9 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store/config/form.ts @@ -0,0 +1,179 @@ +import type { VbenFormProps } from '#/adapter/form'; + +import { getStoreClassificationOptionApi } from '#/views/my-gen/store-classification/api'; + +export const modalFormProps: VbenFormProps = { + wrapperClass: 'grid-cols-12', // 24栅格, + commonConfig: { + formItemClass: 'col-span-12', + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + // handleSubmit: onSubmit, + layout: 'horizontal', + schema: [ + { + component: 'VbenInput', + fieldName: 'id', + label: 'ID', + formItemClass: 'col-span-6', + dependencies: { + show: false, + triggerFields: ['id'], + }, + }, + // 生成的表单字段 + { + fieldName: 'name', + label: '店铺名称', + component: 'VbenInput', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'level', + label: '店铺等级', + component: 'InputNumber', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'introduction', + label: '店铺简介', + component: 'Textarea', + rules: 'required', + }, + { + fieldName: 'description', + label: '详细介绍', + component: 'Textarea', + rules: 'required', + }, + { + fieldName: 'phone', + label: '商家电话号码', + component: 'VbenInput', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'person', + label: '联系人名称', + component: 'VbenInput', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'id_card', + label: '身份证号码', + component: 'VbenInput', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'classification_id', + label: '行业', + component: 'ApiTreeSelect', + componentProps: { + childrenField: 'children', + labelField: 'name', + valueField: 'id', + api: getStoreClassificationOptionApi, + }, + formItemClass: 'col-span-6', + defaultValue: 0, + rules: 'required', + }, + { + fieldName: 'is_featured', + label: '推荐店铺', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '是', + value: 1, + }, + { + label: '否', + value: 0, + }, + ], + }, + formItemClass: 'col-span-6', + defaultValue: 0, + rules: 'required', + }, + { + fieldName: 'chain', + label: '连锁', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '是', + value: 1, + }, + { + label: '否', + value: 0, + }, + ], + }, + formItemClass: 'col-span-6', + defaultValue: 0, + rules: 'required', + }, + { + fieldName: 'business_suspended', + label: '暂停营业', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '是', + value: 1, + }, + { + label: '否', + value: 0, + }, + ], + }, + formItemClass: 'col-span-6', + defaultValue: 0, + rules: 'required', + }, + { + fieldName: 'avatar', + label: '店铺头像', + component: 'Avatar', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'business_license', + label: '营业执照', + component: 'Avatar', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'id_card_portrait_side', + label: '身份证人面', + component: 'Avatar', + formItemClass: 'col-span-6', + rules: 'required', + }, + { + fieldName: 'id_card_national_emblem_side', + label: '身份证国徽面', + component: 'Avatar', + formItemClass: 'col-span-6', + rules: 'required', + }, + ], + showDefaultActions: false, +}; diff --git a/apps/web-antd/src/views/my-gen/store/config/search.ts b/apps/web-antd/src/views/my-gen/store/config/search.ts new file mode 100644 index 00000000..2eff5f36 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store/config/search.ts @@ -0,0 +1,55 @@ +import type { VbenFormProps } from '#/adapter/form'; + +// import dayjs from 'dayjs'; + +export const formOptions: VbenFormProps = { + // 默认展开 + collapsed: false, + schema: [ + // 生成的搜索字段 + { + fieldName: 'name', + label: '店铺名称', + component: 'VbenInput', + }, + { + fieldName: 'level', + label: '店铺等级', + component: 'InputNumber', + }, + { + fieldName: 'phone', + label: '商家电话号码', + component: 'VbenInput', + }, + { + fieldName: 'person', + label: '联系人名称', + component: 'VbenInput', + }, + { + fieldName: 'is_featured', + label: '是否为推荐店铺', + component: 'VbenSelect', + }, + { + fieldName: 'chain', + label: '是否连锁', + component: 'VbenSelect', + }, + { + fieldName: 'business_suspended', + label: '是否暂停营业', + component: 'VbenSelect', + }, + ], + // 控制表单是否显示折叠按钮 + showCollapseButton: true, + submitButtonOptions: { + content: '查询', + }, + // 是否在字段值改变时提交表单 + submitOnChange: true, + // 按下回车时是否提交表单 + submitOnEnter: false, +}; diff --git a/apps/web-antd/src/views/my-gen/store/config/table.ts b/apps/web-antd/src/views/my-gen/store/config/table.ts new file mode 100644 index 00000000..f2fa44b4 --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store/config/table.ts @@ -0,0 +1,82 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { getStoreListApi } from '../api'; + +interface RowType { + id: string; + name: string; + logo: string; + introduce: string; + created_at: string; +} + +export const gridOptions: VxeGridProps = { + checkboxConfig: { + highlight: true, + labelField: '', + }, + columnConfig: { + useKey: true, + }, + rowConfig: { + useKey: true, + }, + columns: [ + { type: 'checkbox', width: 60 }, + { field: 'id', align: 'left', title: 'ID', width: 100 }, + // 生成的列表字段 + { field: 'name', title: '店铺名称' }, + { field: 'level', title: '店铺等级' }, + { field: 'avatar', title: '店铺头像' }, + { field: 'introduction', title: '店铺简介' }, + { field: 'description', title: '详细介绍' }, + { field: 'phone', title: '商家电话号码' }, + { field: 'person', title: '联系人名称' }, + { field: 'id_card', title: '身份证号码' }, + { field: 'qr_code', title: '店铺二维码' }, + { field: 'is_featured', title: '是否为推荐店铺' }, + { field: 'business_license', title: '营业执照' }, + { field: 'id_card_portrait_side', title: '身份证人面' }, + { field: 'id_card_national_emblem_side', title: '身份证国徽面' }, + { field: 'chain', title: '是否连锁' }, + { field: 'business_suspended', title: '是否暂停营业' }, + + { field: 'created_at', title: '创建时间' }, + { field: 'updated_at', title: '编辑时间' }, + { type: 'html', title: '操作', slots: { default: 'action' } }, + ], + keepSource: true, + pagerConfig: {}, + proxyConfig: { + ajax: { + // 请求后端接口方法 + query: async ({ page }, formValues) => { + return await getStoreListApi({ + page: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, + }, + height: 'auto', + border: false, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + refresh: true, // 刷新 + print: false, // 打印 + export: false, // 导出 + // custom: true, // 自定义列 + zoom: true, // 最大化最小化 + slots: { + buttons: 'toolbar-buttons', + }, + custom: { + // 自定义列-图标 + icon: 'vxe-icon-menu', + }, + }, + showOverflow: false, +}; diff --git a/apps/web-antd/src/views/my-gen/store/index.vue b/apps/web-antd/src/views/my-gen/store/index.vue new file mode 100644 index 00000000..eabfbaab --- /dev/null +++ b/apps/web-antd/src/views/my-gen/store/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-antd/vite.config.mts b/apps/web-antd/vite.config.mts index 861e05ef..8d4b43bf 100644 --- a/apps/web-antd/vite.config.mts +++ b/apps/web-antd/vite.config.mts @@ -5,14 +5,14 @@ export default defineConfig(async () => { application: {}, vite: { server: { - port: 8866, + port: 18866, proxy: { '/api': { changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), // mock代理目标地址 // target: 'http://localhost:5320/api', - target: 'http://127.0.0.1:18009/api/', + target: 'http://127.0.0.1:18010/api/', ws: true, }, }, diff --git a/docs/.vitepress/config/en.mts b/docs/.vitepress/config/en.mts index a74a7e5f..ff585694 100644 --- a/docs/.vitepress/config/en.mts +++ b/docs/.vitepress/config/en.mts @@ -51,7 +51,7 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] { return [ { collapsed: false, - text: 'Introduction', + text: '', items: [ { link: 'introduction/vben',