addMaterialTrainingClass.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. }
  216. return () => (
  217. <>
  218. <SaveForm
  219. style={{ padding: 0, boxShadow: 'none' }}
  220. ref={saveForm}
  221. label-width=""
  222. model={searchForm}
  223. onSubmit={onSubmit}
  224. onSetModel={(val: any) => Object.assign(searchForm, val)}
  225. saveKey="addMaterialTraining-abc-key-class"
  226. >
  227. <NFormItem label="知识点分类" path="knowledgePointIds">
  228. <NCascader
  229. v-model:value={searchForm.knowledgePointIds}
  230. options={knowledge.list}
  231. multiple
  232. clearable
  233. filterable
  234. childrenField="children"
  235. expandTrigger="hover"
  236. valueField="id"
  237. labelField="name"
  238. checkStrategy="all"
  239. cascade
  240. showPath
  241. maxTagCount={'responsive'}
  242. v-slots={{
  243. empty: () =>
  244. knowledge.loading ? (
  245. <>
  246. <NEmpty
  247. description="加载中"
  248. v-slots={{
  249. icon: () => (
  250. <NIcon size="30">
  251. <svg
  252. xmlns="http://www.w3.org/2000/svg"
  253. xmlns:xlink="http://www.w3.org/1999/xlink"
  254. viewBox="0 0 1024 1024"
  255. >
  256. <path
  257. 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"
  258. fill="currentColor"
  259. ></path>
  260. </svg>
  261. </NIcon>
  262. )
  263. }}
  264. ></NEmpty>
  265. </>
  266. ) : null
  267. }}
  268. />
  269. </NFormItem>
  270. <NFormItem label="素材名称/编号" path="keyword">
  271. <NInput
  272. v-model:value={searchForm.keyword}
  273. onKeydown={(e) => {
  274. if (e.code === 'Enter') {
  275. onSubmit()
  276. }
  277. }}
  278. clearable
  279. />
  280. </NFormItem>
  281. <NFormItem>
  282. <NSpace>
  283. <NButton type="primary" onClick={onSearch}>
  284. 搜索
  285. </NButton>
  286. <NButton type="default" onClick={onBtnReset}>
  287. 重置
  288. </NButton>
  289. </NSpace>
  290. </NFormItem>
  291. </SaveForm>
  292. <NDataTable
  293. loading={state.loading}
  294. maxHeight="calc(100vh - 270px)"
  295. rowKey={(row: any) => row.tempIndex}
  296. columns={columns()}
  297. data={state.dataList}
  298. v-model:checkedRowKeys={state.checkList}
  299. onUpdate:checkedRowKeys={(keys: any, rows: any, meta: any) => {
  300. // state.selectCheckList
  301. // 处理删除的数据
  302. const tempList: any = []
  303. state.selectCheckList.forEach((item: any) => {
  304. if (state.checkList.includes(item.tempIndex)) {
  305. tempList.push(item)
  306. }
  307. })
  308. // 添加新增的数据
  309. state.checkList.forEach((key: string) => {
  310. const item = state.dataList.find((item: any) => item.tempIndex === key)
  311. const index = state.selectCheckList.findIndex((item: any) => item.tempIndex === key)
  312. if (index <= -1) {
  313. tempList.push(item)
  314. }
  315. })
  316. state.selectCheckList = [...tempList]
  317. }}
  318. ></NDataTable>
  319. <Pagination
  320. v-model:page={state.pagination.page}
  321. v-model:pageTotal={state.pagination.pageTotal}
  322. v-model:pageSize={state.pagination.rows}
  323. onList={getList}
  324. sync
  325. saveKey="addMaterialTraining-abc-key-class"
  326. ></Pagination>
  327. <NButton
  328. type="primary"
  329. disabled={state.checkList.length ? false : true}
  330. loading={state.saveLoading}
  331. onClick={() => handleSave()}
  332. >
  333. 确认
  334. </NButton>
  335. </>
  336. )
  337. }
  338. })