jobs_behalf_post.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. <template>
  2. <div>
  3. <div class="count-list" v-if="auditData">
  4. <div class="count-item">全部:{{count.all.total || 0}}</div>
  5. <div class="count-item">邮箱:{{count.all.email || 0}}</div>
  6. <div>短信:{{count.all.phone || 0}}</div>
  7. <el-divider direction="vertical"></el-divider>
  8. <div class="count-item">开放中:{{count.open.total || 0}}</div>
  9. <div class="count-item">邮箱:{{count.open.email || 0}}</div>
  10. <div>短信:{{count.open.phone || 0}}</div>
  11. <el-divider direction="vertical"></el-divider>
  12. <div class="count-item">累计新增下载量:{{count.add.total || 0}}</div>
  13. <div class="count-item">邮箱:{{count.add.email || 0}}</div>
  14. <div class="count-item">短信:{{count.add.phone || 0}}</div>
  15. <div>
  16. <el-button size="small" @click="onAdd">新建岗位</el-button>
  17. </div>
  18. </div>
  19. <div>
  20. <el-table :data="auditData" @row-click="clickRow" border style="width: 100%">
  21. <el-table-column prop="id" label="岗位ID" width="70"></el-table-column>
  22. <el-table-column prop="id" label="代发类型">
  23. <template slot-scope="scope">
  24. <span v-if="scope.row.issuedType == '1'">邮箱代发</span>
  25. <span v-else-if="scope.row.issuedType == '2'">短信代发</span>
  26. <span v-else>-</span>
  27. </template>
  28. </el-table-column>
  29. <el-table-column prop="occupationName" label="职位类型"></el-table-column>
  30. <el-table-column prop="workTypeName" label="工作方式"></el-table-column>
  31. <el-table-column label="工作周期">
  32. <template slot-scope="scope">
  33. <span>{{scope.row.month}}个月</span>
  34. </template>
  35. </el-table-column>
  36. <el-table-column label="驻场地区">
  37. <template slot-scope="scope">
  38. <span>{{scope.row.cityName || '-'}}</span>
  39. </template>
  40. </el-table-column>
  41. <el-table-column prop="salaryName" label="薪酬范围"></el-table-column>
  42. <el-table-column label="公司名称">
  43. <template slot-scope="scope">
  44. <span>{{scope.row.companyInfo && scope.row.companyInfo.shortName ? scope.row.companyInfo.shortName : (scope.row.companyInfo && scope.row.companyInfo.name ? scope.row.companyInfo.name : '')}}</span>
  45. </template>
  46. </el-table-column>
  47. <el-table-column prop="createdAt" label="发布时间">
  48. <template slot-scope="scope">
  49. <span>{{formatDate(scope.row.createdAt,'Y-m-d H:i')}}</span>
  50. </template>
  51. </el-table-column>
  52. <el-table-column prop="statusName" label="当前状态"></el-table-column>
  53. <el-table-column prop="countApplied" label="投递人数"></el-table-column>
  54. <el-table-column prop="recuitResult" label="是否激活">
  55. <template slot-scope="scope">
  56. <span v-if="scope.row.isActivation == '1'">是</span>
  57. <span v-else>否</span>
  58. </template>
  59. </el-table-column>
  60. <el-table-column prop="recuitResult" label="是否退订">
  61. <template slot-scope="scope">
  62. <span v-if="scope.row.isUnsubscribe == '1'">是</span>
  63. <span v-else>否</span>
  64. </template>
  65. </el-table-column>
  66. </el-table>
  67. </div>
  68. <div>
  69. <el-pagination
  70. class="order-footer"
  71. background
  72. layout="total, prev, pager, next"
  73. :page-size="20"
  74. :total="total"
  75. @current-change="handleCurrentChange"
  76. />
  77. </div>
  78. <el-dialog title="新建岗位" :visible.sync="agencyPost" :closeOnClickModal="false" :closeOnPressEscape="false">
  79. <el-form :model="agencyPostForm" :rules="rules" ref="agencyPostForm" label-width="100px" class="demo-ruleForm">
  80. <el-form-item label="代发类型" prop="workType">
  81. <el-radio-group v-model="agencyPostForm.issuedType">
  82. <el-radio :label="1">邮箱代发</el-radio>
  83. <el-radio :label="2">短信代发</el-radio>
  84. </el-radio-group>
  85. </el-form-item>
  86. <el-form-item label="目标邮箱" :prop="agencyPostForm.issuedType == 1?'email':''"
  87. v-if="agencyPostForm.issuedType == 1">
  88. <el-input v-model="agencyPostForm.email"></el-input>
  89. </el-form-item>
  90. <el-form-item label="手机号码" :prop="agencyPostForm.issuedType == 2?'phone':''"
  91. v-if="agencyPostForm.issuedType == 2">
  92. <el-input type="number" v-model="agencyPostForm.phone"></el-input>
  93. </el-form-item>
  94. <el-form-item label="企业名称" prop="name">
  95. <el-input v-model="agencyPostForm.name"></el-input>
  96. </el-form-item>
  97. <el-form-item label="工作方式" prop="workType">
  98. <el-radio-group v-model="agencyPostForm.workType">
  99. <el-radio :label="1">兼职</el-radio>
  100. <el-radio :label="2">驻场</el-radio>
  101. <el-radio :label="3">全职</el-radio>
  102. </el-radio-group>
  103. </el-form-item>
  104. <el-form-item label="工作地点" v-show="agencyPostForm.workType != 1">
  105. <el-cascader
  106. v-model="agencyPostForm.provIdcity"
  107. :options="areas"
  108. @change="cityChange"></el-cascader>
  109. </el-form-item>
  110. <el-form-item label="职位类型" prop="positionType">
  111. <el-cascader
  112. v-model="agencyPostForm.positionType"
  113. :options="positionType"
  114. @change="positionChange"></el-cascader>
  115. </el-form-item>
  116. <el-form-item label="薪资范围" prop="minSalary">
  117. <el-row>
  118. <el-col :span="8">
  119. <el-select v-model="agencyPostForm.minSalary" placeholder="请选择">
  120. <el-option
  121. v-for="item in minSalary"
  122. :key="item.value"
  123. :label="item.label"
  124. :value="item.value">
  125. </el-option>
  126. </el-select>
  127. </el-col>
  128. <el-col :span="2" :offset="2">
  129. </el-col>
  130. <el-col :span="8" :offset="2">
  131. <el-select v-model="agencyPostForm.maxSalary" placeholder="请选择">
  132. <el-option
  133. v-for="item in maxSalary"
  134. :key="item.value"
  135. :label="item.label"
  136. :value="item.value">
  137. </el-option>
  138. </el-select>
  139. </el-col>
  140. </el-row>
  141. </el-form-item>
  142. <el-form-item label="工作周期">
  143. <el-select v-model="agencyPostForm.month" placeholder="请选择">
  144. <el-option
  145. v-for="item in month"
  146. :key="item.value"
  147. :label="item.label"
  148. :value="item.value">
  149. </el-option>
  150. </el-select>
  151. </el-form-item>
  152. <el-form-item label="技能要求" prop="skills">
  153. <el-select
  154. v-model="agencyPostForm.skills"
  155. multiple
  156. filterable
  157. remote
  158. reserve-keyword
  159. placeholder="请输入关键词"
  160. :remote-method="remoteMethod"
  161. :loading="loading">
  162. <el-option
  163. v-for="item in skillsData"
  164. :key="item.id"
  165. :label="item.name"
  166. :value="item.id">
  167. </el-option>
  168. </el-select>
  169. </el-form-item>
  170. <el-form-item label="经验要求" prop="experience">
  171. <el-radio-group v-model="agencyPostForm.experience">
  172. <el-radio :label="0">不限</el-radio>
  173. <el-radio :label="1">3-5年</el-radio>
  174. <el-radio :label="2">5-10年</el-radio>
  175. <el-radio :label="3">10年以上</el-radio>
  176. </el-radio-group>
  177. </el-form-item>
  178. <el-form-item label="工作说明" prop="description">
  179. <el-input type="textarea" v-model="agencyPostForm.description" placeholder="请输入内容"
  180. minlength="5"
  181. maxlength="5000" rows="5"
  182. show-word-limit></el-input>
  183. </el-form-item>
  184. </el-form>
  185. <div slot="footer" class="dialog-footer">
  186. <el-button @click="agencyPost = false">取 消</el-button>
  187. <el-button type="primary" @click="checkForm('agencyPostForm')">确认发布</el-button>
  188. </div>
  189. </el-dialog>
  190. </div>
  191. </template>
  192. <script>
  193. export default {
  194. data() {
  195. return {
  196. page: 1,
  197. total: 0,
  198. auditData: [],
  199. agencyPost: false,
  200. loading: false,
  201. agencyPostForm: {
  202. // workType: 2, skills: [11815],issuedType:1
  203. workType: 2, skills: [], issuedType: 1
  204. },
  205. rules: {
  206. email: [
  207. {required: true, message: '请输入目标邮箱', trigger: 'blur'},
  208. {type: 'email', message: '邮箱格式不正确', trigger: 'blur'}
  209. ],
  210. phone: [
  211. {required: true, message: '请输入手机号码', trigger: 'blur'},
  212. // {type: 'phone', message: '手机号码格式不正确', trigger: 'blur'}
  213. ],
  214. name: [
  215. {required: true, message: '请输入企业名称', trigger: 'blur'},
  216. {min: 3, max: 50, message: '长度在 3 到 50 个字符', trigger: 'blur'}
  217. ],
  218. workType: [
  219. {required: true, message: '请选择工作方式', trigger: 'blur'}
  220. ],
  221. positionType: [
  222. {required: true, message: '请选择职位类型', trigger: 'blur'}
  223. ],
  224. minSalary: [
  225. {required: true, message: '请选择薪资范围', trigger: 'blur'}
  226. ],
  227. maxSalary: [
  228. {required: true, message: '请选择薪资范围', trigger: 'blur'}
  229. ],
  230. skills: [
  231. {required: true, message: '请选择技能要求', trigger: 'blur'}
  232. ],
  233. experience: [
  234. {required: true, message: '请选择经验要求', trigger: 'blur'}
  235. ],
  236. description: [
  237. {required: true, message: '请输入工作说明', trigger: 'blur'},
  238. {min: 5, max: 5000, message: '长度在 5 到 5000 个字符', trigger: 'blur'}
  239. ],
  240. },
  241. minSalary: [
  242. {
  243. value: '1',
  244. label: '1'
  245. }, {
  246. value: '2',
  247. label: '2'
  248. }, {
  249. value: '3',
  250. label: '3'
  251. }, {
  252. value: '4',
  253. label: '4'
  254. }, {
  255. value: '5',
  256. label: '5'
  257. }, {
  258. value: '6',
  259. label: '6'
  260. }, {
  261. value: '7',
  262. label: '7'
  263. }, {
  264. value: '8',
  265. label: '8'
  266. }, {
  267. value: '9',
  268. label: '9'
  269. }, {
  270. value: '10',
  271. label: '10'
  272. }, {
  273. value: '15',
  274. label: '15'
  275. }, {
  276. value: '20',
  277. label: '20'
  278. }, {
  279. value: '25',
  280. label: '25'
  281. }, {
  282. value: '30',
  283. label: '30'
  284. }, {
  285. value: '50',
  286. label: '50'
  287. }, {
  288. value: '100',
  289. label: '100'
  290. }, {
  291. value: '200',
  292. label: '200'
  293. }, {
  294. value: '-1',
  295. label: '面议'
  296. },
  297. ],
  298. maxSalary: [
  299. {
  300. value: '2',
  301. label: '2'
  302. }, {
  303. value: '3',
  304. label: '3'
  305. }, {
  306. value: '4',
  307. label: '4'
  308. }, {
  309. value: '5',
  310. label: '5'
  311. }, {
  312. value: '6',
  313. label: '6'
  314. }, {
  315. value: '7',
  316. label: '7'
  317. }, {
  318. value: '8',
  319. label: '8'
  320. }, {
  321. value: '9',
  322. label: '9'
  323. }, {
  324. value: '10',
  325. label: '10'
  326. }, {
  327. value: '15',
  328. label: '15'
  329. }, {
  330. value: '20',
  331. label: '20'
  332. }, {
  333. value: '25',
  334. label: '25'
  335. }, {
  336. value: '30',
  337. label: '30'
  338. }, {
  339. value: '50',
  340. label: '50'
  341. }, {
  342. value: '100',
  343. label: '100'
  344. }, {
  345. value: '200',
  346. label: '200'
  347. }, {
  348. value: '500',
  349. label: '500'
  350. },
  351. ],
  352. month: [
  353. {
  354. value: '1',
  355. label: '1'
  356. }, {
  357. value: '2',
  358. label: '2'
  359. }, {
  360. value: '3',
  361. label: '3'
  362. }, {
  363. value: '4',
  364. label: '4'
  365. }, {
  366. value: '5',
  367. label: '5'
  368. }, {
  369. value: '6',
  370. label: '6'
  371. }, {
  372. value: '7',
  373. label: '7'
  374. }, {
  375. value: '8',
  376. label: '8'
  377. }, {
  378. value: '9',
  379. label: '9'
  380. }, {
  381. value: '10',
  382. label: '10'
  383. }, {
  384. value: '11',
  385. label: '11'
  386. }, {
  387. value: '12',
  388. label: '12'
  389. },
  390. ],
  391. //配置
  392. options: [],
  393. areas: [], //工作地点
  394. positionType: [], //职位类型
  395. skillsData: [], //技能类型
  396. count: {
  397. all:{},
  398. open:{},
  399. add:{}
  400. }
  401. };
  402. },
  403. mounted() {
  404. this.getAuditList();
  405. this.getOptions();
  406. },
  407. methods: {
  408. async getAuditList() {
  409. const page = this.page;
  410. const data = {
  411. page
  412. };
  413. let res = await this.$post("/api/admin/recruit/getAuditAgencyPostList", data);
  414. if (res && res.status === 1) {
  415. this.auditData = res.data.list || [];
  416. this.count = res.data.countData || {
  417. all:{},
  418. open:{},
  419. add:{}
  420. };
  421. this.total = res.data.total * 1;
  422. }
  423. },
  424. formatDate(time, format = '') {
  425. if (time === "0") {
  426. return "--";
  427. }
  428. let now = new Date(time * 1000);
  429. let year = now.getFullYear();
  430. let month = now.getMonth() + 1;
  431. let date = now.getDate();
  432. let hour = now.getHours();
  433. let minute = now.getMinutes();
  434. let second = now.getSeconds();
  435. if (hour < 10) {
  436. hour = "0" + hour;
  437. }
  438. if (minute < 10) {
  439. minute = "0" + minute;
  440. }
  441. if (second < 10) {
  442. second = "0" + second;
  443. }
  444. return (format == '' ?
  445. year +
  446. "-" +
  447. month +
  448. "-" +
  449. date +
  450. " " +
  451. hour +
  452. ":" +
  453. minute +
  454. ":" +
  455. second
  456. :
  457. year +
  458. "-" +
  459. month +
  460. "-" +
  461. date +
  462. " " +
  463. hour +
  464. ":" +
  465. minute
  466. );
  467. },
  468. async getOptions() {
  469. let res = await this.$post("/api/recruit/getOptions");
  470. if (res && res.status === 1) {
  471. this.options = res.data || [];
  472. this.getAreas();
  473. this.getPositionType();
  474. }
  475. },
  476. async getSkills(query) {
  477. let data = {
  478. keyword: query,
  479. limit: 20
  480. };
  481. let res = await this.$post("/api/simple_data/select_skill", data);
  482. if (res && res.status === 1) {
  483. this.skillsData = res.data || [];
  484. } else {
  485. this.skillsData = [];
  486. }
  487. },
  488. getAreas() {
  489. let provinces = this.options.provinces;
  490. let cities = this.options.cities;
  491. let data = [];
  492. let id, dd, c;
  493. for (let i = 0; i < provinces.length; i++) {
  494. id = provinces[i].id;
  495. let arr = {
  496. value: id,
  497. label: provinces[i].name,
  498. children: (function () {
  499. c = 0;
  500. dd = [];
  501. for (let j = 0; j < cities.length; j++) {
  502. if (cities[j].prov_id == id) {
  503. let arr1 = {
  504. value: cities[j].id,
  505. label: cities[j].name
  506. };
  507. dd[c] = arr1;
  508. c++;
  509. }
  510. }
  511. return dd;
  512. })()
  513. };
  514. data[i] = arr;
  515. }
  516. this.areas = data;
  517. },
  518. getPositionType() {
  519. let positionType = this.options.direction;
  520. let arr = [];
  521. for (let i = 0; i < positionType.length; i++) {
  522. let d = {
  523. value: positionType[i].occupation_id,
  524. label: positionType[i].occupation_name,
  525. children: (function () {
  526. if (positionType[i].children.length > 0) {
  527. let a = [];
  528. for (let j = 0; j < positionType[i].children.length; j++) {
  529. a[j] = {
  530. value: positionType[i].children[j].direction_id,
  531. label: positionType[i].children[j].direction_name,
  532. }
  533. }
  534. return a;
  535. }
  536. })()
  537. };
  538. arr[i] = d;
  539. }
  540. this.positionType = arr;
  541. },
  542. remoteMethod(query) {
  543. if (query !== '') {
  544. this.loading = true;
  545. setTimeout(() => {
  546. this.loading = false;
  547. this.getSkills(query);
  548. }, 200);
  549. } else {
  550. this.skillsData = [];
  551. }
  552. },
  553. cityChange(value) {
  554. if (!value) return;
  555. this.agencyPostForm.provId = value[0];
  556. this.agencyPostForm.cityId = value[1];
  557. },
  558. positionChange(value) {
  559. if (!value) return;
  560. this.agencyPostForm.occupationId = value[0];
  561. this.agencyPostForm.directionId = value[1];
  562. },
  563. checkForm(formName) {
  564. this.$refs[formName].validate((valid) => {
  565. if (valid) {
  566. this.submitForm();
  567. } else {
  568. console.log('error submit!!');
  569. return false;
  570. }
  571. });
  572. },
  573. async submitForm() {
  574. let formData = this.agencyPostForm;
  575. let data = {
  576. issuedType: formData.issuedType,
  577. phone: formData.phone,
  578. email: formData.email,
  579. name: formData.name,
  580. occupationId: formData.occupationId,
  581. directionId: formData.directionId,
  582. minSalary: formData.minSalary,
  583. maxSalary: formData.maxSalary,
  584. month: formData.month,
  585. skills: formData.skills,
  586. experience: formData.experience,
  587. workType: formData.workType,
  588. cityId: formData.cityId,
  589. provId: formData.provId,
  590. description: formData.description
  591. };
  592. let res = await this.$post("/api/admin/recruit/addRecruit", data);
  593. if (res && res.status === 1) {
  594. this.agencyPost = false;
  595. this.agencyPostForm = {
  596. workType: 2, skills: [], issuedType: 1
  597. };
  598. this.getAuditList();
  599. this.$message({
  600. type: "success",
  601. message: "添加成功!"
  602. });
  603. }
  604. },
  605. async handleApproveClick(recruitId) {
  606. const action = "approve";
  607. const data = {
  608. recruitId,
  609. action
  610. };
  611. let res = await this.$post("/api/admin/recruit/audit", data);
  612. if (res && res.status === 1) {
  613. console.log(res);
  614. this.$message({
  615. message: res.info,
  616. type: "success"
  617. });
  618. this.getAuditList();
  619. }
  620. },
  621. handleCurrentChange(val) {
  622. this.page = val;
  623. this.getAuditList();
  624. },
  625. clickRow(row) {
  626. const id = row.id;
  627. this.$router.push({
  628. path: "/main/job",
  629. query: {
  630. id
  631. }
  632. });
  633. },
  634. onAdd() {
  635. this.agencyPost = true;
  636. }
  637. }
  638. };
  639. </script>
  640. <style lang="scss" scoped>
  641. .count-list {
  642. padding-bottom: 10px;
  643. display: flex;
  644. align-items: center;
  645. }
  646. .count-item {
  647. margin-right: 20px;
  648. font-size: 16px;
  649. }
  650. .content {
  651. white-space: nowrap;
  652. overflow-x: scroll;
  653. height: calc(100% - 150px);
  654. }
  655. .btn {
  656. width: 80px;
  657. }
  658. .order-footer {
  659. margin-top: 10px;
  660. }
  661. </style>