123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <template>
- <view>
- <z-paging ref="paging" v-model="list" @query="handleQuery">
- <template #top>
- <mx-nav-bar v-bind="navBinding"/>
- </template>
- <ai-form-filter @force="init=false,$refs.paging.reload()"/>
- <ai-form-filter-shortcut/>
- <view class="p-20 fx-col gap-20">
- <voluntary-major v-for="item in list" :data="item"/>
- </view>
- <template #bottom>
- <ai-form-footer :total="total" @preview="handlePreview"/>
- </template>
- <uv-loading-page :loading="loading"/>
- </z-paging>
- <ai-form-cart ref="cartRef"/>
- </view>
- </template>
- <script>
- import _ from 'lodash';
- import LargeHeader from "@/pages/ie/components/large-header.vue";
- import AiFormFooter from "@/pages/ie/entry-ai-form/components/ai-form-footer.vue";
- import AiFormFilter from "@/pages/ie/entry-ai-form/components/ai-form-filter.vue";
- import AiFormFilterShortcut from "@/pages/ie/entry-ai-form/components/ai-form-filter-shortcut.vue";
- import VoluntaryMajor from "../components/card/voluntary-major.vue";
- import AiFormCart from "./components/ai-form-cart.vue";
- import MxConst from "@/common/MxConst";
- import {postAIResult, submitVoluntary} from "@/api/webApi/ie-voluntary";
- import {sleep, toast} from "@/uni_modules/uv-ui-tools/libs/function";
- import {confirmAsync} from "@/utils/uni-helper";
- import {useTransfer} from "@/hooks/useTransfer";
- import {useProvidePageScroll} from "@/hooks/usePageScrollInjection";
- import {useProvideMajorTreeService} from "@/pages/ie/hooks/useMajorTreeInjection";
- export default {
- components: {AiFormFilterShortcut, AiFormFilter, AiFormFooter, LargeHeader, VoluntaryMajor, AiFormCart},
- data() {
- return {
- init: false,
- loading: false,
- navBinding: {title: 'AI志愿', mode: 'light', fixed: false, leftClickBlock: this.checkFormBeforeQuit},
- filter: {
- majorTypes: [],
- enumPickType: MxConst.enum.ai.pickType.all.value,
- enumPickEmpty: null,
- hasClearing: null,
- keyword: '',
- level: [],
- type: [],
- natureTypeCN: [],
- location: [],
- star: [],
- bxType: []
- },
- filterShortcut: [],
- config: {
- collegeMin: 2,
- collegeLimit: 5,
- majorLimit: 4,
- // 提交时仅保留的university属性,减少传输量
- commitUPropsKeep: ['code'],
- // 变更条件时,需要清空志愿表的filter属性,这些条件会影响专业概率
- confirmChangeFilterKeys: ['majorTypes', 'enumPickType', 'enumPickEmpty', 'hasClearing']
- },
- list: [],
- total: 0,
- // 填报项 // 包含:填报的院校引用,院校的专业用selected属性标记已填报
- selected: [],
- commit: {
- year: '', // 缺省的话后台会补充
- name: '', // 志愿表名,缺省的话后台会补充
- voluntaryType: MxConst.enum.ai.voluntaryType.ai,
- },
- showCart: false
- }
- },
- setup() {
- const {prevData, transferTo} = useTransfer()
- const scrollTop = useProvidePageScroll()
- return {
- prevData,
- transferTo,
- scrollTop
- }
- },
- computed: {
- request() {
- return {
- ...this.prevData,
- filter: this.filter
- }
- }
- },
- watch: {
- filter: {
- deep: true,
- handler: function () {
- this.init = false
- this.$refs.paging.reload()
- }
- }
- },
- provide() {
- return {
- getPrevData: () => this.prevData,
- getFilter: () => this.filter,
- getShortcut: () => this.filterShortcut,
- getConfig: () => this.config,
- getCart: () => this.selected,
- getCommit: () => this.commit,
- handleCartAdd: this.handleCartAdd,
- handleCartRemove: this.handleCartRemove,
- handleCartClear: this.handleCartClear,
- handleCommit: this.handleCommit
- }
- },
- methods: {
- checkFormBeforeQuit() {
- if (!this.selected.length) return true
- return confirmAsync('您有未保存的志愿表,确认退出?')
- },
- syncRowsToSelected(rows) {
- if (!Array.isArray(rows)) return
- rows.forEach(u => {
- // created `selected` property here, can make it reactive.
- u.majorDetails.forEach(m => m.selected = false)
- const match = this.selected.find(i => i.university.code == u.university.code)
- if (match && match.majorDetails.length == u.majorDetails.length &&
- match.majorDetails.every(m1 => u.majorDetails.some(m2 => m1.majorCode == m2.majorCode))) {
- // fully match, then copy major's selected property, and replace ele in cart.
- u.majorDetails.forEach(m => {
- const mMatch = match.majorDetails.find(item => item.majorCode == m.majorCode)
- m.selected = mMatch.selected
- })
- const replaceIdx = this.selected.indexOf(match)
- this.selected.splice(replaceIdx, 1, u)
- } else if (match) {
- throw new Error('query list not match with selected elements')
- }
- })
- },
- async handleQuery(pageNum, pageSize) {
- const params = {
- pageNum, pageSize,
- ...this.request
- }
- console.log('handle query', params)
- try {
- if (pageNum == 1 && !this.init) this.loading = true
- const res = await postAIResult(params)
- this.syncRowsToSelected(res.rows)
- this.$refs.paging.completeByTotal(res.rows, res.total)
- this.total = res.total
- this.loading = false
- } catch (e) {
- console.log('ai request failed', e)
- this.loading = false
- } finally {
- this.init = true
- }
- },
- handleCartAdd(uElement, mElement) {
- const uAddDisable = !this.selected.includes(uElement) && this.selected.length >= this.config.collegeLimit
- if (uAddDisable) {
- toast(`最多填报${this.config.collegeLimit}个院校`)
- return
- }
- const mAllSelected = uElement.majorDetails.filter(i => i.selected)
- const mAddDisable = !mAllSelected.includes(mElement) && mAllSelected.length >= this.config.majorLimit
- if (mAddDisable) {
- toast(`每个院校最多填报${this.config.majorLimit}个专业`)
- return
- }
- if (!this.selected.includes(uElement)) this.selected.push(uElement)
- mElement.selected = true
- },
- handleCartRemove(uElement, mElement) {
- if (!mElement) {
- // remove all
- uElement.majorDetails.forEach(m => m.selected = false)
- _.remove(this.selected, uElement)
- return
- }
- // remove indicate
- mElement.selected = false
- const anySelected = uElement.majorDetails.some(i => i.selected)
- if (!anySelected) _.pull(this.selected, uElement)
- },
- handleCartClear() {
- this.selected.forEach(u => u.majorDetails.forEach(m => m.selected = false))
- _.remove(this.selected)
- },
- handlePreview() {
- if (!this.selected.length) {
- toast('请先至少选择1个专业到志愿表')
- return
- }
- this.$refs.cartRef.open()
- },
- async _validateCommit() {
- if (this.config.collegeMin && this.selected.length < this.config.collegeMin) {
- const err = `请至少填报${this.config.collegeMin}个院校`
- toast(err)
- return Promise.reject(err)
- }
- },
- async _createCommitData() {
- const uPropsKeep = this.config.commitUPropsKeep || []
- const uPropsClear = (u) => {
- const result = {}
- uPropsKeep.forEach(prop => result[prop] = u[prop])
- return result
- }
- const pureSelected = this.selected.map(u => ({
- ...u,
- university: uPropsClear(u.university),
- majorDetails: u.majorDetails.filter(m => m.selected)
- }))
- return {
- ...this.commit,
- request: this.request,
- details: pureSelected
- }
- },
- async handleCommit() {
- await this._validateCommit()
- const data = await this._createCommitData()
- const res = await submitVoluntary(data)
- toast('保存成功')
- await sleep(2000)
- const url = '/pages/ie/entry-ai-detail/entry-ai-detail'
- this.transferTo({url, params: {id: res.data, type: data.voluntaryType}, type: 'redirect'})
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- ::v-deep .zp-page-bottom-container {
- z-index: 10;
- }
- </style>
|