Browse Source

提交后台

master
xingyongchun 2 years ago
parent
commit
7a174d8bbe
  1. 18
      web/client/src/layout/components/header/index.js
  2. 118
      web/client/src/sections/article/actions/article.js
  3. 288
      web/client/src/sections/article/components/import_model.js
  4. 2
      web/client/src/sections/article/components/modeal.js
  5. 25
      web/client/src/sections/article/containers/index.js
  6. 344
      web/client/src/sections/auth/containers/forget-pwd.js
  7. 2
      web/client/src/sections/auth/containers/login.js
  8. 8
      web/client/src/sections/auth/reducers/domain.js
  9. 8
      web/client/src/sections/auth/reducers/reset-pwd.js
  10. 196
      web/client/src/sections/homePage/actions/profile.js
  11. 48
      web/client/src/sections/homePage/containers/index.js
  12. 2
      web/client/src/sections/homePage/containers/particulars.js
  13. 92
      web/client/src/sections/party/containers/index.js
  14. 116
      web/client/src/sections/personnel/actions/article.js
  15. 306
      web/client/src/sections/personnel/components/import_model.js
  16. 116
      web/client/src/sections/personnel/components/modeal.js
  17. 48
      web/client/src/sections/personnel/containers/index.js
  18. 2
      web/client/src/sections/personnel/nav-item.js
  19. 156
      web/client/src/utils/webapi.js
  20. 2
      web/package.json
  21. 2
      web/readme.md

18
web/client/src/layout/components/header/index.js

@ -18,9 +18,9 @@ function Header(props) {
dispatch, history, user, pathname, toggleCollapsed, collapsed, actions, profile, onChangeTheme,
} = props;
useEffect(() => {
user?.id && actions?.profile?.getProfile && dispatch(actions.profile.getProfile(user?.id));
}, []);
// useEffect(() => {
// user?.id && actions?.profile?.getProfile && dispatch(actions.profile.getProfile(user?.id));
// }, []);
const changeTheme = (themeKey) => {
localStorage.setItem('theme-name', themeKey);
@ -33,8 +33,8 @@ function Header(props) {
const handelClick = (item) => {
if (item.key === 'logout') {
dispatch(actions.auth.logout(user));
sessionStorage.removeItem('selectedKeys');
// dispatch(actions.auth.logout(user));
// sessionStorage.removeItem('selectedKeys');
history.push('/brief');
}
// else if (item.key === 'themeLight') {
@ -91,7 +91,7 @@ function Header(props) {
<Link to="/profile">个人设置</Link>
</Menu.Item> */}
<Menu.Item key="logout" icon={<LogoutOutlined />}>
<span>退出</span>
<span >退出</span>
</Menu.Item>
</Menu.SubMenu>
</Menu>
@ -103,9 +103,9 @@ function Header(props) {
function mapStateToProps(state) {
const { global, auth, profile } = state;
return {
actions: global.actions,
user: auth.user,
profile: profile.data || {},
// actions: global.actions,
// user: auth.user,
// profile: profile.data || {},
};
}

118
web/client/src/sections/article/actions/article.js

@ -3,62 +3,86 @@ import { ApiTable } from "$utils";
import { Request } from "@peace/utils";
import { basicAction } from "@peace/utils";
export function addArticle(articleObj) {
// export function addArticle(articleObj) {
// return (dispatch) =>
// basicAction({
// type: "post",
// dispatch: dispatch,
// data: articleObj,
// actionType: "ADD_ARTICLE",
// url: `${ApiTable.addArticle}`,
// msg: { error: "新增文章失败" },
// reducer: { name: "articleInsertInfo" },
// });
// }
// export function editArticle(articleObj) {
// return (dispatch) =>
// basicAction({
// type: "put",
// dispatch: dispatch,
// data: articleObj,
// actionType: "EDIT_ARTICLE",
// url: `${ApiTable.addArticle}`,
// msg: { error: "编辑文章失败" },
// reducer: { name: "articleInsertInfo" },
// });
// }
// export function getDataList(query) {
// return (dispatch) =>
// basicAction({
// type: "get",
// dispatch: dispatch,
// actionType: "GET_DATALIST",
// url: ApiTable.getDataList,
// query: query,
// msg: { error: "获取文章信息失败" },
// reducer: {
// name: "articlesfrom",
// },
// });
// }
// export function delDataList(id) {
// return (dispatch) =>
// basicAction({
// type: "del",
// dispatch: dispatch,
// actionType: "DEL_DATALIST11",
// url: ApiTable.delDataList + `?id=${id}`,
// query: { id: id },
// msg: { error: "删除文章信息失败" },
// });
// }
// export const MODIFYARTICAL = {
// REQUEST_SUCCESS: "MODIFY_ARTICAL_SUCCESS",
// };
// export function setModifyData(data) {
// return (dispatch) => {
// dispatch({ type: MODIFYARTICAL.REQUEST_SUCCESS, payload: { data } });
// };
// }
export function postProject(articleObj) {
return (dispatch) =>
basicAction({
type: "post",
dispatch: dispatch,
data: articleObj,
actionType: "ADD_ARTICLE",
url: `${ApiTable.addArticle}`,
msg: { error: "新增文章失败" },
reducer: { name: "articleInsertInfo" },
actionType: "POST_PROJECT",
url: `${ApiTable.projectUrl}`,
msg: { error: "获取项目信息失败" },
// reducer: { name: "articleInsertInfo" },
});
}
export function editArticle(articleObj) {
export function postInProject(articleObj) {
return (dispatch) =>
basicAction({
type: "put",
type: "post",
dispatch: dispatch,
data: articleObj,
actionType: "EDIT_ARTICLE",
url: `${ApiTable.addArticle}`,
msg: { error: "编辑文章失败" },
reducer: { name: "articleInsertInfo" },
});
}
export function getDataList(query) {
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_DATALIST",
url: ApiTable.getDataList,
query: query,
msg: { error: "获取文章信息失败" },
reducer: {
name: "articlesfrom",
},
actionType: "POST_IN_PROJECT",
url: `${ApiTable.postInProject}`,
msg: { error: "上传项目信息失败" },
// reducer: { name: "articleInsertInfo" },
});
}
export function delDataList(id) {
return (dispatch) =>
basicAction({
type: "del",
dispatch: dispatch,
actionType: "DEL_DATALIST11",
url: ApiTable.delDataList + `?id=${id}`,
query: { id: id },
msg: { error: "删除文章信息失败" },
});
}
export const MODIFYARTICAL = {
REQUEST_SUCCESS: "MODIFY_ARTICAL_SUCCESS",
};
export function setModifyData(data) {
return (dispatch) => {
dispatch({ type: MODIFYARTICAL.REQUEST_SUCCESS, payload: { data } });
};
}
}

288
web/client/src/sections/article/components/import_model.js

@ -1,163 +1,171 @@
/*
* @description :
* @description :
* @Date : 2021-04-07 14:39:33
* @FilePath : \web\client\src\sections\user\components\userManagement\importUser.js
* @useStrict : use strict
*/
'use strict';
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { Button, Input, Card, Modal, Upload, message } from 'antd';
import { Request } from '@peace/utils'
import request from 'superagent'
import XLSX from 'xlsx'
// import { userBulkAdd } from '../../actions'
"use strict";
import React, { useState } from "react";
import { connect } from "react-redux";
import { Button, Input, Card, Modal, Upload, message } from "antd";
import { Request } from "@peace/utils";
import request from "superagent";
import XLSX from "xlsx";
import { postInProject } from "../actions/article";
//TODO 下载模板和上传文件读取
const ImportUser = props => {
const { user, dispatch, handleCancel, params,editData } = props
const [msg, setMsg] = useState('')
const [loading, setLoading] = useState('')
const [postData, setPostData] = useState([])
const ImportUser = (props) => {
const { user, dispatch, handleCancel, params, editData } = props;
const [msg, setMsg] = useState("");
const [loading, setLoading] = useState("");
const [postData, setPostData] = useState([]);
const confirm = () => {
if (postData.length) {
setLoading(true)
// dispatch(userBulkAdd(postData, params.departmentId ? params.departmentId : null)).then(res => {
// if (res.success) {
// }
// setLoading(false)
// })
} else {
message.warn('没有数据可以提交,请上传数据文件')
const confirm = () => {
if (postData.length) {
setLoading(true);
dispatch(postInProject(postData)).then((res) => {
console.log(res)
if (res.success) {
handleCancel();
message.success("上传成功");
}
setLoading(false);
});
} else {
message.warn("没有数据可以提交,请上传数据文件");
}
};
return (
<Modal
visible={props.importVisible}
onOk={confirm}
confirmLoading={loading}
onCancel={() => {
setMsg('')
setLoading(false)
setPostData([])
handleCancel()
}}
destroyOnClose
>
{/* <Button size="small" type='primary' onClick={() => {
return (
<Modal
visible={props.importVisible}
onOk={confirm}
confirmLoading={loading}
onCancel={() => {
setMsg("");
setLoading(false);
setPostData([]);
handleCancel();
}}
destroyOnClose
>
{/* <Button size="small" type='primary' onClick={() => {
Request.get(`attachments?src=upload/files/1.jpg&filename=${encodeURIComponent('1.jpg')}&token=${user.token}`).then(res => {
})
}}>下载模板</Button> */}
<a href={'/_api/' + `attachments?src=files/用户信息导入模板.xlsx&filename=${encodeURIComponent('用户信息导入模板.xlsx')}&token=${user.token}`} >
<Button size="small" type='primary' >下载模板</Button>
</a>
<div style={{ marginTop: 10 }}>下载模板后填写完整后上传</div>
<div style={{ marginTop: 10 }}>
<Upload {...{
name: 'user_d',
action: '/',
maxCount: 1,
showUploadList: {
showRemoveIcon: false
},
beforeUpload: (file) => {
setMsg('')
setPostData([])
const extNames = file.name.split('.');
let isDAE = false;
if (extNames.length > 0) {
let fileType = extNames[extNames.length - 1].toLowerCase();
isDAE = ['xlsx', 'xls'].some((f) => f == fileType);
}
if (!isDAE) {
setMsg(`只能上传 ${['xlsx', 'xls'].join()} 格式的文件!`);
return false;
}
},
onChange(info) {
<a
href={
"/_api/" +
`attachments?src=files/用户信息导入模板.xlsx&filename=${encodeURIComponent(
"用户信息导入模板.xlsx"
)}&token=${user.token}`
}
>
<Button size="small" type="primary">
下载模板
</Button>
</a>
<div style={{ marginTop: 10 }}>下载模板后填写完整后上传</div>
<div style={{ marginTop: 10 }}>
<Upload
{...{
name: "user_d",
action: "/",
maxCount: 1,
showUploadList: {
showRemoveIcon: false,
},
beforeUpload: (file) => {
setMsg("");
setPostData([]);
const extNames = file.name.split(".");
let isDAE = false;
if (extNames.length > 0) {
let fileType = extNames[extNames.length - 1].toLowerCase();
isDAE = ["xlsx", "xls"].some((f) => f == fileType);
}
if (!isDAE) {
setMsg(`只能上传 ${["xlsx", "xls"].join()} 格式的文件!`);
return false;
}
},
onChange(info) {},
customRequest: async (data) => {
const { file, onSuccess, onError } = data;
},
customRequest: async (data) => {
const { file, onSuccess, onError } = data
const reader = new FileReader(); // 使用 FileReader 读取数据
reader.onload = function (e) {
// 数据读取完成后的回调函数
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: "array" }); // workbook 是 xlsx 解析 excel 后返回的对象
const reader = new FileReader(); // 使用 FileReader 读取数据
reader.onload = function (e) { // 数据读取完成后的回调函数
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: 'array' }); // workbook 是 xlsx 解析 excel 后返回的对象
const firstSheetName = workbook.SheetNames[0]; // 获取第一个 sheet 的名字
const worksheet = workbook.Sheets[firstSheetName]; // 获取第一个 sheet 的内容
const res = XLSX.utils.sheet_to_json(worksheet); // 使用 utils 里的方法转换内容为便于使用的数组
const error = (msg) => {
setMsg(msg);
onError({ message: msg });
};
if (res.length > 1000) {
error("一次性上传数据行数应小于1000行,请分批上传");
return;
}
if (!res.length) {
error("请填写至少一行数据");
return;
}
let postData = [];
const firstSheetName = workbook.SheetNames[0]; // 获取第一个 sheet 的名字
const worksheet = workbook.Sheets[firstSheetName]; // 获取第一个 sheet 的内容
const res = XLSX.utils.sheet_to_json(worksheet); // 使用 utils 里的方法转换内容为便于使用的数组
const error = (msg) => {
setMsg(msg)
onError({ message: msg })
}
if (res.length > 1000) {
error('一次性上传数据行数应小于1000行,请分批上传')
return
}
if (!res.length) {
error('请填写至少一行数据')
return
}
let postData = []
const pattern = /^1[3|4|5|6|7|8|9]\d{9}$/
for (let i = 0; i < res.length; i++) {
let d = res[i]
let name = String(d['姓名']).trim();
let phone = String(d['手机号码']).trim();
let account = String(d['账号']).trim();
let peopleCode = d['人员编号'] && String(d['人员编号']).trim();
if (!name || !phone || !account || !peopleCode) {
error(`${i + 1} 行有空值,请填写后重新上传`)
return
}
if (!pattern.test(phone)) {
error(`${i + 1} 行手机号码错误`)
return
}
if (name.length > 128 || account.length > 128) {
error(`${i + 1} 行数据字符长度大于 128,请更改后重新上传`)
return
}
if (postData.some(p => p.account == account)) {
error(`${i + 1} 行账号重复,请更改后重新上传`)
return
}
postData.push({
name, phone, account, peopleCode
})
}
if (postData.length) {
setPostData(postData)
}
let msg = '文件解析完成,点击确定按钮上传保存!'
setMsg(msg)
onSuccess({ message: msg })
};
reader.readAsArrayBuffer(file); // 读取数据
},
}}>
<Button>上传文件</Button>
</Upload>
<br />
<span>{msg}</span>
</div>
</Modal >
)
}
for (let i = 0; i < res.length; i++) {
let d = res[i];
let name_project = String(d["版本计划"]).trim();
let part_people_in = String(d["投入人力"]).trim();
let build_time = String(d["构建时间"]).trim();
let publish_time = String(d["发布时间"]).trim();
let progress = String(d["目前进度"]).trim();
if (!name_project || !part_people_in || !build_time || !publish_time||!progress) {
error(`${i + 1} 行有空值,请填写后重新上传`);
return;
}
let part_people = part_people_in.split('、').map((i) => {
return {name_people:i}
})
postData.push({
name_project,
part_people,
build_time,
publish_time,progress
});
}
if (postData.length) {
setPostData(postData);
}
let msg = "文件解析完成,点击确定按钮上传保存!";
setMsg(msg);
onSuccess({ message: msg });
};
reader.readAsArrayBuffer(file); // 读取数据
},
}}
>
<Button>上传文件</Button>
</Upload>
<br />
<span>{msg}</span>
</div>
</Modal>
);
};
function mapStateToProps(state) {
const { auth, customizeList } = state;
return {
user: auth.user,
}
const { auth, customizeList } = state;
return {
user: auth.user,
};
}
export default connect(mapStateToProps)(ImportUser);
export default connect(mapStateToProps)(ImportUser);

2
web/client/src/sections/article/components/modeal.js

@ -9,7 +9,7 @@ function modeal(props) {
if (editData && visible) {
form.setFieldsValue({
name_project: editData.name_project,
part_people: editData.part_people,
part_people: editData.part_people.map((i)=>i.name_people),
build_time: dayjs(editData?.build_time),
publish_time: dayjs(editData.publish_time),
progress:editData.progress

25
web/client/src/sections/article/containers/index.js

@ -3,7 +3,7 @@ import React, { useEffect, useState, useRef } from "react";
import { connect } from "react-redux";
import { Button, Popconfirm } from "antd";
import ProTable from "@ant-design/pro-table";
import Action from "../actions/index";
import {postProject} from "../actions/article";
import moment from "moment";
import { push } from "react-router-redux";
import { Scroller } from "$components";
@ -38,7 +38,7 @@ export const Default = (props) => {
dataIndex: "part_people",
hideInSearch: true,
render: (dom, record) => {
return record.part_people
return <div>{record.part_people.map((i, index) => record.part_people.length == 1 ? <span>{i.name_people}</span> : <span>{i.name_people}{index < record.part_people.length-1 ? '':'' }</span>) }</div>
},
},
{
@ -147,28 +147,15 @@ export const Default = (props) => {
actionRef={tableActionRef}
columns={columns}
options={false}
dataSource={dataSore}
dataSource={counts||[]}
search={{
optionRender: false,
collapsed: false,
}}
request={async (params) => {
let query = {
type: -1,
searchValue: heading,
status: state,
page: params.current,
limit: params.pageSize,
publishTime:
day && day.length && day[0].trim() != ""
? JSON.stringify([
moment(day[0]).startOf("day"),
moment(day[1]).endOf("day"),
])
: null,
};
const res = await dispatch(Action.getDataList(query));
setCounts(res.payload.data);
const res = await dispatch(postProject());
console.log(res)
setCounts(res.payload.data.projects);
return {
...res,
total: res.payload.data ? res.payload.data.total : 0,

344
web/client/src/sections/auth/containers/forget-pwd.js

@ -1,182 +1,182 @@
import React, { Component, useState, useEffect } from 'react';
import { connect } from 'react-redux';
import {
Card, Form, Input, Button, Row, Col, Alert, message,
} from 'antd';
import { resetPwd, RESET_PASSWORD_SUCCESS } from '../actions/reset-pwd';
import { sendPhoneCode, checkPhoneCode, checkPhone } from '../actions/validate-phone';
// import React, { Component, useState, useEffect } from 'react';
// import { connect } from 'react-redux';
// import {
// Card, Form, Input, Button, Row, Col, Alert, message,
// } from 'antd';
// import { resetPwd, RESET_PASSWORD_SUCCESS } from '../actions/reset-pwd';
// import { sendPhoneCode, checkPhoneCode, checkPhone } from '../actions/validate-phone';
const FormItem = Form.Item;
// const FormItem = Form.Item;
function ForgetPwdContainer(props) {
const { dispatch, match: { params }, isRequesting } = props;
const [form] = Form.useForm();
const [sleeping, setSleeping] = useState(false);
let [sleepCount, setSleepCount] = useState(60);
const [done, setDone] = useState(false);
let timer;
// function ForgetPwdContainer(props) {
// const { dispatch, match: { params }, isRequesting } = props;
// const [form] = Form.useForm();
// const [sleeping, setSleeping] = useState(false);
// let [sleepCount, setSleepCount] = useState(60);
// const [done, setDone] = useState(false);
// let timer;
const _checkPhone = async (rule, value, callback) => {
await checkPhone(value, params.domain).then((_) => {
// const _checkPhone = async (rule, value, callback) => {
// await checkPhone(value, params.domain).then((_) => {
}, (err) => {
throw new Error('未发现绑定该手机的账号!');
});
};
// }, (err) => {
// throw new Error('未发现绑定该手机的账号!');
// });
// };
const fetchVCode = async () => {
const phoneObj = await form.validateFields(['phone']);
await sendPhoneCode(phoneObj.phone).then((_) => {
setSleeping(true);
timer = setInterval((_) => {
if (sleepCount == 0) {
setSleeping(false);
setSleepCount(60);
clearInterval(timer);
return;
}
setSleepCount(sleepCount--);
}, 1000);
setSleepCount(sleepCount--);
});
};
// const fetchVCode = async () => {
// const phoneObj = await form.validateFields(['phone']);
// await sendPhoneCode(phoneObj.phone).then((_) => {
// setSleeping(true);
// timer = setInterval((_) => {
// if (sleepCount == 0) {
// setSleeping(false);
// setSleepCount(60);
// clearInterval(timer);
// return;
// }
// setSleepCount(sleepCount--);
// }, 1000);
// setSleepCount(sleepCount--);
// });
// };
const submit = () => {
form.validateFields().then((values) => {
checkPhoneCode(values.phone, values.code).then((_) => {
dispatch(resetPwd(params.domain, values.phone, values.code, values.password))
.then((action) => {
if (action.type == RESET_PASSWORD_SUCCESS) {
setDone(true);
} else {
message.error(action.payload.error);
}
});
}, (err) => {
message.error(err.response.body.message);
});
});
};
// const submit = () => {
// form.validateFields().then((values) => {
// checkPhoneCode(values.phone, values.code).then((_) => {
// dispatch(resetPwd(params.domain, values.phone, values.code, values.password))
// .then((action) => {
// if (action.type == RESET_PASSWORD_SUCCESS) {
// setDone(true);
// } else {
// message.error(action.payload.error);
// }
// });
// }, (err) => {
// message.error(err.response.body.message);
// });
// });
// };
return (
<div>
<div style={{ textAlign: 'center', padding: '100px 0 50px 0' }}>
<img src="/assets/images/anxinyun.png" width="180px" />
</div>
<Card style={{ width: 500, padding: 50, margin: '0 auto' }}>
<h3 style={{
color: '#666', paddingBottom: 5, marginBottom: 30, borderBottom: '1px solid #666',
}}
>
找回密码
</h3>
{
done
? (
<Alert
message="完成"
description={(
<div>
<p>
已成功验证您的手机号
{form.getFieldValue('phone')}
, 并重置密码
</p>
<div style={{ padding: '30px 0', fontWeight: 'bold' }}>
<a href={`/${params.domain}/signin`}>返回登录</a>
</div>
</div>
)}
type="success"
showIcon
/>
)
: (
<div>
<Form form={form}>
<FormItem
hasFeedback
name="phone"
validateFirst
rules={[{
pattern: /^1[3|4|5|7|8|9]\d{9}$/, message: '手机号码无效',
}, {
required: true, message: '手机号码不能为空',
}, {
validator: _checkPhone,
}, {
validateTrigger: 'onBlur',
}]}
>
<Input maxLength="11" placeholder="请输入注册时填写的手机号" />
</FormItem>
<FormItem>
<Row>
<Col span={16}>
<FormItem
name="code"
noStyle
rules={[{
required: true, message: '验证码不能为空',
}]}
>
<Input type="text" maxLength="8" placeholder="请输入验证码" />
</FormItem>
// return (
// <div>
// <div style={{ textAlign: 'center', padding: '100px 0 50px 0' }}>
// <img src="/assets/images/anxinyun.png" width="180px" />
// </div>
// <Card style={{ width: 500, padding: 50, margin: '0 auto' }}>
// <h3 style={{
// color: '#666', paddingBottom: 5, marginBottom: 30, borderBottom: '1px solid #666',
// }}
// >
// 找回密码
// </h3>
// {
// done
// ? (
// <Alert
// message="完成"
// description={(
// <div>
// <p>
// 已成功验证您的手机号:
// {form.getFieldValue('phone')}
// , 并重置密码
// </p>
// <div style={{ padding: '30px 0', fontWeight: 'bold' }}>
// <a href={`/${params.domain}/signin`}>返回登录</a>
// </div>
// </div>
// )}
// type="success"
// showIcon
// />
// )
// : (
// <div>
// <Form form={form}>
// <FormItem
// hasFeedback
// name="phone"
// validateFirst
// rules={[{
// pattern: /^1[3|4|5|7|8|9]\d{9}$/, message: '手机号码无效',
// }, {
// required: true, message: '手机号码不能为空',
// }, {
// validator: _checkPhone,
// }, {
// validateTrigger: 'onBlur',
// }]}
// >
// <Input maxLength="11" placeholder="请输入注册时填写的手机号" />
// </FormItem>
// <FormItem>
// <Row>
// <Col span={16}>
// <FormItem
// name="code"
// noStyle
// rules={[{
// required: true, message: '验证码不能为空',
// }]}
// >
// <Input type="text" maxLength="8" placeholder="请输入验证码" />
// </FormItem>
</Col>
<Col span={8}>
<Button type="primary" onClick={fetchVCode} loading={sleeping} style={{ float: 'right' }}>
{sleeping ? `${sleepCount}s后重试` : '获取验证码'}
</Button>
</Col>
</Row>
</FormItem>
<FormItem
hasFeedback
name="password"
rules={[{
pattern: /^[a-z0-9A-Z_]{6,20}$/, message: '密码由6-20位字母、数字或_组成',
}, {
required: true, message: '密码不能为空',
}]}
>
<Input type="password" placeholder="请输入新密码" />
</FormItem>
<FormItem
hasFeedback
name="rptpwd"
rules={[{
required: true, message: '密码不能为空',
}, {
validator: async (rule, value) => {
if (form.getFieldValue('password') != value) {
throw new Error('两次输入的密码不一致!');
}
},
}]}
>
<Input type="password" placeholder="请再次输入新密码" />
</FormItem>
<FormItem>
<Button type="primary" style={{ width: '100%' }} loading={isRequesting} onClick={submit}>重设密码</Button>
</FormItem>
</Form>
<div style={{ padding: '30px 0 0 0' }}>
<a href={`/${params.domain}/signin`}>返回登录</a>
</div>
</div>
)
}
</Card>
</div>
);
}
// </Col>
// <Col span={8}>
// <Button type="primary" onClick={fetchVCode} loading={sleeping} style={{ float: 'right' }}>
// {sleeping ? `${sleepCount}s后重试` : '获取验证码'}
// </Button>
// </Col>
// </Row>
// </FormItem>
// <FormItem
// hasFeedback
// name="password"
// rules={[{
// pattern: /^[a-z0-9A-Z_]{6,20}$/, message: '密码由6-20位字母、数字或_组成',
// }, {
// required: true, message: '密码不能为空',
// }]}
// >
// <Input type="password" placeholder="请输入新密码" />
// </FormItem>
// <FormItem
// hasFeedback
// name="rptpwd"
// rules={[{
// required: true, message: '密码不能为空',
// }, {
// validator: async (rule, value) => {
// if (form.getFieldValue('password') != value) {
// throw new Error('两次输入的密码不一致!');
// }
// },
// }]}
// >
// <Input type="password" placeholder="请再次输入新密码" />
// </FormItem>
// <FormItem>
// <Button type="primary" style={{ width: '100%' }} loading={isRequesting} onClick={submit}>重设密码</Button>
// </FormItem>
// </Form>
// <div style={{ padding: '30px 0 0 0' }}>
// <a href={`/${params.domain}/signin`}>返回登录</a>
// </div>
// </div>
// )
// }
// </Card>
// </div>
// );
// }
function mapStateToProps(state) {
const { resetPwd } = state;
return {
isRequesting: resetPwd.isRequesting,
};
}
// function mapStateToProps(state) {
// const { resetPwd } = state;
// return {
// isRequesting: resetPwd.isRequesting,
// };
// }
export default connect(mapStateToProps)(ForgetPwdContainer);
// export default connect(mapStateToProps)(ForgetPwdContainer);

2
web/client/src/sections/auth/containers/login.js

@ -117,7 +117,7 @@ function mapStateToProps(state) {
return {
user: auth.user,
error: auth.error,
isRequesting: auth.isRequesting,
// isRequesting: auth.isRequesting,
};
}

8
web/client/src/sections/auth/reducers/domain.js

@ -3,7 +3,7 @@ import * as actionTypes from '../actions/domain';
const initState = {
domain: null,
isRequesting: false,
// isRequesting: false,
error: null,
};
@ -12,17 +12,17 @@ function domain(state = initState, action) {
switch (action.type) {
case actionTypes.REQUEST_DOMAIN:
return Immutable.fromJS(state).merge({
isRequesting: true,
// isRequesting: true,
error: null,
}).toJS();
case actionTypes.GET_DOMAIN_SUCCESS:
return Immutable.fromJS(state).merge({
isRequesting: false,
// isRequesting: false,
domain: payload.domain,
}).toJS();
case actionTypes.GET_DOMAIN_ERROR:
return Immutable.fromJS(state).merge({
isRequesting: false,
// isRequesting: false,
error: payload.error,
}).toJS();
default:

8
web/client/src/sections/auth/reducers/reset-pwd.js

@ -2,7 +2,7 @@ import Immutable from 'immutable';
import * as actionTypes from '../actions/reset-pwd';
const initState = {
isRequesting: false,
// isRequesting: false,
error: null,
};
@ -11,16 +11,16 @@ function resetPwd(state = initState, action) {
switch (action.type) {
case actionTypes.REQUEST_RESET_PASSWORD:
return Immutable.fromJS(state).merge({
isRequesting: true,
// isRequesting: true,
error: null,
}).toJS();
case actionTypes.RESET_PASSWORD_SUCCESS:
return Immutable.fromJS(state).merge({
isRequesting: false,
// isRequesting: false,
}).toJS();
case actionTypes.RESET_PASSWORD_ERROR:
return Immutable.fromJS(state).merge({
isRequesting: false,
// isRequesting: false,
error: payload.error,
}).toJS();
default:

196
web/client/src/sections/homePage/actions/profile.js

@ -1,97 +1,97 @@
import { basicAction } from "@peace/utils";
import { ApiTable } from "$utils";
export function getProfile(userId) {
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_PROFILE",
url: ApiTable.getUserInfo.replace("{userId}", userId),
msg: { error: "获取用户信息失败" },
reducer: {
name: "profile",
},
});
}
export function getDataList({ type, page, limit, status }) {
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_DATALIST",
url: ApiTable.getDataList,
query: { type, page, limit, status },
msg: { error: "获取文章信息失败" },
reducer: {
name: "articlesfrom",
},
});
}
export function editProfile(userId, params, type) {
return (dispatch) =>
basicAction({
type: "put",
data: params,
dispatch: dispatch,
actionType: "EDIT_PROFILE",
url: ApiTable.modifyUserInfo
.replace("{userId}", userId)
.replace("{type}", type || "phone"),
msg: { option: "更新个人信息" },
});
}
// export function getProfile(userId) {
// return (dispatch) =>
// basicAction({
// type: "get",
// dispatch: dispatch,
// actionType: "GET_PROFILE",
// url: ApiTable.getUserInfo.replace("{userId}", userId),
// msg: { error: "获取用户信息失败" },
// reducer: {
// name: "profile",
// },
// });
// }
// export function getDataList({ type, page, limit, status }) {
// return (dispatch) =>
// basicAction({
// type: "get",
// dispatch: dispatch,
// actionType: "GET_DATALIST",
// url: ApiTable.getDataList,
// query: { type, page, limit, status },
// msg: { error: "获取文章信息失败" },
// reducer: {
// name: "articlesfrom",
// },
// });
// }
// export function editProfile(userId, params, type) {
// return (dispatch) =>
// basicAction({
// type: "put",
// data: params,
// dispatch: dispatch,
// actionType: "EDIT_PROFILE",
// url: ApiTable.modifyUserInfo
// .replace("{userId}", userId)
// .replace("{type}", type || "phone"),
// msg: { option: "更新个人信息" },
// });
// }
export function editpassword(userId, params) {
return (dispatch) =>
basicAction({
type: "put",
data: params,
dispatch: dispatch,
actionType: "EDIT_PASSWORD",
url: ApiTable.modifyPassWord.replace("{userId}", userId),
msg: { option: "更新密码" },
});
}
// export function editpassword(userId, params) {
// return (dispatch) =>
// basicAction({
// type: "put",
// data: params,
// dispatch: dispatch,
// actionType: "EDIT_PASSWORD",
// url: ApiTable.modifyPassWord.replace("{userId}", userId),
// msg: { option: "更新密码" },
// });
// }
export function editName(userId, params) {
return (dispatch) =>
basicAction({
type: "put",
data: params,
dispatch: dispatch,
actionType: "EDIT_NAME",
url: ApiTable.modifyName.replace("{userId}", userId),
msg: { option: "修改姓名" },
});
}
export function getText(id) {
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_TEXT",
url: ApiTable.getText,
query: { id },
msg: { error: "获取文章信息失败" },
reducer: {
name: "wen",
},
});
}
export function getPartyMember() {
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "PARTY_MEMBER",
url: ApiTable.getpartyMember,
msg: { option: "获取工会人数" },
reducer: {
name: "party",
},
});
}
// export function editName(userId, params) {
// return (dispatch) =>
// basicAction({
// type: "put",
// data: params,
// dispatch: dispatch,
// actionType: "EDIT_NAME",
// url: ApiTable.modifyName.replace("{userId}", userId),
// msg: { option: "修改姓名" },
// });
// }
// export function getText(id) {
// return (dispatch) =>
// basicAction({
// type: "get",
// dispatch: dispatch,
// actionType: "GET_TEXT",
// url: ApiTable.getText,
// query: { id },
// msg: { error: "获取文章信息失败" },
// reducer: {
// name: "wen",
// },
// });
// }
// export function getPartyMember() {
// return (dispatch) =>
// basicAction({
// type: "get",
// dispatch: dispatch,
// actionType: "PARTY_MEMBER",
// url: ApiTable.getpartyMember,
// msg: { option: "获取工会人数" },
// reducer: {
// name: "party",
// },
// });
// }
export function getProject() {
return (dispatch) =>
@ -136,10 +136,16 @@ export function getWait() {
}
export default {
getProfile,
editProfile,
editpassword,
editName,
getText,
getPartyMember,
// getProfile,
// editProfile,
// editpassword,
// editName,
// getText,
// modifyEmailEnable,
// modifyEmailDisable,
// modifySmsEnable,
// modifySmsDisable,
// midifyDndEnable,
// modifyDndDisable,
// getPartyMember,
};

48
web/client/src/sections/homePage/containers/index.js

@ -133,46 +133,9 @@ function Management(props) {
},
];
useEffect(() => {
dispatch(getProject()).then((res) => {
if (res.success) {
const nextData = res.payload?.data?.projects?.map((d, i) => ({
...d,
key: i,
build_time: moment(d.build_time).format("YYYY/MM/DD"),
publish_time: moment(d.publish_time).format("YYYY/MM/DD"),
part_people: d.part_people?.map(p => p.name_people).join(),
}));
setProjectData(nextData)
}
})
dispatch(getPeople()).then((res) => {
console.log(res, 'getPeople')
})
dispatch(getWait()).then((res) => {
if (res.success) {
const nextData = res.payload?.data?.projects?.map((d, i) => ({
...d,
key: i,
}));
setWaitData(nextData)
}
})
let nextData = []
for (let i = 1; i <= 34; i++) {
nextData.push({
key: i,
name: i,
age: 32,
address: '西湖区湖底公园1号',
})
}
setDataSource(nextData)
}, []);
// useEffect(() => {
// dispatch(getPartyMember()).then((res) => {});
// }, []);
return (
<>
@ -231,8 +194,9 @@ function Management(props) {
function mapStateToProps(state) {
const { auth, global } = state;
return {
user: auth.user,
actions: global.actions,
// loding: party.isRequesting,
// user: auth.user,
// actions: global.actions,
};
}
export default connect(mapStateToProps)(Management);

2
web/client/src/sections/homePage/containers/particulars.js

@ -123,7 +123,7 @@ function Particulars(props) {
function mapStateToProps(state) {
const { auth, global, party, wen } = state;
return {
loding: wen.isRequesting,
// loding: wen.isRequesting,
user: auth.user,
actions: global.actions,
party: party,

92
web/client/src/sections/party/containers/index.js

@ -0,0 +1,92 @@
import PropTypes from 'prop-types'
import React, { useEffect, useState } from "react";
import { connect } from 'react-redux'
import { Table, message } from 'antd'
// import { getPartyMember } from '../../homePage/actions/profile'
import { editLaborParty } from '../actions/party'
import EditParty from '../components/edit-party';
var request = false
export const Default = (props) => {
const { dispatch } = props;
const [partyLabor, setPartyLabor] = useState();
const [showEdit, setShowEdit] = useState(false);
const [editData, setEditData] = useState();
useEffect(() => {
// dispatch(getPartyMember()).then(res => {
// if (res.success) {
// setPartyLabor(res.payload.data);
// }
// })
}, [request])
const onEditParty = (record) => {
setShowEdit(true);
setEditData(record)
}
const tableColumns = [
{
key: 'num',
dataIndex: 'num',
title: '序号',
render: () => {
return <span>1</span>
}
},
{
key: 'partyNumber',
dataIndex: 'partyNumber',
title: '党员人数',
},
{
key: 'laborUnion',
dataIndex: 'laborUnion',
title: '工会人数',
},
{
key: 'ation',
title: '操作',
render: (text, record) => {
return <a onClick={() => onEditParty(record)}>编辑</a>
}
}
]
const handleOk = (values) => {
if (values) {
const { labor, party } = values
const result = { partyNumber: party, laborUnion: labor }
dispatch(editLaborParty(result)).then(res => {
if (res.success) {
message.success("编辑成功");
request = !request;
handleCancel();
}
})
}
}
const handleCancel = () => {
setShowEdit(false);
}
return (
<div>
<p style={{ marginBottom: 16, fontSize: 16 }}>党员工会人数维护</p>
<Table columns={tableColumns} dataSource={partyLabor ? [partyLabor] : []} />
<EditParty editData={editData} visible={showEdit} handleOk={handleOk} handleCancel={handleCancel} />
</div>
)
}
Default.propTypes = {
second: PropTypes.third
}
const mapStateToProps = (state) => ({})
export default connect(mapStateToProps)(Default)

116
web/client/src/sections/personnel/actions/article.js

@ -3,62 +3,86 @@ import { ApiTable } from "$utils";
import { Request } from "@peace/utils";
import { basicAction } from "@peace/utils";
export function addArticle(articleObj) {
// export function addArticle(articleObj) {
// return (dispatch) =>
// basicAction({
// type: "post",
// dispatch: dispatch,
// data: articleObj,
// actionType: "ADD_ARTICLE",
// url: `${ApiTable.addArticle}`,
// msg: { error: "新增文章失败" },
// reducer: { name: "articleInsertInfo" },
// });
// }
// export function editArticle(articleObj) {
// return (dispatch) =>
// basicAction({
// type: "put",
// dispatch: dispatch,
// data: articleObj,
// actionType: "EDIT_ARTICLE",
// url: `${ApiTable.addArticle}`,
// msg: { error: "编辑文章失败" },
// reducer: { name: "articleInsertInfo" },
// });
// }
// export function getDataList(query) {
// return (dispatch) =>
// basicAction({
// type: "get",
// dispatch: dispatch,
// actionType: "GET_DATALIST",
// url: ApiTable.getDataList,
// query: query,
// msg: { error: "获取文章信息失败" },
// reducer: {
// name: "articlesfrom",
// },
// });
// }
// export function delDataList(id) {
// return (dispatch) =>
// basicAction({
// type: "del",
// dispatch: dispatch,
// actionType: "DEL_DATALIST11",
// url: ApiTable.delDataList + `?id=${id}`,
// query: { id: id },
// msg: { error: "删除文章信息失败" },
// });
// }
// export const MODIFYARTICAL = {
// REQUEST_SUCCESS: "MODIFY_ARTICAL_SUCCESS",
// };
// export function setModifyData(data) {
// return (dispatch) => {
// dispatch({ type: MODIFYARTICAL.REQUEST_SUCCESS, payload: { data } });
// };
// }
export function postOutPeople(articleObj) {
return (dispatch) =>
basicAction({
type: "post",
dispatch: dispatch,
data: articleObj,
actionType: "ADD_ARTICLE",
url: `${ApiTable.addArticle}`,
msg: { error: "新增文章失败" },
reducer: { name: "articleInsertInfo" },
actionType: "POST_OUTPEOPLE",
url: `${ApiTable.peopleUrl}`,
msg: { error: "获取人员信息失败" },
// reducer: { name: "articleInsertInfo" },
});
}
export function editArticle(articleObj) {
export function postInPeople(articleObj) {
return (dispatch) =>
basicAction({
type: "put",
type: "post",
dispatch: dispatch,
data: articleObj,
actionType: "EDIT_ARTICLE",
url: `${ApiTable.addArticle}`,
msg: { error: "编辑文章失败" },
reducer: { name: "articleInsertInfo" },
});
}
export function getDataList(query) {
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_DATALIST",
url: ApiTable.getDataList,
query: query,
msg: { error: "获取文章信息失败" },
reducer: {
name: "articlesfrom",
},
});
}
export function delDataList(id) {
return (dispatch) =>
basicAction({
type: "del",
dispatch: dispatch,
actionType: "DEL_DATALIST11",
url: ApiTable.delDataList + `?id=${id}`,
query: { id: id },
msg: { error: "删除文章信息失败" },
actionType: "POST_OUTPEOPLE",
url: `${ApiTable.postInPeople}`,
msg: { error: "上传人员信息失败" },
// reducer: { name: "articleInsertInfo" },
});
}
export const MODIFYARTICAL = {
REQUEST_SUCCESS: "MODIFY_ARTICAL_SUCCESS",
};
export function setModifyData(data) {
return (dispatch) => {
dispatch({ type: MODIFYARTICAL.REQUEST_SUCCESS, payload: { data } });
};
}

306
web/client/src/sections/personnel/components/import_model.js

@ -1,163 +1,189 @@
/*
* @description :
* @description :
* @Date : 2021-04-07 14:39:33
* @FilePath : \web\client\src\sections\user\components\userManagement\importUser.js
* @useStrict : use strict
*/
'use strict';
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { Button, Input, Card, Modal, Upload, message } from 'antd';
import { Request } from '@peace/utils'
import request from 'superagent'
import XLSX from 'xlsx'
// import { userBulkAdd } from '../../actions'
"use strict";
import React, { useState } from "react";
import { connect } from "react-redux";
import { Button, Input, Card, Modal, Upload, message } from "antd";
import { Request } from "@peace/utils";
import request from "superagent";
import XLSX from "xlsx";
import { postInPeople } from "../actions/article";
//TODO 下载模板和上传文件读取
const ImportUser = props => {
const { user, dispatch, handleCancel, params,editData } = props
const [msg, setMsg] = useState('')
const [loading, setLoading] = useState('')
const [postData, setPostData] = useState([])
const ImportUser = (props) => {
const { user, dispatch, handleCancel, params, editData } = props;
const [msg, setMsg] = useState("");
const [loading, setLoading] = useState("");
const [postData, setPostData] = useState([]);
const confirm = () => {
if (postData.length) {
setLoading(true)
// dispatch(userBulkAdd(postData, params.departmentId ? params.departmentId : null)).then(res => {
// if (res.success) {
// }
// setLoading(false)
// })
} else {
message.warn('没有数据可以提交,请上传数据文件')
const confirm = () => {
if (postData.length) {
setLoading(true);
dispatch(postInPeople(postData)).then((res) => {
if (res.success) {
handleCancel();
message.success("上传成功");
}
setLoading(false);
});
} else {
message.warn("没有数据可以提交,请上传数据文件");
}
};
return (
<Modal
visible={props.importVisible}
onOk={confirm}
confirmLoading={loading}
onCancel={() => {
setMsg('')
setLoading(false)
setPostData([])
handleCancel()
}}
destroyOnClose
>
{/* <Button size="small" type='primary' onClick={() => {
return (
<Modal
visible={props.importVisible}
onOk={confirm}
confirmLoading={loading}
onCancel={() => {
setMsg("");
setLoading(false);
setPostData([]);
handleCancel();
}}
destroyOnClose
>
{/* <Button size="small" type='primary' onClick={() => {
Request.get(`attachments?src=upload/files/1.jpg&filename=${encodeURIComponent('1.jpg')}&token=${user.token}`).then(res => {
})
}}>下载模板</Button> */}
<a href={'/_api/' + `attachments?src=files/用户信息导入模板.xlsx&filename=${encodeURIComponent('用户信息导入模板.xlsx')}&token=${user.token}`} >
<Button size="small" type='primary' >下载模板</Button>
</a>
<div style={{ marginTop: 10 }}>下载模板后填写完整后上传</div>
<div style={{ marginTop: 10 }}>
<Upload {...{
name: 'user_d',
action: '/',
maxCount: 1,
showUploadList: {
showRemoveIcon: false
},
beforeUpload: (file) => {
setMsg('')
setPostData([])
const extNames = file.name.split('.');
let isDAE = false;
if (extNames.length > 0) {
let fileType = extNames[extNames.length - 1].toLowerCase();
isDAE = ['xlsx', 'xls'].some((f) => f == fileType);
}
if (!isDAE) {
setMsg(`只能上传 ${['xlsx', 'xls'].join()} 格式的文件!`);
return false;
}
},
onChange(info) {
<a
href={
"/_api/" +
`attachments?src=files/用户信息导入模板.xlsx&filename=${encodeURIComponent(
"用户信息导入模板.xlsx"
)}&token=${user.token}`
}
>
<Button size="small" type="primary">
下载模板
</Button>
</a>
<div style={{ marginTop: 10 }}>下载模板后填写完整后上传</div>
<div style={{ marginTop: 10 }}>
<Upload
{...{
name: "user_d",
action: "/",
maxCount: 1,
showUploadList: {
showRemoveIcon: false,
},
beforeUpload: (file) => {
setMsg("");
setPostData([]);
const extNames = file.name.split(".");
let isDAE = false;
if (extNames.length > 0) {
let fileType = extNames[extNames.length - 1].toLowerCase();
isDAE = ["xlsx", "xls"].some((f) => f == fileType);
}
if (!isDAE) {
setMsg(`只能上传 ${["xlsx", "xls"].join()} 格式的文件!`);
return false;
}
},
onChange(info) {},
customRequest: async (data) => {
const { file, onSuccess, onError } = data;
},
customRequest: async (data) => {
const { file, onSuccess, onError } = data
const reader = new FileReader(); // 使用 FileReader 读取数据
reader.onload = function (e) {
// 数据读取完成后的回调函数
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: "array" }); // workbook 是 xlsx 解析 excel 后返回的对象
const reader = new FileReader(); // 使用 FileReader 读取数据
reader.onload = function (e) { // 数据读取完成后的回调函数
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: 'array' }); // workbook 是 xlsx 解析 excel 后返回的对象
const firstSheetName = workbook.SheetNames[0]; // 获取第一个 sheet 的名字
const worksheet = workbook.Sheets[firstSheetName]; // 获取第一个 sheet 的内容
const res = XLSX.utils.sheet_to_json(worksheet); // 使用 utils 里的方法转换内容为便于使用的数组
console.log(res);
const error = (msg) => {
setMsg(msg);
onError({ message: msg });
};
if (res.length > 1000) {
error("一次性上传数据行数应小于1000行,请分批上传");
return;
}
if (!res.length) {
error("请填写至少一行数据");
return;
}
let postData = [];
const firstSheetName = workbook.SheetNames[0]; // 获取第一个 sheet 的名字
const worksheet = workbook.Sheets[firstSheetName]; // 获取第一个 sheet 的内容
const res = XLSX.utils.sheet_to_json(worksheet); // 使用 utils 里的方法转换内容为便于使用的数组
const error = (msg) => {
setMsg(msg)
onError({ message: msg })
}
if (res.length > 1000) {
error('一次性上传数据行数应小于1000行,请分批上传')
return
}
if (!res.length) {
error('请填写至少一行数据')
return
}
let postData = []
const pattern = /^1[3|4|5|6|7|8|9]\d{9}$/
for (let i = 0; i < res.length; i++) {
let d = res[i]
let name = String(d['姓名']).trim();
let phone = String(d['手机号码']).trim();
let account = String(d['账号']).trim();
let peopleCode = d['人员编号'] && String(d['人员编号']).trim();
if (!name || !phone || !account || !peopleCode) {
error(`${i + 1} 行有空值,请填写后重新上传`)
return
}
if (!pattern.test(phone)) {
error(`${i + 1} 行手机号码错误`)
return
}
if (name.length > 128 || account.length > 128) {
error(`${i + 1} 行数据字符长度大于 128,请更改后重新上传`)
return
}
if (postData.some(p => p.account == account)) {
error(`${i + 1} 行账号重复,请更改后重新上传`)
return
}
postData.push({
name, phone, account, peopleCode
})
}
if (postData.length) {
setPostData(postData)
}
let msg = '文件解析完成,点击确定按钮上传保存!'
setMsg(msg)
onSuccess({ message: msg })
};
reader.readAsArrayBuffer(file); // 读取数据
},
}}>
<Button>上传文件</Button>
</Upload>
<br />
<span>{msg}</span>
</div>
</Modal >
)
}
for (let i = 0; i < res.length; i++) {
let d = res[i];
let name_people = String(d["人员姓名"]).trim();
let post_people = String(d["岗位"]).trim();
let time = String(d["本周计划"]).trim();
let project = String(d["本周任务"]).trim();
if (!name_people || !post_people || !time || !project) {
error(`${i + 1} 行有空值,请填写后重新上传`);
return;
}
postData.push({
name_people,
post_people,
time,
project,
});
}
if (postData.length) {
let newArray = postData.reduce((total, cur, index) => {
let hasValue = total.findIndex((current) => {
return current.name_people === cur.name_people;
});
let obj = {
name_people: cur.name_people,
post_people: cur.post_people,
work: [
{
time: cur.time,
project: cur.project,
},
],
};
let obj1 = {
time: cur.time,
project: cur.project,
};
hasValue === -1 && total.push(obj);
hasValue !== -1 && total[hasValue].work.push(obj1);
return total;
}, []);
console.log(newArray);
setPostData(newArray);
}
let msg = "文件解析完成,点击确定按钮上传保存!";
setMsg(msg);
onSuccess({ message: msg });
};
reader.readAsArrayBuffer(file); // 读取数据
},
}}
>
<Button>上传文件</Button>
</Upload>
<br />
<span>{msg}</span>
</div>
</Modal>
);
};
function mapStateToProps(state) {
const { auth, customizeList } = state;
return {
user: auth.user,
}
const { auth, customizeList } = state;
return {
user: auth.user,
};
}
export default connect(mapStateToProps)(ImportUser);
export default connect(mapStateToProps)(ImportUser);

116
web/client/src/sections/personnel/components/modeal.js

@ -1,5 +1,6 @@
import React,{useState,useEffect} from 'react'
import { Modal, Form, Input, Button,DatePicker,Select } from 'antd'
import { Modal, Form, Input, Button, DatePicker, Space } from 'antd'
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
function modeal(props) {
const [form] = Form.useForm();
@ -8,11 +9,12 @@ function modeal(props) {
useEffect(() => {
if (editData && visible) {
form.setFieldsValue({
name_project: editData.name_project,
part_people: editData.part_people,
build_time: dayjs(editData?.build_time),
publish_time: dayjs(editData.publish_time),
progress:editData.progress
name_people: editData.name_people,
post_people: editData.post_people,
progress: editData.progress,
time:editData.work.map((i)=>i.time),
project:editData.work.map((i)=>i.project)
})
}
}, [editData, visible])
@ -21,7 +23,7 @@ function modeal(props) {
visible={visible}
onCancel={handleCancel}
footer={null}
title="研发看板项目编辑"
title="研发看板人员编辑"
>
<Form
name="basic"
@ -31,44 +33,80 @@ function modeal(props) {
autoComplete="off"
>
<Form.Item
label="项目计划"
name="name_project"
rules={[{ required: true, message: '请输入项目计划' }]}
label="人员姓名"
name="name_people"
rules={[{ required: true, message: '请输入人员姓名' }]}
>
<Input/>
</Form.Item>
<Form.Item
label="投入人力"
name="part_people"
rules={[{ required: true, message: '请输入人员姓名' }]}
label="岗位"
name="post_people"
rules={[{ required: true, message: '请输入岗位' }]}
>
<Input/>
</Form.Item>
<Form.Item
label="构建时间"
name="build_time"
rules={[{ required: true, message: '请选择时间' }]}
>
<DatePicker />
</Form.Item>
<Form.Item
label="发布时间"
name="publish_time"
rules={[{ required: true, message: '请选择时间' }]}
>
<DatePicker />
</Form.Item>
<Form.Item
label="目前进度"
name="progress"
rules={[{ required: true, message: '请选择进度' }]}
>
<Select><Select.Option value="需求评审中">需求评审中</Select.Option>
<Select.Option value="研发中">研发中</Select.Option>
<Select.Option value="测试中">测试中</Select.Option>
<Select.Option value="已发布">已发布</Select.Option>
</Select>
</Form.Item>
</Form.Item>
{/* {editData?.work.map(() => {
return <> <Form.Item
label="本周计划"
name="time"
rules={[{ required: true, message: '请填写工作计划' }]}
>
<Input/>
</Form.Item>
<Form.Item
label="本周任务"
name="project"
rules={[{ required: true, message: '请填写工作计划' }]}
>
<Input/>
</Form.Item></>
})} */}
<Form.List name="users">
{(fields, { add, remove }) => (
<>
{editData?.work.map(({ key, name, ...restField }) => (
<Space
key={key}
style={{
display: 'flex',
marginBottom: 8,
}}
align="baseline"
>
<Form.Item
{...restField}
name={[name, 'first']}
rules={[
{
required: true,
message: 'Missing first name',
},
]}
>
<Input placeholder="First Name" />
</Form.Item>
<Form.Item
{...restField}
name={[name, 'last']}
rules={[
{
required: true,
message: 'Missing last name',
},
]}
>
<Input placeholder="Last Name" />
</Form.Item>
</Space>
))}
<Form.Item>
</Form.Item>
</>
)}
</Form.List>
<Form.Item noStyle={true}>
<div style={{
padding: '12px 0',

48
web/client/src/sections/personnel/containers/index.js

@ -3,7 +3,7 @@ import React, { useEffect, useState, useRef } from "react";
import { connect } from "react-redux";
import { Button, Popconfirm } from "antd";
import ProTable from "@ant-design/pro-table";
import Action from "../actions/index";
import {postOutPeople} from "../actions/article";
import moment from "moment";
import { push } from "react-router-redux";
import { Scroller } from "$components";
@ -25,29 +25,31 @@ export const Default = (props) => {
const columns = [
{
title: "人员姓名",
dataIndex: "name_project",
key: "name_project",
dataIndex: "name_people",
key: "name_people",
hideInSearch: true,
render: (dom, record) => {
return record.name_project;
return record.name_people;
},
},
{
title: "岗位",
key: "category",
dataIndex: "part_people",
key: "post_people",
dataIndex: "post_people",
hideInSearch: true,
render: (dom, record) => {
return record.part_people
return record.post_people
},
},
{
title: "本周工作计划",
key: "build_time",
dataIndex: "build_time",
key: "work",
dataIndex: "work",
hideInSearch: true,
render: (dom, record) => {
return moment(record.build_time).format('YYYY-MM-DD')
return <div>{record?.work?.map((item) => {
return <div><span>{item.time}</span><span>{item.project }</span></div>
})}</div>
},
},
{
@ -125,32 +127,20 @@ export const Default = (props) => {
return (
<div style={{ height: "100%" }}>
<Scroller containerId={"article-container-query"} height={"100%"}>
<ProTable
<ProTable
actionRef={tableActionRef}
columns={columns}
options={false}
dataSource={dataSore}
dataSource={counts||[]}
search={{
optionRender: false,
collapsed: false,
}}
request={async (params) => {
let query = {
type: -1,
searchValue: heading,
status: state,
page: params.current,
limit: params.pageSize,
publishTime:
day && day.length && day[0].trim() != ""
? JSON.stringify([
moment(day[0]).startOf("day"),
moment(day[1]).endOf("day"),
])
: null,
};
const res = await dispatch(Action.getDataList(query));
setCounts(res.payload.data);
request={async(params) => {
console.log(params)
const res = await dispatch(postOutPeople());
setCounts(res.payload.data.projects);
return {
...res,
total: res.payload.data ? res.payload.data.total : 0,

2
web/client/src/sections/personnel/nav-item.js

@ -6,7 +6,7 @@ import { BarChartOutlined } from '@ant-design/icons';
export function getNavItem() {
return (
<Menu.Item key="personnel" icon={<BarChartOutlined />}>
<Link to="/personnel">项目信息</Link>
<Link to="/personnel">人员任务</Link>
</Menu.Item>
);
}

156
web/client/src/utils/webapi.js

@ -2,156 +2,12 @@ import request from "superagent";
import noCache from "superagent-no-cache";
export const ApiTable = {
/* 研发看板 */
getProjectUrl: "outProject", // 在研项目
getPeopleUrl: "outPeople", // 人员情况
getWaitUrl: "outWait", // 待研项目
getDataList: "article/management", //全部资讯
delDataList: "article/management", //删除资讯
addArticle: "article/management",
checkDomain: "domain/{domain}",
resetPwd: "reset/password",
phoneVCode: "validate/phone",
checkPhone: "check/phone",
checkRegcode: "validate/regcode",
login: "login",
logout: "logout",
/* 个人设置 */
getUserInfo: "users/{userId}/details",
modifyUserInfo: "users/{userId}/{type}",
modifyEmail: "users/{userId}/email",
modifyAvator: "user/{userId}/avator",
modifySmsEnable: "users/{userId}/sms-notification/enable",
modifyEmailEnable: "users/{userId}/email-notification/enable",
modifySmsDisable: "users/{userId}/sms-notification/disable",
modifyEmailDisable: "users/{userId}/email-notification/disable",
modifyWxEnable: "/users/{userId}/wx-notification/enable",
modifyWxDisable: "/users/{userId}/wx-notification/disable",
midifyDndEnable: "users/{userId}/dnd/enable",
modifyDndDisable: "users/{userId}/dnd/disable",
modifyPassWord: "users/{userId}/password",
modifyName: "users/{userId}/name",
/* 企业 */
getEnterprisesDetails: "users/{userId}/enterprises/details",
getEnterprisesMembers: "enterprises/{enterpriseId}/members",
getEnterprisesRoles: "enterprises/{enterpriseId}/roles",
getPostsUrl: "posts",
addDepartment: "enterprises/{enterpriseId}/departments",
deleteDepartment: "departments/{departmentId}",
modifyDepartment: "departments/{departmentId}/rename",
sortDepartment: "departments/sort",
sortDepartmentUsers: "department/users/sort",
enableMember: "members/{memberId}/enable",
disableMember: "members/{memberId}/disable",
addMember: "members",
deleteMember: "members/{memberId}",
modifyMember: "members/{memberId}",
modifyEnterprise: "enterprises/{enterpriseId}",
/* 权限 */
getAuthorList: "org/{orgId}/resources",
getProejectAuthorList: "org/{orgId}/project/resources",
getAuthorByRoleId: "role/{roleId}/resources",
modifyAuthor: "role/{roleId}/resources",
modifyRoleUsers: "role/{roleId}/users",
modifyRoleStructures: "role/{roleId}/structures",
modifyDepartmentUsers: "department/{depId}/users",
deleteRoleUsers: "role/{roleId}/users/remove",
getDepartmentResources: "orgs/{orgId}/department/resources?platform=true",
modifyDepartmentResources: "department/{departmentId}/resources",
addGroupRoleUrl: "group/role",
groupRoleUrlById: "group/{groupId}/role",
addRoleUrl: "role",
roleUrlById: "role/{roleId}",
/* 项目 */
getProjects: "users/{userId}/projects",
addProject: "users/{userId}/projects",
editProject: "projects/{projectId}",
deleteProject: "projects/{projectId}",
editProjectAdmin: "projects/{projectId}/admin",
editProjectUrl: "projects/{projectId}/url",
applyProject: "projects/{projectId}/apply",
reviewedProject: "projects/{projectId}/reviewed",
publishProject: "projects/{projectId}/publish",
generateReviewReport: "reports/review/immediately",
getReviewReport: "reports/review",
changeProjectEventState: "projects/{projectId}/evnetState",
/* 结构物管理 */
getStructsList: "organizations/{organizationId}/structures",
getStructsListWithoutIOTA:
"organizations/{organizationId}/withoutiota/structures",
// 系统日志
getSystemLog: "/log",
// 大屏
getCarstatisticsUrl: "statistics/cars",
getAlarmsUrl: "alarms",
getDevicesUrl: "devices",
getVideoToken: "video/accessToken",
getVideoList: "video/list",
getLastDataUrl: "last-data/{structId}",
// 隧道配置
getTunnels: "tunnels",
getTunnelSystems: "tunnel/systems",
createTunnel: "tunnel",
modifyTunnel: "tunnel/{tunnelId}",
// 设备配置
getDevices: "devices",
getDeviceTypes: "device/types",
createDevice: "device",
modifyDevice: "device/{deviceId}",
getDeviceStatistics: "devices/statistics/{key}",
getDeviceStatusRecords: "devices/status-records",
// 广播系统
getBroadcastLogin: "control/20140901/infs/login.json",
getBroadcastEmployee: "control/api_v2.2.5/employee/query/queryAll.json",
getBroadcastTask: "control/api_v2.2.5/broad/query/all.json",
getPhoneRecords: "control/20210628/infs/getAllCdrs.json",
getBroadcastAlarms: "control/api_v2.2.5/alarm/query/queryAll.json",
// 视频模块
getTunnelVideos: "tunnel/{id}/videos",
ptzsControl: "tunnel/{id}/ptzsControl",
getTrafficFlow: "traffic/{id}",
getVideoUrls: "video/{id}/urls",
getTerminals: "tunnel/{id}/terminals",
getTerminalDetail: "terminal/{id}/detail",
getTunnelVideosById: "tunnel/{id}/videos",
getRobotRequest: "tunnel/{id}/robot",
// 操作日志配置
getLogs: "logs",
createLog: "log",
modifyLog: "log/{logId}",
// 积水健康监测
fsLoginUrl: "login",
getSensorsStations: "structures/{structureId}/sensors-stations",
getFactorDevice: "structures/{structureId}/factors/{factorId}/devices",
getStationsData:
"structures/{structureId}/factors/{factorId}/stations/data?startTime={startTime}&endTime={endTime}",
getBatchThreshold:
"structures/{structId}/factors/{factorId}/threshold/batches",
getStationThemesData: "stations/theme/data",
getStations: "structures/{structureId}/stations",
// 告警管理
getAlarms: "users/{userId}/alarms",
modifyAlarmChecked: "alarms/check",
// 机器人
robotRequest: "tunnel/{id}/robot",
//党员工会人数统计接口
getpartyMember: "laborUnion/count",
// 文章获取
getText: "article/management/query",
/* 研发看板 */
projectUrl: "outProject", // 在研项目
peopleUrl: "outPeople", // 人员情况
waitUrl: "outWait", // 待研项目
postInProject:'inProject', // 增加项目
postInPeople:'inPeople',//增加人员任务
//支委会人员信息
getCommittee: "partyOrganizations", //获取支委会人员
postCommittee: "partyOrganization", //新增

2
web/package.json

@ -6,7 +6,7 @@
"scripts": {
"test": "mocha",
"start": "cross-env NODE_ENV=development npm run start-params",
"start-params": "npm run color && node server -p 5002 -u http://127.0.0.1:3000",
"start-params": "npm run color && node server -p 5002 -u http://localhost:8080",
"deploy": "export NODE_ENV=production&&npm run color && npm run build && node server",
"build-dev": "export NODE_ENV=development&&webpack --config webpack.config.js",
"build": "export NODE_ENV=production&&npm run color&&webpack --config webpack.config.prod.js",

2
web/readme.md

@ -203,7 +203,7 @@
function mapStateToProps(state) {
const { auth, global, members } = state;
return {
loading: members.isRequesting,
<!-- loading: members.isRequesting, -->
user: auth.user,
actions: global.actions,
members: members.data,

Loading…
Cancel
Save