|
@@ -0,0 +1,551 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <Transition :enter-active-class="proxy?.animate.mask.enter" :leave-active-class="proxy?.animate.mask.leave">
|
|
|
+ <div class="mask" v-if="optionWindow.show"></div>
|
|
|
+ </Transition>
|
|
|
+ <Transition :enter-active-class="proxy?.animate.dialog.enter" :leave-active-class="proxy?.animate.dialog.leave">
|
|
|
+ <div class="optionWindow" v-if="optionWindow.show">
|
|
|
+ <div class="box">
|
|
|
+ <div class="top">
|
|
|
+ <div class="close" @click="close"></div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="areaBox">
|
|
|
+ <div class="content-title content-title2">
|
|
|
+ {{ project.key !== 'skiprope' ? '测试区域' : '设备组' }}
|
|
|
+ </div>
|
|
|
+ <div class="testAreaChooseRoll">
|
|
|
+ <div class="li" v-for="(item, index) in areaList"
|
|
|
+ :class="{ 'select': chooseArea.includes(item.key), 'ing': item.value != '0' }" :key="index"
|
|
|
+ @click="getChooseArea(item)">
|
|
|
+ <div>{{ item.name }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div @click="getAllArea" class="allBtn" :class="{ 'active': chooseAllState }">{{ chooseAllState ? '重 置' :
|
|
|
+ '全 选' }}</div>
|
|
|
+ </div>
|
|
|
+ <!-- <div class="standardBox">
|
|
|
+ <div class="content-title content-title2">评分标准</div>
|
|
|
+ <div class="standardBoxBtn">
|
|
|
+ <div v-for="(item, index) in standardList" :class="{ 'select': optionForm.standard == item.value }"
|
|
|
+ :key="index" class="li" @click="getChooseStandard(item)">
|
|
|
+ <div>{{ item.label }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div> -->
|
|
|
+ <div class="switchList">
|
|
|
+ <div class="li">
|
|
|
+ <span>举右手识别</span>
|
|
|
+ <el-switch v-model="optionForm.gesture" :active-value="true" :inactive-value="false"
|
|
|
+ style="--el-switch-on-color: #08FFA9; --el-switch-off-color: #ACACAC" />
|
|
|
+ </div>
|
|
|
+ <div class="li" v-if="project.key.slice(0, 3) != 'run'">
|
|
|
+ <span>体验模式</span>
|
|
|
+ <el-switch v-model="optionForm.demo" :active-value="1" :inactive-value="0"
|
|
|
+ style="--el-switch-on-color: #08FFA9; --el-switch-off-color: #ACACAC" />
|
|
|
+ </div>
|
|
|
+ <div class="li" v-if="['skiprope'].includes(project.key)">
|
|
|
+ <span>接收心率</span>
|
|
|
+ <el-switch v-model="optionForm.hasHB" :active-value="true" :inactive-value="false"
|
|
|
+ style="--el-switch-on-color: #08FFA9; --el-switch-off-color: #ACACAC" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="['heartbeat'].includes(project.key)">
|
|
|
+ <div>设置运动量目标</div>
|
|
|
+ <div>
|
|
|
+ 平均心率:
|
|
|
+ <div style="display: flex;">
|
|
|
+ <el-input v-model="optionForm.standHBL" />
|
|
|
+ ~
|
|
|
+ <el-input v-model="optionForm.standHBH" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ 预警心率:
|
|
|
+ <div>
|
|
|
+ <el-input v-model="optionForm.highHB" size="small" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="switchList">
|
|
|
+ <div class="li" v-if="['jumprope', 'jumpingjack', 'situp'].includes(project.key)">
|
|
|
+ <span>时长</span>
|
|
|
+ <el-select v-model="optionForm.time" :popper-append-to-body="false" placeholder="请选择">
|
|
|
+ <el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="li" v-if="['jumprope', 'jumpingjack', 'situp'].includes(project.key)">
|
|
|
+ <span>音乐</span>
|
|
|
+ <el-select v-model="optionForm.music" :popper-append-to-body="false" placeholder="请选择" clearable>
|
|
|
+ <el-option v-for="item in musicList" :key="item.id" :label="item.name" :value="item.url" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="bottom">
|
|
|
+ <div class="btn" @click="confirm">
|
|
|
+ <el-icon class="is-loading" v-if="loading">
|
|
|
+ <Loading />
|
|
|
+ </el-icon>
|
|
|
+ <div>确 定</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="boxBg" :style="{ backgroundImage: 'url(static/images/train/' + project.key + '.png)' }">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Transition>
|
|
|
+ </div>
|
|
|
+
|
|
|
+</template>
|
|
|
+<script setup lang="ts">
|
|
|
+import useAppStore from '@/store/modules/app';
|
|
|
+const { proxy } = getCurrentInstance() as any;
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+//父值
|
|
|
+const props = defineProps({
|
|
|
+ projectList: {
|
|
|
+ type: Array as any,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+//评分标准,数据字典无需双向绑定
|
|
|
+const standardList = [{ label: '考试', value: 0 }, { label: '体测', value: 1 }]
|
|
|
+
|
|
|
+//时长选择,数据字典无需双向绑定
|
|
|
+const timeList =
|
|
|
+ [{
|
|
|
+ label: '10秒',
|
|
|
+ value: 10
|
|
|
+ }, {
|
|
|
+ label: '20秒',
|
|
|
+ value: 20
|
|
|
+ }, {
|
|
|
+ label: '30秒',
|
|
|
+ value: 30
|
|
|
+ }, {
|
|
|
+ label: '1分钟',
|
|
|
+ value: 60
|
|
|
+ }, {
|
|
|
+ label: '2分钟',
|
|
|
+ value: 120
|
|
|
+ }, {
|
|
|
+ label: '3分钟',
|
|
|
+ value: 180
|
|
|
+ }, {
|
|
|
+ label: '5分钟',
|
|
|
+ value: 300
|
|
|
+ }];
|
|
|
+
|
|
|
+const data = reactive<any>({
|
|
|
+ optionForm: {
|
|
|
+ gesture: true,
|
|
|
+ standard: 0
|
|
|
+ },
|
|
|
+ optionWindow: {
|
|
|
+ show: false,
|
|
|
+ time: "",
|
|
|
+ },
|
|
|
+ project: {},
|
|
|
+ musicList: [],
|
|
|
+ classList: [],
|
|
|
+ chooseArea: [],
|
|
|
+ chooseAllState: false,
|
|
|
+ loading: false,
|
|
|
+});
|
|
|
+
|
|
|
+const { optionForm, optionWindow, project, musicList, classList, chooseArea, chooseAllState, loading } = toRefs(data);
|
|
|
+
|
|
|
+//打开
|
|
|
+const open = (data: any) => {
|
|
|
+ console.log("data", data);
|
|
|
+ getClass();
|
|
|
+ getMusic();
|
|
|
+ project.value = data;
|
|
|
+ chooseArea.value = [];
|
|
|
+ optionWindow.value.show = true;
|
|
|
+};
|
|
|
+
|
|
|
+//关闭
|
|
|
+const close = () => {
|
|
|
+ optionWindow.value.show = false;
|
|
|
+};
|
|
|
+
|
|
|
+//筛选测试区
|
|
|
+const areaList = computed(() => {
|
|
|
+ let area = [];
|
|
|
+ let list = props.projectList.filter((item: any) => {
|
|
|
+ return item.key == project.value.key;
|
|
|
+ })
|
|
|
+ if (list.length > 0) {
|
|
|
+ area = list[0].area;
|
|
|
+ }
|
|
|
+ //console.log("area", area)
|
|
|
+ return area;
|
|
|
+});
|
|
|
+
|
|
|
+//获取音乐
|
|
|
+const getMusic = () => {
|
|
|
+ const list: any = useAppStore().getMusic();
|
|
|
+ if (list.length) {
|
|
|
+ musicList.value = list;
|
|
|
+ } else {
|
|
|
+ proxy?.$http.train.musicList().then((res: any) => {
|
|
|
+ if (res.data.length > 0) {
|
|
|
+ let myList: any = res.data;
|
|
|
+ musicList.value = myList;
|
|
|
+ useAppStore().setMusic(myList);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+//获取班级列表
|
|
|
+const getClass = () => {
|
|
|
+ const list: any = useAppStore().getClass();
|
|
|
+ if (list.length) {
|
|
|
+ classList.value = list;
|
|
|
+ } else {
|
|
|
+ let params = {
|
|
|
+ page: 1,
|
|
|
+ per_page: 9999,
|
|
|
+ };
|
|
|
+ proxy?.$http.common.classList(params).then((res: any) => {
|
|
|
+ if (res.data.length > 0) {
|
|
|
+ let myList: any = res.data;
|
|
|
+ classList.value = myList;
|
|
|
+ useAppStore().setClass(myList);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//选择测试区
|
|
|
+const getChooseArea = (data: any) => {
|
|
|
+ if (chooseArea.value.length > 10) {
|
|
|
+ optionForm.value.gesture = false;
|
|
|
+ } else {
|
|
|
+ optionForm.value.gesture = true;
|
|
|
+ }
|
|
|
+ let id = data.key;
|
|
|
+ let inData = chooseArea.value.includes(id);
|
|
|
+ if (inData) {
|
|
|
+ //已存在就移除
|
|
|
+ chooseArea.value = chooseArea.value.filter((item: any) => {
|
|
|
+ return item != id
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ //不存在就点选
|
|
|
+ chooseArea.value.push(id);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//选择测试标准
|
|
|
+const getChooseStandard = (data: any) => {
|
|
|
+ optionForm.value.standard = data.value;
|
|
|
+};
|
|
|
+
|
|
|
+//全选或全取消测试区
|
|
|
+const getAllArea = (data: any) => {
|
|
|
+ chooseAllState.value = !chooseAllState.value;
|
|
|
+ if (chooseAllState.value) {
|
|
|
+ //全选
|
|
|
+ chooseArea.value = areaList.value.filter((item: any) => {
|
|
|
+ return item.value == 0;
|
|
|
+ }).map((item: any) => {
|
|
|
+ return item.key;
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ //全取消
|
|
|
+ chooseArea.value = [];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//确定
|
|
|
+const confirm = (data: any) => {
|
|
|
+ optionForm.value.project = project.value.key;
|
|
|
+ optionForm.value.classes = classList.value.map((item: any) => { return item.id; }).join();
|
|
|
+ optionForm.value.area = chooseArea.value.join();
|
|
|
+ console.log("optionForm", optionForm.value);
|
|
|
+ if (!optionForm.value.classes) {
|
|
|
+ getClass();
|
|
|
+ let message = "没有班级,将重新加载班级请重新操作";
|
|
|
+ ElMessage({ message: message, type: 'error', duration: 3 * 1000 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!optionForm.value.area) {
|
|
|
+ let message = "请选择测试区";
|
|
|
+ ElMessage({ message: message, type: 'error', duration: 3 * 1000 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (optionForm.value.standard == null) {
|
|
|
+ let message = "请选择评分标准";
|
|
|
+ ElMessage({ message: message, type: 'error', duration: 3 * 1000 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ loading.value = true;
|
|
|
+ if (chooseArea.value.length > 1) {
|
|
|
+ //多区域
|
|
|
+ router.push({ path: '/train/multiple', query: optionForm.value });
|
|
|
+ }
|
|
|
+ else if (["run50", "run70", "run100", "run200", "run400", "run800", "run1000", "run15x4", "run10x4", "run50x8"].includes(project.value.key)) {
|
|
|
+ //跑步项目
|
|
|
+ router.push({ path: '/train/run', query: optionForm.value });
|
|
|
+ } else {
|
|
|
+ //单项
|
|
|
+ router.push({ path: '/train/test', query: optionForm.value });
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+})
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ loading.value = false;
|
|
|
+})
|
|
|
+
|
|
|
+//暴露给父组件用
|
|
|
+defineExpose({
|
|
|
+ open,
|
|
|
+ close,
|
|
|
+ optionWindow
|
|
|
+})
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.mask {
|
|
|
+ position: fixed;
|
|
|
+ height: 100vh;
|
|
|
+ width: 100vw;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ background: rgba(0, 0, 0, 0.78);
|
|
|
+ z-index: 998;
|
|
|
+}
|
|
|
+
|
|
|
+.optionWindow {
|
|
|
+ position: fixed;
|
|
|
+ height: 100vh;
|
|
|
+ width: 100vw;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: #FFFFFF;
|
|
|
+ z-index: 999;
|
|
|
+
|
|
|
+ .box {
|
|
|
+ width: 50%;
|
|
|
+ border-radius: 1.6rem;
|
|
|
+ background: linear-gradient(46deg, #092941 -83%, #2A484B 95%);
|
|
|
+ box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.2);
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ .top {
|
|
|
+ color: #ffffff;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ position: relative;
|
|
|
+ z-index: 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content {
|
|
|
+ max-height: 65vh;
|
|
|
+ margin-bottom: 2vh;
|
|
|
+ position: relative;
|
|
|
+ z-index: 2;
|
|
|
+
|
|
|
+ .content-title {
|
|
|
+ font-size: 1.65rem;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-title2 {
|
|
|
+ padding: 0 0 2.5vh 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .areaBox {
|
|
|
+ padding-bottom: 2vh;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .testAreaChooseRoll {
|
|
|
+ width: 100%;
|
|
|
+ max-height: 30vh;
|
|
|
+ overflow-y: scroll;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 0 20px 0 30px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ margin-bottom: 5px;
|
|
|
+
|
|
|
+ .li {
|
|
|
+ border: 3px solid #979797;
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 1.6rem;
|
|
|
+ margin: 0 8px 16px 8px;
|
|
|
+ padding: 5px 8px;
|
|
|
+ min-width: 2.6rem;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-weight: bold;
|
|
|
+ text-align: center;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .select {
|
|
|
+ border: 3px solid #ffffff;
|
|
|
+ background: #ffffff;
|
|
|
+ color: #1A293A;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ing {
|
|
|
+ border: 3px solid #ff0000;
|
|
|
+ color: #ff0000;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ border-width: 2px;
|
|
|
+ border-radius: 4px;
|
|
|
+ border-style: dashed;
|
|
|
+ border-color: transparent;
|
|
|
+ background-color: rgba(26, 62, 78, 0.9);
|
|
|
+ background-clip: padding-box;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-button:hover {
|
|
|
+ border-radius: 6px;
|
|
|
+ background: rgba(26, 62, 78, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .allBtn {
|
|
|
+ display: inline;
|
|
|
+ margin: 0 auto;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .standardBox {
|
|
|
+ padding: 2.5vh 0;
|
|
|
+
|
|
|
+ .standardBoxBtn {
|
|
|
+ display: flex;
|
|
|
+ width: 42%;
|
|
|
+ height: 3.6rem;
|
|
|
+ line-height: 3.6rem;
|
|
|
+ font-size: 1.65rem;
|
|
|
+ margin: 0 auto;
|
|
|
+ border-radius: 1.8rem;
|
|
|
+ font-size: 2rem;
|
|
|
+ text-align: center;
|
|
|
+ color: #1A293A;
|
|
|
+ background: #ACACAC;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .li {
|
|
|
+ width: 50%;
|
|
|
+ text-align: center;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .select {
|
|
|
+ border-radius: 1.8rem;
|
|
|
+ box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
|
|
|
+ background: radial-gradient(50% 181% at 163% 0%, #35FFC6 0%, #00FFE8 100%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ .switchList {
|
|
|
+ padding: 2.5vh 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ .li {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin: 0 2rem;
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 1.65rem;
|
|
|
+ margin-right: 8px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select {
|
|
|
+ width: 100px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .bottom {
|
|
|
+ height: 3.59rem;
|
|
|
+ padding: 2.5rem 0;
|
|
|
+ align-items: center;
|
|
|
+ color: #ffffff;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ position: relative;
|
|
|
+ z-index: 2;
|
|
|
+
|
|
|
+ .btn {
|
|
|
+ width: 33%;
|
|
|
+ height: 3.59rem;
|
|
|
+ line-height: 3.59rem;
|
|
|
+ font-size: 2rem;
|
|
|
+ margin: 0 auto;
|
|
|
+ border-radius: 0.83rem;
|
|
|
+ font-size: 2rem;
|
|
|
+ text-align: center;
|
|
|
+ color: #1A293A;
|
|
|
+ background: radial-gradient(141% 126% at 5% 93%, #8EFFA9 0%, #07FFE7 100%);
|
|
|
+ box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
|
|
|
+ cursor: pointer;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ .is-loading {
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .boxBg {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ display: block;
|
|
|
+ background-position: center center;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: contain;
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ z-index: 1;
|
|
|
+ opacity: 0.1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .close {
|
|
|
+ margin: 1.5rem 1.5rem 0 0;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transform: rotate(180deg);
|
|
|
+ background-color: rgba(216, 216, 216, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|