123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- import { defineComponent, nextTick, reactive, watch } from "vue";
- import styles from "./index.module.less";
- import iconClose from "../image/close2.svg";
- import {
- Cell,
- Field,
- NoticeBar,
- Popup,
- Radio,
- RadioGroup,
- Slider,
- Switch,
- Tab,
- Tabs,
- closeToast,
- showLoadingToast,
- showToast,
- } from "vant";
- import state, { IPlatform } from "/src/state";
- import { api_closeCamera, api_openCamera, api_savePicture } from "/src/helpers/communication";
- import iconInfo from "../image/info.svg";
- import iconDown from "../image/down.svg";
- import iconTv from "../image/tv.svg";
- import iconYijian from "../image/yijian.svg";
- import iconSubtract from "../image/subtract.png";
- import iconAdd from "../image/add.png";
- import ScreenModel from "../../custom-plugins/helper-model/screen-model";
- import Recommendation from "../../custom-plugins/helper-model/recommendation";
- import { svg2canvas } from "/src/utils/svg2canvas";
- import { getQuery } from "/src/utils/queryString";
- import { browser } from "/src/utils";
- export default defineComponent({
- name: "header-settting",
- setup() {
- const query = getQuery();
- const helperData = reactive({
- show: false,
- recommendationShow: false, // 建议
- });
- const downPng = () => {
- showLoadingToast({ message: "下载中", duration: 0 });
- setTimeout(async () => {
- const svg: any = document.getElementById("osmdSvgPage1")?.cloneNode(true);
- if (!svg) return showToast({ message: "保存失败", type: "fail" });
- const cw = svg.width.animVal.value;
- const ch = svg.height.animVal.value;
- const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
- rect.setAttribute("x", "0");
- rect.setAttribute("y", "0");
- rect.setAttribute("width", `${cw * 2}`);
- rect.setAttribute("height", `${ch * 2}`);
- rect.setAttribute("fill", "#fff");
- svg.prepend(rect);
- if (svg) {
- const _canvas = svg2canvas(svg.outerHTML);
- const browserInfo = browser();
- if (state.platform === IPlatform.PC || !browserInfo.isApp) {
- let el: any = document.createElement("a");
- // 设置 href 为图片经过 base64 编码后的字符串,默认为 png 格式
- el.href = _canvas.toDataURL();
- el.download = state.examSongName;
- // 创建一个点击事件并对 a 标签进行触发
- const event = new MouseEvent("click");
- el.dispatchEvent(event);
- setTimeout(() => {
- showToast({ message: "保存成功", type: "success" });
- el = null;
- }, 300);
- } else {
- const base64 = _canvas.toDataURL("image/png", 1);
- const res = await api_savePicture({
- base64,
- });
- if (res?.content?.status === "success") {
- showToast({ message: "保存成功", type: "success" });
- } else {
- showToast({ message: "保存失败", type: "fail" });
- }
- }
- }
- }, 500);
- };
- const formatterTimeMs = (value: any) => value = String(Math.min(3000, value));
- // 加减评测频率
- const operateHz = (type: number) => {
- const minFrequency = state.baseFrequency - 10, maxFrequency = state.baseFrequency + 10
- let currentFrequency = state.setting.frequency
- if (type === 1) {
- if (currentFrequency - 1 < minFrequency) return showToast({ message: `最低标准音高${minFrequency}HZ` })
- currentFrequency = currentFrequency - 1
- } else {
- if (currentFrequency + 1 > maxFrequency) return showToast({ message: `最高标准音高${maxFrequency}HZ` })
- currentFrequency = currentFrequency + 1
- }
- state.setting.frequency = currentFrequency >= 0 ? currentFrequency : 0
- }
-
- return () => (
- <div class={styles["header-settting"]}>
- <div class={styles.content}>
- <Tabs border animated swipeable>
- <Tab title="全局设置">
- <NoticeBar
- class={styles.noticebar}
- left-icon={iconInfo}
- text="全局设置会更改所有乐谱练习及评测"
- />
- <Cell title="护眼模式" center>
- {{
- extra: () => <Switch v-model={state.setting.eyeProtection}></Switch>,
- }}
- </Cell>
- <Cell
- title="节拍器音量"
- class={styles.sliderWrap}
- center
- >
- {{
- extra: () => (
- <Slider
- class={[styles.slider, styles.sliderVolume]}
- min={0}
- max={100}
- v-model:modelValue={state.setting.beatVolume}
- >
- {{
- button: () => <div class={styles.sliderBtn}>{state.setting.beatVolume}</div>,
- }}
- </Slider>
- ),
- }}
- </Cell>
- <div class={styles.btnsbar}>
- {/* <div class={styles.btn} onClick={downPng}>
- <img src={iconDown} />
- 下载曲谱
- </div> */}
- <div class={styles.btn} onClick={() => (helperData.show = true)}>
- <img src={iconTv} />
- 投屏帮助
- </div>
- <div class={styles.btn} onClick={() => (helperData.recommendationShow = true)}>
- <img src={iconYijian} />
- 意见反馈
- </div>
- </div>
- </Tab>
- <Tab title="练习设置">
- <Cell title="循环播放" center>
- {{
- extra: () => <Switch v-model={state.setting.repeatAutoPlay}></Switch>,
- }}
- </Cell>
- <Cell class={[state.modeType == "evaluating" && styles.disabled]} title="显示指法" center>
- {{
- extra: () => <Switch v-model={state.setting.displayFingering} disabled={!state.fingeringInfo.name}></Switch>,
- }}
- </Cell>
- </Tab>
- <Tab title="评测设置">
- <Cell class={[query.workRecord && styles.disabled]} title="评测难度" center>
- {{
- extra: () => (
- <RadioGroup
- iconSize={20}
- class={styles.radioGroup}
- v-model={state.setting.evaluationDifficulty}
- >
- <Radio name="BEGINNER">入门</Radio>
- <Radio name="ADVANCED">进阶</Radio>
- <Radio name="PERFORMER">大师</Radio>
- </RadioGroup>
- ),
- }}
- </Cell>
- <Cell title="延迟检测" center>
- {{
- extra: () => <Switch v-model={state.setting.soundEffect}></Switch>,
- }}
- </Cell>
- <Cell title="摄像头" center>
- {{
- extra: () => (
- <Switch
- v-model={state.setting.camera}
- onChange={ async (value) => {
- if (value) {
- const res = await api_openCamera();
- // 没有授权
- if (res?.content?.reson) {
- state.setting.camera = false
- }
- } else {
- api_closeCamera();
- }
- }}
- ></Switch>
- ),
- }}
- </Cell>
- <Cell
- style={{ display: state.setting.camera ? "" : "none" }}
- title="透明度"
- class={styles.sliderWrap}
- center
- >
- {{
- extra: () => (
- <Slider
- class={styles.slider}
- min={0}
- max={100}
- v-model:modelValue={state.setting.cameraOpacity}
- >
- {{
- button: () => <div class={styles.sliderBtn}>{state.setting.cameraOpacity}</div>,
- }}
- </Slider>
- ),
- }}
- </Cell>
- {/* <Cell title="保存到相册" center>
- {{
- extra: () => <Switch v-model={state.setting.saveToAlbum}></Switch>,
- }}
- </Cell> */}
- <Cell title="开启伴奏" center>
- {{
- extra: () => <Switch v-model={state.setting.enableAccompaniment}></Switch>,
- }}
- </Cell>
- <Cell title="标准音高" center>
- {/* {{
- extra: () => (
- <RadioGroup
- iconSize={20}
- class={styles.radioGroup}
- v-model={state.setting.frequency}
- >
- <Radio name={440}>440Hz</Radio>
- <Radio name={442}>442Hz</Radio>
- </RadioGroup>
- ),
- }} */}
- {{
- extra: () => (
- <div class={styles.operateHz}>
- <img src={iconSubtract} onClick={() => operateHz(1)} />
- <span>{state.setting.frequency}HZ</span>
- <img src={iconAdd} onClick={() => operateHz(2)} />
- </div>
- )
- }}
- </Cell>
- <Field class={styles.reactionTime} label="反应时间(毫秒)" type="digit"
- placeholder="最大可输入3000毫秒"
- formatter={formatterTimeMs}
- v-model:modelValue={state.setting.reactionTimeMs} />
- </Tab>
- </Tabs>
- </div>
- <Popup
- class={["popup-custom", styles.screen]}
- v-model:show={helperData.show}
- onClose={() => {
- helperData.show = false;
- }}
- position="right"
- teleport="body"
- >
- <ScreenModel
- onClose={(open: Boolean) => {
- helperData.show = false;
- }}
- />
- </Popup>
- <Popup
- v-model:show={helperData.recommendationShow}
- class="popup-custom van-scale center-closeBtn"
- transition="van-scale"
- teleport="body"
- closeable
- >
- <Recommendation
- onClose={() => {
- helperData.recommendationShow = false;
- }}
- />
- </Popup>
- </div>
- );
- },
- });
|