index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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 iconPPT from '@common/images/icon-ppt.png';
  29. import iconUploadDelete from '../../../images/btn-remove.png';
  30. import { materialSave, materialUpdateAll } from '../../../api';
  31. import { NaturalTypeEnum } from '@/enums/pageEnum';
  32. import { scrollToErrorForm } from '/src/utils';
  33. // 判断链接后辍
  34. export const formatUrlType = (url: string) => {
  35. if (!url) return '';
  36. if (url?.indexOf('.mp3') > -1) {
  37. return NaturalTypeEnum.SONG;
  38. } else if (url?.indexOf('.mp4') > -1) {
  39. return NaturalTypeEnum.VIDEO;
  40. } else if (url?.indexOf('.ppt') > -1) {
  41. return NaturalTypeEnum.PPT;
  42. } else {
  43. return NaturalTypeEnum.IMG;
  44. }
  45. };
  46. export default defineComponent({
  47. name: 'upload-modal',
  48. props: {
  49. list: {
  50. type: Array,
  51. default: () => []
  52. },
  53. editStatus: {
  54. type: Boolean,
  55. default: true
  56. }
  57. },
  58. emits: ['close', 'confirm'],
  59. setup(props, { emit }) {
  60. const catchStore = useCatchStore();
  61. const formRef = ref();
  62. const message = useMessage();
  63. const uploadRef = ref();
  64. const uploadList = ref([] as any);
  65. const uploadForms = reactive({
  66. list: [] as any[],
  67. uploading: false,
  68. uploadUrl: '',
  69. name: '',
  70. subjectIds: [] as any
  71. });
  72. // 判断类型
  73. const formatType = (type: string) => {
  74. let typeImg = iconImage;
  75. switch (type) {
  76. case 'IMG':
  77. typeImg = iconImage;
  78. break;
  79. case 'VIDEO':
  80. typeImg = iconVideo;
  81. break;
  82. case 'SONG':
  83. typeImg = iconAudio;
  84. break;
  85. case 'MUSIC':
  86. typeImg = iconMusic;
  87. break;
  88. case 'PPT':
  89. typeImg = iconPPT;
  90. break;
  91. }
  92. return typeImg;
  93. };
  94. const onSubmit = async () => {
  95. //
  96. formRef.value?.validate(async (err: any) => {
  97. if (err) {
  98. nextTick(scrollToErrorForm);
  99. return;
  100. }
  101. uploadForms.uploading = true;
  102. try {
  103. const body: any[] = [];
  104. uploadForms.list.forEach(item => {
  105. body.push({
  106. subjectIds: item.subjectIds.join(','),
  107. openFlag: item.openFlag,
  108. coverImg: item.coverImg,
  109. name: item.name,
  110. type: item.type,
  111. enableFlag: 1,
  112. content: item.content,
  113. id: item.id || null
  114. });
  115. });
  116. if (isUpdate.value) {
  117. await materialUpdateAll(body);
  118. } else {
  119. await materialSave(body);
  120. }
  121. uploadForms.list = [];
  122. message.success('保存成功');
  123. emit('close', true);
  124. emit('confirm');
  125. } catch {
  126. //
  127. }
  128. uploadForms.uploading = false;
  129. });
  130. };
  131. const handleRemove = (index: number) => {
  132. uploadForms.list.splice(index, 1);
  133. };
  134. const isUpdate = computed(() => (props.list.length > 0 ? true : false));
  135. onMounted(async () => {
  136. const list = props.list || [];
  137. const temps: any[] = [];
  138. list.forEach((item: any) => {
  139. temps.push({
  140. subjectIds: item.subjectId
  141. ? item.subjectId
  142. .split(',')
  143. .map((subjectId: any) => Number(subjectId))
  144. : [],
  145. openFlag: item.openFlag,
  146. coverImg: item.coverImg,
  147. name: item.title,
  148. type: item.type,
  149. sourceFrom: item.sourceFrom,
  150. enableFlag: item.enableFlag,
  151. content: item.content,
  152. id: item.id
  153. });
  154. });
  155. uploadForms.list = temps || [];
  156. console.log(temps, 'uploadForms');
  157. await catchStore.getSubjects();
  158. });
  159. // 全选
  160. const chioseAll = (item: any, list: any) => {
  161. item.subjectIds = list.map((item: any) => {
  162. return item.id;
  163. }) as any;
  164. };
  165. return () => (
  166. <div class={styles.uploadModal}>
  167. <NScrollbar style={{ 'max-height': '55vh' }}>
  168. <NForm
  169. ref={formRef}
  170. labelPlacement="left"
  171. labelWidth={120}
  172. model={uploadForms}
  173. class={styles.formModal}>
  174. <NSpace class={styles.formSpace}>
  175. {uploadForms.list.map((item: any, index: number) => (
  176. <div class={styles.formItem} key={index}>
  177. <div class={styles.previewModal}>
  178. <NImage
  179. class={[styles.titleType]}
  180. src={formatType(item.type)}
  181. previewDisabled
  182. objectFit="cover"
  183. />
  184. {/* 编辑时不能删除 */}
  185. {!isUpdate.value && (
  186. <img
  187. class={[styles.iconUploadDelete]}
  188. src={iconUploadDelete}
  189. onClick={() => handleRemove(index)}
  190. />
  191. )}
  192. <NImage
  193. class={[styles.cover, styles.image]}
  194. lazy
  195. previewDisabled
  196. src={item.coverImg}
  197. objectFit="cover"
  198. />
  199. <div class={styles.commonType}>
  200. 是否公开:
  201. <NSwitch
  202. size="small"
  203. v-model:value={item.openFlag}
  204. disabled={
  205. item.sourceFrom === 'TEACHER' && item.type === 'MUSIC'
  206. }
  207. />
  208. </div>
  209. </div>
  210. <NFormItem
  211. showFeedback={false}
  212. path={`list.${index}.name`}
  213. rule={[
  214. {
  215. required: true,
  216. message: '请输入资源名称',
  217. trigger: ['input', 'blur']
  218. }
  219. ]}>
  220. <NInput
  221. v-model:value={item.name}
  222. placeholder="请输入资源名称"
  223. maxlength={25}
  224. clearable
  225. />
  226. </NFormItem>
  227. <NFormItem
  228. path={`list[${index}].subjectIds`}
  229. showFeedback={false}
  230. rule={[
  231. {
  232. required: true,
  233. message: '请选择素材可用乐器',
  234. trigger: 'change',
  235. type: 'array'
  236. }
  237. ]}>
  238. <NSelect
  239. v-model:value={item.subjectIds}
  240. placeholder="请选择素材可用乐器(可多选)"
  241. options={catchStore.getSubjectList}
  242. labelField="name"
  243. valueField="id"
  244. multiple
  245. maxTagCount={2}
  246. clearable
  247. v-slots={{
  248. action: () => (
  249. <>
  250. <NButton
  251. text
  252. style=" --n-width: 100% "
  253. onClick={() =>
  254. chioseAll(item, catchStore.getSubjectList)
  255. }>
  256. 全选
  257. </NButton>
  258. </>
  259. )
  260. }}
  261. />
  262. </NFormItem>
  263. </div>
  264. ))}
  265. {/* {!isUpdate.value && (
  266. <div class={styles.formItem}>
  267. <UploadFile
  268. v-model:fileList={uploadForms.uploadUrl}
  269. accept=".jpg,jpeg,.png,audio/mp3,video/mp4"
  270. showFileList={false}
  271. ref={uploadRef}
  272. // cropper
  273. multiple
  274. max={10}
  275. // options={{
  276. // autoCropWidth: 320,
  277. // autoCropHeight: 180,
  278. // fixedBox: true
  279. // }}
  280. onFinished={(val: any) => {
  281. console.log(val, 'val');
  282. uploadList.value.push({
  283. subjectIds: uploadForms.subjectIds || [],
  284. openFlag: true,
  285. coverImg: val.coverImg,
  286. name: uploadForms.name || '',
  287. type: formatUrlType(val.content),
  288. enableFlag: 1,
  289. content: val.content
  290. });
  291. // uploadForms.list.push({
  292. // subjectIds: uploadForms.subjectIds || [],
  293. // openFlag: true,
  294. // coverImg: val.coverImg,
  295. // name: uploadForms.name || '',
  296. // type: formatUrlType(val.content),
  297. // enableFlag: 1,
  298. // content: val.content
  299. // });
  300. const timer = setTimeout(() => {
  301. uploadForms.list.push(...uploadList.value);
  302. uploadList.value = [];
  303. uploadForms.uploadUrl = '';
  304. uploadForms.name = '';
  305. uploadForms.subjectIds = [];
  306. uploadRef.value.handleClearFile();
  307. }, 1000);
  308. }}
  309. />
  310. <NFormItem showFeedback={false}>
  311. <NInput
  312. v-model:value={uploadForms.name}
  313. placeholder="请输入资源名称"
  314. maxlength={25}
  315. clearable
  316. />
  317. </NFormItem>
  318. <NFormItem showFeedback={false}>
  319. <NSelect
  320. v-model:value={uploadForms.subjectIds}
  321. placeholder="请选择素材可用乐器(可多选)"
  322. options={catchStore.getSubjectList}
  323. labelField="name"
  324. valueField="id"
  325. multiple
  326. maxTagCount={2}
  327. clearable
  328. v-slots={{
  329. action: () => (
  330. <>
  331. <NButton
  332. text
  333. style=" --n-width: 100% "
  334. onClick={() =>
  335. chioseAll(
  336. uploadForms,
  337. catchStore.getSubjectList
  338. )
  339. }>
  340. 全选
  341. </NButton>
  342. </>
  343. )
  344. }}
  345. />
  346. </NFormItem>
  347. </div>
  348. )} */}
  349. </NSpace>
  350. </NForm>
  351. </NScrollbar>
  352. <NSpace class={styles.btnGroup} justify="center">
  353. <NButton round onClick={() => emit('close')}>
  354. {props.editStatus ? '取消' : '上一步'}
  355. </NButton>
  356. <NButton
  357. round
  358. type="primary"
  359. loading={uploadForms.uploading}
  360. disabled={uploadForms.list.length === 0}
  361. onClick={onSubmit}>
  362. 确定
  363. </NButton>
  364. </NSpace>
  365. </div>
  366. );
  367. }
  368. });