addMaterialTrainingClass.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. import SaveForm from '@/components/save-form'
  2. import Pagination from '@/components/pagination'
  3. import {
  4. DataTableColumn,
  5. NButton,
  6. NCascader,
  7. NCol,
  8. NDataTable,
  9. NDatePicker,
  10. NFormItem,
  11. NInput,
  12. NModal,
  13. NRow,
  14. NSelect,
  15. NSpace,
  16. NTag,
  17. NTooltip,
  18. useDialog,
  19. useMessage,
  20. NEmpty,
  21. NIcon
  22. } from 'naive-ui'
  23. import { defineComponent, inject, onMounted, reactive, ref, provide, nextTick } from 'vue'
  24. import { InternalRowData } from 'naive-ui/es/data-table/src/interface'
  25. import { lessonType, getLessonType } from '@/views/knowledge-manage/knowledgeTypeData'
  26. import { fetchCategoryList } from '@/views/educational-manage/api'
  27. import {
  28. lessonTrainingDetailBatchInsert,
  29. lessonTrainingDetailMaterialPage
  30. } from '@/views/teaching-manage/api'
  31. import { fetchKnowledgeList } from '@/views/knowledge-manage/api'
  32. const classType: { [_: string]: any } = {
  33. VIDEO: '视频',
  34. IMG: '视频',
  35. SONG: '曲目'
  36. }
  37. export default defineComponent({
  38. name: 'addMaterialTraining',
  39. props: {
  40. parentData: {
  41. type: Object,
  42. default: () => {}
  43. }
  44. },
  45. emits: ['close', 'handleSuccess'],
  46. setup(props, { emit }) {
  47. console.log('🚀 ~ props', props.parentData.id)
  48. const dialog = useDialog()
  49. const message = useMessage()
  50. const state = reactive({
  51. loading: false,
  52. saveLoading: false,
  53. pagination: {
  54. page: 1,
  55. rows: 10,
  56. pageTotal: 10
  57. },
  58. dataList: [] as any,
  59. checkList: [] as string[],
  60. selectCheckList: [] as any
  61. })
  62. const searchForm = reactive({
  63. keyword: '',
  64. // materialCategoryId: null
  65. knowledgePointIds: null
  66. })
  67. // 获取分类列表
  68. // const category = reactive({
  69. // list: [] as any,
  70. // index: -1,
  71. // loading: false
  72. // })
  73. // const getCategoryList = async () => {
  74. // category.loading = true
  75. // try {
  76. // const { data } = await fetchCategoryList({ page: 1 })
  77. // category.list = data?.rows || []
  78. // } catch {}
  79. // category.loading = false
  80. // }
  81. // 知识点列表
  82. const knowledge = reactive({
  83. list: [] as any,
  84. index: -1,
  85. loading: false
  86. })
  87. const getKnowledgeList = async () => {
  88. try {
  89. const { data } = await fetchKnowledgeList({
  90. courseTypeCode: props.parentData.courseTypeCode,
  91. page: 1,
  92. rows: 1000
  93. })
  94. console.log(data)
  95. const tempList = data.rows || []
  96. // if (!searchForm.knowledgePointId) {
  97. // searchForm.knowledgePointId = tempList.length > 0 ? tempList[0].id : null
  98. // }
  99. knowledge.list = tempList
  100. } catch {}
  101. }
  102. const columns = (): DataTableColumn[] => {
  103. return [
  104. {
  105. type: 'selection',
  106. disabled(row) {
  107. return row.knowledgePointId ? false : true
  108. }
  109. },
  110. {
  111. title: '素材名称',
  112. key: 'materialName',
  113. fixed: 'left'
  114. },
  115. {
  116. title: '素材类型',
  117. key: 'materialCategoryName',
  118. render(row) {
  119. return classType[row.type as any]
  120. }
  121. },
  122. {
  123. title: '分段编号',
  124. key: 'sn'
  125. },
  126. {
  127. title: '课程类型',
  128. key: 'courseTypeName',
  129. width: 200,
  130. ellipsis: true,
  131. render(row: InternalRowData) {
  132. return (
  133. <NTooltip placement="left-start">
  134. {{
  135. default: () => row.courseTypeName,
  136. trigger: () => row.courseTypeName
  137. }}
  138. </NTooltip>
  139. )
  140. }
  141. },
  142. {
  143. title: '知识点分类',
  144. key: 'knowledgePointName'
  145. }
  146. ]
  147. }
  148. const saveForm = ref()
  149. const onSubmit = () => {
  150. state.pagination.page = 1
  151. getList()
  152. }
  153. const onSearch = () => {
  154. saveForm.value?.submit()
  155. }
  156. const onBtnReset = () => {
  157. // saveForm.value?.reset()
  158. // 默认选中第一个
  159. searchForm.knowledgePointIds = null
  160. searchForm.keyword = ''
  161. onSearch()
  162. }
  163. const getList = async () => {
  164. try {
  165. state.loading = true
  166. const tranbody = {
  167. lessonTrainingId: props.parentData.id,
  168. ...searchForm,
  169. courseTypeCode: props.parentData.courseTypeCode,
  170. page: state.pagination.page,
  171. rows: state.pagination.rows,
  172. knowledgePointId: null
  173. }
  174. const { data } = await lessonTrainingDetailMaterialPage(tranbody)
  175. state.loading = false
  176. state.pagination.pageTotal = Number(data.total)
  177. // state.dataList = data.rows || []
  178. const tempRows = data.rows || []
  179. tempRows.forEach((row: any) => {
  180. row.tempIndex = new Date().getTime() + '' + Math.random()
  181. // state.dataList.push({
  182. // ...row
  183. // })
  184. })
  185. console.log(tempRows, 'rows')
  186. state.dataList = tempRows
  187. } catch {
  188. state.loading = false
  189. }
  190. }
  191. onMounted(async () => {
  192. await getKnowledgeList()
  193. // getCategoryList()
  194. nextTick(async () => {
  195. await getList()
  196. })
  197. })
  198. // 素材关联知识点
  199. const handleSave = async () => {
  200. // state.saveLoading = true
  201. // const list = state.checkList.map((n: any) => {
  202. // const item = state.selectCheckList.find((item: any) => item.tempIndex === n)
  203. // return {
  204. // materialId: item.materialId,
  205. // knowledgePointId: item.knowledgePointId,
  206. // lessonTrainingId: props.parentData.id
  207. // }
  208. // })
  209. // try {
  210. // const res: any = await lessonTrainingDetailBatchInsert(list)
  211. // message.success('保存成功')
  212. // emit('handleSuccess')
  213. // } catch (error) {}
  214. // state.saveLoading = false
  215. dialog.warning({
  216. title: '提示',
  217. content: '请确保作业曲目已添加到业务系统',
  218. positiveText: '确定',
  219. negativeText: '取消',
  220. onPositiveClick: async () => {
  221. state.saveLoading = true
  222. const list = state.checkList.map((n: any) => {
  223. const item = state.selectCheckList.find((item: any) => item.tempIndex === n)
  224. return {
  225. materialId: item.materialId,
  226. knowledgePointId: item.knowledgePointId,
  227. lessonTrainingId: props.parentData.id
  228. }
  229. })
  230. try {
  231. const res: any = await lessonTrainingDetailBatchInsert(list)
  232. message.success('保存成功')
  233. emit('handleSuccess')
  234. } catch (error) {}
  235. state.saveLoading = false
  236. },
  237. onNegativeClick: () => {}
  238. })
  239. }
  240. return () => (
  241. <>
  242. <SaveForm
  243. style={{ padding: 0, boxShadow: 'none' }}
  244. ref={saveForm}
  245. label-width=""
  246. model={searchForm}
  247. onSubmit={onSubmit}
  248. onSetModel={(val: any) => Object.assign(searchForm, val)}
  249. saveKey="addMaterialTraining-abc-key-class"
  250. >
  251. <NFormItem label="知识点分类" path="knowledgePointIds">
  252. <NCascader
  253. v-model:value={searchForm.knowledgePointIds}
  254. options={knowledge.list}
  255. multiple
  256. clearable
  257. filterable
  258. childrenField="children"
  259. expandTrigger="hover"
  260. valueField="id"
  261. labelField="name"
  262. checkStrategy="all"
  263. cascade
  264. showPath
  265. maxTagCount={'responsive'}
  266. v-slots={{
  267. empty: () =>
  268. knowledge.loading ? (
  269. <>
  270. <NEmpty
  271. description="加载中"
  272. v-slots={{
  273. icon: () => (
  274. <NIcon size="30">
  275. <svg
  276. xmlns="http://www.w3.org/2000/svg"
  277. xmlns:xlink="http://www.w3.org/1999/xlink"
  278. viewBox="0 0 1024 1024"
  279. >
  280. <path
  281. d="M988 548c-19.9 0-36-16.1-36-36c0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9a437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7c26.7 63.1 40.2 130.2 40.2 199.3c.1 19.9-16 36-35.9 36z"
  282. fill="currentColor"
  283. ></path>
  284. </svg>
  285. </NIcon>
  286. )
  287. }}
  288. ></NEmpty>
  289. </>
  290. ) : null
  291. }}
  292. />
  293. </NFormItem>
  294. <NFormItem label="素材名称/编号" path="keyword">
  295. <NInput
  296. v-model:value={searchForm.keyword}
  297. onKeydown={(e) => {
  298. if (e.code === 'Enter') {
  299. onSubmit()
  300. }
  301. }}
  302. clearable
  303. />
  304. </NFormItem>
  305. <NFormItem>
  306. <NSpace>
  307. <NButton type="primary" onClick={onSearch}>
  308. 搜索
  309. </NButton>
  310. <NButton type="default" onClick={onBtnReset}>
  311. 重置
  312. </NButton>
  313. </NSpace>
  314. </NFormItem>
  315. </SaveForm>
  316. <NDataTable
  317. loading={state.loading}
  318. maxHeight="calc(100vh - 270px)"
  319. rowKey={(row: any) => row.tempIndex}
  320. columns={columns()}
  321. data={state.dataList}
  322. v-model:checkedRowKeys={state.checkList}
  323. onUpdate:checkedRowKeys={(keys: any, rows: any, meta: any) => {
  324. // state.selectCheckList
  325. // 处理删除的数据
  326. const tempList: any = []
  327. state.selectCheckList.forEach((item: any) => {
  328. if (state.checkList.includes(item.tempIndex)) {
  329. tempList.push(item)
  330. }
  331. })
  332. // 添加新增的数据
  333. state.checkList.forEach((key: string) => {
  334. const item = state.dataList.find((item: any) => item.tempIndex === key)
  335. const index = state.selectCheckList.findIndex((item: any) => item.tempIndex === key)
  336. if (index <= -1) {
  337. tempList.push(item)
  338. }
  339. })
  340. state.selectCheckList = [...tempList]
  341. }}
  342. ></NDataTable>
  343. <Pagination
  344. v-model:page={state.pagination.page}
  345. v-model:pageTotal={state.pagination.pageTotal}
  346. v-model:pageSize={state.pagination.rows}
  347. onList={getList}
  348. sync
  349. saveKey="addMaterialTraining-abc-key-class"
  350. ></Pagination>
  351. <NButton
  352. type="primary"
  353. disabled={state.checkList.length ? false : true}
  354. loading={state.saveLoading}
  355. onClick={() => handleSave()}
  356. >
  357. 确认
  358. </NButton>
  359. </>
  360. )
  361. }
  362. })