recommend.vue 17 KB

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