index.tsx 9.8 KB

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