index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. import ColUpload from '@/components/col-upload'
  2. import ColUploadVideo from '@/components/col-upload-video'
  3. import request from '@/helpers/request'
  4. import { scrollAnimation } from '@/util/scroll'
  5. import {
  6. ElButton,
  7. ElCol,
  8. ElDialog,
  9. ElForm,
  10. ElFormItem,
  11. ElIcon,
  12. ElInput,
  13. ElMessage,
  14. ElMessageBox,
  15. ElRow,
  16. ElTooltip
  17. } from 'element-plus'
  18. import { ArrowDown } from '@element-plus/icons-vue'
  19. import { defineComponent } from 'vue'
  20. import CoursePreview from '../course-preview'
  21. import { createState } from '../createState'
  22. import styles from './index.module.less'
  23. import iconDown from '../images/icon_down.png'
  24. import iconUp from '../images/icon_up.png'
  25. import iconDelete from '../images/icon_delete.png'
  26. import ColVideo from '@/components/col-video'
  27. import SelectMusicAlbum from '../select-music-album'
  28. export default defineComponent({
  29. name: 'course-content',
  30. data() {
  31. return {
  32. show: false,
  33. form: {
  34. lessonList: [
  35. {
  36. key: 1,
  37. videoTitle: '',
  38. videoContent: '',
  39. videoUrl: '',
  40. relationList: [] as any,
  41. coverUrl: ''
  42. }
  43. ] as any
  44. },
  45. musicStatus: false,
  46. selectItem: {} as any // 选中的课程
  47. }
  48. },
  49. methods: {
  50. handleUpload(urls: any) {
  51. console.log(urls)
  52. // 上传视频连接s
  53. const urlList = urls || []
  54. urlList.forEach((item: any) => {
  55. createState.lessonList.push({
  56. videoTitle: '',
  57. videoContent: '',
  58. videoUrl: item,
  59. relationList: [] as any,
  60. coverUrl: ''
  61. })
  62. })
  63. },
  64. handleSubmit() {
  65. ;(this as any).$refs.form.validate(async (valid: any) => {
  66. if (valid) {
  67. if (createState.lessonList.length <= 0) {
  68. ElMessage.error('请上传课程视频')
  69. return
  70. }
  71. // 提交数据
  72. console.log('提交数据')
  73. this.show = true
  74. } else {
  75. this.$nextTick(() => {
  76. const isError = document.getElementsByClassName('is-error')
  77. isError[0].scrollIntoView({
  78. block: 'center',
  79. behavior: 'smooth'
  80. })
  81. })
  82. return false
  83. }
  84. })
  85. },
  86. async createSubmit() {
  87. try {
  88. const videoDetail = createState.lessonGroup
  89. const params = {
  90. lessonList: createState.lessonList,
  91. lessonGroup: {
  92. ...videoDetail,
  93. lessonCoverUrl:
  94. videoDetail.lessonCoverTemplateUrl || videoDetail.lessonCoverUrl
  95. }
  96. }
  97. if (createState.groupId) {
  98. await request.post('/api-website/videoLessonGroup/update', {
  99. data: params
  100. })
  101. ElMessage.success('修改成功')
  102. } else {
  103. await request.post('/api-website/videoLessonGroup/add', {
  104. data: params
  105. })
  106. ElMessage.success('创建成功')
  107. }
  108. sessionStorage.setItem('videoActiveName', 'DOING')
  109. this.$router.back()
  110. } catch {
  111. //
  112. }
  113. },
  114. swapItems(arr: any, index1: number, index2: number) {
  115. arr[index1] = arr.splice(index2, 1, arr[index1])[0]
  116. return arr
  117. },
  118. getName(item: any) {
  119. const relation =
  120. item.relationList.length > 0 ? item.relationList[0] : null
  121. return relation
  122. ? (relation.relationMusicAlbum === 'ALBUM' ? '专辑:' : '曲目:') +
  123. relation.musicAlbumName
  124. : ''
  125. }
  126. },
  127. render() {
  128. return (
  129. <div class={styles.courseContent}>
  130. <ElForm
  131. class="px-6 pb-10 pt-7 min-h-[280px]"
  132. size="large"
  133. labelWidth={'140px'}
  134. labelPosition="left"
  135. ref="form"
  136. model={createState}
  137. >
  138. <ElFormItem label="课程视频" required>
  139. <div>
  140. <ColUploadVideo
  141. multiple
  142. limit={3}
  143. bucket="video-course"
  144. multipleModel={(urls: any) => {
  145. this.handleUpload(urls)
  146. }}
  147. />
  148. </div>
  149. {/* <ElInput placeholder="请输入课程名称" /> */}
  150. </ElFormItem>
  151. {createState.lessonList.map((item: any, index: number) => (
  152. <div
  153. class="p-4 mb-10 border-b border-solid border-[#E7E6E6] relative"
  154. key={item.key}
  155. >
  156. <div class="absolute right-4 top-4 z-10 flex">
  157. {index !== 0 && (
  158. <ElTooltip
  159. class="box-item"
  160. effect="dark"
  161. content="上移"
  162. placement="top"
  163. >
  164. <div
  165. onClick={() => {
  166. this.swapItems(createState.lessonList, index, index - 1)
  167. }}
  168. >
  169. <ElIcon size={29}>
  170. <img src={iconUp} />
  171. </ElIcon>
  172. </div>
  173. </ElTooltip>
  174. )}
  175. {createState.lessonList.length - 1 !== index && (
  176. <ElTooltip
  177. class="box-item"
  178. effect="dark"
  179. content="下移"
  180. placement="top"
  181. >
  182. <div
  183. onClick={() => {
  184. this.swapItems(createState.lessonList, index, index + 1)
  185. }}
  186. >
  187. <ElIcon size={29} class="ml-3">
  188. <img src={iconDown} title="向下移动" />
  189. </ElIcon>
  190. </div>
  191. </ElTooltip>
  192. )}
  193. {createState.lessonList.length > 1 && (
  194. <ElTooltip
  195. class="box-item"
  196. effect="dark"
  197. content="删除"
  198. placement="top"
  199. >
  200. <div
  201. onClick={() => {
  202. ElMessageBox.confirm('确定删除该条数据吗?', '提示', {
  203. type: 'warning'
  204. }).then(() => {
  205. createState.lessonList.splice(index, 1)
  206. })
  207. }}
  208. >
  209. <ElIcon size={29} class="ml-3">
  210. <img src={iconDelete} />
  211. </ElIcon>
  212. </div>
  213. </ElTooltip>
  214. )}
  215. </div>
  216. <h2 class="text-xl font-semibold pb-5">{`第 ${index + 1} 课`}</h2>
  217. <ElFormItem
  218. label="课程标题"
  219. prop={`lessonList.${index}.videoTitle`}
  220. rules={[
  221. {
  222. required: true,
  223. message: '请输入课程标题'
  224. }
  225. ]}
  226. >
  227. <ElInput
  228. placeholder="请输入课程标题"
  229. maxlength={50}
  230. v-model={item.videoTitle}
  231. />
  232. </ElFormItem>
  233. <ElFormItem
  234. label="课程介绍"
  235. prop={`lessonList.${index}.videoContent`}
  236. rules={[
  237. {
  238. required: true,
  239. message: '请输入课程介绍'
  240. }
  241. ]}
  242. >
  243. <ElInput
  244. placeholder="请输入课程介绍"
  245. v-model={item.videoContent}
  246. type="textarea"
  247. // @ts-ignore
  248. maxlength={200}
  249. rows={4}
  250. showWordLimit
  251. />
  252. </ElFormItem>
  253. <ElRow>
  254. <ElCol span={12}>
  255. <ElFormItem label="课程视频" required>
  256. <ColVideo
  257. styleValue={{ with: '150px', height: '85px' }}
  258. controls={false}
  259. src={item.videoUrl}
  260. volume={false}
  261. />
  262. <p></p>
  263. </ElFormItem>
  264. </ElCol>
  265. <ElCol span={11}>
  266. <ElFormItem
  267. label="视频封面"
  268. prop={`lessonList.${index}.coverUrl`}
  269. rules={[{ required: true, message: '请上传视频封面' }]}
  270. >
  271. <ColUpload
  272. v-model:modelValue={item.coverUrl}
  273. bucket="video-course"
  274. />
  275. </ElFormItem>
  276. </ElCol>
  277. </ElRow>
  278. <ElFormItem
  279. label="关联曲目或专辑"
  280. prop={`lessonList.${index}.relationList`}
  281. onClick={() => {
  282. this.selectItem = item
  283. this.musicStatus = true
  284. }}
  285. >
  286. <div class={styles.relationList}></div>
  287. <ElInput
  288. placeholder="请选择关联曲目或专辑"
  289. // v-model={item.videoContent}
  290. modelValue={
  291. item.relationList.length > 0 ? this.getName(item) : ''
  292. }
  293. readonly
  294. suffixIcon={ArrowDown}
  295. />
  296. </ElFormItem>
  297. </div>
  298. ))}
  299. </ElForm>
  300. <div class="text-center pt-6 pb-7">
  301. <ElButton
  302. round
  303. class="!w-44 !h-[48px] !text-base"
  304. onClick={() => {
  305. createState.active = 0
  306. const currentY =
  307. document.documentElement.scrollTop || document.body.scrollTop
  308. scrollAnimation(currentY, 0)
  309. }}
  310. >
  311. 上一步
  312. </ElButton>
  313. <ElButton
  314. round
  315. type="primary"
  316. class="!w-44 !h-[48px] !text-base"
  317. onClick={this.handleSubmit}
  318. >
  319. 下一步
  320. </ElButton>
  321. </div>
  322. {/* @ts-ignore */}
  323. <ElDialog
  324. v-model={this.show}
  325. width={375}
  326. title="预览"
  327. v-slots={{
  328. footer: () => (
  329. <span class="dialog-footer !text-center block ">
  330. <ElButton
  331. size="large"
  332. round
  333. onClick={() => {
  334. this.show = false
  335. }}
  336. >
  337. 返回编辑
  338. </ElButton>
  339. <ElButton
  340. size="large"
  341. round
  342. type="primary"
  343. onClick={this.createSubmit}
  344. >
  345. {createState.groupId ? '确认修改' : '创建完成'}
  346. </ElButton>
  347. </span>
  348. )
  349. }}
  350. >
  351. <CoursePreview />
  352. </ElDialog>
  353. <ElDialog v-model={this.musicStatus} title="选择曲目或专辑" width={750}>
  354. <SelectMusicAlbum
  355. subjectIds={createState.lessonGroup.lessonSubject}
  356. onSelect={(item: any) => {
  357. this.musicStatus = false
  358. this.selectItem.relationList = [
  359. {
  360. musicAlbumId: item.id,
  361. musicAlbumName:
  362. item.selectType === 'ALBUM'
  363. ? item.albumName
  364. : item.musicSheetName,
  365. relationMusicAlbum: item.selectType,
  366. useRelationType: 'RECOMMEND'
  367. }
  368. ]
  369. }}
  370. />
  371. </ElDialog>
  372. </div>
  373. )
  374. }
  375. })