report-table.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <template>
  2. <div>
  3. <div class="mb10 fx-row fx-end-base jc-between">
  4. <div class="fx-row fx-end-cen">
  5. <slot name="header-prefix"></slot>
  6. <p v-if="!currentSupplyInfo.hidden" v-html="currentSupplyInfo.info"></p>
  7. </div>
  8. <div v-if="!readonly">
  9. <el-button v-if="aiButtonShow" type="primary" @click="toAiAnalysis">AI分析</el-button>
  10. <!-- <el-button>选科历史记录</el-button>-->
  11. </div>
  12. </div>
  13. <mx-table :propDefines="formatCols" :rows="formatRows">
  14. <template #underOver="{value}">
  15. <over-under-badge :value="value"></over-under-badge>
  16. </template>
  17. <template #group="{row}">
  18. <el-tag size="medium" :type="row.allowSelect ? 'warning' : 'danger'" >{{row.groupName}}</el-tag>
  19. </template>
  20. <template #temp="{row}">
  21. <span class="btn-blue mr5" @click="toSelectSub(row)">选择</span>
  22. <span class="btn-green" @click="toReport">查看记录</span>
  23. <!-- <el-button>查看</el-button>-->
  24. </template>
  25. <template #signUp="{row}">
  26. <span class="f-red" v-if="!row.allowSelect">无法报名</span>
  27. <div v-else>
  28. <span v-if="generation.current > 1" @click="commit" class="btn-green">报名</span>
  29. <div v-else>
  30. <span class="f-red btn-red" v-if="row.selected" @click="toUnSelect(row)">取消报名</span>
  31. <span class="btn-green" v-else @click="toSelect(row)">报名</span>
  32. </div>
  33. </div>
  34. </template>
  35. <template #subjects="{row}">
  36. <el-row>
  37. <el-col :span="8" v-for="subject in row.subjects">
  38. <el-popover
  39. placement="top"
  40. popper-class="zero-padding-popover"
  41. trigger="hover"
  42. >
  43. <div class="fx-column">
  44. <el-button plain type="text">{{ subject }}</el-button>
  45. </div>
  46. <el-tag type="success" slot="reference" class="mr10 mb10">{{ subject[0] }}</el-tag>
  47. </el-popover>
  48. </el-col>
  49. </el-row>
  50. </template>
  51. <template #colleges="{row}">
  52. <el-row>
  53. <el-col :span="12" v-for="college in row.colleges">
  54. <el-popover
  55. placement="top"
  56. popper-class="zero-padding-popover"
  57. trigger="hover"
  58. >
  59. <div class="fx-column">
  60. <el-button plain type="text">{{ college.major }}</el-button>
  61. </div>
  62. <el-tag type="success" slot="reference" class="mr10 mb10">{{ college.major[0] }}</el-tag>
  63. </el-popover>
  64. :
  65. <span>{{ college.college }}</span>
  66. </el-col>
  67. </el-row>
  68. </template>
  69. </mx-table>
  70. <!-- 初录 多志愿拖拽 -->
  71. <div v-if="this.generation.active == 1">
  72. <p >您的选科志愿: <span v-for="(item,index) in activeModels.selectedList">
  73. {{ item.groupName }}
  74. <!-- {{ index + 1 < selectedList.length ? '、' : '' }}-->
  75. </span>
  76. </p>
  77. <div >
  78. <test-drage ref="drage" :btnDisabled="this.generation.current != 1" :selectedList="activeModels.selectedList"></test-drage>
  79. <el-button @click="commit" type="primary" v-if="this.generation.current == 1">提交</el-button>
  80. </div>
  81. </div>
  82. <!-- 补录报名和二次补录报名和调剂报名 -->
  83. <div v-if="flagShow">
  84. <!-- <div v-for="item in singleList" class="mb5 mt5">-->
  85. <!-- <el-button @click="commit" type="primary">{{ `${item.groupName} : 报名` }}</el-button>-->
  86. <!-- </div>-->
  87. <div class="mb5 mt10 text-right">
  88. <el-popover
  89. placement="right"
  90. width="300"
  91. v-model="popoShow"
  92. trigger="click"
  93. >
  94. <div>
  95. <el-input
  96. type="textarea"
  97. :rows="4"
  98. placeholder="请输入原因"
  99. v-model="regInfo"
  100. >
  101. </el-input>
  102. <p class="fx-row jc-between mt10">
  103. <el-button type="primary" size="mini" @click="popoShow = false">取消</el-button>
  104. <el-button type="danger" size="mini" v-if="">提交</el-button>
  105. </p>
  106. </div>
  107. <el-button slot="reference" type="danger">不同意</el-button>
  108. </el-popover>
  109. </div>
  110. </div>
  111. <esign-dialog ref="esignDialog"></esign-dialog>
  112. <choose-subject-dialog ref="chooseDialog"></choose-subject-dialog>
  113. <select-subject-report-dialog ref="reportDialog"></select-subject-report-dialog>
  114. <Ai-dialog ref="aiDialog" :generation="generation" ></Ai-dialog>
  115. </div>
  116. </template>
  117. <script>
  118. import AiDialog from './ai-analysis-dialog'
  119. import MxSelectTranslate from '@/components/Cache/modules/mx-select-translate-mixin.js'
  120. import TestDrage from './test-drage'
  121. import ChooseSubjectDialog from './choose-subject-dialog'
  122. import SelectSubjectReportDialog from '@/views/system/user/profile/components/select-subject-report-dialog'
  123. import EsignDialog from '@/views/system/user/profile/components/esign-dialog'
  124. import ReportStep from './report-step'
  125. import PrimaryResolverMixins
  126. from '@/views/system/user/profile/components/round-select-resolvers/primary-resolver-mixins'
  127. import PrimaryDMResolverMixins
  128. from '@/views/system/user/profile/components/round-select-resolvers/primaryDM-resolver-mixins'
  129. import BackTrackingResolverMixins
  130. from '@/views/system/user/profile/components/round-select-resolvers/backTracking-resolver-mixins'
  131. import BackTrackingDMResolverMixins
  132. from '@/views/system/user/profile/components/round-select-resolvers/backTrackingDM-resolver-mixins'
  133. import FinalAdjustResolverMixins
  134. from '@/views/system/user/profile/components/round-select-resolvers/finalAdjust-resolver-mixins'
  135. import FinalAdjustDMResolverMixins
  136. from '@/views/system/user/profile/components/round-select-resolvers/finalAdjustDM-resolver-mixins'
  137. import ForceAdjustResolverMixins
  138. from '@/views/system/user/profile/components/round-select-resolvers/forceAdjust-resolver-mixins'
  139. import OverUnderBadge from '@/views/elective/publish/components/steps/fauclty/over-under-badge'
  140. import { submitElectiveModels } from '@/api/webApi/elective/selected-subject'
  141. export default {
  142. props: {
  143. generation: Object,
  144. readonly: Boolean, // 校长端不允许操作
  145. optionalMajors: { type: Array, default: () => [] }
  146. },
  147. components: {
  148. OverUnderBadge,
  149. SelectSubjectReportDialog,
  150. ReportStep,
  151. EsignDialog,
  152. TestDrage,
  153. ChooseSubjectDialog,
  154. AiDialog
  155. },
  156. inject: ['loadStudentSelected','getStudentElectiveModels'],
  157. mixins: [
  158. MxSelectTranslate,
  159. PrimaryResolverMixins,
  160. PrimaryDMResolverMixins,
  161. BackTrackingResolverMixins,
  162. BackTrackingDMResolverMixins,
  163. FinalAdjustDMResolverMixins,
  164. FinalAdjustResolverMixins,
  165. ForceAdjustResolverMixins
  166. ],
  167. data() {
  168. return {
  169. popoShow: false,
  170. activeStep: '',
  171. regInfo: '',
  172. dialogVisible: false,
  173. singleList: [], // 单志愿列表
  174. rows: [],
  175. }
  176. },
  177. computed: {
  178. // 不符
  179. currentSupplyInfo() {
  180. if(!this.generation.models.length) return {}
  181. // console.log(this.generation)
  182. if(this.generation.active < 2) return {}
  183. let info = ''
  184. const activeModels = this.generation.models.find(item => item.generation == this.generation.active)
  185. // 是否被录取?
  186. const approved = activeModels.models.filter(item => {return item.approved})
  187. if(approved.length) {
  188. // 查找
  189. // 已被录取
  190. info = `同学,你好,你之前所选择的${approved.groupName}已被录取`
  191. }else {
  192. // 已报名未被录取的group 取当前models的前一个
  193. const prevModels = this.generation.models.find(item => item.generation == activeModels.generation - 1)
  194. // 拒绝的组合
  195. const refuseGroup = prevModels.models.filter(item => {return item.selected})
  196. // 获取报名的阶段
  197. let tips = ''
  198. console.log( Object.values(this.generation.options))
  199. const prevGen = Object.values(this.generation.options).find(item => item.value == prevModels.generation)
  200. if(prevGen.decisionMaking){
  201. tips = Object.values(this.generation.options).find(item => item.value == prevModels.generation - 1).title
  202. }else {
  203. tips = prevGen.title
  204. }
  205. const isSupply = prevGen.decisionMaking ? '现有以下标黄组合可以重新报名' : ''
  206. console.log(prevGen)
  207. console.log(refuseGroup)
  208. info = `<p>同学,你好,你在${tips}所选择的 <span class="f-red">${refuseGroup.map(g => g.groupName).join(',').toString()} </span>不符合报名条件${isSupply} </p>`
  209. }
  210. console.log(approved)
  211. const isHidden = this.generation.active > 1
  212. return {
  213. hidden: !isHidden,
  214. info:info
  215. }
  216. },
  217. flagShow() {
  218. return (this.generation.current == 3 && this.generation.active == 3) ||
  219. (this.generation.current == 5 && this.generation.active == 5) ||
  220. (this.generation.current == 5 && this.generation.active == 7)
  221. },
  222. aiButtonShow() {
  223. const aiButtonShow = !this.generation.activeOpt?.decisionMaking && this.generation.activeOpt?.key != 'primary'
  224. return aiButtonShow
  225. },
  226. resolveTablePrefix() {
  227. return {
  228. index: {
  229. type: 'index',
  230. label: '编号',
  231. },
  232. groupName: {
  233. label: '选科组合',
  234. slot:'group',
  235. width:'85px'
  236. },
  237. scoreSumGroup: {
  238. label: '组合成绩'
  239. },
  240. classCount: {
  241. label: '开设班级数'
  242. },
  243. personCount: {
  244. label: '人数设置'
  245. }
  246. }
  247. },
  248. resolveTableSuffix() {
  249. const stepMatched = this.generation.active == this.generation.current
  250. const enableApply = !this.generation.currentOpt.decisionMaking
  251. const enableSignUp = stepMatched && enableApply && !this.readonly
  252. return {
  253. allowSelectTips: {
  254. label: '报名状态'
  255. },
  256. temp: {
  257. label: '选择专业',
  258. width: '140',
  259. slot: 'temp',
  260. hidden: this.readonly
  261. },
  262. subjects: {
  263. label: '自选专业',
  264. slot: 'subjects',
  265. width: '150'
  266. },
  267. colleges: {
  268. label: '院校',
  269. slot: 'colleges',
  270. width: '250'
  271. },
  272. signUp: {
  273. label: '操作',
  274. slot: 'signUp',
  275. width: '100',
  276. fixed: 'right',
  277. hidden: !enableSignUp
  278. }
  279. }
  280. },
  281. resolveDynamicTable() {
  282. if (!Object.keys(this.formatRows).length) return {}
  283. const options = this.generation.options
  284. if (!options || !this.generation.active) return {}
  285. const optValues = Object.values(options)
  286. const dynamicColumns = {}
  287. for (let gen = options.primary.value; gen <= this.generation.active; gen++) {
  288. const opt = optValues.find(opt => opt.value == gen)
  289. const resolverKey = opt.key + 'Resolver'
  290. const resolver = this[resolverKey]
  291. if (typeof resolver === 'function') {
  292. const genColumns = resolver(gen, this.generation.active)
  293. Object.assign(dynamicColumns, genColumns)
  294. }
  295. }
  296. return dynamicColumns
  297. },
  298. activeModels(){
  299. if(!this.generation) return {}
  300. const generation = this.generation.models.find(item => item.generation == this.generation.active)
  301. // generation.selectedList = generation.models.filter(item => {
  302. // return item.selected
  303. // })
  304. return generation
  305. },
  306. // 初始化 rows 填充固定数据
  307. formatRows() {
  308. if (!this.optionalMajors) return []
  309. if (!this.generation.roundGroups?.length) return []
  310. if (!this.generation.activeModels?.length) return []
  311. const generationModels = this.generation.activeModels.last()?.models || []
  312. return this.generation.roundGroups.map(rg => {
  313. const row = generationModels.find(item => item.groupId == rg.groupId) || {}
  314. row.allowSelectTips = row.allowSelect ? '报名中' : row.disabledReason || '无法报名'
  315. const matchedMajors = this.optionalMajors.filter(college => college.matchedGroupIds.includes(row.groupId))
  316. row.colleges = matchedMajors.map(m => ({ college: m.collegeName, major: m.majorCategoryName }))
  317. row.subjects = matchedMajors.map(m => m['majorCategoryName'])
  318. // this.$set(row,'colleges',matchedMajors.map(m => ({ college: m.collegeName, major: m.majorCategoryName })))
  319. // this.$set(row,'subjects',matchedMajors.map(m => m['majorCategoryName']))
  320. return row
  321. })
  322. },
  323. formatCols() {
  324. return {
  325. ...this.resolveTablePrefix,
  326. ...this.resolveDynamicTable,
  327. ...this.resolveTableSuffix
  328. }
  329. }
  330. },
  331. methods: {
  332. getModelsByStep() {
  333. return this.models.findIndex()
  334. },
  335. toReport() {
  336. // 是否更改了报名数据 ?
  337. const flag = this.activeModels.models.filter(item => item.selected).length == this.activeModels.selectedList.length
  338. if(!flag) {
  339. this.$message.warning('请先提交更改过的志愿')
  340. return
  341. }
  342. this.$refs.reportDialog.open()
  343. },
  344. toAiAnalysis() {
  345. // AI 分析 跳转
  346. console.log(this.formatRows)
  347. this.$refs.aiDialog.open(this.formatRows)
  348. },
  349. commit() {
  350. if (this.generation.current == 1) {
  351. const real = this.activeModels.selectedList.filter(item => {
  352. return item.selected == true
  353. })
  354. console.log(real)
  355. if (real.length < this.generation.status.preferenceCount) {
  356. this.$message.warning(`初录报名需要选择${this.generation.status.preferenceCount}个志愿`)
  357. return
  358. }
  359. }
  360. this.$confirm(`是否要提交报名`, {
  361. confirmButtonText: '确定',
  362. cancelButtonText: '取消',
  363. type: 'warning'
  364. }).then(() => {
  365. submitElectiveModels({
  366. models:this.activeModels.selectedList,
  367. // esign:this.base64Img
  368. }).then(res => {
  369. if(res.code == 200) {
  370. this.$message.success('报名成功')
  371. this.loadStudentSelected()
  372. this.getStudentElectiveModels()
  373. }
  374. console.log(res)
  375. })
  376. }).catch(() => {
  377. this.$message({
  378. type: 'info',
  379. message: '已取消提交'
  380. })
  381. })
  382. //
  383. // this.$refs.esignDialog.open(this.activeModels.selectedList)
  384. },
  385. toSelect(row) {
  386. const preferenceCount = this.generation.status.preferenceCount
  387. const count = this.formatRows.reduce((prev, cur) => {
  388. return prev += cur.selected ? 1 : 0
  389. },0)
  390. if (count >= preferenceCount) {
  391. this.$message.warning(`最多选择${preferenceCount}个志愿`)
  392. return
  393. }
  394. this.activeModels.models.find(item => item.groupId == row.groupId).selected = true
  395. row.selected = true
  396. this.activeModels.selectedList.push(row)
  397. },
  398. toUnSelect(row) {
  399. this.$confirm(`是否解除选科组合【${row.groupName}】`, '警告', {
  400. confirmButtonText: '确定',
  401. cancelButtonText: '取消',
  402. type: 'warning'
  403. }).then(() => {
  404. this.activeModels.models.find(item => item.groupId == row.groupId).selected = false
  405. row.selected = false
  406. const start = this.activeModels.selectedList.findIndex(item => item.groupId == row.groupId)
  407. console.log(start)
  408. this.activeModels.selectedList.splice(start, 1)
  409. }).catch(() => {
  410. this.$message({
  411. type: 'info',
  412. message: '已取消解除报名'
  413. })
  414. })
  415. },
  416. toSelectSub(row) {
  417. // 是否更改了报名数据 ?
  418. const flag = this.activeModels.models.filter(item => item.selected).length == this.activeModels.selectedList.length
  419. if(!flag) {
  420. this.$message.warning('请先提交更改过的志愿')
  421. return
  422. }
  423. // 打开选科弹窗
  424. const course0 = this.translateCourse0(row.groupId)
  425. const course1 = this.translateCourse1(row.groupId)
  426. this.$refs.chooseDialog.open(course0, course1)
  427. },
  428. initOption(optionalMajors) {
  429. console.log(optionalMajors)
  430. this.optionalMajors = optionalMajors
  431. }
  432. }
  433. }
  434. </script>
  435. <style scoped>
  436. .cell .el-tag {
  437. margin-right: 5px;
  438. }
  439. </style>