useOptions.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { reactive, computed, watch, ref, unref, isRef, nextTick } from 'vue'
  2. import useFetch from '@/hooks/useFetch'
  3. import { ExtractApiResponse } from 'api-type'
  4. import type { Ref } from 'vue'
  5. export interface DataModel {
  6. subject?: string
  7. question?: number
  8. group?: number
  9. }
  10. interface Group {
  11. label: string
  12. value: number
  13. }
  14. type QuestionList = ExtractApiResponse<'getMainQuestionList'>[0] & {
  15. label: string
  16. value: number
  17. }
  18. const useOptions = (types: (keyof DataModel)[], initModel?: DataModel | Ref<DataModel>, autoFill = true) => {
  19. const dataModel = reactive<DataModel>(unref(initModel) || {})
  20. if (isRef(initModel)) {
  21. watch(
  22. initModel,
  23. () => {
  24. Object.assign(dataModel, unref(initModel))
  25. },
  26. { deep: true }
  27. )
  28. }
  29. const changeModelValue = <T extends keyof DataModel>(key: T) => {
  30. return (v: DataModel[T]) => {
  31. dataModel[key] = v
  32. }
  33. }
  34. const { fetch: getSubjectList, result: subjectResult } = useFetch('getSubjectList')
  35. const {
  36. fetch: getMainQuestionList,
  37. result: mainQuestionListResult,
  38. reset: resetQuestionFetch,
  39. } = useFetch('getMainQuestionList')
  40. const {
  41. fetch: getMainQuestionInfo,
  42. result: mainQuestionInfo,
  43. reset: resetMainQuestionFetch,
  44. } = useFetch('getMainQuestionInfo')
  45. const subjectList = computed(() => {
  46. return (
  47. subjectResult.value?.result?.map((subject) => {
  48. return { ...subject, value: subject.code, label: subject.name }
  49. }) || []
  50. )
  51. })
  52. const mainQuestionList = computed<QuestionList[]>(() => {
  53. return (
  54. mainQuestionListResult.value?.map<QuestionList>((v) => {
  55. return {
  56. ...v,
  57. label: v.title,
  58. value: v.mainNumber,
  59. }
  60. }) || []
  61. )
  62. })
  63. const groupList = computed<Group[]>(() => {
  64. return mainQuestionInfo.value?.groupNumber
  65. ? Array.from({ length: mainQuestionInfo.value.groupNumber }).map((_, i) => {
  66. return {
  67. value: i + 1,
  68. label: `第${i + 1}组`,
  69. }
  70. })
  71. : []
  72. })
  73. const groupListWithAll = computed(() => {
  74. return groupList.value?.length ? [{ label: '全部', value: void 0 } as unknown as Group].concat(groupList.value) : []
  75. })
  76. watch(
  77. () => dataModel.subject,
  78. () => {
  79. if (types.includes('question') && dataModel.subject) {
  80. resetQuestionFetch()
  81. resetMainQuestionFetch()
  82. changeModelValue('question')(void 0)
  83. changeModelValue('group')(void 0)
  84. getMainQuestionList({ subjectCode: dataModel.subject })
  85. }
  86. },
  87. { immediate: true }
  88. )
  89. watch(
  90. () => dataModel.question,
  91. () => {
  92. if (types.includes('group') && dataModel.subject && dataModel.question) {
  93. resetMainQuestionFetch()
  94. changeModelValue('group')(void 0)
  95. getMainQuestionInfo({ subjectCode: dataModel.subject, mainNumber: dataModel.question })
  96. }
  97. },
  98. { immediate: true }
  99. )
  100. if (autoFill) {
  101. watch(
  102. subjectList,
  103. () => {
  104. if (subjectList.value?.[0]?.value && !dataModel.subject) {
  105. changeModelValue('subject')(subjectList.value[0].value)
  106. }
  107. },
  108. { deep: true }
  109. )
  110. watch(
  111. mainQuestionList,
  112. () => {
  113. if (mainQuestionList.value?.[0]?.value) {
  114. changeModelValue('question')(mainQuestionList.value[0].value)
  115. }
  116. },
  117. { deep: true }
  118. )
  119. watch(
  120. groupList,
  121. () => {
  122. if (groupList.value?.[0]?.value) {
  123. changeModelValue('group')(groupList.value[0].value)
  124. }
  125. },
  126. { deep: true }
  127. )
  128. }
  129. const initFinish = ref<boolean>(false)
  130. const destroyInit = watch(dataModel, () => {
  131. if (types.every((t) => dataModel[t])) {
  132. nextTick(() => {
  133. initCallbacks.forEach((cb) => cb(dataModel))
  134. initFinish.value = true
  135. destroyInit()
  136. })
  137. }
  138. })
  139. const initCallbacks: ((d: DataModel) => void)[] = []
  140. const onOptionInit = (cb: (d?: DataModel) => void) => {
  141. initCallbacks.push(cb)
  142. }
  143. const forceRefresh = () => {
  144. getSubjectList({ pageNumber: 1, pageSize: 9999 })
  145. }
  146. if (types.includes('subject')) {
  147. forceRefresh()
  148. }
  149. return {
  150. subjectList,
  151. mainQuestionList,
  152. groupList,
  153. groupListWithAll,
  154. dataModel,
  155. initFinish,
  156. onOptionInit,
  157. changeModelValue,
  158. forceRefresh,
  159. }
  160. }
  161. export default useOptions