diff --git a/src/apis.js b/src/apis.js
index 35fe672..2873cb5 100644
--- a/src/apis.js
+++ b/src/apis.js
@@ -8,7 +8,7 @@ try {
switch (envVersion) {
case "develop": // 开发版
- // BASE_URL = "http://192.168.1.2:8000/api/shoot";
+ // BASE_URL = "http://192.168.1.5:8000/api/shoot";
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
break;
case "trial": // 体验版
@@ -26,8 +26,6 @@ try {
}
const ADDONS_BASE_URL = BASE_URL.replace(/\/api\/shoot$/, "/api/shoot");
-const PRACTICE_BASE_URL = BASE_URL.replace(/\/api\/shoot$/, "/api");
-
// 统一处理业务接口请求,包含登录态、业务错误和 WiFi 连接空响应兼容。
function request(method, url, data = {}, baseUrl = BASE_URL) {
const token = uni.getStorageSync(
@@ -264,13 +262,11 @@ export const createPractiseAPI = (arrows, time, target) => {
});
};
-export const createPractiseV2API = (arrows, time, target, deviceId) => {
- return request("POST", "/practice/create-v2", {
- shootNumber: arrows,
- shootTime: time,
- targetType: Number(target || 1) * 20,
- deviceId,
- }, PRACTICE_BASE_URL);
+export const createPractiseV2API = (trainingType, difficultyLevel) => {
+ return request("POST", "/user/practice/create/v2", {
+ trainingType,
+ difficultyLevel,
+ });
};
export const startPractiseAPI = (id) => {
diff --git a/src/components/TargetCanvas.vue b/src/components/TargetCanvas.vue
index 05a9a56..f699158 100644
--- a/src/components/TargetCanvas.vue
+++ b/src/components/TargetCanvas.vue
@@ -21,34 +21,29 @@ const props = defineProps({
type: Boolean,
default: false,
},
- // 是否显示象限文字。
- showQuadrantLabels: {
- type: Boolean,
- default: false,
- },
// 是否显示环数文字。
showRingLabels: {
type: Boolean,
default: true,
},
- // 象限文字配置,key 为 1/2/3/4。
- quadrantLabels: {
- type: Object,
- default: () => ({
- 1: "1",
- 2: "2",
- 3: "3",
- 4: "4",
- }),
+ // 从正上方开始顺时针等分的区域数量。
+ sectorCount: {
+ type: Number,
+ default: 0,
},
- // 高亮区域数组。
- // quadrant: 1/2/3/4,表示第几个象限。
- // rings: "all" 或环数数组,例如 [7, 8, 9, 10]。
- // scope: "box" 表示整象限矩形,"sector" 表示环形扇区。
- // style: 可覆盖高亮填充色、描边色、线宽比例。
- highlightAreas: {
- type: Array,
- default: () => [],
+ // 当前高亮区域,范围为 1 到 sectorCount。
+ activeSector: {
+ type: Number,
+ default: 0,
+ },
+ // 指定环数,1 到 10;无效值表示高亮整个区域。
+ activeRing: {
+ type: Number,
+ default: 0,
+ },
+ showSectorLabels: {
+ type: Boolean,
+ default: false,
},
// 只绘制透明高亮层,不绘制完整靶纸;用于叠加在靶纸图片上。
highlightOnly: {
@@ -74,8 +69,18 @@ const props = defineProps({
type: Object,
default: () => ({}),
},
- // 象限文字样式覆盖配置。
- quadrantLabelStyle: {
+ // 区域分割线样式覆盖配置。
+ sectorStyle: {
+ type: Object,
+ default: () => ({}),
+ },
+ // 区域数字样式覆盖配置。
+ sectorLabelStyle: {
+ type: Object,
+ default: () => ({}),
+ },
+ // 高亮样式覆盖配置。
+ highlightStyle: {
type: Object,
default: () => ({}),
},
@@ -120,16 +125,24 @@ const defaultCrosshairStyle = {
lineWidthRatio: 0.0025,
};
-// 象限文字默认样式。
-const defaultQuadrantLabelStyle = {
+// 顺时针等分线默认样式。
+const defaultSectorStyle = {
+ color: "rgba(255, 255, 255, 0.82)",
+ lineWidthRatio: 0.004,
+};
+
+// 区域数字默认样式。
+const defaultSectorLabelStyle = {
color: "#ffffff",
- fontSizeRatio: 0.045,
- offsetRatio: 0.78,
+ backgroundColor: "rgba(0, 0, 0, 0.62)",
+ fontSizeRatio: 0.075,
+ radiusRatio: 0.76,
+ badgeRadiusRatio: 0.07,
};
// 高亮区域默认样式。
const defaultHighlightStyle = {
- color: "rgba(254, 216, 71, 0.34)",
+ color: "rgba(255, 228, 0, 0.6)",
strokeColor: "rgba(254, 216, 71, 0.82)",
lineWidthRatio: 0.003,
};
@@ -155,40 +168,24 @@ const getRingColor = (ring, config) => {
return config.ringColors?.[ring] || config.ringColors?.[String(ring)] || "#ffffff";
};
-// 规范化高亮环数配置;"all" 表示全部环,数组或单值会过滤非法环数。
-const normalizeRings = (rings, ringCount) => {
- if (rings === "all") {
- return "all";
- }
-
- const rawRings = Array.isArray(rings) ? rings : [rings];
- return rawRings
- .map((ring) => Number(ring))
- .filter((ring) => Number.isInteger(ring) && ring >= 1 && ring <= ringCount);
+const getPositiveInteger = (value) => {
+ const numberValue = Number(value);
+ return Number.isInteger(numberValue) && numberValue > 0 ? numberValue : 0;
};
-// 获取象限对应的扇形弧度范围。
-const getQuadrantAngles = (quadrant) => {
- const angleMap = {
- 1: [Math.PI, Math.PI * 1.5],
- 2: [Math.PI * 1.5, Math.PI * 2],
- 3: [Math.PI * 0.5, Math.PI],
- 4: [0, Math.PI * 0.5],
+// 正上方作为第一区起始边界,Canvas 角度递增方向即为顺时针。
+const getSectorAngles = (sector, sectorCount) => {
+ const count = getPositiveInteger(sectorCount);
+ const index = getPositiveInteger(sector);
+ if (!count || !index || index > count) return null;
+
+ const step = (Math.PI * 2) / count;
+ const startAngle = -Math.PI / 2 + (index - 1) * step;
+ return {
+ startAngle,
+ endAngle: startAngle + step,
+ middleAngle: startAngle + step / 2,
};
-
- return angleMap[Number(quadrant)] || null;
-};
-
-// 获取象限对应的矩形区域,用于整象限高亮。
-const getQuadrantBox = (quadrant, centerX, centerY, radius) => {
- const boxMap = {
- 1: [centerX - radius, centerY - radius, radius, radius],
- 2: [centerX, centerY - radius, radius, radius],
- 3: [centerX - radius, centerY, radius, radius],
- 4: [centerX, centerY, radius, radius],
- };
-
- return boxMap[Number(quadrant)] || null;
};
// 绘制实心圆,靶纸环区和中心点都会用到。
@@ -240,58 +237,61 @@ const drawTargetRings = (ctx, centerX, centerY, targetRadius, config) => {
}
};
-// 绘制所有高亮区域,支持整象限矩形高亮和指定环数扇区高亮。
-const drawHighlights = (ctx, centerX, centerY, targetRadius, config) => {
- props.highlightAreas.forEach((area = {}) => {
- const angles = getQuadrantAngles(area.quadrant);
+// 高亮后端指定区域;activeRing 有效时只高亮该区域内的单个环。
+const drawSectorHighlight = (ctx, centerX, centerY, targetRadius, config) => {
+ const angles = getSectorAngles(props.activeSector, props.sectorCount);
+ if (!angles) return;
- if (!angles) {
- return;
- }
+ const ring = getPositiveInteger(props.activeRing);
+ const hasActiveRing = ring >= 1 && ring <= config.ringCount;
+ const innerRadius = hasActiveRing
+ ? targetRadius * ((config.ringCount - ring) / config.ringCount)
+ : 0;
+ const outerRadius = hasActiveRing
+ ? targetRadius * ((config.ringCount + 1 - ring) / config.ringCount)
+ : targetRadius;
+ const style = {
+ ...defaultHighlightStyle,
+ ...props.highlightStyle,
+ };
- const highlightStyle = {
- ...defaultHighlightStyle,
- ...(area.style || {}),
- };
- const highlightLineWidth = Math.max(1, targetRadius * highlightStyle.lineWidthRatio);
- const rings = normalizeRings(area.rings || "all", config.ringCount);
- const scope = area.scope || (rings === "all" ? "box" : "sector");
+ drawAnnularSector(
+ ctx,
+ centerX,
+ centerY,
+ innerRadius,
+ outerRadius,
+ angles.startAngle,
+ angles.endAngle,
+ style.color,
+ style.strokeColor,
+ Math.max(1, targetRadius * style.lineWidthRatio)
+ );
+};
- // 整象限默认画成矩形高亮,便于对应 1/2/3/4 号框训练提示。
- if (rings === "all" && scope === "box") {
- const box = getQuadrantBox(area.quadrant, centerX, centerY, targetRadius);
- if (!box) return;
- ctx.beginPath();
- ctx.rect(...box);
- ctx.setFillStyle(highlightStyle.color);
- ctx.fill();
- ctx.setStrokeStyle(highlightStyle.strokeColor);
- ctx.setLineWidth(highlightLineWidth);
- ctx.stroke();
- return;
- }
+// 从正上方开始顺时针绘制所有区域边界。
+const drawSectorLines = (ctx, centerX, centerY, targetRadius) => {
+ const count = getPositiveInteger(props.sectorCount);
+ if (!count) return;
- const targetRings = rings === "all"
- ? Array.from({ length: config.ringCount }, (_, index) => index + 1)
- : rings;
+ const style = {
+ ...defaultSectorStyle,
+ ...props.sectorStyle,
+ };
+ const step = (Math.PI * 2) / count;
- targetRings.forEach((ring) => {
- const innerRadius = targetRadius * ((config.ringCount - ring) / config.ringCount);
- const outerRadius = targetRadius * ((config.ringCount + 1 - ring) / config.ringCount);
- drawAnnularSector(
- ctx,
- centerX,
- centerY,
- innerRadius,
- outerRadius,
- angles[0],
- angles[1],
- highlightStyle.color,
- highlightStyle.strokeColor,
- highlightLineWidth
- );
- });
- });
+ ctx.beginPath();
+ for (let index = 0; index < count; index += 1) {
+ const angle = -Math.PI / 2 + index * step;
+ ctx.moveTo(centerX, centerY);
+ ctx.lineTo(
+ centerX + Math.cos(angle) * targetRadius,
+ centerY + Math.sin(angle) * targetRadius
+ );
+ }
+ ctx.setStrokeStyle(style.color);
+ ctx.setLineWidth(Math.max(1, targetRadius * style.lineWidthRatio));
+ ctx.stroke();
};
// 绘制各环之间的分割线。
@@ -351,44 +351,30 @@ const drawRingLabels = (ctx, centerX, centerY, targetRadius, config) => {
}
};
-// 绘制象限文字。
-const drawQuadrantLabels = (ctx, centerX, centerY, targetRadius) => {
- if (!props.showQuadrantLabels) {
- return;
- }
+// 在每个区域中线位置绘制编号,编号层始终位于高亮和分割线之上。
+const drawSectorLabels = (ctx, centerX, centerY, targetRadius) => {
+ const count = getPositiveInteger(props.sectorCount);
+ if (!props.showSectorLabels || !count) return;
const style = {
- ...defaultQuadrantLabelStyle,
- ...props.quadrantLabelStyle,
- };
- const offset = targetRadius * style.offsetRatio;
- const positions = {
- 1: [centerX - offset, centerY - offset],
- 2: [centerX + offset, centerY - offset],
- 3: [centerX - offset, centerY + offset],
- 4: [centerX + offset, centerY + offset],
+ ...defaultSectorLabelStyle,
+ ...props.sectorLabelStyle,
};
+ const labelRadius = targetRadius * style.radiusRatio;
+ const badgeRadius = Math.max(10, targetRadius * style.badgeRadiusRatio);
- ctx.setFontSize(Math.max(12, targetRadius * style.fontSizeRatio));
+ ctx.setFontSize(Math.max(11, targetRadius * style.fontSizeRatio));
ctx.setTextAlign("center");
ctx.setTextBaseline("middle");
- ctx.setFillStyle(style.color);
- Object.entries(positions).forEach(([key, position]) => {
- const label = props.quadrantLabels?.[key] || props.quadrantLabels?.[Number(key)];
- if (label === undefined || label === null || label === "") return;
- ctx.fillText(String(label), position[0], position[1]);
- });
-};
-
-// 生成高亮区域的绘制 key,只保留真正影响画面的字段。
-const getHighlightDrawKeyAreas = () => {
- return props.highlightAreas.map((area = {}) => ({
- quadrant: area.quadrant,
- rings: area.rings,
- scope: area.scope,
- style: area.style,
- }));
+ for (let sector = 1; sector <= count; sector += 1) {
+ const angles = getSectorAngles(sector, count);
+ const x = centerX + Math.cos(angles.middleAngle) * labelRadius;
+ const y = centerY + Math.sin(angles.middleAngle) * labelRadius;
+ drawCircle(ctx, x, y, badgeRadius, style.backgroundColor);
+ ctx.setFillStyle(style.color);
+ ctx.fillText(String(sector), x, y);
+ }
};
// 生成本次绘制状态的唯一 key,用于避免相同内容重复 draw。
@@ -398,12 +384,16 @@ const getDrawKey = (width, height) => {
height,
coordinateRadius: props.coordinateRadius,
showCrosshair: props.showCrosshair,
- showQuadrantLabels: props.showQuadrantLabels,
showRingLabels: props.showRingLabels,
- highlightAreas: getHighlightDrawKeyAreas(),
+ sectorCount: props.sectorCount,
+ activeSector: props.activeSector,
+ activeRing: props.activeRing,
+ showSectorLabels: props.showSectorLabels,
targetStyleConfig: props.targetStyleConfig,
crosshairStyle: props.crosshairStyle,
- quadrantLabelStyle: props.quadrantLabelStyle,
+ sectorStyle: props.sectorStyle,
+ sectorLabelStyle: props.sectorLabelStyle,
+ highlightStyle: props.highlightStyle,
highlightOnly: props.highlightOnly,
});
};
@@ -431,7 +421,7 @@ const drawTarget = () => {
drawTargetRings(ctx, centerX, centerY, targetRadius, config);
}
- drawHighlights(ctx, centerX, centerY, targetRadius, config);
+ drawSectorHighlight(ctx, centerX, centerY, targetRadius, config);
if (!props.highlightOnly) {
drawRingLines(ctx, centerX, centerY, targetRadius, config);
@@ -444,9 +434,12 @@ const drawTarget = () => {
);
drawCrosshair(ctx, centerX, centerY, targetRadius);
drawRingLabels(ctx, centerX, centerY, targetRadius, config);
- drawQuadrantLabels(ctx, centerX, centerY, targetRadius);
}
+ // 高亮先画,等分线和编号后画,避免高亮覆盖区域边界。
+ drawSectorLines(ctx, centerX, centerY, targetRadius);
+ drawSectorLabels(ctx, centerX, centerY, targetRadius);
+
ctx.draw();
lastDrawKey.value = drawKey;
};
@@ -494,16 +487,19 @@ watch(
() => [
props.coordinateRadius,
props.showCrosshair,
- props.showQuadrantLabels,
props.showRingLabels,
- props.highlightAreas,
+ props.sectorCount,
+ props.activeSector,
+ props.activeRing,
+ props.showSectorLabels,
props.highlightOnly,
props.canvasWidth,
props.canvasHeight,
- props.quadrantLabels,
props.targetStyleConfig,
props.crosshairStyle,
- props.quadrantLabelStyle,
+ props.sectorStyle,
+ props.sectorLabelStyle,
+ props.highlightStyle,
],
scheduleDraw,
{
diff --git a/src/manifest.json b/src/manifest.json
index a074640..ff67d53 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -289,6 +289,9 @@
}
]
},
+ "optimization" : {
+ "subPackages" : true
+ },
"setting" : {
"urlCheck" : false,
"minified" : true,
diff --git a/src/matchWebsocket.js b/src/matchWebsocket.js
index bcf5e13..28bc04d 100644
--- a/src/matchWebsocket.js
+++ b/src/matchWebsocket.js
@@ -4,6 +4,7 @@ import {
createAckMessage,
createHeartbeatAckMessage,
createLeaveMessage,
+ createSyncPracticeInfoMessage,
decodeServerMessage,
getServerMessageTypeName,
} from "@/utils/matchProtocol";
@@ -57,6 +58,7 @@ const BUSINESS_TYPE_BY_SERVER_TYPE = {
const MATCH_READY_SNAPSHOT_PREFIX = "match-ready-snapshot:";
export const MATCH_WS_AUDIO_ACK_EVENT = "match-ws-audio-ack";
export const MATCH_WS_STATE_EVENT = "match-ws-state";
+export const MATCH_WS_PRACTICE_SYNC_EVENT = "match-ws-practice-sync";
function normalizeShootData(shootData) {
if (!shootData || typeof shootData !== "object") return shootData;
@@ -184,6 +186,22 @@ function buildBusinessMessage(message) {
};
}
+function buildPracticeSyncMessage(message) {
+ const practiceInfo = normalizePracticeInfo(message.practice_info);
+ const matchId = normalizeId(
+ pickField(message, "matchId", "match_id") ||
+ practiceInfo.id ||
+ currentContext?.matchId
+ );
+
+ return {
+ matchId,
+ timestamp: message.timestamp,
+ sequence: message.sequence,
+ practiceInfo,
+ };
+}
+
function getReadySnapshotKey(matchId) {
return `${MATCH_READY_SNAPSHOT_PREFIX}${normalizeId(matchId)}`;
}
@@ -611,6 +629,24 @@ function sendHeartbeatAck() {
);
}
+function sendPracticeInfoSync() {
+ if (!socket || !currentContext?.matchId || !currentContext?.userId) return;
+
+ const clientMessage = {
+ type: ClientMessageType.CLIENT_MSG_SYNC_PRACTICE_INFO,
+ match_id: currentContext.matchId,
+ user_id: currentContext.userId,
+ };
+ sendBuffer(
+ createSyncPracticeInfoMessage({
+ matchId: clientMessage.match_id,
+ userId: clientMessage.user_id,
+ }),
+ "CLIENT_MSG_SYNC_PRACTICE_INFO",
+ clientMessage
+ );
+}
+
function sendAck({ matchId, sequence }) {
// sequence 由后端处理,前端只原样带回,不做重排和断线补发。
if (sequence === undefined || sequence === null || sequence === "") return;
@@ -682,26 +718,27 @@ function removeAudioAckListener() {
}
function queueAckAfterAudio(message, businessMessage) {
- // 除心跳外,只要服务端带了 sequence,都需要走 ACK;没有语音的消息立即 ACK。
- if (
- message.sequence === undefined ||
- message.sequence === null ||
- message.sequence === ""
- ) {
- return;
- }
+ // 终止消息即使没有 sequence,也要等结束语音完成后主动关闭连接。
+ const leaveAfterAck = shouldCloseAfterAck(message, businessMessage);
+ const hasSequence =
+ message.sequence !== undefined &&
+ message.sequence !== null &&
+ message.sequence !== "";
+ if (!hasSequence && !leaveAfterAck) return;
+
const task = {
matchId: normalizeId(
pickField(message, "matchId", "match_id") || currentContext?.matchId
),
sequence: message.sequence,
- leaveAfterAck: shouldCloseAfterAck(message, businessMessage),
+ leaveAfterAck,
};
+ const actionLabel = hasSequence ? "ack" : "terminal close";
const audioKeys = getAckAudioKeys(message, businessMessage).filter(Boolean);
if (!audioKeys.length) {
console.log(
- "[match-ws] ack immediately without audio",
+ `[match-ws] ${actionLabel} immediately without audio`,
getServerMessageTypeName(message.type),
message.sequence
);
@@ -715,7 +752,7 @@ function queueAckAfterAudio(message, businessMessage) {
if (index === -1) return;
pendingAcks.splice(index, 1);
console.log(
- "[match-ws] ack audio wait timeout",
+ `[match-ws] ${actionLabel} audio wait timeout`,
getServerMessageTypeName(message.type),
message.sequence,
task.expectedAudioKey
@@ -724,7 +761,7 @@ function queueAckAfterAudio(message, businessMessage) {
}, ACK_AUDIO_TIMEOUT_MS);
pendingAcks.push(task);
console.log(
- "[match-ws] ack queued until audioEnded",
+ `[match-ws] ${actionLabel} queued until audioEnded`,
getServerMessageTypeName(message.type),
message.sequence,
task.expectedAudioKey
@@ -741,11 +778,6 @@ function handleMessage(data) {
return;
}
- const decodedMatchId = normalizeId(pickField(message, "matchId", "match_id"));
- if (decodedMatchId && currentContext) {
- currentContext.matchId = decodedMatchId;
- }
-
if (message.type === ServerMessageType.SERVER_MSG_HEARTBEAT) {
sendHeartbeatAck();
return;
@@ -754,6 +786,34 @@ function handleMessage(data) {
const typeName = getServerMessageTypeName(message.type);
console.log("收到比赛服 WebSocket 消息", typeName, message);
+ const decodedMatchId = normalizeId(pickField(message, "matchId", "match_id"));
+ if (message.type === ServerMessageType.SERVER_MSG_SYNC_PRACTICE_INFO) {
+ // 同步响应是完整快照,不映射成开始/报靶等实时事件,避免重放页面副作用。
+ queueAckAfterAudio(message, null);
+ if (
+ decodedMatchId &&
+ currentContext?.matchId &&
+ decodedMatchId !== currentContext.matchId
+ ) {
+ console.log("[match-ws] ignore mismatched practice sync", {
+ expectedMatchId: currentContext.matchId,
+ receivedMatchId: decodedMatchId,
+ });
+ return;
+ }
+
+ const syncMessage = buildPracticeSyncMessage(message);
+ if (syncMessage.matchId && currentContext) {
+ currentContext.matchId = syncMessage.matchId;
+ }
+ uni.$emit(MATCH_WS_PRACTICE_SYNC_EVENT, syncMessage);
+ return;
+ }
+
+ if (decodedMatchId && currentContext) {
+ currentContext.matchId = decodedMatchId;
+ }
+
const businessMessage = buildBusinessMessage(message);
if (businessMessage?.matchId && currentContext) {
currentContext.matchId = businessMessage.matchId;
@@ -788,6 +848,7 @@ export function connectMatchWebSocket(options = {}) {
userId,
token,
mode,
+ requestPracticeInfoOnOpen = false,
force = false,
reconnecting = false,
reconnectReason = "",
@@ -858,6 +919,7 @@ export function connectMatchWebSocket(options = {}) {
mode: Number.isFinite(normalizedMode) ? normalizedMode : undefined,
isMelee:
Number.isFinite(normalizedMode) ? normalizedMode > 3 : undefined,
+ requestPracticeInfoOnOpen: requestPracticeInfoOnOpen === true,
meleeHalfRest: isSameContext
? currentContext?.meleeHalfRest === true
: false,
@@ -911,6 +973,9 @@ export function connectMatchWebSocket(options = {}) {
reason: reconnectReason,
reconnected: wasReconnected,
});
+ if (currentContext?.requestPracticeInfoOnOpen) {
+ sendPracticeInfoSync();
+ }
});
socketTask.onMessage((res) => {
diff --git a/src/mock/index.js b/src/mock/index.js
index 9d627a8..78da2c2 100644
--- a/src/mock/index.js
+++ b/src/mock/index.js
@@ -4,43 +4,43 @@ export const trainingHomeWeekSchedule = [
key: "mon",
label: "周一",
status: "done",
- icon: "../../static/training-home/done.png",
+ icon: "/pages/training/static/training-home/done.png",
},
{
key: "tue",
label: "周二",
status: "done",
- icon: "../../static/training-home/done.png",
+ icon: "/pages/training/static/training-home/done.png",
},
{
key: "wed",
label: "周三",
status: "missed",
- icon: "../../static/training-home/missed.png",
+ icon: "/pages/training/static/training-home/missed.png",
},
{
key: "thu",
label: "周四",
status: "missed",
- icon: "../../static/training-home/missed.png",
+ icon: "/pages/training/static/training-home/missed.png",
},
{
key: "fri",
label: "周五",
status: "done",
- icon: "../../static/training-home/done.png",
+ icon: "/pages/training/static/training-home/done.png",
},
{
key: "sat",
label: "周六",
status: "done",
- icon: "../../static/training-home/done.png",
+ icon: "/pages/training/static/training-home/done.png",
},
{
key: "sun",
label: "周日",
status: "missed",
- icon: "../../static/training-home/missed.png",
+ icon: "/pages/training/static/training-home/missed.png",
},
];
@@ -73,7 +73,7 @@ export const trainingHomeModes = [
key: "endurance",
title: "耐力训练",
progressText: "当前进度 LV5 >",
- icon: "../../static/training-home/img_3.png",
+ icon: "/pages/training/static/training-home/img_3.png",
recommended: true,
disabled: false,
},
@@ -81,7 +81,7 @@ export const trainingHomeModes = [
key: "precision",
title: "精准训练",
progressText: "当前进度 LV3 >",
- icon: "../../static/training-home/img_4.png",
+ icon: "/pages/training/static/training-home/img_4.png",
recommended: false,
disabled: false,
},
@@ -89,7 +89,7 @@ export const trainingHomeModes = [
key: "rhythm",
title: "节奏训练",
progressText: "当前进度 LV6 >",
- icon: "../../static/training-home/img_5.png",
+ icon: "/pages/training/static/training-home/img_5.png",
recommended: false,
disabled: false,
},
@@ -97,7 +97,7 @@ export const trainingHomeModes = [
key: "power",
title: "力量训练",
progressText: "Coming! LV10",
- icon: "../../static/training-home/img_6.png",
+ icon: "/pages/training/static/training-home/img_6.png",
recommended: false,
disabled: true,
},
diff --git a/src/pages.json b/src/pages.json
index e47dbd0..1a12552 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -105,15 +105,6 @@
{
"path": "pages/mine-bow-data"
},
- {
- "path": "pages/training/difficulty"
- },
- {
- "path": "pages/training/index"
- },
- {
- "path": "pages/training/practise-one"
- },
{
"path": "pages/ota-wifi",
"style": {
@@ -169,6 +160,20 @@
"path": "team-bow-data"
}
]
+ },
+ {
+ "root": "pages/training",
+ "pages": [
+ {
+ "path": "index"
+ },
+ {
+ "path": "difficulty"
+ },
+ {
+ "path": "practise-one"
+ }
+ ]
}
]
}
diff --git a/src/pages/training/components/BowTarget.vue b/src/pages/training/components/BowTarget.vue
index fb44324..e2cf77e 100644
--- a/src/pages/training/components/BowTarget.vue
+++ b/src/pages/training/components/BowTarget.vue
@@ -1,11 +1,14 @@
-
+
-
+
-
+
中场休息
经验 +1
{{ latestOne.ringX ? "X" : latestOne.ring || "未上靶"
@@ -378,8 +493,15 @@ onBeforeUnmount(() => {
}}环
+
{
{{ index + 1 }}
+