123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- <template>
- <div v-if="voluntaryData" class="form">
- <el-form
- ref="form"
- :model="form"
- :rules="rules"
- :disabled="disabled||scoreLocked"
- label-width="120px"
- label-position="right"
- >
- <el-form-item
- v-if="gkType == 2 || gkType == 3"
- :label="voluntaryData.isNewGaokao?`您的首选科目`:`您的科目`"
- prop="firstSubject"
- >
- <el-radio-group v-model="form.firstSubject">
- <el-radio v-for="item in voluntaryData.course0" :key="item" :label="item" />
- </el-radio-group>
- </el-form-item>
- <el-form-item v-if="voluntaryData.isNewGaokao" :label="gkType == 2 ? '您的次选科目' : '您的选科科目'" prop="lastSubject">
- <el-checkbox-group v-model="form.lastSubject" :max="gkType == 2 ? 2 : 3">
- <el-checkbox v-for="item in voluntaryData.course1" :key="item" :label="item" />
- </el-checkbox-group>
- </el-form-item>
- <el-form-item label="您的总分" prop="score">
- <el-input v-model="form.score" type="number" placeholder="请输入分数" @mousewheel.native.prevent />
- </el-form-item>
- <el-form-item v-if="false" label="匹配位次">
- <el-input disabled placeholder="输入分数后查看位次" :value="form.rank.lowestRank" />
- <span v-if="!scoreLocked" class="f12 f-666 ml10">当前为估分模拟,不需填写排名</span>
- </el-form-item>
- <el-form v-if="!hiddenRanking" ref="inner" :model="form" :rules="rules" label-width="120px">
- <el-form-item label="填写位次" prop="seatInput">
- <el-input v-model="form.seatInput" placeholder="输入位次(可选)" />
- <el-link type="success" target="_blank" href="/zhiyuan/scoreSegment" class="ml10" :underline="false">查看位次</el-link>
- <div class="f12 f-666 mt5" style="line-height: 16px">
- <i class="el-icon-info" />
- 已根据最新位次表获取分数的最低位次,您也可以修改为成绩单上的位次。<div v-if="form.rank&&scoreLocked">位次区间[{{ form.rank.highestRank }}~{{ form.rank.lowestRank }}]</div>
- </div>
- </el-form-item>
- </el-form>
- <slot />
- <el-form-item v-if="scoreLocked" label="" label-width="0" style="margin-bottom: 0">
- <div class="f-red" style="line-height: 18px">{{ scoreLockedTips }}</div>
- </el-form-item>
- <el-form-item v-if="!isLogin||!scoreLocked&&!scoreUnlock" label="" label-width="0" style="margin-bottom: 0">
- <div class="f-red" style="line-height: 18px">{{ scoreRuleTips }}</div>
- </el-form-item>
- </el-form>
- </div>
- </template>
- <script>
- import { getRankByScore } from '@/api/webApi/career-course'
- import { getVoluntaryData } from '@/api/webApi/professlib'
- import { mapGetters } from 'vuex'
- import MxConfig from '@/common/MxConfig'
- import { debounce } from '@/utils'
- export default {
- name: 'SimulateScore',
- props: ['form', 'disabled', 'hiddenRanking', 'provinceName', 'disableRequired', 'keepValue', 'disableWatch'],
- inject: { 'fetchVoluntaryData': { default: () => () => null }},
- data() {
- return {
- scoreLockedTips: MxConfig.scoreLockedTips,
- scoreRuleTips: MxConfig.scoreRuleTips,
- // TODO: 应该将voluntaryData提取出此控件,因为时间不够没有动这里的逻辑,怕影响其它地方
- voluntaryData: {
- isNewGaokao: false,
- minScore: 0,
- maxScore: 750,
- course0: [],
- course1: []
- },
- gkType: 0, // 1 6选三 2 4选2 3 旧高考文理
- rules: {},
- lazyRules: {
- firstSubject: [
- { required: !this.disableRequired, message: '请选择科目', trigger: 'change' },
- {
- validator: (r, v, cb) => {
- const myForm = this.form || {}
- const emptyLast = Array.isArray(myForm.lastSubject) ? myForm.lastSubject.length : myForm.lastSubject
- if (emptyLast && !v) cb('请选择科目')
- else cb()
- }, trigger: 'change'
- }
- ],
- lastSubject: [
- { required: !this.disableRequired, message: '请选择次选科目', trigger: 'change' },
- {
- validator: (r, v, cb) => {
- const maxCount = this.gkType == 2 ? 2 : 3
- const canEmpty = !this.form.firstSubject && this.disableRequired
- if (v.length < maxCount && !canEmpty) {
- cb(`请选择${maxCount}项科目`)
- } else {
- cb()
- }
- }, trigger: 'change'
- }
- ],
- score: [
- { required: !this.disableRequired, message: '请输入你的总分', trigger: 'blur' },
- { pattern: /^[1-9]\d*$/, message: '分数必须为整数', trigger: 'blur' },
- {
- validator: (r, v, cb) => {
- if (v > this.voluntaryData.maxScore) {
- cb(`成绩超出当前省份满分${this.voluntaryData.maxScore}`)
- } else if (v < 0) {
- cb(`成绩不能为负数`)
- } else {
- cb()
- }
- }, trigger: ['blur', 'change']
- }
- ],
- seatInput: [
- { required: true, message: '请输入你的位次', trigger: 'blur' },
- { pattern: /^[1-9]\d*$/, message: '请输入合法的位次', trigger: 'blur' },
- {
- validator: (r, v, cb) => {
- if (!this.form.rank && !v) {
- cb() // ignore
- } else if (v >= this.form.rank?.highestRank && v <= this.form.rank?.lowestRank) {
- cb() // valid
- } else if (this.scoreUnlock) {
- cb() // 锁分期间启动位次校验,否则用户随意输入
- } else {
- if (!this.form.rank?.highestRank || !this.form.rank?.lowestRank) cb('无效位次') //
- else cb(`输入位次必须在${this.form.rank?.highestRank}~${this.form.rank?.lowestRank}之间`)
- }
- }, trigger: ['blur', 'change']
- }
- ]
- }
- }
- },
- computed: {
- ...mapGetters(['currentUser', 'isLogin', 'scoreLocked', 'scoreUnlock']),
- injectedVoluntaryData() {
- // noinspection JSUnresolvedFunction
- return this.fetchVoluntaryData()
- }
- },
- watch: {
- 'form.score': { handler: 'handleScoreUpdate' },
- 'form.firstSubject': { handler: 'handleScoreUpdate' },
- 'provinceName': function() {
- this.loadVoluntaryEnv()
- }
- },
- mounted() {
- if (this.injectedVoluntaryData?.maxScore) {
- // injected voluntary data is valid
- this.voluntaryData = this.injectedVoluntaryData
- this.processVoluntaryData(this.voluntaryData)
- } else {
- this.loadVoluntaryEnv()
- }
- },
- methods: {
- handleScoreUpdate: debounce(function() {
- if (this.disableWatch) return // 如果是从编辑界面同步的情况,就不去重新加载位次
- if (!this.form.init) return // 只监控用户修改的属性变化
- if (this.form.score < 0) return
- if (this.form.score > this.voluntaryData.maxScore) return
- // validate score, reduce invalid requests for ranking
- this.loadRankByScoreAndSubject()
- }, 800),
- loadVoluntaryEnv() {
- const hasBind = this.isLogin && this.currentUser.isBind
- if (!hasBind && !this.provinceName) return
- const commit = {}
- if (this.provinceName) commit['provinceName'] = this.provinceName
- getVoluntaryData(commit).then(res => {
- this.voluntaryData = res.data
- this.$emit('voluntary-ready', res.data) // 传递给父组件
- this.processVoluntaryData(this.voluntaryData)
- })
- },
- processVoluntaryData(data) {
- if (!data.course0.length && data.course1?.length) {
- this.gkType = 1
- } else if (data.course0.length && data.course1) {
- this.gkType = 2
- } else if (!data.isNewGaokao) {
- this.gkType = 3
- }
- if (this.gkType && !this.keepValue) {
- // reset form data
- this.form.score = ''
- this.form.firstSubject = ''
- this.form.lastSubject = ''
- if (data.isNewGaokao) this.form.lastSubject = []
- }
- this.rules = this.lazyRules
- this.$nextTick(() => {
- this.$refs.form?.clearValidate([])
- this.$refs.inner?.clearValidate([])
- })
- },
- loadRankByScoreAndSubject() {
- if (this.hiddenRanking) return // 此时不需要查位次
- if (!this.form.score) {
- this.$set(this.form, 'seatInput', '')
- this.$set(this.form, 'rank', {})
- return
- }
- getRankByScore({ mode: this.form.firstSubject, scoreRank: this.form.score }).then(res => {
- const { lowestRank, highestRank } = res.data
- const current = this.form.seatInput // valid current seat of user input
- const rangeInvalid = current < highestRank || current > lowestRank
- // const forceChange = !current || (rangeInvalid && !this.scoreUnlock) // 锁分期间启动位次校验,否则用户随意输入
- if (rangeInvalid) this.$set(this.form, 'seatInput', res.data.lowestRank)
- this.$set(this.form, 'rank', res.data)
- this.$nextTick(() => this.$refs.form?.clearValidate([]))
- })
- },
- async validate() {
- try {
- if (this.$refs.inner) await this.$refs.inner.validate()
- await this.$refs.form.validate()
- } catch (e) {
- const demo = Object.values(e).first()?.first()
- if (demo) this.$message.error(demo.message)
- return Promise.reject(e)
- }
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .form {
- ::v-deep {
- input::-webkit-outer-spin-button,
- input::-webkit-inner-spin-button {
- -webkit-appearance: none;
- }
- }
- }
- .form {
- width: 640px;
- padding: 30px 0;
- margin: 0 auto;
- }
- .form {
- ::v-deep {
- .el-form-item__label {
- padding-right: 25px;
- }
- .el-input {
- width: 300px;
- }
- }
- }
- .btn {
- width: 120px;
- margin-left: 83px;
- margin-top: 30px;
- }
- </style>
|