You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/src/views/components/DynamicTrainingStepNavigato...

101 lines
2.4 KiB
Vue

<template>
<aside v-if="customSteps.length" class="dynamic-step-navigator">
<span class="navigator-label">补充步骤</span>
<el-button
v-for="step in customSteps"
:key="step.id"
size="small"
plain
@click="openStep(step)"
>
{{ step.name }}
</el-button>
</aside>
</template>
<script setup>
import { getTrainingTaskByKey } from "@/api/trainingTask";
const props = defineProps({
taskKey: {
type: String,
default: "",
},
});
const router = useRouter();
const customSteps = ref([]);
watch(
() => props.taskKey,
async (taskKey) => {
customSteps.value = [];
if (!taskKey) return;
try {
const res = await getTrainingTaskByKey(taskKey);
customSteps.value = parseSteps(res?.data?.steps).filter((step) => step.kind === "custom");
} catch (error) {
// The original task page remains available when task configuration is unavailable.
}
},
{ immediate: true }
);
function parseSteps(value) {
let source = value;
if (typeof value === "string") {
try {
source = JSON.parse(value);
} catch (error) {
source = value.split(/[,\n]/);
}
}
if (!Array.isArray(source)) return [];
return source
.map((item, index) => {
const raw = item && typeof item === "object" ? item : {};
const name = typeof item === "object" ? String(raw.name || "").trim() : String(item || "").trim();
return {
id: raw.id || `${index < 4 ? "builtin" : "custom"}-${index + 1}`,
name,
kind: raw.kind === "custom" || (!raw.kind && index >= 4) ? "custom" : "builtin",
};
})
.filter((step) => step.name);
}
function openStep(step) {
router.push({ name: "CustomTrainingStep", params: { taskKey: props.taskKey, stepId: step.id } });
}
</script>
<style lang="scss" scoped>
.dynamic-step-navigator {
position: fixed;
right: 28px;
bottom: 24px;
z-index: 20;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
max-width: min(560px, calc(100vw - 48px));
padding: 10px 12px;
border: 1px solid rgba(85, 202, 255, 0.42);
border-radius: 12px;
background: rgba(3, 26, 42, 0.94);
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.3);
}
.navigator-label {
align-self: center;
color: #8cdfff;
font-size: 13px;
font-weight: 700;
}
@media (max-width: 768px) {
.dynamic-step-navigator { right: 12px; bottom: 12px; }
}
</style>