Merge branch 'release_20220715' into 'master'

【生产】7.15版本同步到Master

See merge request eshop/fe_service_ebtp_frontend!188
This commit is contained in:
周建龙
2022-07-18 08:38:13 +08:00
16 changed files with 1066 additions and 27 deletions

View File

@ -9,7 +9,7 @@ export default [
...transfer,//跳转、登陆 ...transfer,//跳转、登陆
//审批单 //审批单
...approvalForm, ...approvalForm,
//党员专题 //党建攻坚
...partyMemberTopic, ...partyMemberTopic,
{ {
path: '/userformal', path: '/userformal',
@ -32,10 +32,15 @@ export default [
], ],
}, },
//日历组件暂时用 //日历组件暂时用
{ // {
path: '/Calendar', // path: '/Calendar',
component: './MainPage/ProjectManager/components/CalendarForm', // component: './MainPage/ProjectManager/components/CalendarForm',
}, // },
//富文本组件
// {
// path: '/editor',
// component: './MainPage/ProjectManager/components/WangEditor',
// },
//401错误页 //401错误页
{ {
exact: true, exact: true,
@ -243,7 +248,7 @@ export default [
path: '/Supervision', path: '/Supervision',
component: './Project/ProjectManage/Supervision' component: './Project/ProjectManage/Supervision'
}, },
{//审查人员 项目管理页 {//审查人员 项目管理页
name: 'Examination', name: 'Examination',
path: '/Examination', path: '/Examination',
component: './Project/ProjectManage/Examination' component: './Project/ProjectManage/Examination'

View File

@ -43,6 +43,11 @@ export default [
path: '/partyMemberTopic/newsDetail', path: '/partyMemberTopic/newsDetail',
component: './PartyMemberTopic/NewsDetail', component: './PartyMemberTopic/NewsDetail',
}, },
{//管理端首页
name: 'manage',
path: '/partyMemberTopic/manage',
component: './PartyMemberTopic/Management/Manage',
},
] ]
} },
]; ];

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -1,7 +1,10 @@
import React, { useEffect, useImperativeHandle, useState } from 'react'; import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
import AlertMenu from './fullScreen' import AlertMenu from './fullScreen'
import E from 'wangeditor'; import E from 'wangeditor';
import { Button } from 'antd'; import { Button, message, Spin } from 'antd';
import { pictureDisplayPath, uploadAttachmentPath } from '@/utils/DownloadUtils';
import { isEmpty, isNotEmpty } from '@/utils/CommonUtils';
import { createNewFileBid } from '@/services/download_';
interface WangType { interface WangType {
braftRef: any;//挂载 braftRef: any;//挂载
@ -9,7 +12,9 @@ interface WangType {
echo?: any;//回显内容 echo?: any;//回显内容
value?: any; value?: any;
height?: number; height?: number;
onChange?: (value: any) => void onChange?: (value: any) => void;
useImage?: boolean;//使用图片上传
imageId?: string;//图片objectId
} }
let editor: any = null; let editor: any = null;
@ -21,6 +26,10 @@ const BraftText: React.FC<WangType> = (props) => {
//======================================================================================state //======================================================================================state
const [content, setContent] = useState(''); const [content, setContent] = useState('');
const [fullScreen, fullScreenSet] = useState(false); const [fullScreen, fullScreenSet] = useState(false);
//遮罩
const [loading, setLoading] = useState(false);
//imageId
const objectId = useRef<string | null | undefined>(null);
const { const {
braftRef, braftRef,
echo, echo,
@ -28,12 +37,14 @@ const BraftText: React.FC<WangType> = (props) => {
value, value,
height, height,
onChange, onChange,
useImage,
imageId,
} = props; } = props;
const tools = [//工具栏 const tools = [//工具栏
'head',//标题 'head',//标题
'fontSize', //字号 'fontSize', //字号
'lineHeight', //行高 // 'lineHeight', //行高
'foreColor', //颜色 'foreColor', //颜色
'bold', //加粗 'bold', //加粗
'italic', //斜体 'italic', //斜体
@ -41,12 +52,13 @@ const BraftText: React.FC<WangType> = (props) => {
'strikeThrough', //文字删除线 'strikeThrough', //文字删除线
'indent', //缩进 'indent', //缩进
'justify', //文字对齐方式 'justify', //文字对齐方式
'list', //列表
'undo', //撤销 'undo', //撤销
'redo', //重做 'redo', //恢复
'fullscreen', //全屏 'fullscreen', //全屏
// 'emoticon',//表情
// 'image',//图片 // 'image',//图片
// 'emoticon',//表情
// 'video',//视频 // 'video',//视频
// 'table',//表格 // 'table',//表格
// 'todo',//待办 // 'todo',//待办
@ -56,12 +68,14 @@ const BraftText: React.FC<WangType> = (props) => {
useEffect(() => { useEffect(() => {
if (willCreate) { if (willCreate) {
// 注class写法需要在componentDidMount 创建编辑器 // 注class写法需要在componentDidMount 创建编辑器
editor = new E("#div1") editor = new E("#div1");
//添加图片上传
useImage && tools.splice(-3, 0, 'image');
//工具栏 //工具栏
editor.config.menus = tools; editor.config.menus = tools;
//提示 //提示
editor.config.placeholder = '为了能顺利发布,建议您内容去掉下划线等格式,尽量以纯文本形式发布。' editor.config.placeholder = '为了能顺利发布,建议您内容去掉下划线等格式,尽量以纯文本形式发布。';
// 配置 onchange 回调函数 // 配置 onchange 回调函数
editor.config.onchange = editorOnChange; editor.config.onchange = editorOnChange;
// 注册菜单 // 注册菜单
@ -73,6 +87,104 @@ const BraftText: React.FC<WangType> = (props) => {
// 设置编辑区域高度为 500px // 设置编辑区域高度为 500px
height && (editor.config.height = height); height && (editor.config.height = height);
//关闭网络上传图片
editor.config.showLinkImg = false;
// 关闭粘贴内容中的样式
editor.config.pasteFilterStyle = false;
// 忽略粘贴内容中的图片
editor.config.pasteIgnoreImg = true;
// 上传图片到服务器,对应的是controller层的@RequestMapping("/upload")
editor.config.uploadImgServer = uploadAttachmentPath;//接口名称
//自定义name,接收的时候图片文件的那么用这个对应的是参数中的MultipartFile upimg名称,这个名称即上传到浏览器的参数名称
editor.config.uploadFileName = "multipartFiles";//这个需要和后台商量上传图片的名称
//设置请求体额外参数
if (useImage) {
if (isEmpty(imageId)) {
createNewFileBid().then(res => {//获取雪花id
editor.config.uploadImgParams = {
appCode: 'ebtp-cloud-frontend',
objectId: res?.id,
};
objectId.current = res?.id;
})
} else {
editor.config.uploadImgParams = {
appCode: 'ebtp-cloud-frontend',
objectId: imageId,
};
objectId.current = imageId;
}
}
// 将 timeout 时间改为 60s
editor.config.uploadImgTimeout = 60000;
// 将图片大小限制为 600k
editor.config.uploadImgMaxSize = 600 * 1024;
// 限制一次最多上传 1 张图片
editor.config.uploadImgMaxLength = 1;
//上传图片的错误提示默认使用alert弹出,也可以自定义用户体验更好的提示方式
editor.config.customAlert = function (info: string) {
const repinfo = info.replace(/0.5859375M/g, '600K');
// info 是需要提示的内容
message.error(repinfo);
};
// 上传图片的结果反馈
editor.config.uploadImgHooks = {
before: function (xhr: any, editor: any, files: any) {
// 图片上传之前触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象files 是选择的图片文件
// 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
// return {
// prevent: true,
// msg: '放弃上传'
// }
// console.log("before:",xhr)
if (isEmpty(objectId.current)) {
return {
prevent: true,
msg: '上传失败,原因:上传参数错误'
}
}
setLoading(true);
return {
prevent: false,
}
},
success: function (xhr: any, editor: any, result: any) {
// 图片上传并返回结果,图片插入成功之后触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象result 是服务器端返回的结果
// console.log("success:",result)
},
fail: function (xhr: any, editor: any, result: any) {
// 图片上传并返回结果,但图片插入错误时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象result 是服务器端返回的结果
},
error: function (xhr: any, editor: any) {
// 图片上传出错时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象
},
// 上传图片超时
timeout: function (xhr: any) {
message.error('服务器超时!');
setLoading(false);
},
// 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
// (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
customInsert: function (insertImg: (arg0: any) => void, result: any, editor: any) {
// 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
// insertImg 是插入图片的函数参数editor 是编辑器对象result 是服务器端返回的结果
// 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
if (result?.success) {
const url = pictureDisplayPath + '?filePath=' + result.data[0].sysStorageVO.filePath;
insertImg(url);
} else {
message.error('图片上传失败!');
}
setLoading(false);
// var url = result.result.remote_path;
// insertImg(url);
// result 必须是一个 JSON 格式字符串!!!否则报错
}
};
/**一定要创建 */ /**一定要创建 */
editor.create(); editor.create();
@ -82,15 +194,18 @@ const BraftText: React.FC<WangType> = (props) => {
willCreate = false; willCreate = false;
} }
// 重新设置编辑器内容
echo && editor.txt.html(echo);
value && editor.txt.html(value);
return () => { return () => {
// 组件销毁时销毁编辑器 注class写法需要在componentWillUnmount中调用 // 组件销毁时销毁编辑器 注class写法需要在componentWillUnmount中调用
editor.destroy() editor.destroy()
setLoading(false);
setContent('');
} }
}, [value, echo]); }, []);
useEffect(() => {
// 重新设置编辑器内容
echo && editor.txt.html(echo);
}, [echo])
/** /**
*提供给父级的内容 *提供给父级的内容
**/ **/
@ -99,6 +214,7 @@ const BraftText: React.FC<WangType> = (props) => {
getHtml, getHtml,
getHtml1, getHtml1,
makeDis, makeDis,
getImageId,
})); }));
// 获取html方法1 // 获取html方法1
@ -131,12 +247,17 @@ const BraftText: React.FC<WangType> = (props) => {
const triggerChange = (newHtml: any) => { const triggerChange = (newHtml: any) => {
onChange?.(newHtml); onChange?.(newHtml);
}; };
//获取富文本图片objectId
function getImageId() {
return objectId.current;
}
return ( return (
<div> <Spin spinning={loading} tip={"上传中……"}>
{/* <Button onClick={() => { editor.enable() }}>全屏</Button> <div>
<Button onClick={() => { editor.disable() }}>全屏</Button> */} <div id="div1" style={{ textAlign: 'left' }}></div>
<div id="div1" style={{ textAlign: 'left' }}></div> </div>
</div> </Spin>
) )
} }
export default BraftText export default BraftText

View File

@ -340,6 +340,10 @@
color: #c9c9c9; color: #c9c9c9;
} }
.right-manager {
margin-top: 12px;
}
// .right-graph { // .right-graph {
// padding-top: 26px; // padding-top: 26px;

View File

@ -11,6 +11,7 @@ import topic_other from '@/assets/topic/topic_other.png'
import topic_project_picture from '@/assets/topic/topic_project_picture.jpg' import topic_project_picture from '@/assets/topic/topic_project_picture.jpg'
import topic_bottom_button from '@/assets/topic/topic_bottom_button.png' import topic_bottom_button from '@/assets/topic/topic_bottom_button.png'
import topic_right_material from '@/assets/topic/topic_right_material.png' import topic_right_material from '@/assets/topic/topic_right_material.png'
import topic_right_manager from '@/assets/topic/topic_right_manager.jpg'
import topic_partymember from '@/assets/topic/topic_partymember.png' import topic_partymember from '@/assets/topic/topic_partymember.png'
import topic_partybranch from '@/assets/topic/topic_partybranch.png' import topic_partybranch from '@/assets/topic/topic_partybranch.png'
import topic_totalamount from '@/assets/topic/topic_totalamount.png' import topic_totalamount from '@/assets/topic/topic_totalamount.png'
@ -25,11 +26,11 @@ import topic_interview from '@/assets/topic/topic_interview.png'
import topic_assure from '@/assets/topic/topic_assure.png' import topic_assure from '@/assets/topic/topic_assure.png'
import topic_difficult from '@/assets/topic/topic_difficult.png' import topic_difficult from '@/assets/topic/topic_difficult.png'
import { getHomeActivity, getHomeBanner, getHomeContact, getHomeGraceful, getHomeProject, getHomeRight, submitAdvice } from './service'; import { getHomeActivity, getHomeBanner, getHomeContact, getHomeGraceful, getHomeProject, getHomeRight, submitAdvice } from './service';
import { chunk, formatTime, getImageUrl } from '../utils'; import { chunk, formatTime, getImageUrl, managerAuthority } from '../utils';
import ExtendUpload from '@/utils/ExtendUpload'; import ExtendUpload from '@/utils/ExtendUpload';
import { getSessionUserData } from '@/utils/session'; import { getSessionUserData } from '@/utils/session';
const tagsData = ['集团总部', '北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '山东', '河南', '上海', '江苏', '浙江', '安徽', '福建', '江西', '湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州', '云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆', '数字科技', '联通在线', '智网科技', '支付公司', '财务公司', '融资租赁', '时科(北京)信息']; const tagsData = ['集团总部', '北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '山东', '河南', '上海', '江苏', '浙江', '安徽', '福建', '江西', '湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州', '云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆', '数字科技', '联通在线', '智网科技', '支付公司', '财务公司', '融资租赁', '时科(北京)信息', '中讯院'];
const formItemLayout = { const formItemLayout = {
labelCol: { span: 5 }, labelCol: { span: 5 },
@ -589,6 +590,14 @@ const Home: React.FC<{}> = () => {
<RightDisplayContent index={8} data={rightList} img={topic_assure} color="number-purple" /> <RightDisplayContent index={8} data={rightList} img={topic_assure} color="number-purple" />
<RightDisplayContent index={9} data={rightList} img={topic_difficult} color="number-purple" /> <RightDisplayContent index={9} data={rightList} img={topic_difficult} color="number-purple" />
</div> </div>
{managerAuthority("ebtp-party-admin") ? null : (
<>
<Divider className='right-divider' />
<div className='right-manager'>
<img src={topic_right_manager} className='right-material' onClick={() => window.open("/partyMemberTopic/manage")} />
</div>
</>
)}
</div> </div>
</div> </div>
<div className='bottom-global'> <div className='bottom-global'>

View File

@ -0,0 +1,200 @@
import React, { useEffect, useRef, useState } from 'react';
import { Modal, Col, Form, Input, Row, Select, Spin, message } from 'antd';
import BraftText from '@/components/richText/wang';
import ExtendUpload from '@/utils/ExtendUpload';
import { isEmpty, isNotEmpty } from '@/pages/PartyMemberTopic/utils';
import { getSessionUserData } from '@/utils/session';
import moment from 'moment';
import { saveEventData } from '../service';
const layout = {
labelCol: { span: 3 },
wrapperCol: { span: 21 },
};
const validateMessages = {
required: '请填写此项',
};
const modalHeight = window.innerHeight * 96 / 100;
interface EventMaintenanceModalProps {
modalVisible: boolean;
onCancel: () => void;
record: any;
}
const EventMaintenanceModal: React.FC<EventMaintenanceModalProps> = (props) => {
const { modalVisible, onCancel, record } = props;
const [form] = Form.useForm();
const { Option } = Select;
const { TextArea } = Input;
const braftRef = useRef<any>(null);
//userData
const userData = getSessionUserData();
//只读 true只读 false编辑
const readOnly: boolean = record.editCode == "2";
//上传文件id
const [imageId, setImageId] = useState<string>('');
//富文本正文图片objectId
const [contentImageId, setContentImageId] = useState<string>('');
//富文本正文
const [content, setContent] = useState<string>('');
//活动类型选择
const [typeSelect, setTypeSelect] = useState<string>('');
//loading
const [loading, setLoading] = useState<boolean>(false);
//保存
const onSubmit = () => {
if (isNotEmpty(typeSelect) && typeSelect != "3" && isEmpty(form.getFieldValue("image"))) {
message.error("请上传主图");
return;
}
if (isEmpty(braftRef.current.getHtml())) {
message.error("请编辑正文内容");
return;
}
form.validateFields().then(values => {
const data = {
banner: null,
createBy: null,
id: null,
image: null,
secordTitle: null,
sendTime: null,
sort: null,
status: null,
title: null,
type: null,
...values,
content: braftRef.current.getHtml(),
contentImageId: braftRef.current.getImageId(),
createTime: null,
}
setLoading(true);
saveEventData(data).then(res => {
if (res?.code == 200) {
message.success('保存成功');
onCancel();
}
}).finally(() => {
setLoading(false);
})
})
};
const onTypeChage = (value: any) => {
setTypeSelect(value);
};
useEffect(() => {
if (record.editCode == "0") {//新建
form.setFieldsValue({
id: null,
createBy: userData?.fullName,
createTime: moment().format("YYYY-MM-DD HH:mm:ss"),
});
} else if (record.editCode == "1" || record.editCode == "2") {//编辑 查看
form.setFieldsValue(record);
setImageId(record?.image);
setContentImageId(record?.contentImageId);
setContent(record?.content);
onTypeChage(record?.type);
}
return () => {
setImageId('');
setContentImageId('');
setTypeSelect('');
setContent('');
setLoading(false);
};
}, [record?.id])
return (
<Modal
destroyOnClose
title={record.editCode == "0" ? "新建" : record.editCode == "1" ? "编辑" : "查看"}
visible={modalVisible}
onCancel={() => onCancel()}
onOk={() => onSubmit()}
okButtonProps={{ loading: loading, hidden: readOnly }}
okText="保存"
maskClosable={false}
style={{ maxHeight: modalHeight }}
bodyStyle={{ maxHeight: modalHeight - 108, overflowY: 'auto', }}
centered
cancelText="返回"
width={'70%'}
>
<Spin spinning={loading}>
<Form
{...layout}
name="nest-messages"
form={form}
validateMessages={validateMessages}
preserve={false}
>
<Form.Item name="id" hidden>
<Input />
</Form.Item>
<Form.Item name="type" label="活动类型" rules={[{ required: !readOnly }]}>
<Select style={{ width: 150 }} onChange={onTypeChage} disabled={readOnly}>
<Option value="1"></Option>
<Option value="2"></Option>
<Option value="3"></Option>
</Select>
</Form.Item>
<Form.Item
name="title"
label="标题名称"
rules={[{ required: !readOnly }]}
tooltip="此项不超过18个汉字"
>
<Input maxLength={18} disabled={readOnly} placeholder="请填写标题不超过18个汉字" />
</Form.Item>
{typeSelect == "2" && <Form.Item
name="secordTitle"
label="副标题名称"
rules={[{ required: typeSelect == "2" && !readOnly }]}
tooltip="此项不超过120个汉字"
>
<TextArea autoSize maxLength={120} disabled={readOnly} placeholder="请填写副标题不超过120个汉字" />
</Form.Item>}
{(isNotEmpty(typeSelect) && typeSelect != "3") && <Form.Item
name="image"
label="主图"
extra="注为了避免页面进入加载时间过长照片尽量压缩至500K左右"
required={!readOnly}
>
<ExtendUpload bid={imageId} btnName="上传" maxCount={1} maxSize={0.6} uploadProps={{ name: "file", disabled: readOnly, accept: ".jfif,.pjpeg,.jpeg,.pjp,.jpg,.png,.gif,.bmp,.dib" }} />
</Form.Item>}
<Form.Item label="编制人员" style={{ margin: 0 }}>
<Row>
<Col span={10}>
<Form.Item name="createBy">
<Input readOnly disabled={readOnly} />
</Form.Item>
</Col>
<Col span={12} offset={2}>
<Form.Item name="createTime" label="编制日期">
<Input readOnly disabled={readOnly} />
</Form.Item>
</Col>
</Row>
</Form.Item>
<Form.Item name="content" label="正文内容">
{readOnly ? (
<div style={{ border: '1px solid #c9d8db', padding: '16px', overflowX: 'auto' }}>
<div dangerouslySetInnerHTML={{ __html: record?.content }}></div>
</div>
) : (
<BraftText braftRef={braftRef} echo={content} disabled={false} useImage imageId={contentImageId} />
)}
</Form.Item>
</Form>
</Spin>
</Modal>
);
};
export default EventMaintenanceModal;

View File

@ -0,0 +1,236 @@
import { PlusOutlined } from '@ant-design/icons';
import { ActionType, ProColumns } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { Button, Card, message, Popconfirm } from 'antd';
import React, { useState } from 'react';
import { useRef } from 'react';
import EventMaintenanceModal from './components/EventMaintenanceModal';
import { changeEventStatus, deleteEvent, getEventList } from './service';
import { managerAuthority } from '../../utils';
const EventMaintenance: React.FC<{}> = () => {
const actionRef = useRef<ActionType>();
//新建 编辑 查看
const [modalVisible, setModalVisible] = useState<boolean>(false);
//行数据
const [recordData, setRecordData] = useState<any>({});
//loading
const [loading, setLoading] = useState<boolean>(false);
//新建 编辑 查看
const editClick = (record: any, code: string) => {
record["editCode"] = code; //新建0 编辑1 查看2
setRecordData(record);
setModalVisible(true);
}
//撤回 发布
const changeClick = async (record: any, code: string) => {
const params = {
id: record.id,
status: code,//草稿0 发布1
}
setLoading(true);
await changeEventStatus(params).then(res => {
if (res?.code == 200) {
message.success("操作成功");
actionRef.current?.reload();
}
}).finally(() => {
setLoading(false);
})
}
//删除
const deleteClick = async (record: any) => {
setLoading(true);
await deleteEvent({ id: record.id }).then(res => {
if (res?.code == 200) {
message.success("删除成功");
actionRef.current?.reload();
}
}).finally(() => {
setLoading(false);
})
}
//modal关闭
const onCancel = () => {
setModalVisible(false);
setRecordData({});
actionRef.current?.reload();
}
const columns: ProColumns<any>[] = [
{
title: '序号',
dataIndex: 'index',
valueType: 'index',
width: 48,
},
{
title: '标题名称',
dataIndex: 'title',
},
{
title: '类型',
dataIndex: 'type',
valueType: 'select',
valueEnum: {
"1": { text: '首页' },
"2": { text: '活动风采' },
"3": { text: '攻坚克难项目' },
},
},
{
title: '发布时间',
key: 'sendTime',
dataIndex: 'sendTime',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '状态',
dataIndex: 'status',
valueType: 'select',
valueEnum: {
"0": { text: '草稿' },
"1": { text: '发布' },
},
},
{
title: '开始时间',
dataIndex: 'startTime',
valueType: 'dateTime',
hideInTable: true,
},
{
title: '结束时间',
dataIndex: 'endTime',
valueType: 'dateTime',
hideInTable: true,
},
{
title: '发布人',
dataIndex: 'createBy',
hideInSearch: true,
},
{
title: '操作',
hideInSearch: true,
render: (text, record, _, action) =>
record.status == "1" ? [
<Button
type='text'
key="view"
onClick={() => editClick(record, "2")}
>
</Button>,
<Popconfirm
title="撤回后,活动将不再发布,确认撤回?"
onConfirm={() => changeClick(record, "0")}
okText="确认"
cancelText="取消"
>
<Button
type='text'
key="withdraw"
hidden={managerAuthority("ebtp-party-admin")}
>
</Button>
</Popconfirm>,
] : [
<Button
type='text'
key="editable"
onClick={() => editClick(record, "1")}
hidden={managerAuthority("ebtp-party-admin")}
>
</Button>,
<Popconfirm
title="此活动将彻底删除,确认删除?"
onConfirm={() => deleteClick(record)}
okText="确认"
cancelText="取消"
>
<Button
type='text'
key="delete"
hidden={managerAuthority("ebtp-party-admin")}
>
</Button>
</Popconfirm>,
<Popconfirm
title="活动将发布,确认发布?"
onConfirm={() => changeClick(record, "1")}
okText="确认"
cancelText="取消"
>
<Button
type='text'
key="release"
hidden={managerAuthority("ebtp-party-admin")}
>
</Button>
</Popconfirm>,
],
},
];
return (
<Card className="zjl-entrust confirm" bodyStyle={{ padding: '16px 24px 0px', height: window.innerHeight - 105, overflowY: 'auto' }}>
<ProTable<any>
columns={columns}
actionRef={actionRef}
loading={loading}
request={async (params) => {
setLoading(true);
return await getEventList(params).then(res => {
if (res?.success) {
return {
data: res?.data.records,
success: res?.success,
total: res?.data.total
};
}
return {
data: [],
success: false,
total: 0,
};
}).finally(() => {
setLoading(false);
})
}}
rowKey="id"
options={false}
pagination={{
pageSize: 10,
}}
search={{
defaultCollapsed: false,//默认展开
}}
dateFormatter="string"
toolBarRender={() => [
<Button
key="button"
icon={<PlusOutlined />}
type="primary"
onClick={() => editClick({}, "0")}
loading={loading}
hidden={managerAuthority("ebtp-party-admin")}
>
</Button>
]}
/>
{modalVisible && <EventMaintenanceModal modalVisible={modalVisible} onCancel={() => onCancel()} record={recordData} />}
</Card>
);
};
export default EventMaintenance

View File

@ -0,0 +1,36 @@
import request from '@/utils/request';
//活动维护列表
export async function getEventList(data: any) {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/styleProject/list', {
method: 'POST',
data: {
...data,
pageNo: data.current,
},
});
}
//发布或撤回维护数据
export async function changeEventStatus(params: any) {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/styleProject/send', {
method: 'GET',
params: { ...params },
});
}
//删除维护数据
export async function deleteEvent(params: any) {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/styleProject/delete', {
method: 'GET',
params: { ...params },
});
}
//保存维护数据
export async function saveEventData(data: any) {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/styleProject/save', {
method: 'POST',
data: { ...data },
});
}

View File

@ -0,0 +1,42 @@
.header {
background-color: #b30000;
color: white;
font-size: 20px;
height: 56px;
display: flex;
.headerAlign {
align-self: center;
margin-left: 20px;
font-weight: 400;
}
.rightBtns {
position: absolute;
right: 0;
li {
float: left;
line-height: 56px;
font-size: 14px;
color: #fff;
padding: 0 14px;
font-weight: 400 !important;
list-style: none;
span {
padding-right: 6px;
font-size: 16px;
}
a {
color: #fff;
}
}
}
}
.topic-manager-tabs .ant-tabs-nav {
background: #fff;
margin: 0 0 0 24px
}

View File

@ -0,0 +1,57 @@
import React, { useState } from 'react';
import { Avatar, Tabs } from 'antd';
import { UserSwitchOutlined, CarryOutOutlined } from '@ant-design/icons';
import moment from 'moment'
import logo from '@/assets/logo.svg';
import styles from './index.less';
import './index.less';
import { getSessionUserData } from "@/utils/session";
import EventMaintenance from '../EventMaintenance';
import OpinionCollection from '../OpinionCollection';
import ProLineMaintenance from '../ProLineMaintenance';
const Dashboard: React.FC<{}> = () => {
let data = getSessionUserData();
const { TabPane } = Tabs;
const [tabsSelect, setTabsSelect] = useState<string>("1")
const onChange = (key: string) => {
setTabsSelect(key)
};
return (
<>
<div className={styles.header}>
<div className={styles.headerAlign} style={{ position: "relative", top: "2px", fontSize: "16px", fontWeight: "600" }}>
<img src={logo} style={{ height: "30px", marginRight: "10px", position: 'relative', top: '-2px' }} />
</div>
<ul className={styles.rightBtns}>
<li><CarryOutOutlined />{moment().format("YYYY-MM-DD")}</li>
{data?.organizationName == null ? null : (<li><UserSwitchOutlined />{data.organizationName}</li>)}
<li>
<Avatar size="small" src="https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png" style={{ width: '30px' }} />
<a className="antd-dropdown-link" style={{ color: "#fff", marginRight: "36px" }}>
{data.fullName}
</a>
</li>
</ul>
</div>
<div className="topic-manager-tabs" style={{ background: '#fff' }}>
<Tabs defaultActiveKey="1" onChange={onChange}>
<TabPane tab="活动维护" key="1">
{tabsSelect == "1" && <EventMaintenance />}
</TabPane>
<TabPane tab="意见收集管理" key="2">
{tabsSelect == "2" && <OpinionCollection />}
</TabPane>
<TabPane tab="物资采购专业线数据维护" key="3">
{tabsSelect == "3" && <ProLineMaintenance />}
</TabPane>
</Tabs>
</div>
</>
);
};
export default Dashboard;

View File

@ -0,0 +1,196 @@
import { UploadOutlined } from '@ant-design/icons';
import { ActionType, ProColumns } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { Button, Card, Space, Typography } from 'antd';
import React, { useState } from 'react';
import { useRef } from 'react';
import { getOpinionList } from './service';
import { isEmpty, managerAuthority } from '../../utils';
import { downloadFileObjectId } from '@/utils/DownloadUtils';
const OpinionCollection: React.FC<{}> = () => {
const actionRef = useRef<ActionType>();
const { Text, Link } = Typography;
//loading
const [loading, setLoading] = useState<boolean>(false);
//select
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys);
};
//下载附件
const downloadClick = (e: any, record: any) => {
e.preventDefault();
downloadFileObjectId(record.attachmentImage);
}
//导出&全量导出
const exportData = (ids?: any[]) => {
let url = "/api/biz-service-ebtp-extend/v1/eventmaintain/suggestion/export/";
let params = '';
if (ids) {
for (let i = 0, length = ids.length; i < length; i++) {
if (i == 0) {
params += `?ids=${ids[i]}`;
} else {
params += `&ids=${ids[i]}`;
}
}
}
url += params;
window.location.href = url;
actionRef.current?.reloadAndRest?.();
}
const columns: ProColumns<any>[] = [
{
title: '序号',
dataIndex: 'index',
valueType: 'index',
width: 48,
},
{
title: '意见类型',
dataIndex: 'suggestionType',
valueType: 'select',
valueEnum: {
"网络运营": { text: '网络运营' },
"IT": { text: 'IT' },
"市场": { text: '市场' },
"综合行政": { text: '综合行政' },
"其他": { text: '其他' },
},
},
{
title: '意见内容',
dataIndex: 'suggestionContent',
width: '30%',
hideInSearch: true,
},
{
title: '补充信息',
dataIndex: 'instructions',
width: '20%',
hideInSearch: true,
},
{
title: '提交时间',
key: 'createTime',
dataIndex: 'createTime',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '开始时间',
dataIndex: 'startTime',
valueType: 'dateTime',
hideInTable: true,
},
{
title: '结束时间',
dataIndex: 'endTime',
valueType: 'dateTime',
hideInTable: true,
},
{
title: '提交人员',
dataIndex: 'suggestionSponsor',
hideInSearch: true,
},
{
title: '附件管理',
hideInSearch: true,
render: (text, record, _, action) =>
isEmpty(record.attachmentImage) ? [
<Text
key="download"
disabled
>
</Text>,
] : [
<Link
key="download"
href='#'
onClick={(e) => downloadClick(e, record)}
hidden={managerAuthority("ebtp-party-admin")}
>
</Link>,
]
},
];
return (
<Card className="zjl-entrust confirm" bodyStyle={{ padding: '16px 24px 0px', height: window.innerHeight - 105, overflowY: 'auto' }}>
<ProTable<any>
columns={columns}
actionRef={actionRef}
loading={loading}
request={async (params) => {
setLoading(true);
return await getOpinionList(params).then(res => {
if (res?.success) {
return {
data: res?.data.records,
success: res?.success,
total: res?.data.total
};
}
return {
data: [],
success: false,
total: 0,
};
}).finally(() => {
setLoading(false);
})
}}
rowKey="id"
options={false}
pagination={{
pageSize: 10,
}}
search={{
span: 6,
defaultCollapsed: false,//默认展开
}}
rowSelection={{
selectedRowKeys,
onChange: onSelectChange,
preserveSelectedRowKeys: true,
}}
tableAlertRender={({ selectedRowKeys, selectedRows, onCleanSelected }) => (
<Space size={24}>
<span>
{selectedRowKeys.length}
<a
style={{ marginLeft: 8 }}
onClick={() => exportData(selectedRowKeys)}
hidden={managerAuthority("ebtp-party-admin")}
>
</a>
</span>
</Space>
)}
dateFormatter="string"
toolBarRender={() => [
<Button
key="button"
icon={<UploadOutlined />}
type="primary"
onClick={() => exportData()}
loading={loading}
hidden={managerAuthority("ebtp-party-admin")}
>
</Button>
]}
/>
</Card>
);
};
export default OpinionCollection

View File

@ -0,0 +1,12 @@
import request from '@/utils/request';
//意见列表
export async function getOpinionList(data: any) {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/suggestion/list', {
method: 'POST',
data: {
...data,
pageNo: data.current,
},
});
}

View File

@ -0,0 +1,86 @@
import { Button, Card, Col, Form, Input, message, Row, Space, Spin, Typography } from 'antd';
import React, { useEffect, useState } from 'react';
import { managerAuthority } from '../../utils';
import { getRightData, saveRightData } from './service';
const layout = {
labelCol: { span: 6 },
wrapperCol: { span: 15 },
};
const validateMessages = {
required: '请填写此项',
};
const ProLineMaintenance: React.FC<{}> = () => {
const { Title } = Typography;
const [form] = Form.useForm();
//按钮显隐 查看-true 编辑-false
const [display, setDisplay] = useState<boolean>(true);
//loading
const [loading, setLoading] = useState<boolean>(false);
const onSubmit = () => {
form.validateFields().then(value => {
setLoading(true);
saveRightData(value).then(res => {
if (res?.code == 200) {
message.success("发布成功");
}
}).finally(() => {
setLoading(false);
})
})
};
//取数据
const getData = () => {
getRightData().then(res => {
if (res?.code == 200) {
form.setFieldsValue(res?.data);
}
})
}
useEffect(() => {
getData();
}, [])
return (
<Card bodyStyle={{ padding: '16px 24px 0px', height: window.innerHeight - 105, overflowY: 'auto' }}>
<Spin spinning={loading}>
<Space>
<Button onClick={() => setDisplay(value => !value)}>{display ? '编辑' : '查看'}</Button>
<Button type='primary' disabled={display} onClick={() => onSubmit()} hidden={managerAuthority("ebtp-party-admin")}></Button>
</Space>
<Title level={3} style={{ margin: '16px 0 24px' }}></Title>
<Form {...layout} name="nest-messages" form={form} validateMessages={validateMessages}>
<Row>
<Col span={12}>
<Form.Item name="yxdy" label="一线调研次数" rules={[{ required: true }]}>
<Input disabled={display} type="number" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="ftrs" label="访谈人数" rules={[{ required: true }]}>
<Input disabled={display} type="number" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="bzxq" label="保障需求条数" rules={[{ required: true }]}>
<Input disabled={display} type="number" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="gjknxm" label="攻坚克难项目个数" rules={[{ required: true }]}>
<Input disabled={display} type="number" />
</Form.Item>
</Col>
</Row>
</Form>
</Spin>
</Card>
);
};
export default ProLineMaintenance

View File

@ -0,0 +1,16 @@
import request from '@/utils/request';
//查询右侧专业线数据
export async function getRightData() {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/query/rightData', {
method: 'POST',
});
}
//保存右侧专业线数据
export async function saveRightData(data: any) {
return request('/api/biz-service-ebtp-extend/v1/eventmaintain/save/rightData', {
method: 'POST',
data: { ...data },
});
}

View File

@ -1,4 +1,5 @@
import { pictureDisplayPath } from "@/utils/DownloadUtils"; import { pictureDisplayPath } from "@/utils/DownloadUtils";
import { getSessionUserData } from "@/utils/session";
import moment from "moment"; import moment from "moment";
/** /**
* 图片路径拼接 * 图片路径拼接
@ -56,4 +57,17 @@ export function chunk(arr: any[], size: number) {
result.push(arr.slice(i, i + size)); result.push(arr.slice(i, i + size));
} }
return result; return result;
}
/**
* 权限校验(党建管理员)
* @returns
*/
export const managerAuthority = (authority: string) => {
const authorityList = getSessionUserData().authorityList;
for (const ite of authorityList) {
if (ite.roleCode === authority) {
return false;
}
}
return true;
} }