s
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
# 启用严格模式,确保依赖版本一致
|
||||||
|
strict-peer-dependencies=false
|
||||||
|
|
||||||
|
# 配置依赖安装目录(pnpm 特有,节省磁盘空间)
|
||||||
|
store-dir=~/.pnpm-store
|
||||||
|
|
||||||
|
# 兼容 uniapp 对依赖的查找逻辑
|
||||||
|
node-linker=hoisted
|
||||||
|
|
||||||
|
# 忽略废弃依赖警告
|
||||||
|
ignore-deprecations=all
|
||||||
|
|
||||||
|
# 忽略对等依赖警告
|
||||||
|
strict-peer-dependencies=false
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<image class="img" src="@/static/images/pointsAndRank/badge-title-right.png" mode=""></image>
|
<image class="img" src="@/static/images/pointsAndRank/badge-title-right.png" mode=""></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-list-container">
|
<view class="item-list-container">
|
||||||
<view class="item" v-for="item in itemList.child">
|
<view class="item" v-for="item in itemList.child" @click="showDetailed(item)">
|
||||||
<view class="badge-img">
|
<view class="badge-img">
|
||||||
<image-preview
|
<image-preview
|
||||||
class="img"
|
class="img"
|
||||||
@@ -56,8 +56,32 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- </view> -->
|
|
||||||
</z-paging>
|
</z-paging>
|
||||||
|
<uni-popup ref="popup" class="popup">
|
||||||
|
<view class="popup-content" @touchmove.stop>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="max-div">
|
||||||
|
<view class="points-img-div">
|
||||||
|
<image-preview class="img" :src="detailedInfo.ossAddr" mode="widthFix"></image-preview>
|
||||||
|
</view>
|
||||||
|
<view class="points-title">{{ detailedInfo.badgeName }}</view>
|
||||||
|
<view class="points-div select-institution-div">
|
||||||
|
<view class="points-remark">{{ detailedInfo.remark }}</view>
|
||||||
|
<view class="points-time">{{ detailedInfo.obtainTm }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="points-button-div">
|
||||||
|
<uv-button
|
||||||
|
class="button"
|
||||||
|
text="关闭"
|
||||||
|
:custom-style="customStyle"
|
||||||
|
@click="closeDetailed()"
|
||||||
|
></uv-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -68,29 +92,63 @@
|
|||||||
import useZpaging from '@/composables/useZpaging.js';
|
import useZpaging from '@/composables/useZpaging.js';
|
||||||
import { queryRankWall } from '@/api/pointsAndRank.js';
|
import { queryRankWall } from '@/api/pointsAndRank.js';
|
||||||
import { getUserInfo } from '@/common/common';
|
import { getUserInfo } from '@/common/common';
|
||||||
|
const buttonColor = '';
|
||||||
|
const customStyle = {
|
||||||
|
background:"linear-gradient( 0deg, RGBA(8, 9, 4, 1) 0%, RGBA(100, 100, 100, .5) 100%)",
|
||||||
|
color:'#fff',
|
||||||
|
width: '290rpx',
|
||||||
|
height: '100rpx',
|
||||||
|
border: '4rpx solid #EEDA9B',
|
||||||
|
borderRadius: '180rpx'
|
||||||
|
}
|
||||||
|
const popup = ref(null);
|
||||||
const user_info = reactive({
|
const user_info = reactive({
|
||||||
userName: '',
|
userName: '',
|
||||||
userId: ''
|
userId: ''
|
||||||
});
|
});
|
||||||
|
const detailedInfo = ref({
|
||||||
|
ossAddr: '',
|
||||||
|
message: '',
|
||||||
|
num: ''
|
||||||
|
});
|
||||||
const fetchFunction = (params) => {
|
const fetchFunction = (params) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
queryRankWall().then(({ body }) => {
|
queryRankWall().then(({ body }) => {
|
||||||
let originalData = body;
|
let originalData = body;
|
||||||
// 处理逻辑:构建二维数组(外层分类列表 + 内层徽章列表)
|
const scoreRankBadges = originalData['积分段位徽章'];
|
||||||
const twoDimensionalArray = [];
|
|
||||||
// 遍历每个分类,生成二维数组的每一项
|
// 2. 动态合并除“积分段位徽章”外的所有徽章数组
|
||||||
Object.entries(originalData).forEach(([categoryKey, badgeArray]) => {
|
const otherBadges = [];
|
||||||
// 构建外层列表项:包含 name 和子列表 badgeList
|
// 遍历原始数据的所有键
|
||||||
const categoryItem = {
|
Object.keys(originalData).forEach((key) => {
|
||||||
name: categoryKey, // 第一维度的 name 是原始键
|
// 排除固定键,其余全部合并
|
||||||
child: badgeArray // 子列表:直接放入当前分类的所有徽章数据
|
if (key !== '积分段位徽章') {
|
||||||
};
|
// 确保对应值是数组,避免非数组类型导致错误
|
||||||
// 将分类项加入二维数组
|
if (Array.isArray(originalData[key])) {
|
||||||
twoDimensionalArray.push(categoryItem);
|
otherBadges.push(...originalData[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// // 处理逻辑:构建二维数组(外层分类列表 + 内层徽章列表)
|
||||||
|
// const twoDimensionalArray = [];
|
||||||
|
// // 遍历每个分类,生成二维数组的每一项
|
||||||
|
// Object.entries(originalData).forEach(([categoryKey, badgeArray]) => {
|
||||||
|
// // 构建外层列表项:包含 name 和子列表 badgeList
|
||||||
|
// const categoryItem = {
|
||||||
|
// name: categoryKey, // 第一维度的 name 是原始键
|
||||||
|
// child: badgeArray // 子列表:直接放入当前分类的所有徽章数据
|
||||||
|
// };
|
||||||
|
// // 将分类项加入二维数组
|
||||||
|
// twoDimensionalArray.push(categoryItem);
|
||||||
|
// });
|
||||||
|
|
||||||
uni.$emit('update_me_data', true);
|
uni.$emit('update_me_data', true);
|
||||||
resolve({
|
resolve({
|
||||||
body: twoDimensionalArray
|
body: [
|
||||||
|
{ name: '段位徽章', child: scoreRankBadges },
|
||||||
|
{ name: '节气徽章', child: otherBadges }
|
||||||
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -98,7 +156,16 @@
|
|||||||
const { pagingRef, queryList, data_list, search } = useZpaging({
|
const { pagingRef, queryList, data_list, search } = useZpaging({
|
||||||
fetchFunction
|
fetchFunction
|
||||||
});
|
});
|
||||||
|
// 显示详细信息
|
||||||
|
const showDetailed = (item) => {
|
||||||
|
if(item.isOpen !== 'Y') return;
|
||||||
|
detailedInfo.value = item;
|
||||||
|
popup.value.open();
|
||||||
|
};
|
||||||
|
const closeDetailed = () => {
|
||||||
|
popup.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
Object.assign(user_info, getUserInfo());
|
Object.assign(user_info, getUserInfo());
|
||||||
pagingRef.value.reload();
|
pagingRef.value.reload();
|
||||||
@@ -107,6 +174,33 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
.popup {
|
||||||
|
.popup-content {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40rpx 0;
|
||||||
|
background-color: rgba(0,0,0,.85);
|
||||||
|
}
|
||||||
|
.max-div {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: var(--status-bar-height);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.points-img-div {
|
||||||
|
width: 420rpx;
|
||||||
|
height: 420rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
.main-div {
|
.main-div {
|
||||||
padding-top: 30rpx;
|
padding-top: 30rpx;
|
||||||
}
|
}
|
||||||
@@ -187,6 +281,7 @@
|
|||||||
gap: 40rpx; /* 调大间距(根据需要调整数值) */
|
gap: 40rpx; /* 调大间距(根据需要调整数值) */
|
||||||
padding: 6vw;
|
padding: 6vw;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
/* 计算宽度:总宽度减去两倍间距后三等分(保证三列) */
|
/* 计算宽度:总宽度减去两倍间距后三等分(保证三列) */
|
||||||
@@ -195,7 +290,6 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
.badge-img {
|
.badge-img {
|
||||||
width: calc(27vw - 14rpx); /* 基于父元素宽度计算,更适配 */
|
width: calc(27vw - 14rpx); /* 基于父元素宽度计算,更适配 */
|
||||||
height: calc(27vw - 14rpx);
|
height: calc(27vw - 14rpx);
|
||||||
@@ -218,7 +312,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
color: #e2d1cc;
|
color: #e2d1cc;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,4 +378,76 @@
|
|||||||
background-repeat: no-repeat; /* 不重复平铺 */
|
background-repeat: no-repeat; /* 不重复平铺 */
|
||||||
background-color: #fef1dd;
|
background-color: #fef1dd;
|
||||||
}
|
}
|
||||||
|
.points-title{
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 54rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
margin: 20rpx 0 60rpx 0;
|
||||||
|
}
|
||||||
|
.points-button-div{
|
||||||
|
margin-bottom: 200rpx;
|
||||||
|
margin-top: 180rpx;
|
||||||
|
.button{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-institution-div {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
width: 560rpx;
|
||||||
|
height: 130rpx;
|
||||||
|
padding: 12rpx 0;
|
||||||
|
border: 2rpx solid #EEDA9B;
|
||||||
|
background: linear-gradient(150deg, RGBA(86, 82, 73, 1), RGBA(17, 17, 17, .4)) border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
.points-remark{
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.points-time{
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 边框高光效果 */
|
||||||
|
.select-institution-div2::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
border: 4rpx solid transparent;
|
||||||
|
background: linear-gradient(90deg, transparent, RGBA(251, 231, 178, 1), transparent) border-box;
|
||||||
|
-webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
|
||||||
|
-webkit-mask-composite: xor;
|
||||||
|
mask-composite: exclude;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
/* 初始位置在左侧外部 */
|
||||||
|
background-size: 200% 100%;
|
||||||
|
|
||||||
|
/* 动画:高光从左到右流动 */
|
||||||
|
animation: highlightFlow 20s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 定义高光流动动画 */
|
||||||
|
@keyframes highlightFlow {
|
||||||
|
0% {
|
||||||
|
background-position: -100% 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 100% 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
* 音频路由兼容方案(适配 H5/小程序/不支持 setAudioRoute 的设备)
|
* 音频路由兼容方案(适配 H5/小程序/不支持 setAudioRoute 的设备)
|
||||||
* @param {string} type - earpiece(听筒)/speaker(扬声器)
|
* @param {string} type - earpiece(听筒)/speaker(扬声器)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
// 关闭通话
|
// 关闭通话
|
||||||
const closeTalking = async () => {
|
const closeTalking = async () => {
|
||||||
// todo 防抖
|
// todo 防抖
|
||||||
common.show('', '挂断'+(isVideoStyle.value?'视频':'电话')+'将结束训练,是否确认?').then((res) => {
|
common.show('', '挂断' + (isVideoStyle.value ? '视频' : '电话') + '将结束训练,是否确认?').then((res) => {
|
||||||
if (res) {
|
if (res) {
|
||||||
destroy(); // 走关闭销毁流程
|
destroy(); // 走关闭销毁流程
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,6 @@
|
|||||||
console.log('当前分贝', res);
|
console.log('当前分贝', res);
|
||||||
};
|
};
|
||||||
|
|
||||||
const targetTimestamp = ref(0);
|
|
||||||
// 定时器实例
|
// 定时器实例
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
|
||||||
@@ -127,13 +126,15 @@
|
|||||||
return `${minutes}:${seconds.toString().padStart(2, '0')}`; // 秒补零
|
return `${minutes}:${seconds.toString().padStart(2, '0')}`; // 秒补零
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const targetTimestamp = ref(0);
|
||||||
// 计算属性:实时格式化剩余时间
|
// 计算属性:实时格式化剩余时间
|
||||||
const formattedTime = ref(0);
|
const formattedTime = ref('00:00');
|
||||||
// 3. 更新剩余时间的核心方法
|
// 3. 更新剩余时间的核心方法
|
||||||
const updateRemaining = () => {
|
const updateRemaining = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const diff = now - targetTimestamp.value;
|
const diff = now - targetTimestamp.value;
|
||||||
formattedTime.value = formatTime(Math.max(0, Math.floor(diff / 1000)));
|
const seconds = Math.max(0, Math.floor(diff / 1000));
|
||||||
|
formattedTime.value = formatTime(seconds);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onStartRecord = (body) => {
|
const onStartRecord = (body) => {
|
||||||
@@ -143,7 +144,8 @@
|
|||||||
console.log('连接成功开始' + dataInfo.traInterTypDesc);
|
console.log('连接成功开始' + dataInfo.traInterTypDesc);
|
||||||
isRecording.value = true;
|
isRecording.value = true;
|
||||||
isVideo.value && talkCameraRef.value.startPreview();
|
isVideo.value && talkCameraRef.value.startPreview();
|
||||||
timer = setInterval(updateRemaining, 1000);
|
if (timer) clearInterval(timer); // 清除旧的定时器,避免多个定时器叠加
|
||||||
|
timer = setInterval(updateRemaining, 400);
|
||||||
// 立即执行一次
|
// 立即执行一次
|
||||||
updateRemaining();
|
updateRemaining();
|
||||||
talkMicrophoneRef.value.start({
|
talkMicrophoneRef.value.start({
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
const { defineConfig } = require('@vue/cli-service');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = defineConfig({
|
||||||
|
// 基础路径(根据你的部署环境调整)
|
||||||
|
publicPath: './',
|
||||||
|
// 输出目录
|
||||||
|
outputDir: 'dist',
|
||||||
|
// 静态资源目录
|
||||||
|
assetsDir: 'static',
|
||||||
|
// 关闭 eslint 校验(可选,根据项目需求)
|
||||||
|
lintOnSave: false,
|
||||||
|
// webpack 配置
|
||||||
|
configureWebpack: {
|
||||||
|
// 配置路径别名(和 Vite 的 alias 功能一致)
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, 'src'),
|
||||||
|
'@/components': path.resolve(__dirname, 'src/components'),
|
||||||
|
'@/utils': path.resolve(__dirname, 'src/utils')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 优化打包(可选)
|
||||||
|
optimization: {
|
||||||
|
minimizer: [
|
||||||
|
// 已安装 terser,可配置压缩
|
||||||
|
require('terser-webpack-plugin')({
|
||||||
|
terserOptions: {
|
||||||
|
compress: {
|
||||||
|
drop_console: process.env.NODE_ENV === 'production', // 生产环境移除 console
|
||||||
|
drop_debugger: true // 移除 debugger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 解决可能的依赖冲突
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.vue', '.js', '.jsx', '.json'],
|
||||||
|
fallback: {
|
||||||
|
"crypto": require.resolve("crypto-js"),
|
||||||
|
"text-encoding": require.resolve("text-encoding")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 链式修改 webpack 配置
|
||||||
|
chainWebpack: config => {
|
||||||
|
// 处理 Vue 文件
|
||||||
|
config.module
|
||||||
|
.rule('vue')
|
||||||
|
.test(/\.vue$/)
|
||||||
|
.use('vue-loader')
|
||||||
|
.loader('vue-loader')
|
||||||
|
.end();
|
||||||
|
|
||||||
|
// 处理 SCSS(项目依赖了 sass,需配置 loader)
|
||||||
|
config.module
|
||||||
|
.rule('scss')
|
||||||
|
.test(/\.scss$/)
|
||||||
|
.use('sass-loader')
|
||||||
|
.loader('sass-loader')
|
||||||
|
.options({
|
||||||
|
implementation: require('sass')
|
||||||
|
})
|
||||||
|
.end();
|
||||||
|
},
|
||||||
|
// 环境变量配置(适配你的多环境脚本)
|
||||||
|
devServer: {
|
||||||
|
// 开发服务器配置(如代理、端口等)
|
||||||
|
port: 8080,
|
||||||
|
open: true,
|
||||||
|
proxy: {
|
||||||
|
// 示例:配置接口代理(根据你的项目需求调整)
|
||||||
|
'/api': {
|
||||||
|
target: 'https://your-api-domain.com',
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: { '^/api': '' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user