lex 10 months ago
parent
commit
9ae326c2e0

+ 743 - 744
src/utils/index.ts

@@ -1,744 +1,743 @@
-import { h, unref } from 'vue';
-import type { App, Plugin } from 'vue';
-import { NIcon, NTag } from 'naive-ui';
-import { PageEnum } from '@/enums/pageEnum';
-import { isObject } from './is/index';
-import { cloneDeep } from 'lodash';
-import dayjs from 'dayjs';
-
-import EventEmitter from 'eventemitter3';
-
-export const eventGlobal = new EventEmitter();
-
-/**
- * render 图标
- * */
-export function renderIcon(icon: any) {
-  return () => h(NIcon, null, { default: () => h(icon) });
-}
-/**
- * font 图标(Font class)
- * */
-export function renderFontClassIcon(icon: string, iconName = 'iconfont') {
-  return () => h('span', { class: [iconName, icon] });
-}
-/**
- * font 图标(Unicode)
- * */
-export function renderUnicodeIcon(icon: string, iconName = 'iconfont') {
-  return () => h('span', { class: [iconName], innerHTML: icon });
-}
-/**
- * font svg 图标
- * */
-export function renderfontsvg(icon: any) {
-  return () =>
-    h(NIcon, null, {
-      default: () =>
-        h(
-          'svg',
-          { class: `icon`, 'aria-hidden': 'true' },
-          h('use', { 'xlink:href': `#${icon}` })
-        )
-    });
-}
-
-/**
- * render new Tag
- * */
-const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' };
-export function renderNew(
-  type = 'warning',
-  text = 'New',
-  color: object = newTagColors
-) {
-  return () =>
-    h(
-      NTag as any,
-      {
-        type,
-        round: true,
-        size: 'small',
-        color
-      },
-      { default: () => text }
-    );
-}
-
-/**
- * 递归组装菜单格式
- */
-export function generatorMenu(routerMap: Array<any>) {
-  return filterRouter(routerMap).map(item => {
-    const isRoot = isRootRouter(item);
-    if (isRoot) {
-      console.log(item.children[0], 'isRoot');
-    }
-    const info = isRoot ? item.children[0] : item;
-    // console.log(item)
-    const currentMenu = {
-      ...info,
-      ...info.meta,
-      label: info.meta?.title,
-      key: info.key,
-      icon: info.meta?.icon
-    };
-    // 是否有子菜单,并递归处理
-    if (info.children && info.children.length > 0) {
-      // Recursion
-      currentMenu.children = generatorMenu(info.children);
-    }
-    return currentMenu;
-  });
-}
-
-/**
- * 混合菜单
- * */
-export function generatorMenuMix(
-  routerMap: Array<any>,
-  routerName: string,
-  location: string
-) {
-  const cloneRouterMap = cloneDeep(routerMap);
-  const newRouter = filterRouter(cloneRouterMap);
-  if (location === 'header') {
-    const firstRouter: any[] = [];
-    newRouter.forEach(item => {
-      const isRoot = isRootRouter(item);
-      const info = isRoot ? item.children[0] : item;
-      info.children = undefined;
-      const currentMenu = {
-        ...info,
-        ...info.meta,
-        label: info.meta?.title,
-        key: info.name
-      };
-      firstRouter.push(currentMenu);
-    });
-    return firstRouter;
-  } else {
-    // 混合菜单
-    console.log('混合菜单');
-    return getChildrenRouter(
-      newRouter.filter(item => item.name === routerName)
-    );
-  }
-}
-
-/**
- * 递归组装子菜单
- * */
-export function getChildrenRouter(routerMap: Array<any>) {
-  return filterRouter(routerMap).map(item => {
-    const isRoot = isRootRouter(item);
-    const info = isRoot ? item.children[0] : item;
-    const currentMenu = {
-      ...info,
-      ...info.meta,
-      label: info.meta?.title,
-      key: info.name
-    };
-    // 是否有子菜单,并递归处理
-    if (info.children && info.children.length > 0) {
-      // Recursion
-      currentMenu.children = getChildrenRouter(info.children);
-    }
-    return currentMenu;
-  });
-}
-
-/**
- * 判断根路由 Router
- * */
-export function isRootRouter(item: any) {
-  return item.meta?.isRoot === true;
-}
-
-/**
- * 排除Router
- * */
-export function filterRouter(routerMap: Array<any>) {
-  return routerMap.filter(item => {
-    // console.log(
-    //   (item.meta?.hidden || false) != true &&
-    //   !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path),
-    //   '过滤完之后的路由'
-    // )
-    return (
-      (item.meta?.hidden || false) != true &&
-      !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(
-        item.path
-      )
-    );
-  });
-}
-
-export const withInstall = <T>(component: T, alias?: string) => {
-  const comp = component as any;
-  comp.install = (app: App) => {
-    app.component(comp.name || comp.displayName, component as any);
-    if (alias) {
-      app.config.globalProperties[alias] = component;
-    }
-  };
-  return component as T & Plugin;
-};
-
-/**
- *  找到对应的节点
- * */
-let result = null as any;
-export function getTreeItem(data: any[], key?: string | number): any {
-  data.map(item => {
-    if (item.key === key) {
-      result = item;
-    } else {
-      if (item.children && item.children.length) {
-        getTreeItem(item.children, key);
-      }
-    }
-  });
-  return result;
-}
-
-/**
- *  找到所有节点
- * */
-const treeAll: any[] = [];
-export function getTreeAll(data: any[]): any[] {
-  data.map(item => {
-    treeAll.push(item.key);
-    if (item.children && item.children.length) {
-      getTreeAll(item.children);
-    }
-  });
-  return treeAll;
-}
-
-export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
-  let key: string;
-  for (key in target) {
-    src[key] = isObject(src[key])
-      ? deepMerge(src[key], target[key])
-      : (src[key] = target[key]);
-  }
-  return src;
-}
-
-/**
- * Sums the passed percentage to the R, G or B of a HEX color
- * @param {string} color The color to change
- * @param {number} amount The amount to change the color by
- * @returns {string} The processed part of the color
- */
-function addLight(color: string, amount: number) {
-  const cc = parseInt(color, 16) + amount;
-  const c = cc > 255 ? 255 : cc;
-  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
-}
-
-/**
- * Lightens a 6 char HEX color according to the passed percentage
- * @param {string} color The color to change
- * @param {number} amount The amount to change the color by
- * @returns {string} The processed color represented as HEX
- */
-export function lighten(color: string, amount: number) {
-  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
-  amount = Math.trunc((255 * amount) / 100);
-  return `#${addLight(color.substring(0, 2), amount)}${addLight(
-    color.substring(2, 4),
-    amount
-  )}${addLight(color.substring(4, 6), amount)}`;
-}
-
-/**
- * 判断是否 url
- * */
-export function isUrl(url: string) {
-  return /^(http|https):\/\//g.test(url);
-}
-
-/** 递归清除空数据 */
-export function clearEmtryData(list: any[], key: string) {
-  for (let i = 0; i < list.length; i++) {
-    if (Array.isArray(list[i][key]) && !list[i][key].length) {
-      list[i][key] = '';
-    } else {
-      list[i][key] = clearEmtryData(list[i][key], key);
-    }
-  }
-  return list;
-}
-
-// 秒转分
-export const getSecondRPM = (second: number, type?: string) => {
-  if (isNaN(second)) return '00:00';
-  const mm = Math.floor(second / 60)
-    .toString()
-    .padStart(2, '0');
-  const dd = Math.floor(second % 60)
-    .toString()
-    .padStart(2, '0');
-  if (type === 'cn') {
-    return mm + '分' + dd + '秒';
-  } else {
-    return mm + ':' + dd;
-  }
-};
-
-// 秒转分
-export const getSecond = (second: number, type?: string) => {
-  if (isNaN(second)) return '0000';
-  const mm = Math.floor(second / 60)
-    .toString()
-    .padStart(2, '0');
-  const dd = Math.floor(second % 60)
-    .toString()
-    .padStart(2, '0');
-  return `${mm}${dd}`;
-};
-
-/** 滚动到表单填写错误的地方 */
-export function scrollToErrorForm() {
-  const isError =
-    document.querySelector('.n-input--error-status') ||
-    document.querySelector('.n-base-selection--error-status');
-  isError?.scrollIntoView({
-    block: 'center',
-    behavior: 'smooth'
-  });
-}
-
-export const getTimes = (
-  times: any,
-  keys: Array<string> = [],
-  format = 'YYYY-MM-DD'
-) => {
-  if (times && times.length) {
-    return format == 'YYYY-MM-DD'
-      ? {
-          [keys[0] || 'start']: dayjs(times[0]).isValid()
-            ? dayjs(times[0]).format(format) + ' 00:00:00'
-            : '',
-          [keys[1] || 'end']: dayjs(times[1]).isValid()
-            ? dayjs(times[1]).format(format) + ' 23:59:59'
-            : ''
-        }
-      : {
-          [keys[0] || 'start']: dayjs(times[0]).isValid()
-            ? dayjs(times[0]).format(format)
-            : '',
-          [keys[1] || 'end']: dayjs(times[1]).isValid()
-            ? dayjs(times[1]).format(format)
-            : ''
-        };
-  }
-  return {};
-};
-
-export const px2vw = (px: number): string => `${(px / 1920) * 100}vw`;
-
-export const px2vwH = (px: number): string =>
-  `${(((px / 1920) * 1920) / 1188) * 100}vw`;
-
-export const fscreen = () => {
-  const el = document.documentElement;
-
-  //进入全屏
-  (el.requestFullscreen && el.requestFullscreen()) ||
-    (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
-    (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
-    (el.msRequestFullscreen && el.msRequestFullscreen());
-
-  //退出全屏
-};
-
-export const exitFullscreen = () => {
-  document.exitFullscreen
-    ? document.exitFullscreen()
-    : document.mozCancelFullScreen
-    ? document.mozCancelFullScreen()
-    : document.webkitExitFullscreen
-    ? document.webkitExitFullscreen()
-    : '';
-};
-
-/** 检测链接格式 */
-export function checkUrlType(urlType: string) {
-  const subfix = (urlType || '').split('.').pop();
-  if (subfix === 'wav' || subfix === 'mp3' || subfix === 'm4a') {
-    return 'audio';
-  }
-  return 'video';
-}
-
-const instruments: any = {
-  'Acoustic Grand Piano': '大钢琴',
-  'Bright Acoustic Piano': '明亮的钢琴',
-  'Electric Grand Piano': '电钢琴',
-  'Rhodes Piano': '柔和的电钢琴',
-  'Chorused Piano': '加合唱效果的电钢琴',
-  Harpsichord: '羽管键琴',
-  Clavichord: '科拉维科特琴',
-  Celesta: '钢片琴',
-  Glockenspiel: '钢片琴',
-  'Music box': '八音盒',
-  Vibraphone: '颤音琴',
-  Marimba: '马林巴',
-  Xylophone: '木琴',
-  'Tubular Bells': '管钟',
-  Dulcimer: '大扬琴',
-  'Hammond Organ': '击杆风琴',
-  'Percussive Organ': '打击式风琴',
-  'Rock Organ': '摇滚风琴',
-  'Church Organ': '教堂风琴',
-  'Reed Organ': '簧管风琴',
-  Accordian: '手风琴',
-  Harmonica: '口琴',
-  'Tango Accordian': '探戈手风琴',
-  'Acoustic Guitar': '钢弦吉他',
-  'Electric Guitar': '闷音电吉他',
-  'Overdriven Guitar': '加驱动效果的电吉他',
-  'Distortion Guitar': '加失真效果的电吉他',
-  'Guitar Harmonics': '吉他和音',
-  'Acoustic Bass': '大贝司',
-  'Electric Bass': '电贝司',
-  'Fretless Bass': '无品贝司',
-  'Slap Bass': '掌击',
-  'Synth Bass': '电子合成',
-  Violin: '小提琴',
-  Viola: '中提琴',
-  Cello: '大提琴',
-  Contrabass: '低音大提琴',
-  'Tremolo Strings': '弦乐群颤音音色',
-  'Pizzicato Strings': '弦乐群拨弦音色',
-  'Orchestral Harp': '竖琴',
-  Timpani: '定音鼓',
-  'String Ensemble': '弦乐合奏音色',
-  'Synth Strings': '合成弦乐合奏音色',
-  'Choir Aahs': '人声合唱',
-  'Voice Oohs': '人声',
-  'Synth Voice': '合成人声',
-  'Orchestra Hit': '管弦乐敲击齐奏',
-  Trumpet: '小号',
-  Trombone: '长号',
-  Tuba: '大号',
-  'Muted Trumpet': '加弱音器小号',
-  'French Horn': '法国号',
-  'Brass Section': '铜管组',
-  'Synth Brass': '合成铜管音色',
-  'Soprano Sax': '高音萨克斯管',
-  'Alto Sax': '中音萨克斯管',
-  'Tenor Sax': '次中音萨克斯管',
-  'Baritone Sax': '低音萨克斯管',
-  Oboe: '双簧管',
-  'English Horn': '英国管',
-  Bassoon: '巴松',
-  Clarinet: '单簧管',
-  'Soprano Saxophone': '高音萨克斯管',
-  'Alto Saxophone': '中音萨克斯管',
-  'Tenor Saxophone': '次中音萨克斯管',
-  'Baritone Saxophone': '低音萨克斯管',
-  Piccolo: '短笛',
-  Flute: '长笛',
-  Recorder: '竖笛',
-  'Soprano Recorder': '高音竖笛',
-  'Pan Flute': '排箫',
-  'Bottle Blow': '瓶木管',
-  Whistle: '口哨声',
-  Ocarina: '陶笛',
-  Lead: '合成主音',
-  'Lead lead': '合成主音',
-  'Pad age': '合成音色',
-  Pad: '合成音色',
-  FX: '合成效果  科幻',
-  Sitar: '西塔尔',
-  Banjo: '班卓琴',
-  Shamisen: '三昧线',
-  Koto: '十三弦筝',
-  Kalimba: '卡林巴',
-  Bagpipe: '风笛',
-  Fiddle: '民族提琴',
-  Shanai: '山奈',
-  'Tinkle Bell': '叮当铃',
-  Agogos: '阿戈戈铃',
-  'Steel Drums': '钢鼓',
-  'Taiko Drum': '太鼓',
-  'Melodic Toms': '嗵嗵鼓',
-  'Synth Drums': '合成鼓',
-  'Reverse Cymbals': '反向镲',
-  'Agogo Bells': '阿戈戈铃',
-  'Taiko Drums': '太鼓',
-  Bongos: '邦戈鼓',
-  'Bongo Bell': '邦戈铃',
-  Congas: '康加鼓',
-  Guiro: '刮壶',
-  'Guitar Fret Noise': '吉他换把杂音',
-  'Breath Noise': '呼吸声',
-  Seashore: '海浪声',
-  'Bird Tweet': '鸟鸣',
-  'Telephone Ring': '电话铃',
-  Helicopter: '直升机',
-  Applause: '鼓掌声',
-  Gunshot: '枪声',
-  'Acoustic Bass Drum': '大鼓',
-  'Bass Drum': '大鼓',
-  'Side Drum': '小鼓鼓边',
-  'Acoustic Snare': '小鼓',
-  'Hand Claps': '拍手',
-  'Electric Snare': '小鼓',
-  'Low Floor Tom': '低音嗵鼓',
-  'Closed Hi-Hat': '闭合踩镲',
-  'High Floor Tom': '高音落地嗵鼓',
-  'Pedal Hi-Hat': '脚踏踩镲',
-  'Low Tom': '低音嗵鼓',
-  'Open Hi-Hat': '开音踩镲',
-  'Low-Mid Tom': '中低音嗵鼓',
-  'Hi Mid Tom': '高音鼓',
-  'Crash Cymbals': '对镲',
-  'High Tom': '高音嗵鼓',
-  'Ride Cymbals': '叮叮镲',
-  'Chinese Cymbals': '中国镲',
-  'Ride Bell': '圆铃',
-  Tambourine: '铃鼓',
-  'Splash Cymbal': '溅音镲',
-  Cowbell: '牛铃',
-  'Crash Cymbal': '强音钹',
-  'Vibra-Slap': '颤音器',
-  'Ride Cymbal': '打点钹',
-  'Hi Bongo': '高音邦戈鼓',
-  'Low Bongo': '低音邦戈鼓',
-  'Mute Hi Conga': '弱音高音康加鼓',
-  'Open Hi Conga': '强音高音康加鼓',
-  'Low Conga': '低音康加鼓',
-  'High Timbale': '高音天巴鼓',
-  'Low Timbale': '低音天巴鼓',
-  'High Agogo': '高音阿戈戈铃',
-  'Low Agogo': '低音阿戈戈铃',
-  Cabasa: '卡巴萨',
-  Maracas: '沙锤',
-  'Short Whistle': '短口哨',
-  'Long Whistle': '长口哨',
-  'Short Guiro': '短刮壶',
-  'Long Guiro': '长刮壶',
-  Claves: '响棒',
-  'Hi Wood Block': '高音木鱼',
-  'Low Wood Block': '低音木鱼',
-  'Mute Triangle': '弱音三角铁',
-  'Open Triangle': '强音三角铁',
-  'Drum Set': '架子鼓',
-  'Hulusi flute': '葫芦丝',
-  Melodica: '口风琴',
-  Nai: '口风琴',
-  'Snare Drum': '小军鼓',
-  Cymbal: '镲',
-  Cymbals: '镲',
-  'Horn in F': '圆号',
-  Triangle: '三角铁',
-  Vibrato: '颤音琴',
-  'Suspend Cymbals': '吊镲',
-  'Suspended Cymbals': '吊镲',
-  'Tom-Toms': '嗵嗵鼓',
-  Bell: '铃铛',
-  Bells: '铃铛',
-  'Alto Clarinet': '中音单簧管',
-  'Bass Clarinet': '低音单簧管',
-  Cornet: '短号',
-  Euphonium: '上低音号',
-  'crash cymbals': '对镲',
-  Castanets: '响板',
-  Shaker: '沙锤',
-  'Mark tree': '音树',
-  Chimes: '管钟',
-  'Mark Tree': '音树',
-  'Tom-toms': '嗵嗵鼓',
-  'Hi-Hat': '踩镲',
-  'Sleigh Bells': '雪橇铃',
-  Flexatone: '弹音器',
-  'Brake drum': '闸鼓',
-  Gong: '锣',
-  'concert tom': '音乐会嗵嗵鼓',
-  'brake drum': '车轮鼓',
-  'finger cymbal': '指钹',
-  'ride cymbal': '叮叮镲',
-  'Concert Toms': '音乐会嗵嗵鼓',
-  Vibraslap: '弹音器',
-  'Wood Blocks': '木鱼',
-  'Temple Blocks': '木鱼',
-  'Wood Block': '木鱼',
-  'Field Drum': '军鼓',
-  'Quad-Toms': '筒鼓',
-  Quads: '筒鼓',
-  'Drums set': '架子鼓',
-  'High Bongo': '邦戈',
-  Timbales: '天巴鼓'
-};
-
-/** 获取分轨名称 */
-export const getInstrumentName = (name = '') => {
-  name = name.toLocaleLowerCase().replace(/ /g, '');
-  if (!name) return '';
-  for (const key in instruments) {
-    const _key = key.toLocaleLowerCase().replace(/ /g, '');
-    if (_key.includes(name)) {
-      return instruments[key];
-    }
-  }
-  for (const key in instruments) {
-    const _key = key.toLocaleLowerCase().replace(/ /g, '');
-    if (name.includes(_key)) {
-      return instruments[key];
-    }
-  }
-  return '';
-};
-
-/**
- * 乐器排序
- * 排序顺序:长笛、单簧管、中音单簧管、低音单簧管、高音萨克斯风、中音萨克斯风、次中音萨克斯风、低音萨克斯风、小号、长号、圆号、大号、上低音号
- * */
-export const sortMusical = (name: string, index: number) => {
-  let sortId = 0;
-  switch (name) {
-    case '长笛':
-      sortId = 1;
-      break;
-    case '单簧管':
-      sortId = 2;
-      break;
-    case '中音单簧管':
-      sortId = 3;
-      break;
-    case '低音单簧管':
-      sortId = 4;
-      break;
-    case '高音萨克斯风':
-      sortId = 5;
-      break;
-    case '中音萨克斯风':
-      sortId = 6;
-      break;
-    case '次中音萨克斯风':
-      sortId = 7;
-      break;
-    case '低音萨克斯风':
-      sortId = 8;
-      break;
-    case '小号':
-      sortId = 9;
-      break;
-    case '长号':
-      sortId = 10;
-      break;
-    case '圆号':
-      sortId = 11;
-      break;
-    case '大号':
-      sortId = 12;
-      break;
-    case '上低音号':
-      sortId = 13;
-      break;
-    default:
-      sortId = index + 14;
-      break;
-  }
-  return sortId;
-};
-
-// 课堂乐器声轨名称集合
-const trackNames: any = {
-  Piccolo: 'Tenor Recorder',
-  flute: 'Flute',
-  Flute: 'Flute',
-  'Flute 1': 'Flute',
-  'Flute 2': 'Flute',
-  Oboe: 'Clarinet',
-  oboe: 'Clarinet',
-  clarinet: 'Clarinet',
-  'Clarinet in Bb': 'Clarinet',
-  'Clarinet in Bb 1': 'Clarinet',
-  'Clarinet in Bb 2': 'Clarinet',
-  'Alto Clarinet in Eb': 'Clarinet',
-  'Bass Clarinet in Bb': 'Clarinet',
-  Bassoon: 'Bassoon',
-  'Alto Saxophone': 'Alto Saxophone',
-  'Tenor Saxophone': 'Alto Saxophone',
-  'Baritone Saxophone': 'Alto Saxophone',
-  altosaxophone: 'Alto Saxophone',
-  tenorsaxophone: 'Alto Saxophone',
-  saxophone: 'Alto Saxophone',
-  'Trumpet in Bb 1': 'Trumpet',
-  'Trumpet in Bb 2': 'Trumpet',
-  trumpet: 'Trumpet',
-  'Horn in F': 'Horn',
-  'Horn in F 1': 'Horn',
-  'Horn in F 2': 'Horn',
-  horn: 'Horn',
-  trombone: 'Trombone',
-  'Trombone 1': 'Trombone',
-  'Trombone 2': 'Trombone',
-  'Trombone 3': 'Trombone',
-  Euphonium: 'Baritone',
-  upbasshorn: 'Baritone',
-  Tuba: 'Tuba',
-  tuba: 'Tuba',
-  Chimes: 'Chimes',
-  Bells: 'Bells',
-  Xylophone: 'Xylophone',
-  'Snare Drum': 'Snare Drum',
-  'Bass Drum': 'Bass Drum',
-  Triangle: 'Triangle',
-  'Suspended Cymbal': 'Suspended Cymbal',
-  'Crash Cymbals': 'Crash Cymbals',
-  'Concert Toms': 'Concert Toms',
-  Timpani: 'Timpani',
-  'Drum Set': 'Drum Set',
-  Marimba: 'Marimba',
-  Vibraphone: 'Vibraphone',
-  'Tubular Bells': 'Tubular Bells',
-  Mallets: 'Mallets',
-  recorder: 'Piccolo',
-  tenorrecorder: 'piccolo',
-  melodica: 'melodica',
-  hulusiFlute: 'hulusiFlute',
-  panflute: 'panflute',
-  ukulele: 'ukulele',
-  mouthorgan: 'mouthorgan',
-  piano: 'piano',
-  woodwind: 'Woodwind',
-  panpipes: 'Panpipes',
-  ocarina: 'Ocarina',
-  nai: 'Nai',
-  BaroqueRecorder: 'Baroque Recorder'
-};
-
-/** 声轨track转换成乐器code */
-export const trackToCode = (track: any) => {
-  return trackNames[track] || track;
-};
-export const iframeDislableKeyboard = (iframeDom: any) => {
-  // 在 iframe 内部注入脚本禁用右键菜单
-  const script = document.createElement('script');
-  script.innerHTML = `
-      document.addEventListener('contextmenu', function(e) {
-          e.preventDefault();
-      });
-
-      document.addEventListener('keydown', function (event) {
-        // 屏蔽 F12 和 Ctrl+Shift+I
-        if (
-          event.key === 'F12' ||
-          (event.ctrlKey && event.shiftKey && event.key === 'I') ||
-          (event.metaKey && event.altKey && event.key === 'I')
-        ) {
-          event.preventDefault();
-        }
-      });
-            `;
-  if (iframeDom.contentWindow.document.body) {
-    iframeDom?.contentDocument?.body.appendChild(script);
-  }
-};
+import { h, unref } from 'vue';
+import type { App, Plugin } from 'vue';
+import { NIcon, NTag } from 'naive-ui';
+import { PageEnum } from '@/enums/pageEnum';
+import { isObject } from './is/index';
+import { cloneDeep } from 'lodash';
+import dayjs from 'dayjs';
+
+import EventEmitter from 'eventemitter3';
+
+export const eventGlobal = new EventEmitter();
+
+/**
+ * render 图标
+ * */
+export function renderIcon(icon: any) {
+  return () => h(NIcon, null, { default: () => h(icon) });
+}
+/**
+ * font 图标(Font class)
+ * */
+export function renderFontClassIcon(icon: string, iconName = 'iconfont') {
+  return () => h('span', { class: [iconName, icon] });
+}
+/**
+ * font 图标(Unicode)
+ * */
+export function renderUnicodeIcon(icon: string, iconName = 'iconfont') {
+  return () => h('span', { class: [iconName], innerHTML: icon });
+}
+/**
+ * font svg 图标
+ * */
+export function renderfontsvg(icon: any) {
+  return () =>
+    h(NIcon, null, {
+      default: () =>
+        h(
+          'svg',
+          { class: `icon`, 'aria-hidden': 'true' },
+          h('use', { 'xlink:href': `#${icon}` })
+        )
+    });
+}
+
+/**
+ * render new Tag
+ * */
+const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' };
+export function renderNew(
+  type = 'warning',
+  text = 'New',
+  color: object = newTagColors
+) {
+  return () =>
+    h(
+      NTag as any,
+      {
+        type,
+        round: true,
+        size: 'small',
+        color
+      },
+      { default: () => text }
+    );
+}
+
+/**
+ * 递归组装菜单格式
+ */
+export function generatorMenu(routerMap: Array<any>) {
+  return filterRouter(routerMap).map(item => {
+    const isRoot = isRootRouter(item);
+    if (isRoot) {
+      console.log(item.children[0], 'isRoot');
+    }
+    const info = isRoot ? item.children[0] : item;
+    // console.log(item)
+    const currentMenu = {
+      ...info,
+      ...info.meta,
+      label: info.meta?.title,
+      key: info.key,
+      icon: info.meta?.icon
+    };
+    // 是否有子菜单,并递归处理
+    if (info.children && info.children.length > 0) {
+      // Recursion
+      currentMenu.children = generatorMenu(info.children);
+    }
+    return currentMenu;
+  });
+}
+
+/**
+ * 混合菜单
+ * */
+export function generatorMenuMix(
+  routerMap: Array<any>,
+  routerName: string,
+  location: string
+) {
+  const cloneRouterMap = cloneDeep(routerMap);
+  const newRouter = filterRouter(cloneRouterMap);
+  if (location === 'header') {
+    const firstRouter: any[] = [];
+    newRouter.forEach(item => {
+      const isRoot = isRootRouter(item);
+      const info = isRoot ? item.children[0] : item;
+      info.children = undefined;
+      const currentMenu = {
+        ...info,
+        ...info.meta,
+        label: info.meta?.title,
+        key: info.name
+      };
+      firstRouter.push(currentMenu);
+    });
+    return firstRouter;
+  } else {
+    // 混合菜单
+    console.log('混合菜单');
+    return getChildrenRouter(
+      newRouter.filter(item => item.name === routerName)
+    );
+  }
+}
+
+/**
+ * 递归组装子菜单
+ * */
+export function getChildrenRouter(routerMap: Array<any>) {
+  return filterRouter(routerMap).map(item => {
+    const isRoot = isRootRouter(item);
+    const info = isRoot ? item.children[0] : item;
+    const currentMenu = {
+      ...info,
+      ...info.meta,
+      label: info.meta?.title,
+      key: info.name
+    };
+    // 是否有子菜单,并递归处理
+    if (info.children && info.children.length > 0) {
+      // Recursion
+      currentMenu.children = getChildrenRouter(info.children);
+    }
+    return currentMenu;
+  });
+}
+
+/**
+ * 判断根路由 Router
+ * */
+export function isRootRouter(item: any) {
+  return item.meta?.isRoot === true;
+}
+
+/**
+ * 排除Router
+ * */
+export function filterRouter(routerMap: Array<any>) {
+  return routerMap.filter(item => {
+    // console.log(
+    //   (item.meta?.hidden || false) != true &&
+    //   !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path),
+    //   '过滤完之后的路由'
+    // )
+    return (
+      (item.meta?.hidden || false) != true &&
+      !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(
+        item.path
+      )
+    );
+  });
+}
+
+export const withInstall = <T>(component: T, alias?: string) => {
+  const comp = component as any;
+  comp.install = (app: App) => {
+    app.component(comp.name || comp.displayName, component as any);
+    if (alias) {
+      app.config.globalProperties[alias] = component;
+    }
+  };
+  return component as T & Plugin;
+};
+
+/**
+ *  找到对应的节点
+ * */
+let result = null as any;
+export function getTreeItem(data: any[], key?: string | number): any {
+  data.map(item => {
+    if (item.key === key) {
+      result = item;
+    } else {
+      if (item.children && item.children.length) {
+        getTreeItem(item.children, key);
+      }
+    }
+  });
+  return result;
+}
+
+/**
+ *  找到所有节点
+ * */
+const treeAll: any[] = [];
+export function getTreeAll(data: any[]): any[] {
+  data.map(item => {
+    treeAll.push(item.key);
+    if (item.children && item.children.length) {
+      getTreeAll(item.children);
+    }
+  });
+  return treeAll;
+}
+
+export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
+  let key: string;
+  for (key in target) {
+    src[key] = isObject(src[key])
+      ? deepMerge(src[key], target[key])
+      : (src[key] = target[key]);
+  }
+  return src;
+}
+
+/**
+ * Sums the passed percentage to the R, G or B of a HEX color
+ * @param {string} color The color to change
+ * @param {number} amount The amount to change the color by
+ * @returns {string} The processed part of the color
+ */
+function addLight(color: string, amount: number) {
+  const cc = parseInt(color, 16) + amount;
+  const c = cc > 255 ? 255 : cc;
+  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
+}
+
+/**
+ * Lightens a 6 char HEX color according to the passed percentage
+ * @param {string} color The color to change
+ * @param {number} amount The amount to change the color by
+ * @returns {string} The processed color represented as HEX
+ */
+export function lighten(color: string, amount: number) {
+  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
+  amount = Math.trunc((255 * amount) / 100);
+  return `#${addLight(color.substring(0, 2), amount)}${addLight(
+    color.substring(2, 4),
+    amount
+  )}${addLight(color.substring(4, 6), amount)}`;
+}
+
+/**
+ * 判断是否 url
+ * */
+export function isUrl(url: string) {
+  return /^(http|https):\/\//g.test(url);
+}
+
+/** 递归清除空数据 */
+export function clearEmtryData(list: any[], key: string) {
+  for (let i = 0; i < list.length; i++) {
+    if (Array.isArray(list[i][key]) && !list[i][key].length) {
+      list[i][key] = '';
+    } else {
+      list[i][key] = clearEmtryData(list[i][key], key);
+    }
+  }
+  return list;
+}
+
+// 秒转分
+export const getSecondRPM = (second: number, type?: string) => {
+  if (isNaN(second)) return '00:00';
+  const mm = Math.floor(second / 60)
+    .toString()
+    .padStart(2, '0');
+  const dd = Math.floor(second % 60)
+    .toString()
+    .padStart(2, '0');
+  if (type === 'cn') {
+    return mm + '分' + dd + '秒';
+  } else {
+    return mm + ':' + dd;
+  }
+};
+
+// 秒转分
+export const getSecond = (second: number, type?: string) => {
+  if (isNaN(second)) return '0000';
+  const mm = Math.floor(second / 60)
+    .toString()
+    .padStart(2, '0');
+  const dd = Math.floor(second % 60)
+    .toString()
+    .padStart(2, '0');
+  return `${mm}${dd}`;
+};
+
+/** 滚动到表单填写错误的地方 */
+export function scrollToErrorForm() {
+  const isError =
+    document.querySelector('.n-input--error-status') ||
+    document.querySelector('.n-base-selection--error-status');
+  isError?.scrollIntoView({
+    block: 'center',
+    behavior: 'smooth'
+  });
+}
+
+export const getTimes = (
+  times: any,
+  keys: Array<string> = [],
+  format = 'YYYY-MM-DD'
+) => {
+  if (times && times.length) {
+    return format == 'YYYY-MM-DD'
+      ? {
+        [keys[0] || 'start']: dayjs(times[0]).isValid()
+          ? dayjs(times[0]).format(format) + ' 00:00:00'
+          : '',
+        [keys[1] || 'end']: dayjs(times[1]).isValid()
+          ? dayjs(times[1]).format(format) + ' 23:59:59'
+          : ''
+      }
+      : {
+        [keys[0] || 'start']: dayjs(times[0]).isValid()
+          ? dayjs(times[0]).format(format)
+          : '',
+        [keys[1] || 'end']: dayjs(times[1]).isValid()
+          ? dayjs(times[1]).format(format)
+          : ''
+      };
+  }
+  return {};
+};
+
+export const px2vw = (px: number): string => `${(px / 1920) * 100}vw`;
+
+export const px2vwH = (px: number): string =>
+  `${(((px / 1920) * 1920) / 1188) * 100}vw`;
+
+export const fscreen = () => {
+  const el = document.documentElement;
+
+  //进入全屏
+  (el.requestFullscreen && el.requestFullscreen()) ||
+    (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
+    (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
+    (el.msRequestFullscreen && el.msRequestFullscreen());
+};
+
+//退出全屏
+export const exitFullscreen = () => {
+  document.exitFullscreen
+    ? document.exitFullscreen()
+    : document.mozCancelFullScreen
+      ? document.mozCancelFullScreen()
+      : document.webkitExitFullscreen
+        ? document.webkitExitFullscreen()
+        : '';
+};
+
+/** 检测链接格式 */
+export function checkUrlType(urlType: string) {
+  const subfix = (urlType || '').split('.').pop();
+  if (subfix === 'wav' || subfix === 'mp3' || subfix === 'm4a') {
+    return 'audio';
+  }
+  return 'video';
+}
+
+const instruments: any = {
+  'Acoustic Grand Piano': '大钢琴',
+  'Bright Acoustic Piano': '明亮的钢琴',
+  'Electric Grand Piano': '电钢琴',
+  'Rhodes Piano': '柔和的电钢琴',
+  'Chorused Piano': '加合唱效果的电钢琴',
+  Harpsichord: '羽管键琴',
+  Clavichord: '科拉维科特琴',
+  Celesta: '钢片琴',
+  Glockenspiel: '钢片琴',
+  'Music box': '八音盒',
+  Vibraphone: '颤音琴',
+  Marimba: '马林巴',
+  Xylophone: '木琴',
+  'Tubular Bells': '管钟',
+  Dulcimer: '大扬琴',
+  'Hammond Organ': '击杆风琴',
+  'Percussive Organ': '打击式风琴',
+  'Rock Organ': '摇滚风琴',
+  'Church Organ': '教堂风琴',
+  'Reed Organ': '簧管风琴',
+  Accordian: '手风琴',
+  Harmonica: '口琴',
+  'Tango Accordian': '探戈手风琴',
+  'Acoustic Guitar': '钢弦吉他',
+  'Electric Guitar': '闷音电吉他',
+  'Overdriven Guitar': '加驱动效果的电吉他',
+  'Distortion Guitar': '加失真效果的电吉他',
+  'Guitar Harmonics': '吉他和音',
+  'Acoustic Bass': '大贝司',
+  'Electric Bass': '电贝司',
+  'Fretless Bass': '无品贝司',
+  'Slap Bass': '掌击',
+  'Synth Bass': '电子合成',
+  Violin: '小提琴',
+  Viola: '中提琴',
+  Cello: '大提琴',
+  Contrabass: '低音大提琴',
+  'Tremolo Strings': '弦乐群颤音音色',
+  'Pizzicato Strings': '弦乐群拨弦音色',
+  'Orchestral Harp': '竖琴',
+  Timpani: '定音鼓',
+  'String Ensemble': '弦乐合奏音色',
+  'Synth Strings': '合成弦乐合奏音色',
+  'Choir Aahs': '人声合唱',
+  'Voice Oohs': '人声',
+  'Synth Voice': '合成人声',
+  'Orchestra Hit': '管弦乐敲击齐奏',
+  Trumpet: '小号',
+  Trombone: '长号',
+  Tuba: '大号',
+  'Muted Trumpet': '加弱音器小号',
+  'French Horn': '法国号',
+  'Brass Section': '铜管组',
+  'Synth Brass': '合成铜管音色',
+  'Soprano Sax': '高音萨克斯管',
+  'Alto Sax': '中音萨克斯管',
+  'Tenor Sax': '次中音萨克斯管',
+  'Baritone Sax': '低音萨克斯管',
+  Oboe: '双簧管',
+  'English Horn': '英国管',
+  Bassoon: '巴松',
+  Clarinet: '单簧管',
+  'Soprano Saxophone': '高音萨克斯管',
+  'Alto Saxophone': '中音萨克斯管',
+  'Tenor Saxophone': '次中音萨克斯管',
+  'Baritone Saxophone': '低音萨克斯管',
+  Piccolo: '短笛',
+  Flute: '长笛',
+  Recorder: '竖笛',
+  'Soprano Recorder': '高音竖笛',
+  'Pan Flute': '排箫',
+  'Bottle Blow': '瓶木管',
+  Whistle: '口哨声',
+  Ocarina: '陶笛',
+  Lead: '合成主音',
+  'Lead lead': '合成主音',
+  'Pad age': '合成音色',
+  Pad: '合成音色',
+  FX: '合成效果  科幻',
+  Sitar: '西塔尔',
+  Banjo: '班卓琴',
+  Shamisen: '三昧线',
+  Koto: '十三弦筝',
+  Kalimba: '卡林巴',
+  Bagpipe: '风笛',
+  Fiddle: '民族提琴',
+  Shanai: '山奈',
+  'Tinkle Bell': '叮当铃',
+  Agogos: '阿戈戈铃',
+  'Steel Drums': '钢鼓',
+  'Taiko Drum': '太鼓',
+  'Melodic Toms': '嗵嗵鼓',
+  'Synth Drums': '合成鼓',
+  'Reverse Cymbals': '反向镲',
+  'Agogo Bells': '阿戈戈铃',
+  'Taiko Drums': '太鼓',
+  Bongos: '邦戈鼓',
+  'Bongo Bell': '邦戈铃',
+  Congas: '康加鼓',
+  Guiro: '刮壶',
+  'Guitar Fret Noise': '吉他换把杂音',
+  'Breath Noise': '呼吸声',
+  Seashore: '海浪声',
+  'Bird Tweet': '鸟鸣',
+  'Telephone Ring': '电话铃',
+  Helicopter: '直升机',
+  Applause: '鼓掌声',
+  Gunshot: '枪声',
+  'Acoustic Bass Drum': '大鼓',
+  'Bass Drum': '大鼓',
+  'Side Drum': '小鼓鼓边',
+  'Acoustic Snare': '小鼓',
+  'Hand Claps': '拍手',
+  'Electric Snare': '小鼓',
+  'Low Floor Tom': '低音嗵鼓',
+  'Closed Hi-Hat': '闭合踩镲',
+  'High Floor Tom': '高音落地嗵鼓',
+  'Pedal Hi-Hat': '脚踏踩镲',
+  'Low Tom': '低音嗵鼓',
+  'Open Hi-Hat': '开音踩镲',
+  'Low-Mid Tom': '中低音嗵鼓',
+  'Hi Mid Tom': '高音鼓',
+  'Crash Cymbals': '对镲',
+  'High Tom': '高音嗵鼓',
+  'Ride Cymbals': '叮叮镲',
+  'Chinese Cymbals': '中国镲',
+  'Ride Bell': '圆铃',
+  Tambourine: '铃鼓',
+  'Splash Cymbal': '溅音镲',
+  Cowbell: '牛铃',
+  'Crash Cymbal': '强音钹',
+  'Vibra-Slap': '颤音器',
+  'Ride Cymbal': '打点钹',
+  'Hi Bongo': '高音邦戈鼓',
+  'Low Bongo': '低音邦戈鼓',
+  'Mute Hi Conga': '弱音高音康加鼓',
+  'Open Hi Conga': '强音高音康加鼓',
+  'Low Conga': '低音康加鼓',
+  'High Timbale': '高音天巴鼓',
+  'Low Timbale': '低音天巴鼓',
+  'High Agogo': '高音阿戈戈铃',
+  'Low Agogo': '低音阿戈戈铃',
+  Cabasa: '卡巴萨',
+  Maracas: '沙锤',
+  'Short Whistle': '短口哨',
+  'Long Whistle': '长口哨',
+  'Short Guiro': '短刮壶',
+  'Long Guiro': '长刮壶',
+  Claves: '响棒',
+  'Hi Wood Block': '高音木鱼',
+  'Low Wood Block': '低音木鱼',
+  'Mute Triangle': '弱音三角铁',
+  'Open Triangle': '强音三角铁',
+  'Drum Set': '架子鼓',
+  'Hulusi flute': '葫芦丝',
+  Melodica: '口风琴',
+  Nai: '口风琴',
+  'Snare Drum': '小军鼓',
+  Cymbal: '镲',
+  Cymbals: '镲',
+  'Horn in F': '圆号',
+  Triangle: '三角铁',
+  Vibrato: '颤音琴',
+  'Suspend Cymbals': '吊镲',
+  'Suspended Cymbals': '吊镲',
+  'Tom-Toms': '嗵嗵鼓',
+  Bell: '铃铛',
+  Bells: '铃铛',
+  'Alto Clarinet': '中音单簧管',
+  'Bass Clarinet': '低音单簧管',
+  Cornet: '短号',
+  Euphonium: '上低音号',
+  'crash cymbals': '对镲',
+  Castanets: '响板',
+  Shaker: '沙锤',
+  'Mark tree': '音树',
+  Chimes: '管钟',
+  'Mark Tree': '音树',
+  'Tom-toms': '嗵嗵鼓',
+  'Hi-Hat': '踩镲',
+  'Sleigh Bells': '雪橇铃',
+  Flexatone: '弹音器',
+  'Brake drum': '闸鼓',
+  Gong: '锣',
+  'concert tom': '音乐会嗵嗵鼓',
+  'brake drum': '车轮鼓',
+  'finger cymbal': '指钹',
+  'ride cymbal': '叮叮镲',
+  'Concert Toms': '音乐会嗵嗵鼓',
+  Vibraslap: '弹音器',
+  'Wood Blocks': '木鱼',
+  'Temple Blocks': '木鱼',
+  'Wood Block': '木鱼',
+  'Field Drum': '军鼓',
+  'Quad-Toms': '筒鼓',
+  Quads: '筒鼓',
+  'Drums set': '架子鼓',
+  'High Bongo': '邦戈',
+  Timbales: '天巴鼓'
+};
+
+/** 获取分轨名称 */
+export const getInstrumentName = (name = '') => {
+  name = name.toLocaleLowerCase().replace(/ /g, '');
+  if (!name) return '';
+  for (const key in instruments) {
+    const _key = key.toLocaleLowerCase().replace(/ /g, '');
+    if (_key.includes(name)) {
+      return instruments[key];
+    }
+  }
+  for (const key in instruments) {
+    const _key = key.toLocaleLowerCase().replace(/ /g, '');
+    if (name.includes(_key)) {
+      return instruments[key];
+    }
+  }
+  return '';
+};
+
+/**
+ * 乐器排序
+ * 排序顺序:长笛、单簧管、中音单簧管、低音单簧管、高音萨克斯风、中音萨克斯风、次中音萨克斯风、低音萨克斯风、小号、长号、圆号、大号、上低音号
+ * */
+export const sortMusical = (name: string, index: number) => {
+  let sortId = 0;
+  switch (name) {
+    case '长笛':
+      sortId = 1;
+      break;
+    case '单簧管':
+      sortId = 2;
+      break;
+    case '中音单簧管':
+      sortId = 3;
+      break;
+    case '低音单簧管':
+      sortId = 4;
+      break;
+    case '高音萨克斯风':
+      sortId = 5;
+      break;
+    case '中音萨克斯风':
+      sortId = 6;
+      break;
+    case '次中音萨克斯风':
+      sortId = 7;
+      break;
+    case '低音萨克斯风':
+      sortId = 8;
+      break;
+    case '小号':
+      sortId = 9;
+      break;
+    case '长号':
+      sortId = 10;
+      break;
+    case '圆号':
+      sortId = 11;
+      break;
+    case '大号':
+      sortId = 12;
+      break;
+    case '上低音号':
+      sortId = 13;
+      break;
+    default:
+      sortId = index + 14;
+      break;
+  }
+  return sortId;
+};
+
+// 课堂乐器声轨名称集合
+const trackNames: any = {
+  Piccolo: 'Tenor Recorder',
+  flute: 'Flute',
+  Flute: 'Flute',
+  'Flute 1': 'Flute',
+  'Flute 2': 'Flute',
+  Oboe: 'Clarinet',
+  oboe: 'Clarinet',
+  clarinet: 'Clarinet',
+  'Clarinet in Bb': 'Clarinet',
+  'Clarinet in Bb 1': 'Clarinet',
+  'Clarinet in Bb 2': 'Clarinet',
+  'Alto Clarinet in Eb': 'Clarinet',
+  'Bass Clarinet in Bb': 'Clarinet',
+  Bassoon: 'Bassoon',
+  'Alto Saxophone': 'Alto Saxophone',
+  'Tenor Saxophone': 'Alto Saxophone',
+  'Baritone Saxophone': 'Alto Saxophone',
+  altosaxophone: 'Alto Saxophone',
+  tenorsaxophone: 'Alto Saxophone',
+  saxophone: 'Alto Saxophone',
+  'Trumpet in Bb 1': 'Trumpet',
+  'Trumpet in Bb 2': 'Trumpet',
+  trumpet: 'Trumpet',
+  'Horn in F': 'Horn',
+  'Horn in F 1': 'Horn',
+  'Horn in F 2': 'Horn',
+  horn: 'Horn',
+  trombone: 'Trombone',
+  'Trombone 1': 'Trombone',
+  'Trombone 2': 'Trombone',
+  'Trombone 3': 'Trombone',
+  Euphonium: 'Baritone',
+  upbasshorn: 'Baritone',
+  Tuba: 'Tuba',
+  tuba: 'Tuba',
+  Chimes: 'Chimes',
+  Bells: 'Bells',
+  Xylophone: 'Xylophone',
+  'Snare Drum': 'Snare Drum',
+  'Bass Drum': 'Bass Drum',
+  Triangle: 'Triangle',
+  'Suspended Cymbal': 'Suspended Cymbal',
+  'Crash Cymbals': 'Crash Cymbals',
+  'Concert Toms': 'Concert Toms',
+  Timpani: 'Timpani',
+  'Drum Set': 'Drum Set',
+  Marimba: 'Marimba',
+  Vibraphone: 'Vibraphone',
+  'Tubular Bells': 'Tubular Bells',
+  Mallets: 'Mallets',
+  recorder: 'Piccolo',
+  tenorrecorder: 'piccolo',
+  melodica: 'melodica',
+  hulusiFlute: 'hulusiFlute',
+  panflute: 'panflute',
+  ukulele: 'ukulele',
+  mouthorgan: 'mouthorgan',
+  piano: 'piano',
+  woodwind: 'Woodwind',
+  panpipes: 'Panpipes',
+  ocarina: 'Ocarina',
+  nai: 'Nai',
+  BaroqueRecorder: 'Baroque Recorder'
+};
+
+/** 声轨track转换成乐器code */
+export const trackToCode = (track: any) => {
+  return trackNames[track] || track;
+};
+export const iframeDislableKeyboard = (iframeDom: any) => {
+  // 在 iframe 内部注入脚本禁用右键菜单
+  const script = document.createElement('script');
+  script.innerHTML = `
+      document.addEventListener('contextmenu', function(e) {
+          e.preventDefault();
+      });
+
+      document.addEventListener('keydown', function (event) {
+        // 屏蔽 F12 和 Ctrl+Shift+I
+        if (
+          event.key === 'F12' ||
+          (event.ctrlKey && event.shiftKey && event.key === 'I') ||
+          (event.metaKey && event.altKey && event.key === 'I')
+        ) {
+          event.preventDefault();
+        }
+      });
+            `;
+  if (iframeDom.contentWindow.document.body) {
+    iframeDom?.contentDocument?.body.appendChild(script);
+  }
+};

+ 49 - 10
src/views/attend-class/model/train-update/index.tsx

@@ -1,4 +1,11 @@
-import { PropType, defineComponent, onMounted, reactive, ref } from 'vue';
+import {
+  PropType,
+  computed,
+  defineComponent,
+  onMounted,
+  reactive,
+  ref
+} from 'vue';
 import styles from './index.module.less';
 import {
   NButton,
@@ -8,6 +15,7 @@ import {
   NInputGroupLabel,
   NInputNumber,
   NSpace,
+  NTooltip,
   useMessage
 } from 'naive-ui';
 import {
@@ -102,8 +110,25 @@ export default defineComponent({
       });
     };
 
+    // 是否可以评测
+    const isDisabledEvaluated = computed(() => {
+      const item = props.item;
+      if (item.background && item.background.length > 0) {
+        let status = false;
+        item.background.forEach((item: any) => {
+          if (!item.audioFileUrl) {
+            status = true;
+          }
+        });
+        return status;
+      } else {
+        return true;
+      }
+    });
+
     onMounted(() => {
       const item = props.item;
+      console.log(item, 'item');
       if (item.trainId) {
         forms.id = item.trainId;
         forms.practiceSpeed = item.practiceSpeed;
@@ -149,15 +174,29 @@ export default defineComponent({
                 onClick={() => (forms.type = 'PRACTICE')}>
                 练习
               </NButton>
-              <NButton
-                secondary
-                class={[
-                  styles.switch,
-                  forms.type === 'EVALUATION' ? styles.active : ''
-                ]}
-                onClick={() => (forms.type = 'EVALUATION')}>
-                评测
-              </NButton>
+
+              {isDisabledEvaluated.value ? (
+                <NTooltip showArrow={false}>
+                  {{
+                    trigger: () => (
+                      <NButton disabled secondary class={[styles.switch]}>
+                        评测
+                      </NButton>
+                    ),
+                    default: () => '该曲目暂不支持评测'
+                  }}
+                </NTooltip>
+              ) : (
+                <NButton
+                  secondary
+                  class={[
+                    styles.switch,
+                    forms.type === 'EVALUATION' ? styles.active : ''
+                  ]}
+                  onClick={() => (forms.type = 'EVALUATION')}>
+                  评测
+                </NButton>
+              )}
             </NSpace>
           </NFormItem>
           <div class={styles.scoreGroup}>

+ 247 - 77
src/views/classList/components/afterWorkDetail.tsx

@@ -1,5 +1,5 @@
 import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
-import styles from '../index.module.less';
+import styles from './afterWorkDetail.module.less';
 import {
   NButton,
   NDataTable,
@@ -7,6 +7,7 @@ import {
   NFormItem,
   NImage,
   NModal,
+  NProgress,
   NSelect,
   NSpace
 } from 'naive-ui';
@@ -14,47 +15,48 @@ import SearchInput from '@/components/searchInput';
 import CSelect from '@/components/CSelect';
 import Pagination from '@/components/pagination';
 import { getWorkDetail, getTrainingStudentList } from '../api';
-import add from './images/add.png';
+// import add from './images/add.png';
 import { useRoute } from 'vue-router';
 import CBreadcrumb from '/src/components/CBreadcrumb';
-import CDatePicker from '/src/components/CDatePicker';
+// import CDatePicker from '/src/components/CDatePicker';
 import defultHeade from '@/components/layout/images/teacherIcon.png';
-import {
-  getNowDateAndMonday,
-  getNowDateAndSunday,
-  getTimes
-} from '/src/utils/dateFormat';
+// import {
+//   getNowDateAndMonday,
+//   getNowDateAndSunday,
+//   getTimes
+// } from '/src/utils/dateFormat';
 import { trainingStatusArray } from '@/utils/searchArray';
 import TrainingDetails from '../modals/TrainingDetails';
 import dayjs from 'dayjs';
-import { lookup } from 'dns';
 import TheEmpty from '/src/components/TheEmpty';
+import { evaluateDifficult } from '/src/utils/contants';
 export default defineComponent({
   name: 'student-studentList',
-  setup(props, { emit }) {
+  setup() {
     const state = reactive({
-      searchForm: { keyword: '', trainingStatus: '' as any },
+      searchForm: {
+        keyword: '',
+        vipFlag: null as any,
+        trainingStatus: '' as any
+        // classGroupId: '' as any
+      },
       loading: false,
       pagination: {
         page: 1,
         rows: 10,
         pageTotal: 4
       },
+      studentClassList: [] as any,
       tableList: [] as any,
-      workInfo: {
-        createTime: '',
-        expireDate: '',
-        teacherAvatar: '',
-        teacherName: ''
-      },
+      workInfo: {} as any,
       detailVisiable: false,
       activeRow: null as any,
       index: 0
     });
-    const timer = ref<[number, number]>([
-      getNowDateAndMonday(new Date().getTime()),
-      getNowDateAndSunday(new Date().getTime())
-    ]);
+    // const timer = ref<[number, number]>([
+    //   getNowDateAndMonday(new Date().getTime()),
+    //   getNowDateAndSunday(new Date().getTime())
+    // ]);
     const TrainingDetailsRef = ref();
     const route = useRoute();
     const routerList = ref([
@@ -70,18 +72,22 @@ export default defineComponent({
     };
 
     const onReset = () => {
-      state.searchForm = { keyword: '', trainingStatus: '' as any };
-      timer.value = [
-        getNowDateAndMonday(new Date().getTime()),
-        getNowDateAndSunday(new Date().getTime())
-      ];
+      state.searchForm = {
+        keyword: '',
+        trainingStatus: '' as any,
+        vipFlag: null
+      };
+      // timer.value = [
+      //   getNowDateAndMonday(new Date().getTime()),
+      //   getNowDateAndSunday(new Date().getTime())
+      // ];
       search();
     };
     const getList = async (type?: string, page?: number) => {
       state.loading = true;
       try {
         const res = await getTrainingStudentList({
-          classGroupId: route.query.classGroupId || '',
+          classGroupId: (route.query.classGroupId as any) || '',
           trainingId: route.query.trainingId,
           ...state.searchForm,
           ...state.pagination,
@@ -109,7 +115,56 @@ export default defineComponent({
     const getWorkInfo = async () => {
       try {
         const res = await getWorkDetail({ trainingId: route.query.trainingId });
-        state.workInfo = { ...res.data };
+        // state.workInfo = { ...res.data };
+        const result = res.data || {};
+        let pTitle = '';
+        let eTitle = '';
+        if (
+          result.studentLessonTrainingDetails &&
+          result.studentLessonTrainingDetails.length > 0
+        ) {
+          result.studentLessonTrainingDetails.forEach((child: any) => {
+            // if (child.trainingType === 'PRACTICE' && child.musicName) {
+            //   pTitle += pTitle ? '、' + child.musicName : child.musicName;
+            // }
+            // if (child.trainingType === 'EVALUATION' && child.musicName) {
+            //   eTitle += eTitle ? '、' + child.musicName : child.musicName;
+            // }
+            const trainingContent = child.trainingContent
+              ? JSON.parse(child.trainingContent)
+              : null;
+
+            if (child.trainingType === 'PRACTICE' && child.musicName) {
+              pTitle += '《' + child.musicName + '》';
+
+              if (trainingContent) {
+                const tempList = [
+                  `${trainingContent.practiceChapterBegin}-${trainingContent.practiceChapterEnd}小节`,
+                  `速度${trainingContent.practiceSpeed}`,
+                  `${trainingContent.trainingTimes}分钟`
+                ];
+                pTitle += tempList.join(' | ') + ';';
+              }
+            }
+            if (child.trainingType === 'EVALUATION' && child.musicName) {
+              eTitle += '《' + child.musicName + '》';
+              if (trainingContent) {
+                const tempList = [
+                  `${evaluateDifficult[trainingContent.evaluateDifficult]}`,
+                  trainingContent.practiceChapterBegin ||
+                  trainingContent.practiceChapterEnd
+                    ? `${trainingContent.practiceChapterBegin}-${trainingContent.practiceChapterEnd}小节`
+                    : '全部小节',
+                  `${trainingContent.trainingTimes}分合格`
+                ];
+                eTitle += tempList.join(' | ') + ';';
+              }
+            }
+          });
+        }
+        result.pTitle = pTitle;
+        result.eTitle = eTitle;
+        state.workInfo = result;
       } catch (e) {
         console.log(e);
       }
@@ -139,9 +194,13 @@ export default defineComponent({
               : '--';
           }
         },
+        // {
+        //   title: '所属班级',
+        //   key: 'classGroupName'
+        // },
         {
           title: '作业状态',
-          key: 'sex',
+          key: 'trainingStatus',
           render(row: any) {
             return (
               <div>
@@ -159,6 +218,13 @@ export default defineComponent({
           }
         },
         {
+          title: '是否会员',
+          key: 'vipFlag',
+          render(row: any) {
+            return row.vipFlag ? '是' : '否';
+          }
+        },
+        {
           title: '操作',
           key: 'id',
           render(row: any, index: number) {
@@ -207,36 +273,129 @@ export default defineComponent({
       <div>
         <CBreadcrumb list={routerList.value}></CBreadcrumb>
         <div class={styles.listWrap}>
-          <div class={styles.teacherList}>
-            <div class={styles.teacherHeader}>
-              <div class={styles.teacherHeaderBorder}>
-                <NImage
-                  class={styles.teacherHeaderImg}
-                  src={
-                    state.workInfo.teacherAvatar
-                      ? state.workInfo.teacherAvatar
-                      : defultHeade
-                  }
-                  previewDisabled></NImage>
+          <div class={styles.teacherSection}>
+            <div class={styles.teacherList}>
+              <div class={styles.tTemp}>
+                <div class={styles.teacherHeader}>
+                  <div class={styles.teacherHeaderBorder}>
+                    <NImage
+                      class={styles.teacherHeaderImg}
+                      src={state.workInfo.teacherAvatar || defultHeade}
+                      previewDisabled></NImage>
+                  </div>
+                </div>
+                <div class={styles.workafterInfo}>
+                  <h4>{state.workInfo.teacherName}</h4>
+                  {state.workInfo.createTime && (
+                    <p>
+                      布置时间:
+                      {state.workInfo.createTime &&
+                        dayjs(state.workInfo.createTime).format(
+                          'YYYY-MM-DD HH:mm'
+                        )}{' '}
+                      |{' '}
+                      <span>
+                        截止时间:
+                        {state.workInfo.expireDate &&
+                          dayjs(state.workInfo.expireDate).format(
+                            'YYYY-MM-DD HH:mm'
+                          )}
+                      </span>
+                    </p>
+                  )}
+                </div>
+              </div>
+              <div class={styles.infos}>
+                <div class={styles.homeTitle}>{state.workInfo.name}</div>
+                <div class={[styles.homeContent, styles.homeworkText]}>
+                  <div class={styles.pSection}>
+                    {state.workInfo.pTitle && (
+                      <p class={[styles.text, styles.p1]}>
+                        <div>
+                          <span>练习曲目:</span>
+                          <p>{state.workInfo.pTitle}</p>
+                        </div>
+                      </p>
+                    )}
+                    {state.workInfo.eTitle && (
+                      <p class={[styles.text, styles.p2]}>
+                        <div>
+                          <span>评测曲目:</span>
+                          <p>{state.workInfo.eTitle}</p>
+                        </div>
+                      </p>
+                    )}
+                  </div>
+                </div>
               </div>
             </div>
-            <div class={styles.workafterInfo}>
-              <h4>{state.workInfo.teacherName}</h4>
-              <p>
-                布置时间:
-                {state.workInfo.createTime
-                  ? dayjs(state.workInfo.createTime).format('YYYY-MM-DD HH:mm')
-                  : '--'}{' '}
-                |{' '}
-                <span>
-                  截止时间:
-                  {state.workInfo.expireDate
-                    ? dayjs(state.workInfo.expireDate).format(
-                        'YYYY-MM-DD HH:mm'
-                      )
-                    : '--'}
-                </span>
-              </p>
+            <div>
+              <div class={styles.stitcTitle}>作业完成情况</div>
+              <div class={styles.stitcConent}>
+                <NSpace size={[38, 0]}>
+                  <NProgress
+                    percentage={state.workInfo.trainingRate || 0}
+                    // percentage={20}
+                    offset-degree={180}
+                    type="circle"
+                    strokeWidth={6}
+                    rail-color={'EDEFFA'}
+                    color={'#64A5FF'}>
+                    <div class={styles.contentRect}>
+                      <div class={styles.nums}>
+                        {state.workInfo.trainingNum || 0}
+                        <i>/</i>
+                        {state.workInfo.expectNum || 0}
+                        <span>人</span>
+                      </div>
+                      <div class={styles.text}>已提交</div>
+                    </div>
+                  </NProgress>
+                  <NProgress
+                    percentage={state.workInfo.trainingRate || 0}
+                    offset-degree={180}
+                    strokeWidth={6}
+                    type="circle"
+                    rail-color={'EDEFFA'}
+                    color={'#64A5FF'}>
+                    <div class={styles.contentRect}>
+                      <div class={styles.nums}>
+                        {state.workInfo.trainingRate || 0}%
+                      </div>
+                      <div class={styles.text}>提交率</div>
+                    </div>
+                  </NProgress>
+                  <NProgress
+                    percentage={state.workInfo.qualifiedRate || 0}
+                    offset-degree={180}
+                    strokeWidth={6}
+                    type="circle"
+                    rail-color={'EDEFFA'}
+                    color={'#40CEAE'}>
+                    <div class={styles.contentRect}>
+                      <div class={styles.nums}>
+                        {state.workInfo.standardNum || 0}
+                        <span>人</span>
+                      </div>
+                      <div class={styles.text}>合格人数</div>
+                    </div>
+                  </NProgress>
+                  <NProgress
+                    percentage={state.workInfo.qualifiedRate || 0}
+                    offset-degree={180}
+                    strokeWidth={6}
+                    type="circle"
+                    rail-color={'EDEFFA'}
+                    color={'#40CEAE'}>
+                    <div class={styles.contentRect}>
+                      <div class={styles.nums}>
+                        {state.workInfo.qualifiedRate || 0}%
+                      </div>
+                      <div class={styles.text}>合格率</div>
+                    </div>
+                  </NProgress>
+                </NSpace>
+              </div>
             </div>
           </div>
           <div class={styles.searchList}>
@@ -251,6 +410,22 @@ export default defineComponent({
                   }></SearchInput>
               </NFormItem>
 
+              {/* <NFormItem>
+                <CSelect
+                  {...({
+                    options: [
+                      {
+                        label: '全部班级',
+                        value: ''
+                      },
+                      ...state.studentClassList
+                    ],
+                    placeholder: '全部班级',
+                    clearable: true,
+                    inline: true
+                  } as any)}
+                  v-model:value={state.searchForm.classGroupId}></CSelect>
+              </NFormItem> */}
               <NFormItem>
                 <CSelect
                   {...({
@@ -267,13 +442,20 @@ export default defineComponent({
                   } as any)}
                   v-model:value={state.searchForm.trainingStatus}></CSelect>
               </NFormItem>
-              {/* <NFormItem>
-                <CDatePicker
-                  v-model:value={timer.value}
-                  separator={'至'}
-                  type="daterange"
-                  timerValue={timer.value}></CDatePicker>
-              </NFormItem> */}
+
+              <NFormItem>
+                <CSelect
+                  {...({
+                    options: [
+                      { label: '是', value: true },
+                      { label: '否', value: false }
+                    ],
+                    placeholder: '是否会员',
+                    clearable: true,
+                    inline: true
+                  } as any)}
+                  v-model:value={state.searchForm.vipFlag}></CSelect>
+              </NFormItem>
 
               <NFormItem>
                 <NSpace justify="end">
@@ -291,18 +473,6 @@ export default defineComponent({
               </NFormItem>
             </NForm>
           </div>
-          {/* <NButton
-          class={styles.addBtn}
-          type="primary"
-          v-slots={{
-            icon: () => (
-              <>
-                <NImage class={styles.addBtnIcon} src={add}></NImage>
-              </>
-            )
-          }}>
-          新增学生
-        </NButton> */}
           <div class={styles.tableWrap}>
             <NDataTable
               v-slots={{
@@ -317,7 +487,7 @@ export default defineComponent({
               v-model:pageSize={state.pagination.rows}
               v-model:pageTotal={state.pagination.pageTotal}
               onList={getList}
-              sync
+              // sync
             />
           </div>
         </div>

+ 1 - 0
src/views/natural-resources/components/my-collect/index.tsx

@@ -64,6 +64,7 @@ export default defineComponent({
             refFlag: row.refFlag,
             content: row.content,
             subjectId: row.subjectIds,
+            background: row.background,
             enableFlag: row.enableFlag ? 1 : 0,
             openFlag: row.openFlag
           });

+ 477 - 476
src/views/natural-resources/components/my-resources/index.tsx

@@ -1,476 +1,477 @@
-import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
-import styles from './index.module.less';
-import CardType from '/src/components/card-type';
-import Pagination from '/src/components/pagination';
-import SearchGroupResources from './search-group-resources';
-import {
-  favorite,
-  materialQueryPage,
-  materialRemove,
-  materialRemoveAll,
-  materialRemoveMusic,
-  materialUpdateAll
-} from '../../api';
-import {
-  NButton,
-  NModal,
-  NSpace,
-  NSpin,
-  useDialog,
-  useMessage
-} from 'naive-ui';
-import TheEmpty from '/src/components/TheEmpty';
-import UploadModal, { formatUrlType } from './upload-modal';
-import CardPreview from '@/components/card-preview';
-import resourceDefault from '../../images/resource-default.png';
-import resourceChecked from '../../images/resource-checked.png';
-import MyResourcesGuide from '@/custom-plugins/guide-page/myResources-guide';
-import SaveModal from './save-modal';
-import deepClone from '/src/helpers/deep-clone';
-import UploadCover from './upload-cover';
-export default defineComponent({
-  name: 'share-resources',
-  setup() {
-    const message = useMessage();
-    const dialog = useDialog();
-    const state = reactive({
-      searchWord: '',
-      loading: false,
-      pageTotal: 0,
-      pagination: {
-        page: 1,
-        rows: 20
-      },
-      searchGroup: {
-        type: 'MUSIC', //
-        name: '',
-        bookVersionId: null,
-        subjectId: null,
-        sourceType: 3
-      },
-      tableList: [] as any,
-      uploadStatus: false,
-      saveStatus: false,
-      show: false,
-      item: {} as any,
-      editStatus: false, // 是否编辑
-      isAdd: false,
-      editList: [] as any, // TOD
-      editIds: [] as any, // 编辑的
-      editOverIds: [] as any, // 确认修改的数据
-      removeVisiable: false,
-      removeContent: '是否删除该资源?',
-      type: 'remove',
-      removeItem: {} as any
-    });
-    const showGuide = ref(false);
-    const getList = async () => {
-      try {
-        state.loading = true;
-        const { data } = await materialQueryPage({
-          ...state.searchGroup,
-          ...state.pagination
-        });
-        state.loading = false;
-        state.pageTotal = Number(data.total);
-        const tempRows = data.rows || [];
-        const temp: any = [];
-        tempRows.forEach((row: any) => {
-          temp.push({
-            id: row.id,
-            coverImg: row.coverImg,
-            type: row.type,
-            title: row.name,
-            isCollect: !!row.favoriteFlag,
-            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
-            refFlag: row.refFlag,
-            content: row.content,
-            // subjectId: row.subjectIds,
-            instrumentIds: row.instrumentIds,
-            sourceFrom: row.sourceFrom,
-            enableFlag: row.enableFlag ? 1 : 0,
-            openFlag: row.openFlag
-          });
-        });
-        state.tableList = temp || [];
-        setTimeout(() => {
-          showGuide.value = true;
-        }, 500);
-      } catch {
-        state.loading = false;
-      }
-    };
-
-    const isEmpty = computed(() => {
-      const list = state.tableList || [];
-      let num = 0;
-      list.forEach((item: any) => {
-        if (!item.delFlag) {
-          num++;
-        }
-      });
-      return num > 0 ? false : true;
-    });
-
-    // 收藏
-    const onCollect = async (item: any) => {
-      try {
-        await favorite({
-          materialId: item.id,
-          favoriteFlag: item.isCollect ? 0 : 1,
-          type: item.type
-        });
-        item.isCollect = !item.isCollect;
-      } catch {
-        //
-      }
-    };
-
-    const onSearch = async (item: any) => {
-      state.pagination.page = 1;
-
-      const { subjectId, ...res } = item;
-      state.searchGroup = Object.assign(state.searchGroup, {
-        ...res,
-        musicalInstrumentId: subjectId,
-        subjectId: null
-      });
-
-      getList();
-    };
-
-    // 批量删除
-    const onDelete = async () => {
-      try {
-        if (state.searchGroup.type === 'MUSIC') {
-          await materialRemoveMusic(state.editIds);
-        } else {
-          await materialRemoveAll(state.editIds);
-        }
-        // message.success('删除成功');
-        // state.pagination.page = 1;
-        // getList();
-        // state.editIds = [];
-      } catch {
-        //
-      }
-    };
-
-    // 单个删除
-    const onRemove = async () => {
-      try {
-        // 如果是乐谱类型则使用其它删除接口
-        if (state.searchGroup.type === 'MUSIC') {
-          await materialRemoveMusic([state.removeItem.id]);
-        } else {
-          await materialRemove({ ids: state.removeItem.id });
-        }
-
-        message.success('删除成功');
-        onSearch(state.searchGroup);
-      } catch {
-        //
-      }
-    };
-    const searchGroupResourcesRef = ref();
-    onMounted(() => {
-      getList();
-    });
-    return () => (
-      <>
-        <SearchGroupResources
-          ref={searchGroupResourcesRef}
-          onSearch={(item: any) => onSearch(item)}
-          onUpload={() => {
-            state.editList = [];
-            // state.uploadStatus = true;
-            state.saveStatus = true;
-          }}
-          onUpdate={() => {
-            // 修改
-            const list: any[] = [];
-            state.tableList.forEach((item: any) => {
-              if (state.editIds.indexOf(item.id) > -1 && item.delFlag !== 1) {
-                list.push(item);
-              }
-            });
-            state.editList = list || [];
-            if (state.editList.length <= 0) {
-              message.error('至少选择一条资源进行编辑');
-              return;
-            }
-            state.uploadStatus = true;
-            state.isAdd = false;
-          }}
-          onEditOver={async (status: boolean) => {
-            state.editStatus = status;
-            try {
-              // 修改
-              if (state.editOverIds.length > 0) {
-                const body = [] as any;
-                state.tableList.forEach((item: any) => {
-                  if (state.editOverIds.includes(item.id)) {
-                    body.push({
-                      instrumentIds: item.instrumentIds,
-                      openFlag: item.openFlag,
-                      coverImg: item.coverImg,
-                      name: item.title,
-                      type: item.type,
-                      enableFlag: 1,
-                      content: item.content,
-                      id: item.id || null,
-                      delFlag: item.delFlag
-                    });
-                  }
-                });
-                //
-                if (body.length > 0) {
-                  if (state.searchGroup.type === 'MUSIC') {
-                    await materialRemoveMusic(state.editIds);
-                  } else {
-                    await materialUpdateAll(body);
-                  }
-                }
-              }
-              message.success('修改成功');
-              state.pagination.page = 1;
-              getList();
-              state.editIds = [];
-              state.editOverIds = [];
-            } catch {
-              //
-            }
-          }}
-          onCancel={status => {
-            state.editStatus = status;
-            state.pagination.page = 1;
-            state.editIds = [];
-            state.editOverIds = [];
-            getList();
-          }}
-          onEdit={async (status: boolean) => {
-            // 点击编辑
-            state.editStatus = status;
-
-            if (!state.editStatus) {
-              state.editIds = [];
-              state.editOverIds = [];
-            }
-          }}
-          onSelectAll={(status: boolean) => {
-            // 全选
-            if (status) {
-              const tempIds: any[] = [];
-              state.tableList.forEach((item: any) => {
-                tempIds.push(item.id);
-              });
-              state.editIds = tempIds;
-            } else {
-              state.editIds = [];
-            }
-          }}
-          onDelete={() => {
-            if (state.editIds.length <= 0) {
-              message.error('至少选择一条资源进行删除');
-              return;
-            }
-            state.type = 'delete';
-            state.removeContent = '是否删除该资源?';
-            state.removeVisiable = true;
-          }}
-        />
-
-        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
-          <div class={styles.list}>
-            {state.tableList.map(
-              (item: any) =>
-                item.delFlag !== 1 && (
-                  <div class={styles.itemWrap}>
-                    <div class={styles.itemWrapBox}>
-                      <CardType
-                        item={item}
-                        isDownload
-                        disabledMouseHover={false}
-                        offShelf={item.enableFlag ? false : true}
-                        onOffShelf={() => {
-                          state.type = 'remove';
-                          state.removeContent = '该资源已下架,是否删除?';
-                          state.removeVisiable = true;
-                          state.removeItem = item;
-                        }} // 下架
-                        onClick={(val: any) => {
-                          if (val.type === 'IMG' || !item.enableFlag) return;
-                          state.show = true;
-                          state.item = val;
-                        }}
-                        onCollect={(item: any) => onCollect(item)}
-                      />
-                      {/* 编辑模式 */}
-                      {state.editStatus && (
-                        <div
-                          class={[
-                            styles.itemBg,
-                            state.editIds.includes(item.id)
-                              ? styles.itemBgChecked
-                              : ''
-                          ]}
-                          onClick={() => {
-                            const index = state.editIds.indexOf(item.id);
-                            if (index > -1) {
-                              state.editIds.splice(index, 1);
-                            } else {
-                              state.editIds.push(item.id);
-                            }
-                          }}>
-                          <img
-                            src={
-                              state.editIds.includes(item.id)
-                                ? resourceChecked
-                                : resourceDefault
-                            }
-                            class={styles.resourceDefault}
-                          />
-                        </div>
-                      )}
-                    </div>
-                  </div>
-                )
-            )}
-
-            {!state.loading && isEmpty.value && (
-              <TheEmpty style={{ minHeight: '50vh' }} description="暂无资源" />
-            )}
-          </div>
-        </NSpin>
-
-        <Pagination
-          disabled={state.editStatus}
-          v-model:page={state.pagination.page}
-          v-model:pageSize={state.pagination.rows}
-          v-model:pageTotal={state.pageTotal}
-          onList={getList}
-        />
-
-        {/* 弹窗查看 */}
-        <CardPreview v-model:show={state.show} item={state.item} />
-
-        <NModal
-          v-model:show={state.uploadStatus}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.attendClassModal]}
-          title={state.editStatus ? '修改资源' : '上传资源'}
-          blockScroll={false}>
-          <UploadModal
-            editStatus={state.editStatus}
-            onClose={() => {
-              state.uploadStatus = false;
-            }}
-            onConfirm={() => {
-              state.editIds = [];
-              state.editList = [];
-              state.editOverIds = [];
-              state.saveStatus = false;
-              searchGroupResourcesRef.value?.resetStatus();
-              onSearch(state.searchGroup);
-            }}
-            list={state.editList}
-            showDelete={state.isAdd}
-            onEditAll={(list: any) => {
-              try {
-                state.tableList.forEach((table: any) => {
-                  const item = list.find((item: any) => item.id === table.id);
-                  if (item) {
-                    table.openFlag = item.openFlag;
-                    table.title = item.name;
-                    table.instrumentIds = item.instrumentIds;
-                    table.content = item.content;
-                    table.coverImg = item.coverImg;
-
-                    if (!state.editOverIds.includes(table.id)) {
-                      state.editOverIds.push(table.id);
-                    }
-                  }
-                });
-                state.uploadStatus = false;
-              } catch (e: any) {
-                console.log(e);
-              }
-            }}
-          />
-        </NModal>
-
-        <NModal
-          v-model:show={state.saveStatus}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.attendClassSaveModal]}
-          title={'上传资源'}
-          blockScroll={false}>
-          <SaveModal
-            onClose={() => (state.saveStatus = false)}
-            onConfrim={(val: any) => {
-              const list = val || [];
-              const temp: any = [];
-              list.forEach((item: any) => {
-                temp.push({
-                  instrumentIds: null,
-                  openFlag: false,
-                  coverImg: item.coverImg,
-                  title: item.name || '',
-                  type: formatUrlType(item.content),
-                  enableFlag: 1,
-                  content: item.content,
-                  id: null
-                });
-              });
-              state.editList = [...temp];
-              state.uploadStatus = true;
-              state.isAdd = true;
-              state.editStatus = false;
-            }}
-          />
-        </NModal>
-
-        {showGuide.value ? <MyResourcesGuide></MyResourcesGuide> : null}
-
-        <NModal
-          v-model:show={state.removeVisiable}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable]}
-          title={'提示'}>
-          <div class={styles.studentRemove}>
-            <p>{state.removeContent}</p>
-
-            <NSpace class={styles.btnGroupModal} justify="center">
-              <NButton
-                round
-                type="primary"
-                onClick={() => {
-                  if (state.type === 'remove') {
-                    onRemove();
-                  } else {
-                    state.tableList.forEach((item: any) => {
-                      if (state.editIds.includes(item.id)) {
-                        item.delFlag = 1;
-
-                        if (!state.editOverIds.includes(item.id)) {
-                          state.editOverIds.push(item.id);
-                        }
-                      }
-                    });
-                  }
-                  state.removeVisiable = false;
-                }}>
-                确定
-              </NButton>
-              <NButton round onClick={() => (state.removeVisiable = false)}>
-                取消
-              </NButton>
-            </NSpace>
-          </div>
-        </NModal>
-      </>
-    );
-  }
-});
+import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import CardType from '/src/components/card-type';
+import Pagination from '/src/components/pagination';
+import SearchGroupResources from './search-group-resources';
+import {
+  favorite,
+  materialQueryPage,
+  materialRemove,
+  materialRemoveAll,
+  materialRemoveMusic,
+  materialUpdateAll
+} from '../../api';
+import {
+  NButton,
+  NModal,
+  NSpace,
+  NSpin,
+  useDialog,
+  useMessage
+} from 'naive-ui';
+import TheEmpty from '/src/components/TheEmpty';
+import UploadModal, { formatUrlType } from './upload-modal';
+import CardPreview from '@/components/card-preview';
+import resourceDefault from '../../images/resource-default.png';
+import resourceChecked from '../../images/resource-checked.png';
+import MyResourcesGuide from '@/custom-plugins/guide-page/myResources-guide';
+import SaveModal from './save-modal';
+import deepClone from '/src/helpers/deep-clone';
+import UploadCover from './upload-cover';
+export default defineComponent({
+  name: 'share-resources',
+  setup() {
+    const message = useMessage();
+    const dialog = useDialog();
+    const state = reactive({
+      searchWord: '',
+      loading: false,
+      pageTotal: 0,
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        type: 'MUSIC', //
+        name: '',
+        bookVersionId: null,
+        subjectId: null,
+        sourceType: 3
+      },
+      tableList: [] as any,
+      uploadStatus: false,
+      saveStatus: false,
+      show: false,
+      item: {} as any,
+      editStatus: false, // 是否编辑
+      isAdd: false,
+      editList: [] as any, // TOD
+      editIds: [] as any, // 编辑的
+      editOverIds: [] as any, // 确认修改的数据
+      removeVisiable: false,
+      removeContent: '是否删除该资源?',
+      type: 'remove',
+      removeItem: {} as any
+    });
+    const showGuide = ref(false);
+    const getList = async () => {
+      try {
+        state.loading = true;
+        const { data } = await materialQueryPage({
+          ...state.searchGroup,
+          ...state.pagination
+        });
+        state.loading = false;
+        state.pageTotal = Number(data.total);
+        const tempRows = data.rows || [];
+        const temp: any = [];
+        tempRows.forEach((row: any) => {
+          temp.push({
+            id: row.id,
+            coverImg: row.coverImg,
+            type: row.type,
+            title: row.name,
+            isCollect: !!row.favoriteFlag,
+            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
+            refFlag: row.refFlag,
+            content: row.content,
+            // subjectId: row.subjectIds,
+            instrumentIds: row.instrumentIds,
+            sourceFrom: row.sourceFrom,
+            background: row.background,
+            enableFlag: row.enableFlag ? 1 : 0,
+            openFlag: row.openFlag
+          });
+        });
+        state.tableList = temp || [];
+        setTimeout(() => {
+          showGuide.value = true;
+        }, 500);
+      } catch {
+        state.loading = false;
+      }
+    };
+
+    const isEmpty = computed(() => {
+      const list = state.tableList || [];
+      let num = 0;
+      list.forEach((item: any) => {
+        if (!item.delFlag) {
+          num++;
+        }
+      });
+      return num > 0 ? false : true;
+    });
+
+    // 收藏
+    const onCollect = async (item: any) => {
+      try {
+        await favorite({
+          materialId: item.id,
+          favoriteFlag: item.isCollect ? 0 : 1,
+          type: item.type
+        });
+        item.isCollect = !item.isCollect;
+      } catch {
+        //
+      }
+    };
+
+    const onSearch = async (item: any) => {
+      state.pagination.page = 1;
+
+      const { subjectId, ...res } = item;
+      state.searchGroup = Object.assign(state.searchGroup, {
+        ...res,
+        musicalInstrumentId: subjectId,
+        subjectId: null
+      });
+
+      getList();
+    };
+
+    // 批量删除
+    const onDelete = async () => {
+      try {
+        if (state.searchGroup.type === 'MUSIC') {
+          await materialRemoveMusic(state.editIds);
+        } else {
+          await materialRemoveAll(state.editIds);
+        }
+        // message.success('删除成功');
+        // state.pagination.page = 1;
+        // getList();
+        // state.editIds = [];
+      } catch {
+        //
+      }
+    };
+
+    // 单个删除
+    const onRemove = async () => {
+      try {
+        // 如果是乐谱类型则使用其它删除接口
+        if (state.searchGroup.type === 'MUSIC') {
+          await materialRemoveMusic([state.removeItem.id]);
+        } else {
+          await materialRemove({ ids: state.removeItem.id });
+        }
+
+        message.success('删除成功');
+        onSearch(state.searchGroup);
+      } catch {
+        //
+      }
+    };
+    const searchGroupResourcesRef = ref();
+    onMounted(() => {
+      getList();
+    });
+    return () => (
+      <>
+        <SearchGroupResources
+          ref={searchGroupResourcesRef}
+          onSearch={(item: any) => onSearch(item)}
+          onUpload={() => {
+            state.editList = [];
+            // state.uploadStatus = true;
+            state.saveStatus = true;
+          }}
+          onUpdate={() => {
+            // 修改
+            const list: any[] = [];
+            state.tableList.forEach((item: any) => {
+              if (state.editIds.indexOf(item.id) > -1 && item.delFlag !== 1) {
+                list.push(item);
+              }
+            });
+            state.editList = list || [];
+            if (state.editList.length <= 0) {
+              message.error('至少选择一条资源进行编辑');
+              return;
+            }
+            state.uploadStatus = true;
+            state.isAdd = false;
+          }}
+          onEditOver={async (status: boolean) => {
+            state.editStatus = status;
+            try {
+              // 修改
+              if (state.editOverIds.length > 0) {
+                const body = [] as any;
+                state.tableList.forEach((item: any) => {
+                  if (state.editOverIds.includes(item.id)) {
+                    body.push({
+                      instrumentIds: item.instrumentIds,
+                      openFlag: item.openFlag,
+                      coverImg: item.coverImg,
+                      name: item.title,
+                      type: item.type,
+                      enableFlag: 1,
+                      content: item.content,
+                      id: item.id || null,
+                      delFlag: item.delFlag
+                    });
+                  }
+                });
+                //
+                if (body.length > 0) {
+                  if (state.searchGroup.type === 'MUSIC') {
+                    await materialRemoveMusic(state.editIds);
+                  } else {
+                    await materialUpdateAll(body);
+                  }
+                }
+              }
+              message.success('修改成功');
+              state.pagination.page = 1;
+              getList();
+              state.editIds = [];
+              state.editOverIds = [];
+            } catch {
+              //
+            }
+          }}
+          onCancel={status => {
+            state.editStatus = status;
+            state.pagination.page = 1;
+            state.editIds = [];
+            state.editOverIds = [];
+            getList();
+          }}
+          onEdit={async (status: boolean) => {
+            // 点击编辑
+            state.editStatus = status;
+
+            if (!state.editStatus) {
+              state.editIds = [];
+              state.editOverIds = [];
+            }
+          }}
+          onSelectAll={(status: boolean) => {
+            // 全选
+            if (status) {
+              const tempIds: any[] = [];
+              state.tableList.forEach((item: any) => {
+                tempIds.push(item.id);
+              });
+              state.editIds = tempIds;
+            } else {
+              state.editIds = [];
+            }
+          }}
+          onDelete={() => {
+            if (state.editIds.length <= 0) {
+              message.error('至少选择一条资源进行删除');
+              return;
+            }
+            state.type = 'delete';
+            state.removeContent = '是否删除该资源?';
+            state.removeVisiable = true;
+          }}
+        />
+
+        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
+          <div class={styles.list}>
+            {state.tableList.map(
+              (item: any) =>
+                item.delFlag !== 1 && (
+                  <div class={styles.itemWrap}>
+                    <div class={styles.itemWrapBox}>
+                      <CardType
+                        item={item}
+                        isDownload
+                        disabledMouseHover={false}
+                        offShelf={item.enableFlag ? false : true}
+                        onOffShelf={() => {
+                          state.type = 'remove';
+                          state.removeContent = '该资源已下架,是否删除?';
+                          state.removeVisiable = true;
+                          state.removeItem = item;
+                        }} // 下架
+                        onClick={(val: any) => {
+                          if (val.type === 'IMG' || !item.enableFlag) return;
+                          state.show = true;
+                          state.item = val;
+                        }}
+                        onCollect={(item: any) => onCollect(item)}
+                      />
+                      {/* 编辑模式 */}
+                      {state.editStatus && (
+                        <div
+                          class={[
+                            styles.itemBg,
+                            state.editIds.includes(item.id)
+                              ? styles.itemBgChecked
+                              : ''
+                          ]}
+                          onClick={() => {
+                            const index = state.editIds.indexOf(item.id);
+                            if (index > -1) {
+                              state.editIds.splice(index, 1);
+                            } else {
+                              state.editIds.push(item.id);
+                            }
+                          }}>
+                          <img
+                            src={
+                              state.editIds.includes(item.id)
+                                ? resourceChecked
+                                : resourceDefault
+                            }
+                            class={styles.resourceDefault}
+                          />
+                        </div>
+                      )}
+                    </div>
+                  </div>
+                )
+            )}
+
+            {!state.loading && isEmpty.value && (
+              <TheEmpty style={{ minHeight: '50vh' }} description="暂无资源" />
+            )}
+          </div>
+        </NSpin>
+
+        <Pagination
+          disabled={state.editStatus}
+          v-model:page={state.pagination.page}
+          v-model:pageSize={state.pagination.rows}
+          v-model:pageTotal={state.pageTotal}
+          onList={getList}
+        />
+
+        {/* 弹窗查看 */}
+        <CardPreview v-model:show={state.show} item={state.item} />
+
+        <NModal
+          v-model:show={state.uploadStatus}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassModal]}
+          title={state.editStatus ? '修改资源' : '上传资源'}
+          blockScroll={false}>
+          <UploadModal
+            editStatus={state.editStatus}
+            onClose={() => {
+              state.uploadStatus = false;
+            }}
+            onConfirm={() => {
+              state.editIds = [];
+              state.editList = [];
+              state.editOverIds = [];
+              state.saveStatus = false;
+              searchGroupResourcesRef.value?.resetStatus();
+              onSearch(state.searchGroup);
+            }}
+            list={state.editList}
+            showDelete={state.isAdd}
+            onEditAll={(list: any) => {
+              try {
+                state.tableList.forEach((table: any) => {
+                  const item = list.find((item: any) => item.id === table.id);
+                  if (item) {
+                    table.openFlag = item.openFlag;
+                    table.title = item.name;
+                    table.instrumentIds = item.instrumentIds;
+                    table.content = item.content;
+                    table.coverImg = item.coverImg;
+
+                    if (!state.editOverIds.includes(table.id)) {
+                      state.editOverIds.push(table.id);
+                    }
+                  }
+                });
+                state.uploadStatus = false;
+              } catch (e: any) {
+                console.log(e);
+              }
+            }}
+          />
+        </NModal>
+
+        <NModal
+          v-model:show={state.saveStatus}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassSaveModal]}
+          title={'上传资源'}
+          blockScroll={false}>
+          <SaveModal
+            onClose={() => (state.saveStatus = false)}
+            onConfrim={(val: any) => {
+              const list = val || [];
+              const temp: any = [];
+              list.forEach((item: any) => {
+                temp.push({
+                  instrumentIds: null,
+                  openFlag: false,
+                  coverImg: item.coverImg,
+                  title: item.name || '',
+                  type: formatUrlType(item.content),
+                  enableFlag: 1,
+                  content: item.content,
+                  id: null
+                });
+              });
+              state.editList = [...temp];
+              state.uploadStatus = true;
+              state.isAdd = true;
+              state.editStatus = false;
+            }}
+          />
+        </NModal>
+
+        {showGuide.value ? <MyResourcesGuide></MyResourcesGuide> : null}
+
+        <NModal
+          v-model:show={state.removeVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable]}
+          title={'提示'}>
+          <div class={styles.studentRemove}>
+            <p>{state.removeContent}</p>
+
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton
+                round
+                type="primary"
+                onClick={() => {
+                  if (state.type === 'remove') {
+                    onRemove();
+                  } else {
+                    state.tableList.forEach((item: any) => {
+                      if (state.editIds.includes(item.id)) {
+                        item.delFlag = 1;
+
+                        if (!state.editOverIds.includes(item.id)) {
+                          state.editOverIds.push(item.id);
+                        }
+                      }
+                    });
+                  }
+                  state.removeVisiable = false;
+                }}>
+                确定
+              </NButton>
+              <NButton round onClick={() => (state.removeVisiable = false)}>
+                取消
+              </NButton>
+            </NSpace>
+          </div>
+        </NModal>
+      </>
+    );
+  }
+});

+ 174 - 173
src/views/natural-resources/components/share-resources/index.tsx

@@ -1,173 +1,174 @@
-import { defineComponent, onMounted, reactive, ref } from 'vue';
-import styles from './index.module.less';
-import CardType from '/src/components/card-type';
-import Pagination from '/src/components/pagination';
-import SearchGroupResources from './search-group-resources';
-import { favorite, materialQueryPage } from '../../api';
-import { NModal, NSpin } from 'naive-ui';
-import TheEmpty from '/src/components/TheEmpty';
-import CardPreview from '/src/components/card-preview';
-import AddTeaching from '../../model/add-teaching';
-import ShareResourcesGuide from '@/custom-plugins/guide-page/shareResources-guide';
-
-export default defineComponent({
-  name: 'share-resources',
-  setup() {
-    const state = reactive({
-      searchWord: '',
-      loading: false,
-      pageTotal: 0,
-      pagination: {
-        page: 1,
-        rows: 20
-      },
-      searchGroup: {
-        type: 'MUSIC', //
-        name: '',
-        bookVersionId: null,
-        subjectId: null,
-        sourceType: 2
-      },
-      tableList: [] as any,
-      teachingStatus: false,
-      show: false,
-      item: {} as any
-    });
-    const showGuide = ref(false);
-    const SearchGroupResourcesRef = ref();
-    const getList = async () => {
-      try {
-        state.loading = true;
-        const { data } = await materialQueryPage({
-          ...state.searchGroup,
-          ...state.pagination
-        });
-        state.loading = false;
-        state.pageTotal = Number(data.total);
-        const tempRows = data.rows || [];
-        const temp: any = [];
-        tempRows.forEach((row: any) => {
-          temp.push({
-            id: row.id,
-            coverImg: row.coverImg,
-            type: row.type,
-            title: row.name,
-            isCollect: !!row.favoriteFlag,
-            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
-            refFlag: row.refFlag,
-            content: row.content
-          });
-        });
-        state.tableList = temp || [];
-        setTimeout(() => {
-          showGuide.value = true;
-        }, 500);
-      } catch {
-        state.loading = false;
-      }
-    };
-
-    const onSearch = async (item: any) => {
-      state.pagination.page = 1;
-
-      const { subjectId, ...res } = item;
-      state.searchGroup = Object.assign(state.searchGroup, {
-        ...res,
-        musicalInstrumentId: subjectId,
-        subjectId: null
-      });
-
-      getList();
-    };
-
-    // 收藏
-    const onCollect = async (item: any) => {
-      try {
-        await favorite({
-          materialId: item.id,
-          favoriteFlag: item.isCollect ? 0 : 1,
-          type: item.type
-        });
-        item.isCollect = !item.isCollect;
-      } catch {
-        //
-      }
-    };
-
-    onMounted(() => {
-      getList();
-    });
-    return () => (
-      <>
-        <SearchGroupResources
-          ref={SearchGroupResourcesRef}
-          onSearch={(item: any) => onSearch(item)}
-          onAdd={() => (state.teachingStatus = true)}
-        />
-        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
-          <div class={styles.list}>
-            {state.tableList.map((item: any, index: number) => (
-              <div class={styles.itemWrap}>
-                <div class={styles.itemWrapBox}>
-                  {index == 0 ? (
-                    <CardType
-                      {...{ id: 'shareResources-1' }}
-                      item={item}
-                      disabledMouseHover={false}
-                      onClick={(val: any) => {
-                        if (val.type === 'IMG') return;
-                        state.show = true;
-                        state.item = val;
-                      }}
-                      onCollect={(item: any) => onCollect(item)}
-                    />
-                  ) : (
-                    <CardType
-                      item={item}
-                      disabledMouseHover={false}
-                      onClick={(val: any) => {
-                        if (val.type === 'IMG') return;
-                        state.show = true;
-                        state.item = val;
-                      }}
-                      onCollect={(item: any) => onCollect(item)}
-                    />
-                  )}
-                </div>
-              </div>
-            ))}
-
-            {!state.loading && state.tableList.length <= 0 && (
-              <TheEmpty
-                style={{ minHeight: '50vh' }}
-                description="暂无共享资源"
-              />
-            )}
-          </div>
-        </NSpin>
-
-        <Pagination
-          v-model:page={state.pagination.page}
-          v-model:pageSize={state.pagination.rows}
-          v-model:pageTotal={state.pageTotal}
-          onList={getList}
-        />
-
-        {/* 弹窗查看 */}
-        <CardPreview v-model:show={state.show} item={state.item} />
-
-        {/* 添加自定义教材 */}
-        <NModal
-          v-model:show={state.teachingStatus}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.teachingModal]}
-          title={'自定义教材'}
-          blockScroll={false}>
-          <AddTeaching onClose={() => (state.teachingStatus = false)} />
-        </NModal>
-        {showGuide.value ? <ShareResourcesGuide></ShareResourcesGuide> : null}
-      </>
-    );
-  }
-});
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import CardType from '/src/components/card-type';
+import Pagination from '/src/components/pagination';
+import SearchGroupResources from './search-group-resources';
+import { favorite, materialQueryPage } from '../../api';
+import { NModal, NSpin } from 'naive-ui';
+import TheEmpty from '/src/components/TheEmpty';
+import CardPreview from '/src/components/card-preview';
+import AddTeaching from '../../model/add-teaching';
+import ShareResourcesGuide from '@/custom-plugins/guide-page/shareResources-guide';
+
+export default defineComponent({
+  name: 'share-resources',
+  setup() {
+    const state = reactive({
+      searchWord: '',
+      loading: false,
+      pageTotal: 0,
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        type: 'MUSIC', //
+        name: '',
+        bookVersionId: null,
+        subjectId: null,
+        sourceType: 2
+      },
+      tableList: [] as any,
+      teachingStatus: false,
+      show: false,
+      item: {} as any
+    });
+    const showGuide = ref(false);
+    const SearchGroupResourcesRef = ref();
+    const getList = async () => {
+      try {
+        state.loading = true;
+        const { data } = await materialQueryPage({
+          ...state.searchGroup,
+          ...state.pagination
+        });
+        state.loading = false;
+        state.pageTotal = Number(data.total);
+        const tempRows = data.rows || [];
+        const temp: any = [];
+        tempRows.forEach((row: any) => {
+          temp.push({
+            id: row.id,
+            coverImg: row.coverImg,
+            type: row.type,
+            title: row.name,
+            isCollect: !!row.favoriteFlag,
+            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
+            refFlag: row.refFlag,
+            background: row.background,
+            content: row.content
+          });
+        });
+        state.tableList = temp || [];
+        setTimeout(() => {
+          showGuide.value = true;
+        }, 500);
+      } catch {
+        state.loading = false;
+      }
+    };
+
+    const onSearch = async (item: any) => {
+      state.pagination.page = 1;
+
+      const { subjectId, ...res } = item;
+      state.searchGroup = Object.assign(state.searchGroup, {
+        ...res,
+        musicalInstrumentId: subjectId,
+        subjectId: null
+      });
+
+      getList();
+    };
+
+    // 收藏
+    const onCollect = async (item: any) => {
+      try {
+        await favorite({
+          materialId: item.id,
+          favoriteFlag: item.isCollect ? 0 : 1,
+          type: item.type
+        });
+        item.isCollect = !item.isCollect;
+      } catch {
+        //
+      }
+    };
+
+    onMounted(() => {
+      getList();
+    });
+    return () => (
+      <>
+        <SearchGroupResources
+          ref={SearchGroupResourcesRef}
+          onSearch={(item: any) => onSearch(item)}
+          onAdd={() => (state.teachingStatus = true)}
+        />
+        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
+          <div class={styles.list}>
+            {state.tableList.map((item: any, index: number) => (
+              <div class={styles.itemWrap}>
+                <div class={styles.itemWrapBox}>
+                  {index == 0 ? (
+                    <CardType
+                      {...{ id: 'shareResources-1' }}
+                      item={item}
+                      disabledMouseHover={false}
+                      onClick={(val: any) => {
+                        if (val.type === 'IMG') return;
+                        state.show = true;
+                        state.item = val;
+                      }}
+                      onCollect={(item: any) => onCollect(item)}
+                    />
+                  ) : (
+                    <CardType
+                      item={item}
+                      disabledMouseHover={false}
+                      onClick={(val: any) => {
+                        if (val.type === 'IMG') return;
+                        state.show = true;
+                        state.item = val;
+                      }}
+                      onCollect={(item: any) => onCollect(item)}
+                    />
+                  )}
+                </div>
+              </div>
+            ))}
+
+            {!state.loading && state.tableList.length <= 0 && (
+              <TheEmpty
+                style={{ minHeight: '50vh' }}
+                description="暂无共享资源"
+              />
+            )}
+          </div>
+        </NSpin>
+
+        <Pagination
+          v-model:page={state.pagination.page}
+          v-model:pageSize={state.pagination.rows}
+          v-model:pageTotal={state.pageTotal}
+          onList={getList}
+        />
+
+        {/* 弹窗查看 */}
+        <CardPreview v-model:show={state.show} item={state.item} />
+
+        {/* 添加自定义教材 */}
+        <NModal
+          v-model:show={state.teachingStatus}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.teachingModal]}
+          title={'自定义教材'}
+          blockScroll={false}>
+          <AddTeaching onClose={() => (state.teachingStatus = false)} />
+        </NModal>
+        {showGuide.value ? <ShareResourcesGuide></ShareResourcesGuide> : null}
+      </>
+    );
+  }
+});

+ 11 - 12
src/views/prepare-lessons/components/lesson-main/train/index.tsx

@@ -361,22 +361,21 @@ export default defineComponent({
               <NButton
                 bordered={false}
                 type="default"
-                disabled={forms.trainList.length <= 0}
                 onClick={() => {
                   if (!forms.title) {
                     message.error('请输入标题');
                     return;
                   }
-                  let count = 0;
-                  forms.trainList.forEach((item: any) => {
-                    if (!item.removeFlag) {
-                      count++;
-                    }
-                  });
-                  if (count <= 0) {
-                    message.error('作业内容不能为空');
-                    return;
-                  }
+                  // let count = 0;
+                  // forms.trainList.forEach((item: any) => {
+                  //   if (!item.removeFlag) {
+                  //     count++;
+                  //   }
+                  // });
+                  // if (count <= 0) {
+                  //   message.error('作业内容不能为空');
+                  //   return;
+                  // }
 
                   forms.preSaveVisiable = true;
                 }}
@@ -436,7 +435,7 @@ export default defineComponent({
               }}
               onDrop={(e: any) => {
                 let dropItem = e.dataTransfer.getData('text');
-                console.log(dropItem, 'dropItem', dropItem);
+                // console.log(dropItem, 'dropItem', dropItem);
                 dropItem = dropItem ? JSON.parse(dropItem) : {};
                 // 判断是否有数据
                 if (dropItem.id) {

+ 1 - 0
src/views/prepare-lessons/components/resource-main/components/resource-item/index.tsx

@@ -94,6 +94,7 @@ export default defineComponent({
             isCollect: !!row.favoriteFlag,
             refFlag: row.refFlag,
             isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
+            background: row.background,
             content: row.content
             // exist: index !== -1 ? true : false // 是否存在
           });

+ 360 - 359
src/views/prepare-lessons/components/resource-main/components/select-music/index.tsx

@@ -1,359 +1,360 @@
-import {
-  PropType,
-  defineComponent,
-  onMounted,
-  reactive,
-  watch,
-  toRef
-} from 'vue';
-import ResourceSearchGroup from './resource-search-group';
-import { NModal, NScrollbar, NSpin } from 'naive-ui';
-import styles from './index.module.less';
-import CardType from '/src/components/card-type';
-import TheEmpty from '/src/components/TheEmpty';
-import { useThrottleFn } from '@vueuse/core';
-import { usePrepareStore } from '/src/store/modules/prepareLessons';
-import { musicSheetPage } from '/src/views/prepare-lessons/api';
-import TrainUpdate from '/src/views/attend-class/model/train-update';
-import requestOrigin from 'umi-request';
-import CardPreview from '/src/components/card-preview';
-import { evaluateDifficult } from '/src/utils/contants';
-import { eventGlobal } from '/src/utils';
-import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
-import useDrag from '@/hooks/useDrag';
-import Dragbom from '@/hooks/useDrag/dragbom';
-import { useUserStore } from '@/store/modules/users';
-
-const formatType = (type: string) => {
-  if (type === 'sahreMusic') {
-    return 2;
-  } else if (type === 'myMusic') {
-    return 3;
-  } else if (type === 'collectMusic') {
-    return 4;
-  }
-};
-
-export const typeFormat = (trainingType: string, configJson: any) => {
-  let tList: string[] = [];
-
-  if (trainingType === 'EVALUATION') {
-    tList = [
-      `${evaluateDifficult[configJson.evaluateDifficult]}`,
-      configJson.practiceChapterBegin || configJson.practiceChapterEnd
-        ? `${configJson.practiceChapterBegin}-${configJson.practiceChapterEnd}小节`
-        : '全部小节',
-      // `速度${configJson.evaluateSpeed}`,
-      `${configJson.trainingTimes}分合格`
-    ];
-  } else {
-    tList = [
-      `${configJson.practiceChapterBegin}-${configJson.practiceChapterEnd}小节`,
-      `速度${configJson.practiceSpeed}`,
-      `${configJson.trainingTimes}分钟`
-    ];
-  }
-  return tList;
-};
-
-export default defineComponent({
-  name: 'share-resources',
-  props: {
-    type: {
-      type: String as PropType<'myMusic' | 'sahreMusic' | 'collectMusic'>,
-      default: 'myMusic'
-    },
-    /** 类型 */
-    cardType: {
-      type: String as PropType<'' | 'homerowk-record' | 'prepare'>,
-      default: ''
-    },
-    from: {
-      // 来自哪里
-      type: String,
-      default: ''
-    }
-  },
-  setup(props) {
-    const prepareStore = usePrepareStore();
-    const state = reactive({
-      loading: false,
-      finshed: false, // 是否加载完
-      pagination: {
-        page: 1,
-        rows: 20
-      },
-      searchGroup: {
-        name: '',
-        type: 'MUSIC', //
-        musicSheetCategoriesId: '',
-        musicalInstrumentId: '',
-        sourceType: formatType(props.type),
-        status: 1,
-        versionFlag: false,
-        musicSubject: null
-      },
-      tableList: [] as any,
-      editStatus: false,
-      editItem: {} as any,
-      show: false,
-      item: {} as any
-    });
-    const getList = async () => {
-      try {
-        if (
-          !prepareStore.getSubjectId &&
-          !['homerowk-record', 'prepare'].includes(props.cardType)
-        )
-          return;
-        if (state.pagination.page === 1) {
-          state.loading = true;
-        }
-        // const { data } = await musicSheetPage({
-        //   ...state.searchGroup,
-        //   ...state.pagination,
-        //   musicSubject: prepareStore.getSubjectId
-        // });
-        const { data } = await materialQueryPage({
-          ...state.searchGroup,
-          ...state.pagination
-          // subjectId: prepareStore.getSubjectId
-        });
-        state.loading = false;
-        const tempRows = data.rows || [];
-        const temp: any = [];
-
-        tempRows.forEach((row: any) => {
-          const index = prepareStore.getTrainList.findIndex(
-            (course: any) => course.musicId === row.id
-          );
-          temp.push({
-            id: row.id,
-            coverImg: row.coverImg || row.musicSvg,
-            type: 'MUSIC',
-            title: row.name,
-            isCollect: !!row.favoriteFlag,
-            refFlag: row.refFlag,
-            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
-            content: row.id,
-            xmlFileUrl: row.xmlFileUrl
-            // exist: index !== -1 ? true : false // 是否存在
-          });
-        });
-        state.tableList.push(...temp);
-        state.finshed = data.pages <= data.current ? true : false;
-      } catch {
-        state.loading = false;
-      }
-    };
-
-    const onSearch = async (item: any) => {
-      state.pagination.page = 1;
-      state.tableList = [];
-      state.searchGroup = Object.assign(state.searchGroup, item);
-      getList();
-    };
-
-    // 声部变化时
-    watch(
-      () => prepareStore.getSubjectId,
-      () => {
-        onSearch(state.searchGroup);
-      }
-    );
-    // watch(
-    //   () => prepareStore.trainList,
-    //   () => {
-    //     state.tableList.forEach((item: any) => {
-    //       const index = prepareStore.getTrainList.findIndex(
-    //         (course: any) => course.musicId === item.id
-    //       );
-    //       item.exist = index !== -1 ? true : false; // 是否存在
-    //     });
-    //   },
-    //   {
-    //     deep: true,
-    //     immediate: true
-    //   }
-    // );
-
-    const throttledFn = useThrottleFn(() => {
-      state.pagination.page = state.pagination.page + 1;
-      getList();
-    }, 500);
-
-    // 添加资源
-    const onAdd = async (item: any) => {
-      let xmlStatus = 'init';
-      // 第一个声部小节
-      let firstMeasures: any = null;
-      try {
-        // 获取文件
-        const res = await requestOrigin.get(item.xmlFileUrl, {
-          mode: 'cors'
-        });
-        const xmlParse = new DOMParser().parseFromString(res, 'text/xml');
-        const parts = xmlParse.getElementsByTagName('part');
-        firstMeasures = parts[0]?.getElementsByTagName('measure');
-        xmlStatus = 'success';
-      } catch (error) {
-        xmlStatus = 'error';
-      }
-
-      // 判断读取小节数
-      if (xmlStatus == 'success') {
-        item.practiceChapterMax = firstMeasures.length;
-      } else {
-        item.practiceChapterMax = 0;
-      }
-      item.coursewareKnowledgeDetailId = prepareStore.getSelectKey;
-      item.subjectId = prepareStore.getSubjectId;
-
-      state.editItem = item;
-      state.editStatus = true;
-    };
-
-    // 收藏
-    const onCollect = async (item: any) => {
-      try {
-        await favorite({
-          materialId: item.id,
-          favoriteFlag: item.isCollect ? 0 : 1,
-          type: item.type
-        });
-        item.isCollect = !item.isCollect;
-      } catch {
-        //
-      }
-    };
-
-    onMounted(() => {
-      getList();
-
-      eventGlobal.on('onTrainDragItem', (item: any, point?: any) => {
-        onAdd(item);
-      });
-    });
-    // 弹窗拖动
-    // 作业设置
-    let workSetingBoxDragData: any;
-    let workSetingBoxClass: string;
-    if (props.from === 'class') {
-      const users = useUserStore();
-      workSetingBoxClass = 'workSetingBoxClass_drag';
-      workSetingBoxDragData = useDrag(
-        [
-          `${workSetingBoxClass}>.n-card-header`,
-          `${workSetingBoxClass} .bom_drag`
-        ],
-        workSetingBoxClass,
-        toRef(state, 'editStatus'),
-        users.info.id
-      );
-    }
-    return () => (
-      <div>
-        <ResourceSearchGroup
-          type={props.type}
-          onSearch={(item: any) => onSearch(item)}
-        />
-        <NScrollbar
-          class={[
-            styles.listContainer,
-            props.type === 'myMusic' ? styles.listNoMusic : ''
-          ]}
-          onScroll={(e: any) => {
-            const clientHeight = e.target?.clientHeight;
-            const scrollTop = e.target?.scrollTop;
-            const scrollHeight = e.target?.scrollHeight;
-            // 是否到底,是否加载完
-            if (
-              clientHeight + scrollTop + 20 >= scrollHeight &&
-              !state.finshed &&
-              !state.loading
-            ) {
-              throttledFn();
-            }
-          }}>
-          <NSpin show={state.loading} size={'small'}>
-            <div
-              class={[
-                styles.listSection,
-                !state.loading && state.tableList.length <= 0
-                  ? styles.emptySection
-                  : ''
-              ]}>
-              {state.tableList.length > 0 && (
-                <div class={styles.list}>
-                  {state.tableList.map((item: any) => (
-                    <CardType
-                      isShowAdd
-                      item={item}
-                      draggable
-                      isShowCollect
-                      // isShowAddDisabled={!prepareStore.getIsEditTrain}
-                      disabledMouseHover={false}
-                      onClick={() => {
-                        if (item.type === 'IMG') return;
-                        state.show = true;
-                        state.item = item;
-                      }}
-                      onAdd={(child: any) => onAdd(child)}
-                      onCollect={(item: any) => onCollect(item)}
-                    />
-                  ))}
-                </div>
-              )}
-              {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
-            </div>
-          </NSpin>
-        </NScrollbar>
-
-        {/* 弹窗查看 */}
-        <CardPreview
-          from={props.from}
-          v-model:show={state.show}
-          item={state.item}
-        />
-
-        <NModal
-          v-model:show={state.editStatus}
-          style={
-            props.from === 'class' ? workSetingBoxDragData.styleDrag.value : {}
-          }
-          class={[
-            'modalTitle background',
-            styles.trainEditModal,
-            workSetingBoxClass
-          ]}
-          preset="card"
-          title="作业设置">
-          <TrainUpdate
-            item={state.editItem}
-            type="homework"
-            onClose={() => (state.editStatus = false)}
-            onConfirm={(item: any) => {
-              // state.editItem = {};
-              // prepareStore.setIsAddTrain(true);
-
-              const tList = typeFormat(
-                item.trainingType,
-                item.trainingConfigJson
-              );
-              //
-              const train = {
-                ...item,
-                id: null,
-                musicName: state.editItem.title,
-                typeList: tList
-              };
-
-              eventGlobal.emit('onTrainAddItem', train);
-            }}
-          />
-          {props.from === 'class' && <Dragbom></Dragbom>}
-        </NModal>
-      </div>
-    );
-  }
-});
+import {
+  PropType,
+  defineComponent,
+  onMounted,
+  reactive,
+  watch,
+  toRef
+} from 'vue';
+import ResourceSearchGroup from './resource-search-group';
+import { NModal, NScrollbar, NSpin } from 'naive-ui';
+import styles from './index.module.less';
+import CardType from '/src/components/card-type';
+import TheEmpty from '/src/components/TheEmpty';
+import { useThrottleFn } from '@vueuse/core';
+import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import { musicSheetPage } from '/src/views/prepare-lessons/api';
+import TrainUpdate from '/src/views/attend-class/model/train-update';
+import requestOrigin from 'umi-request';
+import CardPreview from '/src/components/card-preview';
+import { evaluateDifficult } from '/src/utils/contants';
+import { eventGlobal } from '/src/utils';
+import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
+import useDrag from '@/hooks/useDrag';
+import Dragbom from '@/hooks/useDrag/dragbom';
+import { useUserStore } from '@/store/modules/users';
+
+const formatType = (type: string) => {
+  if (type === 'sahreMusic') {
+    return 2;
+  } else if (type === 'myMusic') {
+    return 3;
+  } else if (type === 'collectMusic') {
+    return 4;
+  }
+};
+
+export const typeFormat = (trainingType: string, configJson: any) => {
+  let tList: string[] = [];
+
+  if (trainingType === 'EVALUATION') {
+    tList = [
+      `${evaluateDifficult[configJson.evaluateDifficult]}`,
+      configJson.practiceChapterBegin || configJson.practiceChapterEnd
+        ? `${configJson.practiceChapterBegin}-${configJson.practiceChapterEnd}小节`
+        : '全部小节',
+      // `速度${configJson.evaluateSpeed}`,
+      `${configJson.trainingTimes}分合格`
+    ];
+  } else {
+    tList = [
+      `${configJson.practiceChapterBegin}-${configJson.practiceChapterEnd}小节`,
+      `速度${configJson.practiceSpeed}`,
+      `${configJson.trainingTimes}分钟`
+    ];
+  }
+  return tList;
+};
+
+export default defineComponent({
+  name: 'share-resources',
+  props: {
+    type: {
+      type: String as PropType<'myMusic' | 'sahreMusic' | 'collectMusic'>,
+      default: 'myMusic'
+    },
+    /** 类型 */
+    cardType: {
+      type: String as PropType<'' | 'homerowk-record' | 'prepare'>,
+      default: ''
+    },
+    from: {
+      // 来自哪里
+      type: String,
+      default: ''
+    }
+  },
+  setup(props) {
+    const prepareStore = usePrepareStore();
+    const state = reactive({
+      loading: false,
+      finshed: false, // 是否加载完
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        name: '',
+        type: 'MUSIC', //
+        musicSheetCategoriesId: '',
+        musicalInstrumentId: '',
+        sourceType: formatType(props.type),
+        status: 1,
+        versionFlag: false,
+        musicSubject: null
+      },
+      tableList: [] as any,
+      editStatus: false,
+      editItem: {} as any,
+      show: false,
+      item: {} as any
+    });
+    const getList = async () => {
+      try {
+        if (
+          !prepareStore.getSubjectId &&
+          !['homerowk-record', 'prepare'].includes(props.cardType)
+        )
+          return;
+        if (state.pagination.page === 1) {
+          state.loading = true;
+        }
+        // const { data } = await musicSheetPage({
+        //   ...state.searchGroup,
+        //   ...state.pagination,
+        //   musicSubject: prepareStore.getSubjectId
+        // });
+        const { data } = await materialQueryPage({
+          ...state.searchGroup,
+          ...state.pagination
+          // subjectId: prepareStore.getSubjectId
+        });
+        state.loading = false;
+        const tempRows = data.rows || [];
+        const temp: any = [];
+
+        tempRows.forEach((row: any) => {
+          const index = prepareStore.getTrainList.findIndex(
+            (course: any) => course.musicId === row.id
+          );
+          temp.push({
+            id: row.id,
+            coverImg: row.coverImg || row.musicSvg,
+            type: 'MUSIC',
+            title: row.name,
+            isCollect: !!row.favoriteFlag,
+            refFlag: row.refFlag,
+            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
+            content: row.id,
+            background: row.background,
+            xmlFileUrl: row.xmlFileUrl
+            // exist: index !== -1 ? true : false // 是否存在
+          });
+        });
+        state.tableList.push(...temp);
+        state.finshed = data.pages <= data.current ? true : false;
+      } catch {
+        state.loading = false;
+      }
+    };
+
+    const onSearch = async (item: any) => {
+      state.pagination.page = 1;
+      state.tableList = [];
+      state.searchGroup = Object.assign(state.searchGroup, item);
+      getList();
+    };
+
+    // 声部变化时
+    watch(
+      () => prepareStore.getSubjectId,
+      () => {
+        onSearch(state.searchGroup);
+      }
+    );
+    // watch(
+    //   () => prepareStore.trainList,
+    //   () => {
+    //     state.tableList.forEach((item: any) => {
+    //       const index = prepareStore.getTrainList.findIndex(
+    //         (course: any) => course.musicId === item.id
+    //       );
+    //       item.exist = index !== -1 ? true : false; // 是否存在
+    //     });
+    //   },
+    //   {
+    //     deep: true,
+    //     immediate: true
+    //   }
+    // );
+
+    const throttledFn = useThrottleFn(() => {
+      state.pagination.page = state.pagination.page + 1;
+      getList();
+    }, 500);
+
+    // 添加资源
+    const onAdd = async (item: any) => {
+      let xmlStatus = 'init';
+      // 第一个声部小节
+      let firstMeasures: any = null;
+      try {
+        // 获取文件
+        const res = await requestOrigin.get(item.xmlFileUrl, {
+          mode: 'cors'
+        });
+        const xmlParse = new DOMParser().parseFromString(res, 'text/xml');
+        const parts = xmlParse.getElementsByTagName('part');
+        firstMeasures = parts[0]?.getElementsByTagName('measure');
+        xmlStatus = 'success';
+      } catch (error) {
+        xmlStatus = 'error';
+      }
+
+      // 判断读取小节数
+      if (xmlStatus == 'success') {
+        item.practiceChapterMax = firstMeasures.length;
+      } else {
+        item.practiceChapterMax = 0;
+      }
+      item.coursewareKnowledgeDetailId = prepareStore.getSelectKey;
+      item.subjectId = prepareStore.getSubjectId;
+
+      state.editItem = item;
+      state.editStatus = true;
+    };
+
+    // 收藏
+    const onCollect = async (item: any) => {
+      try {
+        await favorite({
+          materialId: item.id,
+          favoriteFlag: item.isCollect ? 0 : 1,
+          type: item.type
+        });
+        item.isCollect = !item.isCollect;
+      } catch {
+        //
+      }
+    };
+
+    onMounted(() => {
+      getList();
+
+      eventGlobal.on('onTrainDragItem', (item: any, point?: any) => {
+        onAdd(item);
+      });
+    });
+    // 弹窗拖动
+    // 作业设置
+    let workSetingBoxDragData: any;
+    let workSetingBoxClass: string;
+    if (props.from === 'class') {
+      const users = useUserStore();
+      workSetingBoxClass = 'workSetingBoxClass_drag';
+      workSetingBoxDragData = useDrag(
+        [
+          `${workSetingBoxClass}>.n-card-header`,
+          `${workSetingBoxClass} .bom_drag`
+        ],
+        workSetingBoxClass,
+        toRef(state, 'editStatus'),
+        users.info.id
+      );
+    }
+    return () => (
+      <div>
+        <ResourceSearchGroup
+          type={props.type}
+          onSearch={(item: any) => onSearch(item)}
+        />
+        <NScrollbar
+          class={[
+            styles.listContainer,
+            props.type === 'myMusic' ? styles.listNoMusic : ''
+          ]}
+          onScroll={(e: any) => {
+            const clientHeight = e.target?.clientHeight;
+            const scrollTop = e.target?.scrollTop;
+            const scrollHeight = e.target?.scrollHeight;
+            // 是否到底,是否加载完
+            if (
+              clientHeight + scrollTop + 20 >= scrollHeight &&
+              !state.finshed &&
+              !state.loading
+            ) {
+              throttledFn();
+            }
+          }}>
+          <NSpin show={state.loading} size={'small'}>
+            <div
+              class={[
+                styles.listSection,
+                !state.loading && state.tableList.length <= 0
+                  ? styles.emptySection
+                  : ''
+              ]}>
+              {state.tableList.length > 0 && (
+                <div class={styles.list}>
+                  {state.tableList.map((item: any) => (
+                    <CardType
+                      isShowAdd
+                      item={item}
+                      draggable
+                      isShowCollect
+                      // isShowAddDisabled={!prepareStore.getIsEditTrain}
+                      disabledMouseHover={false}
+                      onClick={() => {
+                        if (item.type === 'IMG') return;
+                        state.show = true;
+                        state.item = item;
+                      }}
+                      onAdd={(child: any) => onAdd(child)}
+                      onCollect={(item: any) => onCollect(item)}
+                    />
+                  ))}
+                </div>
+              )}
+              {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
+            </div>
+          </NSpin>
+        </NScrollbar>
+
+        {/* 弹窗查看 */}
+        <CardPreview
+          from={props.from}
+          v-model:show={state.show}
+          item={state.item}
+        />
+
+        <NModal
+          v-model:show={state.editStatus}
+          style={
+            props.from === 'class' ? workSetingBoxDragData.styleDrag.value : {}
+          }
+          class={[
+            'modalTitle background',
+            styles.trainEditModal,
+            workSetingBoxClass
+          ]}
+          preset="card"
+          title="作业设置">
+          <TrainUpdate
+            item={state.editItem}
+            type="homework"
+            onClose={() => (state.editStatus = false)}
+            onConfirm={(item: any) => {
+              // state.editItem = {};
+              // prepareStore.setIsAddTrain(true);
+
+              const tList = typeFormat(
+                item.trainingType,
+                item.trainingConfigJson
+              );
+              //
+              const train = {
+                ...item,
+                id: null,
+                musicName: state.editItem.title,
+                typeList: tList
+              };
+
+              eventGlobal.emit('onTrainAddItem', train);
+            }}
+          />
+          {props.from === 'class' && <Dragbom></Dragbom>}
+        </NModal>
+      </div>
+    );
+  }
+});

+ 229 - 228
src/views/prepare-lessons/model/select-music/select-item/index.tsx

@@ -1,228 +1,229 @@
-import { NScrollbar, NSpin, NTabPane, NTabs } from 'naive-ui';
-import { defineComponent, onMounted, reactive, watch } from 'vue';
-import styles from './index.module.less';
-import CardType from '@/components/card-type';
-import SearchGroup from './search-group';
-import TheEmpty from '/src/components/TheEmpty';
-import { useDebounceFn, useThrottleFn, useResizeObserver } from '@vueuse/core';
-import { usePrepareStore } from '/src/store/modules/prepareLessons';
-import { musicSheetPage } from '../../../api';
-import CardPreview from '/src/components/card-preview';
-import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
-
-const formatType = (type: string) => {
-  if (type === 'shareResources') {
-    return 2;
-  } else if (type === 'myResources') {
-    return 3;
-  } else if (type === 'myCollect') {
-    return 4;
-  }
-};
-
-export default defineComponent({
-  name: 'select-music',
-  props: {
-    type: {
-      type: String,
-      default: ''
-    },
-    from: {
-      type: String,
-      default: ''
-    }
-  },
-  emits: ['add'],
-  setup(props, { emit }) {
-    const prepareStore = usePrepareStore();
-    const state = reactive({
-      searchHeight: '0px',
-      loading: false,
-      finshed: false, // 是否加载完
-      pagination: {
-        page: 1,
-        rows: 20
-      },
-      searchGroup: {
-        name: '',
-        type: 'MUSIC', //
-        musicSheetCategoriesId: '',
-        musicalInstrumentId: '',
-        sourceType: formatType(props.type),
-        status: 1,
-        versionFlag: false,
-        subjectId: null
-      },
-      tableList: [] as any,
-      show: false,
-      item: {} as any,
-      isShowAddDisabled: !prepareStore.getIsEditTrain
-    });
-    const className = 'musicSearchGroup' + +new Date();
-    const getList = async () => {
-      try {
-        if (state.pagination.page === 1) {
-          state.loading = true;
-        }
-        const { data } = await materialQueryPage({
-          ...state.searchGroup,
-          ...state.pagination
-        });
-        state.loading = false;
-        if (data.current === 1 && state.tableList.length > 0) return;
-        const tempRows = data.rows || [];
-        const temp: any = [];
-        tempRows.forEach((row: any) => {
-          const index = prepareStore.getTrainList.findIndex(
-            (course: any) => course.musicId === row.id
-          );
-          temp.push({
-            id: row.id,
-            coverImg: row.coverImg || row.musicSvg,
-            type: 'MUSIC',
-            title: row.name,
-            isCollect: !!row.favoriteFlag,
-            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
-            refFlag: row.refFlag,
-            content: row.id,
-            xmlFileUrl: row.xmlFileUrl,
-            exist: index !== -1 ? true : false // 是否存在
-          });
-        });
-        state.tableList.push(...temp);
-
-        state.finshed = data.pages <= data.current ? true : false;
-      } catch {
-        state.loading = false;
-      }
-    };
-
-    watch(
-      () => prepareStore.trainList,
-      () => {
-        state.tableList.forEach((item: any) => {
-          const index = prepareStore.getTrainList.findIndex(
-            (course: any) => course.musicId === item.id
-          );
-          item.exist = index !== -1 ? true : false; // 是否存在
-        });
-      },
-      {
-        deep: true,
-        immediate: true
-      }
-    );
-
-    const throttledFnSearch = useDebounceFn(item => {
-      state.pagination.page = 1;
-      state.tableList = [];
-      state.searchGroup = Object.assign(state.searchGroup, item);
-      getList();
-    }, 500);
-
-    const throttledFn = useThrottleFn(() => {
-      state.pagination.page = state.pagination.page + 1;
-      getList();
-    }, 500);
-
-    // 收藏
-    const onCollect = async (item: any) => {
-      try {
-        await favorite({
-          materialId: item.id,
-          favoriteFlag: item.isCollect ? 0 : 1,
-          type: item.type
-        });
-        item.isCollect = !item.isCollect;
-      } catch {
-        //
-      }
-    };
-
-    onMounted(() => {
-      useResizeObserver(
-        document.querySelector('.' + className) as HTMLElement,
-        (entries: any) => {
-          const entry = entries[0];
-          const { height } = entry.contentRect;
-          state.searchHeight = height + 'px';
-        }
-      );
-      if (props.type === 'homework') {
-        state.isShowAddDisabled = false;
-      }
-      getList();
-    });
-    return () => (
-      <div class={styles.selectMusic}>
-        <div class={className}>
-          <SearchGroup
-            type={props.type}
-            onSearch={(item: any) => throttledFnSearch(item)}
-          />
-        </div>
-
-        <NScrollbar
-          class={styles.listContainer}
-          style={{
-            'max-height': `calc(85vh - var(--modal-lesson-tab-height) - ${state.searchHeight} - 12px) `
-          }}
-          onScroll={(e: any) => {
-            const clientHeight = e.target?.clientHeight;
-            const scrollTop = e.target?.scrollTop;
-            const scrollHeight = e.target?.scrollHeight;
-            // 是否到底,是否加载完
-            if (
-              clientHeight + scrollTop + 20 >= scrollHeight &&
-              !state.finshed &&
-              !state.loading
-            ) {
-              throttledFn();
-            }
-          }}>
-          <NSpin show={state.loading} size={'small'}>
-            <div
-              style={{
-                'min-height': `calc(85vh - var(--modal-lesson-tab-height) - ${state.searchHeight} - 12px)`
-              }}
-              class={[
-                styles.listSection,
-                !state.loading && state.tableList.length <= 0
-                  ? styles.emptySection
-                  : ''
-              ]}>
-              {state.tableList.length > 0 && (
-                <div class={styles.list}>
-                  {state.tableList.map((item: any) => (
-                    <CardType
-                      isShowAdd
-                      isShowCollect
-                      item={item}
-                      // isShowAddDisabled={state.isShowAddDisabled}
-                      onAdd={() => emit('add', item)}
-                      disabledMouseHover={false}
-                      onClick={() => {
-                        if (item.type === 'IMG') return;
-                        state.show = true;
-                        state.item = item;
-                      }}
-                      onCollect={(item: any) => onCollect(item)}
-                    />
-                  ))}
-                </div>
-              )}
-              {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
-            </div>
-          </NSpin>
-        </NScrollbar>
-
-        {/* 弹窗查看 */}
-        <CardPreview
-          from={props.from}
-          v-model:show={state.show}
-          item={state.item}
-        />
-      </div>
-    );
-  }
-});
+import { NScrollbar, NSpin, NTabPane, NTabs } from 'naive-ui';
+import { defineComponent, onMounted, reactive, watch } from 'vue';
+import styles from './index.module.less';
+import CardType from '@/components/card-type';
+import SearchGroup from './search-group';
+import TheEmpty from '/src/components/TheEmpty';
+import { useDebounceFn, useThrottleFn, useResizeObserver } from '@vueuse/core';
+import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import { musicSheetPage } from '../../../api';
+import CardPreview from '/src/components/card-preview';
+import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
+
+const formatType = (type: string) => {
+  if (type === 'shareResources') {
+    return 2;
+  } else if (type === 'myResources') {
+    return 3;
+  } else if (type === 'myCollect') {
+    return 4;
+  }
+};
+
+export default defineComponent({
+  name: 'select-music',
+  props: {
+    type: {
+      type: String,
+      default: ''
+    },
+    from: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['add'],
+  setup(props, { emit }) {
+    const prepareStore = usePrepareStore();
+    const state = reactive({
+      searchHeight: '0px',
+      loading: false,
+      finshed: false, // 是否加载完
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        name: '',
+        type: 'MUSIC', //
+        musicSheetCategoriesId: '',
+        musicalInstrumentId: '',
+        sourceType: formatType(props.type),
+        status: 1,
+        versionFlag: false,
+        subjectId: null
+      },
+      tableList: [] as any,
+      show: false,
+      item: {} as any,
+      isShowAddDisabled: !prepareStore.getIsEditTrain
+    });
+    const className = 'musicSearchGroup' + +new Date();
+    const getList = async () => {
+      try {
+        if (state.pagination.page === 1) {
+          state.loading = true;
+        }
+        const { data } = await materialQueryPage({
+          ...state.searchGroup,
+          ...state.pagination
+        });
+        state.loading = false;
+        if (data.current === 1 && state.tableList.length > 0) return;
+        const tempRows = data.rows || [];
+        const temp: any = [];
+        tempRows.forEach((row: any) => {
+          const index = prepareStore.getTrainList.findIndex(
+            (course: any) => course.musicId === row.id
+          );
+          temp.push({
+            id: row.id,
+            coverImg: row.coverImg || row.musicSvg,
+            type: 'MUSIC',
+            title: row.name,
+            isCollect: !!row.favoriteFlag,
+            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
+            refFlag: row.refFlag,
+            content: row.id,
+            xmlFileUrl: row.xmlFileUrl,
+            background: row.background,
+            exist: index !== -1 ? true : false // 是否存在
+          });
+        });
+        state.tableList.push(...temp);
+
+        state.finshed = data.pages <= data.current ? true : false;
+      } catch {
+        state.loading = false;
+      }
+    };
+
+    watch(
+      () => prepareStore.trainList,
+      () => {
+        state.tableList.forEach((item: any) => {
+          const index = prepareStore.getTrainList.findIndex(
+            (course: any) => course.musicId === item.id
+          );
+          item.exist = index !== -1 ? true : false; // 是否存在
+        });
+      },
+      {
+        deep: true,
+        immediate: true
+      }
+    );
+
+    const throttledFnSearch = useDebounceFn(item => {
+      state.pagination.page = 1;
+      state.tableList = [];
+      state.searchGroup = Object.assign(state.searchGroup, item);
+      getList();
+    }, 500);
+
+    const throttledFn = useThrottleFn(() => {
+      state.pagination.page = state.pagination.page + 1;
+      getList();
+    }, 500);
+
+    // 收藏
+    const onCollect = async (item: any) => {
+      try {
+        await favorite({
+          materialId: item.id,
+          favoriteFlag: item.isCollect ? 0 : 1,
+          type: item.type
+        });
+        item.isCollect = !item.isCollect;
+      } catch {
+        //
+      }
+    };
+
+    onMounted(() => {
+      useResizeObserver(
+        document.querySelector('.' + className) as HTMLElement,
+        (entries: any) => {
+          const entry = entries[0];
+          const { height } = entry.contentRect;
+          state.searchHeight = height + 'px';
+        }
+      );
+      if (props.type === 'homework') {
+        state.isShowAddDisabled = false;
+      }
+      getList();
+    });
+    return () => (
+      <div class={styles.selectMusic}>
+        <div class={className}>
+          <SearchGroup
+            type={props.type}
+            onSearch={(item: any) => throttledFnSearch(item)}
+          />
+        </div>
+
+        <NScrollbar
+          class={styles.listContainer}
+          style={{
+            'max-height': `calc(85vh - var(--modal-lesson-tab-height) - ${state.searchHeight} - 12px) `
+          }}
+          onScroll={(e: any) => {
+            const clientHeight = e.target?.clientHeight;
+            const scrollTop = e.target?.scrollTop;
+            const scrollHeight = e.target?.scrollHeight;
+            // 是否到底,是否加载完
+            if (
+              clientHeight + scrollTop + 20 >= scrollHeight &&
+              !state.finshed &&
+              !state.loading
+            ) {
+              throttledFn();
+            }
+          }}>
+          <NSpin show={state.loading} size={'small'}>
+            <div
+              style={{
+                'min-height': `calc(85vh - var(--modal-lesson-tab-height) - ${state.searchHeight} - 12px)`
+              }}
+              class={[
+                styles.listSection,
+                !state.loading && state.tableList.length <= 0
+                  ? styles.emptySection
+                  : ''
+              ]}>
+              {state.tableList.length > 0 && (
+                <div class={styles.list}>
+                  {state.tableList.map((item: any) => (
+                    <CardType
+                      isShowAdd
+                      isShowCollect
+                      item={item}
+                      // isShowAddDisabled={state.isShowAddDisabled}
+                      onAdd={() => emit('add', item)}
+                      disabledMouseHover={false}
+                      onClick={() => {
+                        if (item.type === 'IMG') return;
+                        state.show = true;
+                        state.item = item;
+                      }}
+                      onCollect={(item: any) => onCollect(item)}
+                    />
+                  ))}
+                </div>
+              )}
+              {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
+            </div>
+          </NSpin>
+        </NScrollbar>
+
+        {/* 弹窗查看 */}
+        <CardPreview
+          from={props.from}
+          v-model:show={state.show}
+          item={state.item}
+        />
+      </div>
+    );
+  }
+});

+ 318 - 317
src/views/prepare-lessons/model/select-resources/select-item/index.tsx

@@ -1,317 +1,318 @@
-import {
-  PropType,
-  defineComponent,
-  onMounted,
-  onUnmounted,
-  reactive,
-  toRefs,
-  watch
-} from 'vue';
-import ResourceSearchGroup from './resource-search-group';
-import { NScrollbar, NSpin, useMessage } from 'naive-ui';
-import styles from './index.module.less';
-import CardType from '/src/components/card-type';
-import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
-import TheEmpty from '/src/components/TheEmpty';
-import { usePrepareStore } from '/src/store/modules/prepareLessons';
-import { useDebounceFn, useResizeObserver } from '@vueuse/core';
-import CardPreview from '/src/components/card-preview';
-import { eventGlobal } from '/src/utils';
-import ClassSearchGroup from './class-search-group';
-import { useCatchStore } from '/src/store/modules/catchData';
-
-const formatType = (type: string) => {
-  if (type === 'shareResources') {
-    return 2;
-  } else if (type === 'myResources') {
-    return 3;
-  } else if (type === 'myCollect') {
-    return 4;
-  } else if (type === 'relateResources') {
-    return 5;
-  }
-};
-
-export default defineComponent({
-  name: 'share-resources',
-  props: {
-    type: {
-      type: String as PropType<
-        'relateResources' | 'shareResources' | 'myResources' | 'myCollect'
-      >,
-      default: 'shareResources'
-    },
-    /** 从哪里使用 */
-    from: {
-      type: String,
-      default: ''
-    }
-  },
-  setup(props) {
-    const prepareStore = usePrepareStore();
-    const catchStore = useCatchStore();
-    const message = useMessage();
-    const { type } = toRefs(props);
-    const className = 'resourceSearchGroup' + +new Date();
-    const state = reactive({
-      searchHeight: '0px',
-      loading: false,
-      finshed: false, // 是否加载完
-      pagination: {
-        page: 1,
-        rows: 20
-      },
-      searchGroup: {
-        type: 'MUSIC', //
-        name: '',
-        bookVersionId: null,
-        subjectId: null,
-        sourceType: formatType(type.value),
-        musicalInstrumentId: null as any,
-        enableFlag: true
-      },
-      tableList: [] as any,
-      show: false,
-      item: {} as any
-    });
-
-    // 查询列表
-    const getList = async () => {
-      try {
-        if (state.pagination.page === 1) {
-          state.loading = true;
-        }
-        const { data } = await materialQueryPage({
-          ...state.searchGroup,
-          ...state.pagination,
-          lessonCoursewareKnowledgeId:
-            props.type === 'relateResources' || props.type === 'shareResources'
-              ? prepareStore.getSelectKey
-              : null,
-          relateLessonCoursewareKnowledgeMaterialIds: getIds()
-        });
-        state.loading = false;
-        const tempRows = data.rows || [];
-        const temp: any = [];
-        tempRows.forEach((row: any) => {
-          temp.push({
-            id: row.id,
-            coverImg: row.coverImg,
-            type: row.type,
-            title: row.name,
-            isCollect: !!row.favoriteFlag,
-            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
-            refFlag: row.refFlag,
-            content: row.content
-          });
-        });
-        state.tableList.push(...temp);
-
-        state.finshed = data.pages <= data.current ? true : false;
-      } catch {
-        state.loading = false;
-      }
-    };
-
-    const throttledFnSearch = useDebounceFn(item => {
-      state.pagination.page = 1;
-      state.tableList = [];
-      const { subjectId, ...res } = item;
-      state.searchGroup = Object.assign(state.searchGroup, {
-        ...res,
-        musicalInstrumentId: subjectId,
-        subjectId: null
-      });
-      getList();
-    }, 500);
-
-    // 添加资源
-    const onAdd = async (item: any) => {
-      try {
-        eventGlobal.emit('onPrepareAddItem', {
-          materialId: item.id,
-          coverImg: item.coverImg,
-          type: item.type,
-          title: item.title,
-          refFlag: item.refFlag,
-          isCollect: item.isCollect,
-          isSelected: item.isSelected,
-          content: item.content,
-          removeFlag: false
-        });
-      } catch {
-        //
-      }
-    };
-
-    // 收藏
-    const onCollect = async (item: any) => {
-      try {
-        await favorite({
-          materialId: item.id,
-          favoriteFlag: item.isCollect ? 0 : 1,
-          type: item.type
-        });
-        item.isCollect = !item.isCollect;
-      } catch {
-        //
-      }
-    };
-
-    const getIds = () => {
-      let noRepeatIds: any = [];
-      if (props.type === 'relateResources') {
-        const materialIds: any = [];
-        prepareStore.getCoursewareList.forEach((course: any) => {
-          course.list?.forEach((item: any) => {
-            materialIds.push(item.materialId);
-          });
-        });
-        noRepeatIds = Array(...new Set(materialIds));
-      }
-      return noRepeatIds.join(',');
-    };
-
-    const onUpdate = () => {
-      state.pagination.page = 1;
-      state.tableList = [];
-      getList();
-    };
-
-    onMounted(async () => {
-      // 加载的时候判断是否有资源数据
-      // 获取声部
-      await catchStore.getSubjects();
-
-      useResizeObserver(
-        document.querySelector('.' + className) as HTMLElement,
-        (entries: any) => {
-          const entry = entries[0];
-          const { height } = entry.contentRect;
-          state.searchHeight = height + 'px';
-        }
-      );
-      getList();
-
-      if (props.type === 'relateResources') {
-        eventGlobal.on('onCoursewareUpdate', onUpdate);
-      }
-    });
-    onUnmounted(() => {
-      eventGlobal.off('onCoursewareUpdate', onUpdate);
-    });
-
-    // onMounted(async () => {
-    //   // 获取声部
-    //   await catchStore.getSubjects();
-
-    //   // 加载的时候判断是否有资源数据
-    //   let noRepeatIds: any = [];
-    //   if (props.type === 'relateResources') {
-    //     const materialIds: any = [];
-    //     prepareStore.getCoursewareList.forEach((course: any) => {
-    //       course.list?.forEach((item: any) => {
-    //         materialIds.push(item.materialId);
-    //       });
-    //     });
-    //     noRepeatIds = Array(...new Set(materialIds));
-    //   }
-    //   getList(noRepeatIds.join(','));
-
-    //   useResizeObserver(
-    //     document.querySelector('.' + className) as HTMLElement,
-    //     (entries: any) => {
-    //       const entry = entries[0];
-    //       const { height } = entry.contentRect;
-    //       state.searchHeight = height + 'px';
-    //     }
-    //   );
-    // });
-    return () => (
-      <div>
-        <div class={className}>
-          {props.from === 'class' ? (
-            <ClassSearchGroup
-              type={props.type}
-              subjectId={prepareStore.getSubjectId as any}
-              onSearch={(item: any) => throttledFnSearch(item)}
-            />
-          ) : (
-            <ResourceSearchGroup
-              type={props.type}
-              // subjectId={prepareStore.getSubjectId as any}
-              onSearch={(item: any) => throttledFnSearch(item)}
-            />
-          )}
-        </div>
-        <NScrollbar
-          class={[styles.listContainer, 'list_container']}
-          style={{
-            'max-height': `calc(var(--listContainerHeight) - var(--modal-lesson-tab-height) - ${state.searchHeight}) `
-          }}
-          onScroll={(e: any) => {
-            const clientHeight = e.target?.clientHeight;
-            const scrollTop = e.target?.scrollTop;
-            const scrollHeight = e.target?.scrollHeight;
-            // 是否到底,是否加载完
-            if (
-              clientHeight + scrollTop + 20 >= scrollHeight &&
-              !state.finshed &&
-              !state.loading
-            ) {
-              state.pagination.page = state.pagination.page + 1;
-              getList();
-            }
-          }}>
-          <NSpin show={state.loading} size={'small'}>
-            <div
-              style={{
-                'min-height': `calc(var(--listContainerHeight) - var(--modal-lesson-tab-height) - ${state.searchHeight})`
-              }}
-              class={[
-                styles.listSection,
-                !state.loading && state.tableList.length <= 0
-                  ? styles.emptySection
-                  : ''
-              ]}>
-              {state.tableList.length > 0 && (
-                <div class={styles.list}>
-                  {state.tableList.map((item: any) => (
-                    <div class={[styles.itemWrap, 'selresources_item_Wrap']}>
-                      <div class={styles.itemWrapBox}>
-                        <CardType
-                          isShowAdd={props.from === 'class' ? false : true}
-                          item={item}
-                          isShowCollect={true}
-                          // isShowAddDisabled={!prepareStore.getIsEditResource}
-                          onAdd={(item: any) => onAdd(item)}
-                          disabledMouseHover={false}
-                          onCollect={(item: any) => onCollect(item)}
-                          onClick={() => {
-                            if (item.type === 'IMG') return;
-                            state.show = true;
-                            state.item = item;
-                          }}
-                        />
-                      </div>
-                    </div>
-                  ))}
-                </div>
-              )}
-
-              {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
-            </div>
-          </NSpin>
-        </NScrollbar>
-
-        {/* 弹窗查看 */}
-        <CardPreview
-          size={props.from === 'class' ? 'large' : 'default'}
-          v-model:show={state.show}
-          from={props.from}
-          item={state.item}
-        />
-      </div>
-    );
-  }
-});
+import {
+  PropType,
+  defineComponent,
+  onMounted,
+  onUnmounted,
+  reactive,
+  toRefs,
+  watch
+} from 'vue';
+import ResourceSearchGroup from './resource-search-group';
+import { NScrollbar, NSpin, useMessage } from 'naive-ui';
+import styles from './index.module.less';
+import CardType from '/src/components/card-type';
+import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
+import TheEmpty from '/src/components/TheEmpty';
+import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import { useDebounceFn, useResizeObserver } from '@vueuse/core';
+import CardPreview from '/src/components/card-preview';
+import { eventGlobal } from '/src/utils';
+import ClassSearchGroup from './class-search-group';
+import { useCatchStore } from '/src/store/modules/catchData';
+
+const formatType = (type: string) => {
+  if (type === 'shareResources') {
+    return 2;
+  } else if (type === 'myResources') {
+    return 3;
+  } else if (type === 'myCollect') {
+    return 4;
+  } else if (type === 'relateResources') {
+    return 5;
+  }
+};
+
+export default defineComponent({
+  name: 'share-resources',
+  props: {
+    type: {
+      type: String as PropType<
+        'relateResources' | 'shareResources' | 'myResources' | 'myCollect'
+      >,
+      default: 'shareResources'
+    },
+    /** 从哪里使用 */
+    from: {
+      type: String,
+      default: ''
+    }
+  },
+  setup(props) {
+    const prepareStore = usePrepareStore();
+    const catchStore = useCatchStore();
+    const message = useMessage();
+    const { type } = toRefs(props);
+    const className = 'resourceSearchGroup' + +new Date();
+    const state = reactive({
+      searchHeight: '0px',
+      loading: false,
+      finshed: false, // 是否加载完
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        type: 'MUSIC', //
+        name: '',
+        bookVersionId: null,
+        subjectId: null,
+        sourceType: formatType(type.value),
+        musicalInstrumentId: null as any,
+        enableFlag: true
+      },
+      tableList: [] as any,
+      show: false,
+      item: {} as any
+    });
+
+    // 查询列表
+    const getList = async () => {
+      try {
+        if (state.pagination.page === 1) {
+          state.loading = true;
+        }
+        const { data } = await materialQueryPage({
+          ...state.searchGroup,
+          ...state.pagination,
+          lessonCoursewareKnowledgeId:
+            props.type === 'relateResources' || props.type === 'shareResources'
+              ? prepareStore.getSelectKey
+              : null,
+          relateLessonCoursewareKnowledgeMaterialIds: getIds()
+        });
+        state.loading = false;
+        const tempRows = data.rows || [];
+        const temp: any = [];
+        tempRows.forEach((row: any) => {
+          temp.push({
+            id: row.id,
+            coverImg: row.coverImg,
+            type: row.type,
+            title: row.name,
+            isCollect: !!row.favoriteFlag,
+            isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
+            refFlag: row.refFlag,
+            background: row.background,
+            content: row.content
+          });
+        });
+        state.tableList.push(...temp);
+
+        state.finshed = data.pages <= data.current ? true : false;
+      } catch {
+        state.loading = false;
+      }
+    };
+
+    const throttledFnSearch = useDebounceFn(item => {
+      state.pagination.page = 1;
+      state.tableList = [];
+      const { subjectId, ...res } = item;
+      state.searchGroup = Object.assign(state.searchGroup, {
+        ...res,
+        musicalInstrumentId: subjectId,
+        subjectId: null
+      });
+      getList();
+    }, 500);
+
+    // 添加资源
+    const onAdd = async (item: any) => {
+      try {
+        eventGlobal.emit('onPrepareAddItem', {
+          materialId: item.id,
+          coverImg: item.coverImg,
+          type: item.type,
+          title: item.title,
+          refFlag: item.refFlag,
+          isCollect: item.isCollect,
+          isSelected: item.isSelected,
+          content: item.content,
+          removeFlag: false
+        });
+      } catch {
+        //
+      }
+    };
+
+    // 收藏
+    const onCollect = async (item: any) => {
+      try {
+        await favorite({
+          materialId: item.id,
+          favoriteFlag: item.isCollect ? 0 : 1,
+          type: item.type
+        });
+        item.isCollect = !item.isCollect;
+      } catch {
+        //
+      }
+    };
+
+    const getIds = () => {
+      let noRepeatIds: any = [];
+      if (props.type === 'relateResources') {
+        const materialIds: any = [];
+        prepareStore.getCoursewareList.forEach((course: any) => {
+          course.list?.forEach((item: any) => {
+            materialIds.push(item.materialId);
+          });
+        });
+        noRepeatIds = Array(...new Set(materialIds));
+      }
+      return noRepeatIds.join(',');
+    };
+
+    const onUpdate = () => {
+      state.pagination.page = 1;
+      state.tableList = [];
+      getList();
+    };
+
+    onMounted(async () => {
+      // 加载的时候判断是否有资源数据
+      // 获取声部
+      await catchStore.getSubjects();
+
+      useResizeObserver(
+        document.querySelector('.' + className) as HTMLElement,
+        (entries: any) => {
+          const entry = entries[0];
+          const { height } = entry.contentRect;
+          state.searchHeight = height + 'px';
+        }
+      );
+      getList();
+
+      if (props.type === 'relateResources') {
+        eventGlobal.on('onCoursewareUpdate', onUpdate);
+      }
+    });
+    onUnmounted(() => {
+      eventGlobal.off('onCoursewareUpdate', onUpdate);
+    });
+
+    // onMounted(async () => {
+    //   // 获取声部
+    //   await catchStore.getSubjects();
+
+    //   // 加载的时候判断是否有资源数据
+    //   let noRepeatIds: any = [];
+    //   if (props.type === 'relateResources') {
+    //     const materialIds: any = [];
+    //     prepareStore.getCoursewareList.forEach((course: any) => {
+    //       course.list?.forEach((item: any) => {
+    //         materialIds.push(item.materialId);
+    //       });
+    //     });
+    //     noRepeatIds = Array(...new Set(materialIds));
+    //   }
+    //   getList(noRepeatIds.join(','));
+
+    //   useResizeObserver(
+    //     document.querySelector('.' + className) as HTMLElement,
+    //     (entries: any) => {
+    //       const entry = entries[0];
+    //       const { height } = entry.contentRect;
+    //       state.searchHeight = height + 'px';
+    //     }
+    //   );
+    // });
+    return () => (
+      <div>
+        <div class={className}>
+          {props.from === 'class' ? (
+            <ClassSearchGroup
+              type={props.type}
+              subjectId={prepareStore.getSubjectId as any}
+              onSearch={(item: any) => throttledFnSearch(item)}
+            />
+          ) : (
+            <ResourceSearchGroup
+              type={props.type}
+              // subjectId={prepareStore.getSubjectId as any}
+              onSearch={(item: any) => throttledFnSearch(item)}
+            />
+          )}
+        </div>
+        <NScrollbar
+          class={[styles.listContainer, 'list_container']}
+          style={{
+            'max-height': `calc(var(--listContainerHeight) - var(--modal-lesson-tab-height) - ${state.searchHeight}) `
+          }}
+          onScroll={(e: any) => {
+            const clientHeight = e.target?.clientHeight;
+            const scrollTop = e.target?.scrollTop;
+            const scrollHeight = e.target?.scrollHeight;
+            // 是否到底,是否加载完
+            if (
+              clientHeight + scrollTop + 20 >= scrollHeight &&
+              !state.finshed &&
+              !state.loading
+            ) {
+              state.pagination.page = state.pagination.page + 1;
+              getList();
+            }
+          }}>
+          <NSpin show={state.loading} size={'small'}>
+            <div
+              style={{
+                'min-height': `calc(var(--listContainerHeight) - var(--modal-lesson-tab-height) - ${state.searchHeight})`
+              }}
+              class={[
+                styles.listSection,
+                !state.loading && state.tableList.length <= 0
+                  ? styles.emptySection
+                  : ''
+              ]}>
+              {state.tableList.length > 0 && (
+                <div class={styles.list}>
+                  {state.tableList.map((item: any) => (
+                    <div class={[styles.itemWrap, 'selresources_item_Wrap']}>
+                      <div class={styles.itemWrapBox}>
+                        <CardType
+                          isShowAdd={props.from === 'class' ? false : true}
+                          item={item}
+                          isShowCollect={true}
+                          // isShowAddDisabled={!prepareStore.getIsEditResource}
+                          onAdd={(item: any) => onAdd(item)}
+                          disabledMouseHover={false}
+                          onCollect={(item: any) => onCollect(item)}
+                          onClick={() => {
+                            if (item.type === 'IMG') return;
+                            state.show = true;
+                            state.item = item;
+                          }}
+                        />
+                      </div>
+                    </div>
+                  ))}
+                </div>
+              )}
+
+              {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
+            </div>
+          </NSpin>
+        </NScrollbar>
+
+        {/* 弹窗查看 */}
+        <CardPreview
+          size={props.from === 'class' ? 'large' : 'default'}
+          v-model:show={state.show}
+          from={props.from}
+          item={state.item}
+        />
+      </div>
+    );
+  }
+});