feat: 添加设备振动功能,支持多种振动模式和反馈
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import type { Awaitable } from "@vueuse/core";
|
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 { AreaSeries, BarSeries, BaselineSeries, CandlestickSeries, ColorType, createChart, HistogramSeries, LineSeries } from "lightweight-charts";
|
||||||
import { mergeWith } from "lodash-es";
|
import { mergeWith } from "lodash-es";
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ const initializeOptions: Required<TradingViewOptions> = {
|
|||||||
width: 400,
|
width: 400,
|
||||||
height: 300,
|
height: 300,
|
||||||
layout: {
|
layout: {
|
||||||
textColor: "white",
|
textColor: "black",
|
||||||
background: { type: ColorType.Solid, color: "#000000" },
|
background: { type: ColorType.Solid, color: "#fff" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
autosize: true,
|
autosize: true,
|
||||||
|
|||||||
116
src/composables/useVibrate.ts
Normal file
116
src/composables/useVibrate.ts
Normal file
@@ -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,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import IssuePeriod from "./issue-period.vue";
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const now = useNow();
|
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<number>("step", 1, { transform: v => Number(v), mode: "push" });
|
const step = useRouteQuery<number>("step", 1, { transform: v => Number(v), mode: "push" });
|
||||||
const initialData: RwaIssuanceProductBody = {
|
const initialData: RwaIssuanceProductBody = {
|
||||||
@@ -33,6 +33,12 @@ const initialData: RwaIssuanceProductBody = {
|
|||||||
};
|
};
|
||||||
const form = useStorage<RwaIssuanceProductBody>("issuing-apply-form", { ...initialData });
|
const form = useStorage<RwaIssuanceProductBody>("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) {
|
function handleNext(values: GenericObject) {
|
||||||
form.value.product = { ...values as any };
|
form.value.product = { ...values as any };
|
||||||
step.value = 2;
|
step.value = 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user