三期pk功能开发以及积分两个页
@@ -2,32 +2,32 @@
|
|||||||
ENV = 'development'
|
ENV = 'development'
|
||||||
# 'development'
|
# 'development'
|
||||||
|
|
||||||
#VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001'
|
# VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001'
|
||||||
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
|
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
|
||||||
# VITE_APP_BASE_API_Url = ' http://25.18.122.66:9786'
|
# VITE_APP_BASE_API_Url = 'http://192.168.247.200'
|
||||||
#sit
|
# VITE_APP_BASE_API_Url = 'http://aitscdn.jlbank.com.cn:7001'
|
||||||
|
# VITE_APP_BASE_API_Url = 'http://192.168.108.129'
|
||||||
|
# dev
|
||||||
|
#VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
||||||
|
# sit
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.18.122.91:9786'
|
# VITE_APP_BASE_API_Url = 'http://25.18.122.91:9786'
|
||||||
# UAT
|
# UAT
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.18.122.78:9786'
|
# VITE_APP_BASE_API_Url = 'http://25.18.122.78:9786'
|
||||||
|
|
||||||
# DEV
|
# DEV
|
||||||
|
|
||||||
# app入口
|
# app入口
|
||||||
|
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.16.122.91:9786'
|
# VITE_APP_BASE_API_Url = 'http://25.16.122.91:9786'
|
||||||
# VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
|
# VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
|
||||||
|
|
||||||
# h5专用地址x2
|
# h5专用地址x2
|
||||||
|
|
||||||
|
|
||||||
VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
|
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
|
||||||
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
|
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
|
||||||
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
|
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
|
||||||
|
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://192.168.247.200'
|
||||||
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.32.154:9601'
|
|
||||||
# VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.32.154:9602'
|
# VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.32.154:9602'
|
||||||
VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
|
# VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://192.168.247.200'
|
||||||
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.32.154:9605'
|
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.32.154:9605'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# 任东专用开发环境
|
||||||
|
ENV = 'development.rd'
|
||||||
|
# 'development.rd'
|
||||||
|
|
||||||
|
VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
||||||
|
|
||||||
|
VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# 田岩开发环境
|
||||||
|
ENV = 'development.ty'
|
||||||
|
# 'development.ty'
|
||||||
|
|
||||||
|
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
|
||||||
|
|
||||||
|
VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://192.168.108.129'
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# 杨航开发环境
|
||||||
|
ENV = 'development.yh'
|
||||||
|
# 'development.yh'
|
||||||
|
|
||||||
|
VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
||||||
|
|
||||||
|
VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:h5": "uni",
|
"dev:h5": "uni",
|
||||||
|
"dev:rd": "uni -p h5 --mode development.rd",
|
||||||
|
"dev:yh": "uni -p h5 --mode development.yh",
|
||||||
|
"dev:ty": "uni -p h5 --mode development.ty",
|
||||||
"dev:h5:sit": "uni -p h5 --mode sit",
|
"dev:h5:sit": "uni -p h5 --mode sit",
|
||||||
"dev:h5:uat": "uni -p h5 --mode uat",
|
"dev:h5:uat": "uni -p h5 --mode uat",
|
||||||
"dev:h5:production": "uni -p h5 --mode production",
|
"dev:h5:production": "uni -p h5 --mode production",
|
||||||
|
|||||||
@@ -9,23 +9,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onShow: function () {
|
onShow: function () {
|
||||||
// function getBrowserInfo() {
|
|
||||||
// const userAgent = navigator.userAgent;
|
|
||||||
// let browserName = '未知浏览器';
|
|
||||||
// let version = '未知版本';
|
|
||||||
|
|
||||||
// // 检测 Chrome
|
|
||||||
// if (userAgent.indexOf('Chrome') > -1 && userAgent.indexOf('Edg') === -1) {
|
|
||||||
// browserName = 'Chrome';
|
|
||||||
// version = userAgent.match(/Chrome\/(\d+\.\d+)/)[1];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// browser: browserName,
|
|
||||||
// version: version,
|
|
||||||
// userAgent: userAgent
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
onHide: function () {
|
onHide: function () {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import request from '@/api/request'
|
||||||
|
|
||||||
|
const module_url = '/traexam'
|
||||||
|
|
||||||
|
// 查询竞赛列表
|
||||||
|
export const queryTraCompetitionInfoPaging = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryTraCompetitionInfoPaging',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查询试卷
|
||||||
|
export const queryTestPapers = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryTestPapers',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查询PK人员+试题
|
||||||
|
export const queryTraCompetitionInfoByPkUser = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryTraCompetitionInfoByPkUser',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 循环获取简答题结果
|
||||||
|
export const queryCompetitionPracticeAnswerResult = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryCompetitionPracticeAnswerResult',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 答题结束
|
||||||
|
export const competitionAnswerEnd = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/competitionAnswerEnd',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
suppressErrors: true // 屏蔽报错信息
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 竞赛答题
|
||||||
|
export const competitionAnswer = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/competitionAnswer',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查询答题结果
|
||||||
|
export const queryCompetitionAnswerResult = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryCompetitionAnswerResult',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 竞赛排行榜
|
||||||
|
export const queryTraCompetitionRankingList = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryTraCompetitionRankingList',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 全行的机构数据
|
||||||
|
export const queryOrgTree = (data) => {
|
||||||
|
return request({
|
||||||
|
url: module_url + '/traCompetitionInfo/queryOrgTree',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import request from '@/api/request'
|
||||||
|
const base_url = '/traapp'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询签到
|
||||||
|
* userId 学员ID String
|
||||||
|
* checkInToday 今日是否签到 String
|
||||||
|
* days 连续签到天数 int
|
||||||
|
*/
|
||||||
|
export const queryCheckIn = (data) => {
|
||||||
|
return request({
|
||||||
|
url: base_url + '/traPointsInfo/queryCheckIn',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击签到
|
||||||
|
*/
|
||||||
|
export const addPointsByCheckIn = (data) => {
|
||||||
|
return request({
|
||||||
|
url: base_url + '/traPointsInfo/addPointsByCheckIn',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次完成任务获得弹窗奖励
|
||||||
|
* 入参:
|
||||||
|
taskId 必输项:true 类型:String
|
||||||
|
type 必输项:true 类型:String
|
||||||
|
出参:
|
||||||
|
userId 学员ID String
|
||||||
|
badgeName 徽章名称 String
|
||||||
|
badgeImg 徽章图片 String
|
||||||
|
num 次数 int
|
||||||
|
name 描述 String
|
||||||
|
pointsBadgeName 积分徽章名称 String
|
||||||
|
pointsBadgeImg 徽章图片 String
|
||||||
|
currentPoints 当前积分 int
|
||||||
|
changePoints 本次获得积分 int
|
||||||
|
*/
|
||||||
|
export const addPointsByTask = (data) => {
|
||||||
|
return request({
|
||||||
|
url: base_url + '/traPointsInfo/addPointsByTask',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询积分明细
|
||||||
|
* 出参:
|
||||||
|
detailId 明细ID String
|
||||||
|
userId 学员ID String
|
||||||
|
mattr 积分来源事项 String
|
||||||
|
mattrDesc 积分来源描述 String
|
||||||
|
changeValue 积分变化值 String
|
||||||
|
currentPoints 当前积分 int
|
||||||
|
countPoints 累计积分 int
|
||||||
|
ctTime 创建时间 String
|
||||||
|
*/
|
||||||
|
export const queryPointsDetail = (data) => {
|
||||||
|
return request({
|
||||||
|
url: base_url + '/traPointsInfo/queryPointsDetail',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询段位明细
|
||||||
|
* 出参:
|
||||||
|
rankId 段位ID String
|
||||||
|
rankName 段位名称 String
|
||||||
|
currentRankName 当前段位名称 String
|
||||||
|
ossAddr 段位图片 String
|
||||||
|
pointsStart 段位开始区间 int
|
||||||
|
pointsEnd 段位结束区间 int
|
||||||
|
countPoints 累计积分 int
|
||||||
|
*/
|
||||||
|
export const queryRankDetail = (data) => {
|
||||||
|
return request({
|
||||||
|
url: base_url + '/traPointsInfo/queryRankDetail',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前状态
|
||||||
|
* 出参:
|
||||||
|
userId 学员ID String
|
||||||
|
orgId 机构ID String
|
||||||
|
countPoints 累计积分 int
|
||||||
|
currentPoints 当前积分 int
|
||||||
|
currentRankName 当前段位 String
|
||||||
|
badgeNum 徽章数 int
|
||||||
|
*/
|
||||||
|
export const queryCurrentStatus = (data) => {
|
||||||
|
return request({
|
||||||
|
url: base_url + '/traPointsInfo/queryCurrentStatus',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -4,9 +4,27 @@ import {
|
|||||||
import common from '@/common/common.js'
|
import common from '@/common/common.js'
|
||||||
|
|
||||||
const ENV = import.meta.env
|
const ENV = import.meta.env
|
||||||
|
// function getBrowserInfo() {
|
||||||
|
// const userAgent = navigator.userAgent;
|
||||||
|
// let browserName = '未知浏览器';
|
||||||
|
// let version = '未知版本';
|
||||||
|
|
||||||
|
// // 检测 Chrome
|
||||||
|
// if (userAgent.indexOf('Chrome') > -1 && userAgent.indexOf('Edg') === -1) {
|
||||||
|
// browserName = 'Chrome';
|
||||||
|
// version = userAgent.match(/Chrome\/(\d+\.\d+)/)[1];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// browser: browserName,
|
||||||
|
// version: version,
|
||||||
|
// userAgent: userAgent
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
export const get_base_url = (url = '') => {
|
export const get_base_url = (url = '') => {
|
||||||
if (ENV.MODE === 'development') { // 开发环境
|
if (['development', 'development.rd', 'development.yh', 'development.ty'].includes(ENV.MODE)) { // 开发环境
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
if (url) {
|
if (url) {
|
||||||
let _str = (url.split('/')[0] || url.split('/')[1])?.toUpperCase()
|
let _str = (url.split('/')[0] || url.split('/')[1])?.toUpperCase()
|
||||||
@@ -20,7 +38,7 @@ export const get_base_url = (url = '') => {
|
|||||||
return ENV.VITE_APP_BASE_API_Url
|
return ENV.VITE_APP_BASE_API_Url
|
||||||
// #endif
|
// #endif
|
||||||
} else { // 其他环境,包括生产环境,sit环境,uat环境
|
} else { // 其他环境,包括生产环境,sit环境,uat环境
|
||||||
|
|
||||||
return ENV.VITE_APP_BASE_API_Url
|
return ENV.VITE_APP_BASE_API_Url
|
||||||
// return ENV.VITE_APP_BASE_API_Url
|
// return ENV.VITE_APP_BASE_API_Url
|
||||||
|
|
||||||
|
|||||||
@@ -36,4 +36,22 @@ export const updateDfSysUserExtandInfoGender = (data) => {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 设置匿名 是Y 否N
|
||||||
|
export const updateTraUserAnony = (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/traapp/traUserAnony/updateTraUserAnony',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查询是否匿名 是Y 否N
|
||||||
|
export const queryTraUserAnonyByUserId = (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/traapp/traUserAnony/queryTraUserAnonyByUserId',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export const optionSuccessIcon = (color : string) : string => {
|
|||||||
|
|
||||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
};
|
};
|
||||||
export const optionErrorIcon = (color: string='#F5212D') : string => {
|
export const optionErrorIcon = (color : string = '#F5212D') : string => {
|
||||||
const svgXml = `
|
const svgXml = `
|
||||||
<svg t="1754619171929" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6505" width="64" height="64"><path d="M910.336 186.368l-72.704-72.704L512 439.808 186.368 113.664 113.664 186.368 439.808 512l-326.144 325.632 72.704 72.704L512 584.192l325.632 326.144 72.704-72.704L584.192 512l326.144-325.632z" fill="${color}" p-id="6506"></path></svg>
|
<svg t="1754619171929" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6505" width="64" height="64"><path d="M910.336 186.368l-72.704-72.704L512 439.808 186.368 113.664 113.664 186.368 439.808 512l-326.144 325.632 72.704 72.704L512 584.192l325.632 326.144 72.704-72.704L584.192 512l326.144-325.632z" fill="${color}" p-id="6506"></path></svg>
|
||||||
`.trim();
|
`.trim();
|
||||||
@@ -19,7 +19,7 @@ export const examinationSheetIcon = () : string => {
|
|||||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const markIcon = (color: string='#ABABAB') : string => {
|
export const markIcon = (color : string = '#ABABAB') : string => {
|
||||||
const svgXml = `
|
const svgXml = `
|
||||||
<svg t="1754987745092" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13983" width="64" height="64"><path d="M693.01933598 59.45166004c-24.99339629-24.99339629-65.5162717-24.99339629-90.50966799 0-24.99339629 24.99339629-24.99339629 65.5162717 0 90.50966799l22.627417 22.627417-181.19328425 181.19328425c-78.50370195-71.13564929-199.8637317-68.83684515-275.5976964 6.89711955l-33.94112549 33.94112549a8 8 0 0 0 0 11.3137085l208.59650045 208.59650045-175.36248174 175.36248174a8 8 0 0 0 0 11.3137085l56.5685425 56.56854249a8 8 0 0 0 11.3137085 0L410.88373029 682.41273427l208.59650045 208.59650045a8 8 0 0 0 11.3137085 0l33.9411255-33.9411255c76.21055466-76.21055466 78.05893179-198.62346641 5.54583848-277.07484246L851.41125497 398.86291501l22.627417 22.627417c24.99339629 24.99339629 65.5162717 24.99339629 90.50966799 0 24.99339629-24.99339629 24.99339629-65.5162717 0-90.50966799L693.01933598 59.45166004z" fill="${color}" p-id="13984"></path></svg>
|
<svg t="1754987745092" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13983" width="64" height="64"><path d="M693.01933598 59.45166004c-24.99339629-24.99339629-65.5162717-24.99339629-90.50966799 0-24.99339629 24.99339629-24.99339629 65.5162717 0 90.50966799l22.627417 22.627417-181.19328425 181.19328425c-78.50370195-71.13564929-199.8637317-68.83684515-275.5976964 6.89711955l-33.94112549 33.94112549a8 8 0 0 0 0 11.3137085l208.59650045 208.59650045-175.36248174 175.36248174a8 8 0 0 0 0 11.3137085l56.5685425 56.56854249a8 8 0 0 0 11.3137085 0L410.88373029 682.41273427l208.59650045 208.59650045a8 8 0 0 0 11.3137085 0l33.9411255-33.9411255c76.21055466-76.21055466 78.05893179-198.62346641 5.54583848-277.07484246L851.41125497 398.86291501l22.627417 22.627417c24.99339629 24.99339629 65.5162717 24.99339629 90.50966799 0 24.99339629-24.99339629 24.99339629-65.5162717 0-90.50966799L693.01933598 59.45166004z" fill="${color}" p-id="13984"></path></svg>
|
||||||
`.trim();
|
`.trim();
|
||||||
@@ -34,7 +34,7 @@ export const feedbackIcon = () : string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 通过考试
|
// 通过考试
|
||||||
export const passTheExamIcon = (color: string) : string => {
|
export const passTheExamIcon = (color : string) : string => {
|
||||||
const svgXml = `
|
const svgXml = `
|
||||||
<svg t="1755670289043" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6974" width="64" height="64"><path d="M97.878 483.853c0-117.062-0.108-160.999-0.108-278.062 0-101.472 56.328-108.082 110.483-108.082h441.933c85.128 0 111.453 28.968 111.453 110.481v55.241c0 43.562-55.419 38.57-55.419 0V208.19c0-40.918-13.309-55.24-56.035-55.24H208.252c-45.746 0-55.241 6.203-55.241 55.24v552.407c0 30.278 16.572 55.241 55.241 55.241 67.004 0 43.482 0.026 110.484 0 33.77 0 36.252 55.241 0 55.241s-63.711 0.44-131.306 0.17c-39.867-0.163-72.883-23.774-84.643-60.322-3.292-10.223-4.694-21.525-4.694-32.34-0.323-116.658-0.215-178.076-0.215-294.734" fill="${color}" p-id="6975"></path><path d="M649.644 926.291c-152.344-0.027-275.666-123.537-275.666-276.122 0-152.586 123.915-276.259 276.529-276.042 152.616 0.215 275.884 124.022 275.722 276.878-0.16 152.236-123.807 275.314-276.585 275.286m0.756-496.868c-121.109-0.271-220.641 98.828-220.91 220.045-0.27 121.541 98.345 220.934 219.561 221.287 121.704 0.324 221.505-98.208 221.775-219.047 0.324-122.594-98.236-221.99-220.426-222.285m-55.455-166.362c44.02 0.027 37.978 55.979 0 55.979h-331.45c-41.431 0-39.704-55.979 0-55.979 108.756-0.027 289.155-0.027 331.45 0zM318.736 428.782c44.021 0.028 37.979 55.98 0 55.98h-55.242c-41.431 0-39.704-55.98 0-55.98 108.757-0.027 12.948-0.027 55.242 0z" fill="${color}" p-id="6976"></path><path d="M785.502 547.22c-12.496-12.498-32.758-12.498-45.254 0L602.151 685.316l-42.191-42.191c-12.498-12.496-32.758-12.496-45.256 0-12.496 12.497-12.496 32.759 0 45.256l64.818 64.818c6.249 6.248 14.438 9.372 22.628 9.372s16.379-3.124 22.628-9.372a32.424 32.424 0 0 0 2.402-2.695 32.304 32.304 0 0 0 2.689-2.397l155.633-155.633c12.497-12.496 12.497-32.758 0-45.254z" fill="${color}" p-id="6977"></path></svg>
|
<svg t="1755670289043" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6974" width="64" height="64"><path d="M97.878 483.853c0-117.062-0.108-160.999-0.108-278.062 0-101.472 56.328-108.082 110.483-108.082h441.933c85.128 0 111.453 28.968 111.453 110.481v55.241c0 43.562-55.419 38.57-55.419 0V208.19c0-40.918-13.309-55.24-56.035-55.24H208.252c-45.746 0-55.241 6.203-55.241 55.24v552.407c0 30.278 16.572 55.241 55.241 55.241 67.004 0 43.482 0.026 110.484 0 33.77 0 36.252 55.241 0 55.241s-63.711 0.44-131.306 0.17c-39.867-0.163-72.883-23.774-84.643-60.322-3.292-10.223-4.694-21.525-4.694-32.34-0.323-116.658-0.215-178.076-0.215-294.734" fill="${color}" p-id="6975"></path><path d="M649.644 926.291c-152.344-0.027-275.666-123.537-275.666-276.122 0-152.586 123.915-276.259 276.529-276.042 152.616 0.215 275.884 124.022 275.722 276.878-0.16 152.236-123.807 275.314-276.585 275.286m0.756-496.868c-121.109-0.271-220.641 98.828-220.91 220.045-0.27 121.541 98.345 220.934 219.561 221.287 121.704 0.324 221.505-98.208 221.775-219.047 0.324-122.594-98.236-221.99-220.426-222.285m-55.455-166.362c44.02 0.027 37.978 55.979 0 55.979h-331.45c-41.431 0-39.704-55.979 0-55.979 108.756-0.027 289.155-0.027 331.45 0zM318.736 428.782c44.021 0.028 37.979 55.98 0 55.98h-55.242c-41.431 0-39.704-55.98 0-55.98 108.757-0.027 12.948-0.027 55.242 0z" fill="${color}" p-id="6976"></path><path d="M785.502 547.22c-12.496-12.498-32.758-12.498-45.254 0L602.151 685.316l-42.191-42.191c-12.498-12.496-32.758-12.496-45.256 0-12.496 12.497-12.496 32.759 0 45.256l64.818 64.818c6.249 6.248 14.438 9.372 22.628 9.372s16.379-3.124 22.628-9.372a32.424 32.424 0 0 0 2.402-2.695 32.304 32.304 0 0 0 2.689-2.397l155.633-155.633c12.497-12.496 12.497-32.758 0-45.254z" fill="${color}" p-id="6977"></path></svg>
|
||||||
`.trim();
|
`.trim();
|
||||||
@@ -42,7 +42,7 @@ export const passTheExamIcon = (color: string) : string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 完成练习
|
// 完成练习
|
||||||
export const completeTheExercisesIcon = (color: string) : string => {
|
export const completeTheExercisesIcon = (color : string) : string => {
|
||||||
const svgXml = `
|
const svgXml = `
|
||||||
<svg t="1755670357132" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7127" width="64" height="64"><path d="M832 704a42.666667 42.666667 0 0 0-42.666667 42.666667v106.666666H170.666667V170.666667h618.666666v226.133333a42.666667 42.666667 0 0 0 85.333334 0V166.4A83.2 83.2 0 0 0 789.333333 85.333333H170.666667a83.2 83.2 0 0 0-85.333334 81.066667v691.2A83.413333 83.413333 0 0 0 170.666667 938.666667h618.666666a83.413333 83.413333 0 0 0 85.333334-81.066667V746.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z" fill="${color}" p-id="7128"></path><path d="M682.666667 341.333333a42.666667 42.666667 0 0 0-42.666667-42.666666H298.666667a42.666667 42.666667 0 0 0 0 85.333333h341.333333a42.666667 42.666667 0 0 0 42.666667-42.666667zM298.666667 512a42.666667 42.666667 0 0 0 0 85.333333h213.333333a42.666667 42.666667 0 0 0 0-85.333333zM921.386667 491.733333a42.666667 42.666667 0 0 0-60.373334 0L649.813333 704l-60.16-60.373333A42.666667 42.666667 0 0 0 529.28 704l90.453333 90.453333a42.666667 42.666667 0 0 0 60.373334 0l241.28-242.346666a42.666667 42.666667 0 0 0 0-60.373334z" fill="${color}" p-id="7129"></path></svg>
|
<svg t="1755670357132" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7127" width="64" height="64"><path d="M832 704a42.666667 42.666667 0 0 0-42.666667 42.666667v106.666666H170.666667V170.666667h618.666666v226.133333a42.666667 42.666667 0 0 0 85.333334 0V166.4A83.2 83.2 0 0 0 789.333333 85.333333H170.666667a83.2 83.2 0 0 0-85.333334 81.066667v691.2A83.413333 83.413333 0 0 0 170.666667 938.666667h618.666666a83.413333 83.413333 0 0 0 85.333334-81.066667V746.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z" fill="${color}" p-id="7128"></path><path d="M682.666667 341.333333a42.666667 42.666667 0 0 0-42.666667-42.666666H298.666667a42.666667 42.666667 0 0 0 0 85.333333h341.333333a42.666667 42.666667 0 0 0 42.666667-42.666667zM298.666667 512a42.666667 42.666667 0 0 0 0 85.333333h213.333333a42.666667 42.666667 0 0 0 0-85.333333zM921.386667 491.733333a42.666667 42.666667 0 0 0-60.373334 0L649.813333 704l-60.16-60.373333A42.666667 42.666667 0 0 0 529.28 704l90.453333 90.453333a42.666667 42.666667 0 0 0 60.373334 0l241.28-242.346666a42.666667 42.666667 0 0 0 0-60.373334z" fill="${color}" p-id="7129"></path></svg>
|
||||||
`.trim();
|
`.trim();
|
||||||
@@ -50,7 +50,7 @@ export const completeTheExercisesIcon = (color: string) : string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 锁定
|
// 锁定
|
||||||
export const lockIcon = (color: string) : string => {
|
export const lockIcon = (color : string) : string => {
|
||||||
const svgXml = `
|
const svgXml = `
|
||||||
<svg t="1755683025230" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6630" width="64" height="64"><path d="M787.136 395.466H373.113c0.036-0.579 0.173-1.128 0.173-1.716V267.63c0-81.153 72.891-147.174 162.483-147.174 86.561 0 162.488 64.414 162.488 137.851 0 15.446 12.523 27.969 27.969 27.969 15.446 0 27.969-12.523 27.969-27.969 0-105.043-100.027-193.789-218.426-193.789-120.439 0-218.422 91.118-218.422 203.112v126.12c0 0.588 0.137 1.138 0.173 1.716h-14.467c-82.25 0-149.168 66.918-149.168 149.168v284.402c0 71.971 58.551 130.522 130.522 130.522h502.728c71.971 0 130.522-58.551 130.522-130.522V525.988c0.001-71.971-58.55-130.522-130.521-130.522z m74.584 433.57c0 41.125-33.459 74.584-74.584 74.584H284.408c-41.125 0-74.584-33.459-74.584-74.584V544.634c0-51.409 41.822-93.23 93.23-93.23h484.082c41.125 0 74.584 33.459 74.584 74.584v303.048z" fill="${color}" p-id="6631"></path><path d="M613.108 649.541H458.436c-15.446 0-27.969 12.523-27.969 27.969 0 15.446 12.523 27.969 27.969 27.969h154.672c15.446 0 27.969-12.523 27.969-27.969 0-15.446-12.523-27.969-27.969-27.969z" fill="${color}" p-id="6632"></path></svg>
|
<svg t="1755683025230" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6630" width="64" height="64"><path d="M787.136 395.466H373.113c0.036-0.579 0.173-1.128 0.173-1.716V267.63c0-81.153 72.891-147.174 162.483-147.174 86.561 0 162.488 64.414 162.488 137.851 0 15.446 12.523 27.969 27.969 27.969 15.446 0 27.969-12.523 27.969-27.969 0-105.043-100.027-193.789-218.426-193.789-120.439 0-218.422 91.118-218.422 203.112v126.12c0 0.588 0.137 1.138 0.173 1.716h-14.467c-82.25 0-149.168 66.918-149.168 149.168v284.402c0 71.971 58.551 130.522 130.522 130.522h502.728c71.971 0 130.522-58.551 130.522-130.522V525.988c0.001-71.971-58.55-130.522-130.521-130.522z m74.584 433.57c0 41.125-33.459 74.584-74.584 74.584H284.408c-41.125 0-74.584-33.459-74.584-74.584V544.634c0-51.409 41.822-93.23 93.23-93.23h484.082c41.125 0 74.584 33.459 74.584 74.584v303.048z" fill="${color}" p-id="6631"></path><path d="M613.108 649.541H458.436c-15.446 0-27.969 12.523-27.969 27.969 0 15.446 12.523 27.969 27.969 27.969h154.672c15.446 0 27.969-12.523 27.969-27.969 0-15.446-12.523-27.969-27.969-27.969z" fill="${color}" p-id="6632"></path></svg>
|
||||||
`.trim();
|
`.trim();
|
||||||
@@ -66,3 +66,53 @@ export const practiceExitIcon = () : string => {
|
|||||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Pk页规则图标
|
||||||
|
export const pkRules = () : string => {
|
||||||
|
const svgXml = `
|
||||||
|
<svg t="1760676829470" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7500" width="64" height="64"><path d="M512 69.963c248.05 0 445.217 197.167 445.217 445.217S760.05 960.398 512 960.398 66.783 763.23 66.783 515.18 263.95 69.963 512 69.963m0-63.603C232.15 6.36 3.18 235.33 3.18 515.18 3.18 795.031 232.15 1024 512 1024s508.82-228.969 508.82-508.82C1020.82 235.33 791.85 6.36 512 6.36z" fill="#ffffff" p-id="7501"></path><path d="M512 432.497c-38.161 0-63.602 25.44-63.602 57.242v273.49c0 31.802 25.44 57.243 63.602 57.243 38.161 0 63.602-25.44 63.602-57.242V489.74c0-31.802-25.44-57.243-63.602-57.243z m0-95.404c38.161 0 63.602-25.44 63.602-63.602 0-38.162-25.44-63.603-63.602-63.603-38.161 0-63.602 25.441-63.602 63.603 0 38.161 25.44 63.602 63.602 63.602z" fill="#ffffff" p-id="7502"></path></svg>
|
||||||
|
`.trim();
|
||||||
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pk页排行榜图标
|
||||||
|
export const pkRankingList = () : string => {
|
||||||
|
const svgXml = `
|
||||||
|
<svg t="1760676897154" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7659" width="64" height="64"><path d="M323.9 326.9H215.8c-14.9 0-27 12.1-27 27v459.2c0 14.9 12.1 27 27 27h108.1c14.9 0 27-12.1 27-27V353.9c0-14.9-12.1-27-27-27zM567 488.9H459c-14.9 0-27 12.1-27 27v297.2c0 14.9 12.1 27 27 27h108c14.9 0 27-12.1 27-27V515.9c0-14.9-12-27-27-27zM810.2 191.8H702.1c-14.9 0-27 12.1-27 27v594.3c0 14.9 12.1 27 27 27h108.1c14.9 0 27-12.1 27-27V218.8c0-14.9-12.1-27-27-27z" p-id="7660" fill="#ffffff"></path></svg>
|
||||||
|
`.trim();
|
||||||
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pk页匿名关
|
||||||
|
export const pkAnonymousClose = () : string => {
|
||||||
|
const svgXml = `
|
||||||
|
<svg t="1760677024029" class="icon" viewBox="0 0 1292 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8345" width="64" height="64"><path d="M1188.53945615 539.42278643a46.73094873 46.73094873 0 0 0 0-55.20152813C979.91575068 197.74436416 724.94179737 84.96193203 470.63406904 166.33659834a486.48725859 486.48725859 0 0 0-86.32376894 35.69064258L256.91849844 75.92030263a48.25374961 48.25374961 0 0 0-67.81222178 0 47.06406123 47.06406123 0 0 0 0 67.09840841L300.03279541 252.47001641c-17.22668379 12.37275615-34.31060508 24.7455123-51.15658887 39.02177021A1053.25466924 1053.25466924 0 0 0 71.1843919 484.2212583a46.68336123 46.68336123 0 0 0 0 55.20152813c163.55832011 224.61311338 356.90643018 343.58192315 558.67753212 343.58192402a542.49777422 542.49777422 0 0 0 245.64679893-60.91203076l127.10627666 125.63106328a47.68269873 47.68269873 0 0 0 67.81222177-67.09840928l-110.40305536-108.97542949a992.43781348 992.43781348 0 0 0 228.51529013-232.22711777z m-558.48718212 248.40687568c-161.79758174 0-320.21644922-95.17504834-460.07618204-276.00763974a952.03600576 952.03600576 0 0 1 140.66872119-147.99719971 675.74284102 675.74284102 0 0 1 58.58024239-42.8287711l87.46586894 86.60929307a197.8213377 197.8213377 0 0 0-30.31325332 104.21667774 202.86561533 202.86561533 0 0 0 203.67460284 201.77110195 200.20071357 200.20071357 0 0 0 105.5491286-30.45601495l68.00257179 67.57428428a440.51770987 440.51770987 0 0 1-173.55170039 37.11826846z m101.69453935-242.22049717l-135.67203106-134.19681767a100.74278847 100.74278847 0 0 1 33.97749171-6.18637852 105.35877862 105.35877862 0 0 1 101.55177685 140.38319619z m-67.76463427 67.0984084a114.210058 114.210058 0 0 1-33.97749258 5.71050351 107.119517 107.119517 0 0 1-107.690567-106.59605448 101.69453848 101.69453848 0 0 1 5.99602852-33.3112667z m226.61178925 89.9404207l-87.27551894-86.60929394a196.53647432 196.53647432 0 0 0 30.31325243-104.21667773 202.96079033 202.96079033 0 0 0-309.31890556-171.31508614L456.31022451 272.93265195c2.47455088-0.95175088 4.75875263-2.37937588 7.37606602-3.33112676 12.08723115-4.75875263 24.26963731-9.5175044 36.40445595-13.32450615 203.34149033-65.19490752 411.9176083 25.69726318 589.75218545 255.54500333a847.91450303 847.91450303 0 0 1-199.43931357 190.82597167z" fill="#ffffff" p-id="8346"></path></svg>
|
||||||
|
`.trim();
|
||||||
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pk页匿名开
|
||||||
|
export const pkAnonymousOpen = () : string => {
|
||||||
|
const svgXml = `
|
||||||
|
<svg t="1760676973291" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7945" width="64" height="64"><path d="M900.4 424.87c19.47 0 37.03-11.73 44.49-29.73 7.46-17.98 3.33-38.7-10.43-52.48L713.97 122.19c-7.3-7.3-19.12-7.3-26.42 0l-41.69 41.69c-7.3 7.3-7.3 19.13 0 26.42l138.28 138.27H86.32c-10.19 0-18.46 8.26-18.46 18.46v59.39c0 10.19 8.26 18.46 18.46 18.46H900.4zM937.65 598.72H123.8c-19.47 0-37.03 11.73-44.49 29.73-7.46 17.98-3.33 38.7 10.43 52.48l220.49 220.48c7.3 7.3 19.12 7.3 26.42 0l41.69-41.69c7.3-7.3 7.3-19.13 0-26.42L240.06 695.02h697.59c10.32 0 18.68-8.37 18.68-18.68v-58.93c0-10.32-8.36-18.69-18.68-18.69z" p-id="7946" fill="#ffffff"></path></svg>
|
||||||
|
`.trim();
|
||||||
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 重置页图标
|
||||||
|
export const resetIcon = () : string => {
|
||||||
|
const svgXml = `
|
||||||
|
<svg t="1760952234942" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7688" width="64" height="64"><path d="M931.07 384.75a368 368 0 0 0-704 95.25H64l192 192 192-192H288.91C312 333.51 439.12 221.13 592 221.13c169.21 0 306.87 137.66 306.87 306.87S761.21 834.87 592 834.87a307.37 307.37 0 0 1-194.56-69.55 30.57 30.57 0 0 0-38.79 47.25 368.1 368.1 0 0 0 572.42-427.82z" fill="#333333" p-id="7689"></path></svg>
|
||||||
|
`.trim();
|
||||||
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// pk页切换图标
|
||||||
|
export const switchIcon = () : string => {
|
||||||
|
const svgXml = `
|
||||||
|
<svg t="1761037923256" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7561" width="32" height="32"><path d="M900.4 424.87c19.47 0 37.03-11.73 44.49-29.73 7.46-17.98 3.33-38.7-10.43-52.48L713.97 122.19c-7.3-7.3-19.12-7.3-26.42 0l-41.69 41.69c-7.3 7.3-7.3 19.13 0 26.42l138.28 138.27H86.32c-10.19 0-18.46 8.26-18.46 18.46v59.39c0 10.19 8.26 18.46 18.46 18.46H900.4zM937.65 598.72H123.8c-19.47 0-37.03 11.73-44.49 29.73-7.46 17.98-3.33 38.7 10.43 52.48l220.49 220.48c7.3 7.3 19.12 7.3 26.42 0l41.69-41.69c7.3-7.3 7.3-19.13 0-26.42L240.06 695.02h697.59c10.32 0 18.68-8.37 18.68-18.68v-58.93c0-10.32-8.36-18.69-18.68-18.69z" p-id="7562" fill="#e6e6e6"></path></svg>
|
||||||
|
`.trim();
|
||||||
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||||
|
};
|
||||||
|
|||||||
@@ -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="item">
|
||||||
<view class="top">
|
<view class="top">
|
||||||
<view class="type">{{ subject_type_text }}</view>
|
<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="fl1"></view>
|
||||||
<view class="right">
|
<view class="right">
|
||||||
<!-- 反馈中心 -->
|
<!-- 反馈中心 -->
|
||||||
|
<slot name="title-right"></slot>
|
||||||
<view class="mark_and_feedback_div" v-if="['examination', 'practice'].includes(props.mode)">
|
<view class="mark_and_feedback_div" v-if="['examination', 'practice'].includes(props.mode)">
|
||||||
<image
|
<image
|
||||||
v-if="props.mode === 'examination'"
|
v-if="props.mode === 'examination'"
|
||||||
@@ -23,12 +24,10 @@
|
|||||||
<template v-if="['mistake'].includes(props.mode)">
|
<template v-if="['mistake'].includes(props.mode)">
|
||||||
<view class="expand_button_div" @click="toggleExpand()">
|
<view class="expand_button_div" @click="toggleExpand()">
|
||||||
<!-- <view class="right_text">{{animationState?'收起':'展开'}}</view> -->
|
<!-- <view class="right_text">{{animationState?'收起':'展开'}}</view> -->
|
||||||
|
|
||||||
<view class="toggle-container">
|
<view class="toggle-container">
|
||||||
<view class="toggle-text" :class="{ active: !animationState }">展开</view>
|
<view class="toggle-text" :class="{ active: !animationState }">展开</view>
|
||||||
<view class="toggle-text" :class="{ active: animationState }">收起</view>
|
<view class="toggle-text" :class="{ active: animationState }">收起</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<uv-icon
|
<uv-icon
|
||||||
class="click_text_icon"
|
class="click_text_icon"
|
||||||
name="arrow-right"
|
name="arrow-right"
|
||||||
@@ -52,7 +51,7 @@
|
|||||||
:isPreview="props.isPreview"
|
:isPreview="props.isPreview"
|
||||||
:activeVoiceId="subject_data.qnsId"
|
:activeVoiceId="subject_data.qnsId"
|
||||||
@buutton_click="questionButtonClick"
|
@buutton_click="questionButtonClick"
|
||||||
:button_complete_show="props.mode === 'practice'"
|
:button_complete_show="['practice', 'pk_in'].includes(props.mode)"
|
||||||
></questionVue>
|
></questionVue>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -67,7 +66,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="option_div_button"
|
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
|
<uv-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -85,7 +84,7 @@
|
|||||||
class="analysis_div"
|
class="analysis_div"
|
||||||
v-if="
|
v-if="
|
||||||
!clearResult &&
|
!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'">
|
<view class="analysis_title" v-if="qnsTyp !== 'ES'">
|
||||||
@@ -153,8 +152,8 @@
|
|||||||
// 错题本: mistake
|
// 错题本: mistake
|
||||||
// 学习: study
|
// 学习: study
|
||||||
// 考试结算页 settlement
|
// 考试结算页 settlement
|
||||||
// 练习记录页 practice_record
|
// 练习记录页 practice_record, 'practice_record'
|
||||||
return ['examination', 'practice', 'mistake', 'study', 'settlement', 'practice_record'].includes(value);
|
return ['examination', 'practice', 'mistake', 'study', 'settlement', 'practice_record', 'pk_in'].includes(value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 是否预览模式
|
// 是否预览模式
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view style="line-height: 0;">
|
||||||
<image :src="imgUrlShow" :mode="mode" @click="showDetail" style="width: 100%; height: 100%"></image>
|
<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">
|
<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>
|
<view class="overlay-box" @click="closePopup" @touchmove.stop>
|
||||||
@@ -167,6 +167,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
.overlay-box {
|
.overlay-box {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -182,6 +183,7 @@
|
|||||||
width: 100vw;
|
width: 100vw;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</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>
|
||||||
@@ -43,7 +43,8 @@ export default function useZpaging({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
const search = (value, state) => {
|
const search = (value, state=true) => {
|
||||||
|
console.log('搜索', value, state);
|
||||||
searchText.value = value;
|
searchText.value = value;
|
||||||
if (state) {
|
if (state) {
|
||||||
reload()
|
reload()
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const GENDER = [{
|
|||||||
value: "f",
|
value: "f",
|
||||||
label: "女性",
|
label: "女性",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
// 试题题型
|
// 试题题型
|
||||||
export const SUBJECT_TYPE = [{
|
export const SUBJECT_TYPE = [{
|
||||||
value: "SN",
|
value: "SN",
|
||||||
@@ -32,4 +32,19 @@ export const SUBJECT_TYPE = [{
|
|||||||
label: "问答题",
|
label: "问答题",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
export const defaultAvatar = '/static/images/me/default_user_avatar.png'
|
export const defaultAvatar = '/static/images/me/default_user_avatar.png'
|
||||||
|
export const defaultAnonymousAvatar = '/static/images/me/default_user_avatar.png'
|
||||||
|
export const styleButton = {
|
||||||
|
style_button_1: {
|
||||||
|
color: '#FFFFFF',
|
||||||
|
fontSize: '30rpx',
|
||||||
|
backgroundColor: '#0066FF',
|
||||||
|
borderRadius: '8rpx'
|
||||||
|
},
|
||||||
|
style_button_2: {
|
||||||
|
color: '#0066FF',
|
||||||
|
fontSize: '30rpx',
|
||||||
|
backgroundColor: '#E2EDFF',
|
||||||
|
borderRadius: '8rpx'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,11 +48,13 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
/* ios打包配置 */
|
/* ios打包配置 */
|
||||||
"ios" : {},
|
"ios" : {
|
||||||
|
"dSYMs" : false
|
||||||
|
},
|
||||||
/* SDK配置 */
|
/* SDK配置 */
|
||||||
"sdkConfigs" : {},
|
"sdkConfigs" : {},
|
||||||
"splashscreen" : {
|
"splashscreen" : {
|
||||||
"androidStyle" : "default",
|
"androidStyle" : "common",
|
||||||
"android" : {
|
"android" : {
|
||||||
"hdpi" : "src/static/images/login/open.9.png",
|
"hdpi" : "src/static/images/login/open.9.png",
|
||||||
"xhdpi" : "src/static/images/login/open.9.png",
|
"xhdpi" : "src/static/images/login/open.9.png",
|
||||||
|
|||||||
@@ -311,6 +311,70 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "竞赛列表页",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/matching",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "匹配页面",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/pk",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "pk页面",
|
||||||
|
"disableSwipeBack": true,
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/result",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "pk结果页面",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/ranking",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "pk排行榜",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/pointsAndRank/points",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "积分变动明细",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/pointsAndRank/rank",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "段位列表",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/course/index",
|
"path": "pages/course/index",
|
||||||
"style": {
|
"style": {
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
<template>
|
||||||
|
<z-paging
|
||||||
|
ref="pagingRef"
|
||||||
|
v-model="data_list"
|
||||||
|
@query="queryList"
|
||||||
|
class="scroll_div"
|
||||||
|
bg-color="#F1F5FA"
|
||||||
|
empty-view-img="/static/images/competition/list_empty.png"
|
||||||
|
empty-view-text="竞赛正在筹备中,敬请期待~"
|
||||||
|
:empty-view-super-style="{ paddingTop: '10%' }"
|
||||||
|
:empty-view-img-style="{ height: '520rpx', width: '494rpx', marginBottom: '40rpx' }"
|
||||||
|
>
|
||||||
|
<template #top>
|
||||||
|
<view class="main_div">
|
||||||
|
<view class="body-title">
|
||||||
|
<view class="back_div" @click="common.navigateBack()">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
<view>竞赛练习</view>
|
||||||
|
</view>
|
||||||
|
<view class="input-view">
|
||||||
|
<search-input placeholder="请输入竞赛名" @search="search"></search-input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<view class="scroll-Y">
|
||||||
|
<view class="item" v-for="(item, index) in data_list" @click="goto_competition(item)">
|
||||||
|
<view class="cover">
|
||||||
|
<image-preview class="img" :src="item.ossAddr" mode="aspectFill"></image-preview>
|
||||||
|
</view>
|
||||||
|
<view class="title ellipsis-text">
|
||||||
|
{{ item.comName }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 竞赛列表
|
||||||
|
import { ref, reactive, watch, onMounted } from 'vue';
|
||||||
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||||
|
import useZpaging from '@/composables/useZpaging.js';
|
||||||
|
import common from '@/common/common';
|
||||||
|
import { queryTraUserAnonyByUserId } from '@/api/user.js';
|
||||||
|
import { queryTraCompetitionInfoPaging, queryTestPapers, queryOrgTree } from '@/api/competition.js';
|
||||||
|
|
||||||
|
const { pagingRef, queryList, data_list, search } = useZpaging({
|
||||||
|
searchKey: 'comName',
|
||||||
|
fetchFunction: queryTraCompetitionInfoPaging
|
||||||
|
});
|
||||||
|
const goto_competition = (item) => {
|
||||||
|
common.loading();
|
||||||
|
const result = Promise.all([queryTestPapers({ comId: item.comId }), queryTraUserAnonyByUserId(), queryOrgTree()]);
|
||||||
|
result
|
||||||
|
.then((res) => {
|
||||||
|
const papersId = res[0].body;
|
||||||
|
const comId = item.comId;
|
||||||
|
common.setPageCache('competition_list', {
|
||||||
|
papersId: papersId, // 试卷id
|
||||||
|
isAnony: res[1].body.isAnony, // 是否匿名 Y是N否
|
||||||
|
ruleDesc: item.ruleDesc, // 规则说明
|
||||||
|
comName: item.comName, // 标题
|
||||||
|
comId: comId
|
||||||
|
});
|
||||||
|
common.setValue('orgTree', res[2].body ?? []);
|
||||||
|
common.hideLoading();
|
||||||
|
common.navigateTo(`/pages/competition/matching?papersId=${papersId}&comId=${comId}`);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
common.msg('网络繁忙,请稍后再试!');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
onLoad(() => {});
|
||||||
|
onUnload(() => {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.item {
|
||||||
|
margin: 28rpx;
|
||||||
|
padding: 22rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
.cover {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
width: calc(100vw - 100rpx);
|
||||||
|
padding-top: calc(9 / 16 * 100%);
|
||||||
|
position: relative;
|
||||||
|
.img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-Y {
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #f1f5fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main_div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: var(--status-bar-height);
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-title {
|
||||||
|
width: 100%;
|
||||||
|
height: 70rpx;
|
||||||
|
font-size: 33rpx;
|
||||||
|
padding-top: 10rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #000;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.delete_div {
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.back_div {
|
||||||
|
position: absolute;
|
||||||
|
left: 26rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #2b2c2e;
|
||||||
|
border-left: 4rpx solid #2b2c2e;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-view {
|
||||||
|
width: 90%;
|
||||||
|
margin: 20rpx auto;
|
||||||
|
height: 78rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.search_div {
|
||||||
|
position: absolute;
|
||||||
|
top: 0%;
|
||||||
|
right: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 70rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* 生成随机匹配时间
|
||||||
|
* 特点:同一时间段生成的时间会比较接近,时间范围可配置
|
||||||
|
*/
|
||||||
|
export const MatchTimeGenerator = (() => {
|
||||||
|
// 可配置的时间范围(毫秒)
|
||||||
|
const MIN_TIME = 2000; // 最小时间
|
||||||
|
const MAX_TIME = 6000; // 最大时间
|
||||||
|
|
||||||
|
// 时间窗口:100秒内生成的时间会基于同一基准(可根据需要调整)
|
||||||
|
const TIME_WINDOW = 100000;
|
||||||
|
// 同一窗口内的最大偏差(±1.5秒,可根据需要调整)
|
||||||
|
const MAX_DEVIATION = 1500;
|
||||||
|
|
||||||
|
// 记录上一次生成的基准时间和时间戳
|
||||||
|
let lastBaseTime = 0;
|
||||||
|
let lastTimestamp = 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* 生成匹配时间(毫秒)
|
||||||
|
* @returns {number} 介于MIN_TIME和MAX_TIME之间的随机数(毫秒)
|
||||||
|
*/
|
||||||
|
generate() : number {
|
||||||
|
const now = Date.now();
|
||||||
|
let baseTime : number;
|
||||||
|
|
||||||
|
// 如果超过时间窗口或首次生成,重新计算基准时间
|
||||||
|
if (now - lastTimestamp > TIME_WINDOW || lastBaseTime === 0) {
|
||||||
|
// 生成MIN_TIME到MAX_TIME之间的基准时间(毫秒)
|
||||||
|
const timeRange = MAX_TIME - MIN_TIME;
|
||||||
|
baseTime = MIN_TIME + Math.floor(Math.random() * timeRange);
|
||||||
|
lastBaseTime = baseTime;
|
||||||
|
lastTimestamp = now;
|
||||||
|
} else {
|
||||||
|
// 在同一时间窗口内,基于上次基准时间生成偏差
|
||||||
|
baseTime = lastBaseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成偏差值(-MAX_DEVIATION 到 MAX_DEVIATION)
|
||||||
|
const deviation = Math.floor(Math.random() * (MAX_DEVIATION * 2 + 1)) - MAX_DEVIATION;
|
||||||
|
let matchTime = baseTime + deviation;
|
||||||
|
|
||||||
|
// 确保结果在配置的范围内
|
||||||
|
matchTime = Math.max(MIN_TIME, Math.min(MAX_TIME, matchTime));
|
||||||
|
|
||||||
|
return matchTime;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成匹配时间(秒)
|
||||||
|
* @returns {number} 介于MIN_TIME/1000和MAX_TIME/1000之间的随机数(秒,保留一位小数)
|
||||||
|
*/
|
||||||
|
generateInSeconds() : number {
|
||||||
|
return Math.round(this.generate() / 100) / 10;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
export const formatTime = (seconds : number) => {
|
||||||
|
const m = Math.floor(seconds / 60);
|
||||||
|
const s = seconds % 60;
|
||||||
|
return [m.toString().padStart(2, '0'), s.toString().padStart(2, '0')].join(':');
|
||||||
|
};
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import AvatarW1 from '@/static/images/competition/avatar/f_1.jpg'
|
||||||
|
import AvatarW2 from '@/static/images/competition/avatar/f_2.jpg'
|
||||||
|
import AvatarW3 from '@/static/images/competition/avatar/f_3.jpg'
|
||||||
|
import AvatarW4 from '@/static/images/competition/avatar/f_4.jpg'
|
||||||
|
import AvatarM1 from '@/static/images/competition/avatar/m_1.jpg'
|
||||||
|
import AvatarM2 from '@/static/images/competition/avatar/m_2.jpg'
|
||||||
|
import AvatarM3 from '@/static/images/competition/avatar/m_3.jpg'
|
||||||
|
import AvatarM4 from '@/static/images/competition/avatar/m_4.jpg'
|
||||||
|
import AvatarS1 from '@/static/images/competition/avatar/s_1.jpg'
|
||||||
|
import AvatarS2 from '@/static/images/competition/avatar/s_2.jpg'
|
||||||
|
import AvatarS3 from '@/static/images/competition/avatar/s_3.jpg'
|
||||||
|
import AvatarS4 from '@/static/images/competition/avatar/s_4.jpg'
|
||||||
|
|
||||||
|
// 定义头像类型
|
||||||
|
type AvatarType = 'f' | 'm' | 's';
|
||||||
|
|
||||||
|
// 按类型分组
|
||||||
|
const avatarsByType = {
|
||||||
|
f: [AvatarW1, AvatarW2, AvatarW3, AvatarW4],
|
||||||
|
m: [AvatarM1, AvatarM2, AvatarM3, AvatarM4],
|
||||||
|
s: [AvatarS1, AvatarS2, AvatarS3, AvatarS4]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机获取头像
|
||||||
|
* @param type1 第一个头像类型(可选)
|
||||||
|
* @param type2 第二个头像类型(可选,传入则返回2个头像)
|
||||||
|
* @returns 单个头像路径(当只传type1或都不传时)或两个头像路径的数组(当传入type2时)
|
||||||
|
*/
|
||||||
|
export default function getRandomAvatars(
|
||||||
|
type1 ?: AvatarType,
|
||||||
|
type2 ?: AvatarType
|
||||||
|
) {
|
||||||
|
// 随机获取指定类型的头像
|
||||||
|
const getRandomAvatar = (type ?: AvatarType) => {
|
||||||
|
// 如果指定了类型且有效,则从该类型中选择
|
||||||
|
if (type && avatarsByType[type]) {
|
||||||
|
const avatars = avatarsByType[type];
|
||||||
|
return avatars[Math.floor(Math.random() * avatars.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则从所有头像中随机选择
|
||||||
|
const allAvatars = [
|
||||||
|
...avatarsByType.f,
|
||||||
|
...avatarsByType.m,
|
||||||
|
...avatarsByType.s
|
||||||
|
];
|
||||||
|
return allAvatars[Math.floor(Math.random() * allAvatars.length)];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 只传type1或都不传时,返回1个头像
|
||||||
|
if (type2 === undefined) {
|
||||||
|
return getRandomAvatar(type1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 传入type2时,返回2个头像
|
||||||
|
const avatar1 = getRandomAvatar(type1);
|
||||||
|
let avatar2;
|
||||||
|
|
||||||
|
// 当两个类型相同时,确保头像不重复
|
||||||
|
if (type1 && type1 === type2) {
|
||||||
|
const sameTypeAvatars = avatarsByType[type1].filter(avatar => avatar !== avatar1);
|
||||||
|
avatar2 = sameTypeAvatars[Math.floor(Math.random() * sameTypeAvatars.length)];
|
||||||
|
} else {
|
||||||
|
avatar2 = getRandomAvatar(type2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [avatar1, avatar2];
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export function formatSecondsToMS(seconds) {
|
||||||
|
|
||||||
|
// 尝试将输入转换为数字(处理字符串类型的数字)
|
||||||
|
const num = Number(seconds);
|
||||||
|
|
||||||
|
// 处理无效输入(转换失败、非数字、负数)
|
||||||
|
if (isNaN(num) || num < 0) {
|
||||||
|
return '0-秒';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算分钟(不进位,直接取整)
|
||||||
|
const minutes = Math.floor(num / 60);
|
||||||
|
// 计算剩余秒数(取整)
|
||||||
|
const remainingSeconds = Math.floor(num % 60);
|
||||||
|
if (minutes === 0) {
|
||||||
|
return `${remainingSeconds}秒`;
|
||||||
|
}
|
||||||
|
// 拼接结果
|
||||||
|
return `${minutes}分${remainingSeconds}秒`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
<template>
|
||||||
|
<view class="main_div max_page">
|
||||||
|
<template v-if="!isMatchingSuccess">
|
||||||
|
<!-- 顶部一些按钮 -->
|
||||||
|
<view class="top-button-div">
|
||||||
|
<view class="back_div" @click="common.navigateBack()">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="top-icon-div" @click="click_top_icon(1)">
|
||||||
|
<image class="img1" :src="data_info.isAnony === 'N' ? pkAnonymousClose() : pkAnonymousOpen()"></image>
|
||||||
|
<view class="text">{{ data_info.isAnony === 'N' ? '不匿名' : '匿名' }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="top-icon-div" @click="click_top_icon(2)">
|
||||||
|
<image class="img2" :src="pkRules()"></image>
|
||||||
|
<view class="text">规则说明</view>
|
||||||
|
</view>
|
||||||
|
<view class="top-icon-div" @click="click_top_icon(3)">
|
||||||
|
<image class="img3" :src="pkRankingList()"></image>
|
||||||
|
<view class="text">排行榜</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="title-div" :class="{ hidden: challengeLoading }">
|
||||||
|
{{ data_info.comName }}
|
||||||
|
</view>
|
||||||
|
<view class="match-msg-div" :class="{ hidden: !challengeLoading }">匹配中...</view>
|
||||||
|
<view class="avatar-div">
|
||||||
|
<view class="avatar-surround-div">
|
||||||
|
<view class="avatar-img-div" :class="{ hidden: challengeLoading }">
|
||||||
|
<cached-avatar v-show="data_info.isAnony === 'N'" class="img"></cached-avatar>
|
||||||
|
<image v-show="data_info.isAnony === 'Y'" class="img" :src="defaultAnonymousAvatar"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="avatar-name-div">{{ data_info.isAnony === 'N' ? data_info.userName : '匿名' }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="select-div" :class="{ hidden: challengeLoading }" @click="selectionInstitutionsRef.open(true)">
|
||||||
|
<view class="select-institution-div">
|
||||||
|
{{ data_info.orgName }}
|
||||||
|
<image class="img" :src="switchIcon()"></image>
|
||||||
|
</view>
|
||||||
|
<view class="select-institution-msg-div">*选择机构后,会根据机构进行人员随机匹配挑战</view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<!-- 匹配时间 -->
|
||||||
|
<view class="match-time-div" :class="{ hidden: !challengeLoading }">
|
||||||
|
{{ formatTime(practiceTime) }}
|
||||||
|
</view>
|
||||||
|
<view class="button-div" v-show="challengeButtonStatus">
|
||||||
|
<view
|
||||||
|
:class="{ start_button: !challengeLoading, cancel_button: challengeLoading, 'button-transition': true }"
|
||||||
|
@click="start_challenge"
|
||||||
|
>
|
||||||
|
{{ challengeLoading ? '取消匹配' : '开始挑战' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<view class="matching-success-msg">匹配成功</view>
|
||||||
|
<view class="matching-success-animation">
|
||||||
|
<view class="left animate-left">
|
||||||
|
<image class="img" src="@/static/images/competition/matching-success-left.png" mode="widthFix"></image>
|
||||||
|
<view class="information-div-left">
|
||||||
|
<view class="avatar-img-div">
|
||||||
|
<cached-avatar v-show="data_info.isAnony === 'N'" class="img"></cached-avatar>
|
||||||
|
<image v-show="data_info.isAnony === 'Y'" class="img" :src="defaultAnonymousAvatar"></image>
|
||||||
|
</view>
|
||||||
|
<view class="name">
|
||||||
|
{{ data_info.isAnony === 'N' ? data_info.userName : '匿名' }}
|
||||||
|
</view>
|
||||||
|
<view class="org">
|
||||||
|
{{ data_info.isAnony === 'N' ? data_info.orgIdName : '机构不显示' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="right animate-right">
|
||||||
|
<image class="img" src="@/static/images/competition/matching-success-right.png" mode="widthFix"></image>
|
||||||
|
<view class="information-div-right">
|
||||||
|
<view class="avatar-img-div">
|
||||||
|
<image-preview
|
||||||
|
v-if="data_info.pkIsAnony === 'N'"
|
||||||
|
class="img"
|
||||||
|
:src="data_info.pkimgAddr"
|
||||||
|
></image-preview>
|
||||||
|
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="name">
|
||||||
|
{{ data_info.pkIsAnony === 'N' ? data_info.pkUserName : '匿名' }}
|
||||||
|
</view>
|
||||||
|
<view class="org">
|
||||||
|
{{ data_info.pkIsAnony === 'N' ? data_info.pkOrgIdName : '机构不显示' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="matching-success-text">准备!</view>
|
||||||
|
</template>
|
||||||
|
<uni-popup ref="popupRef" class="popup">
|
||||||
|
<view class="sheet_popup_div">
|
||||||
|
<view class="title_div">双人对战规则说明</view>
|
||||||
|
<view class="note_div">
|
||||||
|
{{ data_info.ruleDesc }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
<selectionInstitutions ref="selectionInstitutionsRef" @submit="selectionInstitutionsSubmit"></selectionInstitutions>
|
||||||
|
<uv-picker ref="anonyPickerRef" :columns="[anonyOptions]" keyName="label" @confirm="anonyConfirm"></uv-picker>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {ref, onMounted, reactive} from 'vue';
|
||||||
|
import common, {getUserInfo} from '@/common/common';
|
||||||
|
import {MatchTimeGenerator, formatTime} from './js/matching';
|
||||||
|
import {queryTraCompetitionInfoByPkUser} from '@/api/competition';
|
||||||
|
import {onLoad} from '@dcloudio/uni-app';
|
||||||
|
import {defaultAnonymousAvatar} from '@/enum';
|
||||||
|
import {pkAnonymousClose, pkAnonymousOpen, pkRankingList, pkRules, switchIcon} from '@/common/imgSvg';
|
||||||
|
import {queryTraUserAnonyByUserId, updateTraUserAnony} from '@/api/user';
|
||||||
|
import selectionInstitutions from '@/components/selection-institutions/index.vue';
|
||||||
|
|
||||||
|
const data_info = reactive({
|
||||||
|
userId: '',
|
||||||
|
userName: '',
|
||||||
|
orgName: '全部', // 机构名称
|
||||||
|
orgId: 'A', // 机构的ID,全行是A
|
||||||
|
papersId: '', // 试卷id
|
||||||
|
isAnony: '', // 是否匿名 Y是N否
|
||||||
|
ruleDesc: '', // 规则说明
|
||||||
|
comName: '', // 标题
|
||||||
|
comId: '',
|
||||||
|
orgIdName: '',
|
||||||
|
pkIsAnony: '',
|
||||||
|
pkimgAddr: '',
|
||||||
|
pkUserName: '',
|
||||||
|
pkOrgIdName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const popupRef = ref(null);
|
||||||
|
const anonyPickerRef = ref(null);
|
||||||
|
const selectionInstitutionsRef = ref(null);
|
||||||
|
const challengeLoading = ref(false);
|
||||||
|
const isMatchingSuccess = ref(false); // 匹配成功状态
|
||||||
|
const challengeButtonStatus = ref(true); // 匹配按钮显示
|
||||||
|
const practiceTime = ref(0); // 匹配时间
|
||||||
|
let practiceTimeTimer: number | null = null; // 匹配时间计时器
|
||||||
|
let matchTimer: number | null = null; // 匹配成功定时器
|
||||||
|
const anonyOptions = [
|
||||||
|
{
|
||||||
|
value: 'Y',
|
||||||
|
label: '匿名'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'N',
|
||||||
|
label: '不匿名'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
// 开始挑战
|
||||||
|
const start_challenge = () => {
|
||||||
|
if (!challengeLoading.value) {
|
||||||
|
challengeLoading.value = true;
|
||||||
|
// 清除旧计时器
|
||||||
|
if (practiceTimeTimer) {
|
||||||
|
clearInterval(practiceTimeTimer);
|
||||||
|
}
|
||||||
|
// 开始计时
|
||||||
|
const practiceStartTime = new Date().getTime();
|
||||||
|
practiceTimeTimer = setInterval(() => {
|
||||||
|
const currentTime = Date.now();
|
||||||
|
practiceTime.value = Math.floor((currentTime - practiceStartTime) / 1000);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// 生成匹配延迟时间
|
||||||
|
// const delayTime = 0;
|
||||||
|
const delayTime = MatchTimeGenerator.generateInSeconds();
|
||||||
|
|
||||||
|
// 匹配定时器
|
||||||
|
matchTimer = setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
challengeButtonStatus.value = false;
|
||||||
|
const orgId = data_info.orgId
|
||||||
|
const papersId = data_info.papersId
|
||||||
|
const comId = data_info.comId
|
||||||
|
const pkDataBody = await queryTraCompetitionInfoByPkUser({
|
||||||
|
// orgId:510121,
|
||||||
|
// papersId:'COMPETITION_PAPERS0250640321542025101615442400000003107',
|
||||||
|
// comId:'TRA_COMPETITION_INFO0250640321542025101615442400000003099'
|
||||||
|
orgId, papersId, comId
|
||||||
|
});
|
||||||
|
const pkData = pkDataBody.body;
|
||||||
|
// 下面两行是给后端擦屁股,后端传回的数值为空
|
||||||
|
pkData.orgId = orgId
|
||||||
|
pkData.papersId = papersId
|
||||||
|
common.setPageCache('competition_pk', pkData);
|
||||||
|
// 1. 显示匹配成功状态
|
||||||
|
isMatchingSuccess.value = true;
|
||||||
|
uni.vibrateLong({
|
||||||
|
success: function () {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 2. 执行匹配成功动画(等待1.5秒)
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 600));
|
||||||
|
// 3. 清除计时器
|
||||||
|
if (practiceTimeTimer) {
|
||||||
|
clearInterval(practiceTimeTimer);
|
||||||
|
practiceTimeTimer = null;
|
||||||
|
}
|
||||||
|
// 5. 跳转页面
|
||||||
|
common.navigateTo('/pages/competition/pk');
|
||||||
|
challengeLoading.value = true;
|
||||||
|
} catch (error) {
|
||||||
|
common.msg('队列繁忙,请稍后再试!');
|
||||||
|
// 出错处理
|
||||||
|
} finally {
|
||||||
|
resetChallengeState();
|
||||||
|
}
|
||||||
|
}, delayTime * 1000);
|
||||||
|
} else {
|
||||||
|
// 取消挑战
|
||||||
|
resetChallengeState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface InstitutionItem {
|
||||||
|
orgName: string; // 机构名称,类型为字符串
|
||||||
|
orgId: string; // 机构ID,类型为字符串
|
||||||
|
parentId: string; // 父级ID,类型为字符串
|
||||||
|
children?: InstitutionItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectionInstitutionsSubmit = (options: [InstitutionItem, ...InstitutionItem[]]) => {
|
||||||
|
// 缓存起来
|
||||||
|
common.setValue('cache_selection_institutions' + data_info.userId, options);
|
||||||
|
const lastItem = options.at(-1);
|
||||||
|
data_info.orgName = lastItem.orgName;
|
||||||
|
data_info.orgId = lastItem.orgId;
|
||||||
|
|
||||||
|
selectionInstitutionsRef.value.close();
|
||||||
|
};
|
||||||
|
const anonyConfirm = (e) => {
|
||||||
|
const originalIsAnony = data_info.isAnony;
|
||||||
|
const isAnony = e.value[0].value;
|
||||||
|
if (isAnony === data_info.isAnony) return;
|
||||||
|
data_info.isAnony = isAnony;
|
||||||
|
common.loading('修改中');
|
||||||
|
updateTraUserAnony({isAnony})
|
||||||
|
.then(() => {
|
||||||
|
setTimeout(() => common.msg('切换成功'), 400);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 4. 请求失败:用初始值回滚
|
||||||
|
data_info.isAnony = originalIsAnony;
|
||||||
|
common.msg('切换失败,请重试'); // 可选:提示失败
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
common.hideLoading();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const click_top_icon = (type: number) => {
|
||||||
|
// 匿名切换
|
||||||
|
if (type === 1) {
|
||||||
|
anonyPickerRef.value.setIndexs([data_info.isAnony === 'Y' ? 0 : 1], true);
|
||||||
|
anonyPickerRef.value.open();
|
||||||
|
} else if (type === 2) {
|
||||||
|
// 打开规则说明
|
||||||
|
popupRef.value.open('bottom');
|
||||||
|
} else if (type === 3) {
|
||||||
|
// 去排行榜
|
||||||
|
common.navigateTo(`/pages/competition/ranking?papersId=${data_info.papersId}&orgId=${data_info.orgId}`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 统一重置状态的函数
|
||||||
|
const resetChallengeState = () => {
|
||||||
|
if (matchTimer) {
|
||||||
|
clearTimeout(matchTimer);
|
||||||
|
matchTimer = null;
|
||||||
|
}
|
||||||
|
if (practiceTimeTimer) {
|
||||||
|
clearInterval(practiceTimeTimer);
|
||||||
|
practiceTimeTimer = null;
|
||||||
|
}
|
||||||
|
challengeButtonStatus.value = true;
|
||||||
|
challengeLoading.value = false;
|
||||||
|
isMatchingSuccess.value = false;
|
||||||
|
practiceTime.value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
const lastData = common.getPageCache('competition_list');
|
||||||
|
console.log('lastData', lastData);
|
||||||
|
const userInfo = getUserInfo();
|
||||||
|
Object.assign(data_info, {
|
||||||
|
...lastData,
|
||||||
|
userId: userInfo.userId,
|
||||||
|
userName: userInfo.userName,
|
||||||
|
gender: userInfo.gender,
|
||||||
|
papersId: e.papersId,
|
||||||
|
comId: e.comId
|
||||||
|
});
|
||||||
|
const selectOptions = common.getValue('cache_selection_institutions' + data_info.userId);
|
||||||
|
if (Array.isArray(selectOptions) && selectOptions.length > 0) {
|
||||||
|
const lastItem = selectOptions.at(-1);
|
||||||
|
data_info.orgName = lastItem.orgName;
|
||||||
|
data_info.orgId = lastItem.orgId;
|
||||||
|
// const orgTreeInit = common.getValue('orgTree');
|
||||||
|
// if (Array.isArray(orgTreeInit) && orgTreeInit.length > 0) {
|
||||||
|
// console.log('selectOptions', selectOptions);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 匹配成功样式动画
|
||||||
|
@import './style/matching-success.scss';
|
||||||
|
@import './style/matching-loading.scss';
|
||||||
|
@import './style/matching-prelude.scss';
|
||||||
|
|
||||||
|
/* 容器样式 */
|
||||||
|
.max_page {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-image: url('@/static/images/competition/bg.png');
|
||||||
|
background-color: #000; /* 图片高度不足时的背景色 */
|
||||||
|
background-size: 100% auto; /* 宽度填满,高度自适应 */
|
||||||
|
background-position: center top; /* 图片顶部居中显示 */
|
||||||
|
background-repeat: no-repeat; /* 不重复平铺 */
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,803 @@
|
|||||||
|
<template>
|
||||||
|
<view class="main_div max_page">
|
||||||
|
<nav-bar :is_seat="true"></nav-bar>
|
||||||
|
<view class="nav-div">
|
||||||
|
<view class="title ellipsis-text">PK中</view>
|
||||||
|
<view class="back_div" @click="exit_practice">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 对决信息框 -->
|
||||||
|
<view class="duel-msg-div">
|
||||||
|
<view class="personnel-div">
|
||||||
|
<view class="avatar-div">
|
||||||
|
<cached-avatar v-if="pkData.isAnony === 'N'" class="img"></cached-avatar>
|
||||||
|
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="name-div ellipsis-text">{{ pkData.isAnony === 'N' ? pkData.userName : '匿名' }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="fraction-div left">
|
||||||
|
<view class="fraction-title">分数</view>
|
||||||
|
<view class="fraction-value">{{ ourScore }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="fraction-div right">
|
||||||
|
<view class="fraction-title">分数</view>
|
||||||
|
<view class="fraction-value">{{ opponentScore }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="personnel-div">
|
||||||
|
<view class="avatar-div">
|
||||||
|
<image-preview v-if="pkData.pkIsAnony === 'N'" class="img" :src="pkData.pkImgAddr"></image-preview>
|
||||||
|
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="name-div">{{ pkData.pkIsAnony === 'N' ? pkData.pkUserName : '匿名' }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="body-area-div">
|
||||||
|
<view class="countdown-and-question-number-div">
|
||||||
|
<view class="top">
|
||||||
|
<view class="countdown">
|
||||||
|
<text class="bold">{{ questionNumber + 1 }}</text>
|
||||||
|
<text class="grey">/{{ topicList.length }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="question">
|
||||||
|
<view class="countdown_time">
|
||||||
|
{{ formatSeconds(practiceRemainingTime) }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="progress">
|
||||||
|
<uv-line-progress
|
||||||
|
:percentage="progress"
|
||||||
|
:showText="false"
|
||||||
|
activeColor="#0066FF"
|
||||||
|
inactiveColor="#D9DEE8"
|
||||||
|
:height="8"
|
||||||
|
></uv-line-progress>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="scroll_div">
|
||||||
|
<swiper
|
||||||
|
class="swiper"
|
||||||
|
:indicator-dots="false"
|
||||||
|
:current="questionNumber"
|
||||||
|
:disable-touch="true"
|
||||||
|
easing-function="linear"
|
||||||
|
>
|
||||||
|
<swiper-item v-for="(item, index) in topicList">
|
||||||
|
<view class="content">
|
||||||
|
<view class="expose_shadow"></view>
|
||||||
|
<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0">
|
||||||
|
<Subject
|
||||||
|
:item="item"
|
||||||
|
:mode="mode"
|
||||||
|
:isPreview="item.isPreview"
|
||||||
|
:clearResult="item.clearResult"
|
||||||
|
@subject_click="subject_click"
|
||||||
|
v-model="item.my_answer"
|
||||||
|
>
|
||||||
|
<template #title-right>
|
||||||
|
<text class="success-sun-div">
|
||||||
|
已答对
|
||||||
|
<text class="number">{{ correctQuestions.length }}</text>
|
||||||
|
题
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
|
</Subject>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</view>
|
||||||
|
<view class="fixed-box font_pf" :style="{ marginBottom: popup_input_bottom }">
|
||||||
|
<view class="touch-btn-div" :class="{ show: showTouchBtn }">
|
||||||
|
<TouchBtn
|
||||||
|
ref="touchBtnRef"
|
||||||
|
class="talk-btns"
|
||||||
|
@submit="touchBtnSubmit"
|
||||||
|
disabledText="只能进行一条回答"
|
||||||
|
:isDisabled="touchIsDisabled"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 反馈组件 -->
|
||||||
|
<Feedback ref="feedbackRef"></Feedback>
|
||||||
|
<!-- 结尾弹出层 -->
|
||||||
|
<Dialog ref="dialogRef" @button_click="result_click"></Dialog>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, computed, onMounted, nextTick, onUnmounted } from 'vue';
|
||||||
|
import { onLoad, onHide, onShow, onUnload, onBackPress, onReady } from '@dcloudio/uni-app';
|
||||||
|
import { defaultAnonymousAvatar, styleButton } from '@/enum';
|
||||||
|
import Feedback from '@/pages/examination/components/feedback.vue';
|
||||||
|
import Dialog from '@/pages/examination/components/dialog.vue';
|
||||||
|
import Subject from '@/components/examination/subject.vue';
|
||||||
|
import CharactersSubject from '@/components/examination/characters-subject.vue';
|
||||||
|
import TouchBtn from '@/components/examination/touchBtn.vue';
|
||||||
|
import common from '@/common/common';
|
||||||
|
import { setPageCache, formatSeconds, getPageCache, setupKeyboardHeightListener } from '@/common/common';
|
||||||
|
import { commonUploadVoiceFile } from '@/api/common.js';
|
||||||
|
import { optionErrorIcon, examinationSheetIcon, practiceExitIcon } from '@/common/imgSvg';
|
||||||
|
import { practiceCommit, queryCrsPracticeAnswerResult } from '@/api/practice.js';
|
||||||
|
import { competitionAnswer, queryCompetitionPracticeAnswerResult, competitionAnswerEnd } from '@/api/competition.js';
|
||||||
|
import { startExamByCrs } from '@/api/examination.js';
|
||||||
|
import { startPracticeByCrs } from '@/api/practice.js';
|
||||||
|
|
||||||
|
const feedbackRef = ref(null);
|
||||||
|
const dialogRef = ref(null);
|
||||||
|
const touchBtnRef = ref(null);
|
||||||
|
const countDownRef = ref(null);
|
||||||
|
const practiceTime = ref(0); // 当前Pk时长
|
||||||
|
const practiceRemainingTime = ref(0); // 当前Pk剩余时长
|
||||||
|
let practiceStartTime = 0; // Pk开始时间
|
||||||
|
let practiceTimeTimer = null; // Pk计时器
|
||||||
|
let leaveStartTime = 0; // 离开开始时间
|
||||||
|
const mode = ref('pk_in'); // PK中 pk_in
|
||||||
|
|
||||||
|
// 计算对方分数
|
||||||
|
const opponentScore = computed(() => {
|
||||||
|
|
||||||
|
// 筛选出所有 asrTm <= 当前时长的项
|
||||||
|
const validItems = pkData.traCompetitionPkTimeRecordVos.filter((item) => item.asrTm <= practiceTime.value);
|
||||||
|
if (validItems.length > 0) {
|
||||||
|
return validItems[validItems.length - 1].singleGrade;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
const pkData = reactive({
|
||||||
|
comLimit: 0,
|
||||||
|
crsId: '',
|
||||||
|
name: '', // 名称
|
||||||
|
orgId: '',
|
||||||
|
papersId: '',
|
||||||
|
pkImgAddr: '',
|
||||||
|
traCompetitionPkTimeRecordVos:[]
|
||||||
|
}); // 试卷信息
|
||||||
|
const topicList = reactive([]); // 问题列表
|
||||||
|
const popup_input_bottom = ref('0px');
|
||||||
|
const questionNumber = ref(0); // 题号
|
||||||
|
// 答对的题目数组
|
||||||
|
const correctQuestions = computed(() => topicList.filter((res) => res.judgeResult === 'P'));
|
||||||
|
// 我方分数
|
||||||
|
const ourScore = computed(() => correctQuestions.value.reduce((sum, item) => sum + item.tgtGrade, 0));
|
||||||
|
|
||||||
|
const topic = computed({
|
||||||
|
get: () => topicList[questionNumber.value],
|
||||||
|
set: (val) => (topicList[questionNumber.value] = val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const showTouchBtn = computed(() => {
|
||||||
|
return topic.value?.qnsTyp === 'ES' && !topic.value?.my_answer.anserResult;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 下面语音组件的禁用状态判断
|
||||||
|
const touchIsDisabled = computed(() => {
|
||||||
|
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
const progress = computed(() => {
|
||||||
|
// 计算进度百分比(保留两位小数)
|
||||||
|
const total = topicList.length;
|
||||||
|
if (total === 0) return 0;
|
||||||
|
const completed = questionNumber.value + 1;
|
||||||
|
return Math.min(Math.round((completed / total) * 10000) / 100, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
const subject_click = (type, params) => {
|
||||||
|
if (type === 'answer') {
|
||||||
|
//多选点击按钮答题
|
||||||
|
if (params.qnsTyp === 'MU') {
|
||||||
|
submitProblem({
|
||||||
|
anserResult: params.answer.join(',')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (type === 'choose') {
|
||||||
|
//单选判断点击选项答题
|
||||||
|
if (['JD', 'SN'].includes(params.qnsTyp)) {
|
||||||
|
submitProblem({ anserResult: params.answer.join(',') });
|
||||||
|
}
|
||||||
|
} else if (type === 'complete') {
|
||||||
|
// 问答题点击完成
|
||||||
|
submitProblem(params.answer);
|
||||||
|
} else if (type === 'again') {
|
||||||
|
// 问答题点击重答
|
||||||
|
topic.value.my_answer = {};
|
||||||
|
topic.value.isPreview = false;
|
||||||
|
topic.value.es_status = ''; // 取消转圈
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单题回答
|
||||||
|
const submitProblem = (answer) => {
|
||||||
|
common.loading('答题中');
|
||||||
|
// execId 执行ID 必输项:true 类型:String
|
||||||
|
// papersId 竞赛试卷ID 必输项:true 类型:String
|
||||||
|
// comId 竞赛ID 必输项:true 类型:String
|
||||||
|
// qnsId 试题ID 必输项:true 类型:String
|
||||||
|
// ossKey 对象存储 必输项:false 类型:String
|
||||||
|
// ossAddr 对象存储 必输项:false 类型:String
|
||||||
|
// showOrder 顺序号 必输项:false 类型:int
|
||||||
|
// anserResult 作答结果 必输项:false 类型:String
|
||||||
|
// asrStartTm 答题开始时间 必输项:false 类型:String
|
||||||
|
|
||||||
|
competitionAnswer({
|
||||||
|
execId: pkData.execId,
|
||||||
|
papersId: pkData.papersId,
|
||||||
|
comId: pkData.comId,
|
||||||
|
qnsId: topic.value.qnsId,
|
||||||
|
ossKey: '',
|
||||||
|
showOrder: questionNumber.value + 1,
|
||||||
|
limit: practiceTime.value, // 当前答题的秒
|
||||||
|
...answer
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
let traQnsInfoVo;
|
||||||
|
// 是问答题
|
||||||
|
if (topic.value.qnsTyp === 'ES') {
|
||||||
|
try {
|
||||||
|
const result = await queryWithRetry(res.body.execLogId);
|
||||||
|
traQnsInfoVo = result.body.traQnsInfoVo;
|
||||||
|
} catch (e) {
|
||||||
|
common.msg('当前服务器繁忙,请重新作答');
|
||||||
|
common.hideLoading();
|
||||||
|
topic.value.isPreview = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
traQnsInfoVo = res.body.traQnsInfoVo;
|
||||||
|
}
|
||||||
|
topic.value.isPreview = true; // 不能在点击了,打开预览模式
|
||||||
|
console.log('给出来的traQnsInfoVo', traQnsInfoVo);
|
||||||
|
common.hideLoading();
|
||||||
|
topic.value.clearResult = false; // 不清除正确答案
|
||||||
|
topic.value.analyContent = traQnsInfoVo.analyContent; // 答案解析
|
||||||
|
// 更新选项正确项目
|
||||||
|
topic.value.itemVos = traQnsInfoVo.itemVos; // 答案选项(todo应该不这样替换)
|
||||||
|
topic.value.anserResult = traQnsInfoVo.anserResult; // 正确答案字符串分割
|
||||||
|
topic.value.judgeResult = traQnsInfoVo.judgeResult; // 正确答案字符串分割
|
||||||
|
|
||||||
|
if (questionNumber.value >= topicList.length - 1) {
|
||||||
|
console.log('pk页答完了,带走的数据', pkData);
|
||||||
|
common.setPageCache('competition_pk_to_resulf', pkData);
|
||||||
|
nextTick(() => {
|
||||||
|
common.redirectTo(
|
||||||
|
`/pages/competition/result?&execId=${pkData.execId}&orgId=${pkData.orgId}&papersId=${pkData.papersId}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
questionNumber.value++;
|
||||||
|
}, 400);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 单选和判断需要清除已点击的按钮
|
||||||
|
if (['JD', 'SN'].includes(topic.value.qnsTyp)) {
|
||||||
|
topic.value.my_answer = [];
|
||||||
|
}
|
||||||
|
common.hideLoading();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 问答题轮询结果方法
|
||||||
|
const queryWithRetry = (execLogId, maxRetries = 20) => {
|
||||||
|
// 递归终止条件:达到最大重试次数
|
||||||
|
console.log('递归终止条件:达到最大重试次数', maxRetries);
|
||||||
|
if (maxRetries <= 0) {
|
||||||
|
console.log('超过最大重试次数,查询失败');
|
||||||
|
const error = new Error('超过最大重试次数,查询失败');
|
||||||
|
error.isMaxRetry = true; // 标记为"超过最大重试次数"错误
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
return queryCompetitionPracticeAnswerResult({ execLogId })
|
||||||
|
.then((res) => {
|
||||||
|
console.log('queryCompetitionPracticeAnswerResult', maxRetries, res.body);
|
||||||
|
const isWait = res.body.isWait;
|
||||||
|
if (isWait === 'Y') {
|
||||||
|
// 如果是Y,延迟2秒后重试,重试次数减1
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(queryWithRetry(execLogId, maxRetries - 1));
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 不是Y,直接返回结果
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log('error', error);
|
||||||
|
// 对接口调用错误进行重试
|
||||||
|
if (error.isMaxRetry) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(queryWithRetry(execLogId, maxRetries - 1));
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 录音组件提交
|
||||||
|
const touchBtnSubmit = (type, submitObj) => {
|
||||||
|
const topic = topicList[questionNumber.value];
|
||||||
|
touchBtnRef.value?.clearinputText(); // 清除发送框数据
|
||||||
|
if (type === 'voice') {
|
||||||
|
if (topic.es_status === '00') return;
|
||||||
|
topic.es_status = '00'; // 00转圈
|
||||||
|
const voicePath = submitObj;
|
||||||
|
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
|
||||||
|
.then((_res) => {
|
||||||
|
const _content = _res.body.transContent.trim();
|
||||||
|
if (_content === '') {
|
||||||
|
topic.es_status = ''; // 取消转圈
|
||||||
|
return common.msg('未识别到文字');
|
||||||
|
} else {
|
||||||
|
topic.es_status = '02';
|
||||||
|
topic.my_answer = {
|
||||||
|
anserResult: _res.body.transContent,
|
||||||
|
ossKey: _res.body.fileId,
|
||||||
|
ossAddr: _res.body.ossFileAddr,
|
||||||
|
voicePath: voicePath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
topic.es_status = ''; // 取消转圈
|
||||||
|
if (error === 'Other') {
|
||||||
|
common.msg('系统异常,请联系管理员');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (type === 'text') {
|
||||||
|
topic.es_status = '01';
|
||||||
|
topic.my_answer = {
|
||||||
|
anserResult: submitObj // 正确答案文字内容
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const examStat = ref('');
|
||||||
|
|
||||||
|
const result_click = async ({ key }) => {
|
||||||
|
if (key === 'exit') {
|
||||||
|
// 中途退出
|
||||||
|
dialogRef.value.close();
|
||||||
|
try {
|
||||||
|
// 考试结束
|
||||||
|
await competitionAnswerEnd({ execId: pkData.execId, comGrade: ourScore.value });
|
||||||
|
} catch (e) {}
|
||||||
|
common.navigateBack();
|
||||||
|
} else if (key === 'revert') {
|
||||||
|
// 返回
|
||||||
|
dialogRef.value.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 弹出框配置
|
||||||
|
const dialogConfiguration = reactive({});
|
||||||
|
|
||||||
|
// 中途退出
|
||||||
|
const exit_practice = () => {
|
||||||
|
dialogRef.value.open({
|
||||||
|
title: '提示',
|
||||||
|
msg: '中途退出视为结束竞赛,确定要退出吗?',
|
||||||
|
buttonList: [
|
||||||
|
{
|
||||||
|
key: 'exit',
|
||||||
|
name: '确定退出',
|
||||||
|
style: styleButton.style_button_2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'revert',
|
||||||
|
name: '继续竞赛',
|
||||||
|
style: styleButton.style_button_1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 启动练习时长定时器
|
||||||
|
const startTimer = () => {
|
||||||
|
if (practiceTimeTimer) {
|
||||||
|
clearInterval(practiceTimeTimer);
|
||||||
|
}
|
||||||
|
practiceTimeTimer = setInterval(() => {
|
||||||
|
const currentTime = Date.now();
|
||||||
|
const elapsedSeconds = Math.floor((currentTime - practiceStartTime) / 1000);
|
||||||
|
practiceTime.value = elapsedSeconds;
|
||||||
|
practiceRemainingTime.value = pkData.comLimit - practiceTime.value;
|
||||||
|
// console.log('倒计时时间', practiceRemainingTime.value);
|
||||||
|
// Pk时间到
|
||||||
|
if (practiceRemainingTime.value <= 0) {
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
// 初始化时检查
|
||||||
|
onLoad((e) => {
|
||||||
|
const pkDataParams = getPageCache('competition_pk');
|
||||||
|
if (!pkData) {
|
||||||
|
common.navigateBack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.assign(pkData, pkDataParams);
|
||||||
|
console.log('pkData', pkData);
|
||||||
|
pkDataParams.qnsInfoVos.forEach((res) => {
|
||||||
|
topicList.push({
|
||||||
|
...res,
|
||||||
|
isPreview: false,
|
||||||
|
clearResult: true,
|
||||||
|
es_status: '', // 预设一下问答题的状态,'' 空为没有 00 转圈 01 播放,其他暂定
|
||||||
|
my_answer: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 记录练习起始时间
|
||||||
|
practiceStartTime = new Date().getTime();
|
||||||
|
practiceRemainingTime.value = pkData.comLimit; // 设置倒计时初始值
|
||||||
|
setupKeyboardHeightListener((height) => {
|
||||||
|
popup_input_bottom.value = `${height}px`;
|
||||||
|
console.log('需要卸载吗');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
startTimer(); // 启动/恢复定时器
|
||||||
|
});
|
||||||
|
onBackPress((res) => res.from === 'backbutton');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
$bg-margin-left: 30rpx;
|
||||||
|
|
||||||
|
.popup_title_text {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup {
|
||||||
|
//答题卡
|
||||||
|
z-index: 1800;
|
||||||
|
padding: 0 38rpx;
|
||||||
|
|
||||||
|
.sheet_popup_div {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 10rpx 34rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 16rpx 16rpx 0px 0px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.title_div {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
font-family: PingFangSC;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
border-bottom: 2rpx solid #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup_back_div {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 30rpx;
|
||||||
|
right: 30rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet_table {
|
||||||
|
margin-top: 48rpx;
|
||||||
|
margin-bottom: 48rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: calc(100vw - 108rpx);
|
||||||
|
align-content: space-between;
|
||||||
|
|
||||||
|
.sheet_table_item {
|
||||||
|
width: calc((100vw - 108rpx) / 5 - 16rpx);
|
||||||
|
height: calc((100vw - 108rpx) / 5 - 16rpx);
|
||||||
|
margin: 8rpx;
|
||||||
|
border: 2rpx solid #e5e5e5;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current {
|
||||||
|
background-color: rgba(0, 102, 255, 0.6);
|
||||||
|
border-color: #0066ff;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.completed {
|
||||||
|
// 已完成
|
||||||
|
background-color: rgba(0, 102, 255, 0.1);
|
||||||
|
border-color: #0066ff;
|
||||||
|
color: #0066ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mark,
|
||||||
|
.completed.mark {
|
||||||
|
background-color: rgba(232, 181, 49, 0.1);
|
||||||
|
color: #e8b531;
|
||||||
|
border-color: #e8b531;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current.mark {
|
||||||
|
// 已完成
|
||||||
|
background-color: rgba(0, 102, 255, 0.6);
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: #e8b531;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet_button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-box {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 16rpx 16rpx 0px 0px;
|
||||||
|
border: 2rpx solid #e5e5e5;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.touch-btn-div {
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: height 0.2s ease-out;
|
||||||
|
}
|
||||||
|
.touch-btn-div.show {
|
||||||
|
height: 150rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-Y {
|
||||||
|
max-height: calc(100vh - var(--status-bar-height) - 70rpx - 210rpx - 70rpx - 40rpx - 160rpx);
|
||||||
|
min-height: calc(100vh - var(--status-bar-height) - 70rpx - 210rpx - 70rpx - 40rpx - 380rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper {
|
||||||
|
// 状态栏 var(--status-bar-height)
|
||||||
|
// 标题栏目 70rpx
|
||||||
|
// PK栏 170rpx + 上间距 40rpx
|
||||||
|
// 进度时间栏 70rpx
|
||||||
|
// 进度时间栏上下间距 40rpx = 20rpx + 20rpx
|
||||||
|
// height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx);
|
||||||
|
height: calc(100vh - var(--status-bar-height) - 70rpx - 210rpx - 70rpx - 40rpx);
|
||||||
|
.no_questions {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
margin: 32rpx $bg-margin-left;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 34rpx 30rpx 34rpx 36rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
.expose_shadow {
|
||||||
|
margin-left: 36rpx;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -26rpx;
|
||||||
|
left: 0%;
|
||||||
|
width: calc(100% - 66rpx);
|
||||||
|
height: 28rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 0 0 14rpx 14rpx;
|
||||||
|
opacity: 0.4;
|
||||||
|
z-index: 0;
|
||||||
|
// background-color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正确总数
|
||||||
|
.success-sun-div {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
.number {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #0066ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.body-area-div {
|
||||||
|
margin-top: -2rpx;
|
||||||
|
background: linear-gradient(185deg, #eff4ff 0%, #e9ebf9 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-and-question-number-div {
|
||||||
|
margin: 20rpx $bg-margin-left;
|
||||||
|
height: 70rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
.top {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #0066ff;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 216rpx;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
height: 42rpx;
|
||||||
|
background-color: #b2d1ff;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: #044ebb;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
.countdown_time {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.grey {
|
||||||
|
color: #8cabeb;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.bold {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.duel-msg-div {
|
||||||
|
width: 100%;
|
||||||
|
height: 172rpx;
|
||||||
|
background-image: url('@/static/images/competition/pk_bg_icon.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%; /* 让背景图填满盒子,与宽高比匹配 */
|
||||||
|
margin-top: 40rpx;
|
||||||
|
border-radius: 22rpx 22rpx 0 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
.personnel-div {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
.name-div {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
max-width: 5rem;
|
||||||
|
}
|
||||||
|
.avatar-div {
|
||||||
|
width: 78rpx;
|
||||||
|
height: 78rpx;
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fraction-div {
|
||||||
|
&.left {
|
||||||
|
margin: 0 74rpx 0 30rpx;
|
||||||
|
}
|
||||||
|
&.right {
|
||||||
|
margin: 0 30rpx 0 74rpx;
|
||||||
|
}
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
.fraction-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #fbe7d9;
|
||||||
|
line-height: 34rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
.fraction-value {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-family: Arial, Arial;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 50rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 60rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-div {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0 calc($bg-margin-left + 70rpx);
|
||||||
|
height: 70rpx;
|
||||||
|
font-family: PingFangSC;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: 70rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back_div {
|
||||||
|
position: absolute;
|
||||||
|
left: $bg-margin-left;
|
||||||
|
top: 0;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #ffffff;
|
||||||
|
border-left: 4rpx solid #ffffff;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main_div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #000;
|
||||||
|
/* 确保背景占满整个视口高度 */
|
||||||
|
min-height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,399 @@
|
|||||||
|
<template>
|
||||||
|
<view class="exam-ranking">
|
||||||
|
<image src="@/static/images/competition/ranking/ranking_bg.png" mode="widthFix" class="bg-box"></image>
|
||||||
|
<view class="ranking-box">
|
||||||
|
<view class="nav-div">
|
||||||
|
<view class="back_div" @click="common.navigateBack()">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="title-view">
|
||||||
|
<!-- <view class="title-info">考试排行榜</view> -->
|
||||||
|
<image
|
||||||
|
class="title-image"
|
||||||
|
src="@/static/images/competition/ranking/ranking_title.png"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
|
<view class="title-desc">欲穷千里目,更上一层楼</view>
|
||||||
|
<image class="cup-image" src="@/static/images/examRanking/cup.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<view class="ranking-body">
|
||||||
|
<view class="list-header list-item">
|
||||||
|
<view class="rank-column">排名</view>
|
||||||
|
<view class="user-column">用户名/所属机构</view>
|
||||||
|
<view class="score-column">最高分</view>
|
||||||
|
<view class="time-column">用时</view>
|
||||||
|
</view>
|
||||||
|
<scroll-view :scroll-y="true" class="scroll-items-view">
|
||||||
|
<view v-for="(item, index) in userList" :class="['list-item', 'item-' + (index + 1)]">
|
||||||
|
<view class="rank-column">
|
||||||
|
{{ item.ranking }}
|
||||||
|
</view>
|
||||||
|
<view class="user-column">
|
||||||
|
<view class="avatar-box">
|
||||||
|
<image-preview
|
||||||
|
v-if="item.ossAddr"
|
||||||
|
class="avatar-image"
|
||||||
|
:src="item.ossAddr"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image-preview>
|
||||||
|
<image v-else class="avatar-image" :src="defaultAvatarSrc"></image>
|
||||||
|
</view>
|
||||||
|
<view class="user-name">{{ item.userName }}</view>
|
||||||
|
<view class="user-org">{{ item.orgName }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="score-column">{{ item.examGrade }}</view>
|
||||||
|
<view class="time-column">{{ item.time ?? 0 }}s</view>
|
||||||
|
</view>
|
||||||
|
<list-no-data v-if="userList.length == 0">暂无数据</list-no-data>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<view class="ranking-self">
|
||||||
|
<view class="list-header list-item">
|
||||||
|
<view class="rank-column">我的排名</view>
|
||||||
|
</view>
|
||||||
|
<view class="list-item item-me">
|
||||||
|
<view class="rank-column">
|
||||||
|
{{ userRankObj.ranking }}
|
||||||
|
</view>
|
||||||
|
<view class="user-column">
|
||||||
|
<view class="avatar-box">
|
||||||
|
<image-preview
|
||||||
|
v-if="userRankObj.ossAddr"
|
||||||
|
class="avatar-image"
|
||||||
|
:src="userRankObj.ossAddr"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image-preview>
|
||||||
|
<image class="avatar-image" v-else :src="defaultAvatarSrc"></image>
|
||||||
|
</view>
|
||||||
|
<view class="user-name">{{ userRankObj.userName }}</view>
|
||||||
|
<view class="user-org">{{ userRankObj.orgName }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="score-column">{{ userRankObj.examGrade }}</view>
|
||||||
|
<view class="time-column">{{ userRankObj.time }}s</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {queryTraCompetitionRankingList} from '@/api/competition.js';
|
||||||
|
import {defaultAvatar} from '@/enum.js';
|
||||||
|
import common from '@/common/common';
|
||||||
|
import {onLoad} from '@dcloudio/uni-app';
|
||||||
|
import {formatSecondsToMS} from './js/tool';
|
||||||
|
import {ref} from 'vue';
|
||||||
|
|
||||||
|
const papersId = ref('');
|
||||||
|
const orgId = ref('');
|
||||||
|
const userList = ref([]);
|
||||||
|
const userRankObj = ref({});
|
||||||
|
onLoad((e) => {
|
||||||
|
papersId.value = e.papersId;
|
||||||
|
orgId.value = e.orgId;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
const getList = () => {
|
||||||
|
queryTraCompetitionRankingList({
|
||||||
|
papersId: papersId.value,
|
||||||
|
orgId: orgId.value
|
||||||
|
}).then((res) => {
|
||||||
|
userList.value = res.body.rankingListVos || [];
|
||||||
|
userRankObj.value = res.body;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
$top-height: var(--status-bar-height);
|
||||||
|
|
||||||
|
.exam-ranking {
|
||||||
|
position: relative;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-top: $top-height;
|
||||||
|
|
||||||
|
// background:url(@/static/images/examRanking/bg.png) no-repeat top center;
|
||||||
|
.bg-box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 412rpx;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranking-box {
|
||||||
|
height: calc(100% - $top-height);
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: $top-height;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-div {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 70rpx;
|
||||||
|
|
||||||
|
.back_div {
|
||||||
|
margin-right: 10rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 25rpx;
|
||||||
|
top: 0;
|
||||||
|
padding: 15rpx;
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #000;
|
||||||
|
border-left: 4rpx solid #000;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-view {
|
||||||
|
height: 180rpx;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 79rpx;
|
||||||
|
padding-top: 20rpx;
|
||||||
|
|
||||||
|
.cup-image {
|
||||||
|
position: absolute;
|
||||||
|
right: 90rpx;
|
||||||
|
bottom: -5rpx;
|
||||||
|
width: 178rpx;
|
||||||
|
height: 159rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-desc {
|
||||||
|
line-height: 34rpx;
|
||||||
|
font-size: 25rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-top: -6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-image {
|
||||||
|
width: 354rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
margin-left: -20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranking-body {
|
||||||
|
height: calc(100% - 170rpx - 180rpx - 70rpx);
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 31rpx 31rpx 0 0;
|
||||||
|
padding-top: 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
.scroll-items-view {
|
||||||
|
height: calc(100% - 54rpx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
height: 108rpx;
|
||||||
|
border-bottom: 2rpx solid #efefef;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.list-header {
|
||||||
|
height: 54rpx;
|
||||||
|
line-height: 54rpx;
|
||||||
|
color: #999;
|
||||||
|
font-size: 25rpx;
|
||||||
|
border-bottom: 0;
|
||||||
|
|
||||||
|
.rank-column {
|
||||||
|
height: 54rpx;
|
||||||
|
line-height: 54rpx;
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 25rpx;
|
||||||
|
font-style: initial;
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-column {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-column {
|
||||||
|
line-height: 54rpx;
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 25rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-column {
|
||||||
|
line-height: 54rpx;
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 25rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.item-1 {
|
||||||
|
border-bottom: 0;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
background: linear-gradient(90deg, #fbf9f5 0%, #fffffd 100%);
|
||||||
|
|
||||||
|
.rank-column {
|
||||||
|
color: #ffffff00;
|
||||||
|
background: url(@/static/images/examRanking/no-1.png) no-repeat;
|
||||||
|
background-position: 40rpx center;
|
||||||
|
background-size: 44rpx 66rpx;
|
||||||
|
text-indent: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.item-2 {
|
||||||
|
border-bottom: 0;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
background: linear-gradient(90deg, #f4f8f9 0%, #f7fbfe 100%);
|
||||||
|
|
||||||
|
.rank-column {
|
||||||
|
color: #ffffff00;
|
||||||
|
background: url(@/static/images/examRanking/no-2.png) no-repeat;
|
||||||
|
background-position: 40rpx center;
|
||||||
|
background-size: 44rpx 66rpx;
|
||||||
|
text-indent: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.item-3 {
|
||||||
|
border-bottom: 0;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
background: linear-gradient(90deg, #faf6f5 0%, #fcfbfc 100%);
|
||||||
|
|
||||||
|
.rank-column {
|
||||||
|
color: #ffffff00;
|
||||||
|
background: url(@/static/images/examRanking/no-3.png) no-repeat;
|
||||||
|
background-position: 40rpx center;
|
||||||
|
background-size: 44rpx 66rpx;
|
||||||
|
text-indent: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.item-me {
|
||||||
|
border-bottom: 0;
|
||||||
|
|
||||||
|
.rank-column {
|
||||||
|
color: #06f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-column {
|
||||||
|
width: 170rpx;
|
||||||
|
padding-left: 40rpx;
|
||||||
|
float: left;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 92rpx;
|
||||||
|
height: 108rpx;
|
||||||
|
color: #333;
|
||||||
|
font-size: 38rpx;
|
||||||
|
font-style: italic;
|
||||||
|
text-indent: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-column {
|
||||||
|
width: 300rpx;
|
||||||
|
float: left;
|
||||||
|
padding: 15rpx 0;
|
||||||
|
|
||||||
|
.avatar-box {
|
||||||
|
width: 77rpx;
|
||||||
|
height: 77rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
float: left;
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
.avatar-image {
|
||||||
|
width: 77rpx;
|
||||||
|
height: 77rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
float: left;
|
||||||
|
width: calc(100% - 77rpx);
|
||||||
|
padding-left: 18rpx;
|
||||||
|
padding-right: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 40rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
font-size: 29rpx;
|
||||||
|
color: #000;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-org {
|
||||||
|
float: left;
|
||||||
|
width: calc(100% - 77rpx);
|
||||||
|
padding-left: 18rpx;
|
||||||
|
padding-right: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 34rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
font-size: 25rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-column {
|
||||||
|
width: 126rpx;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 108rpx;
|
||||||
|
color: #333;
|
||||||
|
font-size: 31rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-column {
|
||||||
|
width: 100rpx;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 108rpx;
|
||||||
|
color: #333;
|
||||||
|
font-size: 31rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranking-self {
|
||||||
|
height: 170rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #f5f9ff;
|
||||||
|
padding-top: 4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,586 @@
|
|||||||
|
<template>
|
||||||
|
<view class="main_div max_page">
|
||||||
|
<!-- 顶部一些按钮 -->
|
||||||
|
<view class="top-button-div">
|
||||||
|
<view class="back_div" @click="common.navigateBack()">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="show-main-div" :class="action">
|
||||||
|
<!-- 伸展出的吉祥物 -->
|
||||||
|
<view class="result-container-div" :class="{ victory: jieguo === 'Y' }">
|
||||||
|
<image class="img" src="@/static/images/competition/result_shengli.png"></image>
|
||||||
|
</view>
|
||||||
|
<view class="result-container-div" :class="{ defeat: jieguo === 'N' }">
|
||||||
|
<image class="img defeat" src="@/static/images/competition/result_shibai.png"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="mascot-div">
|
||||||
|
<image class="img" src="@/static/images/competition/result_loading_mascot.png"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="mascot-msg-div">
|
||||||
|
<image class="img" src="@/static/images/competition/result_loading_msg.png"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="bg-div">
|
||||||
|
<!-- 下方的pk结算信息 -->
|
||||||
|
<view class="pk-msg-div">
|
||||||
|
<view class="win-icon" :class="jieguo">
|
||||||
|
<image class="img_100" src="@/static/images/competition/result_huosheng.png"></image>
|
||||||
|
</view>
|
||||||
|
<view class="pk-msg-left-div">
|
||||||
|
<view class="avatar-div">
|
||||||
|
<cached-avatar v-if="pkData.isAnony === 'N'" class="img"></cached-avatar>
|
||||||
|
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="name-div">{{ pkData.userName }}</view>
|
||||||
|
<view class="title">正确/总题数</view>
|
||||||
|
<view class="topic-div number">
|
||||||
|
<text class="loadingNoText font-size-54">{{ pkData.correctNub }}</text>
|
||||||
|
<text class="loadingNoText">/{{ pkData.qnsNub }}</text>
|
||||||
|
<text class="loadingText">结算中</text>
|
||||||
|
</view>
|
||||||
|
<view class="title">总分</view>
|
||||||
|
<view class="score-div number">
|
||||||
|
<text class="font-size-54 loadingNoText">{{ pkData.totalScore }}</text>
|
||||||
|
<text class="loadingText">结算中</text>
|
||||||
|
</view>
|
||||||
|
<view class="title">用时</view>
|
||||||
|
<view class="time-div number">
|
||||||
|
<text class="loadingNoText">{{ formatSecondsToMS(pkData.timeTaken) }}</text>
|
||||||
|
<text class="loadingText">结算中</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pk-msg-right-div">
|
||||||
|
<view class="avatar-div">
|
||||||
|
<image-preview v-if="pkData.isAnonyPk === 'N'" class="img" :src="pkData.imgPk"></image-preview>
|
||||||
|
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="name-div">{{ pkData.userNamePk }}</view>
|
||||||
|
<view class="title">正确/总题数</view>
|
||||||
|
<view class="topic-div number">
|
||||||
|
<text class="loadingNoText font-size-54">{{ pkData.correctNubPk }}</text>
|
||||||
|
<text class="loadingNoText">/{{ pkData.qnsNubPk }}</text>
|
||||||
|
<text class="loadingText">结算中</text>
|
||||||
|
</view>
|
||||||
|
<view class="title">总分</view>
|
||||||
|
<view class="score-div number">
|
||||||
|
<text class="font-size-54 loadingNoText">{{ pkData.totalScorePk }}</text>
|
||||||
|
<text class="loadingText">结算中</text>
|
||||||
|
</view>
|
||||||
|
<view class="title">用时</view>
|
||||||
|
<view class="time-div number">
|
||||||
|
<text class="loadingNoText">{{ formatSecondsToMS(pkData.timeTakenPk) }}</text>
|
||||||
|
<text class="loadingText">结算中</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 查看排行榜按钮 -->
|
||||||
|
<view class="ranking-list-div" @click="buttonClick('toRanking')">查看排行榜</view>
|
||||||
|
<!-- 下方的两个按钮 -->
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="bottom-button-div">
|
||||||
|
<uv-button class="button-1" text="退出挑战" shape="circle" @click="buttonClick('exit')"></uv-button>
|
||||||
|
<uv-button class="button-2" text="继续挑战" shape="circle" @click="buttonClick('continue')"></uv-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, reactive, computed, nextTick } from 'vue';
|
||||||
|
import common, { getUserInfo } from '@/common/common';
|
||||||
|
import { MatchTimeGenerator, formatTime } from './js/matching';
|
||||||
|
import { queryCompetitionAnswerResult } from '@/api/competition';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import { defaultAnonymousAvatar } from '@/enum';
|
||||||
|
import { pkAnonymousClose, pkAnonymousOpen, pkRankingList, pkRules } from '@/common/imgSvg';
|
||||||
|
import { queryTraUserAnonyByUserId, updateTraUserAnony } from '@/api/user';
|
||||||
|
import { formatSecondsToMS } from './js/tool';
|
||||||
|
|
||||||
|
const action = ref('');
|
||||||
|
const pkData = reactive({
|
||||||
|
// 公共的
|
||||||
|
execId: '',
|
||||||
|
papersId: '',
|
||||||
|
orgId: '',
|
||||||
|
answerResult: '', // 答题结果 Y代表我赢,N代表我输
|
||||||
|
timeDifference: 30, // 时差 int 单位 s
|
||||||
|
|
||||||
|
// 自己的
|
||||||
|
userName: '',
|
||||||
|
isAnony: 'Y', // 匿名 String
|
||||||
|
correctNub: 0, // 正确数 int
|
||||||
|
qnsNub: 0, // 总数 int
|
||||||
|
timeTaken: 0, // 用时 int
|
||||||
|
totalScore: 0, // 我方总分 int
|
||||||
|
|
||||||
|
// 对方的
|
||||||
|
userIdPk: '', // 用户Id String
|
||||||
|
userNamePk: '', // 用户姓名 String
|
||||||
|
imgPk: '', // 对方头像 String
|
||||||
|
isAnonyPk: 'Y', // 匿名 String
|
||||||
|
correctNubPk: 0, // 正确数 int
|
||||||
|
qnsNubPk: 0, // 总数 int
|
||||||
|
timeTakenPk: 0, // 用时 int
|
||||||
|
totalScorePk: 0 // 对方总分 int
|
||||||
|
});
|
||||||
|
const jieguo = computed(() => pkData.answerResult);
|
||||||
|
const buttonClick = (type: String) => {
|
||||||
|
if (type === 'exit') {
|
||||||
|
common.navigateBack(2);
|
||||||
|
} else if (type === 'continue') {
|
||||||
|
common.navigateBack();
|
||||||
|
} else if (type === 'toRanking') {
|
||||||
|
common.navigateTo(`/pages/competition/ranking?papersId=${pkData.papersId}&orgId=${pkData.orgId}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
pkData.execId = e.execId || '';
|
||||||
|
pkData.papersId = e.papersId || '';
|
||||||
|
pkData.orgId = e.orgId || '';
|
||||||
|
const pkDataInit = common.getPageCache('competition_pk_to_resulf');
|
||||||
|
Object.assign(pkData, {
|
||||||
|
userName: pkDataInit.userName,
|
||||||
|
isAnony: pkDataInit.isAnony
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
action.value = 'loading';
|
||||||
|
setTimeout(() => {
|
||||||
|
queryCompetitionAnswerResult({ execId: pkData.execId }).then(({ body }) => {
|
||||||
|
const userResult = body.userResult;
|
||||||
|
pkData.answerResult = body.answerResult; // 答题结果 Y代表我赢,N代表我输
|
||||||
|
pkData.timeDifference = body.timeDifference; // 时差 int 单位 s
|
||||||
|
Object.assign(pkData, {
|
||||||
|
// 自己的
|
||||||
|
isAnony: userResult.isAnony, // 匿名 String
|
||||||
|
correctNub: userResult.correctNub, // 正确数 int
|
||||||
|
qnsNub: userResult.qnsNub, // 总数 int
|
||||||
|
timeTaken: userResult.timeTaken, // 用时 int
|
||||||
|
totalScore: userResult.totalScore || 0, // 我方总分
|
||||||
|
// 对方的
|
||||||
|
userIdPk: userResult.userIdPk, // 用户Id String
|
||||||
|
userNamePk: userResult.userNamePk, // 用户姓名 String
|
||||||
|
imgPk: userResult.imgPk, // 用户姓名 String
|
||||||
|
pkIsAnony: userResult.pkIsAnony, // 匿名 String
|
||||||
|
correctNubPk: userResult.correctNubPk, // 正确数 int
|
||||||
|
qnsNubPk: userResult.qnsNubPk || 0, // 总数 int
|
||||||
|
timeTakenPk: userResult.timeTakenPk || 0, // 用时 int
|
||||||
|
totalScorePk: userResult.totalScorePk || 0 // 对方总分
|
||||||
|
});
|
||||||
|
nextTick(() => {
|
||||||
|
action.value = 'result';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.pk-msg-div {
|
||||||
|
width: 570rpx;
|
||||||
|
height: 480rpx;
|
||||||
|
background-image: url('@/static/images/competition/result_pk_bg.png');
|
||||||
|
background-size: 100% auto; /* 宽度填满,高度自适应 */
|
||||||
|
background-position: center top; /* 图片顶部居中显示 */
|
||||||
|
background-repeat: no-repeat; /* 不重复平铺 */
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
font-size: 26rpx;
|
||||||
|
.pk-msg-left-div > .avatar-div {
|
||||||
|
border: 3rpx solid #2b7af1;
|
||||||
|
}
|
||||||
|
.pk-msg-right-div > .avatar-div {
|
||||||
|
border: 3rpx solid #f63c13;
|
||||||
|
}
|
||||||
|
.avatar-div {
|
||||||
|
width: 78rpx;
|
||||||
|
height: 78rpx;
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.name-div {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #000000;
|
||||||
|
height: 42rpx;
|
||||||
|
}
|
||||||
|
.topic-div {
|
||||||
|
font-family: Arial, Arial;
|
||||||
|
font-style: italic;
|
||||||
|
height: 62rpx;
|
||||||
|
line-height: 62rpx;
|
||||||
|
}
|
||||||
|
.score-div {
|
||||||
|
font-family: Arial, Arial;
|
||||||
|
height: 62rpx;
|
||||||
|
line-height: 62rpx;
|
||||||
|
}
|
||||||
|
.win-icon {
|
||||||
|
width: 140rpx;
|
||||||
|
height: 130rpx;
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
&.Y {
|
||||||
|
display: block;
|
||||||
|
left: -20rpx;
|
||||||
|
top: -46rpx;
|
||||||
|
}
|
||||||
|
&.N {
|
||||||
|
display: block;
|
||||||
|
right: -30rpx;
|
||||||
|
top: -46rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pk-msg-left-div,
|
||||||
|
.pk-msg-right-div {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
.title {
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pk-msg-left-div {
|
||||||
|
.title {
|
||||||
|
color: #6a8db1;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
color: #2b7af1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pk-msg-right-div {
|
||||||
|
.title {
|
||||||
|
color: #b16f6a;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
color: #f63c13;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.font-size-54 {
|
||||||
|
font-size: 54rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-main-div {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 500rpx;
|
||||||
|
background-color: #fff; /* 关键:背景图未覆盖的区域填充白色 */
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 31px 31px 0px 0px;
|
||||||
|
@keyframes victoryEnter {
|
||||||
|
0% {
|
||||||
|
transform: translateY(50rpx) scale(0.8);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
30% {
|
||||||
|
transform: translateY(-10rpx) scale(1.05);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(0) scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes defeatEnter {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-50rpx) scale(1.2);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
transform: translateY(10rpx) scale(0.95);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(0) scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes defeatRotateSway {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg); // 初始角度
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
transform: rotate(-2deg); // 向左微转2度
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: rotate(2deg); // 向右微转2度
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(0deg); // 回到初始角度
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes victoryFloat {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
// transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10rpx);
|
||||||
|
// transform: translateY(-10rpx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.loadingText {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
// loading 状态样式(保持不变)
|
||||||
|
&.loading {
|
||||||
|
.mascot-div {
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
.mascot-msg-div {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.topic-div,
|
||||||
|
.score-div,
|
||||||
|
.time-div {
|
||||||
|
position: relative;
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 4rpx;
|
||||||
|
left: calc(100% + 3rpx);
|
||||||
|
animation: loading 2.5s infinite;
|
||||||
|
}
|
||||||
|
@keyframes loading {
|
||||||
|
0% {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
content: '.';
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
content: '..';
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
content: '...';
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.loadingText {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.loadingNoText {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当 action=result 时,触发结果动画
|
||||||
|
&.result {
|
||||||
|
// 胜利状态:入场 + 浮动 + 闪光
|
||||||
|
.result-container-div.victory {
|
||||||
|
animation: victoryEnter 0.8s cubic-bezier(0.22, 1, 0.36, 1) forwards,
|
||||||
|
victoryFloat 2s ease-in-out infinite 0.8s;
|
||||||
|
}
|
||||||
|
// 失败状态:入场 + 抖动
|
||||||
|
.result-container-div.defeat {
|
||||||
|
// defeatShake 1s ease-in-out infinite 0.6s
|
||||||
|
animation: defeatEnter 0.6s ease-out forwards, defeatRotateSway 1s ease-in-out 0.6s 1; // 入场后开始晃动,2秒结束,仅1次
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结果容器基础样式
|
||||||
|
.result-container-div {
|
||||||
|
position: absolute;
|
||||||
|
top: -300rpx; // 初始位置(可根据需求调整)
|
||||||
|
z-index: 20;
|
||||||
|
opacity: 0; // 初始隐藏,动画中变为1
|
||||||
|
.img {
|
||||||
|
width: 512rpx;
|
||||||
|
height: 408rpx;
|
||||||
|
display: block; // 避免图片底部间隙
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mascot-div {
|
||||||
|
position: absolute;
|
||||||
|
top: -300rpx;
|
||||||
|
margin-left: 50rpx;
|
||||||
|
transition: top 0.6s ease-out;
|
||||||
|
z-index: 5;
|
||||||
|
left: 100%;
|
||||||
|
transform: translateX(0);
|
||||||
|
transition: left 0.5s ease-out, transform 0.5s ease-out;
|
||||||
|
.img {
|
||||||
|
width: 284rpx;
|
||||||
|
height: 400rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mascot-msg-div {
|
||||||
|
position: absolute;
|
||||||
|
top: -300rpx;
|
||||||
|
transition: top 0.6s ease-out;
|
||||||
|
z-index: 20;
|
||||||
|
margin-top: 240rpx;
|
||||||
|
transition: top 0.6s ease-out, opacity 0.5s ease-out; /* 新增透明度过渡 */
|
||||||
|
z-index: 20;
|
||||||
|
opacity: 0; /* 初始隐藏 */
|
||||||
|
pointer-events: none; /* 隐藏时不响应交互 */
|
||||||
|
.img {
|
||||||
|
width: 326rpx;
|
||||||
|
height: 198rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bg-div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding-top: 140rpx;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
// width: 100%;
|
||||||
|
// height: 100%;
|
||||||
|
}
|
||||||
|
z-index: 10;
|
||||||
|
background: linear-gradient(to bottom, transparent 0%, #ffffff 200rpx, #ffffff 100%),
|
||||||
|
linear-gradient(to right, #bfebff 0%, #fef1de 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranking-list-div {
|
||||||
|
margin-top: 48rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #0066ff;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
.bottom-button-div {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 50rpx;
|
||||||
|
margin-bottom: 60rpx;
|
||||||
|
:deep(.uv-button) {
|
||||||
|
/* 以下是所有 .uv-button 共用的公共样式 */
|
||||||
|
margin: 16rpx;
|
||||||
|
width: 246rpx;
|
||||||
|
height: 92rpx;
|
||||||
|
border-radius: 58px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
.uv-button__text {
|
||||||
|
font-size: 30rpx !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-1 :deep(.uv-button) {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.button-2 :deep(.uv-button) {
|
||||||
|
background: linear-gradient(0deg, #009fff 0%, #0066ff 100%) !important;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-button-div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 70rpx;
|
||||||
|
padding-top: 10rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
position: relative;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
.top-icon-div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
.img1,
|
||||||
|
.img2,
|
||||||
|
.img3 {
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
.img1,
|
||||||
|
.img3 {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
.img2 {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.back_div {
|
||||||
|
position: absolute;
|
||||||
|
left: 26rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #ffffff;
|
||||||
|
border-left: 4rpx solid #ffffff;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 容器样式 */
|
||||||
|
.max_page {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-image: url('@/static/images/competition/bg.png');
|
||||||
|
background-color: #000; /* 图片高度不足时的背景色 */
|
||||||
|
background-size: 100% auto; /* 宽度填满,高度自适应 */
|
||||||
|
background-position: center top; /* 图片顶部居中显示 */
|
||||||
|
background-repeat: no-repeat; /* 不重复平铺 */
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
.match-time-div {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 34rpx;
|
||||||
|
font-style: normal;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
transition: opacity 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
opacity: 1; /* 初始显示状态 */
|
||||||
|
transform: translateY(0); /* 初始位置 */
|
||||||
|
&.hidden {
|
||||||
|
opacity: 0; /* 完全透明 */
|
||||||
|
transform: translateY(40rpx); /* 轻微上移增强淡出效果 */
|
||||||
|
pointer-events: none; /* 隐藏后不响应事件 */
|
||||||
|
height: 0; /* 可选:完全隐藏高度 */
|
||||||
|
overflow: hidden; /* 可选:隐藏溢出内容 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.match-msg-div {
|
||||||
|
width: 100%;
|
||||||
|
height: 8vh;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 72rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
transition: opacity 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
opacity: 1; /* 初始显示状态 */
|
||||||
|
transform: translateY(0); /* 初始位置 */
|
||||||
|
&.hidden {
|
||||||
|
opacity: 0; /* 完全透明 */
|
||||||
|
transform: translateY(-40rpx); /* 轻微上移增强淡出效果 */
|
||||||
|
pointer-events: none; /* 隐藏后不响应事件 */
|
||||||
|
overflow: hidden; /* 可选:隐藏溢出内容 */
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
.select-div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
transition: opacity 0.3s ease-out;
|
||||||
|
opacity: 1; /* 初始显示状态 */
|
||||||
|
&.hidden {
|
||||||
|
opacity: 0; /* 完全透明 */
|
||||||
|
pointer-events: none; /* 隐藏后不响应事件 */
|
||||||
|
height: 0; /* 可选:完全隐藏高度 */
|
||||||
|
overflow: hidden; /* 可选:隐藏溢出内容 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.select-institution-msg-div {
|
||||||
|
width: calc(100% - 228rpx);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 32rpx;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
opacity: 0.8;
|
||||||
|
padding-top: 18rpx;
|
||||||
|
padding-bottom: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-institution-div {
|
||||||
|
width: calc(100% - 228rpx);
|
||||||
|
height: 86rpx;
|
||||||
|
border: 1rpx solid transparent;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 86rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
z-index: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 60rpx 0 20rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
/* 强制不换行 */
|
||||||
|
overflow: hidden;
|
||||||
|
/* 超出部分隐藏 */
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
.img {
|
||||||
|
// background-color: red;
|
||||||
|
padding: 16rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
right: 10rpx;
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 边框高光效果 */
|
||||||
|
.select-institution-div::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border: 4rpx solid transparent;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.8), transparent) border-box;
|
||||||
|
-webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
|
||||||
|
-webkit-mask-composite: xor;
|
||||||
|
mask-composite: exclude;
|
||||||
|
|
||||||
|
/* 初始位置在左侧外部 */
|
||||||
|
background-size: 200% 100%;
|
||||||
|
|
||||||
|
/* 动画:高光从左到右流动 */
|
||||||
|
animation: highlightFlow 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 定义高光流动动画 */
|
||||||
|
@keyframes highlightFlow {
|
||||||
|
0% {
|
||||||
|
background-position: -100% 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 100% 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 环绕版本带呼吸效果 */
|
||||||
|
.select-institution-div.full-flow::before {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent,
|
||||||
|
rgba(255, 255, 255, 0.8),
|
||||||
|
transparent,
|
||||||
|
transparent,
|
||||||
|
transparent,
|
||||||
|
transparent,
|
||||||
|
transparent,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
background-size: 300% 300%;
|
||||||
|
animation: fullBorderFlow 2s linear infinite, breathing 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fullBorderFlow {
|
||||||
|
0% {
|
||||||
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
background-position: 100% 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-position: 100% 100%;
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
background-position: 0 100%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-div {
|
||||||
|
width: calc(100% - 80rpx);
|
||||||
|
margin: 40rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 44rpx;
|
||||||
|
text-shadow: 0px 0px 19px rgba(0, 0, 0, 0.11);
|
||||||
|
text-align: center;
|
||||||
|
font-family: none;
|
||||||
|
min-height: 88rpx;
|
||||||
|
margin: calc(var(--status-bar-height) + 40rpx);
|
||||||
|
|
||||||
|
/* 添加过渡动画 */
|
||||||
|
transition: opacity 0.3s ease-out, transform 0.3s ease-out;
|
||||||
|
opacity: 1; /* 初始显示状态 */
|
||||||
|
transform: translateY(0); /* 初始位置 */
|
||||||
|
&.hidden {
|
||||||
|
opacity: 0; /* 完全透明 */
|
||||||
|
transform: translateY(-10rpx); /* 轻微上移增强淡出效果 */
|
||||||
|
pointer-events: none; /* 隐藏后不响应事件 */
|
||||||
|
height: 0; /* 可选:完全隐藏高度 */
|
||||||
|
overflow: hidden; /* 可选:隐藏溢出内容 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-div {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
.avatar-img-div {
|
||||||
|
width: 204rpx;
|
||||||
|
height: 204rpx;
|
||||||
|
border: 4rpx solid #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
/* 修复伪元素显示问题 */
|
||||||
|
&.hidden::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
/* 使用固定尺寸确保计算正确 */
|
||||||
|
width: 230rpx;
|
||||||
|
height: 230rpx;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
/* 确保在z轴上处于正确层级 */
|
||||||
|
z-index: 1;
|
||||||
|
/* 背景图设置 */
|
||||||
|
background-image: url('@/static/images/competition/avatar_surround.png');
|
||||||
|
background-size: contain; /* 改用contain确保完整显示 */
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
/* 旋转动画 */
|
||||||
|
animation: variableRotate 2s linear infinite;
|
||||||
|
}
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes variableRotate {
|
||||||
|
0% {
|
||||||
|
transform: translate(-50%, -50%) rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-50%, -50%) rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-name-div {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 46rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 64rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
padding-top: 16rpx;
|
||||||
|
padding-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.button-div {
|
||||||
|
.start_button {
|
||||||
|
width: 569rpx;
|
||||||
|
height: 92rpx;
|
||||||
|
background: linear-gradient(#009fff 0%, #0066ff 100%);
|
||||||
|
border-radius: 58rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 92rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 250rpx;
|
||||||
|
}
|
||||||
|
.cancel_button {
|
||||||
|
width: 246rpx;
|
||||||
|
height: 92rpx;
|
||||||
|
border-radius: 58rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 92rpx;
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
background: linear-gradient(rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.5) 100%);
|
||||||
|
border-radius: 58rpx;
|
||||||
|
border: 2rpx solid #dbdbdb;
|
||||||
|
margin-bottom: 250rpx; /* 向上移动50rpx,可根据需要调整 */
|
||||||
|
}
|
||||||
|
.button-transition {
|
||||||
|
/* 添加过渡动画属性 */
|
||||||
|
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
/* 确保边框变化也有过渡效果 */
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-button-div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 70rpx;
|
||||||
|
padding-top: calc(16rpx + var(--status-bar-height));
|
||||||
|
font-weight: 500;
|
||||||
|
position: relative;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
.top-icon-div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: left;
|
||||||
|
.img1,
|
||||||
|
.img3 {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
.img2 {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.back_div {
|
||||||
|
position: absolute;
|
||||||
|
left: 26rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
top: calc(10rpx + var(--status-bar-height));
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #ffffff;
|
||||||
|
border-left: 4rpx solid #ffffff;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup {
|
||||||
|
z-index: 1800;
|
||||||
|
padding: 0 38rpx;
|
||||||
|
|
||||||
|
.sheet_popup_div {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 10rpx 34rpx;
|
||||||
|
border-radius: 34rpx 34rpx 0px 0px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.title_div {
|
||||||
|
width: 100%;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
font-family: PingFangSC;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #000000;
|
||||||
|
font-style: normal;
|
||||||
|
border-bottom: 2rpx solid #efefef;
|
||||||
|
}
|
||||||
|
.note_div {
|
||||||
|
padding: 20rpx 0 80rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
// 坠落动画配置变量 - 方便调整效果
|
||||||
|
$fall-duration: 0.26s; // 动画总时长
|
||||||
|
$initial-scale: 2.8; // 初始大小倍数
|
||||||
|
$impact-scale: 0.9; // 撞击瞬间的压缩倍数
|
||||||
|
$final-scale: 1; // 最终稳定大小
|
||||||
|
$primary-color: #ffe271; // 文字颜色
|
||||||
|
|
||||||
|
.matching-success-text {
|
||||||
|
margin-top: 10%;
|
||||||
|
padding-left: 1rem;
|
||||||
|
// 基础样式
|
||||||
|
font-size: 74rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffe271;
|
||||||
|
text-align: center;
|
||||||
|
// 动画属性
|
||||||
|
animation: fallDown $fall-duration ease-out forwards;
|
||||||
|
|
||||||
|
// 坠落动画关键帧
|
||||||
|
@keyframes fallDown {
|
||||||
|
0% {
|
||||||
|
// 初始状态:高处坠落的起点
|
||||||
|
transform: scale($initial-scale);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
// 撞击瞬间:略微压缩,增强冲击力
|
||||||
|
transform: scale($impact-scale);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
// 稳定状态:恢复正常大小
|
||||||
|
transform: scale($final-scale);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增强版:带震动效果的撞击(可选)
|
||||||
|
&.with-vibration {
|
||||||
|
animation: fallWithVibration $fall-duration cubic-bezier(0.21, 0.98, 0.6, 0.99) forwards;
|
||||||
|
|
||||||
|
@keyframes fallWithVibration {
|
||||||
|
0% {
|
||||||
|
transform: scale($initial-scale) rotate(0deg);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
70% {
|
||||||
|
transform: scale($impact-scale) rotate(2deg);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
85% {
|
||||||
|
transform: scale($final-scale * 1.05) rotate(-1deg);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: scale($final-scale) rotate(0deg);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可通过修改变量快速调整效果
|
||||||
|
// 示例:更重的坠落效果
|
||||||
|
.heavy-impact {
|
||||||
|
$fall-duration: 0.3s;
|
||||||
|
$initial-scale: 2.5;
|
||||||
|
$impact-scale: 0.8;
|
||||||
|
|
||||||
|
animation: fallDown $fall-duration ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matching-success-msg {
|
||||||
|
margin-top: 20%;
|
||||||
|
font-family: Alibaba-PuHuiTi, Alibaba-PuHuiTi;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 74rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**匹配成功样式*/
|
||||||
|
.matching-success-animation {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 540rpx;
|
||||||
|
position: relative;
|
||||||
|
// overflow: hidden;
|
||||||
|
.left {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(59vw);
|
||||||
|
left: -10rpx;
|
||||||
|
top: 0%;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
position: absolute;
|
||||||
|
right: -10rpx;
|
||||||
|
top: 18vw;
|
||||||
|
width: calc(59vw);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
// 左侧元素回弹动画
|
||||||
|
.animate-left {
|
||||||
|
animation: leftCollision 0.24s ease-out forwards;
|
||||||
|
}
|
||||||
|
@keyframes leftCollision {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
} // 初始位置
|
||||||
|
90% {
|
||||||
|
transform: translateX(10rpx);
|
||||||
|
} // 超过目标位置10rpx(冲刺)
|
||||||
|
100% {
|
||||||
|
transform: translateX(0);
|
||||||
|
} // 回到目标位置(回弹)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧元素回弹动画
|
||||||
|
.animate-right {
|
||||||
|
animation: rightCollision 0.24s ease-out forwards;
|
||||||
|
}
|
||||||
|
@keyframes rightCollision {
|
||||||
|
0% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
} // 初始位置
|
||||||
|
90% {
|
||||||
|
transform: translateX(-10rpx);
|
||||||
|
} // 超过目标位置10rpx(冲刺)
|
||||||
|
100% {
|
||||||
|
transform: translateX(0);
|
||||||
|
} // 回到目标位置(回弹)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上面的双方头像
|
||||||
|
.information-div-left,
|
||||||
|
.information-div-right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.avatar-img-div {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border: 4rpx solid #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
margin-bottom: 100rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.org {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 160rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.information-div-left {
|
||||||
|
position: absolute;
|
||||||
|
top: 0%;
|
||||||
|
left: 0%;
|
||||||
|
transform: translate(24%, -20%);
|
||||||
|
}
|
||||||
|
.information-div-right {
|
||||||
|
position: absolute;
|
||||||
|
right: 0%;
|
||||||
|
top: 0%;
|
||||||
|
transform: translate(-24%, -20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
<!-- 3. 最后显示默认标题 -->
|
<!-- 3. 最后显示默认标题 -->
|
||||||
<template v-else>{{ title }}</template>
|
<template v-else>{{ title }}</template>
|
||||||
</view>
|
</view>
|
||||||
|
<view v-if="msg" class="msg_div">
|
||||||
|
{{ msg }}
|
||||||
|
</view>
|
||||||
<view class="button_div">
|
<view class="button_div">
|
||||||
<view class="button_item" v-for="item in buttonList" :style="item?.style" @click="click_button(item)">
|
<view class="button_item" v-for="item in buttonList" :style="item?.style" @click="click_button(item)">
|
||||||
{{ item?.name || '' }}
|
{{ item?.name || '' }}
|
||||||
@@ -25,12 +28,14 @@
|
|||||||
dialogConfiguration: {
|
dialogConfiguration: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: false
|
required: false
|
||||||
}
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['button_click']);
|
const emit = defineEmits(['button_click']);
|
||||||
|
|
||||||
const title = ref('');
|
const title = ref('');
|
||||||
const html = ref('');
|
const html = ref('');
|
||||||
|
const msg = ref('');
|
||||||
const buttonList = ref([]);
|
const buttonList = ref([]);
|
||||||
const PopupRef = ref(null);
|
const PopupRef = ref(null);
|
||||||
// 点击按钮
|
// 点击按钮
|
||||||
@@ -41,9 +46,10 @@
|
|||||||
const close = () => PopupRef.value?.close();
|
const close = () => PopupRef.value?.close();
|
||||||
const open = (dialogConfiguration) => {
|
const open = (dialogConfiguration) => {
|
||||||
// 解构赋值更清晰
|
// 解构赋值更清晰
|
||||||
const { title: t, html: h, buttonList: bl = [] } = dialogConfiguration || props.dialogConfiguration || {};
|
const { title: t, html: h, msg: m, buttonList: bl = [] } = dialogConfiguration || props.dialogConfiguration || {};
|
||||||
title.value = t || '';
|
title.value = t || '';
|
||||||
html.value = h || '';
|
html.value = h || '';
|
||||||
|
msg.value = m || '';
|
||||||
buttonList.value = Array.isArray(bl) ? bl : [];
|
buttonList.value = Array.isArray(bl) ? bl : [];
|
||||||
|
|
||||||
// 确保PopupRef存在再调用open
|
// 确保PopupRef存在再调用open
|
||||||
@@ -62,7 +68,7 @@
|
|||||||
z-index: 1810;
|
z-index: 1810;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.9);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup_div {
|
.popup_div {
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
removeListener();
|
removeListener();
|
||||||
});
|
});
|
||||||
|
|
||||||
const open = (qnsId) => {
|
const open = (qnsId) => {
|
||||||
feedbackInfo.qnsId = qnsId;
|
feedbackInfo.qnsId = qnsId;
|
||||||
openFeedback(true);
|
openFeedback(true);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<view class="talking-cont">
|
<view class="talking-cont">
|
||||||
<MarkdownPreview :mdString="mdText" />
|
<MarkdownPreview :mdString="mdText" />
|
||||||
</view>
|
</view>
|
||||||
<view class="talking-link" v-show="dataInfo.asrTime > 0">
|
<view class="talking-link">
|
||||||
<view class="link-cont-desc">语音转文字的耗时:{{ dataInfo.asrTime }}ms</view>
|
<view class="link-cont-desc">语音转文字的耗时:{{ dataInfo.asrTime }}ms</view>
|
||||||
<!-- <view class="link-cont-desc">请求的文字:{{ dataInfo.reqContent }}</view> -->
|
<!-- <view class="link-cont-desc">请求的文字:{{ dataInfo.reqContent }}</view> -->
|
||||||
<view class="link-cont-desc">请求内容的字符长度:{{ dataInfo.reqContSize }}</view>
|
<view class="link-cont-desc">请求内容的字符长度:{{ dataInfo.reqContSize }}</view>
|
||||||
|
|||||||
@@ -138,7 +138,8 @@
|
|||||||
<image class="icon" src="@/static/images/index/navigation_examination.png"></image>
|
<image class="icon" src="@/static/images/index/navigation_examination.png"></image>
|
||||||
<view class="title">考试中心</view>
|
<view class="title">考试中心</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="item">
|
|
||||||
|
<view class="item" @click="common.navigateTo('/pages/competition/index')">
|
||||||
<image class="icon" src="@/static/images/index/navigation_practice.png"></image>
|
<image class="icon" src="@/static/images/index/navigation_practice.png"></image>
|
||||||
<view class="title">竞赛练习</view>
|
<view class="title">竞赛练习</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<view class="fl1"></view>
|
<view class="fl1"></view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 显示当前选中的徽章 -->
|
<!-- 显示当前选中的徽章 -->
|
||||||
<!-- <view class="dan" @click="changeBadge">
|
<view class="dan" @click="changeBadge">
|
||||||
<view class="dan_img">
|
<view class="dan_img">
|
||||||
<image
|
<image
|
||||||
class="img_100"
|
class="img_100"
|
||||||
@@ -48,18 +48,18 @@
|
|||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="dan_text">{{ badgeList[currentIndex].name }}</view>
|
<view class="dan_text">{{ badgeList[currentIndex].name }}</view>
|
||||||
</view> -->
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 用户学习时间信息 -->
|
<!-- 用户学习时间信息 -->
|
||||||
<view class="study_information">
|
<view class="study_information">
|
||||||
<view class="item">
|
<view class="item" @click="common.navigateTo('/pages/pointsAndRank/points')">
|
||||||
<view class="top">我的积分</view>
|
<view class="top">我的积分</view>
|
||||||
<view class="bottom">
|
<view class="bottom">
|
||||||
<uv-count-to :startVal="0" :endVal="0" :useEasing="true" ref="accmTaskCntRef"></uv-count-to>
|
<uv-count-to :startVal="0" :endVal="0" :useEasing="true" ref="accmTaskCntRef"></uv-count-to>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-interval"></view>
|
<view class="item-interval"></view>
|
||||||
<view class="item">
|
<view class="item" @click="common.navigateTo('/pages/pointsAndRank/rank')">
|
||||||
<view class="top">徽章墙</view>
|
<view class="top">徽章墙</view>
|
||||||
<view class="bottom">
|
<view class="bottom">
|
||||||
<uv-count-to :startVal="0" :endVal="0" :useEasing="true" ref="accmTaskCntRef"></uv-count-to>
|
<uv-count-to :startVal="0" :endVal="0" :useEasing="true" ref="accmTaskCntRef"></uv-count-to>
|
||||||
@@ -101,7 +101,12 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="cell_div">
|
<view class="cell_div">
|
||||||
<uv-cell-group :border="false">
|
<uv-cell-group :border="false">
|
||||||
<uv-cell title="问答演示" v-if="user_info.loginName === 'ADMIN'" :isLink="true" @click="common.navigateTo('/pages/example/dialog')"></uv-cell>
|
<uv-cell
|
||||||
|
title="问答演示"
|
||||||
|
v-if="user_info.loginName === 'ADMIN'"
|
||||||
|
:isLink="true"
|
||||||
|
@click="common.navigateTo('/pages/example/dialog')"
|
||||||
|
></uv-cell>
|
||||||
<uv-cell
|
<uv-cell
|
||||||
title="消息通知"
|
title="消息通知"
|
||||||
:isLink="true"
|
:isLink="true"
|
||||||
|
|||||||
@@ -0,0 +1,265 @@
|
|||||||
|
<template>
|
||||||
|
<z-paging
|
||||||
|
ref="pagingRef"
|
||||||
|
v-model="data_list"
|
||||||
|
@query="queryList"
|
||||||
|
class="scroll_div"
|
||||||
|
empty-view-text="暂无积分记录"
|
||||||
|
paging-class="z-paging-class"
|
||||||
|
>
|
||||||
|
<template #top>
|
||||||
|
<view class="top-main-div">
|
||||||
|
<view class="content">
|
||||||
|
<view class="body-title">
|
||||||
|
<view class="back_div" @click="common.navigateBack()">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
<view>积分明细</view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="my-points">
|
||||||
|
<view class="msg">我的积分</view>
|
||||||
|
<view class="score">
|
||||||
|
<uv-count-to
|
||||||
|
:startVal="startVal"
|
||||||
|
:endVal="endVal"
|
||||||
|
:useEasing="true"
|
||||||
|
ref="countToRef"
|
||||||
|
></uv-count-to>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<view class="scroll-Y">
|
||||||
|
<view class="item_th">
|
||||||
|
<view class="title">事项明细</view>
|
||||||
|
<view class="time">时间</view>
|
||||||
|
<view class="value">积分变化</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" v-for="(item, index) in data_list">
|
||||||
|
<view class="title ellipsis-text">
|
||||||
|
{{ item.mattrDesc }}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
{{ item.ctTime.substr(0, 16) }}
|
||||||
|
</view>
|
||||||
|
<view class="value" :class="Number(item.changeValue) >= 0 ? 'up' : 'down'">
|
||||||
|
{{ item.changeValue }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 竞赛列表
|
||||||
|
import { ref, reactive, watch, onMounted } from 'vue';
|
||||||
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||||
|
import useZpaging from '@/composables/useZpaging.js';
|
||||||
|
import common from '@/common/common';
|
||||||
|
import { queryPointsDetail, queryCurrentStatus } from '@/api/pointsAndRank.js';
|
||||||
|
const startVal = ref(0);
|
||||||
|
const endVal = ref(0);
|
||||||
|
const countToRef = ref(null);
|
||||||
|
const fetchFunction = (params) => {
|
||||||
|
queryCurrentStatus().then(({ body }) => {
|
||||||
|
const { currentPoints } = body;
|
||||||
|
console.log('recurrentPointss', currentPoints);
|
||||||
|
startVal.value = 9999;
|
||||||
|
endVal.value = 99999;
|
||||||
|
stdtTmLenRef.value.start();
|
||||||
|
});
|
||||||
|
return queryPointsDetail({ ...params });
|
||||||
|
};
|
||||||
|
const { pagingRef, queryList, data_list, search } = useZpaging({
|
||||||
|
fetchFunction
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad(() => {});
|
||||||
|
onUnload(() => {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
.z-paging-class {
|
||||||
|
background-color: #e0e3ef;
|
||||||
|
::v-deep .zp-view-super {
|
||||||
|
background-color: #ffffff;
|
||||||
|
margin: 0 24rpx;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 30rpx 30rpx 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.top-main-div {
|
||||||
|
/* 宽度占满父容器 */
|
||||||
|
width: 100%;
|
||||||
|
/* 隐藏超出容器的背景图部分 */
|
||||||
|
overflow: hidden;
|
||||||
|
/* 使用 padding-top 实现 78:35 的宽高比(计算公式:35/78*100% ≈ 44.87%) */
|
||||||
|
padding-top: 44.87%;
|
||||||
|
/* 背景图设置,确保图片覆盖且不重复 */
|
||||||
|
background-image: url('@/static/images/pointsAndRank/bg.png');
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
/* 若盒子内有内容,需用相对定位让内容脱离文档流 */
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: -44rpx;
|
||||||
|
.content {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-points {
|
||||||
|
padding-bottom: 84rpx;
|
||||||
|
padding-left: 46rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
.msg {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score {
|
||||||
|
margin-left: 16rpx;
|
||||||
|
width: 112px;
|
||||||
|
::v-deep .uv-count-num {
|
||||||
|
font-family: DINAlternate, DINAlternate !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
font-size: 77rpx !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
line-height: 77rpx !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item_th {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 4rpx solid #efefef;
|
||||||
|
font-family: PingFangSC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
text-align: left;
|
||||||
|
padding: 32rpx 38rpx 32rpx 26rpx;
|
||||||
|
.title {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.time {
|
||||||
|
min-width: max(150rpx, 42%);
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
text-align: right;
|
||||||
|
min-width: max(80rpx, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
background: #ffffff;
|
||||||
|
border-bottom: 2rpx solid #efefef;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 40rpx 38rpx 40rpx 26rpx;
|
||||||
|
.title {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.time {
|
||||||
|
font-family: ArialMT;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #000000;
|
||||||
|
text-align: left;
|
||||||
|
min-width: max(150rpx, 42%);
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
font-family: Arial, Arial;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 30rpx;
|
||||||
|
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 600;
|
||||||
|
min-width: max(80rpx, 20%);
|
||||||
|
}
|
||||||
|
.up {
|
||||||
|
color: #ff8a2d;
|
||||||
|
}
|
||||||
|
.down {
|
||||||
|
color: #48ae80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-Y {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-title {
|
||||||
|
width: 100%;
|
||||||
|
height: 70rpx;
|
||||||
|
font-size: 33rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: var(--status-bar-height);
|
||||||
|
.delete_div {
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.back_div {
|
||||||
|
position: absolute;
|
||||||
|
left: 26rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #ffffff;
|
||||||
|
border-left: 4rpx solid #ffffff;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
<template>
|
||||||
|
<z-paging
|
||||||
|
ref="pagingRef"
|
||||||
|
v-model="data_list"
|
||||||
|
@query="queryList"
|
||||||
|
class="scroll_div"
|
||||||
|
:layout-only="true"
|
||||||
|
empty-view-text="暂无积分记录"
|
||||||
|
paging-class="z-paging-class"
|
||||||
|
>
|
||||||
|
<template #top>
|
||||||
|
<view class="top-main-div">
|
||||||
|
<view class="content">
|
||||||
|
<view class="body-title">
|
||||||
|
<view class="back_div" @click="common.navigateBack()">
|
||||||
|
<view class="back-icon"></view>
|
||||||
|
</view>
|
||||||
|
<view>积分段位说明</view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="my-rank">
|
||||||
|
<view class="left">
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="note">当前段位:{{dataInfo.currentRankName}}</view>
|
||||||
|
<view class="note">
|
||||||
|
我的累计积分:
|
||||||
|
<text class="score">{{dataInfo.currentPoints}}/{{dataInfo.countPoints}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fl1"></view>
|
||||||
|
<view class="right">
|
||||||
|
<image-preview class="img_100" :src="dataInfo.ossAddr" mode="widthFix"></image-preview>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<view class="scroll-Y">
|
||||||
|
<view class="item_th">
|
||||||
|
<view class="title">段位</view>
|
||||||
|
<view class="score">积分范围</view>
|
||||||
|
<view class="value">标识</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" v-for="(item, index) in data_list">
|
||||||
|
<view class="title ellipsis-text">
|
||||||
|
{{ item.rankName }}
|
||||||
|
</view>
|
||||||
|
<view class="score">{{ item.pointsStart }}~{{ item.pointsEnd }}</view>
|
||||||
|
<view class="icon" :class="Number(item.changeValue) >= 0 ? 'up' : 'down'">
|
||||||
|
<image-preview class="img_100" :src="item.ossAddr" mode="heightFix"></image-preview>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 竞赛列表
|
||||||
|
import { ref, reactive, watch, onMounted } from 'vue';
|
||||||
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||||
|
import useZpaging from '@/composables/useZpaging.js';
|
||||||
|
import common from '@/common/common';
|
||||||
|
import { queryRankDetail, queryCurrentStatus } from '@/api/pointsAndRank.js';
|
||||||
|
const dataInfo = reactive({
|
||||||
|
countPoints: 0, // 累计积分 int
|
||||||
|
currentPoints: 0, // 当前积分 int
|
||||||
|
currentRankName: '', // 当前段位 String
|
||||||
|
ossAddr: '', // 当前段位图片
|
||||||
|
badgeNum: 0 // 徽章数 int
|
||||||
|
});
|
||||||
|
const fetchFunction = (params) => {
|
||||||
|
queryCurrentStatus().then(({ body }) => {
|
||||||
|
const { countPoints, currentPoints, currentRankName, badgeNum, ossAddr } = body;
|
||||||
|
Object.assign(dataInfo, {
|
||||||
|
countPoints,
|
||||||
|
currentPoints,
|
||||||
|
currentRankName,
|
||||||
|
badgeNum,
|
||||||
|
ossAddr,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return queryRankDetail({ ...params });
|
||||||
|
};
|
||||||
|
const { pagingRef, queryList, data_list, search } = useZpaging({
|
||||||
|
fetchFunction
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
pagingRef.value.reload();
|
||||||
|
});
|
||||||
|
onUnload(() => {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.z-paging-class {
|
||||||
|
background-color: #e0e3ef;
|
||||||
|
::v-deep .zp-view-super {
|
||||||
|
background-color: #ffffff;
|
||||||
|
// margin: 0 24rpx;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 30rpx 30rpx 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.top-main-div {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: calc(44.87% + var(--status-bar-height));
|
||||||
|
background: linear-gradient(to right, #78238d, #5b25a0, #3b28b6);
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: -44rpx;
|
||||||
|
.content {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-rank {
|
||||||
|
padding-bottom: 84rpx;
|
||||||
|
padding-left: 46rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
.left {
|
||||||
|
.score {
|
||||||
|
font-family: DINAlternate, DINAlternate;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 33rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 38rpx;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
font-family: PingFangSC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 25rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 35rpx;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
width: 124rpx;
|
||||||
|
margin-right: 60rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item_th {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 4rpx solid #efefef;
|
||||||
|
font-family: PingFangSC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
text-align: left;
|
||||||
|
padding: 30rpx 38rpx 30rpx 26rpx;
|
||||||
|
.title {
|
||||||
|
text-align: left;
|
||||||
|
min-width: max(150rpx, 42%);
|
||||||
|
}
|
||||||
|
.score {
|
||||||
|
flex: 1;
|
||||||
|
// min-width: max(150rpx, 42%);/
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
// min-width: max(80rpx, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
background: #ffffff;
|
||||||
|
border-bottom: 2rpx solid #efefef;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 26rpx 38rpx 26rpx 26rpx;
|
||||||
|
.title {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
text-align: left;
|
||||||
|
min-width: max(150rpx, 42%);
|
||||||
|
}
|
||||||
|
.score {
|
||||||
|
flex: 1;
|
||||||
|
font-family: ArialMT;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
height: 44rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-Y {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-title {
|
||||||
|
width: 100%;
|
||||||
|
height: 70rpx;
|
||||||
|
font-size: 33rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: var(--status-bar-height);
|
||||||
|
.delete_div {
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.back_div {
|
||||||
|
position: absolute;
|
||||||
|
left: 26rpx;
|
||||||
|
top: 17rpx;
|
||||||
|
.back-icon {
|
||||||
|
position: relative;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::before,
|
||||||
|
.back-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon::after {
|
||||||
|
top: 25%;
|
||||||
|
left: 25%;
|
||||||
|
width: 40%;
|
||||||
|
height: 40%;
|
||||||
|
border-top: 4rpx solid #ffffff;
|
||||||
|
border-left: 4rpx solid #ffffff;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
const storageTopicList = ref([]); // 所有题列表
|
const storageTopicList = ref([]); // 所有题列表
|
||||||
const popup_input_bottom = ref('0px');
|
const popup_input_bottom = ref('0px');
|
||||||
const questionNumber = ref(0); // 题号
|
const questionNumber = ref(0); // 题号
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
|
||||||
|
|
||||||
const topic = computed({
|
const topic = computed({
|
||||||
get: () => topicList[questionNumber.value],
|
get: () => topicList[questionNumber.value],
|
||||||
@@ -747,7 +747,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main_div {
|
.main_div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -67,16 +67,7 @@
|
|||||||
|
|
||||||
const mascotName = computed(() => userInfo.value.mascotInfo?.mascotName || '');
|
const mascotName = computed(() => userInfo.value.mascotInfo?.mascotName || '');
|
||||||
const sexOptions = GENDER;
|
const sexOptions = GENDER;
|
||||||
const anonymousOptions = [
|
|
||||||
{
|
|
||||||
value: 'y',
|
|
||||||
label: '是'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'n',
|
|
||||||
label: '否'
|
|
||||||
}
|
|
||||||
]; // 性别
|
|
||||||
|
|
||||||
// 去选择百禄
|
// 去选择百禄
|
||||||
const gotoMascot = () => {
|
const gotoMascot = () => {
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "错题本",
|
"navigationBarTitleText": "错题本",
|
||||||
"app-plus": {
|
"app-plus": {
|
||||||
"titleNView": false
|
"titleNView": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -246,7 +246,70 @@
|
|||||||
"titleNView": false
|
"titleNView": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "竞赛列表页",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/matching",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "匹配页面",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/pk",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "pk页面",
|
||||||
|
"disableSwipeBack": true,
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/result",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "pk结果页面",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/competition/ranking",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "pk排行榜",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/pointsAndRank/points",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "积分变动明细",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/pointsAndRank/rank",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "段位列表",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/index/dialog",
|
"path": "pages/index/dialog",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "AI问答",
|
"navigationBarTitleText": "AI问答",
|
||||||
"app-plus": {
|
"app-plus": {
|
||||||
"titleNView": false,
|
"titleNView": false,
|
||||||
"animationType": "fade-in"
|
"animationType": "fade-in"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 830 KiB |
|
After Width: | Height: | Size: 312 KiB |
|
After Width: | Height: | Size: 262 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 174 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 172 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
// 声明图片文件模块
|
||||||
|
declare module '*.jpg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*.jpeg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*.png' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*.gif' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Vue 项目常用配置(根据实际版本调整)
|
||||||
|
"moduleResolution": "NodeNext", // 或 "Node"
|
||||||
|
"module": "NodeNext", // 与 moduleResolution 保持一致
|
||||||
|
"target": "ES2022",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["ES2022", "DOM"],
|
||||||
|
"baseUrl": ".", // 表示以 tsconfig.json 所在目录为基准
|
||||||
|
"types": ["vue"], // 确保包含 vue 类型定义
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||||
|
}
|
||||||
@@ -1,8 +1,14 @@
|
|||||||
import { defineConfig } from 'vite'
|
import {
|
||||||
|
defineConfig
|
||||||
|
} from 'vite'
|
||||||
import uni from '@dcloudio/vite-plugin-uni'
|
import uni from '@dcloudio/vite-plugin-uni'
|
||||||
// https://vitejs.dev/config/
|
import path from 'path'
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [uni()],
|
||||||
uni(),
|
// 新增服务器配置,指定启动端口
|
||||||
],
|
server: {
|
||||||
})
|
port: 5174,
|
||||||
|
strictPort: true, // 可选:端口被占用时直接报错(避免自动切换端口)
|
||||||
|
open: false // 可选:启动后自动打开浏览器(按需开启)
|
||||||
|
}
|
||||||
|
})
|
||||||