edit.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <template>
  2. <view class="page-content h-screen">
  3. <cart-step ref="cart" edit-mode>
  4. <template #top>
  5. <mx-nav-bar :title="title" :sub-title="name" :left-click-block="confirmBackChange"
  6. style="z-index: 20000"/>
  7. </template>
  8. </cart-step>
  9. </view>
  10. </template>
  11. <script setup>
  12. import {ref, computed, onMounted} from 'vue';
  13. import {zytbBatches} from '@/api/webApi/volunteer'
  14. import MxConst from "@/common/MxConst";
  15. import {useProvideTransfer} from "@/hooks/useTransfer";
  16. import {useVoluntaryPageDataFormat} from "@/pages/voluntary/hooks/useVoluntaryPageDataFormat";
  17. import {useProvideVoluntaryMajorHighlight} from "@/pages/voluntary/hooks/useVoluntaryMajorHighlightInjection";
  18. import {useProvideVoluntaryStep} from "@/pages/voluntary/hooks/useVoluntaryStepInjection";
  19. import {useProvideVoluntaryHeader} from "@/pages/voluntary/hooks/useVoluntaryHeaderInjection";
  20. import {useProvideVoluntaryData} from "@/hooks/useVoluntaryDataInjection";
  21. import {useProvideVoluntaryCart} from "@/pages/voluntary/hooks/useVoluntaryCartInjection";
  22. import {useProvideVoluntaryForm} from "@/pages/voluntary/hooks/useVoluntaryFormInjection";
  23. import {useProvideVoluntaryAssistant} from "@/pages/voluntary/hooks/useVoluntaryAssistantInjection";
  24. import {useVoluntaryMajorGroupIdentifier} from "@/pages/voluntary/hooks/useVoluntaryMajorGroupIdentifier";
  25. import CartStep from "@/pages/voluntary/index/components/cart-step.vue";
  26. const cart = ref(null)
  27. const {prevData, transferBack, callbackEventData} = useProvideTransfer()
  28. const year = computed(() => prevData.value?.detail?.year)
  29. const {isMock} = useProvideVoluntaryHeader()
  30. const stepSvc = useProvideVoluntaryStep('志愿编辑')
  31. const dataSvc = useProvideVoluntaryData(year)
  32. const formSvc = useProvideVoluntaryForm()
  33. const cartSvc = useProvideVoluntaryCart()
  34. const highlightSvc = useProvideVoluntaryMajorHighlight()
  35. const {save, onComplete} = useProvideVoluntaryAssistant(stepSvc, dataSvc, formSvc, cartSvc, highlightSvc)
  36. const {title, currentStep} = stepSvc
  37. const {model, batch, mode} = formSvc
  38. const {id, name, selectedList, defaultSort} = cartSvc
  39. const {resolveFormedMajorsFromSavedData} = highlightSvc
  40. const tryFixScoreMissing = async () => {
  41. const {score1, score2} = batch.value
  42. if (score1 && score2) return
  43. const {year} = prevData.value.detail
  44. const {score} = model.value
  45. // NOTE: try to fix score range in edit mode, because old versions `scorel` defined in the API model.
  46. const res = await zytbBatches({year, score, mode: toValue(mode)})
  47. const match = res.rows.find(r => r.batch == this.batch.batch)
  48. if (match) {
  49. batch.value.score1 = match.score1
  50. batch.value.score2 = match.score2
  51. }
  52. }
  53. const reloadScoreAndMode = () => {
  54. // 编辑模式下应该使用prevData中的数据
  55. const {mode, score, detail: {seatInput}} = prevData.value
  56. const modeParams = mode?.split(',') || []
  57. model.value.score = score
  58. model.value.firstSubject = modeParams[0]
  59. model.value.lastSubject = modeParams.slice(1) || []
  60. model.value.seatInput = seatInput || 0
  61. }
  62. const reloadBatch = () => {
  63. const {batch: batchId, batchName, detail} = prevData.value
  64. batch.value = {
  65. batch: batchId,
  66. batchName,
  67. name: batchName,
  68. score1: detail.batch.score1 || detail.batch.scorel,
  69. score2: detail.batch.score2,
  70. year: detail.year
  71. }
  72. }
  73. const reloadSelectedList = () => {
  74. const detail = prevData.value.detail
  75. const wishes = detail.batch.wishes
  76. // 反向转化选中专业,参照index的保存逻辑
  77. const restoredWishes = wishes.map(group => ({
  78. uniqueCode: group.uniqueCode,
  79. pickType: group.pickType,
  80. enrollRatio: group.enrollRatio,
  81. enrollRatioText: group.enrollRatioText,
  82. jCode: group.jCode,
  83. university: {
  84. id: group.universityId,
  85. name: group.name,
  86. code: group.code,
  87. ranking: group.ranking,
  88. rankingOfEdu: group.rankingOfEdu
  89. },
  90. history: {
  91. seat: group.seat
  92. },
  93. recruitPlan: {
  94. collegeCode: group.collegeCode
  95. },
  96. // marjors is a write error of history issue
  97. majors: group.marjors.map((m, index) => ({
  98. selected: true,
  99. localPriority: index + 1,
  100. id: m.id,
  101. marjorBelongs: m.code,
  102. marjorName: m.name,
  103. enrollRatio: m.enrollRatio,
  104. enrollRatioText: m.enrollRatioText,
  105. enrollFluctuate: m.enrollFluctuate,
  106. history: {
  107. submitMajorId: m.submitMajorId
  108. }
  109. }))
  110. }))
  111. restoredWishes.forEach(useVoluntaryMajorGroupIdentifier)
  112. selectedList.value = restoredWishes
  113. defaultSort.value = selectedList.value.map(g => g.uniqueCode)
  114. }
  115. const isSelectedListChanged = () => {
  116. const old = prevData.value.detail.batch.wishes.map(g => ({
  117. uniqueCode: g.uniqueCode,
  118. majors: [...g.marjors].sort(MxConst.recommendMajorSortFn).map(m => m.id)
  119. }))
  120. const current = selectedList.value.map(g => ({
  121. uniqueCode: g.uniqueCode,
  122. majors: [...g.majors].filter(m => m.selected).sort(MxConst.recommendMajorSortFn).map(m => m.id)
  123. }))
  124. console.log('aop compare selected old and current', old, current)
  125. // validate the sequence and unique code/id of major group and major item
  126. return JSON.stringify(old) != JSON.stringify(current)
  127. }
  128. const confirmBackChange = async () => {
  129. await cart.value.checkPopupBlock()
  130. if (isSelectedListChanged()) {
  131. await cart.value.confirmSave()
  132. }
  133. }
  134. onMounted(() => {
  135. useVoluntaryPageDataFormat(prevData)
  136. resolveFormedMajorsFromSavedData(prevData.value)
  137. id.value = prevData.value.id
  138. name.value = prevData.value.name
  139. isMock.value = prevData.value.detail.isMock
  140. reloadScoreAndMode()
  141. reloadBatch()
  142. reloadSelectedList()
  143. tryFixScoreMissing()
  144. //
  145. currentStep.value = 2
  146. })
  147. onComplete(() => {
  148. callbackEventData.value = true
  149. transferBack()
  150. })
  151. // export default {
  152. // extends: VoluntaryIndex,
  153. // mixins: [mxTransferPageMixins],
  154. // data() {
  155. // return {
  156. // currentStep: 2,
  157. // resetCalled: false // reset only need to call once in edit mode
  158. // }
  159. // },
  160. // computed: {
  161. // voluntaryDataCalculate() {
  162. // // NOTE: overriding by history voluntary data in edit mode
  163. // const param = this.voluntaryData || {}
  164. // const defaultLimit = {groups: 9999, profession: 9999}
  165. // // noinspection JSUnresolvedVariable
  166. // const historyParam = {
  167. // sort: this.prevData.detail.batch?.sort || '',
  168. // firedLimit: ext.arrayFirst(this.prevData.detail.batch?.paramBatches) || defaultLimit
  169. // }
  170. // return {
  171. // ...param,
  172. // ...historyParam
  173. // }
  174. // },
  175. // batchScoreRangeCalculate() {
  176. // // NOTE: overriding by history batch score range in edit mode
  177. // const min = this.batchMinScore
  178. // const max = this.prevData.detail?.batch?.scoreBatchLimit || this.voluntaryData?.maxScore
  179. // return [min, max]
  180. // },
  181. // batchMinScore() {
  182. // return this.batch.score2 || this.batch.score1 || this.batch.scorel
  183. // }
  184. // },
  185. // watch: {
  186. // 'filter': function () {
  187. // // 这里与index作区分,因为filter数据可能还没有准备好
  188. // if (this.batchMinScore && !this.resetCalled) {
  189. // this.resetCalled = true
  190. // this.reset()
  191. // }
  192. // },
  193. // 'batchMinScore': function () {
  194. // // if filter is ready first, call reset here.
  195. // if (!this.resetCalled && Object.keys(this.filter).length) {
  196. // this.resetCalled = true
  197. // this.reset()
  198. // }
  199. // }
  200. // },
  201. // async mounted() {
  202. // this.title = '志愿编辑'
  203. // this.subTitle = this.prevData.name
  204. // this.id = this.prevData.id
  205. // // super中会调用 reloadScoreAndMode
  206. // this.reloadBatch()
  207. // this.reloadSelectedList()
  208. // this.simulateFormedMajors()
  209. // await this.tryFixScoreMissing()
  210. // },
  211. // methods: {
  212. // prepareData() {
  213. // // important: string to json
  214. // if (typeof this.prevData.userSnapshot === 'string') {
  215. // this.prevData.userSnapshot = JSON.parse(this.prevData.userSnapshot)
  216. // }
  217. // if (typeof this.prevData.detail === 'string') {
  218. // const parsedData = JSON.parse(this.prevData.detail)
  219. // parsedData.batch?.wishes?.forEach(this.ensureMajorGroupIdentifier)
  220. // this.prevData.detail = parsedData
  221. // }
  222. // this.isMockHeader = this.prevData.detail.isMock || false
  223. // },
  224. // prevStep() {
  225. // const next = () => {
  226. // const pages = getCurrentPages()
  227. // return pages.length > 1 ? uni.navigateBack() : this.transferToIndex()
  228. // }
  229. // this.confirmSave(next)
  230. // },
  231. // async tryFixScoreMissing() {
  232. // if (this.batchMinScore) return
  233. // // NOTE: try to fix score range in edit mode, because old versions `scorel` defined in the API model.
  234. // const res = await zytbBatches({
  235. // year: this.prevData.detail.year,
  236. // score: this.scoreProps.score,
  237. // mode: this.form.mode
  238. // })
  239. // const match = res.rows.find(r => r.batch == this.batch.batch)
  240. // if (match) {
  241. // this.batch.score1 = match.score1
  242. // this.batch.score2 = match.score2
  243. // }
  244. // },
  245. // async reloadScoreAndMode() {
  246. // // 编辑模式下应该使用prevData中的数据
  247. // const {
  248. // mode,
  249. // score,
  250. // detail: {seatInput}
  251. // } = this.prevData
  252. // const modeParams = mode?.split(',') || []
  253. // this.scoreProps.score = score
  254. // this.scoreProps.firstSubject = modeParams[0]
  255. // this.scoreProps.lastSubject = modeParams.slice(1) || []
  256. // this.scoreProps.seatInput = seatInput || 0
  257. //
  258. // await sleep(50)
  259. // this.scoreProps.init = true // begin seat monitor after init
  260. // },
  261. // reloadBatch() {
  262. // const {
  263. // batch,
  264. // batchName
  265. // } = this.prevData
  266. // this.batch = {
  267. // batch,
  268. // batchName,
  269. // name: batchName,
  270. // score1: this.prevData.detail.batch.score1 || this.prevData.detail.batch.scorel,
  271. // score2: this.prevData.detail.batch.score2,
  272. // year: this.prevData.detail.year
  273. // }
  274. // this.form = {
  275. // batch: this.batch.batch,
  276. // mode: this.mode
  277. // }
  278. // },
  279. // reloadSelectedList() {
  280. // const detail = this.prevData.detail
  281. // const wishes = detail.batch.wishes
  282. // // 反向转化选中专业,参照index的保存逻辑
  283. // const restoredWishes = wishes.map(group => ({
  284. // uniqueCode: group.uniqueCode,
  285. // pickType: group.pickType,
  286. // enrollRatio: group.enrollRatio,
  287. // enrollRatioText: group.enrollRatioText,
  288. // jCode: group.jCode,
  289. // university: {
  290. // id: group.universityId,
  291. // name: group.name,
  292. // code: group.code,
  293. // ranking: group.ranking,
  294. // rankingOfEdu: group.rankingOfEdu
  295. // },
  296. // history: {
  297. // seat: group.seat
  298. // },
  299. // recruitPlan: {
  300. // collegeCode: group.collegeCode
  301. // },
  302. // // marjors is a write error of history issue
  303. // majors: group.marjors.map((m, index) => ({
  304. // selected: true,
  305. // localPriority: index + 1,
  306. // id: m.id,
  307. // marjorBelongs: m.code,
  308. // marjorName: m.name,
  309. // enrollRatio: m.enrollRatio,
  310. // enrollRatioText: m.enrollRatioText,
  311. // enrollFluctuate: m.enrollFluctuate,
  312. // history: {
  313. // submitMajorId: m.submitMajorId
  314. // }
  315. // }))
  316. // }))
  317. // restoredWishes.forEach(this.ensureMajorGroupIdentifier)
  318. // this.selectedList = restoredWishes
  319. // this.defaultSort = this.selectedList.map(g => g.uniqueCode)
  320. // },
  321. // // simulate formed majors for highlight major
  322. // simulateFormedMajors() {
  323. // this.formedMajors = this.resolveFormedMajorsFromSavedData(this.prevData)
  324. // },
  325. // // override the NewSimulatedVolunteer
  326. // isSelectedListChanged() {
  327. // const old = this.prevData.detail.batch.wishes.map(g => ({
  328. // jCode: g.jCode,
  329. // majors: [...g.marjors].sort(MxConst.recommendMajorSortFn).map(m => m.id)
  330. // }))
  331. // const current = this.selectedList.map(g => ({
  332. // jCode: g.jCode,
  333. // majors: [...g.majors].filter(m => m.selected).sort(MxConst.recommendMajorSortFn).map(m => m.id)
  334. // }))
  335. // console.log('aop compare selected old and current', old, current)
  336. // // validate the sequence and unique code/id of major group and major item
  337. // return JSON.stringify(old) != JSON.stringify(current)
  338. // }
  339. // }
  340. // }
  341. </script>
  342. <style lang="scss" scoped>
  343. </style>