index.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { defineComponent, nextTick, reactive, watch } from "vue";
  2. import styles from "./index.module.less";
  3. import iconClose from "../image/close2.svg";
  4. import { Cell, Field, NoticeBar, Popup, Radio, RadioGroup, Slider, Switch, Tab, Tabs, closeToast, showLoadingToast, showToast } from "vant";
  5. import state from "/src/state";
  6. import { api_closeCamera, api_openCamera, api_savePicture } from "/src/helpers/communication";
  7. import store from "store";
  8. import iconInfo from "../image/info.svg";
  9. import iconDown from "../image/down.svg";
  10. import iconTv from "../image/tv.svg";
  11. import iconYijian from "../image/yijian.svg";
  12. import ScreenModel from "../../custom-plugins/helper-model/screen-model";
  13. import Recommendation from "../../custom-plugins/helper-model/recommendation";
  14. import html2canvas from "html2canvas";
  15. export default defineComponent({
  16. name: "header-settting",
  17. emits: ["close"],
  18. setup(props, { emit }) {
  19. const helperData = reactive({
  20. show: false,
  21. recommendationShow: false, // 建议
  22. });
  23. const downPng = () => {
  24. showLoadingToast({ message: "下载中", duration: 0 });
  25. setTimeout(() => {
  26. const _div = document.createElement("div");
  27. const svg: any = document.getElementById("osmdSvgPage1")?.cloneNode(true);
  28. if (!svg) return;
  29. _div.appendChild(svg);
  30. document.body.appendChild(_div);
  31. html2canvas(_div).then(async (_canvas) => {
  32. document.body.removeChild(_div);
  33. const res = await api_savePicture({
  34. base64: _canvas.toDataURL(),
  35. });
  36. closeToast()
  37. if (res?.content?.status === "success") {
  38. showToast({ message: "保存成功", type: "success" });
  39. } else {
  40. showToast({ message: "保存失败", type: "fail" });
  41. }
  42. });
  43. }, 50);
  44. };
  45. // 设置改变触发
  46. watch(state.setting, () => {
  47. store.set("musicscoresetting", state.setting);
  48. });
  49. return () => (
  50. <div class={styles["header-settting"]}>
  51. <div class={styles.closeBtn} onClick={() => emit("close")}>
  52. <img src={iconClose} />
  53. </div>
  54. <div class={styles.content}>
  55. <Tabs border animated swipeable>
  56. <Tab title="全局设置">
  57. <NoticeBar class={styles.noticebar} left-icon={iconInfo} text="全局设置会更改所有乐谱练习及评测" />
  58. <Cell title="护眼模式" center>
  59. {{
  60. extra: () => <Switch v-model={state.setting.eyeProtection}></Switch>,
  61. }}
  62. </Cell>
  63. <div class={styles.btnsbar}>
  64. <div class={styles.btn} onClick={downPng}>
  65. <img src={iconDown} />
  66. 下载曲谱
  67. </div>
  68. <div class={styles.btn} onClick={() => (helperData.show = true)}>
  69. <img src={iconTv} />
  70. 投屏帮助
  71. </div>
  72. <div class={styles.btn} onClick={() => (helperData.recommendationShow = true)}>
  73. <img src={iconYijian} />
  74. 意见反馈
  75. </div>
  76. </div>
  77. </Tab>
  78. <Tab title="练习设置">
  79. <Cell title="循环播放" center>
  80. {{
  81. extra: () => <Switch v-model={state.setting.repeatAutoPlay}></Switch>,
  82. }}
  83. </Cell>
  84. <Cell title="显示指法" center>
  85. {{
  86. extra: () => <Switch v-model={state.setting.displayFingering}></Switch>,
  87. }}
  88. </Cell>
  89. </Tab>
  90. <Tab title="评测">
  91. <Cell title="选择评测难度" center>
  92. {{
  93. extra: () => (
  94. <RadioGroup iconSize={20} class={styles.radioGroup} v-model={state.setting.evaluationDifficulty}>
  95. <Radio name="BEGINNER">入门</Radio>
  96. <Radio name="ADVANCED">进阶</Radio>
  97. <Radio name="PERFORMER">大师</Radio>
  98. </RadioGroup>
  99. ),
  100. }}
  101. </Cell>
  102. <Cell title="校音提醒" center>
  103. {{
  104. extra: () => <Switch v-model={state.setting.soundEffect}></Switch>,
  105. }}
  106. </Cell>
  107. <Cell title="摄像头" center>
  108. {{
  109. extra: () => (
  110. <Switch
  111. v-model={state.setting.camera}
  112. onChange={(value) => {
  113. if (value) {
  114. api_openCamera();
  115. } else {
  116. api_closeCamera();
  117. }
  118. }}
  119. ></Switch>
  120. ),
  121. }}
  122. </Cell>
  123. <Cell style={{ display: state.setting.camera ? "" : "none" }} title="透明度" class={styles.sliderWrap} center>
  124. {{
  125. extra: () => (
  126. <Slider class={styles.slider} min={0} max={100} v-model:modelValue={state.setting.cameraOpacity}>
  127. {{
  128. button: () => <div class={styles.sliderBtn}>{state.setting.cameraOpacity}</div>,
  129. }}
  130. </Slider>
  131. ),
  132. }}
  133. </Cell>
  134. <Cell title="保存到相册" center>
  135. {{
  136. extra: () => <Switch v-model={state.setting.saveToAlbum}></Switch>,
  137. }}
  138. </Cell>
  139. <Cell title="开启伴奏" center>
  140. {{
  141. extra: () => <Switch v-model={state.setting.enableAccompaniment}></Switch>,
  142. }}
  143. </Cell>
  144. <Cell title="标准音高" center>
  145. {{
  146. extra: () => (
  147. <RadioGroup iconSize={20} class={styles.radioGroup} v-model={state.setting.frequency}>
  148. <Radio name={440}>440Hz</Radio>
  149. <Radio name={442}>442Hz</Radio>
  150. </RadioGroup>
  151. ),
  152. }}
  153. </Cell>
  154. <Field class={styles.reactionTime} label="反应时间(毫秒)" type="digit" v-model:modelValue={state.setting.reactionTimeMs} />
  155. </Tab>
  156. </Tabs>
  157. </div>
  158. <Popup
  159. class={["popup-custom", styles.screen]}
  160. v-model:show={helperData.show}
  161. onClose={() => {
  162. helperData.show = false;
  163. }}
  164. position="right"
  165. teleport="body"
  166. >
  167. <ScreenModel
  168. onClose={(open: Boolean) => {
  169. helperData.show = false;
  170. }}
  171. />
  172. </Popup>
  173. <Popup v-model:show={helperData.recommendationShow} class="popup-custom van-scale" transition="van-scale" teleport="body">
  174. <Recommendation
  175. onClose={() => {
  176. helperData.recommendationShow = false;
  177. }}
  178. />
  179. </Popup>
  180. </div>
  181. );
  182. },
  183. });