feat: config模块新增列表、表单配置项,统一设置筛选&序号左侧固定、两种尺寸弹框表单;

develop
zhoux 1 year ago
parent a2d9e3c3f5
commit 60228f360b

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-09 14:10:27
* @LastEditTime: 2023-11-13 13:12:38
* @FilePath: \general-ai-platform-web\README.md
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
@ -45,7 +45,11 @@
3. 列表action有多个按钮显示更多
暂时使用默认超过3个显示更多如需统一处理或者权限控制下的按钮显示隐藏导致的按钮数量不一致可根据需要独立封装TableActionComp
4. 列表多选悬浮展示在底部,顶部隐藏处理 【待处理】
4. 列表多选固定在顶部
使用表格内容固定高度,溢出垂直方向可滚动
5. 列表可选时,首列需要固定
新增首列index栏位设置{fixed: 'left'}可实现固定
## ProTable 固定列表
@ -70,6 +74,6 @@ chore: 对构建过程或辅助工具和库(如文档)的更改(无法确
### TODO bug汇总
### bug汇总
* 新增路由页面,默认该角色拥有查看权限,实际配置并没有(重新配置权限,又能正常访问该新增页面)

@ -0,0 +1,17 @@
// 通用表单配置
export const proFormCommonOptions: Record<string,any> = {
}
// normal 804
export const proFormModelWidth: number = 804;
export const proFormItemStyleProps: Record<string, any> = {
width: proFormModelWidth - 30,
};
// max 968
export const proFormMaxModelWidth: number = 968;
export const proFormMaxItemStyleProps: Record<string, any> = {
width: proFormMaxModelWidth - 30,
};

@ -0,0 +1,21 @@
import { ProColumns } from "@ant-design/pro-components";
// 通用列表配置
export const proTableCommonOptions: Record<string,any> = {
scrollX: 'max-content', // 保证左右侧列的固定,并能保证没列标题不换行
scrollY: 500, // 保证列表高度固定
commscrollX: 1300,
searchLabelWidth: 'auto', // 整体对齐label根据实际字数自适应
}
// 默认索引列配置
export const proTableIndexColumnOptions : ProColumns = {
title: '序号',
dataIndex: 'index',
valueType: 'indexBorder', // 增加该属性以添加边框
fixed: 'left', // 将该列固定在左侧
width: 70,
align:'center'
}

@ -0,0 +1,15 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-13 15:05:27
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-13 15:05:35
* @FilePath: \general-ai-platform-web\src\components\OperateConfirm\delete.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// TODO 统一设置确实删除弹框,抛出确认的方法参数供业务层使用
// const DeleteConfirm

@ -61,6 +61,10 @@ ol {
border-block-end: none;
}
/* 1108 update 全局样式新增调整 */
.gn .ant-pro-checkcard-content {
padding-inline: 0;
padding-block: 0;
}
.ant-table-cell .ant-btn.ant-btn-sm {
padding: 0;
}
@ -75,6 +79,9 @@ ol {
font-weight: 700;
font-size: 16px;
}
.ant-modal .ant-modal-content {
padding: 20px 15px;
}
/* 单行文本溢出显示省略号 */
.single_line {
white-space: nowrap;
@ -97,3 +104,14 @@ ol {
padding: 0;
margin: 0;
}
/* 颜色 */
.theme_color,
.ant-table-cell > a {
color: #155BD4;
}
.theme_bg_color {
background-color: #155BD4;
}
.ant-btn-link.ant-btn-dangerous {
color: #E80D0D;
}

@ -75,7 +75,12 @@ ol {
border-block-end: none;
}
/* 1108 update 全局样式新增调整 */
// TODO 全局小尺寸按钮,统一间距 (列表操作栏位按钮)
// TODO_update 重置覆盖默认样式使用统一类名gn + 需要覆盖的类名
.gn .ant-pro-checkcard-content {
padding-inline: 0;
padding-block: 0;
}
// TODO_update 全局小尺寸按钮,统一间距 (列表操作栏位按钮)
.ant-table-cell .ant-btn.ant-btn-sm{
padding: 0;
}
@ -93,7 +98,12 @@ ol {
font-size: 16px;
}
// TODO 自定义样式块
// 弹出框
.ant-modal .ant-modal-content{
padding: 20px 15px;
}
// TODO_update 自定义样式块
/* 单行文本溢出显示省略号 */
.single_line {
@ -115,3 +125,17 @@ ol {
margin: 0;
}
/* 颜色 */
.theme_color, .ant-table-cell>a{
color: #155BD4;
}
.theme_bg_color{
background-color: #155BD4;
}
.ant-btn-link.ant-btn-dangerous {
color: #E80D0D;
}

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-09 13:11:05
* @LastEditTime: 2023-11-13 13:43:47
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\resource.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -42,6 +42,10 @@ export const model_category: { [key: string]: string } = {
'resource.model_category.table.list.updateTime': '更新时间',
'resource.model_category.table.rule.required.name': '类别名称为必填项',
'resource.model_category.table.rule.required.code': '类别代码为必填项',
'resource.model_category.table.list.add': '新建模型类别',
'resource.model_category.table.list.update': '更新模型类别',
};
export const model_image: { [key: string]: string } = {
'resource.model_image.table.list.id': 'ID',

@ -23,6 +23,7 @@ import { FormListActionType } from '@ant-design/pro-form/lib';
import yaml from 'js-yaml';
// @ts-ignore
import cookie from 'react-cookies';
import { proFormItemStyleProps } from '../../../../../config/defaultForm';
interface RecordType {
key: string;
@ -58,10 +59,7 @@ const waitTime = (time: number = 100) => {
};
/**styles 配置 */
const formContainerWidth: number = 755;
const stepFormItemStyleProps: Record<string, any> = {
width: formContainerWidth,
};
const MyCreateForm: React.FC<CreateFormProps> = (props) => {
@ -220,7 +218,7 @@ const MyCreateForm: React.FC<CreateFormProps> = (props) => {
>
<ProForm.Group>
<ProFormText
{...stepFormItemStyleProps}
{...proFormItemStyleProps}
name="name"
label={<FormattedMessage id="project.project.table.list.name" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
@ -282,7 +280,7 @@ const MyCreateForm: React.FC<CreateFormProps> = (props) => {
}
/>
<ProFormText
{...stepFormItemStyleProps}
{...proFormItemStyleProps}
name="info"
label={<FormattedMessage id="project.project.table.list.info" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
@ -306,7 +304,7 @@ const MyCreateForm: React.FC<CreateFormProps> = (props) => {
]}
/>
<ProFormText
{...stepFormItemStyleProps}
{...proFormItemStyleProps}
name="remark"
label={<FormattedMessage id="project.project.table.list.remark" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
@ -363,7 +361,7 @@ const MyCreateForm: React.FC<CreateFormProps> = (props) => {
}>
name="project_file"
title="上传业务代码"
style={{ width: stepFormItemStyleProps.width }}
style={{ width: proFormItemStyleProps.width }}
stepProps={{
description: '上传业务代码格式为(.zip,.tar.gz)',
}}
@ -460,7 +458,7 @@ const MyCreateForm: React.FC<CreateFormProps> = (props) => {
}}
/>
<ProFormList
style={{ width: stepFormItemStyleProps.width }}
style={{ width: proFormItemStyleProps.width }}
actionRef={actionFormListRef}
copyIconProps={{
Icon: SnippetsOutlined,
@ -497,7 +495,7 @@ const MyCreateForm: React.FC<CreateFormProps> = (props) => {
onFinish={async () => {
return true;
}}
style={{ width: stepFormItemStyleProps.width }}
style={{ width: proFormItemStyleProps.width }}
formRef={formRef3}
>
<div style={{ paddingBottom: 10 }}>{'选择网点'}</div>

@ -137,7 +137,6 @@ const ProjectList: React.FC = () => {
);
},
},
{
title: <FormattedMessage id="project.project.table.list.remark" defaultMessage="$$$" />,
dataIndex: 'remark',

@ -16,10 +16,10 @@ import { PageContainer, ProFormSelect, ProFormText, ProTable } from '@ant-design
import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max';
import { Button, Modal, Popconfirm, message } from 'antd';
import React, { useRef, useState } from 'react';
import { proTableCommonOptions, proTableIndexColumnOptions } from '../../../../config/defaultTable';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
const AlgorithmModelList: React.FC = () => {
/**
* @en-US Pop-up window of new window
@ -100,10 +100,10 @@ const AlgorithmModelList: React.FC = () => {
setShowDetail(true);
}
};
const doToDetail = (rowData: Record<string,any>) => {
const doToDetail = (rowData: Record<string, any>) => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
history.push(`/resource/algorithm-model-detail/${rowData.id}`)
}
history.push(`/resource/algorithm-model-detail/${rowData.id}`);
};
const handleDestroy = async (selectedRow: API.AlgorithmModel) => {
deleteAlgorithmModelDeleteAlgorithmModel({ id: selectedRow.id })
.then(() => {
@ -116,6 +116,9 @@ const AlgorithmModelList: React.FC = () => {
};
const columns: ProColumns<API.AlgorithmModel>[] = [
{
...proTableIndexColumnOptions,
},
{
title: <FormattedMessage id="resource.algorithm_model.table.list.id" defaultMessage="id" />,
dataIndex: 'id',
@ -125,7 +128,7 @@ const AlgorithmModelList: React.FC = () => {
<a
onClick={() => {
setCurrentRow(entity);
doToDetail(entity)
doToDetail(entity);
// setShowDetail(true);
}}
>
@ -133,24 +136,7 @@ const AlgorithmModelList: React.FC = () => {
</a>
);
},
//TODO 默认使用renderFormItem update1101
renderFormItem: () => {
return (
<>
<ProFormText
style={{ textAlign: 'left' }}
labelAlign="left"
wrapperCol={{ span: 22 }}
name="id"
placeholder={`123${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}`}
required={false}
/>
</>
);
},
//update 默认使用renderFormItem update1101
},
{
@ -282,7 +268,7 @@ const AlgorithmModelList: React.FC = () => {
size="small"
onClick={() => {
setCurrentRow(record);
doToDetail(record)
doToDetail(record);
// setShowDetail(true);
}}
>
@ -328,13 +314,12 @@ const AlgorithmModelList: React.FC = () => {
id: 'pages.searchTable.title',
defaultMessage: '$$$',
})}
scroll={{ y: 500 , x: 1300}}
scroll={{ y: proTableCommonOptions.scrollY, x: proTableCommonOptions.commscrollX }}
options={{ fullScreen: true, setting: true, density: true, reload: true }}
actionRef={actionRef}
rowKey="key"
search={{
labelWidth: 100,
labelWidth: proTableCommonOptions.searchLabelWidth,
}}
onDataSourceChange={(data) => {
let CategoryFkIdIds: any = data.map((v) => {

@ -19,6 +19,7 @@ import React, { useRef, useState } from 'react';
import { ColumnDrawer } from './components/ColumnDrawer';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
import { proTableCommonOptions, proTableIndexColumnOptions } from '../../../../config/defaultTable';
const BusinessImageList: React.FC = () => {
/**
* @en-US Pop-up window of new window
@ -109,9 +110,13 @@ const BusinessImageList: React.FC = () => {
};
const columns: ProColumns<API.BusinessImage>[] = [
{
...proTableIndexColumnOptions
},
{
title: <FormattedMessage id="resource.business_image.table.list.id" defaultMessage="id" />,
dataIndex: 'id',
// fixed: 'left',
sorter: true,
render: (dom, entity) => {
return (
@ -313,10 +318,11 @@ const BusinessImageList: React.FC = () => {
actionRef={actionRef}
rowKey="key"
scroll={{
x: 1300,
x: proTableCommonOptions.scrollX,
}}
search={{
labelWidth: 120,
labelWidth: 'auto',
}}
onDataSourceChange={(data) => {
let ProjectFkIdIds: any = data.map((v) => {
@ -332,6 +338,7 @@ const BusinessImageList: React.FC = () => {
persistenceKey: 'business_image_list',
persistenceType: 'localStorage',
}}
// TODO 此处需要补一个批量删除
toolBarRender={() => [
<Access
accessible={access.canUpdate(history.location.pathname)}
@ -397,7 +404,7 @@ const BusinessImageList: React.FC = () => {
},
}}
/>
{selectedRowsState?.length > 0 && (
{/* {selectedRowsState?.length > 0 && (
<FooterToolbar
extra={
<div>
@ -424,7 +431,7 @@ const BusinessImageList: React.FC = () => {
/>
</Button>
</FooterToolbar>
)}
)} */}
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}

@ -336,8 +336,8 @@ const ModelVersionList: React.FC = () => {
>
<FormattedMessage id="pages.searchTable.update" defaultMessage="Update" />
</Button>,
// eslint-disable-next-line react/jsx-key
<Popconfirm
key="setDefault"
title="设为默认"
description="确认设置为默认版本吗?"
onConfirm={() => {
@ -361,12 +361,12 @@ const ModelVersionList: React.FC = () => {
cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })}
>
<Button key="set_default" type="link" size="small">
{/* <FormattedMessage id="common.set_default" defaultMessage="$$$" /> */}
</Button>
</Popconfirm>,
// eslint-disable-next-line react/jsx-key
<Popconfirm
key="publishModel"
title="发布模型"
description="确认发布模型吗?"
onConfirm={() => {}}
@ -386,18 +386,24 @@ const ModelVersionList: React.FC = () => {
<FormattedMessage id="common.confirm_publish" defaultMessage="confirm_publish" />
</Button>
</Popconfirm>,
<Button
<Popconfirm
key="destroy"
type="link"
size="small"
danger
onClick={() => {
placement="topLeft"
title={intl.formatMessage({ id: 'common.tip.title', defaultMessage: '$$$' })}
description={intl.formatMessage({
id: 'common.modal.table.delete.content',
defaultMessage: '$$$',
})}
okText={intl.formatMessage({ id: 'common.yes', defaultMessage: '$$$' })}
cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })}
onConfirm={() => {
handleDestroy(record).then(() => {});
}}
>
<FormattedMessage id="pages.searchTable.destroy" defaultMessage="Destroy" />
</Button>,
// eslint-disable-next-line react/jsx-key
<Button type="link" size="small" danger>
<FormattedMessage id="pages.searchTable.destroy" defaultMessage="Destroy" />
</Button>
</Popconfirm>,
]}
></TableActionCard>

@ -50,7 +50,7 @@ const AlgorithmSetting: React.FC = () => {
const [modelVersionData, setModelVersionData] = useState<any[]>([]);
const [projectData, setProjectData] = useState<any>({});
const [targetKeys, setTargetKeys] = useState<string[]>([]);
const [projectConfigId, setProjectConfigId] = useState<number>(0)
const [projectConfigId, setProjectConfigId] = useState<number>(0);
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
@ -171,34 +171,34 @@ const AlgorithmSetting: React.FC = () => {
// console.log('clickTreeNode', projectCardListRef.current)
postProjectGetProjectByGroupId({ id: record.id }).then((resp) => {
let tab_data = (resp?.data?.list || []).map((v: any) => {
console.log(resp.data.list)
let model_data = ([...v?.models] || []).map((item: any) =>
(
{
title: (
<>
<div>{JSON.stringify(item.configId)}</div>
<img src="/images/model.png" alt="" style={{ width: '50px' }} />
</>
console.log(resp.data.list);
let model_data = ([...v?.models] || []).map((item: any) => ({
content: (
<ProCard bodyStyle={{ margin: 0, padding: 0 }}>
<div
style={{ display: 'flex', alignItems: 'center', padding: 15, justifyContent: 'space-between' }}
>
<div>
<div>{JSON.stringify(item.configId)}</div>
<img src="/images/model.png" alt="" style={{ width: '50px' }} />
</div>
<Button
type="link"
size='small'
key={item.configId}
style={{padding: 0}}
onClick={() => {
setProjectConfigId(item.configId);
handleUpdateModal();
}}
>
</Button>
</div>
<ProjectCard info={item}></ProjectCard>
</ProCard>
),
actions: [
<Button
type="link"
key={item.configId}
onClick={() => {
setProjectConfigId(item.configId);
handleUpdateModal();
}}
>
</Button>,
],
content: <ProjectCard info={item}></ProjectCard>,
})
);
}));
// console.log(88, model_data);
// setProjectData({...projectData, [v.id]: v})
return {
@ -206,21 +206,19 @@ const AlgorithmSetting: React.FC = () => {
key: v.id,
children: (
<ProList<any>
className='gn'
ghost={true}
itemCardProps={{
ghost: true,
// headStyle: {background: 'red', padding: 0, margin: 0},
bodyStyle: {padding: 0, margin: 0},
bodyStyle: { padding: 0, margin: 0 },
}}
pagination={{
defaultPageSize: 6,
showSizeChanger: false,
}}
showActions="hover"
grid={{gutter: 8, xs: 1, md: 2, xl: 3, xxl: 4}}
grid={{ gutter: 8, xs: 1, md: 2, xl: 3, xxl: 4 }}
metas={{
title: {},
type: {},
content: {},
actions: {
@ -246,21 +244,31 @@ const AlgorithmSetting: React.FC = () => {
postModelVersionGetModelVersionListByIds({ ids: model_ids }).then((resp) => {
let version_model_data = (resp?.data?.list || []).map((item: Record<string, any>) => {
return {
title: '苏胜天算法模型',
subTitle: <Tag color="#5BD8A6"></Tag>,
actions: [
subTitle: <Tag color="#5BD8A6"></Tag>,
avatar: 'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
content: <ProCard bodyStyle={{ margin: 0, padding: 0 }}>
<div
style={{ display: 'flex', alignItems: 'center', padding: 15, justifyContent: 'space-between' }}
>
<div>
<div>{JSON.stringify(item.configId)}</div>
<img src="/images/model.png" alt="" style={{ width: '50px' }} />
</div>
<Button
type="link"
key="run"
size='small'
key={item.configId}
style={{padding: 0}}
onClick={() => {
setProjectConfigId(item.configId);
handleUpdateModal();
}}
>
</Button>,
],
avatar: 'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
content: <ProjectCard info={item}></ProjectCard>,
</Button>
</div>
<ProjectCard info={item}></ProjectCard>
</ProCard>,
};
});
setModelVersionData(version_model_data);
@ -285,7 +293,8 @@ const AlgorithmSetting: React.FC = () => {
<ProCard split="vertical">
<ProCard
title="网点选择"
colSpan="30%"
colSpan="24%"
bodyStyle={{padding: 0, margin: 0}}
extra={
<Button
icon={<RedoOutlined />}
@ -299,12 +308,12 @@ const AlgorithmSetting: React.FC = () => {
}
>
<ProTable<API.DeviceGroup>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: '$$$',
})}
// headerTitle={intl.formatMessage({
// id: 'pages.searchTable.title',
// defaultMessage: '$$$',
// })}
options={{
search: true,
search: true, // TODO 1113 搜索需要对接比对UI调整交互
fullScreen: false,
setting: false,
density: false,
@ -366,10 +375,9 @@ const AlgorithmSetting: React.FC = () => {
}}
/>
</ProCard>
<ProCard title="" headerBordered split={'horizontal'}>
<ProCard title="" headerBordered split={'horizontal'}>
<ProCard colSpan="80%">
<ProDescriptions
column={2}
dataSource={currentRow}
title="网点详细信息"
@ -394,7 +402,8 @@ const AlgorithmSetting: React.FC = () => {
handleModal={handleUpdateModal}
groupId={currentRow?.id || 0}
reload={actionRef.current?.reload}
projectModelConfigId={projectConfigId}/>
projectModelConfigId={projectConfigId}
/>
</PageContainer>
);
};

@ -1,20 +1,17 @@
import React, { useState } from 'react';
import { Space, Switch, Table, Tag, Transfer } from 'antd';
import { Table, Transfer } from 'antd';
import type { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
import type { TransferItem, TransferProps } from 'antd/es/transfer';
import difference from 'lodash/difference';
import {randomInt} from "@antv/xflow-extension";
import {ProTable} from "@ant-design/pro-components";
import React, { useState } from 'react';
interface RecordType extends API.Device{
key: string
interface RecordType extends API.Device {
key: string;
}
interface DataType extends API.Device{
key: string,
interface DataType extends API.Device {
key: string;
}
const tableListDataSource = [];
const valueEnum = {
0: 'close',
@ -33,10 +30,7 @@ for (let i = 0; i < 5; i += 1) {
creator: creators[Math.floor(Math.random() * creators.length)],
status: valueEnum[((Math.floor(Math.random() * 10) % 4) + '') as '0'],
createdAt: Date.now() - Math.floor(Math.random() * 100000),
memo:
i % 2 === 1
? '很长很长很长很长很长很长很长的文字要展示但是要留下尾巴'
: '简短备注文案',
memo: i % 2 === 1 ? '很长很长很长很长很长很长很长的文字要展示但是要留下尾巴' : '简短备注文案',
});
}
@ -62,43 +56,50 @@ const columns1 = [
},
];
const testData = Array(100).fill(0).map((v, index)=>{
return {
"id": index,
"key": index+"",
"createTime": "2023-10-17T10:47:51.629494+08:00",
"updateTime": "2023-10-26T11:02:39.559715+08:00",
"name": "控制设备",
"code": "DEVICE00002",
"position": "二楼客厅",
"param": "rtsp://admin:@192.168.10.203",
"spec": "",
"categoryFkId": 2,
"groupFkId": 3,
"isEnable": true,
"remark": ""
}
})
const testData = Array(100)
.fill(0)
.map((v, index) => {
return {
id: index,
key: index + '',
createTime: '2023-10-17T10:47:51.629494+08:00',
updateTime: '2023-10-26T11:02:39.559715+08:00',
name: '控制设备',
code: 'DEVICE00002',
position: '二楼客厅',
param: 'rtsp://admin:@192.168.10.203',
spec: '',
categoryFkId: 2,
groupFkId: 3,
isEnable: true,
remark: '',
};
});
interface TableTransferProps extends TransferProps<TransferItem> {
dataSource: DataType[];
leftColumns: ColumnsType<DataType>;
rightColumns: ColumnsType<DataType>
rightColumns: ColumnsType<DataType>;
}
// Customize Table Transfer
const TableTransfer = ({ leftColumns, rightColumns, ...restProps }: TableTransferProps) => (
<Transfer {...restProps} locale={{ itemUnit: '项', itemsUnit: '项', searchPlaceholder: '请输入搜索内容' }}
<Transfer
{...restProps}
locale={{ itemUnit: '项', itemsUnit: '项', searchPlaceholder: '请输入搜索内容' }}
listStyle={{ width: 432 }}
operationStyle={{ width: 32, alignItems: 'center' }}
>
{({
direction,
filteredItems,
onItemSelectAll,
onItemSelect,
selectedKeys: listSelectedKeys,
disabled: listDisabled,
}) => {
direction,
filteredItems,
onItemSelectAll,
onItemSelect,
selectedKeys: listSelectedKeys,
disabled: listDisabled,
}) => {
const columns = direction === 'left' ? leftColumns : rightColumns;
const rowSelection: TableRowSelection<TransferItem> = {
@ -123,26 +124,23 @@ const TableTransfer = ({ leftColumns, rightColumns, ...restProps }: TableTransfe
const diffKeys = selected
? difference(treeSelectedKeys, listSelectedKeys)
: difference(listSelectedKeys, treeSelectedKeys);
console.log(45678, diffKeys)
console.log(45678, diffKeys);
onItemSelectAll(diffKeys as string[], true);
}
},
onSelect({ key }, selected) {
console.log(890, key)
console.log(890, key);
onItemSelect(key as string, selected);
},
selectedRowKeys: listSelectedKeys,
};
return (
<Table<any>
rowSelection={rowSelection}
virtual={true}
columns={columns}
scroll={{y: 500}}
scroll={{ y: 500 }}
dataSource={filteredItems}
size="small"
pagination={false}
@ -165,8 +163,8 @@ const mockData: RecordType[] = Array.from({ length: 20 }).map((_, i) => ({
key: i.toString(),
title: `监控1`,
description: `DEVICE1002`,
tag: "走廊123",
age: "rtsp://129.12.12.12:90001"
tag: '走廊123',
age: 'rtsp://129.12.12.12:90001',
}));
const originTargetKeys = mockData
@ -213,11 +211,11 @@ const rightTableColumns: ColumnsType<DataType> = [
export type UpdateFormProps = {
targetKeys: string[];
setTargetKeys: (data: string[])=>void;
setTargetKeys: (data: string[]) => void;
dataSource: DataType[];
};
const TableTransferList: React.FC<UpdateFormProps> = (props) => {
const TableTransferList: React.FC<UpdateFormProps> = (props) => {
const [showSearch, setShowSearch] = useState(false);
const onChange = (nextTargetKeys: string[]) => {

@ -1,51 +1,45 @@
import TableTransferList from '@/pages/Setting/components/TableTransfer';
import { postDeviceGetAllDeviceByGroup } from '@/services/device/Device';
import {
ProForm, ProFormDigit, ProFormSelect,
postProjectModelConfigGetProjectModelConfigById,
putProjectModelConfigUpdateProjectModelConfig,
} from '@/services/project/ProjectModelConfig';
import { postAlgorithmModelGetAllVersionsById } from '@/services/resource/AlgorithmModel';
import { postModelVersionGetModelVersionById } from '@/services/resource/ModelVersion';
import {
ProForm,
ProFormDigit,
ProFormSelect,
ProFormSwitch,
ProFormText,
StepsForm
StepsForm,
} from '@ant-design/pro-components';
import {useIntl} from '@umijs/max';
import React, {useEffect, useRef, useState} from 'react';
import {message, Modal} from 'antd';
import { FormListActionType } from '@ant-design/pro-form/lib';
import { useIntl } from '@umijs/max';
import { Modal, message } from 'antd';
import type { ColumnsType } from 'antd/es/table/interface';
import type { TransferItem, TransferProps } from 'antd/es/transfer';
import {
postAlgorithmModelGetAllVersionsById
} from "@/services/resource/AlgorithmModel";
import {
postDeviceGetAllDeviceByGroup,
} from "@/services/device/Device";
import {FormListActionType, ProFormDatePicker} from "@ant-design/pro-form/lib";
import {
postModelVersionGetModelVersionById,
} from "@/services/resource/ModelVersion";
import TableTransferList from "@/pages/Setting/components/TableTransfer";
import {
postProjectModelConfigGetProjectModelConfigById,
putProjectModelConfigUpdateProjectModelConfig
} from "@/services/project/ProjectModelConfig";
import React, { useEffect, useRef, useState } from 'react';
import { proFormMaxItemStyleProps, proFormMaxModelWidth, proFormModelWidth } from '../../../../config/defaultForm';
const formContainerWidth: number = 755;
const stepFormItemStyleProps: Record<string, any> = {
width: formContainerWidth,
};
interface DataType extends API.Device{
key: string,
interface DataType extends API.Device {
key: string;
}
interface ProjectModelConfigById {
configId: number,
configId: number;
}
interface TableTransferProps extends TransferProps<TransferItem> {
dataSource: DataType[];
leftColumns: ColumnsType<DataType>;
rightColumns: ColumnsType<DataType>;
dataSource: DataType[];
leftColumns: ColumnsType<DataType>;
rightColumns: ColumnsType<DataType>;
}
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
@ -54,9 +48,7 @@ export type UpdateFormProps = {
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [targetKeys, setTargetKeys] = useState<string[]>([]);
@ -64,22 +56,21 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const [configData, setConfigData] = useState<any>([]);
const [addrValue, setAddr] = useState('')
const [projectModelConfig, setProjectModelConfig] = useState<API.ProjectModelConfig>({})
const [configResult, setConfigResult] = useState<API.ProjectModelConfig>({})
const [deviceData, setDeviceData] = useState<DataType[]>([])
const [selectValue, setSelectValue] = useState<number>(0)
const [isInit, setIsInit] = useState<boolean>(false)
const handleSelectChange = (value: number)=>{
const [addrValue, setAddr] = useState('');
const [projectModelConfig, setProjectModelConfig] = useState<API.ProjectModelConfig>({});
const [configResult, setConfigResult] = useState<API.ProjectModelConfig>({});
const [deviceData, setDeviceData] = useState<DataType[]>([]);
const [selectValue, setSelectValue] = useState<number>(0);
const [isInit, setIsInit] = useState<boolean>(false);
const handleSelectChange = (value: number) => {
if (value !== projectModelConfig.modelVersionFkId) {
postModelVersionGetModelVersionById({ id: value }).then((resp) => {
let data = resp.data.modelVersion.modelConfig?.params || [];
setConfigData(data);
});
}
setSelectValue(value)
}
setSelectValue(value);
};
// useEffect(() => {
// if (selectValue > 0) {
@ -97,28 +88,33 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
>();
useEffect(() => {
setTargetKeys([])
setConfigData([])
setIsInit(false)
if (props.updateModalOpen) {
// getModelData();
if (props.projectModelConfigId && props.projectModelConfigId !== 0) {
postProjectModelConfigGetProjectModelConfigById({id: props.projectModelConfigId}).then((resp)=>{
setProjectModelConfig(resp.data.ProjectModelConfig)
setTargetKeys((resp.data.ProjectModelConfig?.devices || '').split(',').map((v: string)=>{return parseInt(v)}))
setConfigData(resp.data.ProjectModelConfig?.modelConfig || [])
setSelectValue(resp.data.ProjectModelConfig?.modelVersionFkId || 0)
setIsInit(true)
})
}
} else {
setTargetKeys([]);
setConfigData([]);
setIsInit(false);
if (props.updateModalOpen) {
// getModelData();
if (props.projectModelConfigId && props.projectModelConfigId !== 0) {
postProjectModelConfigGetProjectModelConfigById({ id: props.projectModelConfigId }).then(
(resp) => {
setProjectModelConfig(resp.data.ProjectModelConfig);
setTargetKeys(
(resp.data.ProjectModelConfig?.devices || '').split(',').map((v: string) => {
return parseInt(v);
}),
);
setConfigData(resp.data.ProjectModelConfig?.modelConfig || []);
setSelectValue(resp.data.ProjectModelConfig?.modelVersionFkId || 0);
setIsInit(true);
},
);
}
}, [props.updateModalOpen])
} else {
}
}, [props.updateModalOpen]);
const handleChange = (newTargetKeys: string[]) => {
setTargetKeys(newTargetKeys);
setTargetKeys(newTargetKeys);
};
return (
<StepsForm<{
name: string;
}>
@ -126,18 +122,20 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
labelPlacement: 'vertical',
}}
current={current}
onCurrentChange={(value)=>{
setCurrent(value)
if (value == 1) {
postDeviceGetAllDeviceByGroup({id: props.groupId}).then((resp)=>{
setDeviceData((resp.data?.list || []).map((v: API.Device)=>{
return {key: v.id, ...v}
}))
})
}
onCurrentChange={(value) => {
setCurrent(value);
if (value == 1) {
postDeviceGetAllDeviceByGroup({ id: props.groupId }).then((resp) => {
setDeviceData(
(resp.data?.list || []).map((v: API.Device) => {
return { key: v.id, ...v };
}),
);
});
}
}}
onFinish={async (values) => {
setCurrent(0)
setCurrent(0);
return true;
}}
formProps={{
@ -148,8 +146,8 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
stepsFormRender={(dom, submitter) => {
return (
<Modal
title="分步表单"
width={1200}
title="项目部署配置"
width={proFormMaxModelWidth}
onCancel={() => {
setCurrent(0);
props.handleModal();
@ -172,188 +170,216 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
description: '业务参数配置',
}}
onFinish={async (values: any) => {
let projectConfig:any = []
Object.keys(values).forEach((key)=>{
let projectConfig: any = [];
Object.keys(values).forEach((key) => {
if (key !== 'modelFkId') {
projectConfig.push({name: key, value: values[key]})
projectConfig.push({ name: key, value: values[key] });
}
})
configResult.projectConfig = projectConfig
});
configResult.projectConfig = projectConfig;
return true;
}}
>
<>
<ProForm.Group>
{
isInit && (projectModelConfig?.projectConfig || []).map((item: any, index: number)=>{
let value_type = typeof item.value
{isInit &&
(projectModelConfig?.projectConfig || []).map((item: any, index: number) => {
let value_type = typeof item.value;
if (value_type === 'number') {
return (<ProFormDigit
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
tooltip={item.remark}
/>)
return (
<ProFormDigit
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
tooltip={item.remark}
/>
);
} else if (value_type === 'boolean') {
return (<ProFormSwitch
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
tooltip={item.remark}
/>)
return (
<ProFormSwitch
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
tooltip={item.remark}
/>
);
} else if (value_type === 'string') {
return (<ProFormText
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
tooltip={item.remark}
/>)
return (
<ProFormText
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
tooltip={item.remark}
/>
);
} else {
return
return;
}
})
}
})}
</ProForm.Group>
</>
</StepsForm.StepForm>
<StepsForm.StepForm<{
config: string;
}>
name="config"
title="模型参数配置"
stepProps={{
description: '模型参数配置',
}}
onFinish={async (values: any) => {
configResult.modelVersionFkId = values.modelFkId
let modelConfig:any = []
Object.keys(values).forEach((key)=>{
if (key !== 'modelFkId') {
modelConfig.push({name: key, value: values[key]})
}
})
configResult.modelConfig = modelConfig
return true;
}}
>
<>
<div>{props.projectModelConfigId}</div>
{
isInit && projectModelConfig.modelFkId && projectModelConfig.modelFkId !== 0 && (
<ProFormSelect
name="modelFkId"
width="xs"
label="模型版本"
onChange={handleSelectChange}
initialValue={projectModelConfig.modelVersionFkId}
// dependencies 的内容会注入 request 中
request={async () => {
let resp =await postAlgorithmModelGetAllVersionsById({id: projectModelConfig.modelFkId})
return resp.data.list.map((v: any)=>{
return {
label: v.name,
value: v.id
}
})
}}
<StepsForm.StepForm<{
config: string;
}>
name="config"
title="模型参数配置"
stepProps={{
description: '模型参数配置',
}}
onFinish={async (values: any) => {
configResult.modelVersionFkId = values.modelFkId;
let modelConfig: any = [];
Object.keys(values).forEach((key) => {
if (key !== 'modelFkId') {
modelConfig.push({ name: key, value: values[key] });
}
});
configResult.modelConfig = modelConfig;
return true;
}}
>
<>
<ProForm.Group>
{/* <div>{props.projectModelConfigId}</div> */}
{isInit && projectModelConfig.modelFkId && projectModelConfig.modelFkId !== 0 && (
<ProFormSelect
{...proFormMaxItemStyleProps}
name="modelFkId"
label="模型版本"
onChange={handleSelectChange}
initialValue={projectModelConfig.modelVersionFkId}
// dependencies 的内容会注入 request 中
request={async () => {
let resp = await postAlgorithmModelGetAllVersionsById({
id: projectModelConfig.modelFkId,
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
)}
{/* <div>
{selectValue}={projectModelConfig.modelVersionFkId}
</div> */}
{isInit &&
(selectValue !== projectModelConfig.modelVersionFkId
? configData.map((item: any, index: number) => {
if (typeof item.default === 'number') {
return (
<ProFormDigit
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.default}
/>
)
}
<div>{selectValue}={projectModelConfig.modelVersionFkId}</div>
{
isInit && (selectValue !== projectModelConfig.modelVersionFkId ?
(
configData.map((item:any, index: number)=> {
if (typeof item.default === 'number') {
return (<ProFormDigit
key={index}
name={item.name}
label={item.name}
initialValue={item.default}
/>)
} else if (typeof item.default === 'boolean') {
return (<ProFormSwitch
key={index}
name={item.name}
label={item.name}
initialValue={item.default}
/>)
} else {
return (<ProFormText
key={index}
name={item.name}
label={item.name}
initialValue={item.default}
/>)
}
}
)
): (configData.map((item:any, index: number)=> {
if (typeof item.value === 'number') {
return (<ProFormDigit
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
/>)
} else if (typeof item.value === 'boolean') {
return (<ProFormSwitch
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
/>)
} else {
return (<ProFormText
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
/>)
}
}
)))
}
</>
);
} else if (typeof item.default === 'boolean') {
return (
<ProFormSwitch
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.default}
/>
);
} else {
return (
<ProFormText
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.default}
/>
);
}
})
: configData.map((item: any, index: number) => {
if (typeof item.value === 'number') {
return (
<ProFormDigit
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
/>
);
} else if (typeof item.value === 'boolean') {
return (
<ProFormSwitch
{...proFormMaxItemStyleProps}
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
/>
);
} else {
return (
<ProFormText
{...proFormMaxItemStyleProps}
</StepsForm.StepForm>
key={index}
name={item.name}
label={item.name}
initialValue={item.value}
/>
);
}
}))}
</ProForm.Group>
</>
</StepsForm.StepForm>
{/* 关联算法模型 */}
<StepsForm.StepForm<{
config: string;
}>
name="config3"
title="设备配置"
stepProps={{
description: '设备关联配置',
}}
onFinish={async (values: any) => {
configResult.devices = targetKeys.join(',')
configResult.id = props.projectModelConfigId
putProjectModelConfigUpdateProjectModelConfig(configResult).then((resp)=>{
message.success(intl.formatMessage({id: 'common.success', defaultMessage: '$$$'}))
props.handleModal()
props.reload()
return true
}).catch(()=>{
message.error(intl.formatMessage({id: 'common.failure', defaultMessage: '$$$'}))
return false;
})
}}
>
<>
{
}
<TableTransferList setTargetKeys={setTargetKeys} dataSource={deviceData}
targetKeys={targetKeys}></TableTransferList>
</>
</StepsForm.StepForm>
<StepsForm.StepForm<{
config: string;
}>
name="config3"
title="设备配置"
stepProps={{
description: '设备关联配置',
}}
onFinish={async (values: any) => {
configResult.devices = targetKeys.join(',');
configResult.id = props.projectModelConfigId;
putProjectModelConfigUpdateProjectModelConfig(configResult)
.then((resp) => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
props.handleModal();
props.reload();
return true;
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
return false;
});
}}
>
<>
<TableTransferList
setTargetKeys={setTargetKeys}
dataSource={deviceData}
targetKeys={targetKeys}
></TableTransferList>
</>
</StepsForm.StepForm>
</StepsForm>
)}
);
};
export default UpdateForm;

Loading…
Cancel
Save