上传
This commit is contained in:
parent
64311d8e06
commit
c2696e5b1c
13260
package-lock.json
generated
Normal file
13260
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,15 +7,22 @@
|
||||
"@testing-library/react": "^13.0.0",
|
||||
"@testing-library/user-event": "^13.2.1",
|
||||
"antd": "^4.20.7",
|
||||
"axios": "^0.27.2",
|
||||
"babel-plugin-import": "^1.13.5",
|
||||
"customize-cra": "^1.0.0",
|
||||
"echarts": "^5.3.3",
|
||||
"echarts-for-react": "^3.0.2",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^11.0.0",
|
||||
"pubsub-js": "^1.9.4",
|
||||
"react": "^18.1.0",
|
||||
"react-app-rewired": "^2.2.1",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-pdf": "^5.7.2",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"serve": "^14.0.1",
|
||||
"store": "^2.0.12",
|
||||
"web-vitals": "^2.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
BIN
public/images/1.pdf
Normal file
BIN
public/images/1.pdf
Normal file
Binary file not shown.
BIN
public/images/logo.png
Normal file
BIN
public/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -9,6 +9,7 @@
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
|
||||
<title>乐谷人事管理系统</title>
|
||||
</head>
|
||||
<body>
|
||||
@ -16,4 +17,5 @@
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
<script src="http://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
|
||||
</html>
|
||||
|
58
src/App.css
58
src/App.css
@ -12,26 +12,44 @@
|
||||
.trigger:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
.appcontent { min-height: 280px; overflow-y: auto;}
|
||||
.divdisplay { display: flex; }
|
||||
.appcontent { min-height: 280px; overflow-y: auto; position: relative;}
|
||||
.divdisplay { display: flex; align-items: center; }
|
||||
.divdisplay2 { display: flex; }
|
||||
.logo_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 16px;
|
||||
}
|
||||
.logo_box .logo {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
.logo img { width: 100%; border-radius: 50%; }
|
||||
.logo_box .logo_txt {
|
||||
height: 40px;
|
||||
height: 48px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo_box .logo_txt2 {
|
||||
height: 48px;
|
||||
animation:txttran 1s 1;
|
||||
}
|
||||
|
||||
@keyframes txttran {
|
||||
from {opacity: 0; display: block;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
|
||||
.logo_box .logo_txt p {
|
||||
margin-bottom: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.logo_box .logo_txt2 p {
|
||||
margin-bottom: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.logo_box .introduction {
|
||||
font-size: 12px;
|
||||
color: #c1c5cc;
|
||||
@ -94,19 +112,36 @@
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
.backgroundcolor .ant-tree{ background-color: rgba(255, 255, 255, 0) !important; }
|
||||
|
||||
.fontweight{font-weight: bold;}
|
||||
.padding24 { padding: 24px; }
|
||||
.margin24 { margin: 24px; }
|
||||
.margintop5{ margin-top: 5px; }
|
||||
.margintop20{ margin-top: 20px; }
|
||||
.margintop30 { margin-top: 30px; }
|
||||
.margintop50 { margin-top: 50px; }
|
||||
|
||||
.margin10 {margin: 0 10px;}
|
||||
.marginbottom10 { margin-bottom: 10px; }
|
||||
|
||||
.marginleft6{ margin-left: 6px; }
|
||||
|
||||
.marginright5 { margin-right: 5px;}
|
||||
.marginright6{ margin-right: 6px; }
|
||||
.marginright10{ margin-right: 10px; }
|
||||
.marginright24{ margin-right: 24px; }
|
||||
|
||||
.cursor { cursor: pointer; }
|
||||
|
||||
.font-size12 { font-size: 12px; margin-bottom: 0;}
|
||||
.font-size14 {font-size: 14px;}
|
||||
.fontsize28 { font-size: 28px; }
|
||||
.fontsize24 { font-size: 24px; }
|
||||
.fontsize22 { font-size: 22px; }
|
||||
|
||||
.lineheight24{line-height: 24px;}
|
||||
|
||||
.color0 { color: #575d6a; }
|
||||
.color1 { color: #75777d; }
|
||||
.color2 { color: #5c5f6c; }
|
||||
@ -115,6 +150,19 @@
|
||||
.coloc5 { color: #312b2e; }
|
||||
.color6 { color: #f47f76; }
|
||||
.color7 { color: #5b524b; }
|
||||
.color8 { color: #f59f00; }
|
||||
|
||||
.border3 { border-color: #f49300 !important; }
|
||||
.border6 { border-color: #f47f76 !important; }
|
||||
|
||||
.textalign { text-align: right; }
|
||||
.textaligncenter { text-align: center; }
|
||||
|
||||
|
||||
.transform90 { transform:rotate(90deg); }
|
||||
|
||||
|
||||
.Empty-box2 {
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
import React from 'react'
|
||||
import GlobalRouter from './routes/GlobalRouter'
|
||||
import { pdfjs } from 'react-pdf';
|
||||
import './App.css'
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.bootcdn.net/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
|
||||
// console.log(pdfjs.version)
|
||||
// const App = () => {
|
||||
// return <GlobalRouter/>
|
||||
// }
|
||||
|
@ -1,8 +1,11 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { Layout, Menu, Image } from 'antd'
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom'
|
||||
import NavHeader from './components/NavHeader'
|
||||
import HeadLeftTtile from './components/HeadLeftTtile'
|
||||
import PubSub from 'pubsub-js'
|
||||
import memoryUtils from './util/memoryUtils'
|
||||
import storageUtils from './util/storageUtils'
|
||||
import './App.css'
|
||||
import {
|
||||
AppstoreOutlined,
|
||||
@ -12,17 +15,22 @@ import {
|
||||
ShoppingOutlined,
|
||||
PieChartOutlined,
|
||||
SettingOutlined,
|
||||
FilterOutlined,
|
||||
} from '@ant-design/icons'
|
||||
// import GlobalRouter from './routes/GlobalRouter'
|
||||
const { Header, Sider, Content } = Layout
|
||||
// 读取localStorage保存的userInfo,保存到内存里面
|
||||
|
||||
function AppLayOut() {
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
const [collapsed, setCollapsed] = useState(true)
|
||||
const [headtitle, setHeadtitle] = useState('总览')
|
||||
const [headnav,setHeadnav] = useState('')
|
||||
const [defaultSelectedKeys,setdefaultSelectedKeys] = useState('/')
|
||||
const [headnav, setHeadnav] = useState('')
|
||||
const [defaultSelectedKeys, setdefaultSelectedKeys] = useState('/')
|
||||
|
||||
//添加用户登录信息
|
||||
var userInfo = storageUtils.getUser()
|
||||
memoryUtils.userInfo = userInfo
|
||||
|
||||
// 单击侧边栏跳转路由
|
||||
const click = (e) => {
|
||||
@ -31,8 +39,7 @@ function AppLayOut() {
|
||||
|
||||
const select = (e) => {
|
||||
const { title } = e.item.props
|
||||
// console.log(title)
|
||||
setHeadtitle(title)
|
||||
PubSub.publish('headtitle', { headtitle: title })
|
||||
}
|
||||
|
||||
// 鼠标移入
|
||||
@ -42,20 +49,149 @@ function AppLayOut() {
|
||||
|
||||
// 鼠标移出
|
||||
const handlMouseLeave = () => {
|
||||
console.log(11111)
|
||||
setCollapsed(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// return ()=>{
|
||||
const pathname = location.pathname;
|
||||
const pathurl = pathname.split('/')[2];
|
||||
setHeadnav(pathurl)
|
||||
setdefaultSelectedKeys(pathname)
|
||||
// }
|
||||
// return ()=>{
|
||||
const pathname = location.pathname
|
||||
const pathurl = pathname.split('/')[2]
|
||||
setHeadnav(pathurl)
|
||||
setdefaultSelectedKeys(pathurl ? '/admin/' + pathurl : pathname)
|
||||
// }
|
||||
// const routes = matchRoutes(GlobalRouter, location.pathname);
|
||||
// console.log(routes);
|
||||
}, [location.pathname])
|
||||
|
||||
const hr_items = [
|
||||
{
|
||||
key: '/',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: '总览',
|
||||
title: '总览',
|
||||
},
|
||||
{
|
||||
key: '/admin/candidate',
|
||||
icon: <UsergroupAddOutlined />,
|
||||
label: '候选人管理',
|
||||
title: '候选人管理',
|
||||
},
|
||||
{
|
||||
key: '/admin/interview',
|
||||
icon: <CalendarOutlined />,
|
||||
label: '面试安排',
|
||||
title: '面试安排',
|
||||
},
|
||||
{
|
||||
key: '/admin/position',
|
||||
icon: <ShoppingOutlined />,
|
||||
label: '职位管理',
|
||||
title: '职位管理',
|
||||
},
|
||||
{
|
||||
key: '/admin/talentpool',
|
||||
icon: <RestOutlined />,
|
||||
label: '人才库',
|
||||
title: '人才库',
|
||||
},
|
||||
{
|
||||
key: '/admin/reportforms',
|
||||
icon: <PieChartOutlined />,
|
||||
label: '报表中心',
|
||||
title: '报表中心',
|
||||
},
|
||||
{
|
||||
key: '/admin/setup',
|
||||
icon: <SettingOutlined />,
|
||||
label: '设置',
|
||||
title: '设置',
|
||||
},
|
||||
]
|
||||
|
||||
const manager_items = [
|
||||
{
|
||||
key: '/',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: '总览',
|
||||
title: '总览',
|
||||
},
|
||||
{
|
||||
key: '/admin/Interview_manager',
|
||||
icon: <CalendarOutlined />,
|
||||
label: '经理-面试安排',
|
||||
title: '经理-面试安排',
|
||||
},
|
||||
{
|
||||
key: '/admin/resumescreen',
|
||||
icon: <FilterOutlined />,
|
||||
label: '简历筛选',
|
||||
title: '简历筛选',
|
||||
},
|
||||
{
|
||||
key: '/admin/setup',
|
||||
icon: <SettingOutlined />,
|
||||
label: '设置',
|
||||
title: '设置',
|
||||
},
|
||||
]
|
||||
|
||||
const root_items = [
|
||||
{
|
||||
key: '/',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: '总览',
|
||||
title: '总览',
|
||||
},
|
||||
{
|
||||
key: '/admin/resumescreen',
|
||||
icon: <FilterOutlined />,
|
||||
label: '简历筛选',
|
||||
title: '简历筛选',
|
||||
},
|
||||
{
|
||||
key: '/admin/Interview_manager',
|
||||
icon: <CalendarOutlined />,
|
||||
label: '经理-面试安排',
|
||||
title: '经理-面试安排',
|
||||
},
|
||||
{
|
||||
key: '/admin/candidate',
|
||||
icon: <UsergroupAddOutlined />,
|
||||
label: '候选人管理',
|
||||
title: '候选人管理',
|
||||
},
|
||||
{
|
||||
key: '/admin/interview',
|
||||
icon: <CalendarOutlined />,
|
||||
label: '面试安排',
|
||||
title: '面试安排',
|
||||
},
|
||||
{
|
||||
key: '/admin/position',
|
||||
icon: <ShoppingOutlined />,
|
||||
label: '职位管理',
|
||||
title: '职位管理',
|
||||
},
|
||||
{
|
||||
key: '/admin/talentpool',
|
||||
icon: <RestOutlined />,
|
||||
label: '人才库',
|
||||
title: '人才库',
|
||||
},
|
||||
{
|
||||
key: '/admin/reportforms',
|
||||
icon: <PieChartOutlined />,
|
||||
label: '报表中心',
|
||||
title: '报表中心',
|
||||
},
|
||||
{
|
||||
key: '/admin/setup',
|
||||
icon: <SettingOutlined />,
|
||||
label: '设置',
|
||||
title: '设置',
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Sider
|
||||
@ -67,65 +203,21 @@ function AppLayOut() {
|
||||
>
|
||||
{/* <div className="logo" /> */}
|
||||
<div className="logo_box">
|
||||
<div className="logo" />
|
||||
<div
|
||||
className="logo_txt"
|
||||
style={{ display: collapsed ? 'none' : 'block' }}
|
||||
>
|
||||
<p className="introduction">Moka</p>
|
||||
<p className="role">用人经理端</p>
|
||||
<div className="logo">
|
||||
<img src='https://legu-cdn-source.obs.cn-east-2.myhuaweicloud.com/hrms/216.png'/>
|
||||
</div>
|
||||
<div className={collapsed ? 'logo_txt' : 'logo_txt2'}>
|
||||
<p className="introduction">Legu</p>
|
||||
<p className="role">{userInfo.rank === 1? 'HR端':'经理端'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
selectedKeys={defaultSelectedKeys}
|
||||
selectedKeys={defaultSelectedKeys}
|
||||
defaultSelectedKeys={defaultSelectedKeys}
|
||||
items={[
|
||||
{
|
||||
key: '/',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: '总览',
|
||||
title: '总览',
|
||||
},
|
||||
{
|
||||
key: '/admin/candidate',
|
||||
icon: <UsergroupAddOutlined />,
|
||||
label: '候选人管理',
|
||||
title: '候选人管理',
|
||||
},
|
||||
{
|
||||
key: '/admin/interview',
|
||||
icon: <CalendarOutlined />,
|
||||
label: '面试安排',
|
||||
title: '面试安排',
|
||||
},
|
||||
{
|
||||
key: '/admin/position',
|
||||
icon: <ShoppingOutlined />,
|
||||
label: '职位管理',
|
||||
title: '职位管理',
|
||||
},
|
||||
{
|
||||
key: '/admin/talentpool',
|
||||
icon: <RestOutlined />,
|
||||
label: '人才库',
|
||||
title: '人才库',
|
||||
},
|
||||
{
|
||||
key: '/admin/reportforms',
|
||||
icon: <PieChartOutlined />,
|
||||
label: '报表中心',
|
||||
title: '报表中心',
|
||||
},
|
||||
{
|
||||
key: '/admin/setup',
|
||||
icon: <SettingOutlined />,
|
||||
label: '设置',
|
||||
title: '设置',
|
||||
},
|
||||
]}
|
||||
items={userInfo.rank === 1 ? hr_items : userInfo.rank === 2? manager_items: root_items}
|
||||
onClick={click}
|
||||
onSelect={select}
|
||||
/>
|
||||
@ -137,12 +229,10 @@ function AppLayOut() {
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
<HeadLeftTtile headtitle={headtitle} />
|
||||
<NavHeader headnav={headnav}/>
|
||||
<HeadLeftTtile />
|
||||
<NavHeader userInfo={userInfo} />
|
||||
</Header>
|
||||
<Content
|
||||
className='appcontent'
|
||||
>
|
||||
<Content className="appcontent">
|
||||
<Outlet />
|
||||
</Content>
|
||||
</Layout>
|
||||
|
0
src/components/AddPosition/Addperson/index.css
Normal file
0
src/components/AddPosition/Addperson/index.css
Normal file
68
src/components/AddPosition/Addperson/index.jsx
Normal file
68
src/components/AddPosition/Addperson/index.jsx
Normal file
@ -0,0 +1,68 @@
|
||||
import React from 'react'
|
||||
import { Form, Modal, Select } from 'antd'
|
||||
const { Option } = Select
|
||||
|
||||
export default function Addperson({ visible, onCancel, onCreate, data }) {
|
||||
const [form] = Form.useForm()
|
||||
let title = '招聘协助人'
|
||||
switch (data.type) {
|
||||
case 'principal':
|
||||
title = '负责人'
|
||||
break
|
||||
case 'patronn':
|
||||
title = '协助人'
|
||||
break
|
||||
case 'hr_name':
|
||||
title = '用人经理'
|
||||
break
|
||||
default:
|
||||
title = '面试官'
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title={'添加' + title}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields();
|
||||
onCreate(data.list[values['userinfo']]);
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Form form={form} layout="vertical" name="form_in_modal">
|
||||
<Form.Item
|
||||
name="userinfo"
|
||||
label={'选择' + title}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message:
|
||||
'请选择',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
{data['list'].map((item,key) => {
|
||||
return item.nickname != 0 ?(
|
||||
<Option value={key} key={key}>
|
||||
{item.nickname}
|
||||
</Option>
|
||||
):''
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
76
src/components/AddPosition/PositionResponsble/index.css
Normal file
76
src/components/AddPosition/PositionResponsble/index.css
Normal file
@ -0,0 +1,76 @@
|
||||
.PositionResponsble-box {
|
||||
margin: 0 120px;
|
||||
min-height: 300px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.PositionResponsble-list {
|
||||
width: calc(100% - 308px);
|
||||
}
|
||||
|
||||
.PositionResponsble-type-box {
|
||||
width: 276px;
|
||||
height: 170px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.PositionResponsble-list-box {
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
border-bottom: 1px solid #dfe1e5;
|
||||
}
|
||||
.PositionResponsble-list-box .title{
|
||||
font-size: 16px;
|
||||
color: #575d6a;
|
||||
font-weight: bold;
|
||||
}
|
||||
.PositionResponsble-list-box .tips-box { font-size: 14px; color: #89909e; margin-top: 14px; }
|
||||
.user-list-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
margin-right: 14px;
|
||||
}
|
||||
.PositionResponsble-user-list-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.user-list-box .surname-box {
|
||||
padding: 5px 8px;
|
||||
background-color: #f06595;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
.user-list-box .name-box {
|
||||
padding: 4px 8px;
|
||||
background-color: #f4f4f5;
|
||||
color: #292c32;
|
||||
font-size: 14px;
|
||||
border-radius: 0 0px 0px 0;
|
||||
border-right: 1px solid #b6b6b6;
|
||||
}
|
||||
.user-list-box .delete-box {
|
||||
padding: 4px 8px;
|
||||
background-color: #f4f4f5;
|
||||
color: #292c32;
|
||||
font-size: 14px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
color: rgb(230, 47, 47);
|
||||
}
|
||||
|
||||
.PositionResponsble-user-list-box button { margin-left: 0px; border: 0; background-color: #f4f4f5; border-radius: 4px; padding: 0 10px;}
|
||||
|
||||
.PositionResponsble-type-box .title{
|
||||
font-size: 15px;
|
||||
}
|
||||
.PositionResponsble-type-box .type-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.PositionResponsble-type-box .type-box label { width: 160px; }
|
||||
|
272
src/components/AddPosition/PositionResponsble/index.jsx
Normal file
272
src/components/AddPosition/PositionResponsble/index.jsx
Normal file
@ -0,0 +1,272 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Button, Switch, message } from 'antd'
|
||||
import Addperson from '../Addperson'
|
||||
import {
|
||||
EditFilled,
|
||||
PlusOutlined,
|
||||
InfoCircleOutlined,
|
||||
DeleteFilled,
|
||||
} from '@ant-design/icons'
|
||||
import './index.css'
|
||||
import { getname } from '../../../util/requestURL'
|
||||
|
||||
export default function PositionResponsble({ updataPosition, postdata }) {
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [userlist, setUserlist] = useState({ type: 0, list: [] })
|
||||
const [personlist, setPersonlist] = useState({
|
||||
principal: postdata['principal'] || [],
|
||||
patronn: postdata['patronn'] || [],
|
||||
hr_name: postdata['hr_name'] || [],
|
||||
interview: postdata['interview'] || [],
|
||||
})
|
||||
// let gatuserlist = []
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log(11111)
|
||||
// getname().then(
|
||||
// (res) => {
|
||||
// gatuserlist = res.data
|
||||
// },
|
||||
// (error) => {
|
||||
// message.error('网络加载错误,请稍后再试')
|
||||
// }
|
||||
// )
|
||||
// }, [visible])
|
||||
|
||||
const onCreate = (values) => {
|
||||
const newPersonlist = JSON.parse(JSON.stringify(personlist))
|
||||
if (userlist['type'] !== 'principal') {
|
||||
newPersonlist[userlist['type']].push(values)
|
||||
} else {
|
||||
newPersonlist['principal'][0] = values
|
||||
}
|
||||
setVisible(false)
|
||||
setPersonlist((values) => {
|
||||
return newPersonlist
|
||||
})
|
||||
updataPosition(newPersonlist)
|
||||
}
|
||||
const handelAddUser = (type) => {
|
||||
//type 1:招聘负责人 2:招聘协助人 3:用人经理 4:面试官
|
||||
// console.log(type)
|
||||
getname().then(
|
||||
(res) => {
|
||||
const gatuserlist = res.data
|
||||
const data = {
|
||||
type: type,
|
||||
list: [],
|
||||
}
|
||||
if (type === 'hr_name') {
|
||||
for (let i in gatuserlist) {
|
||||
if (gatuserlist[i]['rank'] == 2) {
|
||||
data['list'].push(gatuserlist[i])
|
||||
}
|
||||
}
|
||||
} else if (type === 'patronn') {
|
||||
for (let i in gatuserlist) {
|
||||
if (gatuserlist[i]['rank'] == 1) {
|
||||
data['list'].push(gatuserlist[i])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data['list'] = gatuserlist
|
||||
}
|
||||
console.log(data)
|
||||
setUserlist(data)
|
||||
setVisible(true)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const handeldelete = (type, index) => {
|
||||
const newpersonlist = personlist[type].filter((item, key) => {
|
||||
return index !== key
|
||||
})
|
||||
setPersonlist({ ...personlist, [type]: newpersonlist })
|
||||
updataPosition({ [type]: newpersonlist })
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="PositionResponsble-box">
|
||||
<Addperson
|
||||
visible={visible}
|
||||
onCreate={onCreate}
|
||||
data={userlist}
|
||||
onCancel={() => {
|
||||
setVisible(false)
|
||||
}}
|
||||
/>
|
||||
<div className="PositionResponsble-list">
|
||||
<div className="PositionResponsble-list-box">
|
||||
<div className="title">招聘负责人</div>
|
||||
<p className="tips-box">
|
||||
负责该职位的招聘,拥有对该职位的操作权限
|
||||
</p>
|
||||
|
||||
<div className="PositionResponsble-user-list-box">
|
||||
{personlist['principal'].map((item, key) => {
|
||||
return (
|
||||
<div className="user-list-box" key={key}>
|
||||
<div className="surname-box">
|
||||
{item.nickname.charAt(0)}
|
||||
</div>
|
||||
<div className="name-box">{item.nickname}</div>
|
||||
<div
|
||||
className="delete-box"
|
||||
onClick={() => {
|
||||
handeldelete('principal', key)
|
||||
}}
|
||||
>
|
||||
<DeleteFilled />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<Button
|
||||
size={'default'}
|
||||
onClick={() => {
|
||||
handelAddUser('principal')
|
||||
}}
|
||||
>
|
||||
<EditFilled />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="PositionResponsble-list-box margintop20">
|
||||
<div className="title">招聘协助人</div>
|
||||
<p className="tips-box">
|
||||
协助参与该职位的招聘,拥有对该职位的权限操作
|
||||
</p>
|
||||
|
||||
<div className="PositionResponsble-user-list-box">
|
||||
{personlist['patronn'].map((item, key) => {
|
||||
return (
|
||||
<div className="user-list-box" key={key}>
|
||||
<div className="surname-box">
|
||||
{item.nickname.charAt(0)}
|
||||
</div>
|
||||
<div className="name-box">{item.nickname}</div>
|
||||
<div
|
||||
className="delete-box"
|
||||
onClick={() => {
|
||||
handeldelete('patronn', key)
|
||||
}}
|
||||
>
|
||||
<DeleteFilled />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<Button
|
||||
size={'default'}
|
||||
onClick={() => {
|
||||
handelAddUser('patronn')
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="PositionResponsble-list-box margintop20">
|
||||
<div className="title">用人经理</div>
|
||||
<p className="tips-box">
|
||||
推荐简历给用人部门时优先找到该用户
|
||||
</p>
|
||||
|
||||
<div className="PositionResponsble-user-list-box">
|
||||
{personlist['hr_name'].map((item, key) => {
|
||||
return (
|
||||
<div className="user-list-box" key={key}>
|
||||
<div className="surname-box">
|
||||
{item.nickname.charAt(0)}
|
||||
</div>
|
||||
<div className="name-box">{item.nickname}</div>
|
||||
<div
|
||||
className="delete-box"
|
||||
onClick={() => {
|
||||
handeldelete('hr_name', key)
|
||||
}}
|
||||
>
|
||||
<DeleteFilled />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<Button
|
||||
size={'default'}
|
||||
onClick={() => {
|
||||
handelAddUser('hr_name')
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="PositionResponsble-list-box margintop20">
|
||||
<div className="title">面试官</div>
|
||||
<p className="tips-box">
|
||||
添加面试时优先找到该用户作为面试官
|
||||
</p>
|
||||
|
||||
<div className="PositionResponsble-user-list-box">
|
||||
{personlist['interview'].map((item, key) => {
|
||||
return (
|
||||
<div className="user-list-box" key={key}>
|
||||
<div className="surname-box">
|
||||
{item.nickname.charAt(0)}
|
||||
</div>
|
||||
<div className="name-box">{item.nickname}</div>
|
||||
<div
|
||||
className="delete-box"
|
||||
onClick={() => {
|
||||
handeldelete('interview', key)
|
||||
}}
|
||||
>
|
||||
<DeleteFilled />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<Button
|
||||
size={'default'}
|
||||
onClick={() => {
|
||||
handelAddUser('interview')
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className="PositionResponsble-list-box margintop20 textalign">
|
||||
<Button type="primary" >保存</Button>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className="PositionResponsble-type-box">
|
||||
<div className="margin24">
|
||||
<p className="title fontweight">高级用人经理安排面试</p>
|
||||
<div className="type-box">
|
||||
<label>
|
||||
允许安排面试 <InfoCircleOutlined />
|
||||
</label>{' '}
|
||||
<Switch defaultChecked />
|
||||
</div>
|
||||
<div className="type-box margintop20">
|
||||
<label>
|
||||
允许给自己面试过的候选人安排面试{' '}
|
||||
<InfoCircleOutlined />
|
||||
</label>{' '}
|
||||
<Switch defaultChecked />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
11
src/components/AddPosition/PositionSetup/index.css
Normal file
11
src/components/AddPosition/PositionSetup/index.css
Normal file
@ -0,0 +1,11 @@
|
||||
.PositionSetup-box {
|
||||
margin: 0 120px;
|
||||
min-height: 300px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.PositionSetup-box .title {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
color: #575d6a;
|
||||
margin-bottom: 24px;
|
||||
}
|
129
src/components/AddPosition/PositionSetup/index.jsx
Normal file
129
src/components/AddPosition/PositionSetup/index.jsx
Normal file
@ -0,0 +1,129 @@
|
||||
import React, {useState} from 'react'
|
||||
import './index.css'
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
Radio,
|
||||
Select,
|
||||
Row,
|
||||
Col,
|
||||
InputNumber,
|
||||
Divider,
|
||||
DatePicker,
|
||||
} from 'antd'
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
|
||||
const { Option } = Select
|
||||
|
||||
export default function PositionSetup({updataPosition, postdata}) {
|
||||
const [form] = Form.useForm()
|
||||
// form.setFieldsValue(postdata)
|
||||
console.log(postdata)
|
||||
return (
|
||||
<div className="PositionSetup-box">
|
||||
<div className="padding24">
|
||||
<div className="title">职位设置</div>
|
||||
|
||||
<Form >
|
||||
<Form.Item
|
||||
label="招聘状态"
|
||||
name="state"
|
||||
initialValue={postdata['state']}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Radio.Group onChange={(e)=>{
|
||||
console.log(e.target.value)
|
||||
updataPosition({state: e.target.value})
|
||||
}}>
|
||||
<Radio.Button value={true}>正在招聘</Radio.Button>
|
||||
<Radio.Button value={false}>结束招聘</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Divider />
|
||||
|
||||
{/* <Form.Item
|
||||
label="招聘流程"
|
||||
name=""
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
defaultValue="0"
|
||||
>
|
||||
<Option value="0">普通流程</Option>
|
||||
<Option value="1">技术岗招聘流程</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Divider />
|
||||
|
||||
<Form.Item
|
||||
label="职位优先级"
|
||||
name=""
|
||||
|
||||
>
|
||||
<Select
|
||||
defaultValue="0"
|
||||
>
|
||||
<Option value="0">普通流程</Option>
|
||||
<Option value="1">技术岗招聘流程</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Divider /> */}
|
||||
|
||||
<Form.Item
|
||||
label="开始招聘时间"
|
||||
name="start_time"
|
||||
initialValue={postdata['start_time'] ? moment(postdata['start_time'], 'YYYY-MM-DD') : ''}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<DatePicker
|
||||
locale={locale}
|
||||
placeholder="请选择招聘开始时间"
|
||||
onChange={(dates, dateStrings) => {
|
||||
updataPosition({start_time: dateStrings+" 00:00:00"})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Divider />
|
||||
|
||||
<Form.Item
|
||||
label="目标完成时间"
|
||||
name="end_time"
|
||||
initialValue={postdata['end_time'] ? moment(postdata['end_time'], 'YYYY-MM-DD') : ''}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<DatePicker
|
||||
locale={locale}
|
||||
placeholder="请选择目标完成时间"
|
||||
onChange={(dates, dateStrings) => {
|
||||
updataPosition({end_time: dateStrings+" 23:59:59"})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* <Form.Item className="textalign">
|
||||
<Button type="primary">保存</Button>
|
||||
</Form.Item> */}
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
43
src/components/AddPosition/Positioninfo/index.css
Normal file
43
src/components/AddPosition/Positioninfo/index.css
Normal file
@ -0,0 +1,43 @@
|
||||
.Positioninfo-box {
|
||||
margin: 0 120px;
|
||||
min-height: 300px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.Positioninfo-box .Positioninfo-info-box {
|
||||
background-color: #fff;
|
||||
width: calc(100% - 308px);
|
||||
border-right: 1px solid #ececee;
|
||||
}
|
||||
.Positioninfo-custom-box {
|
||||
width: 278px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.Positioninfo-info-box .title {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
color: #575d6a;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.Positioninfo-custom-box .title {
|
||||
font-size: 16px;
|
||||
color: #575d6a;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.Positioninfo-custom-box .title span {
|
||||
color: #40a9ff;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.Positioninfo-custom-box .title2 {
|
||||
margin: 14px 0;
|
||||
font-size: 14px;
|
||||
color: #89909e;
|
||||
}
|
||||
|
||||
.Positioninfo-custom-box .label {
|
||||
color: #40a9ff;
|
||||
}
|
452
src/components/AddPosition/Positioninfo/index.jsx
Normal file
452
src/components/AddPosition/Positioninfo/index.jsx
Normal file
@ -0,0 +1,452 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { ownerlist, addjob, postamendjob } from '../../../util/requestURL'
|
||||
import './index.css'
|
||||
import { ProjectFilled } from '@ant-design/icons'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
Radio,
|
||||
Select,
|
||||
Row,
|
||||
Col,
|
||||
InputNumber,
|
||||
Divider,
|
||||
message,
|
||||
DatePicker,
|
||||
} from 'antd'
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
const { Option } = Select
|
||||
const { TextArea } = Input
|
||||
|
||||
export default function Positioninfo({ updataPosition, postdata }) {
|
||||
const [form] = Form.useForm()
|
||||
const navigate = useNavigate()
|
||||
const [value, setValue] = useState(1)
|
||||
const [sectorlist, setSectorlist] = useState([])
|
||||
const [functiontype, setFunctiontype] = useState([])
|
||||
|
||||
const onChange = (e) => {
|
||||
console.log('radio checked', e.target.value)
|
||||
setValue(e.target.value)
|
||||
updataPosition({ job_nature: e.target.value })
|
||||
}
|
||||
|
||||
const onFinish = (values) => {
|
||||
console.log(postdata)
|
||||
if (!postdata.principal || !postdata.hr_name) {
|
||||
message.warning('信息填写不完整,请选择负责人和用人经理!')
|
||||
return
|
||||
} else {
|
||||
if (
|
||||
postdata.principal.length === 0 ||
|
||||
postdata.hr_name.length === 0
|
||||
) {
|
||||
message.warning('信息填写不完整,请选择负责人和用人经理!')
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!postdata.end_time || !postdata.start_time) {
|
||||
message.warning('信息填写不完整,请选择开始时间和结束时间!')
|
||||
return
|
||||
}
|
||||
|
||||
if (postdata.job_id) {
|
||||
postamendjob(postdata).then(
|
||||
(res) => {
|
||||
message.success('修改成功')
|
||||
navigate('/admin/position')
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
} else {
|
||||
addjob(postdata).then(
|
||||
(res) => {
|
||||
// setSectorlist(res.data.date)
|
||||
message.success('添加成功')
|
||||
navigate('/admin/position')
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const handelreturn=()=>{
|
||||
window.history.back()
|
||||
}
|
||||
|
||||
//字段值更新时吧值传入父组件
|
||||
// const onValuesChange = (changedValues) => {
|
||||
// updataPosition(changedValues)
|
||||
// }
|
||||
|
||||
useEffect(() => {
|
||||
//所属部门
|
||||
ownerlist({ name: 'sector' }).then(
|
||||
(res) => {
|
||||
setSectorlist(res.data.date)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
//职能类型
|
||||
ownerlist({ name: 'function_type' }).then(
|
||||
(res) => {
|
||||
setFunctiontype(res.data.date)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}, [])
|
||||
setTimeout(() => {
|
||||
form.setFieldsValue(postdata)
|
||||
}, 1)
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="register"
|
||||
onFinish={(e) => {
|
||||
form.validateFields()
|
||||
onFinish(e)
|
||||
}}
|
||||
// onValuesChange={onValuesChange}
|
||||
initialValues={postdata}
|
||||
>
|
||||
<div className="Positioninfo-box">
|
||||
<div className="Positioninfo-info-box">
|
||||
<div className="margin24">
|
||||
<div className="title">职位信息</div>
|
||||
|
||||
<Form.Item
|
||||
label="职位名称"
|
||||
name={'job_name'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请填写职位名称!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入职位名称"
|
||||
onChange={(e) => {
|
||||
updataPosition({ job_name: e.target.value })
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="所属部门"
|
||||
name={'job_sector'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请填写所属部门!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
onChange={(e) => {
|
||||
updataPosition({ job_sector: e })
|
||||
}}
|
||||
>
|
||||
{sectorlist.map((item, key) => {
|
||||
return (
|
||||
<Option value={item} key={key}>
|
||||
{item}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="职位性质"
|
||||
name={'job_nature'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择职位性质!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Radio.Group
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
>
|
||||
<Radio value={1} checked>
|
||||
全职
|
||||
</Radio>
|
||||
<Radio value={2}>兼职</Radio>
|
||||
<Radio value={3}>实习</Radio>
|
||||
<Radio value={4}>其他</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
{/* <Col span={12}>
|
||||
<Form.Item label="职位类别" name={'function_type'} required>
|
||||
<Input placeholder="input placeholder" />
|
||||
</Form.Item>
|
||||
</Col> */}
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="工作经验"
|
||||
name={'work_exp'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择工作经验!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
onChange={(e) => {
|
||||
updataPosition({ work_exp: e })
|
||||
}}
|
||||
>
|
||||
<Option value={0}>不限</Option>
|
||||
<Option value={1}>应届生</Option>
|
||||
<Option value={2}>1-3年</Option>
|
||||
<Option value={3}>3-5年</Option>
|
||||
<Option value={4}>5年以上</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={2}>
|
||||
<Form.Item
|
||||
label="薪资范围"
|
||||
name={'min_money'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择薪资范围!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="最低薪资 K"
|
||||
onChange={(e) => {
|
||||
updataPosition({
|
||||
min_money: e,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={1} className="textaligncenter">
|
||||
<Form.Item label=" ">~</Form.Item>
|
||||
</Col>
|
||||
<Col span={9}>
|
||||
<Form.Item
|
||||
label=" "
|
||||
name={'max_money'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择薪资范围!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="最高薪资 K"
|
||||
onChange={(e) => {
|
||||
updataPosition({
|
||||
max_money: e,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="招聘人数"
|
||||
name={'job_num'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择招聘人数!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请填写招聘人数"
|
||||
onChange={(e) => {
|
||||
updataPosition({
|
||||
job_num: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="职能类型"
|
||||
name={'function_type'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择职能类型!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
onChange={(e) => {
|
||||
updataPosition({ function_type: e })
|
||||
}}
|
||||
>
|
||||
{functiontype.map((item, key) => {
|
||||
return (
|
||||
<Option value={item} key={key}>
|
||||
{item}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="职位级别"
|
||||
name={'job_rank'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择职位级别!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
onChange={(e) => {
|
||||
updataPosition({ job_rank: e })
|
||||
}}
|
||||
>
|
||||
<Option value="0">不限</Option>
|
||||
<Option value={1}>p1 - p4</Option>
|
||||
<Option value={2}>p5 - p9</Option>
|
||||
<Option value={3}>m1 - m2</Option>
|
||||
<Option value={4}>m2以上</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="学历要求"
|
||||
name={'education'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择学历要求!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
onChange={(e) => {
|
||||
updataPosition({ education: e })
|
||||
}}
|
||||
>
|
||||
<Option value={0}>不限</Option>
|
||||
<Option value={1}>专科</Option>
|
||||
<Option value={2}>本科</Option>
|
||||
<Option value={3}>硕士</Option>
|
||||
<Option value={4}>博士</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="职位描述"
|
||||
name={'requirement'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择职位描述!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<TextArea
|
||||
rows={4}
|
||||
onChange={(e) => {
|
||||
updataPosition({
|
||||
requirement: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{'justifyContent': 'end'}}>
|
||||
<Col span={1}>
|
||||
<Form.Item className="textalign">
|
||||
<Button type="primary" danger onClick={handelreturn}>
|
||||
取消
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={2}>
|
||||
<Form.Item className="textalign">
|
||||
<Button type="primary" htmlType="submit">
|
||||
保存
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 自定义 */}
|
||||
<div className="Positioninfo-custom-box">
|
||||
<div className="margin24">
|
||||
<div className="title">
|
||||
自定义岗位推荐{' '}
|
||||
<span>
|
||||
{' '}
|
||||
<ProjectFilled /> 不准确反馈
|
||||
</span>
|
||||
</div>
|
||||
<div className="title2">
|
||||
从您JD中的提取岗位画像如下:
|
||||
</div>
|
||||
<label className="label">行业要求:软件开发</label>
|
||||
<Divider />
|
||||
<div className="title2">
|
||||
您也可自定义岗位画像的特征,设置完成后在【候选人→人才库推荐】处看到岗位推荐结果
|
||||
</div>
|
||||
{/*
|
||||
<Form.Item label="候选人所在地" required>
|
||||
<Select defaultValue="lucy">
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
<Option value="disabled" disabled>
|
||||
Disabled
|
||||
</Option>
|
||||
<Option value="Yiminghe">
|
||||
yiminghe
|
||||
</Option>
|
||||
</Select>
|
||||
</Form.Item> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
}
|
2
src/components/AddPosition/index.css
Normal file
2
src/components/AddPosition/index.css
Normal file
@ -0,0 +1,2 @@
|
||||
.AddPosition-box .ant-tabs { width: 100%; margin: 0 auto; }
|
||||
.AddPosition-box .ant-tabs-nav { background-color: #fff; padding: 0 24px; }
|
81
src/components/AddPosition/index.jsx
Normal file
81
src/components/AddPosition/index.jsx
Normal file
@ -0,0 +1,81 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, Tabs, message } from 'antd'
|
||||
import Positioninfo from './Positioninfo'
|
||||
import PositionSetup from './PositionSetup'
|
||||
import PositionResponsble from './PositionResponsble'
|
||||
import { EllipsisOutlined, BarsOutlined } from '@ant-design/icons'
|
||||
import { postfindjob } from '../../util/requestURL'
|
||||
import PubSub from 'pubsub-js'
|
||||
import './index.css'
|
||||
const { TabPane } = Tabs
|
||||
|
||||
export default class AddPosition extends Component {
|
||||
state = {
|
||||
state: true
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const urlParams = new URL(window.location.href);
|
||||
const pathname = urlParams.hash;
|
||||
const pathnameArr = pathname.split('/');
|
||||
const id = pathnameArr[pathnameArr.length - 1] //获取id
|
||||
console.log(pathnameArr)
|
||||
if(id !== "addposition"){
|
||||
postfindjob({job_id: id}).then((res)=>{
|
||||
|
||||
this.setState({...res.data})
|
||||
PubSub.publish('headtitle',{headtitle: res.data.job_name})
|
||||
}).catch((err)=>{
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
})
|
||||
|
||||
}else {
|
||||
PubSub.publish('headtitle',{headtitle: '添加职位'})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const onChange = (key) => {
|
||||
|
||||
}
|
||||
|
||||
//更新提交数据
|
||||
const updataPosition = (item) =>{
|
||||
|
||||
this.setState(item,()=>{
|
||||
console.log(this.state)
|
||||
})
|
||||
}
|
||||
const operations = (
|
||||
<>
|
||||
<Button>结束招聘</Button>
|
||||
<Button>
|
||||
<BarsOutlined />
|
||||
</Button>
|
||||
<Button>
|
||||
<EllipsisOutlined className="transform90" />
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="AddPosition-box">
|
||||
<Tabs
|
||||
defaultActiveKey="1"
|
||||
onChange={onChange}
|
||||
tabBarExtraContent={operations}
|
||||
>
|
||||
<TabPane tab="职位信息" key="1">
|
||||
<Positioninfo updataPosition={updataPosition} postdata={this.state}/>
|
||||
</TabPane>
|
||||
<TabPane tab="职位设置" key="2">
|
||||
<PositionSetup updataPosition={updataPosition} postdata={this.state}/>
|
||||
</TabPane>
|
||||
<TabPane tab="负责人" key="3">
|
||||
<PositionResponsble updataPosition={updataPosition} postdata={this.state}/>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
0
src/components/Assignmentposition/index.css
Normal file
0
src/components/Assignmentposition/index.css
Normal file
108
src/components/Assignmentposition/index.jsx
Normal file
108
src/components/Assignmentposition/index.jsx
Normal file
@ -0,0 +1,108 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Form, Modal, Select, message } from 'antd'
|
||||
import { getjob, updatainterview } from '../../util/requestURL'
|
||||
import './index.css'
|
||||
import { get } from 'store'
|
||||
const { Option } = Select
|
||||
|
||||
export default function Assignmentposition(props) {
|
||||
const [form] = Form.useForm()
|
||||
const { visible, onCreate, onCancel, uid } = props
|
||||
const [getjobdata, setgetjobdata] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
if (uid) {
|
||||
getjob({
|
||||
job_name: '',
|
||||
job_sector: '',
|
||||
principal: [],
|
||||
}).then(
|
||||
(res) => {
|
||||
setgetjobdata(res.data.job)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="进入下一阶段"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
destroyOnClose={true}
|
||||
maskClosable={false}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
const job_names = values['job_name'][0].split('-')[0]
|
||||
const job_id = values['job_name'][0].split('-')[1]
|
||||
updatainterview({
|
||||
data_in: {
|
||||
interview_stage: 1,
|
||||
job_names: job_names,
|
||||
job_id: job_id,
|
||||
},
|
||||
interview_query: { uid: uid },
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('添加成功!')
|
||||
onCreate()
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form form={form} layout="vertical" name="form_in_modal">
|
||||
<Form.Item
|
||||
name="job_name"
|
||||
label="分配职位"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '分配职位!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
showSearch
|
||||
placeholder="分配职位"
|
||||
onChange={(option) =>{
|
||||
if(option.length > 1){
|
||||
option.splice(0,1)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getjobdata.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
value={item.job_name + '-' + item.key}
|
||||
key={item.key}
|
||||
>
|
||||
{item.job_name}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,15 +1,19 @@
|
||||
.CandidateTable-box {}
|
||||
.CandidateTable-box { height: calc(100% - 32px); overflow-y: auto; position: relative; }
|
||||
.CandidateTable-list-box { width: 100%; padding: 14px; border-bottom: 1px solid #f4f4f5; display: flex; justify-content: space-between; }
|
||||
.CandidateTable-list-box:hover { background-color: #f9f9fa; }
|
||||
.CandidateTable-list-box:hover .but-box { display: flex; }
|
||||
|
||||
.CandidateTable-info-box { width: 510px; display: flex;}
|
||||
.CandidateTable-info { margin-left: 45px; color: #575d6a; }
|
||||
.CandidateTable-action { width: 420px; position: relative; }
|
||||
|
||||
.CandidateTable-info .name { font-size: 16px; font-weight: bold; color: #000; margin-right: 5px; }
|
||||
.CandidateTable-info div { height: 28px; line-height: 28px; }
|
||||
.but-box { width: 100%; display: flex; position: absolute; bottom: 0; }
|
||||
.CandidateTable-info div {line-height: 28px; }
|
||||
.CandidateTable-action .but-box { width: 100%; display: none; position: absolute; bottom: 0; }
|
||||
.CandidateTable-action .but-box button { margin-right: 14px; }
|
||||
|
||||
.qxcheck-box { color: #c1c5cc; border: 1px solid #c1c5cc; width: 46px; text-align: center; margin-left: 14px; }
|
||||
.qxcheck-box .ant-checkbox + span { padding-right: 0; }
|
||||
.CandidateTable-table-action { border-bottom: 1px solid #f4f4f5; padding: 10px 0;}
|
||||
|
||||
|
||||
|
@ -1,122 +1,679 @@
|
||||
import React from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import './index.css'
|
||||
import { Checkbox, Tag, Button } from 'antd'
|
||||
import { Checkbox, Tag, Button, message, Empty, Popconfirm, Modal } from 'antd'
|
||||
import {
|
||||
ShoppingFilled,
|
||||
BankOutlined,
|
||||
SendOutlined,
|
||||
RightOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import Remarks from '../Remarks'
|
||||
import Eliminate from '../Eliminate'
|
||||
import Recommend from '../Recommend'
|
||||
import Enterthenextstage from '../Enterthenextstage'
|
||||
import Assignmentposition from '../Assignmentposition'
|
||||
import InterviewerInfoPop from '../../components/InterviewerInfoPop'
|
||||
import Editresume from '../../components/Editresume'
|
||||
import {
|
||||
interviewwaiteinfind,
|
||||
interviewupdate,
|
||||
sendinterviewee,
|
||||
} from '../../util/requestURL'
|
||||
const { confirm } = Modal
|
||||
|
||||
export default function CandidateTable() {
|
||||
const onChange = (e) => {
|
||||
console.log(`checked = ${e.target.checked}`)
|
||||
export default class CandidateTable extends Component {
|
||||
state = {
|
||||
data: [
|
||||
// {
|
||||
// interview_name: '张四',
|
||||
// interview_type: 0,
|
||||
// interview_sign: 1,
|
||||
// feedback: 0,
|
||||
// interview_round: 1,
|
||||
// star_time: '2022-07-11T10:30:00',
|
||||
// end_time: '2022-07-11T11:00:00',
|
||||
// event_time: '2022-07-01T10:00:00',
|
||||
// uid: '1234567890',
|
||||
// name: '李五',
|
||||
// phone: '13789923799',
|
||||
// job_name: 'python开发',
|
||||
// hr_name: '王六',
|
||||
// work_exp: '2年',
|
||||
// interview_stage: 1,
|
||||
// owner_name: 2,
|
||||
// education: 1,
|
||||
// work_undergo: '',
|
||||
// school: '武汉大学',
|
||||
// specialty: '计算机专业',
|
||||
// mmended_state: 0,
|
||||
// mail: '250213000@qq.com',
|
||||
// account: '湖北武汉',
|
||||
// id_card: '421202199986750339',
|
||||
// gender: '男',
|
||||
// interview_state: 2,
|
||||
// graduate_time: '2022-07-01T08:00:00',
|
||||
// counts: 1,
|
||||
// choice: false, //选中状态
|
||||
// },
|
||||
// {
|
||||
// interview_name: '张四',
|
||||
// interview_type: 0,
|
||||
// interview_sign: 1,
|
||||
// feedback: 0,
|
||||
// interview_round: 1,
|
||||
// star_time: '2022-07-11T10:30:00',
|
||||
// end_time: '2022-07-11T11:00:00',
|
||||
// event_time: '2022-07-01T10:00:00',
|
||||
// uid: '1234567890',
|
||||
// name: '李五',
|
||||
// phone: '13789923799',
|
||||
// job_name: 'python开发',
|
||||
// hr_name: '王六',
|
||||
// work_exp: '2年',
|
||||
// interview_stage: 1,
|
||||
// owner_name: 2,
|
||||
// education: 1,
|
||||
// work_undergo: '',
|
||||
// school: '武汉大学',
|
||||
// specialty: '计算机专业',
|
||||
// mmended_state: 0,
|
||||
// mail: '250213000@qq.com',
|
||||
// account: '湖北武汉',
|
||||
// id_card: '421202199983750339',
|
||||
// gender: '男',
|
||||
// interview_state: 2,
|
||||
// graduate_time: '2022-07-01T08:00:00',
|
||||
// counts: 1,
|
||||
// choice: false, //选中状态
|
||||
// },
|
||||
],
|
||||
isremarks: false,
|
||||
iseliminate: false,
|
||||
isrecommend: false,
|
||||
isenterthenextstage: false,
|
||||
isassignmentposition: false,
|
||||
interviewerInfo: false,
|
||||
editresume: false,
|
||||
uid: '',
|
||||
step1open: false,
|
||||
}
|
||||
componentDidMount() {
|
||||
this.PostInterviewwaiteinfind()
|
||||
}
|
||||
|
||||
const data = [
|
||||
{
|
||||
interview_name: '张四',
|
||||
interview_type: 0,
|
||||
interview_sign: 1,
|
||||
feedback: 0,
|
||||
interview_round: 1,
|
||||
star_time: '2022-07-11T10:30:00',
|
||||
end_time: '2022-07-11T11:00:00',
|
||||
event_time: '2022-07-01T10:00:00',
|
||||
uid: '1234567890',
|
||||
name: '李五',
|
||||
phone: '13789923799',
|
||||
job_name: 'python开发',
|
||||
hr_name: '王六',
|
||||
work_exp: '2年',
|
||||
interview_stage: 1,
|
||||
owner_name: 2,
|
||||
education: 1,
|
||||
work_undergo: '',
|
||||
school: '武汉大学',
|
||||
specialty: '计算机专业',
|
||||
mmended_state: 0,
|
||||
mail: '250213000@qq.com',
|
||||
account: '湖北武汉',
|
||||
id_card: '421202199986750339',
|
||||
gender: '男',
|
||||
interview_state: 2,
|
||||
graduate_time: '2022-07-01T08:00:00',
|
||||
counts: 1,
|
||||
},
|
||||
]
|
||||
componentDidUpdate() {
|
||||
if (this.props.step !== this.state.prevstep) {
|
||||
this.PostInterviewwaiteinfind()
|
||||
} else if (this.props.job_names !== this.state.provjob_names) {
|
||||
this.PostInterviewwaiteinfind()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="CandidateTable-box">
|
||||
<div className="CandidateTable-table-action">
|
||||
<div className="qxcheck-box">
|
||||
<Checkbox onChange={onChange}>
|
||||
|
||||
<RightOutlined style={{ color: '#c1c5cc' }} />
|
||||
</Checkbox>
|
||||
//请求列表数据
|
||||
PostInterviewwaiteinfind() {
|
||||
interviewwaiteinfind({
|
||||
interview_query: {
|
||||
interview_stage: this.props.step,
|
||||
job_names: this.props.job_names,
|
||||
},
|
||||
}).then(
|
||||
(res) => {
|
||||
for (let i in res.data) {
|
||||
res.data[i]['choice'] = false
|
||||
}
|
||||
this.setState({
|
||||
data: res.data,
|
||||
prevstep: this.props.step,
|
||||
provjob_names: this.props.job_names,
|
||||
})
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onPopconfirm = (uid) => {
|
||||
sendinterviewee({ uid: uid }).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
this.PostInterviewwaiteinfind()
|
||||
message.success('推荐成功,请尽快要用人经理确认!')
|
||||
} else {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, step1open } = this.state
|
||||
const { step, job_names } = this.props
|
||||
|
||||
//已勾选个数
|
||||
let choiceCount = 0
|
||||
if (data.length > 0) {
|
||||
choiceCount = data.reduce(
|
||||
(pre, item) => pre + (item.choice ? 1 : 0),
|
||||
0
|
||||
)
|
||||
}
|
||||
//数据个数
|
||||
const todata = data.length
|
||||
|
||||
//单个选择框
|
||||
const onChange = (e) => {
|
||||
const type = e.target.checked
|
||||
const id = e.target.value
|
||||
const { data } = this.state
|
||||
const newData = data.map((dataObj) => {
|
||||
if (dataObj.id_card === id) return { ...dataObj, choice: type }
|
||||
else return dataObj
|
||||
})
|
||||
this.setState({
|
||||
data: newData,
|
||||
})
|
||||
}
|
||||
// 全选框
|
||||
const onAllChange = (e) => {
|
||||
const type = e.target.checked
|
||||
const { data } = this.state
|
||||
const newData = data.map((dataObj) => {
|
||||
return { ...dataObj, choice: type }
|
||||
})
|
||||
this.setState({ data: newData })
|
||||
}
|
||||
|
||||
//淘汰关闭按钮
|
||||
const onClose = () => {
|
||||
this.setState({
|
||||
isremarks: false,
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemarks = (uid) => {
|
||||
this.setState({
|
||||
isremarks: true,
|
||||
uid: uid,
|
||||
})
|
||||
}
|
||||
|
||||
const handleEliminate = (uid) => {
|
||||
this.setState({
|
||||
iseliminate: true,
|
||||
uid: uid,
|
||||
})
|
||||
}
|
||||
|
||||
const handleRecommend = (uid) => {
|
||||
this.setState({
|
||||
isrecommend: true,
|
||||
uid: uid,
|
||||
})
|
||||
}
|
||||
|
||||
const onEliminateCreate = (e) => {
|
||||
setTimeout(() => {
|
||||
this.PostInterviewwaiteinfind()
|
||||
this.props.updatainterviewstagenum()
|
||||
this.setState({
|
||||
iseliminate: false,
|
||||
isrecommend: false,
|
||||
isenterthenextstage: false,
|
||||
isassignmentposition: false,
|
||||
})
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
//进入下一阶段
|
||||
const handelinterviewupdate = (uid) => {
|
||||
const type = parseInt(this.props.step) + parseInt(1)
|
||||
interviewupdate({
|
||||
data_in: { interview_stage: type },
|
||||
interview_query: { uid: uid },
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('操作成功!')
|
||||
setTimeout(() => {
|
||||
this.PostInterviewwaiteinfind()
|
||||
this.props.updatainterviewstagenum()
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
}
|
||||
|
||||
const handelCandidateClick = (uid) => {
|
||||
console.log(uid)
|
||||
this.setState({
|
||||
interviewerInfo: true,
|
||||
uid: uid,
|
||||
})
|
||||
}
|
||||
|
||||
// 查看详情里面编辑按钮
|
||||
const onEditresume = (data) => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
editresume: true,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="CandidateTable-box">
|
||||
<div className="CandidateTable-table-action">
|
||||
<div className="qxcheck-box">
|
||||
<Checkbox
|
||||
onChange={onAllChange}
|
||||
checked={choiceCount === todata ? true : false}
|
||||
>
|
||||
<RightOutlined style={{ color: '#c1c5cc' }} />
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div>
|
||||
|
||||
</div> */}
|
||||
</div>
|
||||
<div style={{ width: 'calc(100% - 4px)' }}>
|
||||
{this.state.data.length > 0 ? (
|
||||
this.state.data.map((item, key) => {
|
||||
return (
|
||||
<div
|
||||
className="CandidateTable-list-box"
|
||||
key={item.uid}
|
||||
onClick={() =>
|
||||
handelCandidateClick(item.uid)
|
||||
}
|
||||
>
|
||||
<div className="CandidateTable-info-box">
|
||||
<div>
|
||||
<Checkbox
|
||||
checked={item.choice}
|
||||
onChange={onChange}
|
||||
value={item.id_card}
|
||||
></Checkbox>
|
||||
</div>
|
||||
<div className="CandidateTable-info">
|
||||
<div>
|
||||
<span className="time">
|
||||
{item.event_time}申请 |
|
||||
</span>
|
||||
<span> {item.job_name}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="name">
|
||||
{item.name}
|
||||
</span>
|
||||
<span> {item.gender} |</span>
|
||||
<span> {item.age} | </span>
|
||||
{item.work_exp == 0 ? (
|
||||
<span>无经验</span>
|
||||
) : (
|
||||
<span>
|
||||
{item.work_exp}工作经验
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{item['work_list'].map(
|
||||
(items, key) => {
|
||||
return (
|
||||
<div key={key}>
|
||||
<ShoppingFilled />
|
||||
<span>
|
||||
{
|
||||
items.company_name
|
||||
}{' '}
|
||||
|{' '}
|
||||
{
|
||||
items.position_name
|
||||
}{' '}
|
||||
| {items.time}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)}
|
||||
|
||||
<div>
|
||||
{data.map((item, key) => {
|
||||
return (
|
||||
<div className="CandidateTable-list-box">
|
||||
<div className="CandidateTable-info-box">
|
||||
<div>
|
||||
<Checkbox onChange={onChange}></Checkbox>
|
||||
</div>
|
||||
<div className="CandidateTable-info">
|
||||
<div>
|
||||
<span className="time">
|
||||
2022-05-16申请 |
|
||||
</span>
|
||||
<span> {item.job_name}</span>
|
||||
<div>
|
||||
<BankOutlined />
|
||||
{item.school !== '' ? (
|
||||
<span> {item.school}</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{item.specialty !== '' ? (
|
||||
<span>
|
||||
{' '}
|
||||
| {item.specialty}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{item.education !== '' ? (
|
||||
<span>
|
||||
{' '}
|
||||
| {item.education}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{item.graduate_time !== '' ? (
|
||||
<span>
|
||||
{' '}
|
||||
| {item.graduate_time}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Tag color="processing">
|
||||
{item.education}
|
||||
</Tag>
|
||||
{/* <Tag color="warning">
|
||||
空白经历
|
||||
</Tag> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="name">{item.name}</span>
|
||||
<span> {item.gender} |</span> <span> 25 |</span>
|
||||
<span> {item.work_exp}工作经验</span>
|
||||
<div className="CandidateTable-owner">
|
||||
候选人所有者:<span>{item.hr_name}</span>
|
||||
</div>
|
||||
<div>
|
||||
<ShoppingFilled />
|
||||
<span>{item.account} |</span>
|
||||
<span> 2021-06至2022-05</span>
|
||||
</div>
|
||||
<div>
|
||||
<BankOutlined /> <span> {item.school} |</span>
|
||||
<span> {item.specialty} | </span> <span> 硕士 |</span>
|
||||
<span> {item.graduate_time}</span>
|
||||
</div>
|
||||
<div>
|
||||
<Tag color="processing">硕士</Tag>
|
||||
<Tag color="warning">空白经历</Tag>
|
||||
<div className="CandidateTable-action">
|
||||
推荐状态:
|
||||
{item.mmended_state == '未推荐' ? (
|
||||
<Tag
|
||||
icon={<SendOutlined />}
|
||||
color="default"
|
||||
>
|
||||
未推荐
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag
|
||||
icon={<SendOutlined />}
|
||||
color="magenta"
|
||||
>
|
||||
以推荐
|
||||
</Tag>
|
||||
)}
|
||||
<div className="but-box">
|
||||
{step < 5 && step != 1 && step != 3? (
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
if (step === '2') {
|
||||
this.setState({
|
||||
isenterthenextstage: true,
|
||||
uid: item.uid,
|
||||
})
|
||||
} else if (
|
||||
step === '0'
|
||||
) {
|
||||
this.setState({
|
||||
isassignmentposition: true,
|
||||
uid: item.uid,
|
||||
})
|
||||
} else {
|
||||
handelinterviewupdate(
|
||||
item.uid
|
||||
)
|
||||
}
|
||||
}}
|
||||
>
|
||||
进入 下一阶段
|
||||
</Button>
|
||||
) : step === '1' ? (
|
||||
<Popconfirm
|
||||
title="确定进入下一阶段,并推送给对应的用人经理"
|
||||
onConfirm={(e) => {
|
||||
e.stopPropagation()
|
||||
this.onPopconfirm(
|
||||
item.uid
|
||||
)
|
||||
}}
|
||||
open={step1open}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
onCancel={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
this.setState({
|
||||
step1open: true,
|
||||
})
|
||||
}}
|
||||
>
|
||||
进入下一阶段
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
) : step === '3'?(
|
||||
item.teacher_state === "未反馈"?(
|
||||
<Button
|
||||
type="primary"
|
||||
disabled
|
||||
>
|
||||
{item.teacher_state}
|
||||
</Button>
|
||||
):(
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handelinterviewupdate(
|
||||
item.uid
|
||||
)
|
||||
}}
|
||||
>
|
||||
进入 下一阶段
|
||||
</Button>
|
||||
)
|
||||
|
||||
):(
|
||||
''
|
||||
)}
|
||||
{step < 5 ? (
|
||||
<>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleEliminate(
|
||||
item.uid
|
||||
)
|
||||
}}
|
||||
>
|
||||
淘汰
|
||||
</Button>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleRemarks(
|
||||
item.uid
|
||||
)
|
||||
}}
|
||||
>
|
||||
备注
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleRemarks(
|
||||
item.uid
|
||||
)
|
||||
}}
|
||||
>
|
||||
{/* 淘汰 */}
|
||||
未入职
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
confirm({
|
||||
title: '确认修改候选人状态为已入职',
|
||||
icon: (
|
||||
<ExclamationCircleOutlined />
|
||||
),
|
||||
okText: '确认',
|
||||
cancelText:
|
||||
'取消',
|
||||
onOk() {
|
||||
interviewupdate({
|
||||
data_in: { interview_stage: 8 },
|
||||
interview_query: { uid: item.uid },
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('操作成功!')
|
||||
setTimeout(() => {
|
||||
this.PostInterviewwaiteinfind()
|
||||
this.props.updatainterviewstagenum()
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
{/* 备注 */}
|
||||
待入职
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* {
|
||||
step <= 3? (<Button >重新推荐</Button>) :''
|
||||
} */}
|
||||
{/* {step === '1' ? (
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleRecommend(
|
||||
item.uid
|
||||
)
|
||||
}}
|
||||
>
|
||||
推荐给用人部门
|
||||
</Button>
|
||||
) : (
|
||||
''
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="CandidateTable-owner">
|
||||
候选人所有者:<span>张三</span>
|
||||
</div>
|
||||
<div className="CandidateTable-action">
|
||||
推荐状态:
|
||||
<Tag icon={<SendOutlined />} color="default">
|
||||
未推荐
|
||||
</Tag>
|
||||
<div className="but-box">
|
||||
<Button type="primary">
|
||||
进入 下一阶段
|
||||
</Button>
|
||||
<Button>淘汰</Button>
|
||||
<Button>备注</Button>
|
||||
<Button>推荐给用人部门</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="margintop30 Empty-box">
|
||||
<Empty description={'暂无数据'} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
)}
|
||||
</div>
|
||||
{/* 备注 */}
|
||||
<Remarks
|
||||
onClose={onClose}
|
||||
visible={this.state.isremarks}
|
||||
uid={this.state.uid}
|
||||
remark_stage={step}
|
||||
/>
|
||||
|
||||
{/* 淘汰 */}
|
||||
<Eliminate
|
||||
visible={this.state.iseliminate}
|
||||
onCreate={onEliminateCreate}
|
||||
uid={this.state.uid}
|
||||
remark_stage={step}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
iseliminate: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 推荐给用人部门 */}
|
||||
<Recommend
|
||||
visible={this.state.isrecommend}
|
||||
onCreate={onEliminateCreate}
|
||||
uid={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
isrecommend: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 进入下一阶段 */}
|
||||
<Enterthenextstage
|
||||
visible={this.state.isenterthenextstage}
|
||||
onCreate={onEliminateCreate}
|
||||
uid={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
isenterthenextstage: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 下一阶段分配岗位 */}
|
||||
<Assignmentposition
|
||||
visible={this.state.isassignmentposition}
|
||||
onCreate={onEliminateCreate}
|
||||
uid={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
isassignmentposition: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 查看面试人信息弹窗 */}
|
||||
<InterviewerInfoPop
|
||||
visible={this.state.interviewerInfo}
|
||||
onCreate={() => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
})
|
||||
}}
|
||||
data={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
})
|
||||
}}
|
||||
onEditresume={() => {
|
||||
onEditresume()
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 编辑候选人信息弹窗 */}
|
||||
<Editresume
|
||||
visible={this.state.editresume}
|
||||
onCreate={() => {
|
||||
this.setState({
|
||||
editresume: false,
|
||||
})
|
||||
}}
|
||||
data={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
editresume: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -29,10 +29,15 @@
|
||||
.upload-head-box label { color: #75777d; font-size: 12px; margin-top: 5px; }
|
||||
.Editresume-box .ant-tabs-content-holder {
|
||||
max-height: 557px !important;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.upload-button-box {
|
||||
margin: 24px;
|
||||
}
|
||||
.upload-button-box .ant-upload {width: 100%;}
|
||||
.upload-button-box button { width: 100%; }
|
||||
.upload-button-box .ant-upload-list {display: none;}
|
||||
|
||||
.resume-energy-box { display: flex; justify-content: space-between; }
|
||||
.resume-xq-box { height: 625px; overflow-x: hidden; overflow-y: auto; }
|
||||
.width700 { width: 700px; }
|
||||
|
File diff suppressed because it is too large
Load Diff
0
src/components/Eliminate/index.css
Normal file
0
src/components/Eliminate/index.css
Normal file
105
src/components/Eliminate/index.jsx
Normal file
105
src/components/Eliminate/index.jsx
Normal file
@ -0,0 +1,105 @@
|
||||
import React, { useEffect , useState} from 'react'
|
||||
import { Form, Input, Modal, Radio,Select, message } from 'antd'
|
||||
import {interviewupdate, operatelog} from "../../util/requestURL"
|
||||
import memoryUtils from '../../util/memoryUtils'
|
||||
const { Option } = Select
|
||||
|
||||
export default function Eliminate(props) {
|
||||
const { visible, onCreate, onCancel, uid, remark_stage } = props
|
||||
const [form] = Form.useForm()
|
||||
const pass_why_list = [
|
||||
{title: '招聘需求变更', value: 0},
|
||||
{title: '福利待遇不匹配', value: 1},
|
||||
{title: '与公司文化不符', value: 2},
|
||||
{title: '淘汰', value: 3},
|
||||
{title: '胜任力不足', value: 4},
|
||||
{title: '没有回应', value: 5},
|
||||
{title: '其他', value: 6}
|
||||
]
|
||||
let userInfo = memoryUtils.userInfo
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="淘汰候选人"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
interviewupdate({
|
||||
data_in: {"interview_stage": 11, ...values},//淘汰
|
||||
interview_query: { uid: uid },
|
||||
data:{interview_stage: remark_stage},
|
||||
find_column:[]
|
||||
}).then(
|
||||
(res) => {
|
||||
// console.log(res)
|
||||
message.success('操作成功!')
|
||||
onCreate(values)
|
||||
operatelog({
|
||||
user_id: uid,
|
||||
why: "淘汰候选人",
|
||||
content: pass_why_list[values.pass_why]['title'] + values.pass_text,
|
||||
})
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="form_in_modal"
|
||||
initialValues={{
|
||||
modifier: 'message',
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
name="pass_why"
|
||||
label="淘汰原因"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message:
|
||||
'请选择淘汰原因!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
<Option value={0}>招聘需求变更</Option>
|
||||
<Option value={1}>福利待遇不匹配</Option>
|
||||
<Option value={2}>与公司文化不符</Option>
|
||||
<Option value={3}>淘汰</Option>
|
||||
<Option value={4}>胜任力不足</Option>
|
||||
<Option value={5}>没有回应</Option>
|
||||
<Option value={6}>其他</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="pass_text" label="详细原因">
|
||||
<Input type="textarea" />
|
||||
</Form.Item>
|
||||
{/* <Form.Item
|
||||
name="modifier"
|
||||
className="collection-create-form_last-form-item"
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value="message" >短信拒绝</Radio>
|
||||
<Radio value="mailbox">邮箱拒绝</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item> */}
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
0
src/components/Enterthenextstage/index.css
Normal file
0
src/components/Enterthenextstage/index.css
Normal file
190
src/components/Enterthenextstage/index.jsx
Normal file
190
src/components/Enterthenextstage/index.jsx
Normal file
@ -0,0 +1,190 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Form, Modal, DatePicker, Select, message, Row, Col } from 'antd'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import moment from 'moment'
|
||||
import { getname, addinterviewe } from '../../util/requestURL'
|
||||
import './index.css'
|
||||
const { Option } = Select
|
||||
const { RangePicker } = DatePicker
|
||||
|
||||
export default function Enterthenextstage(props) {
|
||||
const [form] = Form.useForm()
|
||||
const { visible, onCreate, onCancel, uid } = props
|
||||
const [getnamedata, setgetnamedata] = useState([])
|
||||
const [stime, ssettime] = useState()
|
||||
const [etime, esettime] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
if (uid) {
|
||||
getname().then(
|
||||
(res) => {
|
||||
console.log(res.data)
|
||||
setgetnamedata(res.data)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="进入下一阶段"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
destroyOnClose={true}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
var data = {}
|
||||
data['uid'] = uid
|
||||
data['user_id'] = values.user_id
|
||||
data['hr_user'] = values.hr_user
|
||||
data['star_time'] = stime
|
||||
data['end_time'] = etime
|
||||
addinterviewe(data).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('添加成功!')
|
||||
onCreate()
|
||||
esettime('')
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="form_in_modal"
|
||||
preserve={false}
|
||||
>
|
||||
<Form.Item
|
||||
name="hr_user"
|
||||
label="分配HR"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择HR!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select mode="multiple">
|
||||
{getnamedata.map((item, key) => {
|
||||
return item.rank === 1 ? (
|
||||
<Option value={item.user_id} key={item._id}>
|
||||
{item.nickname}
|
||||
</Option>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="user_id"
|
||||
label="分配面试官"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择面试官!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select mode="multiple">
|
||||
{getnamedata.map((item, key) => {
|
||||
return item.rank === 2 ? (
|
||||
<Option value={item.user_id} key={item._id}>
|
||||
{item.nickname}
|
||||
</Option>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Row gutter={24}>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="stime"
|
||||
label="面试时间"
|
||||
>
|
||||
<DatePicker
|
||||
showTime
|
||||
locale={locale}
|
||||
onChange={(date, dateString) => {
|
||||
// console.log(dateString)
|
||||
var date = new Date(dateString)
|
||||
var time3 =
|
||||
(Date.parse(date) / 1000 + 1800) *
|
||||
1000
|
||||
var time = new Date(time3)
|
||||
var y = time.getFullYear()
|
||||
var m =
|
||||
time.getMonth() + 1 < 10
|
||||
? '0' + (time.getMonth() + 1)
|
||||
: time.getMonth() + 1
|
||||
var d =
|
||||
time.getDate() < 10
|
||||
? '0' + time.getDate()
|
||||
: time.getDate()
|
||||
var h =
|
||||
time.getHours() < 10
|
||||
? '0' + time.getHours()
|
||||
: time.getHours()
|
||||
var mm =
|
||||
time.getMinutes() < 10
|
||||
? '0' + time.getMinutes()
|
||||
: time.getMinutes()
|
||||
var s =
|
||||
time.getSeconds() < 10
|
||||
? '0' + time.getSeconds()
|
||||
: time.getSeconds()
|
||||
var end_time =
|
||||
y +
|
||||
'-' +
|
||||
m +
|
||||
'-' +
|
||||
d +
|
||||
' ' +
|
||||
h +
|
||||
':' +
|
||||
mm +
|
||||
':' +
|
||||
s
|
||||
|
||||
ssettime(dateString)
|
||||
esettime(end_time)
|
||||
}}
|
||||
/>
|
||||
<DatePicker
|
||||
showTime
|
||||
locale={locale}
|
||||
value={etime?moment(
|
||||
etime,
|
||||
'YYYY/MM/DD HH:mm:ss'
|
||||
):''}
|
||||
format={'YYYY/MM/DD HH:mm:ss'}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Modal, DatePicker, Form, Radio, Button } from 'antd'
|
||||
import { Modal, DatePicker, Form, Radio, Button, message } from 'antd'
|
||||
import { downloadinterview } from '../../util/requestURL'
|
||||
import './index.css'
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/zh-cn'
|
||||
@ -7,6 +8,7 @@ import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
const { RangePicker } = DatePicker
|
||||
const dateFormat = 'YYYY/MM/DD'
|
||||
|
||||
|
||||
export default function ExportForm({ visible, onCreate, onCancel }) {
|
||||
const today = [
|
||||
moment(
|
||||
@ -59,7 +61,26 @@ export default function ExportForm({ visible, onCreate, onCancel }) {
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
console.log(time)
|
||||
// console.log(time)
|
||||
let name = ''
|
||||
if(time[0] === time[1]){
|
||||
name = time[0]+'面试安排'
|
||||
}else{
|
||||
name = time[0]+'至'+time[1]+'面试安排'
|
||||
}
|
||||
const dateTimes = {
|
||||
start_time: time[0],
|
||||
end_time: time[1],
|
||||
name: name
|
||||
}
|
||||
downloadinterview(dateTimes).then(
|
||||
(res) => {
|
||||
// console.log(res)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试');
|
||||
}
|
||||
)
|
||||
}}
|
||||
>
|
||||
<h5>最多可导出连续7天的面试</h5>
|
||||
@ -71,7 +92,6 @@ export default function ExportForm({ visible, onCreate, onCancel }) {
|
||||
value={dataArr}
|
||||
onChange={(dates, dateStrings) => {
|
||||
setdataArr(dates)
|
||||
console.log(dateStrings)
|
||||
setTime(dateStrings)
|
||||
}}
|
||||
/>
|
||||
|
@ -1,11 +1,27 @@
|
||||
import React,{Component} from 'react'
|
||||
import PubSub from 'pubsub-js'
|
||||
import "./index.css"
|
||||
// import { withRouter } from 'react-router-dom'
|
||||
|
||||
|
||||
class HeadLeftTtile extends Component {
|
||||
render() {
|
||||
const { headtitle } = this.props
|
||||
|
||||
componentDidMount(){
|
||||
this.headtitle = PubSub.subscribe('headtitle',(_,stateObj)=>{
|
||||
this.setState(stateObj)
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
PubSub.unsubscribe(this.headtitle)
|
||||
}
|
||||
|
||||
render() {
|
||||
let headtitle
|
||||
if(this.state){
|
||||
headtitle = this.state.headtitle
|
||||
}
|
||||
|
||||
return <div className="HeadLeftTitle-box">{headtitle}</div>
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Button } from 'antd'
|
||||
import ResumeUpload from '../../pages/ResumeUpload'
|
||||
import {PlusOutlined} from '@ant-design/icons'
|
||||
|
||||
export default function InterviewUploadPop() {
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
// onClick={() => {
|
||||
// setVisible(true)
|
||||
// }}
|
||||
>
|
||||
<PlusOutlined />上传
|
||||
</Button>
|
||||
|
||||
{/* <ResumeUpload
|
||||
visible={visible}
|
||||
onCreate={onCreate}
|
||||
onCancel={() => {
|
||||
setVisible(false)
|
||||
}}
|
||||
/> */}
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,29 +1,48 @@
|
||||
import React from 'react'
|
||||
import React,{useEffect} from 'react'
|
||||
import './index.css'
|
||||
import { UploadOutlined } from '@ant-design/icons'
|
||||
import { Button, message, Upload,Input } from 'antd'
|
||||
|
||||
const props = {
|
||||
name: 'file',
|
||||
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
|
||||
headers: {
|
||||
authorization: 'authorization-text',
|
||||
},
|
||||
export default function EnclosureTabs({data, Tabsnum}) {
|
||||
|
||||
onChange(info) {
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
useEffect(() => {
|
||||
if (Tabsnum === '6') {
|
||||
// getoperatelog({ user_id: data }).then(
|
||||
// (res) => {
|
||||
// console.log(res)
|
||||
// setdatalist(res.data)
|
||||
// },
|
||||
// (err) => {
|
||||
// message.error('网络加载错误,请稍后再试')
|
||||
// }
|
||||
// )
|
||||
}
|
||||
}, [Tabsnum])
|
||||
|
||||
if (info.file.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`)
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
},
|
||||
}
|
||||
const props = {
|
||||
name: 'file',
|
||||
// action: 'http://myip.legu.cc:7800/api/v1/itr/resume_affix',
|
||||
action: 'http://10.0.0.4:7800/api/v1/itr/resume_affix',
|
||||
data:{
|
||||
uid: data.uid
|
||||
},
|
||||
headers: {
|
||||
authorization: 'authorization-text',
|
||||
},
|
||||
|
||||
onChange(info) {
|
||||
if (info.file.status != 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
}
|
||||
|
||||
if (info.file.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`)
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default function EnclosureTabs() {
|
||||
return (
|
||||
<div className="EnclosureTabs-box">
|
||||
<h2>附件</h2>
|
||||
|
5
src/components/InterviewerInfoPop/Feedback/index.css
Normal file
5
src/components/InterviewerInfoPop/Feedback/index.css
Normal file
@ -0,0 +1,5 @@
|
||||
.Feedback-title { font-size: 17px; color: #000; font-weight: bold; margin-top: 24px; }
|
||||
.Feedback-tag { margin-bottom: 0; color: #75777d; }
|
||||
|
||||
/* .result-box .ant-radio-button-wrapper { padding: 16px 30px; } */
|
||||
|
193
src/components/InterviewerInfoPop/Feedback/index.jsx
Normal file
193
src/components/InterviewerInfoPop/Feedback/index.jsx
Normal file
@ -0,0 +1,193 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Drawer, Button, Input, message, Radio, Space } from 'antd'
|
||||
import {
|
||||
interviewteacher,
|
||||
getteacher,
|
||||
upteacher,
|
||||
} from '../../../util/requestURL'
|
||||
import storageUtils from '../../../util/storageUtils'
|
||||
import './index.css'
|
||||
const { TextArea } = Input
|
||||
|
||||
export default function Feedback({ visible, onClose, uid }) {
|
||||
var userInfo = storageUtils.getUser()
|
||||
const [voice, setvoice] = useState(1)
|
||||
const [thought, setthought] = useState(1)
|
||||
const [diathesis, setdiathesis] = useState(1)
|
||||
const [evaluate, setevaluate] = useState('')
|
||||
const [teacherback, setteacherback] = useState(1)
|
||||
const [isupdata, setisupdata] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (uid) {
|
||||
getteacher({ uid: uid }).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
if (res.data.uid) {
|
||||
const user_id = userInfo.user_id
|
||||
if (res.data['survey']['']) {
|
||||
setisupdata(1)
|
||||
setvoice(res.data['survey'][user_id].voice || 1)
|
||||
setthought(res.data['survey'][user_id].thought || 1)
|
||||
setdiathesis(
|
||||
res.data['survey'][user_id].diathesis || 1
|
||||
)
|
||||
setevaluate(res.data['survey'][user_id].evaluate)
|
||||
setteacherback(res.data['survey'][user_id].teacher_back)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载失败,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
const handelFeedback = () => {
|
||||
const date = {
|
||||
name: userInfo.name,
|
||||
voice,
|
||||
thought,
|
||||
diathesis,
|
||||
evaluate,
|
||||
teacher_back: teacherback,
|
||||
}
|
||||
|
||||
if (isupdata === 0) {
|
||||
interviewteacher({
|
||||
uid: uid,
|
||||
survey: {
|
||||
[userInfo.user_id]: date,
|
||||
},
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('添加成功')
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载失败,请稍后再试')
|
||||
}
|
||||
)
|
||||
} else {
|
||||
upteacher({
|
||||
uid: uid,
|
||||
[userInfo.user_id]: date,
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('修改成功')
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载失败,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Drawer
|
||||
title="填写反馈"
|
||||
placement="right"
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
zIndex={10000}
|
||||
width={520}
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>取消</Button>
|
||||
<Button type="primary" onClick={handelFeedback}>
|
||||
确定
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div className="Feedback-box">
|
||||
<div className="Feedback-title">语言表达(单选题)</div>
|
||||
<p className="Feedback-tag">
|
||||
语言表达是否具有逻辑性,简洁性及感染力。
|
||||
</p>
|
||||
<p className="Feedback-tag">
|
||||
评分规则:好8-10分,中4-7分,差:0-3分
|
||||
</p>
|
||||
<Radio.Group
|
||||
onChange={(e) => setvoice(e.target.value)}
|
||||
value={voice}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<Radio value={1}>好</Radio>
|
||||
<Radio value={2}>中</Radio>
|
||||
<Radio value={3}>差</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
|
||||
<div className="Feedback-title">逻辑思维(单选题)</div>
|
||||
<p className="Feedback-tag">
|
||||
思维是否清晰,分析问题是否准确,透彻。
|
||||
</p>
|
||||
<p className="Feedback-tag">
|
||||
评分规则:好8-10分,中4-7分,差:0-3分
|
||||
</p>
|
||||
<Radio.Group
|
||||
onChange={(e) => setthought(e.target.value)}
|
||||
value={thought}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<Radio value={1}>好</Radio>
|
||||
<Radio value={2}>中</Radio>
|
||||
<Radio value={3}>差</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
<div className="Feedback-title">个人素养(单选题)</div>
|
||||
<p className="Feedback-tag">
|
||||
个人学历,仪表气质是否达到要求。
|
||||
</p>
|
||||
<p className="Feedback-tag">
|
||||
评分规则:好8-10分,中4-7分,差:0-3分
|
||||
</p>
|
||||
<Radio.Group
|
||||
onChange={(e) => setdiathesis(e.target.value)}
|
||||
value={diathesis}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<Radio value={1}>好</Radio>
|
||||
<Radio value={2}>中</Radio>
|
||||
<Radio value={3}>差</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
|
||||
<div className="Feedback-title">综合评价</div>
|
||||
<p className="Feedback-tag">
|
||||
请详细说明候选人的优势,不足,及任何值得注意的方面。
|
||||
</p>
|
||||
<TextArea
|
||||
rows={4}
|
||||
className="margintop20"
|
||||
value={evaluate}
|
||||
onChange={(e) => setevaluate(e.target.value)}
|
||||
/>
|
||||
|
||||
<div className="Feedback-title">面试结果</div>
|
||||
<div className="margintop20 result-box">
|
||||
<Radio.Group
|
||||
value={teacherback}
|
||||
buttonStyle="solid"
|
||||
onChange={(e) => setteacherback(e.target.value)}
|
||||
>
|
||||
<Radio.Button value={4}>非常不满意</Radio.Button>
|
||||
<Radio.Button value={3}>不满意</Radio.Button>
|
||||
<Radio.Button value={1}>满意</Radio.Button>
|
||||
<Radio.Button value={2}>非常满意</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -14,6 +14,8 @@
|
||||
.InterviewTabs-content-list-box label { width: 160px; }
|
||||
.InterviewTabs-content-list-actionbar { margin-top: 10px; padding: 0 10px; display: flex; justify-content: space-between; align-items: center; background-color: #f0f0f0; height: 35px; line-height: 35px; }
|
||||
|
||||
.InterviewTabs-content-list-left-box { display: flex; }
|
||||
.InterviewTabs-content-list-left-name { width: 160px; }
|
||||
|
||||
|
||||
|
||||
|
@ -1,68 +1,61 @@
|
||||
import React from 'react'
|
||||
import { Button, Collapse, Divider, Tag } from 'antd'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Button, Collapse, Divider, message, Tag, Empty } from 'antd'
|
||||
import Enterthenextstage from '../../Enterthenextstage'
|
||||
import { record, teacherstate } from '../../../util/requestURL'
|
||||
import storageUtils from '../../../util/storageUtils'
|
||||
import './index.css'
|
||||
import {
|
||||
CalendarFilled,
|
||||
SettingOutlined,
|
||||
WarningFilled,
|
||||
DislikeOutlined,
|
||||
LikeOutlined,
|
||||
} from '@ant-design/icons'
|
||||
|
||||
const { Panel } = Collapse
|
||||
|
||||
export default function InterviewTabs() {
|
||||
export default function InterviewTabs({
|
||||
data,
|
||||
Tabsnum,
|
||||
setisfeedback,
|
||||
seefeedback,
|
||||
}) {
|
||||
const [isenterthenextstage, setisenterthenextstage] = useState(false)
|
||||
const [datalist, setdatalist] = useState([])
|
||||
let userinfo = storageUtils.getUser()
|
||||
useEffect(() => {
|
||||
if (Tabsnum === '2') {
|
||||
record({ uid: data.uid }).then(
|
||||
(res) => {
|
||||
// console.log(res)
|
||||
setdatalist(res.data)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [Tabsnum])
|
||||
|
||||
const handelFeedback = (record) => {
|
||||
teacherstate({
|
||||
user_id: [record.interview_id],
|
||||
name: record.name,
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.code == 200) {
|
||||
message.success('发送成功')
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const onChange = (key) => {
|
||||
console.log(key)
|
||||
}
|
||||
const data = [
|
||||
{
|
||||
title: '2022年5月16日 星期一·现场面试',
|
||||
place: '武汉市洪山区野芷湖西路创意天地5号楼2层',
|
||||
pic: '张三',
|
||||
rounds: 0,
|
||||
time: '12:00',
|
||||
duration: '30分钟',
|
||||
},
|
||||
{
|
||||
title: '2022年5月16日 星期一·现场面试',
|
||||
place: '武汉市洪山区野芷湖西路创意天地5号楼2层',
|
||||
pic: '张三',
|
||||
rounds: 0,
|
||||
time: '12:00',
|
||||
duration: '30分钟',
|
||||
},
|
||||
{
|
||||
title: '2022年5月16日 星期一·现场面试',
|
||||
place: '武汉市洪山区野芷湖西路创意天地5号楼2层',
|
||||
pic: '张三',
|
||||
rounds: 0,
|
||||
time: '12:00',
|
||||
duration: '30分钟',
|
||||
},
|
||||
{
|
||||
title: '2022年5月16日 星期一·现场面试',
|
||||
place: '武汉市洪山区野芷湖西路创意天地5号楼2层',
|
||||
pic: '张三',
|
||||
rounds: 0,
|
||||
time: '12:00',
|
||||
duration: '30分钟',
|
||||
},
|
||||
{
|
||||
title: '2022年5月16日 星期一·现场面试',
|
||||
place: '武汉市洪山区野芷湖西路创意天地5号楼2层',
|
||||
pic: '张三',
|
||||
rounds: 0,
|
||||
time: '12:00',
|
||||
duration: '30分钟',
|
||||
},
|
||||
{
|
||||
title: '2022年5月16日 星期一·现场面试',
|
||||
place: '武汉市洪山区野芷湖西路创意天地5号楼2层',
|
||||
pic: '张三',
|
||||
rounds: 0,
|
||||
time: '12:00',
|
||||
duration: '30分钟',
|
||||
},
|
||||
]
|
||||
|
||||
const genExtra = () => (
|
||||
<SettingOutlined
|
||||
onClick={(event) => {
|
||||
@ -72,56 +65,193 @@ export default function InterviewTabs() {
|
||||
/>
|
||||
)
|
||||
|
||||
const handeladdinterview = () => {
|
||||
setisenterthenextstage(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="InterviewTabs-box">
|
||||
<div className="InterviewTabs-top-buttom-box">
|
||||
<Button size="Large">添加面试</Button>
|
||||
<Button size="Large" onClick={handeladdinterview}>
|
||||
添加面试
|
||||
</Button>
|
||||
<label>导出面试反馈</label>
|
||||
</div>
|
||||
|
||||
<div className="InterviewTabs-content-box">
|
||||
<Collapse defaultActiveKey="0" onChange={onChange}>
|
||||
{data.map((item, key) => {
|
||||
return (
|
||||
<Panel
|
||||
header={item.title}
|
||||
key={key}
|
||||
extra={genExtra()}
|
||||
>
|
||||
<div className="InterviewTabs-content-list-box">
|
||||
<label className="color2">面试地点</label>
|
||||
<span>{item.place}</span>
|
||||
</div>
|
||||
<div className="InterviewTabs-content-list-box">
|
||||
<label className="color2">面试负责人</label>
|
||||
<span>{item.pic}</span>
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="InterviewTabs-content-list-box">
|
||||
<label className="color2">面试信息</label>
|
||||
<span>
|
||||
{' '}
|
||||
<Tag color="#22b8cf">初试</Tag>{' '}
|
||||
{item.time} 时长:{item.duration}
|
||||
</span>
|
||||
</div>
|
||||
<div className="InterviewTabs-content-list-actionbar">
|
||||
<div>{item.pic}</div>
|
||||
<div>
|
||||
<WarningFilled style={{color:'#f57527'}}/>
|
||||
为评估
|
||||
{datalist.length > 0 ? (
|
||||
datalist.map((item, key) => {
|
||||
return (
|
||||
<Panel
|
||||
header={item.times}
|
||||
key={key}
|
||||
extra={genExtra()}
|
||||
>
|
||||
<div className="InterviewTabs-content-list-box">
|
||||
<label className="color2">
|
||||
面试地点
|
||||
</label>
|
||||
<span>
|
||||
武汉市洪山区野芷湖西路创意天地5号楼2层
|
||||
</span>
|
||||
</div>
|
||||
<div className="InterviewTabs-content-list-box">
|
||||
<label className="color2">
|
||||
面试负责人
|
||||
</label>
|
||||
<span>{item.hr_name}</span>
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="InterviewTabs-content-list-box">
|
||||
<label className="color2">
|
||||
面试信息
|
||||
</label>
|
||||
<span>
|
||||
{' '}
|
||||
<Tag color="#22b8cf">初试</Tag>{' '}
|
||||
{/* {item.time} 时长:{item.duration} */}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="link">催促反馈</Button>
|
||||
<Button type="link">填写反馈</Button>
|
||||
<Button type="link">面试未进行</Button>
|
||||
{item.survey.map((items, keys) => {
|
||||
return (
|
||||
<div
|
||||
className="InterviewTabs-content-list-actionbar"
|
||||
key={keys}
|
||||
>
|
||||
<div className="InterviewTabs-content-list-left-box">
|
||||
<div className="InterviewTabs-content-list-left-name">
|
||||
{items.name}
|
||||
</div>
|
||||
<div>
|
||||
{!items.type ? (
|
||||
<div>
|
||||
<WarningFilled
|
||||
style={{
|
||||
color: '#f57527',
|
||||
}}
|
||||
/>{' '}
|
||||
未评估
|
||||
</div>
|
||||
) : item.teacher_back ===
|
||||
1 ? (
|
||||
<div>
|
||||
<LikeOutlined
|
||||
style={{
|
||||
color: '#2cda6c',
|
||||
}}
|
||||
/>{' '}
|
||||
满意
|
||||
</div>
|
||||
) : item.teacher_back ===
|
||||
2 ? (
|
||||
<div>
|
||||
<LikeOutlined
|
||||
style={{
|
||||
color: '#2cda6c',
|
||||
}}
|
||||
/>{' '}
|
||||
非常满意
|
||||
</div>
|
||||
) : item.teacher_back ===
|
||||
3 ? (
|
||||
<div>
|
||||
<DislikeOutlined
|
||||
style={{
|
||||
color: '#f7260f',
|
||||
}}
|
||||
/>{' '}
|
||||
不满意
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<DislikeOutlined
|
||||
style={{
|
||||
color: '#f7260f',
|
||||
}}
|
||||
/>{' '}
|
||||
非常满意
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{item.back_status ===
|
||||
0 ? (
|
||||
<div>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
handelFeedback(
|
||||
item
|
||||
)
|
||||
}}
|
||||
>
|
||||
催促反馈
|
||||
</Button>
|
||||
{userinfo.id ===
|
||||
items.user_id || userinfo.name === 'root' ? (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setisfeedback()
|
||||
}}
|
||||
>
|
||||
填写反馈
|
||||
</Button>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
seefeedback()
|
||||
}}
|
||||
>
|
||||
查看反馈
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{item.interview_sign !=
|
||||
0 ? (
|
||||
<Button type="link">
|
||||
面试未进行
|
||||
</Button>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
)
|
||||
})}
|
||||
</Panel>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="margintop30">
|
||||
<Empty description={'暂无数据'} />
|
||||
</div>
|
||||
)}
|
||||
</Collapse>
|
||||
</div>
|
||||
{/* 添加面试 */}
|
||||
<Enterthenextstage
|
||||
visible={isenterthenextstage}
|
||||
onCreate={() => {
|
||||
setisenterthenextstage(false)
|
||||
}}
|
||||
uid={data.uid}
|
||||
onCancel={() => {
|
||||
setisenterthenextstage(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -3,16 +3,17 @@
|
||||
.OfferTabs-title-box span { color: #0c8cf6; font-size: 14px; cursor: pointer; font-weight: 400; }
|
||||
|
||||
.OfferTabs-border-box { border: 1px solid #dddfe3; padding: 16px; margin-top: 16px; text-align: left; }
|
||||
.OfferTabs-border-box .OfferTabs-border-div { margin-bottom: 20px; }
|
||||
.display { display: flex; justify-content: space-between; align-items: center; }
|
||||
.Approval-box { text-align: left; }
|
||||
.Approval-box .title {font-weight: bold;}
|
||||
.Approval-box span { color: #0c8cf6; }
|
||||
.but-box { display: flex; justify-content: space-between; align-items: center; margin-top: 16px;}
|
||||
.OfferTabs-box .but-box { display: flex; justify-content: space-between; align-items: center; margin-top: 16px;}
|
||||
|
||||
.Offer-info-top-box { display: flex; justify-content: space-between; align-items: center; text-align: left; }
|
||||
.Offer-info-box { text-align: left; margin: 16px 24px; }
|
||||
|
||||
.label-box { background-color: #dddfe3; padding: 8px 5px; color: #6e7686; }
|
||||
.label-box { background-color: #dddfe3; padding: 6px 8px; color: #6e7686; }
|
||||
.generate-box { display: flex; justify-content: space-between; align-items: center; margin: 16px 0; }
|
||||
.generate-box span { margin-left: 10px; color: #0c8cf6; cursor: pointer; }
|
||||
|
||||
.OfferTabs-maillist { width: 100%; }
|
||||
|
@ -1,13 +1,66 @@
|
||||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import './index.css'
|
||||
import { Button, Dropdown, Menu, Tag } from 'antd'
|
||||
import {
|
||||
Button,
|
||||
Dropdown,
|
||||
Menu,
|
||||
Tag,
|
||||
message,
|
||||
DatePicker,
|
||||
InputNumber,
|
||||
Input,
|
||||
Select,
|
||||
} from 'antd'
|
||||
import {
|
||||
emailrecord,
|
||||
updataentry,
|
||||
sendstrmail,
|
||||
getname,
|
||||
updatainterview,
|
||||
operatelog
|
||||
} from '../../../util/requestURL'
|
||||
import memoryUtils from '../../../util/memoryUtils'
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import {
|
||||
RightOutlined,
|
||||
EllipsisOutlined,
|
||||
DownOutlined,
|
||||
} from '@ant-design/icons'
|
||||
const { Option } = Select
|
||||
const dateFormat = 'YYYY/MM/DD'
|
||||
|
||||
export default function OfferTabs({ data }) {
|
||||
const [OfferPostList, setOfferPostList] = useState([]) //offer发送记录
|
||||
const [Offerstate, setOfferstate] = useState(false)
|
||||
const [offerdata, setoffdata] = useState({
|
||||
Entry_time: data.Entry_time || '', //入职时间
|
||||
wages: data.wages || data.hope_money, //工资
|
||||
phone: data.phone, //电话
|
||||
mail: data.mail, //邮箱
|
||||
hr_name: data.hr_name, //人事负责人
|
||||
hr_id: data.hr_id
|
||||
})
|
||||
const [getnames, setgetnames] = useState([])
|
||||
let userInfo = memoryUtils.userInfo
|
||||
|
||||
useEffect(() => {
|
||||
emailrecord({ user_id: data.uid }).then(
|
||||
(res) => {
|
||||
// console.log(res.data)
|
||||
setOfferPostList(res.data)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
|
||||
getname().then((res) => {
|
||||
setgetnames(res.data)
|
||||
})
|
||||
}, [])
|
||||
|
||||
export default function OfferTabs() {
|
||||
const onMenuClick = (e) => {
|
||||
console.log('click', e)
|
||||
}
|
||||
@ -32,21 +85,94 @@ export default function OfferTabs() {
|
||||
/>
|
||||
)
|
||||
|
||||
const postupdataentry = (type) => {
|
||||
updataentry({
|
||||
uid: data.uid,
|
||||
interview_stage: type,
|
||||
job_id: data.job_id,
|
||||
}).then(
|
||||
(res) => {
|
||||
console.log(res.data)
|
||||
// setOfferPostList(res.data)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 发送Offer详情
|
||||
const handelSendstrMail = () => {
|
||||
sendstrmail({
|
||||
user_id: data.uid,
|
||||
name: data.name,
|
||||
email: data.mail,
|
||||
email_str:`${data.name},您好\n\n感谢关注乐谷在线科技有限公司!很高兴的通知您通过了我们的面试,真诚的邀请您加入我们的团队\n职位:${data.job_names}\n入职时间:${data.Entry_time}
|
||||
\n薪酬:${data.wages}\n联系人:${data.hr_name}\n联系电话:${data.phone}\n联系邮箱:${data.email}\n\n如有问题请用以上联系方式及时与我们沟通,谢谢!\n(系统邮件,请勿回复)`
|
||||
}).then(
|
||||
(res) => {
|
||||
operatelog({
|
||||
user_id: data.uid,
|
||||
why: "发送Offer",
|
||||
content: `${data.name},您好\n\n感谢关注乐谷在线科技有限公司!很高兴的通知您通过了我们的面试,真诚的邀请您加入我们的团队\n职位:${data.job_names}\n入职时间:${data.Entry_time}
|
||||
\n薪酬:${data.wages}\n联系人:${data.hr_name}\n联系电话:${data.phone}\n联系邮箱:${data.email}\n\n如有问题请用以上联系方式及时与我们沟通,谢谢!\n(系统邮件,请勿回复)`,
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
}
|
||||
|
||||
const handelOfferstate = (type) => {
|
||||
if (!type) {
|
||||
const data_in = {
|
||||
...data,
|
||||
Entry_time: offerdata.Entry_time,
|
||||
wages: offerdata.wages,
|
||||
phone: offerdata.phone,
|
||||
mail: offerdata.mail,
|
||||
hr_name: offerdata.hr_name,
|
||||
hr_id: offerdata.hr_id
|
||||
}
|
||||
updatainterview({data_in: data_in}).then((res)=>{
|
||||
operatelog({
|
||||
user_id: data.uid,
|
||||
why: "修改候选人Offer信息",
|
||||
content: '修改候选人Offer信息',
|
||||
})
|
||||
},(err)=>{
|
||||
|
||||
})
|
||||
}
|
||||
setOfferstate(type)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="OfferTabs-box">
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Dropdown.Button overlay={menu}>导出offer信息</Dropdown.Button>
|
||||
{/* <Dropdown.Button overlay={menu}>导出offer信息</Dropdown.Button> */}
|
||||
|
||||
<div className="OfferTabs-title-box">入职记录</div>
|
||||
<div className="OfferTabs-border-box display">
|
||||
<span>尚未确定候选人是否入职</span>
|
||||
<div className="">
|
||||
<Button>确认入职</Button>
|
||||
<Button>放弃入职</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
postupdataentry(7)
|
||||
}}
|
||||
>
|
||||
确认入职
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
postupdataentry(6)
|
||||
}}
|
||||
>
|
||||
放弃入职
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="OfferTabs-title-box">Offer审批</div>
|
||||
{/* <div className="OfferTabs-title-box">Offer审批</div>
|
||||
<div className="but-box">
|
||||
<Button>重新发起审批</Button>
|
||||
<Button>修改审批流程</Button>
|
||||
@ -63,96 +189,221 @@ export default function OfferTabs() {
|
||||
<Tag color="#37b24d">已通过</Tag>
|
||||
<RightOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div className="OfferTabs-title-box">Offer发送记录</div>
|
||||
<div className="but-box">
|
||||
<Button>重新发送</Button>
|
||||
<Button onClick={handelSendstrMail}> {OfferPostList.length > 0 ? '重新发送': '发送Offer'} </Button>
|
||||
</div>
|
||||
|
||||
<div className="OfferTabs-border-box display">
|
||||
<div className="Approval-box">
|
||||
<div className="title">杨女士的Offer(邮件)</div>
|
||||
<div>2022-05-16 发起</div>
|
||||
</div>
|
||||
<div className="OfferTabs-border-box">
|
||||
{OfferPostList.map((item, key) => {
|
||||
return (
|
||||
<div
|
||||
className="display OfferTabs-maillist"
|
||||
key={key}
|
||||
>
|
||||
<div className="Approval-box">
|
||||
<div className="title">
|
||||
{item.name}的Offer(邮件)
|
||||
</div>
|
||||
<div>{item.times} 发起</div>
|
||||
</div>
|
||||
|
||||
<div className="">
|
||||
<Tag color="#f79f00">候选人未决定Offer</Tag>
|
||||
<EllipsisOutlined />
|
||||
</div>
|
||||
<div className="">
|
||||
<Tag color="#f79f00">候选人未决定Offer</Tag>
|
||||
<EllipsisOutlined />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="OfferTabs-title-box display">
|
||||
{/* <div className="OfferTabs-title-box display">
|
||||
Offer详情
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
|
||||
<div className="OfferTabs-border-box">
|
||||
<div className="Offer-info-top-box">
|
||||
<span>杨女士的Offer</span>
|
||||
<span>
|
||||
{data.name.charAt(0)}
|
||||
{data.gender === '男' ? '先生' : '女士'}的Offer
|
||||
</span>
|
||||
<DownOutlined />
|
||||
</div>
|
||||
<div className="Offer-info-box">
|
||||
<h4 className="fontweight">offer详情</h4>
|
||||
|
||||
{/* <div>
|
||||
<span>薪资待遇</span>
|
||||
|
||||
</div> */}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div className="OfferTabs-title-box display">
|
||||
Offer邮件及短信
|
||||
<span>编辑</span>
|
||||
{Offerstate ? (
|
||||
<span
|
||||
onClick={() => {
|
||||
handelOfferstate(false)
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
onClick={() => {
|
||||
handelOfferstate(true)
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<h4 className="fontweight">邮件信息</h4>
|
||||
<div className="OfferTabs-border-box">
|
||||
<p>
|
||||
<label className='label-box'>杨女士</label>,你好
|
||||
</p>
|
||||
<p>
|
||||
感谢关注<label className='label-box'>武汉乐谷在线科技有限公司</label>!
|
||||
跟高兴的通知您通过了我们的面试,真诚的邀请您加入我们的团队
|
||||
<div className="OfferTabs-border-div">
|
||||
<label className="label-box">
|
||||
{data.name.charAt(0)}
|
||||
{data.gender === '男' ? '先生' : '女士'}
|
||||
</label>
|
||||
,你好
|
||||
</div>
|
||||
<div className="OfferTabs-border-div">
|
||||
感谢关注
|
||||
<label className="label-box">
|
||||
武汉乐谷在线科技有限公司
|
||||
</label>
|
||||
!
|
||||
很高兴的通知您通过了我们的面试,真诚的邀请您加入我们的团队
|
||||
<br />
|
||||
</p>
|
||||
<p>
|
||||
职位: <label className='label-box'>高级游戏测试工程师</label>
|
||||
</p>
|
||||
<p>
|
||||
入职时间:<label className='label-box'>2022-05-26</label>
|
||||
</p>
|
||||
<p>
|
||||
薪酬:<label className='label-box'>月薪</label>
|
||||
</p>
|
||||
<p>
|
||||
<label className='label-box'>111111</label>
|
||||
</p>
|
||||
<p>
|
||||
入职地点:<label className='label-box'>xxx</label>
|
||||
</p>
|
||||
<p>
|
||||
联系人:<label className='label-box'>张三</label>
|
||||
</p>
|
||||
<p>
|
||||
联系电话:<label className='label-box'>123568875145</label>
|
||||
</p>
|
||||
<p>
|
||||
联系邮箱:<label className='label-box'>123659@163.com</label>
|
||||
</p>
|
||||
<p>如有问题请用以上联系方式及时与我们沟通,谢谢!</p>
|
||||
<p>(系统邮件,请勿直接回复)</p>
|
||||
</div>
|
||||
<div className="OfferTabs-border-div">
|
||||
职位:{' '}
|
||||
<label className="label-box">{data.job_names}</label>
|
||||
</div>
|
||||
<div className="OfferTabs-border-div">
|
||||
入职时间:
|
||||
{/* <label className="label-box"> */}
|
||||
<DatePicker
|
||||
onChange={(date, dateString) => {
|
||||
setoffdata({
|
||||
...offerdata,
|
||||
Entry_time: dateString,
|
||||
})
|
||||
}}
|
||||
disabled={!Offerstate}
|
||||
locale={locale}
|
||||
defaultValue={moment(
|
||||
moment(
|
||||
(Math.round(new Date() / 1000) -
|
||||
7 * 86400) *
|
||||
1000
|
||||
).format('YYYY-MM-DD'),
|
||||
dateFormat
|
||||
)}
|
||||
/>
|
||||
{/* </label> */}
|
||||
</div>
|
||||
|
||||
<div className="OfferTabs-border-div">
|
||||
薪酬:<label className="label-box">月薪</label>{' '}
|
||||
<InputNumber
|
||||
min={1}
|
||||
defaultValue={offerdata.wages}
|
||||
disabled={!Offerstate}
|
||||
onChange={(e) => {
|
||||
setoffdata({
|
||||
...offerdata,
|
||||
wages: e,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className='OfferTabs-border-div'>
|
||||
Entry_time wages phone mail hr_name
|
||||
</div> */}
|
||||
<div className="OfferTabs-border-div">
|
||||
入职地点:
|
||||
<label className="label-box">
|
||||
武汉市洪山区野芷湖西路16号创意天地-05办公楼2楼,6楼
|
||||
</label>
|
||||
</div>
|
||||
<div className="OfferTabs-border-div">
|
||||
联系人:
|
||||
<label>
|
||||
<Select
|
||||
defaultValue={offerdata.hr_name}
|
||||
disabled={!Offerstate}
|
||||
style={{
|
||||
width: 120,
|
||||
}}
|
||||
onChange={(e) => {
|
||||
const hr_name = e.split(',')[0]
|
||||
const hr_id = e.split(',')[1]
|
||||
setoffdata({
|
||||
...offerdata,
|
||||
hr_name: hr_name,
|
||||
hr_id:hr_id
|
||||
})
|
||||
}}
|
||||
>
|
||||
{getnames.map((item, key) => {
|
||||
return (
|
||||
<Option key={key} value={item.name + ',' + item._id}>
|
||||
{item.nickname}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</label>
|
||||
</div>
|
||||
<div className="OfferTabs-border-div">
|
||||
联系电话:
|
||||
<label>
|
||||
<InputNumber
|
||||
style={{
|
||||
width: 120,
|
||||
}}
|
||||
maxLength={11}
|
||||
defaultValue={offerdata.phone}
|
||||
disabled={!Offerstate}
|
||||
onChange={(e) => {
|
||||
setoffdata({
|
||||
...offerdata,
|
||||
phone: e,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="OfferTabs-border-div">
|
||||
联系邮箱:
|
||||
<label>
|
||||
<Input
|
||||
placeholder="请输入邮箱"
|
||||
defaultValue={offerdata.mail}
|
||||
disabled={!Offerstate}
|
||||
onChange={(e) => {
|
||||
setoffdata({
|
||||
...offerdata,
|
||||
mail: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<p>如有问题请用以上联系方式及时与我们沟通,谢谢!</p>
|
||||
<p>(系统邮件,请勿直接回复)</p>
|
||||
</div>
|
||||
|
||||
<div className='generate-box'>
|
||||
<label>生成Offer附件</label>
|
||||
<a href='#'>杨女士录用通知函.pdf</a>
|
||||
<div>
|
||||
<span>下载</span>
|
||||
<span>预览</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className="generate-box">
|
||||
<label>生成Offer附件</label>
|
||||
<a href="#">杨女士录用通知函.pdf</a>
|
||||
<div>
|
||||
<span>下载</span>
|
||||
<span>预览</span>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,35 +1,47 @@
|
||||
import React from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import './index.css'
|
||||
import { Timeline, Divider } from 'antd'
|
||||
import { getoperatelog } from '../../../util/requestURL'
|
||||
import { Timeline, Divider, message, Empty } from 'antd'
|
||||
import Item from 'antd/lib/list/Item'
|
||||
|
||||
export default function OperatiolistTabs({ data, Tabsnum }) {
|
||||
const [datalist, setdatalist] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
if (Tabsnum === '7') {
|
||||
getoperatelog({ user_id: data }).then(
|
||||
(res) => {
|
||||
console.log(res)
|
||||
setdatalist(res.data)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [Tabsnum])
|
||||
|
||||
export default function OperatiolistTabs() {
|
||||
return (
|
||||
<div className="OperatiolistTabs-box ">
|
||||
<Timeline>
|
||||
<Timeline.Item>
|
||||
<p className="fontweight">2022-05-15 16:06:35</p>
|
||||
<p className="">候选人更新信息</p>
|
||||
<p className="color1">由管理员 王二狗操作</p>
|
||||
<Divider />
|
||||
</Timeline.Item>
|
||||
<Timeline.Item>
|
||||
<p className="fontweight">2022-05-15 16:06:35</p>
|
||||
<p className="">候选人更新信息</p>
|
||||
<p className="color1">由管理员 王二狗操作</p>
|
||||
<Divider />
|
||||
</Timeline.Item>
|
||||
<Timeline.Item>
|
||||
<p className="fontweight">2022-05-15 16:06:35</p>
|
||||
<p className="">候选人更新信息</p>
|
||||
<p className="color1">由管理员 王二狗操作</p>
|
||||
<Divider />
|
||||
</Timeline.Item>
|
||||
<Timeline.Item>
|
||||
<p className="fontweight">2022-05-15 16:06:35</p>
|
||||
<p className="">候选人更新信息</p>
|
||||
<p className="color1">由管理员 王二狗操作</p>
|
||||
<Divider />
|
||||
</Timeline.Item>
|
||||
{datalist.length > 0 ? (
|
||||
datalist.map((item, key) => {
|
||||
return (
|
||||
<Timeline.Item key={key}>
|
||||
<p className="fontweight">{item.times}</p>
|
||||
<p className="">{item.content}</p>
|
||||
<p className="color1">
|
||||
{item.why} {item.who}操作
|
||||
</p>
|
||||
<Divider />
|
||||
</Timeline.Item>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="Empty-box2">
|
||||
<Empty description="暂无数据..." />
|
||||
</div>
|
||||
)}
|
||||
</Timeline>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,70 +1,91 @@
|
||||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { findremark } from '../../../util/requestURL'
|
||||
import Remarks from '../../Remarks'
|
||||
import './index.css'
|
||||
import { Checkbox, Button } from 'antd'
|
||||
import { Checkbox, Button , Empty } from 'antd'
|
||||
|
||||
export default function RemarksTabs({ uid, interview_stage,Tabsnum }) {
|
||||
const [remarklist, setremarklist] = useState([])
|
||||
const [isremarks, setisremarks] = useState(false)
|
||||
useEffect(() => {
|
||||
if (uid != '' && Tabsnum === '5') {
|
||||
handelFindremark()
|
||||
}
|
||||
}, [Tabsnum])
|
||||
|
||||
//获取备注列表
|
||||
const handelFindremark = () => {
|
||||
findremark({ remark_uid: uid, where: {} })
|
||||
.then((res) => {
|
||||
// console.log(res)
|
||||
setremarklist(res.data)
|
||||
})
|
||||
.catch((err) => {})
|
||||
}
|
||||
|
||||
const onChange = (e) => {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
//淘汰关闭按钮
|
||||
const onClose = () => {
|
||||
setisremarks(false)
|
||||
}
|
||||
|
||||
export default function RemarksTabs() {
|
||||
const onChange=(e)=>{
|
||||
console.log(e);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="RemarksTabs-top-box">
|
||||
<Checkbox onChange={onChange}>设为私密</Checkbox>
|
||||
<Button type="primary">添加</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setisremarks(true)
|
||||
}}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='remarks-title'>查看备注</div>
|
||||
<div className='remarks-list-box'>
|
||||
<div className='remarks-list'>
|
||||
<div className='head-box'>刘</div>
|
||||
<div className='remarks-list-right-box'>
|
||||
<div className='remarks-list-userinfo-box'>
|
||||
<p className='remarks-list-name'>刘大哥 (我) </p>
|
||||
<div className='operation-box'>
|
||||
<Button type="link" danger>删除</Button>
|
||||
<p className='remarks-list-time'>2022-07-07</p>
|
||||
</div>
|
||||
<div className="remarks-title">查看备注</div>
|
||||
<div className="remarks-list-box">
|
||||
{remarklist.length > 0?( remarklist.map((item, key) => {
|
||||
return (
|
||||
<div className="remarks-list" key={key}>
|
||||
<div className="head-box">
|
||||
{item.remark_from.charAt(0)}
|
||||
</div>
|
||||
<div className="remarks-list-right-box">
|
||||
<div className="remarks-list-userinfo-box">
|
||||
<p className="remarks-list-name">
|
||||
{item.remark_from}
|
||||
</p>
|
||||
<div className="operation-box">
|
||||
<Button type="link" danger>
|
||||
删除
|
||||
</Button>
|
||||
<p className="remarks-list-time">
|
||||
{item.remark_time}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="color1">{item.comment}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})):(
|
||||
<div className='Empty-box2'>
|
||||
<Empty description="暂无数据..."/>
|
||||
</div>
|
||||
<div className='color1'>
|
||||
呵呵哈哈哈或或
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='remarks-list'>
|
||||
<div className='head-box'>刘</div>
|
||||
<div className='remarks-list-right-box'>
|
||||
<div className='remarks-list-userinfo-box'>
|
||||
<p className='remarks-list-name'>刘大哥 (我) </p>
|
||||
<div className='operation-box'>
|
||||
<Button type="link" danger>删除</Button>
|
||||
<p className='remarks-list-time'>2022-07-07</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className='color1'>
|
||||
呵呵哈哈哈或或
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='remarks-list'>
|
||||
<div className='head-box'>刘</div>
|
||||
<div className='remarks-list-right-box'>
|
||||
<div className='remarks-list-userinfo-box'>
|
||||
<p className='remarks-list-name'>刘大哥 (我) </p>
|
||||
<div className='operation-box'>
|
||||
<Button type="link" danger>删除</Button>
|
||||
<p className='remarks-list-time'>2022-07-07</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className='color1'>
|
||||
呵呵哈哈哈或或
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 备注 */}
|
||||
<Remarks
|
||||
onClose={onClose}
|
||||
visible={isremarks}
|
||||
uid={uid}
|
||||
remark_stage={interview_stage}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -16,9 +16,10 @@
|
||||
display: flex;
|
||||
padding: 50px 0 10px 0;
|
||||
}
|
||||
.resume-head { width: 90px; height: 90px; overflow: hidden; border-radius: 50%; border: 1px solid #000; margin-left: 24px; box-shadow: 0 0px 10px rgba(000, 000, 000, 0.2); }
|
||||
.resume-head { width: 90px; height: 90px; overflow: hidden; border-radius: 50%; border: 0px solid #000; margin-left: 24px; box-shadow: 0 0px 10px rgba(000, 000, 000, 0.2); }
|
||||
.resume-head img { width: 100%; }
|
||||
.resume-info { margin-left: 14px; }
|
||||
.resume-info-name { font-size: 22px; font-weight: bold; margin-bottom: 30px; }
|
||||
.resume-info-name { font-size: 22px; font-weight: bold; margin-bottom: 0px; }
|
||||
.xian { width: 60px; height: 4px; background-color: #dddfe0; }
|
||||
.personal-information-box {margin: 20px 100px; }
|
||||
/* .personal-info-box { padding-bottom: 30px; } */
|
||||
|
@ -1,11 +1,14 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Button, Form, Input, Modal, Tabs, Badge } from 'antd'
|
||||
import { Button, Form, Input, Modal, Tabs, Badge, message, Avatar } from 'antd'
|
||||
import Steptone from '../Steptone'
|
||||
import InterviewTabs from './InterviewTabs'
|
||||
import OperatiolistTabs from './OperatiolistTabs'
|
||||
import EnclosureTabs from './EnclosureTabs'
|
||||
import RemarksTabs from './RemarksTabs'
|
||||
import OfferTabs from './OfferTabs'
|
||||
import Eliminate from '../Eliminate'
|
||||
import Remarks from '../Remarks'
|
||||
import Feedback from './Feedback'
|
||||
import './index.css'
|
||||
import {
|
||||
UserOutlined,
|
||||
@ -18,6 +21,7 @@ import {
|
||||
EditOutlined,
|
||||
CloseOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { findcriterion, interviewupdate } from '../../util/requestURL'
|
||||
|
||||
export default function InterviewerInfoPop({
|
||||
visible,
|
||||
@ -28,9 +32,60 @@ export default function InterviewerInfoPop({
|
||||
}) {
|
||||
const [form] = Form.useForm()
|
||||
const { TabPane } = Tabs
|
||||
const [candidateinfo, setcandidateinfo] = useState({})
|
||||
const [iseliminate, setiseliminate] = useState(false)
|
||||
const [isremarks, setisremarks] = useState(false)
|
||||
const [Tabsnum, setTabsnum] = useState(0)
|
||||
const [isfeedback, setisfeedback] = useState(false)
|
||||
|
||||
const onChange = (key) => {
|
||||
console.log(key)
|
||||
// console.log(key)
|
||||
setTabsnum(key)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (data != 0) {
|
||||
postfindcriterion()
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
const postfindcriterion = () => {
|
||||
findcriterion({ uid: data }).then(
|
||||
(res) => {
|
||||
setcandidateinfo(res.data)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//进入下一阶段
|
||||
const handelNextstage = () => {
|
||||
// console.log(candidateinfo)
|
||||
const interview_stage =
|
||||
parseInt(candidateinfo.interview_stage) + parseInt(1)
|
||||
interviewupdate({
|
||||
data_in: { interview_stage: interview_stage },
|
||||
interview_query: { uid: candidateinfo.uid },
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('操作成功!')
|
||||
setTimeout(() => {
|
||||
postfindcriterion()
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//淘汰关闭按钮
|
||||
const onClose = () => {
|
||||
setisremarks(false)
|
||||
}
|
||||
|
||||
return (
|
||||
@ -41,22 +96,28 @@ export default function InterviewerInfoPop({
|
||||
footer={null}
|
||||
closable={false}
|
||||
width={1200}
|
||||
destroyOnClose={true}
|
||||
>
|
||||
<div className="InterviewerInfoPop-box">
|
||||
<div className="InterviewerInfoPop-top-box">
|
||||
<div className="">
|
||||
<div className="divdisplay">
|
||||
<span className="InterviewerInfoPop-name coloc5">
|
||||
张三
|
||||
{candidateinfo.name}
|
||||
</span>
|
||||
<div className="InterviewerInfoPop-label color6 border6">
|
||||
重
|
||||
</div>
|
||||
{candidateinfo.counts > 1 ? (
|
||||
<div className="InterviewerInfoPop-label color6 border6">
|
||||
重
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
<div className="InterviewerInfoPop-label color3 border3">
|
||||
<UserOutlined />
|
||||
</div>
|
||||
<div className="InterviewerInfoPop-apply-num">
|
||||
已申请1次
|
||||
已申请{candidateinfo.counts}次
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@ -64,75 +125,136 @@ export default function InterviewerInfoPop({
|
||||
style={{ marginTop: 10 }}
|
||||
>
|
||||
<div className="color1 font-size14 marginright10">
|
||||
<UserOutlined /> 女 · 24岁
|
||||
<UserOutlined /> {candidateinfo.gender} ·{' '}
|
||||
{candidateinfo.age}岁
|
||||
</div>
|
||||
<div className="color1 font-size14 marginright10">
|
||||
<PhoneOutlined /> 15369874569(上海)
|
||||
<PhoneOutlined /> {candidateinfo.phone}
|
||||
</div>
|
||||
<div className="color1 font-size14 marginright10">
|
||||
<MailOutlined /> 212365748@qq.com
|
||||
<MailOutlined /> {candidateinfo.mail}
|
||||
</div>
|
||||
<div className="color1 font-size14 marginright10">
|
||||
<ShoppingOutlined /> 1年
|
||||
<ShoppingOutlined />{' '}
|
||||
{candidateinfo.work_exp === 0
|
||||
? '应届生'
|
||||
: candidateinfo.work_exp === 1
|
||||
? '1-3年'
|
||||
: candidateinfo.work_exp === 2
|
||||
? '3-5年'
|
||||
: candidateinfo.work_exp === 3
|
||||
? '5年以上'
|
||||
: ''}
|
||||
</div>
|
||||
<div className="color1 font-size14 marginright10">
|
||||
<ReadOutlined /> 硕士
|
||||
<ReadOutlined />{' '}
|
||||
{candidateinfo.education === 1
|
||||
? '专科'
|
||||
: candidateinfo.education === 2
|
||||
? '本科'
|
||||
: candidateinfo.education === 3
|
||||
? '硕士'
|
||||
: candidateinfo.education === 2
|
||||
? '博士'
|
||||
: '未填学历'}
|
||||
</div>
|
||||
<div className="color1 font-size14 marginright10">
|
||||
<SendOutlined /> 湖北省-武汉市
|
||||
<SendOutlined /> {candidateinfo.account}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="operationbutton">
|
||||
<div className="">
|
||||
<DeleteOutlined />
|
||||
</div>
|
||||
<div className="">
|
||||
<EditOutlined
|
||||
onClick={() => onEditresume({ data })}
|
||||
/>
|
||||
</div>
|
||||
{onEditresume ? (
|
||||
<div className="">
|
||||
<EditOutlined
|
||||
onClick={() => onEditresume({ data })}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
<div className="">
|
||||
<CloseOutlined onClick={onCreate} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="divdisplay">
|
||||
<div className="divdisplay2">
|
||||
<div style={{ width: '850px' }}>
|
||||
<Tabs defaultActiveKey="1" onChange={onChange}>
|
||||
<TabPane tab="基本信息" key="1">
|
||||
<div className="information-box">
|
||||
<div className="resume-top-info">
|
||||
<div className="resume-head"></div>
|
||||
<div className="resume-head">
|
||||
{candidateinfo.head ? (
|
||||
<img
|
||||
src={candidateinfo.head}
|
||||
></img>
|
||||
) : (
|
||||
<Avatar
|
||||
size={90}
|
||||
icon={<UserOutlined />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="resume-info">
|
||||
<div className="resume-info-name coloc5">
|
||||
张三
|
||||
{candidateinfo.name}
|
||||
</div>
|
||||
<div>
|
||||
<span className="fontsize14 color1 marginright10">
|
||||
{' '}
|
||||
<PhoneOutlined className="marginright5" />{' '}
|
||||
<PhoneOutlined className="marginright5" />
|
||||
<span>
|
||||
15369874569(上海)
|
||||
</span>{' '}
|
||||
{
|
||||
candidateinfo.phone
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span className="fontsize14 color1">
|
||||
{' '}
|
||||
<MailOutlined className="marginright5" />{' '}
|
||||
<MailOutlined className="marginright5" />
|
||||
<span>
|
||||
212365748@qq.com
|
||||
</span>{' '}
|
||||
{candidateinfo.mail}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="fontsize14 color1 margintop5">
|
||||
女·24岁·1年工作经验·硕士·湖北-武汉
|
||||
{candidateinfo.gender}·
|
||||
{candidateinfo.age}岁·
|
||||
{candidateinfo.work_exp ===
|
||||
0
|
||||
? '应届生'
|
||||
: candidateinfo.work_exp ===
|
||||
1
|
||||
? '1-3年'
|
||||
: candidateinfo.work_exp ===
|
||||
2
|
||||
? '3-5年'
|
||||
: candidateinfo.work_exp ===
|
||||
3
|
||||
? '5年以上'
|
||||
: ''}
|
||||
·
|
||||
{candidateinfo.education ===
|
||||
1
|
||||
? '专科'
|
||||
: candidateinfo.education ===
|
||||
2
|
||||
? '本科'
|
||||
: candidateinfo.education ===
|
||||
3
|
||||
? '硕士'
|
||||
: candidateinfo.education ===
|
||||
2
|
||||
? '博士'
|
||||
: '未填学历'}
|
||||
·{candidateinfo.account}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="fontsize24 fontweight margintop50 coloc5">
|
||||
<div className="fontsize22 fontweight margintop50 coloc5">
|
||||
个人信息
|
||||
<div className="xian margintop20"></div>
|
||||
</div>
|
||||
@ -142,124 +264,376 @@ export default function InterviewerInfoPop({
|
||||
最近公司
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
武汉掌游科技有限公司
|
||||
{candidateinfo.firm}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
毕业院校
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{candidateinfo.at_school}{' '}
|
||||
{candidateinfo.school}{' '}
|
||||
{candidateinfo.specialty}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fontsize24 fontweight margintop50 coloc5">
|
||||
<div className="fontsize22 fontweight margintop50 coloc5">
|
||||
工作经历
|
||||
<div className="xian margintop20"></div>
|
||||
</div>
|
||||
<div className="personal-info-box">
|
||||
<div>
|
||||
<div className="work-experience-box margintop20 divdisplay">
|
||||
<label className="color7 marginright24">
|
||||
2122-11 - 2022-02
|
||||
</label>
|
||||
<div className="coloc5 fontweight">
|
||||
武汉xxx有限公司
|
||||
</div>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
职位名称
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
计算会计
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
工作职责
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
安守本分挥洒的回访客户萨迪克返回空上岛咖啡哈师大放开手大富科技阿士大夫卡啥打开就发生接口黄卡就收到回复交换空间撒大黄蜂尽快哈萨克东方红卡上的反馈
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{candidateinfo.work_list
|
||||
? candidateinfo.work_list.map(
|
||||
(item, key) => {
|
||||
return (
|
||||
<div key={key}>
|
||||
<div className="work-experience-box margintop20 divdisplay">
|
||||
<label className="color7 marginright24">
|
||||
{
|
||||
item.time
|
||||
}
|
||||
</label>
|
||||
<div className="coloc5 fontweight">
|
||||
{
|
||||
item.company_name
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
职位名称
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{
|
||||
item.position_name
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
工作职责
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{
|
||||
item.duty
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
: ''}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="work-experience-box margintop20 divdisplay">
|
||||
<label className="color7 marginright24">
|
||||
2122-11 - 2022-02
|
||||
</label>
|
||||
<div className="coloc5 fontweight">
|
||||
武汉xxx有限公司
|
||||
</div>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
职位名称
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
计算会计
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
工作职责
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
安守本分挥洒的回访客户萨迪克返回空上岛咖啡哈师大放开手大富科技阿士大夫卡啥打开就发生接口黄卡就收到回复交换空间撒大黄蜂尽快哈萨克东方红卡上的反馈
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fontsize22 fontweight margintop50 coloc5">
|
||||
项目经历
|
||||
<div className="xian margintop20"></div>
|
||||
</div>
|
||||
<div className="personal-info-box">
|
||||
{candidateinfo.project_undergo
|
||||
? candidateinfo.project_undergo.map(
|
||||
(item, key) => {
|
||||
return (
|
||||
<div key={key}>
|
||||
<div className="work-experience-box margintop20 divdisplay">
|
||||
<label className="color7 marginright24">
|
||||
{
|
||||
item.time
|
||||
}
|
||||
</label>
|
||||
<div className="coloc5 fontweight">
|
||||
{
|
||||
item.name
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
职位名称
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{
|
||||
item.work
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
项目介绍
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{
|
||||
item.comment
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
工作职责
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{
|
||||
item.duty
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
: ''}
|
||||
</div>
|
||||
|
||||
<div className="fontsize22 fontweight margintop50 coloc5">
|
||||
语言能力
|
||||
<div className="xian margintop20"></div>
|
||||
</div>
|
||||
<div className="personal-info-box">
|
||||
{candidateinfo.language_list
|
||||
? candidateinfo.language_list.map(
|
||||
(item, key) => {
|
||||
return (
|
||||
<div key={key}>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
语言类型
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{item.language_name !=
|
||||
''
|
||||
? item.language_name
|
||||
: '未填写'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
掌握程度
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{item.has_sleep !=
|
||||
''
|
||||
? item.has_sleep
|
||||
: '未填写'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
听说
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{item.reading !=
|
||||
''
|
||||
? item.reading
|
||||
: '未填写'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
读写
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{item.writing !=
|
||||
''
|
||||
? item.writing
|
||||
: '未填写'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
: ''}
|
||||
</div>
|
||||
<div className="fontsize22 fontweight margintop50 coloc5">
|
||||
获奖经历
|
||||
<div className="xian margintop20"></div>
|
||||
</div>
|
||||
<div className="personal-info-box">
|
||||
{candidateinfo.remembrance_list
|
||||
? candidateinfo.remembrance_list.map(
|
||||
(item, key) => {
|
||||
return (
|
||||
<div key={key}>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
获奖时间
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{item.prize_time !=
|
||||
''
|
||||
? item.prize_time
|
||||
: '未填写'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="divdisplay personal-information-box lineheight24">
|
||||
<label className="color1 marginright24">
|
||||
获奖名称
|
||||
</label>
|
||||
<p className="coloc5">
|
||||
{item.prize_name !=
|
||||
''
|
||||
? item.prize_name
|
||||
: '未填写'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
: ''}
|
||||
</div>
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="面试" key="2">
|
||||
<div className="information-box">
|
||||
<InterviewTabs />
|
||||
<InterviewTabs
|
||||
data={candidateinfo}
|
||||
Tabsnum={Tabsnum}
|
||||
setisfeedback={() => {
|
||||
setisfeedback(true)
|
||||
}}
|
||||
seefeedback={() => {
|
||||
setisfeedback(true)
|
||||
postfindcriterion()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="考试/测评" key="3">
|
||||
考试/测评
|
||||
</TabPane>
|
||||
<TabPane tab="Offer/录用" key="4">
|
||||
<OfferTabs/>
|
||||
<OfferTabs data={candidateinfo} />
|
||||
</TabPane>
|
||||
|
||||
<TabPane
|
||||
tab={
|
||||
<Badge
|
||||
size="small"
|
||||
count="2"
|
||||
count="0"
|
||||
color={'blue'}
|
||||
>
|
||||
<span>备注</span>
|
||||
<span>备注</span>
|
||||
</Badge>
|
||||
}
|
||||
key="5"
|
||||
>
|
||||
<RemarksTabs/>
|
||||
<RemarksTabs
|
||||
uid={candidateinfo.uid}
|
||||
interview_stage={
|
||||
candidateinfo.interview_stage
|
||||
}
|
||||
Tabsnum={Tabsnum}
|
||||
/>
|
||||
</TabPane>
|
||||
|
||||
<TabPane tab="附加信息" key="6">
|
||||
<EnclosureTabs/>
|
||||
<EnclosureTabs data={candidateinfo.uid} Tabsnum={Tabsnum}/>
|
||||
</TabPane>
|
||||
<TabPane tab="操作记录" key="7">
|
||||
<OperatiolistTabs />
|
||||
<OperatiolistTabs
|
||||
data={candidateinfo.uid}
|
||||
Tabsnum={Tabsnum}
|
||||
/>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div className="side-action-bar-box">
|
||||
<div className="progress-bar-box">
|
||||
{/* 步骤条组件 */}
|
||||
<Steptone data="1" />
|
||||
<Steptone
|
||||
data={candidateinfo.interview_stage}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="button-box">
|
||||
<Button type="primary" block>
|
||||
进入下一阶段
|
||||
{onEditresume ? (
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
onClick={handelNextstage}
|
||||
disabled={candidateinfo.interview_stage === 3 && candidateinfo.teacher_state !== 2? true:false}
|
||||
>
|
||||
进入下一阶段
|
||||
</Button>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
{candidateinfo.teacher_state != 2 ? (
|
||||
<Button
|
||||
block
|
||||
onClick={() => {
|
||||
setisfeedback(true)
|
||||
postfindcriterion()
|
||||
}}
|
||||
>
|
||||
填写反馈
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
block
|
||||
onClick={() => {
|
||||
setisfeedback(true)
|
||||
postfindcriterion()
|
||||
}}
|
||||
>
|
||||
修改反馈
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
block
|
||||
onClick={() => {
|
||||
setiseliminate(true)
|
||||
}}
|
||||
>
|
||||
淘汰
|
||||
</Button>
|
||||
<Button
|
||||
block
|
||||
onClick={() => {
|
||||
setisremarks(true)
|
||||
}}
|
||||
>
|
||||
备注
|
||||
</Button>
|
||||
<Button block>淘汰</Button>
|
||||
<Button block>关注</Button>
|
||||
<Button block>备注</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
{/* 淘汰 */}
|
||||
<Eliminate
|
||||
visible={iseliminate}
|
||||
onCreate={() => {
|
||||
postfindcriterion()
|
||||
setiseliminate(false)
|
||||
}}
|
||||
uid={candidateinfo.uid}
|
||||
remark_stage={candidateinfo.interview_stage}
|
||||
onCancel={() => {
|
||||
setiseliminate(false)
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 备注 */}
|
||||
<Remarks
|
||||
onClose={onClose}
|
||||
visible={isremarks}
|
||||
uid={candidateinfo.uid}
|
||||
remark_stage={candidateinfo.interview_stage}
|
||||
/>
|
||||
|
||||
{/* 反馈 */}
|
||||
<Feedback
|
||||
visible={isfeedback}
|
||||
uid={candidateinfo.uid}
|
||||
onClose={() => {
|
||||
setisfeedback(false)
|
||||
postfindcriterion()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.navheader-box { height: 32px; margin-right: 24px; display: flex; align-items: center; }
|
||||
.navheader-box .ant-space-item{ line-height: 0; }
|
||||
.navheader-box .ant-space-item{ line-height: 0; }
|
||||
.navheader-box .navheader-biv{ margin-right: 16px; line-height: 0; cursor: pointer;}
|
||||
.navheader-box .navheader-biv .headimg { width: 32px; height: 32px; border-radius: 50%; text-align: center; line-height: 32px; background-color: #0c8cf6; color: #fff; font-size: 12px; }
|
@ -1,8 +1,8 @@
|
||||
import React, { Component, useState } from 'react'
|
||||
import ResumeUploadPop from '../ResumeUploadPop'
|
||||
import InterviewUploadPop from '../InterviewUploadPop'
|
||||
import './index.css'
|
||||
import { Input, Space, Button, Badge, Menu, Dropdown } from 'antd'
|
||||
import { Input, Space, Button, Badge, Menu, Dropdown, message } from 'antd'
|
||||
import storageUtils from '../../util/storageUtils'
|
||||
import {
|
||||
ShopOutlined,
|
||||
QuestionCircleOutlined,
|
||||
@ -19,51 +19,34 @@ const { Search } = Input
|
||||
// />
|
||||
// )
|
||||
|
||||
const menu = (
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: <p>1st menu item</p>,
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: <p>2nd menu item</p>,
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: <p>退出登录</p>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)
|
||||
|
||||
const onSearch = (value) => console.log(value)
|
||||
export default class NavHeader extends Component {
|
||||
state = { component: '' }
|
||||
|
||||
componentDidMount(){
|
||||
handelLogout=()=>{
|
||||
storageUtils.removerUser()
|
||||
window.location.reload();
|
||||
}
|
||||
handeluserinfo=()=>{
|
||||
|
||||
message.success("该功能暂未开放")
|
||||
}
|
||||
|
||||
componentWillUpdate(){
|
||||
const { headnav } = this.props
|
||||
// console.log('NavHeader')
|
||||
// switch (headnav) {
|
||||
// case 'position':
|
||||
// this.setState({
|
||||
// component: <ResumeUploadPop />,
|
||||
// })
|
||||
// break
|
||||
// case 'interview':
|
||||
// this.setState({
|
||||
// component: <InterviewUploadPop />,
|
||||
// })
|
||||
// break
|
||||
// }
|
||||
}
|
||||
|
||||
render() {
|
||||
const { headnav } = this.props
|
||||
const { userInfo } = this.props
|
||||
const menu = (
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
key: '2',
|
||||
label: <span onClick={this.handeluserinfo}>个人信息</span>,
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: <span onClick={this.handelLogout}>退出登录</span>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)
|
||||
return (
|
||||
<div className="navheader-box">
|
||||
<div className="navheader-biv">
|
||||
@ -77,7 +60,9 @@ export default class NavHeader extends Component {
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
<div className="navheader-biv">{headnav== 'position'? <ResumeUploadPop />: <InterviewUploadPop />}</div>
|
||||
<div className="navheader-biv">
|
||||
<ResumeUploadPop />
|
||||
</div>
|
||||
<div className="navheader-biv">
|
||||
<ShopOutlined
|
||||
style={{ fontSize: '20px', color: '#ff6b6b' }}
|
||||
@ -94,7 +79,7 @@ export default class NavHeader extends Component {
|
||||
</div>
|
||||
<div className="navheader-biv">
|
||||
<Dropdown overlay={menu} placement="bottomLeft" arrow>
|
||||
<div className="headimg">罗</div>
|
||||
<div className="headimg">{userInfo.name? userInfo.name.charAt(0): '' }</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
0
src/components/Originalresume/index.css
Normal file
0
src/components/Originalresume/index.css
Normal file
53
src/components/Originalresume/index.jsx
Normal file
53
src/components/Originalresume/index.jsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Document, Page } from 'react-pdf'
|
||||
import axios from 'axios'
|
||||
|
||||
export default class Originalresume extends Component {
|
||||
state = {
|
||||
numPages: 0,
|
||||
pageNumber: 1,
|
||||
}
|
||||
|
||||
onDocumentLoad = ({ numPages }) => {
|
||||
this.setState({ numPages })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { pageNumber, numPages } = this.state
|
||||
const { data } = this.props
|
||||
var url = ""
|
||||
if(JSON.stringify(data) != "{}"){
|
||||
const urlarr = data.file_url.split('hrms/')
|
||||
// url = 'http://localhost:3000/pdf/hrms/' + decodeURIComponent(urlarr[1])
|
||||
url = 'http://10.0.0.4/pdf/hrms/' + decodeURIComponent(urlarr[1])
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
url !== ""?(<Document
|
||||
file={url}
|
||||
// file={data.file_url}
|
||||
onLoadSuccess={this.onDocumentLoad}
|
||||
onLoadError={() => {
|
||||
console.log('CALLED')
|
||||
}}
|
||||
onLoadProgress={() => {
|
||||
console.log('PRGREOSS')
|
||||
}}
|
||||
>
|
||||
{
|
||||
new Array(numPages).fill('').map((item,key)=>{
|
||||
|
||||
return <Page key={key+1} pageNumber={key+1} scale={1.3}/>
|
||||
})
|
||||
}
|
||||
|
||||
</Document>):''
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
1
src/components/Recommend/index.css
Normal file
1
src/components/Recommend/index.css
Normal file
@ -0,0 +1 @@
|
||||
.Tips { font-size: 12px; color: #75777d; }
|
118
src/components/Recommend/index.jsx
Normal file
118
src/components/Recommend/index.jsx
Normal file
@ -0,0 +1,118 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Form, Input, Modal, Radio, Select, message } from 'antd'
|
||||
import { getname, sendinterviewee } from '../../util/requestURL'
|
||||
import './index.css'
|
||||
const { Option } = Select
|
||||
const { TextArea } = Input
|
||||
|
||||
export default function Eliminate(props) {
|
||||
const [form] = Form.useForm()
|
||||
const [getnamedata, setgetnamedata] = useState([])
|
||||
const { visible, onCreate, onCancel, uid } = props
|
||||
useEffect(() => {
|
||||
if(uid){
|
||||
getname().then(
|
||||
(res) => {
|
||||
console.log(res.data)
|
||||
setgetnamedata(res.data)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="推荐给用人部门"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
var data = values;
|
||||
data['uid'] = uid
|
||||
sendinterviewee(data).then(
|
||||
(res) => {
|
||||
|
||||
if(res.msg === "ok"){
|
||||
message.success("推荐成功!")
|
||||
onCreate();
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form form={form} layout="vertical" name="form_in_modal">
|
||||
<p>
|
||||
重新推荐会使前一次推荐取消,且前一次的推荐链接无法操作
|
||||
</p>
|
||||
<Form.Item
|
||||
name="push"
|
||||
label="推荐到"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择淘汰原因!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select mode="multiple">
|
||||
{getnamedata.map((item, key) => {
|
||||
return item.rank === 2 ? (
|
||||
<Option value={item.user_id} key={item._id}>
|
||||
{item.name}
|
||||
</Option>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<span className="Tips">
|
||||
一次推荐简历给多位面试官,在面试官全部反馈后,需HR判断候选人是否进入面试
|
||||
</span>
|
||||
<Form.Item name="content" label="告诉用人部门">
|
||||
<TextArea
|
||||
rows={4}
|
||||
placeholder="例如:大公司从业经历,有成功产品案例"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="bcc"
|
||||
label="抄送"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择抄送人账号!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select mode="multiple">
|
||||
{getnamedata.map((item, key) => {
|
||||
return (
|
||||
<Option value={item.user_id} key={item._id}>
|
||||
{item.name}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
6
src/components/Remarks/index.css
Normal file
6
src/components/Remarks/index.css
Normal file
@ -0,0 +1,6 @@
|
||||
.Remarks-box .remarks-list-box{
|
||||
margin: 0;
|
||||
}
|
||||
.Remarks-box .RemarksTabs-top-box {
|
||||
margin: 24px 0;
|
||||
}
|
167
src/components/Remarks/index.jsx
Normal file
167
src/components/Remarks/index.jsx
Normal file
@ -0,0 +1,167 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Form, Drawer, Button, Checkbox, Input, message, Empty } from 'antd'
|
||||
import {
|
||||
findremark,
|
||||
addremark,
|
||||
operatelog,
|
||||
interviewupdate,
|
||||
} from '../../util/requestURL'
|
||||
import storageUtils from '../../util/storageUtils'
|
||||
import './index.css'
|
||||
const { TextArea } = Input
|
||||
const { form } = Form
|
||||
|
||||
export default function Remarks(props) {
|
||||
const { onClose, visible, uid, remark_stage } = props
|
||||
const [remarklist, setremarklist] = useState([])
|
||||
let userinfo = storageUtils.getUser()
|
||||
|
||||
useEffect(() => {
|
||||
if (uid != '' && uid) {
|
||||
handelFindremark()
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
//获取备注列表
|
||||
const handelFindremark = () => {
|
||||
findremark({ remark_uid: uid, where: {} })
|
||||
.then((res) => {
|
||||
setremarklist(res.data)
|
||||
})
|
||||
.catch((err) => {})
|
||||
}
|
||||
|
||||
//添加备注
|
||||
const handelAddremark = (values) => {
|
||||
if (values.stage_num == undefined) {
|
||||
values.stage_num = 0
|
||||
} else if (values.stage_num) {
|
||||
values.stage_num = 1
|
||||
} else {
|
||||
values.stage_num = 0
|
||||
}
|
||||
addremark({
|
||||
remark_from: userinfo.name,
|
||||
remark_uid: uid,
|
||||
comment: values.remark,
|
||||
stage_num: values.stage_num,
|
||||
remark_stage: remark_stage,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code == 200) {
|
||||
if (remark_stage === 5) {
|
||||
interviewupdate({
|
||||
data_in: { interview_stage: 11 }, //淘汰
|
||||
interview_query: { uid: uid },
|
||||
data: { interview_stage: remark_stage },
|
||||
find_column: [],
|
||||
}).then(
|
||||
(res) => {
|
||||
// console.log(res)
|
||||
message.success('操作成功!')
|
||||
handelFindremark()
|
||||
operatelog({
|
||||
user_id: uid,
|
||||
why: '淘汰候选人',
|
||||
content:'对方放弃入职机会',
|
||||
})
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
} else {
|
||||
message.success('添加成功!')
|
||||
handelFindremark()
|
||||
operatelog({
|
||||
user_id: uid,
|
||||
why: '添加备注',
|
||||
content: values.remark,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Drawer
|
||||
title="备注"
|
||||
placement="right"
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
width={520}
|
||||
>
|
||||
<div className="Remarks-box">
|
||||
<Form onFinish={handelAddremark}>
|
||||
<Form.Item
|
||||
name="remark"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请填写备注!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<TextArea
|
||||
rows={4}
|
||||
placeholder="请输入备注,支持@提醒他人"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<div className="RemarksTabs-top-box">
|
||||
<Form.Item name="stage_num" valuePropName="checked">
|
||||
<Checkbox>设为私密</Checkbox>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
添加
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
<div className="remarks-list-box">
|
||||
{remarklist.length > 0 ? (
|
||||
remarklist.map((item, key) => {
|
||||
return (
|
||||
<div className="remarks-list" key={key}>
|
||||
<div className="head-box">
|
||||
{item.remark_from.charAt(0)}
|
||||
</div>
|
||||
<div className="remarks-list-right-box">
|
||||
<div className="remarks-list-userinfo-box">
|
||||
<p className="remarks-list-name">
|
||||
{item.remark_from}
|
||||
</p>
|
||||
<div className="operation-box">
|
||||
<Button type="link" danger>
|
||||
删除
|
||||
</Button>
|
||||
<p className="remarks-list-time">
|
||||
{item.remark_time}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="color1">
|
||||
{item.comment}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="margin24">
|
||||
<Empty description="暂无数据" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,30 +1,98 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Button } from 'antd'
|
||||
import ResumeUpload from '../../pages/ResumeUpload'
|
||||
import Uploadresume from '../Uploadresume'
|
||||
import { Button, Dropdown, Menu } from 'antd'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
|
||||
export default function ResumeUploadPop() {
|
||||
const navigate = useNavigate()
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [usvisible, setusvisible] = useState(false)
|
||||
|
||||
//上传简历导出的数据
|
||||
const [data, setdata] = useState([])
|
||||
|
||||
const onCreate = (values) => {
|
||||
console.log('Received values of form: ', values)
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
const UsonCreate = (values) => {
|
||||
setusvisible(false)
|
||||
}
|
||||
|
||||
const onMenuClick = (e) => {
|
||||
console.log('click', e)
|
||||
if (e.key == 1) {
|
||||
setVisible(true)
|
||||
} else if (e.key == 2) {
|
||||
//跳转到添加职位界面
|
||||
navigate('/admin/position/addposition')
|
||||
} else if (e.key == 4) {
|
||||
setusvisible(true)
|
||||
}
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu
|
||||
onClick={onMenuClick}
|
||||
items={[
|
||||
// {
|
||||
// key: '1',
|
||||
// label: '添加简历',
|
||||
// },
|
||||
{
|
||||
key: '4',
|
||||
label: '上传简历',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: '添加职位',
|
||||
},
|
||||
// {
|
||||
// key: '3',
|
||||
// label: '添加候选人',
|
||||
// },
|
||||
]}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setVisible(true)
|
||||
}}
|
||||
>
|
||||
上传简历
|
||||
</Button>
|
||||
<Dropdown overlay={menu} placement="bottomLeft">
|
||||
<Button type="primary">
|
||||
<PlusOutlined />
|
||||
上传
|
||||
</Button>
|
||||
</Dropdown>
|
||||
|
||||
<ResumeUpload
|
||||
visible={visible}
|
||||
onCreate={onCreate}
|
||||
data={data}
|
||||
onCancel={() => {
|
||||
setVisible(false)
|
||||
}}
|
||||
onReupload={() => {
|
||||
//重新上传
|
||||
setVisible(false)
|
||||
setusvisible(true)
|
||||
}}
|
||||
/>
|
||||
|
||||
<Uploadresume
|
||||
visible={usvisible}
|
||||
onCreate={UsonCreate}
|
||||
onResumeUpload={(data) => {
|
||||
setusvisible(false)
|
||||
setVisible(true)
|
||||
setdata(data)
|
||||
}}
|
||||
onCancel={() => {
|
||||
setusvisible(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,7 +1,10 @@
|
||||
.progress-bar-box { background-color: #edeff1; height: 70px; padding: 24px; position: relative; }
|
||||
.progress-bar-bg { width: 100%; height: 6px; background-color: #fff; }
|
||||
.progress-bar-bg { width: 100%; height: 6px; background-color: #fff; overflow: hidden; }
|
||||
.progress-bar-yuan-mr { width: 100%; display: flex; justify-content: space-between; position: relative; top: -13px; }
|
||||
.progress-bar-yuan-mr div { width: 20px; height: 20px; border-radius: 50%; background-color: #fff; text-align: center; line-height: 20px; color: #75777d; }
|
||||
.progress-bar-yuan-mr div { width: 20px; height: 20px; border-radius: 50%; background-color: #fff; text-align: center; line-height: 20px; color: #75777d; cursor: pointer; }
|
||||
.progress-bar-complete { width: 23%; height: 6px; background-color: #40a9ff; }
|
||||
.progress-bar-yuan-complete { background-color: #40a9ff !important; color: #fff !important; }
|
||||
.progress-bar-complete-title { width: 60px; text-align: center; position: relative; left: -20px; top: -10px; font-size: 12px; color: #75777d; }
|
||||
.progress-bar-yuan-complete { background-color: #40a9ff !important; color: #fff !important; cursor: pointer; }
|
||||
.progress-bar-complete-title { width: 60px; text-align: center; position: relative; left: -20px; top: -10px; font-size: 12px; color: #75777d; }
|
||||
.hover-show-title { display: flex;align-items: center; position: absolute; top: 40px; font-size: 12px; }
|
||||
.hover-show-title div { position: relative;}
|
||||
|
||||
|
@ -2,16 +2,48 @@ import React, { Component } from 'react'
|
||||
import './index.css'
|
||||
|
||||
export class Steptone extends Component {
|
||||
state = {
|
||||
isshow1: false,
|
||||
isshow2: false,
|
||||
isshow3: false,
|
||||
isshow4: false,
|
||||
isshow5: false,
|
||||
}
|
||||
|
||||
handlMouseLeave = (key) => {
|
||||
this.setState({
|
||||
[key]: false,
|
||||
})
|
||||
}
|
||||
|
||||
handlMouseEnter = (key) => {
|
||||
this.setState({
|
||||
[key]: true,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.props //当前处于第几步
|
||||
let { data } = this.props //当前处于第几步
|
||||
const { isshow1, isshow2, isshow3, isshow4, isshow5 } = this.state
|
||||
if (data === 11) {
|
||||
data = 6
|
||||
}
|
||||
const dataArr = [1, 2, 3, 4, 5] //步骤总数
|
||||
const completetitlearr = [-20, 33, 84, 133, 185] //步骤标题移动距离
|
||||
const completetitlearr = [-20, 38, 96, 155, 215, 215] //步骤标题移动距离
|
||||
const titarr = ['初筛', '复筛', '面试', '沟通Offer', '待入职', '已淘汰']
|
||||
return (
|
||||
<div>
|
||||
<div className="progress-bar-bg">
|
||||
<div
|
||||
className="progress-bar-complete"
|
||||
style={{ width: (data - 1) * 23 + '%' }}
|
||||
style={{
|
||||
width:
|
||||
((data - 1) * 23 > 100
|
||||
? 100
|
||||
: (data - 1) * 23) < 0
|
||||
? 0
|
||||
: (data - 1) * 23 + '%',
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
<div className="progress-bar-yuan-mr">
|
||||
@ -24,6 +56,12 @@ export class Steptone extends Component {
|
||||
: ''
|
||||
}
|
||||
key={i}
|
||||
onMouseLeave={() => {
|
||||
this.handlMouseLeave('isshow' + i)
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
this.handlMouseEnter('isshow' + i)
|
||||
}}
|
||||
>
|
||||
{i}
|
||||
</div>
|
||||
@ -31,11 +69,58 @@ export class Steptone extends Component {
|
||||
})}
|
||||
</div>
|
||||
{/* -20 40 155 210 */}
|
||||
<div className="hover-show-title">
|
||||
<div
|
||||
className="hover-show"
|
||||
style={{
|
||||
display: isshow1 ? 'block' : 'none',
|
||||
left: '-2px',
|
||||
}}
|
||||
>
|
||||
初筛
|
||||
</div>
|
||||
<div
|
||||
className="hover-show"
|
||||
style={{
|
||||
display: isshow2 ? 'block' : 'none',
|
||||
left: '56px',
|
||||
}}
|
||||
>
|
||||
复筛
|
||||
</div>
|
||||
<div
|
||||
className="hover-show"
|
||||
style={{
|
||||
display: isshow3 ? 'block' : 'none',
|
||||
left: '114px',
|
||||
}}
|
||||
>
|
||||
面试
|
||||
</div>
|
||||
<div
|
||||
className="hover-show"
|
||||
style={{
|
||||
display: isshow4 ? 'block' : 'none',
|
||||
left: '160px',
|
||||
}}
|
||||
>
|
||||
沟通Offer
|
||||
</div>
|
||||
<div
|
||||
className="hover-show"
|
||||
style={{
|
||||
display: isshow5 ? 'block' : 'none',
|
||||
left: '227px',
|
||||
}}
|
||||
>
|
||||
待入职
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="progress-bar-complete-title"
|
||||
style={{ left: completetitlearr[data - 1] }}
|
||||
>
|
||||
沟通Offer
|
||||
{titarr[data - 1]}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
0
src/components/Uploadresume/index.css
Normal file
0
src/components/Uploadresume/index.css
Normal file
222
src/components/Uploadresume/index.jsx
Normal file
222
src/components/Uploadresume/index.jsx
Normal file
@ -0,0 +1,222 @@
|
||||
import React, { Component, useState } from 'react'
|
||||
import {
|
||||
message,
|
||||
Upload,
|
||||
Modal,
|
||||
Spin,
|
||||
Alert,
|
||||
Select,
|
||||
Row,
|
||||
Col,
|
||||
Button,
|
||||
} from 'antd'
|
||||
import {
|
||||
InboxOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
UploadOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { interviewfileinsert, filetohw } from '../../util/requestURL'
|
||||
import memoryUtils from '../../util/memoryUtils'
|
||||
import './index.css'
|
||||
const { Dragger } = Upload
|
||||
const { confirm } = Modal
|
||||
const { Option } = Select
|
||||
|
||||
export default class Candidate extends Component {
|
||||
state = {
|
||||
loading: false,
|
||||
resume_affix_id: '',
|
||||
owner_name: 0,
|
||||
}
|
||||
render() {
|
||||
const { visible, onCancel, onCreate, onResumeUpload } = this.props
|
||||
let userInfo = memoryUtils.userInfo
|
||||
const token = userInfo.token_type + ' ' + userInfo.token || ''
|
||||
const that = this
|
||||
|
||||
const props = {
|
||||
name: 'file',
|
||||
multiple: true,
|
||||
action: 'http://10.0.0.240:7800/api/v1/itr/file_to_hw',
|
||||
// action: 'http://myip.legu.cc:7800/api/v1/itr/file_to_hw',
|
||||
// action: 'http://10.0.0.4:7800/api/v1/itr/file_to_hw',
|
||||
headers: {
|
||||
Authorization: token,
|
||||
},
|
||||
onChange(info) {
|
||||
const { status } = info.file
|
||||
if (status == 'done') {
|
||||
that.setState(
|
||||
{
|
||||
loading: true,
|
||||
},
|
||||
() => {
|
||||
that.setState({
|
||||
loading: false,
|
||||
})
|
||||
if (
|
||||
info.file.response.data !== null &&
|
||||
info.file.response.data.length !== 0
|
||||
) {
|
||||
if (info.file.response.data.exist === 1) {
|
||||
showPromiseConfirm(info.file.response.data)
|
||||
} else {
|
||||
const candidatedata =
|
||||
info.file.response.data
|
||||
candidatedata.data['uid'] =
|
||||
info.file.response.data.uid
|
||||
candidatedata.data['owner_name'] =
|
||||
this.state.owner_name
|
||||
candidatedata.data['resume_affix_id'] =
|
||||
this.state.resume_affix_id
|
||||
that.props.onResumeUpload(candidatedata)
|
||||
}
|
||||
} else {
|
||||
message.error(info.file.response.msg)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (status === 'done') {
|
||||
message.success(`${info.file.name} 已成功上传.`)
|
||||
} else if (status === 'error') {
|
||||
message.error(`${info.file.name} 上传失败.`)
|
||||
}
|
||||
},
|
||||
|
||||
onDrop(e) {
|
||||
console.log('Dropped files', e.dataTransfer.files)
|
||||
},
|
||||
}
|
||||
|
||||
const showPromiseConfirm = (data) => {
|
||||
var that = this;
|
||||
confirm({
|
||||
title: '提示',
|
||||
icon: <ExclamationCircleOutlined />,
|
||||
content: '当前简历以添加,是否覆盖',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
// console.log(data)
|
||||
const candidatedata = data
|
||||
candidatedata.data['uid'] = data.uid
|
||||
candidatedata.data['owner_name'] = that.state.owner_name
|
||||
candidatedata.data['resume_affix_id'] =
|
||||
that.state.resume_affix_id
|
||||
that.props.onResumeUpload(candidatedata)
|
||||
},
|
||||
|
||||
onCancel() {},
|
||||
})
|
||||
}
|
||||
|
||||
const propss = {
|
||||
name: 'file',
|
||||
multiple: true,
|
||||
action: 'http://10.0.0.240:7800/api/v1/itr/resume_affix',
|
||||
// action: 'http://myip.legu.cc:7800/api/v1/itr/resume_affix',
|
||||
// action: 'http://10.0.0.4:7800/api/v1/itr/resume_affix',
|
||||
headers: {
|
||||
Authorization: token,
|
||||
},
|
||||
|
||||
onChange(info) {
|
||||
if (info.file.status !== 'uploading') {
|
||||
const data = JSON.parse(info.file.response.data)
|
||||
|
||||
this.setState({
|
||||
resume_affix_id: data.file_url,
|
||||
})
|
||||
}
|
||||
|
||||
if (info.file.status === 'done') {
|
||||
message.success(
|
||||
`${info.file.name} file uploaded successfully`
|
||||
)
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={visible}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
closable={false}
|
||||
maskClosable={false}
|
||||
destroyOnClose={true}
|
||||
onOk={() => {}}
|
||||
>
|
||||
<Row gutter={24} align="baseline">
|
||||
<Col span={24} className="marginbottom10">
|
||||
<label className="from-label">选择渠道</label>
|
||||
<Select
|
||||
defaultValue={0}
|
||||
onChange={(e) => {
|
||||
this.setState({
|
||||
owner_name: e,
|
||||
})
|
||||
}}
|
||||
style={{
|
||||
width: 240,
|
||||
marginLeft: 16,
|
||||
}}
|
||||
placeholder="请选择简历渠道"
|
||||
>
|
||||
<Option value={0}>内推</Option>
|
||||
<Option value={1}>boss</Option>
|
||||
<Option value={2}>前程无忧</Option>
|
||||
<Option value={3}>智联招聘</Option>
|
||||
<Option value={4}>58同城</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
|
||||
<Col span={24} className="marginbottom10">
|
||||
<label className="from-label">上传附件</label>
|
||||
<Upload {...propss}>
|
||||
<Button
|
||||
icon={<UploadOutlined />}
|
||||
style={{
|
||||
marginLeft: 16,
|
||||
}}
|
||||
>
|
||||
上传附件
|
||||
</Button>
|
||||
</Upload>
|
||||
</Col>
|
||||
|
||||
<Col span={24} className="marginbottom10">
|
||||
<label className="from-label">上传简历</label>
|
||||
<Spin
|
||||
spinning={this.state.loading}
|
||||
tip="解析简历中请等待..."
|
||||
>
|
||||
<Dragger
|
||||
{...props}
|
||||
// customRequest={(e)=>{customRequest(e)}}
|
||||
>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<InboxOutlined />
|
||||
</p>
|
||||
<p className="ant-upload-text">
|
||||
单击或拖动文件到此区域上传
|
||||
</p>
|
||||
<p className="ant-upload-hint">
|
||||
支持单次或批量上传。严禁
|
||||
通过上传公司数据或其他频带文件
|
||||
</p>
|
||||
</Dragger>
|
||||
</Spin>
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
BIN
src/images/bg_login.png
Normal file
BIN
src/images/bg_login.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
src/images/left-logo.jpg
Normal file
BIN
src/images/left-logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 153 KiB |
BIN
src/images/logo_2.png
Normal file
BIN
src/images/logo_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
@ -3,13 +3,14 @@ import ReactDOM from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App'
|
||||
import reportWebVitals from './reportWebVitals'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
|
||||
import { HashRouter } from 'react-router-dom'
|
||||
// HashRouter
|
||||
// BrowserRouter
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'))
|
||||
root.render(
|
||||
<BrowserRouter>
|
||||
<HashRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</HashRouter>
|
||||
)
|
||||
|
||||
reportWebVitals()
|
||||
|
@ -1,80 +1,99 @@
|
||||
import React from 'react';
|
||||
import { Form, Input, Button, Checkbox } from 'antd';
|
||||
import {useNavigate} from 'react-router-dom';
|
||||
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
||||
import './login.css'
|
||||
import { Button, message, Form, Input } from 'antd'
|
||||
import React from 'react'
|
||||
import { Login } from '../util/requestURL'
|
||||
import storageUtils from '../util/storageUtils'
|
||||
import memoryUtils from '../util/memoryUtils'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import Redirect from '../routes/Redirect'
|
||||
import '../pages/Login.css'
|
||||
|
||||
export default function Loging() {
|
||||
const navigate = useNavigate()
|
||||
|
||||
//当有登录状态时重定向到首页
|
||||
const userInfo = memoryUtils.userInfo
|
||||
if (userInfo.user_id) {
|
||||
return <Redirect to="/" />
|
||||
}
|
||||
|
||||
const onFinish = (values) => {
|
||||
Login(values).then(
|
||||
(res) => {
|
||||
storageUtils.saceUser(res.data)
|
||||
navigate('/')
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const onFinishFailed = (errorInfo) => {
|
||||
console.log('Failed:', errorInfo)
|
||||
}
|
||||
|
||||
export default function Login() {
|
||||
const navigator = useNavigate();
|
||||
const onFinish = (values) => {
|
||||
localStorage.setItem('token',"asdasdasd");
|
||||
navigator('/')
|
||||
// console.log('Received values of form: ', values);
|
||||
};
|
||||
return (
|
||||
<div className='components-form-demo-normal-login'>
|
||||
<Form
|
||||
name="normal_login"
|
||||
className="login-form"
|
||||
initialValues={{
|
||||
remember: true,
|
||||
}}
|
||||
onFinish={onFinish}
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
prefix={
|
||||
<UserOutlined className="site-form-item-icon" />
|
||||
}
|
||||
placeholder="用户名"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
prefix={
|
||||
<LockOutlined className="site-form-item-icon" />
|
||||
}
|
||||
type="password"
|
||||
placeholder="密码"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Form.Item name="remember" valuePropName="checked" noStyle>
|
||||
<Checkbox>记住我</Checkbox>
|
||||
</Form.Item>
|
||||
|
||||
{/* <a className="login-form-forgot" href="#">
|
||||
忘记密码
|
||||
</a> */}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
className="login-form-button"
|
||||
<div className="login-box">
|
||||
<div className='login-boxs'>
|
||||
<div className="login-left">
|
||||
</div>
|
||||
<div className="components-form-demo-normal-login">
|
||||
<div className='login-logo'></div>
|
||||
<Form
|
||||
name="basic"
|
||||
labelCol={{
|
||||
span: 8,
|
||||
}}
|
||||
wrapperCol={{
|
||||
span: 16,
|
||||
}}
|
||||
initialValues={{
|
||||
remember: true,
|
||||
}}
|
||||
onFinish={onFinish}
|
||||
onFinishFailed={onFinishFailed}
|
||||
autoComplete="off"
|
||||
size={'Large'}
|
||||
>
|
||||
登录
|
||||
</Button>
|
||||
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Form.Item
|
||||
label="账号"
|
||||
name="username"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input style={{height: '40px'}}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="密码"
|
||||
name="password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input.Password style={{height: '40px'}}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
wrapperCol={{
|
||||
offset: 8,
|
||||
span: 16,
|
||||
}}
|
||||
>
|
||||
<Button type="primary" htmlType="submit" block style={{height: '40px'}}>
|
||||
登录
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
9
src/pages/ResumeUpload/StandardResume/index.css
Normal file
9
src/pages/ResumeUpload/StandardResume/index.css
Normal file
@ -0,0 +1,9 @@
|
||||
.StandardResume-box .ant-row { margin-left: 0 !important; margin-right: 0 !important; }
|
||||
|
||||
.resume-pop-box .ant-tabs-content-holder { overflow-y: scroll; max-height: calc( 100vh - 375px); }
|
||||
.from-label {padding: 0 0 8px; line-height: 1.5715; white-space: initial; text-align: left; display: inline-block; margin-top: 12px;}
|
||||
.textalignright { text-align: right; }
|
||||
.select-box div {
|
||||
width: 100%;
|
||||
}
|
||||
.StandardResume-box { width: 700px; }
|
@ -1,10 +1,561 @@
|
||||
import React from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Row,
|
||||
Col,
|
||||
Divider,
|
||||
Button,
|
||||
Space,
|
||||
DatePicker,
|
||||
Select,
|
||||
} from 'antd'
|
||||
import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons'
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import moment from 'moment'
|
||||
import './index.css'
|
||||
const dateFormat = 'YYYY-MM-DD'
|
||||
|
||||
export default function StandardResume() {
|
||||
return (
|
||||
<div>
|
||||
StandardResume
|
||||
</div>
|
||||
)
|
||||
export default function StandardResume({ data, updataPosition }) {
|
||||
const [form] = Form.useForm()
|
||||
const { TextArea } = Input
|
||||
const { Option } = Select
|
||||
const { RangePicker } = DatePicker
|
||||
const typelist = {
|
||||
work_list: {
|
||||
company_name: '',
|
||||
duty: '',
|
||||
position_name: '',
|
||||
},
|
||||
project_undergo: {
|
||||
time: '',
|
||||
name: '',
|
||||
work: '',
|
||||
comment: '',
|
||||
duty: '',
|
||||
},
|
||||
language: {
|
||||
language_name: '',
|
||||
has_sleep: 1,
|
||||
reading: 1,
|
||||
writing: 1,
|
||||
},
|
||||
remembrance: {
|
||||
prize_name: '',
|
||||
prize_time: '',
|
||||
},
|
||||
}
|
||||
|
||||
const [worklist, setworklist] = useState(data['work_list'])
|
||||
const [projectundergo, setprojectundergo] = useState(
|
||||
data['project_undergo']
|
||||
)
|
||||
const [language, setlanguage] = useState(data['language_list'])
|
||||
const [remembrance, setremembrance] = useState(data['remembrance_list'])
|
||||
|
||||
useEffect(()=>{
|
||||
updataPosition({...data.data,work_list:worklist,project_undergo:projectundergo,language_list:language,remembrance_list:remembrance})
|
||||
},[])
|
||||
|
||||
const onValuesChange = (type, e, valuestype, index) => {
|
||||
switch (type) {
|
||||
case 'work_list':
|
||||
const newworklist = worklist.map((item, key) => {
|
||||
if (index === key)
|
||||
return { ...item, [valuestype]: e }
|
||||
else return item
|
||||
})
|
||||
setworklist(newworklist)
|
||||
updataPosition({work_list:newworklist})
|
||||
break
|
||||
case 'project_undergo':
|
||||
const newprojectundergo = projectundergo.map((item, key) => {
|
||||
if (index === key)
|
||||
return valuestype != 'time'
|
||||
? { ...item, [valuestype]: e }
|
||||
: { ...item, [valuestype]: e }
|
||||
else return item
|
||||
})
|
||||
setprojectundergo(newprojectundergo)
|
||||
updataPosition({project_undergo:newprojectundergo})
|
||||
break
|
||||
case 'language':
|
||||
const newlanguage = language.map((item, key) => {
|
||||
if (index === key)
|
||||
return { ...item, [valuestype]: e }
|
||||
else return item
|
||||
})
|
||||
setlanguage(newlanguage)
|
||||
updataPosition({language_list:newlanguage})
|
||||
break
|
||||
case 'remembrance':
|
||||
const newremembrance = remembrance.map((item, key) => {
|
||||
if (index === key)
|
||||
return valuestype != 'prize_time'
|
||||
? { ...item, [valuestype]: e }
|
||||
: { ...item, [valuestype]: e }
|
||||
else return item
|
||||
})
|
||||
setremembrance(newremembrance)
|
||||
updataPosition({remembrance_list:newremembrance})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const add = (type) => {
|
||||
switch (type) {
|
||||
case 'work_list':
|
||||
const newworklist = [...worklist, typelist[type]]
|
||||
setworklist(newworklist)
|
||||
break
|
||||
case 'project_undergo':
|
||||
const newprojectundergo = [...projectundergo, typelist[type]]
|
||||
setprojectundergo(newprojectundergo)
|
||||
break
|
||||
case 'language':
|
||||
const newlanguage = [...language, typelist[type]]
|
||||
setlanguage(newlanguage)
|
||||
break
|
||||
case 'remembrance':
|
||||
const newremembrance = [...remembrance, typelist[type]]
|
||||
setremembrance(newremembrance)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const remove = (type, index) => {
|
||||
switch (type) {
|
||||
case 'work_list':
|
||||
const newworklist = worklist.filter((item, key) => {
|
||||
return key != index
|
||||
})
|
||||
setworklist(newworklist)
|
||||
break
|
||||
case 'project_undergo':
|
||||
const newprojectundergo = projectundergo.filter((item, key) => {
|
||||
return key != index
|
||||
})
|
||||
setprojectundergo(newprojectundergo)
|
||||
break
|
||||
case 'language':
|
||||
const newlanguage = language.filter((item, key) => {
|
||||
return key != index
|
||||
})
|
||||
setlanguage(newlanguage)
|
||||
break
|
||||
case 'remembrance':
|
||||
const newremembrance = remembrance.filter((item, key) => {
|
||||
return key != index
|
||||
})
|
||||
setremembrance(newremembrance)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="StandardResume-box">
|
||||
{/* <Form layout="vertical" onValuesChange={onValuesChange}> */}
|
||||
<Divider orientation="left">工作经验</Divider>
|
||||
|
||||
{worklist.map((item, key) => {
|
||||
return (
|
||||
<Row gutter={24} align="baseline" key={key}>
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">公司名称</label>
|
||||
<Input
|
||||
placeholder="请输入公司名称"
|
||||
value={item.company_name}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'work_list',
|
||||
e.target.value,
|
||||
'company_name',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">职位名称</label>
|
||||
<Input
|
||||
placeholder="请输入职位名称"
|
||||
value={item.position_name}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'work_list',
|
||||
e.target.value,
|
||||
'position_name',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={2} className="textalignright">
|
||||
<MinusCircleOutlined
|
||||
onClick={() => remove('work_list', key)}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24} className="marginbottom10">
|
||||
<label className="from-label">工作职责</label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
placeholder="请输入工作职责"
|
||||
value={item.duty}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'work_list',
|
||||
e.target.value,
|
||||
'duty',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
})}
|
||||
<Col span={24}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add('work_list')}
|
||||
block
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Divider orientation="left">项目经验</Divider>
|
||||
{projectundergo.map((item, key) => {
|
||||
return (
|
||||
<Row key={key} gutter={24} align="baseline">
|
||||
<Col span={12} className="marginbottom10">
|
||||
<label className="from-label">起止时间 </label>
|
||||
<div>
|
||||
<RangePicker
|
||||
locale={locale}
|
||||
picker="month"
|
||||
value={
|
||||
item.time.length > 0
|
||||
?( [
|
||||
moment(
|
||||
item.time.split(
|
||||
'-'
|
||||
)[0],
|
||||
dateFormat
|
||||
),
|
||||
moment(
|
||||
item.time.split(
|
||||
'-'
|
||||
)[1],
|
||||
dateFormat
|
||||
),
|
||||
])
|
||||
: ''
|
||||
}
|
||||
onChange={(date, dateString) => {
|
||||
onValuesChange(
|
||||
'project_undergo',
|
||||
dateString[0] +
|
||||
'-' +
|
||||
dateString[1],
|
||||
'time',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12} className="textalignright">
|
||||
<MinusCircleOutlined
|
||||
onClick={() =>
|
||||
remove('project_undergo', key)
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={12} className="marginbottom10">
|
||||
<label className="from-label">项目名称</label>
|
||||
<Input
|
||||
placeholder="参与项目"
|
||||
value={item.name}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'project_undergo',
|
||||
e.target.value,
|
||||
'name',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={12} className="marginbottom10">
|
||||
<label className="from-label">职务</label>
|
||||
<Input
|
||||
placeholder="请输入职务名称"
|
||||
value={item.work}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'project_undergo',
|
||||
e.target.value,
|
||||
'work',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={24} className="marginbottom10">
|
||||
<label className="from-label">项目介绍</label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
placeholder="内容"
|
||||
value={item.comment}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'project_undergo',
|
||||
e.target.value,
|
||||
'comment',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={24} className="marginbottom10">
|
||||
<label className="from-label">项目中职责</label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
placeholder="项目中职责"
|
||||
value={item.duty}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'project_undergo',
|
||||
e.target.value,
|
||||
'duty',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
})}
|
||||
<Col span={24}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add('project_undergo')}
|
||||
block
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Divider orientation="left">语言能力</Divider>
|
||||
{language.map((item, key) => {
|
||||
return (
|
||||
<Row key={key} gutter={24} align="baseline">
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">语言类型</label>
|
||||
<Input
|
||||
placeholder="请输入掌握语言类型"
|
||||
value={item.language_name}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'language',
|
||||
e.target.value,
|
||||
'language_name',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">掌握程度</label>
|
||||
<div className="select-box">
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
value={item.has_sleep}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'language',
|
||||
e,
|
||||
'has_sleep',
|
||||
key
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value={"初级"}>初级</Option>
|
||||
<Option value={"中级"}>中级</Option>
|
||||
<Option value={"高级"}>高级</Option>
|
||||
</Select>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<Col span={2} className="textalignright">
|
||||
<MinusCircleOutlined
|
||||
onClick={() => remove('language', key)}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">听说</label>
|
||||
<div className="select-box">
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
value={item.reading}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'language',
|
||||
e,
|
||||
'reading',
|
||||
key
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value={"初级"}>初级</Option>
|
||||
<Option value={"中级"}>中级</Option>
|
||||
<Option value={"高级"}>高级</Option>
|
||||
</Select>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">读写</label>
|
||||
<div className="select-box">
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
value={item.writing}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'language',
|
||||
e,
|
||||
'writing',
|
||||
key
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value={"初级"}>初级</Option>
|
||||
<Option value={"中级"}>中级</Option>
|
||||
<Option value={"高级"}>高级</Option>
|
||||
</Select>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
})}
|
||||
<Col span={24}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add('language')}
|
||||
block
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Divider orientation="left">自我描述</Divider>
|
||||
<Row gutter={24} align="baseline">
|
||||
<Col span={24}>
|
||||
<label className="from-label">自我描述</label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
placeholder="请输入自我描述"
|
||||
defaultValue={data['data']['review']}
|
||||
onChange={(e) => {
|
||||
updataPosition({review: e.target.value})
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider orientation="left">获奖经历</Divider>
|
||||
{remembrance.map((item, key) => {
|
||||
return (
|
||||
<Row key={key} gutter={24} align="baseline">
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">获奖时间</label>
|
||||
<div className="select-box">
|
||||
<DatePicker
|
||||
locale={locale}
|
||||
value={
|
||||
item.prize_time.length > 0
|
||||
? (moment(
|
||||
item.prize_time,
|
||||
dateFormat
|
||||
))
|
||||
: ''
|
||||
}
|
||||
onChange={(date, dateString) => {
|
||||
onValuesChange(
|
||||
'remembrance',
|
||||
dateString[0],
|
||||
'prize_time',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<Col span={11} className="marginbottom10">
|
||||
<label className="from-label">奖项名称</label>
|
||||
<Input
|
||||
placeholder="请输入奖项名称"
|
||||
value={item.prize_name}
|
||||
onChange={(e) => {
|
||||
onValuesChange(
|
||||
'remembrance',
|
||||
e.target.value,
|
||||
'prize_name',
|
||||
key
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={2} className="textalignright">
|
||||
<Form.Item label=" ">
|
||||
<MinusCircleOutlined
|
||||
onClick={() =>
|
||||
remove('remembrance', key)
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
})}
|
||||
|
||||
<Col span={24}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add('remembrance')}
|
||||
block
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
width: 40%;
|
||||
}
|
||||
.resume-content-box {
|
||||
width: 55%;
|
||||
/* width: 55%; */
|
||||
}
|
||||
.resume-energy-box {
|
||||
width: 100%;
|
||||
@ -20,4 +20,6 @@
|
||||
width: 20%;
|
||||
background-color: #eee;
|
||||
margin-top: 46px;
|
||||
}
|
||||
}
|
||||
.resume-energy-box .ant-tabs { width: 100%; display: flex; justify-content: space-between; }
|
||||
.ResumeUpload-box .resume-pop-box .ant-tabs-content-holder{overflow-y:scroll; max-height: calc( 100vh - 375px);}
|
||||
|
@ -1,195 +1,235 @@
|
||||
import React from 'react';
|
||||
import { Form, Input, Modal, Radio, Row ,Col, Select, DatePicker, Tabs } from 'antd';
|
||||
import 'moment/locale/zh-cn';
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN';
|
||||
import React,{ useState, Component } from 'react'
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Modal,
|
||||
Radio,
|
||||
Row,
|
||||
Col,
|
||||
Select,
|
||||
DatePicker,
|
||||
Tabs,
|
||||
Button,
|
||||
message,
|
||||
} from 'antd'
|
||||
import 'moment/locale/zh-cn'
|
||||
import moment from 'moment'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import StandardResume from './StandardResume'
|
||||
import Originalresume from '../../components/Originalresume'
|
||||
import {updatainterview} from '../../util/requestURL'
|
||||
import './index.css'
|
||||
const {Option} = Select
|
||||
const { Option } = Select
|
||||
const { TabPane } = Tabs
|
||||
const dateFormat = 'YYYY-MM-DD'
|
||||
|
||||
export default class ResumeUpload extends Component {
|
||||
state= this.props.data.data
|
||||
|
||||
updataPosition = (item)=>{
|
||||
this.setState(item,()=>{
|
||||
// console.log(this.state)
|
||||
})
|
||||
}
|
||||
|
||||
export default function ResumeUpload({visible,onCancel,onCreate}) {
|
||||
const [form] = Form.useForm();
|
||||
const onChange = (key) => {
|
||||
console.log(key);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
width={'96%'}
|
||||
visible={visible}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
closable= {false}
|
||||
onOk={() => {
|
||||
form
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields();
|
||||
onCreate(values);
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<div className='resume-pop-box'>
|
||||
<div className='resume-img-box'>
|
||||
onValuesChange = (item) =>{
|
||||
this.setState(item,()=>{
|
||||
// console.log(this.state)
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
<div className='resume-content-box'>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="form_in_modal"
|
||||
initialValues={{
|
||||
modifier: 'public',
|
||||
}}
|
||||
>
|
||||
<Row gutter={24}>
|
||||
render(){
|
||||
const { visible, onCancel, onCreate,onReupload, data } = this.props
|
||||
|
||||
<Col span={6}>
|
||||
<Form.Item
|
||||
name="title"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '填写姓名',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder='填写姓名'/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
return(
|
||||
<div className="ResumeUpload-box">
|
||||
<Modal
|
||||
width={'1600px'}
|
||||
visible={visible}
|
||||
closable={false}
|
||||
maskClosable={false}
|
||||
destroyOnClose={true}
|
||||
footer={[
|
||||
<Button key={'cancel'} onClick={onCancel}>取消</Button>,
|
||||
<Button key={'Reupload'} onClick={onReupload}>重新上传</Button>,
|
||||
<Button
|
||||
key={'ok'}
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
var data= this.state;
|
||||
if(data.name === "" || data.job_name === "" || data.phone === "" || data.mail ===""){
|
||||
message.warning('姓名,职位,电话,邮箱必填')
|
||||
return;
|
||||
}
|
||||
updatainterview({data_in:this.state}).then((res)=>{
|
||||
if(res.msg === "ok"){
|
||||
message.success("添加成功!")
|
||||
}
|
||||
},(err)=>{
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
})
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div className="resume-pop-box">
|
||||
{/* <div className='resume-img-box'>
|
||||
|
||||
<Col span={6}>
|
||||
<Form.Item name="position">
|
||||
<Input type="textarea" placeholder='填写岗位'/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item name="sex">
|
||||
<Select
|
||||
placeholder="选择性别"
|
||||
optionFilterProp="children"
|
||||
>
|
||||
<Option value="1">男</Option>
|
||||
<Option value="2">女</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</div> */}
|
||||
<div className="resume-content-box">
|
||||
<Form
|
||||
onValuesChange={this.onValuesChange}
|
||||
layout="vertical"
|
||||
name="form_in_modal"
|
||||
initialValues={data.data}
|
||||
>
|
||||
<Row gutter={24}>
|
||||
<Col span={6}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '填写姓名',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder="填写姓名" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={6}>
|
||||
<Form.Item name="age">
|
||||
<DatePicker locale={locale} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item
|
||||
name="phone"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
addonBefore={'+86'}
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item
|
||||
name="email"
|
||||
rules={[
|
||||
{
|
||||
type: 'email',
|
||||
message: '邮箱格式错误!',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: '请输入邮箱!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item name="workingyears">
|
||||
<Select
|
||||
placeholder="选择工作年限"
|
||||
optionFilterProp="children"
|
||||
>
|
||||
<Option value="1">应届生</Option>
|
||||
<Option value="2">1-3年</Option>
|
||||
<Option value="3">3-5年</Option>
|
||||
<Option value="4">5年以上</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item name="education">
|
||||
<Select
|
||||
placeholder="选择学历"
|
||||
optionFilterProp="children"
|
||||
>
|
||||
<Option value="1">高中及以下</Option>
|
||||
<Option value="2">专科</Option>
|
||||
<Option value="3">本科</Option>
|
||||
<Option value="4">硕士</Option>
|
||||
<Option value="5">博士</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item name="job_name" rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请填写岗位',
|
||||
},
|
||||
]}>
|
||||
<Input
|
||||
type="textarea"
|
||||
placeholder="填写岗位"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item name="gender">
|
||||
<Select
|
||||
placeholder="选择性别"
|
||||
optionFilterProp="children"
|
||||
>
|
||||
<Option value={0}>男</Option>
|
||||
<Option value={1}>女</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={4}>
|
||||
<Form.Item
|
||||
name="address"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '填写现住地址',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder='填写现住地址'/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item name="birthday"
|
||||
>
|
||||
<DatePicker placeholder='请选择出生年月' value={
|
||||
data.data > 0
|
||||
? (moment(
|
||||
data.data.birthday,
|
||||
dateFormat
|
||||
))
|
||||
: ''
|
||||
} locale={locale} onChange={(dates, dateStrings) => {
|
||||
this.updataPosition({birthday: dateStrings})
|
||||
}}/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item
|
||||
name="phone"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
addonBefore={'+86'}
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.Item
|
||||
name="mail"
|
||||
rules={[
|
||||
{
|
||||
type: 'email',
|
||||
message: '邮箱格式错误!',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: '请输入邮箱!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item name="work_exp">
|
||||
<Select
|
||||
placeholder="选择工作年限"
|
||||
optionFilterProp="children"
|
||||
>
|
||||
<Option value={0}>应届生</Option>
|
||||
<Option value={1}>1-3年</Option>
|
||||
<Option value={2}>3-5年</Option>
|
||||
<Option value={3}>5年以上</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item name="education">
|
||||
<Select
|
||||
placeholder="选择学历"
|
||||
optionFilterProp="children"
|
||||
>
|
||||
<Option value={1}>大专</Option>
|
||||
<Option value={2}>本科</Option>
|
||||
<Option value={3}>硕士</Option>
|
||||
<Option value={4}>博士</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
</Form>
|
||||
<Col span={4}>
|
||||
<Form.Item
|
||||
name="now_address"
|
||||
rules={[
|
||||
{
|
||||
message: '填写现住地址',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder="填写现住地址"/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div className='resume-energy-box'>
|
||||
<Tabs defaultActiveKey="2" onChange={onChange}>
|
||||
<TabPane tab="原始简历" key="1">
|
||||
原始简历
|
||||
</TabPane>
|
||||
<TabPane tab="标准简历" key="2">
|
||||
<StandardResume />
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<div className='resume-right-box'>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
<div className="resume-energy-box">
|
||||
<div className='resume-xq-box'>
|
||||
<Originalresume data={data}/>
|
||||
</div>
|
||||
<div className='resume-xq-box'>
|
||||
<StandardResume data={data} updataPosition={this.updataPosition}/>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -7,7 +7,85 @@
|
||||
.Candidate-left-box {
|
||||
width: 250px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.Candidate-left-top-box {
|
||||
border-top: 1px solid #d9d9d9;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
background-color: #e9eaec;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.Candidate-left-icon-box {
|
||||
font-size: 20px;
|
||||
border-right: 1px solid #dddfe3;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
.Candidate-left-tit-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.Candidate-left-tit-icon-box {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 30px;
|
||||
background-color: #fff;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
color: #0c8cf6;
|
||||
|
||||
}
|
||||
.Candidate-left-tit {
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
color: #0c8cf6;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.Candidate-left-tit-jt-box {
|
||||
color: #0c8cf6;
|
||||
margin-right: 15px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.Candidate-position-box {
|
||||
margin: 15px;
|
||||
}
|
||||
.Candidate-position-search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.Candidate-position-search-box button {
|
||||
margin-left: 10px;
|
||||
padding: 4px 10px;
|
||||
color: #c1c5cc;
|
||||
}
|
||||
.Candidate-addgroup-box {
|
||||
color: #89909e;
|
||||
}
|
||||
.Candidate-info-screen-box {
|
||||
width: 100%;
|
||||
padding: 18px 15px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
border-top: 1px solid #dddfe3;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #292c32;
|
||||
}
|
||||
.Candidate-info-screen-icon-box {
|
||||
height: 20px;
|
||||
font-size: 12px;
|
||||
display: grid;
|
||||
}
|
||||
.Candidate-info-screen-icon-xia-box {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.Candidate-right-box {
|
||||
width: calc(100% - 250px);
|
||||
background-color: #fff;
|
||||
@ -48,7 +126,7 @@
|
||||
}
|
||||
.Candidate-table-box {
|
||||
margin: 24px;
|
||||
|
||||
height: calc(100vh - 210px);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,97 +1,357 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, Form, Input, Modal, Radio, Tabs } from 'antd'
|
||||
import { Button, Form, Input, Tabs, Tree, TreeSelect, message } from 'antd'
|
||||
import './index.css'
|
||||
import CandidateTable from '../../../components/CandidateTable'
|
||||
import { interviewstagenum, getsection } from '../../../util/requestURL'
|
||||
import memoryUtils from '../../../util/memoryUtils'
|
||||
import PubSub from 'pubsub-js'
|
||||
import {
|
||||
ShareAltOutlined,
|
||||
TeamOutlined,
|
||||
RightOutlined,
|
||||
SearchOutlined,
|
||||
FilterFilled,
|
||||
FolderFilled,
|
||||
FireFilled,
|
||||
PlusCircleOutlined,
|
||||
MenuOutlined,
|
||||
CaretUpOutlined,
|
||||
CaretDownOutlined,
|
||||
} from '@ant-design/icons'
|
||||
const { TabPane } = Tabs
|
||||
const { DirectoryTree } = Tree
|
||||
const { SHOW_PARENT } = TreeSelect
|
||||
|
||||
export default class Candidate extends Component {
|
||||
state = {
|
||||
tjnum: 0,
|
||||
csnum: 2,
|
||||
fsnum: 3,
|
||||
msnum: 4,
|
||||
gtnum: 5,
|
||||
drznum: 2,
|
||||
csnum: 0,
|
||||
fsnum: 0,
|
||||
msnum: 0,
|
||||
gtnum: 0,
|
||||
drznum: 0,
|
||||
step: '0',
|
||||
job_names:'',
|
||||
treeData: [],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
PubSub.publish('headtitle', { headtitle: '候选人管理' })
|
||||
|
||||
getsection().then(
|
||||
(res) => {
|
||||
const data = res.data
|
||||
const treeData = []
|
||||
for (let i in data) {
|
||||
const arr = {
|
||||
title: data[i]['name'],
|
||||
key: i,
|
||||
icon: <FolderFilled style={{ color: '#0c8cf6' }} />,
|
||||
children: [],
|
||||
}
|
||||
treeData.push(arr)
|
||||
for (let j in data[i]['position']) {
|
||||
const drr = {
|
||||
title: data[i]['position'][j]['job_name'],
|
||||
key: data[i]['position'][j]['job_id'],
|
||||
icon: <FireFilled style={{ color: '#ff6b6b' }} />,
|
||||
}
|
||||
treeData[i]['children'].push(drr)
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ treeData })
|
||||
},
|
||||
(ree) => {}
|
||||
)
|
||||
|
||||
this.updatainterviewstagenum()
|
||||
}
|
||||
|
||||
//更新候选人总数
|
||||
updatainterviewstagenum = () => {
|
||||
interviewstagenum({ data_in: {} }).then(
|
||||
(res) => {
|
||||
// console.log(res)
|
||||
const data = res.data
|
||||
this.setState({
|
||||
tjnum: data[0],
|
||||
csnum: data[1],
|
||||
fsnum: data[2],
|
||||
msnum: data[3],
|
||||
gtnum: data[4],
|
||||
drznum: data[5],
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { treeData } = this.state
|
||||
|
||||
const onSelect = (selectedKeys, info) => {
|
||||
// console.log(selectedKeys)
|
||||
if(selectedKeys[0].length > 3){
|
||||
console.log(selectedKeys)
|
||||
console.log(info.node.title)
|
||||
this.setState({
|
||||
job_names:info.node.title
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleClickTabs = (key) => {
|
||||
console.log(key)
|
||||
this.setState({
|
||||
step: key,
|
||||
})
|
||||
}
|
||||
|
||||
const treeSeletData = [
|
||||
{
|
||||
title: '初试',
|
||||
value: '0-0',
|
||||
key: '0-0',
|
||||
},
|
||||
{
|
||||
title: '复试',
|
||||
value: '0-1',
|
||||
key: '0-1',
|
||||
},
|
||||
{
|
||||
title: '终试',
|
||||
value: '0-2',
|
||||
key: '0-2',
|
||||
},
|
||||
]
|
||||
|
||||
const interviewstatusData = [
|
||||
{
|
||||
title: '待安排',
|
||||
value: '0-0',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{
|
||||
title: '待安排一',
|
||||
value: '0-0-0',
|
||||
key: '0-0-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '已安排',
|
||||
value: '0-1',
|
||||
key: '0-1',
|
||||
children: [
|
||||
{
|
||||
title: '已安排一',
|
||||
value: '0-1-0',
|
||||
key: '0-1-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const undetestatusData = [
|
||||
{
|
||||
title: '待安排',
|
||||
value: '0-0',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{
|
||||
title: '待安排一',
|
||||
value: '0-0-0',
|
||||
key: '0-0-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '已安排',
|
||||
value: '0-1',
|
||||
key: '0-1',
|
||||
children: [
|
||||
{
|
||||
title: '已安排一',
|
||||
value: '0-1-0',
|
||||
key: '0-1-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const onTreeChange = (newValue) => {
|
||||
// console.log('onChange ', value);
|
||||
// setValue(newValue);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="Candidate-box">
|
||||
<div className="Candidate-left-box"></div>
|
||||
<div className="Candidate-left-box">
|
||||
<div className="Candidate-left-top-box">
|
||||
<div className="Candidate-left-icon-box">
|
||||
<ShareAltOutlined />
|
||||
</div>
|
||||
<div className="Candidate-left-tit-box cursor">
|
||||
<div className="Candidate-left-tit">
|
||||
<div className="Candidate-left-tit-icon-box">
|
||||
<TeamOutlined />
|
||||
</div>
|
||||
<span className="marginleft6 fontweight">
|
||||
优先招聘职位
|
||||
</span>
|
||||
</div>
|
||||
<div className="Candidate-left-tit-jt-box">
|
||||
<RightOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Candidate-position-box">
|
||||
<p className="fontweight">招聘职位</p>
|
||||
<div className="Candidate-position-search-box">
|
||||
<Input
|
||||
placeholder="搜索职位"
|
||||
suffix={<SearchOutlined />}
|
||||
onChange={(e)=>{
|
||||
this.setState({
|
||||
job_names: e.target.value
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button>
|
||||
<FilterFilled />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="margintop20 backgroundcolor">
|
||||
<DirectoryTree
|
||||
multiple
|
||||
defaultExpandAll
|
||||
showIcon={true}
|
||||
blockNode={true}
|
||||
onSelect={onSelect}
|
||||
treeData={treeData}
|
||||
/>
|
||||
|
||||
<div className="Candidate-addgroup-box cursor margintop20">
|
||||
<PlusCircleOutlined />{' '}
|
||||
<span className="marginleft6">
|
||||
添加职位分组
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Candidate-info-screen-box cursor">
|
||||
<div>
|
||||
<MenuOutlined />{' '}
|
||||
<span className="marginleft6">候选人信息筛选</span>
|
||||
</div>
|
||||
<div className="Candidate-info-screen-icon-box">
|
||||
<CaretUpOutlined />
|
||||
<CaretDownOutlined className="Candidate-info-screen-icon-xia-box" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="Candidate-right-box">
|
||||
<div className="Candidate-tabs-box">
|
||||
<Tabs defaultActiveKey="1">
|
||||
<Tabs defaultActiveKey="0" onChange={handleClickTabs}>
|
||||
<TabPane
|
||||
tab={
|
||||
<div className='tabs-box shadowright'>
|
||||
<div className="tabs-box shadowright">
|
||||
<div>{this.state.tjnum}</div>
|
||||
<div>人才推荐</div>
|
||||
</div>
|
||||
}
|
||||
key="1"
|
||||
>
|
||||
|
||||
</TabPane>
|
||||
key="0"
|
||||
></TabPane>
|
||||
<TabPane
|
||||
tab={
|
||||
<div className='tabs-box tabs-border'>
|
||||
<div className="tabs-box tabs-border">
|
||||
<div>{this.state.csnum}</div>
|
||||
<div>处筛</div>
|
||||
<div>初筛</div>
|
||||
</div>
|
||||
}
|
||||
key="2"
|
||||
>
|
||||
</TabPane>
|
||||
key="1"
|
||||
></TabPane>
|
||||
|
||||
<TabPane
|
||||
<TabPane
|
||||
tab={
|
||||
<div className='tabs-box tabs-border'>
|
||||
<div className="tabs-box tabs-border">
|
||||
<div>{this.state.fsnum}</div>
|
||||
<div>用人部门复筛</div>
|
||||
</div>
|
||||
}
|
||||
key="3"
|
||||
>
|
||||
</TabPane>
|
||||
key="2"
|
||||
></TabPane>
|
||||
|
||||
<TabPane
|
||||
<TabPane
|
||||
tab={
|
||||
<div className='tabs-box tabs-border'>
|
||||
<div className="tabs-box tabs-border">
|
||||
<div>{this.state.msnum}</div>
|
||||
<div>面试</div>
|
||||
</div>
|
||||
}
|
||||
key="4"
|
||||
>
|
||||
</TabPane>
|
||||
<TabPane
|
||||
key="3"
|
||||
></TabPane>
|
||||
<TabPane
|
||||
tab={
|
||||
<div className='tabs-box tabs-border'>
|
||||
<div className="tabs-box tabs-border">
|
||||
<div>{this.state.gtnum}</div>
|
||||
<div>沟通offer</div>
|
||||
</div>
|
||||
}
|
||||
key="5"
|
||||
>
|
||||
</TabPane>
|
||||
<TabPane
|
||||
key="4"
|
||||
></TabPane>
|
||||
<TabPane
|
||||
tab={
|
||||
<div className='tabs-box border0'>
|
||||
<div className="tabs-box border0">
|
||||
<div>{this.state.drznum}</div>
|
||||
<div>待入职</div>
|
||||
</div>
|
||||
}
|
||||
key="6"
|
||||
>
|
||||
</TabPane>
|
||||
key="5"
|
||||
></TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
<div className='Candidate-table-box'>
|
||||
|
||||
<CandidateTable/>
|
||||
|
||||
</div>
|
||||
<div className="Candidate-table-box">
|
||||
{/* <div className="">
|
||||
<TreeSelect
|
||||
treeData={treeSeletData}
|
||||
onChange={onTreeChange}
|
||||
treeCheckable={true}
|
||||
showCheckedStrategy={SHOW_PARENT}
|
||||
placeholder="面试轮次"
|
||||
style={{ width: '10%' }}
|
||||
/>
|
||||
<TreeSelect
|
||||
treeData={interviewstatusData}
|
||||
onChange={onTreeChange}
|
||||
treeCheckable={true}
|
||||
showCheckedStrategy={SHOW_PARENT}
|
||||
placeholder="面试状态"
|
||||
style={{ width: '10%' }}
|
||||
/>
|
||||
<TreeSelect
|
||||
treeData={undetestatusData}
|
||||
onChange={onTreeChange}
|
||||
treeCheckable={true}
|
||||
showCheckedStrategy={SHOW_PARENT}
|
||||
placeholder="面试状态"
|
||||
style={{ width: '10%' }}
|
||||
/>
|
||||
</div> */}
|
||||
|
||||
<CandidateTable
|
||||
step={this.state.step}
|
||||
job_names = {this.state.job_names}
|
||||
updatainterviewstagenum={
|
||||
this.updatainterviewstagenum
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
.Interview-bj { width: 100%; background-color: #fff;}
|
||||
.Interview-bj { width: 100%; background-color: #fff; padding-bottom: 20px;}
|
||||
.Interview-box {
|
||||
margin: 0px 180px;
|
||||
padding-top: 45px;
|
||||
@ -9,3 +9,9 @@
|
||||
|
||||
.Interview-querycriteria-box { margin-top: 25px; width: 80%; }
|
||||
.Interview-table-title { font-size: 17px; font-weight: bold; color: #575d6a; margin: 20px 0; }
|
||||
.ewmimg {
|
||||
opacity: 0;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
top: 0
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import ExportForm from '../../../components/ExportForm'
|
||||
import InterviewerInfoPop from '../../../components/InterviewerInfoPop'
|
||||
import Editresume from '../../../components/Editresume'
|
||||
import PubSub from 'pubsub-js'
|
||||
import storageUtils from '../../../util/storageUtils'
|
||||
import './index.css'
|
||||
import {
|
||||
Button,
|
||||
@ -15,6 +17,9 @@ import {
|
||||
Col,
|
||||
Table,
|
||||
Tag,
|
||||
message,
|
||||
Pagination,
|
||||
Image,
|
||||
} from 'antd'
|
||||
import {
|
||||
UnorderedListOutlined,
|
||||
@ -25,18 +30,81 @@ import {
|
||||
LikeOutlined,
|
||||
WarningOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import {
|
||||
getname,
|
||||
getjob,
|
||||
postcondition,
|
||||
teacherstate,
|
||||
} from '../../../util/requestURL'
|
||||
|
||||
const { Option } = Select
|
||||
function Interview() {
|
||||
const [tabPosition, setTabPosition] = useState('list')
|
||||
const [visible, setVisible] = useState(false) //导出面试安排弹窗
|
||||
const [interviewerInfo, setInterviewerInfo] = useState(false) //弹出面试人信息弹窗
|
||||
const [editresume, setEditresume] = useState(false) //编辑候选人信息弹窗
|
||||
const [candidateid,setcandidateid] = useState(0)
|
||||
const [interviewerInfo, setInterviewerInfo] = useState(false) //弹出面试人信息弹窗
|
||||
const [editresume, setEditresume] = useState(false) //编辑候选人信息弹窗
|
||||
const [candidateid, setcandidateid] = useState(0) //查看面试人信息弹窗传的id
|
||||
const [hrName, setHrName] = useState([]) //负责人下拉选框数据
|
||||
const [interviewName, setinterviewName] = useState([]) //面试官下拉数据
|
||||
const [job, setjob] = useState([]) //职位下拉数据
|
||||
const [today, settoday] = useState() //今天面试数据
|
||||
const [todaynum, settodaynum] = useState(0)
|
||||
const [tomorrow, settomorrow] = useState() //明天面试数据
|
||||
const [tomorrownum, settomorrownum] = useState(0)
|
||||
const [yesterday, setyesterday] = useState() //昨天面试数据
|
||||
const [yesterdaynum, setyesterdaynum] = useState(0)
|
||||
const [form] = Form.useForm()
|
||||
const todaynum = 0
|
||||
const tomorrow = 0
|
||||
const yesterday = 0
|
||||
|
||||
var userInfo = storageUtils.getUser()
|
||||
|
||||
let screenData = {
|
||||
date: {
|
||||
job_name: '',
|
||||
hr_name: '',
|
||||
interview_name: '',
|
||||
interview_type: '',
|
||||
interview_sign: '',
|
||||
feedback: '',
|
||||
interview_round: '',
|
||||
hr_id: '',
|
||||
},
|
||||
pages: 1,
|
||||
time_type: 'now',
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
PubSub.publish('headtitle', { headtitle: '面试安排' })
|
||||
// console.log('首次渲染页面')
|
||||
//获取所有用户
|
||||
getname().then(
|
||||
(res) => {
|
||||
const interview_name = []
|
||||
const hr_name = []
|
||||
for (let i in res.data) {
|
||||
if (res.data[i]['rank'] == 1) {
|
||||
hr_name.push(res.data[i])
|
||||
} else if (res.data[i]['rank'] == 2) {
|
||||
interview_name.push(res.data[i])
|
||||
}
|
||||
}
|
||||
setinterviewName(interview_name)
|
||||
setHrName(hr_name)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
//获取全部职位名称
|
||||
getjob().then(
|
||||
(res) => {
|
||||
setjob(res.data.job)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
|
||||
CallApiList()
|
||||
}, [])
|
||||
|
||||
const changeTabPosition = (e) => {
|
||||
setTabPosition(e.target.value)
|
||||
@ -49,32 +117,120 @@ function Interview() {
|
||||
console.log('Received values of form: ', values)
|
||||
setVisible(false)
|
||||
}
|
||||
const handelFeedback = (record,index)=>{
|
||||
console.log("催促反馈")
|
||||
}
|
||||
const handelInterviewerInfo = (record,index)=>{
|
||||
console.log("查看信息")
|
||||
setcandidateid(record.key)
|
||||
setInterviewerInfo(true)
|
||||
}
|
||||
const handelFeedback = (record, index) => {
|
||||
teacherstate({
|
||||
user_id: [record.interview_id],
|
||||
name: record.name,
|
||||
}).then(
|
||||
(res) => {
|
||||
console.log(res)
|
||||
if (res.code == 200) {
|
||||
message.success('发送成功')
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
const handelInterviewerInfo = (record, index) => {
|
||||
// console.log('查看信息',record)
|
||||
// console.log(record.key)
|
||||
setcandidateid(record.key)
|
||||
setInterviewerInfo(true)
|
||||
}
|
||||
|
||||
const onInterviewerInfo = (values) =>{
|
||||
setInterviewerInfo(false)
|
||||
}
|
||||
const onInterviewerInfo = (values) => {
|
||||
setInterviewerInfo(false)
|
||||
}
|
||||
|
||||
const onEditresumeCreate = () =>{
|
||||
setEditresume(false)
|
||||
}
|
||||
const onEditresumeCreate = () => {
|
||||
setEditresume(false)
|
||||
}
|
||||
|
||||
// 查看详情里面编辑按钮
|
||||
const onEditresume = (data)=>{
|
||||
setInterviewerInfo(false)
|
||||
console.log(data);
|
||||
setTimeout(()=>{
|
||||
setEditresume(true)
|
||||
},500)
|
||||
|
||||
}
|
||||
// 查看详情里面编辑按钮
|
||||
const onEditresume = (data) => {
|
||||
setInterviewerInfo(false)
|
||||
console.log(data)
|
||||
setTimeout(() => {
|
||||
setEditresume(true)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const handelSelect = (value, res) => {
|
||||
// console.log(value)
|
||||
screenData['date'][res] = value == 0 ? '' : value
|
||||
CallApiList()
|
||||
}
|
||||
|
||||
const CallApiList = () => {
|
||||
PostTableData(screenData, 'now')
|
||||
PostTableData(screenData, 'tomorrow')
|
||||
PostTableData(screenData, 'yesterday')
|
||||
}
|
||||
|
||||
const PostTableData = (screenData, type, pages) => {
|
||||
screenData['time_type'] = type
|
||||
if (pages) {
|
||||
screenData['pages'] = pages
|
||||
}
|
||||
postcondition(screenData).then(
|
||||
(res) => {
|
||||
switch (type) {
|
||||
case 'now':
|
||||
settoday(res.data.data)
|
||||
settodaynum(res.data.lens)
|
||||
break
|
||||
case 'tomorrow':
|
||||
settomorrow(res.data.data)
|
||||
settomorrownum(res.data.lens)
|
||||
break
|
||||
default:
|
||||
setyesterday(res.data.data)
|
||||
setyesterdaynum(res.data.lens)
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const handelPage = (page, type) => {
|
||||
PostTableData(screenData, 'tomorrow', page)
|
||||
}
|
||||
|
||||
const [allpositionmenutitle, setallpositionmenutitle] = useState('全部职位')
|
||||
const onallpositionclick = (item) => {
|
||||
setallpositionmenutitle(item.key)
|
||||
if (item.key === '我负责的职位') {
|
||||
screenData.date.hr_id = userInfo.user_id
|
||||
} else {
|
||||
screenData.date.hr_id = ''
|
||||
}
|
||||
CallApiList()
|
||||
}
|
||||
const allpositionmenu = (
|
||||
<Menu
|
||||
selectable
|
||||
defaultSelectedKeys={['1']}
|
||||
onClick={onallpositionclick}
|
||||
items={[
|
||||
{
|
||||
key: '全部职位',
|
||||
label: '全部职位',
|
||||
},
|
||||
{
|
||||
key: '我负责的职位',
|
||||
label: '我负责的职位',
|
||||
},
|
||||
// {
|
||||
// key: '我协助的职位',
|
||||
// label: '我协助的职位',
|
||||
// },
|
||||
]}
|
||||
/>
|
||||
)
|
||||
|
||||
const menu = (
|
||||
<Menu
|
||||
@ -82,12 +238,22 @@ function Interview() {
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: '面试签到二维码',
|
||||
label: (
|
||||
<div>
|
||||
<Image
|
||||
width={'100px'}
|
||||
height={20}
|
||||
className="ewmimg"
|
||||
src="https://legu-cdn-source.obs.cn-east-2.myhuaweicloud.com/hrms/checkInQR.png"
|
||||
/>
|
||||
<p style={{ position: 'absolute' , top: 10 , 'z-index': 1}}>面试签到二维码</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: '显示已取消的面试',
|
||||
}
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)
|
||||
@ -95,14 +261,14 @@ function Interview() {
|
||||
const columns = [
|
||||
{
|
||||
title: '面试信息',
|
||||
dataIndex: 'info',
|
||||
dataIndex: 'msg',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div className="basicdata-box">
|
||||
<Tag color="#00d1db">
|
||||
{text.rounds === 0
|
||||
{text.interview_round === 0
|
||||
? '初试'
|
||||
: text.rounds === 1
|
||||
: text.interview_round === 1
|
||||
? '复试'
|
||||
: '终试'}
|
||||
</Tag>
|
||||
@ -116,21 +282,16 @@ function Interview() {
|
||||
},
|
||||
{
|
||||
title: '候选人',
|
||||
dataIndex: 'candidate',
|
||||
dataIndex: 'name',
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color0">
|
||||
{text.type ? (
|
||||
<CheckCircleTwoTone twoToneColor="#51cf66" />
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<span style={{ marginLeft: 2 }}>{text.name}</span>
|
||||
<span style={{ marginLeft: 2 }}>{text}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '联系方式',
|
||||
dataIndex: 'tel',
|
||||
dataIndex: 'phone',
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color0">
|
||||
<span>{text}</span>
|
||||
@ -139,21 +300,14 @@ function Interview() {
|
||||
},
|
||||
{
|
||||
title: '应聘职位',
|
||||
dataIndex: 'position',
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color1">{text}</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '面试地点',
|
||||
dataIndex: 'address',
|
||||
dataIndex: 'job_names',
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color1">{text}</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '面试负责人',
|
||||
dataIndex: 'principal',
|
||||
dataIndex: 'hr_name',
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color1">{text}</div>
|
||||
),
|
||||
@ -164,74 +318,38 @@ function Interview() {
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color1">
|
||||
{text.type === 0 ? (
|
||||
<LikeOutlined style={{ color: '#51cf66' }} />
|
||||
) : (
|
||||
<WarningOutlined style={{ color: '#f59f00' }} />
|
||||
) : (
|
||||
<LikeOutlined style={{ color: '#51cf66' }} />
|
||||
)}
|
||||
{text.name}
|
||||
{text.name}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'setup',
|
||||
dataIndex: 'type',
|
||||
render: (text, record, index) => (
|
||||
<div className="font-size14 color4 ">
|
||||
<span className='cursor' style={{'margin':'0px 5px'}} onClick={()=>handelInterviewerInfo(record,index)}>查看详情</span>
|
||||
<span className='cursor' style={{'margin':'0px 5px'}} onClick={()=>handelFeedback(record,index)}>{text.type === 0 ? '催促反馈' : ''}</span>
|
||||
<span
|
||||
className="cursor"
|
||||
style={{ margin: '0px 5px' }}
|
||||
onClick={() => handelInterviewerInfo(record, index)}
|
||||
>
|
||||
查看详情
|
||||
</span>
|
||||
<span
|
||||
className="cursor"
|
||||
style={{ margin: '0px 5px' }}
|
||||
onClick={() => handelFeedback(record, index)}
|
||||
>
|
||||
{text.type === 0 ? '催促反馈' : ''}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
const data = [
|
||||
{
|
||||
key: 0,
|
||||
info: {
|
||||
rounds: 0,
|
||||
type: 0,
|
||||
time: '5云17日 09:30 - 10:00',
|
||||
},
|
||||
candidate: {
|
||||
type: true,
|
||||
name: '张三',
|
||||
},
|
||||
tel: 18563265489,
|
||||
position: '前端工程师',
|
||||
address: '武汉 创意天地',
|
||||
principal: '李四',
|
||||
type: {
|
||||
type: 0,
|
||||
name: '王五',
|
||||
},
|
||||
setup: {
|
||||
type: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 1,
|
||||
info: {
|
||||
rounds: 1,
|
||||
type: 1,
|
||||
time: '5云17日 09:30 - 10:00',
|
||||
},
|
||||
candidate: {
|
||||
type: false,
|
||||
name: '张三',
|
||||
},
|
||||
tel: 18563265489,
|
||||
position: '前端工程师',
|
||||
address: '武汉 创意天地',
|
||||
principal: '李四',
|
||||
type: {
|
||||
type: 1,
|
||||
name: '王五',
|
||||
},
|
||||
setup: {
|
||||
type: 1,
|
||||
},
|
||||
},
|
||||
]
|
||||
const [hasData, setHasData] = useState(true)
|
||||
const tableColumns = columns.map((item) => ({ ...item }))
|
||||
return (
|
||||
@ -252,10 +370,12 @@ function Interview() {
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
|
||||
<Button className="allposition">
|
||||
<TeamOutlined /> 全部职位
|
||||
<RightOutlined />
|
||||
</Button>
|
||||
<Dropdown overlay={allpositionmenu}>
|
||||
<Button className="allposition">
|
||||
<TeamOutlined /> {allpositionmenutitle}
|
||||
<RightOutlined />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
@ -283,86 +403,144 @@ function Interview() {
|
||||
<Row gutter={12}>
|
||||
<Col span={4}>
|
||||
<Form.Item label="职位">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
<Select
|
||||
defaultValue=""
|
||||
onChange={(value) => {
|
||||
handelSelect(value, 'job_id')
|
||||
}}
|
||||
>
|
||||
<Option value="">全部职位</Option>
|
||||
{job.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
key={item['key']}
|
||||
value={item['key']}
|
||||
>
|
||||
{item['job_name']}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item label="面试负责人">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
<Select
|
||||
defaultValue=""
|
||||
defaultActiveFirstOption={true}
|
||||
onChange={(value) => {
|
||||
handelSelect(value, 'hr_name')
|
||||
}}
|
||||
>
|
||||
<Option value="">全部</Option>
|
||||
{hrName.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
value={item.name}
|
||||
key={(key + 1) * 1}
|
||||
>
|
||||
{item.name}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item label="面试官">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
<Select
|
||||
defaultValue=""
|
||||
onChange={(value) => {
|
||||
handelSelect(
|
||||
value,
|
||||
'interview_name'
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value="">全部</Option>
|
||||
{interviewName.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
value={item.name}
|
||||
key={(key + 1) * 1}
|
||||
>
|
||||
{item.name}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item label="面试类型">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item label="面试地点">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
<Select
|
||||
defaultValue=""
|
||||
onChange={(value) => {
|
||||
handelSelect(
|
||||
value,
|
||||
'interview_type'
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value="">全部类型</Option>
|
||||
<Option value="0">现场面试</Option>
|
||||
<Option value="1">视频面试</Option>
|
||||
<Option value="2">集体面试</Option>
|
||||
<Option value="3">电话面试</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item label="面试签到">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
<Select
|
||||
defaultValue=""
|
||||
onChange={(value) => {
|
||||
handelSelect(
|
||||
value,
|
||||
'interview_sign'
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value="">全部</Option>
|
||||
<Option value="0">已签到</Option>
|
||||
<Option value="1">未签到</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={4}>
|
||||
<Form.Item label="面反馈">
|
||||
<Select defaultValue="0">
|
||||
<Option value="0">全部职位</Option>
|
||||
<Option value="1">职位一</Option>
|
||||
<Option value="2">职位二</Option>
|
||||
<Option value="3">职位三</Option>
|
||||
<Form.Item label="面试反馈">
|
||||
<Select
|
||||
defaultValue=""
|
||||
onChange={(value) => {
|
||||
handelSelect(value, 'feedback')
|
||||
}}
|
||||
>
|
||||
<Option value="">全部反馈</Option>
|
||||
<Option value={0}>已全部反馈</Option>
|
||||
<Option value={1}>未全部反馈</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={4}>
|
||||
{/* <Col span={4}>
|
||||
<Form.Item label="面试轮次">
|
||||
<Select defaultValue="0">
|
||||
<Select
|
||||
defaultValue="0"
|
||||
onChange={(value) => {
|
||||
handelSelect(
|
||||
value,
|
||||
'interview_round'
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Option value="0">全部轮次</Option>
|
||||
<Option value="1">初试</Option>
|
||||
<Option value="2">复试</Option>
|
||||
<Option value="3">终试</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Col> */}
|
||||
</Row>
|
||||
</Form>
|
||||
</div>
|
||||
@ -374,48 +552,68 @@ function Interview() {
|
||||
<Table
|
||||
bordered
|
||||
columns={tableColumns}
|
||||
dataSource={hasData ? data : []}
|
||||
dataSource={hasData ? today : []}
|
||||
pagination={{
|
||||
position: ['none', 'none'],
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="margintop20 textalign">
|
||||
<Pagination total={todaynum} hideOnSinglePage={true} />
|
||||
</div>
|
||||
{/* 明天及之后的面试 */}
|
||||
<div className="Interview-table-title">
|
||||
明天及之后的面试({tomorrow})
|
||||
明天及之后的面试({tomorrownum})
|
||||
</div>
|
||||
<Table
|
||||
bordered
|
||||
columns={tableColumns}
|
||||
dataSource={hasData ? data : []}
|
||||
dataSource={hasData ? tomorrow : []}
|
||||
pagination={{
|
||||
position: ['none', 'none'],
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="margintop20 textalign">
|
||||
<Pagination
|
||||
total={tomorrownum}
|
||||
hideOnSinglePage={true}
|
||||
onChange={(page) => handelPage(page, 'tomorrow')}
|
||||
/>
|
||||
</div>
|
||||
{/* 昨天及之前的面试 */}
|
||||
<div className="Interview-table-title">
|
||||
昨天及之前的面试({yesterday})
|
||||
昨天及之前的面试({yesterdaynum})
|
||||
</div>
|
||||
<Table
|
||||
bordered
|
||||
columns={tableColumns}
|
||||
dataSource={hasData ? data : []}
|
||||
dataSource={hasData ? yesterday : []}
|
||||
pagination={{
|
||||
position: ['none', 'none'],
|
||||
}}
|
||||
/>
|
||||
<div className="margintop20 textalign">
|
||||
<Pagination total={yesterdaynum} hideOnSinglePage={true} />
|
||||
</div>
|
||||
{/* 查看面试人信息弹窗 */}
|
||||
<InterviewerInfoPop
|
||||
visible={interviewerInfo}
|
||||
onCreate={onInterviewerInfo}
|
||||
data={candidateid}
|
||||
onCancel={() => {
|
||||
setInterviewerInfo(false)
|
||||
}}
|
||||
onEditresume={onEditresume}
|
||||
/>
|
||||
|
||||
{/* 查看面试人信息弹窗 */}
|
||||
<InterviewerInfoPop
|
||||
visible={interviewerInfo}
|
||||
onCreate={onInterviewerInfo}
|
||||
data={candidateid}
|
||||
onCancel={() => {
|
||||
setInterviewerInfo(false);
|
||||
}}
|
||||
onEditresume={onEditresume}
|
||||
/>
|
||||
|
||||
{/* 编辑候选人信息弹窗 */}
|
||||
<Editresume
|
||||
visible={editresume}
|
||||
onCreate={onEditresumeCreate}
|
||||
onCancel={()=>{
|
||||
setEditresume(false)
|
||||
}}
|
||||
/>
|
||||
{/* 编辑候选人信息弹窗 */}
|
||||
<Editresume
|
||||
visible={editresume}
|
||||
onCreate={onEditresumeCreate}
|
||||
data={candidateid}
|
||||
onCancel={() => {
|
||||
setEditresume(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
23
src/pages/admin/Interview_manager/index.css
Normal file
23
src/pages/admin/Interview_manager/index.css
Normal file
@ -0,0 +1,23 @@
|
||||
.Resumescreen-box {
|
||||
margin: 60px 230px;
|
||||
}
|
||||
.Resumescreen-list-data-box {
|
||||
background-color: #fff;
|
||||
min-height: 600px;
|
||||
}
|
||||
.Resumescreen-list-tab-box {
|
||||
margin: 0 30px;
|
||||
}
|
||||
.Resumescreen-list-tab-box .ant-tabs-tab-btn {
|
||||
color: #312b2e !important;
|
||||
}
|
||||
.Resumescreen-list-tab-box .num {
|
||||
font-size: 17px;
|
||||
}
|
||||
.Resumescreen-list-tab-box .ant-tabs { width: 100%; }
|
||||
.Resumescreen-list-table-box { margin: 0 30px; }
|
||||
.Resumescreen-list-data-box .CandidateTable-owner { width: 10%; }
|
||||
.Resumescreen-list-data-box .CandidateTable-list-box { align-items: center; }
|
||||
.Resumescreen-list-data-box .CandidateTable-info { margin-left: 0; }
|
||||
|
||||
|
334
src/pages/admin/Interview_manager/index.jsx
Normal file
334
src/pages/admin/Interview_manager/index.jsx
Normal file
@ -0,0 +1,334 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
Input,
|
||||
Space,
|
||||
Form,
|
||||
Select,
|
||||
Col,
|
||||
Row,
|
||||
Tabs,
|
||||
Empty,
|
||||
Tag,
|
||||
Button,
|
||||
message,
|
||||
DatePicker,
|
||||
Table,
|
||||
} from 'antd'
|
||||
import { AudioOutlined, ShoppingFilled, BankOutlined } from '@ant-design/icons'
|
||||
import PubSub from 'pubsub-js'
|
||||
import {
|
||||
getjob,
|
||||
postcondition,
|
||||
interview,
|
||||
interviewfind,
|
||||
interviews,
|
||||
} from '../../../util/requestURL'
|
||||
import storageUtils from '../../../util/storageUtils'
|
||||
import InterviewerInfoPop from '../../../components/InterviewerInfoPop'
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import './index.css'
|
||||
const { Search } = Input
|
||||
const { Option } = Select
|
||||
|
||||
export default class Resumescreen extends Component {
|
||||
state = {
|
||||
getjoblist: {},
|
||||
name: '',
|
||||
job_name: '',
|
||||
result: '',
|
||||
userInfo: storageUtils.getUser(),
|
||||
interviewerInfo: false,
|
||||
uid: 0,
|
||||
psges: 1,
|
||||
star_time: '',
|
||||
later: 0,
|
||||
later_false: 0,
|
||||
later_invalid: 0,
|
||||
teacher_true: 0,
|
||||
dataSource: [],
|
||||
columns: [
|
||||
{
|
||||
title: '候选人',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '应聘职位',
|
||||
dataIndex: 'job_names',
|
||||
key: 'job_names',
|
||||
},
|
||||
{
|
||||
title: '面试日期',
|
||||
dataIndex: 'star_time',
|
||||
key: 'star_time',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'interview_type',
|
||||
key: 'interview_type',
|
||||
},
|
||||
{
|
||||
title: '面试负责人',
|
||||
dataIndex: 'hr_name',
|
||||
key: 'hr_name',
|
||||
},
|
||||
{
|
||||
title: '候选人状态',
|
||||
dataIndex: 'interview_stage',
|
||||
key: 'interview_stage',
|
||||
},
|
||||
{
|
||||
title: '反馈结果',
|
||||
dataIndex: 'teacher_back',
|
||||
key: 'teacher_back',
|
||||
render: (text, item) => {
|
||||
switch (item.teacher_back) {
|
||||
case 1:
|
||||
return <span>满意</span>
|
||||
break
|
||||
case 2:
|
||||
return <span>非常满意</span>
|
||||
break
|
||||
case 3:
|
||||
return <span>不满意</span>
|
||||
break
|
||||
case 4:
|
||||
return <span>非常满意</span>
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
PubSub.publish('headtitle', { headtitle: '面试安排' })
|
||||
getjob().then(
|
||||
(res) => {
|
||||
this.setState({
|
||||
getjoblist: res.data.job,
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
|
||||
this.postupdata()
|
||||
}
|
||||
|
||||
postupdata = () => {
|
||||
const { psges, name, job_name, result, star_time, userInfo } =
|
||||
this.state
|
||||
const postlist = {
|
||||
date: {
|
||||
name,
|
||||
job_name,
|
||||
result,
|
||||
star_time,
|
||||
interview_id: userInfo.user_id,
|
||||
},
|
||||
pages: psges,
|
||||
time_type: 'later',
|
||||
}
|
||||
postcondition(postlist).then(
|
||||
(res) => {
|
||||
console.log(res.data)
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
|
||||
interviews({ date: postlist['date'] }).then(
|
||||
(res) => {
|
||||
// console.log(res.data)
|
||||
var newdataSource = res.data['later'].map((item, key) => {
|
||||
return { ...item, key: item.uid }
|
||||
})
|
||||
// console.log(newdataSource)
|
||||
this.setState({
|
||||
dataSource: newdataSource,
|
||||
data: res.data,
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
|
||||
//获取数量
|
||||
interview({ date: postlist['date'] }).then(
|
||||
(res) => {
|
||||
this.setState(res.data)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onValuesChange = (e) => {
|
||||
this.setState(e)
|
||||
}
|
||||
|
||||
handelonChange = (e) => {
|
||||
const { data } = this.state
|
||||
var newdataSource = data[e].map((item, key) => {
|
||||
return { ...item, key: item.uid }
|
||||
})
|
||||
this.setState({
|
||||
dataSource: newdataSource,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
getjoblist,
|
||||
data,
|
||||
later,
|
||||
later_false,
|
||||
later_invalid,
|
||||
teacher_true,
|
||||
} = this.state
|
||||
const onSearch = (value) => console.log(value)
|
||||
|
||||
return (
|
||||
<div className="Resumescreen-box">
|
||||
<div className="">
|
||||
<Form
|
||||
layout="vertical"
|
||||
onValuesChange={this.onValuesChange}
|
||||
>
|
||||
<Row gutter={24}>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="候选人" name="name">
|
||||
<Search
|
||||
placeholder="请输入候选人姓名"
|
||||
onSearch={onSearch}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="应聘职位" name="job_name">
|
||||
<Select>
|
||||
<Option value="">全部职位</Option>
|
||||
{getjoblist.length > 0
|
||||
? getjoblist.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
value={
|
||||
item.job_name
|
||||
}
|
||||
key={key}
|
||||
>
|
||||
{item.job_name}
|
||||
</Option>
|
||||
)
|
||||
})
|
||||
: ''}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="面试时间" name="time">
|
||||
<DatePicker locale={locale} style={{'width':'210px'}}/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="反馈结果" name="result">
|
||||
<Select>
|
||||
<Option value={''}>全部</Option>
|
||||
<Option value={0}>满意</Option>
|
||||
<Option value={1}>一般</Option>
|
||||
<Option value={2}>不满意</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div className="Resumescreen-list-data-box">
|
||||
<div className="Resumescreen-list-tab-box">
|
||||
<Tabs
|
||||
defaultActiveKey={'later'}
|
||||
onChange={(e) => this.handelonChange(e)}
|
||||
>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<div className="tabs-box">
|
||||
<div className="num">{later}</div>
|
||||
<div>今后的面试</div>
|
||||
</div>
|
||||
}
|
||||
key={'later'}
|
||||
></Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<div className="tabs-box">
|
||||
<div className="num">{later_false}</div>
|
||||
<div>未反馈的面试</div>
|
||||
</div>
|
||||
}
|
||||
key={'later_false'}
|
||||
></Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<div className="tabs-box">
|
||||
<div className="num">
|
||||
{teacher_true}
|
||||
</div>
|
||||
<div>已反馈的面试</div>
|
||||
</div>
|
||||
}
|
||||
key={'teacher_true'}
|
||||
></Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<div className="tabs-box">
|
||||
<div className="num">
|
||||
{later_invalid}
|
||||
</div>
|
||||
<div>已失效的面试</div>
|
||||
</div>
|
||||
}
|
||||
key={'later_invalid'}
|
||||
></Tabs.TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div className="Resumescreen-list-table-box">
|
||||
<Table
|
||||
dataSource={this.state.dataSource}
|
||||
columns={this.state.columns}
|
||||
pagination={false}
|
||||
onRow={(record) => {
|
||||
return {
|
||||
onClick: (event) => {
|
||||
this.setState({
|
||||
interviewerInfo: true,
|
||||
uid: record.key,
|
||||
})
|
||||
},
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* 查看面试人信息弹窗 */}
|
||||
<InterviewerInfoPop
|
||||
visible={this.state.interviewerInfo}
|
||||
onCreate={() => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
})
|
||||
}}
|
||||
data={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
108
src/pages/admin/Overview/index.css
Normal file
108
src/pages/admin/Overview/index.css
Normal file
@ -0,0 +1,108 @@
|
||||
.Overview-box {
|
||||
margin: 40px 180px;
|
||||
}
|
||||
.Overview-box p {
|
||||
color: #121316;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.Overview-top-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Overview-content-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.Overview-card-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
margin-top: 30px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(000, 000, 000, 0.1);
|
||||
}
|
||||
.Overview-card-list-box {
|
||||
width: 160px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.Overview-card-list {
|
||||
margin-left: 14px;
|
||||
}
|
||||
.Overview-card-list p {
|
||||
font-size: 16px;
|
||||
color: #121316;
|
||||
}
|
||||
.Overview-card-list2 span {
|
||||
color: #575d6a;
|
||||
}
|
||||
.Overview-card-list span {
|
||||
font-size: 14px;
|
||||
color: #575d6a;
|
||||
}
|
||||
.Overview-card-box .xian {
|
||||
width: 1px;
|
||||
height: 46px;
|
||||
background-color: #f4f4f5;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.Overview-card-top-box {
|
||||
width: 100%;
|
||||
background-color: #f9f9fa;
|
||||
padding: 8px 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.Overview-card-box2 {
|
||||
/* display: flex;
|
||||
align-items: center; */
|
||||
/* padding: 16px 0; */
|
||||
background-color: #fff;
|
||||
margin-top: 18px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(000, 000, 000, 0.1);
|
||||
}
|
||||
.Overview-card-list-box2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.Overview-card-list2 {
|
||||
min-width: 111px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.Overview-card-tips {
|
||||
color: #575d6a;
|
||||
font-size: 14px;
|
||||
padding: 8px 16px;
|
||||
border-top: 1px solid #f4f4f5;
|
||||
}
|
||||
.Overview-card-tips label {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.Overview-content-right-box {
|
||||
background-color: #fff;
|
||||
padding: 16px;
|
||||
width: calc(100% - 425px);
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.Overview-content-right-top-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
font-size: 18px;
|
||||
color: #575d6a;
|
||||
}
|
||||
.allsign {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.Overview-tab-box .ant-tabs {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -1,9 +1,264 @@
|
||||
import React from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import PubSub from 'pubsub-js'
|
||||
import {
|
||||
Button,
|
||||
Space,
|
||||
Tabs,
|
||||
Tag,
|
||||
Avatar,
|
||||
List,
|
||||
Dropdown,
|
||||
message,
|
||||
Empty,
|
||||
} from 'antd'
|
||||
import {
|
||||
ApartmentOutlined,
|
||||
RightOutlined,
|
||||
TeamOutlined,
|
||||
CalendarOutlined,
|
||||
FilterOutlined,
|
||||
InfoCircleFilled,
|
||||
CheckCircleFilled,
|
||||
CalendarFilled,
|
||||
} from '@ant-design/icons'
|
||||
import { interviewstagenu } from '../../../util/requestURL'
|
||||
import { Link } from 'react-router-dom'
|
||||
import './index.css'
|
||||
const { TabPane } = Tabs
|
||||
const { CheckableTag } = Tag
|
||||
const tagsData = [
|
||||
'面试反馈',
|
||||
'安排面试',
|
||||
'通讯记录',
|
||||
'面试官拒绝面试',
|
||||
'其它',
|
||||
]
|
||||
|
||||
function Overview() {
|
||||
return (
|
||||
<div>总览</div>
|
||||
)
|
||||
export default class Overview extends Component {
|
||||
state = {
|
||||
selectedTags: [],
|
||||
datalist: [
|
||||
{
|
||||
title: 'Ant Design Title 1',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 2',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 3',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 4',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
PubSub.publish('headtitle', { headtitle: '总览' })
|
||||
interviewstagenu({ date: {} }).then(
|
||||
(res) => {
|
||||
this.setState({
|
||||
data: res.data,
|
||||
})
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.state
|
||||
|
||||
const onChange = (key) => {
|
||||
console.log(key)
|
||||
}
|
||||
|
||||
const handleChange = (tag, checked) => {
|
||||
const nextSelectedTags = checked
|
||||
? [...this.state.selectedTags, tag]
|
||||
: this.state.selectedTags.filter((t) => t != tag)
|
||||
console.log('You are interested in: ', tag, checked)
|
||||
this.setState({
|
||||
selectedTags: nextSelectedTags,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="Overview-box">
|
||||
<div className="Overview-top-box">
|
||||
<div>
|
||||
<Space size={10}>
|
||||
<Button className="allposition">
|
||||
<ApartmentOutlined /> 默认招聘流程
|
||||
<RightOutlined />
|
||||
</Button>
|
||||
|
||||
<Button className="allposition">
|
||||
<TeamOutlined /> 全部职位
|
||||
<RightOutlined />
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Overview-content-box">
|
||||
<div className="Overview-content-left-box">
|
||||
<div className="Overview-card-box">
|
||||
<div className="Overview-card-list-box">
|
||||
<div className="margin10">
|
||||
<TeamOutlined
|
||||
style={{
|
||||
fontSize: '22px',
|
||||
color: '#845ef7',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="Overview-card-list">
|
||||
<Link to={'/admin/candidate'}>
|
||||
<p>{data[1]}</p>
|
||||
<span>今日待筛选申请</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="xian"></div>
|
||||
<div className="Overview-card-list-box">
|
||||
<div className="margin10">
|
||||
<CalendarFilled
|
||||
style={{
|
||||
fontSize: '22px',
|
||||
color: '#22b8cf',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="Overview-card-list">
|
||||
<Link to={'/admin/interview'}>
|
||||
<p>{data.now}</p>
|
||||
<span>今日面试</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Overview-card-box2">
|
||||
<div className="Overview-card-top-box">
|
||||
<CheckCircleFilled /> <span>录用</span>
|
||||
</div>
|
||||
<div className="Overview-card-list-box2">
|
||||
<div className="Overview-card-list2">
|
||||
<Link to={'/admin/candidate'}>
|
||||
<p>{data.offer}</p>
|
||||
<span>待发送Offer</span>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="Overview-card-list2">
|
||||
<Link to={'/admin/candidate'}>
|
||||
<p>{data[6]}</p>
|
||||
<span>待入职</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Overview-card-box2">
|
||||
<div className="Overview-card-top-box">
|
||||
<CalendarOutlined /> <span>面试</span>
|
||||
</div>
|
||||
<div className="Overview-card-list-box2">
|
||||
<div className="color8 Overview-card-list2">
|
||||
<Link to={'/admin/interview'}>
|
||||
<p>0</p>
|
||||
<span>待面试</span>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="Overview-card-list2">
|
||||
<Link to={'/admin/interview'}>
|
||||
<p>0</p>
|
||||
<span>待反馈</span>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="Overview-card-list2">
|
||||
<Link to={'/admin/candidate'}>
|
||||
<p>0</p>
|
||||
<span>待处理</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="Overview-content-right-box">
|
||||
<div className="Overview-content-right-top-box">
|
||||
<div>重要事项</div>
|
||||
<div className="allsign color4">全部标记已读</div>
|
||||
</div>
|
||||
|
||||
<div className="Overview-tab-box">
|
||||
<Tabs defaultActiveKey="4" onChange={onChange}>
|
||||
<TabPane tab="@提醒" key="1">
|
||||
<Empty description="暂无数据" />
|
||||
</TabPane>
|
||||
<TabPane tab="招聘需求相关" key="2">
|
||||
<Empty description="暂无数据" />
|
||||
</TabPane>
|
||||
<TabPane tab="职位相关" key="3">
|
||||
<Empty description="暂无数据" />
|
||||
</TabPane>
|
||||
<TabPane tab="面试相关" key="4">
|
||||
<div>
|
||||
{tagsData.map((tag) => (
|
||||
<CheckableTag
|
||||
key={tag}
|
||||
checked={
|
||||
this.state.selectedTags.indexOf(
|
||||
tag
|
||||
) > -1
|
||||
}
|
||||
onChange={(checked) =>
|
||||
handleChange(tag, checked)
|
||||
}
|
||||
>
|
||||
{tag}
|
||||
</CheckableTag>
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<Empty description="暂无数据" />
|
||||
{/* <List
|
||||
itemLayout="horizontal"
|
||||
dataSource={this.state.datalist}
|
||||
renderItem={(item) => (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={
|
||||
<Avatar src="https://joeschmoe.io/api/v1/random" />
|
||||
}
|
||||
title={
|
||||
<a href="https://ant.design">
|
||||
{item.title}
|
||||
</a>
|
||||
}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/> */}
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="Offer相关" key="5">
|
||||
<Empty description="暂无数据" />
|
||||
</TabPane>
|
||||
<TabPane tab="推荐相关" key="6">
|
||||
<Empty description="暂无数据" />
|
||||
</TabPane>
|
||||
<TabPane tab="其他" key="7">
|
||||
<Empty description="暂无数据" />
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Overview
|
@ -1,17 +1,19 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Table, } from 'antd'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Table, message} from 'antd'
|
||||
import { getjob } from '../../../../util/requestURL'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import './index.css'
|
||||
const columns = [
|
||||
{
|
||||
title: '基本资料',
|
||||
dataIndex: 'basicdata',
|
||||
dataIndex: 'job_name',
|
||||
render: (text, record, index) => (
|
||||
<div className='basicdata-box'>
|
||||
<p className='basicdata-post'>
|
||||
{text.post}
|
||||
<span>({text.id})</span>
|
||||
{record.job_name}
|
||||
<span>({record.key})</span>
|
||||
</p>
|
||||
<p className='basicdata-des'> {text.des} </p>
|
||||
<p className='basicdata-des'> {record.job_sector} </p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@ -19,97 +21,91 @@ const columns = [
|
||||
title: '招聘负责人',
|
||||
dataIndex: 'principal',
|
||||
render: (text, record, index) => (
|
||||
<p className='font-size12 color1'>{text}</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '招聘渠道',
|
||||
dataIndex: 'channel',
|
||||
render: (text, record, index) => (
|
||||
// console.log(text)
|
||||
text.map((item,key)=>{
|
||||
return <span key={key} className='font-size12 color1 '>{item}</span>
|
||||
})
|
||||
<p className='font-size12 color1'>{text[0]['name']}</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '职位来源',
|
||||
dataIndex: 'source',
|
||||
render: (text, record, index) => (
|
||||
<p className='font-size12 color1'>{text}</p>
|
||||
<p className='font-size12 color1'>手动添加</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '候选人总数',
|
||||
dataIndex: 'candidatenum',
|
||||
dataIndex: 'hou_num',
|
||||
render: (text, record, index) => (
|
||||
<p className='font-size12 color1'>{text}</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '入职人数',
|
||||
dataIndex: 'inductionnum',
|
||||
dataIndex: 'now_job_num',
|
||||
render: (text, record, index) => (
|
||||
<p className='font-size12 color1'>{text}</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '招聘人数',
|
||||
dataIndex: 'recruitingnumbers',
|
||||
dataIndex: 'job_num',
|
||||
render: (text, record, index) => (
|
||||
<p className='font-size12 color1'>{text}</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '候选人满意度',
|
||||
dataIndex: 'satisfaction',
|
||||
render: (text, record, index) => (
|
||||
<div className='satisfaction-box'>
|
||||
<p className='font-size12 color1'> <span className='font-size14 color3'>{text.satisfaction}</span>/5</p>
|
||||
<p className='font-size12 color2'>{text.des}条评价</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
}
|
||||
]
|
||||
const data = []
|
||||
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
data.push({
|
||||
key: i,
|
||||
basicdata: {
|
||||
post: '高级游戏测试工程师',
|
||||
id: 'MJ0000005',
|
||||
des: '海外其他·技术部',
|
||||
},
|
||||
principal: '张三',
|
||||
channel: ['BOSS'],
|
||||
source: '手动添加',
|
||||
candidatenum: '13',
|
||||
inductionnum: '0',
|
||||
recruitingnumbers: '3',
|
||||
satisfaction: { satisfaction: 0, des: 0 },
|
||||
})
|
||||
}
|
||||
|
||||
const Inrecruitment = () => {
|
||||
const Inrecruitment = (props) => {
|
||||
const navigate = useNavigate()
|
||||
const [hasData, setHasData] = useState(true)
|
||||
|
||||
const [data,setdata] = useState([])
|
||||
const [loading,setloading] = useState(false)
|
||||
|
||||
const tableColumns = columns.map((item) => ({ ...item }))
|
||||
console.log(tableColumns)
|
||||
const tableProps = {
|
||||
showHeader: true,
|
||||
rowSelection: true,
|
||||
Size: 'Small',
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
// console.log('aaaaa',props.data)
|
||||
setloading(true)
|
||||
postgender()
|
||||
|
||||
},[props.data])
|
||||
|
||||
const postgender = ()=>{
|
||||
getjob(props.data).then(
|
||||
(res) => {
|
||||
setloading(false)
|
||||
setdata(res.data.job)
|
||||
props.handelnum(res)
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='Inrecruitment'>
|
||||
<Table
|
||||
{...tableProps}
|
||||
columns={tableColumns}
|
||||
loading={loading}
|
||||
dataSource={hasData ? data : []}
|
||||
pagination={false}
|
||||
onRow={record=>{
|
||||
return {
|
||||
onClick:(event)=>{
|
||||
// console.log(record)
|
||||
navigate('/admin/position/addposition/'+record.key)
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Inrecruitment
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
.Position-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
/* height: 100%; */
|
||||
}
|
||||
.Position-left-box {
|
||||
width: 250px;
|
||||
|
@ -1,130 +1,204 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom'
|
||||
import { Input, Space, Select, Button } from 'antd'
|
||||
import { Input, Space, Select, Button, message } from 'antd'
|
||||
import { getjob, getsection, getname } from '../../../util/requestURL'
|
||||
import Inrecruitment from './Inrecruitment'
|
||||
import PubSub from 'pubsub-js'
|
||||
import './index.css'
|
||||
const { Search } = Input
|
||||
const { Option } = Select
|
||||
const { Option, OptGroup } = Select
|
||||
|
||||
export default function Position() {
|
||||
const [onmenu, setonmenu] = useState(true)
|
||||
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const handelSwitchNav = (e, path) => {
|
||||
navigate(path)
|
||||
setonmenu((onmenu) => !onmenu)
|
||||
export default class Position extends Component {
|
||||
state = {
|
||||
onmenu: true,
|
||||
gatdata: { state: true, job_name: '', job_id: '', principal: [] },
|
||||
section: [],
|
||||
responsible: [],
|
||||
end_num: 0,
|
||||
start_num: 0,
|
||||
}
|
||||
|
||||
const onSearch = (value) => {
|
||||
console.log(value)
|
||||
componentDidMount() {
|
||||
getsection().then(
|
||||
(res) => {
|
||||
this.setState((state, props) => {
|
||||
return {
|
||||
section: res.data,
|
||||
}
|
||||
})
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
getname().then(
|
||||
(res) => {
|
||||
this.setState((state, props) => {
|
||||
return {
|
||||
responsible: res.data,
|
||||
}
|
||||
})
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
|
||||
// getjob(this.state.gatdata).then(
|
||||
// (res) => {
|
||||
// this.setState({
|
||||
// start_num: res.data.start_num,
|
||||
// end_num: res.data.end_num
|
||||
// })
|
||||
// },
|
||||
// (error) => {
|
||||
// message.error('网络加载错误,请稍后再试')
|
||||
// }
|
||||
// )
|
||||
|
||||
PubSub.publish('headtitle', { headtitle: '职位管理' })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handelSwitchNav = (e, state) => {
|
||||
// console.log(e,state)
|
||||
const newGatdata = this.state.gatdata
|
||||
this.setState({
|
||||
onmenu: state,
|
||||
gatdata: { ...newGatdata, state },
|
||||
})
|
||||
}
|
||||
|
||||
if (location.pathname.indexOf('Endrecruitment') >= 0) {
|
||||
setonmenu((onmenu) => false)
|
||||
onSearch = (e) => {
|
||||
// console.log(e.target.value)
|
||||
const newGatdata = this.state.gatdata
|
||||
this.setState((state, props) => {
|
||||
return {
|
||||
gatdata: { ...newGatdata, job_name: e.target.value },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
seleOnChange = (value, type) => {
|
||||
const newGatdata = this.state.gatdata
|
||||
if (type == 'job_id') {
|
||||
var arr = value
|
||||
} else {
|
||||
setonmenu((onmenu) => true)
|
||||
var arr = []
|
||||
arr.push({user_id:value})
|
||||
}
|
||||
}, [location.pathname])
|
||||
return (
|
||||
<div className="Position-box">
|
||||
<div className="Position-left-box">
|
||||
<div className="Position-menu-box">
|
||||
<div
|
||||
className={onmenu ? 'on-menu-box' : ''}
|
||||
onClick={(e) => handelSwitchNav(e, '/admin/position')}
|
||||
>
|
||||
{/* <Link to="/admin/position"> */}
|
||||
<p>1</p>
|
||||
<span>招聘中职位</span>
|
||||
{/* </Link> */}
|
||||
</div>
|
||||
<div
|
||||
className={onmenu ? '' : 'on-menu-box'}
|
||||
onClick={(e) =>
|
||||
handelSwitchNav(e, '/admin/position/Endrecruitment')
|
||||
}
|
||||
>
|
||||
{/* <Link to="/admin/position/Endrecruitment"> */}
|
||||
<p>2</p>
|
||||
<span>已关闭职位</span>
|
||||
{/* </Link> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="screen-form-box">
|
||||
<h4>职位信息</h4>
|
||||
<p className="title">职位名称筛选</p>
|
||||
<Space direction="vertical">
|
||||
<Search
|
||||
placeholder="根据职位名称或职位编码搜索"
|
||||
onSearch={onSearch}
|
||||
style={{
|
||||
width: 219,
|
||||
this.setState((state, props) => {
|
||||
return {
|
||||
gatdata: { ...newGatdata, [type]: arr },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
// const location = useLocation()
|
||||
const { onmenu, gatdata, section, responsible } = this.state
|
||||
return (
|
||||
<div className="Position-box">
|
||||
<div className="Position-left-box">
|
||||
<div className="Position-menu-box">
|
||||
<div
|
||||
className={onmenu ? 'on-menu-box' : ''}
|
||||
onClick={(e) => this.handelSwitchNav(e, true)}
|
||||
>
|
||||
<p>{this.state.start_num}</p>
|
||||
<span>招聘中职位</span>
|
||||
</div>
|
||||
<div
|
||||
className={onmenu ? '' : 'on-menu-box'}
|
||||
onClick={(e) => this.handelSwitchNav(e, false)}
|
||||
>
|
||||
<p>{this.state.end_num}</p>
|
||||
<span>已关闭职位</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="screen-form-box">
|
||||
<h4>职位信息</h4>
|
||||
<p className="title">职位名称筛选</p>
|
||||
<Space direction="vertical">
|
||||
<Search
|
||||
placeholder="根据职位名称或职位编码搜索"
|
||||
onChange={this.onSearch}
|
||||
style={{
|
||||
width: 219,
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
<p className="title">职位部门筛选</p>
|
||||
<Select
|
||||
style={{ width: 219 }}
|
||||
showSearch
|
||||
defaultValue=""
|
||||
optionFilterProp="children"
|
||||
onChange={(e) => {
|
||||
this.seleOnChange(e, 'job_id')
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
<p className="title">职位部门筛选</p>
|
||||
<Select
|
||||
style={{ width: 219 }}
|
||||
showSearch
|
||||
defaultValue="all"
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) =>
|
||||
option.children
|
||||
.toLowerCase()
|
||||
.includes(input.toLowerCase())
|
||||
}
|
||||
>
|
||||
<Option value="all">全部负责人</Option>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
<Option value="tom">Tom</Option>
|
||||
</Select>
|
||||
<p className="title">渠道筛选</p>
|
||||
<Select
|
||||
style={{ width: 219 }}
|
||||
showSearch
|
||||
defaultValue="all"
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) =>
|
||||
option.children
|
||||
.toLowerCase()
|
||||
.includes(input.toLowerCase())
|
||||
}
|
||||
>
|
||||
<Option value="all">全部负责人</Option>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
<Option value="tom">Tom</Option>
|
||||
</Select>
|
||||
<p className="title">负责人筛选</p>
|
||||
<Select
|
||||
style={{ width: 219 }}
|
||||
showSearch
|
||||
defaultValue="all"
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) =>
|
||||
option.children
|
||||
.toLowerCase()
|
||||
.includes(input.toLowerCase())
|
||||
}
|
||||
>
|
||||
<Option value="all">全部负责人</Option>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
<Option value="tom">Tom</Option>
|
||||
</Select>
|
||||
>
|
||||
<Option value="">全部</Option>
|
||||
{section.map((item, key) => {
|
||||
return (
|
||||
<OptGroup label={item.name} key={key}>
|
||||
{item['position'].map((items, keys) => {
|
||||
return (
|
||||
<Option
|
||||
value={items.job_id}
|
||||
key={items.job_id}
|
||||
>
|
||||
{items.job_name}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</OptGroup>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
<p className="title">负责人筛选</p>
|
||||
<Select
|
||||
style={{ width: 219 }}
|
||||
showSearch
|
||||
defaultValue=""
|
||||
optionFilterProp="children"
|
||||
onChange={(e) => {
|
||||
this.seleOnChange(e, 'principal')
|
||||
}}
|
||||
>
|
||||
<Option value="">全部负责人</Option>
|
||||
{responsible.map((item, key) => {
|
||||
return item.rank == 1 ? (
|
||||
<Option value={item.user_id} key={item.user_id}>
|
||||
{item.name}
|
||||
</Option>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
|
||||
<Button className='setfilteritem' block>设置筛选项</Button>
|
||||
<Button className="setfilteritem" block>
|
||||
设置筛选项
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Position-right-box">
|
||||
{/* <Outlet data={gatdata}/> */}
|
||||
<Inrecruitment
|
||||
data={gatdata}
|
||||
handelnum={(res) => {
|
||||
// console.log(res)
|
||||
this.setState({
|
||||
start_num: res.data.start_num,
|
||||
end_num: res.data.end_num,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Position-right-box">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
19
src/pages/admin/Report_forms/AddUser/index.css
Normal file
19
src/pages/admin/Report_forms/AddUser/index.css
Normal file
@ -0,0 +1,19 @@
|
||||
.adduser-box .ant-tabs{
|
||||
width: 100%;
|
||||
}
|
||||
.adduser-list-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 0px;
|
||||
}
|
||||
.adduser-list-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.adduser-list-left p {margin: 0;}
|
||||
.name { font-size: 13px; height: 18px; }
|
||||
.mail { font-size: 12px; color: #8c8e93; height: 18px; }
|
||||
.right { font-size: 12px; color: #8c8e93; height: 18px; }
|
||||
.adduser-info-box { margin-left: 8px; }
|
||||
.right-box { font-size: 12px; color: #8c8e93; }
|
56
src/pages/admin/Report_forms/AddUser/index.jsx
Normal file
56
src/pages/admin/Report_forms/AddUser/index.jsx
Normal file
@ -0,0 +1,56 @@
|
||||
import React from 'react'
|
||||
import { Tabs, Avatar } from 'antd'
|
||||
import './index.css'
|
||||
const { TabPane } = Tabs
|
||||
|
||||
export default function AddUser() {
|
||||
const onChange = (key) => {
|
||||
console.log(key)
|
||||
}
|
||||
return (
|
||||
<div className="adduser-box">
|
||||
<Tabs defaultActiveKey="1" onChange={onChange}>
|
||||
<TabPane tab="用户" key="1">
|
||||
<div className="adduser-list-box">
|
||||
<div className="adduser-list-left">
|
||||
<Avatar
|
||||
style={{
|
||||
backgroundColor: '#319dff',
|
||||
}}
|
||||
>
|
||||
吴
|
||||
</Avatar>
|
||||
<div className="adduser-info-box">
|
||||
<p className="name">吴操</p>
|
||||
<p className="mail">xxxxxxx.com</p>
|
||||
<p className="right">超级管理员</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="right-box">所有者</div>
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="角色" key="2">
|
||||
<div className="adduser-list-box">
|
||||
<div className="adduser-list-left">
|
||||
<Avatar
|
||||
style={{
|
||||
backgroundColor: '#319dff',
|
||||
}}
|
||||
>
|
||||
吴
|
||||
</Avatar>
|
||||
<div className="adduser-info-box">
|
||||
<p className="name">吴操</p>
|
||||
<p className="mail">xxxxxxx.com</p>
|
||||
<p className="right">超级管理员</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="right-box">所有者</div>
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
25
src/pages/admin/Report_forms/Kanbandetails/index.css
Normal file
25
src/pages/admin/Report_forms/Kanbandetails/index.css
Normal file
@ -0,0 +1,25 @@
|
||||
.Kanbandetails-box {
|
||||
min-height: calc(100vh - 64px);
|
||||
background-color: #fff;
|
||||
}
|
||||
.Kanbandetails-top-box {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
.Kanbandetails-title-box {
|
||||
margin: 16px 24px;
|
||||
}
|
||||
.Kanbandetails-title-box .Kanbandetails-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #312b2e;
|
||||
}
|
||||
.Kanbandetails-title-box p {
|
||||
font-size: 12px;
|
||||
color: #75777d;
|
||||
}
|
||||
.Kanbandetails-actionbar-box {
|
||||
margin: 16px 24px;
|
||||
}
|
||||
.Kanbandetails-table-box {
|
||||
margin: 16px 24px;
|
||||
}
|
425
src/pages/admin/Report_forms/Kanbandetails/index.jsx
Normal file
425
src/pages/admin/Report_forms/Kanbandetails/index.jsx
Normal file
@ -0,0 +1,425 @@
|
||||
import React, { Component } from 'react'
|
||||
import PubSub from 'pubsub-js'
|
||||
import { Button, Table, DatePicker, message, Empty } from 'antd'
|
||||
import request from '../../../../util/request'
|
||||
import {
|
||||
LeftOutlined,
|
||||
MoreOutlined,
|
||||
MailOutlined,
|
||||
TeamOutlined,
|
||||
CloudDownloadOutlined,
|
||||
EditOutlined,
|
||||
ArrowsAltOutlined,
|
||||
} from '@ant-design/icons'
|
||||
|
||||
//rcharts统计图
|
||||
import 'echarts/lib/chart/line'
|
||||
import 'echarts/lib/chart/pie'
|
||||
import 'echarts/lib/chart/bar'
|
||||
import 'echarts/lib/component/tooltip'
|
||||
import 'echarts/lib/component/title'
|
||||
import 'echarts/lib/component/legend'
|
||||
import 'echarts/lib/component/markPoint'
|
||||
import ReactEcharts from 'echarts-for-react'
|
||||
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import './index.css'
|
||||
const { RangePicker } = DatePicker
|
||||
const dateFormat = 'YYYY/MM/DD'
|
||||
|
||||
export default class Kanbandetails extends Component {
|
||||
state = {
|
||||
data: {
|
||||
table_data: {},
|
||||
},
|
||||
time: [
|
||||
moment((Math.round(new Date() / 1000) - 7 * 86400) * 1000).format('YYYY-MM-DD'),
|
||||
moment(Math.round(new Date() / 1000) * 1000).format('YYYY-MM-DD'),
|
||||
],
|
||||
timevalue: [
|
||||
moment(
|
||||
moment((Math.round(new Date() / 1000) - 7 * 86400) * 1000).format(
|
||||
'YYYY-MM-DD'
|
||||
),
|
||||
dateFormat
|
||||
),
|
||||
moment(
|
||||
moment(Math.round(new Date() / 1000) * 1000).format(
|
||||
'YYYY-MM-DD'
|
||||
),
|
||||
dateFormat
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const urlParams = new URL(window.location.href)
|
||||
const pathname = urlParams.hash
|
||||
const pathnameArr = pathname.split('/')
|
||||
const url = pathnameArr[pathnameArr.length - 2] //获取id
|
||||
const tableid = pathnameArr[pathnameArr.length - 1] //获取id
|
||||
|
||||
PubSub.publish('headtitle', { headtitle: '报表中心' })
|
||||
this.setState(
|
||||
{
|
||||
url,
|
||||
tableid,
|
||||
},
|
||||
() => {
|
||||
this.postdata()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
postdata() {
|
||||
const { url, tableid, time } = this.state
|
||||
request('post', 'forms/' + url, {
|
||||
data_in: { table_id: tableid },
|
||||
interview_query: {
|
||||
start_time: time[0],
|
||||
end_time: time[1],
|
||||
},
|
||||
}).then(
|
||||
(res) => {
|
||||
var dataList = res.data
|
||||
if(JSON.stringify(dataList) != "{}"){
|
||||
if (dataList['table_data']['type'] === 'table' && dataList['table_data']['size'] != "small") {
|
||||
var dataSource = this.handeldataSource(dataList['data'])
|
||||
const columns = this.handelcolumns(dataList['data'])
|
||||
dataList['table_data']['dataSource'] = dataSource
|
||||
dataList['table_data']['columns'] = columns
|
||||
}
|
||||
}
|
||||
console.log(dataList)
|
||||
this.setState({
|
||||
data: dataList,
|
||||
})
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handelback() {
|
||||
window.history.back()
|
||||
}
|
||||
|
||||
getOption = (type, data) => {
|
||||
if (type === 'line') {
|
||||
var seriesData = []
|
||||
var xAxisData = []
|
||||
|
||||
var datalist = {}
|
||||
|
||||
for (let i in data) {
|
||||
for (let j in data[i]) {
|
||||
if (!datalist[j]) {
|
||||
datalist[j] = []
|
||||
}
|
||||
datalist[j].push(data[i][j])
|
||||
}
|
||||
xAxisData.push(i)
|
||||
}
|
||||
for(let i in datalist){
|
||||
var arr = {
|
||||
name: i,
|
||||
type: 'line', //这块要定义type类型,柱形图是bar,饼图是pie
|
||||
data: datalist[i],
|
||||
}
|
||||
seriesData.push(arr)
|
||||
}
|
||||
|
||||
console.log(seriesData)
|
||||
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
xAxis: {
|
||||
data: xAxisData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: seriesData,
|
||||
}
|
||||
return option
|
||||
} else if (type === 'pie') {
|
||||
var datalist = []
|
||||
for (let i in data) {
|
||||
var arr = {}
|
||||
arr['value'] = data[i].length
|
||||
arr['name'] = i
|
||||
datalist.push(arr)
|
||||
}
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
left: 'center',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'inner',
|
||||
formatter: '{b}:{c}' + '\n\r' + '({d}%)',
|
||||
color:"#fff"
|
||||
}
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
},
|
||||
data: datalist,
|
||||
},
|
||||
],
|
||||
}
|
||||
return option
|
||||
} else if (type === 'bar') {
|
||||
var seriesData = []
|
||||
var xAxisData = []
|
||||
for (let i in data) {
|
||||
seriesData.push(data[i].length)
|
||||
xAxisData.push(i)
|
||||
}
|
||||
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: seriesData,
|
||||
type: 'bar',
|
||||
barWidth: '30px',
|
||||
},
|
||||
],
|
||||
}
|
||||
return option
|
||||
}else if (type === 'funnel') {
|
||||
var seriesData = []
|
||||
var xAxisData = []
|
||||
for (let i in data) {
|
||||
var arr = {
|
||||
value: data[i],
|
||||
name: i
|
||||
}
|
||||
seriesData.push(arr)
|
||||
}
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c}%',
|
||||
},
|
||||
legend: {
|
||||
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order'],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Funnel',
|
||||
type: 'funnel',
|
||||
left: '10%',
|
||||
top: 60,
|
||||
bottom: 60,
|
||||
width: '80%',
|
||||
min: 0,
|
||||
max: 100,
|
||||
minSize: '50%',
|
||||
maxSize: '80%',
|
||||
sort: 'descending',
|
||||
gap: 2,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside',
|
||||
},
|
||||
labelLine: {
|
||||
length: 10,
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
type: 'solid',
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
borderColor: '#fff',
|
||||
borderWidth: 1,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
fontSize: 20,
|
||||
},
|
||||
},
|
||||
data: seriesData,
|
||||
},
|
||||
],
|
||||
}
|
||||
return option
|
||||
}
|
||||
}
|
||||
|
||||
handeldataSource = (data) => {
|
||||
// 给每行数据添加key
|
||||
const newdataSoure = data['data'].map((item, key) => {
|
||||
return { ...item, key }
|
||||
})
|
||||
return newdataSoure
|
||||
}
|
||||
|
||||
handelcolumns = (data) => {
|
||||
const newcolumns = []
|
||||
for (let i in data['level_list']) {
|
||||
var arr = {
|
||||
title: data['level_list'][i],
|
||||
dataIndex: i,
|
||||
key: i,
|
||||
}
|
||||
newcolumns.push(arr)
|
||||
}
|
||||
//首航浮动
|
||||
newcolumns[0]['fixed'] = 'left'
|
||||
return newcolumns
|
||||
}
|
||||
|
||||
handelexport = ()=>{
|
||||
const { url, tableid, time } = this.state
|
||||
request('ExportPost', 'forms/' + url, {
|
||||
data_in: { table_id: tableid },
|
||||
interview_query: {
|
||||
start_time: time[0],
|
||||
end_time: time[1],
|
||||
out_form: 'out'
|
||||
},
|
||||
name: this.state.data.table_data.title
|
||||
}).then(
|
||||
(res) => {
|
||||
console.log(res)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.state
|
||||
|
||||
return (
|
||||
<div className="Kanbandetails-box">
|
||||
<div className="Kanbandetails-top-box">
|
||||
<div className="Reportcenter-top-cz-box">
|
||||
<div className="cursor" onClick={this.handelback}>
|
||||
<LeftOutlined /> 返回
|
||||
</div>
|
||||
<div>
|
||||
<Button type="text" disabled>
|
||||
<EditOutlined />
|
||||
编辑
|
||||
</Button>
|
||||
<Button type="text" onClick={this.handelexport}>
|
||||
<CloudDownloadOutlined /> 导出
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<TeamOutlined />
|
||||
共享
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<MailOutlined />
|
||||
订阅
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<MoreOutlined /> 更多
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Kanbandetails-title-box">
|
||||
<div className="Kanbandetails-title">
|
||||
{data.table_data.title}
|
||||
</div>
|
||||
<p>最后更新时间{data.table_data.mode_time}</p>
|
||||
</div>
|
||||
|
||||
<div className="Kanbandetails-actionbar-box">
|
||||
<RangePicker
|
||||
value={this.state.timevalue}
|
||||
onChange={(dates, dateStrings) => {
|
||||
this.setState({
|
||||
time: dateStrings,
|
||||
timevalue: dates,
|
||||
},()=>{
|
||||
this.postdata()
|
||||
})
|
||||
}}
|
||||
locale={locale}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="Kanbandetails-table-box">
|
||||
{JSON.stringify(data) != '{}' ? (
|
||||
data.table_data.type === 'table' && data.table_data.size != "small" ? (
|
||||
<Table
|
||||
columns={data.table_data.columns}
|
||||
dataSource={data.table_data.dataSource}
|
||||
pagination={{ pageSize: 6 }}
|
||||
scroll={{
|
||||
x: 1600,
|
||||
y: '100vh - 212px ',
|
||||
}}
|
||||
/>
|
||||
) : data.table_data.type === 'echarts' ? (
|
||||
<ReactEcharts
|
||||
option={this.getOption(
|
||||
data.table_data.charts,
|
||||
data.data
|
||||
)}
|
||||
theme="Imooc"
|
||||
style={{
|
||||
height: '500px',
|
||||
}}
|
||||
/>
|
||||
) : data.table_data.size === "small"? (
|
||||
<div>
|
||||
<div className="card-small-box">
|
||||
<p className="title">
|
||||
{data.table_data.title}
|
||||
</p>
|
||||
<p className="num" >{ data.data? data.data.value : 0}</p>
|
||||
</div>
|
||||
</div>
|
||||
):''
|
||||
) : (
|
||||
<Empty description="暂无数据" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
0
src/pages/admin/Report_forms/Moveto/index.css
Normal file
0
src/pages/admin/Report_forms/Moveto/index.css
Normal file
49
src/pages/admin/Report_forms/Moveto/index.jsx
Normal file
49
src/pages/admin/Report_forms/Moveto/index.jsx
Normal file
@ -0,0 +1,49 @@
|
||||
import React from 'react'
|
||||
import { Select, Form, Input, Modal } from 'antd'
|
||||
const { Option } = Select
|
||||
export default function Moveto({ visible, onCreate, onCancel }) {
|
||||
const [form] = Form.useForm()
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="移动到"
|
||||
okText="Create"
|
||||
cancelText="Cancel"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
onCreate(values)
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="form_in_modal"
|
||||
initialValues={{}}
|
||||
>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="分组"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '标题必填!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
<Option value="Yiminghe">yiminghe</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
0
src/pages/admin/Report_forms/Rename/index.css
Normal file
0
src/pages/admin/Report_forms/Rename/index.css
Normal file
51
src/pages/admin/Report_forms/Rename/index.jsx
Normal file
51
src/pages/admin/Report_forms/Rename/index.jsx
Normal file
@ -0,0 +1,51 @@
|
||||
import { Button, Form, Input, Modal, Radio } from 'antd'
|
||||
import React, { useState } from 'react'
|
||||
const { TextArea } = Input;
|
||||
|
||||
export default function Rename({ visible, onCreate, onCancel }) {
|
||||
const [form] = Form.useForm()
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="重命名"
|
||||
okText="Create"
|
||||
cancelText="Cancel"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
onCreate(values)
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="form_in_modal"
|
||||
initialValues={{
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="标题"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '标题必填!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="describe" label="描述">
|
||||
<TextArea rows={4} placeholder='请输入描述,最多100字' />
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
54
src/pages/admin/Report_forms/Reportcenter/index.css
Normal file
54
src/pages/admin/Report_forms/Reportcenter/index.css
Normal file
@ -0,0 +1,54 @@
|
||||
.Reportcenter-top-box {
|
||||
background-color: #fff;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
.Reportcenter-top-cz-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.Reportcenter-table-overflow {
|
||||
width: 100%;
|
||||
height: calc(100vh - 180px);
|
||||
}
|
||||
|
||||
.Reportcenter-table-box {
|
||||
/* display: flex; */
|
||||
margin: 0px 0px 24px 0;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
.ant-card { margin-left: 24px; margin-top: 24px; border-radius: 4px; }
|
||||
.table-top-box { display: flex; justify-content: space-between; align-items: center; }
|
||||
.table-name { font-weight: bold; font-size: 16px; color: #312b2e; }
|
||||
.card-small-box { margin-top: 24px; }
|
||||
.card-small-box .title{
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #75777d;
|
||||
margin: 0;
|
||||
}
|
||||
.card-small-box .num {
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
color: #312b2e;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card-small-box2 {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #75777d;
|
||||
margin: 10px 0;
|
||||
height: 300px;
|
||||
}
|
||||
.Empty-box {
|
||||
height: 130px;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
508
src/pages/admin/Report_forms/Reportcenter/index.jsx
Normal file
508
src/pages/admin/Report_forms/Reportcenter/index.jsx
Normal file
@ -0,0 +1,508 @@
|
||||
import React, { Component } from 'react'
|
||||
import PubSub from 'pubsub-js'
|
||||
import { Button, Row, Col, Card, Table, DatePicker, message, Empty } from 'antd'
|
||||
import {
|
||||
LeftOutlined,
|
||||
MoreOutlined,
|
||||
MailOutlined,
|
||||
TeamOutlined,
|
||||
CloudDownloadOutlined,
|
||||
EditOutlined,
|
||||
ArrowsAltOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { findmodetables } from '../../../../util/requestURL'
|
||||
import request from '../../../../util/request'
|
||||
import moment from 'moment'
|
||||
//rcharts统计图
|
||||
import 'echarts/lib/chart/line'
|
||||
import 'echarts/lib/chart/pie'
|
||||
import 'echarts/lib/chart/bar'
|
||||
import 'echarts/lib/component/tooltip'
|
||||
import 'echarts/lib/component/title'
|
||||
import 'echarts/lib/component/legend'
|
||||
import 'echarts/lib/component/markPoint'
|
||||
import ReactEcharts from 'echarts-for-react'
|
||||
import 'moment/locale/zh-cn'
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN'
|
||||
import './index.css'
|
||||
const { RangePicker } = DatePicker
|
||||
const dateFormat = 'YYYY/MM/DD'
|
||||
|
||||
export default class Reportcenter extends Component {
|
||||
state = {
|
||||
time: [
|
||||
moment((Math.round(new Date() / 1000) - 7 * 86400) * 1000).format(
|
||||
'YYYY-MM-DD'
|
||||
),
|
||||
moment(Math.round(new Date() / 1000) * 1000).format('YYYY-MM-DD'),
|
||||
],
|
||||
timevalue: [
|
||||
moment(
|
||||
moment(
|
||||
(Math.round(new Date() / 1000) - 7 * 86400) * 1000
|
||||
).format('YYYY-MM-DD'),
|
||||
dateFormat
|
||||
),
|
||||
moment(
|
||||
moment(Math.round(new Date() / 1000) * 1000).format(
|
||||
'YYYY-MM-DD'
|
||||
),
|
||||
dateFormat
|
||||
),
|
||||
],
|
||||
data: [],
|
||||
id:''
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// echarts.registerTheme('Imooc',echartTheme);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const urlParams = new URL(window.location.href)
|
||||
const pathname = urlParams.hash
|
||||
const pathnameArr = pathname.split('/')
|
||||
const id = pathnameArr[pathnameArr.length - 1] //获取id
|
||||
let { time } = this.state
|
||||
this.setState({
|
||||
id: id
|
||||
},()=>{
|
||||
this.postData(id,time)
|
||||
})
|
||||
PubSub.publish('headtitle', { headtitle: '报表中心' })
|
||||
const { data } = this.state
|
||||
}
|
||||
|
||||
postData=(id,time)=>{
|
||||
findmodetables({ mode_id: id, update_data: {} }).then(
|
||||
(res) => {
|
||||
let dataList = res.data
|
||||
console.log(dataList)
|
||||
for (let i in dataList) {
|
||||
request('post', 'forms/' + res.data[i]['url'], {
|
||||
data_in: { table_id: dataList[i]['table_id'] },
|
||||
interview_query: {
|
||||
start_time: time[0],
|
||||
end_time: time[1],
|
||||
},
|
||||
}).then(
|
||||
(res) => {
|
||||
dataList[i]['data'] = res.data.data
|
||||
if (dataList[i]['type'] === 'table' && dataList[i]['size'] != "small") {
|
||||
var dataSource = this.handeldataSource(
|
||||
dataList[i]['data']
|
||||
)
|
||||
const columns = this.handelcolumns(
|
||||
dataList[i]['data']
|
||||
)
|
||||
dataList[i]['dataSource'] = dataSource
|
||||
dataList[i]['columns'] = columns
|
||||
}
|
||||
|
||||
this.setState({
|
||||
data: dataList,
|
||||
})
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handelback() {
|
||||
window.history.back()
|
||||
}
|
||||
|
||||
getOption = (type, data) => {
|
||||
if (type === 'line') {
|
||||
var seriesData = []
|
||||
var xAxisData = []
|
||||
|
||||
var datalist = {}
|
||||
|
||||
for (let i in data) {
|
||||
for (let j in data[i]) {
|
||||
if (!datalist[j]) {
|
||||
datalist[j] = []
|
||||
}
|
||||
datalist[j].push(data[i][j])
|
||||
}
|
||||
xAxisData.push(i)
|
||||
}
|
||||
for(let i in datalist){
|
||||
var arr = {
|
||||
name: i,
|
||||
type: 'line', //这块要定义type类型,柱形图是bar,饼图是pie
|
||||
data: datalist[i],
|
||||
}
|
||||
seriesData.push(arr)
|
||||
}
|
||||
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
xAxis: {
|
||||
data: xAxisData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: seriesData,
|
||||
}
|
||||
return option
|
||||
} else if (type === 'pie') {
|
||||
var datalist = []
|
||||
for (let i in data) {
|
||||
var arr = {}
|
||||
arr['value'] = data[i].length
|
||||
arr['name'] = i
|
||||
datalist.push(arr)
|
||||
}
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
left: 'center',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
label: {
|
||||
// show: false,
|
||||
// position: 'center',
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'inner',
|
||||
formatter: '{b}:{c}' + '\n\r' + '({d}%)',
|
||||
color: '#fff',
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
},
|
||||
data: datalist,
|
||||
},
|
||||
],
|
||||
}
|
||||
return option
|
||||
} else if (type === 'bar') {
|
||||
var seriesData = []
|
||||
var xAxisData = []
|
||||
for (let i in data) {
|
||||
seriesData.push(data[i].length)
|
||||
xAxisData.push(i)
|
||||
}
|
||||
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: seriesData,
|
||||
type: 'bar',
|
||||
barWidth: '30px',
|
||||
},
|
||||
],
|
||||
}
|
||||
return option
|
||||
} else if (type === 'funnel') {
|
||||
var seriesData = []
|
||||
var xAxisData = []
|
||||
for (let i in data) {
|
||||
var arr = {
|
||||
value: data[i],
|
||||
name: i
|
||||
}
|
||||
seriesData.push(arr)
|
||||
}
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c}%',
|
||||
},
|
||||
legend: {
|
||||
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order'],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Funnel',
|
||||
type: 'funnel',
|
||||
left: '10%',
|
||||
top: 60,
|
||||
bottom: 60,
|
||||
width: '80%',
|
||||
min: 0,
|
||||
max: 100,
|
||||
minSize: '50%',
|
||||
maxSize: '80%',
|
||||
sort: 'descending',
|
||||
gap: 2,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside',
|
||||
},
|
||||
labelLine: {
|
||||
length: 10,
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
type: 'solid',
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
borderColor: '#fff',
|
||||
borderWidth: 1,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
fontSize: 20,
|
||||
},
|
||||
},
|
||||
data: seriesData,
|
||||
},
|
||||
],
|
||||
}
|
||||
return option
|
||||
}
|
||||
}
|
||||
|
||||
handeldataSource = (data) => {
|
||||
// 给每行数据添加key
|
||||
|
||||
const newdataSoure = data['data'].map((item, key) => {
|
||||
return { ...item, key }
|
||||
})
|
||||
|
||||
return newdataSoure
|
||||
}
|
||||
|
||||
handelcolumns = (data) => {
|
||||
// const newcolumns = data['level_list'].map((item,key)=>{
|
||||
// return { title: item, dataIndex: key,key }
|
||||
// })
|
||||
|
||||
const newcolumns = []
|
||||
for (let i in data['level_list']) {
|
||||
var arr = {
|
||||
title: data['level_list'][i],
|
||||
dataIndex: i,
|
||||
key: i,
|
||||
}
|
||||
newcolumns.push(arr)
|
||||
}
|
||||
//首航浮动
|
||||
newcolumns[0]['fixed'] = 'left'
|
||||
return newcolumns
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.state
|
||||
|
||||
return (
|
||||
<div className="Reportcenter-box">
|
||||
<div className="Reportcenter-top-box">
|
||||
<div className="Reportcenter-top-cz-box">
|
||||
<div className="cursor" onClick={this.handelback}>
|
||||
<LeftOutlined /> 返回
|
||||
</div>
|
||||
<div>
|
||||
<Button type="text" disabled>
|
||||
<EditOutlined />
|
||||
编辑
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<CloudDownloadOutlined /> 导出
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<TeamOutlined />
|
||||
共享
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<MailOutlined />
|
||||
订阅
|
||||
</Button>
|
||||
<Button type="text" disabled>
|
||||
<MoreOutlined /> 更多
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="margintop20">
|
||||
<RangePicker
|
||||
locale={locale}
|
||||
value={this.state.timevalue}
|
||||
onChange={(dates, dateStrings) => {
|
||||
this.setState({
|
||||
time: dateStrings,
|
||||
timevalue: dates,
|
||||
},()=>{
|
||||
this.postData(this.state.id, dateStrings)
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="Reportcenter-table-overflow">
|
||||
<div className="Reportcenter-table-box">
|
||||
<Row justify="start">
|
||||
{data.map((item, key) => {
|
||||
return item.size == 'small' ? (
|
||||
<Col span={6} key={item.table_id}>
|
||||
<Card>
|
||||
<div className="table-top-box">
|
||||
<Link className="table-name" to={`/admin/reportforms/Kanbandetails/${item.url}/${item.table_id}`}>
|
||||
{item.title}
|
||||
</Link>
|
||||
<Link
|
||||
className="cursor"
|
||||
to={`/admin/reportforms/Kanbandetails/${item.url}/${item.table_id}`}
|
||||
>
|
||||
<ArrowsAltOutlined />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="card-small-box">
|
||||
<p className="title">
|
||||
{item.title}
|
||||
</p>
|
||||
<p className="num" >{ item.data? item.data.value : 0}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
) : item.size == 'in' ? (
|
||||
<Col span={12} key={item.table_id}>
|
||||
<Card>
|
||||
<div className="table-top-box">
|
||||
<Link className="table-name" to={`/admin/reportforms/Kanbandetails/${item.url}/${item.table_id}`}>
|
||||
{item.title}
|
||||
</Link>
|
||||
<Link
|
||||
className="cursor"
|
||||
to={`/admin/reportforms/Kanbandetails/${item.url}/${item.table_id}`}
|
||||
>
|
||||
<ArrowsAltOutlined />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="card-small-box2">
|
||||
{item.type === 'echarts' ? (
|
||||
JSON.stringify(item.data) !=
|
||||
'{}' ? (
|
||||
<ReactEcharts
|
||||
option={this.getOption(
|
||||
item.charts,
|
||||
item.data
|
||||
)}
|
||||
theme="Imooc"
|
||||
style={{
|
||||
height: '350px',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="Empty-box">
|
||||
<Empty
|
||||
description={
|
||||
'暂无数据'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<Table
|
||||
dataSource={
|
||||
item.dataSource
|
||||
}
|
||||
columns={item.columns}
|
||||
scroll={{
|
||||
x: 1600,
|
||||
y: 250,
|
||||
}}
|
||||
pagination={false}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
) : (
|
||||
<Col span={24} key={item.table_id}>
|
||||
<Card>
|
||||
<div className="table-top-box">
|
||||
<div className="table-name">
|
||||
{item.title}
|
||||
</div>
|
||||
<Link
|
||||
className="cursor"
|
||||
to={`/admin/reportforms/Kanbandetails/${item.url}/${item.table_id}`}
|
||||
>
|
||||
<ArrowsAltOutlined />
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className="card-small-box2"
|
||||
id={item.table_id}
|
||||
>
|
||||
{item.type === 'echarts' ? (
|
||||
<ReactEcharts
|
||||
option={this.getOption(
|
||||
item.charts,
|
||||
item.data
|
||||
)}
|
||||
theme="Imooc"
|
||||
style={{
|
||||
height: '350px',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
// <Table
|
||||
// dataSource={
|
||||
// item.dataSource
|
||||
// }
|
||||
// columns={item.columns}
|
||||
// scroll={{
|
||||
// x: 1600,
|
||||
// y: 250,
|
||||
// }}
|
||||
// pagination={false}
|
||||
// />
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
72
src/pages/admin/Report_forms/index.css
Normal file
72
src/pages/admin/Report_forms/index.css
Normal file
@ -0,0 +1,72 @@
|
||||
.Reportforms-top-box {
|
||||
width: 100%;
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.Reportforms-top-title {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.Reportforms-top-action {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #625f69;
|
||||
}
|
||||
.Reportforms-top-action button { margin-left: 8px; }
|
||||
|
||||
.Reportforms-list-box {
|
||||
margin: 16px 40px;
|
||||
display: grid;
|
||||
grid-template-columns: 340px 340px 340px 340px 340px;
|
||||
grid-row-gap:16px;
|
||||
grid-column-gap:16px;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
width: 340px;
|
||||
background-color: #fff;
|
||||
padding: 20px 0px 0 0px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 6px 0px rgba(000, 000, 000, 0.2);
|
||||
}
|
||||
|
||||
.card-top-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.card-top-box div {
|
||||
cursor: pointer;
|
||||
}
|
||||
.card-top-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #312b2e;
|
||||
}
|
||||
.card-bottom-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
border-top: 1px solid #f6f6f5;
|
||||
color: #8c8e93;
|
||||
font-size: 13px;
|
||||
}
|
||||
.card-bottom-box div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.card-name-box{
|
||||
margin-left: 6px;
|
||||
}
|
||||
.card-time {
|
||||
margin-top: 35px;
|
||||
color: #8c8e93;
|
||||
font-size: 13px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
@ -1,9 +1,255 @@
|
||||
import React from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import PubSub, { publish } from 'pubsub-js'
|
||||
import { Button, Avatar, Dropdown, Menu, Drawer, Modal, message } from 'antd'
|
||||
import { findmode } from '../../../util/requestURL'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Rename from './Rename'
|
||||
import Moveto from './Moveto'
|
||||
import AddUser from './AddUser'
|
||||
import {
|
||||
PlusOutlined,
|
||||
MoreOutlined,
|
||||
TeamOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import './index.css'
|
||||
|
||||
function Report_forms() {
|
||||
return (
|
||||
<div>报表中心</div>
|
||||
)
|
||||
export default class Report_forms extends Component {
|
||||
state = {
|
||||
Renamevisible: false,
|
||||
Movetovisible: false,
|
||||
AddUservisible: false,
|
||||
datalist:[]
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
PubSub.publish('headtitle', { headtitle: '报表分析' })
|
||||
|
||||
findmode({hr_uid:'16291104873568418', where: {}}).then(
|
||||
(res) => {
|
||||
console.log(res)
|
||||
this.setState({
|
||||
datalist: res.data
|
||||
})
|
||||
},
|
||||
(error) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
onVisibleChange = (e) => {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
onMovetoCreate = (e) => {
|
||||
this.setState({
|
||||
Movetovisible: false,
|
||||
})
|
||||
}
|
||||
|
||||
onRenameCreate = (e) => {
|
||||
this.setState({
|
||||
Renamevisible: false,
|
||||
})
|
||||
}
|
||||
|
||||
onmoveto = (e) => {
|
||||
this.setState({
|
||||
Movetovisible: true,
|
||||
})
|
||||
}
|
||||
|
||||
onrename = (e) => {
|
||||
this.setState({
|
||||
Renamevisible: true,
|
||||
})
|
||||
}
|
||||
|
||||
AddUseronClose = () => {
|
||||
this.setState({
|
||||
AddUservisible: false,
|
||||
})
|
||||
}
|
||||
|
||||
handelAddUser = () => {
|
||||
this.setState({
|
||||
AddUservisible: true,
|
||||
})
|
||||
}
|
||||
|
||||
handelDelTable = () => {
|
||||
console.log('点击删除')
|
||||
}
|
||||
|
||||
pushReportcenter = (id) => {
|
||||
// this.props.history.push(`/admin/reportforms/Reportcenter`,{id})
|
||||
// this.props.history.push
|
||||
console.log(this.props)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const {datalist} = this.state
|
||||
const menu = (
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
<a rel="noopener noreferrer" href="#">
|
||||
另存为
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: (
|
||||
<div onClick={() => this.onrename()}>重命名</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: (
|
||||
<div onClick={() => this.onmoveto()}>移动到</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: (
|
||||
<div className="color6" onClick={() => confirm()}>
|
||||
删除
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)
|
||||
|
||||
const confirm = () => {
|
||||
Modal.confirm({
|
||||
title: '删除',
|
||||
icon: <ExclamationCircleOutlined />,
|
||||
content: '确定删除当前看板',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
console.log('OK')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="Reportforms-box">
|
||||
<div className="Reportforms-top-box">
|
||||
<div className="Reportforms-top-title">报表中心</div>
|
||||
<div className="Reportforms-top-action">
|
||||
<div>
|
||||
legu报表中心旨在自动化的检索,分析各类指标情况;并进行可视化的展示。提高洞察力,帮助您做出更好的决策。
|
||||
</div>
|
||||
<div>
|
||||
<Button type="primary">
|
||||
{' '}
|
||||
<PlusOutlined /> 新建
|
||||
</Button>
|
||||
<Button>分组管理</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Reportforms-list-box">
|
||||
{
|
||||
datalist.map((item,key)=>{
|
||||
return (
|
||||
<div className="card-box" key={key}>
|
||||
<div className="card-top-box">
|
||||
<Link
|
||||
to={`/admin/reportforms/Reportcenter/${item.mode_id}`}
|
||||
className="card-top-title"
|
||||
onClick={() => this.pushReportcenter(item.mode_id)}
|
||||
>
|
||||
{item.mode_name}
|
||||
</Link>
|
||||
<div>
|
||||
<Dropdown
|
||||
overlay={menu}
|
||||
placement="bottom"
|
||||
onVisibleChange={(e) => {
|
||||
this.onVisibleChange('1')
|
||||
}}
|
||||
>
|
||||
<MoreOutlined
|
||||
style={{
|
||||
fontSize: '16px',
|
||||
color: '#5e5e5e',
|
||||
}}
|
||||
/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<p className="card-time">
|
||||
最近修改时间: {item.mode_time}
|
||||
</p>
|
||||
<div className="card-bottom-box">
|
||||
<div>
|
||||
<Avatar
|
||||
size="small"
|
||||
icon={item.hr_name.charAt(0)}
|
||||
style={{
|
||||
backgroundColor: '#319dff',
|
||||
}}
|
||||
/>
|
||||
<span className="card-name-box">
|
||||
{item.hrname} 所有
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="cursor"
|
||||
onClick={() => this.handelAddUser()}
|
||||
>
|
||||
<TeamOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<Rename
|
||||
visible={this.state.Renamevisible}
|
||||
onCreate={this.onRenameCreate}
|
||||
onCancel={() => {
|
||||
// setVisible(false)
|
||||
this.setState({
|
||||
Renamevisible: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
<Moveto
|
||||
visible={this.state.Movetovisible}
|
||||
onCreate={this.onMovetoCreate}
|
||||
onCancel={() => {
|
||||
// setVisible(false)
|
||||
this.setState({
|
||||
Movetovisible: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
<Drawer
|
||||
title="共享"
|
||||
placement="right"
|
||||
onClose={() => this.AddUseronClose()}
|
||||
visible={this.state.AddUservisible}
|
||||
>
|
||||
<AddUser />
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Report_forms
|
23
src/pages/admin/Resumescreen/index.css
Normal file
23
src/pages/admin/Resumescreen/index.css
Normal file
@ -0,0 +1,23 @@
|
||||
.Resumescreen-box {
|
||||
margin: 60px 230px;
|
||||
}
|
||||
.Resumescreen-list-data-box {
|
||||
background-color: #fff;
|
||||
min-height: 600px;
|
||||
}
|
||||
.Resumescreen-list-tab-box {
|
||||
margin: 0 30px;
|
||||
}
|
||||
.Resumescreen-list-tab-box .ant-tabs-tab-btn {
|
||||
color: #312b2e !important;
|
||||
}
|
||||
.Resumescreen-list-tab-box .num {
|
||||
font-size: 17px;
|
||||
}
|
||||
.Resumescreen-list-tab-box .ant-tabs { width: 100%; }
|
||||
.Resumescreen-list-table-box { margin: 0 30px; }
|
||||
.Resumescreen-list-data-box .CandidateTable-owner { width: 10%; }
|
||||
.Resumescreen-list-data-box .CandidateTable-list-box { align-items: center; }
|
||||
.Resumescreen-list-data-box .CandidateTable-info { margin-left: 0; }
|
||||
|
||||
|
415
src/pages/admin/Resumescreen/index.jsx
Normal file
415
src/pages/admin/Resumescreen/index.jsx
Normal file
@ -0,0 +1,415 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
Input,
|
||||
Space,
|
||||
Form,
|
||||
Select,
|
||||
Col,
|
||||
Row,
|
||||
Tabs,
|
||||
Table,
|
||||
Empty,
|
||||
Checkbox,
|
||||
Tag,
|
||||
Button,
|
||||
message,
|
||||
} from 'antd'
|
||||
import { AudioOutlined, ShoppingFilled, BankOutlined } from '@ant-design/icons'
|
||||
import PubSub from 'pubsub-js'
|
||||
import {
|
||||
getjob,
|
||||
interviewfind,
|
||||
interviewupdate,
|
||||
interviewmannernum,
|
||||
} from '../../../util/requestURL'
|
||||
import storageUtils from '../../../util/storageUtils'
|
||||
import InterviewerInfoPop from '../../../components/InterviewerInfoPop'
|
||||
import './index.css'
|
||||
const { Search } = Input
|
||||
const { Option } = Select
|
||||
|
||||
export default class Resumescreen extends Component {
|
||||
state = {
|
||||
getjoblist: {},
|
||||
data: [],
|
||||
name: '',
|
||||
job_id: '',
|
||||
hr_manner: 2,
|
||||
userInfo: storageUtils.getUser(),
|
||||
interviewerInfo: false,
|
||||
uid: 0
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
PubSub.publish('headtitle', { headtitle: '简历筛选' })
|
||||
getjob().then(
|
||||
(res) => {
|
||||
this.setState({
|
||||
getjoblist: res.data.job,
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
|
||||
this.Updatalist()
|
||||
}
|
||||
|
||||
Updatalist = () => {
|
||||
const { name, job_id, hr_manner, userInfo } = this.state
|
||||
interviewfind({
|
||||
interview_query: {
|
||||
interview_stage: 1,
|
||||
department: userInfo.user_id,
|
||||
name: name,
|
||||
job_id: job_id,
|
||||
hr_manner: hr_manner,
|
||||
},
|
||||
data_in: {},
|
||||
}).then(
|
||||
(res) => {
|
||||
this.setState({
|
||||
data: res.data,
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
|
||||
interviewmannernum({
|
||||
interview_query: {
|
||||
interview_stage: 1,
|
||||
department: userInfo.user_id,
|
||||
name: name,
|
||||
job_id: job_id
|
||||
},
|
||||
data_in: {},
|
||||
}).then(
|
||||
(res) => {
|
||||
console.log(res.data)
|
||||
this.setState({
|
||||
manner_2_num : res.data.manner_2_num,
|
||||
manner_01_num : res.data.manner_01_num
|
||||
})
|
||||
},
|
||||
(err) => {}
|
||||
)
|
||||
}
|
||||
onValuesChange = (e) => {
|
||||
// console.log(e)
|
||||
this.setState(e,()=>{
|
||||
this.Updatalist()
|
||||
})
|
||||
}
|
||||
|
||||
handeleditstate = (uid, hr_manner) => {
|
||||
interviewupdate({
|
||||
data_in: { hr_manner: hr_manner, interview_stage:2 },
|
||||
interview_query: { uid: uid },
|
||||
}).then(
|
||||
(res) => {
|
||||
if (res.msg === 'ok') {
|
||||
message.success('操作成功!')
|
||||
setTimeout(() => {
|
||||
this.Updatalist()
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handelonChange = (e) => {
|
||||
this.setState(
|
||||
{
|
||||
hr_manner: e,
|
||||
},
|
||||
() => {
|
||||
this.Updatalist()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handelCandidateClick = (uid) =>{
|
||||
console.log(uid)
|
||||
this.setState({
|
||||
interviewerInfo: true,
|
||||
uid : uid
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getjoblist, data, manner_2_num, manner_01_num } = this.state
|
||||
const onSearch = (value) => console.log(value)
|
||||
return (
|
||||
<div className="Resumescreen-box">
|
||||
<div className="">
|
||||
<Form
|
||||
layout="vertical"
|
||||
onValuesChange={this.onValuesChange}
|
||||
>
|
||||
<Row gutter={24}>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="候选人" name="name">
|
||||
<Search
|
||||
placeholder="请输入候选人姓名"
|
||||
onSearch={onSearch}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="应聘职位" name="job_id">
|
||||
<Select>
|
||||
<Option value="">全部职位</Option>
|
||||
{getjoblist.length > 0
|
||||
? getjoblist.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
value={item.key}
|
||||
key={key}
|
||||
>
|
||||
{item.job_name}
|
||||
</Option>
|
||||
)
|
||||
})
|
||||
: ''}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={4}>
|
||||
<Form.Item label="筛选状态" name="hr_manner">
|
||||
<Select>
|
||||
<Option value={''}>全部</Option>
|
||||
<Option value={1}>通过</Option>
|
||||
<Option value={0}>拒绝</Option>
|
||||
{/* <Option value="Yiminghe">待定</Option> */}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div className="Resumescreen-list-data-box">
|
||||
<div className="Resumescreen-list-tab-box">
|
||||
<Tabs
|
||||
defaultActiveKey="2"
|
||||
onChange={(e) => this.handelonChange(e)}
|
||||
>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<div className="tabs-box">
|
||||
<div className="num">
|
||||
{manner_2_num}
|
||||
</div>
|
||||
<div>待筛选的候选人</div>
|
||||
</div>
|
||||
}
|
||||
key={2}
|
||||
></Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<div className="tabs-box">
|
||||
<div className="num">
|
||||
{manner_01_num}
|
||||
</div>
|
||||
<div>筛选记录</div>
|
||||
</div>
|
||||
}
|
||||
key=""
|
||||
></Tabs.TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div className="Resumescreen-list-table-box">
|
||||
<div className="CandidateTable-list-box ">
|
||||
<div className="CandidateTable-info-box">
|
||||
基本资料
|
||||
</div>
|
||||
<div className="CandidateTable-owner">申请日期</div>
|
||||
<div className="CandidateTable-owner">应聘职位</div>
|
||||
{/* <div className='CandidateTable-owner'>推荐详情</div> */}
|
||||
<div className="CandidateTable-owner">
|
||||
候选人状态
|
||||
</div>
|
||||
<div className="CandidateTable-owner">反馈结果</div>
|
||||
</div>
|
||||
<div style={{ width: 'calc(100% - 4px)' }}>
|
||||
{data.length > 0 ? (
|
||||
data.map((item, key) => {
|
||||
return (
|
||||
<div
|
||||
className="CandidateTable-list-box"
|
||||
key={item.uid}
|
||||
onClick={() =>
|
||||
this.handelCandidateClick(item.uid)
|
||||
}
|
||||
>
|
||||
<div className="CandidateTable-info-box">
|
||||
<div className="CandidateTable-info">
|
||||
<div>
|
||||
<span className="name">
|
||||
{item.name}
|
||||
</span>
|
||||
<span>
|
||||
{' '}
|
||||
{item.gender} |
|
||||
</span>
|
||||
<span>
|
||||
{' '}
|
||||
{item.age} |{' '}
|
||||
</span>
|
||||
{item.work_exp == 0 ? (
|
||||
<span>无经验</span>
|
||||
) : (
|
||||
<span>
|
||||
{item.work_exp}
|
||||
工作经验
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{item['work_list'].map(
|
||||
(items, key) => {
|
||||
return (
|
||||
<div key={key}>
|
||||
<ShoppingFilled />
|
||||
<span>
|
||||
{
|
||||
items.company_name
|
||||
}{' '}
|
||||
|{' '}
|
||||
{
|
||||
items.position_name
|
||||
}{' '}
|
||||
|{' '}
|
||||
{
|
||||
items.time
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)}
|
||||
|
||||
<div>
|
||||
<BankOutlined />
|
||||
{item.school != '' ? (
|
||||
<span>
|
||||
{' '}
|
||||
{item.school}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{item.specialty !=
|
||||
'' ? (
|
||||
<span>
|
||||
{' '}
|
||||
|{' '}
|
||||
{item.specialty}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{item.education !=
|
||||
'' ? (
|
||||
<span>
|
||||
{' '}
|
||||
|{' '}
|
||||
{item.education}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{item.graduate_time !=
|
||||
'' ? (
|
||||
<span>
|
||||
{' '}
|
||||
|{' '}
|
||||
{
|
||||
item.graduate_time
|
||||
}
|
||||
</span>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Tag color="processing">
|
||||
{item.education}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="CandidateTable-owner">
|
||||
<span>{item.star_time}</span>
|
||||
</div>
|
||||
<div className="CandidateTable-owner">
|
||||
<span>{item.job_names}</span>
|
||||
</div>
|
||||
{/* <div className="CandidateTable-owner">
|
||||
<span>推荐详情</span>
|
||||
</div> */}
|
||||
<div className="CandidateTable-owner">
|
||||
<span>
|
||||
{item.interview_stage}
|
||||
</span>
|
||||
</div>
|
||||
<div className="CandidateTable-owner">
|
||||
<Button
|
||||
type="text"
|
||||
style={{ color: '#0c8cf6' }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
this.handeleditstate(
|
||||
item.uid,
|
||||
1
|
||||
)
|
||||
}}
|
||||
>
|
||||
同意
|
||||
</Button>
|
||||
<Button
|
||||
type="text"
|
||||
style={{ color: '#0c8cf6' }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
this.handeleditstate(
|
||||
item.uid,
|
||||
0
|
||||
)
|
||||
}}
|
||||
>
|
||||
拒绝
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="margintop30">
|
||||
<Empty description={'暂无数据'} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 查看面试人信息弹窗 */}
|
||||
<InterviewerInfoPop
|
||||
visible={this.state.interviewerInfo}
|
||||
onCreate={() => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
})
|
||||
}}
|
||||
data={this.state.uid}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
interviewerInfo: false,
|
||||
})
|
||||
}}
|
||||
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
0
src/pages/admin/Set_up/Editpassword/index.css
Normal file
0
src/pages/admin/Set_up/Editpassword/index.css
Normal file
68
src/pages/admin/Set_up/Editpassword/index.jsx
Normal file
68
src/pages/admin/Set_up/Editpassword/index.jsx
Normal file
@ -0,0 +1,68 @@
|
||||
import React from 'react'
|
||||
import { Form, Input, message, Modal } from 'antd'
|
||||
import { set_userinfo } from '../../../../util/requestURL'
|
||||
|
||||
export default function Editpassword({ visible, onCreate, onCancel }) {
|
||||
const [form] = Form.useForm()
|
||||
return (
|
||||
<div className="Editpassword-box">
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="修改密码"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
form.resetFields()
|
||||
if(values.newpassword === values.confirmpassword){
|
||||
set_userinfo({password:values.newpassword,nickname:"",tel:"",email:''}).then(
|
||||
(res) => {
|
||||
message.success('修改成功!')
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络出错,请稍后再试!')
|
||||
}
|
||||
)
|
||||
onCreate(values)
|
||||
}else {
|
||||
message.error('两次密码输入不一致!')
|
||||
}
|
||||
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log('Validate Failed:', info)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form form={form} layout="vertical" name="form_in_modal">
|
||||
<Form.Item
|
||||
name="newpassword"
|
||||
label="新密码"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请填写修改后的密码!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="confirmpassword"
|
||||
label="确认密码"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请填写修改后的密码!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
5
src/pages/admin/Set_up/index.css
Normal file
5
src/pages/admin/Set_up/index.css
Normal file
@ -0,0 +1,5 @@
|
||||
.set-form-box {
|
||||
margin: 60px;
|
||||
}
|
||||
.set-form-button-box { margin-left: 580px; }
|
||||
.set-form-button-box button { margin-left: 10px; }
|
@ -1,9 +1,146 @@
|
||||
import React from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import PubSub from 'pubsub-js'
|
||||
import { Form, Input, Button, InputNumber, message } from 'antd'
|
||||
import Editpassword from './Editpassword'
|
||||
import storageUtils from '../../../util/storageUtils'
|
||||
import { set_userinfo } from '../../../util/requestURL'
|
||||
import './index.css'
|
||||
|
||||
function Set_up() {
|
||||
return (
|
||||
<div>设置</div>
|
||||
)
|
||||
const [componentDisabled, setComponentDisabled] = useState(true)
|
||||
const [userInfo, setuserInfo] = useState(storageUtils.getUser())
|
||||
const [ismmpop, setismmpop] = useState(false)
|
||||
const [postdata, setposrdata] = useState({
|
||||
password: '',
|
||||
nickname: '',
|
||||
tel: '',
|
||||
email: '',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
PubSub.publish('headtitle', { headtitle: '设置' })
|
||||
}, [])
|
||||
|
||||
const onFormLayoutChange = (disabled) => {
|
||||
// message.error("暂不支持编辑")
|
||||
setComponentDisabled(disabled)
|
||||
if (disabled) {
|
||||
if (
|
||||
postdata.password === '' &&
|
||||
postdata.nickname === '' &&
|
||||
postdata.tel === '' &&
|
||||
postdata.email === ''
|
||||
) {
|
||||
} else {
|
||||
set_userinfo(postdata).then(
|
||||
(res) => {
|
||||
message.error('修改成功!请退出后重新登录')
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络请求错误,请稍后再试!')
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="set-box">
|
||||
<div className="set-form-box">
|
||||
<Form
|
||||
labelCol={{
|
||||
span: 4,
|
||||
}}
|
||||
wrapperCol={{
|
||||
span: 14,
|
||||
}}
|
||||
layout="horizontal"
|
||||
initialValues={userInfo}
|
||||
>
|
||||
<Form.Item label="账号" name={'name'}>
|
||||
<Input style={{ width: 304 }} disabled={true} />
|
||||
</Form.Item>
|
||||
<Form.Item label="用户名" name={'nickname'}>
|
||||
<Input
|
||||
style={{ width: 304 }}
|
||||
disabled={componentDisabled}
|
||||
onChange={(e) => {
|
||||
setposrdata({
|
||||
...postdata,
|
||||
nickname: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="电话" name={'tel'}>
|
||||
<InputNumber
|
||||
style={{ width: 304 }}
|
||||
disabled={componentDisabled}
|
||||
onChange={(e) => {
|
||||
setposrdata({
|
||||
...postdata,
|
||||
tel: e,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="邮箱" name={'email'}>
|
||||
<Input
|
||||
style={{ width: 304 }}
|
||||
disabled={componentDisabled}
|
||||
onChange={(e) => {
|
||||
setposrdata({
|
||||
...postdata,
|
||||
email: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="密码">
|
||||
<Button
|
||||
disabled={componentDisabled}
|
||||
onClick={() => {
|
||||
console.log(123456789)
|
||||
setismmpop(true)
|
||||
}}
|
||||
>
|
||||
更改密码
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<div className="set-form-button-box">
|
||||
{componentDisabled ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
onFormLayoutChange(false)
|
||||
message.warning("修改信息后需要重新登录!")
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
onFormLayoutChange(true)
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
<Editpassword
|
||||
visible={ismmpop}
|
||||
onCreate={() => {
|
||||
setismmpop(false)
|
||||
}}
|
||||
onCancel={() => {
|
||||
setismmpop(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Set_up
|
||||
export default Set_up
|
||||
|
5
src/pages/admin/Talent_pool/Addscreen/index.css
Normal file
5
src/pages/admin/Talent_pool/Addscreen/index.css
Normal file
@ -0,0 +1,5 @@
|
||||
.Addscreen-box {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background-color: #000;
|
||||
}
|
62
src/pages/admin/Talent_pool/Addscreen/index.jsx
Normal file
62
src/pages/admin/Talent_pool/Addscreen/index.jsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { Select, Modal, message } from 'antd'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { up_option } from '../../../../util/requestURL'
|
||||
import './index.css'
|
||||
const { Option } = Select
|
||||
|
||||
export default function Addscreen({ visible, data, onCancel }) {
|
||||
const [defaultValue, setdefaultValue] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
const isCheck = []
|
||||
data.map((item, key) => {
|
||||
if (item.type) return isCheck.push(item.id)
|
||||
})
|
||||
setdefaultValue(isCheck)
|
||||
}, [visible])
|
||||
|
||||
const handleChange = (value) => {
|
||||
console.log(value)
|
||||
setdefaultValue(value)
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="添加筛选项"
|
||||
visible={visible}
|
||||
onCancel={onCancel}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
onOk={() => {
|
||||
up_option({where:defaultValue}).then(
|
||||
(res) => {
|
||||
message.success('更改成功')
|
||||
onCancel()
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络加载错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
placeholder="select one country"
|
||||
value={defaultValue}
|
||||
onChange={handleChange}
|
||||
optionLabelProp="label"
|
||||
>
|
||||
{data.map((item, key) => {
|
||||
return (
|
||||
<Option value={item.id} key={key}>
|
||||
{item.name}
|
||||
</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Modal>
|
||||
)
|
||||
}
|
192
src/pages/admin/Talent_pool/index.css
Normal file
192
src/pages/admin/Talent_pool/index.css
Normal file
@ -0,0 +1,192 @@
|
||||
.talentpool-Empty-box { height: 122px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; }
|
||||
.talentpool-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
}
|
||||
.talentpool-left-box {
|
||||
width: 250px;
|
||||
height: 100%;
|
||||
}
|
||||
.talentpool-right-box {
|
||||
width: calc(100% - 250px);
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
.filter_criteria-top-box {
|
||||
padding: 10px 16px;
|
||||
background-color: #e9eaec;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #008bff;
|
||||
}
|
||||
.filter_criteria-top-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
font-size: 17px;
|
||||
color: #008bff;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.filter_criteria-top-left-box{
|
||||
color: #008bff;
|
||||
}
|
||||
|
||||
.talentpool-add-screen-box {
|
||||
padding: 20px 16px;
|
||||
box-shadow: 1px 1px 4px rgb(0 0 0 / 8%);
|
||||
}
|
||||
.talentpool-add-screen-box p {
|
||||
color: #333;
|
||||
}
|
||||
.talentpool-add-screen-tab-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.talentpool-add-but-box {
|
||||
color: #008bff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.talentpool-screen-list-box {
|
||||
height: calc(100% - 150px);
|
||||
}
|
||||
.talentpool-content-box {
|
||||
padding: 30px 24px;
|
||||
}
|
||||
.talentpool-title {
|
||||
font-size: 24px;
|
||||
color: #4b505d;
|
||||
}
|
||||
.talentpool-tishi {
|
||||
font-size: 14px;
|
||||
color: #4b505d;
|
||||
}
|
||||
.talentpool-tab-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.talentpool-tab {
|
||||
width: 30%;
|
||||
padding: 26px 18px;
|
||||
border: 1px solid #f1f1f1;
|
||||
border-radius: 4px;
|
||||
margin-top: 18px;
|
||||
box-shadow: 1px 1px 4px rgb(0 0 0 / 8%);
|
||||
}
|
||||
.talentpool-tab .tit {
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.talentpool-con-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.talentpool-con-box .tit {
|
||||
font-size: 16px;
|
||||
}
|
||||
.talentpool-con-box .data {
|
||||
font-size: 14px;
|
||||
color: #96989d;
|
||||
}
|
||||
.talentpool-con-box .data span {
|
||||
color: #008bff;
|
||||
}
|
||||
.qxcheck-box {
|
||||
border: 0;
|
||||
}
|
||||
.talentpool-screen-list-select {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.talentpool-list-box {
|
||||
height: 570px;
|
||||
/* overflow: hidden; */
|
||||
/* height: calc(100% - 32px); */
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
.talentpool-screen-list {
|
||||
padding: 20px 16px;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
}
|
||||
.talentpool-screen-list-tit {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.talentpool-table-action {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #f4f4f5; padding: 10px 0;
|
||||
}
|
||||
|
||||
.talentpool-info-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px 18px;
|
||||
}
|
||||
.talentpool-info {
|
||||
margin-left: 34px;
|
||||
}
|
||||
.talentpool-info .name {
|
||||
font-size: 16px;
|
||||
color: #4b505d;
|
||||
font-weight: bold;
|
||||
}
|
||||
.talentpool-info .sex {
|
||||
color: #9294a2;
|
||||
margin-left: 6px;
|
||||
}
|
||||
.talentpool-info .age {
|
||||
color: #9294a2;
|
||||
margin-left: 6px;
|
||||
}
|
||||
.talentpool-info .exp {
|
||||
color: #9294a2;
|
||||
margin-left: 6px;
|
||||
}
|
||||
.similar {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
background-color: #008bff;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
margin-left: 6px;
|
||||
}
|
||||
.similar-num {
|
||||
color: #008bff;
|
||||
}
|
||||
.work-exp-box {
|
||||
color: #9294a2;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.work-exp-box span {
|
||||
margin-right: 6px;
|
||||
}
|
||||
.apply_info-box {
|
||||
color: #4b505d;
|
||||
}
|
||||
.apply_info-box span {
|
||||
color: #312b2e;
|
||||
}
|
||||
.talentpool-list-left {
|
||||
display: flex;
|
||||
}
|
||||
.page-box {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,471 @@
|
||||
import React from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
Checkbox,
|
||||
Select,
|
||||
Input,
|
||||
Empty,
|
||||
message,
|
||||
Pagination,
|
||||
Modal,
|
||||
} from 'antd'
|
||||
import Addscreen from './Addscreen'
|
||||
import {
|
||||
option_data,
|
||||
talent_pool,
|
||||
talent_pool_nu,
|
||||
option,
|
||||
get_number
|
||||
} from '../../../util/requestURL'
|
||||
import {
|
||||
PrinterFilled,
|
||||
DownOutlined,
|
||||
FunnelPlotOutlined,
|
||||
CaretDownFilled,
|
||||
BlockOutlined,
|
||||
CalendarFilled,
|
||||
BankFilled,
|
||||
CloseOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import PubSub from 'pubsub-js'
|
||||
import './index.css'
|
||||
const { Option } = Select
|
||||
const { confirm } = Modal
|
||||
|
||||
function Talent_pool() {
|
||||
return (
|
||||
<div>人才库</div>
|
||||
)
|
||||
export default class Talent_pool extends Component {
|
||||
state = {
|
||||
isaddscreen: false,
|
||||
data: [],
|
||||
screencondition: {},
|
||||
datalist: [],
|
||||
pages: 1,
|
||||
total: 0,
|
||||
candidate:0,
|
||||
now:0
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
PubSub.publish('headtitle', { headtitle: '人才库' })
|
||||
get_number().then((res)=>{
|
||||
console.log(res)
|
||||
this.setState({
|
||||
candidate: res.data.candidate,
|
||||
now: res.data.now
|
||||
})
|
||||
},
|
||||
(err)=>{
|
||||
message.error('网络错误,请稍后再试')
|
||||
})
|
||||
this.handelupdatascreen()
|
||||
this.posttalentpool()
|
||||
}
|
||||
|
||||
handelAddscreen = () => {
|
||||
// console.log(1111)
|
||||
this.setState({ isaddscreen: true })
|
||||
}
|
||||
|
||||
handelupdatascreen = () => {
|
||||
option().then(
|
||||
(res) => {
|
||||
var data = res.data
|
||||
var where = []
|
||||
for (let i in data) {
|
||||
if (data[i]['type'] && data[i]['style'] === 'select') {
|
||||
where.push(data[i]['id'])
|
||||
}
|
||||
}
|
||||
option_data({ where }).then(
|
||||
(res) => {
|
||||
const datalist = res.data
|
||||
const newdata = data.map((item, key) => {
|
||||
if (datalist[item.id]) {
|
||||
return { ...item, list: datalist[item.id] }
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
this.setState({ data: newdata })
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handelobtainscreen = (e, id) => {
|
||||
const { screencondition } = this.state
|
||||
for (let i in screencondition) {
|
||||
if (i === id) {
|
||||
screencondition[i] = e
|
||||
}
|
||||
}
|
||||
screencondition[id] = e
|
||||
// console.log(screencondition)
|
||||
this.setState({ screencondition: screencondition }, () => {
|
||||
this.posttalentpool()
|
||||
})
|
||||
}
|
||||
|
||||
posttalentpool = (e, id) => {
|
||||
const { screencondition, pages } = this.state
|
||||
talent_pool({ date: screencondition, pages: pages }).then(
|
||||
(res) => {
|
||||
console.log(res.data)
|
||||
this.setState({
|
||||
datalist: res.data,
|
||||
})
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
|
||||
talent_pool_nu({ date: screencondition }).then(
|
||||
(res) => {
|
||||
// console.log(res.data)
|
||||
this.setState({
|
||||
total: res.data,
|
||||
})
|
||||
},
|
||||
(err) => {
|
||||
message.error('网络错误,请稍后再试')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onChangePage = (e) => {
|
||||
this.setState(
|
||||
{
|
||||
pages: e,
|
||||
},
|
||||
() => {
|
||||
this.posttalentpool()
|
||||
}
|
||||
)
|
||||
// console.log(e)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, datalist,candidate,now } = this.state
|
||||
return (
|
||||
<div className="talentpool-box">
|
||||
{/* <Empty description="该功能暂未开放" className='talentpool-Empty-box'/> */}
|
||||
<div className="talentpool-left-box">
|
||||
<div className="filter_criteria-top-box">
|
||||
<div className="divdisplay filter_criteria-top-left-box">
|
||||
<div className="filter_criteria-top-img">
|
||||
<PrinterFilled />
|
||||
</div>
|
||||
<span className="">全部 {candidate}</span>
|
||||
</div>
|
||||
<div>
|
||||
<DownOutlined />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="talentpool-add-screen-box">
|
||||
<p>筛选条件</p>
|
||||
<div className="talentpool-add-screen-tab-box">
|
||||
<div
|
||||
className="talentpool-add-but-box"
|
||||
onClick={() => {
|
||||
this.handelAddscreen()
|
||||
}}
|
||||
>
|
||||
+ 添加筛选项
|
||||
</div>
|
||||
<div>
|
||||
<FunnelPlotOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="talentpool-screen-list-box">
|
||||
{data.map((item, key) => {
|
||||
return item.type ? (
|
||||
item.style === 'select' ? (
|
||||
<div
|
||||
className="talentpool-screen-list"
|
||||
key={key}
|
||||
>
|
||||
<div className="talentpool-screen-list-tit">
|
||||
<span>{item.name}</span>
|
||||
<CloseOutlined />
|
||||
</div>
|
||||
<div className="talentpool-screen-list-select">
|
||||
<Select
|
||||
defaultValue=""
|
||||
style={{
|
||||
width: 218,
|
||||
}}
|
||||
onChange={(e) => {
|
||||
this.handelobtainscreen(
|
||||
e,
|
||||
item.id
|
||||
)
|
||||
}}
|
||||
>
|
||||
{item.list
|
||||
? item.list.map(
|
||||
(items, keys) => {
|
||||
return (
|
||||
<Option
|
||||
value={
|
||||
items.id
|
||||
}
|
||||
key={
|
||||
keys
|
||||
}
|
||||
>
|
||||
{
|
||||
items.name
|
||||
}
|
||||
</Option>
|
||||
)
|
||||
}
|
||||
)
|
||||
: ''}
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="talentpool-screen-list"
|
||||
key={key}
|
||||
>
|
||||
<div className="talentpool-screen-list-tit">
|
||||
<span>{item.name}</span>
|
||||
<CloseOutlined />
|
||||
</div>
|
||||
<div className="talentpool-screen-list-select">
|
||||
<Input
|
||||
placeholder={
|
||||
'请输入' + item.name
|
||||
}
|
||||
onChange={(e) => {
|
||||
this.handelobtainscreen(
|
||||
e.target.value,
|
||||
item.id
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
''
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="talentpool-right-box">
|
||||
<div className="talentpool-content-box">
|
||||
<div className="talentpool-title">人才库概览</div>
|
||||
<div className="talentpool-tishi">
|
||||
列表中显示候选人数量上限10000人,您可以使用左方的筛选栏位快速寻找符合需求的候选人。
|
||||
</div>
|
||||
|
||||
<div className="talentpool-tab-box">
|
||||
<div className="talentpool-tab">
|
||||
<div className="tit">{candidate}</div>
|
||||
<div className="talentpool-con-box">
|
||||
<div className="tit">候选人总数</div>
|
||||
<div className="data">
|
||||
今日归档人数:<span>{now}</span>{' '}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className='talentpool-tab'>
|
||||
<div className='tit'>22</div>
|
||||
<div className='talentpool-con-box'>
|
||||
<div className='tit'>候选人总数</div>
|
||||
<div className='data'>今日归档人数:<span>0</span> </div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className="talentpool-list-box">
|
||||
<div className="talentpool-table-action">
|
||||
<div className="qxcheck-box">
|
||||
<Checkbox>
|
||||
<CaretDownFilled
|
||||
style={{ color: '#424954' }}
|
||||
/>
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{datalist.map((item, key) => {
|
||||
return (
|
||||
<div
|
||||
className="talentpool-info-box"
|
||||
key={key}
|
||||
>
|
||||
<div className="talentpool-list-left">
|
||||
<div>
|
||||
<Checkbox></Checkbox>
|
||||
</div>
|
||||
<div className="talentpool-info">
|
||||
<div>
|
||||
<span className="name">
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="sex">
|
||||
{item.gander}
|
||||
</span>
|
||||
<span className="age">
|
||||
| {item.age}
|
||||
</span>
|
||||
<span className="exp">
|
||||
{item.work_exp === 0
|
||||
? '| 实习生'
|
||||
: item.work_exp ===
|
||||
1
|
||||
? '1-3年'
|
||||
: item.work_exp ===
|
||||
2
|
||||
? '3-5年'
|
||||
: '5年以上'}
|
||||
</span>
|
||||
<span className="similar">
|
||||
<BlockOutlined />{' '}
|
||||
</span>{' '}
|
||||
<span className="similar-num">
|
||||
{item.similarity}
|
||||
位相似候选人
|
||||
</span>
|
||||
</div>
|
||||
{item.work_list.map(
|
||||
(items, index) => {
|
||||
return (
|
||||
<div
|
||||
className="work-exp-box"
|
||||
key={index}
|
||||
>
|
||||
<CalendarFilled />
|
||||
<span>
|
||||
{
|
||||
items.company_name
|
||||
}
|
||||
</span>
|
||||
<span>
|
||||
|{' '}
|
||||
{
|
||||
items.position_name
|
||||
}
|
||||
</span>
|
||||
<span>
|
||||
|
|
||||
{
|
||||
items.time
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)}
|
||||
|
||||
<div className="work-exp-box">
|
||||
<BankFilled />
|
||||
<span>
|
||||
{item.school}
|
||||
</span>
|
||||
<span>
|
||||
| {item.specialty}
|
||||
</span>
|
||||
<span>
|
||||
| {item.education}
|
||||
</span>
|
||||
<span>
|
||||
|{item.at_school}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="apply_info-box">
|
||||
<div>
|
||||
申请日期:
|
||||
<span>
|
||||
{item.event_time}
|
||||
</span>
|
||||
</div>
|
||||
<div className="margintop5">
|
||||
应聘职位:
|
||||
<span>{item.job_name}</span>
|
||||
</div>
|
||||
<div className="margintop5">
|
||||
归档人才库:
|
||||
<span>系统公共人才库</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="apply_info-box">
|
||||
<div>
|
||||
归档日期:
|
||||
<span>
|
||||
{item.pass_time}
|
||||
</span>
|
||||
</div>
|
||||
<div className="margintop5">
|
||||
归档前阶段:
|
||||
<span>
|
||||
{item.ago === 0
|
||||
? '人才推荐'
|
||||
: item.ago === 1
|
||||
? '初筛'
|
||||
: item.ago === 2
|
||||
? '复筛'
|
||||
: item.ago === 3
|
||||
? '面试'
|
||||
: item.ago === 4
|
||||
? '沟通Offer'
|
||||
: '待入职'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="margintop5">
|
||||
归档原因:
|
||||
<span>
|
||||
{item.pass_why}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-box">
|
||||
<Pagination
|
||||
defaultCurrent={1}
|
||||
current={1}
|
||||
total={this.state.total}
|
||||
onChange={(e) => {
|
||||
this.onChangePage(e)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Addscreen
|
||||
visible={this.state.isaddscreen}
|
||||
data={this.state.data}
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
isaddscreen: false,
|
||||
},()=>{
|
||||
this.handelupdatascreen()
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Talent_pool
|
@ -1,4 +1,34 @@
|
||||
.components-form-demo-normal-login { width: 300px; height: 222px; position: fixed; top: 0; bottom: 0; left: 0; right: 0; margin: auto; }
|
||||
.login-box { background: url('../images/bg_login.png'); width: 100%;height: 100%;}
|
||||
|
||||
.login-boxs {width: 69%;
|
||||
height: 70%;
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.login-left {
|
||||
width: 55.5%;
|
||||
height: 100%;
|
||||
background-color: #e0f1ff;
|
||||
border-radius: 8px 0 0 8px;
|
||||
line-height: 100%;
|
||||
display: flex;
|
||||
background: url('../images/left-logo.jpg');
|
||||
}
|
||||
|
||||
.components-form-demo-normal-login {width: 44.5%;
|
||||
height: 150px; position: absolute; top: 90px; bottom: 0; right: 70px; margin: auto; }
|
||||
|
||||
/* .components-form-demo-normal-login input { height: 40px; max-height: 40px; } */
|
||||
|
||||
.login-logo { background: url('../images/logo_2.png') no-repeat; width: 70%; height: 75px; position: absolute; top: -170px; right: -40px;}
|
||||
|
||||
.components-form-demo-normal-login .login-form {
|
||||
max-width: 300px;
|
||||
|
@ -3,6 +3,6 @@ import React from 'react'
|
||||
import Redirect from './Redirect'
|
||||
|
||||
export default function AuthComponent({children }) {
|
||||
const islogin = localStorage.getItem("token");
|
||||
const islogin = localStorage.getItem("userInfo");
|
||||
return islogin ? children : <Redirect to="/login" />
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import {useRoutes, Navigate} from 'react-router-dom'
|
||||
import { useRoutes, Navigate } from 'react-router-dom'
|
||||
import AppLayOut from '../AppLayOut'
|
||||
import AuthComponent from './AuthComponent'
|
||||
import Login from '../pages/Login'
|
||||
@ -12,27 +12,65 @@ import SetUp from '../pages/admin/Set_up'
|
||||
import TalentPool from '../pages/admin/Talent_pool'
|
||||
import Endrecruitment from '../pages/admin/Position/Endrecruitment'
|
||||
import Inrecruitment from '../pages/admin/Position/Inrecruitment'
|
||||
import AddPosition from '../components/AddPosition'
|
||||
import Reportcenter from '../pages/admin/Report_forms/Reportcenter'
|
||||
import Kanbandetails from '../pages/admin/Report_forms/Kanbandetails'
|
||||
import Resumescreen from '../pages/admin/Resumescreen'
|
||||
import Interview_manager from '../pages/admin/Interview_manager'
|
||||
|
||||
// import PageNotFound from '../pages/PageNotFound'
|
||||
|
||||
|
||||
function GlobalRouter() {
|
||||
|
||||
return useRoutes([
|
||||
{
|
||||
path: '/',
|
||||
element: <AuthComponent> <AppLayOut /> </AuthComponent> ,
|
||||
element: (
|
||||
<AuthComponent>
|
||||
{' '}
|
||||
<AppLayOut />{' '}
|
||||
</AuthComponent>
|
||||
),
|
||||
children: [
|
||||
{ path: '/', element: <Overview /> },
|
||||
{ path: '/admin/candidate',element: <Candidate />,},
|
||||
{ path: '/', element: <Overview /> },
|
||||
{ path: '/admin/candidate', element: <Candidate /> },
|
||||
{
|
||||
path: `/admin/resumescreen`,
|
||||
element: <Resumescreen />,
|
||||
},
|
||||
{
|
||||
path: `/admin/Interview_manager`,
|
||||
element: <Interview_manager />,
|
||||
},
|
||||
{ path: '/admin/interview', element: <Interview /> },
|
||||
{ path: '/admin/position', element: <Position />, children:[
|
||||
{ index:true, element: <Inrecruitment /> },
|
||||
{ path: '/admin/position/Endrecruitment', element: <Endrecruitment /> }
|
||||
]},
|
||||
{
|
||||
path: '/admin/position',
|
||||
element: <Position />,
|
||||
children: [
|
||||
{ index: true, element: <Inrecruitment /> },
|
||||
{
|
||||
path: '/admin/position/Endrecruitment',
|
||||
element: <Endrecruitment />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{ path: '/admin/reportforms', element: <ReportForms /> },
|
||||
{ path: '/admin/setup', element: <SetUp /> },
|
||||
{ path: '/admin/talentPool', element: <TalentPool /> },
|
||||
{
|
||||
path: `/admin/position/addposition/:id`,
|
||||
element: <AddPosition />,
|
||||
},
|
||||
{
|
||||
path: `/admin/position/addposition`,
|
||||
element: <AddPosition />,
|
||||
},
|
||||
{
|
||||
path: `/admin/reportforms/Reportcenter/:id`,
|
||||
element: <Reportcenter />,
|
||||
},{
|
||||
path:'/admin/reportforms/Kanbandetails/:url/:id',
|
||||
element: <Kanbandetails />,
|
||||
}
|
||||
],
|
||||
},
|
||||
{ path: '/login', element: <Login /> },
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user