feat: 内容管理

This commit is contained in:
2025-10-29 17:10:53 +08:00
parent 476ee7a754
commit 4c628fee22
67 changed files with 8210 additions and 4494 deletions

View File

@@ -0,0 +1,5 @@
const CateGorySelect = () => {
return <div></div>;
};
export default CateGorySelect;

View File

@@ -2,51 +2,54 @@ import type {
ProColumns,
ProCoreActionType,
ProFormColumnsType,
} from "@ant-design/pro-components";
import dayjs from "dayjs";
import TagEditor from "@/components/TagEditor";
import TinyMCEEditor from "@/components/Tinymce";
} from '@ant-design/pro-components';
import { Modal, message, Switch } from 'antd';
import dayjs from 'dayjs';
import TagEditor from '@/components/TagEditor';
import TinyMCEEditor from '@/components/Tinymce';
import UploadImages from '@/components/Upload/UploadImages';
import { dateFormatS } from '@/constants';
import {
getCategoryList,
putCategoryUpdate,
} from "@/services/prodApi/category";
import { Input, message, Modal, Switch } from "antd";
export const baseTenantColumns: ProColumns<API.CategoryDO>[] = [
type Category,
getProdCategoryPage,
updateProdCategory,
} from '@/services/prod/category-manager';
export const baseTenantColumns: ProColumns<Category>[] = [
{
title: "类目名称",
dataIndex: "categoryName",
title: '类目名称',
dataIndex: 'categoryName',
width: 100,
},
{
title: "类目ID",
dataIndex: "categoryId",
title: '类目ID',
dataIndex: 'categoryId',
},
{
title: "类目层级",
dataIndex: "grade",
title: '类目层级',
dataIndex: 'grade',
hideInSearch: true, // 在搜索表单中隐藏
},
{
title: "父级类目",
dataIndex: "parentName",
title: '父级类目',
dataIndex: 'parentName',
hideInSearch: true, // 在搜索表单中隐藏
},
{
title: "排序权重",
dataIndex: "sort",
title: '排序权重',
dataIndex: 'sort',
hideInSearch: true, // 在搜索表单中隐藏
},
{
title: "状态",
dataIndex: "status",
valueType: "switch",
title: '状态',
dataIndex: 'status',
valueType: 'switch',
hideInSearch: true,
render: (
_,
record: API.CategoryDO,
record: Category,
_index: number,
action: ProCoreActionType | undefined
action: ProCoreActionType | undefined,
) => (
<Switch
checked={record.status === 1}
@@ -54,17 +57,17 @@ export const baseTenantColumns: ProColumns<API.CategoryDO>[] = [
unCheckedChildren="禁用"
onChange={(checked) => {
Modal.confirm({
title: "确认操作",
content: `确认要"${checked ? "启用" : "禁用"}${
title: '确认操作',
content: `确认要"${checked ? '启用' : '禁用'}${
record.categoryName
}"类目吗?`,
onOk: async () => {
console.log(checked);
await putCategoryUpdate({
await updateProdCategory({
status: checked ? 1 : 0,
categoryId: record.categoryId,
});
message.success("修改成功");
message.success('修改成功');
action?.reload();
},
});
@@ -73,145 +76,158 @@ export const baseTenantColumns: ProColumns<API.CategoryDO>[] = [
),
},
{
title: "创建时间",
dataIndex: "createTime",
valueType: "dateRange",
title: '创建时间',
dataIndex: 'createTime',
valueType: 'dateRange',
hideInSearch: true, // 在搜索表单中隐藏
render: (_, record: API.CategoryDO) =>
dayjs(record.createTime).format("YYYY-MM-DD HH:mm:ss"),
render: (_, record: Category) =>
dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss'),
},
];
export const formColumns = (data: {
type: string;
grade: number;
}): ProFormColumnsType[] => [
{
title: "类目",
dataIndex: "grade",
valueType: "radio",
fieldProps: {
options: [
{ label: "一级类目", value: 1 },
{ label: "二级类目", value: 2 },
{ label: "三级类目", value: 3 },
],
disabled: data.type === "update",
export const formColumns = (data: { type: string }): ProFormColumnsType[] => {
console.log(data, 'data');
return [
{
title: '类目',
dataIndex: 'grade',
valueType: 'radio',
fieldProps: {
options: [
{ label: '一级类目', value: 1 },
{ label: '二级类目', value: 2 },
{ label: '三级类目', value: 3 },
],
disabled: data.type === 'update',
},
},
},
{
title: "类目名称",
dataIndex: "categoryName",
formItemProps: {
rules: [
{
required: true,
message: "请输入用户名",
},
],
{
title: '类目名称',
dataIndex: 'categoryName',
formItemProps: {
rules: [
{
required: true,
message: '请输入用户名',
},
],
},
},
},
{
title: "排序权重",
dataIndex: "sort",
valueType: "digit",
},
{
title: "类目描述",
dataIndex: "description",
valueType: "textarea",
renderFormItem: () => {
return <TinyMCEEditor />;
{
title: '排序权重',
dataIndex: 'sort',
valueType: 'digit',
},
},
{
title: "关联父级",
dataIndex: "parentId",
valueType: "select",
hideInForm: data.grade - 1 <= 0,
fieldProps: {
fieldNames: { label: "categoryName", value: "categoryId" },
{
title: '类目描述',
dataIndex: 'description',
valueType: 'textarea',
renderFormItem: () => {
return <TinyMCEEditor />;
},
},
request: async () => {
const grade = data.grade ? data.grade - 1 : undefined;
const res = await getCategoryList({ grade });
return res;
{
title: '关联父级',
dataIndex: 'parentId',
valueType: 'select',
fieldProps: {
fieldNames: { label: 'categoryName', value: 'categoryId' },
},
dependencies: ['grade'],
request: async (params) => {
const res = await getProdCategoryPage({
grade: Number(params.grade) - 1,
});
return res;
},
renderFormItem: (schema, config, form) => {
const grade = form.getFieldValue('grade');
if (Number(grade) === 1) {
return null;
}
return config.defaultRender(schema);
},
},
},
{
title: "类目icon",
dataIndex: "icon",
},
{
title: "类目标签",
dataIndex: "tag",
renderFormItem: () => {
return (
<TagEditor
placeholder="输入标签名称"
maxCount={10}
tagProps={{
color: "blue",
}}
/>
);
{
title: '类目icon',
dataIndex: 'icon',
renderFormItem: () => {
return <UploadImages multiple={true} />;
},
},
},
{
title: "类目状态",
dataIndex: "status",
hideInForm: data.type === "create",
fieldProps: {
disabled: data.type === "update",
{
title: '类目标签',
dataIndex: 'tag',
renderFormItem: () => {
return (
<TagEditor
placeholder="输入标签名称"
maxCount={10}
tagProps={{
color: 'blue',
}}
/>
);
},
},
renderFormItem: (_schema, _config, form) => {
const status = form.getFieldValue("type");
return <Input value={status ? "开启" : "禁用"} disabled />;
{
title: '类目状态',
dataIndex: 'status',
hideInForm: data.type === 'create',
renderFormItem: (_schema, _config, form) => {
const status = form.getFieldValue('status');
return <span>{status ? '启用' : '禁用'}</span>;
},
},
},
{
title: "类目ID",
dataIndex: "categoryId",
hideInForm: data.type === "create",
fieldProps: {
disabled: data.type === "update",
{
title: '类目ID',
dataIndex: 'categoryId',
hideInForm: data.type === 'create',
renderFormItem: (_schema, _config, form) => {
const categoryId = form.getFieldValue('categoryId');
return <span>{categoryId}</span>;
},
},
},
{
title: "创建时间",
dataIndex: "createTime",
valueType: "dateTime",
hideInForm: data.type === "create",
fieldProps: {
disabled: data.type === "update",
{
title: '创建时间',
dataIndex: 'createTime',
valueType: 'dateTime',
hideInForm: data.type === 'create',
renderFormItem: (_schema, _config, form) => {
const createTime = form.getFieldValue('createTime');
return <span>{dayjs(createTime).format(dateFormatS)}</span>;
},
},
},
{
title: "创建人",
dataIndex: "creator",
hideInForm: data.type === "create",
fieldProps: {
disabled: data.type === "update",
{
title: '创建人',
dataIndex: 'creator',
hideInForm: data.type === 'create',
renderFormItem: (_schema, _config, form) => {
const creator = form.getFieldValue('creator');
return <span>{creator}</span>;
},
},
},
{
title: "更新时间",
dataIndex: "updateTime",
valueType: "dateTime",
hideInForm: data.type === "create",
fieldProps: {
disabled: data.type === "update",
{
title: '更新时间',
dataIndex: 'updateTime',
valueType: 'dateTime',
hideInForm: data.type === 'create',
renderFormItem: (_schema, _config, form) => {
const dateTime = form.getFieldValue('dateTime');
return <span>{dayjs(dateTime).format(dateFormatS)}</span>;
},
},
},
{
title: "更新人",
dataIndex: "updator",
hideInForm: data.type === "create",
fieldProps: {
disabled: data.type === "update",
{
title: '更新人',
dataIndex: 'updator',
hideInForm: data.type === 'create',
renderFormItem: (_schema, _config, form) => {
const updator = form.getFieldValue('updator');
return <span>{updator}</span>;
},
},
},
];
];
};
// {
// title: "模板内容",

View File

@@ -1,24 +1,26 @@
import { PlusOutlined } from "@ant-design/icons";
import type { ActionType, ProColumns } from "@ant-design/pro-components";
import type { TabsProps } from "antd";
import { Tabs } from "antd";
import { useCallback, useRef, useState } from "react";
import { PlusOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import type { TabsProps } from 'antd';
import { Tabs } from 'antd';
import { useCallback, useRef, useState } from 'react';
import ConfigurableDrawerForm, {
type ConfigurableDrawerFormRef,
} from "@/components/DrawerForm";
import EnhancedProTable from "@/components/EnhancedProTable";
import type { ToolbarAction } from "@/components/EnhancedProTable/types";
import { formStatusType } from "@/constants";
} from '@/components/DrawerForm';
import EnhancedProTable from '@/components/EnhancedProTable';
import type { ToolbarAction } from '@/components/EnhancedProTable/types';
import { formStatusType } from '@/constants';
import {
getCategoryList,
postCategoryCreate,
putCategoryUpdate,
} from "@/services/prodApi/category";
import { baseTenantColumns, formColumns } from "./config";
type Category,
type CategoryReq,
createProdCategory,
getProdCategoryPage,
updateProdCategory,
} from '@/services/prod/category-manager';
import { baseTenantColumns, formColumns } from './config';
const ProdCategory = () => {
const tableRef = useRef<ActionType>(null);
const [type, setType] = useState<"create" | "update" | "test">("create");
const [type, setType] = useState<'create' | 'update' | 'test'>('create');
const [grade, setGrade] = useState<number>();
const configurableDrawerRef = useRef<ConfigurableDrawerFormRef>(null);
const [id, setId] = useState<number>(0);
@@ -26,11 +28,11 @@ const ProdCategory = () => {
(key: string) => {
setGrade(Number(key));
},
[grade]
[grade],
);
const onFetch = async (params: API.getProductCategoryCategoryListParams) => {
const data = await getCategoryList({
const onFetch = async (params: CategoryReq) => {
const data = await getProdCategoryPage({
...params,
grade: grade ? Number(grade) : undefined,
});
@@ -41,48 +43,48 @@ const ProdCategory = () => {
};
const handleAdd = () => {
setType("create");
configurableDrawerRef.current?.open({ grade: grade ? grade : 1 });
setType('create');
configurableDrawerRef.current?.open({ grade: 1 });
};
const toolbarActions: ToolbarAction[] = [
{
key: "add",
label: "新建",
type: "primary",
key: 'add',
label: '新建',
type: 'primary',
icon: <PlusOutlined />,
onClick: handleAdd,
},
];
const handleEdit = async (row: API.CategoryDO) => {
setType("update");
const handleEdit = async (row: Category) => {
setType('update');
row.categoryId && setId(row.categoryId);
configurableDrawerRef.current?.open(row);
};
const handleSubmit = useCallback(
async (values: API.CategoryDO) => {
if (type === "create") {
await postCategoryCreate(values);
async (values: Category) => {
if (type === 'create') {
await createProdCategory(values);
} else {
await putCategoryUpdate({
await updateProdCategory({
...values,
categoryId: id,
});
}
tableRef.current?.reload();
tableRef.current?.reload(true);
return true;
},
[id, type]
[id, type],
);
const actionColumns: ProColumns<API.CategoryDO> = {
title: "操作",
dataIndex: "option",
valueType: "option",
fixed: "right",
const actionColumns: ProColumns<Category> = {
title: '操作',
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
width: 120,
render: (_text: React.ReactNode, record: API.CategoryDO, _: number) => [
render: (_text: React.ReactNode, record: Category, _: number) => [
<a key="edit" onClick={() => handleEdit(record)}>
</a>,
@@ -94,7 +96,7 @@ const ProdCategory = () => {
const renderChildren = () => {
return (
<>
<EnhancedProTable<API.CategoryDO>
<EnhancedProTable<Category>
ref={tableRef}
columns={columns}
rowKey="categoryId"
@@ -107,8 +109,8 @@ const ProdCategory = () => {
<ConfigurableDrawerForm
ref={configurableDrawerRef}
title={formStatusType[type]}
// width="50vw"
columns={formColumns({ grade: Number(grade), type })}
width={'60vw'}
columns={formColumns({ type })}
onSubmit={handleSubmit}
footer={undefined}
bodyStyle={{}}
@@ -117,25 +119,25 @@ const ProdCategory = () => {
);
};
const items: TabsProps["items"] = [
const items: TabsProps['items'] = [
{
key: "",
label: "全部分类",
key: '',
label: '全部分类',
children: renderChildren(),
},
{
key: "3",
label: "三级分类",
key: '3',
label: '三级分类',
children: renderChildren(),
},
{
key: "2",
label: "二级分类",
key: '2',
label: '二级分类',
children: renderChildren(),
},
{
key: "1",
label: "一级分类",
key: '1',
label: '一级分类',
children: renderChildren(),
},
];
@@ -143,6 +145,7 @@ const ProdCategory = () => {
<Tabs
defaultActiveKey={grade as unknown as string}
items={items}
destroyOnHidden
onChange={onChange}
/>
);

View File

@@ -0,0 +1,151 @@
import {
ProForm,
ProFormGroup,
ProFormSelect,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { Divider } from 'antd';
import React from 'react';
import TagEditor from '@/components/TagEditor';
import TinymceEditor from '@/components/Tinymce';
import UploadImages from '@/components/Upload/UploadImages';
import UploadVideo from '@/components/Upload/UploadVideo';
import type { Prod } from '@/services/prod/prod-manager';
interface ProdInfoProps<T> {
onRefresh?: (type?: string) => void;
data?: T;
}
const ProdInfo = <T extends Record<string, any>>(props: ProdInfoProps<T>) => {
console.log(props, 'ProdInfo');
return (
<>
<ProFormGroup title="一、基础信息">
<ProFormText
name="prodName"
label="商品名字"
rules={[{ required: true }]}
width="xl"
/>
<ProFormText name="abbreviation" label="商品简称" width="xl" />
<ProFormText name="brief" label="商品概述" width="xl" />
<ProFormText name="prodNumber" label="商品编码" width="xl" />
<ProFormText name="brand" label="品牌" width="xl" />
<ProFormText name="shopId" label="商品所有权" width="xl" />
<ProFormText name="categoryName" label="关联类目" width="xl" />
<ProForm.Item
name="tag"
label="商品标签"
tooltip="设置卖点标签单标签限xx字符最多x个标签"
layout="horizontal"
width="xl"
required={false}
// getValueFromEvent={(e) => e.fileList}
>
<TagEditor
placeholder="输入标签名称"
maxCount={10}
tagProps={{
color: 'blue',
}}
/>
</ProForm.Item>
</ProFormGroup>
<ProFormGroup title="二、内容展示">
<ProForm.Item
style={{ width: '100%' }}
name="pic"
label="主图"
width="xl"
extra="仅支持.jpg .png 格式建议图片比例1:1限1张"
// rules={[{ required: true }]}
// getValueFromEvent={(e) => e.fileList}
>
<UploadImages />
</ProForm.Item>
<ProForm.Item
style={{ width: '100%' }}
name="imgs"
label="轮播图"
layout="horizontal"
width="xl"
extra="仅支持.jpg .png 格式建议图片比例1:1限7张"
// getValueFromEvent={(e) => e.fileList}
>
<UploadImages />
</ProForm.Item>
<ProForm.Item
style={{ width: '100%' }}
name="whiteImg"
label="白底图"
width="xl"
extra="仅支持.jpg .png 格式建议图片比例1:1限1张"
// getValueFromEvent={(e) => e.fileList}
>
<UploadImages />
</ProForm.Item>
<ProForm.Item
name="video"
label="主视频"
width="xl"
extra="仅支持.MP4 .MOV 格式建议比例1:1、16:9限1个"
// getValueFromEvent={(e) => e.fileList}
>
<UploadVideo />
</ProForm.Item>
<ProForm.Item
name="content"
label="图文介绍"
rules={[{ required: true }]}
width="xl"
// getValueFromEvent={(e) => e.fileList}
>
<TinymceEditor />
</ProForm.Item>
</ProFormGroup>
<ProFormGroup title="三、营销与传播">
<ProFormText
name="seoShortName"
label="短标题"
colProps={{
span: 20,
}}
/>
<ProFormText name="seoSearch" label="SEO标题" width={'xl'} />
<ProFormTextArea name="keyword" label="商品关键词" width={'xl'} />
<Divider />
<ProForm.Item
style={{ width: '100%' }}
name="shareImage"
label="分享图"
width="xl"
extra="仅支持.jpg .png 格式限1张"
>
<UploadImages />
</ProForm.Item>
<ProFormTextArea
name="shareContent"
label="分享话术"
placeholder={'请输入分享话术'}
width={'xl'}
/>
</ProFormGroup>
<ProFormGroup>
<ProFormSelect name="status" label="商品状态" readonly />
<ProFormText name="prodId" label="商品ID" readonly />
<ProFormText name="createTime" label="创建时间" readonly />
<ProFormText name="creator" label="创建人" readonly />
<ProFormText name="updateTime" label="更新时间" readonly />
<ProFormText name="updater" label="更新人" readonly />
<ProFormText name="version" label="版本号" readonly />
</ProFormGroup>
</>
);
};
export default React.memo(ProdInfo) as <_T extends Record<string, any>>(
props: ProdInfoProps<Prod>,
) => React.ReactElement;

View File

@@ -0,0 +1,69 @@
import { ProForm, ProFormText } from '@ant-design/pro-components';
const ServiceRule: React.FC = () => {
return (
<ProForm<{
name: string;
company: string;
}>
grid
onFinish={async (values) => {
// await waitTime(2000);
console.log(values);
// message.success('提交成功');
}}
initialValues={{
name: '蚂蚁设计有限公司',
useMode: 'chapter',
}}
>
<ProForm.Group>
<ProFormText
width="md"
name="name"
label="签约客户名称"
tooltip="最长为 24 位"
placeholder="请输入名称"
/>
<ProFormText
width="md"
name="company"
label="我方公司名称"
placeholder="请输入名称"
/>
</ProForm.Group>
<ProFormText width="sm" name="id" label="主合同编号" />
<ProForm.Item
label="数组数据"
name="dataSource"
// initialValue={defaultData}
trigger="onValuesChange"
>
{/* <EditableProTable<DataSourceType>
rowKey="id"
toolBarRender={false}
columns={columns}
recordCreatorProps={{
newRecordType: 'dataSource',
position: 'top',
record: () => ({
id: Date.now(),
addonBefore: 'ccccccc',
decs: 'testdesc',
}),
}}
editable={{
type: 'multiple',
editableKeys,
onChange: setEditableRowKeys,
actionRender: (row, _, dom) => {
return [dom.delete];
},
}} */}
{/* /> */}
</ProForm.Item>
</ProForm>
);
};
export default ServiceRule;

View File

@@ -0,0 +1,31 @@
import { ProForm } from '@ant-design/pro-components';
import React from 'react';
import SkuConfig from './sku-confiig';
import SkuList from './sku-list';
const Sku: React.FC = () => {
return (
<>
<ProForm.Item
style={{ width: '100%' }}
name="prodPropSaveReqVO"
layout="horizontal"
width="xl"
// getValueFromEvent={(e) => e.fileList}
>
<SkuConfig />
</ProForm.Item>
<ProForm.Item
style={{ width: '100%' }}
name="skuList"
layout="horizontal"
width="xl"
// getValueFromEvent={(e) => e.fileList}
>
<SkuList />
</ProForm.Item>
</>
);
};
export default React.memo(Sku);

View File

@@ -0,0 +1,23 @@
import { Typography } from 'antd';
import React from 'react';
import DraggableTagList from '@/components/Draggable/DraggableTagList';
const { Title, Text } = Typography;
const SkuConfig: React.FC<{
value?: API.ProdPropSaveReqVO;
onChange?: (value: API.ProdPropSaveReqVO) => void;
}> = () => {
// const { value, onChange } = props;
return (
<>
<Title level={4}></Title>
<Text type="secondary">
使<a></a>
</Text>
<DraggableTagList />
</>
);
};
export default React.memo(SkuConfig);

View File

@@ -0,0 +1,22 @@
import { Typography } from 'antd';
import React from 'react';
import type { SkuConfig } from '@/services/prod/prod-manager';
const { Title, Text } = Typography;
const SkuList: React.FC<{
value?: SkuConfig;
onChange?: (value: SkuConfig) => void;
}> = (props) => {
const { value } = props;
console.log('value', value);
return (
<>
<Title level={4}>SKU </Title>
<Text type="secondary">
SKU价格与可售数量
</Text>
</>
);
};
export default React.memo(SkuList);

View File

@@ -0,0 +1,90 @@
import type { ProColumns } from '@ant-design/pro-components';
import { Badge, Button, Image, Space, Typography } from 'antd';
import dayjs from 'dayjs';
import type { Prod } from '@/services/prod/prod-manager';
const { Text } = Typography;
export const baseTenantColumns: ProColumns<Prod>[] = [
{
title: '商品',
dataIndex: 'prodName',
render: (_, record) => (
<Space>
<Image width={64} height={64} src={record.pic} />
<div>
<div>
<Text>{record.categoryName}</Text>
</div>
<div>
<Text type="secondary">ID{record.categoryName}</Text>
</div>
<div>
<Text type="secondary">{record.categoryName}</Text>
</div>
</div>
</Space>
),
},
{
title: '服务信息',
dataIndex: 'categoryId',
render: () => (
<Space direction="vertical">
<div>
<Text type="secondary"></Text>
<Text></Text>
</div>
<div>
<Text type="secondary"></Text>
<Text></Text>
</div>
<div>
<Text type="secondary"></Text>
<Text></Text>
</div>
</Space>
),
},
{
title: '状态',
dataIndex: 'status',
valueType: 'switch',
width: 300,
hideInSearch: true,
render: () => (
<Space direction="vertical">
<Space>
<Badge status="success" text="出售中" />
<Badge status="default" text="已置灰" />
<Badge status="warning" text="待审核" />
<Badge status="default" text="仓库中" />
</Space>
<Button size="small" type="dashed">
</Button>
</Space>
),
},
{
title: '时间信息',
dataIndex: 'createTime',
valueType: 'dateRange',
hideInSearch: true, // 在搜索表单中隐藏
render: (_, record) => (
<Space direction="vertical">
<div>
<Image></Image>
</div>
<div>
<Text type="secondary"></Text>
{dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss')}
</div>
<div>
<Text type="secondary"></Text>
{dayjs(record.updateTime).format('YYYY-MM-DD HH:mm:ss')}
</div>
</Space>
),
},
];

View File

@@ -0,0 +1,84 @@
import type { FormInstance } from '@ant-design/pro-components';
import { ProCard, ProForm, StepsForm } from '@ant-design/pro-components';
import { message } from 'antd';
import { useEffect } from 'react';
import ProdInfo from '@/pages/prod/list/components/prod-info';
import Sku from '@/pages/prod/list/components/sku';
import type { Prod, ProdDetail, SkuConfig } from '@/services/prod/prod-manager';
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
const ProdDetailPage: React.FC<{
data?: Prod;
formRef?: React.RefObject<FormInstance<any>>;
}> = (props) => {
const { data, formRef } = props;
console.log(data, 'ProdDetailPage');
useEffect(() => {
if (data) {
formRef?.current?.setFieldsValue(data);
}
}, [data]);
return (
<ProCard>
{data?.prodId ? (
<ProForm
formRef={formRef}
layout="horizontal"
grid={true}
submitter={false}
>
<ProdInfo />
</ProForm>
) : (
<StepsForm<ProdDetail>
current={0}
formRef={formRef}
submitter={false}
onFinish={async () => {
await waitTime(1000);
message.success('提交成功');
}}
formProps={{
validateMessages: {
required: '此项为必填项',
},
}}
>
<StepsForm.StepForm<ProdDetail>
grid={true}
layout="horizontal"
name="info"
title="填写商品信息"
onFinish={async () => {
try {
await formRef?.current?.validateFields();
console.log(formRef?.current?.getFieldsValue());
} catch (error: any) {
console.log(error);
message.error(error.msg);
}
return true;
}}
>
<ProdInfo data={data} />
</StepsForm.StepForm>
<StepsForm.StepForm<SkuConfig> name="sku" title="设置商品规格">
<Sku />
</StepsForm.StepForm>
<StepsForm.StepForm<ProdDetail> name="prod" title="发布商品">
</StepsForm.StepForm>
</StepsForm>
)}
</ProCard>
);
};
export default ProdDetailPage;

View File

@@ -1,5 +1,250 @@
import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import type { MenuProps, TabsProps } from 'antd';
import { Button, Dropdown, Space, Tabs } from 'antd';
import { useCallback, useRef, useState } from 'react';
import ConfigurableDrawerForm, {
type ConfigurableDrawerFormRef,
} from '@/components/DrawerForm';
import EnhancedProTable from '@/components/EnhancedProTable';
import type { ToolbarAction } from '@/components/EnhancedProTable/types';
import { formStatusType } from '@/constants';
import ProdDetail from '@/pages/prod/list/detail';
import {
createProd,
getProdDetail,
getProdPage,
type Prod,
type ProdReq,
updateProd,
} from '@/services/prod/prod-manager';
import { baseTenantColumns } from './config';
const ProdList = () => {
return <div>ProdList</div>;
const tableRef = useRef<ActionType>(null);
const [type, setType] = useState<'create' | 'update' | 'test'>('create');
const [status, setStatus] = useState<number>();
const detailRef = useRef<ConfigurableDrawerFormRef>(null);
// const editRef = useRef<ConfigurableDrawerFormRef>(null);
const [id, setId] = useState<number>(0);
const onChange = useCallback(
(key: string) => {
setStatus(Number(key));
},
[status],
);
const onFetch = async (params: ProdReq) => {
const data = await getProdPage({
...params,
status: status ? status : undefined,
});
return {
data: data.list,
success: true,
};
};
const handleAdd = () => {
setType('create');
detailRef.current?.open({});
};
const toolbarActions: ToolbarAction[] = [
{
key: 'add',
label: '新建',
type: 'primary',
icon: <PlusOutlined />,
onClick: handleAdd,
},
];
const handleEdit = async (row: Prod) => {
setType('update');
const res = await getProdDetail({ id: row.prodId as number });
setId(row.prodId as number);
detailRef.current?.open(res);
};
// 商品更新
// const _handleEditSubmit = async (values: Prod) => {
// await updateProd(values);
// tableRef.current?.reload();
// message.success("编辑成功");
// return true;
// };
const handleSubmit = useCallback(
async (values: Prod) => {
if (type === 'create') {
await createProd(values);
} else {
await updateProd({
...values,
categoryId: id,
});
}
tableRef.current?.reload();
return true;
},
[id, type],
);
// const renderDetailFooter = () => {
// if (type === "update") {
// return (
// <Space>
// <Button onClick={() => detailRef.current?.close()}>取消</Button>
// <Button type="primary" onClick={handleEditSubmit}>
// 确定
// </Button>
// </Space>
// );
// } else {
// return (
// <Button type="primary" onClick={() => detailRef.current?.close()}>
// 确定
// </Button>
// );
// }
// };
const itemsMenu = (row: Prod): MenuProps['items'] => [
{
key: 'edit',
label: (
<Button type="link" onClick={() => handleEdit(row)}>
</Button>
),
},
{
key: 'sku',
label: <Button type="link">SKU管理</Button>,
},
{
key: 'rules-service',
label: <Button type="link"></Button>,
},
{
key: 'extend-service',
label: <Button type="link"></Button>,
},
{
key: 'status',
label: <Button type="link"></Button>,
},
{
key: 'delete',
label: (
<Button color="danger" variant="link">
</Button>
),
},
];
const actionColumns: ProColumns<Prod> = {
title: '操作',
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
align: 'center',
width: 200,
render: (_text: React.ReactNode, record: Prod, _: number) => [
<Space style={{ width: '100%' }} wrap size={0} key={record.prodId}>
<Space.Compact direction="vertical" block key="1">
<Button type="link" onClick={() => handleEdit(record)}>
</Button>
<Button type="link">SKU管理</Button>
</Space.Compact>
<Space.Compact direction="vertical" block key="2">
<Button type="link"></Button>
<Button type="link"></Button>
</Space.Compact>
<Space.Compact direction="vertical" block key="3">
<Dropdown menu={{ items: itemsMenu(record) }} placement="bottomLeft">
<Button type="link">
<EllipsisOutlined />
</Button>
</Dropdown>
</Space.Compact>
</Space>,
],
};
const columns = [...baseTenantColumns, actionColumns];
const renderChildren = () => {
return (
<>
<EnhancedProTable<Prod>
ref={tableRef}
columns={columns}
request={onFetch}
toolbarActions={toolbarActions}
headerTitle="短信渠道"
showIndex={false}
rowKey="prodId"
showSelection={false}
/>
<ConfigurableDrawerForm
ref={detailRef}
onSubmit={handleSubmit}
// footer={renderDetailFooter()}
title={formStatusType[type]}
width={'80vw'}
bodyStyle={{
background: '#f5f5f5',
paddingTop: 8,
}}
>
<ProdDetail />
</ConfigurableDrawerForm>
{/* <ConfigurableDrawerForm
ref={editRef}
onSubmit={handleEditSubmit}
footer={renderDetailFooter()}
width={"80vw"}
bodyStyle={{
background: "#f5f5f5",
paddingTop: 8,
}}
>
<ProdDetail />
</ConfigurableDrawerForm> */}
</>
);
};
const items: TabsProps['items'] = [
{
key: '',
label: '全部商品',
children: renderChildren(),
},
{
key: '1',
label: '出售中的商品',
children: renderChildren(),
},
{
key: '0',
label: '仓库中的商品',
children: renderChildren(),
},
{
key: '2',
label: '待审核的商品',
children: renderChildren(),
},
];
return (
<Tabs
defaultActiveKey={status as unknown as string}
items={items}
onChange={onChange}
/>
);
};
export default ProdList;