From 6ceb80e6f26175e76f0d9852589e6597dfe95139 Mon Sep 17 00:00:00 2001 From: Seven Date: Thu, 18 Dec 2025 15:48:30 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=8C=AF=E5=8A=A8=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=A4=9A=E7=A7=8D=E6=8C=AF=E5=8A=A8=E6=A8=A1=E5=BC=8F=E5=92=8C?= =?UTF-8?q?=E5=8F=8D=E9=A6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/useTradingView.ts | 6 +- src/composables/useVibrate.ts | 116 ++++++++++++++++++++++++ src/views/issue/issuing-apply/index.vue | 8 +- 3 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 src/composables/useVibrate.ts diff --git a/src/composables/useTradingView.ts b/src/composables/useTradingView.ts index 9cea067..9cb58c7 100644 --- a/src/composables/useTradingView.ts +++ b/src/composables/useTradingView.ts @@ -1,5 +1,5 @@ import type { Awaitable } from "@vueuse/core"; -import type { ChartOptions, DeepPartial, IChartApi, ISeriesApi, OhlcData, SeriesOptionsMap, SeriesType } from "lightweight-charts"; +import type { ChartOptions, DeepPartial, IChartApi, ISeriesApi, OhlcData, SeriesType } from "lightweight-charts"; import { AreaSeries, BarSeries, BaselineSeries, CandlestickSeries, ColorType, createChart, HistogramSeries, LineSeries } from "lightweight-charts"; import { mergeWith } from "lodash-es"; @@ -27,8 +27,8 @@ const initializeOptions: Required = { width: 400, height: 300, layout: { - textColor: "white", - background: { type: ColorType.Solid, color: "#000000" }, + textColor: "black", + background: { type: ColorType.Solid, color: "#fff" }, }, }, autosize: true, diff --git a/src/composables/useVibrate.ts b/src/composables/useVibrate.ts new file mode 100644 index 0000000..f5ab424 --- /dev/null +++ b/src/composables/useVibrate.ts @@ -0,0 +1,116 @@ +import { Capacitor } from "@capacitor/core"; +import { Haptics, ImpactStyle } from "@capacitor/haptics"; + +export interface HapticsOptions { + /** + * 振动强度 + * - light: 轻微振动 + * - medium: 中等振动 + * - heavy: 强烈振动 + */ + impact?: ImpactStyle; + /** + * 振动时长 (毫秒) + */ + duration?: number; +} + +/** + * 设备振动 Composable + */ +export function useHaptics() { + /** + * 检查设备是否支持振动 + */ + const isHapticsAvailable = computed(() => { + return Capacitor.isNativePlatform(); + }); + + /** + * 触发振动反馈 + * @param options 振动配置选项 + */ + async function vibrate(options: HapticsOptions = {}) { + if (!isHapticsAvailable.value) { + console.warn("Haptics not available on this platform"); + return; + } + + const { impact = ImpactStyle.Medium, duration } = options; + + try { + if (duration) { + // 自定义时长振动 + await Haptics.vibrate({ duration }); + } + else { + // 触觉反馈振动 + await Haptics.impact({ style: impact }); + } + } + catch (error) { + console.error("Haptics error:", error); + } + } + + /** + * 轻微振动 (适用于按钮点击) + */ + async function lightVibrate() { + await vibrate({ impact: ImpactStyle.Light }); + } + + /** + * 中等振动 (适用于选择操作) + */ + async function mediumVibrate() { + await vibrate({ impact: ImpactStyle.Medium }); + } + + /** + * 强烈振动 (适用于重要通知) + */ + async function heavyVibrate() { + await vibrate({ impact: ImpactStyle.Heavy }); + } + + /** + * 成功振动模式 + */ + async function successVibrate() { + await lightVibrate(); + await new Promise(resolve => setTimeout(resolve, 100)); + await lightVibrate(); + } + + /** + * 错误振动模式 + */ + async function errorVibrate() { + await heavyVibrate(); + await new Promise(resolve => setTimeout(resolve, 200)); + await heavyVibrate(); + await new Promise(resolve => setTimeout(resolve, 200)); + await heavyVibrate(); + } + + /** + * 警告振动模式 + */ + async function warningVibrate() { + await mediumVibrate(); + await new Promise(resolve => setTimeout(resolve, 150)); + await mediumVibrate(); + } + + return { + isHapticsAvailable, + vibrate, + lightVibrate, + mediumVibrate, + heavyVibrate, + successVibrate, + errorVibrate, + warningVibrate, + }; +} diff --git a/src/views/issue/issuing-apply/index.vue b/src/views/issue/issuing-apply/index.vue index c30059d..46eda17 100644 --- a/src/views/issue/issuing-apply/index.vue +++ b/src/views/issue/issuing-apply/index.vue @@ -10,7 +10,7 @@ import IssuePeriod from "./issue-period.vue"; const { t } = useI18n(); const now = useNow(); -const { data: categories } = await safeClient(() => client.api.rwa.issuance.categories.get()); +const { data: categories, onFetchResponse } = await safeClient(() => client.api.rwa.issuance.categories.get()); const step = useRouteQuery("step", 1, { transform: v => Number(v), mode: "push" }); const initialData: RwaIssuanceProductBody = { @@ -33,6 +33,12 @@ const initialData: RwaIssuanceProductBody = { }; const form = useStorage("issuing-apply-form", { ...initialData }); +onFetchResponse(() => { + if (!form.value.product.categoryId && categories.value?.data && categories.value?.data.length > 0) { + form.value.product.categoryId = categories.value?.data![0].id; + } +}); + function handleNext(values: GenericObject) { form.value.product = { ...values as any }; step.value = 2;