Pārlūkot izejas kodu

Merge branch 'video-tcplayer' into jenkins

lex 1 gadu atpakaļ
vecāks
revīzija
c2d4d421c9

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

@@ -81,7 +81,7 @@ export default defineComponent({
         });
         item.isCollect = !item.isCollect;
 
-        onSearch(state.searchGroup);
+        // onSearch(state.searchGroup);
       } catch {
         //
       }

+ 2 - 2
src/views/natural-resources/components/share-resources/search-group-resources.tsx

@@ -112,7 +112,7 @@ export default defineComponent({
             ))}
           </NSpace>
 
-          <NButton
+          {/* <NButton
             type="primary"
             class={styles.addTrain}
             focusable={false}
@@ -120,7 +120,7 @@ export default defineComponent({
             onClick={() => emit('add')}>
             <img src={iconAdd} />
             添加自定义教材
-          </NButton>
+          </NButton> */}
         </div>
         <NForm labelAlign="left" labelPlacement="left">
           {forms.type === 'MUSIC' && (

+ 22 - 19
src/views/notation/index.tsx

@@ -15,24 +15,26 @@ export default defineComponent({
     const Authorization = userStore.getToken || '';
     const iframeRef = ref();
     console.log(Authorization);
+    const notationOpenCreate = sessionStorage.getItem('notation-open-create');
+    const openCreateUrl = notationOpenCreate == '1' ? '&addShow=1' : '';
     const data = reactive({
       src: `${
         /(192|localhost)/.test(location.origin)
           ? // ?
-          // 'https://test.lexiaoya.cn'
-            'http://localhost:3050'
-          : location.origin
-      }/notation/#/create?Authorization=${Authorization}`
+            'https://test.lexiaoya.cn'
+          : // 'http://localhost:3050'
+            location.origin
+      }/notation/#/create?Authorization=${Authorization}${openCreateUrl}`
       //   src: `http://localhost:3050/#/create?Authorization=${Authorization}`
     });
-    const fscreen=()=> {
-      const el = document.documentElement as any
-        //进入全屏
-        (el.requestFullscreen && el.requestFullscreen()) ||
+    const fscreen = () => {
+      const el = document.documentElement as any;
+      //进入全屏
+      (el.requestFullscreen && el.requestFullscreen()) ||
         (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
         (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
-        (el.msRequestFullscreen && el.msRequestFullscreen())
-       }
+        (el.msRequestFullscreen && el.msRequestFullscreen());
+    };
     const handleOpen = (e: MessageEvent) => {
       console.log(e.data, 'data');
       if (e.data.api === 'notation_open') {
@@ -42,12 +44,12 @@ export default defineComponent({
           previewParams.value = {
             url: e.data.url
           };
-          fscreen()
+          fscreen();
         } else {
           window.open(e.data.url);
         }
       } else if (e.data.api === 'notation_exit') {
-        console.log('进来')
+        console.log('进来');
 
         removeVisiable.value = true;
       }
@@ -100,13 +102,14 @@ export default defineComponent({
                   );
                   if (state.application) {
                     document.exitFullscreen
-                    ? document.exitFullscreen()
-                    : document.mozCancelFullScreen
-                    ? document.mozCancelFullScreen()
-                    : document.webkitExitFullscreen
-                    ? document.webkitExitFullscreen()
-                    : ''
-                }}}>
+                      ? document.exitFullscreen()
+                      : document.mozCancelFullScreen
+                      ? document.mozCancelFullScreen()
+                      : document.webkitExitFullscreen
+                      ? document.webkitExitFullscreen()
+                      : '';
+                  }
+                }}>
                 确定
               </NButton>
               <NButton round onClick={() => (removeVisiable.value = false)}>

+ 35 - 0
src/views/prepare-lessons/components/lesson-main/courseware/index.module.less

@@ -285,6 +285,41 @@
   }
 }
 
+.addMusicItem {
+  position: relative;
+  box-sizing: border-box;
+  width: 300px;
+  height: 220px;
+  border-radius: 14px;
+  background: #F9FAFD;
+  display: inline-flex;
+  transition: all .3s ease-in-out;
+  border: 2px solid rgba(209, 216, 235, 1) !important;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+
+  img {
+    width: 50px;
+    height: 50px;
+  }
+
+  .addMusicName {
+    padding-top: 16px;
+    font-size: 16px;
+    color: #131415;
+  }
+
+  // 鼠标经过时样式
+  &:hover {
+    transform: scale(1.01);
+    transition: all .3s ease-in-out;
+    border: 2px solid rgba(0, 122, 254, 1) !important;
+  }
+}
+
 
 .subjectSyncModal {
   width: 920px;

+ 65 - 13
src/views/prepare-lessons/components/lesson-main/courseware/index.tsx

@@ -23,6 +23,7 @@ import {
 } from '../../../api';
 import Draggable from 'vuedraggable';
 import iconDelete from '../../../images/icon-delete.png';
+import iconAddMusic from '../../../images/icon-add-music.png';
 import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
 import deepClone from '/src/helpers/deep-clone';
 import CardPreview from '/src/components/card-preview';
@@ -40,10 +41,20 @@ export default defineComponent({
     const router = useRouter();
     const dialog = useDialog();
     const message = useMessage();
+
+    const localStorageSubjectId = localStorage.getItem(
+      'prepareLessonSubjectId'
+    );
+
     const forms = reactive({
       className: route.query.name as any,
       classGroupId: route.query.classGroupId,
-      subjectId: route.query.subjectId ? Number(route.query.subjectId) : null,
+      // 选取参数带的,后取缓存
+      subjectId: route.query.subjectId
+        ? Number(route.query.subjectId)
+        : localStorageSubjectId
+        ? Number(localStorageSubjectId)
+        : null,
       coursewareList: [] as any,
       loadingStatus: false,
       showAttendClass: false,
@@ -281,20 +292,31 @@ export default defineComponent({
 
       // 并且没有声部时才会更新
       if (subjectList.length > 0) {
+        // 并且声部在列表中
+        const localStorageSubjectId = localStorage.getItem(
+          'prepareLessonSubjectId'
+        );
+        const subjectId =
+          forms.subjectId || localStorageSubjectId
+            ? Number(localStorageSubjectId)
+            : null;
         // 判断浏览器上面是否有
         const index = subjectList.findIndex(
-          (subject: any) => subject.id == forms.subjectId
+          (subject: any) => subject.id == subjectId
         );
 
-        // 并且声部在列表中
-        if (forms.subjectId && index >= 0) {
-          prepareStore.setSubjectId(forms.subjectId);
+        if (subjectId && index >= 0) {
+          prepareStore.setSubjectId(subjectId);
         } else {
           // 判断是否有缓存
           prepareStore.setSubjectId(subjectList[0].id);
         }
 
-        // console.log(prepareStore.getSubjectId, 'getSubjectId');
+        // 保存
+        localStorage.setItem(
+          'prepareLessonSubjectId',
+          prepareStore.getSubjectId as any
+        );
       }
     };
 
@@ -367,6 +389,8 @@ export default defineComponent({
                   value={prepareStore.getSubjectId}
                   onUpdate:value={(val: any) => {
                     prepareStore.setSubjectId(val);
+                    // 保存
+                    localStorage.setItem('prepareLessonSubjectId', val);
                     getList();
                   }}
                 />
@@ -432,10 +456,10 @@ export default defineComponent({
           <NSpin show={forms.loadingStatus}>
             <div
               class={[
-                styles.listSection,
-                !forms.loadingStatus && forms.coursewareList.length <= 0
-                  ? styles.emptySection
-                  : ''
+                styles.listSection
+                // !forms.loadingStatus && forms.coursewareList.length <= 0
+                //   ? styles.emptySection
+                //   : ''
               ]}>
               {forms.coursewareList.length > 0 && (
                 <>
@@ -497,13 +521,43 @@ export default defineComponent({
                           }}
                         />
                       ))}
+                      <div
+                        class={[
+                          styles.itemContent,
+                          styles.addMusicItem,
+                          'handle'
+                        ]}
+                        onClick={() => {
+                          // 直接跳转到制谱页面 (临时存储数据)
+                          sessionStorage.setItem('notation-open-create', '1');
+                          router.push('/notation');
+                        }}>
+                        <img src={iconAddMusic} />
+
+                        <p class={styles.addMusicName}>开始制谱</p>
+                      </div>
                     </div>
                   )}
                 </>
               )}
 
-              {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
+              {/* {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
                 <TheEmpty description="暂无课件" />
+              )} */}
+              {forms.coursewareList.length <= 0 && (
+                <div class={styles.list}>
+                  <div
+                    class={[styles.itemContent, styles.addMusicItem, 'handle']}
+                    onClick={() => {
+                      // 直接跳转到制谱页面 (临时存储数据)
+                      sessionStorage.setItem('notation-open-create', '1');
+                      router.push('/notation');
+                    }}>
+                    <img src={iconAddMusic} />
+
+                    <p class={styles.addMusicName}>开始制谱</p>
+                  </div>
+                </div>
               )}
             </div>
           </NSpin>
@@ -710,8 +764,6 @@ export default defineComponent({
                   forms.removeVisiable1 = false;
                   forms.isEdit = true;
                   // prepareStore.setCoursewareList([]);
-
-                  console.log(prepareStore.getCoursewareList, 'getCourseware1');
                 }}>
                 确定
               </NButton>

+ 1 - 1
src/views/prepare-lessons/components/lesson-main/index.tsx

@@ -16,7 +16,7 @@ export default defineComponent({
           paneClass={styles.paneTitle}
           justifyContent="center"
           paneWrapperClass={styles.paneWrapperContainer}
-          onUpdate: value={(val: string) => {
+          onUpdate:value={(val: string) => {
             prepareStore.setTabType(val);
           }}>
           <NTabPane name="courseware" tab="课件" displayDirective="show">

+ 3 - 4
src/views/prepare-lessons/components/lesson-main/train/index.tsx

@@ -121,9 +121,9 @@ export default defineComponent({
           }
         });
         forms.trainList = tempCourse || [];
-        setTimeout(()=>{
+        setTimeout(() => {
           showGuide.value = true;
-        },500)
+        }, 500);
       } catch {
         //
       }
@@ -217,8 +217,6 @@ export default defineComponent({
       // checkSubjectIds();
 
       await getList();
-
-
     });
     return () => (
       <div class={styles.coursewareModal}>
@@ -276,6 +274,7 @@ export default defineComponent({
                   value={prepareStore.getSubjectId}
                   onUpdate:value={(val: any) => {
                     prepareStore.setSubjectId(val);
+                    localStorage.setItem('prepareLessonSubjectId', val);
                   }}
                 />
               </div>

+ 17 - 2
src/views/prepare-lessons/components/resource-main/components/resource-item/index.tsx

@@ -3,7 +3,7 @@ import ResourceSearchGroup from './resource-search-group';
 import { NScrollbar, NSpin, useDialog, useMessage } from 'naive-ui';
 import styles from './index.module.less';
 import CardType from '/src/components/card-type';
-import { materialQueryPage } from '/src/views/natural-resources/api';
+import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
 import TheEmpty from '/src/components/TheEmpty';
 import { usePrepareStore } from '/src/store/modules/prepareLessons';
 import { useDebounceFn, useThrottleFn } from '@vueuse/core';
@@ -191,6 +191,20 @@ export default defineComponent({
       // });
     };
 
+    // 收藏
+    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();
     });
@@ -235,13 +249,14 @@ export default defineComponent({
                     <CardType
                       isShowAdd
                       item={item}
-                      isShowCollect={false}
+                      isShowCollect={true}
                       disabledMouseHover={false}
                       onClick={() => {
                         if (item.type === 'IMG') return;
                         state.show = true;
                         state.item = item;
                       }}
+                      onCollect={(item: any) => onCollect(item)}
                       isShowAddDisabled={!prepareStore.getIsEditResource}
                       onAdd={(item: any) => onAdd(item)}
                     />

+ 6 - 3
src/views/prepare-lessons/components/resource-main/index.tsx

@@ -90,19 +90,22 @@ export default defineComponent({
                   <NTabPane
                     name="myResources"
                     tab="我的资源"
-                    displayDirective="show:lazy">
+                    // displayDirective="show:lazy"
+                  >
                     <ResourceItem type="myResources" />
                   </NTabPane>
                   <NTabPane
                     name="shareResources"
                     tab="共享资源"
-                    displayDirective="show:lazy">
+                    // displayDirective="show:lazy"
+                  >
                     <ResourceItem type="shareResources" />
                   </NTabPane>
                   <NTabPane
                     name="myCollect"
                     tab="我的收藏"
-                    displayDirective="show:lazy">
+                    // displayDirective="show:lazy"
+                  >
                     <ResourceItem type="myCollect" />
                   </NTabPane>
                 </>

BIN
src/views/prepare-lessons/images/icon-add-music.png


+ 6 - 3
src/views/prepare-lessons/model/select-resources/index.tsx

@@ -29,19 +29,22 @@ export default defineComponent({
           <NTabPane
             name="myResources"
             tab="我的资源"
-            displayDirective="show:lazy">
+            // displayDirective="show:lazy"
+          >
             <SelectItem type="myResources" />
           </NTabPane>
           <NTabPane
             name="shareResources"
             tab="共享资源"
-            displayDirective="show:lazy">
+            // displayDirective="show:lazy"
+          >
             <SelectItem type="shareResources" />
           </NTabPane>
           <NTabPane
             name="myCollect"
             tab="我的收藏"
-            displayDirective="show:lazy">
+            // displayDirective="show:lazy"
+          >
             <SelectItem type="myCollect" />
           </NTabPane>
         </NTabs>

+ 17 - 2
src/views/prepare-lessons/model/select-resources/select-item/index.tsx

@@ -10,7 +10,7 @@ import ResourceSearchGroup from './resource-search-group';
 import { NScrollbar, NSpin, useDialog, useMessage } from 'naive-ui';
 import styles from './index.module.less';
 import CardType from '/src/components/card-type';
-import { materialQueryPage } from '/src/views/natural-resources/api';
+import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
 import TheEmpty from '/src/components/TheEmpty';
 import { usePrepareStore } from '/src/store/modules/prepareLessons';
 import { saveCourseware } from '../../../api';
@@ -180,6 +180,20 @@ export default defineComponent({
       }
     );
 
+    // 收藏
+    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();
     });
@@ -220,10 +234,11 @@ export default defineComponent({
                     <CardType
                       isShowAdd
                       item={item}
-                      isShowCollect={false}
+                      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;

+ 177 - 0
src/views/prepare-lessons/model/the-create/index.module.less

@@ -0,0 +1,177 @@
+:global{
+    .n-modal-mask{
+        background-color: transparent;
+    }
+}
+.setbox {
+    position: relative;
+    top: 0;
+    display: flex;
+    flex-direction: column;
+    border-radius: 6px;
+    background: #fff;
+    overflow: hidden;
+}
+
+.head {
+    position: relative;
+    line-height: 53px;
+    height: 53px;
+    text-align: center;
+    background: #F5F6FA;
+    color: #131415;
+    font-weight: 600;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 16px;
+    flex-shrink: 0;
+
+    .close {
+        position: absolute;
+        top: 50%;
+        right: 20px;
+        transform: translateY(-50%);
+    }
+}
+
+.content {
+    flex: 1;
+    padding: 30px;
+    overflow: hidden;
+}
+
+.lineTitle {
+    height: 21px;
+    font-size: 15px;
+    font-weight: 600;
+    color: #131415;
+    line-height: 21px;
+    margin-bottom: 10px;
+}
+
+.item {
+    position: relative;
+    text-align: center;
+    font-size: 14px;
+    font-weight: 400;
+    color: #777;
+    cursor: pointer;
+
+    .itemImg {
+        width: 100px;
+        height: 100px;
+        border: 2px solid #fff;
+        border-radius: 18px;
+        overflow: hidden;
+        margin-bottom: 7px;
+    }
+
+    .icon {
+        width: 100%;
+        height: 100%;
+    }
+
+    &.itemActive {
+        font-weight: 600;
+        color: var(--primary-color);
+
+        .itemImg {
+            border-color: var(--primary-color);
+        }
+        .itemIcon{
+            display: block;
+        }
+    }
+    .itemIcon{
+        position: absolute;
+        right: 8px;
+        top: 8px;
+        display: none;
+        width: 18px;
+        height: 18px;
+    }
+}
+
+.beatItem {
+    position: relative;
+    width: 195px;
+    height: 110px;
+    background: #F5F5F7;
+    border-radius: 8px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    
+
+    .beatIcon {
+        width: 80%;
+        height: 60%;
+        cursor: pointer;
+
+        :global {
+            .svg-icon {
+                width: 100% !important;
+                height: 100% !important;
+            }
+        }
+    }
+
+    :global {
+        .n-input-number {
+            width: 80%;
+        }
+        .n-input{
+            border-radius: 6px !important;
+        }
+    }
+
+    .speedIcon {
+        font-size: 30px;
+    }
+}
+
+.btnItem {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    border-radius: 6px;
+    padding: 4px 8px;
+    cursor: pointer;
+
+    .btnItemIcon {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 60px;
+    }
+
+    &:hover {
+        background-color: rgba(0, 0, 0, 0.1);
+    }
+
+    .btnItemName {
+        font-size: 12px;
+    }
+    &.active{
+        background-color: #BADCFE;
+    }
+}
+
+.btns {
+    text-align: center;
+    padding: 15px 0;
+
+    :global {
+        .n-button {
+            width: 117px;
+            height: 35px;
+            padding: 0;
+            text-align: center;
+            font-size: 14px;
+            margin: 0 15px;
+        }
+    }
+}

+ 297 - 0
src/views/prepare-lessons/model/the-create/index.tsx

@@ -0,0 +1,297 @@
+import {
+	NButton,
+	NCard,
+	NCheckbox,
+	NGi,
+	NGrid,
+	NIcon,
+	NInputNumber,
+	NLayout,
+	NLayoutContent,
+	NLayoutSider,
+	NModal,
+	NPopover,
+	NRadio,
+	NRadioGroup,
+	NScrollbar,
+	NSpace,
+	NTabPane,
+	NTable,
+	NTabs,
+	useMessage,
+} from "naive-ui";
+import { defineComponent, onMounted, reactive, watch } from "vue";
+import { CheckmarkCircle, Close } from "@vicons/ionicons5";
+import styles from "./index.module.less";
+import { getImage } from "/src/pc/home/images";
+import { ABC_DATA } from "/src/pc/home/runtime";
+import TheIcon from "/src/components/The-icon";
+import TheSpeed from "/src/pc/home/component/the-speed";
+import { api_musicSheetCreationSave, api_subjectList } from "/src/pc/api";
+import { initMusic } from "/src/pc/home";
+import { encodeUrl } from "/src/utils";
+const instruments = [
+	{
+		label: "竖笛",
+		key: "recorder",
+		id: 4,
+		icon: getImage("icon_27_0.png"),
+		range: {
+			min: 48,
+			max: 74,
+		},
+	},
+	{
+		label: "排箫",
+		key: "pan_flute",
+		id: 1,
+		icon: getImage("icon_27_1.png"),
+		range: {
+			min: 43,
+			max: 77,
+		},
+	},
+	{
+		label: "口风琴",
+		key: "piccolo",
+		id: 5,
+		icon: getImage("icon_27_2.png"),
+		range: {
+			min: 41,
+			max: 72,
+		},
+	},
+	{
+		label: "陶笛",
+		key: "blown_bottle",
+		id: 2,
+		icon: getImage("icon_27_3.png"),
+		range: {
+			min: 45,
+			max: 65,
+		},
+	},
+	{
+		label: "葫芦丝",
+		key: "clarinet",
+		id: 3,
+		icon: getImage("icon_27_4.png"),
+		range: {
+			min: 40,
+			max: 57,
+		},
+	},
+];
+export const notationInstruments = instruments;
+export default defineComponent({
+	name: "TheCreate",
+	props: {
+		show: {
+			type: Boolean,
+			default: false,
+		},
+	},
+	emits: ["update:show", "create"],
+	setup(props, { emit }) {
+		const message = useMessage();
+
+		const formsOptions = reactive({
+			loading: false,
+		});
+		const froms = reactive({
+			key: ABC_DATA.key[0],
+			meter: ABC_DATA.meter[0],
+			speed: 80,
+			measure: 30,
+			subjectCode: "recorder",
+		});
+
+		const handleCreate = async () => {
+			if (!froms.speed) {
+				message.warning("请输入开始速度");
+				return;
+			}
+			if (!froms.measure) {
+				message.warning("请输入小节数量");
+				return;
+			}
+			formsOptions.loading = true;
+			handleOpenNotaion({
+				meter: froms.meter.value,
+				speed: `Q:1/4=${froms.speed}`,
+				key: froms.key.value,
+				subjectCode: froms.subjectCode,
+				measure: froms.measure,
+			});
+			emit("create");
+			formsOptions.loading = false;
+		};
+
+		const handleOpenNotaion = (data: any) => {
+			const url = `${location.origin}/notation/#/?v=1.0.3&config=${encodeUrl(data)}`;
+			window.parent.postMessage(
+				{
+					api: "notation_open",
+					url: url,
+				},
+				"*"
+			);
+			// window.open(url, "_blank");
+		};
+
+		return () => (
+			<NModal
+				transformOrigin="center"
+				autoFocus={false}
+				show={props.show}
+				onUpdate:show={(val) => emit("update:show", val)}
+			>
+				<div class={styles.setbox}>
+					<div class={styles.head}>
+						<div>新建乐谱</div>
+						<NButton
+							class={styles.close}
+							quaternary
+							circle
+							size="small"
+							onClick={() => emit("update:show", false)}
+						>
+							<NIcon component={Close} size={18} />
+						</NButton>
+					</div>
+					<div class={styles.content}>
+						<div class={styles.lineTitle}>声部</div>
+						<NSpace size={32} style={{ paddingBottom: "45px" }}>
+							{instruments.map((item) => (
+								<div
+									class={[styles.item, froms.subjectCode === item.key && styles.itemActive]}
+									onClick={() => {
+										froms.subjectCode = item.key;
+									}}
+								>
+									<div class={styles.itemImg}>
+										<img class={styles.icon} src={item.icon} />
+									</div>
+									<div>{item.label}</div>
+									<img class={styles.itemIcon} src={getImage("icon_check.png")} />
+								</div>
+							))}
+						</NSpace>
+						<NSpace style={{ paddingBottom: "45px" }}>
+							<NPopover to="body" trigger="click">
+								{{
+									trigger: () => (
+										<div>
+											<div class={styles.lineTitle}>调号</div>
+											<div class={styles.beatItem}>
+												<div class={[styles.beatIcon]}>
+													<TheIcon iconClassName={froms.key.icon} />
+												</div>
+												<div>{froms.key.name}</div>
+											</div>
+										</div>
+									),
+									default: () => (
+										<NGrid cols={5} xGap={20} yGap={8}>
+											{ABC_DATA.key.map((item) => (
+												<NGi>
+													<div
+														class={[styles.btnItem, froms.key.value === item.value && styles.active]}
+														onClick={() => (froms.key = item)}
+													>
+														<div class={[styles.btnItemIcon]}>
+															<TheIcon iconClassName={item.icon} />
+														</div>
+														<div class={styles.btnItemName}>{item.name}</div>
+													</div>
+												</NGi>
+											))}
+										</NGrid>
+									),
+								}}
+							</NPopover>
+
+							<NPopover to="body" trigger="click">
+								{{
+									trigger: () => (
+										<div>
+											<div class={styles.lineTitle}>拍号</div>
+											<div class={styles.beatItem}>
+												<div class={[styles.beatIcon]}>
+													<TheIcon iconClassName={froms.meter.icon} />
+												</div>
+												<div>{froms.meter.name}</div>
+											</div>
+										</div>
+									),
+									default: () => (
+										<NGrid cols={5} xGap={50} yGap={20}>
+											{ABC_DATA.meter.map((item) => (
+												<NGi>
+													<div
+														class={[styles.btnItem, froms.meter.value === item.value && styles.active]}
+														onClick={() => (froms.meter = item)}
+													>
+														<div class={[styles.btnItemIcon]}>
+															<TheIcon iconClassName={item.icon} />
+														</div>
+														<div class={styles.btnItemName}>{item.name}</div>
+													</div>
+												</NGi>
+											))}
+										</NGrid>
+									),
+								}}
+							</NPopover>
+							<div>
+								<div class={styles.lineTitle}>速度</div>
+								<div class={styles.beatItem}>
+									<NInputNumber
+										size="large"
+										v-model:value={froms.speed}
+										placeholder="开始速度"
+										showButton={false}
+										min={50}
+									>
+										{{
+											prefix: () => (
+												<div class={styles.speedIcon}>
+													<TheIcon iconClassName="icon-a-sudu-4fenyinfu" size={["2em", "1em"]} />
+												</div>
+											),
+										}}
+									</NInputNumber>
+								</div>
+							</div>
+							<div>
+								<div class={styles.lineTitle}>小节</div>
+								<div class={styles.beatItem}>
+									<NInputNumber
+										placeholder="小节数量"
+										size="large"
+										v-model:value={froms.measure}
+										min={4}
+									></NInputNumber>
+								</div>
+							</div>
+						</NSpace>
+
+						<div class={styles.btns}>
+							<NButton round onClick={() => emit("update:show", false)}>
+								取消
+							</NButton>
+							<NButton
+								loading={formsOptions.loading}
+								round
+								type="primary"
+								onClick={() => handleCreate()}
+							>
+								确定
+							</NButton>
+						</div>
+					</div>
+				</div>
+			</NModal>
+		);
+	},
+});

+ 58 - 8
src/views/xiaoku-ai/index.tsx

@@ -12,10 +12,13 @@ export default defineComponent({
   setup() {
     const catchStore = useCatchStore();
     const router = useRouter();
+
+    const xiaokuAiSearch = localStorage.getItem('xiaoku-ai-search');
+    const xiaokuAi = xiaokuAiSearch ? JSON.parse(xiaokuAiSearch) : {};
     const forms = reactive({
-      musicTagIds: [] as any[],
+      musicTagIds: xiaokuAi.musicTagIds ? xiaokuAi.musicTagIds : ([] as any[]),
       enable: true,
-      subjectId: null,
+      subjectId: xiaokuAi.subjectId || null,
       keyword: '',
       page: 1,
       rows: 9999
@@ -23,7 +26,7 @@ export default defineComponent({
     const data = reactive({
       tags: [] as any[],
       tagChildren: [] as any[],
-      tagActiveId: '',
+      tagActiveId: xiaokuAi.tagActiveId || '',
       tagActive: {} as any,
       list: [] as any,
       loading: false
@@ -31,11 +34,21 @@ export default defineComponent({
     const getTags = async () => {
       const res = await api_musicTagTree();
       if (Array.isArray(res?.data) && res.data.length) {
-        data.tags = res.data;
-        data.tagActiveId = res.data[0].id;
-        const list: any[] = [];
-        renderTag(res.data[0].children, list);
-        data.tagChildren = list;
+        data.tags = res.data || [];
+        const index = data.tags.findIndex(
+          (item: any) => item.id == data.tagActiveId
+        );
+        if (index > -1) {
+          data.tagActiveId = res.data[index].id;
+          const list: any[] = [];
+          renderTag(res.data[index].children, list);
+          data.tagChildren = list;
+        } else {
+          data.tagActiveId = res.data[0].id;
+          const list: any[] = [];
+          renderTag(res.data[0].children, list);
+          data.tagChildren = list;
+        }
       }
     };
 
@@ -85,6 +98,15 @@ export default defineComponent({
         await getList();
         // 获取教材分类列表
         await catchStore.getSubjects();
+
+        localStorage.setItem(
+          'xiaoku-ai-search',
+          JSON.stringify({
+            tagActiveId: data.tagActiveId,
+            subjectId: forms.subjectId,
+            musicTagIds: forms.musicTagIds
+          })
+        );
       } catch {
         //
       }
@@ -95,6 +117,16 @@ export default defineComponent({
     const changeTag = (item: any, index: number) => {
       data.tagActiveId = item.id;
       forms.musicTagIds = [];
+
+      localStorage.setItem(
+        'xiaoku-ai-search',
+        JSON.stringify({
+          tagActiveId: item.id,
+          subjectId: forms.subjectId,
+          musicTagIds: forms.musicTagIds
+        })
+      );
+
       const list: any[] = [];
       renderTag(data.tags[index].children, list);
       data.tagChildren = list;
@@ -122,6 +154,15 @@ export default defineComponent({
         forms.musicTagIds.push(activeItem.id);
         data.tagChildren[columnIndex].activeIndex = index;
       }
+
+      localStorage.setItem(
+        'xiaoku-ai-search',
+        JSON.stringify({
+          tagActiveId: data.tagActiveId,
+          subjectId: forms.subjectId,
+          musicTagIds: forms.musicTagIds
+        })
+      );
       getList();
     };
     return () => (
@@ -196,6 +237,15 @@ export default defineComponent({
                         }
                         onClick={() => {
                           forms.subjectId = item.id;
+
+                          localStorage.setItem(
+                            'xiaoku-ai-search',
+                            JSON.stringify({
+                              tagActiveId: data.tagActiveId,
+                              subjectId: item.id,
+                              musicTagIds: forms.musicTagIds
+                            })
+                          );
                           getList();
                         }}>
                         {item.name}