三期pk功能开发以及积分两个页
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<image class="img_100" v-if="showLocalImage" :src="imagePath"></image>
|
||||
<image-preview v-else-if="showNetworkImage" class="img_100" :src="imageAddr"></image-preview>
|
||||
<image class="img_100" v-else :src="defaultAvatar"></image>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch, onMounted } from 'vue';
|
||||
import { defaultAvatar } from '@/enum.js';
|
||||
import { getUserInfo } from '@/common/common';
|
||||
|
||||
const imagePath = ref('');
|
||||
const imageAddr = ref('');
|
||||
|
||||
// 状态标识
|
||||
const showLocalImage = ref(false);
|
||||
const showNetworkImage = ref(false);
|
||||
|
||||
// 初始化用户信息
|
||||
const initUserInfo = () => {
|
||||
const info = getUserInfo();
|
||||
imagePath.value = info.imagePath || '';
|
||||
imageAddr.value = info.imageAddr || '';
|
||||
validateAvatarSources();
|
||||
};
|
||||
|
||||
// 验证头像来源
|
||||
const validateAvatarSources = () => {
|
||||
if (imagePath.value) {
|
||||
showLocalImage.value = true;
|
||||
showNetworkImage.value = false;
|
||||
} else if (imageAddr.value) {
|
||||
showLocalImage.value = false;
|
||||
showNetworkImage.value = true;
|
||||
} else {
|
||||
showLocalImage.value = false;
|
||||
showNetworkImage.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 强制刷新方法 - 重新获取用户信息并刷新头像
|
||||
const forceRefreshAvatar = () => {
|
||||
// 清空当前图片信息
|
||||
imagePath.value = '';
|
||||
imageAddr.value = '';
|
||||
// 重新获取用户信息
|
||||
initUserInfo();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initUserInfo();
|
||||
});
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
forceRefreshAvatar
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -2,10 +2,11 @@
|
||||
<view class="item">
|
||||
<view class="top">
|
||||
<view class="type">{{ subject_type_text }}</view>
|
||||
<view class="score" v-if="['settlement', 'examination'].includes(props.mode)">{{ item.tgtGrade }}分</view>
|
||||
<view class="score" v-if="['settlement', 'examination', 'pk_in'].includes(props.mode)">{{ item.tgtGrade }}分</view>
|
||||
<view class="fl1"></view>
|
||||
<view class="right">
|
||||
<!-- 反馈中心 -->
|
||||
<slot name="title-right"></slot>
|
||||
<view class="mark_and_feedback_div" v-if="['examination', 'practice'].includes(props.mode)">
|
||||
<image
|
||||
v-if="props.mode === 'examination'"
|
||||
@@ -23,12 +24,10 @@
|
||||
<template v-if="['mistake'].includes(props.mode)">
|
||||
<view class="expand_button_div" @click="toggleExpand()">
|
||||
<!-- <view class="right_text">{{animationState?'收起':'展开'}}</view> -->
|
||||
|
||||
<view class="toggle-container">
|
||||
<view class="toggle-text" :class="{ active: !animationState }">展开</view>
|
||||
<view class="toggle-text" :class="{ active: animationState }">收起</view>
|
||||
</view>
|
||||
|
||||
<uv-icon
|
||||
class="click_text_icon"
|
||||
name="arrow-right"
|
||||
@@ -52,7 +51,7 @@
|
||||
:isPreview="props.isPreview"
|
||||
:activeVoiceId="subject_data.qnsId"
|
||||
@buutton_click="questionButtonClick"
|
||||
:button_complete_show="props.mode === 'practice'"
|
||||
:button_complete_show="['practice', 'pk_in'].includes(props.mode)"
|
||||
></questionVue>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -67,7 +66,7 @@
|
||||
</view>
|
||||
<view
|
||||
class="option_div_button"
|
||||
v-if="qnsTyp === 'MU' && ['practice', 'study'].includes(props.mode) && !props.isPreview && clearResult"
|
||||
v-if="qnsTyp === 'MU' && ['practice', 'study', 'pk_in'].includes(props.mode) && !props.isPreview && clearResult"
|
||||
>
|
||||
<uv-button
|
||||
type="primary"
|
||||
@@ -85,7 +84,7 @@
|
||||
class="analysis_div"
|
||||
v-if="
|
||||
!clearResult &&
|
||||
['study', 'mistake', 'settlement', 'practice', 'practice_record'].includes(props.mode)
|
||||
['study', 'mistake', 'settlement', 'practice', 'practice_record', 'pk_in'].includes(props.mode)
|
||||
"
|
||||
>
|
||||
<view class="analysis_title" v-if="qnsTyp !== 'ES'">
|
||||
@@ -153,8 +152,8 @@
|
||||
// 错题本: mistake
|
||||
// 学习: study
|
||||
// 考试结算页 settlement
|
||||
// 练习记录页 practice_record
|
||||
return ['examination', 'practice', 'mistake', 'study', 'settlement', 'practice_record'].includes(value);
|
||||
// 练习记录页 practice_record, 'practice_record'
|
||||
return ['examination', 'practice', 'mistake', 'study', 'settlement', 'practice_record', 'pk_in'].includes(value);
|
||||
}
|
||||
},
|
||||
// 是否预览模式
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view>
|
||||
<view style="line-height: 0;">
|
||||
<image :src="imgUrlShow" :mode="mode" @click="showDetail" style="width: 100%; height: 100%"></image>
|
||||
<uni-popup ref="PopupRef" class="popup" mask-background-color="rgba(0,0,0,.2)" background-color="rgba(0,0,0,.2)" @change="changeShow">
|
||||
<view class="overlay-box" @click="closePopup" @touchmove.stop>
|
||||
@@ -167,6 +167,7 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.overlay-box {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
@@ -182,6 +183,7 @@
|
||||
width: 100vw;
|
||||
max-height: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<uni-popup ref="popupRef" class="popup">
|
||||
<view class="tree-selector-div">
|
||||
<view class="title">
|
||||
<view class="title-text">机构选择</view>
|
||||
<view class="back_div" @click="openDialog(false)">
|
||||
<image :src="optionErrorIcon('#000000')" class="img"></image>
|
||||
</view>
|
||||
<uv-tabs
|
||||
class="uvTabs"
|
||||
:list="selectedPaths"
|
||||
:lineWidth="40"
|
||||
lineColor="#0066FF"
|
||||
:activeStyle="{ color: '#0066FF', fontSize: '30rpx' }"
|
||||
keyName="orgName"
|
||||
:current="selectedPaths.length - 1"
|
||||
@click="tabsClick"
|
||||
></uv-tabs>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
ref="scrollRef"
|
||||
scroll-with-animation
|
||||
:scroll-into-view="scrollIntoId"
|
||||
class="tree-selector-scroll"
|
||||
scroll-x="true"
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
<treeSelector :node="orgTree"></treeSelector>
|
||||
</scroll-view>
|
||||
<view class="button-div">
|
||||
<view class="button">
|
||||
<image class="img" :src="resetIcon()"></image>
|
||||
<view class="" @click="click_button('reset')">重置</view>
|
||||
</view>
|
||||
|
||||
<view class="button" @click="click_button('all')">全部</view>
|
||||
<view class="button" @click="click_button('confirm')">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, provide, nextTick } from 'vue';
|
||||
import common, { getUserInfo } from '@/common/common';
|
||||
import { resetIcon, optionErrorIcon } from '@/common/imgSvg';
|
||||
import treeSelector from './treeSelector';
|
||||
const popupRef = ref(null);
|
||||
// 滚动容器的 ref
|
||||
const scrollRef = ref(null);
|
||||
// 控制滚动位置的属性(scroll-top)
|
||||
const scrollIntoId = ref('');
|
||||
const openDialog = (status) => {
|
||||
if (status) {
|
||||
popupRef.value.open('bottom');
|
||||
} else {
|
||||
popupRef.value.close();
|
||||
}
|
||||
};
|
||||
const tabsClick = (item) => {
|
||||
if (item.index === selectedPaths.value.length - 1) {
|
||||
return;
|
||||
}
|
||||
updateSelectedPaths(
|
||||
{
|
||||
orgName: item.orgName,
|
||||
orgId: item.orgId,
|
||||
parentId: item.parentId
|
||||
},
|
||||
item.index
|
||||
);
|
||||
};
|
||||
const orgTreeInit = common.getValue('orgTree');
|
||||
// 初始选中的
|
||||
const initSelect = {
|
||||
orgName: orgTreeInit[0].orgName,
|
||||
orgId: orgTreeInit[0].orgId,
|
||||
parentId: orgTreeInit[0].parentId
|
||||
};
|
||||
const orgTree = ref(orgTreeInit);
|
||||
|
||||
// 把全行信息插入
|
||||
const selectedPaths = ref([initSelect]);
|
||||
|
||||
const updateSelectedPaths = (node, level) => {
|
||||
console.log('node', node);
|
||||
const newPaths = [...selectedPaths.value];
|
||||
newPaths.splice(level);
|
||||
newPaths.push(
|
||||
reactive({
|
||||
orgName: node['orgName'],
|
||||
orgId: node['orgId'],
|
||||
parentId: node['parentId']
|
||||
})
|
||||
);
|
||||
selectedPaths.value = newPaths;
|
||||
nextTick(() => {
|
||||
scrollIntoId.value = `item-${selectedPaths.value.length}`;
|
||||
});
|
||||
};
|
||||
const click_button = (type) => {
|
||||
if (type === 'reset') {
|
||||
updateSelectedPaths(initSelect, 0);
|
||||
} else if (type === 'confirm') {
|
||||
emit('submit', JSON.parse(JSON.stringify(selectedPaths.value)));
|
||||
} else if (type === 'all') {
|
||||
emit('submit', [{ orgName: '全部', orgId: 'A', parentId: '' }]);
|
||||
}
|
||||
};
|
||||
provide('treeContextKey', {
|
||||
selectedPaths,
|
||||
updateSelectedPaths
|
||||
});
|
||||
|
||||
const emit = defineEmits(['submit']);
|
||||
defineExpose({
|
||||
open: () => openDialog(true),
|
||||
close: () => openDialog(false)
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tree-selector-div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 34rpx;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
padding: 40rpx 0 0 0;
|
||||
border-bottom: 4rpx solid #efefef;
|
||||
.back_div {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.img {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
.uvTabs {
|
||||
margin-bottom: -6rpx;
|
||||
:deep(.uv-tabs__wrapper__nav__item) {
|
||||
padding: 0 44rpx 0 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: #ffffff;
|
||||
// box-shadow: 0px -6 15px 0px rgba(0,0,0,0.05);
|
||||
.button {
|
||||
flex: 1;
|
||||
border: none;
|
||||
display: flex;
|
||||
height: 124rpx;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
font-size: 30rpx;
|
||||
.img {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
&:first-child {
|
||||
color: #333333;
|
||||
}
|
||||
&:last-child {
|
||||
color: #0066ff;
|
||||
}
|
||||
&:active {
|
||||
background: #eaeaea;
|
||||
// transform: scale(0.98); /* 按下时轻微缩小,增强反馈 */
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); /* 内阴影模拟按下凹陷感 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tree-selector-scroll {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<view class="tree-selector" :id="`item-${props.level}`">
|
||||
<view class="tree-child-selector" :class="{ fl1: props.level === 0}">
|
||||
<view class="level" v-for="item in props.node" @click="click_node(item)">
|
||||
<view class="node" :class="classList(item.orgId)">
|
||||
{{ item.orgName }}
|
||||
</view>
|
||||
<view class="fl1"></view>
|
||||
</view>
|
||||
</view>
|
||||
<treeSelector v-if="childNode && childNode.length" :node="childNode" :level="props.level + 1"></treeSelector>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineOptions, ref, inject, reactive } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
const treeContextKey = 'treeContextKey';
|
||||
const { selectedPaths, updateSelectedPaths } = inject(treeContextKey);
|
||||
const props = defineProps({
|
||||
// 当前节点数据
|
||||
node: {
|
||||
type: Array, // 改为数组类型
|
||||
required: true,
|
||||
// 验证数组中的每个元素是否符合结构要求
|
||||
validator: (value) => {
|
||||
// 先判断是否为数组
|
||||
if (!Array.isArray(value)) return false;
|
||||
// 验证数组中的每个对象
|
||||
return value.every((item) => {
|
||||
// 每个元素必须是对象
|
||||
if (typeof item !== 'object' || item === null) return false;
|
||||
// 必须包含 orgId(字符串类型)
|
||||
if (typeof item.orgId !== 'string') return false;
|
||||
// 必须包含 orgName(字符串类型)
|
||||
if (typeof item.orgName !== 'string') return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
// 把选择的层级树处理成id列表
|
||||
const selectedPathsOrgCodeList = computed(() => selectedPaths.value.map((res) => res.orgId));
|
||||
// 设置子列表的数据
|
||||
const childNode = computed(() => {
|
||||
const lastItem = selectedPaths.value.at(-1);
|
||||
const selectItem = props.node.find((res) => selectedPathsOrgCodeList.value.includes(res.orgId));
|
||||
if (selectItem) return selectItem['children'] || [];
|
||||
return [];
|
||||
});
|
||||
|
||||
// 判断需要的样式class
|
||||
const classList = (orgId) => {
|
||||
let a = [];
|
||||
if (selectedPathsOrgCodeList.value.includes(orgId) || props.level === selectedPathsOrgCodeList.value.length) {
|
||||
a.push('select-bg');
|
||||
}
|
||||
if (selectedPathsOrgCodeList.value.at(-1) === orgId) {
|
||||
a.push('select-text');
|
||||
}
|
||||
return a;
|
||||
};
|
||||
const emit = defineEmits(['update:selectedKeys']);
|
||||
|
||||
// 处理当前节点被点击
|
||||
const click_node = (node) => {
|
||||
updateSelectedPaths(node, props.level);
|
||||
};
|
||||
|
||||
defineOptions({
|
||||
name: 'treeSelector'
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-selector {
|
||||
border-left: 1rpx solid #eaeaea;
|
||||
border-right: 1rpx solid #eaeaea;
|
||||
display: flex;
|
||||
min-height: 600rpx;
|
||||
max-height: 800rpx;
|
||||
display: flex;
|
||||
transition: all 0.3s ease 2s; /* 关键配置 */
|
||||
}
|
||||
|
||||
.tree-child-selector {
|
||||
|
||||
display: inline-block;
|
||||
// 每一级树形容器
|
||||
min-width: 6rem;
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: none; /* Firefox 特有:直接隐藏滚动条 */
|
||||
-ms-overflow-style: none; /* IE 和 Edge 特有:隐藏滚动条 */
|
||||
&::-webkit-scrollbar {
|
||||
display: none; /* 隐藏滚动条 */
|
||||
}
|
||||
.level {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.node {
|
||||
padding: 0 1rem;
|
||||
background: #f7f7f7;
|
||||
font-weight: 700;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
text-align: left;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
|
||||
white-space: nowrap;
|
||||
/* 强制不换行 */
|
||||
overflow: hidden;
|
||||
/* 超出部分隐藏 */
|
||||
text-overflow: ellipsis;
|
||||
/* 超出部分显示省略号 */
|
||||
|
||||
&.select-bg {
|
||||
background: #fff;
|
||||
|
||||
}
|
||||
&.select-text {
|
||||
color: #0066ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user