index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. import ColCropper from '@/components/col-cropper'
  2. import styles from './index.module.less'
  3. import request from '@/helpers/request'
  4. import {
  5. verifiyNumberInteger,
  6. verifyNumberIntegerAndFloat
  7. } from '@/helpers/toolsValidate'
  8. import {
  9. ElButton,
  10. ElCol,
  11. ElForm,
  12. ElFormItem,
  13. ElImage,
  14. ElInput,
  15. ElOption,
  16. ElRadio,
  17. ElRadioGroup,
  18. ElRow,
  19. ElSelect,
  20. ElTabPane,
  21. ElTabs
  22. } from 'element-plus'
  23. import { defineComponent } from 'vue'
  24. import { createState } from '../createState'
  25. import { scrollAnimation } from '@/util/scroll'
  26. export default defineComponent({
  27. name: 'course-info',
  28. data() {
  29. return {
  30. url: '',
  31. calcRatePrice: 0 as any,
  32. calcSingleRatePrice: 0 as any
  33. }
  34. },
  35. computed: {
  36. subjectList() {
  37. // 学科列表
  38. return createState.subjectList || []
  39. }
  40. },
  41. async mounted() {
  42. try {
  43. // 获取手续费和分钟数
  44. let config = await request.get(
  45. '/api-website/sysConfig/queryByParamNameList',
  46. {
  47. params: {
  48. paramNames: 'live_service_rate,live_time_setting'
  49. }
  50. }
  51. )
  52. let configData = config.data || []
  53. configData.forEach((item: any) => {
  54. if (item.paramName === 'live_time_setting') {
  55. let mins = item.paramValue ? JSON.parse(item.paramValue) : []
  56. let tempArr = [] as any
  57. mins.forEach((item: any) => {
  58. tempArr.push({
  59. ...item,
  60. name: item.courseMinutes
  61. })
  62. })
  63. createState.minutes = [...tempArr]
  64. }
  65. if (item.paramName === 'live_service_rate') {
  66. createState.rate = item.paramValue
  67. }
  68. })
  69. let teacher = await request.post('/api-website/teacher/querySubject')
  70. createState.subjectList = teacher.data || []
  71. } catch (err: any) {
  72. console.log(err)
  73. }
  74. },
  75. methods: {
  76. // onChoice(id: number) {
  77. // createState.live.subjectId = id
  78. // this.subjectStatus = false
  79. // },
  80. onFormaterCourse(e: any) {
  81. e.target.value = verifiyNumberInteger(e.target.value)
  82. let rate = createState.rate || 0
  83. let nums = createState.live.courseNum
  84. let tempPrice = createState.live.coursePrice || 0
  85. this.calcSingleRatePrice = nums
  86. ? ((tempPrice / nums) * (1 - rate / 100)).toFixed(2)
  87. : 0
  88. },
  89. onFormatter(e: any) {
  90. e.target.value = verifyNumberIntegerAndFloat(e.target.value)
  91. // 计算手续费
  92. let rate = createState.rate || 0
  93. let price = e.target.value || 0
  94. this.calcRatePrice = (price - (rate / 100) * price).toFixed(2)
  95. let nums = createState.live.courseNum
  96. // let tempPrice = createState.live.coursePrice || 0
  97. this.calcSingleRatePrice = nums
  98. ? ((price / nums) * (1 - rate / 100)).toFixed(2)
  99. : 0
  100. },
  101. tabChange(name: number) {
  102. ;(this as any).$refs.form.clearValidate('lessonCoverTemplateUrl')
  103. ;(this as any).$refs.form.clearValidate('lessonCoverUrl')
  104. createState.tabIndex = name
  105. },
  106. selectImg(val: string) {
  107. // createState.live.lessonCoverUrl = ''
  108. // createState.live.lessonCoverTemplateUrl = val
  109. }
  110. },
  111. render() {
  112. return (
  113. <>
  114. <ElForm
  115. class="px-[200px] pb-10 pt-7"
  116. size="large"
  117. ref="form"
  118. labelWidth={'100px'}
  119. labelPosition="left"
  120. model={createState.live}
  121. >
  122. <ElFormItem
  123. label="课程名称"
  124. prop="name"
  125. rules={[
  126. {
  127. required: true,
  128. message: '请输入课程名称'
  129. }
  130. ]}
  131. >
  132. <ElInput
  133. v-model={createState.live.name}
  134. placeholder="请输入课程名称"
  135. />
  136. </ElFormItem>
  137. <ElFormItem
  138. label="课程声部"
  139. prop="subjectId"
  140. rules={[
  141. {
  142. required: true,
  143. message: '请选择课程声部'
  144. }
  145. ]}
  146. >
  147. <ElSelect
  148. class="w-full"
  149. v-model={createState.live.subjectId}
  150. placeholder="请选择课程声部"
  151. >
  152. {createState.subjectList.map((item: any) => (
  153. <ElOption key={item.id} value={item.id} label={item.name} />
  154. ))}
  155. </ElSelect>
  156. </ElFormItem>
  157. <ElFormItem
  158. label="课程介绍"
  159. prop="courseIntroduce"
  160. rules={[
  161. {
  162. required: true,
  163. message: '请输入课程介绍'
  164. }
  165. ]}
  166. >
  167. <ElInput
  168. placeholder="请输入课程介绍"
  169. v-model={createState.live.courseIntroduce}
  170. type="textarea"
  171. // @ts-ignore
  172. maxlength={200}
  173. rows={4}
  174. showWordLimit
  175. />
  176. </ElFormItem>
  177. <ElFormItem
  178. label="课时数"
  179. prop="courseNum"
  180. rules={[
  181. {
  182. required: true,
  183. message: '请输入课时数'
  184. }
  185. ]}
  186. >
  187. <ElInput
  188. placeholder="请输入课时数"
  189. v-model={createState.live.courseNum}
  190. // @ts-ignore
  191. onKeyup={this.onFormaterCourse}
  192. maxlength={3}
  193. v-slots={{
  194. append: () => <span class="text-base text-[#333]">课时</span>
  195. }}
  196. />
  197. </ElFormItem>
  198. <ElFormItem
  199. label="单课时长"
  200. prop="singleMins"
  201. rules={[
  202. {
  203. required: true,
  204. message: '请选择单课时长'
  205. }
  206. ]}
  207. >
  208. <ElSelect
  209. class="w-full"
  210. v-model={createState.live.singleMins}
  211. placeholder="请选择单课时长"
  212. >
  213. {createState.minutes.map((item: any) => (
  214. <ElOption
  215. key={item.courseMinutes}
  216. value={item.courseMinutes}
  217. label={item.name}
  218. />
  219. ))}
  220. </ElSelect>
  221. </ElFormItem>
  222. <ElFormItem
  223. label="课程组售价"
  224. prop="coursePrice"
  225. rules={[
  226. {
  227. required: true,
  228. message: '请输入课程组售价'
  229. }
  230. ]}
  231. >
  232. <ElInput
  233. placeholder="请输入课程组售价"
  234. v-model={createState.live.coursePrice}
  235. // @ts-ignore
  236. onKeyup={this.onFormatter}
  237. maxlength={9}
  238. v-slots={{
  239. append: () => <span class="text-base text-[#333]">元</span>
  240. }}
  241. />
  242. </ElFormItem>
  243. <div class="text-sm text-[#999] pl-[100px] leading-relaxed pb-2">
  244. <p>扣除手续费后您的课程预计收入为:</p>
  245. <p>
  246. 单课时
  247. <span class="px-1 text-[#FF4E19]">
  248. {this.calcSingleRatePrice}
  249. </span>
  250. 元/人
  251. </p>
  252. <p>
  253. 课程组总收入
  254. <span class="px-1 text-[#FF4E19]">{this.calcRatePrice}</span>元/人
  255. </p>
  256. <p>您的课程收入将在课程结束后结算到您的账户中</p>
  257. </div>
  258. {/* <ElFormItem label="课程封面" class="!mb-0">
  259. <ElTabs
  260. v-model={createState.tabIndex}
  261. class={styles.tabs}
  262. onTab-change={(name: any) => {
  263. this.tabChange(name)
  264. }}
  265. >
  266. <ElTabPane label="图片模板" name={1}></ElTabPane>
  267. <ElTabPane label="自定义模板" name={2}></ElTabPane>
  268. </ElTabs>
  269. </ElFormItem>
  270. {createState.tabIndex === 1 && (
  271. <ElFormItem
  272. prop="lessonCoverTemplateUrl"
  273. rules={[
  274. {
  275. required: true,
  276. message: '请上传课程封面'
  277. }
  278. ]}
  279. >
  280. <ElRadioGroup v-model={createState.live.lessonCoverTemplateUrl}>
  281. <ElRow>
  282. {createState.templateList.map((item: any) => (
  283. <ElCol span={10} class="mb-3 cursor-pointer">
  284. <div
  285. class="w-40 relative rounded-xl overflow-hidden border"
  286. onClick={() => {
  287. this.selectImg(item)
  288. }}
  289. >
  290. <ElImage src={item} class="align-middle" />
  291. <ElRadio
  292. label={item}
  293. class="!absolute bottom-2 right-0 !h-auto z-10"
  294. >
  295. {''}
  296. </ElRadio>
  297. </div>
  298. </ElCol>
  299. ))}
  300. </ElRow>
  301. </ElRadioGroup>
  302. </ElFormItem>
  303. )}
  304. {createState.tabIndex === 2 && (
  305. <ElFormItem
  306. prop="lessonCoverUrl"
  307. rules={[
  308. {
  309. required: true,
  310. message: '请上传课程封面',
  311. trigger: 'change'
  312. }
  313. ]}
  314. >
  315. <ColCropper
  316. modelValue={createState.live.lessonCoverUrl}
  317. bucket="video-course"
  318. cropUploadSuccess={(data: any) => {
  319. createState.live.lessonCoverUrl = data
  320. createState.live.lessonCoverTemplateUrl = ''
  321. }}
  322. options={{
  323. fixedNumber: [3, 2],
  324. autoCropWidth: 300,
  325. autoCropHeight: 200
  326. }}
  327. />
  328. </ElFormItem>
  329. )} */}
  330. </ElForm>
  331. <div class="border-t border-t-[#E5E5E5] text-center pt-6 pb-7">
  332. <ElButton
  333. type="primary"
  334. class="!w-40 !h-[38px]"
  335. onClick={() => {
  336. ;(this as any).$refs.form.validate(async (valid: boolean) => {
  337. if (valid) {
  338. createState.active = 1
  339. const currentY =
  340. document.documentElement.scrollTop ||
  341. document.body.scrollTop
  342. scrollAnimation(currentY, 0)
  343. } else {
  344. this.$nextTick(() => {
  345. let isError = document.getElementsByClassName('is-error')
  346. isError[0].scrollIntoView({
  347. block: 'center',
  348. behavior: 'smooth'
  349. })
  350. })
  351. return false
  352. }
  353. })
  354. }}
  355. >
  356. 下一步
  357. </ElButton>
  358. </div>
  359. </>
  360. )
  361. }
  362. })