Commit 9b0d4504 authored by 涂伟's avatar 涂伟
parents 4d559b2a a82438ab
Pipeline #74123 passed with stages
......@@ -93,7 +93,7 @@
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-react": "^1.0.6",
"@wisdom-cesium/cesium": "1.1.12",
"@wisdom-cesium/krpano": "^1.0.29-52",
"@wisdom-cesium/krpano": "^1.0.29-55",
"@wisdom-map/amap": "1.1.0-beta.45",
"@wisdom-map/arcgismap": "1.4.0-150",
"@wisdom-map/basemap": "1.1.0-24",
......
......@@ -259,7 +259,7 @@ const EditableCell = ({
},
},
{
pattern: /^(?!(\d+)$)[\u4e00-\u9fffa-zA-Z0-9_]+$/,
pattern: /^[^\d][\u4e00-\u9fffA-Za-z0-9_]+$/,
message: '不能输入特殊符号或者纯数字',
},
];
......
......@@ -17,7 +17,13 @@ import FlowModal from './workFlowComponents/FlowModal';
import FlowGroupModal from './workFlowComponents/FlowGroupModal';
import Order from './workFlowComponents/Order';
import styles from './WorkflowHomePage.less';
import { WFGetAllFlow, GetFlowNode, DeleteFlow } from '@/services/workflow/workflow';
import {
WFGetAllFlow,
GetFlowNode,
DeleteFlow,
CheckDoingFlowNodes,
CloseDoingFlowNodes,
} from '@/services/workflow/workflow';
import { DownLoadFiles } from '@/services/common/api';
import { UpdateFlowGroup } from '@/services/workflow/workflow';
const plugins = [ScrollToPlugin];
......@@ -114,7 +120,7 @@ const WorkflowHomePage = () => {
let list = res.data.map((item, index) => {
item.children.forEach(ele => {
flowNameList.push(ele.FlowName);
ele.PreviewImage = getImgUrl(ele.PreviewImage)
ele.PreviewImage = getImgUrl(ele.PreviewImage);
});
item.isOld = true;
item.bgType = (index + 1) % 5;
......@@ -248,36 +254,81 @@ const WorkflowHomePage = () => {
});
};
// 删除流程
const delFlow = (val, e) => {
const delFlow = async (val, e) => {
e.stopPropagation();
confirm({
title: '确定要删除吗?',
icon: <ExclamationCircleOutlined />,
content: '',
okText: '是',
okType: 'danger',
cancelText: '否',
onOk() {
DeleteFlow({ FlowId: val.FlowID })
.then(res => {
if (res.code === 0) {
setModalType('del');
getFlowList();
message.success('删除成功');
} else {
message.error({
content: (
<div style={{ whiteSpace: 'pre-line', textAlign: 'justify' }}>{res.msg}</div>
),
let res1 = await CheckDoingFlowNodes({ flowID: val.FlowID });
if (res1.code === 0) {
if (res1.data > 0) {
confirm({
title: '确定要删除当前流程吗?',
icon: <ExclamationCircleOutlined />,
content: <div>当前流程有{res1.data}条在办工单,确定删除会自动归档在办工单。</div>,
okText: '是',
okType: 'danger',
cancelText: '否',
onOk() {
CloseDoingFlowNodes({ flowID: val.FlowID }).then(res2 => {
if (res2.code === 0) {
DeleteFlow({ FlowId: val.FlowID })
.then(res3 => {
if (res3.code === 0) {
setModalType('del');
getFlowList();
message.success('删除成功');
} else {
message.error({
content: (
<div style={{ whiteSpace: 'pre-line', textAlign: 'justify' }}>
{res3.msg}
</div>
),
});
}
})
.catch(() => {
message.error('网络异常请稍后再试');
});
} else {
message.error(res2.msg);
}
});
},
onCancel() {},
});
} else {
confirm({
title: '确定要删除吗?',
icon: <ExclamationCircleOutlined />,
content: '',
okText: '是',
okType: 'danger',
cancelText: '否',
onOk() {
DeleteFlow({ FlowId: val.FlowID })
.then(res2 => {
if (res2.code === 0) {
setModalType('del');
getFlowList();
message.success('删除成功');
} else {
message.error({
content: (
<div style={{ whiteSpace: 'pre-line', textAlign: 'justify' }}>{res2.msg}</div>
),
});
}
})
.catch(() => {
message.error('网络异常请稍后再试');
});
}
})
.catch(() => {
message.error('网络异常请稍后再试');
});
},
onCancel() {},
});
},
onCancel() {},
});
}
} else {
message.error(res1.msg);
}
};
const getImgUrl = img => {
// return new Promise((resolve, reject) => {
......@@ -287,7 +338,7 @@ const WorkflowHomePage = () => {
// reader.onload = () => resolve(reader.result);
// });
// });a
return `/PandaOMS/OMS/FileCenter/DownLoadFiles?module=熊猫智慧水务平台\\WorkFlowImage&filePath=${img}`
return `/PandaOMS/OMS/FileCenter/DownLoadFiles?module=熊猫智慧水务平台\\WorkFlowImage&filePath=${img}`;
};
// tab栏选项渲染
const tabRender = (val, index) => (
......
......@@ -10,6 +10,8 @@ import {
DeleteFlowNode,
DeleteFlowNodes,
SaveWorkFlowImage,
CheckDoingFlowNodes,
CloseDoingFlowNodes,
} from '@/services/workflow/workflow';
import { compress } from '@/utils/utils';
import { ExclamationCircleOutlined, TrophyOutlined } from '@ant-design/icons';
......@@ -153,14 +155,24 @@ const FlowChart = props => {
delLinks.add(item.data.LineId);
}
});
showDeleteConfirm([...delNodeIds], [...delNodes], [...delLinks]);
CheckDoingFlowNodes({ activityIds: [...delNodes] }).then(res => {
if (res.code === 0) {
if (res.data > 0) {
showCloseList([...delNodeIds], [...delNodes], [...delLinks], res.data);
} else {
showDeleteConfirm([...delNodeIds], [...delNodes], [...delLinks]);
}
} else {
message.error(res.msg);
}
});
return false;
};
// 监听线,连接线的时候加上text属性
diagram.addDiagramListener('LinkDrawn', e => {
// e.subject.data.text = '';
e.subject.data.lineDetail = JSON.stringify(e.subject.data);
console.log(e, e.subject.data, 'fasdfasdgds');
diagram.model.updateTargetBindings(e.subject.data);
// leaveCallBack(true);
});
......@@ -168,7 +180,6 @@ const FlowChart = props => {
diagram.addDiagramListener('externalobjectsdropped', e => {
afterNodes.current = new Map([]);
const list = JSON.parse(diagram.model.toJson()).nodeDataArray;
console.log(list, 'list');
let newNum;
let newKey;
......@@ -322,6 +333,27 @@ const FlowChart = props => {
return i;
};
}, [currentFlowData]);
const showCloseList = (delNodeIds, delNodes, delLinks, listMsg) => {
confirm({
title: '确定要删除所选节点吗?',
icon: <ExclamationCircleOutlined />,
content: <div>当前节点有{listMsg}条在办工单,确定删除会自动归档在办工单。</div>,
okText: '是',
okType: 'primary',
cancelText: '否',
onOk() {
CloseDoingFlowNodes({ activityIds: [...delNodes] }).then(res => {
if (res.code === 0) {
delNode(delNodeIds, delNodes, delLinks);
} else {
message.error(res.msg);
}
});
},
onCancel() {},
});
};
// 删除提醒
const showDeleteConfirm = (delNodeIds, delNodes, delLinks) => {
confirm({
......@@ -329,7 +361,7 @@ const FlowChart = props => {
icon: <ExclamationCircleOutlined />,
content: '',
okText: '是',
okType: 'danger',
okType: 'primary',
cancelText: '否',
onOk() {
delNode(delNodeIds, delNodes, delLinks);
......
......@@ -390,7 +390,7 @@ const AddModal = props => {
if (obj.iconUrl.includes('CityTemp') && obj.iconUrl.includes('图库')) {
obj.iconUrl = obj.iconUrl;
} else {
obj.iconUrl = 'CityTemp\\图库\\' + obj.iconUrl;
obj.iconUrl = obj.iconUrl;
}
}
if (type === 'add') {
......@@ -543,7 +543,7 @@ const AddModal = props => {
// };
// });
if (info.file.response.code === 0) {
setIsFromLocal(false)
setIsFromLocal(false);
console.log('触发咯');
if (
info.file.response.data.includes('CityTemp') &&
......@@ -551,7 +551,7 @@ const AddModal = props => {
) {
setImageUrl(getImg(info.file.response.data));
} else {
setImageUrl(getImg('CityTemp\\图库\\' + info.file.response.data));
setImageUrl(getImg(info.file.response.data));
}
setLoading(false);
} else {
......
......@@ -82,6 +82,12 @@ const MobileConfigPage = props => {
Modal.confirm({
title: '确认删除应用?',
icon: <ExclamationCircleOutlined />,
content: (
<span>
删除应用 <span style={{ fontWeight: 800, color: '#1890ff' }}>{key}</span>{' '}
后,将一并删除所属角色与菜单,确认删除?
</span>
),
okText: '确认',
cancelText: '取消',
onOk: closeModal => {
......
......@@ -3,7 +3,7 @@ import { Modal, Form, Select, Input, Checkbox, message } from 'antd';
import lodash from 'lodash';
import styles from './HomeConfigModal.less';
import { GetRoleGroups } from '@/services/webConfig/api';
import TreeSelect from '../menuconfig/TreeSelect';
import TreeSelect from '../menuconfig/NewTreeSelect';
const { Option } = Select;
const HomeConfigModal = props => {
const {
......@@ -13,7 +13,9 @@ const HomeConfigModal = props => {
visible,
onFinish,
currentPageConfig,
userMode,
client,
curWeb,
} = props;
const [form] = Form.useForm();
......@@ -261,7 +263,7 @@ const HomeConfigModal = props => {
</Form.Item> */}
<Form.Item label="主页Url" name="homePage">
{/* <Input placeholder="请输入主页路径" autoComplete="off" /> */}
<TreeSelect menuChange={val => {}} />
<TreeSelect menuChange={val => {}} userMode={userMode} curWeb={curWeb} />
</Form.Item>
</Form>
<div className={styles.roleCheck}>{checkRender(checkList)}</div>
......
......@@ -7,7 +7,7 @@ import HomeConfigModal from './HomeConfigModal';
import styles from './HomePageConfigs.less';
const HomePageConfigs = (props, ref) => {
const { productList, client, roleHomePages, allProductList } = props;
const { productList, client, roleHomePages, allProductList, curWeb, userMode } = props;
const [orderTable, setOrderTable] = useState([]);
const [visible, setVisible] = useState(false);
const [modalType, setModalType] = useState();
......@@ -161,6 +161,8 @@ const HomePageConfigs = (props, ref) => {
modalType={modalType}
productList={productList}
allProductList={allProductList}
userMode={userMode}
curWeb={curWeb}
client={client}
currentPageConfig={currentPageConfig}
onFinish={val => onsubmit(val)}
......
......@@ -59,7 +59,9 @@ export default props => {
submitting,
productList,
allProductList,
userMode,
webs,
curWeb,
} = props;
const [form] = Form.useForm();
const [loginPages, setLoginPages] = useState([]);
......@@ -274,7 +276,7 @@ export default props => {
let arr = validate.homePage.split('/'); // 用const声明常量
let allProList = JSON.parse(JSON.stringify(allProductList));
allProList.push({ PackageName: 'civ_base' });
const product = allProList.find(item => item.PackageName.includes(arr[0]));
const product = allProList.find(item => item.PackageName === arr[0]);
if (product) {
arr.shift();
validate.homePage = arr.join('/');
......@@ -504,6 +506,8 @@ export default props => {
</Form.Item>
<HomePageConfigs
ref={homepageConfigRef}
userMode={userMode}
curWeb={curWeb}
roleHomePages={homePageConfig}
productList={productList}
allProductList={allProductList}
......
......@@ -195,7 +195,7 @@ const WebConfigPage = props => {
<span>
删除网站{' '}
<span style={{ fontWeight: 800, color: '#1890ff' }}>{webToOperate.text}</span>{' '}
将无法恢复, 确认删除?
,将一并删除所属角色与菜单,确认删除?
</span>
),
okText: '确认',
......@@ -471,9 +471,11 @@ const WebConfigPage = props => {
</div>
<SiteConfig
webs={webs}
curWeb={curWeb}
productList={productList}
allProductList={allProductList}
isEdit={isEdit}
userMode={userMode}
visible={configVisible}
onClose={onDrawerClose}
config={toEdit}
......
......@@ -36,7 +36,7 @@ const AddForm = props => {
}
let allProList = JSON.parse(JSON.stringify(allProductList));
allProList.push({ PackageName: 'civ_base' });
const product = allProList.find(item => item.PackageName.includes(arr[0]));
const product = allProList.find(item => item.PackageName === arr[0]);
if (product) {
if (arr.length > 1) {
arr.shift();
......
/* eslint-disable no-restricted-syntax */
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { GetWebMenuInfo, getWebModuleTree } from '@/services/webConfig/api';
import { message, Input, Tree, Empty, Tooltip, notification } from 'antd';
import lodash from 'lodash';
import {
FolderFilled,
FileOutlined,
InfoCircleOutlined,
HomeOutlined,
DesktopOutlined,
} from '@ant-design/icons';
import styles from './TreeSelect.less';
const TreeSelect = (props, ref) => {
const { value, onChange, menuChange, code, initCurrentMenu, userMode, curWeb } = props;
const [menuWebList, setMenuWebList] = useState({});
const [webList, setWebList] = useState([]);
const [visible, setVisible] = useState(false);
const [expandedKeys, setExpandedKeys] = useState([]);
const { TreeNode } = TreeSelect;
const [keepKey, setKeepKey] = useState([]);
useEffect(() => {
getMenu();
}, []);
const getMenu = () => {
getWebModuleTree('super')
.then(res => {
const { data } = res;
if (res.code === 0) {
let list = [];
let arr = data.filter(item => item.id === 'Web4SingleStation');
let datalist = arr[0].children;
datalist.map((i, j) => {
let aa = [];
i.children.map(k => {
if (k.text === '菜单管理') {
aa = k.children;
}
});
let a = {};
a.value = `praent${j}`;
a.text = i.text;
a.children = aa;
a.menuID = `praent${j}`;
a.key = `praent${j}`;
a.item = 'father';
list.push(a);
});
let str = list.find(i => i.text === curWeb.text);
setMenuWebList(str);
setWebList(str.children);
let aa = getKey(str.children);
setKeepKey(aa);
setExpandedKeys([...aa]);
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
.catch(err => {
message.error(err);
});
};
const filterList = val => {
if (!val) {
val = '';
}
if (val !== '') {
let newTree = menuWebList.children.map(item => mapTree(item, val));
let filter = filterTree(newTree);
let newData = filterTreeParent(filter);
let arr = [];
newData.map(i => {
if (i.children.length !== 0 || i.show !== '') {
arr.push(i);
}
});
setWebList(arr);
let aa = getKey(arr);
setExpandedKeys([...aa]);
} else {
setWebList(menuWebList.children);
setExpandedKeys([...keepKey]);
}
};
const getKey = (users, allKeys = []) => {
users.forEach(v => {
let name = v.menuID || v.key;
if (v.children.length > 0) {
name && allKeys.push(name);
}
if (v.children.length > 0) {
return getKey(v.children, allKeys);
}
});
return allKeys;
};
const mapTree = (val, word) => {
const obj = { ...val };
const hasChild = obj.children.length > 0;
let status = '';
if (!condition(obj, word) && word !== '' && obj.children.length === 0) {
status = false;
}
if (condition(obj, word) && word !== '' && obj.children.length === 0) {
status = true;
}
return {
title: obj.text || obj.title,
key: obj.menuID || obj.key,
icon: obj.menuType === 'Web4MenuGroup' ? <FolderFilled /> : <FileOutlined />,
menuType: obj.menuType,
disabled: hasChild || obj.pageUrl === null,
pageUrl: obj.pageUrl,
product: obj.product,
show: status,
children: hasChild ? obj.children.map(i => mapTree(i, word)) : [],
};
};
const filterTree = data => {
let result = [];
for (let item of data) {
if (item.show !== false) {
let node = { ...item };
if (item.children) {
node.children = filterTree(item.children);
}
result.push(node);
}
}
return result;
};
const filterTreeParent = data => {
let result = [];
for (let item of data) {
if (item.show !== '' || item.children.length > 0) {
let node = { ...item };
if (item.children) {
node.children = filterTreeParent(item.children);
}
result.push(node);
}
}
return result;
};
// 过滤条件
const condition = (node, val) => {
let name = node.title || node.text;
return name?.includes(val) || node.pageUrl?.includes(val);
};
const changeValue = e => {
// 过滤数组
onChange(e.target.value);
filterList(e.target.value);
setVisible(true);
};
const onSelect = (selectedKeysValue, info) => {
onChange(info.node.pageUrl);
setVisible(false);
};
const onExpand = expandedKeysValue => {
setExpandedKeys(expandedKeysValue);
};
return (
<div className={styles.treeSelect}>
<Input
allowClear
placeholder="请选填写菜单功能路径"
value={value}
onFocus={() => filterList(value)}
onClick={() => setVisible(!visible)}
onChange={changeValue}
onBlur={() => setVisible(false)}
/>
<div
className={styles.dropBox}
onMouseDown={event => {
event.preventDefault();
}}
style={{ display: visible ? 'block' : 'none' }}
>
<Tree
onExpand={onExpand}
selectedKeys={null}
showIcon
expandedKeys={expandedKeys}
autoExpandParent
onSelect={onSelect}
treeData={webList && webList.map(val => mapTree(val))}
style={{ width: '100%' }}
/>
{Object.keys(webList).length === 0 ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null}
</div>
</div>
);
};
export default forwardRef(TreeSelect);
......@@ -158,7 +158,7 @@ const EditForm = props => {
}
let allProList = JSON.parse(JSON.stringify(allProductList));
allProList.push({ PackageName: 'civ_base' });
const product = allProList.find(item => item.PackageName.includes(arr[0]));
const product = allProList.find(item => item.PackageName === arr[0]);
console.log(product, 'product');
if (product) {
arr.shift();
......
......@@ -98,6 +98,11 @@ const AddUserModal = props => {
message: '提交失败',
description: '密码至少为6位,且包含数字和字母!',
});
} else if (passwordLevel === '弱') {
notification.error({
message: '提交失败',
description: '密码强度太弱,加强密码强度',
});
} else if (userName === '') {
notification.error({
message: '提交失败',
......@@ -257,8 +262,12 @@ const AddUserModal = props => {
label="账号密码"
rules={[
{
pattern: /^[a-zA-Z0-9_]{6,16}$/,
message: '长度6-16位,支持字母与数字,允许下划线',
pattern: /^(?=.*[a-zA-Z])(?=.*\d)[\w\S]{6,16}$/,
message: '长度6-16位,必须包含数字与字母',
},
{
pattern: /^(?!.*(?:SELECT|UPDATE|INSERT|AND|OR|'|"|;|--|\\)).*$/,
message: '当前密码存在sql注入风险,请重新输入', // 防止sql注入
},
{ required: true },
]}
......
......@@ -94,6 +94,7 @@ const EditUserModal = props => {
// });
// return;
// }
if ((newPassword && newPassword.length < 6) || (passwordConfirm && passwordConfirm < 6)) {
notification.error({
message: '提交失败',
......@@ -108,6 +109,25 @@ const EditUserModal = props => {
});
return;
}
if (newPassword && newPassword) {
if (newPasswordLevel === '弱') {
notification.error({
message: '提交失败',
description: '密码强度太弱,加强密码强度',
});
return;
}
if (
!/^(?=.*[a-zA-Z])(?=.*\d)[\w\S]{6,16}$/.test(newPassword) ||
!/^(?!.*(?:SELECT|UPDATE|INSERT|AND|OR|'|"|;|--|\\)).*$/.test(newPassword)
) {
notification.error({
message: '提交失败',
description: '密码验证未通过',
});
return;
}
}
// 所有验证通过才可以提交,phone/email为空时不验证
if (
loginName &&
......@@ -339,8 +359,12 @@ const EditUserModal = props => {
label="新密码"
rules={[
{
pattern: /^[a-zA-Z0-9_]{6,16}$/,
message: '长度6-16位,支持字母与数字,允许下划线',
pattern: /^(?=.*[a-zA-Z])(?=.*\d)[\w\S]{6,16}$/,
message: '长度6-16位,必须包含数字与字母',
},
{
pattern: /^(?!.*(?:SELECT|UPDATE|INSERT|AND|OR|'|"|;|--|\\)).*$/,
message: '当前密码存在sql注入风险,请重新输入', // 防止sql注入
},
// { required: true },
]}
......@@ -374,10 +398,13 @@ const EditUserModal = props => {
label="确认密码"
rules={[
{
pattern: /^[a-zA-Z0-9_]{6,16}$/,
message: '长度6-16位,支持字母与数字,允许下划线',
pattern: /^(?=.*[a-zA-Z])(?=.*\d)[\w\S]{6,16}$/,
message: '长度6-16位,必须包含数字与字母',
},
{
pattern: /^(?!.*(?:SELECT|UPDATE|INSERT|AND|OR|'|"|;|--|\\)).*$/,
message: '当前密码存在sql注入风险,请重新输入', // 防止sql注入
},
// { required: true },
]}
>
<Input.Password
......
......@@ -41,3 +41,9 @@ export const DeleteFlowNodes = param => post(`${PUBLISH_SERVICE}/WorkFlow/Delete
// 保存basde65
export const SaveWorkFlowImage = param =>
post(`${PUBLISH_SERVICE}/FileCenter/SaveWorkFlowImage`, param);
// 检查流程和节点的在办
export const CheckDoingFlowNodes = param =>
post(`${PUBLISH_SERVICE}/WorkFlow/CheckDoingFlowNodes`, param);
// 一键关单接口
export const CloseDoingFlowNodes = param =>
post(`${PUBLISH_SERVICE}/WorkFlow/CloseDoingFlowNodes`, param);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment