useOptions.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. import { reactive, computed, watch, ref, unref, isRef, nextTick } from 'vue'
  2. import useFetch from '@/hooks/useFetch'
  3. import useMainStore from '@/store/main'
  4. import { ExtractApiResponse } from '@/api/api'
  5. import { useRoute } from 'vue-router'
  6. import type { Ref } from 'vue'
  7. export interface DataModel {
  8. subject?: string
  9. question?: number | string
  10. group?: any
  11. }
  12. interface Group {
  13. label: string
  14. value: any
  15. }
  16. type QuestionList = ExtractApiResponse<'getMainQuestionList'>[0] & {
  17. label: string
  18. value: number
  19. }
  20. const useOptions = (
  21. types: (keyof DataModel)[],
  22. initModel?: DataModel | Ref<DataModel>,
  23. autoFill = true,
  24. subjectEnable: boolean | null = true,
  25. multGroup = false,
  26. isAiCheck = false,
  27. showAllLabel = true
  28. ) => {
  29. const mainStore = useMainStore()
  30. const route = useRoute()
  31. const _subjectCode = (route.query?._subjectCode || '') as string
  32. const _questionMainNumber = Number(route.query?._questionMainNumber || '')
  33. const userInfo = computed(() => {
  34. return mainStore?.myUserInfo
  35. })
  36. const isAdmin = computed(() => {
  37. return userInfo?.value?.role === 'ADMIN'
  38. })
  39. const isChief = computed(() => {
  40. return userInfo?.value?.role === 'CHIEF'
  41. })
  42. const isExpert = computed(() => {
  43. return userInfo?.value?.role === 'EXPERT'
  44. })
  45. const isLeader = computed(() => {
  46. return userInfo?.value?.role === 'SECTION_LEADER'
  47. })
  48. const isDeputy = computed(() => {
  49. return userInfo?.value?.role === 'DEPUTY'
  50. })
  51. const dataModel = reactive<DataModel>(unref(initModel) || {})
  52. if (isRef(initModel)) {
  53. watch(
  54. initModel,
  55. () => {
  56. Object.assign(dataModel, unref(initModel))
  57. },
  58. { deep: true }
  59. )
  60. }
  61. const changeModelValue = <T extends keyof DataModel>(key: T) => {
  62. return (v: DataModel[T]) => {
  63. console.log('changeModelValue', key, v)
  64. // dataModel[key] = v
  65. if (multGroup && showAllLabel && key === 'group') {
  66. if (v.includes(undefined)) {
  67. if (dataModel[key]?.length === groupListWithAll.value.length) {
  68. //说明了原本是全选状态,取消勾选了某个不是“全部”的选项
  69. dataModel[key] = v.filter((item: any) => !!item)
  70. } else {
  71. //说明原本是非全选状态,而点击后包含了“全部”选项, 那么就触发全部勾选逻辑
  72. dataModel[key] = groupListWithAll.value.map((item: any) => item.value)
  73. }
  74. } else {
  75. if (v?.length === groupListWithAll.value.length - 1 && dataModel[key]?.includes(undefined)) {
  76. //说明在全部勾选的情况下,点了“全部”,则要全部取消勾选;
  77. dataModel[key] = []
  78. } else if (v?.length === groupListWithAll.value.length - 1) {
  79. //说明了在没有点击“全部”的情况下,逐步勾选完了除了“全部”以外的所有选项,那么就要出发全部勾选逻辑,同时给“全部”自动加上勾选
  80. dataModel[key] = groupListWithAll.value.map((item: any) => item.value)
  81. } else {
  82. dataModel[key] = v.filter((item: any) => !!item)
  83. }
  84. }
  85. } else {
  86. dataModel[key] = v
  87. }
  88. }
  89. }
  90. const { fetch: getSubjectList, result: subjectResult } = useFetch('getSubjectList')
  91. const {
  92. fetch: getMainQuestionList,
  93. result: mainQuestionListResult,
  94. reset: resetQuestionFetch,
  95. } = useFetch('getMainQuestionList')
  96. const {
  97. fetch: getQuestionGroupList,
  98. result: groupListResult,
  99. reset: resetGroupList,
  100. } = useFetch('getQuestionGroupList')
  101. const subjectList = computed(() => {
  102. // const arr: any =
  103. // subjectResult.value?.result?.map((subject) => {
  104. // return { ...subject, value: subject.code, label: `${subject.code}-${subject.name}` }
  105. // }) || []
  106. // if (isExpert.value) {
  107. // arr.unshift({ label: '全部', value: void 0 })
  108. // }
  109. // return arr
  110. return (
  111. subjectResult.value?.result?.map((subject) => {
  112. return { ...subject, value: subject.code, label: `${subject.code}-${subject.name}` }
  113. }) || []
  114. )
  115. })
  116. const mainQuestionList = computed<any[]>(() => {
  117. // const arr =
  118. // mainQuestionListResult.value?.map((v: any) => {
  119. // return {
  120. // ...v,
  121. // label: `${v.mainNumber}-${v.title}`,
  122. // value: v.mainNumber,
  123. // }
  124. // }) || []
  125. // if (isExpert.value || isLeader.value) {
  126. // arr.unshift({ label: '全部', value: void 0 })
  127. // }
  128. // return arr
  129. return (
  130. mainQuestionListResult.value?.map((v: any) => {
  131. return {
  132. ...v,
  133. label: `${v.mainNumber}-${v.title}`,
  134. value: v.mainNumber,
  135. }
  136. }) || []
  137. ).filter((v: any) => {
  138. if (isAiCheck) {
  139. return !!v.relationMainNumber
  140. } else {
  141. return v
  142. }
  143. })
  144. })
  145. const groupList = computed<Group[]>(() => {
  146. return (
  147. groupListResult?.value?.map((n) => {
  148. return {
  149. value: n,
  150. label: `第${n}组`,
  151. }
  152. }) || []
  153. )
  154. })
  155. const groupListWithAll = computed(() => {
  156. return groupList.value?.length &&
  157. (isAdmin.value || isChief.value || isExpert.value || isLeader.value) &&
  158. showAllLabel
  159. ? [{ label: '全部', value: void 0 } as unknown as Group].concat(groupList.value)
  160. : groupList.value
  161. })
  162. watch(
  163. userInfo,
  164. () => {
  165. if (!dataModel.subject && userInfo.value?.subjectCode) {
  166. dataModel.subject = userInfo.value.subjectCode
  167. }
  168. if (!dataModel.question && userInfo.value?.mainNumber) {
  169. dataModel.question = userInfo.value.mainNumber
  170. }
  171. if (!dataModel.group && userInfo.value?.markingGroupNumber && !(isAdmin.value || isChief.value)) {
  172. dataModel.group = multGroup
  173. ? userInfo.value.markingGroupNumber
  174. ? [userInfo.value.markingGroupNumber]
  175. : []
  176. : userInfo.value.markingGroupNumber
  177. }
  178. },
  179. { immediate: true }
  180. )
  181. watch(
  182. () => dataModel.subject,
  183. () => {
  184. if (types.includes('question') && dataModel.subject) {
  185. // resetQuestionFetch()
  186. // resetGroupList()
  187. // changeModelValue('question')(void 0)
  188. // changeModelValue('group')(void 0)
  189. getMainQuestionList({ subjectCode: dataModel.subject })
  190. // dataModel.question = undefined
  191. }
  192. },
  193. { immediate: true }
  194. )
  195. const watchQuestionHandle = () => {
  196. if (types.includes('group') && dataModel.subject && dataModel.question) {
  197. // resetGroupList()
  198. // changeModelValue('group')(void 0)
  199. getQuestionGroupList({ subjectCode: dataModel.subject, mainNumber: dataModel.question }).then((res: any) => {
  200. changeModelValue('group')(
  201. multGroup && showAllLabel
  202. ? groupList.value?.length && (isAdmin.value || isChief.value || isExpert.value || isLeader.value)
  203. ? // ? [void 0]
  204. []
  205. : []
  206. : void 0
  207. )
  208. })
  209. }
  210. }
  211. watch(
  212. // [() => dataModel.question, () => dataModel.question],
  213. () => dataModel.question,
  214. () => {
  215. watchQuestionHandle()
  216. },
  217. { immediate: true }
  218. )
  219. if (autoFill) {
  220. watch(
  221. [subjectList, userInfo],
  222. () => {
  223. if (userInfo.value?.subjectCode && !dataModel.subject) {
  224. changeModelValue('subject')(userInfo.value?.subjectCode)
  225. }
  226. //如果是专家进来,则用户信息里的subjectCode是没值的,这种情况,给专家默认选择科目列表里的第一个科目
  227. if (userInfo.value?.role === 'EXPERT' && !userInfo.value?.subjectCode) {
  228. if (subjectList.value.length) {
  229. changeModelValue('subject')(_subjectCode || subjectList.value[0].value)
  230. }
  231. }
  232. },
  233. { deep: true }
  234. )
  235. watch(
  236. [mainQuestionList, userInfo],
  237. () => {
  238. if (userInfo.value?.mainNumber && !dataModel.question) {
  239. changeModelValue('question')(userInfo.value?.mainNumber)
  240. }
  241. if (
  242. (userInfo.value?.role === 'EXPERT' || userInfo.value?.role === 'SECTION_LEADER') &&
  243. !userInfo.value?.mainNumber
  244. ) {
  245. if (mainQuestionList.value.length) {
  246. const oldQuestionNumber = dataModel.question
  247. changeModelValue('question')(_questionMainNumber || mainQuestionList.value[0].value)
  248. if (oldQuestionNumber == mainQuestionList.value[0].value) {
  249. //防止切换科目前的大题号和切换科目后的大题号相同,watch question监听不执行
  250. watchQuestionHandle()
  251. }
  252. }
  253. }
  254. },
  255. { deep: true }
  256. )
  257. watch(
  258. [groupList, userInfo, isAdmin, isChief],
  259. () => {
  260. if (userInfo.value?.markingGroupNumber && !dataModel.question && !(isAdmin.value || isChief.value)) {
  261. changeModelValue('group')(
  262. multGroup
  263. ? userInfo.value?.markingGroupNumber
  264. ? [userInfo.value?.markingGroupNumber]
  265. : []
  266. : userInfo.value?.markingGroupNumber
  267. )
  268. }
  269. },
  270. { deep: true }
  271. )
  272. }
  273. const initFinish = ref<boolean>(false)
  274. const destroyInit = watch(
  275. [dataModel, isAdmin, isChief],
  276. () => {
  277. if (
  278. types.every((t) => {
  279. return (
  280. (Array.isArray(dataModel[t]) ? dataModel[t].length > 0 : !!dataModel[t]) ||
  281. (t === 'group' && (isAdmin.value || isChief.value || isExpert.value || isLeader.value))
  282. )
  283. })
  284. ) {
  285. nextTick(() => {
  286. initCallbacks.forEach((cb) => cb(dataModel))
  287. initFinish.value = true
  288. destroyInit()
  289. })
  290. }
  291. },
  292. { immediate: true }
  293. )
  294. const initCallbacks: ((d: DataModel) => void)[] = []
  295. const onOptionInit = (cb: (d?: DataModel) => void) => {
  296. initCallbacks.push(cb)
  297. }
  298. const forceRefresh = () => {
  299. getSubjectList({ pageNumber: 1, pageSize: 9999, enable: subjectEnable || void 0 })
  300. }
  301. if (types.includes('subject')) {
  302. forceRefresh()
  303. }
  304. return {
  305. getMainQuestionList,
  306. getQuestionGroupList,
  307. subjectList,
  308. mainQuestionList,
  309. groupList,
  310. groupListWithAll,
  311. dataModel,
  312. initFinish,
  313. onOptionInit,
  314. changeModelValue,
  315. forceRefresh,
  316. isExpert,
  317. isLeader,
  318. isDeputy,
  319. }
  320. }
  321. export default useOptions