index.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
  2. import styles from './index.module.less';
  3. import CardType from '/src/components/card-type';
  4. import Pagination from '/src/components/pagination';
  5. import SearchGroupResources from './search-group-resources';
  6. import {
  7. favorite,
  8. materialQueryPage,
  9. materialRemove,
  10. materialRemoveAll,
  11. materialRemoveMusic,
  12. materialUpdateAll
  13. } from '../../api';
  14. import {
  15. NButton,
  16. NModal,
  17. NSpace,
  18. NSpin,
  19. useDialog,
  20. useMessage
  21. } from 'naive-ui';
  22. import TheEmpty from '/src/components/TheEmpty';
  23. import UploadModal, { formatUrlType } from './upload-modal';
  24. import CardPreview from '@/components/card-preview';
  25. import resourceDefault from '../../images/resource-default.png';
  26. import resourceChecked from '../../images/resource-checked.png';
  27. import MyResourcesGuide from '@/custom-plugins/guide-page/myResources-guide';
  28. import SaveModal from './save-modal';
  29. import deepClone from '/src/helpers/deep-clone';
  30. import UploadCover from './upload-cover';
  31. import { modalClickMask } from '/src/state';
  32. export default defineComponent({
  33. name: 'share-resources',
  34. setup() {
  35. const message = useMessage();
  36. const dialog = useDialog();
  37. const state = reactive({
  38. searchWord: '',
  39. loading: false,
  40. pageTotal: 0,
  41. pagination: {
  42. page: 1,
  43. rows: 20
  44. },
  45. searchGroup: {
  46. type: 'MUSIC', //
  47. name: '',
  48. bookVersionId: null,
  49. subjectId: null,
  50. sourceType: 3
  51. },
  52. tableList: [] as any,
  53. uploadStatus: false,
  54. saveStatus: false,
  55. show: false,
  56. item: {} as any,
  57. editStatus: false, // 是否编辑
  58. isAdd: false,
  59. editList: [] as any, // TOD
  60. editIds: [] as any, // 编辑的
  61. editOverIds: [] as any, // 确认修改的数据
  62. removeVisiable: false,
  63. removeContent: '是否删除该资源?',
  64. type: 'remove',
  65. removeItem: {} as any
  66. });
  67. const showGuide = ref(false);
  68. const getList = async () => {
  69. try {
  70. state.loading = true;
  71. const { data } = await materialQueryPage({
  72. ...state.searchGroup,
  73. ...state.pagination
  74. });
  75. state.loading = false;
  76. state.pageTotal = Number(data.total);
  77. const tempRows = data.rows || [];
  78. const temp: any = [];
  79. tempRows.forEach((row: any) => {
  80. temp.push({
  81. id: row.id,
  82. coverImg: row.coverImg,
  83. type: row.type,
  84. title: row.name,
  85. isCollect: !!row.favoriteFlag,
  86. isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
  87. refFlag: row.refFlag,
  88. content: row.content,
  89. // subjectId: row.subjectIds,
  90. instrumentIds: row.instrumentIds,
  91. sourceFrom: row.sourceFrom,
  92. background: row.background,
  93. audioPlayTypeArray: row.audioPlayTypes
  94. ? row.audioPlayTypes.split(',')
  95. : [],
  96. enableFlag: row.enableFlag ? 1 : 0,
  97. openFlag: row.openFlag
  98. });
  99. });
  100. state.tableList = temp || [];
  101. setTimeout(() => {
  102. showGuide.value = true;
  103. }, 500);
  104. } catch {
  105. state.loading = false;
  106. }
  107. };
  108. const isEmpty = computed(() => {
  109. const list = state.tableList || [];
  110. let num = 0;
  111. list.forEach((item: any) => {
  112. if (!item.delFlag) {
  113. num++;
  114. }
  115. });
  116. return num > 0 ? false : true;
  117. });
  118. // 收藏
  119. const onCollect = async (item: any) => {
  120. try {
  121. await favorite({
  122. materialId: item.id,
  123. favoriteFlag: item.isCollect ? 0 : 1,
  124. type: item.type
  125. });
  126. item.isCollect = !item.isCollect;
  127. } catch {
  128. //
  129. }
  130. };
  131. const onSearch = async (item: any) => {
  132. state.pagination.page = 1;
  133. const { subjectId, ...res } = item;
  134. state.searchGroup = Object.assign(state.searchGroup, {
  135. ...res,
  136. musicalInstrumentId: subjectId,
  137. subjectId: null
  138. });
  139. getList();
  140. };
  141. // 批量删除
  142. const onDelete = async () => {
  143. try {
  144. if (state.searchGroup.type === 'MUSIC') {
  145. await materialRemoveMusic(state.editIds);
  146. } else {
  147. await materialRemoveAll(state.editIds);
  148. }
  149. // message.success('删除成功');
  150. // state.pagination.page = 1;
  151. // getList();
  152. // state.editIds = [];
  153. } catch {
  154. //
  155. }
  156. };
  157. // 单个删除
  158. const onRemove = async () => {
  159. try {
  160. // 如果是乐谱类型则使用其它删除接口
  161. if (state.searchGroup.type === 'MUSIC') {
  162. await materialRemoveMusic([state.removeItem.id]);
  163. } else {
  164. await materialRemove({ ids: state.removeItem.id });
  165. }
  166. message.success('删除成功');
  167. onSearch(state.searchGroup);
  168. } catch {
  169. //
  170. }
  171. };
  172. const searchGroupResourcesRef = ref();
  173. onMounted(() => {
  174. getList();
  175. });
  176. return () => (
  177. <>
  178. <SearchGroupResources
  179. ref={searchGroupResourcesRef}
  180. onSearch={(item: any) => onSearch(item)}
  181. onUpload={() => {
  182. state.editList = [];
  183. // state.uploadStatus = true;
  184. state.saveStatus = true;
  185. }}
  186. onUpdate={() => {
  187. // 修改
  188. const list: any[] = [];
  189. state.tableList.forEach((item: any) => {
  190. if (state.editIds.indexOf(item.id) > -1 && item.delFlag !== 1) {
  191. list.push(item);
  192. }
  193. });
  194. state.editList = list || [];
  195. if (state.editList.length <= 0) {
  196. message.error('至少选择一条资源进行编辑');
  197. return;
  198. }
  199. state.uploadStatus = true;
  200. state.isAdd = false;
  201. }}
  202. onEditOver={async (status: boolean) => {
  203. state.editStatus = status;
  204. try {
  205. // 修改
  206. if (state.editOverIds.length > 0) {
  207. const body = [] as any;
  208. state.tableList.forEach((item: any) => {
  209. if (state.editOverIds.includes(item.id)) {
  210. body.push({
  211. instrumentIds: item.instrumentIds,
  212. openFlag: item.openFlag,
  213. coverImg: item.coverImg,
  214. name: item.title,
  215. type: item.type,
  216. enableFlag: 1,
  217. content: item.content,
  218. id: item.id || null,
  219. delFlag: item.delFlag
  220. });
  221. }
  222. });
  223. //
  224. if (body.length > 0) {
  225. if (state.searchGroup.type === 'MUSIC') {
  226. await materialRemoveMusic(state.editIds);
  227. } else {
  228. await materialUpdateAll(body);
  229. }
  230. }
  231. }
  232. message.success('修改成功');
  233. state.pagination.page = 1;
  234. getList();
  235. state.editIds = [];
  236. state.editOverIds = [];
  237. } catch {
  238. //
  239. }
  240. }}
  241. onCancel={status => {
  242. state.editStatus = status;
  243. state.pagination.page = 1;
  244. state.editIds = [];
  245. state.editOverIds = [];
  246. getList();
  247. }}
  248. onEdit={async (status: boolean) => {
  249. // 点击编辑
  250. state.editStatus = status;
  251. if (!state.editStatus) {
  252. state.editIds = [];
  253. state.editOverIds = [];
  254. }
  255. }}
  256. onSelectAll={(status: boolean) => {
  257. // 全选
  258. if (status) {
  259. const tempIds: any[] = [];
  260. state.tableList.forEach((item: any) => {
  261. tempIds.push(item.id);
  262. });
  263. state.editIds = tempIds;
  264. } else {
  265. state.editIds = [];
  266. }
  267. }}
  268. onDelete={() => {
  269. if (state.editIds.length <= 0) {
  270. message.error('至少选择一条资源进行删除');
  271. return;
  272. }
  273. state.type = 'delete';
  274. state.removeContent = '是否删除该资源?';
  275. state.removeVisiable = true;
  276. }}
  277. />
  278. <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
  279. <div class={styles.list}>
  280. {state.tableList.map(
  281. (item: any) =>
  282. item.delFlag !== 1 && (
  283. <div class={styles.itemWrap}>
  284. <div class={styles.itemWrapBox}>
  285. <CardType
  286. item={item}
  287. isDownload
  288. disabledMouseHover={false}
  289. offShelf={item.enableFlag ? false : true}
  290. onOffShelf={() => {
  291. state.type = 'remove';
  292. state.removeContent = '该资源已下架,是否删除?';
  293. state.removeVisiable = true;
  294. state.removeItem = item;
  295. }} // 下架
  296. onClick={(val: any) => {
  297. if (val.type === 'IMG' || !item.enableFlag) return;
  298. state.show = true;
  299. state.item = val;
  300. }}
  301. onCollect={(item: any) => onCollect(item)}
  302. />
  303. {/* 编辑模式 */}
  304. {state.editStatus && (
  305. <div
  306. class={[
  307. styles.itemBg,
  308. state.editIds.includes(item.id)
  309. ? styles.itemBgChecked
  310. : ''
  311. ]}
  312. onClick={() => {
  313. const index = state.editIds.indexOf(item.id);
  314. if (index > -1) {
  315. state.editIds.splice(index, 1);
  316. } else {
  317. state.editIds.push(item.id);
  318. }
  319. }}>
  320. <img
  321. src={
  322. state.editIds.includes(item.id)
  323. ? resourceChecked
  324. : resourceDefault
  325. }
  326. class={styles.resourceDefault}
  327. />
  328. </div>
  329. )}
  330. </div>
  331. </div>
  332. )
  333. )}
  334. {!state.loading && isEmpty.value && (
  335. <TheEmpty style={{ minHeight: '50vh' }} description="暂无资源" />
  336. )}
  337. </div>
  338. </NSpin>
  339. <Pagination
  340. disabled={state.editStatus}
  341. v-model:page={state.pagination.page}
  342. v-model:pageSize={state.pagination.rows}
  343. v-model:pageTotal={state.pageTotal}
  344. onList={getList}
  345. />
  346. {/* 弹窗查看 */}
  347. <CardPreview v-model:show={state.show} item={state.item} />
  348. <NModal
  349. maskClosable={modalClickMask}
  350. v-model:show={state.uploadStatus}
  351. preset="card"
  352. showIcon={false}
  353. class={['modalTitle background', styles.attendClassModal]}
  354. title={state.editStatus ? '修改资源' : '上传资源'}
  355. blockScroll={false}>
  356. <UploadModal
  357. editStatus={state.editStatus}
  358. onClose={() => {
  359. state.uploadStatus = false;
  360. }}
  361. onConfirm={() => {
  362. state.editIds = [];
  363. state.editList = [];
  364. state.editOverIds = [];
  365. state.saveStatus = false;
  366. searchGroupResourcesRef.value?.resetStatus();
  367. onSearch(state.searchGroup);
  368. }}
  369. list={state.editList}
  370. showDelete={state.isAdd}
  371. onEditAll={(list: any) => {
  372. try {
  373. state.tableList.forEach((table: any) => {
  374. const item = list.find((item: any) => item.id === table.id);
  375. if (item) {
  376. table.openFlag = item.openFlag;
  377. table.title = item.name;
  378. table.instrumentIds = item.instrumentIds;
  379. table.content = item.content;
  380. table.coverImg = item.coverImg;
  381. if (!state.editOverIds.includes(table.id)) {
  382. state.editOverIds.push(table.id);
  383. }
  384. }
  385. });
  386. state.uploadStatus = false;
  387. } catch (e: any) {
  388. console.log(e);
  389. }
  390. }}
  391. />
  392. </NModal>
  393. <NModal
  394. maskClosable={modalClickMask}
  395. v-model:show={state.saveStatus}
  396. preset="card"
  397. showIcon={false}
  398. class={['modalTitle background', styles.attendClassSaveModal]}
  399. title={'上传资源'}
  400. blockScroll={false}>
  401. <SaveModal
  402. onClose={() => (state.saveStatus = false)}
  403. onConfrim={(val: any) => {
  404. const list = val || [];
  405. const temp: any = [];
  406. list.forEach((item: any) => {
  407. temp.push({
  408. instrumentIds: null,
  409. openFlag: false,
  410. coverImg: item.coverImg,
  411. title: item.name || '',
  412. type: formatUrlType(item.content),
  413. enableFlag: 1,
  414. content: item.content,
  415. id: null
  416. });
  417. });
  418. state.editList = [...temp];
  419. state.uploadStatus = true;
  420. state.isAdd = true;
  421. state.editStatus = false;
  422. }}
  423. />
  424. </NModal>
  425. {showGuide.value ? <MyResourcesGuide></MyResourcesGuide> : null}
  426. <NModal
  427. maskClosable={modalClickMask}
  428. v-model:show={state.removeVisiable}
  429. preset="card"
  430. class={['modalTitle', styles.removeVisiable]}
  431. title={'提示'}>
  432. <div class={styles.studentRemove}>
  433. <p>{state.removeContent}</p>
  434. <NSpace class={styles.btnGroupModal} justify="center">
  435. <NButton
  436. round
  437. type="primary"
  438. onClick={() => {
  439. if (state.type === 'remove') {
  440. onRemove();
  441. } else {
  442. state.tableList.forEach((item: any) => {
  443. if (state.editIds.includes(item.id)) {
  444. item.delFlag = 1;
  445. if (!state.editOverIds.includes(item.id)) {
  446. state.editOverIds.push(item.id);
  447. }
  448. }
  449. });
  450. }
  451. state.removeVisiable = false;
  452. }}>
  453. 确定
  454. </NButton>
  455. <NButton round onClick={() => (state.removeVisiable = false)}>
  456. 取消
  457. </NButton>
  458. </NSpace>
  459. </div>
  460. </NModal>
  461. </>
  462. );
  463. }
  464. });