Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-bi
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-bi
Commits
b5a25e0b
提交
b5a25e0b
authored
3月 24, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
28abbff8
隐藏空白字符变更
内嵌
并排
正在显示
44 个修改的文件
包含
1466 行增加
和
1352 行删除
+1466
-1352
base.ts
src/api/base.ts
+5
-1092
data.ts
src/api/data.ts
+36
-0
ChartWrap.tsx
src/components/chart/ChartWrap.tsx
+4
-3
ViewDataButtonModal.tsx
src/components/data/ViewDataButtonModal.tsx
+2
-2
ViewMyDataButtonModal.tsx
src/components/data/ViewMyDataButtonModal.tsx
+32
-0
useQuery.ts
src/hooks/useQuery.ts
+52
-3
Index.tsx
src/modules/data/chart/bar/views/Index.tsx
+1
-1
Index.tsx
src/modules/data/chart/line/views/Index.tsx
+1
-1
Index.tsx
src/modules/data/chart/pie/views/Index.tsx
+1
-1
Index.tsx
src/modules/data/chart/radar/views/Index.tsx
+1
-1
ButtonModal.tsx
src/modules/data/preprocess/error/components/ButtonModal.tsx
+4
-4
ButtonModal.tsx
src/modules/data/preprocess/max/components/ButtonModal.tsx
+4
-4
ButtonModal.tsx
src/modules/data/preprocess/min/components/ButtonModal.tsx
+4
-4
api.ts
src/modules/data/preprocess/null/api.ts
+7
-0
ButtonModal.tsx
src/modules/data/preprocess/null/components/ButtonModal.tsx
+63
-52
query.ts
src/modules/data/preprocess/null/query.ts
+24
-0
types.ts
src/modules/data/preprocess/null/types.ts
+7
-0
ButtonModal.tsx
src/modules/data/preprocess/space/components/ButtonModal.tsx
+4
-4
ButtonModal.tsx
src/modules/data/preprocess/split/components/ButtonModal.tsx
+4
-4
ButtonModal.tsx
...modules/data/preprocess/symbol/components/ButtonModal.tsx
+4
-4
api.ts
src/modules/data/process/binning/api.ts
+7
-0
ButtonModal.tsx
src/modules/data/process/binning/components/ButtonModal.tsx
+131
-98
query.ts
src/modules/data/process/binning/query.ts
+24
-0
types.ts
src/modules/data/process/binning/types.ts
+7
-0
api.ts
src/modules/data/process/date/api.ts
+7
-0
ButtonModal.tsx
src/modules/data/process/date/components/ButtonModal.tsx
+281
-0
query.ts
src/modules/data/process/date/query.ts
+24
-0
types.ts
src/modules/data/process/date/types.ts
+11
-0
Index.tsx
src/modules/data/process/date/views/Index.tsx
+3
-2
api.ts
src/modules/data/process/desensitization/api.ts
+7
-0
ButtonModal.tsx
...s/data/process/desensitization/components/ButtonModal.tsx
+288
-0
query.ts
src/modules/data/process/desensitization/query.ts
+24
-0
types.ts
src/modules/data/process/desensitization/types.ts
+11
-0
Index.tsx
src/modules/data/process/desensitization/views/Index.tsx
+3
-2
api.ts
src/modules/data/process/group/api.ts
+7
-0
ButtonModal.tsx
src/modules/data/process/group/components/ButtonModal.tsx
+247
-0
query.ts
src/modules/data/process/group/query.ts
+24
-0
types.ts
src/modules/data/process/group/types.ts
+6
-0
Index.tsx
src/modules/data/process/group/views/Index.tsx
+3
-2
api.ts
src/modules/data/process/mapping/api.ts
+7
-0
ButtonModal.tsx
src/modules/data/process/mapping/components/ButtonModal.tsx
+51
-65
query.ts
src/modules/data/process/mapping/query.ts
+24
-0
types.ts
src/modules/data/process/mapping/types.ts
+6
-0
axios.ts
src/utils/axios.ts
+3
-3
没有找到文件。
src/api/base.ts
浏览文件 @
b5a25e0b
...
@@ -36,1106 +36,19 @@ export function getMapList() {
...
@@ -36,1106 +36,19 @@ export function getMapList() {
// 我的数据集列表
// 我的数据集列表
export
function
getMyList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
}
>
)
{
export
function
getMyList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
}
>
)
{
// return Promise.resolve({
// code: 0,
// message: 'OK',
// data: {
// total: 10,
// title: [
// {
// name: '序号',
// english_name: 'pk_id',
// type: 'INT',
// },
// {
// name: '订单编号',
// english_name: 'order_number',
// type: 'VARCHAR(7)',
// },
// {
// name: '品牌',
// english_name: 'brand',
// type: 'VARCHAR(12)',
// },
// {
// name: '店铺',
// english_name: 'store',
// type: 'VARCHAR(21)',
// },
// {
// name: '负责人',
// english_name: 'person_in_charge',
// type: 'VARCHAR(9)',
// },
// {
// name: '商品',
// english_name: 'product',
// type: 'VARCHAR(21)',
// },
// {
// name: '颜色',
// english_name: 'color',
// type: 'VARCHAR(6)',
// },
// {
// name: '客户购买类型',
// english_name: 'customer_purchase_type',
// type: 'VARCHAR(6)',
// },
// {
// name: '销量',
// english_name: 'sales_volume',
// type: 'SMALLINT',
// },
// {
// name: '单价',
// english_name: 'unit_price',
// type: 'DECIMAL(5, 2)',
// },
// {
// name: '销售额',
// english_name: 'sales_amount',
// type: 'DECIMAL(6, 2)',
// },
// {
// name: '是否优惠',
// english_name: 'is_discounted',
// type: 'VARCHAR(18)',
// },
// {
// name: '优惠金额',
// english_name: 'discount_amount',
// type: 'SMALLINT',
// },
// {
// name: '实际单价',
// english_name: 'actual_unit_price',
// type: 'DECIMAL(5, 2)',
// },
// {
// name: '实际付款',
// english_name: 'actual_payment',
// type: 'DECIMAL(6, 2)',
// },
// {
// name: '成本',
// english_name: 'cost',
// type: 'DECIMAL(7, 3)',
// },
// {
// name: '利润',
// english_name: 'profit',
// type: 'DECIMAL(6, 3)',
// },
// {
// name: '客户性别',
// english_name: 'customer_gender',
// type: 'TINYINT',
// },
// {
// name: '客户年龄',
// english_name: 'customer_age',
// type: 'VARCHAR(5)',
// },
// {
// name: '会员情况',
// english_name: 'membership_status',
// type: 'VARCHAR(12)',
// },
// {
// name: '是否访问页面',
// english_name: 'has_visited_page',
// type: 'VARCHAR(3)',
// },
// {
// name: '访问页面时长',
// english_name: 'page_visit_duration',
// type: 'TINYINT',
// },
// {
// name: '交易状态',
// english_name: 'transaction_status',
// type: 'VARCHAR(12)',
// },
// {
// name: '商品状态',
// english_name: 'product_status',
// type: 'VARCHAR(9)',
// },
// {
// name: '收货人姓名',
// english_name: 'recipient_name',
// type: 'VARCHAR(9)',
// },
// {
// name: '收货人电话',
// english_name: 'recipient_phone',
// type: 'VARCHAR(11)',
// },
// {
// name: '发货地址',
// english_name: 'shipping_address',
// type: 'VARCHAR(9)',
// },
// {
// name: '收货地址省份',
// english_name: 'recipient_province',
// type: 'VARCHAR(21)',
// },
// {
// name: '收货地址',
// english_name: 'recipient_address',
// type: 'VARCHAR(39)',
// },
// {
// name: '物流公司',
// english_name: 'logistics_company',
// type: 'VARCHAR(15)',
// },
// {
// name: '运单号',
// english_name: 'waybill_number',
// type: 'VARCHAR(7)',
// },
// {
// name: '运送方式',
// english_name: 'shipping_method',
// type: 'VARCHAR(12)',
// },
// {
// name: '支付时间',
// english_name: 'payment_time',
// type: 'VARCHAR(10)',
// },
// {
// name: '预计到达时间',
// english_name: 'estimated_arrival_time',
// type: 'VARCHAR(10)',
// },
// {
// name: '实际到达时间',
// english_name: 'actual_arrival_time',
// type: 'VARCHAR(10)',
// },
// {
// name: '快递反馈',
// english_name: 'courier_feedback',
// type: 'VARCHAR(6)',
// },
// {
// name: '是否退货',
// english_name: 'is_returned',
// type: 'VARCHAR(3)',
// },
// {
// name: '退款原因',
// english_name: 'refund_reason',
// type: 'VARCHAR(9)',
// },
// {
// name: '客户满意度',
// english_name: 'customer_satisfaction',
// type: 'VARCHAR(9)',
// },
// {
// name: '出生日期',
// english_name: 'date_of_birth',
// type: 'VARCHAR(17)',
// },
// {
// name: '品类',
// english_name: 'category',
// type: 'VARCHAR(9)',
// },
// {
// name: '材质',
// english_name: 'material',
// type: 'VARCHAR(6)',
// },
// ],
// list: [
// {
// pk_id: '1',
// order_number: 'A929818',
// brand: '丽丽',
// store: '卡卡家女装',
// person_in_charge: '袁英',
// product: '安全裤',
// color: '红色',
// customer_purchase_type: '零售',
// sales_volume: '256',
// unit_price: '156.14',
// sales_amount: '156.14',
// is_discounted: '店铺活动优惠',
// discount_amount: '12',
// actual_unit_price: '144.14',
// actual_payment: '144.14',
// cost: '99.460',
// profit: '44.680',
// customer_gender: '0',
// customer_age: '33岁',
// membership_status: '无会员',
// has_visited_page: '是',
// page_visit_duration: '2',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '孙倩',
// recipient_phone: '181****4056',
// shipping_address: '福建省',
// recipient_province: '陕西省',
// recipient_address: '陕西省延安市子长县',
// logistics_company: ' 百世快递',
// waybill_number: 'L810590',
// shipping_method: '公路运输',
// payment_time: '6/21/2020',
// estimated_arrival_time: '6/26/2020',
// actual_arrival_time: '6/26/2020',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '中评',
// date_of_birth: '1989年10月26日',
// category: '女裤',
// material: '麻质',
// },
// {
// pk_id: '2',
// order_number: 'A451538',
// brand: '雅羊人',
// store: '秋兰女装专卖店',
// person_in_charge: '刘佳',
// product: '不规则连衣裙',
// color: '粉色',
// customer_purchase_type: '零售',
// sales_volume: '198',
// unit_price: '247.44',
// sales_amount: '247.44',
// is_discounted: '无',
// discount_amount: '0',
// actual_unit_price: '247.44',
// actual_payment: '247.44',
// cost: '158.360',
// profit: '89.080',
// customer_gender: '0',
// customer_age: '36岁',
// membership_status: '无会员',
// has_visited_page: '是',
// page_visit_duration: '8',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '余玉英',
// recipient_phone: '181****8027',
// shipping_address: '广东省',
// recipient_province: '⼴西壮族⾃治区',
// recipient_address: '广西壮族自治区贵港市',
// logistics_company: '极兔快 递',
// waybill_number: 'L806051',
// shipping_method: '公路运输',
// payment_time: '4/13/2023',
// estimated_arrival_time: '4/15/2023',
// actual_arrival_time: '4/15/2023',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '好评',
// date_of_birth: '1986年7月17日',
// category: '连衣裙',
// material: '氨纶',
// },
// {
// pk_id: '3',
// order_number: 'A479212',
// brand: '威兰西',
// store: '威兰西旗舰店',
// person_in_charge: '陈建平',
// product: '网红同款连衣裙',
// color: '白色',
// customer_purchase_type: '零售',
// sales_volume: '128',
// unit_price: '245.49',
// sales_amount: '245.49',
// is_discounted: '双12优惠',
// discount_amount: '15',
// actual_unit_price: '230.49',
// actual_payment: '230.49',
// cost: '117.550',
// profit: '112.940',
// customer_gender: '0',
// customer_age: '22岁',
// membership_status: '无会员',
// has_visited_page: '是',
// page_visit_duration: '4',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '杨军',
// recipient_phone: '139****7024',
// shipping_address: '浙江省',
// recipient_province: '河北省',
// recipient_address: '河北省衡水市武强县',
// logistics_company: '顺丰快递',
// waybill_number: 'L356804',
// shipping_method: '公路运输',
// payment_time: '12/1/2019',
// estimated_arrival_time: '12/6/2019',
// actual_arrival_time: '12/7/2019',
// courier_feedback: '延后',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '好评',
// date_of_birth: '2000年5月3日',
// category: '连衣裙',
// material: '棉质',
// },
// {
// pk_id: '4',
// order_number: 'A389270',
// brand: 'H&R',
// store: '壹佰女装',
// person_in_charge: '杨兰英',
// product: '蕾丝花边T恤',
// color: '紫色',
// customer_purchase_type: '批发',
// sales_volume: '13',
// unit_price: '168.30',
// sales_amount: '2187.90',
// is_discounted: '双11优惠',
// discount_amount: '200',
// actual_unit_price: '152.92',
// actual_payment: '1987.90',
// cost: '1013.830',
// profit: '974.070',
// customer_gender: '0',
// customer_age: '26岁',
// membership_status: '无会员',
// has_visited_page: '是',
// page_visit_duration: '4',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '郑强',
// recipient_phone: '159****6299',
// shipping_address: '四川省',
// recipient_province: '河南省',
// recipient_address: '河南省郑州市新密市',
// logistics_company: '顺丰快递',
// waybill_number: 'L335437',
// shipping_method: '公路运输',
// payment_time: '11/10/2019',
// estimated_arrival_time: '11/14/2019',
// actual_arrival_time: '11/15/2019',
// courier_feedback: '延后',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '好评',
// date_of_birth: '1996年5月4日',
// category: '上衣',
// material: '棉质',
// },
// {
// pk_id: '5',
// order_number: 'A327122',
// brand: 'H&R',
// store: 'H&R旗舰店',
// person_in_charge: '袁英',
// product: '春夏新款连衣裙',
// color: '红色',
// customer_purchase_type: '批发',
// sales_volume: '13',
// unit_price: '119.64',
// sales_amount: '1555.32',
// is_discounted: '无',
// discount_amount: '0',
// actual_unit_price: '119.64',
// actual_payment: '1555.32',
// cost: '839.870',
// profit: '715.450',
// customer_gender: '0',
// customer_age: '22岁',
// membership_status: '无会员',
// has_visited_page: '是',
// page_visit_duration: '8',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '刘冬梅',
// recipient_phone: '185****4586',
// shipping_address: '广东省',
// recipient_province: '陕西省',
// recipient_address: '陕西省延安市富县',
// logistics_company: '中通快递',
// waybill_number: 'L209106',
// shipping_method: '公路运输',
// payment_time: '4/28/2019',
// estimated_arrival_time: '4/30/2019',
// actual_arrival_time: '4/30/2019',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '无评论',
// date_of_birth: '2000年7月3日',
// category: '连衣裙',
// material: '氨纶',
// },
// {
// pk_id: '6',
// order_number: 'A577484',
// brand: 'H&R',
// store: 'COCO女装',
// person_in_charge: '刘佳',
// product: '秋冬款连衣裙',
// color: '粉色',
// customer_purchase_type: '批发',
// sales_volume: '12',
// unit_price: '173.70',
// sales_amount: '2084.40',
// is_discounted: '店铺活动优惠',
// discount_amount: '100',
// actual_unit_price: '165.37',
// actual_payment: '1984.40',
// cost: '1091.420',
// profit: '892.980',
// customer_gender: '0',
// customer_age: '61岁',
// membership_status: '钻石会员',
// has_visited_page: '是',
// page_visit_duration: '7',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '谢博',
// recipient_phone: '147****5024',
// shipping_address: '广东省',
// recipient_province: '⽢肃省',
// recipient_address: '甘肃省甘南藏族自治州卓尼县',
// logistics_company: '申通快递',
// waybill_number: 'L913348',
// shipping_method: '航空运输',
// payment_time: '4/7/2019',
// estimated_arrival_time: '4/11/2019',
// actual_arrival_time: '4/11/2019',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '中评',
// date_of_birth: '1961年8月12日',
// category: '连衣裙',
// material: '麻质',
// },
// {
// pk_id: '7',
// order_number: 'A293474',
// brand: '拉夏贝尔',
// store: '拉夏贝尔旗舰店',
// person_in_charge: '刘佳',
// product: '泫雅风T恤',
// color: '粉色',
// customer_purchase_type: '批发',
// sales_volume: '12',
// unit_price: '162.02',
// sales_amount: '1944.24',
// is_discounted: '双11优惠',
// discount_amount: '200',
// actual_unit_price: '145.35',
// actual_payment: '1744.24',
// cost: '1186.080',
// profit: '558.160',
// customer_gender: '0',
// customer_age: '59岁',
// membership_status: '普通会员',
// has_visited_page: '是',
// page_visit_duration: '2',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '赵丽丽',
// recipient_phone: '186****8566',
// shipping_address: '浙江省',
// recipient_province: '⼴东省',
// recipient_address: '广东省梅州市',
// logistics_company: '圆通快递',
// waybill_number: 'L841704',
// shipping_method: '铁路运输',
// payment_time: '11/10/2019',
// estimated_arrival_time: '11/15/2019',
// actual_arrival_time: '11/15/2019',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '中评',
// date_of_birth: '1963年5月27日',
// category: '上衣',
// material: '氨纶',
// },
// {
// pk_id: '8',
// order_number: 'A424004',
// brand: '艾米丽',
// store: '卡卡家女装',
// person_in_charge: '宋建华',
// product: '大码牛仔裤',
// color: '红色',
// customer_purchase_type: '批发',
// sales_volume: '11',
// unit_price: '73.54',
// sales_amount: '808.94',
// is_discounted: '双11优惠',
// discount_amount: '100',
// actual_unit_price: '64.45',
// actual_payment: '708.94',
// cost: '425.360',
// profit: '283.580',
// customer_gender: '0',
// customer_age: '23岁',
// membership_status: '无会员',
// has_visited_page: '是',
// page_visit_duration: '8',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '谢雷',
// recipient_phone: '150****7487',
// shipping_address: '浙江省',
// recipient_province: '宁夏回族自治区',
// recipient_address: '宁夏回族自治区银川市贺兰县',
// logistics_company: ' 百世快递',
// waybill_number: 'L451724',
// shipping_method: '公路运输',
// payment_time: '11/27/2023',
// estimated_arrival_time: '12/1/2023',
// actual_arrival_time: '12/1/2023',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '好评',
// date_of_birth: '1999年12月18日',
// category: '女裤',
// material: '锦纶',
// },
// {
// pk_id: '9',
// order_number: 'A561021',
// brand: 'TARA',
// store: 'TARA旗舰店',
// person_in_charge: '邹勇',
// product: '春夏季新款裤子',
// color: '橙色',
// customer_purchase_type: '批发',
// sales_volume: '11',
// unit_price: '57.25',
// sales_amount: '629.75',
// is_discounted: '双12优惠',
// discount_amount: '150',
// actual_unit_price: '43.61',
// actual_payment: '479.75',
// cost: '287.850',
// profit: '191.900',
// customer_gender: '0',
// customer_age: '36岁',
// membership_status: '普通会员',
// has_visited_page: '是',
// page_visit_duration: '7',
// transaction_status: '交易成功',
// product_status: '已收货',
// recipient_name: '王桂珍',
// recipient_phone: '137****8424',
// shipping_address: '福建省',
// recipient_province: '湖南省',
// recipient_address: '湖南省永州市市辖区',
// logistics_company: '申通快递',
// waybill_number: 'L948843',
// shipping_method: '公路运输',
// payment_time: '12/17/2019',
// estimated_arrival_time: '12/19/2019',
// actual_arrival_time: '12/19/2019',
// courier_feedback: '准时',
// is_returned: '否',
// refund_reason: '无',
// customer_satisfaction: '好评',
// date_of_birth: '1986年6月1日',
// category: '女裤',
// material: '锦纶',
// },
// {
// pk_id: '10',
// order_number: 'A191677',
// brand: '富贵人',
// store: '富贵人旗舰店',
// person_in_charge: '刘佳',
// product: '蕾丝花边T恤',
// color: '粉色',
// customer_purchase_type: '批发',
// sales_volume: '11',
// unit_price: '117.92',
// sales_amount: '1297.12',
// is_discounted: '无',
// discount_amount: '0',
// actual_unit_price: '117.92',
// actual_payment: '1297.12',
// cost: '674.500',
// profit: '622.620',
// customer_gender: '0',
// customer_age: '38岁',
// membership_status: '无会员',
// has_visited_page: '否',
// page_visit_duration: '0',
// transaction_status: '交易取消',
// product_status: '已取消',
// recipient_name: '梁秀华',
// recipient_phone: '136****1451',
// shipping_address: '广东省',
// recipient_province: '⼭东省',
// recipient_address: '山东省聊城市冠县',
// logistics_company: '申通快递',
// waybill_number: 'L385723',
// shipping_method: '航空运输',
// payment_time: '12/3/2019',
// estimated_arrival_time: '12/8/2019',
// actual_arrival_time: '12/8/2019',
// courier_feedback: '准时',
// is_returned: '是',
// refund_reason: '不喜欢',
// customer_satisfaction: '无评论',
// date_of_birth: '1984年2月27日',
// category: '上衣',
// material: '棉质',
// },
// ],
// info: {
// id: '7306145818979860480',
// experiment_id: '7028276368903241728',
// name: '王',
// table_name: '7028276368903241728_6602032005293015040_my_data',
// type: '2',
// source: {
// name: '《商务数据分析基础》数据集-电子商务-10条.xlsx',
// url: 'https://webapp-pub.ezijing.com/upload/saas-bi/f6a1ab335e0a19935b750537e5d8a6f2.xlsx',
// },
// created_operator: '6602032005293015040',
// created_time: '2025-03-14 10:55:04',
// updated_operator: '6602032005293015040',
// updated_time: '2025-03-14 16:31:47',
// },
// },
// })
return
httpRequest
.
get
(
'/api/resource/bi/v1/data/my/list'
,
{
params
})
return
httpRequest
.
get
(
'/api/resource/bi/v1/data/my/list'
,
{
params
})
}
}
// 查看字段详情
// 查看字段详情
export
function
getMyField
()
{
export
function
getMyField
()
{
// return Promise.resolve({
// code: 0,
// message: 'OK',
// data: [
// {
// name: '订单编号',
// english_name: 'order_number',
// type: 'VARCHAR(7)',
// length: '7',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '品牌',
// english_name: 'brand',
// type: 'VARCHAR(12)',
// length: '12',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '店铺',
// english_name: 'store',
// type: 'VARCHAR(21)',
// length: '21',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '负责人',
// english_name: 'person_in_charge',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '商品',
// english_name: 'product',
// type: 'VARCHAR(21)',
// length: '21',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '颜色',
// english_name: 'color',
// type: 'VARCHAR(6)',
// length: '6',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '客户购买类型',
// english_name: 'customer_purchase_type',
// type: 'VARCHAR(6)',
// length: '6',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '销量',
// english_name: 'sales_volume',
// type: 'SMALLINT',
// length: '',
// point: '',
// null: '允许',
// default: '',
// type_name: '整数',
// },
// {
// name: '单价',
// english_name: 'unit_price',
// type: 'DECIMAL(5, 2)',
// length: '5',
// point: '2',
// null: '允许',
// default: '',
// type_name: '小数',
// },
// {
// name: '销售额',
// english_name: 'sales_amount',
// type: 'DECIMAL(6, 2)',
// length: '6',
// point: '2',
// null: '允许',
// default: '',
// type_name: '小数',
// },
// {
// name: '是否优惠',
// english_name: 'is_discounted',
// type: 'VARCHAR(18)',
// length: '18',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '优惠金额',
// english_name: 'discount_amount',
// type: 'SMALLINT',
// length: '',
// point: '',
// null: '允许',
// default: '',
// type_name: '整数',
// },
// {
// name: '实际单价',
// english_name: 'actual_unit_price',
// type: 'DECIMAL(5, 2)',
// length: '5',
// point: '2',
// null: '允许',
// default: '',
// type_name: '小数',
// },
// {
// name: '实际付款',
// english_name: 'actual_payment',
// type: 'DECIMAL(6, 2)',
// length: '6',
// point: '2',
// null: '允许',
// default: '',
// type_name: '小数',
// },
// {
// name: '成本',
// english_name: 'cost',
// type: 'DECIMAL(7, 3)',
// length: '7',
// point: '3',
// null: '允许',
// default: '',
// type_name: '小数',
// },
// {
// name: '利润',
// english_name: 'profit',
// type: 'DECIMAL(6, 3)',
// length: '6',
// point: '3',
// null: '允许',
// default: '',
// type_name: '小数',
// },
// {
// name: '客户性别',
// english_name: 'customer_gender',
// type: 'TINYINT',
// length: '',
// point: '',
// null: '允许',
// default: '',
// type_name: '整数',
// },
// {
// name: '客户年龄',
// english_name: 'customer_age',
// type: 'VARCHAR(5)',
// length: '5',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '会员情况',
// english_name: 'membership_status',
// type: 'VARCHAR(12)',
// length: '12',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '是否访问页面',
// english_name: 'has_visited_page',
// type: 'VARCHAR(3)',
// length: '3',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '访问页面时长',
// english_name: 'page_visit_duration',
// type: 'TINYINT',
// length: '',
// point: '',
// null: '允许',
// default: '',
// type_name: '整数',
// },
// {
// name: '交易状态',
// english_name: 'transaction_status',
// type: 'VARCHAR(12)',
// length: '12',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '商品状态',
// english_name: 'product_status',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '收货人姓名',
// english_name: 'recipient_name',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '收货人电话',
// english_name: 'recipient_phone',
// type: 'VARCHAR(11)',
// length: '11',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '发货地址',
// english_name: 'shipping_address',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '收货地址省份',
// english_name: 'recipient_province',
// type: 'VARCHAR(21)',
// length: '21',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '收货地址',
// english_name: 'recipient_address',
// type: 'VARCHAR(39)',
// length: '39',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '物流公司',
// english_name: 'logistics_company',
// type: 'VARCHAR(15)',
// length: '15',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '运单号',
// english_name: 'waybill_number',
// type: 'VARCHAR(7)',
// length: '7',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '运送方式',
// english_name: 'shipping_method',
// type: 'VARCHAR(12)',
// length: '12',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '支付时间',
// english_name: 'payment_time',
// type: 'VARCHAR(10)',
// length: '10',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '预计到达时间',
// english_name: 'estimated_arrival_time',
// type: 'VARCHAR(10)',
// length: '10',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '实际到达时间',
// english_name: 'actual_arrival_time',
// type: 'VARCHAR(10)',
// length: '10',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '快递反馈',
// english_name: 'courier_feedback',
// type: 'VARCHAR(6)',
// length: '6',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '是否退货',
// english_name: 'is_returned',
// type: 'VARCHAR(3)',
// length: '3',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '退款原因',
// english_name: 'refund_reason',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '客户满意度',
// english_name: 'customer_satisfaction',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '出生日期',
// english_name: 'date_of_birth',
// type: 'VARCHAR(17)',
// length: '17',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '品类',
// english_name: 'category',
// type: 'VARCHAR(9)',
// length: '9',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// {
// name: '材质',
// english_name: 'material',
// type: 'VARCHAR(6)',
// length: '6',
// point: '',
// null: '允许',
// default: '',
// type_name: '字符串',
// },
// ],
// })
return
httpRequest
.
get
(
'/api/resource/bi/v1/data/my/field-detail'
)
return
httpRequest
.
get
(
'/api/resource/bi/v1/data/my/field-detail'
)
}
}
// 进度查询
export
function
getProcessProgress
(
params
:
{
function_name
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/bi/v1/processing/processing/progress'
,
{
params
})
}
// 我的数据集列表
// 我的数据集列表
export
function
getChartList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
}
>
)
{
export
function
getChartList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
}
>
)
{
return
Promise
.
resolve
({
return
Promise
.
resolve
({
...
...
src/api/data.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
// 我的数据集列表
export
function
getMyList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
}
>
)
{
return
httpRequest
.
get
(
'/api/resource/bi/v1/data/my/list'
,
{
params
})
}
// 查看字段详情
export
function
getMyField
()
{
return
httpRequest
.
get
(
'/api/resource/bi/v1/data/my/field-detail'
)
}
// 进度查询
export
function
getProcessProgress
(
params
:
{
function_name
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/bi/v1/processing/processing/progress'
,
{
params
})
}
// 数据可视化组件列表
export
function
getComponentList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
;
type
:
string
}
>
)
{
return
httpRequest
.
get
(
'/api/resource/bi/v1/reporting/component/list'
,
{
params
})
}
// 更新数据可视化组件
export
function
updateComponent
(
data
:
{
id
:
string
;
name
:
string
;
type
:
string
;
content
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/reporting/component/list'
,
data
)
}
// 删除数据可视化组件
export
function
deleteComponent
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/reporting/component/list'
,
data
)
}
// 数据可视化组件详情
export
function
getComponent
(
params
:
{
id
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/bi/v1/reporting/component/list'
,
{
params
})
}
src/components/
data
/ChartWrap.tsx
→
src/components/
chart
/ChartWrap.tsx
浏览文件 @
b5a25e0b
import
{
Button
,
Card
,
Flex
}
from
'antd'
import
{
Button
,
Card
,
Flex
}
from
'antd'
import
{
ReactNode
}
from
'react'
import
{
ReactNode
}
from
'react'
import
AppList
,
{
AppListProps
}
from
'@/components/AppList'
import
AppList
,
{
AppListProps
}
from
'@/components/AppList'
import
{
getChartList
}
from
'@/api/base'
import
ViewDataButtonModal
from
'../data/ViewMyDataButtonModal'
import
{
getComponentList
}
from
'@/api/data'
export
default
function
DataWrap
({
title
,
buttons
}:
{
title
:
string
;
buttons
:
ReactNode
;
children
?:
ReactNode
})
{
export
default
function
DataWrap
({
title
,
buttons
}:
{
title
:
string
;
buttons
:
ReactNode
;
children
?:
ReactNode
})
{
const
listOptions
:
AppListProps
=
{
const
listOptions
:
AppListProps
=
{
fetchApi
:
async
(
params
)
=>
{
fetchApi
:
async
(
params
)
=>
{
const
{
data
}
=
await
getC
har
tList
(
params
)
const
{
data
}
=
await
getC
omponen
tList
(
params
)
return
{
...
data
}
return
{
...
data
}
},
},
columns
:
[
columns
:
[
...
@@ -54,7 +55,7 @@ export default function DataWrap({ title, buttons }: { title: string; buttons: R
...
@@ -54,7 +55,7 @@ export default function DataWrap({ title, buttons }: { title: string; buttons: R
<
Flex
wrap
gap=
{
10
}
>
<
Flex
wrap
gap=
{
10
}
>
{
buttons
}
{
buttons
}
</
Flex
>
</
Flex
>
<
Button
>
查看我的数据集
</
Button
>
<
ViewDataButtonModal
></
ViewDataButtonModal
>
</
Flex
>
</
Flex
>
<
AppList
{
...
listOptions
}
/>
<
AppList
{
...
listOptions
}
/>
</
Card
>
</
Card
>
...
...
src/components/data/ViewDataButtonModal.tsx
浏览文件 @
b5a25e0b
import
{
useEffect
,
useState
}
from
'react'
import
{
useEffect
,
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
}
from
'antd'
import
{
Button
,
Flex
,
Modal
}
from
'antd'
import
axios
from
'axios'
import
DataRender
from
'./DataRender'
import
{
read
,
utils
}
from
'xlsx'
import
{
read
,
utils
}
from
'xlsx'
import
{
uniqueId
}
from
'lodash-es'
import
{
uniqueId
}
from
'lodash-es'
import
axios
from
'axios'
import
DataRender
from
'./DataRender'
export
default
function
ViewDataButtonModal
({
data
}:
{
data
:
any
})
{
export
default
function
ViewDataButtonModal
({
data
}:
{
data
:
any
})
{
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
...
...
src/components/data/ViewMyDataButtonModal.tsx
0 → 100644
浏览文件 @
b5a25e0b
import
{
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
}
from
'antd'
import
{
useDataQuery
}
from
'@/hooks/useQuery'
import
DataRender
from
'./DataRender'
export
default
function
ViewDataButtonModal
()
{
const
[
open
,
setOpen
]
=
useState
(
false
)
const
{
data
,
isPending
}
=
useDataQuery
()
const
columns
:
any
=
data
.
title
.
map
((
item
:
any
)
=>
{
return
{
title
:
item
.
name
,
dataIndex
:
item
.
english_name
,
align
:
'center'
,
minWidth
:
120
,
}
})
return
(
<>
<
Button
onClick=
{
()
=>
setOpen
(
true
)
}
>
查看我的数据集
</
Button
>
<
Modal
title=
"查看我的数据集"
width=
{
'80%'
}
open=
{
open
}
footer=
{
null
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
<
div
>
数据集名称:
{
data
.
info
?.
name
}
</
div
>
<
div
>
共计:
{
data
.
total
}
条数据
</
div
>
</
Flex
>
<
DataRender
rowKey=
{
'pk_id'
}
loading=
{
isPending
}
dataSource=
{
data
.
list
}
columns=
{
columns
}
/>
</
Modal
>
</>
)
}
src/hooks/useQuery.ts
浏览文件 @
b5a25e0b
import
{
useEffect
}
from
'react'
import
{
useEffect
,
useState
}
from
'react'
import
{
useQuery
}
from
'@tanstack/react-query'
import
{
useQuery
}
from
'@tanstack/react-query'
import
{
getUser
,
getMapList
,
getMyList
,
getMyField
}
from
'@/api/base'
import
{
getUser
,
getMapList
,
getMyList
,
getMyField
,
getProcessProgress
}
from
'@/api/base'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
import
axios
from
'axios'
import
axios
from
'axios'
import
{
read
,
utils
}
from
'xlsx'
import
{
read
,
utils
}
from
'xlsx'
// 用户信息
export
function
useUserQuery
()
{
export
function
useUserQuery
()
{
const
{
setUser
}
=
useUserStore
()
const
{
setUser
}
=
useUserStore
()
...
@@ -20,6 +21,7 @@ export function useUserQuery() {
...
@@ -20,6 +21,7 @@ export function useUserQuery() {
return
query
return
query
}
}
// 字典
export
function
useMapQuery
()
{
export
function
useMapQuery
()
{
const
{
setMap
}
=
useMapStore
()
const
{
setMap
}
=
useMapStore
()
...
@@ -53,6 +55,7 @@ export function useDataQuery() {
...
@@ -53,6 +55,7 @@ export function useDataQuery() {
return
query
return
query
}
}
// 读取excel文件
export
function
useExcelQuery
(
url
:
string
)
{
export
function
useExcelQuery
(
url
:
string
)
{
const
query
=
useQuery
({
const
query
=
useQuery
({
queryKey
:
[
'excel'
,
url
],
queryKey
:
[
'excel'
,
url
],
...
@@ -80,6 +83,7 @@ interface DataField {
...
@@ -80,6 +83,7 @@ interface DataField {
type
:
string
type
:
string
}
}
// 字段
export
function
useDataFieldQuery
()
{
export
function
useDataFieldQuery
()
{
const
query
=
useQuery
({
const
query
=
useQuery
({
queryKey
:
[
'dataFiled'
],
queryKey
:
[
'dataFiled'
],
...
@@ -89,6 +93,51 @@ export function useDataFieldQuery() {
...
@@ -89,6 +93,51 @@ export function useDataFieldQuery() {
return
{
data
:
[]
}
return
{
data
:
[]
}
},
},
})
})
const
fields
=
query
.
data
?.
map
((
item
)
=>
{
return
{
...
item
,
label
:
item
.
name
,
value
:
item
.
english_name
}
})
||
[]
return
query
const
getFieldName
=
(
value
:
string
)
=>
{
return
fields
.
find
((
item
)
=>
item
.
value
===
value
)?.
label
||
value
}
const
getFieldNames
=
(
values
:
string
[])
=>
{
return
values
.
map
((
value
)
=>
getFieldName
(
value
))
}
return
{
...
query
,
fields
,
fieldOptions
:
fields
,
getFieldName
,
getFieldNames
}
}
// 进度查询
export
function
useProcessProgressQuery
(
params
:
{
function_name
:
string
})
{
const
[
enabled
,
setEnabled
]
=
useState
(
false
)
const
query
=
useQuery
({
queryKey
:
[
'processProgress'
,
params
],
queryFn
:
()
=>
{
return
getProcessProgress
(
params
)
},
select
:
(
res
)
=>
res
.
data
,
enabled
,
refetchInterval
:
enabled
?
1000
:
false
,
})
// 开始轮询的方法
const
start
=
()
=>
{
setEnabled
(
true
)
}
// 结束轮询的方法
const
stop
=
()
=>
{
setEnabled
(
false
)
}
// 组件卸载时清理
useEffect
(()
=>
{
return
()
=>
{
stop
()
}
},
[])
return
{
...
query
,
start
,
stop
}
}
}
src/modules/data/chart/bar/views/Index.tsx
浏览文件 @
b5a25e0b
import
{
lazy
}
from
'react'
import
{
lazy
}
from
'react'
import
ChartWrap
from
'@/components/
data
/ChartWrap'
import
ChartWrap
from
'@/components/
chart
/ChartWrap'
const
ButtonModal
=
lazy
(()
=>
import
(
'../components/ButtonModal'
))
const
ButtonModal
=
lazy
(()
=>
import
(
'../components/ButtonModal'
))
...
...
src/modules/data/chart/line/views/Index.tsx
浏览文件 @
b5a25e0b
import
ChartWrap
from
'@/components/
data
/ChartWrap'
import
ChartWrap
from
'@/components/
chart
/ChartWrap'
import
{
Button
}
from
'antd'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
export
default
function
DataProcess
()
{
...
...
src/modules/data/chart/pie/views/Index.tsx
浏览文件 @
b5a25e0b
import
ChartWrap
from
'@/components/
data
/ChartWrap'
import
ChartWrap
from
'@/components/
chart
/ChartWrap'
import
{
Button
}
from
'antd'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
export
default
function
DataProcess
()
{
...
...
src/modules/data/chart/radar/views/Index.tsx
浏览文件 @
b5a25e0b
import
ChartWrap
from
'@/components/
data
/ChartWrap'
import
ChartWrap
from
'@/components/
chart
/ChartWrap'
import
{
Button
}
from
'antd'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
export
default
function
DataProcess
()
{
...
...
src/modules/data/preprocess/error/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -27,7 +27,7 @@ export default function ButtonModal() {
...
@@ -27,7 +27,7 @@ export default function ButtonModal() {
})
})
}
}
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -59,9 +59,9 @@ export default function ButtonModal() {
...
@@ -59,9 +59,9 @@ export default function ButtonModal() {
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择逻辑错误值字段'
}]
}
>
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择逻辑错误值字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
...
src/modules/data/preprocess/max/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -27,7 +27,7 @@ export default function ButtonModal() {
...
@@ -27,7 +27,7 @@ export default function ButtonModal() {
})
})
}
}
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -59,9 +59,9 @@ export default function ButtonModal() {
...
@@ -59,9 +59,9 @@ export default function ButtonModal() {
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择过大值字段'
}]
}
>
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择过大值字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
...
src/modules/data/preprocess/min/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -27,7 +27,7 @@ export default function ButtonModal() {
...
@@ -27,7 +27,7 @@ export default function ButtonModal() {
})
})
}
}
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -59,9 +59,9 @@ export default function ButtonModal() {
...
@@ -59,9 +59,9 @@ export default function ButtonModal() {
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择过小值字段'
}]
}
>
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择过小值字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
...
src/modules/data/preprocess/null/api.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
import
type
{
ProcessDataParams
}
from
'./types'
// 缺省值处理
export
function
processData
(
data
:
ProcessDataParams
)
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/processing/pre-processing/missing'
,
data
)
}
src/modules/data/preprocess/null/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -5,6 +5,22 @@ import AppProgressSteps from '@/components/AppProgressSteps'
...
@@ -5,6 +5,22 @@ import AppProgressSteps from '@/components/AppProgressSteps'
import
{
useSearchParams
}
from
'react-router'
import
{
useSearchParams
}
from
'react-router'
import
{
useAI
}
from
'@/hooks/useAI'
import
{
useAI
}
from
'@/hooks/useAI'
import
prompt
from
'@/utils/prompt'
import
prompt
from
'@/utils/prompt'
import
{
useProcessData
}
from
'../query'
const
actionOptions
=
[
{
label
:
'统一规则处理'
,
value
:
'统一规则处理'
},
{
label
:
'逐个配置规则处理'
,
value
:
'逐个配置规则处理'
},
]
const
ruleOptions
=
[
{
label
:
'不处理'
,
value
:
'不处理'
},
{
label
:
'AI智能填充'
,
value
:
'AI智能填充'
},
{
label
:
'删除'
,
value
:
'删除'
},
{
label
:
'平均值填充'
,
value
:
'平均值填充'
},
{
label
:
'特殊值填充'
,
value
:
'特殊值填充'
},
{
label
:
'热卡填充(上)'
,
value
:
'热卡填充(上)'
},
{
label
:
'热卡填充(下)'
,
value
:
'热卡填充(下)'
},
]
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
[
searchParams
]
=
useSearchParams
()
const
[
searchParams
]
=
useSearchParams
()
...
@@ -14,13 +30,12 @@ export default function ButtonModal() {
...
@@ -14,13 +30,12 @@ export default function ButtonModal() {
try
{
try
{
const
parse
=
JSON
.
parse
(
message
.
content
)
const
parse
=
JSON
.
parse
(
message
.
content
)
console
.
log
(
parse
)
console
.
log
(
parse
)
if
(
parse
.
results
.
length
)
form
.
setFieldValue
(
'
checkedList
'
,
parse
.
results
.
map
((
item
:
any
)
=>
item
.
name
)
||
[])
if
(
parse
.
results
.
length
)
form
.
setFieldValue
(
'
fields
'
,
parse
.
results
.
map
((
item
:
any
)
=>
item
.
name
)
||
[])
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
error
)
console
.
error
(
error
)
}
}
},
},
})
})
const
handleSearch
=
()
=>
{
const
handleSearch
=
()
=>
{
post
({
post
({
response_format
:
{
type
:
'json_object'
},
response_format
:
{
type
:
'json_object'
},
...
@@ -28,7 +43,7 @@ export default function ButtonModal() {
...
@@ -28,7 +43,7 @@ export default function ButtonModal() {
})
})
}
}
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
,
getFieldName
,
getFieldNames
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -36,46 +51,48 @@ export default function ButtonModal() {
...
@@ -36,46 +51,48 @@ export default function ButtonModal() {
setOpen
(
true
)
setOpen
(
true
)
}
}
},
[
searchParams
])
},
[
searchParams
])
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
[
form
]
=
Form
.
useForm
()
const
initialValues
=
{
const
initialValues
=
{
checkedList
:
searchParams
.
get
(
'results'
)?.
split
(
','
)
||
[],
fields
:
searchParams
.
get
(
'results'
)?.
split
(
','
)
||
[],
method
:
'unified
'
,
action
:
'统一规则处理
'
,
rule
:
'
1
'
,
rule
:
'
不处理
'
,
}
}
const
checkedList
:
string
[]
=
Form
.
useWatch
(
'checkedList
'
,
form
)
||
[]
const
fields
:
string
[]
=
Form
.
useWatch
(
'fields
'
,
form
)
||
[]
const
method
=
Form
.
useWatch
(
'method
'
,
form
)
const
action
=
Form
.
useWatch
(
'action
'
,
form
)
const
rule
=
Form
.
useWatch
(
'rule'
,
form
)
const
rule
=
Form
.
useWatch
(
'rule'
,
form
)
const
rules
=
Form
.
useWatch
(
'rules'
,
form
)
||
{}
const
rules
=
Form
.
useWatch
(
'rules'
,
form
)
||
{}
const
methodOptions
=
[
const
{
mutate
,
isPending
,
progress
,
message
}
=
useProcessData
()
{
label
:
'统一规则处理'
,
value
:
'unified'
},
// 开始处理
{
label
:
'逐个配置规则处理'
,
value
:
'individual'
},
const
handleStart
=
()
=>
{
]
form
.
validateFields
().
then
((
values
)
=>
{
const
params
=
{
...
values
,
fields
:
values
.
fields
.
join
(
','
),
rules
:
JSON
.
stringify
(
values
.
rules
)
}
const
ruleOptions
=
[
mutate
(
params
,
{
{
label
:
'不处理'
,
value
:
'1'
},
onSuccess
:
handleClose
,
{
label
:
'AI智能填充'
,
value
:
'2'
},
})
{
label
:
'删除'
,
value
:
'3'
},
})
{
label
:
'平均值填充'
,
value
:
'4'
},
}
{
label
:
'特殊值填充'
,
value
:
'5'
},
{
label
:
'热卡填充(上)'
,
value
:
'6'
},
{
label
:
'热卡填充(下)'
,
value
:
'7'
},
]
const
[
step
,
setStep
]
=
useState
<
number
>
(
-
1
)
// 关闭并重置
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
form
.
resetFields
()
}
const
steps
=
[
const
steps
=
[
{
{
title
:
'请选择缺失值字段'
,
title
:
'请选择缺失值字段'
,
content
:
(
content
:
(
<
Form
.
Item
name=
"
checkedList
"
>
<
Form
.
Item
name=
"
fields
"
>
<
Checkbox
.
Group
>
<
Checkbox
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Checkbox
value=
{
item
.
name
}
>
{
item
.
name
}
</
Checkbox
>
<
Checkbox
value=
{
item
.
value
}
>
{
item
.
label
}
</
Checkbox
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
@@ -87,18 +104,17 @@ export default function ButtonModal() {
...
@@ -87,18 +104,17 @@ export default function ButtonModal() {
title
:
'配置处理规则'
,
title
:
'配置处理规则'
,
content
:
(
content
:
(
<>
<>
<
Form
.
Item
label=
"缺失值字段处理方法"
name=
"
method
"
>
<
Form
.
Item
label=
"缺失值字段处理方法"
name=
"
action
"
>
<
Radio
.
Group
options=
{
method
Options
}
/>
<
Radio
.
Group
options=
{
action
Options
}
/>
</
Form
.
Item
>
</
Form
.
Item
>
{
/* 统一规则处理 */
}
{
action
===
'统一规则处理'
&&
(
{
method
===
'unified'
&&
(
<>
<>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
"rule"
>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
"rule"
>
<
Select
options=
{
ruleOptions
}
/>
<
Select
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
</
Form
.
Item
>
{
rule
===
'
5
'
&&
(
{
rule
===
'
特殊值填充
'
&&
(
<
Form
.
Item
label=
"请填写特殊值"
name=
"special"
>
<
Form
.
Item
label=
"请填写特殊值"
name=
"special"
>
<
Input
placeholder=
"请输入"
/>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</
Form
.
Item
>
...
@@ -106,16 +122,17 @@ export default function ButtonModal() {
...
@@ -106,16 +122,17 @@ export default function ButtonModal() {
</>
</>
)
}
)
}
{
/* 逐个配置规则处理 */
}
{
action
===
'逐个配置规则处理'
&&
{
method
===
'individual'
&&
fields
.
map
((
field
,
index
)
=>
(
checkedList
.
map
((
field
)
=>
(
<
div
key=
{
field
}
style=
{
{
marginBottom
:
10
}
}
>
<
div
key=
{
field
}
style=
{
{
marginBottom
:
10
}
}
>
<
Form
.
Item
label=
"字段"
>
{
field
}
</
Form
.
Item
>
<
Form
.
Item
label=
"字段"
name=
{
[
'rules'
,
index
,
'field'
]
}
initialValue=
{
field
}
>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
{
[
'rules'
,
field
,
'rule'
]
}
>
<
span
>
{
getFieldName
(
field
)
}
</
span
>
</
Form
.
Item
>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
{
[
'rules'
,
index
,
'rule'
]
}
>
<
Select
options=
{
ruleOptions
}
/>
<
Select
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
</
Form
.
Item
>
{
rules
[
field
]?.
rule
===
'5
'
&&
(
{
rules
[
index
]?.
rule
===
'特殊值填充
'
&&
(
<
Form
.
Item
label=
"请填写特殊值"
name=
{
[
'rules'
,
field
,
'special'
]
}
>
<
Form
.
Item
label=
"请填写特殊值"
name=
{
[
'rules'
,
index
,
'special'
]
}
>
<
Input
placeholder=
"请输入"
/>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</
Form
.
Item
>
)
}
)
}
...
@@ -129,14 +146,14 @@ export default function ButtonModal() {
...
@@ -129,14 +146,14 @@ export default function ButtonModal() {
title
:
'处理执行'
,
title
:
'处理执行'
,
content
:
(
content
:
(
<>
<>
<
p
>
缺失值处理字段:
{
checkedList
.
join
(
',
'
)
}
</
p
>
<
p
>
缺失值处理字段:
{
getFieldNames
(
fields
).
join
(
'、
'
)
}
</
p
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setStep
(
1
)
}
>
<
Button
type=
"primary"
loading=
{
isPending
}
onClick=
{
handleStart
}
>
开始处理
开始处理
</
Button
>
</
Button
>
<
AppProgressSteps
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
current=
{
progress
}
items=
{
[
items=
{
[
{
{
title
:
(
title
:
(
...
@@ -164,13 +181,7 @@ export default function ButtonModal() {
...
@@ -164,13 +181,7 @@ export default function ButtonModal() {
处理结果
处理结果
</>
</>
),
),
description
:
(
description
:
<>
{
message
[
3
]
}
</>,
<>
累计处理XX个字段
<
br
/>
累计处理XX条记录
</>
),
},
},
]
}
]
}
/>
/>
...
@@ -197,12 +208,12 @@ export default function ButtonModal() {
...
@@ -197,12 +208,12 @@ export default function ButtonModal() {
)
}
)
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
setCurrent
(
current
+
1
)
}
disabled=
{
!
checkedList
.
length
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setCurrent
(
current
+
1
)
}
disabled=
{
!
fields
.
length
}
>
下一步
下一步
</
Button
>
</
Button
>
)
}
)
}
{
current
===
steps
.
length
-
1
&&
(
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
false
)
}
>
<
Button
type=
"primary"
disabled=
{
isPending
}
onClick=
{
handleClose
}
>
关闭
关闭
</
Button
>
</
Button
>
)
}
)
}
...
@@ -210,7 +221,7 @@ export default function ButtonModal() {
...
@@ -210,7 +221,7 @@ export default function ButtonModal() {
}
}
destroyOnClose
destroyOnClose
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
handleClose
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
initialValues=
{
initialValues
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
initialValues=
{
initialValues
}
>
{
steps
.
map
((
item
,
index
)
=>
(
{
steps
.
map
((
item
,
index
)
=>
(
...
...
src/modules/data/preprocess/null/query.ts
0 → 100644
浏览文件 @
b5a25e0b
import
{
useMutation
,
useQueryClient
}
from
'@tanstack/react-query'
import
{
message
}
from
'antd'
import
{
processData
}
from
'./api'
import
type
{
ProcessDataParams
}
from
'./types'
import
{
useProcessProgressQuery
}
from
'@/hooks/useQuery'
// 处理数据
export
function
useProcessData
()
{
const
queryClient
=
useQueryClient
()
const
{
data
,
start
,
stop
}
=
useProcessProgressQuery
({
function_name
:
'missing'
})
const
query
=
useMutation
({
mutationFn
:
(
data
:
ProcessDataParams
)
=>
{
start
()
return
processData
(
data
)
},
onSuccess
:
()
=>
{
stop
()
message
.
success
(
'处理完成'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
},
})
return
{
...
query
,
progress
:
data
?.
progress
??
-
1
,
message
:
data
?.
message
??
{}
}
}
src/modules/data/preprocess/null/types.ts
0 → 100644
浏览文件 @
b5a25e0b
export
interface
ProcessDataParams
{
fields
:
string
action
:
string
rules
:
string
rule
:
string
specify
:
string
}
src/modules/data/preprocess/space/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -24,7 +24,7 @@ export default function ButtonModal() {
...
@@ -24,7 +24,7 @@ export default function ButtonModal() {
})
})
}
}
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
...
@@ -53,9 +53,9 @@ export default function ButtonModal() {
...
@@ -53,9 +53,9 @@ export default function ButtonModal() {
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择数据去空格字段'
}]
}
>
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择数据去空格字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
...
src/modules/data/preprocess/split/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -4,7 +4,7 @@ import { useDataFieldQuery } from '@/hooks/useQuery'
...
@@ -4,7 +4,7 @@ import { useDataFieldQuery } from '@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
...
@@ -34,9 +34,9 @@ export default function ButtonModal() {
...
@@ -34,9 +34,9 @@ export default function ButtonModal() {
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择数据拆分字段'
}]
}
>
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择数据拆分字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
...
src/modules/data/preprocess/symbol/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
...
@@ -4,7 +4,7 @@ import { useDataFieldQuery } from '@/hooks/useQuery'
...
@@ -4,7 +4,7 @@ import { useDataFieldQuery } from '@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
...
@@ -26,9 +26,9 @@ export default function ButtonModal() {
...
@@ -26,9 +26,9 @@ export default function ButtonModal() {
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择去标点字段'
}]
}
>
<
Form
.
Item
name=
"checked"
rules=
{
[{
required
:
true
,
message
:
'请选择去标点字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
6
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
...
src/modules/data/process/binning/api.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
import
type
{
ProcessDataParams
}
from
'./types'
// 数据分箱
export
function
processData
(
data
:
ProcessDataParams
)
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/processing/processing/binning'
,
data
)
}
src/modules/data/process/binning/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
import
{
use
Effect
,
use
State
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Table
,
message
}
from
'antd'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Checkbox
}
from
'antd'
import
{
useData
Query
,
useData
FieldQuery
}
from
'@/hooks/useQuery'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
{
uniqBy
}
from
'lodash-es'
import
{
useProcessData
}
from
'../query'
import
{
MinusCircleOutlined
}
from
'@ant-design/icons'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
{
data
=
{
list
:
[]
}
}
=
useDataQuery
()
// 添加默认值防止 data 为 undefined
const
{
fieldOptions
,
getFieldName
}
=
useDataFieldQuery
()
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
// 数字类型字段
const
currentFieldOptions
=
fieldOptions
.
filter
(
(
item
)
=>
item
.
type
.
includes
(
'DECIMAL'
)
||
item
.
type
.
includes
(
'SMALLINT'
)
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
[
form
]
=
Form
.
useForm
()
const
[
dataSource
,
setDataSource
]
=
useState
<
{
key
:
number
;
raw_value
:
string
;
mapping_value
:
string
}[]
>
([])
const
[
step
,
setStep
]
=
useState
(
-
1
)
// 使用 Form.useWatch 监听表单值变化
const
field
=
Form
.
useWatch
(
'field'
,
form
)
const
checked
=
Form
.
useWatch
(
'checked'
,
form
)
const
action
=
Form
.
useWatch
(
'action'
,
form
)
const
rules
=
Form
.
useWatch
(
'rules'
,
form
)
||
[]
// 当 checked 或 data 变化时更新数据源
// 处理下一步按钮逻辑
useEffect
(()
=>
{
const
handleNext
=
async
()
=>
{
if
(
checked
&&
data
.
list
?.
length
)
{
if
(
current
===
0
)
{
const
uniqList
=
uniqBy
(
data
.
list
,
checked
)
// 第一步验证表单
setDataSource
(
await
form
.
validateFields
([
'name'
,
'english_name'
,
'field'
])
uniqList
.
map
((
item
:
any
,
index
)
=>
({
}
else
if
(
current
===
1
)
{
key
:
index
+
1
,
await
form
.
validateFields
()
raw_value
:
item
[
checked
]
||
''
,
mapping_value
:
''
,
}))
)
}
}
},
[
checked
,
data
.
list
])
setCurrent
(
current
+
1
)
// 处理映射值变化
const
handleMappingValueChange
=
(
value
:
string
,
key
:
number
)
=>
{
setDataSource
((
prevDataSource
)
=>
prevDataSource
.
map
((
item
)
=>
(
item
.
key
===
key
?
{
...
item
,
mapping_value
:
value
}
:
item
))
)
}
}
const
{
mutate
,
isPending
,
progress
,
message
}
=
useProcessData
()
// 开始处理
const
handleStart
=
()
=>
{
const
handleStart
=
()
=>
{
setStep
(
0
)
const
values
=
form
.
getFieldsValue
()
// Simulate processing steps with timeouts
const
params
=
{
...
values
,
rules
:
JSON
.
stringify
(
values
.
rules
),
action
:
'固定步长分箱'
}
setTimeout
(()
=>
{
mutate
(
params
,
{
setStep
(
1
)
onSuccess
:
handleClose
,
setTimeout
(()
=>
{
})
setStep
(
4
)
}
message
.
success
(
'数据处理完成!'
)
},
1000
)
// 关闭并重置
},
1000
)
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
}
}
const
[
groupName
,
setGroupName
]
=
useState
(
''
)
// 步骤定义
// 步骤定义
const
steps
=
[
const
steps
=
[
{
{
...
@@ -67,13 +67,13 @@ export default function ButtonModal() {
...
@@ -67,13 +67,13 @@ export default function ButtonModal() {
</
Form
.
Item
>
</
Form
.
Item
>
<
Form
.
Item
<
Form
.
Item
label=
"请选择数据分箱字段"
label=
"请选择数据分箱字段"
name=
"
checke
d"
name=
"
fiel
d"
rules=
{
[{
required
:
true
,
message
:
'请选择数据分箱字段'
}]
}
>
rules=
{
[{
required
:
true
,
message
:
'请选择数据分箱字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
field
s
.
map
((
item
)
=>
(
{
currentFieldOption
s
.
map
((
item
)
=>
(
<
Col
span=
{
8
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
8
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
english_name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
@@ -86,30 +86,86 @@ export default function ButtonModal() {
...
@@ -86,30 +86,86 @@ export default function ButtonModal() {
title
:
'配置数据分箱规则'
,
title
:
'配置数据分箱规则'
,
content
:
(
content
:
(
<>
<>
<
Form
.
Item
label=
"数据分箱操作字段"
>
{
checked
}
</
Form
.
Item
>
<
Form
.
Item
label=
"数据分箱操作字段"
>
{
getFieldName
(
field
)
}
</
Form
.
Item
>
<
Form
.
Item
>
<
Form
.
Item
name=
"action"
>
<
Table
<
Radio
.
Group
block
options=
{
[
'固定步长分箱'
,
'自定义刻度值分箱'
]
}
optionType=
"button"
buttonStyle=
"solid"
/>
bordered
pagination=
{
{
pageSize
:
10
}
}
columns=
{
[
{
title
:
'序号'
,
dataIndex
:
'key'
,
align
:
'center'
,
width
:
80
},
{
title
:
'原始值'
,
dataIndex
:
'raw_value'
,
align
:
'center'
},
{
title
:
'映射值'
,
dataIndex
:
'mapping_value'
,
align
:
'center'
,
render
:
(
_
,
record
)
=>
(
<
Input
value=
{
record
.
mapping_value
}
onChange=
{
(
e
)
=>
handleMappingValueChange
(
e
.
target
.
value
,
record
.
key
)
}
placeholder=
"请输入映射值"
/>
),
},
]
}
dataSource=
{
dataSource
}
/>
</
Form
.
Item
>
</
Form
.
Item
>
{
action
===
'固定步长分箱'
&&
(
<>
<
Form
.
Item
label=
"最小值"
>
<
Form
.
Item
name=
"min"
rules=
{
[{
required
:
true
,
message
:
'请输入最小值'
}]
}
noStyle
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
p
>
分箱的取值规则为:大于等于最小值。例如最小值为5,则为
>
=5
</
p
>
</
Form
.
Item
>
<
Form
.
Item
label=
"最大值"
>
<
Form
.
Item
name=
"max"
rules=
{
[{
required
:
true
,
message
:
'请输入最大值'
}]
}
noStyle
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
p
>
分箱的取值规则为:小于等于最大值。例如最大值为200,则为
<
=200
</
p
>
</
Form
.
Item
>
<
Form
.
Item
label=
"步长值"
>
<
Form
.
Item
name=
"step"
rules=
{
[{
required
:
true
,
message
:
'请输入步长值'
}]
}
noStyle
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
p
>
以步长为分箱。例如步长值为100,则分箱结果为:5-100(含100),100-200(不含100)
</
p
>
</
Form
.
Item
>
<
Form
.
Item
label=
"边界"
>
<
Form
.
Item
name=
"include_min"
noStyle
valuePropName=
"checked"
>
<
Checkbox
>
包含小于最小值
</
Checkbox
>
</
Form
.
Item
>
<
Form
.
Item
name=
"include_max"
noStyle
valuePropName=
"checked"
>
<
Checkbox
>
包含大于最大值
</
Checkbox
>
</
Form
.
Item
>
</
Form
.
Item
>
</>
)
}
{
action
===
'自定义刻度值分箱'
&&
(
<>
<
Form
.
List
name=
"rules"
>
{
(
fields
,
{
add
,
remove
})
=>
(
<>
<
Form
.
Item
label=
"数据分组名称"
>
<
Flex
gap=
{
10
}
align=
"center"
>
<
Input
placeholder=
"请输入"
value=
{
groupName
}
onChange=
{
(
e
)
=>
setGroupName
(
e
.
target
.
value
)
}
style=
{
{
width
:
'60%'
}
}
/>
<
Button
type=
"primary"
onClick=
{
()
=>
{
if
(
!
groupName
)
return
add
(
groupName
)
// 添加新分组
setGroupName
(
''
)
}
}
>
添加刻度
</
Button
>
</
Flex
>
</
Form
.
Item
>
{
fields
.
map
(({
key
,
name
,
...
restField
})
=>
(
<
Form
.
Item
{
...
restField
}
label=
"刻度值"
style=
{
{
flex
:
1
}
}
key=
{
key
}
>
<
Flex
gap=
{
10
}
>
<
p
style=
{
{
width
:
'60%'
}
}
>
{
rules
[
name
]
}
</
p
>
<
MinusCircleOutlined
onClick=
{
()
=>
remove
(
name
)
}
/>
</
Flex
>
</
Form
.
Item
>
))
}
</>
)
}
</
Form
.
List
>
<
Form
.
Item
label=
"边界"
>
<
Form
.
Item
name=
"include_min"
noStyle
valuePropName=
"checked"
>
<
Checkbox
>
包含小于最小值
</
Checkbox
>
</
Form
.
Item
>
<
Form
.
Item
name=
"include_max"
noStyle
valuePropName=
"checked"
>
<
Checkbox
>
包含大于最大值
</
Checkbox
>
</
Form
.
Item
>
</
Form
.
Item
>
</>
)
}
</>
</>
),
),
},
},
...
@@ -118,12 +174,12 @@ export default function ButtonModal() {
...
@@ -118,12 +174,12 @@ export default function ButtonModal() {
content
:
(
content
:
(
<>
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
loading=
{
isPending
}
>
开始处理
开始处理
</
Button
>
</
Button
>
<
AppProgressSteps
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
current=
{
progress
}
items=
{
[
items=
{
[
{
{
title
:
(
title
:
(
...
@@ -160,13 +216,7 @@ export default function ButtonModal() {
...
@@ -160,13 +216,7 @@ export default function ButtonModal() {
处理结果
处理结果
</>
</>
),
),
description
:
(
description
:
<>
{
message
[
3
]
}
</>,
<>
累计处理
{
dataSource
.
length
}
个字段
<
br
/>
累计处理
{
data
.
list
?.
length
||
0
}
条记录
</>
),
},
},
]
}
]
}
/>
/>
...
@@ -176,29 +226,6 @@ export default function ButtonModal() {
...
@@ -176,29 +226,6 @@ export default function ButtonModal() {
},
},
]
]
// 处理下一步按钮逻辑
const
handleNext
=
async
()
=>
{
try
{
if
(
current
===
0
)
{
// 第一步验证表单
await
form
.
validateFields
([
'name'
,
'english_name'
,
'checked'
])
}
setCurrent
(
current
+
1
)
}
catch
(
error
)
{
// 表单验证错误处理
console
.
error
(
'表单验证失败'
,
error
)
}
}
// 重置状态
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
setStep
(
-
1
)
form
.
resetFields
()
setDataSource
([])
}
return
(
return
(
<>
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
...
@@ -217,7 +244,7 @@ export default function ButtonModal() {
...
@@ -217,7 +244,7 @@ export default function ButtonModal() {
</
Button
>
</
Button
>
)
}
)
}
{
current
===
steps
.
length
-
1
&&
(
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleClose
}
>
<
Button
type=
"primary"
onClick=
{
handleClose
}
disabled=
{
isPending
}
>
关闭
关闭
</
Button
>
</
Button
>
)
}
)
}
...
@@ -227,7 +254,13 @@ export default function ButtonModal() {
...
@@ -227,7 +254,13 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
handleClose
}
>
onCancel=
{
handleClose
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
initialValues=
{
{
action
:
'固定步长分箱'
,
}
}
>
{
steps
.
map
((
item
,
index
)
=>
(
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
{
item
.
content
}
...
...
src/modules/data/process/binning/query.ts
0 → 100644
浏览文件 @
b5a25e0b
import
{
useMutation
,
useQueryClient
}
from
'@tanstack/react-query'
import
{
message
}
from
'antd'
import
{
processData
}
from
'./api'
import
type
{
ProcessDataParams
}
from
'./types'
import
{
useProcessProgressQuery
}
from
'@/hooks/useQuery'
// 处理数据
export
function
useProcessData
()
{
const
queryClient
=
useQueryClient
()
const
{
data
,
start
,
stop
}
=
useProcessProgressQuery
({
function_name
:
'mapping'
})
const
query
=
useMutation
({
mutationFn
:
(
data
:
ProcessDataParams
)
=>
{
start
()
return
processData
(
data
)
},
onSuccess
:
()
=>
{
stop
()
message
.
success
(
'处理完成'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
},
})
return
{
...
query
,
progress
:
data
?.
progress
??
-
1
,
message
:
data
?.
message
??
{}
}
}
src/modules/data/process/binning/types.ts
0 → 100644
浏览文件 @
b5a25e0b
export
interface
ProcessDataParams
{
name
:
string
english_name
:
string
field
:
string
rule
:
string
action
:
string
}
src/modules/data/process/date/api.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
import
type
{
ProcessDataParams
}
from
'./types'
// 数据分箱
export
function
processData
(
data
:
ProcessDataParams
)
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/processing/processing/anonymization'
,
data
)
}
src/modules/data/process/date/components/ButtonModal.tsx
0 → 100644
浏览文件 @
b5a25e0b
import
{
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Space
,
Select
}
from
'antd'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
{
useProcessData
}
from
'../query'
const
functionShortcutOptions
=
[
{
label
:
'获取“年份”信息'
,
value
:
'YEAR'
,
demo
:
'如:“2025年”'
,
},
// {
// label: '获取“季度”信息',
// value: 'YEAR',
// demo: '如:“一季度”',
// },
// {
// label: '获取“年季度”信息',
// value: 'YEAR',
// demo: '如:“2025年一季度”',
// },
{
label
:
'获取“月份”信息'
,
value
:
'MONTH'
,
demo
:
'如:“3月”'
,
},
{
label
:
'获取“年月份”信息'
,
value
:
'DATE'
,
demo
:
'如:“2025年3月”'
,
},
{
label
:
'获取“周”信息'
,
value
:
'NETWORKDAYS'
,
demo
:
'如:“12周”'
,
},
// {
// label: '获取“年周”信息',
// value: 'YEAR',
// demo: '如:“2025年12周”',
// },
{
label
:
'获取“日”信息'
,
value
:
'DAY'
,
demo
:
'如:“21日”'
,
},
{
label
:
'获取“小时”信息'
,
value
:
'HOUR'
,
demo
:
'如:“12时”'
,
},
{
label
:
'获取“分钟”信息'
,
value
:
'MINUTE'
,
demo
:
'如:“21分”'
,
},
{
label
:
'获取“秒”信息'
,
value
:
'SECOND'
,
demo
:
'如:“18秒”'
,
},
]
const
functionOptions
=
[
{
label
:
'DATE:组合年、月、日为标准日期'
,
value
:
'DATE'
},
{
label
:
'DATEDIF:计算两个日期间的年/月/日差值'
,
value
:
'DATEDIF'
},
{
label
:
'DATEVALUE:将文本日期转换为 Excel 可识别的序列号'
,
value
:
'DATEVALUE'
},
{
label
:
'DAY:提取日期中的“日”部分'
,
value
:
'DAY'
},
{
label
:
'EDATE:返回指定日期之前/之后几个月的日期'
,
value
:
'EDATE'
},
{
label
:
'EMONTH:返回指定日期之前/之后几个月的最后一天'
,
value
:
'EMONTH'
},
{
label
:
'HOUR:提取时间中的“小时”部分'
,
value
:
'HOUR'
},
{
label
:
'MINUTE:提取时间中的“分钟”部分'
,
value
:
'MINUTE'
},
{
label
:
'MONTH:提取日期中的“月”部分'
,
value
:
'MONTH'
},
{
label
:
'NETWORKDAYS:计算两个日期之间的工作日天数(排除周末和节假日)'
,
value
:
'NETWORKDAYS'
},
{
label
:
'NOW:返回当前日期和时间(精确到秒)'
,
value
:
'NOW'
},
{
label
:
'SECOND:提取时间中的“秒”部分'
,
value
:
'SECOND'
},
{
label
:
'TIME:组合时、分、秒为标准时间'
,
value
:
'TIME'
},
{
label
:
'TIMEVALUE:将文本时间转换为小数'
,
value
:
'TIMEVALUE'
},
{
label
:
'TODAY:返回当前系统日期(无参数)'
,
value
:
'TODAY'
},
{
label
:
'WEEKDAY:返回日期对应的星期几(数字形式)'
,
value
:
'WEEKDAY'
},
{
label
:
'WORKDAY:计算指定工作日天数后的日期(跳过周末和节假日)'
,
value
:
'WORKDAY'
},
{
label
:
'YEAR:提取日期中的“年”部分'
,
value
:
'YEAR'
},
]
export
default
function
ButtonModal
()
{
const
{
fieldOptions
,
getFieldName
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
action
=
Form
.
useWatch
(
'action'
,
form
)
// 处理下一步按钮逻辑
const
handleNext
=
async
()
=>
{
if
(
current
===
0
)
{
// 第一步验证表单
await
form
.
validateFields
([
'name'
,
'english_name'
])
}
else
if
(
current
===
1
)
{
await
form
.
validateFields
()
}
setCurrent
(
current
+
1
)
}
const
{
mutate
,
isPending
,
progress
,
message
}
=
useProcessData
()
// 开始处理
const
handleStart
=
()
=>
{
const
values
=
form
.
getFieldsValue
()
const
params
=
{
...
values
,
rules
:
JSON
.
stringify
(
values
.
rules
),
action
:
'固定步长分箱'
}
mutate
(
params
,
{
onSuccess
:
handleClose
,
})
}
// 关闭并重置
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
}
// 步骤定义
const
steps
=
[
{
title
:
'请选择日期计算字段'
,
content
:
(
<>
<
Form
.
Item
label=
"日期计算字段名称"
name=
"name"
rules=
{
[{
required
:
true
,
message
:
'请输入字段名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"日期计算字段英文名称"
name=
"english_name"
rules=
{
[{
required
:
true
,
message
:
'请输入英文名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</>
),
},
{
title
:
'配置日期计算规则'
,
content
:
(
<>
<
Form
.
Item
label=
"请选择日期计算方法"
name=
"action"
>
<
Radio
.
Group
options=
{
[
'快速日期计算'
,
'日期函数计算'
]
}
/>
</
Form
.
Item
>
{
action
===
'快速日期计算'
&&
(
<>
<
Form
.
Item
label=
"请选择快速日期计算方法"
name=
"function"
>
<
Radio
.
Group
style=
{
{
width
:
'100%'
}
}
>
{
functionShortcutOptions
.
map
((
item
)
=>
(
<
Flex
>
<
Radio
value=
{
item
.
value
}
>
<
Space
key=
{
item
.
value
}
>
<
p
style=
{
{
minWidth
:
200
}
}
>
{
item
.
label
}
</
p
>
<
p
style=
{
{
color
:
'#999'
}
}
>
{
item
.
demo
}
</
p
>
</
Space
>
</
Radio
>
</
Flex
>
))
}
</
Radio
.
Group
>
</
Form
.
Item
>
</>
)
}
{
action
===
'日期函数计算'
&&
(
<>
<
Form
.
Item
label=
"请选择函数"
name=
"function"
>
<
Select
options=
{
functionOptions
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请输入函数公式"
>
<
Flex
gap=
{
10
}
>
<
Form
.
Item
name=
"content"
noStyle
>
<
Input
.
TextArea
rows=
{
4
}
/>
</
Form
.
Item
>
<
Button
type=
"primary"
style=
{
{
height
:
100
}
}
>
添加字段
</
Button
>
</
Flex
>
</
Form
.
Item
>
</>
)
}
</>
),
},
{
title
:
'处理执行'
,
content
:
(
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
loading=
{
isPending
}
>
开始处理
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
progress
}
items=
{
[
{
title
:
(
<>
第一步
<
br
/>
新建字段
</>
),
},
{
title
:
(
<>
第二步
<
br
/>
复制数据
</>
),
},
{
title
:
(
<>
第三步
<
br
/>
日期计算处理
</>
),
},
{
title
:
(
<>
第四步
<
br
/>
处理结果
</>
),
description
:
<>
{
message
[
3
]
}
</>,
},
]
}
/>
</
Flex
>
</>
),
},
]
return
(
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
日期计算
</
Button
>
<
Modal
title=
{
steps
[
current
]?.
title
}
open=
{
open
}
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
1
&&
action
===
'日期函数计算'
&&
<
Button
type=
"primary"
>
AI智能建议
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleNext
}
>
下一步
</
Button
>
)
}
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleClose
}
disabled=
{
isPending
}
>
关闭
</
Button
>
)
}
</
Flex
>
}
destroyOnClose
width=
{
800
}
onCancel=
{
handleClose
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
initialValues=
{
{
action
:
'快速日期计算'
}
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
Modal
>
</>
)
}
src/modules/data/process/date/query.ts
0 → 100644
浏览文件 @
b5a25e0b
import
{
useMutation
,
useQueryClient
}
from
'@tanstack/react-query'
import
{
message
}
from
'antd'
import
{
processData
}
from
'./api'
import
type
{
ProcessDataParams
}
from
'./types'
import
{
useProcessProgressQuery
}
from
'@/hooks/useQuery'
// 处理数据
export
function
useProcessData
()
{
const
queryClient
=
useQueryClient
()
const
{
data
,
start
,
stop
}
=
useProcessProgressQuery
({
function_name
:
'anonymization'
})
const
query
=
useMutation
({
mutationFn
:
(
data
:
ProcessDataParams
)
=>
{
start
()
return
processData
(
data
)
},
onSuccess
:
()
=>
{
stop
()
message
.
success
(
'处理完成'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
},
})
return
{
...
query
,
progress
:
data
?.
progress
??
-
1
,
message
:
data
?.
message
??
{}
}
}
src/modules/data/process/date/types.ts
0 → 100644
浏览文件 @
b5a25e0b
export
interface
ProcessDataParams
{
name
:
string
english_name
:
string
field
:
string
action
:
string
function
:
string
char
?:
string
sm_fun
?:
string
start
?:
string
end
?:
string
}
src/modules/data/process/date/views/Index.tsx
浏览文件 @
b5a25e0b
import
{
lazy
}
from
'react'
import
DataWrap
from
'@/components/data/DataWrap'
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
const
ButtonModal
=
lazy
(()
=>
import
(
'../components/ButtonModal'
))
export
default
function
DataProcess
()
{
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:日期计算"
buttons=
{
<
Button
type=
"primary"
>
日期计算
</
Button
>
}
></
DataWrap
>
return
<
DataWrap
title=
"数据加工:日期计算"
buttons=
{
<
Button
Modal
/
>
}
></
DataWrap
>
}
}
src/modules/data/process/desensitization/api.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
import
type
{
ProcessDataParams
}
from
'./types'
// 数据分箱
export
function
processData
(
data
:
ProcessDataParams
)
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/processing/processing/anonymization'
,
data
)
}
src/modules/data/process/desensitization/components/ButtonModal.tsx
0 → 100644
浏览文件 @
b5a25e0b
import
{
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
}
from
'antd'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
{
useProcessData
}
from
'../query'
export
default
function
ButtonModal
()
{
const
{
fieldOptions
,
getFieldName
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
field
=
Form
.
useWatch
(
'field'
,
form
)
const
action
=
Form
.
useWatch
(
'action'
,
form
)
const
formFunction
=
Form
.
useWatch
(
'function'
,
form
)
const
formSmFun
=
Form
.
useWatch
(
'sm_fun'
,
form
)
// 处理下一步按钮逻辑
const
handleNext
=
async
()
=>
{
if
(
current
===
0
)
{
// 第一步验证表单
await
form
.
validateFields
([
'name'
,
'english_name'
,
'field'
])
}
else
if
(
current
===
1
)
{
await
form
.
validateFields
()
}
setCurrent
(
current
+
1
)
}
const
{
mutate
,
isPending
,
progress
,
message
}
=
useProcessData
()
// 开始处理
const
handleStart
=
()
=>
{
const
values
=
form
.
getFieldsValue
()
const
params
=
{
...
values
,
rules
:
JSON
.
stringify
(
values
.
rules
),
action
:
'固定步长分箱'
}
mutate
(
params
,
{
onSuccess
:
handleClose
,
})
}
// 关闭并重置
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
}
// 步骤定义
const
steps
=
[
{
title
:
'请选择数据脱敏字段'
,
content
:
(
<>
<
Form
.
Item
label=
"数据脱敏字段名称"
name=
"name"
rules=
{
[{
required
:
true
,
message
:
'请输入字段名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"数据脱敏字段英文名称"
name=
"english_name"
rules=
{
[{
required
:
true
,
message
:
'请输入英文名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择数据脱敏字段"
name=
"field"
rules=
{
[{
required
:
true
,
message
:
'请选择数据脱敏字段'
}]
}
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fieldOptions
.
map
((
item
)
=>
(
<
Col
span=
{
8
}
key=
{
item
.
value
}
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
))
}
</
Row
>
</
Radio
.
Group
>
</
Form
.
Item
>
</>
),
},
{
title
:
'配置数据脱敏规则'
,
content
:
(
<>
<
Form
.
Item
label=
"数据脱敏操作字段"
>
{
getFieldName
(
field
)
}
</
Form
.
Item
>
<
Form
.
Item
name=
"action"
>
<
Radio
.
Group
block
options=
{
[
'基础脱敏方法'
,
'高级脱敏方法'
,
'特殊脱敏方法'
]
}
optionType=
"button"
buttonStyle=
"solid"
/>
</
Form
.
Item
>
{
action
===
'基础脱敏方法'
&&
(
<>
<
Form
.
Item
label=
"请选择脱敏方法"
name=
"function"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'固定遮蔽'
,
'动态遮蔽'
,
'内容替换'
,
'内容模糊'
]
}
/>
</
Form
.
Item
>
{
formFunction
===
'固定遮蔽'
&&
(
<>
<
Form
.
Item
label=
"请输入遮蔽符号"
name=
"char"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入用于替换的固定符号,如:*、X等"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择遮蔽范围"
name=
"sm_fun"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'部分遮蔽'
,
'全部遮蔽'
]
}
/>
</
Form
.
Item
>
{
formSmFun
===
'部分遮蔽'
&&
(
<>
<
Form
.
Item
label=
"请输入开始位数"
name=
"start"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请输入结束位数"
name=
"end"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</>
)
}
</>
)
}
{
formFunction
===
'动态遮蔽'
&&
(
<>
<
Form
.
Item
label=
"请输入遮蔽符号"
name=
"char"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入用于替换的固定符号,如:*、X等"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请输入开始动态位数"
name=
"start"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请输入结束动态位数"
name=
"end"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</>
)
}
{
formFunction
===
'内容替换'
&&
(
<>
<
Form
.
Item
label=
"请输入替换内容"
name=
"char"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</>
)
}
{
formFunction
===
'内容模糊'
&&
(
<>
<
Form
.
Item
label=
"请输入模糊内容"
name=
"char"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</>
)
}
</>
)
}
{
action
===
'高级脱敏方法'
&&
(
<>
<
Form
.
Item
label=
"请选择脱敏方法"
name=
"function"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'伪名化'
,
'数据扰动'
,
'空值化'
,
'数据组合'
]
}
/>
</
Form
.
Item
>
{
formFunction
===
'伪名化'
&&
(
<>
<
Form
.
Item
label=
"请选择伪名化方法"
name=
"sm_fun"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'AI智能'
]
}
/>
</
Form
.
Item
>
</>
)
}
{
formFunction
===
'数据扰动'
&&
(
<>
<
Form
.
Item
label=
"请选择伪名化方法"
name=
"sm_fun"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'AI智能'
]
}
/>
</
Form
.
Item
>
</>
)
}
{
formFunction
===
'数据组合'
&&
(
<>
<
Form
.
Item
label=
"请选择数据组合方法"
name=
"sm_fun"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'添加前缀'
,
'添加后缀'
]
}
/>
</
Form
.
Item
>
<
Form
.
Item
name=
"char"
rules=
{
[{
required
:
true
,
message
:
'请输入'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</>
)
}
</>
)
}
{
action
===
'特殊脱敏方法'
&&
(
<>
<
Form
.
Item
label=
"请选择脱敏方法"
name=
"function"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'数据加密'
]
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择数据加密方法"
name=
"sm_fun"
rules=
{
[{
required
:
true
,
message
:
'请选择'
}]
}
>
<
Radio
.
Group
options=
{
[
'AES'
,
'RSA'
]
}
/>
</
Form
.
Item
>
</>
)
}
</>
),
},
{
title
:
'处理执行'
,
content
:
(
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
loading=
{
isPending
}
>
开始处理
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
progress
}
items=
{
[
{
title
:
(
<>
第一步
<
br
/>
新建字段
</>
),
},
{
title
:
(
<>
第二步
<
br
/>
复制数据
</>
),
},
{
title
:
(
<>
第三步
<
br
/>
数据脱敏处理
</>
),
},
{
title
:
(
<>
第四步
<
br
/>
处理结果
</>
),
description
:
<>
{
message
[
3
]
}
</>,
},
]
}
/>
</
Flex
>
</>
),
},
]
return
(
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
数据脱敏
</
Button
>
<
Modal
title=
{
steps
[
current
]?.
title
}
open=
{
open
}
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
1
&&
<
Button
type=
"primary"
>
AI智能建议
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleNext
}
>
下一步
</
Button
>
)
}
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleClose
}
disabled=
{
isPending
}
>
关闭
</
Button
>
)
}
</
Flex
>
}
destroyOnClose
width=
{
800
}
onCancel=
{
handleClose
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
initialValues=
{
{
action
:
'基础脱敏方法'
}
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
Modal
>
</>
)
}
src/modules/data/process/desensitization/query.ts
0 → 100644
浏览文件 @
b5a25e0b
import
{
useMutation
,
useQueryClient
}
from
'@tanstack/react-query'
import
{
message
}
from
'antd'
import
{
processData
}
from
'./api'
import
type
{
ProcessDataParams
}
from
'./types'
import
{
useProcessProgressQuery
}
from
'@/hooks/useQuery'
// 处理数据
export
function
useProcessData
()
{
const
queryClient
=
useQueryClient
()
const
{
data
,
start
,
stop
}
=
useProcessProgressQuery
({
function_name
:
'anonymization'
})
const
query
=
useMutation
({
mutationFn
:
(
data
:
ProcessDataParams
)
=>
{
start
()
return
processData
(
data
)
},
onSuccess
:
()
=>
{
stop
()
message
.
success
(
'处理完成'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
},
})
return
{
...
query
,
progress
:
data
?.
progress
??
-
1
,
message
:
data
?.
message
??
{}
}
}
src/modules/data/process/desensitization/types.ts
0 → 100644
浏览文件 @
b5a25e0b
export
interface
ProcessDataParams
{
name
:
string
english_name
:
string
field
:
string
action
:
string
function
:
string
char
?:
string
sm_fun
?:
string
start
?:
string
end
?:
string
}
src/modules/data/process/desensitization/views/Index.tsx
浏览文件 @
b5a25e0b
import
{
lazy
}
from
'react'
import
DataWrap
from
'@/components/data/DataWrap'
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
const
ButtonModal
=
lazy
(()
=>
import
(
'../components/ButtonModal'
))
export
default
function
DataProcess
()
{
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:数据脱敏"
buttons=
{
<
Button
type=
"primary"
>
数据脱敏
</
Button
>
}
></
DataWrap
>
return
<
DataWrap
title=
"数据加工:数据脱敏"
buttons=
{
<
Button
Modal
/
>
}
></
DataWrap
>
}
}
src/modules/data/process/group/api.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
import
type
{
ProcessDataParams
}
from
'./types'
// 数据分箱
export
function
processData
(
data
:
ProcessDataParams
)
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/processing/processing/grouping'
,
data
)
}
src/modules/data/process/group/components/ButtonModal.tsx
0 → 100644
浏览文件 @
b5a25e0b
import
{
useEffect
,
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Select
}
from
'antd'
import
{
useDataQuery
,
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
{
useProcessData
}
from
'../query'
import
{
MinusCircleOutlined
}
from
'@ant-design/icons'
import
{
uniqBy
}
from
'lodash-es'
export
default
function
ButtonModal
()
{
const
{
data
=
{
list
:
[]
}
}
=
useDataQuery
()
const
{
fieldOptions
,
getFieldName
}
=
useDataFieldQuery
()
// 数字类型字段
const
currentFieldOptions
=
fieldOptions
.
filter
((
item
)
=>
item
.
type
.
includes
(
'VARCHAR'
))
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
[
dataSource
,
setDataSource
]
=
useState
<
{
key
:
number
;
label
:
string
;
value
:
string
}[]
>
([])
const
field
=
Form
.
useWatch
(
'field'
,
form
)
const
rules
=
Form
.
useWatch
(
'rules'
,
form
)
||
[]
useEffect
(()
=>
{
if
(
field
&&
data
.
list
?.
length
)
{
const
uniqList
=
uniqBy
(
data
.
list
,
field
)
setDataSource
(
uniqList
.
map
((
item
:
any
,
index
)
=>
({
key
:
index
+
1
,
label
:
item
[
field
]
||
''
,
value
:
item
[
field
]
||
''
,
}))
)
}
},
[
field
,
data
.
list
])
// 处理下一步按钮逻辑
const
handleNext
=
async
()
=>
{
if
(
current
===
0
)
{
// 第一步验证表单
await
form
.
validateFields
([
'name'
,
'english_name'
,
'field'
])
}
else
if
(
current
===
1
)
{
await
form
.
validateFields
()
}
setCurrent
(
current
+
1
)
}
const
{
mutate
,
isPending
,
progress
,
message
}
=
useProcessData
()
// 开始处理
const
handleStart
=
()
=>
{
const
values
=
form
.
getFieldsValue
()
const
params
=
{
...
values
,
rules
:
JSON
.
stringify
(
values
.
rules
.
map
((
item
:
any
)
=>
{
return
{
...
item
,
fields
:
item
.
fields
.
join
(
','
),
}
})
),
}
mutate
(
params
,
{
onSuccess
:
handleClose
,
})
}
// 关闭并重置
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
}
const
[
groupName
,
setGroupName
]
=
useState
(
''
)
// 步骤定义
const
steps
=
[
{
title
:
'请选择数据分组字段'
,
content
:
(
<>
<
Form
.
Item
label=
"数据分组字段名称"
name=
"name"
rules=
{
[{
required
:
true
,
message
:
'请输入字段名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"数据分组字段英文名称"
name=
"english_name"
rules=
{
[{
required
:
true
,
message
:
'请输入英文名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择数据分组字段"
name=
"field"
rules=
{
[{
required
:
true
,
message
:
'请选择数据分组字段'
}]
}
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
currentFieldOptions
.
map
((
item
)
=>
(
<
Col
span=
{
8
}
key=
{
item
.
value
}
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
))
}
</
Row
>
</
Radio
.
Group
>
</
Form
.
Item
>
</>
),
},
{
title
:
'配置数据分组规则'
,
content
:
(
<>
<
Form
.
Item
label=
"数据分组操作字段"
>
{
getFieldName
(
field
)
}
</
Form
.
Item
>
<
Form
.
List
name=
"rules"
>
{
(
fields
,
{
add
,
remove
})
=>
(
<>
<
Form
.
Item
label=
"数据分组名称"
>
<
Flex
gap=
{
10
}
align=
"center"
>
<
Input
placeholder=
"请输入"
value=
{
groupName
}
onChange=
{
(
e
)
=>
setGroupName
(
e
.
target
.
value
)
}
style=
{
{
width
:
'60%'
}
}
/>
<
Button
type=
"primary"
onClick=
{
()
=>
{
if
(
!
groupName
)
return
add
({
name
:
groupName
,
fields
:
[]
})
// 添加新分组
setGroupName
(
''
)
}
}
>
添加分组
</
Button
>
</
Flex
>
</
Form
.
Item
>
{
fields
.
map
(({
key
,
name
,
...
restField
})
=>
(
<
Form
.
Item
{
...
restField
}
label=
{
rules
[
name
]?.
name
}
style=
{
{
flex
:
1
}
}
key=
{
key
}
>
<
Flex
gap=
{
10
}
>
<
Form
.
Item
name=
{
[
name
,
'fields'
]
}
noStyle
>
<
Select
options=
{
dataSource
}
mode=
"multiple"
style=
{
{
width
:
'60%'
}
}
/>
</
Form
.
Item
>
<
MinusCircleOutlined
onClick=
{
()
=>
remove
(
name
)
}
/>
</
Flex
>
</
Form
.
Item
>
))
}
</>
)
}
</
Form
.
List
>
</>
),
},
{
title
:
'处理执行'
,
content
:
(
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
loading=
{
isPending
}
>
开始处理
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
progress
}
items=
{
[
{
title
:
(
<>
第一步
<
br
/>
新建字段
</>
),
},
{
title
:
(
<>
第二步
<
br
/>
复制数据
</>
),
},
{
title
:
(
<>
第三步
<
br
/>
数据分组处理
</>
),
},
{
title
:
(
<>
第四步
<
br
/>
处理结果
</>
),
description
:
<>
{
message
[
3
]
}
</>,
},
]
}
/>
</
Flex
>
</>
),
},
]
return
(
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
数据分组
</
Button
>
<
Modal
title=
{
steps
[
current
]?.
title
}
open=
{
open
}
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
1
&&
<
Button
type=
"primary"
>
AI智能建议
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleNext
}
>
下一步
</
Button
>
)
}
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleClose
}
disabled=
{
isPending
}
>
关闭
</
Button
>
)
}
</
Flex
>
}
destroyOnClose
width=
{
800
}
onCancel=
{
handleClose
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
Modal
>
</>
)
}
src/modules/data/process/group/query.ts
0 → 100644
浏览文件 @
b5a25e0b
import
{
useMutation
,
useQueryClient
}
from
'@tanstack/react-query'
import
{
message
}
from
'antd'
import
{
processData
}
from
'./api'
import
type
{
ProcessDataParams
}
from
'./types'
import
{
useProcessProgressQuery
}
from
'@/hooks/useQuery'
// 处理数据
export
function
useProcessData
()
{
const
queryClient
=
useQueryClient
()
const
{
data
,
start
,
stop
}
=
useProcessProgressQuery
({
function_name
:
'grouping'
})
const
query
=
useMutation
({
mutationFn
:
(
data
:
ProcessDataParams
)
=>
{
start
()
return
processData
(
data
)
},
onSuccess
:
()
=>
{
stop
()
message
.
success
(
'处理完成'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
},
})
return
{
...
query
,
progress
:
data
?.
progress
??
-
1
,
message
:
data
?.
message
??
{}
}
}
src/modules/data/process/group/types.ts
0 → 100644
浏览文件 @
b5a25e0b
export
interface
ProcessDataParams
{
name
:
string
english_name
:
string
field
:
string
rules
:
string
}
src/modules/data/process/group/views/Index.tsx
浏览文件 @
b5a25e0b
import
{
lazy
}
from
'react'
import
DataWrap
from
'@/components/data/DataWrap'
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
const
ButtonModal
=
lazy
(()
=>
import
(
'../components/ButtonModal'
))
export
default
function
DataProcess
()
{
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:数据分组"
buttons=
{
<
Button
type=
"primary"
>
数据分组
</
Button
>
}
></
DataWrap
>
return
<
DataWrap
title=
"数据加工:数据分组"
buttons=
{
<
Button
Modal
/
>
}
></
DataWrap
>
}
}
src/modules/data/process/mapping/api.ts
0 → 100644
浏览文件 @
b5a25e0b
import
httpRequest
from
'@/utils/axios'
import
type
{
ProcessDataParams
}
from
'./types'
// 值映射
export
function
processData
(
data
:
ProcessDataParams
)
{
return
httpRequest
.
post
(
'/api/resource/bi/v1/processing/processing/mapping'
,
data
)
}
src/modules/data/process/mapping/components/ButtonModal.tsx
浏览文件 @
b5a25e0b
import
{
useEffect
,
useState
}
from
'react'
import
{
useEffect
,
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Table
,
message
}
from
'antd'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Table
}
from
'antd'
import
{
useDataQuery
,
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
{
useDataQuery
,
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
import
{
uniqBy
}
from
'lodash-es'
import
{
uniqBy
}
from
'lodash-es'
import
{
useProcessData
}
from
'../query'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
{
data
=
{
list
:
[]
}
}
=
useDataQuery
()
// 添加默认值防止 data 为 undefined
const
{
data
=
{
list
:
[]
}
}
=
useDataQuery
()
const
{
data
:
fields
=
[]
}
=
useDataFieldQuery
()
const
{
fieldOptions
,
getFieldName
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
[
form
]
=
Form
.
useForm
()
const
[
dataSource
,
setDataSource
]
=
useState
<
{
key
:
number
;
raw_value
:
string
;
mapping_value
:
string
}[]
>
([])
const
[
dataSource
,
setDataSource
]
=
useState
<
{
key
:
number
;
raw_value
:
string
;
new_value
:
string
}[]
>
([])
const
[
step
,
setStep
]
=
useState
(
-
1
)
// 使用 Form.useWatch 监听表单值变化
const
field
=
Form
.
useWatch
(
'field'
,
form
)
const
checked
=
Form
.
useWatch
(
'checked'
,
form
)
// 当 checked 或 data 变化时更新数据源
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
checke
d
&&
data
.
list
?.
length
)
{
if
(
fiel
d
&&
data
.
list
?.
length
)
{
const
uniqList
=
uniqBy
(
data
.
list
,
checke
d
)
const
uniqList
=
uniqBy
(
data
.
list
,
fiel
d
)
setDataSource
(
setDataSource
(
uniqList
.
map
((
item
:
any
,
index
)
=>
({
uniqList
.
map
((
item
:
any
,
index
)
=>
({
key
:
index
+
1
,
key
:
index
+
1
,
raw_value
:
item
[
checke
d
]
||
''
,
raw_value
:
item
[
fiel
d
]
||
''
,
mapping
_value
:
''
,
new
_value
:
''
,
}))
}))
)
)
}
}
},
[
checke
d
,
data
.
list
])
},
[
fiel
d
,
data
.
list
])
// 处理映射值变化
// 处理映射值变化
const
handle
Mapping
ValueChange
=
(
value
:
string
,
key
:
number
)
=>
{
const
handleValueChange
=
(
value
:
string
,
key
:
number
)
=>
{
setDataSource
((
prevDataSource
)
=>
setDataSource
((
prevDataSource
)
=>
prevDataSource
.
map
((
item
)
=>
(
item
.
key
===
key
?
{
...
item
,
mapping
_value
:
value
}
:
item
))
prevDataSource
.
map
((
item
)
=>
(
item
.
key
===
key
?
{
...
item
,
new
_value
:
value
}
:
item
))
)
)
}
}
// 处理下一步按钮逻辑
const
handleNext
=
async
()
=>
{
if
(
current
===
0
)
{
// 第一步验证表单
await
form
.
validateFields
([
'name'
,
'english_name'
,
'field'
])
}
setCurrent
(
current
+
1
)
}
const
{
mutate
,
isPending
,
progress
,
message
}
=
useProcessData
()
// 开始处理
const
handleStart
=
()
=>
{
const
handleStart
=
()
=>
{
setStep
(
0
)
const
values
=
form
.
getFieldsValue
()
// Simulate processing steps with timeouts
const
rule
=
dataSource
.
reduce
((
result
,
item
)
=>
{
setTimeout
(()
=>
{
return
{
...
result
,
[
item
.
raw_value
]:
item
.
new_value
}
setStep
(
1
)
},
{})
setTimeout
(()
=>
{
const
params
=
{
...
values
,
rule
:
JSON
.
stringify
(
rule
)
}
setStep
(
4
)
mutate
(
params
,
{
message
.
success
(
'数据处理完成!'
)
onSuccess
:
handleClose
,
},
1000
)
})
},
1000
)
}
// 关闭并重置
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
}
}
// 步骤定义
// 步骤定义
...
@@ -65,12 +80,12 @@ export default function ButtonModal() {
...
@@ -65,12 +80,12 @@ export default function ButtonModal() {
rules=
{
[{
required
:
true
,
message
:
'请输入英文名称'
}]
}
>
rules=
{
[{
required
:
true
,
message
:
'请输入英文名称'
}]
}
>
<
Input
placeholder=
"请输入"
/>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择值映射字段"
name=
"
checke
d"
rules=
{
[{
required
:
true
,
message
:
'请选择值映射字段'
}]
}
>
<
Form
.
Item
label=
"请选择值映射字段"
name=
"
fiel
d"
rules=
{
[{
required
:
true
,
message
:
'请选择值映射字段'
}]
}
>
<
Radio
.
Group
>
<
Radio
.
Group
>
<
Row
gutter=
{
[
10
,
10
]
}
>
<
Row
gutter=
{
[
10
,
10
]
}
>
{
fields
.
map
((
item
)
=>
(
{
field
Option
s
.
map
((
item
)
=>
(
<
Col
span=
{
8
}
key=
{
item
.
english_nam
e
}
>
<
Col
span=
{
8
}
key=
{
item
.
valu
e
}
>
<
Radio
value=
{
item
.
english_name
}
>
{
item
.
name
}
</
Radio
>
<
Radio
value=
{
item
.
value
}
>
{
item
.
label
}
</
Radio
>
</
Col
>
</
Col
>
))
}
))
}
</
Row
>
</
Row
>
...
@@ -83,7 +98,7 @@ export default function ButtonModal() {
...
@@ -83,7 +98,7 @@ export default function ButtonModal() {
title
:
'配置值映射规则'
,
title
:
'配置值映射规则'
,
content
:
(
content
:
(
<>
<>
<
Form
.
Item
label=
"值映射操作字段"
>
{
checked
}
</
Form
.
Item
>
<
Form
.
Item
label=
"值映射操作字段"
>
{
getFieldName
(
field
)
}
</
Form
.
Item
>
<
Form
.
Item
>
<
Form
.
Item
>
<
Table
<
Table
bordered
bordered
...
@@ -93,12 +108,12 @@ export default function ButtonModal() {
...
@@ -93,12 +108,12 @@ export default function ButtonModal() {
{
title
:
'原始值'
,
dataIndex
:
'raw_value'
,
align
:
'center'
},
{
title
:
'原始值'
,
dataIndex
:
'raw_value'
,
align
:
'center'
},
{
{
title
:
'映射值'
,
title
:
'映射值'
,
dataIndex
:
'
mapping
_value'
,
dataIndex
:
'
new
_value'
,
align
:
'center'
,
align
:
'center'
,
render
:
(
_
,
record
)
=>
(
render
:
(
_
,
record
)
=>
(
<
Input
<
Input
value=
{
record
.
mapping
_value
}
value=
{
record
.
new
_value
}
onChange=
{
(
e
)
=>
handle
Mapping
ValueChange
(
e
.
target
.
value
,
record
.
key
)
}
onChange=
{
(
e
)
=>
handleValueChange
(
e
.
target
.
value
,
record
.
key
)
}
placeholder=
"请输入映射值"
placeholder=
"请输入映射值"
/>
/>
),
),
...
@@ -115,12 +130,12 @@ export default function ButtonModal() {
...
@@ -115,12 +130,12 @@ export default function ButtonModal() {
content
:
(
content
:
(
<>
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
disabled=
{
step
>=
0
}
>
<
Button
type=
"primary"
onClick=
{
handleStart
}
loading=
{
isPending
}
>
开始处理
开始处理
</
Button
>
</
Button
>
<
AppProgressSteps
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
current=
{
progress
}
items=
{
[
items=
{
[
{
{
title
:
(
title
:
(
...
@@ -157,13 +172,7 @@ export default function ButtonModal() {
...
@@ -157,13 +172,7 @@ export default function ButtonModal() {
处理结果
处理结果
</>
</>
),
),
description
:
(
description
:
<>
{
message
[
3
]
}
</>,
<>
累计处理
{
dataSource
.
length
}
个字段
<
br
/>
累计处理
{
data
.
list
?.
length
||
0
}
条记录
</>
),
},
},
]
}
]
}
/>
/>
...
@@ -173,29 +182,6 @@ export default function ButtonModal() {
...
@@ -173,29 +182,6 @@ export default function ButtonModal() {
},
},
]
]
// 处理下一步按钮逻辑
const
handleNext
=
async
()
=>
{
try
{
if
(
current
===
0
)
{
// 第一步验证表单
await
form
.
validateFields
([
'name'
,
'english_name'
,
'checked'
])
}
setCurrent
(
current
+
1
)
}
catch
(
error
)
{
// 表单验证错误处理
console
.
error
(
'表单验证失败'
,
error
)
}
}
// 重置状态
const
handleClose
=
()
=>
{
setOpen
(
false
)
setCurrent
(
0
)
setStep
(
-
1
)
form
.
resetFields
()
setDataSource
([])
}
return
(
return
(
<>
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
...
@@ -214,7 +200,7 @@ export default function ButtonModal() {
...
@@ -214,7 +200,7 @@ export default function ButtonModal() {
</
Button
>
</
Button
>
)
}
)
}
{
current
===
steps
.
length
-
1
&&
(
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
handleClose
}
>
<
Button
type=
"primary"
onClick=
{
handleClose
}
disabled=
{
isPending
}
>
关闭
关闭
</
Button
>
</
Button
>
)
}
)
}
...
...
src/modules/data/process/mapping/query.ts
0 → 100644
浏览文件 @
b5a25e0b
import
{
useMutation
,
useQueryClient
}
from
'@tanstack/react-query'
import
{
message
}
from
'antd'
import
{
processData
}
from
'./api'
import
type
{
ProcessDataParams
}
from
'./types'
import
{
useProcessProgressQuery
}
from
'@/hooks/useQuery'
// 处理数据
export
function
useProcessData
()
{
const
queryClient
=
useQueryClient
()
const
{
data
,
start
,
stop
}
=
useProcessProgressQuery
({
function_name
:
'mapping'
})
const
query
=
useMutation
({
mutationFn
:
(
data
:
ProcessDataParams
)
=>
{
start
()
return
processData
(
data
)
},
onSuccess
:
()
=>
{
stop
()
message
.
success
(
'处理完成'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
},
})
return
{
...
query
,
progress
:
data
?.
progress
??
-
1
,
message
:
data
?.
message
??
{}
}
}
src/modules/data/process/mapping/types.ts
0 → 100644
浏览文件 @
b5a25e0b
export
interface
ProcessDataParams
{
name
:
string
english_name
:
string
field
:
string
rule
:
string
}
src/utils/axios.ts
浏览文件 @
b5a25e0b
...
@@ -47,13 +47,13 @@ axiosInstance.interceptors.response.use(
...
@@ -47,13 +47,13 @@ axiosInstance.interceptors.response.use(
},
},
(
error
)
=>
{
(
error
)
=>
{
if
(
error
.
response
)
{
if
(
error
.
response
)
{
const
{
status
,
message
}
=
error
.
response
.
data
const
{
status
,
message
:
errorMessage
}
=
error
.
response
.
data
// 未登录
// 未登录
if
(
status
===
403
)
{
if
(
status
===
403
)
{
location
.
href
=
`
${
import
.
meta
.
env
.
VITE_LOGIN_URL
}
?rd=
${
encodeURIComponent
(
location
.
href
)}
`
location
.
href
=
`
${
import
.
meta
.
env
.
VITE_LOGIN_URL
}
?rd=
${
encodeURIComponent
(
location
.
href
)}
`
}
else
{
}
else
{
message
.
error
(
m
essage
||
error
.
message
)
message
.
error
(
errorM
essage
||
error
.
message
)
console
.
error
(
`
${
status
}
:
${
m
essage
}
`
)
console
.
error
(
`
${
status
}
:
${
errorM
essage
}
`
)
}
}
}
else
{
}
else
{
console
.
error
(
error
)
console
.
error
(
error
)
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论