elective-table.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <template>
  2. <div>
  3. <div class="mb10 fx-row fx-bet-cen">
  4. <div class="fx-row fx-end-cen">
  5. <el-button circle icon="el-icon-refresh" @click="refreshData" class="mr30"></el-button>
  6. <elective-enroll-info v-if="enrollInfoVisible" :generation="generation"
  7. :enroll-status="enrollStatus"></elective-enroll-info>
  8. </div>
  9. <el-button v-if="enableAIFeature" type="primary" @click="toAiAnalysis">AI分析</el-button>
  10. </div>
  11. <mx-table :propDefines="formatCols" :rows="formatRows">
  12. <template #underOver="{value}">
  13. <over-under-badge :value="value"></over-under-badge>
  14. </template>
  15. <template #group="{row}">
  16. <elective-table-group-tag :generation="generation" :group="row"></elective-table-group-tag>
  17. </template>
  18. <template #temp="{row}">
  19. <span class="btn-blue mr5" @click="toSelectSub(row)">选择</span>
  20. <span class="btn-green" @click="toReport">查看记录</span>
  21. </template>
  22. <template #signUp="{row}">
  23. <elective-preference-command :generation="generation" :group="row"></elective-preference-command>
  24. </template>
  25. <template #subjects="{row}">
  26. <elective-major-thumbnail :group="row"></elective-major-thumbnail>
  27. </template>
  28. <template #colleges="{row}">
  29. <elective-major-college :group="row"></elective-major-college>
  30. </template>
  31. </mx-table>
  32. <elective-preference-info :generation="generation"></elective-preference-info>
  33. <elective-preference-batch v-if="enableMultipleDrag" :generation="generation"
  34. :disabled="!enableSelect"></elective-preference-batch>
  35. <elective-preference-reject v-if="enableReject" :generation="generation"></elective-preference-reject>
  36. <elective-esign-dialog ref="esignDialog"></elective-esign-dialog>
  37. <choose-subject-dialog ref="chooseDialog"></choose-subject-dialog>
  38. <select-subject-report-dialog ref="reportDialog"></select-subject-report-dialog>
  39. <elective-ai-analysis-dialog ref="aiDialog" :optionalMajors="optionalMajors"
  40. :generation="generation"></elective-ai-analysis-dialog>
  41. </div>
  42. </template>
  43. <script>
  44. import consts from '@/common/mx-const'
  45. import { mapGetters } from 'vuex'
  46. import MxSelectTranslate from '@/components/Cache/modules/mx-select-translate-mixin.js'
  47. import ChooseSubjectDialog from '../../../system/user/profile/components/choose-subject-dialog'
  48. import SelectSubjectReportDialog from '@/views/system/user/profile/components/select-subject-report-dialog'
  49. import OverUnderBadge from '@/views/elective/publish/components/steps/fauclty/over-under-badge'
  50. import ElectiveEnrollInfo from '@/views/elective/select/components/elective-enroll-info'
  51. import ElectiveToolsMixin from './elective-tools-mixins'
  52. import ElectivePreferenceInfo from '@/views/elective/select/components/elective-preference-info'
  53. import ElectivePreferenceReject from '@/views/elective/select/components/elective-preference-reject'
  54. import ElectivePreferenceCommand from '@/views/elective/select/components/elective-preference-command'
  55. import ElectiveAiAnalysisDialog from '@/views/elective/select/components/elective-ai-analysis-dialog'
  56. import ElectiveEsignDialog from '@/views/elective/select/components/elective-esign-dialog'
  57. import ElectiveMajorThumbnail from '@/views/elective/select/components/elective-major-thumbnail'
  58. import ElectiveMajorCollege from '@/views/elective/select/components/elective-major-college'
  59. import ElectivePreferenceBatch from '@/views/elective/select/components/elective-preference-batch'
  60. import ElectiveTableGroupTag from '@/views/elective/select/components/elective-table-group-tag'
  61. const resolverModules = require.context('./round-select-resolvers', false, /\.js$/)
  62. const resolvers = resolverModules.keys().map(key => resolverModules(key).default)
  63. export default {
  64. mixins: [ElectiveToolsMixin, MxSelectTranslate, ...resolvers],
  65. name: 'elective-table',
  66. props: {
  67. generation: Object,
  68. readonly: Boolean, // 校长端不允许操作
  69. optionalMajors: { type: Array, default: () => [] }
  70. },
  71. components: {
  72. ElectiveTableGroupTag,
  73. ElectivePreferenceBatch,
  74. ElectiveMajorCollege,
  75. ElectiveMajorThumbnail,
  76. ElectiveEsignDialog,
  77. ElectiveAiAnalysisDialog,
  78. ElectivePreferenceCommand,
  79. ElectivePreferenceReject,
  80. ElectivePreferenceInfo,
  81. ElectiveEnrollInfo,
  82. OverUnderBadge,
  83. SelectSubjectReportDialog,
  84. ChooseSubjectDialog
  85. },
  86. inject: {
  87. refreshData: {
  88. default: function() {
  89. }
  90. }
  91. },
  92. computed: {
  93. ...mapGetters(['hasPermissions']),
  94. enrollInfoVisible() {
  95. return this.generation.active > this.generation.options.primary.value
  96. },
  97. enrollStatus() {
  98. const enrolledGroup = this.generation.activeModel.models?.find(this.isGroupEnrolled)
  99. if (enrolledGroup) {
  100. let enrolledModel = this.generation.activeModel
  101. do {
  102. const matched = enrolledModel.models?.find(this.isGroupEnrolled)
  103. if (matched
  104. && matched.groupId == enrolledGroup.groupId
  105. && enrolledModel.selectedList.includes(matched)) {
  106. return {
  107. enrolledGroup,
  108. enrolledModel
  109. }
  110. }
  111. enrolledModel = enrolledModel.prevModel
  112. }
  113. while (enrolledModel)
  114. }
  115. return { enrolledGroup, enrolledModel: null }
  116. },
  117. stepMatched() {
  118. return this.generation.active == this.generation.current
  119. },
  120. selectStep() {
  121. return !this.generation.activeOpt.decisionMaking
  122. },
  123. enableSelect() {
  124. return this.stepMatched && this.selectStep && !!!this.enrollStatus.enrolledGroup && !this.readonly
  125. },
  126. selectedList() {
  127. return this.generation.activeModel.selectedList
  128. },
  129. multipleSelect() {
  130. return this.generation.activeModel.preferenceCount > 1
  131. },
  132. enableMultipleDrag() {
  133. return this.selectStep && this.multipleSelect
  134. },
  135. enableReject() {
  136. return this.enableSelect && this.generation.active > this.generation.options.primary.value
  137. },
  138. enableAIFeature() {
  139. return !this.generation.activeOpt.decisionMaking
  140. && this.generation.activeOpt != this.generation.options.primary
  141. && !this.readonly
  142. },
  143. resolveTablePrefix() {
  144. return {
  145. index: {
  146. type: 'index',
  147. label: '编号'
  148. },
  149. groupName: {
  150. label: '选科组合',
  151. slot: 'group',
  152. width: '85px'
  153. },
  154. scoreSumGroup: {
  155. label: '组合成绩',
  156. hidden: this.hasPermissions([consts.enum.electivePermission.rankInGroup.scoreByGroup])
  157. },
  158. classCount: {
  159. label: '开设班级数'
  160. },
  161. personCount: {
  162. label: '人数设置'
  163. }
  164. }
  165. },
  166. resolveTableSuffix() {
  167. const stepMatched = this.generation.active == this.generation.current
  168. const enableApply = !this.generation.currentOpt.decisionMaking
  169. const enableSignUp = stepMatched && enableApply && !this.readonly && !this.enrollStatus.enrolledGroup
  170. return {
  171. rankInGroup: {
  172. label: '当前组合实时排名',
  173. hidden: this.hasPermissions([consts.enum.electivePermission.rankInGroup])
  174. },
  175. rankInGrade: {
  176. label: '选科全校排名',
  177. hidden: this.hasPermissions([consts.enum.electivePermission.rankInGrade])
  178. },
  179. allowSelectTips: {
  180. label: '报名状态'
  181. },
  182. temp: {
  183. label: '选择专业',
  184. width: '140',
  185. slot: 'temp',
  186. hidden: this.readonly
  187. },
  188. subjects: {
  189. label: '自选专业',
  190. slot: 'subjects',
  191. minWidth: '150'
  192. },
  193. colleges: {
  194. label: '院校',
  195. slot: 'colleges',
  196. minWidth: '250'
  197. },
  198. signUp: {
  199. label: '操作',
  200. slot: 'signUp',
  201. width: '100',
  202. fixed: 'right',
  203. hidden: !enableSignUp
  204. }
  205. }
  206. },
  207. resolveDynamicTable() {
  208. if (!Object.keys(this.formatRows).length) return {}
  209. const options = this.generation.options
  210. if (!options || !this.generation.active) return {}
  211. const dynamicColumns = {}
  212. this.generation.activeModels.forEach(model => {
  213. const resolverKey = model.option.key + 'Resolver'
  214. const resolver = this[resolverKey]
  215. if (typeof resolver === 'function') {
  216. const genColumns = resolver(model, this.generation.activeModel, dynamicColumns)
  217. Object.assign(dynamicColumns, genColumns)
  218. }
  219. })
  220. return dynamicColumns
  221. },
  222. formatRows() {
  223. if (!this.optionalMajors) return []
  224. if (!this.generation.roundGroups?.length) return []
  225. if (!this.generation.activeModels?.length) return []
  226. const activeModel = this.generation.activeModel
  227. return this.generation.roundGroups.map(rg => {
  228. const row = activeModel.models?.find(item => item.groupId == rg.groupId) || {}
  229. this.$set(row, 'allowSelectTips', this.combineGroupStatus(row, activeModel))
  230. const matchedMajors = this.optionalMajors.filter(college => college.matchedGroupIds.includes(row.groupId))
  231. this.$set(row, 'colleges', matchedMajors.map(m => ({ college: m.collegeName, major: m.majorCategoryName })))
  232. this.$set(row, 'subjects', matchedMajors.map(m => m['majorCategoryName']))
  233. return row
  234. })
  235. },
  236. formatCols() {
  237. return {
  238. ...this.resolveTablePrefix,
  239. ...this.resolveDynamicTable,
  240. ...this.resolveTableSuffix
  241. }
  242. }
  243. },
  244. methods: {
  245. preventSelectedListChanged() {
  246. if (!this.enableSelect) return Promise.resolve(true)
  247. const from = this.generation.activeModel.selectedList
  248. const to = this.generation.activeModel.selectedListSnapshot
  249. let changedMsg = '请先提交更改过的志愿', changed = false
  250. if (from.length != to.length) {
  251. changed = true
  252. } else if (from.length) {
  253. const elementCheckFields = ['selected', 'rejected', 'groupId']
  254. from.forEach((eleFrom, idx) => {
  255. const eleTo = to[idx]
  256. const eleChanged = elementCheckFields.some(f => eleFrom[f] != eleTo[f])
  257. if (eleChanged) changed = true
  258. })
  259. }
  260. if (changed) this.$message.warning(changedMsg)
  261. return changed ? Promise.reject(changedMsg) : Promise.resolve(true)
  262. },
  263. async toReport() {
  264. await this.preventSelectedListChanged()
  265. this.$refs.reportDialog.open()
  266. },
  267. async toSelectSub(row) {
  268. await this.preventSelectedListChanged()
  269. // 打开选科弹窗
  270. const course0 = this.translateCourse0(row.groupId)
  271. const course1 = this.translateCourse1(row.groupId)
  272. this.$refs.chooseDialog.open(course0, course1)
  273. },
  274. toAiAnalysis() {
  275. // AI 分析 跳转
  276. this.$refs.aiDialog.open(this.formatRows)
  277. }
  278. }
  279. }
  280. </script>
  281. <style scoped>
  282. </style>