Browse Source

添加弹窗

lex 1 year ago
parent
commit
720359b001

+ 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>
+		);
+	},
+});