fix: todo

pull/210/head
xingyu4j 2025-09-05 14:11:35 +08:00
parent 2369f06654
commit f30a3451de
27 changed files with 170 additions and 137 deletions

View File

@ -59,6 +59,9 @@ const Textarea = defineAsyncComponent(() =>
const TimePicker = defineAsyncComponent(
() => import('ant-design-vue/es/time-picker'),
);
const TimeRangePicker = defineAsyncComponent(() =>
import('ant-design-vue/es/time-picker').then((res) => res.TimeRangePicker),
);
const TreeSelect = defineAsyncComponent(
() => import('ant-design-vue/es/tree-select'),
);
@ -126,6 +129,7 @@ export type ComponentType =
| 'Switch'
| 'Textarea'
| 'TimePicker'
| 'TimeRangePicker'
| 'TreeSelect'
| 'Upload'
| BaseFormComponentType;
@ -195,6 +199,7 @@ async function initComponentAdapter() {
Textarea: withDefaultPlaceholder(Textarea, 'input'),
RichTextarea,
TimePicker,
TimeRangePicker,
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
Upload,
FileUpload,

View File

@ -113,6 +113,8 @@ export namespace MallSpuApi {
createTime?: Date;
/** 商品状态 */
status?: number;
/** 浏览量 */
browseCount?: number;
}
/** 商品状态更新 */

View File

@ -31,6 +31,8 @@ export namespace MallDeliveryPickUpStoreApi {
status: number;
/** 绑定用户编号组数 */
verifyUserIds: number[];
/** 营业时间 用于fieldMappingTime */
rangeTime: any[];
}
/** 绑定自提店员请求 */

View File

@ -16,6 +16,7 @@ export namespace PayAppApi {
merchantId: number;
merchantName: string;
createTime?: Date;
channelCodes: string[];
}
/** 更新状态请求 */

View File

@ -1,76 +1,76 @@
// import type { RouteRecordRaw } from 'vue-router';
import type { RouteRecordRaw } from 'vue-router';
// const routes: RouteRecordRaw[] = [
// {
// path: '/mall/product',
// name: 'ProductCenter',
// meta: {
// title: '商品中心',
// icon: 'lucide:shopping-bag',
// keepAlive: true,
// hideInMenu: true,
// },
// children: [
// {
// path: 'spu/add',
// name: 'ProductSpuAdd',
// meta: {
// title: '商品添加',
// activeMenu: '/mall/product/spu',
// },
// component: () => import('#/views/mall/product/spu/form/index.vue'),
// },
// {
// path: String.raw`spu/edit/:id(\d+)`,
// name: 'ProductSpuEdit',
// meta: {
// title: '商品编辑',
// activeMenu: '/mall/product/spu',
// },
// component: () => import('#/views/mall/product/spu/form/index.vue'),
// },
// {
// path: String.raw`spu/detail/:id(\d+)`,
// name: 'ProductSpuDetail',
// meta: {
// title: '商品详情',
// activeMenu: '/crm/business',
// },
// component: () => import('#/views/mall/product/spu/form/index.vue'),
// },
// ],
// },
// {
// path: '/mall/trade',
// name: 'TradeCenter',
// meta: {
// title: '交易中心',
// icon: 'lucide:shopping-cart',
// keepAlive: true,
// hideInMenu: true,
// },
// children: [
// {
// path: String.raw`order/detail/:id(\d+)`,
// name: 'TradeOrderDetail',
// meta: {
// title: '订单详情',
// activeMenu: '/mall/trade/order',
// },
// component: () => import('#/views/mall/trade/order/detail/index.vue'),
// },
// {
// path: String.raw`after-sale/detail/:id(\d+)`,
// name: 'TradeAfterSaleDetail',
// meta: {
// title: '退款详情',
// activeMenu: '/mall/trade/after-sale',
// },
// component: () =>
// import('#/views/mall/trade/afterSale/detail/index.vue'),
// },
// ],
// },
// ];
const routes: RouteRecordRaw[] = [
{
path: '/mall/product',
name: 'ProductCenter',
meta: {
title: '商品中心',
icon: 'lucide:shopping-bag',
keepAlive: true,
hideInMenu: true,
},
children: [
{
path: 'spu/add',
name: 'ProductSpuAdd',
meta: {
title: '商品添加',
activeMenu: '/mall/product/spu',
},
component: () => import('#/views/mall/product/spu/modules/form.vue'),
},
{
path: String.raw`spu/edit/:id(\d+)`,
name: 'ProductSpuEdit',
meta: {
title: '商品编辑',
activeMenu: '/mall/product/spu',
},
component: () => import('#/views/mall/product/spu/modules/form.vue'),
},
{
path: String.raw`spu/detail/:id(\d+)`,
name: 'ProductSpuDetail',
meta: {
title: '商品详情',
activeMenu: '/crm/business',
},
component: () => import('#/views/mall/product/spu/modules/detail.vue'),
},
],
},
{
path: '/mall/trade',
name: 'TradeCenter',
meta: {
title: '交易中心',
icon: 'lucide:shopping-cart',
keepAlive: true,
hideInMenu: true,
},
children: [
{
path: String.raw`order/detail/:id(\d+)`,
name: 'TradeOrderDetail',
meta: {
title: '订单详情',
activeMenu: '/mall/trade/order',
},
component: () => import('#/views/mall/trade/order/modules/detail.vue'),
},
{
path: String.raw`after-sale/detail/:id(\d+)`,
name: 'TradeAfterSaleDetail',
meta: {
title: '退款详情',
activeMenu: '/mall/trade/after-sale',
},
component: () =>
import('#/views/mall/trade/afterSale/modules/detail.vue'),
},
],
},
];
// export default routes;
export default routes;

View File

@ -43,13 +43,12 @@ function handleEdit(row: MallCategoryApi.Category) {
/** 查看商品操作 */
const router = useRouter(); //
const handleViewSpu = (id: number) => {
// TODO @xingyu
function handleViewSpu(id: number) {
router.push({
name: 'ProductSpu',
query: { categoryId: id },
});
};
}
/** 删除分类 */
async function handleDelete(row: MallCategoryApi.Category) {

View File

@ -269,7 +269,7 @@ onMounted(async () => {
<!-- TODO @xingyu展开的样子有点丑 -->
<Descriptions
:column="4"
class="mt-4"
class="m-4"
:label-style="{
width: '100px',
fontWeight: 'bold',
@ -278,7 +278,7 @@ onMounted(async () => {
:content-style="{ width: '100px', fontSize: '14px' }"
>
<Descriptions.Item label="商品分类">
{{ treeToString(categoryList, row.categoryId as string) }}
{{ treeToString(categoryList, row.categoryId!) }}
</Descriptions.Item>
<Descriptions.Item label="商品名称">
{{ row.name }}
@ -291,7 +291,7 @@ onMounted(async () => {
{{ fenToYuan(row.costPrice as number) }}
</Descriptions.Item>
<Descriptions.Item label="浏览量">
{{ row.browseCount as number }}
{{ row.browseCount }}
</Descriptions.Item>
<Descriptions.Item label="虚拟销量">
{{ row.virtualSalesCount }}
@ -320,7 +320,7 @@ onMounted(async () => {
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['product:spu:delete'],
ifShow: () => row.type === 4,
ifShow: () => tabType === 4,
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: handleDelete.bind(null, row),
@ -331,7 +331,6 @@ onMounted(async () => {
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['product:spu:update'],
ifShow: () => row.type === 4,
onClick: handleStatus02Change.bind(
null,
row,
@ -343,7 +342,6 @@ onMounted(async () => {
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['product:spu:update'],
ifShow: () => row.type !== 4,
onClick: handleStatus02Change.bind(
null,
row,

View File

@ -1,6 +1,6 @@
<script lang="ts" setup></script>
<template>
detail
<!-- TODO @xingyu待开发 -->
<div>detail</div>
</template>

View File

@ -1,6 +1,6 @@
<script lang="ts" setup></script>
<template>
form
<!-- TODO @xingyu待开发 -->
<div>form</div>
</template>

View File

@ -31,7 +31,6 @@ function openAfterSaleDetail(row: MallAfterSaleApi.AfterSale) {
push({ name: 'TradeAfterSaleDetail', params: { id: row.id } });
}
// TODO @xingyu
/** 查看订单详情 */
function openOrderDetail(row: MallAfterSaleApi.AfterSale) {
push({ name: 'TradeOrderDetail', params: { id: row.id } });

View File

@ -0,0 +1,6 @@
<script lang="ts" setup></script>
<template>
<!-- TODO @xingyu待开发 -->
<div>detail</div>
</template>

View File

@ -7,14 +7,12 @@ import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { BrokerageRecordBizTypeEnum } from '@vben/constants';
import { BrokerageRecordBizTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { fenToYuan } from '@vben/utils';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getBrokerageRecordPage } from '#/api/mall/trade/brokerage/record';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { getRangePickerDefaultProps } from '#/utils';
/** 推广订单列表 */
@ -52,16 +50,13 @@ function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'sourceUserLevel',
label: '用户类型',
component: 'RadioGroup',
// TODO @xingyu
component: 'Select',
componentProps: {
options: [
{ label: '全部', value: 0 },
{ label: '一级推广人', value: 1 },
{ label: '二级推广人', value: 2 },
],
buttonStyle: 'solid',
optionType: 'button',
},
defaultValue: 0,
},

View File

@ -41,16 +41,13 @@ function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'level',
label: '用户类型',
component: 'RadioGroup',
// TODO @xingyu
component: 'Select',
componentProps: {
options: [
{ label: '全部', value: undefined },
{ label: '一级推广人', value: '1' },
{ label: '二级推广人', value: '2' },
],
buttonStyle: 'solid',
optionType: 'button',
},
},
{

View File

@ -58,18 +58,22 @@ export function useFormSchema(): VbenFormSchema[] {
label: '详细地址',
rules: 'required',
},
// TODO @xingyu时间类型不对
{
component: 'TimePicker',
fieldName: 'openingTime',
label: '营业开始时间',
rules: 'required',
},
{
component: 'TimePicker',
fieldName: 'closingTime',
label: '营业结束时间',
component: 'TimeRangePicker',
fieldName: 'rangeTime',
label: '营业时间',
rules: 'required',
componentProps: {
format: 'HH:mm',
minuteStep: 15,
disabledTime: () => {
return {
disabledHours: () => {
return [0, 1, 2, 3, 4, 5, 6, 7];
},
};
},
},
},
{
component: 'Input',

View File

@ -18,7 +18,6 @@ import { useBindFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<MallDeliveryPickUpStoreApi.PickUpStore>();
// TODO @xingyu
const getTitle = computed(() => {
return formData.value?.id
? $t('ui.actionTitle.edit', ['绑定店员'])

View File

@ -6,6 +6,7 @@ import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import dayjs from 'dayjs';
import { useVbenForm } from '#/adapter/form';
import {
@ -33,6 +34,7 @@ const [Form, formApi] = useVbenForm({
formItemClass: 'col-span-2',
labelWidth: 120,
},
fieldMappingTime: [['rangeTime', ['openingTime', 'closingTime'], 'HH:mm']],
layout: 'horizontal',
schema: useFormSchema(),
showDefaultActions: false,
@ -73,6 +75,10 @@ const [Modal, modalApi] = useVbenModal({
modalApi.lock();
try {
formData.value = await getDeliveryPickUpStore(data.id);
formData.value.rangeTime = [
dayjs(formData.value.openingTime, 'HH:mm'),
dayjs(formData.value.closingTime, 'HH:mm'),
];
// values
await formApi.setValues(formData.value);
} finally {

View File

@ -33,7 +33,6 @@ function onRefresh() {
gridApi.query();
}
const { push } = useRouter();
// TODO xingyu
/** 详情 */
function handleDetail(row: MallOrderApi.Order) {
push({ name: 'TradeOrderDetail', params: { id: row.id } });

View File

@ -0,0 +1,6 @@
<script lang="ts" setup></script>
<template>
<!-- TODO @xingyu待开发 -->
<div>detail</div>
</template>

View File

@ -263,7 +263,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
}
/** 修改用户等级 */
export function useLeavelFormSchema(): VbenFormSchema[] {
export function useLevelFormSchema(): VbenFormSchema[] {
return [
{
component: 'Input',

View File

@ -14,7 +14,7 @@ import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import BalanceForm from './modules/balance-form.vue';
import Form from './modules/form.vue';
import LeavelForm from './modules/leavel-form.vue';
import LevelForm from './modules/level-form.vue';
import PointForm from './modules/point-form.vue';
const router = useRouter();
@ -34,9 +34,8 @@ const [BalanceFormModal, balanceFormModalApi] = useVbenModal({
destroyOnClose: true,
});
// TODO @xingyu
const [LeavelFormModal, leavelFormModalApi] = useVbenModal({
connectedComponent: LeavelForm,
const [LevelFormModal, levelFormModalApi] = useVbenModal({
connectedComponent: LevelForm,
destroyOnClose: true,
});
@ -64,7 +63,7 @@ function handleEdit(row: MemberUserApi.User) {
/** 修改会员等级 */
function handleUpdateLevel(row: MemberUserApi.User) {
leavelFormModalApi.setData(row).open();
levelFormModalApi.setData(row).open();
}
/** 修改会员积分 */
@ -138,7 +137,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" />
<PointFormModal @success="onRefresh" />
<BalanceFormModal @success="onRefresh" />
<LeavelFormModal @success="onRefresh" />
<LevelFormModal @success="onRefresh" />
<Grid table-title="">
<template #toolbar-tools>
<TableAction

View File

@ -11,7 +11,7 @@ import { useVbenForm } from '#/adapter/form';
import { getUser, updateUser } from '#/api/member/user';
import { $t } from '#/locales';
import { useLeavelFormSchema } from '../data';
import { useLevelFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<MemberUserApi.User>();
@ -25,7 +25,7 @@ const [Form, formApi] = useVbenForm({
labelWidth: 80,
},
layout: 'horizontal',
schema: useLeavelFormSchema(),
schema: useLevelFormSchema(),
showDefaultActions: false,
});

View File

@ -80,13 +80,15 @@ export function useFormSchema(): VbenFormSchema[] {
}
/** 搜索表单配置 */
// TODO @xingyu缺了 placeholder
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
fieldName: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
},
];
}

View File

@ -34,20 +34,18 @@ function handleCreate() {
appFormModalApi.setData(null).open();
}
function handleEdit(row: Required<PayAppApi.App>) {
function handleEdit(row: PayAppApi.App) {
appFormModalApi.setData({ id: row.id }).open();
}
async function handleDelete(row: Required<PayAppApi.App>) {
async function handleDelete(row: PayAppApi.App) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.name]),
key: 'action_key_msg',
});
try {
await deleteApp(row.id as number);
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
key: 'action_key_msg',
});
onRefresh();
} finally {
@ -180,7 +178,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
/>
</template>
<template #alipayAppConfig="{ row }">
<!-- TODO @xingyuchannelCodes 爆红 -->
<TableAction
:actions="[
{

View File

@ -1,10 +1,10 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getAppList } from '#/api/pay/app';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { getAppList } from '#/api/pay/app';
import { getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */
@ -33,12 +33,16 @@ export function useGridFormSchema(): VbenFormSchema[] {
componentProps: {
allowClear: true,
options: getDictOptions(DICT_TYPE.PAY_NOTIFY_TYPE, 'number'),
placeholder: '请选择通知类型',
},
},
{
fieldName: 'dataId',
label: '关联编号',
component: 'Input',
componentProps: {
placeholder: '请输入关联编号',
},
},
{
fieldName: 'status',
@ -47,12 +51,16 @@ export function useGridFormSchema(): VbenFormSchema[] {
componentProps: {
allowClear: true,
options: getDictOptions(DICT_TYPE.PAY_NOTIFY_STATUS, 'number'),
placeholder: '请选择通知状态',
},
},
{
fieldName: 'merchantOrderId',
label: '商户订单编号',
component: 'Input',
componentProps: {
placeholder: '请输入商户订单编号',
},
},
{
fieldName: 'createTime',
@ -61,12 +69,12 @@ export function useGridFormSchema(): VbenFormSchema[] {
componentProps: {
...getRangePickerDefaultProps(),
allowClear: true,
placeholder: ['开始日期', '结束日期'],
},
},
];
}
// TODO @xingyu缺少 placeholder
/** 列表的字段 */
export function useGridColumns(): VxeTableGridOptions['columns'] {
return [

View File

@ -8,13 +8,15 @@ import { getDictOptions } from '@vben/hooks';
import { getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */
// TODO @xingyu少了 placeholder
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
fieldName: 'userId',
label: '用户编号',
component: 'Input',
componentProps: {
placeholder: '请输入用户编号',
},
},
{
fieldName: 'userType',
@ -22,6 +24,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
component: 'Select',
componentProps: {
options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'),
placeholder: '请选择用户类型',
},
},
{
@ -31,6 +34,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
componentProps: {
allowClear: true,
...getRangePickerDefaultProps(),
placeholder: ['开始日期', '结束日期'],
},
},
];

View File

@ -14,6 +14,9 @@ export function useFormSchema(): VbenFormSchema[] {
label: '套餐名',
component: 'Input',
rules: 'required',
componentProps: {
placeholder: '请输入套餐名称',
},
},
{
fieldName: 'payPrice',
@ -24,6 +27,7 @@ export function useFormSchema(): VbenFormSchema[] {
min: 0,
precision: 2,
step: 0.01,
placeholder: '请输入支付金额',
},
},
{
@ -35,6 +39,7 @@ export function useFormSchema(): VbenFormSchema[] {
min: 0,
precision: 2,
step: 0.01,
placeholder: '请输入赠送金额',
},
},
{
@ -44,19 +49,22 @@ export function useFormSchema(): VbenFormSchema[] {
rules: 'required',
componentProps: {
options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'),
placeholder: '请选择开启状态',
},
},
];
}
/** 列表的搜索表单 */
// TODO @xingyu少了 placeholder
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
fieldName: 'name',
label: '套餐名称',
component: 'Input',
componentProps: {
placeholder: '请输入套餐名称',
},
},
{
fieldName: 'status',
@ -65,6 +73,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
componentProps: {
allowClear: true,
options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'),
placeholder: '请选择状态',
},
},
{
@ -74,6 +83,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
componentProps: {
allowClear: true,
...getRangePickerDefaultProps(),
placeholder: ['开始日期', '结束日期'],
},
},
];

View File

@ -7,14 +7,12 @@ import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { BrokerageRecordBizTypeEnum } from '@vben/constants';
import { BrokerageRecordBizTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { fenToYuan } from '@vben/utils';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getBrokerageRecordPage } from '#/api/mall/trade/brokerage/record';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { getRangePickerDefaultProps } from '#/utils';
/** 推广订单列表 */
@ -52,16 +50,13 @@ function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'sourceUserLevel',
label: '用户类型',
component: 'RadioGroup',
// TODO @
component: 'Select',
componentProps: {
options: [
{ label: '全部', value: 0 },
{ label: '一级推广人', value: 1 },
{ label: '二级推广人', value: 2 },
],
buttonStyle: 'solid',
optionType: 'button',
},
defaultValue: 0,
},