提交 5dfaf713 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 d0308fdc
......@@ -14,6 +14,7 @@
"antd": "^5.24.3",
"axios": "^1.8.1",
"blueimp-md5": "^2.19.0",
"lodash-es": "^4.17.21",
"lucide-react": "^0.477.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
......@@ -25,6 +26,7 @@
},
"devDependencies": {
"@types/blueimp-md5": "^2.18.2",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.13.9",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
......@@ -1468,6 +1470,23 @@
"@types/unist": "*"
}
},
"node_modules/@types/lodash": {
"version": "4.17.16",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/mdast": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
......@@ -3284,6 +3303,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"license": "MIT"
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
......
......@@ -16,6 +16,7 @@
"antd": "^5.24.3",
"axios": "^1.8.1",
"blueimp-md5": "^2.19.0",
"lodash-es": "^4.17.21",
"lucide-react": "^0.477.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
......@@ -27,6 +28,7 @@
},
"devDependencies": {
"@types/blueimp-md5": "^2.18.2",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.13.9",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
......
......@@ -33,3 +33,13 @@ export async function uploadFile(data: Record<string, any>) {
export function getMapList() {
return httpRequest.get('/api/resource/v1/util/get-data-dictionary-list')
}
// 我的数据集列表
export function getMyList(params?: Partial<{ page: number; 'per-page': number }>) {
return httpRequest.get('/api/bi/v1/data/my/list', { params })
}
// 查看字段详情
export function getMyField() {
return httpRequest.get('/api/bi/v1/data/my/field-detail')
}
......@@ -20,80 +20,80 @@ export interface AppListRef {
reset: () => void
}
const AppList = forwardRef<AppListRef, AppListProps>((props, ref) => {
const { fetchApi, filters = [], filterAside, dataSource = [], ...rest } = props
const AppList = forwardRef<AppListRef, AppListProps>(
({ fetchApi, filters = [], filterAside, dataSource = [], ...props }, ref) => {
const [form] = Form.useForm()
const [queryParams, setQueryParams] = useState<QueryParams>({ page: 1, 'per-page': 10 })
const [form] = Form.useForm()
const [queryParams, setQueryParams] = useState<QueryParams>({ page: 1, 'per-page': 10 })
const { data, refetch, isLoading } = useQuery({
queryKey: ['appList', queryParams],
queryFn: async () => {
return fetchApi ? await fetchApi(queryParams) : { list: dataSource || [], total: dataSource?.length || 0 }
},
})
const { data, refetch, isLoading } = useQuery({
queryKey: ['appList', queryParams],
queryFn: async () => {
return fetchApi ? await fetchApi(queryParams) : { list: dataSource || [], total: dataSource?.length || 0 }
},
})
// 暴露方法
useImperativeHandle(ref, () => ({
refresh: refetch,
reset: handleReset,
}))
// 暴露方法
useImperativeHandle(ref, () => ({
refresh: refetch,
reset: handleReset,
}))
// 提交筛选
const handleSearch = (values: Record<string, any>) => {
console.log(values)
setQueryParams((prev) => ({ ...prev, ...values, page: 1 }))
}
// 提交筛选
const handleSearch = (values: Record<string, any>) => {
console.log(values)
setQueryParams((prev) => ({ ...prev, ...values, page: 1 }))
}
const handleReset = () => {
form.resetFields()
setQueryParams({ page: 1, 'per-page': 10 })
}
const handleReset = () => {
form.resetFields()
setQueryParams({ page: 1, 'per-page': 10 })
}
// 处理分页
const handlePageChange = (page: number, pageSize: number) => {
setQueryParams((prev) => ({ ...prev, page, 'per-page': pageSize }))
}
// 处理分页
const handlePageChange = (page: number, pageSize: number) => {
setQueryParams((prev) => ({ ...prev, page, 'per-page': pageSize }))
}
const pagination = {
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: [10, 20, 30, 40, 50],
showTotal: (total: number) => `共${total}条数据`,
onChange: handlePageChange,
}
const pagination = {
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: [10, 20, 30, 40, 50],
showTotal: (total: number) => `共${total}条数据`,
onChange: handlePageChange,
}
const filterElement = (
<div className="app-list-filter" style={{ marginBottom: 20 }}>
<Flex justify="space-between">
<Form layout="inline" autoComplete="off" form={form} onFinish={handleSearch}>
{filters.map((item, index) => (
<Form.Item label={item.label} name={item.name} key={index}>
{item.element}
</Form.Item>
))}
<Space>
<Button type="primary" htmlType="button" ghost onClick={handleReset}>
重置
</Button>
<Button type="primary" htmlType="submit">
查询
</Button>
</Space>
</Form>
{filterAside}
</Flex>
</div>
)
const filterElement = (
<div className="app-list-filter" style={{ marginBottom: 20 }}>
<Flex justify="space-between">
<Form layout="inline" autoComplete="off" form={form} onFinish={handleSearch}>
{filters.map((item, index) => (
<Form.Item label={item.label} name={item.name} key={index}>
{item.element}
</Form.Item>
))}
<Space>
<Button type="primary" htmlType="button" ghost onClick={handleReset}>
重置
</Button>
<Button type="primary" htmlType="submit">
查询
</Button>
</Space>
</Form>
{filterAside}
</Flex>
</div>
)
return (
<div className="app-list">
{filters.length > 0 && filterElement}
<div className="app-list-table">
<Table rowKey="id" dataSource={data?.list} loading={isLoading} pagination={pagination} {...rest} />
return (
<div className="app-list">
{filters.length > 0 && filterElement}
<div className="app-list-table">
<Table bordered rowKey="id" dataSource={data?.list} loading={isLoading} pagination={pagination} {...props} />
</div>
</div>
</div>
)
})
)
}
)
export default AppList
import { Table, TableProps } from 'antd'
export default function DataRender(props: TableProps) {
const pagination = {
showSizeChanger: true,
pageSize: 100,
pageSizeOptions: [100, 200, 500],
showTotal: (total: number) => `共${total}条数据`,
}
export default function DataRender({ pagination = {}, ...props }: TableProps) {
return (
<Table
bordered
scroll={{ x: 'max-content', y: 600 }}
scroll={{ x: 'max-content', y: 800 }}
tableLayout="auto"
size="middle"
pagination={pagination}
pagination={{
hideOnSinglePage: true,
showSizeChanger: true,
defaultPageSize: 100,
pageSizeOptions: [100, 200, 500],
showTotal: (total: number) => `共${total}条数据`,
...pagination,
}}
{...props}
/>
)
......
import { Button, Card, Flex } from 'antd'
import { lazy, ReactNode, useState } from 'react'
import { Card, Flex } from 'antd'
import AIChat from '@/components/ai/AIChat'
import ViewData from './ViewData'
import { ReactNode } from 'react'
import DataRender from './DataRender'
import { useDataQuery } from '@/hooks/useQuery'
export default function DataWrap({ title, buttons }: { title: string; buttons: ReactNode }) {
const ViewDataFiledButtonModal = lazy(() => import('./ViewDataFiledButtonModal'))
export default function DataWrap({
hasAI = true,
title,
headerRender,
buttons,
empty,
}: {
title: string
buttons?: ReactNode
headerRender?: (data: any) => ReactNode
empty?: ReactNode
hasAI: boolean
}) {
const [pagination, setPagination] = useState({ page: 1, 'per-page': 100 })
const { data, isPending } = useDataQuery(pagination)
const columns: any = data.title.map((item: any) => {
return {
title: item.name,
dataIndex: item.english_name,
align: 'center',
minWidth: 120,
}
})
const handleTableChange = (pagination: any) => {
setPagination({ page: pagination.current, 'per-page': pagination.pageSize })
}
const Header = () => {
if (headerRender) return headerRender(data)
return (
<Flex justify="space-between" style={{ marginBottom: '20px' }}>
<Flex wrap gap={10}>
{buttons}
</Flex>
<ViewDataFiledButtonModal></ViewDataFiledButtonModal>
</Flex>
)
}
return (
<Flex gap={20} style={{ height: '100%' }}>
<Card className="app-card" title={title} style={{ flex: 1, overflowX: 'hidden' }}>
<Flex justify="space-between" style={{ marginBottom: '20px' }}>
<Flex wrap gap={10}>
{buttons}
</Flex>
<Button>查看字段详细信息</Button>
</Flex>
<ViewData />
{empty && !data.info ? (
empty
) : (
<>
<Header />
<DataRender
rowKey={'pk_id'}
loading={isPending}
dataSource={data.list}
pagination={{ total: data.total, current: pagination.page, pageSize: pagination['per-page'] }}
columns={columns}
onChange={handleTableChange}
/>
</>
)}
</Card>
<AIChat></AIChat>
{hasAI && <AIChat />}
</Flex>
)
}
import DataRender from './DataRender'
export default function FormModal(props) {
const columns = [
{
title: '订单编号',
dataIndex: '订单编号',
align: 'center',
minWidth: 120,
},
{
title: '品牌',
dataIndex: '品牌',
align: 'center',
minWidth: 120,
},
{
title: '店铺',
dataIndex: '店铺',
align: 'center',
minWidth: 120,
},
{
title: '负责人',
dataIndex: '负责人',
align: 'center',
minWidth: 120,
},
{
title: '商品',
dataIndex: '商品',
align: 'center',
minWidth: 120,
},
{
title: '颜色',
dataIndex: '颜色',
align: 'center',
minWidth: 120,
},
{
title: '客户购买类型',
dataIndex: '客户购买类型',
align: 'center',
minWidth: 120,
},
{
title: '销量',
dataIndex: '销量',
align: 'center',
minWidth: 120,
},
{
title: '单价',
dataIndex: '单价',
align: 'center',
minWidth: 120,
},
{
title: '销售额',
dataIndex: '销售额',
align: 'center',
minWidth: 120,
},
{
title: '是否优惠',
dataIndex: '是否优惠',
align: 'center',
minWidth: 120,
},
{
title: '优惠金额',
dataIndex: '优惠金额',
align: 'center',
minWidth: 120,
},
{
title: '实际单价',
dataIndex: '实际单价',
align: 'center',
minWidth: 120,
},
{
title: '实际付款',
dataIndex: '实际付款',
align: 'center',
minWidth: 120,
},
{
title: '成本',
dataIndex: '成本',
align: 'center',
minWidth: 120,
},
{
title: '利润',
dataIndex: '利润',
align: 'center',
minWidth: 120,
},
{
title: '客户性别',
dataIndex: '客户性别',
align: 'center',
minWidth: 120,
},
{
title: '客户年龄',
dataIndex: '客户年龄',
align: 'center',
minWidth: 120,
},
{
title: '会员情况',
dataIndex: '会员情况',
align: 'center',
minWidth: 120,
},
{
title: '是否访问页面',
dataIndex: '是否访问页面',
align: 'center',
minWidth: 120,
},
{
title: '访问页面时长',
dataIndex: '访问页面时长',
align: 'center',
minWidth: 120,
},
{
title: '交易状态',
dataIndex: '交易状态',
align: 'center',
minWidth: 120,
},
{
title: '商品状态',
dataIndex: '商品状态',
align: 'center',
minWidth: 120,
},
{
title: '收货人姓名',
dataIndex: '收货人姓名',
align: 'center',
minWidth: 120,
},
{
title: '收货人电话',
dataIndex: '收货人电话',
align: 'center',
minWidth: 120,
},
{
title: '发货地址',
dataIndex: '发货地址',
align: 'center',
minWidth: 120,
},
{
title: '收货地址省份',
dataIndex: '收货地址省份',
align: 'center',
minWidth: 120,
},
{
title: '收货地址',
dataIndex: '收货地址',
align: 'center',
minWidth: 120,
},
{
title: '物流公司',
dataIndex: '物流公司',
align: 'center',
minWidth: 120,
},
{
title: '运单号',
dataIndex: '运单号',
align: 'center',
minWidth: 120,
},
{
title: '运送方式',
dataIndex: '运送方式',
align: 'center',
minWidth: 120,
},
{
title: '支付时间',
dataIndex: '支付时间',
align: 'center',
minWidth: 120,
},
{
title: '预计到达时间',
dataIndex: '预计到达时间',
align: 'center',
minWidth: 120,
},
{
title: '实际到达时间',
dataIndex: '实际到达时间',
align: 'center',
minWidth: 120,
},
{
title: '快递反馈',
dataIndex: '快递反馈',
align: 'center',
minWidth: 120,
},
{
title: '是否退货',
dataIndex: '是否退货',
align: 'center',
minWidth: 120,
},
{
title: '退款原因',
dataIndex: '退款原因',
align: 'center',
minWidth: 120,
},
{
title: '客户满意度',
dataIndex: '客户满意度',
align: 'center',
minWidth: 120,
},
{
title: '出生日期',
dataIndex: '出生日期',
align: 'center',
minWidth: 120,
},
{
title: '品类',
dataIndex: '品类',
align: 'center',
minWidth: 120,
},
{
title: '材质',
dataIndex: '材质',
align: 'center',
minWidth: 120,
},
]
const data = [
{
订单编号: 'A929818',
品牌: '丽丽',
店铺: '卡卡家女装',
负责人: '袁英',
商品: '安全裤',
颜色: '红色',
客户购买类型: '零售',
销量: 256,
单价: 156.14,
销售额: 156.14,
是否优惠: '店铺活动优惠',
优惠金额: 12,
实际单价: 144.14,
实际付款: 144.14,
成本: 92.25,
利润: 51.89,
客户性别: 0,
客户年龄: '33岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 2,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '孙倩',
收货人电话: '181****4056',
发货地址: '福建省',
收货地址省份: '陕西省',
收货地址: '陕西省延安市子长县',
物流公司: ' 百世快递',
运单号: 'L810590',
运送方式: '公路运输',
支付时间: 44003,
预计到达时间: 44008,
实际到达时间: 44008,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '中评',
出生日期: 32807,
品类: '女裤',
材质: '麻质',
},
{
订单编号: 'A451538',
品牌: '雅羊人',
店铺: '秋兰女装专卖店',
负责人: '刘佳',
商品: '不规则连衣裙',
颜色: '粉色',
客户购买类型: '零售',
销量: 198,
单价: 247.44,
销售额: 247.44,
是否优惠: '无',
优惠金额: 0,
实际单价: 247.44,
实际付款: 247.44,
成本: 133.62,
利润: 113.82,
客户性别: 0,
客户年龄: '36岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 8,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '余玉英',
收货人电话: '181****8027',
发货地址: '广东省',
收货地址省份: '⼴西壮族⾃治区',
收货地址: '广西壮族自治区贵港市',
物流公司: '极兔快 递',
运单号: 'L806051',
运送方式: '公路运输',
支付时间: 45029,
预计到达时间: 45031,
实际到达时间: 45031,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 31610,
品类: '连衣裙',
材质: '氨纶',
},
{
订单编号: 'A479212',
品牌: '威兰西',
店铺: '威兰西旗舰店',
负责人: '陈建平',
商品: '网红同款连衣裙',
颜色: '白色',
客户购买类型: '零售',
销量: 128,
单价: 245.49,
销售额: 245.49,
是否优惠: '双12优惠',
优惠金额: 15,
实际单价: 230.49,
实际付款: 230.49,
成本: 147.51,
利润: 82.98,
客户性别: 0,
客户年龄: '22岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 4,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '杨军',
收货人电话: '139****7024',
发货地址: '浙江省',
收货地址省份: '河北省',
收货地址: '河北省衡水市武强县',
物流公司: '顺丰快递',
运单号: 'L356804',
运送方式: '公路运输',
支付时间: 43800,
预计到达时间: 43805,
实际到达时间: 43806,
快递反馈: '延后',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 36649,
品类: '连衣裙',
材质: '棉质',
},
{
订单编号: 'A389270',
品牌: 'H&R',
店铺: '壹佰女装',
负责人: '杨兰英',
商品: '蕾丝花边T恤',
颜色: '紫色',
客户购买类型: '批发',
销量: 13,
单价: 168.3,
销售额: 2187.9,
是否优惠: '双11优惠',
优惠金额: 200,
实际单价: 152.92,
实际付款: 1987.9,
成本: 1212.62,
利润: 775.28,
客户性别: 0,
客户年龄: '26岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 4,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '郑强',
收货人电话: '159****6299',
发货地址: '四川省',
收货地址省份: '河南省',
收货地址: '河南省郑州市新密市',
物流公司: '顺丰快递',
运单号: 'L335437',
运送方式: '公路运输',
支付时间: 43779,
预计到达时间: 43783,
实际到达时间: 43784,
快递反馈: '延后',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 35189,
品类: '上衣',
材质: '棉质',
},
{
订单编号: 'A327122',
品牌: 'H&R',
店铺: 'H&R旗舰店',
负责人: '袁英',
商品: '春夏新款连衣裙',
颜色: '红色',
客户购买类型: '批发',
销量: 13,
单价: 119.64,
销售额: 1555.32,
是否优惠: '无',
优惠金额: 0,
实际单价: 119.64,
实际付款: 1555.32,
成本: 855.43,
利润: 699.89,
客户性别: 0,
客户年龄: '22岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 8,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '刘冬梅',
收货人电话: '185****4586',
发货地址: '广东省',
收货地址省份: '陕西省',
收货地址: '陕西省延安市富县',
物流公司: '中通快递',
运单号: 'L209106',
运送方式: '公路运输',
支付时间: 43583,
预计到达时间: 43585,
实际到达时间: 43585,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '无评论',
出生日期: 36710,
品类: '连衣裙',
材质: '氨纶',
},
{
订单编号: 'A577484',
品牌: 'H&R',
店铺: 'COCO女装',
负责人: '刘佳',
商品: '秋冬款连衣裙',
颜色: '粉色',
客户购买类型: '批发',
销量: 12,
单价: 173.7,
销售额: 2084.39999999999,
是否优惠: '店铺活动优惠',
优惠金额: 100,
实际单价: 165.37,
实际付款: 1984.39999999999,
成本: 1170.8,
利润: 813.59999999999,
客户性别: 0,
客户年龄: '61岁',
会员情况: '钻石会员',
是否访问页面: '是',
访问页面时长: 7,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '谢博',
收货人电话: '147****5024',
发货地址: '广东省',
收货地址省份: '⽢肃省',
收货地址: '甘肃省甘南藏族自治州卓尼县',
物流公司: '申通快递',
运单号: 'L913348',
运送方式: '航空运输',
支付时间: 43562,
预计到达时间: 43566,
实际到达时间: 43566,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '中评',
出生日期: 22505,
品类: '连衣裙',
材质: '麻质',
},
{
订单编号: 'A293474',
品牌: '拉夏贝尔',
店铺: '拉夏贝尔旗舰店',
负责人: '刘佳',
商品: '泫雅风T恤',
颜色: '粉色',
客户购买类型: '批发',
销量: 12,
单价: 162.02,
销售额: 1944.24,
是否优惠: '双11优惠',
优惠金额: 200,
实际单价: 145.35,
实际付款: 1744.24,
成本: 1011.66,
利润: 732.58,
客户性别: 0,
客户年龄: '59岁',
会员情况: '普通会员',
是否访问页面: '是',
访问页面时长: 2,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '赵丽丽',
收货人电话: '186****8566',
发货地址: '浙江省',
收货地址省份: '⼴东省',
收货地址: '广东省梅州市',
物流公司: '圆通快递',
运单号: 'L841704',
运送方式: '铁路运输',
支付时间: 43779,
预计到达时间: 43784,
实际到达时间: 43784,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '中评',
出生日期: 23158,
品类: '上衣',
材质: '氨纶',
},
{
订单编号: 'A424004',
品牌: '艾米丽',
店铺: '卡卡家女装',
负责人: '宋建华',
商品: '大码牛仔裤',
颜色: '红色',
客户购买类型: '批发',
销量: 11,
单价: 73.54,
销售额: 808.94,
是否优惠: '双11优惠',
优惠金额: 100,
实际单价: 64.45,
实际付款: 708.94,
成本: 361.56,
利润: 347.38,
客户性别: 0,
客户年龄: '23岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 8,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '谢雷',
收货人电话: '150****7487',
发货地址: '浙江省',
收货地址省份: '宁夏回族自治区',
收货地址: '宁夏回族自治区银川市贺兰县',
物流公司: ' 百世快递',
运单号: 'L451724',
运送方式: '公路运输',
支付时间: 45257,
预计到达时间: 45261,
实际到达时间: 45261,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 36512,
品类: '女裤',
材质: '锦纶',
},
{
订单编号: 'A561021',
品牌: 'TARA',
店铺: 'TARA旗舰店',
负责人: '邹勇',
商品: '春夏季新款裤子',
颜色: '橙色',
客户购买类型: '批发',
销量: 11,
单价: 57.25,
销售额: 629.75,
是否优惠: '双12优惠',
优惠金额: 150,
实际单价: 43.61,
实际付款: 479.75,
成本: 283.05,
利润: 196.7,
客户性别: 0,
客户年龄: '36岁',
会员情况: '普通会员',
是否访问页面: '是',
访问页面时长: 7,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '王桂珍',
收货人电话: '137****8424',
发货地址: '福建省',
收货地址省份: '湖南省',
收货地址: '湖南省永州市市辖区',
物流公司: '申通快递',
运单号: 'L948843',
运送方式: '公路运输',
支付时间: 43816,
预计到达时间: 43818,
实际到达时间: 43818,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 31564,
品类: '女裤',
材质: '锦纶',
},
{
订单编号: 'A191677',
品牌: '富贵人',
店铺: '富贵人旗舰店',
负责人: '刘佳',
商品: '蕾丝花边T恤',
颜色: '粉色',
客户购买类型: '批发',
销量: 11,
单价: 117.92,
销售额: 1297.12,
是否优惠: '无',
优惠金额: 0,
实际单价: 117.92,
实际付款: 1297.12,
成本: 648.56,
利润: 648.56,
客户性别: 0,
客户年龄: '38岁',
会员情况: '无会员',
是否访问页面: '否',
访问页面时长: 0,
交易状态: '交易取消',
商品状态: '已取消',
收货人姓名: '梁秀华',
收货人电话: '136****1451',
发货地址: '广东省',
收货地址省份: '⼭东省',
收货地址: '山东省聊城市冠县',
物流公司: '申通快递',
运单号: 'L385723',
运送方式: '航空运输',
支付时间: 43802,
预计到达时间: 43807,
实际到达时间: 43807,
快递反馈: '准时',
是否退货: '是',
退款原因: '不喜欢',
客户满意度: '无评论',
出生日期: 30739,
品类: '上衣',
材质: '棉质',
},
]
return <DataRender dataSource={data} columns={columns}></DataRender>
}
import { useEffect, useState } from 'react'
import { Button, Flex, Modal } from 'antd'
import axios from 'axios'
import DataRender from './DataRender'
import { read, utils } from 'xlsx'
import { uniqueId } from 'lodash-es'
export default function ViewDataButtonModal({ data }: { data: any }) {
const [open, setOpen] = useState(false)
const [dataset, setDataset] = useState<any[]>([])
const [isLoading, setIsLoading] = useState(false)
useEffect(() => {
const workbook = async () => {
setIsLoading(true)
try {
const file = JSON.parse(data.file)
const res = await axios(file.url, { responseType: 'arraybuffer' })
const workbook = read(res.data)
const sheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[sheetName]
const jsonData = utils.sheet_to_json(worksheet)
setDataset(jsonData)
} catch (error) {
console.error(error)
}
setIsLoading(false)
}
if (open) workbook()
}, [open, data])
const columns: any =
dataset.length > 0
? Object.keys(dataset[0]).map((key) => ({
title: key,
dataIndex: key,
align: 'center',
}))
: []
const dataSource = dataset.map((item) => ({ ...item, pk_id: uniqueId() }))
return (
<>
<Button color="primary" variant="text" onClick={() => setOpen(true)}>
查阅
</Button>
<Modal title="查阅数据集" width={'80%'} open={open} footer={null} onCancel={() => setOpen(false)}>
<Flex justify="space-between" style={{ marginBottom: 20 }}>
<div>数据集名称:{data.name}</div>
<div>共计:{data.number}条数据</div>
</Flex>
<DataRender rowKey={'pk_id'} dataSource={dataSource} columns={columns} loading={isLoading}></DataRender>
</Modal>
</>
)
}
import { useState } from 'react'
import { Button, Modal } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppList, { AppListProps } from '@/components/AppList'
export default function ViewDataFiledButtonModal({ children }: { children?: string }) {
const [open, setOpen] = useState(false)
const { data } = useDataFieldQuery()
const listOptions: AppListProps = {
columns: [
{
title: '序号',
key: 'index',
render(_value, _record, index) {
return index + 1
},
width: 62,
align: 'center',
},
{ title: '字段名称', dataIndex: 'english_name', align: 'center' },
{ title: '字段类型', dataIndex: 'type_name', align: 'center' },
{ title: '长度', dataIndex: 'length', align: 'center' },
{ title: '小数点', dataIndex: 'point', align: 'center' },
{ title: '是否允许为空', dataIndex: 'null', align: 'center' },
{ title: '默认值', dataIndex: 'default', align: 'center' },
{ title: '备注', dataIndex: 'name', align: 'center' },
],
dataSource: data || [],
}
return (
<>
<Button onClick={() => setOpen(true)}>{children ? children : '查看字段详细信息'}</Button>
<Modal title="查看字段详细信息" width={1000} open={open} footer={null} onCancel={() => setOpen(false)}>
<AppList rowKey="english_name" pagination={false} {...listOptions}></AppList>
</Modal>
</>
)
}
import { Flex, Modal } from 'antd'
import DataRender from './DataRender'
export default function FormModal(props) {
const columns = [
{
title: '订单编号',
dataIndex: '订单编号',
align: 'center',
minWidth: 120,
},
{
title: '品牌',
dataIndex: '品牌',
align: 'center',
minWidth: 120,
},
{
title: '店铺',
dataIndex: '店铺',
align: 'center',
minWidth: 120,
},
{
title: '负责人',
dataIndex: '负责人',
align: 'center',
minWidth: 120,
},
{
title: '商品',
dataIndex: '商品',
align: 'center',
minWidth: 120,
},
{
title: '颜色',
dataIndex: '颜色',
align: 'center',
minWidth: 120,
},
{
title: '客户购买类型',
dataIndex: '客户购买类型',
align: 'center',
minWidth: 120,
},
{
title: '销量',
dataIndex: '销量',
align: 'center',
minWidth: 120,
},
{
title: '单价',
dataIndex: '单价',
align: 'center',
minWidth: 120,
},
{
title: '销售额',
dataIndex: '销售额',
align: 'center',
minWidth: 120,
},
{
title: '是否优惠',
dataIndex: '是否优惠',
align: 'center',
minWidth: 120,
},
{
title: '优惠金额',
dataIndex: '优惠金额',
align: 'center',
minWidth: 120,
},
{
title: '实际单价',
dataIndex: '实际单价',
align: 'center',
minWidth: 120,
},
{
title: '实际付款',
dataIndex: '实际付款',
align: 'center',
minWidth: 120,
},
{
title: '成本',
dataIndex: '成本',
align: 'center',
minWidth: 120,
},
{
title: '利润',
dataIndex: '利润',
align: 'center',
minWidth: 120,
},
{
title: '客户性别',
dataIndex: '客户性别',
align: 'center',
minWidth: 120,
},
{
title: '客户年龄',
dataIndex: '客户年龄',
align: 'center',
minWidth: 120,
},
{
title: '会员情况',
dataIndex: '会员情况',
align: 'center',
minWidth: 120,
},
{
title: '是否访问页面',
dataIndex: '是否访问页面',
align: 'center',
minWidth: 120,
},
{
title: '访问页面时长',
dataIndex: '访问页面时长',
align: 'center',
minWidth: 120,
},
{
title: '交易状态',
dataIndex: '交易状态',
align: 'center',
minWidth: 120,
},
{
title: '商品状态',
dataIndex: '商品状态',
align: 'center',
minWidth: 120,
},
{
title: '收货人姓名',
dataIndex: '收货人姓名',
align: 'center',
minWidth: 120,
},
{
title: '收货人电话',
dataIndex: '收货人电话',
align: 'center',
minWidth: 120,
},
{
title: '发货地址',
dataIndex: '发货地址',
align: 'center',
minWidth: 120,
},
{
title: '收货地址省份',
dataIndex: '收货地址省份',
align: 'center',
minWidth: 120,
},
{
title: '收货地址',
dataIndex: '收货地址',
align: 'center',
minWidth: 120,
},
{
title: '物流公司',
dataIndex: '物流公司',
align: 'center',
minWidth: 120,
},
{
title: '运单号',
dataIndex: '运单号',
align: 'center',
minWidth: 120,
},
{
title: '运送方式',
dataIndex: '运送方式',
align: 'center',
minWidth: 120,
},
{
title: '支付时间',
dataIndex: '支付时间',
align: 'center',
minWidth: 120,
},
{
title: '预计到达时间',
dataIndex: '预计到达时间',
align: 'center',
minWidth: 120,
},
{
title: '实际到达时间',
dataIndex: '实际到达时间',
align: 'center',
minWidth: 120,
},
{
title: '快递反馈',
dataIndex: '快递反馈',
align: 'center',
minWidth: 120,
},
{
title: '是否退货',
dataIndex: '是否退货',
align: 'center',
minWidth: 120,
},
{
title: '退款原因',
dataIndex: '退款原因',
align: 'center',
minWidth: 120,
},
{
title: '客户满意度',
dataIndex: '客户满意度',
align: 'center',
minWidth: 120,
},
{
title: '出生日期',
dataIndex: '出生日期',
align: 'center',
minWidth: 120,
},
{
title: '品类',
dataIndex: '品类',
align: 'center',
minWidth: 120,
},
{
title: '材质',
dataIndex: '材质',
align: 'center',
minWidth: 120,
},
]
const data = [
{
订单编号: 'A929818',
品牌: '丽丽',
店铺: '卡卡家女装',
负责人: '袁英',
商品: '安全裤',
颜色: '红色',
客户购买类型: '零售',
销量: 256,
单价: 156.14,
销售额: 156.14,
是否优惠: '店铺活动优惠',
优惠金额: 12,
实际单价: 144.14,
实际付款: 144.14,
成本: 92.25,
利润: 51.89,
客户性别: 0,
客户年龄: '33岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 2,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '孙倩',
收货人电话: '181****4056',
发货地址: '福建省',
收货地址省份: '陕西省',
收货地址: '陕西省延安市子长县',
物流公司: ' 百世快递',
运单号: 'L810590',
运送方式: '公路运输',
支付时间: 44003,
预计到达时间: 44008,
实际到达时间: 44008,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '中评',
出生日期: 32807,
品类: '女裤',
材质: '麻质',
},
{
订单编号: 'A451538',
品牌: '雅羊人',
店铺: '秋兰女装专卖店',
负责人: '刘佳',
商品: '不规则连衣裙',
颜色: '粉色',
客户购买类型: '零售',
销量: 198,
单价: 247.44,
销售额: 247.44,
是否优惠: '无',
优惠金额: 0,
实际单价: 247.44,
实际付款: 247.44,
成本: 133.62,
利润: 113.82,
客户性别: 0,
客户年龄: '36岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 8,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '余玉英',
收货人电话: '181****8027',
发货地址: '广东省',
收货地址省份: '⼴西壮族⾃治区',
收货地址: '广西壮族自治区贵港市',
物流公司: '极兔快 递',
运单号: 'L806051',
运送方式: '公路运输',
支付时间: 45029,
预计到达时间: 45031,
实际到达时间: 45031,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 31610,
品类: '连衣裙',
材质: '氨纶',
},
{
订单编号: 'A479212',
品牌: '威兰西',
店铺: '威兰西旗舰店',
负责人: '陈建平',
商品: '网红同款连衣裙',
颜色: '白色',
客户购买类型: '零售',
销量: 128,
单价: 245.49,
销售额: 245.49,
是否优惠: '双12优惠',
优惠金额: 15,
实际单价: 230.49,
实际付款: 230.49,
成本: 147.51,
利润: 82.98,
客户性别: 0,
客户年龄: '22岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 4,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '杨军',
收货人电话: '139****7024',
发货地址: '浙江省',
收货地址省份: '河北省',
收货地址: '河北省衡水市武强县',
物流公司: '顺丰快递',
运单号: 'L356804',
运送方式: '公路运输',
支付时间: 43800,
预计到达时间: 43805,
实际到达时间: 43806,
快递反馈: '延后',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 36649,
品类: '连衣裙',
材质: '棉质',
},
{
订单编号: 'A389270',
品牌: 'H&R',
店铺: '壹佰女装',
负责人: '杨兰英',
商品: '蕾丝花边T恤',
颜色: '紫色',
客户购买类型: '批发',
销量: 13,
单价: 168.3,
销售额: 2187.9,
是否优惠: '双11优惠',
优惠金额: 200,
实际单价: 152.92,
实际付款: 1987.9,
成本: 1212.62,
利润: 775.28,
客户性别: 0,
客户年龄: '26岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 4,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '郑强',
收货人电话: '159****6299',
发货地址: '四川省',
收货地址省份: '河南省',
收货地址: '河南省郑州市新密市',
物流公司: '顺丰快递',
运单号: 'L335437',
运送方式: '公路运输',
支付时间: 43779,
预计到达时间: 43783,
实际到达时间: 43784,
快递反馈: '延后',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 35189,
品类: '上衣',
材质: '棉质',
},
{
订单编号: 'A327122',
品牌: 'H&R',
店铺: 'H&R旗舰店',
负责人: '袁英',
商品: '春夏新款连衣裙',
颜色: '红色',
客户购买类型: '批发',
销量: 13,
单价: 119.64,
销售额: 1555.32,
是否优惠: '无',
优惠金额: 0,
实际单价: 119.64,
实际付款: 1555.32,
成本: 855.43,
利润: 699.89,
客户性别: 0,
客户年龄: '22岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 8,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '刘冬梅',
收货人电话: '185****4586',
发货地址: '广东省',
收货地址省份: '陕西省',
收货地址: '陕西省延安市富县',
物流公司: '中通快递',
运单号: 'L209106',
运送方式: '公路运输',
支付时间: 43583,
预计到达时间: 43585,
实际到达时间: 43585,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '无评论',
出生日期: 36710,
品类: '连衣裙',
材质: '氨纶',
},
{
订单编号: 'A577484',
品牌: 'H&R',
店铺: 'COCO女装',
负责人: '刘佳',
商品: '秋冬款连衣裙',
颜色: '粉色',
客户购买类型: '批发',
销量: 12,
单价: 173.7,
销售额: 2084.39999999999,
是否优惠: '店铺活动优惠',
优惠金额: 100,
实际单价: 165.37,
实际付款: 1984.39999999999,
成本: 1170.8,
利润: 813.59999999999,
客户性别: 0,
客户年龄: '61岁',
会员情况: '钻石会员',
是否访问页面: '是',
访问页面时长: 7,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '谢博',
收货人电话: '147****5024',
发货地址: '广东省',
收货地址省份: '⽢肃省',
收货地址: '甘肃省甘南藏族自治州卓尼县',
物流公司: '申通快递',
运单号: 'L913348',
运送方式: '航空运输',
支付时间: 43562,
预计到达时间: 43566,
实际到达时间: 43566,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '中评',
出生日期: 22505,
品类: '连衣裙',
材质: '麻质',
},
{
订单编号: 'A293474',
品牌: '拉夏贝尔',
店铺: '拉夏贝尔旗舰店',
负责人: '刘佳',
商品: '泫雅风T恤',
颜色: '粉色',
客户购买类型: '批发',
销量: 12,
单价: 162.02,
销售额: 1944.24,
是否优惠: '双11优惠',
优惠金额: 200,
实际单价: 145.35,
实际付款: 1744.24,
成本: 1011.66,
利润: 732.58,
客户性别: 0,
客户年龄: '59岁',
会员情况: '普通会员',
是否访问页面: '是',
访问页面时长: 2,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '赵丽丽',
收货人电话: '186****8566',
发货地址: '浙江省',
收货地址省份: '⼴东省',
收货地址: '广东省梅州市',
物流公司: '圆通快递',
运单号: 'L841704',
运送方式: '铁路运输',
支付时间: 43779,
预计到达时间: 43784,
实际到达时间: 43784,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '中评',
出生日期: 23158,
品类: '上衣',
材质: '氨纶',
},
{
订单编号: 'A424004',
品牌: '艾米丽',
店铺: '卡卡家女装',
负责人: '宋建华',
商品: '大码牛仔裤',
颜色: '红色',
客户购买类型: '批发',
销量: 11,
单价: 73.54,
销售额: 808.94,
是否优惠: '双11优惠',
优惠金额: 100,
实际单价: 64.45,
实际付款: 708.94,
成本: 361.56,
利润: 347.38,
客户性别: 0,
客户年龄: '23岁',
会员情况: '无会员',
是否访问页面: '是',
访问页面时长: 8,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '谢雷',
收货人电话: '150****7487',
发货地址: '浙江省',
收货地址省份: '宁夏回族自治区',
收货地址: '宁夏回族自治区银川市贺兰县',
物流公司: ' 百世快递',
运单号: 'L451724',
运送方式: '公路运输',
支付时间: 45257,
预计到达时间: 45261,
实际到达时间: 45261,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 36512,
品类: '女裤',
材质: '锦纶',
},
{
订单编号: 'A561021',
品牌: 'TARA',
店铺: 'TARA旗舰店',
负责人: '邹勇',
商品: '春夏季新款裤子',
颜色: '橙色',
客户购买类型: '批发',
销量: 11,
单价: 57.25,
销售额: 629.75,
是否优惠: '双12优惠',
优惠金额: 150,
实际单价: 43.61,
实际付款: 479.75,
成本: 283.05,
利润: 196.7,
客户性别: 0,
客户年龄: '36岁',
会员情况: '普通会员',
是否访问页面: '是',
访问页面时长: 7,
交易状态: '交易成功',
商品状态: '已收货',
收货人姓名: '王桂珍',
收货人电话: '137****8424',
发货地址: '福建省',
收货地址省份: '湖南省',
收货地址: '湖南省永州市市辖区',
物流公司: '申通快递',
运单号: 'L948843',
运送方式: '公路运输',
支付时间: 43816,
预计到达时间: 43818,
实际到达时间: 43818,
快递反馈: '准时',
是否退货: '否',
退款原因: '无',
客户满意度: '好评',
出生日期: 31564,
品类: '女裤',
材质: '锦纶',
},
{
订单编号: 'A191677',
品牌: '富贵人',
店铺: '富贵人旗舰店',
负责人: '刘佳',
商品: '蕾丝花边T恤',
颜色: '粉色',
客户购买类型: '批发',
销量: 11,
单价: 117.92,
销售额: 1297.12,
是否优惠: '无',
优惠金额: 0,
实际单价: 117.92,
实际付款: 1297.12,
成本: 648.56,
利润: 648.56,
客户性别: 0,
客户年龄: '38岁',
会员情况: '无会员',
是否访问页面: '否',
访问页面时长: 0,
交易状态: '交易取消',
商品状态: '已取消',
收货人姓名: '梁秀华',
收货人电话: '136****1451',
发货地址: '广东省',
收货地址省份: '⼭东省',
收货地址: '山东省聊城市冠县',
物流公司: '申通快递',
运单号: 'L385723',
运送方式: '航空运输',
支付时间: 43802,
预计到达时间: 43807,
实际到达时间: 43807,
快递反馈: '准时',
是否退货: '是',
退款原因: '不喜欢',
客户满意度: '无评论',
出生日期: 30739,
品类: '上衣',
材质: '棉质',
},
]
return (
<Modal title="查阅数据集" destroyOnClose width={1000} {...props}>
<Flex justify="space-between">
<div>数据集名称:数据集名称</div>
<div>共计:1000条数据</div>
</Flex>
<DataRender dataSource={data} columns={columns}></DataRender>
</Modal>
)
}
.app-header {
position: sticky;
top: 0;
z-index: 2001;
z-index: 100;
padding: 0 20px;
display: flex;
align-items: center;
......
import { useEffect } from 'react'
import { useQuery } from '@tanstack/react-query'
import { getUser, getMapList } from '@/api/base'
import { useQuery, keepPreviousData } from '@tanstack/react-query'
import { getUser, getMapList, getMyList, getMyField } from '@/api/base'
import { useUserStore } from '@/stores/user'
import { useMapStore } from '@/stores/map'
......@@ -31,3 +31,27 @@ export function useMapQuery() {
return query
}
// 我的数据集
export function useDataQuery(params?: Partial<{ page: number; 'per-page': number }>) {
const query = useQuery({
queryKey: ['data', params],
queryFn: () => {
return getMyList(params)
},
select: (res) => res.data,
initialData: (): any => {
return { data: { total: 0, list: [], title: [] } }
},
placeholderData: keepPreviousData,
})
return query
}
// 查看字段详情
export function useDataFieldQuery() {
const query = useQuery({ queryKey: ['data-filed'], queryFn: getMyField, select: (res) => res.data })
return query
}
......@@ -4,7 +4,7 @@ import AppUpload from '@/components/AppUpload'
import { useCreateDataset } from '../query'
import { useState } from 'react'
export default function FormButtonModal({ title, children }: { title: string; children?: React.ReactNode }) {
export default function FormButtonModal({ title = '添加数据集' }: { title?: string }) {
const [open, setOpen] = useState(false)
const [form] = Form.useForm()
......@@ -27,13 +27,9 @@ export default function FormButtonModal({ title, children }: { title: string; ch
return (
<>
{children ? (
children
) : (
<Button type="primary" onClick={() => setOpen(true)}>
{title}
</Button>
)}
<Button type="primary" onClick={() => setOpen(true)}>
{title}
</Button>
<Modal
title={title}
open={open}
......
import { lazy, useState } from 'react'
import { lazy } from 'react'
import { Button, Card, Input, Select } from 'antd'
import AppList, { AppListProps } from '@/components/AppList'
import { useMapStore } from '@/stores/map'
......@@ -6,19 +6,12 @@ import { getDatasetList } from '../api'
import { useDeleteDataset } from '../query'
const FormButtonModal = lazy(() => import('../components/FormButtonModal'))
const ViewDataModal = lazy(() => import('@/components/data/ViewDataModal'))
const ViewDataButtonModal = lazy(() => import('@/components/data/ViewDataButtonModal'))
export default function DataWriteBuilt() {
const getMapValuesByKey = useMapStore((state) => state.getMapValuesByKey)
const industryList = getMapValuesByKey('bi_data_industry')
const [viewModalIsOpen, setViewModalIsOpen] = useState(false)
const handleView = (record: any) => {
console.log(record)
setViewModalIsOpen(true)
}
const { mutate } = useDeleteDataset()
const handleRemove = (record: any) => {
mutate({ id: record.id })
......@@ -67,9 +60,7 @@ export default function DataWriteBuilt() {
render(_value, record) {
return (
<>
<Button color="primary" variant="text" onClick={() => handleView(record)}>
查阅
</Button>
<ViewDataButtonModal data={record}></ViewDataButtonModal>
<Button color="danger" variant="text" onClick={() => handleRemove(record)}>
删除
</Button>
......@@ -82,8 +73,6 @@ export default function DataWriteBuilt() {
return (
<Card className="app-card" title="内置数据集管理">
<AppList bordered {...listOptions} filterAside={<FormButtonModal title="添加数据集"></FormButtonModal>}></AppList>
<ViewDataModal open={viewModalIsOpen} onCancel={() => setViewModalIsOpen(false)}></ViewDataModal>
</Card>
)
}
......@@ -14,3 +14,8 @@ export function getDatasetList(
) {
return httpRequest.get('/api/bi/v1/data/built-in/list', { params })
}
// 复制数据集
export function copyDataset(data: { id: string; name: string; force: string }) {
return httpRequest.post('/api/bi/v1/data/my/copy-built-in', data)
}
import { Button, Form, Input, Modal } from 'antd'
import { useState } from 'react'
import { useCopyDataset } from '../query'
export default function CopyButtonModal({ children, data }: { children?: string; data: any }) {
const [open, setOpen] = useState(false)
const [form] = Form.useForm()
const { mutate, isPending } = useCopyDataset()
const handleOk = () => {
form.validateFields().then((values) => {
const params = { id: data.id, force: '1', ...values }
mutate(params, {
onSuccess: () => setOpen(false),
})
})
}
return (
<>
<Button color="primary" variant="text" onClick={() => setOpen(true)}>
{children ? children : '复制'}
</Button>
<Modal
title="复制数据集"
open={open}
onOk={handleOk}
onCancel={() => setOpen(false)}
confirmLoading={isPending}
okText="复制"
destroyOnClose>
<Form form={form} labelCol={{ span: 5 }} preserve={false}>
<Form.Item label="数据集名称" name="name">
<Input placeholder="请输入" />
</Form.Item>
<Form.Item label="原始数据集">{data.name}</Form.Item>
<Form.Item label="数据量">{data.number}</Form.Item>
<Form.Item label="所属行业">{data.industry_name}</Form.Item>
<Form.Item label="数据来源">{data.source_name}</Form.Item>
<Form.Item label="敏感等级">{data.sensitivity_level_name}</Form.Item>
<Form.Item label="访问权限">{data.access_permissions_name}</Form.Item>
<Form.Item label="创建人">{data.created_operator_name}</Form.Item>
<Form.Item label="创建时间">{data.created_time}</Form.Item>
<Form.Item label="更新时间">{data.updated_time}</Form.Item>
</Form>
</Modal>
</>
)
}
import { Form, Input, Modal } from 'antd'
export default function FormModal(props) {
return (
<Modal title="复制数据集" destroyOnClose {...props}>
<Form labelCol={{ span: 4 }} preserve={false}>
<Form.Item label="数据集名称" name="name">
<Input placeholder="请输入" />
</Form.Item>
<Form.Item label="原始数据集">电子商务案例数据集</Form.Item>
<Form.Item label="数据量">2000</Form.Item>
<Form.Item label="所属行业">电子商务</Form.Item>
<Form.Item label="数据来源">案例数据</Form.Item>
<Form.Item label="敏感等级">L1一般敏感</Form.Item>
<Form.Item label="访问权限">完全开放</Form.Item>
<Form.Item label="创建人">张三疯</Form.Item>
<Form.Item label="创建时间">2024-12-12 13:13:13</Form.Item>
<Form.Item label="更新时间">2024-12-12 13:13:13</Form.Item>
</Form>
</Modal>
)
}
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { copyDataset } from './api'
import { message } from 'antd'
// 复制
export function useCopyDataset() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: { id: string; name: string; force: string }) => copyDataset(data),
onSuccess: () => {
message.success('复制成功')
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
}
import { Button, Card, Input, Select } from 'antd'
import { lazy } from 'react'
import { Card, Input, Select } from 'antd'
import AppList, { AppListProps } from '@/components/AppList'
import { useMapStore } from '@/stores/map'
import { lazy, useState } from 'react'
import { getDatasetList } from '../api'
const CopyModal = lazy(() => import('../components/CopyModal'))
const ViewDataModal = lazy(() => import('@/components/data/ViewDataModal'))
const CopyButtonModal = lazy(() => import('../components/CopyButtonModal'))
const ViewDataButtonModal = lazy(() => import('@/components/data/ViewDataButtonModal'))
export default function DataWriteCopy() {
const getMapValuesByKey = useMapStore((state) => state.getMapValuesByKey)
const industryList = getMapValuesByKey('bi_data_industry')
const [viewModalIsOpen, setViewModalIsOpen] = useState(false)
const handleView = (record: any) => {
console.log(record)
setViewModalIsOpen(true)
}
const [copyModalIsOpen, setCopyModalIsOpen] = useState(false)
const handleCopy = (record: any) => {
console.log(record)
setCopyModalIsOpen(true)
}
const listOptions: AppListProps = {
fetchApi: async (params) => {
const { data } = await getDatasetList({ ...params, access_permissions: '1' })
......@@ -67,12 +54,8 @@ export default function DataWriteCopy() {
render(_value, record) {
return (
<>
<Button color="primary" variant="text" onClick={() => handleView(record)}>
查阅
</Button>
<Button color="primary" variant="text" onClick={() => handleCopy(record)}>
复制
</Button>
<ViewDataButtonModal data={record}></ViewDataButtonModal>
<CopyButtonModal data={record}></CopyButtonModal>
</>
)
},
......@@ -82,8 +65,6 @@ export default function DataWriteCopy() {
return (
<Card className="app-card" title="数据复制">
<AppList bordered {...listOptions}></AppList>
<CopyModal open={copyModalIsOpen} onCancel={() => setCopyModalIsOpen(false)}></CopyModal>
<ViewDataModal open={viewModalIsOpen} onCancel={() => setViewModalIsOpen(false)}></ViewDataModal>
</Card>
)
}
import { Button, Card, Empty, Flex, Space } from 'antd'
import { Link } from 'react-router'
import { Button, Empty, Flex, Space } from 'antd'
import DataWrap from '@/components/data/DataWrap'
export default function DataWriteMy() {
const isEmpty = true
// 无数据渲染
const emptyRender = () => {
return (
<>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="无数据"></Empty>
<Flex justify="center" align="middle">
<Space>
<Link to="/data/write/copy">
<Button type="primary">复制数据</Button>
</Link>
<Link to="/data/write/upload">
<Button type="primary">导入数据</Button>
</Link>
<Button type="primary" disabled>
爬取数据
</Button>
<Button type="primary" disabled>
本地数据库连接
</Button>
<Button type="primary" disabled>
API数据获取
</Button>
</Space>
</Flex>
</>
)
}
// 无数据渲染
const EmptyRender = () => {
return (
<Card className="app-card" title="我的数据集">
<Flex justify="space-between" align="middle">
<h4>数据集名称:电子商务案例分析数据集</h4>
<Button type="primary" disabled={isEmpty}>
数据质量分析报告
</Button>
<>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="无数据"></Empty>
<Flex justify="center" align="middle">
<Space>
<Link to="/data/write/copy">
<Button type="primary">复制数据</Button>
</Link>
<Link to="/data/write/upload">
<Button type="primary">导入数据</Button>
</Link>
<Button type="primary" disabled>
爬取数据
</Button>
<Button type="primary" disabled>
本地数据库连接
</Button>
<Button type="primary" disabled>
API数据获取
</Button>
</Space>
</Flex>
{!isEmpty && (
<Flex justify="space-between" align="middle">
<p>《商务数据分析基础》数据集-电子商务2025.xlsx</p>
<p>共计:1000条数据</p>
</>
)
}
export default function DataWriteMy() {
return (
<DataWrap
title="我的数据集"
hasAI={false}
headerRender={(data) => (
<Flex justify="space-between" align="middle" style={{ marginBottom: '20px' }}>
<h4>数据集名称:{data.info.name}</h4>
<Button type="primary">数据质量分析报告</Button>
</Flex>
)}
{isEmpty && emptyRender()}
</Card>
empty={<EmptyRender />}></DataWrap>
)
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论