index.tsx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. import ColCropper from '@/components/col-cropper'
  2. import ColUpload from '@/components/col-upload'
  3. import request from '@/helpers/request'
  4. import { verifyNumberIntegerAndFloat } from '@/helpers/toolsValidate'
  5. import { getCodeBaseUrl } from '@/helpers/utils'
  6. import {
  7. ElButton,
  8. ElForm,
  9. ElFormItem,
  10. ElInput,
  11. ElOption,
  12. ElOptionGroup,
  13. ElRadioButton,
  14. ElRadioGroup,
  15. ElSelect,
  16. ElDialog,
  17. ElMessage
  18. } from 'element-plus'
  19. import { defineComponent } from 'vue'
  20. import styles from './index.module.less'
  21. export type BackgroundMp3 = {
  22. url?: string
  23. track?: string
  24. }
  25. export const validator = (rule, value, callback) => {
  26. console.log(value)
  27. if (value == '') {
  28. callback(new Error('请输入收费价格'))
  29. } else if (Number(value) <= 0) {
  30. callback(new Error('收费金额必须大于0'))
  31. } else {
  32. callback()
  33. }
  34. }
  35. export default defineComponent({
  36. name: 'music-operation',
  37. data() {
  38. const query = this.$route.query
  39. return {
  40. type: query.type || 'create',
  41. subjectList: [],
  42. tagList: [],
  43. submitLoading: false,
  44. reason: '',
  45. form: {
  46. titleImg: '',
  47. accompanimentType: 'HOMEMODE',
  48. audioType: 'MP3',
  49. xmlFileUrl: '',
  50. mp3Url: '',
  51. bgmp3Url: '',
  52. midiUrl: '',
  53. musicSheetName: '',
  54. composer: '',
  55. musicSubject: null as any,
  56. tags: [] as string[],
  57. hasBeat: 0,
  58. notation: 1,
  59. canEvaluate: 1,
  60. showFingering: 1,
  61. chargeType: 0,
  62. paymentType: '',
  63. exquisiteFlag: 0, // 是否精品
  64. musicPrice: '',
  65. backgroundMp3s: [
  66. {
  67. url: '',
  68. track: ''
  69. }
  70. ] as BackgroundMp3[]
  71. },
  72. radioList: [], // 选中的人数
  73. tagStatus: false,
  74. music_sheet_service_fee: 0
  75. }
  76. },
  77. async mounted() {
  78. document.title = this.type === 'create' ? '新建曲谱' : '编辑曲谱'
  79. try {
  80. await request
  81. .get('/api-website/sysConfig/queryByParamName', {
  82. params: {
  83. paramName: 'music_sheet_service_fee'
  84. }
  85. })
  86. .then(res => (this.music_sheet_service_fee = res.data.paramValue))
  87. await request.get('/api-website/open/subject/subjectSelect').then(res => {
  88. this.subjectList = res.data || []
  89. })
  90. await request.get('/api-website/open/MusicTag/tree').then(res => {
  91. this.tagList = res.data || []
  92. })
  93. if (this.$route.query.id) {
  94. this.setDetail(this.$route.query.id as string)
  95. }
  96. } catch {}
  97. },
  98. methods: {
  99. async setDetail(id: string) {
  100. try {
  101. const res = await request.get(
  102. '/api-website/open/music/sheet/detail/' + id
  103. )
  104. this.form.chargeType = res.data.chargeType === 'FREE' ? 0 : 2
  105. this.form.exquisiteFlag = res.data.exquisiteFlag
  106. this.form.showFingering = res.data.showFingering
  107. this.form.notation = res.data.notation
  108. this.form.canEvaluate = res.data.canEvaluate
  109. if (this.form.chargeType) {
  110. this.form.musicPrice = res.data.musicPrice
  111. }
  112. this.form.composer = res.data.composer
  113. this.form.musicSheetName = res.data.musicSheetName
  114. this.form.audioType = res.data.audioType
  115. this.form.musicSubject = Number(res.data.musicSubject)
  116. const musicTag = res.data.musicTag.split(',')
  117. const filterMusicTag = musicTag.filter((el: any) => {
  118. return el != ''
  119. })
  120. this.form.tags = filterMusicTag.map((item: any) => {
  121. return Number(item)
  122. })
  123. this.radioList = musicTag.map((item: any) => {
  124. return Number(item)
  125. })
  126. this.form.xmlFileUrl = res.data.xmlFileUrl
  127. this.form.accompanimentType = res.data.accompanimentType
  128. this.form.titleImg = res.data.titleImg
  129. // this.form.audioType = res.data.mp3Type
  130. if (this.form.audioType === 'MP3') {
  131. this.form.hasBeat = res.data.hasBeat || 0
  132. this.form.mp3Url = res.data.metronomeUrl || res.data.url
  133. } else {
  134. this.form.midiUrl = res.data.midiUrl
  135. }
  136. this.form.backgroundMp3s = (res.data.background || []).map(
  137. (item: any, index: any) => {
  138. if (index === 0) {
  139. this.form.bgmp3Url = item.metronomeUrl || item.audioFileUrl
  140. }
  141. return {
  142. url: this.form.hasBeat ? item.metronomeUrl : item.audioFileUrl,
  143. track: item.track
  144. }
  145. }
  146. )
  147. this.reason = res.data.reason
  148. // console.log(this.form.bgmp3Url)
  149. } catch (error) {
  150. console.log(error)
  151. }
  152. },
  153. createSubmitData() {
  154. const { form } = this
  155. const beatType = form.hasBeat ? 'MP3_METRONOME' : 'MP3'
  156. const mp3Type = form.audioType === 'MP3' ? beatType : 'MIDI'
  157. return {
  158. audioType: form.audioType,
  159. sourceType: 'TEACHER',
  160. mp3Type,
  161. accompanimentType: form.accompanimentType,
  162. titleImg: form.titleImg,
  163. hasBeat: Number(form.hasBeat),
  164. url: form.hasBeat ? '' : form.mp3Url,
  165. metronomeUrl: form.hasBeat ? form.mp3Url : '',
  166. showFingering: Number(form.showFingering),
  167. notation: Number(form.notation),
  168. musicTag: form.tags.join(','),
  169. musicSubject: form.musicSubject || undefined,
  170. musicSheetName: form.musicSheetName,
  171. midiUrl: form.midiUrl,
  172. xmlFileUrl: form.xmlFileUrl,
  173. canEvaluate: Number(form.canEvaluate),
  174. chargeType: form.chargeType === 0 ? 'FREE' : 'CHARGE',
  175. paymentType: form.paymentType
  176. ? form.paymentType
  177. : form.chargeType === 0
  178. ? 'FREE'
  179. : 'CHARGE',
  180. exquisiteFlag: form.exquisiteFlag,
  181. composer: form.composer,
  182. musicPrice: form.chargeType === 0 ? 0 : form.musicPrice,
  183. background: form.backgroundMp3s.map(item => ({
  184. audioFileUrl: form.hasBeat ? '' : form.bgmp3Url,
  185. track: item.track,
  186. metronomeUrl: form.hasBeat ? form.bgmp3Url : ''
  187. }))
  188. }
  189. },
  190. onFormatter(e: any) {
  191. e.target.value = verifyNumberIntegerAndFloat(e.target.value)
  192. },
  193. onSubmit() {
  194. ;(this as any).$refs.form.validate(async (valid: any) => {
  195. if (valid) {
  196. this.submitLoading = true
  197. console.log(this.createSubmitData(), 'createSubmitData')
  198. try {
  199. if (this.$route.query.id) {
  200. await request.post('/api-website/music/sheet/update', {
  201. data: {
  202. ...this.createSubmitData(),
  203. id: this.$route.query.id
  204. }
  205. })
  206. } else {
  207. await request.post('/api-website/music/sheet/create', {
  208. data: this.createSubmitData()
  209. })
  210. }
  211. this.submitLoading = false
  212. ElMessage.success('上传成功')
  213. sessionStorage.setItem('musicActiveName', 'DOING')
  214. this.$router.back()
  215. } catch (error) {
  216. this.submitLoading = false
  217. }
  218. } else {
  219. this.$nextTick(() => {
  220. const isError = document.getElementsByClassName('is-error')
  221. isError[0].scrollIntoView({
  222. block: 'center',
  223. behavior: 'smooth'
  224. })
  225. })
  226. return false
  227. }
  228. })
  229. },
  230. onDetail(type: string) {
  231. let url = `${getCodeBaseUrl('/teacher')}/#/registerProtocol`
  232. if (type === 'question') {
  233. url = `${getCodeBaseUrl('/teacher')}/muic-standard/question.html`
  234. } else if (type === 'music') {
  235. url = `${getCodeBaseUrl('/teacher')}/muic-standard/index.html`
  236. }
  237. window.open(url)
  238. }
  239. },
  240. render() {
  241. return (
  242. <div class={styles.form}>
  243. <div class="text-2xl font-semibold text-black leading-none px-6 py-5 ">
  244. {this.type === 'create' ? '新建曲谱' : '编辑曲谱'}
  245. </div>
  246. <ElForm
  247. size="large"
  248. labelPosition="left"
  249. labelWidth={'150px'}
  250. model={this.form}
  251. ref="form"
  252. class="px-7 py-5"
  253. >
  254. <div class={styles.tips}>
  255. <div class={styles.tipsTitle}>注意事项:</div>
  256. <div class={styles.tipsContent}>
  257. 1、必须是上传人自己参与制作的作品。
  258. <br />
  259. 2、歌曲及歌曲信息中请勿涉及政治、宗教、广告、涉毒、犯罪、色情、低俗、暴力、血腥、消极等违规内容,违反者直接删除内容。多次违反将封号。
  260. <br />
  261. 3、点击查看{' '}
  262. <span onClick={() => this.onDetail('protocol')}>
  263. 《用户注册协议》
  264. </span>
  265. ,如果您上传了文件,即认为您完全同意并遵守该协议的内容;
  266. </div>
  267. </div>
  268. <ElFormItem
  269. label="上传XML"
  270. prop="xmlFileUrl"
  271. rules={[{ required: true, message: '请选择MusicXML文件' }]}
  272. >
  273. <ColUpload
  274. v-model:modelValue={this.form.xmlFileUrl}
  275. bucket={'cloud-coach'}
  276. accept={'application/xml'}
  277. uploadType={'file'}
  278. extraTips="文件最大不能超过5MB"
  279. />
  280. </ElFormItem>
  281. <div class={styles.tips}>
  282. <div class={styles.tipsTitle}>曲谱审核标准:</div>
  283. <div class={styles.tipsContent}>
  284. 1、文件大小不要超过5MB,不符合版面规范的乐谱,审核未通过的不予上架,详情参考
  285. <span onClick={() => this.onDetail('music')}>
  286. 《曲谱排版规范》
  287. </span>
  288. ; 1、必须是上传人自己参与制作的作品。
  289. <br />
  290. 2、XML与MIDI文件内容必须一致,推荐使用Sibelius打谱软件。导出设置:导出XML-未压缩(*.xml)/导出MIDI:音色-其他回放设备General
  291. MIDI、MIDI、MIDI文件类型-类型0、不要勾选“将弱拍小节导出为具有休止符的完整小节”。点击查看
  292. <span onClick={() => this.onDetail('question')}>
  293. 《常见问题》
  294. </span>
  295. </div>
  296. </div>
  297. <ElFormItem
  298. label="播放类型"
  299. prop="audioType"
  300. rules={[{ required: true, message: '请选择播放类型' }]}
  301. >
  302. <ElRadioGroup v-model={this.form.audioType}>
  303. <ElRadioButton label={'MIDI'} class="mr-3 w-24">
  304. MIDI
  305. </ElRadioButton>
  306. <ElRadioButton label={'MP3'} class="w-24">
  307. MP3
  308. </ElRadioButton>
  309. </ElRadioGroup>
  310. </ElFormItem>
  311. {this.form.audioType === 'MP3' ? (
  312. <>
  313. {/* <ElFormItem
  314. label="是否带节拍器"
  315. prop="hasBeat"
  316. rules={[{ required: true, message: '请选择是否带节拍器' }]}
  317. >
  318. <ElRadioGroup v-model={this.form.hasBeat}>
  319. <ElRadioButton label={0} class="mr-3 w-24">
  320. </ElRadioButton>
  321. <ElRadioButton label={1} class="w-24">
  322. </ElRadioButton>
  323. </ElRadioGroup>
  324. </ElFormItem> */}
  325. <ElFormItem
  326. label="伴奏类型"
  327. prop="accompanimentType"
  328. rules={[{ required: true, message: '请选择伴奏类型' }]}
  329. >
  330. <ElRadioGroup v-model={this.form.accompanimentType}>
  331. <ElRadioButton label={'HOMEMODE'} class="mr-3 w-24">
  332. 自制伴奏
  333. </ElRadioButton>
  334. <ElRadioButton label={'COMMON'} class="w-24">
  335. 普通伴奏
  336. </ElRadioButton>
  337. </ElRadioGroup>
  338. </ElFormItem>
  339. <ElFormItem label="伴奏文件" prop="mp3Url">
  340. <ColUpload
  341. v-model:modelValue={this.form.mp3Url}
  342. bucket={'cloud-coach'}
  343. accept={'.mp3'}
  344. uploadType={'file'}
  345. size={8}
  346. extraTips="文件最大不能超过8MB"
  347. />
  348. </ElFormItem>
  349. </>
  350. ) : (
  351. <>
  352. <ElFormItem
  353. label="伴奏类型"
  354. prop="accompanimentType"
  355. rules={[{ required: true, message: '请选择伴奏类型' }]}
  356. >
  357. <ElRadioGroup v-model={this.form.accompanimentType}>
  358. <ElRadioButton label={'HOMEMODE'} class="mr-3 w-24">
  359. 自制伴奏
  360. </ElRadioButton>
  361. <ElRadioButton label={'COMMON'} class="w-24">
  362. 普通伴奏
  363. </ElRadioButton>
  364. </ElRadioGroup>
  365. </ElFormItem>
  366. <ElFormItem
  367. label="MIDI文件"
  368. prop="midiUrl"
  369. rules={[{ required: true, message: '请选择MIDI文件' }]}
  370. >
  371. <ColUpload
  372. v-model:modelValue={this.form.midiUrl}
  373. bucket={'cloud-coach'}
  374. accept={'.midi,.mid'}
  375. uploadType={'file'}
  376. size={8}
  377. extraTips="文件最大不能超过8MB"
  378. />
  379. </ElFormItem>
  380. </>
  381. )}
  382. <div class={styles.tips}>
  383. <div class={styles.tipsContent}>
  384. 1、推荐上传自制伴奏,伴奏和谱面必须对齐。自制伴奏可以设置更高的收费标准。
  385. <br />
  386. 2、普通伴奏如果涉及到版权纠纷,根据
  387. <span onClick={() => this.onDetail('protocol')}>
  388. 《用户注册协议》
  389. </span>
  390. 平台有权进行下架处理。
  391. </div>
  392. </div>
  393. {this.form.audioType === 'MP3' && (
  394. <ElFormItem
  395. label="原音文件"
  396. prop="bgmp3Url"
  397. rules={[{ required: true, message: '请选择原音文件' }]}
  398. >
  399. <ColUpload
  400. v-model:modelValue={this.form.bgmp3Url}
  401. bucket={'cloud-coach'}
  402. accept={'.mp3'}
  403. uploadType={'file'}
  404. extraTips="文件最大不能超过8MB"
  405. />
  406. </ElFormItem>
  407. )}
  408. <ElFormItem
  409. label="曲目名称"
  410. prop="musicSheetName"
  411. rules={[{ required: true, message: '请输入曲目名称' }]}
  412. >
  413. <ElInput
  414. v-model={this.form.musicSheetName}
  415. placeholder="请选择曲目名称"
  416. />
  417. </ElFormItem>
  418. <div class={styles.tips}>
  419. <div class={styles.tipsContent}>
  420. 1、同一首曲目不可重复上传,如有不同版本统一用“()”补充。举例:人生的旋转木马(长笛二重奏版)。
  421. <br />
  422. 2、曲目名后可添加曲目信息备注,包含但不限于曲目类型等。曲目名《xxxx》,举例:人生的旋转木马《哈尔的移动城堡》(长笛二重奏版)
  423. <br />
  424. 3、其他信息不要写在曲目名里,如歌手、上传人员昵称等。
  425. </div>
  426. </div>
  427. <ElFormItem
  428. label="曲谱封面"
  429. prop="titleImg"
  430. rules={[
  431. {
  432. required: true,
  433. message: '请上传曲谱封面'
  434. }
  435. ]}
  436. >
  437. <ColCropper
  438. modelValue={this.form.titleImg}
  439. bucket={'cloud-coach'}
  440. cropUploadSuccess={(data: any) => {
  441. this.form.titleImg = data
  442. }}
  443. domSize={{ height: '150px' }}
  444. options={{
  445. title: '曲谱封面',
  446. enlarge: 2,
  447. autoCropWidth: 300,
  448. autoCropHeight: 300
  449. }}
  450. />
  451. </ElFormItem>
  452. <ElFormItem
  453. label="艺术家"
  454. prop="composer"
  455. rules={[{ required: true, message: '请输入艺术家' }]}
  456. >
  457. <ElInput v-model={this.form.composer} placeholder="请输入艺术家" />
  458. </ElFormItem>
  459. <ElFormItem
  460. label="曲目声部"
  461. prop="musicSubject"
  462. rules={[
  463. { required: true, message: '请选择曲目声部', trigger: 'change' }
  464. ]}
  465. >
  466. <ElSelect
  467. filterable
  468. v-model={this.form.musicSubject}
  469. placeholder="请选择曲目声部"
  470. class="w-full"
  471. >
  472. {this.subjectList.map((group: any) => (
  473. <ElOptionGroup key={group.id} label={group.name}>
  474. {group.subjects &&
  475. group.subjects.map((item: any) => (
  476. <ElOption
  477. key={item.id}
  478. value={item.id}
  479. label={item.name}
  480. />
  481. ))}
  482. </ElOptionGroup>
  483. ))}
  484. </ElSelect>
  485. </ElFormItem>
  486. <div class={styles.tips}>
  487. <div class={styles.tipsContent}>
  488. XML文件中,选择的曲目声部需要在总谱的置顶位置。
  489. </div>
  490. </div>
  491. <ElFormItem
  492. label="曲目标签"
  493. prop="tags"
  494. rules={[{ required: true, message: '请选择曲目标签' }]}
  495. >
  496. <div class="w-full relative">
  497. <div
  498. class=" w-full block h-[42px] absolute top-0 left-0 z-10"
  499. onClick={() => {
  500. console.log(111)
  501. this.tagStatus = true
  502. }}
  503. ></div>
  504. <ElSelect
  505. multiple
  506. v-model={this.form.tags}
  507. placeholder="请选择曲目标签"
  508. class="w-full"
  509. >
  510. {this.tagList.map((group: any) => (
  511. <ElOptionGroup key={group.id} label={group.name}>
  512. {group.children &&
  513. group.children.map((item: any) => (
  514. <ElOption
  515. key={item.id}
  516. value={item.id}
  517. label={item.name}
  518. />
  519. ))}
  520. </ElOptionGroup>
  521. ))}
  522. </ElSelect>
  523. </div>
  524. </ElFormItem>
  525. {/* <ElFormItem
  526. label="支持简谱"
  527. prop="notation"
  528. rules={[{ required: true, message: '请选择是否支持简谱' }]}
  529. >
  530. <ElRadioGroup v-model={this.form.notation}>
  531. <ElRadioButton label={0} class="mr-3 w-24">
  532. </ElRadioButton>
  533. <ElRadioButton label={1} class="w-24">
  534. </ElRadioButton>
  535. </ElRadioGroup>
  536. </ElFormItem> */}
  537. {/* <ElFormItem
  538. label="是否评测"
  539. prop="canEvaluate"
  540. rules={[{ required: true, message: '请选择是否评测' }]}
  541. >
  542. <ElRadioGroup v-model={this.form.canEvaluate}>
  543. <ElRadioButton label={0} class="mr-3 w-24">
  544. </ElRadioButton>
  545. <ElRadioButton label={1} class="w-24">
  546. </ElRadioButton>
  547. </ElRadioGroup>
  548. </ElFormItem> */}
  549. {/* <ElFormItem
  550. label="指法展示"
  551. prop="showFingering"
  552. rules={[{ required: true, message: '请选择指法展示' }]}
  553. >
  554. <ElRadioGroup v-model={this.form.showFingering}>
  555. <ElRadioButton label={0} class="mr-3 w-24">
  556. </ElRadioButton>
  557. <ElRadioButton label={1} class="w-24">
  558. </ElRadioButton>
  559. </ElRadioGroup>
  560. </ElFormItem> */}
  561. <ElFormItem
  562. label="是否收费"
  563. prop="chargeType"
  564. rules={[{ required: true, message: '请选择是否收费' }]}
  565. >
  566. <ElRadioGroup v-model={this.form.chargeType}>
  567. <ElRadioButton label={0} class="mr-3 w-24">
  568. </ElRadioButton>
  569. <ElRadioButton label={2} class="w-24">
  570. </ElRadioButton>
  571. </ElRadioGroup>
  572. </ElFormItem>
  573. {this.form.chargeType === 2 && (
  574. <>
  575. <ElFormItem
  576. label="收费价格"
  577. prop="musicPrice"
  578. rules={[{ required: true, validator }]}
  579. >
  580. <ElInput
  581. v-model={this.form.musicPrice}
  582. placeholder="请输入收费价格"
  583. // @ts-ignore
  584. maxlength={5}
  585. onKeyup={this.onFormatter}
  586. v-slots={{
  587. suffix: () => <span class="text-base text-[#999]">元</span>
  588. }}
  589. />
  590. </ElFormItem>
  591. <ElFormItem>
  592. <div class={styles.rule}>
  593. <p>扣除手续费后该曲目预计收入为:</p>
  594. <p>
  595. 每人:
  596. <span>
  597. {((parseFloat(this.form.musicPrice || '0') || 0) *
  598. (100 - this.music_sheet_service_fee)) /
  599. 100}
  600. </span>
  601. 元/人
  602. </p>
  603. <p>您的乐谱收入将在学员购买后结算到您的账户中</p>
  604. </div>
  605. </ElFormItem>
  606. </>
  607. )}
  608. <ElFormItem
  609. label="是否精品乐谱"
  610. prop="exquisiteFlag"
  611. rules={[{ required: true, message: '请选择是否精品乐谱' }]}
  612. >
  613. <ElRadioGroup v-model={this.form.exquisiteFlag}>
  614. <ElRadioButton label={0} class="mr-3 w-24">
  615. </ElRadioButton>
  616. <ElRadioButton label={1} class="w-24">
  617. </ElRadioButton>
  618. </ElRadioGroup>
  619. </ElFormItem>
  620. </ElForm>
  621. <div class="text-center pt-6 pb-7">
  622. <ElButton
  623. class="!w-44 !h-[48px]"
  624. round
  625. onClick={() => {
  626. this.$router.back()
  627. }}
  628. >
  629. 取消
  630. </ElButton>
  631. <ElButton
  632. type="primary"
  633. class="!w-44 !h-[48px]"
  634. round
  635. onClick={this.onSubmit}
  636. loading={this.submitLoading}
  637. >
  638. 提交审核
  639. </ElButton>
  640. </div>
  641. <ElDialog
  642. modelValue={this.tagStatus}
  643. onUpdate:modelValue={val => (this.tagStatus = val)}
  644. width="35%"
  645. title="全部标签"
  646. >
  647. {this.tagList.map((item: any, index: number) => (
  648. <div class={[styles.tags, 'py-2']}>
  649. <div class="text-sm pb-2">{item.name}</div>
  650. {item.children.map((child: any) => (
  651. <ElRadioGroup v-model={this.radioList[index]} class="pb-2">
  652. <ElRadioButton label={child.id} class="mr-3">
  653. {child.name}
  654. </ElRadioButton>
  655. </ElRadioGroup>
  656. ))}
  657. </div>
  658. ))}
  659. <div class="text-center pt-2">
  660. <ElButton
  661. class="!w-36 !h-[48px]"
  662. round
  663. size="large"
  664. onClick={() => {
  665. this.radioList = []
  666. }}
  667. >
  668. 重置
  669. </ElButton>
  670. <ElButton
  671. class="!w-36 !h-[48px]"
  672. round
  673. size="large"
  674. type="primary"
  675. onClick={() => {
  676. this.form.tags = this.radioList.filter((el: any) => {
  677. return el != ''
  678. })
  679. this.tagStatus = false
  680. ;(this as any).$refs.form.clearValidate('tags')
  681. }}
  682. >
  683. 确认
  684. </ElButton>
  685. </div>
  686. </ElDialog>
  687. </div>
  688. )
  689. }
  690. })