recommend.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. <template>
  2. <div style="width: 90%; margin:0 auto" >
  3. <div class="zhiyuan-filter">
  4. <div class="header">
  5. <h3 class="f-666">您的选考科目为:<em>{{ formSubject.firstSubject }}<em v-for="item in formSubject.lastSubject"
  6. >,{{ item }}</em> </em>, 请手动选择志愿</h3>
  7. </div>
  8. <div class="filters">
  9. <!-- 院校筛选条件 -->
  10. <filter-form :filter="filter_form" :levelHide="true"></filter-form>
  11. <!--其他筛选 -->
  12. <el-row class="radioInput">
  13. <div>
  14. <span class="radiaTitle">院校层次:</span>
  15. </div>
  16. <el-radio-group v-model="filter_form.pickType">
  17. <el-radio-button label="">所有</el-radio-button>
  18. <el-radio-button v-for="item in localFilters.picks" :key="item.value" :label="item.value" style="margin-bottom:10px"
  19. >
  20. {{ item.label }}
  21. </el-radio-button>
  22. </el-radio-group>
  23. </el-row>
  24. <!-- 专业 -->
  25. <el-row class="radioInput">
  26. <div>
  27. <span class="radiaTitle">专业类别:</span>
  28. </div>
  29. <el-radio-group v-model="currentMajor">
  30. <el-radio-button label="">
  31. <span @click="clear">所有</span></el-radio-button>
  32. <el-radio-button v-for="item in majorList" :key="item.code" :label="item.code" style="margin-bottom:10px">
  33. {{ item.name }}
  34. </el-radio-button>
  35. </el-radio-group>
  36. </el-row>
  37. <!-- 专业子类 -->
  38. <el-row class="radioInput filter" v-if="childrenMajors.length">
  39. <div>
  40. <span class="radiaTitle"></span>
  41. </div>
  42. <div class="items fx-row">
  43. <div class="no_limited">
  44. <el-checkbox @change="changeAll" v-model="isAll">全部</el-checkbox>
  45. </div>
  46. <el-checkbox-group v-model="checkedList" :max="10">
  47. <el-checkbox v-for="item in childrenMajors" :label="item.code" :key="item.code">{{item.name}}</el-checkbox>
  48. </el-checkbox-group>
  49. </div>
  50. </el-row>
  51. </div>
  52. <div class="selected">
  53. <span class="f14 f-666">您已选择:</span>
  54. <div class="tags" style="width: 100%">
  55. <el-tag @close="handleClose(item)" type="success" class="mr5 mb5" closable v-for="item in checkedListName">{{item.name}}</el-tag>
  56. </div>
  57. <el-button plain size="mini" @click="getList">确认</el-button>
  58. <el-button plain size="mini" @click="clear">清除</el-button>
  59. </div>
  60. </div>
  61. <div class="zhiyuan-list">
  62. <zhiyuan-list :tableList="rows" @apply="apply" :cols="cols" @expand="expand"></zhiyuan-list>
  63. </div>
  64. <div :class="{'active':show,'right_cart': true}" >
  65. <div class="btn-wrap" @click="show = !show">
  66. 当前志愿表
  67. </div>
  68. <transition name="content">
  69. <div class="content-wrap">
  70. <!-- <el-input class="input" v-model="input" placeholder="院校/专业搜索"></el-input>-->
  71. <div class="content">
  72. <div class="list-item" v-for="(college,collegeIndex) in this.formatZhiyuan">
  73. <div class="head-college f16">
  74. <el-tag type="success" size="mini" class="mr12">{{ collegeIndex + 1 }}</el-tag>
  75. {{ `${college.university.name}(${college.recruitPlan.collegeCode })` }}
  76. <i class="el-icon-delete delete-icon"></i>
  77. </div>
  78. <div class="majors f12">
  79. <div class="major mt10" v-for="(major,majorIndex) in college.majors">
  80. <span class="mr12 ml10">{{majorIndex + 1}}</span>
  81. {{major.marjorName}}
  82. <i class="el-icon-delete delete-icon" @click="deleteMajor(major)"></i>
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. <div class="btn">
  88. <el-button style="width: 100%;height: 30px" type="primary" @click="save">保存志愿表</el-button>
  89. </div>
  90. </div>
  91. </transition>
  92. </div>
  93. </div>
  94. </template>
  95. <script>
  96. import FilterForm from '@/views/career/components/FilterForm';
  97. import { Debounce, Throttle } from '@/utils/common.js'
  98. import ZhiyuanList from '@/views/career/zhiyuan/components/zhiyuan-list';
  99. import { allMajor,getRecommendVoluntary,getVoluntaryMarjors,getVoluntaryHeaders,saveZhiyuan } from '@/api/webApi/professlib'
  100. export default {
  101. props: {
  102. formSubject: {
  103. type: Object,
  104. default: {}
  105. },
  106. batch: {
  107. type: Object,
  108. default: {}
  109. }
  110. },
  111. components:{
  112. FilterForm,
  113. ZhiyuanList
  114. },
  115. data() {
  116. return {
  117. indeterminate:false,
  118. checkedList:[],
  119. filter_form:{
  120. location:'',
  121. natureTypeCN:'',
  122. type:'',
  123. features:'',
  124. pickType:'',
  125. },
  126. currentMajor:'',
  127. majorList:[],
  128. show: false,
  129. localFilters: {
  130. picks: [
  131. { label: '冲刺型', value: '0' },
  132. { label: '稳妥型', value: '1' },
  133. { label: '保守型', value: '2' }
  134. ]
  135. },
  136. pageForm: {
  137. pageSize: 10,
  138. pageNum:1
  139. },
  140. total: 0,
  141. rows: [],
  142. cols: [],
  143. selectedList:[],
  144. loading:false
  145. }
  146. },
  147. created() {
  148. this.$nextTick(_ => {
  149. this.getAllMajor()
  150. this.getList()
  151. this.getCols()
  152. })
  153. },
  154. mounted() {
  155. let dom = document.querySelector(".el-table__body-wrapper");
  156. console.log(dom)
  157. dom.addEventListener("scroll", (v) => {
  158. const scrollDistance = dom.scrollHeight - dom.scrollTop - dom.clientHeight;
  159. console.log('scrollDistance',scrollDistance)
  160. // 判断是否到底,可以加载下一页
  161. if (scrollDistance <= 10) {
  162. this.load()
  163. }
  164. });
  165. },
  166. watch:{
  167. filter_form:{
  168. deep:true,
  169. handler(){
  170. this.getList()
  171. }
  172. },
  173. selectedList:{
  174. deep:true,
  175. handler(selectedList){
  176. const index= selectedList.findIndex(item => { return item.majors.filter(major =>{ return major.selected }).length <= 0 })
  177. if(index != -1) {
  178. this.selectedList.splice(index,1)
  179. }
  180. }
  181. }
  182. },
  183. computed: {
  184. // 所有二级
  185. majorAllChildren() {
  186. let arr = []
  187. this.majorList.map(item => {
  188. arr = [...arr,...item.children]
  189. })
  190. return arr
  191. },
  192. checkedListName() {
  193. return this.majorAllChildren.filter(item => {
  194. return this.checkedList.findIndex(code => code == item.code) != -1
  195. }) || []
  196. },
  197. childrenMajors() {
  198. if(!this.currentMajor) return []
  199. return this.majorList.find(item => {
  200. return item.code == this.currentMajor
  201. }).children || []
  202. },
  203. formatZhiyuan() {
  204. if(!this.selectedList.length) return []
  205. return this.selectedList.map(item => {
  206. return {
  207. university: item.university,
  208. majors:item.majors.filter(major =>{ return major.selected }),
  209. recruitPlan: item.recruitPlan
  210. }
  211. }).filter(item => {
  212. return item.majors.length > 0
  213. })
  214. },
  215. isAll:{
  216. get(){
  217. // 当前children 全选
  218. let count = 0
  219. const childrenMajors = this.childrenMajors
  220. this.checkedList.forEach(item => {
  221. if(childrenMajors.findIndex(major => {return major.code == item}) != -1){
  222. count++
  223. }
  224. })
  225. console.log('选中数',count)
  226. return count == childrenMajors.length
  227. },
  228. set(){
  229. }
  230. },
  231. },
  232. methods: {
  233. load() {
  234. if (Math.ceil(this.total / this.pageForm.pageSize) > this.pageForm.pageNum) {
  235. // 标识正在请求
  236. // 加载下一页方法
  237. if(!this.loading){
  238. //当前页数小于总页数就请求
  239. this.pageForm.pageNum++; //当前页数自增
  240. this.getList('push')
  241. }
  242. }else {
  243. this.$message.warning("已经见底了 ~");
  244. }
  245. },
  246. save(){
  247. const wishes = this.selectedList.map(item =>{
  248. return {
  249. universityId:item.university.id,
  250. collegeCode: item.recruitPlan.collegeCode,
  251. code:item.university.code,
  252. name:item.university.name,
  253. marjors:item.majors.filter(major => {return major.selected}).map(major=> {
  254. return {
  255. id: major.id,
  256. code: major.marjorBelongs,
  257. name: major.marjorName,
  258. }
  259. })
  260. }
  261. })
  262. const data = {
  263. batch: this.batch.batch,
  264. detail:{
  265. batch:{
  266. batch:this.batch.batch,
  267. name:this.batch.name,
  268. recommand: true,
  269. scores:[],
  270. wishes:wishes,
  271. },
  272. mode:`${this.formSubject.firstSubject},${this.formSubject.lastSubject}`,
  273. score:this.batch.score1
  274. },
  275. id: 0,
  276. name: ''
  277. }
  278. saveZhiyuan(data).then(res =>{
  279. this.$router.push({ name:'VolunteerList' })
  280. })
  281. },
  282. apply(item,index) {
  283. // 有无院校 ?
  284. const codeFlag = this.selectedList.find(item => item.recruitPlan.collegeCode == this.rows[index].recruitPlan.collegeCode)
  285. console.log(!codeFlag)
  286. if(!codeFlag){
  287. this.selectedList.push(this.rows[index])
  288. }
  289. item.selected = !item.selected
  290. },
  291. deleteMajor(major){
  292. major.selected = false
  293. },
  294. expand(item) {
  295. console.log(item)
  296. if(item.isExpand) {
  297. // 取消
  298. return
  299. }else {
  300. item.isExpand = true
  301. this.getVoluntaryMarjors(item)
  302. }
  303. },
  304. getCols() {
  305. getVoluntaryHeaders({
  306. mode:`${this.formSubject.firstSubject},${this.formSubject.lastSubject}`,
  307. year: this.batch.year
  308. }).then(res => {
  309. this.cols = res.data
  310. })
  311. },
  312. getList(type) {
  313. this.loading = true
  314. const data = {
  315. batchName: this.batch.name,
  316. batch: this.batch.batch,
  317. majors: this.checkedList,
  318. mode: `${this.formSubject.firstSubject},${this.formSubject.lastSubject}`,
  319. // mode1: string,
  320. pickType: this.filter_form.pickType,
  321. // "rank": 0,
  322. score: this.formSubject.score,
  323. university: {
  324. // "code": "string",
  325. features: this.filter_form.features,
  326. level: this.filter_form.level,
  327. location: this.filter_form.location,
  328. type: this.filter_form.type,
  329. natureTypeCN: this.filter_form.natureTypeCN,
  330. // "status": 0,
  331. // "type": "string"
  332. },
  333. }
  334. getRecommendVoluntary({ ...data }, { ...this.pageForm }).then(res =>{
  335. console.log(res)
  336. this.total = res.total
  337. let rows = {}
  338. rows = res.rows.map(item => {
  339. item.isExpand = false
  340. item.majors = []
  341. return item
  342. })
  343. // 回显
  344. if(this.selectedList.length) {
  345. rows = rows.map(row => {
  346. const flagIndex = this.selectedList.findIndex(selected => {
  347. return selected.recruitPlan.collegeCode == row.recruitPlan.collegeCode
  348. })
  349. if(flagIndex == -1) {
  350. return row
  351. }else {
  352. return this.selectedList[flagIndex]
  353. }
  354. })
  355. }
  356. if(type == 'push') {
  357. this.rows.push(...rows)
  358. return
  359. }
  360. this.rows = rows
  361. }).finally(_ => {
  362. this.loading = false
  363. })
  364. },
  365. getVoluntaryMarjors(item) {
  366. getVoluntaryMarjors(
  367. {
  368. batchName: this.batch.name,
  369. collegeCode: item.recruitPlan.collegeCode,
  370. mode: this.formSubject.firstSubject,
  371. universityId: item.recruitPlan.universityId,
  372. year: item.recruitPlan.year,}
  373. ).then(res => {
  374. item.majors = res.data.map(item => {
  375. item.selected = false
  376. return item
  377. })
  378. console.log(res)
  379. })
  380. },
  381. handleClose(item) {
  382. const index = this.checkedList.findIndex(code => code == item.code)
  383. this.checkedList.splice(index,1)
  384. },
  385. clear() {
  386. if(!this.checkedList.length) return
  387. this.checkedList = []
  388. this.getList()
  389. },
  390. changeAll(val){
  391. const checkedList = this.checkedList
  392. if(val) {
  393. // 添加
  394. this.childrenMajors.forEach(item => {
  395. if(this.checkedList.length >= 10) {
  396. this.$message.warning('最多选择10个专业')
  397. throw Error('最多选择10个专业')
  398. }
  399. if(this.checkedList.findIndex(code => code == item.code) == -1 ){
  400. this.checkedList.push(item.code)
  401. }
  402. })
  403. }else {
  404. // 移除
  405. this.childrenMajors.forEach(item => {
  406. for (let i = 0; i < checkedList.length; i++) {
  407. if(item.code == checkedList[i]){
  408. this.checkedList.remove(item.code)
  409. }
  410. }
  411. })
  412. }
  413. console.log(val)
  414. },
  415. handleCheckAllChange(val) {
  416. this.isIndeterminate = false;
  417. },
  418. getAllMajor(){
  419. allMajor({
  420. level:2,
  421. batch:this.batch.batch
  422. }).then(res => {
  423. this.majorList = res.data
  424. console.log(res)
  425. })
  426. },
  427. }
  428. }
  429. </script>
  430. <style scoped lang="scss">
  431. .more span {
  432. margin-right: 10px;
  433. }
  434. .selected{
  435. display: flex;
  436. align-items: center;
  437. justify-content: space-between;
  438. padding: 10px;
  439. margin-bottom: 20px;
  440. background: #42b98340;
  441. span{
  442. flex-shrink: 0;
  443. }
  444. }
  445. .filters {
  446. padding: 10px 0px;
  447. border: 1px solid #eee;
  448. }
  449. .delete-icon{
  450. float: right;
  451. cursor: pointer;
  452. }
  453. .filter_name {
  454. box-sizing: border-box;
  455. width: 70px;
  456. font-size: 14px;
  457. line-height: 20px;
  458. flex: none;
  459. padding: 6px 0 6px 0;
  460. margin-right: 10px;
  461. }
  462. .zhiyuan-filter .filters .filter .items .no_limited {
  463. margin-right: 10px;
  464. }
  465. .zhiyuan-filter .filters .filter .items .no_limited ::v-deep .el-checkbox__input {
  466. display: none;
  467. }
  468. .filters .filter {
  469. padding: 10px 0;
  470. display: flex;
  471. border-bottom: 1px solid #eee;
  472. }
  473. .filters .filter:last-child {
  474. border-bottom: 0;
  475. }
  476. .zhiyuan-filter .filters .filter ::v-deep .el-checkbox, .zhiyuan-filter .filters .filter ::v-deep .el-radio {
  477. -webkit-box-sizing: border-box;
  478. box-sizing: border-box;
  479. height: 32px;
  480. padding: 8px 8px;
  481. margin: 0;
  482. }
  483. em {
  484. font-weight: 400;
  485. font-style: normal;
  486. }
  487. ::v-deep .el-input--medium .el-input__inner {
  488. height: 30px;
  489. line-height: 30px;
  490. }
  491. ::v-deep .el-input {
  492. width: 260px;
  493. }
  494. .radioInput ::v-deep {
  495. background-color: #ffffff;font-size: 14px;padding:5px;
  496. .el-radio {
  497. .el-radio__input {
  498. display: none;
  499. }
  500. }
  501. }
  502. .radioInput ::v-deep {
  503. display: flex;
  504. .el-radio-button .el-radio-button__inner {
  505. border-radius: 4px !important;
  506. border: none;
  507. padding: 5px 10px !important;
  508. font-weight: 400;
  509. font-family: PingFangSC-Regular, PingFang SC;
  510. }
  511. .el-radio-button__orig-radio:checked + .el-radio-button__inner {
  512. box-shadow: none;
  513. }
  514. .radiaTitle {
  515. display: inline-block;
  516. width: 80px;
  517. font-size: 14px;
  518. text-align: right;
  519. margin-top: 2px;
  520. margin-right: 10px;
  521. }
  522. }
  523. .right_cart{
  524. position: fixed;
  525. top: 50%;
  526. right: -320px;
  527. transform: translate(0%,-50%);
  528. transition: all 1s ease;
  529. }
  530. .active{
  531. right: 0;
  532. }
  533. .right_cart{
  534. display: flex;
  535. z-index: 9999;
  536. }
  537. .right_cart .btn-wrap{
  538. cursor: pointer;
  539. align-self: baseline;
  540. border-radius: 5px 0 0 5px;
  541. color: white;
  542. background: #42b983;
  543. width: 30px;
  544. text-align: center;
  545. font-size: 16px;
  546. padding: 7px;
  547. }
  548. .content-wrap{
  549. padding: 10px 0;
  550. background: #fff;
  551. width: 320px;
  552. height: 400px;
  553. display: flex;
  554. flex-direction: column;
  555. border: 1px solid #f2f2f2;
  556. }
  557. .content{
  558. height: 100%;
  559. overflow-y: auto;
  560. padding: 0 20px
  561. }
  562. .content-wrap .input{
  563. padding: 0 15px;
  564. }
  565. .content-wrap .btn{
  566. width: 100% ;
  567. padding: 0 15px;
  568. }
  569. .list-item{
  570. margin-bottom: 10px;
  571. border-bottom: 1px solid #e6e6e6;
  572. padding-bottom: 20px;
  573. }
  574. .mask{
  575. z-index: 2009;
  576. position: absolute;
  577. top: 0;
  578. right: 0;
  579. bottom: 0;
  580. left: 0;
  581. overflow: auto;
  582. opacity: 0.5;
  583. margin: 0;
  584. }
  585. </style>