初始化后台管理分支代码

This commit is contained in:
何童崇 2022-03-04 11:47:14 +08:00
parent 3ac6021d9e
commit d1d9213527
11 changed files with 594 additions and 1 deletions

View File

@ -104,6 +104,7 @@ module.exports = {
src: path.join(paths.appSrc), // 整个源代码目录
forge: path.join(paths.appSrc, 'forge'),
military: path.join(paths.appSrc, 'military'),
components: path.join(paths.appSrc, 'components'),
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
"react-native": "react-native-web",

View File

@ -5,6 +5,7 @@
"educoder": ["./src/common/educoder.js"],
"forge":["./src/forge"],
"military":["./src/military"],
"components":["./src/components"],
}
},
"exclude": [

View File

@ -137,7 +137,7 @@ const HomePage = Loadable({
// 管理页面
const Managements = Loadable({
loader: () => import('./military/managements'),
loader: () => import('./managements/index'),
loading: Loading,
})
// const CreateMerge = Loadable({

View File

@ -0,0 +1,125 @@
/* eslint-disable react/jsx-no-duplicate-props */
import React, { useState } from 'react';
import * as ReactDOM from 'react-dom';
import { Modal, Button } from 'antd';
import './index.scss';
//
InitModal.defaultProps = {
okText: '确认', //
cancelText: '取消', //
className: '', //
inputId: 'copyText', //ID
onCancel:()=>{}, //
onOk:()=>{}, //
title:'提示', //
contentTitle:'', //
content:'', //
afterClose:()=>{}, //
};
// 使
export default function DelModal(props) {
renderModal({ ...props, type: 'delete' })
}
// 使
export function Confirm(props) {
renderModal({ ...props, type: 'confirm' })
}
function renderModal(props) {
const { type, afterClose } = props;
const div = document.createElement('div');
document.body.appendChild(div);
function destroy() {
afterClose && afterClose();
const unmountResult = ReactDOM.unmountComponentAtNode(div);
if (unmountResult && div.parentNode) {
div.parentNode.removeChild(div);
}
}
function modalType(type) {
if (type === 'delete') {
return <InitModal
title="删除"
contentTitle="确定要删除吗?"
okText="确认删除"
{...props}
afterClose={destroy}
contentTitle={<React.Fragment>
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
{props.contentTitle}
</React.Fragment>}
/>
} else if (type === 'confirm') {
return <InitModal title="选择" afterClose={destroy} {...props} />
} else {
return <InitModal title="选择" afterClose={destroy} {...props} />
}
}
function render() {
setTimeout(() => {
ReactDOM.render(
modalType(type),
div,
);
});
}
render();
}
//
function InitModal({
onCancel,
onOk,
title,
contentTitle,
content,
okText,
cancelText,
afterClose,
className,
}) {
const [visible, setVisible] = useState(true);
function onCancelModal() {
setVisible(false);
onCancel && onCancel()
}
function onSuccess() {
setVisible(false);
onOk && onOk();
}
return (
<Modal
visible={visible}
onCancel={onCancelModal}
afterClose={afterClose}
title={title}
className={`myself-modal ${className}`}
centered
footer={[
<Button type="default" key="back" onClick={onCancelModal}>
{cancelText}
</Button>,
<Button className="foot-submit" key="submit" onClick={onSuccess}>
{okText}
</Button>,
]}
>
<div>
{contentTitle && <p className="content-title">{contentTitle}</p>}
<p className="content-descibe">{content}</p>
</div>
</Modal>
)
}

View File

@ -0,0 +1,63 @@
.myself-modal {
.ant-modal-header {
padding: 9px 24px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
}
.ant-modal-title {
text-align: left;
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-close-x {
font-size: 24px;
}
.ant-modal-body {
text-align: center;
}
.content-title {
display: flex;
justify-content: center;
align-items: center;
margin: 2rem 0 1rem !important;
font-size: 16px;
color: #333;
letter-spacing: 0;
line-height: 29px;
font-weight: 400;
}
.red-circle {
align-self: flex-start;
color: #ca0002;
font-size: 1.5rem !important;
}
.content-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
font-weight: 400;
}
.ant-modal-footer {
padding: 2rem 0;
text-align: center;
border: 0;
.ant-btn {
width: 6rem;
}
}
.foot-submit {
margin-left: 3rem;
color: #df0002;
&:hover {
border-color: #df0002;
}
}
.ant-btn-default:hover,
.ant-btn-default:active,
.ant-btn-default:focus {
background: #f3f4f6;
color: #333;
border-color: #d0d0d0;
}
}

View File

@ -0,0 +1,36 @@
import React, { Fragment } from 'react';
import { Table, Pagination } from 'antd';
import './index.scss';
export default (props) => {
const { loading, dataSource, columns, handleRow, total, setCurPage, current, rowSelection, expandedRowRender, expandIconColumnIndex, expandIconAsCell, onShowSizeChange, showSizeChanger, pagination, scroll } = props;
return (
<div className='pagination-table'>
<Table
{...props}
loading={loading}
rowKey={(row,i) => row.id || i}
dataSource={dataSource}
columns={columns}
pagination={false}
onRow={handleRow}
rowSelection={rowSelection}
expandedRowRender={expandedRowRender}
expandIconColumnIndex={expandIconColumnIndex}
expandIconAsCell={expandIconAsCell}
scroll={scroll}
/>
{total > 10 && (!pagination) &&
<Pagination
showQuickJumper
onShowSizeChange={onShowSizeChange}
onChange={setCurPage}
current={current}
total={total}
showSizeChanger={showSizeChanger}
/>}
</div>
)
}

View File

@ -0,0 +1,39 @@
.pagination-table {
.ant-table {
border: 1px solid #ececec;
border-radius: 0 0 4px 4px;
}
.ant-table-thead tr th div {
color: #181818;
font-weight: 500;
}
.ant-table-wrapper {
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
.ant-table-hide-scrollbar {
margin-bottom: -5px;
overflow-y: hidden !important;
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
}
}
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding: 14px 8px;
}
.ant-pagination {
margin-top: 1.25rem;
text-align: right;
}
// .ant-table-row-cell-break-word{
// .ant-btn{
// display: inline-block;
// }
// }
}

View File

@ -0,0 +1,80 @@
import React, { useState ,useEffect } from 'react';
import { Link } from "react-router-dom";
import { Menu,Icon, Dropdown, } from 'antd';
import './index.scss';
const { SubMenu } = Menu;
export default (props) => {
const {current_user,history}=props;
const main_web_site_url =localStorage.chromesetting&& JSON.parse(localStorage.chromesetting).main_web_site_url;
const current_main_site_url =localStorage.chromesetting&& JSON.parse(localStorage.chromesetting).current_main_site_url;
const noticeUrl =localStorage.chromesetting&& JSON.parse(localStorage.chromesetting).api_urls.notice;
useEffect(()=>{
sessionStorage.setItem('current_user',JSON.stringify(current_user));
},[current_user.login]);
const [current,setCurrent]=useState(JSON.parse(sessionStorage.adminRouter||'[]'));
const [title,setTitle]=useState('');
function handleClick (e){
setCurrent([e.key]);
setTitle(e.item.props.title);
sessionStorage.setItem( 'adminRouter',JSON.stringify([e.key]));
};
return (
<div className="layouts">
<Menu
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
mode="inline"
>
<SubMenu
key="sub1"
title={
<span>
<Icon type="mail" />
<span>概览</span>
</span>
}
>
<Menu.Item key="1" onClick={() => { history.push('/global') }}>全局统计</Menu.Item>
<Menu.Item key="6" onClick={() => { history.push('/member') }}>成员工作统计</Menu.Item>
<Menu.Item key="7" onClick={() => { history.push('/activity') }}>项目活跃度统计</Menu.Item>
</SubMenu>
<SubMenu
key="task"
title={
<span>
<Icon type="mail" />
<span>创客空间</span>
</span>
}
>
<SubMenu title="基础数据" >
<Menu.Item><a href={`${main_web_site_url}/admin/categories/list`}>任务领域</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/industries/list`}>行业信息</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/placements/list`}>职位信息</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/task_templates/list`}>需求导入模板</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/agreement_setting`}>签订协议内容</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/sign_agreement_setting`}>应征投稿协议内容</a></Menu.Item>
</SubMenu>
<SubMenu title="代办事项" >
<Menu.Item title="task" key="delayManage"><Link to="/managements/task/delayManage">延期任务处理</Link></Menu.Item>
<Menu.Item title="task" key="payProof"><Link to="/managements/task/payProof">支付报酬凭证上传</Link></Menu.Item>
</SubMenu>
<Menu.Item title="task" key="taskAdmin"><Link to="/managements/task/taskAdmin">创客任务列表</Link></Menu.Item>
</SubMenu>
</Menu>
</div>
);
};

View File

@ -0,0 +1,14 @@
.layouts {
background: #aaa;
position: fixed;
top: 70px;
left:0;
width: 10vw;
}
@media screen and (max-width: 600px) {
.layouts{
display: none;
}
}

229
src/managements/index.js Normal file
View File

@ -0,0 +1,229 @@
import React, { useEffect, useState } from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import Loadable from "react-loadable";
import Loading from "../Loading";
import AdminRouter from "../military/components/adminRouter";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import Layouts from "./components/layouts";
import './index.scss';
{/* 任务管理审核 */}
const TaskManage = Loadable({
loader: () => import("../military/task/taskManage"),
loading: Loading,
});
{/* 成果管理审核 */}
const PaperManage = Loadable({
loader: () => import("../military/task/paperManage"),
loading: Loading,
});
{/* 成果申诉管理审核 */}
const PaperComplain = Loadable({
loader: () => import("../military/task/paperComplain"),
loading: Loading,
});
const ProofManage = Loadable({
loader: () => import("../military/task/proofManage"),
loading: Loading,
});
const PublicityComplain = Loadable({
loader: () => import("../military/task/publicityComplain"),
loading: Loading,
});
const AgreementManage = Loadable({
loader: () => import("../military/task/agreementManage"),
loading: Loading,
});
const PayProof = Loadable({
loader: () => import("../military/task/payProof"),
loading: Loading,
});
const TaskAdmin = Loadable({
loader: () => import("../military/task/taskAdmin"),
loading: Loading,
});
const DelayManage = Loadable({
loader: () => import("../military/task/delayManage"),
loading: Loading,
});
// 专家库
const ExpertList = Loadable({
loader: () => import("../military/expert/expertList"),
loading: Loading,
});
// 专家审核
const RegisterList = Loadable({
loader: () => import("../military/expert/registerList"),
loading: Loading,
});
//创客任务评审规则
const ReviewRules = Loadable({
loader : () => import("../military/expert/reviewRules"),
loading: Loading,
});
//创客任务选择评审专家
const SelectExpert = Loadable({
loader: () => import("../military/expert/selectExpert"),
loading: Loading,
});
//创客任务评审结果查看
const ReviewResult = Loadable({
loader: () => import("../military/expert/reviewResult"),
loading: Loading,
});
//竞赛评审任务列表
const CompetitionList = Loadable({
loader: () => import("../military/expert/competionList"),
loading: Loading,
})
const Managements = (propsF) => {
return (
<div className="newMain clearfix managements">
{/* <AdminRouter {...propsF} /> */}
<Layouts {...propsF} />
<Switch {...propsF}>
{/* 任务管理审核 */}
<Route
path="/managements/task/taskManage/:publishMode"
render={(props) => (
<TaskManage {...propsF} {...props} />
)}
></Route>
{/* 成果管理审核 */}
<Route
path="/managements/task/paperManage"
render={(props) => (
<PaperManage {...propsF} {...props} />
)}
></Route>
{/* 成果申诉管理审核 */}
<Route
path="/managements/task/paperComplain"
render={(props) => (
<PaperComplain {...propsF} {...props} />
)}
></Route>
{/* 公示期成果申诉管理审核 */}
<Route
path="/managements/task/publicityComplain"
render={(props) => (
<PublicityComplain {...propsF} {...props} />
)}
></Route>
{/* 佐证管理审核 */}
<Route
path="/managements/task/proofManage"
render={(props) => (
<ProofManage {...propsF} {...props} />
)}
></Route>
{/* 管理员协议审核 */}
<Route
path="/managements/task/agreementManage"
render={(props) => (
<AgreementManage {...propsF} {...props} />
)}
></Route>
{/* 管理员上传支付凭证 */}
<Route
path="/managements/task/payProof"
render={(props) => (
<PayProof {...propsF} {...props} />
)}
></Route>
{/* 管理员任务列表 */}
<Route
path="/managements/task/taskAdmin"
render={(props) => (
<TaskAdmin {...propsF} {...props} />
)}
></Route>
{/* 延期管理 */}
<Route
path="/managements/task/delayManage"
render={(props) => (
<DelayManage {...propsF} {...props} />
)}
></Route>
{/* 专家审核 */}
<Route
path="/managements/expert/register"
render={(props) => (
<RegisterList {...propsF} {...props} />
)}
></Route>
{/* 专家库列表 */}
<Route
path="/managements/expert/list"
render={(props) => (
<ExpertList {...propsF} {...props} />
)}
></Route>
{/* 创客任务评审规则 */}
<Route
path="/managements/expert/task/review/rules/:containerType/:containerId"
render={(props) => (
<ReviewRules {...propsF} {...props} />
)}
></Route>
{/* 创客任务选择评审专家 */}
<Route
path="/managements/expert/task/review/select/:containerType/:containerId"
render={(props) => (
<SelectExpert {...propsF} {...props} />
)}
></Route>
{/* 创客任务评审结果查看 */}
<Route
path="/managements/expert/task/review/results/:containerType/:containerId"
render={(props) => (
<ReviewResult {...propsF} {...props} />
)}
></Route>
{/* 竞赛评审任务列表 */}
<Route
path="/managements/expert/competition"
render={(props) => (
<CompetitionList {...propsF} {...props} />
)}
></Route>
</Switch>
</div>
);
}
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Managements))))
);

View File

@ -0,0 +1,5 @@
.managements{
.centerbox{
margin-left: 10vw;
}
}