index.tsx 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import {
  2. computed,
  3. defineComponent,
  4. nextTick,
  5. onMounted,
  6. reactive,
  7. ref
  8. } from 'vue';
  9. import styles from './index.module.less';
  10. import {
  11. NButton,
  12. NForm,
  13. NFormItem,
  14. NImage,
  15. NInput,
  16. NScrollbar,
  17. NSelect,
  18. NSpace,
  19. NSwitch,
  20. useMessage
  21. } from 'naive-ui';
  22. import UploadFile from './upload-file';
  23. import { useCatchStore } from '/src/store/modules/catchData';
  24. import iconImage from '@common/images/icon-image.png';
  25. import iconVideo from '@common/images/icon-video.png';
  26. import iconAudio from '@common/images/icon-audio.png';
  27. import iconMusic from '@common/images/icon-music.png';
  28. import iconUploadDelete from '../../../images/icon-upload-delete.svg';
  29. import { materialSave, materialUpdateAll } from '../../../api';
  30. import { NaturalTypeEnum } from '@/enums/pageEnum';
  31. import { scrollToErrorForm } from '/src/utils';
  32. // 判断链接后辍
  33. export const formatUrlType = (url: string) => {
  34. if (url.indexOf('.mp3') > -1) {
  35. return NaturalTypeEnum.SONG;
  36. } else if (url.indexOf('.mp4') > -1) {
  37. return NaturalTypeEnum.VIDEO;
  38. } else {
  39. return NaturalTypeEnum.IMG;
  40. }
  41. };
  42. export default defineComponent({
  43. name: 'upload-modal',
  44. props: {
  45. list: {
  46. type: Array,
  47. default: () => []
  48. }
  49. },
  50. emits: ['close', 'confirm'],
  51. setup(props, { emit }) {
  52. const catchStore = useCatchStore();
  53. const formRef = ref();
  54. const message = useMessage();
  55. const uploadRef = ref();
  56. const uploadForms = reactive({
  57. list: [] as any[],
  58. uploading: false,
  59. uploadUrl: '',
  60. name: '',
  61. subjectIds: [] as any
  62. });
  63. // 判断类型
  64. const formatType = (type: string) => {
  65. let typeImg = iconImage;
  66. switch (type) {
  67. case 'IMG':
  68. typeImg = iconImage;
  69. break;
  70. case 'VIDEO':
  71. typeImg = iconVideo;
  72. break;
  73. case 'SONG':
  74. typeImg = iconAudio;
  75. break;
  76. case 'MUSIC':
  77. typeImg = iconMusic;
  78. break;
  79. }
  80. return typeImg;
  81. };
  82. const onSubmit = async () => {
  83. //
  84. formRef.value?.validate(async (err: any) => {
  85. if (err) {
  86. nextTick(scrollToErrorForm);
  87. return;
  88. }
  89. uploadForms.uploading = true;
  90. try {
  91. const body: any[] = [];
  92. uploadForms.list.forEach(item => {
  93. body.push({
  94. subjectIds: item.subjectIds.join(','),
  95. openFlag: item.openFlag,
  96. coverImg: item.coverImg,
  97. name: item.name,
  98. type: item.type,
  99. enableFlag: 1,
  100. content: item.content,
  101. id: item.id || null
  102. });
  103. });
  104. if (isUpdate.value) {
  105. await materialUpdateAll(body);
  106. } else {
  107. await materialSave(body);
  108. }
  109. uploadForms.list = [];
  110. message.success('保存成功');
  111. emit('close', true);
  112. emit('confirm');
  113. } catch {
  114. //
  115. }
  116. uploadForms.uploading = false;
  117. });
  118. };
  119. const handleRemove = (index: number) => {
  120. uploadForms.list.splice(index, 1);
  121. };
  122. const isUpdate = computed(() => (props.list.length > 0 ? true : false));
  123. onMounted(async () => {
  124. const list = props.list || [];
  125. const temps: any[] = [];
  126. list.forEach((item: any) => {
  127. temps.push({
  128. subjectIds: item.subjectId
  129. ? item.subjectId
  130. .split(',')
  131. .map((subjectId: any) => Number(subjectId))
  132. : [],
  133. openFlag: item.openFlag,
  134. coverImg: item.coverImg,
  135. name: item.title,
  136. type: item.type,
  137. enableFlag: item.enableFlag,
  138. content: item.content,
  139. id: item.id
  140. });
  141. });
  142. uploadForms.list = temps || [];
  143. await catchStore.getSubjects();
  144. });
  145. return () => (
  146. <div class={styles.uploadModal}>
  147. <NScrollbar style={{ 'max-height': '55vh' }}>
  148. <NForm
  149. ref={formRef}
  150. labelPlacement="left"
  151. labelWidth={120}
  152. model={uploadForms}
  153. class={styles.formModal}>
  154. <NSpace class={styles.formSpace}>
  155. {uploadForms.list.map((item: any, index: number) => (
  156. <div class={styles.formItem} key={index}>
  157. <div class={styles.previewModal}>
  158. <NImage
  159. class={[styles.titleType]}
  160. src={formatType(item.type)}
  161. previewDisabled
  162. objectFit="cover"
  163. />
  164. {/* 编辑时不能删除 */}
  165. {!isUpdate.value && (
  166. <img
  167. class={[styles.iconUploadDelete]}
  168. src={iconUploadDelete}
  169. onClick={() => handleRemove(index)}
  170. />
  171. )}
  172. <NImage
  173. class={[styles.cover, styles.image]}
  174. lazy
  175. previewDisabled
  176. src={item.coverImg}
  177. objectFit="cover"
  178. />
  179. <div class={styles.commonType}>
  180. 公开资源:
  181. <NSwitch size="small" v-model:value={item.openFlag} />
  182. </div>
  183. </div>
  184. <NFormItem
  185. showFeedback={false}
  186. path={`list.${index}.name`}
  187. rule={[
  188. {
  189. required: true,
  190. message: '请输入资源名称',
  191. trigger: ['input', 'blur']
  192. }
  193. ]}>
  194. <NInput
  195. v-model:value={item.name}
  196. placeholder="请输入资源名称"
  197. maxlength={25}
  198. clearable
  199. />
  200. </NFormItem>
  201. <NFormItem
  202. path={`list[${index}].subjectIds`}
  203. showFeedback={false}
  204. rule={[
  205. {
  206. required: true,
  207. message: '请选择素材可用乐器',
  208. trigger: 'change',
  209. type: 'array'
  210. }
  211. ]}>
  212. <NSelect
  213. v-model:value={item.subjectIds}
  214. placeholder="请选择素材可用乐器(可多选)"
  215. options={catchStore.getSubjectList}
  216. labelField="name"
  217. valueField="id"
  218. multiple
  219. maxTagCount={2}
  220. clearable
  221. />
  222. </NFormItem>
  223. </div>
  224. ))}
  225. {!isUpdate.value && (
  226. <div class={styles.formItem}>
  227. <UploadFile
  228. v-model:fileList={uploadForms.uploadUrl}
  229. accept=".jpg,jpeg,.png,audio/mp3,video/mp4"
  230. showFileList={false}
  231. ref={uploadRef}
  232. cropper
  233. options={{
  234. autoCropWidth: 320,
  235. autoCropHeight: 180,
  236. fixedBox: true
  237. }}
  238. onFinished={(val: any) => {
  239. uploadForms.list.push({
  240. subjectIds: uploadForms.subjectIds || [],
  241. openFlag: true,
  242. coverImg: val.coverImg,
  243. name: uploadForms.name || '',
  244. type: formatUrlType(val.content),
  245. enableFlag: 1,
  246. content: val.content
  247. });
  248. uploadForms.uploadUrl = '';
  249. uploadForms.name = '';
  250. uploadForms.subjectIds = [];
  251. uploadRef.value.handleClearFile();
  252. }}
  253. />
  254. <NFormItem showFeedback={false}>
  255. <NInput
  256. v-model:value={uploadForms.name}
  257. placeholder="请输入资源名称"
  258. maxlength={25}
  259. clearable
  260. />
  261. </NFormItem>
  262. <NFormItem showFeedback={false}>
  263. <NSelect
  264. v-model:value={uploadForms.subjectIds}
  265. placeholder="请选择素材可用乐器(可多选)"
  266. options={catchStore.getSubjectList}
  267. labelField="name"
  268. valueField="id"
  269. multiple
  270. maxTagCount={2}
  271. clearable
  272. />
  273. </NFormItem>
  274. </div>
  275. )}
  276. </NSpace>
  277. </NForm>
  278. </NScrollbar>
  279. <NSpace class={styles.btnGroup} justify="center">
  280. <NButton round onClick={() => emit('close')}>
  281. 取消
  282. </NButton>
  283. <NButton
  284. round
  285. type="primary"
  286. loading={uploadForms.uploading}
  287. disabled={uploadForms.list.length === 0}
  288. onClick={onSubmit}>
  289. 确定
  290. </NButton>
  291. </NSpace>
  292. </div>
  293. );
  294. }
  295. });