388 lines
12 KiB
JavaScript
388 lines
12 KiB
JavaScript
const gaokaoApi = require('../../utils/gaokao')
|
||
|
||
/** 科类/选科备选项:首项为占位,不可作为有效保存值 */
|
||
const SUBJECT_PLACEHOLDER = '请选择科类/选科'
|
||
const SUBJECT_CHOICES = [
|
||
SUBJECT_PLACEHOLDER,
|
||
'文科',
|
||
'理科',
|
||
'物化生',
|
||
'物化地',
|
||
'物化政',
|
||
'物生地',
|
||
'物生政',
|
||
'物政地',
|
||
'化生地',
|
||
'化政地',
|
||
'生政地',
|
||
'史政地',
|
||
'史化政',
|
||
'史化生',
|
||
'物化技',
|
||
'物生技',
|
||
'史地技',
|
||
'艺术类(物理向)',
|
||
'艺术类(历史向)',
|
||
'体育类(物理向)',
|
||
'体育类(历史向)',
|
||
'中职/对口/单招'
|
||
]
|
||
|
||
/** 在意向专业中展示/保存的选项:首项表示不填 */
|
||
const MAJOR_PLACEHOLDER = '(可选)不填'
|
||
const MAJOR_CHOICES = [
|
||
MAJOR_PLACEHOLDER,
|
||
'哲学',
|
||
'经济学 / 金融',
|
||
'法学',
|
||
'教育学 / 师范',
|
||
'文学',
|
||
'外语 / 新传',
|
||
'理学',
|
||
'工学 / 工程',
|
||
'计算机 / 软件 / 人工智能',
|
||
'电子 / 通信 / 信息',
|
||
'医学 / 临床 / 公卫 / 中医',
|
||
'农学 / 林学 / 生科',
|
||
'历史学',
|
||
'管理学 / 商学',
|
||
'艺术学',
|
||
'交叉学科 / 暂未确定'
|
||
]
|
||
|
||
/** 将微信 region 结果格式化为只到「市」的文案(不含区) */
|
||
function regionToCityText(v) {
|
||
if (!v || !v.length) return ''
|
||
const p = (v[0] || '').trim()
|
||
const c = (v[1] || '').trim()
|
||
if (p && c) return p + ' ' + c
|
||
return p || c
|
||
}
|
||
|
||
/** 展示用:只取省+市,直辖市 p===c 时只显示一个 */
|
||
function formatRegionLine(v) {
|
||
if (!v || !v.length) return ''
|
||
const p = (v[0] || '').trim()
|
||
const c = (v[1] || '').trim()
|
||
if (!p && !c) return ''
|
||
if (c && c !== p) return p + ' · ' + c
|
||
return p || c
|
||
}
|
||
|
||
/** 从 bindchange 取 value(部分环境 detail 结构异常时兜底) */
|
||
function regionValueFromEvent(e) {
|
||
const d = (e && e.detail) || {}
|
||
let v = d.value
|
||
if (Array.isArray(v) && v.length) return v
|
||
return []
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
form: {
|
||
name: '',
|
||
province: '',
|
||
/** 高考生源地所在市(与省同一套 region 选择结果,用于展示/扩展) */
|
||
city: '',
|
||
streamOrSubjects: '',
|
||
/** 与微信 region picker 联动;level=city 时为 [省,市];老数据或省级可能为 3 项 */
|
||
region: [],
|
||
/**
|
||
* 意向地区:仅省为 [p];老数据 可能 为 [p,c];与 preferredRegions 对应
|
||
*/
|
||
preferredRegion: [],
|
||
estimatedScore: '',
|
||
scoreText: '',
|
||
wishListText: '',
|
||
preferredRegions: '',
|
||
preferredFields: ''
|
||
},
|
||
/** 高考生源:与 level=city 一致,为 [省,市] */
|
||
regionPickerValue: [],
|
||
/** 意向:只省 */
|
||
intendedProvPicker: [],
|
||
/** 意向:省+市 */
|
||
intendedCityPicker: [],
|
||
/** 0=只到省份 1=到省+市 */
|
||
intendedModeOptions: ['只到省份', '到省+市'],
|
||
intendedModeIndex: 1,
|
||
intendedModeLine: '到省+市',
|
||
/** 地区展示文案(不依赖 wxml 里对 length 的比较,避免真机/模拟器不渲染) */
|
||
regionLine: '',
|
||
intendedRegionLine: '',
|
||
subjectOptions: SUBJECT_CHOICES,
|
||
streamOrSubjectsIndex: 0,
|
||
majorOptions: MAJOR_CHOICES,
|
||
preferredFieldsIndex: 0,
|
||
saving: false
|
||
},
|
||
|
||
/** 每次页面展示拉取(含从上级页返回),避免栈内页面不触发 onLoad 时看不到已保存内容 */
|
||
onShow() {
|
||
this.loadFormFromServer()
|
||
},
|
||
|
||
loadFormFromServer() {
|
||
gaokaoApi
|
||
.getForm()
|
||
.then((res) => {
|
||
const form = res.form || {}
|
||
const pr = (() => {
|
||
const a = form.preferredRegion
|
||
if (!Array.isArray(a) || a.length < 1) return []
|
||
return a
|
||
})()
|
||
const baseForm = {
|
||
...this.data.form,
|
||
...form,
|
||
city: (form.city != null && form.city !== '') ? String(form.city) : (this.data.form.city || ''),
|
||
region: (() => {
|
||
const a = form.region
|
||
if (!Array.isArray(a) || a.length < 2) return []
|
||
return a
|
||
})(),
|
||
preferredRegion: pr,
|
||
preferredRegions: (() => {
|
||
if (pr && pr.length >= 2) {
|
||
return regionToCityText([pr[0], pr[1]])
|
||
}
|
||
if (pr && pr.length === 1) {
|
||
return (pr[0] || '').trim()
|
||
}
|
||
return form.preferredRegions != null ? String(form.preferredRegions) : ''
|
||
})(),
|
||
estimatedScore: form.estimatedScore != null ? String(form.estimatedScore) : ''
|
||
}
|
||
const rpv = baseForm.region
|
||
if (rpv && rpv.length >= 2) {
|
||
baseForm.province = rpv[0] || baseForm.province
|
||
baseForm.city = rpv[1] || baseForm.city
|
||
}
|
||
const rForPicker = (() => {
|
||
if (Array.isArray(baseForm.region) && baseForm.region.length >= 2) {
|
||
const a0 = (baseForm.region[0] || '').trim()
|
||
const a1 = (baseForm.region[1] || a0).trim()
|
||
return [a0, a1]
|
||
}
|
||
if (baseForm.province) {
|
||
const a0 = String(baseForm.province).trim()
|
||
const a1 = (baseForm.city && String(baseForm.city).trim()) || a0
|
||
return [a0, a1]
|
||
}
|
||
return []
|
||
})()
|
||
const regionLine = rForPicker.length
|
||
? formatRegionLine(rForPicker)
|
||
: ''
|
||
const intendedModeOptions = this.data.intendedModeOptions
|
||
const modeIdx = (() => {
|
||
if (pr && pr.length >= 2) return 1
|
||
if (pr && pr.length === 1) return 0
|
||
return 1
|
||
})()
|
||
const intendedModeLine = intendedModeOptions[modeIdx] || '到省+市'
|
||
const intendedProvPicker = (() => {
|
||
if (pr && pr.length >= 1) return [(String(pr[0] || '')).trim()]
|
||
return []
|
||
})()
|
||
const intendedCityPicker = (() => {
|
||
if (pr && pr.length >= 2) {
|
||
return [
|
||
(String(pr[0] || '')).trim(),
|
||
(String(pr[1] || '')).trim()
|
||
]
|
||
}
|
||
if (pr && pr.length === 1 && modeIdx === 1) {
|
||
const p0 = (String(pr[0] || '')).trim()
|
||
return p0 ? [p0, p0] : []
|
||
}
|
||
return []
|
||
})()
|
||
let intendedRegionLine = (() => {
|
||
if (pr && pr.length >= 2) {
|
||
return formatRegionLine([(pr[0] || '').trim(), (pr[1] || '').trim()])
|
||
}
|
||
if (pr && pr.length === 1) {
|
||
return (pr[0] || '').trim()
|
||
}
|
||
if (form.preferredRegions) return String(form.preferredRegions)
|
||
return ''
|
||
})()
|
||
const stream = baseForm.streamOrSubjects || ''
|
||
const opts = (() => {
|
||
if (stream && SUBJECT_CHOICES.indexOf(stream) < 0) {
|
||
return [SUBJECT_CHOICES[0], stream, ...SUBJECT_CHOICES.slice(1)]
|
||
}
|
||
return SUBJECT_CHOICES
|
||
})()
|
||
let sIdx = opts.indexOf(stream)
|
||
if (sIdx < 0) sIdx = 0
|
||
const pField = baseForm.preferredFields || ''
|
||
const mOpts = (() => {
|
||
if (pField && MAJOR_CHOICES.indexOf(pField) < 0) {
|
||
return [MAJOR_CHOICES[0], pField, ...MAJOR_CHOICES.slice(1)]
|
||
}
|
||
return MAJOR_CHOICES
|
||
})()
|
||
let mIdx = mOpts.indexOf(pField)
|
||
if (mIdx < 0) mIdx = 0
|
||
this.setData({
|
||
form: baseForm,
|
||
regionPickerValue: rForPicker,
|
||
regionLine,
|
||
intendedModeIndex: modeIdx,
|
||
intendedModeLine,
|
||
intendedProvPicker,
|
||
intendedCityPicker,
|
||
intendedRegionLine,
|
||
subjectOptions: opts,
|
||
streamOrSubjectsIndex: sIdx,
|
||
majorOptions: mOpts,
|
||
preferredFieldsIndex: mIdx
|
||
})
|
||
})
|
||
.catch(() => {
|
||
wx.showToast({ title: '加载表单失败', icon: 'none' })
|
||
})
|
||
},
|
||
|
||
onInput(e) {
|
||
const key = e.currentTarget.dataset.key
|
||
this.setData({ [`form.${key}`]: e.detail.value })
|
||
},
|
||
|
||
onRegionChange(e) {
|
||
const v = regionValueFromEvent(e)
|
||
if (!v || !v.length) return
|
||
const p = (v[0] || '').trim()
|
||
if (!p) return
|
||
const c2 = v[1] != null && v[1] !== '' ? String(v[1]).trim() : ''
|
||
const pair = [p, c2 || p]
|
||
this.setData({
|
||
regionPickerValue: pair,
|
||
regionLine: formatRegionLine(pair),
|
||
'form.province': p,
|
||
'form.city': c2 || p,
|
||
'form.region': pair
|
||
})
|
||
},
|
||
|
||
onSubjectChange(e) {
|
||
const idx = parseInt(e.detail.value, 10) || 0
|
||
const opts = this.data.subjectOptions
|
||
const raw = opts[idx] || ''
|
||
const val =
|
||
raw && raw !== SUBJECT_PLACEHOLDER
|
||
? raw
|
||
: ''
|
||
this.setData({
|
||
streamOrSubjectsIndex: idx,
|
||
'form.streamOrSubjects': val
|
||
})
|
||
},
|
||
|
||
onIntendedModeChange(e) {
|
||
const idx = parseInt(e.detail.value, 10) || 0
|
||
const opts = this.data.intendedModeOptions
|
||
const pr = this.data.form.preferredRegion
|
||
const arr = Array.isArray(pr) ? pr : []
|
||
if (idx === 0) {
|
||
const p = arr[0] ? String(arr[0]).trim() : ''
|
||
const next = p ? [p] : []
|
||
this.setData({
|
||
intendedModeIndex: idx,
|
||
intendedModeLine: opts[idx],
|
||
intendedProvPicker: next,
|
||
intendedRegionLine: p,
|
||
'form.preferredRegion': next,
|
||
'form.preferredRegions': p
|
||
})
|
||
return
|
||
}
|
||
let cityPick = []
|
||
if (arr.length >= 2) {
|
||
cityPick = [String(arr[0] || '').trim(), String(arr[1] || '').trim()]
|
||
} else if (arr.length === 1) {
|
||
const p0 = String(arr[0] || '').trim()
|
||
cityPick = p0 ? [p0, p0] : []
|
||
}
|
||
const hasPair = arr.length >= 2
|
||
this.setData({
|
||
intendedModeIndex: idx,
|
||
intendedModeLine: opts[idx],
|
||
intendedCityPicker: cityPick
|
||
})
|
||
if (hasPair) {
|
||
const line = formatRegionLine(cityPick)
|
||
this.setData({
|
||
intendedRegionLine: line,
|
||
'form.preferredRegion': [cityPick[0], cityPick[1]],
|
||
'form.preferredRegions': regionToCityText(cityPick)
|
||
})
|
||
} else {
|
||
this.setData({
|
||
intendedRegionLine: arr[0] ? String(arr[0]).trim() : '',
|
||
'form.preferredRegion': arr
|
||
})
|
||
}
|
||
},
|
||
|
||
onIntendedRegionProv(e) {
|
||
const v = regionValueFromEvent(e)
|
||
if (!v || !v.length) return
|
||
const p = (v[0] || '').trim()
|
||
if (!p) return
|
||
this.setData({
|
||
intendedProvPicker: [p],
|
||
intendedRegionLine: p,
|
||
'form.preferredRegion': [p],
|
||
'form.preferredRegions': p
|
||
})
|
||
},
|
||
|
||
onIntendedRegionCity(e) {
|
||
const v = regionValueFromEvent(e)
|
||
if (!v || !v.length) return
|
||
const p = (v[0] || '').trim()
|
||
if (!p) return
|
||
const c2 = v[1] != null && v[1] !== '' ? String(v[1]).trim() : ''
|
||
const pair = [p, c2 || p]
|
||
this.setData({
|
||
intendedCityPicker: pair,
|
||
intendedRegionLine: formatRegionLine(pair),
|
||
'form.preferredRegion': pair,
|
||
'form.preferredRegions': regionToCityText(pair)
|
||
})
|
||
},
|
||
|
||
onPreferredFieldChange(e) {
|
||
const idx = parseInt(e.detail.value, 10) || 0
|
||
const opts = this.data.majorOptions
|
||
const raw = opts[idx] || ''
|
||
const val = raw && raw !== MAJOR_PLACEHOLDER ? raw : ''
|
||
this.setData({
|
||
preferredFieldsIndex: idx,
|
||
'form.preferredFields': val
|
||
})
|
||
},
|
||
|
||
onSave() {
|
||
const f = this.data.form
|
||
if (!f.name || !f.province || !f.streamOrSubjects) {
|
||
wx.showToast({ title: '请选择姓名、所在地区与科类/选科', icon: 'none' })
|
||
return
|
||
}
|
||
this.setData({ saving: true })
|
||
gaokaoApi.saveForm({
|
||
...f,
|
||
estimatedScore: f.estimatedScore ? Number(f.estimatedScore) : null
|
||
}).then(() => {
|
||
wx.showToast({ title: '保存成功', icon: 'success' })
|
||
setTimeout(() => wx.navigateBack(), 400)
|
||
}).catch((e) => {
|
||
wx.showToast({ title: e.message || '保存失败', icon: 'none' })
|
||
}).finally(() => this.setData({ saving: false }))
|
||
}
|
||
})
|
||
|