candidateAll.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <!--
  2. * @Description: create
  3. * @Version: 1.0
  4. * @Autor: XuTongZhang
  5. * @Date: 2020-07-30 10:17:25
  6. * @LastEditors : yuanrunwei
  7. * @LastEditTime : 2021-02-05 17:11:16
  8. -->
  9. <template>
  10. <div class="indexPage">
  11. <v-input :btn="btn" :list="list" @search="search" @exports="exports" @upload="upload=true" @excel="handleExcel"></v-input>
  12. <v-table :table="table" :tableList="tableList" :sortType="true" :queryData="queryData" :form="searchForm" @details="details" @update="update" @duplicate="handleDuplicate" @delete="handleDelete"></v-table>
  13. <v-pager @page="callPage" :total="totalrecords"></v-pager>
  14. <!-- <resume :dialogFormVisible="dialogFormVisible" :close="close" :info="info" :searchForm="searchForm" :queryData="queryData"></resume> -->
  15. <el-dialog :visible.sync="dialogVisible" width="600px" :before-close="closeDia" :close-on-click-modal="false">
  16. <el-form :model="form" ref="uform" label-width="140px" :rules="rules" label-position="right">
  17. <el-form-item label="姓名" prop="delivererName">
  18. <el-input placeholder="请输入姓名" v-model="form.delivererName" maxlength="32" show-word-limit></el-input>
  19. </el-form-item>
  20. <el-form-item label="性别" prop="delivererSex">
  21. <el-select v-model="form.delivererSex" class="select" placeholder="请选择性别">
  22. <el-option v-for="item in [{ value: 0, label: '女' }, { value: 1, label: '男' }]" :key="item.value" :label="item.label" :value="item.value">
  23. </el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="投递职位" prop="positionApplied">
  27. <el-input placeholder="请输入投递职位" v-model="form.positionApplied" maxlength="32" show-word-limit></el-input>
  28. </el-form-item>
  29. <el-form-item label="工作年限" prop="delivererWorkExp">
  30. <el-input placeholder="请输入工作年限" v-model="form.delivererWorkExp" maxlength="200" show-word-limit></el-input>
  31. </el-form-item>
  32. <el-form-item label="学历" prop="delivererEducation">
  33. <el-select class="select" v-model="form.delivererEducation" placeholder="请选择学历">
  34. <el-option v-for="item in ['大专', '本科', '研究生', '博士', '其他']" :key="item" :label="item" :value="item">
  35. </el-option>
  36. </el-select>
  37. </el-form-item>
  38. <el-form-item label="联系电话" prop="delivererPhone">
  39. <el-input placeholder="请输入联系电话" v-model.number="form.delivererPhone" maxlength="11" show-word-limit></el-input>
  40. </el-form-item>
  41. <el-form-item label="邮箱地址" prop="delivererMail">
  42. <el-input placeholder="请输入邮箱地址" v-model="form.delivererMail" maxlength="32" show-word-limit></el-input>
  43. </el-form-item>
  44. <el-form-item label="应聘职位" prop="desiredPositionId">
  45. <el-select class="select" v-model="form.desiredPositionId" placeholder="请选择应聘职位">
  46. <el-option v-for="item in positionList" :key="item.value" :label="item.label" :value="item.value">
  47. </el-option>
  48. </el-select>
  49. </el-form-item>
  50. <el-form-item>
  51. <el-button @click="closeDia">取 消</el-button>
  52. <el-button type="primary" @click="submit">修 改</el-button>
  53. </el-form-item>
  54. </el-form>
  55. </el-dialog>
  56. <!-- upload -->
  57. <el-dialog :visible.sync="upload" width="600px" :before-close="() => {upload=false}" :close-on-click-modal="false">
  58. <el-form label-width="140px" label-position="right">
  59. <el-form-item label="姓名">
  60. <el-input placeholder="请输入姓名" v-model="uploadForm.delivererName" maxlength="32" show-word-limit></el-input>
  61. </el-form-item>
  62. <el-form-item label="性别">
  63. <el-select v-model="uploadForm.delivererSex" class="select" placeholder="请选择性别">
  64. <el-option v-for="item in [{ value: 0, label: '女' }, { value: 1, label: '男' }]" :key="item.value" :label="item.label" :value="item.value">
  65. </el-option>
  66. </el-select>
  67. </el-form-item>
  68. <el-form-item label="请选择出生日期">
  69. <el-date-picker
  70. v-model="uploadForm.delivererBirthday"
  71. value-format="yyyy/MM/dd"
  72. type="date"
  73. placeholder="选择日期">
  74. </el-date-picker>
  75. </el-form-item>
  76. <el-form-item label="手机号码">
  77. <el-input placeholder="请输入手机号码" v-model.number="uploadForm.delivererPhone" maxlength="11" show-word-limit></el-input>
  78. </el-form-item>
  79. <el-form-item label="邮箱">
  80. <el-input placeholder="请输入邮箱" v-model="uploadForm.delivererMail" maxlength="32" show-word-limit></el-input>
  81. </el-form-item>
  82. <el-form-item label="国籍">
  83. <el-input placeholder="请输入国籍" v-model="uploadForm.delivererNationality" maxlength="32" show-word-limit></el-input>
  84. </el-form-item>
  85. <el-form-item label="联系地址">
  86. <el-input placeholder="请输入联系地址" v-model="uploadForm.delivererAddress" maxlength="32" show-word-limit></el-input>
  87. </el-form-item>
  88. <el-form-item label="意向城市-省市">
  89. <!-- <el-input placeholder="请选择意向城市-省市" v-model="uploadForm.delivererIntention" maxlength="32" show-word-limit></el-input> -->
  90. <!-- <el-cascader placeholder="请选择意向城市-省市" v-model="uploadForm.delivererIntention" :props="{
  91. lazy: true,
  92. value: 'id',
  93. label: 'name',
  94. lazyLoad (node, resolve) {
  95. const { level } = node;
  96. $api.post('/addr/all_addr').then(result=>{
  97. resolve(result.list.map(item => ({
  98. value: item.id,
  99. label: item.name,
  100. leaf: level >= 2,
  101. })))
  102. })
  103. }
  104. }"></el-cascader> -->
  105. <el-cascader :options="addrOptions" placeholder="请选择意向城市-省市" v-model="uploadForm.delivererIntention" :props="{
  106. value: 'name',
  107. label: 'name'
  108. }"></el-cascader>
  109. </el-form-item>
  110. <el-form-item label="学历">
  111. <el-select class="select" v-model="uploadForm.delivererEducation" placeholder="请选择学历">
  112. <el-option v-for="item in ['大专', '本科', '研究生', '博士', '其他']" :key="item" :label="item" :value="item"></el-option>
  113. </el-select>
  114. </el-form-item>
  115. <el-form-item label="年级">
  116. <el-input placeholder="请输入年级" v-model="uploadForm.delivererGrade" maxlength="200" show-word-limit></el-input>
  117. </el-form-item>
  118. <el-form-item label="语言能力">
  119. <el-cascader
  120. v-model="uploadForm.delivererLanguageAbility"
  121. :options="options"
  122. :props="{
  123. multiple:false,
  124. emitPath:false
  125. }"
  126. :show-all-levels="false"
  127. clearable></el-cascader>
  128. </el-form-item>
  129. <el-form-item label="期望薪资">
  130. <el-input placeholder="请输入期望薪资" v-model="uploadForm.delivererExpectSalary" maxlength="200" show-word-limit></el-input>
  131. </el-form-item>
  132. <el-form-item label="工作年限">
  133. <el-select v-model="uploadForm.delivererWorkExp" class="select" placeholder="请选择工作年限">
  134. <el-option v-for="item in expOptions" :key="item.value" :label="item.label" :value="item.value">
  135. </el-option>
  136. </el-select>
  137. </el-form-item>
  138. <el-form-item>
  139. <el-button @click="upload = false">取 消</el-button>
  140. <el-button type="primary" @click="handleSubmit">提 交</el-button>
  141. </el-form-item>
  142. </el-form>
  143. </el-dialog>
  144. <el-dialog :visible.sync="duplicate" width="90%" :before-close="()=>{duplicate=false}" :close-on-click-modal="false">
  145. <v-table :table="table" :tableList="duplicateList" :sortType="true" @update="update" @delete="handleDelete" readonly></v-table>
  146. </el-dialog>
  147. </div>
  148. </template>
  149. <script>
  150. export default {
  151. data () {
  152. let validator = (rule, value, callback) => {
  153. if (value === '') {
  154. callback(new Error('请输入手机号'))
  155. } else {
  156. if (!(/^1[3456789]\d{9}$/.test(value))) {
  157. callback(new Error('请输入正确的手机格式'))
  158. }
  159. callback()
  160. }
  161. }
  162. return {
  163. tableList: [],
  164. dialogFormVisible: false,
  165. dialogVisible: false,
  166. duplicate: false,
  167. upload: false,
  168. page: 1,
  169. totalrecords: 0,
  170. pickList: [],
  171. duplicateList: [],
  172. downList1: [],
  173. searchForm: {},
  174. form: {},
  175. uploadForm: {
  176. delivererName: '',
  177. delivererSex: 0,
  178. delivererBirthday: '',
  179. delivererPhone: '',
  180. delivererMail: '',
  181. delivererNationality: '',
  182. delivererAddress: '',
  183. delivererIntention: '',
  184. delivererEducation: '',
  185. delivererGrade: '',
  186. delivererLanguageAbility: '',
  187. delivererExpectSalary: '',
  188. delivererWorkExp: ''
  189. },
  190. options: [],
  191. addrOptions: [],
  192. expOptions: [
  193. {
  194. value: '1年以内工作经验',
  195. label: '1年以内工作经验'
  196. },
  197. {
  198. value: '1-3年工作经验',
  199. label: '1-3年工作经验'
  200. },
  201. {
  202. value: '3-5年工作经验',
  203. label: '3-5年工作经验'
  204. },
  205. {
  206. value: '5-10年工作经验',
  207. label: '5-10年工作经验'
  208. },
  209. {
  210. value: '10年以上工作经验',
  211. label: '10年以上工作经验'
  212. }
  213. ],
  214. rules: {
  215. delivererEducation: [{
  216. required: true,
  217. message: '请选择学历',
  218. trigger: 'change'
  219. }],
  220. delivererName: [{
  221. required: true,
  222. message: '请输入姓名',
  223. trigger: 'change'
  224. }],
  225. delivererPhone: [{
  226. required: true,
  227. validator,
  228. trigger: 'change'
  229. }],
  230. delivererMail: [{
  231. required: true,
  232. message: '请输入邮箱',
  233. trigger: 'change'
  234. }],
  235. delivererSex: [{
  236. required: true,
  237. message: '请选择性别',
  238. trigger: 'change'
  239. }],
  240. delivererWorkExp: [{
  241. required: true,
  242. message: '请填写工作经验',
  243. trigger: 'change'
  244. }],
  245. // desiredPositionId: [{
  246. // required: true,
  247. // message: '请选择应聘职位',
  248. // trigger: 'change'
  249. // }],
  250. positionApplied: [{
  251. required: true,
  252. message: '请填写投递职位',
  253. trigger: 'change'
  254. }]
  255. },
  256. positionList: [],
  257. info: {},
  258. list: [{
  259. placeholder: '请输入关键字查询',
  260. props: 'condition'
  261. },
  262. {
  263. type: 'select',
  264. placeholder: '性别',
  265. props: 'delivererSex',
  266. options: [{
  267. label: '全部',
  268. value: null
  269. }, {
  270. label: '男',
  271. value: 1
  272. }, {
  273. label: '女',
  274. value: 0
  275. }]
  276. },
  277. {
  278. type: 'select',
  279. placeholder: '来源',
  280. props: 'resumeFrom',
  281. options: [{
  282. label: '全部',
  283. value: null
  284. },
  285. {
  286. label: '51job',
  287. value: 0
  288. },
  289. {
  290. label: '智联',
  291. value: 1
  292. },
  293. {
  294. label: '58同城',
  295. value: 2
  296. },
  297. {
  298. label: '平台',
  299. value: 3
  300. },
  301. {
  302. label: 'boss直聘',
  303. value: 4
  304. }
  305. ]
  306. }
  307. ],
  308. btn: [{
  309. name: '确定',
  310. type: 'primary',
  311. method: 'search'
  312. },
  313. {
  314. name: '导出',
  315. type: 'primary',
  316. method: 'exports'
  317. },
  318. {
  319. name: '上传简历',
  320. type: 'primary',
  321. method: 'upload'
  322. },
  323. {
  324. name: '导入简历',
  325. type: 'upload',
  326. method: 'excel'
  327. }
  328. ],
  329. table: {
  330. selection: true,
  331. column: [{
  332. label: this.$t('field.serialNumber'),
  333. props: 'serialNumber'
  334. },
  335. {
  336. label: '姓名',
  337. props: 'delivererName',
  338. width: 60
  339. },
  340. {
  341. label: '性别',
  342. props: 'delivererSex',
  343. options: ['女', '男'],
  344. width: 60
  345. },
  346. {
  347. label: '简历来源',
  348. props: 'resumeFrom',
  349. options: ['51job', '智联招聘', '58同城', '平台', 'boss直聘'],
  350. width: 80
  351. },
  352. {
  353. label: '招聘类型',
  354. props: 'recruitType',
  355. options: ['社招', '校招', '直接校招'],
  356. width: 80
  357. },
  358. {
  359. label: '投递职位',
  360. props: 'positionApplied'
  361. },
  362. {
  363. label: '简历状态',
  364. props: 'state'
  365. },
  366. {
  367. label: '工作年限',
  368. props: 'delivererWorkExp'
  369. },
  370. {
  371. label: '学历',
  372. props: 'delivererEducation'
  373. },
  374. {
  375. label: '联系电话',
  376. props: 'delivererPhone'
  377. },
  378. {
  379. label: '邮箱',
  380. props: 'delivererMail'
  381. },
  382. {
  383. label: '应聘职位',
  384. props: 'positionName'
  385. },
  386. {
  387. label: '通知时间',
  388. props: 'sendMailTime'
  389. },
  390. {
  391. label: '完成时间',
  392. props: 'confirmInterviewTime'
  393. },
  394. {
  395. label: '面试状态',
  396. props: 'interviewStatus',
  397. options: ['未面试', '已面试']
  398. },
  399. {
  400. label: '面试结果',
  401. props: 'interviewResult',
  402. options: ['未读', '已通过', '已淘汰']
  403. }
  404. ],
  405. // fixed: true,
  406. width: 200,
  407. handle: [
  408. {
  409. title: '修改',
  410. method: 'update',
  411. type: 'warning'
  412. },
  413. {
  414. title: '去重',
  415. method: 'duplicate',
  416. type: 'primary',
  417. readonly: true
  418. },
  419. {
  420. title: '删除',
  421. method: 'delete',
  422. type: 'danger'
  423. }
  424. // {
  425. // title: '查看简历',
  426. // method: 'details',
  427. // type: 'info'
  428. // }
  429. ]
  430. }
  431. }
  432. },
  433. mounted () {
  434. this.queryData()
  435. this.queryDownList()
  436. this.handleOptions()
  437. },
  438. methods: {
  439. queryData (form = {}) {
  440. let page = this.page
  441. this.searchForm = form
  442. let reqdata = form
  443. this.$api
  444. .post('/resumeInfo/queryTalentPoolList', {
  445. reqdata,
  446. page
  447. })
  448. .then((res) => {
  449. this.totalrecords = res.totalrecords
  450. this.tableList = res.list.map((item, index) => {
  451. item.delivererSex = item.delivererSex - 0 || 0
  452. item.desiredPositionId = item.desiredPositionId - 0 || null
  453. item.serialNumber = (this.page - 1) * 10 + index + 1
  454. // item.desiredPositionId = item.desiredPositionId ? this.downList1.some(i => i.id === item.desiredPositionId) ? this.downList1.find(i => i.id === item.desiredPositionId).positionName : '' : ''
  455. item.state = item.interviewResult ? ['', '已通过', '未通过'][item.interviewResult] : item.isSendInviteMail ? '已通知' : ['未读', '通过', '淘汰', '待定'][item.isPass]
  456. return item
  457. })
  458. })
  459. },
  460. queryDownList () {
  461. this.$api
  462. .post('/position/queryPositionList', {
  463. reqdata: {}
  464. })
  465. .then((res) => {
  466. this.positionList = res.list.map((item) => ({
  467. value: item.id,
  468. label: item.positionName
  469. }))
  470. this.downList1 = res.list
  471. })
  472. },
  473. search (form) {
  474. this.queryData(form)
  475. },
  476. update (row) {
  477. this.openDia()
  478. this.form = Object.assign({}, row)
  479. },
  480. submit () {
  481. let a
  482. this.$refs['uform'].validate((valid) => {
  483. a = valid
  484. })
  485. if (!a) return
  486. let reqdata = this.form
  487. this.$api
  488. .post('/resumeInfo/updateResumeInfo', {
  489. reqdata
  490. })
  491. .then((res) => {
  492. this.$message({
  493. message: '修改成功!',
  494. type: 'success'
  495. })
  496. this.closeDia()
  497. this.queryData()
  498. if (this.duplicate) {
  499. this.handleDuplicateRefresh(reqdata)
  500. }
  501. })
  502. },
  503. details (row) {
  504. this.open()
  505. this.info = row
  506. },
  507. exports () {
  508. this.$api
  509. .post('/export/export2Web', {
  510. reqdata: this.searchForm
  511. })
  512. .then((res) => {
  513. })
  514. },
  515. openDia () {
  516. this.dialogVisible = true
  517. },
  518. closeDia () {
  519. this.dialogVisible = false
  520. this.form = {}
  521. },
  522. open () {
  523. this.dialogFormVisible = true
  524. },
  525. close () {
  526. this.dialogFormVisible = false
  527. this.form = {}
  528. },
  529. callPage (val) {
  530. this.page = val
  531. this.queryData(this.searchForm)
  532. },
  533. handleOptions () {
  534. this.options = ['不限', '英语', '日语', '俄语', '阿拉伯语', '法语', '德语', '西班牙语', '葡萄牙语', '意大利语', '韩语/朝鲜语', '普通话', '粤语', '闽南话', '上海话', '其他'].map(item => {
  535. return {
  536. label: item,
  537. value: item,
  538. children: [item + '-一般', item + '-良好', item + '-熟练', item + '-精通'].map(item => {
  539. return {
  540. label: item,
  541. value: item
  542. }
  543. })
  544. }
  545. })
  546. this.$api.post('/addr/all_addr').then(result => {
  547. this.addrOptions = result.list.map(item => (
  548. {
  549. name: item.name,
  550. children: item.children.map(item => ({
  551. name: item.name
  552. }))
  553. }
  554. ))
  555. })
  556. },
  557. handleSubmit () {
  558. const reg = /^\w+@[a-z0-9]+\.[a-z]{2,4}$/
  559. if (!reg.test(this.uploadForm.delivererMail)) {
  560. this.$message.error('请输入正确的邮箱')
  561. return false
  562. }
  563. this.$api.post('/resumeInfo/uploadResume', {
  564. reqdata: {
  565. ...this.uploadForm,
  566. delivererIntention: `${this.uploadForm.delivererIntention[0]} ${this.uploadForm.delivererIntention[1]}`
  567. }
  568. }).then(result => {
  569. this.upload = false
  570. this.uploadForm = {
  571. delivererName: '',
  572. delivererSex: 0,
  573. delivererBirthday: '',
  574. delivererPhone: '',
  575. delivererMail: '',
  576. delivererNationality: '',
  577. delivererAddress: '',
  578. delivererIntention: '',
  579. delivererEducation: '',
  580. delivererGrade: '',
  581. delivererLanguageAbility: '',
  582. delivererExpectSalary: '',
  583. delivererWorkExp: ''
  584. }
  585. this.queryData()
  586. })
  587. },
  588. handleExcel () {
  589. this.$api.post('/admin/resumeInfo/batchUploadResume').then(result => {
  590. this.$message.success('导入成功')
  591. this.queryData()
  592. })
  593. },
  594. handleDuplicate (param) {
  595. this.$api.post('/resumeInfo/duplicateResume', {
  596. reqdata: {
  597. ...param
  598. }
  599. }).then(result => {
  600. if (result.list && result.list.length) {
  601. this.$confirm(`检索到“${param.delivererName}”的疑似重复记录${result.list.length}条,是否查看?`, '提示', {
  602. confirmButtonText: '确定',
  603. cancelButtonText: '取消',
  604. type: 'warning'
  605. }).then(() => {
  606. this.duplicateList = result.list.map((item, index) => ({
  607. serialNumber: index + 1,
  608. state: item.interviewResult ? ['', '已通过', '未通过'][item.interviewResult] : item.isSendInviteMail ? '已通知' : ['未读', '通过', '淘汰', '待定'][item.isPass],
  609. ...item
  610. }))
  611. this.duplicate = true
  612. })
  613. }
  614. })
  615. },
  616. handleDuplicateRefresh (param) {
  617. this.$api.post('/resumeInfo/duplicateResume', {
  618. reqdata: {
  619. ...param
  620. }
  621. }).then(result => {
  622. this.duplicateList = result.list.map((item, index) => ({
  623. serialNumber: index + 1,
  624. state: item.interviewResult ? ['', '已通过', '未通过'][item.interviewResult] : item.isSendInviteMail ? '已通知' : ['未读', '通过', '淘汰', '待定'][item.isPass],
  625. ...item
  626. }))
  627. })
  628. },
  629. handleDelete (param) {
  630. this.$confirm(`确定删除该条简历吗?`, '提示', {
  631. confirmButtonText: '确定',
  632. cancelButtonText: '取消',
  633. type: 'warning'
  634. }).then(() => {
  635. this.$api.post('/resumeInfo/deleteResumeInfo', {
  636. reqdata: {
  637. resumeInfoStatusList: [{
  638. ...param,
  639. status: 1
  640. }]
  641. }
  642. }).then(result => {
  643. this.$message.success('删除成功')
  644. this.queryData()
  645. if (this.duplicate) {
  646. this.handleDuplicateRefresh(param)
  647. }
  648. })
  649. })
  650. }
  651. }
  652. }
  653. </script>