소스 검색

add product list page

dev
powersir 1 년 전
부모
커밋
087f896594
7개의 변경된 파일386개의 추가작업 그리고 71개의 파일을 삭제
  1. +2
    -1
      src/models/index.ts
  2. +49
    -13
      src/models/product.data.ts
  3. +0
    -0
      src/models/user.data.ts
  4. +192
    -4
      src/pages/custom/product/finished/index.tsx
  5. +38
    -23
      src/pages/custom/product/material/index.tsx
  6. +39
    -2
      src/pages/custom/product/sample/index.tsx
  7. +66
    -28
      src/pages/custom/product/shape/index.tsx

+ 2
- 1
src/models/index.ts 파일 보기

@@ -1,4 +1,5 @@
export * from './user.ts'
export * from './user.data.ts'
export * from './product.data.ts'

export interface ResponseDTO<T>{
code: number;


src/pages/custom/product/shape/shape.data.ts → src/models/product.data.ts 파일 보기

@@ -24,11 +24,14 @@ export interface Shape {


export interface ProductBase {
id?: number;
productName: string;
productNameEn?:string;
}

export interface ProductClassify {
id: number;
name?: string;
}

export interface ProductImage {
@@ -36,23 +39,14 @@ export interface ProductImage {
imgUrl:string;
}

export interface Product {
export interface ProductCategory {
id: number;
spuCode: string;
classifyId: number;
sourceType: number;
productStatus: number;
creatorId: number;
createTime: string;
base: ProductBase;
classify: ProductClassify;
attrs: string[];
productImgs: ProductImage[];
productSkus: string[];
creatorName: string;
categoryName: string;
categoryNameEn: string;
}



export interface SdParamEmplate {
id: number;
createTime: string;
@@ -73,3 +67,45 @@ export interface SdParamEmplate {
isDelete: number;
niter: number;
}

export interface SkuAttr {
attrName: string;
attrValName: string;
}

export interface ProductSku {
id: number;
spuCode: string;
skuCode: string;
skuImgId: number;
weight: number;
costPrice: number;
homeFreight: number;
packCost: number;
minRetailPrice: number;
length: number;
width: number;
height: number;
rawSku: string;
skuStatus: number;
attrs: SkuAttr[];
skuImgUrl: string;
}

export interface Product {
id: number;
spuCode: string;
categoryId?: number;
classifyId: number;
sourceType: number;
productStatus: number;
creatorId: number;
createTime: string;
base: ProductBase;
category?: ProductCategory;
classify: ProductClassify;
attrs: string[];
productImgs: ProductImage[];
productSkus: ProductSku[];
creatorName: string;
}

src/models/user.ts → src/models/user.data.ts 파일 보기


+ 192
- 4
src/pages/custom/product/finished/index.tsx 파일 보기

@@ -1,9 +1,197 @@
import { Empty } from 'antd';
import { Space, Table, Button, Image, Divider, Badge, Modal, notification, message } from 'antd';
import type { TableColumnsType } from 'antd';
import { t } from '@/utils/i18n';
import React, { useState } from 'react';
import mData from '../../../../../mock/productListPage.json'
import { PlusOutlined, ExclamationCircleFilled } from '@ant-design/icons';
import type { Product, ProductBase, ProductImage, ProductSku } from '@/models'

const { confirm } = Modal;
type NotificationType = 'success' | 'info' | 'warning' | 'error';
//成品
const FinishedProductPage: React.FC = () => {

const [notificationApi, notificationContextHolder] = notification.useNotification();
const [messageApi, messageContextHolder] = message.useMessage();

const openNotificationWithIcon = (type: NotificationType) => {
notificationApi[type]({
message: '删除成功',
description:
'商品信息已删除',
});
};

const showDeleteConfirm = () => {
confirm({
title: '确认要将该商品删除吗?',
icon: <ExclamationCircleFilled />,
content: '请注意删除以后不可恢复!',
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk() {
return new Promise((resolve, reject) => {
setTimeout(() => {
messageApi.open({
type: 'success',
content: '删除成功',
});
resolve(null)
}, 1000);
// openNotificationWithIcon('success')

}).catch(() => messageApi.open({
type: 'error',
content: '操作失败',
}));
},
onCancel() {
},
});
};

const columns: TableColumnsType<Product> = [
{
title: '商品主图',
dataIndex: 'productImgs',
key: 'productImgs',
render: (value: ProductImage[]) => (
value.length > 0 && <Image className='bg-[gold]' src={value[0].imgUrl} />
),
align: 'center',
width: 100,
},
{
title: 'SPU编码',
dataIndex: 'spuCode',
key: 'spuCode',
width: 100,
},
{
title: '数据源',
dataIndex: 'sourceType',
key: 'sourceType',
width: 100,
render: (value: number) => (value == 4 ? 'diy导入' : '未知')
},
{
title: '商品标题',
key: 'base',
dataIndex: 'base',
render: (value: ProductBase) => (
<>
<div>{value.productName}</div>
<div>{value.productNameEn}</div>
</>
)
},
{
title: '类目',
key: 'category',
dataIndex: ['category', 'categoryName'],
width: 100,
},
{
title: '商品状态',
key: 'productStatus',
dataIndex: 'productStatus',
width: 100,
render: (value: number) => {
return (value === 1 ? <Badge status="error" text="未审核" /> : <Badge status="success" text="已审核" />)
}
},
{
title: '总销售额',
key: 'specimenNumber',
dataIndex: 'specimenNumber',
width: 100,
render: (value: number) => ('-')
},
{
title: '创建人',
dataIndex: 'creatorName',
key: 'creatorName',
width: 150,
},
{
title: '创建时间',
key: 'createTime',
dataIndex: 'createTime',
width: 200,
},
{
title: t("QkOmYwne" /* 操作 */),
key: 'action',
render: (_, record) => (
<Space size="small" split={(
<Divider type='vertical' />
)}>
<a
onClick={() => {

}}>
编辑
</a>
<a
onClick={() => {
showDeleteConfirm()
}}>
删除
</a>
<a
onClick={() => {

}}>
认领商品
</a>
</Space>
),
width: 250,
},
];

const expandedColumnsRender = (item: Product) => {
const expandedColumns: TableColumnsType<ProductSku> = [
{ title: '序号', key: 'index', align: 'center', render: (data, _, index) => (<>{index}</>) },
{
title: '缩略图', dataIndex: 'skuImgUrl', key: 'productImgs', width: 80, render: (value: string) => (
<Image className='bg-[gold] align-middle flex items-center justify-center w-[40px] h-[40px]' src={value} />
)
},
{ title: 'SKU编码', dataIndex: 'skuCode', key: 'spuCode' },
{ title: '建议零售价', dataIndex: 'costPrice', key: 'costPrice' },
{ title: '重量', dataIndex: 'weight', key: 'weight' },
{ title: '销售额', dataIndex: 'packCost', key: 'packCost' },
{ title: '长', dataIndex: 'length', key: 'length' },
{ title: '宽', dataIndex: 'width', key: 'width' },
{ title: '高', dataIndex: 'height', key: 'height' }
];
const data: Array<ProductSku> = item.productSkus;
return <Table columns={expandedColumns} dataSource={data} pagination={false} size='small' />;
}

const data: Array<Product> = mData as Array<Product>;

const CustomMade = () => {
return (
<Empty />
<>
{notificationContextHolder}
{messageContextHolder}
<div className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div className="py-[8px]">
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />}> 批量操作 </Button>
</div>
<Table rowKey="id"
scroll={{ x: true }}
columns={columns}
expandable={{ expandedRowRender: expandedColumnsRender, defaultExpandedRowKeys: ['0'] }}
dataSource={data}
className='bg-transparent'
pagination={{ position: ['bottomRight'] }} />
</div>
</>

);
};

export default CustomMade;
export default FinishedProductPage;

+ 38
- 23
src/pages/custom/product/material/index.tsx 파일 보기

@@ -1,30 +1,13 @@
import { Space, Tag, Table, Form, Row, Col, Input, InputNumber, Button, Avatar, Divider } from 'antd';
import { Space, Tag, Table, Modal, message, Col, Input, InputNumber, Button, Avatar, Divider } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { t } from '@/utils/i18n';
import { IconBuguang } from '@/assets/icons/buguang';
import React, { useState } from 'react';
import type { TableRowSelection } from 'antd/es/table/interface';
import mData from '../../../../../mock/findMaterialPage.json'
import { PlusOutlined } from '@ant-design/icons';
import { PlusOutlined, ExclamationCircleFilled } from '@ant-design/icons';


// {
// "id": 1465,
// "createTime": "2023-06-06 10:47:21",
// "classifyId": 52,
// "materialImgId": 1875217,
// "materialName": "HDC-11010015-P",
// "materialRemark": "multiple boys, brown hair, striped, hat, baseball cap, dark skin, backpack, jacket, dark-skinned male, pink dress, bag, white background, headband, camera, pants, shirt, striped shirt, backwards hat, dress, 1girl, parody, bandana, black hair, simple background, vest, holding, english text, 3boys, standing, blue jacket, white skin, short hair, shoes",
// "materialWidth": 885.0000,
// "materialHeight": 711.0000,
// "materialSize": 617393,
// "createId": 1,
// "classify": {
// "id": 52,
// "classifyName": "其他"
// },
// "materialImgUrl": "https://test.vogocm.com:9010/eshop/eshop_img/2023/6/06/20230606104721A806.png"
// },
const { confirm } = Modal;

interface Classify {
id: number;
@@ -48,6 +31,35 @@ interface DataType {
}

const TablePage: React.FC = () => {
const [messageApi, messageContextHolder] = message.useMessage();

const showDeleteConfirm = (item: DataType) => {
confirm({
title: `确认删除标题为: ${item.materialName} 的素材吗?`,
icon: <ExclamationCircleFilled />,
content: '请注意删除以后不可恢复!',
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk() {
return new Promise((resolve, reject) => {
setTimeout(() => {
messageApi.open({
type: 'success',
content: '删除成功',
});
resolve(null)
}, 1000);

}).catch(() => messageApi.open({
type: 'error',
content: '操作失败',
}));
},
onCancel() {
},
});
};

const columns: ColumnsType<DataType> = [
{
@@ -172,8 +184,7 @@ const TablePage: React.FC = () => {
</a>
<a
onClick={() => {
// setEditData(record);
// setCreateVisible(true);
showDeleteConfirm(record)
}}>
删除
</a>
@@ -232,7 +243,9 @@ const TablePage: React.FC = () => {


return (
<div className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<>
{messageContextHolder}
<div className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div className="py-[8px]">
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined/>}> 新增素材 </Button>
</div>
@@ -240,6 +253,8 @@ const TablePage: React.FC = () => {
pagination={{ position: ['bottomRight'] }}
/>
</div>
</>

);
};



+ 39
- 2
src/pages/custom/product/sample/index.tsx 파일 보기

@@ -1,4 +1,4 @@
import { Space, Tag, Table, Form, Row, Col, Input, InputNumber, Button, Avatar } from 'antd';
import { Space, Modal, Table, Form, message, Col, Input, InputNumber, Button, Avatar } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { t } from '@/utils/i18n';
import { IconBuguang } from '@/assets/icons/buguang';
@@ -9,6 +9,9 @@ import MaskPictureEditor from './components/mask-picture-editor';
import type { SampleAttribute } from './components/attr-editor'
import type { MaskPicture } from './components/mask-picture-editor';
import { useNavigate } from 'react-router-dom';
import { ExclamationCircleFilled } from '@ant-design/icons';

const { confirm } = Modal;

interface DataType {
id: number;
@@ -25,6 +28,36 @@ interface DataType {

const TablePage: React.FC = () => {

const [messageApi, messageContextHolder] = message.useMessage();

const showDeleteConfirm = (item: DataType) => {
confirm({
title: `确认删除标题为: ${item.prototypeName} 的样机吗?`,
icon: <ExclamationCircleFilled />,
content: `请注意删除以后不可恢复!`,
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk() {
return new Promise((resolve, reject) => {
setTimeout(() => {
messageApi.open({
type: 'success',
content: '删除成功',
});
resolve(null)
}, 1000);

}).catch(() => messageApi.open({
type: 'error',
content: '操作失败',
}));
},
onCancel() {
},
});
};

const columns: ColumnsType<DataType> = [
{
title: '示例图',
@@ -84,7 +117,10 @@ const TablePage: React.FC = () => {
onClick={() => {
navigate('/custom/product/sample/editor')
}}>编辑</a>
<a>删除</a>
<a
onClick={() => {
showDeleteConfirm(record)
}}>删除</a>
</Space>
),
},
@@ -269,6 +305,7 @@ const TablePage: React.FC = () => {

return (
<div>
{messageContextHolder}
<div className="dark:bg-[rgb(33,41,70)] rounded-md">
<Table rowKey="id" rowSelection={rowSelection} scroll={{ x: true }} columns={columns} dataSource={data} className='bg-transparent'
pagination={{ position: ['bottomRight'] }}


+ 66
- 28
src/pages/custom/product/shape/index.tsx 파일 보기

@@ -1,23 +1,54 @@
import { Space, Table, Button, Image, Divider } from 'antd';
import { Space, Table, Button, Image, Divider, message, Modal } from 'antd';
import type { TableColumnsType } from 'antd';
import { t } from '@/utils/i18n';
import { IconBuguang } from '@/assets/icons/buguang';
import React, { useState } from 'react';
import mData from '../../../../../mock/findDiySpecimenPage.json'
import shapeData from '../../../../../mock/findSpecimensByPrototypeId.json'
import { PlusOutlined } from '@ant-design/icons';
import type { ShapeProperty, Shape, ProductImage } from './shape.data'
import { PlusOutlined, ExclamationCircleFilled } from '@ant-design/icons';
import type { ShapeProperty, Shape, ProductImage } from '@/models'

const { confirm } = Modal;

const ShapePage: React.FC = () => {

const [messageApi, messageContextHolder] = message.useMessage();

const showDeleteConfirm = (item: Shape) => {
confirm({
title: `确认删除标题为: ${item.sdParamEmplate.chinaName} 的素材吗?`,
icon: <ExclamationCircleFilled />,
content: '请注意删除以后不可恢复!',
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk() {
return new Promise((resolve, reject) => {
setTimeout(() => {
messageApi.open({
type: 'success',
content: '删除成功',
});
resolve(null)
}, 1000);

}).catch(() => messageApi.open({
type: 'error',
content: '操作失败',
}));
},
onCancel() {
},
});
};

const columns: TableColumnsType<ShapeProperty> = [
{
title: '示例图',
dataIndex: 'oneImgUrl',
key: 'oneImgUrl',
render: (value: string) => (
<div className='flex justify-center'>
<Image className='bg-[gold] align-middle flex items-center justify-center w-[40px] h-[40px]' src={value}/>
</div>
<Image className='bg-[gold] w-[40px] h-[40px]' src={value} />
),
align: 'center',
width: 130,
@@ -35,7 +66,7 @@ const ShapePage: React.FC = () => {
width: 150,
},
{
title:'类目',
title: '类目',
key: 'categoryName',
dataIndex: 'categoryName'
},
@@ -44,7 +75,7 @@ const ShapePage: React.FC = () => {
key: 'specimenNumber',
dataIndex: 'specimenNumber',
width: 100,
render:(value: number) => (<>{value}</>)
render: (value: number) => (<>{value}</>)
},
{
title: '创建人',
@@ -53,7 +84,7 @@ const ShapePage: React.FC = () => {
width: 150,
},
{
title:'创建时间',
title: '创建时间',
key: 'createTime',
dataIndex: 'createTime',
width: 200,
@@ -79,24 +110,27 @@ const ShapePage: React.FC = () => {

const expandedColumnsRender = (item: ShapeProperty) => {
const expandedColumns: TableColumnsType<Shape> = [
{ title: '序号', key: 'index', align: 'center', render:(data, _ ,index)=>(<>{index}</>)},
{ title: '主图', dataIndex: ['product', 'productImgs'], key: 'productImgs', width: 100, render: (value: ProductImage[]) => (
value.length > 0 && <Image className='bg-[gold] align-middle flex items-center justify-center w-[40px] h-[40px]' src={value[0].imgUrl}/>
)},
{ title: '序号', key: 'index', align: 'center', render: (data, _, index) => (<>{index}</>) },
{
title: '主图', dataIndex: ['product', 'productImgs'], key: 'productImgs', width: 100, render: (value: ProductImage[]) => (
value.length > 0 && <Image className='bg-[gold] align-middle flex items-center justify-center w-[40px] h-[40px]' src={value[0].imgUrl} />
)
},
{ title: 'SPU', dataIndex: ['product', 'spuCode'], key: 'spuCode' },
{ title: '商品标题', dataIndex: ['product', 'base', 'productName'], key: 'productName' },
{ title: '背景词', dataIndex: ['sdParamEmplate','chinaName'], key: 'chinaName' },
{ title: '背景词', dataIndex: ['sdParamEmplate', 'chinaName'], key: 'chinaName' },
{ title: '商品状态', dataIndex: 'upgradeNum', key: 'status' },
{ title: '数据来源', dataIndex: ['product', 'sourceType'], key: 'sourceType', render: (value: number) => (<>diy导入</>)},
{ title: '数据来源', dataIndex: ['product', 'sourceType'], key: 'sourceType', render: (value: number) => (<>diy导入</>) },
{ title: '创建人', dataIndex: ['product', 'creatorName'], key: 'creatorName' },
{
title: t("QkOmYwne" /* 操作 */),
key: 'operation',
render: () => (
render: (_, record) => (
<Space size="middle">
<a>审核</a>
<a>编辑</a>
<a>删除</a>
<a
onClick={() => {showDeleteConfirm(record)}}>删除</a>
</Space>
),
},
@@ -118,18 +152,22 @@ const ShapePage: React.FC = () => {


return (
<div className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div className="py-[8px]">
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined/>}> 新增款式 </Button>
<>
{messageContextHolder}
<div className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div className="py-[8px]">
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />}> 新增款式 </Button>
</div>
<Table rowKey="id"
scroll={{ x: true }}
columns={columns}
expandable={{ expandedRowRender: expandedColumnsRender, defaultExpandedRowKeys: ['0'] }}
dataSource={data}
className='bg-transparent'
pagination={{ position: ['bottomRight'] }} />
</div>
<Table rowKey="id"
scroll={{ x: true }}
columns={columns}
expandable={{ expandedRowRender: expandedColumnsRender, defaultExpandedRowKeys: ['0'] }}
dataSource={data}
className='bg-transparent'
pagination={{ position: ['bottomRight'] }}/>
</div>
</>

);
};



불러오는 중...
취소
저장