diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json
index d030f48..30e8c35 100644
--- a/api/.vscode/launch.json
+++ b/api/.vscode/launch.json
@@ -41,11 +41,14 @@
// "--qndmn http://rhvqdivo5.hn-bkt.clouddn.com",
// click 开发
// "--clickHouseUrl http://10.8.30.71",
+ // "--clickHousePort 8123",
// click 测试
- "--clickHouseUrl http://10.8.30.161",
+ // "--clickHouseUrl http://10.8.30.161",
+ // "--clickHousePort 30123",
// "--clickHouseUrl https://clickhouse01.anxinyun.cn/play",
- "--clickHousePort 30123",
- // "--clickHousePort 8123",
+ // click 测试
+ "--clickHouseUrl http://10.8.30.156",
+ "--clickHousePort 8123",
// 似乎不能传空 先注释 * 2
// "--clickHouseUser ",
// "--clickHousePassword ",
@@ -57,9 +60,9 @@
// "--clickHouseDataAlarm default",
// "--clickHouseIot iot",
// 测试
- "--clickHouseAnxincloud anxinyun1",
- "--clickHousePepEmis pepca9",
- "--clickHouseProjectManage peppm",
+ "--clickHouseAnxincloud Anxinyun101",
+ "--clickHousePepEmis pepca8",
+ "--clickHouseProjectManage peppm8",
"--clickHouseVcmp video_access_dev",
"--clickHouseDataAlarm default",
"--clickHouseIot iota",
diff --git a/api/app/lib/controllers/workOrder/index.js b/api/app/lib/controllers/workOrder/index.js
index dd1c92d..6002667 100644
--- a/api/app/lib/controllers/workOrder/index.js
+++ b/api/app/lib/controllers/workOrder/index.js
@@ -4,8 +4,27 @@ const moment = require('moment')
async function getEnabledWorkflowProcess (ctx) {
try {
const { models } = ctx.fs.dc;
+ const { clickHouse } = ctx.app.fs
+
+ const listRes = await clickHouse.pepEmis.query(`
+ SELECT
+ workflow_process.id AS id,
+ workflow_process.name AS name,
+ workflow_process.create_time AS createTime,
+ workflow_process.update_time AS updateTime,
+ workflow_group.name AS group
+ FROM
+ workflow_process
+ RIGHT JOIN workflow_group
+ ON workflow_process.group_id = workflow_group.id
+ AND workflow_group.name = '销售'
+ WHERE
+ workflow_process.deleted = 0
+ AND workflow_process.is_enable = 1
+ `).toPromise()
ctx.status = 200;
+ ctx.body = listRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
diff --git a/web/client/index.html b/web/client/index.html
index 3ee9392..c6ebcf6 100644
--- a/web/client/index.html
+++ b/web/client/index.html
@@ -10,8 +10,8 @@
-
+
diff --git a/web/client/src/components/index.js b/web/client/src/components/index.js
index effcb7c..04b40ae 100644
--- a/web/client/src/components/index.js
+++ b/web/client/src/components/index.js
@@ -5,6 +5,7 @@ import Setup from './setup'
import { SkeletonScreen } from './skeletonScreen'
import OutHidden from './outHidden'
import Uploads from './Uploads/index'
+import WorkflowModal from './workflow';
export {
SimpleFileDownButton,
@@ -12,5 +13,6 @@ export {
Setup,
SkeletonScreen,
OutHidden,
- Uploads
+ Uploads,
+ WorkflowModal
};
diff --git a/web/client/src/components/workflow/index.js b/web/client/src/components/workflow/index.js
new file mode 100644
index 0000000..b3bbe29
--- /dev/null
+++ b/web/client/src/components/workflow/index.js
@@ -0,0 +1,198 @@
+'use strict';
+
+import React from 'react';
+import { connect } from 'react-redux';
+import { Modal, Spin, Notification, Row } from '@douyinfe/semi-ui';
+import { RouteTable } from '../../utils/webapi';
+import { RouteRequest } from '@peace/utils';
+import { useState } from 'react';
+import { useEffect } from 'react';
+import { IconClose } from '@douyinfe/semi-icons';
+// import { delDraft } from '../../sections/myform/actions/myform';
+import './index.less'
+
+const { confirm } = Modal;
+
+const WorkFlowModal = (props) => {
+ const { successCallBack = () => { }, title, visible, clientHeight, postData, processId, user, dispatch } = props;
+ const [loading, setLoading] = useState(true);
+ const [ifShowMessage, setIfShowMessage] = useState(true);
+ const [webUrl, setWebUrl] = useState(null);
+ const [customVisible, setCustomVisible] = useState(false);
+ const [draftId, setDraftId] = useState();
+ const iframeRef = React.createRef();
+
+ const handelCancel = () => {
+ if (draftId) {
+ setCustomVisible(false);
+ } else {
+ const { onCancel } = props;
+ onCancel && onCancel();
+ setLoading(false);
+ }
+ }
+
+ const showConfirm = () => {
+ if (draftId) {
+ setCustomVisible(true);
+ } else {
+ confirm({
+ title: '确定关闭此表单吗?',
+ onOk () {
+ handelCancel()
+ },
+ onCancel () { },
+ });
+ }
+ }
+
+ const handelApprovalCenter = (activeKey) => {
+ RouteRequest.get(RouteTable.getWebUrl + `?sys=emisWebUrl`).then(res => {
+ if (res.url) {
+ window.open(res.url + "/approval/center?activeKey=" + activeKey);
+ }
+ });
+ }
+
+ const handelOk = () => {
+ const { onCancel } = props;
+ onCancel && onCancel();
+ setLoading(false);
+ setCustomVisible(false);
+ setDraftId(null);
+ }
+
+ const handelDeny = () => {
+ // dispatch(delDraft(draftId)).then(res => {
+ // if (res.success) {
+ // Notification.success('删除草稿成功');
+ // const { onCancel } = props;
+ // onCancel && onCancel();
+ // setLoading(false);
+ // setCustomVisible(false);
+ // setDraftId(null);
+ // } else {
+ // Notification.error('删除草稿失败,请联系管理员');
+ // }
+ // })
+ }
+
+ const cancel = () => {
+ setCustomVisible(false);
+ }
+
+ useEffect(() => {
+ window.receiveMessageFromIndex = function (event) {
+ if (event && event.data && typeof (event.data) == 'string') {
+ let data = JSON.parse(event.data);
+ const { type, isSaveDraft, setIntervalSave, draftId, msg } = data;
+ if (msg) {
+ Notification.success(msg)
+ }
+ setDraftId(draftId);
+ if (type == 'saveSuccess' && successCallBack) {
+ if (ifShowMessage) {
+ if (isSaveDraft) {
+ if (setIntervalSave) {
+ Notification.success('60秒,表单暂存草稿成功');
+ } else {
+ Notification.success(保存草稿成功,可在 handelApprovalCenter("save")}>【审批中心/保存待发】查看详情, 10);
+ }
+ } else {
+ Notification.success('提交成功,可在【审批中心/由我发起】查看详情');
+ successCallBack();
+ }
+ //防止提示多次
+ setIfShowMessage(false);
+ }
+ // successCallBack(); 阻止页面关闭
+ setLoading(false);
+ }
+ }
+ }
+ //监听message事件
+ window.addEventListener('message', receiveMessageFromIndex, false);
+ //获取企业统一认证管理平台web的URL
+ if (!webUrl) {
+ RouteRequest.get(RouteTable.getEmisWebUrl).then(res => {
+ if (res.url) {
+ setWebUrl(res.url);
+ }
+ });
+ }
+ }, [])
+
+ return (
+
+
+
+
+
+
+
+ |
+ 让世间万物拥有感知,服务人类社会于美好
+
+
+
+
+
+ {webUrl && processId ? : ''}
+
+
+
+ {
+ customVisible ?
+
+
此表单已保存为草稿,是否需要保留
+
+ - handelOk()}>是
+ - handelDeny()}>否
+ - cancel()}>取消
+
+
+
: ''
+ }
+
+
+
+ )
+}
+
+function mapStateToProps (state) {
+ const { auth, global } = state;
+ return {
+ user: auth.user,
+ clientHeight: global.clientHeight,
+ }
+}
+
+export default connect(mapStateToProps)(WorkFlowModal);
\ No newline at end of file
diff --git a/web/client/src/components/workflow/index.less b/web/client/src/components/workflow/index.less
new file mode 100644
index 0000000..280ecdb
--- /dev/null
+++ b/web/client/src/components/workflow/index.less
@@ -0,0 +1,123 @@
+.process_modal_wrap {
+ overflow: hidden !important;
+}
+
+.workflow-body {
+ height : 100vh;
+ width : 100%;
+ position: relative;
+
+ &-header {
+ width : calc(100vw - 71px);
+ height : 80px;
+ background: linear-gradient(90deg, #1890ff 0%, #1271c9 100%);
+ position : fixed;
+ top : 0px;
+ left : 32px;
+ z-index : 1;
+
+ img {
+ // padding: 12px 0 0 18px;
+ position: relative;
+ // top: 18%;
+ left : 18px;
+ top : 8px;
+ }
+
+ &_title {
+ span {
+ margin-top : 32px;
+ position : relative;
+ top : 10px;
+ left : 12px;
+ padding-left: 20px;
+ }
+
+ &_shu {
+ font-size: 25px;
+ color : rgba(255, 255, 255, 0.5);
+ }
+
+ &_zi {
+ font-size : 16px;
+ color : #fff;
+ line-height: 60px;
+ font-weight: bold;
+ }
+ }
+
+ &_closeIcon {
+ position : absolute;
+ top : 0px;
+ right : 0px;
+ font-size: 37px;
+ color : #999999 !important;
+ }
+ }
+
+ &-form {
+ position: fixed;
+ top : 0;
+ bottom : 0;
+ left : 0;
+ right : 0;
+ height : 100vh;
+ }
+}
+
+.modalBox {
+ position : fixed;
+ width : 96.3%;
+ height : 100%;
+ background: rgba(0, 0, 0, 0.3);
+
+ .modal {
+ background : #fff;
+ position : absolute;
+ top : 20%;
+ left : 50%;
+ margin-left : -112px;
+ padding : 10px 20px;
+ border : 1px solid #ddd;
+ border-radius: 2px;
+ width : 370px;
+
+ .content {
+ margin-top : 20px;
+ font-size : 18px;
+ color : #000;
+ }
+
+ .btn {
+ display : flex;
+ justify-content: flex-end;
+ width : 100%;
+ font-size : 16px;
+
+ .confirm {
+ padding : 0 10px;
+ color : #fff;
+ border-radius: 3px;
+ background : #1890FF;
+ cursor : pointer;
+ }
+
+ .deny {
+ padding : 0 10px;
+ color : #1890FF;
+ border-radius: 3px;
+ border : 1px solid #1890FF;
+ margin : 0 10px;
+ cursor : pointer;
+ }
+
+ .cancel {
+ padding : 0 10px;
+ color : #1890FF;
+ border-radius: 3px;
+ border : 1px solid #1890FF;
+ cursor : pointer;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/client/src/components/workflow/view.js b/web/client/src/components/workflow/view.js
new file mode 100644
index 0000000..304d285
--- /dev/null
+++ b/web/client/src/components/workflow/view.js
@@ -0,0 +1,110 @@
+'use strict';
+
+import React from 'react';
+import { connect } from 'react-redux';
+// import { Modal, Spin, message, Row } from 'antd';
+import { RouteTable } from '../../utils/webapi';
+import { RouteRequest } from '@peace/utils';
+import { useState } from 'react';
+import { useEffect } from 'react';
+import { CloseCircleFilled } from '@ant-design/icons';
+import './index.less'
+
+const { confirm } = Modal;
+
+const WorkFlowViewModal = (props) => {
+ // const { successCallBack, title, visible, clientHeight, postData, processId, user } = props;
+ // const [loading, setLoading] = useState(true);
+ // const [ifShowMessage, setIfShowMessage] = useState(true);
+ // const [webUrl, setWebUrl] = useState(null);
+ // const iframeRef = React.createRef();
+
+ // const handelCancel = () => {
+ // const { onCancel } = props;
+ // onCancel && onCancel();
+ // setLoading(false);
+ // }
+
+ // const showConfirm = () => {
+ // confirm({
+ // title: '确定关闭此表单吗?',
+ // onOk() {
+ // handelCancel()
+ // },
+ // onCancel() { },
+ // });
+ // }
+
+ // useEffect(() => {
+ // if (!webUrl) {
+ // RouteRequest.get(RouteTable.getEmisWebUrl).then(res => {
+ // if (res.url) {
+ // setWebUrl(res.url);
+ // }
+ // });
+ // }
+ // }, [])
+ const bodyStyle = { paddingLeft: 32, paddingRight: 32, margin: 0, backgroundColor: '#FAFAFA', height: '100%', overflowY: 'auto' }
+ return (
+
+ {/*
+
+
+
+
+
+ {webUrl && processId ? : ''}
+
+
+
+
+
+ */}
+
+
+ )
+}
+
+function mapStateToProps(state) {
+ const { auth, global } = state;
+ return {
+ user: auth.user,
+ clientHeight: global.clientHeight,
+ }
+}
+
+export default connect(mapStateToProps)(WorkFlowViewModal);
\ No newline at end of file
diff --git a/web/client/src/sections/workOrder/actions/index.js b/web/client/src/sections/workOrder/actions/index.js
index eb109ab..0d9ee61 100644
--- a/web/client/src/sections/workOrder/actions/index.js
+++ b/web/client/src/sections/workOrder/actions/index.js
@@ -1,2 +1,7 @@
'use strict';
+import * as jobOrder from './jobOrder'
+
+export default {
+ ...jobOrder
+}
\ No newline at end of file
diff --git a/web/client/src/sections/workOrder/actions/jobOrder.js b/web/client/src/sections/workOrder/actions/jobOrder.js
index 82bfac3..b977ddd 100644
--- a/web/client/src/sections/workOrder/actions/jobOrder.js
+++ b/web/client/src/sections/workOrder/actions/jobOrder.js
@@ -6,7 +6,7 @@ export function getEnabledWorkflowProcess () {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
- actionType: 'GET_MEMBERS',
+ actionType: 'GET_ENABLED_WORKFLOW_PROCESS',
url: `${ApiTable.getEnabledWorkflowProcess}`,
msg: { error: '获取可用表单失败' },
reducer: { name: 'workflowProcess' }
diff --git a/web/client/src/sections/workOrder/containers/jobOrder.jsx b/web/client/src/sections/workOrder/containers/jobOrder.jsx
index a9785f4..34a8d4c 100644
--- a/web/client/src/sections/workOrder/containers/jobOrder.jsx
+++ b/web/client/src/sections/workOrder/containers/jobOrder.jsx
@@ -1,24 +1,73 @@
-import React, { useEffect } from 'react';
+import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
+import moment from 'moment';
+import { WorkflowModal } from "$components"
+import { Card, Typography, Space, Button } from '@douyinfe/semi-ui';
+import { IconArticle } from '@douyinfe/semi-icons';
+import '../style.less'
+
+const { Meta } = Card;
const JobOrder = (props) => {
- const { dispatch, actions, user, loading, socket } = props
+ const { dispatch, actions, user, workflowProcess } = props
+ const { workOrder } = actions
+ const [workflowModalVisible, setWorkflowModalVisible] = useState(false)
+ const [launchProcessId, setLaunchProcessId] = useState(null)
useEffect(() => {
-
+ dispatch(workOrder.getEnabledWorkflowProcess())
}, [])
return (
-
-
+
+ {
+ workflowProcess.map(p => {
+ return (
+
{
+ setLaunchProcessId(p.id)
+ setWorkflowModalVisible(true)
+ }}
+ >
+
+
+ }
+ />
+
+
+ )
+ })
+ }
+
{ setWorkflowModalVisible(false) }}
+ successCallBack={() => { setWorkflowModalVisible(false) }}
+ />
)
}
function mapStateToProps (state) {
- const { auth, global, members, webSocket } = state;
+ const { auth, global, workflowProcess } = state;
return {
- // user: auth.user,
+ user: auth.user,
+ actions: global.actions,
+ workflowProcess: workflowProcess.data || []
};
}
diff --git a/web/client/src/sections/workOrder/style.less b/web/client/src/sections/workOrder/style.less
index 75ecdb6..c4b69ca 100644
--- a/web/client/src/sections/workOrder/style.less
+++ b/web/client/src/sections/workOrder/style.less
@@ -1,7 +1,6 @@
-#example {
- box-shadow: 3px 3px 2px black;
-}
-
-#example:hover {
- color: yellowgreen;
+.work-order-container {
+ .work-order-card:hover {
+ // 阴影
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ }
}
\ No newline at end of file
diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js
index 83b4921..e74df6d 100644
--- a/web/client/src/utils/webapi.js
+++ b/web/client/src/utils/webapi.js
@@ -79,6 +79,13 @@ export const ApiTable = {
//工单
getEnabledWorkflowProcess: 'workflow/process/enabled',//获取工作流可用表单
};
+
+// 项企的接口
+export const EmisApiTable = {
+ //通过流程名称查找指定流程
+ getProcessByName: '/workflow/process/name',
+}
+
export const RouteTable = {
apiRoot: "/api/root",
fileUpload: "/_upload/new",