Browse Source

250618调整

master
梁欣 5 days ago
parent
commit
9f0fc8fa12
  1. 2
      src/api/article.js
  2. 1
      src/api/common.js
  3. 6
      src/api/exam.js
  4. 1
      src/api/signUp.js
  5. 135
      src/components/MessageItem.vue
  6. 4
      src/manifest.json
  7. 24
      src/pages.json
  8. 201
      src/pages/exam/checkScore.vue
  9. 117
      src/pages/exam/exam.vue
  10. 154
      src/pages/exam/makeScore.vue
  11. 77
      src/pages/exam/makeScoreList.vue
  12. 121
      src/pages/exam/train/randExam.vue
  13. 131
      src/pages/exam/train/sortExam.vue
  14. 387
      src/pages/index/components/articleListComponent.vue
  15. 59
      src/pages/index/components/tab0.vue
  16. 4
      src/pages/index/components/tab3.vue
  17. 10
      src/pages/index/index.vue
  18. 427
      src/pages/index/publish.vue
  19. 190
      src/pages/promote/components/ReviewList.vue
  20. 2
      src/pages/promote/exam.vue
  21. 253
      src/pages/promote/promote.vue
  22. 12
      src/pages/promote/result.vue
  23. 2
      src/pages/signUp/info.vue
  24. 34
      src/pages/signUp/self.vue
  25. 113
      src/pages/user/message.vue
  26. 53
      src/pages/user/shareList.vue
  27. 133
      src/pages/user/signIn.vue
  28. 149
      src/pages/user/signUp.vue
  29. 34
      src/pages/user/user.vue
  30. 4
      src/pages/user/userDetail.vue
  31. BIN
      src/static/image/activity.png
  32. BIN
      src/static/image/address.png
  33. BIN
      src/static/image/archiveBox.png
  34. BIN
      src/static/image/board.png
  35. BIN
      src/static/image/booking.png
  36. BIN
      src/static/image/order.png
  37. BIN
      src/static/image/patent.png
  38. BIN
      src/static/image/profile.png
  39. BIN
      src/static/image/score.png
  40. BIN
      src/static/image/service.png
  41. BIN
      src/static/image/setting.png
  42. BIN
      src/static/image/share.png
  43. BIN
      src/static/image/task.png
  44. 2
      src/uni_modules/custom-waterfalls-flow/components/custom-waterfalls-flow/custom-waterfalls-flow.vue

2
src/api/article.js

@ -28,7 +28,9 @@ export const articlePageByTopReq = (params) => http.get('/cms/article/page-by-to
export const articleListForPolicyReq = (params) => http.get('/cms/article/list-for-policy', {params})
export const pageMatchArticleReq = (params) => http.post('/match/match-article/page-for-front', params)
export const pageMatchArticleForUserReq = (params) => http.post('/match/match-article/list-for-user', params)
export const matchArticleActionReq = (params) => http.post('/match/match-article/action', params)
export const matchArticleInfoReq = (id) => http.get(`/match/match-article/${id}`)
export const matchArticleLikeAction = (params) => http.post('/match/match-article-like/action', params)
export const matchArticleCommentListReq = (params) => http.post('/match/match-article-comment/list-for-front', params)
export const matchArticleCommentActionReq = (params) => http.post('/match/match-article-comment/action', params)

1
src/api/common.js

@ -29,4 +29,5 @@ export const getCodeReq = (data) => http.post('/sms/get-code', data)
export const checkCodeReq = (data) => http.post('/sms/check-code', data)
export const regReq = (data) => http.post('/sys/user-detail/reg', data)
export const userInfoByIdCardPhoneReq = (data) => http.post('/sys/user-detail/info-by-id-card-phone', data)

6
src/api/exam.js

@ -40,6 +40,12 @@ export const addExamCorrectionReq = data => http.post('/exam/correction', data)
export const addExamUpgradeReq = data => http.post('/exam/upgrade', data)
export const getExamReq = id => http.get(`/exam/paper-detail/${id}`)
export const trainExamStaffListReq = () => http.get(`/train/train-exam-staff/user-list`)
export const operatePaperDetailReq = params => http.get(`/exam/operate-paper-detail`, {params})
export const operateScoreActionReq = (data) => http.post(`/exam/operate-score`, data)
export const operateScoreListReq = (params) => http.get(`/exam/operate-score`, {params})
export const operateScoreCheckReq = (data) => http.post(`/exam/operate-score/check-score`, data)
export const operateScoreRefuseReq = (data) => http.post(`/exam/operate-score/check-score-refuse`, data)
export const TASK_TYPE_LIST = [

1
src/api/signUp.js

@ -4,6 +4,7 @@ export const signUpListReq = () => http.get('/train/train-sign-up')
export const signUpSelfListReq = () => http.get('/train/train-sign-up-self')
export const signUpInfoReq = id => http.get(`/train/train-sign-up/${id}`)
export const signUpUserListReq = () => http.post(`/train/train-sign-up/user-list`)
export const signUpUserSelfListReq = () => http.post(`/train/train-sign-up-self/user-list`)
export const signUpJoinReq = data => http.post(`/train/train-sign-up-people/join`, data)
export const signUpPeopleListReq = params => http.get(`/train/train-sign-up-people`, {params})
export const signUpUpdateReq = data => http.put(`/train/train-sign-up-people`, data)

135
src/components/MessageItem.vue

@ -0,0 +1,135 @@
<template>
<view class="card mb-20 flex justify-between items-center pos-r"
@click="jump(item, index)">
<view class="dot" v-if="!item.hasRead"></view>
<view class="flex justify-start items-start flex-col">
<template v-if="item.title">
<text class="text-26 font-bold">{{ item.title }}</text>
</template>
<text v-else class="text-26 font-bold">{{ TYPE_LIST.find(t => t.type === item.type).title }}</text>
<text class="text-gray text-25 mt-20">{{
dayjs(item.createTime).format('YYYY-MM-DD HH:mm')
}}
</text>
</view>
<uv-icon name="arrow-right"/>
</view>
</template>
<script setup>
import {ref} from 'vue'
import dayjs from "dayjs";
import {messageReadReq} from "@/api/shop";
const props = defineProps({
item: {
type: Object,
default: () => {
return {}
}
},
index: {
type: Number,
default: 0
}
})
const jump = (item, index) => {
let url
switch (item.type) {
case 'exam' : {
uni.switchTab({url: '/pages/promote/promote'})
}
break;
case 'matchEnd' :
case 'matchStart' : {
url = `/pages/match/ing`
}
break;
case 'trainEnd' :
case 'trainStart' : {
url = `/pages/promote/learn?courseId=${item.train.courseId}&trainId=${item.pk}`
}
break;
case 'express' : {
url = `/pages/user/order/detail?orderId=${item.pk}`
}
break;
case 'activity' : {
url = `/pages/activity/info?id=${item.pk}`
}
break;
case 'signUp' :
case 'signUpSelf' :
case 'activityNotice':
case 'trainEndNotice' : {
url = `/pages/user/trainEndNotice?id=${item.id}`
}
break;
}
if (url) uni.redirectTo({url})
read(item.id, index)
}
const read = async (id, index) => {
await messageReadReq({id, hasRead: 1})
list.value[index].hasRead = true
}
const TYPE_LIST = [
{
type: 'exam',
title: '考试即将开始'
},
{
type: 'matchEnd',
title: '竞赛即将结束'
},
{
type: 'matchStart',
title: '竞赛即将开始'
},
{
type: 'trainEnd',
title: '培训即将结束'
},
{
type: 'trainStart',
title: '培训即将开始'
},
{
type: 'express',
title: '订单已发货'
},
{
type: 'activity',
title: '新活动提醒'
},
{
type: 'signUp',
title: '报名资料待修改'
},
{
type: 'signUpSelf',
title: '自主报名资料待修改'
},
{
type: 'review',
title: '复习通知'
},
]
</script>
<style scoped lang="scss">
.dot {
position: absolute;
left: 10rpx;
top: 10rpx;
width: 5rpx;
height: 5rpx;
border-radius: 5rpx;
background-color: red;
}
</style>

4
src/manifest.json

@ -3,8 +3,8 @@
"appid" : "__UNI__06C03D0",
//__UNI__06C03D0
"description" : "",
"versionName" : "1.35.0",
"versionCode" : "254",
"versionName" : "2.2.0",
"versionCode" : "275",
"transformPx" : false,
/* 5+App */
"app-plus" : {

24
src/pages.json

@ -656,6 +656,30 @@
"style": {
"navigationBarTitleText": "钱包"
}
},
{
"path": "pages/user/shareList",
"style": {
"navigationBarTitleText": "我的分享"
}
},
{
"path": "pages/exam/makeScoreList",
"style": {
"navigationBarTitleText": "实操考试打分"
}
},
{
"path": "pages/exam/makeScore",
"style": {
"navigationBarTitleText": "实操考试打分"
}
},
{
"path": "pages/exam/checkScore",
"style": {
"navigationBarTitleText": "实操考试核分"
}
}
],
"tabBar": {

201
src/pages/exam/checkScore.vue

@ -0,0 +1,201 @@
<template>
<view class="p-20 min-height bg-gray-light">
<view class="card text-25 m-20">
<view class="flex justify-between items-center">
<text>考生姓名: {{ realnameVal }}</text>
<text>考生身份证: {{ idCardVal }}</text>
</view>
<view class="flex justify-between items-center my-10">
<text>打分人: {{ scoreUserNameVal }}</text>
</view>
<view class="text-main my-15">总分: {{ totalScore }}</view>
<view class="text-main my-15">分数: {{ totalGetScore }}</view>
<view class="flex justify-center items-center">
<view class="flex-1 mx-15">
<uv-button type="primary" shape="circle" @click="submit" :disabled="disabled">确认</uv-button>
</view>
<view class="flex-1 mx-15">
<uv-button type="error" shape="circle" @click="refuse" :disabled="disabled">退回</uv-button>
</view>
</view>
</view>
<view style="height: calc(100vh - 360rpx)" class="overflow-y">
<view class="card m-20 text-25 flex flex-col justify-start items-start"
v-for="(item, index) in list" :key="index">
<view class="flex justify-start items-center mb-10" @click="item.showAll = !item.showAll">
<text class="text-main mr-10" style="flex: 0 0 100rpx ">
{{ item.showAll ? '折叠' : '展开详情' }}
</text>
<text class="font-bold text-28">{{ item.title }}</text>
</view>
<view class="flex flex-col justify-start items-start py-15" v-if="item.showAll">
<text class="pb-15 font-bold">考试内容</text>
<text class="text-25 mt-15 pb-15 border-bottom" v-html="item.content"></text>
<text class="pb-15 font-bold">评分表</text>
<view v-for="(content, contentIndex) in item.examContent" :key="contentIndex"
class="p-15 text-25 bg-main-light rounded mb-10 w-90p">
<text class="font-bold pb-15 border-bottom w-100p">{{ content.title }}(分数: {{
content.score
}}/{{ content.totalScore }})
</text>
<view class="py-10 flex flex-col justify-start items-start"
v-for="(contentItem, contentItemIndex) in content.list" :key="contentItemIndex">
<text class="mb-10">{{ contentItem.content }}</text>
<view class="p-10 my-10 w-90p bg-white flex justify-start items-center">
<text>分数: {{ list[index].examContent[contentIndex].list[contentItemIndex].rating }}</text>
</view>
<text class="mb-10 text-gray">配分:{{ contentItem.score }}</text>
<text class="mb-10 text-gray">最大扣分:{{ contentItem.maxReduce }}</text>
<text class="mb-10 text-gray">扣分步长:{{ contentItem.step }}</text>
<text class="mb-10 text-gray">评分标准:{{ contentItem.standard }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
import {
operatePaperDetailReq,
operateScoreActionReq,
operateScoreCheckReq,
operateScoreListReq,
operateScoreRefuseReq
} from "@/api/exam";
import {onLoad} from "@dcloudio/uni-app";
import {$toast} from "@/utils";
const list = ref([])
const getPaperDetailList = async (paperId) => {
const {data} = await operatePaperDetailReq({
paperId
})
list.value = data.map(item => {
item.showAll = true
item.score = ''
item.examContent = JSON.parse(item.examContent).map(content => {
content.score = 0
content.totalScore = 0
content.list.map(contentItem => {
contentItem.rating = parseInt(contentItem.score)
contentItem.score = parseInt(contentItem.score)
contentItem.maxReduce = parseInt(contentItem.maxReduce)
content.score += contentItem.rating
content.totalScore += contentItem.rating
totalScore.value += contentItem.rating
return contentItem
})
return content
})
return item
})
}
const getScoreList = async (paperId, userId) => {
const {data} = await operateScoreListReq({
paperId, userId
})
data.forEach(score => {
list.value.forEach(item => {
item.examContent.forEach(content => {
content.list.map(contentItem => {
if (contentItem.content === score.title && item.id === score.detailId) {
contentItem.rating = score.score
}
return contentItem
})
})
})
})
calTotalScore()
}
const totalScore = ref(0)
const totalGetScore = ref(0)
const calTotalScore = () => {
totalGetScore.value = 0
list.value.forEach(item => {
item.examContent.forEach(content => {
content.list.forEach(contentItem => {
totalGetScore.value += contentItem.rating
})
})
})
}
const disabled = ref(false)
const submit = async () => {
uni.showModal({
title: '提示',
content: `确认核分吗?`,
success: async ({confirm}) => {
if (confirm) {
disabled.value = true
uni.showLoading({title: '提交中'})
await operateScoreCheckReq({
examId: examVal,
paperId: paperIdVal,
userId: userIdVal,
scoreUserId: scoreUserIdVal,
}).catch(() => {
disabled.value = false
})
disabled.value = false
uni.hideLoading()
$toast('操作成功')
setTimeout(async () => {
await uni.navigateBack()
}, 1500)
}
}
})
}
const refuse = async () => {
uni.showModal({
title: '提示',
content: `确认退回吗?`,
success: async ({confirm}) => {
if (confirm) {
disabled.value = true
uni.showLoading({title: '提交中'})
await operateScoreRefuseReq({
examId: examVal,
paperId: paperIdVal,
userId: userIdVal,
scoreUserId: scoreUserIdVal,
}).catch(() => {
disabled.value = false
})
disabled.value = false
uni.hideLoading()
$toast('操作成功')
setTimeout(async () => {
await uni.navigateBack()
}, 1500)
}
}
})
}
const idCardVal = ref('')
const realnameVal = ref('')
const scoreUserNameVal = ref('')
let examVal = null, paperIdVal = null, userIdVal = null, scoreUserIdVal = null
onLoad(async ({paperId, idCard, realname, examId, userId, scoreUserId, scoreUserName}) => {
await getPaperDetailList(paperId)
await getScoreList(paperId, userId)
idCardVal.value = idCard
realnameVal.value = realname
examVal = examId
paperIdVal = paperId
userIdVal = userId
scoreUserIdVal = scoreUserId
scoreUserNameVal.value = scoreUserName
})
</script>

117
src/pages/exam/exam.vue

@ -1,7 +1,10 @@
<template>
<view class="wrap">
<view class="layout-room">
<view class="time" v-if="timeLimitVal">{{ (parseInt(timeLimitVal / 60)).toString().padStart(2, '0') }}:{{ (timeLimitVal % 60).toString().padStart(2, '0') }}</view>
<view class="time" v-if="timeLimitVal">{{
(parseInt(timeLimitVal / 60)).toString().padStart(2, '0')
}}:{{ (timeLimitVal % 60).toString().padStart(2, '0') }}
</view>
<view class="xu">
<text class="now">{{ currentIndex + 1 }}</text>
/{{ examList.length }}
@ -31,9 +34,22 @@
<uv-button type="primary" shape="circle" @click="next">下一题
</uv-button>
</view>
<CorrectionItem :exam-detail-id="examList[currentIndex].id" v-if="currentIndex > -1 && examList.length" :exam-id="examIdVal"/>
<ExamUpgrade :exam-detail-id="examList[currentIndex].id" v-if="currentIndex > -1 && examList.length" :exam-id="examIdVal"/>
<CorrectionItem :exam-detail-id="examList[currentIndex].id" v-if="currentIndex > -1 && examList.length"
:exam-id="examIdVal"/>
<ExamUpgrade :exam-detail-id="examList[currentIndex].id" v-if="currentIndex > -1 && examList.length"
:exam-id="examIdVal"/>
</view>
<uv-popup ref="popup" mode="bottom" overlayOpacity="0.1" round="15" safe-area-inset-bottom>
<view class="p-50">
<view class="text-25 mb-25">
<text>正确答案:</text>
<text class="text-blue font-bold">{{ correctContent }}</text>
</view>
<uv-button type="primary" shape="circle" @click="doNext">下一题
</uv-button>
</view>
<uv-gap height="20rpx"></uv-gap>
</uv-popup>
</view>
</template>
@ -53,14 +69,34 @@ const getExamList = async (paperId) => {
const res = await paperDetailListReq({
paperId,
num: numVal,
id: detailIdVal
id: detailIdVal,
type: typeVal
})
examList.value = []
if (res) {
examList.value = res.data
examList.value = res.data.map(item => {
if (['cal', 'answer', 'essay', 'explain'].includes(item.type)) {
const correct = JSON.parse(item.answer).find(item => item.isCorrect)
item.userAnswer = correct.content
}
return item
})
}
}
const popup = ref()
const doNext = () => {
popup.value.close()
correctContent.value = ''
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else saveResult()
}
const correctContent = ref('')
const selectedAnswerIndex = ref([])
const selectAnswer = (index) => {
const currentExam = examList.value[currentIndex.value]
@ -76,21 +112,32 @@ let correctNum = 0
let resultList = []
const next = () => {
if (!selectedAnswerIndex.value.length) return $toast('请选择答案')
const currentExam = examList.value[currentIndex.value]
if (['single', 'multi', 'single'].includes(currentExam.type)) {
if (!selectedAnswerIndex.value.length) return $toast('请选择答案')
}
const answerList = JSON.parse(currentExam.answer)
let toNext = true
if (!['multi'].includes(currentExam.type)) {
if (['single', 'judge'].includes(currentExam.type)) {
hasResultNum++
const answer = answerList[selectedAnswerIndex.value[0]]
if (!answer.isCorrect) {
// let correct
// for (let i = 0; i < answerList.length; i++) {
// if (answerList[i].isCorrect) {
// correct = answerList[i]
// break
// }
// }
if (isSim) {
let correct
for (let i = 0; i < answerList.length; i++) {
if (answerList[i].isCorrect) {
if (currentExam.type === 'single')
correct = `${ANSWER_CHAR[i]}${answerList[i].content}`
else correct = answerList[i].content
break
}
}
correctContent.value = correct
popup.value.open()
toNext = false
}
examUserWrongActionReq({
courseId: examList.value[0].courseId,
examDetailId: currentExam.id,
@ -106,10 +153,12 @@ const next = () => {
type: currentExam.type,
userAnswer: answer.content
})
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else saveResult()
if (toNext) {
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else saveResult()
}
} else {
resultList.push({
paperId: paperIdVal,
@ -126,15 +175,17 @@ const next = () => {
resultList.push({
paperId: paperIdVal,
detailId: currentExam.id,
getScore: null,
getScore: currentExam.score,
examType: examTypeVal,
examId: examIdVal,
type: currentExam.type,
userAnswer: examList.value[currentIndex.value].content
userAnswer: currentExam.userAnswer
})
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
} else saveResult()
if (toNext) {
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
} else saveResult()
}
}
} else {
hasResultNum++
@ -158,6 +209,11 @@ const next = () => {
})
correctNext()
} else {
if (isSim) {
correctContent.value = correctList.map(i => i.content).join(', ')
popup.value.open()
toNext = false
}
examUserWrongActionReq({
courseId: examList.value[0].courseId,
examDetailId: currentExam.id,
@ -173,10 +229,12 @@ const next = () => {
type: currentExam.type,
userAnswer: JSON.stringify(answerList.filter((_, index) => selectedAnswerIndex.value.includes(index)).map(i => i.content))
})
if (currentIndex.value < examList.value.length - 1) {
selectedAnswerIndex.value = []
currentIndex.value++
} else saveResult()
if (toNext) {
if (currentIndex.value < examList.value.length - 1) {
selectedAnswerIndex.value = []
currentIndex.value++
} else saveResult()
}
}
}
}
@ -230,9 +288,10 @@ const countDown = () => {
}
}
let paperIdVal = null, examTypeVal = null, examIdVal = null, numVal = null, detailIdVal = null
let paperIdVal = null, examTypeVal = null, examIdVal = null, numVal = null, detailIdVal = null, isSim = false,
typeVal = null
const timeLimitVal = ref(null)
onLoad(({title, paperId, examType, examId, num, timeLimit, detailId}) => {
onLoad(({title, paperId, examType, examId, num, timeLimit, detailId, type}) => {
currentIndex.value = 0
correctNum = 0
selectedAnswerIndex.value = []
@ -243,11 +302,13 @@ onLoad(({title, paperId, examType, examId, num, timeLimit, detailId}) => {
examIdVal = examId
if (num) numVal = num
if (detailId) detailIdVal = detailId
if (type) typeVal = type
if (timeLimit) {
timeLimitVal.value = parseInt(timeLimit * 60)
countDown()
}
getExamList(paperId)
isSim = title === '模拟考试'
uni.setNavigationBarTitle({title})
})

154
src/pages/exam/makeScore.vue

@ -0,0 +1,154 @@
<template>
<view class="p-20 min-height bg-gray-light">
<view class="card text-25 m-20">
<view class="flex justify-between items-center">
<text>考生姓名: {{ realnameVal }}</text>
<text>考生身份证: {{ idCardVal }}</text>
</view>
<view class="text-main my-15">总分: {{ totalScore }}</view>
<view class="text-main my-15">分数: {{ totalGetScore }}</view>
<uv-button type="primary" shape="circle" @click="submit" :disabled="disabled">提交</uv-button>
</view>
<view style="height: calc(100vh - 360rpx)" class="overflow-y">
<view class="card m-20 text-25 flex flex-col justify-start items-start"
v-for="(item, index) in list" :key="index">
<view class="flex justify-start items-center mb-10" @click="item.showAll = !item.showAll">
<text class="text-main mr-10" style="flex: 0 0 100rpx ">
{{ item.showAll ? '折叠' : '展开详情' }}
</text>
<text class="font-bold text-28">{{ item.title }}</text>
</view>
<view class="flex flex-col justify-start items-start py-15" v-if="item.showAll">
<text class="pb-15 font-bold">考试内容</text>
<text class="text-25 mt-15 pb-15 border-bottom" v-html="item.content"></text>
<text class="pb-15 font-bold">评分表</text>
<view v-for="(content, contentIndex) in item.examContent" :key="contentIndex"
class="p-15 text-25 bg-main-light rounded mb-10 w-90p">
<text class="font-bold pb-15 border-bottom w-100p">{{ content.title }}(分数: {{
content.score
}}/{{ content.totalScore }})
</text>
<view class="py-10 flex flex-col justify-start items-start"
v-for="(contentItem, contentItemIndex) in content.list" :key="contentItemIndex">
<text class="mb-10">{{ contentItem.content }}</text>
<view class="p-10 my-10 w-90p bg-white flex justify-start items-center">
<text>分数:</text>
<uv-number-box :min="0" :step="contentItem.step" integer inputWidth="60" :max="contentItem.score"
disabled-input
@change="changeScore($event, index, contentIndex, contentItemIndex)"
v-model="list[index].examContent[contentIndex].list[contentItemIndex].rating"></uv-number-box>
</view>
<text class="mb-10 text-gray">配分:{{ contentItem.score }}</text>
<text class="mb-10 text-gray">最大扣分:{{ contentItem.maxReduce }}</text>
<text class="mb-10 text-gray">扣分步长:{{ contentItem.step }}</text>
<text class="mb-10 text-gray">评分标准:{{ contentItem.standard }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
import {operatePaperDetailReq, operateScoreActionReq} from "@/api/exam";
import {onLoad} from "@dcloudio/uni-app";
import {$toast} from "@/utils";
const list = ref([])
const getPaperDetailList = async (paperId) => {
const {data} = await operatePaperDetailReq({
paperId
})
list.value = data.map(item => {
item.showAll = true
item.score = ''
item.examContent = JSON.parse(item.examContent).map(content => {
content.score = 0
content.totalScore = 0
content.list.map(contentItem => {
contentItem.rating = parseInt(contentItem.score)
contentItem.score = parseInt(contentItem.score)
contentItem.maxReduce = parseInt(contentItem.maxReduce)
content.score += contentItem.rating
content.totalScore += contentItem.rating
totalScore.value += contentItem.rating
totalGetScore.value += contentItem.rating
return contentItem
})
return content
})
console.log(item)
return item
})
calTotalScore()
}
const totalScore = ref(0)
const totalGetScore = ref(0)
const changeScore = ({value}, index, contentIndex, contentItemIndex) => {
list.value[index].examContent[contentIndex].list[contentItemIndex].rating = parseInt(value)
const detailList = list.value[index].examContent[contentIndex].list
list.value[index].examContent[contentIndex].score = detailList.reduce((pre, cur) => {
return parseInt(pre) + parseInt(cur.rating)
}, 0)
calTotalScore()
}
const calTotalScore = () => {
totalGetScore.value = 0
for (let i = 0; i < list.value.length; i++) {
const item = list.value[i]
for (let j = 0; j < item.examContent.length; j++) {
const content = item.examContent[j]
totalGetScore.value += content.score
}
}
}
const disabled = ref(false)
const submit = async () => {
const dataList = []
for (let i = 0; i < list.value.length; i++) {
const item = list.value[i]
for (let j = 0; j < item.examContent.length; j++) {
const content = item.examContent[j]
for (let k = 0; k < content.list.length; k++) {
const contentItem = content.list[k]
dataList.push({
examId: examVal,
detailId: item.id,
paperId: paperIdVal,
title: contentItem.content,
score: contentItem.rating,
userId: userIdVal,
})
}
}
}
disabled.value = true
uni.showLoading({title: '提交中'})
await operateScoreActionReq(dataList).catch(() => {
disabled.value = false
})
disabled.value = false
uni.hideLoading()
$toast('打分成功')
setTimeout(async () => {
await uni.navigateBack()
}, 1500)
}
const idCardVal = ref('')
const realnameVal = ref('')
let examVal = null, paperIdVal = null, userIdVal = null
onLoad(({paperId, idCard, realname, examId, userId}) => {
getPaperDetailList(paperId)
idCardVal.value = idCard
realnameVal.value = realname
examVal = examId
paperIdVal = paperId
userIdVal = userId
})
</script>

77
src/pages/exam/makeScoreList.vue

@ -0,0 +1,77 @@
<template>
<view class="p-20 min-height">
<uv-empty v-if="!list.length" text="暂无打分任务"></uv-empty>
<view v-for="(item, index) in list" :key="index" class="border p-20 m-20 text-25 rounded">
<view>{{ item.title }}</view>
<view class="mt-15 text-gray">考试时长: {{ item.examTime }}分钟</view>
<view class="mt-15 text-gray">考试企业: {{ item.orgName }}</view>
<view class="mt-15 text-gray">{{ item.level }}</view>
<view class="mt-15 text-gray flex justify-start items-start">
<text>试卷:</text>
<view class="ml-10 flex flex-col justify-start items-start">
<text class="mb-10" v-if="item.paperList[0].operatePaper">{{ item.paperList[0].operatePaper.title }}</text>
</view>
</view>
<view class="mt-15 text-main pb-15" @click="item.showPeople = !item.showPeople">
{{ item.showPeople ? '收起' : '查看考试人员' }}
</view>
<template v-if="item.showPeople">
<view class="flex flex-col justify-start items-start py-15 border-top text-main text-25"
v-for="(people, peopleIndex) in item.peopleList" :key="peopleIndex">
<view class="flex justify-between items-center w-100p">
<text>{{ people.userDetail.realname }}</text>
<uv-button v-if="!people.staffHasScore && item.staffTypeList.includes('考评人员')" shape="circle"
type="primary"
@click="jump('/pages/exam/makeScore', item, people)"
size="mini">去打分
</uv-button>
<text v-if="people.staffHasScore">总分: {{ people.operateScore }}</text>
</view>
<template v-if="people.staffHasScore && item.staffTypeList.includes('督导人员')">
<view class="flex justify-between items-center w-100p py-15 border-bottom text-gray"
v-for="(score, scoreIndex) in people.scoreList" :key="scoreIndex">
<view class="flex justify-start items-center">
<text>打分人:{{ score.scoreUserName }}</text>
<text class="ml-10">评分:{{ score.totalScore }}</text>
</view>
<uv-button v-if="!score.checkUserName" shape="circle"
type="primary"
@click="jump('/pages/exam/checkScore', item, people, score)"
size="mini">核分
</uv-button>
<text v-else>核分人:{{ score.checkUserName }}</text>
</view>
</template>
</view>
</template>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
import {trainExamStaffListReq} from "@/api/exam";
import {onShow} from "@dcloudio/uni-app";
const list = ref([])
const getList = async () => {
const {data} = await trainExamStaffListReq()
list.value = data.map(item => {
item.showPeople = false
return item
})
}
onShow(() => {
getList()
})
const jump = (url, item, people, score = null) => {
url += `?examId=${item.id}&paperId=${item.paperList[0].operatePaperId}&userId=${people.userId}`
url += `&idCard=${people.userDetail.idCard}&realname=${people.userDetail.realname}`
if (score) {
url += `&scoreUserId=${score.scoreUserId}&scoreUserName=${score.scoreUserName}`
}
uni.navigateTo({url})
}
</script>

121
src/pages/exam/train/randExam.vue

@ -39,6 +39,17 @@
<CorrectionItem :exam-detail-id="examList[currentIndex].id" v-if="examList.length" :exam-id="examIdVal"/>
<ExamUpgrade :exam-detail-id="examList[currentIndex].id" v-if="examList.length" :exam-id="examIdVal"/>
</view>
<uv-popup ref="popup" mode="bottom" overlayOpacity="0.1" round="15" safe-area-inset-bottom>
<view class="p-50">
<view class="text-25 mb-25">
<text>正确答案:</text>
<text class="text-blue font-bold">{{ correctContent }}</text>
</view>
<uv-button type="primary" shape="circle" @click="doNext">下一题
</uv-button>
</view>
<uv-gap height="20rpx"></uv-gap>
</uv-popup>
</view>
</template>
@ -62,6 +73,16 @@ import {$toast} from "@/utils";
const currentIndex = ref(0)
const progress = ref(0)
const popup = ref()
const correctContent = ref('')
const doNext = () => {
popup.value.close()
correctContent.value = ''
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else done()
}
const selectedAnswerIndex = ref([])
const selectAnswer = (index) => {
@ -94,8 +115,9 @@ const next = () => {
paperId: paperIdVal,
detailId: currentExam.id,
getScore: currentExam.score,
examType: 3,
examType: 4,
examId: examIdVal,
startTime,
userAnswer: JSON.stringify(answerList.map(i => i.content))
})
correctNext()
@ -110,24 +132,32 @@ const next = () => {
paperId: paperIdVal,
detailId: currentExam.id,
getScore: 0,
examType: 3,
examType: 4,
startTime,
examId: examIdVal,
userAnswer: JSON.stringify(answerList.filter((_, index) => selectedAnswerIndex.value.includes(index)).map(i => i.content))
})
uni.showModal({
title: '答题错误',
content: `正确答案为: ${correctList.map(i => i.content).join(', ')}`,
showCancel: false,
confirmText: '知道了',
success: async ({confirm}) => {
if (confirm) {
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else await done()
}
// uni.showModal({
// title: '',
// content: `: ${correctList.map(i => i.content).join(', ')}`,
// showCancel: false,
// confirmText: '',
// success: async ({confirm}) => {
// if (confirm) {
// if (currentIndex.value < examList.value.length - 1) {
// currentIndex.value++
// selectedAnswerIndex.value = []
// } else await done()
// }
// }
// })
for (let i = 0; i < answerList.length; i++) {
if (answerList[i].isCorrect) {
correctContent.value += `${ANSWER_CHAR[i]}${answerList[i].content}, `
}
})
}
correctContent.value = correctContent.value.slice(0, -2)
popup.value.open()
}
} else {
const answer = answerList[selectedAnswerIndex.value[0]]
@ -145,36 +175,48 @@ const next = () => {
courseId: examList.value[0].courseId,
type: 1
})
uni.showModal({
title: '答题错误',
content: `正确答案为: ${correct.content}`,
showCancel: false,
confirmText: '知道了',
success: async ({confirm}) => {
if (confirm) {
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else await done()
}
// uni.showModal({
// title: '',
// content: `: ${correct.content}`,
// showCancel: false,
// confirmText: '',
// success: async ({confirm}) => {
// if (confirm) {
// if (currentIndex.value < examList.value.length - 1) {
// currentIndex.value++
// selectedAnswerIndex.value = []
// } else await done()
// }
// }
// })
for (let i = 0; i < answerList.length; i++) {
if (answerList[i].isCorrect) {
if (currentExam.type === 'single')
correct = `${ANSWER_CHAR[i]}${answerList[i].content}`
else correct = answerList[i].content
break
}
})
}
correctContent.value = correct
popup.value.open()
resultList.push({
paperId: paperIdVal,
detailId: currentExam.id,
getScore: 0,
examType: 3,
examType: 4,
examId: examIdVal,
userAnswer: answer.content
userAnswer: answer.content,
startTime
})
} else {
resultList.push({
paperId: paperIdVal,
detailId: currentExam.id,
getScore: currentExam.score,
examType: 3,
examType: 4,
examId: examIdVal,
userAnswer: answer.content
userAnswer: answer.content,
startTime
})
correctNext()
}
@ -192,11 +234,10 @@ const correctNext = () => {
const resultList = []
const done = async () => {
uni.showLoading({title: '正在提交'})
await examResultActionReq(resultList)
await trainExamAddTimeReq({
examId: examIdVal,
learnUseTime: dayjs().unix() - startTime
})
await examResultActionReq(resultList.map(i => {
i.addTime = true
return i
}))
uni.hideLoading()
await uni.navigateTo({url: `/pages/match/result?correctNum=${correctNum}&mode=rand`})
}
@ -238,7 +279,7 @@ const getExamList = async (paperId, takeDiffNumList, takeTypeNumList) => {
const back = async () => {
await uni.navigateBack()
}
let paperIdVal = null, examIdVal = null, startTime = null, endTime = null, takeDiffNumListVal = null,
let paperIdVal = null, examIdVal = null, startTime = dayjs().unix(), endTime = null, takeDiffNumListVal = null,
takeTypeNumListVal = null
onLoad(({paperId, examId, takeTypeNumList}) => {
currentIndex.value = 0
@ -247,6 +288,10 @@ onLoad(({paperId, examId, takeTypeNumList}) => {
correctNum = 0
selectedAnswerIndex.value = []
takeTypeNumListVal = takeTypeNumList
// trainExamAddTimeReq({
// examId: examIdVal,
// learnUseTime: dayjs().unix() - startTime
// })
})
onShow(() => {

131
src/pages/exam/train/sortExam.vue

@ -39,6 +39,17 @@
<CorrectionItem :exam-detail-id="examList[currentIndex].id" v-if="examList.length" :exam-id="examIdVal"/>
<ExamUpgrade :exam-detail-id="examList[currentIndex].id" v-if="examList.length" :exam-id="examIdVal"/>
</view>
<uv-popup ref="popup" mode="bottom" overlayOpacity="0.1" round="15" safe-area-inset-bottom>
<view class="p-50">
<view class="text-25 mb-25">
<text>正确答案:</text>
<text class="text-blue font-bold">{{ correctContent }}</text>
</view>
<uv-button type="primary" shape="circle" @click="doNext">下一题
</uv-button>
</view>
<uv-gap height="20rpx"></uv-gap>
</uv-popup>
</view>
</template>
@ -75,9 +86,20 @@ const selectAnswer = (index) => {
}
let correctNum = 0
const popup = ref()
const correctContent = ref('')
const doNext = () => {
popup.value.close()
correctContent.value = ''
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
} else saveRes()
}
const next = () => {
if (!selectedAnswerIndex.value.length) return $toast('请选择答案')
correctContent.value = ''
const currentExam = examList.value[currentIndex.value]
const answerList = JSON.parse(currentExam.answer)
if (['multi'].includes(currentExam.type)) {
@ -97,6 +119,7 @@ const next = () => {
getScore: currentExam.score,
examType: 3,
examId: examIdVal,
startTime,
userAnswer: JSON.stringify(answerList.map(i => i.content))
})
correctNext()
@ -114,23 +137,31 @@ const next = () => {
examType: 3,
examId: examIdVal,
userAnswer: JSON.stringify(answerList.filter((_, index) => selectedAnswerIndex.value.includes(index)).map(i => i.content)),
isCorrect: true
isCorrect: true,
startTime
})
uni.showModal({
title: '答题错误',
content: `正确答案为: ${correctList.map(i => i.content).join(', ')}`,
showCancel: false,
confirmText: '知道了',
success: async ({confirm}) => {
if (confirm) {
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
saveRes()
} else await done()
}
for (let i = 0; i < answerList.length; i++) {
if (answerList[i].isCorrect) {
correctContent.value += `${ANSWER_CHAR[i]}${answerList[i].content}, `
}
})
}
correctContent.value = correctContent.value.slice(0, -2)
popup.value.open()
// uni.showModal({
// title: '',
// content: `: ${correctList.map(i => i.content).join(', ')}`,
// showCancel: false,
// confirmText: '',
// success: async ({confirm}) => {
// if (confirm) {
// if (currentIndex.value < examList.value.length - 1) {
// currentIndex.value++
// selectedAnswerIndex.value = []
// saveRes()
// } else await done()
// }
// }
// })
}
} else {
const answer = answerList[selectedAnswerIndex.value[0]]
@ -148,28 +179,39 @@ const next = () => {
courseId: examList.value[0].courseId,
type: 1
})
uni.showModal({
title: '答题错误',
content: `正确答案为: ${correct.content}`,
showCancel: false,
confirmText: '知道了',
success: async ({confirm}) => {
if (confirm) {
if (currentIndex.value < examList.value.length - 1) {
currentIndex.value++
selectedAnswerIndex.value = []
saveRes()
} else await done()
}
// uni.showModal({
// title: '',
// content: `: ${correct.content}`,
// showCancel: false,
// confirmText: '',
// success: async ({confirm}) => {
// if (confirm) {
// if (currentIndex.value < examList.value.length - 1) {
// currentIndex.value++
// selectedAnswerIndex.value = []
// saveRes()
// } else await done()
// }
// }
// })
for (let i = 0; i < answerList.length; i++) {
if (answerList[i].isCorrect) {
if (currentExam.type === 'single')
correct = `${ANSWER_CHAR[i]}${answerList[i].content}`
else correct = answerList[i].content
break
}
})
}
correctContent.value = correct
popup.value.open()
resultList.push({
paperId: paperIdVal,
detailId: currentExam.id,
getScore: 0,
examType: 3,
examId: examIdVal,
userAnswer: answer.content
userAnswer: answer.content,
startTime
})
} else {
resultList.push({
@ -179,7 +221,8 @@ const next = () => {
examType: 3,
examId: examIdVal,
userAnswer: answer.content,
isCorrect: true
isCorrect: true,
startTime
})
correctNext()
}
@ -189,7 +232,12 @@ const next = () => {
const saveRes = () => {
if (resultList.length % 3 === 0) {
// 3
examResultActionReq(resultList.filter((_, i) => i > resultList.length - 4))
const list = resultList.filter((_, i) => i > resultList.length - 4).map(i => {
i.addTime = false
return i
})
examResultActionReq(list)
startTime = dayjs().unix()
}
}
@ -205,11 +253,10 @@ const correctNext = () => {
const resultList = []
const done = async () => {
uni.showLoading({title: '正在提交'})
await examResultActionReq(resultList)
await trainExamAddTimeReq({
examId: examIdVal,
learnUseTime: dayjs().unix() - startTime
})
await examResultActionReq(resultList.map(i => {
i.addTime = true
return i
}))
uni.hideLoading()
await uni.navigateTo({url: `/pages/match/result?correctNum=${correctNum}&mode=sort`})
}
@ -217,7 +264,10 @@ const done = async () => {
const examList = ref([])
const getExamList = async (paperId) => {
const res = await paperDetailListReq({paperId})
const res = await paperDetailListReq({
paperId,
type: typeVal ?? null
})
examList.value = []
if (res) {
examList.value = res.data
@ -227,11 +277,12 @@ const getExamList = async (paperId) => {
const back = async () => {
await uni.navigateBack()
}
let paperIdVal = null, examIdVal = null, startTime = null, endTime = null
onLoad(({paperId, index, examId}) => {
let paperIdVal = null, examIdVal = null, startTime = dayjs().unix(), endTime = null, typeVal = null
onLoad(({paperId, index, examId, type}) => {
currentIndex.value = parseInt(index)
paperIdVal = parseInt(paperId)
examIdVal = parseInt(examId)
if (type) typeVal = type
correctNum = 0
selectedAnswerIndex.value = []
getExamList(paperId)

387
src/pages/index/components/articleListComponent.vue

@ -1,151 +1,170 @@
<template>
<view class="share-box">
<template v-if="articleList.length > 0">
<view class="same-item" v-for="(item,index) in articleList" :key="index">
<view class="same-top">
<uv-avatar :src="item.userDetail.avatar ?? '/static/logo.jpg'" size="64rpx"></uv-avatar>
<view class="name">{{ item.userDetail.realname }}</view>
<view class="zhu zhued" @click="followAction(item.userId, index)">{{
item.hasFollow ? '已关注' : '关注'
}}
</view>
</view>
<view class="same-img">
<view :class="['img', {pic: JSON.parse(item.album).length === 1}]"
v-for="(img,idx) in JSON.parse(item.album)"
:key="idx">
<uv-image :src="img" radius="20rpx" width="100%" height="100%"
@click="handPreviewImage(JSON.parse(item.album), idx)"></uv-image>
</view>
</view>
<view class="text">
<uv-text :text="item.title" size="28rpx"
lineHeight="48rpx" :lines="2" bold color="#333"></uv-text>
</view>
<view class="between">
<view class="num">
<text class="grey">{{ item.friendlyTime }}</text>
</view>
<view class="msg" @click="openComment(item.id, index)">
<uv-image src="/static/image/i-msg.png" width="40rpx" height="40rpx"></uv-image>
<view class="shu grey">{{ item.commentNumbers }}</view>
</view>
<view class="msg" @click="changeLike(item.id, index)">
<uv-icon name="thumb-up" color="#1fc92e" v-if="!item.hasLike" size="40rpx"/>
<uv-icon name="thumb-up-fill" color="#1fc92e" v-else size="40rpx"/>
<view class="shu shued">{{ item.likes }}</view>
</view>
<uv-image src="/static/image/i-nav.png" width="40rpx" height="40rpx"></uv-image>
</view>
<view class="share-box">
<template v-if="articleList.length > 0">
<view class="same-item" v-for="(item,index) in articleList" :key="index">
<view class="same-top">
<uv-avatar :src="(item.user && item.user.avatar) ? item.user.avatar : '/static/logo.jpg'"
size="64rpx"></uv-avatar>
<view class="name">**{{ item.userDetail.realname.slice(-2) }}</view>
<view class="zhu zhued" @click="followAction(item.userId, index)" v-if="showFollow">{{
item.hasFollow ? '已关注' : '关注'
}}
</view>
</view>
<view class="same-img">
<view :class="['img', {pic: JSON.parse(item.album).length === 1}]"
v-for="(img,idx) in JSON.parse(item.album)"
:key="idx">
<uv-image :src="img" radius="20rpx" width="100%" height="100%"
@click="handPreviewImage(JSON.parse(item.album), idx)"></uv-image>
</view>
</view>
<view class="text">
<uv-text :text="item.title" size="28rpx"
lineHeight="48rpx" :lines="2" bold color="#333"></uv-text>
</view>
<view class="between">
<view class="num">
<text class="grey">{{ item.friendlyTime }}</text>
</view>
<view class="msg" @click="openComment(item.id, index)">
<uv-image src="/static/image/i-msg.png" width="40rpx" height="40rpx"></uv-image>
<view class="shu grey">{{ item.commentNumbers }}</view>
</view>
<view class="msg" @click="changeLike(item.id, index)">
<uv-icon name="thumb-up" color="#1fc92e" v-if="!item.hasLike" size="40rpx"/>
<uv-icon name="thumb-up-fill" color="#1fc92e" v-else size="40rpx"/>
<view class="shu shued">{{ item.likes }}</view>
</view>
<uv-image src="/static/image/i-nav.png" width="40rpx" height="40rpx"></uv-image>
<template v-if="showEdit">
<view class="mx-15">
<uv-button shape="circle" size="mini" @click="$jump(`/pages/index/publish?id=${item.id}`)" type="warning">编辑</uv-button>
</view>
</template>
<uv-empty v-else/>
<uv-popup ref="commentPopup" mode="bottom" round="15" closeable>
<view style="max-height: 800rpx" class="p-30">
<uv-empty v-if="commentList.length === 0" mode="list" text="暂无评论"/>
<view v-else>
<view v-for="(item, index) in commentList" :key="index">
<view class="flex justify-start items-center">
<uv-avatar :src="item.userDetail.avatar ?? '/static/logo.jpg'" size="64rpx"></uv-avatar>
<view class="name ml-25">{{ item.userDetail.realname }}</view>
</view>
<view class="my-20">{{ item.content }}</view>
<view class="mt-20 text-right text-gray text-25">
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
</view>
</view>
</view>
<view class="mt-30">
<uv-button type="primary" shape="circle" @click="openSetComment">发表评论</uv-button>
</view>
<uv-button shape="circle" size="mini" @click="removeArticle(item.id)" type="error">删除</uv-button>
</template>
</view>
</view>
</template>
<uv-empty v-else/>
<uv-popup ref="commentPopup" mode="bottom" round="15" closeable>
<view style="max-height: 800rpx" class="p-30">
<uv-empty v-if="commentList.length === 0" mode="list" text="暂无评论"/>
<view v-else>
<view v-for="(item, index) in commentList" :key="index">
<view class="flex justify-start items-center">
<uv-avatar :src="item.userDetail.avatar ?? '/static/logo.jpg'" size="64rpx"></uv-avatar>
<view class="name ml-25">{{ item.userDetail.realname }}</view>
</view>
<uv-gap height="100rpx"/>
</uv-popup>
<uv-modal ref="commentModal" title="评论" @confirm="saveComment" show-cancel-button>
<view class="w-100p">
<uv-textarea v-model="commentContent" placeholder="请输入评论内容"></uv-textarea>
<view class="my-20">{{ item.content }}</view>
<view class="mt-20 text-right text-gray text-25">
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
</view>
</uv-modal>
</view>
</view>
</view>
<view class="mt-30">
<uv-button type="primary" shape="circle" @click="openSetComment">发表评论</uv-button>
</view>
</view>
<uv-gap height="100rpx"/>
</uv-popup>
<uv-modal ref="commentModal" title="评论" @confirm="saveComment" show-cancel-button>
<view class="w-100p">
<uv-textarea v-model="commentContent" placeholder="请输入评论内容"></uv-textarea>
</view>
</uv-modal>
</view>
</template>
<script setup>
import dayjs from "dayjs";
import {ref, onMounted, nextTick} from "vue";
import {ref} from "vue";
import {matchArticleCommentActionReq, matchArticleCommentListReq, matchArticleLikeAction} from "@/api/article";
import {$toast} from "@/utils";
import {followActionReq} from "@/api/user-follow";
const props = defineProps({
articleList: Array,
articleList: Array,
showFollow: {
type: Boolean,
default: true
},
showEdit: {
type: Boolean,
default: false
},
})
const emits = defineEmits(['done'])
const commentList = ref([])
const getCommentList = async () => {
const {data} = await matchArticleCommentListReq({articleId: clickedArticleId.value})
commentList.value = data
const {data} = await matchArticleCommentListReq({articleId: clickedArticleId.value})
commentList.value = data
}
const clickedArticleId = ref(null)
const clickedArticleIndex = ref(null)
const commentPopup = ref()
const openComment = (id, index) => {
clickedArticleId.value = id
clickedArticleIndex.value = index
commentPopup.value.open()
getCommentList()
clickedArticleId.value = id
clickedArticleIndex.value = index
commentPopup.value.open()
getCommentList()
}
const commentContent = ref('')
const saveComment = async () => {
const res = await matchArticleCommentActionReq({
articleId: clickedArticleId.value,
content: commentContent.value
})
if (res) {
$toast('评论成功')
commentContent.value = ''
await getCommentList()
props.articleList[clickedArticleIndex.value].commentNumbers++
}
const res = await matchArticleCommentActionReq({
articleId: clickedArticleId.value,
content: commentContent.value
})
if (res) {
$toast('评论成功')
commentContent.value = ''
await getCommentList()
props.articleList[clickedArticleIndex.value].commentNumbers++
}
}
const commentModal = ref()
const openSetComment = () => {
commentContent.value = ''
commentModal.value.open()
commentContent.value = ''
commentModal.value.open()
}
const changeLike = async (articleId, index) => {
if (props.articleList[index].hasLike) {
props.articleList[index].likes--
} else {
props.articleList[index].likes++
}
props.articleList[index].hasLike = !props.articleList[index].hasLike
await matchArticleLikeAction({articleId})
if (props.articleList[index].hasLike) {
props.articleList[index].likes--
} else {
props.articleList[index].likes++
}
props.articleList[index].hasLike = !props.articleList[index].hasLike
await matchArticleLikeAction({articleId})
}
const followAction = async (followUserId, index) => {
await followActionReq({followUserId})
// props.articleList[index].hasFollow = !props.articleList[index].hasFollow
emits('done')
$toast('操作成功')
await followActionReq({followUserId})
// props.articleList[index].hasFollow = !props.articleList[index].hasFollow
emits('done')
$toast('操作成功')
}
const handPreviewImage = (urls, index) => {
uni.previewImage({
current: index,
urls,
longPressActions: {
// itemList: ['', '', ''],
success: function (data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
}
}
})
uni.previewImage({
current: index,
urls,
longPressActions: {
// itemList: ['', '', ''],
success: function (data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
}
}
})
}
const removeArticle = async (id) => {
}
// onMounted(() => {
@ -159,104 +178,104 @@ const handPreviewImage = (urls, index) => {
<style lang="scss" scoped>
.same-item {
margin-top: 30rpx;
margin-top: 30rpx;
.text {
padding: 10rpx 0;
}
.text {
padding: 10rpx 0;
}
.between {
display: flex;
align-items: center;
padding: 20rpx 0 30rpx;
font-size: 26rpx;
line-height: 40rpx;
color: $dark-color;
border-bottom: 1px solid $border-color;
}
.between {
display: flex;
align-items: center;
padding: 20rpx 0 30rpx;
font-size: 26rpx;
line-height: 40rpx;
color: $dark-color;
border-bottom: 1px solid $border-color;
}
.blue {
color: $blue-color;
}
.blue {
color: $blue-color;
}
.red {
color: $red-color;
}
.red {
color: $red-color;
}
.grey {
color: $grey-color;
}
.num {
flex: 1;
}
.grey {
color: $grey-color;
.msg {
display: flex;
align-items: center;
margin: 0 10rpx;
.shu {
margin: 0rpx 10rpx;
}
.num {
flex: 1;
.shued {
color: $green-color;
}
}
.msg {
display: flex;
align-items: center;
margin: 0 10rpx;
.same-top {
display: flex;
align-items: center;
padding-bottom: 20rpx;
.shu {
margin: 0rpx 10rpx;
}
.name {
flex: 1;
padding: 0 10rpx;
font-size: 24rpx;
line-height: 40rpx;
color: $minor-color;
}
.shued {
color: $green-color;
}
.zhu {
display: inline-block;
padding: 0 20rpx;
font-size: 24rpx;
line-height: 44rpx;
color: $minor-color;
border: 1px solid $minor-color;
border-radius: 22rpx;
}
.same-top {
display: flex;
align-items: center;
padding-bottom: 20rpx;
.name {
flex: 1;
padding: 0 10rpx;
font-size: 24rpx;
line-height: 40rpx;
color: $minor-color;
}
.zhu {
display: inline-block;
padding: 0 20rpx;
font-size: 24rpx;
line-height: 44rpx;
color: $minor-color;
border: 1px solid $minor-color;
border-radius: 22rpx;
}
.zhued {
color: $grey-color;
border-color: $grey-color;
}
.zhued {
color: $grey-color;
border-color: $grey-color;
}
}
.same-img {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.img {
margin: 10rpx 0;
width: 334rpx;
height: 240rpx;
}
.pic {
width: 100%;
height: 400rpx !important;
}
.same-img {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.img {
margin: 10rpx 0;
width: 334rpx;
height: 240rpx;
}
.img:last-child:nth-child(2n - 1) {
width: 100% !important;
.pic {
width: 100%;
height: 400rpx !important;
}
}
.img:last-child:nth-child(2n - 1) {
width: 100% !important;
}
}
.same-item:nth-child(1) {
margin-top: 10rpx;
margin-top: 10rpx;
}
</style>

59
src/pages/index/components/tab0.vue

@ -1,7 +1,7 @@
<template>
<view>
<view class="layout-banner">
<uv-swiper :list="imgList" indicator indicatorMode="dot" height="300rpx" radius="30rpx"></uv-swiper>
<uv-swiper :list="imgList" indicator indicatorMode="dot" height="300rpx" radius="0"></uv-swiper>
</view>
<!-- 新闻资讯 -->
<view class="layout-news">
@ -19,13 +19,20 @@
</view>
</view>
<!-- 五分区 -->
<view class="layout-fifth">
<view class="fifth-item" v-for="(item,index) in fifthList" :key="index"
@click="handFifth(item.type)">
<view class="icon">
<uv-image :src="item.icon" width="60rpx" height="60rpx"></uv-image>
<view class="pos-r">
<view class="layout-fifth">
<view class="fifth-item" v-for="(item,index) in fifthList" :key="index"
@click="handFifth(item.type)">
<view class="icon">
<uv-image :src="item.icon" width="60rpx" height="60rpx"></uv-image>
</view>
<view class="text">{{ item.name }}</view>
</view>
</view>
<view class="pos-a" style="right: 0;top: 20rpx">
<view class="flex justify-center items-center" style="height: 100rpx; background-color: #EEE">
<uv-icon name="arrow-right" color="white" size="30rpx"/>
</view>
<view class="text">{{ item.name }}</view>
</view>
</view>
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
@ -33,7 +40,7 @@
<view class="p-20 border-bottom">
<view class="flex justify-start items-center" @click="$jump(`/pages/article/info?id=${item.articleId}`)">
<uv-icon name="/static/image/hot.png" v-if="item.recommend === 1"/>
<view class="text-30 font-bold ml-10">{{ item.title }}</view>
<view class="text-30 font-bold">{{ item.title }}</view>
</view>
<view class="mt-20 text-25 text-gray">
<view class="flex justify-start items-center">
@ -48,20 +55,20 @@
{{ item.actualViews + item.virtualViews }} 浏览
</text>
</view>
<view @click="$jump(`/pages/article/info?id=${item.articleId}`)" class="mt-20 text-25 text-black line-2"
v-if="item.comments">{{ item.comments }}
</view>
<!-- <view @click="$jump(`/pages/article/info?id=${item.articleId}`)" class="mt-20 text-25 text-black line-2"-->
<!-- v-if="item.comments">{{ item.comments }}-->
<!-- </view>-->
<view class="mt-20">
<uv-image v-if="item.album && item.album.length === 1 && item.album[0]" :src="item.album[0].url" radius="15"
<uv-image v-if="item.album && item.album.length === 1 && item.album[0]" :src="item.album[0].url" radius="0"
width="710rpx" height="710rpx" @click="handPreviewImage(item.album, 0)"/>
<view v-else-if="item.album && item.album.length === 2"
class="flex justify-center items-center">
<view class="mx-10">
<uv-image :src="item.album[0].url" @click="handPreviewImage(item.album, 0)" radius="15" width="340rpx"
<uv-image :src="item.album[0].url" @click="handPreviewImage(item.album, 0)" radius="0" width="340rpx"
height="340rpx"/>
</view>
<view class="mx-10">
<uv-image :src="item.album[1].url" @click="handPreviewImage(item.album, 1)" radius="15" width="340rpx"
<uv-image :src="item.album[1].url" @click="handPreviewImage(item.album, 1)" radius="0" width="340rpx"
height="340rpx"/>
</view>
</view>
@ -69,36 +76,36 @@
v-else-if="item.album && item.album.length === 3">
<view class="flex justify-center items-center mb-20">
<view class="mx-10">
<uv-image :src="item.album[0].url" @click="handPreviewImage(item.album, 0)" radius="15" width="340rpx"
<uv-image :src="item.album[0].url" @click="handPreviewImage(item.album, 0)" radius="0" width="340rpx"
height="340rpx"/>
</view>
<view class="mx-10">
<uv-image :src="item.album[1].url" @click="handPreviewImage(item.album, 1)" radius="15" width="340rpx"
<uv-image :src="item.album[1].url" @click="handPreviewImage(item.album, 1)" radius="0" width="340rpx"
height="340rpx"/>
</view>
</view>
<uv-image :src="item.album[2].url" @click="handPreviewImage(item.album, 2)" radius="15" width="710rpx"
<uv-image :src="item.album[2].url" @click="handPreviewImage(item.album, 2)" radius="0" width="710rpx"
height="340rpx"/>
</view>
<view class="flex flex-col justify-center items-center"
v-else-if="item.album && item.album.length === 4">
<view class="flex justify-center items-center mb-20">
<view class="mx-10">
<uv-image :src="item.album[0].url" @click="handPreviewImage(item.album, 0)" radius="15" width="340rpx"
<uv-image :src="item.album[0].url" @click="handPreviewImage(item.album, 0)" radius="0" width="340rpx"
height="340rpx"/>
</view>
<view class="mx-10">
<uv-image :src="item.album[1].url" @click="handPreviewImage(item.album, 1)" radius="15" width="340rpx"
<uv-image :src="item.album[1].url" @click="handPreviewImage(item.album, 1)" radius="0" width="340rpx"
height="340rpx"/>
</view>
</view>
<view class="flex justify-center items-center">
<view class="mx-10">
<uv-image :src="item.album[2].url" @click="handPreviewImage(item.album, 2)" radius="15" width="340rpx"
<uv-image :src="item.album[2].url" @click="handPreviewImage(item.album, 2)" radius="0" width="340rpx"
height="340rpx"/>
</view>
<view class="mx-10">
<uv-image :src="item.album[3].url" @click="handPreviewImage(item.album, 3)" radius="15" width="340rpx"
<uv-image :src="item.album[3].url" @click="handPreviewImage(item.album, 3)" radius="0" width="340rpx"
height="340rpx"/>
</view>
</view>
@ -735,6 +742,12 @@ onMounted(async () => {
.layout-fifth {
padding: 10rpx 20rpx;
background: #fff;
display: flex;
align-items: center;
justify-content: flex-start;
overflow-x: scroll;
width: 730rpx;
position: relative;
.fifth-scroll {
white-space: nowrap;
@ -742,8 +755,8 @@ onMounted(async () => {
}
.fifth-item {
display: inline-block;
width: 20%;
//display: inline-block;
flex: 0 0 20%;
height: auto;
padding: 10rpx 0;
overflow: hidden;

4
src/pages/index/components/tab3.vue

@ -11,11 +11,11 @@
<view class="grad-item" v-for="(item,index) in articleCateList" :key="index"
@click="$jump(`/pages/article/list?title=${item.title}&id=${item.categoryId}`)">
<view class="img">
<uv-image :src="item.image" radius="10rpx" width="100%" height="100%"></uv-image>
<uv-image :src="item.image" radius="0" width="100%" height="100%"></uv-image>
</view>
<view class="name">
<uv-text :text="item.title" size="28rpx" lineHeight="40rpx" :lines="1"
color="#333"></uv-text>
color="#333" align="center"/>
</view>
</view>
</view>

10
src/pages/index/index.vue

@ -2,7 +2,7 @@
<view class="container">
<uv-sticky bgColor="#fff" customNavHeight="0">
<view class="statusbar"></view>
<view class="layout-title">工匠基地</view>
<!-- <view class="layout-title">工匠基地</view>-->
<!-- 搜索区 -->
<view class="layout-search">
<uv-search placeholder="请输入搜索内容" :disabled="true" @click="$jump(`/pages/index/search`)"
@ -17,7 +17,7 @@
</view>
<!-- 选项卡 -->
<view class="layout-tab">
<view :class="['tab-item',{active:tabIndex==index}]" v-for="(item,index) in list" :key="index"
<view :class="['tab-item',{active:tabIndex === index}]" v-for="(item,index) in list" :key="index"
@click="handTab(index)">
{{ item.name }}
</view>
@ -229,6 +229,7 @@ export default {
page {
padding-top: var(--status-bar-height);
background: #fff;
overflow-x: hidden;
}
.statusbar {
@ -301,6 +302,7 @@ page {
.share-tab {
display: flex;
align-items: center;
justify-content: space-around;
.tab-item {
//flex: 1;
@ -336,8 +338,8 @@ page {
.tab-item {
//flex-shrink: 0;
position: relative;
margin: 0 16rpx;
padding: 10rpx 4rpx;
//margin: 0 16rpx;
padding: 10rpx 0;
font-size: 32rpx;
line-height: 56rpx;
color: $dark-color;

427
src/pages/index/publish.vue

@ -1,246 +1,259 @@
<template>
<view class="wrap">
<view class="layout-share">
<view class="video-box">
<!-- <view class="video-image">-->
<!-- <view class="img">-->
<!-- <uv-image src="/static/image/cover.png" width="220rpx" height="240rpx"></uv-image>-->
<!-- </view>-->
<!-- <view class="choice">选择封面</view>-->
<!-- </view>-->
<view class="video-text">
<uv-textarea
v-model="textareaValue"
placeholder="取个标题吧~"
height="250rpx"
:count="true"
maxlength="50"
:customStyle="customStyle"
:countStyl="countStyle"
border="none"
></uv-textarea>
</view>
</view>
<view class="flex justify-start items-start flex-wrap">
<view class="pos-r album-item" v-for="(item, index) in imgList" :key="index">
<uv-image :src="item" mode="aspectFill" width="220rpx" height="220rpx"/>
<view class="del">
<uv-icon name="close" color="white" @click="delImg(index)"/>
</view>
</view>
<view class="flex justify-center items-center album-item" @click="upload">
<uv-icon name="camera" size="70rpx"/>
</view>
</view>
<!-- <uv-cell-group>
<uv-cell
icon="grid"
title="分类"
value="项目一号"
:isLink="true"
:clickable="false"
></uv-cell>
</uv-cell-group> -->
<view class="cell-box">
<!-- <view class="cell-item islink">-->
<!-- <view class="icon">-->
<!-- <uv-image src="/static/image/pu-1.png" width="32rpx" height="32rpx"></uv-image>-->
<!-- </view>-->
<!-- <view class="text">分类</view>-->
<!-- <view class="value">项目一号</view>-->
<!-- </view>-->
<view class="cell-item">
<view class="icon">
<uv-image src="/static/image/pu-2.png" width="32rpx" height="32rpx" mode="aspectFit"></uv-image>
</view>
<view class="text">所有人可见</view>
<uv-switch v-model="isPublic" activeColor="#fbd153" style="transform:scale(0.7)"/>
</view>
</view>
<view class="wrap">
<view class="layout-share">
<view class="video-box">
<!-- <view class="video-image">-->
<!-- <view class="img">-->
<!-- <uv-image src="/static/image/cover.png" width="220rpx" height="240rpx"></uv-image>-->
<!-- </view>-->
<!-- <view class="choice">选择封面</view>-->
<!-- </view>-->
<view class="video-text">
<uv-textarea
v-model="textareaValue"
placeholder="取个标题吧~"
height="250rpx"
:count="true"
maxlength="50"
:customStyle="customStyle"
:countStyl="countStyle"
border="none"
></uv-textarea>
</view>
<view class="layout-fixed">
<view class="share-btn" @click="submit">分享</view>
</view>
<view class="flex justify-start items-start flex-wrap">
<view class="pos-r album-item" v-for="(item, index) in imgList" :key="index">
<uv-image :src="item" mode="aspectFill" width="220rpx" height="220rpx"/>
<view class="del">
<uv-icon name="close" color="white" @click="delImg(index)"/>
</view>
</view>
<view class="flex justify-center items-center album-item" @click="upload">
<uv-icon name="camera" size="70rpx"/>
</view>
</view>
<!-- <uv-cell-group>
<uv-cell
icon="grid"
title="分类"
value="项目一号"
:isLink="true"
:clickable="false"
></uv-cell>
</uv-cell-group> -->
<view class="cell-box">
<!-- <view class="cell-item islink">-->
<!-- <view class="icon">-->
<!-- <uv-image src="/static/image/pu-1.png" width="32rpx" height="32rpx"></uv-image>-->
<!-- </view>-->
<!-- <view class="text">分类</view>-->
<!-- <view class="value">项目一号</view>-->
<!-- </view>-->
<view class="cell-item">
<view class="icon">
<uv-image src="/static/image/pu-2.png" width="32rpx" height="32rpx" mode="aspectFit"></uv-image>
</view>
<view class="text">所有人可见</view>
<uv-switch v-model="isPublic" activeColor="#fbd153" style="transform:scale(0.7)"/>
</view>
</view>
</view>
<view class="layout-fixed">
<view class="share-btn" @click="submit">分享</view>
</view>
</view>
</template>
<script>
import {$toast, chooseImg, getLocationAction} from "@/utils";
import {matchArticleActionReq} from "@/api/article";
import {matchArticleActionReq, matchArticleInfoReq} from "@/api/article";
export default {
data() {
return {
textareaValue: '',
customStyle: {
background: '#f7f7f7',
},
countStyle: {
backgroundColor: '#f7f7f7',
},
imgList: [],
isPublic: true,
trainId: null
};
data() {
return {
textareaValue: '',
customStyle: {
background: '#f7f7f7',
},
countStyle: {
backgroundColor: '#f7f7f7',
},
imgList: [],
isPublic: true,
trainId: null,
id: null,
};
},
methods: {
async upload() {
const res = await chooseImg(9 - this.imgList.length)
res.forEach(item => {
this.imgList.push(item)
})
},
methods: {
async upload() {
const res = await chooseImg(9 - this.imgList.length)
res.forEach(item => {
this.imgList.push(item)
})
},
delImg(index) {
this.imgList.splice(index, 1)
},
async submit() {
if (this.imgList.length === 0) {
return $toast('请选择图片')
}
if (!this.textareaValue) {
return $toast('请填写标题')
}
const data = {
city: 450100,
province: 450000,
}
data.album = JSON.stringify(this.imgList)
data.title = this.textareaValue
data.isPublic = this.isPublic ? 1 : 0
this.trainId ? data.trainId = this.trainId : null
const res = await matchArticleActionReq(data)
if (res) {
$toast('发布成功')
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
}
delImg(index) {
this.imgList.splice(index, 1)
},
async onLoad(option) {
if (option.trainId) this.trainId = option.trainId
// const res = await getLocationAction()
// console.log(res)
async submit() {
if (this.imgList.length === 0) {
return $toast('请选择图片')
}
if (!this.textareaValue) {
return $toast('请填写标题')
}
const data = {
city: 450100,
province: 450000,
}
data.album = JSON.stringify(this.imgList)
data.title = this.textareaValue
data.isPublic = this.isPublic ? 1 : 0
this.trainId ? data.trainId = this.trainId : null
if (this.id) data.id = this.id
const res = await matchArticleActionReq(data)
if (res) {
$toast('发布成功')
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
},
async getInfo() {
const {data} = await matchArticleInfoReq(this.id)
this.textareaValue = data.title
this.imgList = JSON.parse(data.album)
this.isPublic = data.isPublic
this.trainId = data.trainId
}
},
async onLoad(option) {
if (option.trainId) this.trainId = option.trainId
if (option.id) {
this.id = option.id
await this.getInfo()
}
// const res = await getLocationAction()
// console.log(res)
}
}
</script>
<style lang="scss">
page {
background: #fff;
background: #fff;
}
.video-box {
display: flex;
padding: 50rpx 30rpx;
background: #f7f7f7;
.video-image {
width: 220rpx;
// height: 280rpx;
border: 1px solid #999;
border-radius: 10rpx;
background: #e5e5e5;
overflow: hidden;
.img {
width: 100%;
height: 240rpx;
}
.choice {
height: 48rpx;
font-size: 26rpx;
line-height: 48rpx;
color: #fff;
text-align: center;
background: #000;
}
display: flex;
padding: 50rpx 30rpx;
background: #f7f7f7;
.video-image {
width: 220rpx;
// height: 280rpx;
border: 1px solid #999;
border-radius: 10rpx;
background: #e5e5e5;
overflow: hidden;
.img {
width: 100%;
height: 240rpx;
}
.video-text {
flex: 1;
margin-left: 20rpx;
.choice {
height: 48rpx;
font-size: 26rpx;
line-height: 48rpx;
color: #fff;
text-align: center;
background: #000;
}
}
.video-text {
flex: 1;
margin-left: 20rpx;
}
}
.cell-item {
position: relative;
display: flex;
align-items: center;
padding: 24rpx 30rpx 24rpx 30rpx;
border-bottom: 1px solid #f2f2f2;
.text {
flex: 1;
padding: 0 20rpx;
font-size: 28rpx;
line-height: 32rpx;
color: $minor-color;
}
position: relative;
display: flex;
align-items: center;
padding: 24rpx 30rpx 24rpx 30rpx;
border-bottom: 1px solid #f2f2f2;
.value {
font-size: 28rpx;
line-height: 32rpx;
color: $grey-color;
}
.text {
flex: 1;
padding: 0 20rpx;
font-size: 28rpx;
line-height: 32rpx;
color: $minor-color;
}
.value {
font-size: 28rpx;
line-height: 32rpx;
color: $grey-color;
}
}
.islink {
padding-right: 60rpx !important;
&::after {
position: absolute;
right: 30rpx;
top: 50%;
z-index: 90;
display: block;
margin-top: -6rpx;
transform: rotate(45deg);
content: '';
width: 12rpx;
height: 12rpx;
border-top: 1px solid $dark-color;
border-right: 1px solid $dark-color;
}
padding-right: 60rpx !important;
&::after {
position: absolute;
right: 30rpx;
top: 50%;
z-index: 90;
display: block;
margin-top: -6rpx;
transform: rotate(45deg);
content: '';
width: 12rpx;
height: 12rpx;
border-top: 1px solid $dark-color;
border-right: 1px solid $dark-color;
}
}
.layout-fixed {
position: fixed;
left: 0;
bottom: 0;
z-index: 99;
width: 100%;
height: auto;
padding: 50rpx 0rpx;
.share-btn {
margin: 0 30rpx;
height: 80rpx;
font-size: 32rpx;
line-height: 80rpx;
text-align: center;
color: #fff;
border-radius: 40rpx;
background: #00abf4;
}
position: fixed;
left: 0;
bottom: 0;
z-index: 99;
width: 100%;
height: auto;
padding: 50rpx 0rpx;
.share-btn {
margin: 0 30rpx;
height: 80rpx;
font-size: 32rpx;
line-height: 80rpx;
text-align: center;
color: #fff;
border-radius: 40rpx;
background: #00abf4;
}
}
.album-item {
width: 220rpx;
height: 220rpx;
border: 1px solid #E1E1E1;
.del {
position: absolute;
right: 0;
top: 0;
background-color: red;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
width: 220rpx;
height: 220rpx;
border: 1px solid #E1E1E1;
.del {
position: absolute;
right: 0;
top: 0;
background-color: red;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>

190
src/pages/promote/components/ReviewList.vue

@ -0,0 +1,190 @@
<template>
<view class="layout layout-plan">
<view class="title-box">
<view class="title">复习任务({{ examList.length }})</view>
<view class="text-main text-25 text-center" v-if="examList.length > 5" @click="showAllExam = !showAllExam">{{
showAllExam ? '折叠' : '展开'
}}
</view>
</view>
<view class="exam-box">
<block v-for="(item,index) in examList"
:key="index">
<view class="exam-item" @click="resultLink(item)" v-if="showAllExam || (!showAllExam && index < 5)">
<view class="info info-1">
<view class="name">
<uv-text :text="item.title" size="24rpx" lineHeight="40rpx" :lines="1" bold></uv-text>
</view>
<template v-if="item.type === 0">
<view class="fen" v-if="item.examDateMode === 0">复习截止日期: {{ item.examDate }}</view>
<view class="fen flex justify-start flex-col items-start" v-else>
<text>复习时间段:</text>
<text v-for="(item, index) in JSON.parse(item.examDateList)" :key="index">
{{ item.date.join('~') }}
</text>
</view>
</template>
<view class="fen"
v-if="item.workTypeLists && item.workTypeLists.length > 0 && item.workTypeLists[0].course">复习科目:
{{
item.workTypeLists[0].course.title
}}({{
['初级', '中级', '高级', '技师', '高级技师'][item.workTypeLists[0].course.level]
}})
</view>
<view class="fen flex flex-col justify-start items-start" v-if="item.trainExamPeopleInfo">
<text>复习次数: {{ item.trainExamPeopleInfo.learnTime }}</text>
<text class="mt-10">复习时长: {{ Math.floor(item.trainExamPeopleInfo.learnUseTime / 3600) }}小时
{{ Math.floor(item.trainExamPeopleInfo.learnUseTime % 3600 / 60) }}
{{ item.trainExamPeopleInfo.learnUseTime % 60 }}
</text>
</view>
</view>
</view>
</block>
<uv-empty v-if="!examList.length" text="暂无复习任务"/>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
import {$toast} from "@/utils";
const props = defineProps({
examList: {
type: Array,
default: () => []
}
})
const showAllExam = ref(false)
const resultLink = ({
id,
type,
examId,
paper,
needFinishAdventure,
hasFinishAdventure,
needFinishNormal,
hasFinishNormal
}) => {
if (type === 1) return
let url
if (needFinishAdventure === 1 && !hasFinishAdventure) return $toast('请先完成游戏学')
if (needFinishNormal === 1 && !hasFinishNormal) return $toast('请先完成常规学')
url = `/pages/promote/exam?paperId=${examId}&title=${paper.title}&examType=0&examId=${id}`
uni.navigateTo({url})
}
</script>
<style scoped lang="scss">
.title-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 0;
.title {
font-size: 32rpx;
font-weight: 600;
line-height: 40rpx;
color: $black-color;
}
.link {
position: relative;
padding-right: 30rpx;
font-size: 24rpx;
line-height: 32rpx;
color: $grey-color;
&::after {
position: absolute;
right: 10rpx;
top: 50%;
z-index: 90;
display: block;
margin-top: -6rpx;
transform: rotate(45deg);
content: '';
width: 12rpx;
height: 12rpx;
border-top: 1px solid $grey-color;
border-right: 1px solid $grey-color;
}
}
}
.exam-box {
padding: 10rpx 0 20rpx;
.exam-item {
display: flex;
align-items: center;
margin-top: 24rpx;
padding: 24rpx 24rpx;
border-radius: 16rpx;
border: 1px solid #6c6c6c;
overflow: hidden;
}
.info {
position: relative;
flex: 1;
margin-right: 20rpx;
.fen {
margin-top: 8rpx;
font-size: 24rpx;
line-height: 32rpx;
color: #bababa;
}
}
.info-1 {
min-height: 80rpx;
&::after {
position: absolute;
right: 0%;
top: 50%;
z-index: 9;
margin-top: -25rpx;
content: '';
width: 1px;
height: 50rpx;
background: #f3f3f3;
}
}
.look {
display: inline-block;
width: 110rpx;
height: 44rpx;
font-size: 24rpx;
line-height: 44rpx;
color: #fff;
text-align: center;
border-radius: 22rpx;
background: #00abf4;
}
.between {
display: flex;
align-items: center;
.ren {
width: 100rpx;
font-size: 24rpx;
line-height: 40rpx;
color: $grey-color;
}
.progress {
flex: 1;
margin-right: 20rpx;
}
}
}
</style>

2
src/pages/promote/exam.vue

@ -18,7 +18,7 @@
<uv-icon name="/static/image/rand.png" label="随机练习" label-pos="right" label-color="white"/>
<uv-icon name="arrow-right" color="white"/>
</view>
<view class="card mb-20 flex justify-between items-center py-30 bg-orange" @click="toSim">
<view class="card mb-20 flex justify-between items-center py-30 bg-orange" @click="toSim" v-if="review">
<uv-icon name="empty-favor" label="模拟考试" color="white" label-pos="right" label-color="white"/>
<uv-icon name="arrow-right" color="white"/>
</view>

253
src/pages/promote/promote.vue

@ -20,7 +20,7 @@
<view class="text">当前培训作业学时统计小时</view>
<view class="time">{{ (trainData.learnSec / 3600).toFixed(2) }}</view>
</view>
<view class="record-item" @click="$jump(`/pages/promote/learnProgress`)">
<view class="record-item" @click="$jump(`/pages/promote/learnProgress`)" style="padding: 15rpx 30rpx">
<view class="text">当前培训作业完成比例</view>
<mprogress
:progress="((trainDataRate) * 100).toFixed(2)"
@ -52,42 +52,133 @@
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
<!-- 通知 -->
<view class="layout layout-notice">
<view class="title-box" @click="$jump(`/pages/article/list?title=通知&id=273`)">
<view class="title-box">
<view class="title">通知</view>
<view class="link"></view>
<!-- <view class="link"></view>-->
</view>
<view class="notice-box">
<swiper class="notice-swiper" :autoplay="true" vertical="true">
<swiper-item v-for="(item, index) in newsList" :key="index">
<view class="flex justify-between items-center"
@click="$jump(`/pages/article/info?id=${item.articleId}`)">
<view class="uv-line-1" style="width: 500rpx; height: 32rpx">{{ item.title }}</view>
<view class="date">{{ item.createTime }}</view>
</view>
</swiper-item>
</swiper>
<!-- <view class="flex justify-between items-center"-->
<!-- v-for="(item, index) in newsList" :key="index">-->
<!-- <view class="uv-line-1" style="width: 500rpx; height: 32rpx">{{ item.title }}</view>-->
<!-- <view class="date">{{ item.createTime }}</view>-->
<!-- </view>-->
<MessageItem v-for="(item, index) in newsList" :key="index" :item="item" :index="index"/>
</view>
</view>
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
<!-- 培训计划 -->
<!-- 复习任务 -->
<ReviewList :exam-list="examList.filter(item => item.hasReview)"/>
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
<!-- 考试任务 -->
<view class="layout layout-plan">
<view class="title-box">
<view class="title">培训计划</view>
<view class="title">考试任务({{ examList.length }})</view>
<view class="text-main text-25 text-center" v-if="examList.length > 5" @click="showAllExam = !showAllExam">{{
showAllExam ? '折叠' : '展开'
}}
</view>
<!-- <view class="link"></view>-->
</view>
<!-- <scroll-view class="tab-box" scroll-x="true">-->
<!-- <view :class="['tab-item',{active:tabIndex === index}]" v-for="(item,index) in tabList" :key="index"-->
<!-- @click="handTab(index)">-->
<!-- {{ item.name }}-->
<!-- </view>-->
<!-- </scroll-view>-->
<view class="exam-box">
<view class="exam-item" v-for="(item, index) in trainList.filter(i => i.courseFile)" :key="index"
@click="openCourseFile(item)">
<view class="info">
<view class="name">
<uv-text :text="`${item.workType.title}课表`" size="24rpx" lineHeight="40rpx" :lines="1"
bold></uv-text>
<block v-for="(item,index) in examList"
:key="index">
<view class="exam-item" @click="resultLink(item)" v-if="showAllExam || (!showAllExam && index < 5)">
<view class="info info-1">
<view class="name">
<uv-text :text="item.title" size="24rpx" lineHeight="40rpx" :lines="1" bold></uv-text>
</view>
<view class="fen">考试类型: {{ ['线上', '线下'][item.type] }}</view>
<template v-if="item.type === 1 && item.trainExamPeopleInRoom">
<view v-if="item.trainExamPeopleInRoom.roomConfig" class="fen">考场:
{{ item.trainExamPeopleInRoom.roomConfig.position }}
</view>
<view v-if="item.trainExamPeopleInRoom.examSession" class="fen">考试时间:
{{ item.trainExamPeopleInRoom.examSession.startTime }} ~
{{ item.trainExamPeopleInRoom.examSession.endTime }}
</view>
</template>
<template v-if="item.type === 0">
<view class="fen" v-if="item.examDateMode === 0">考试截止日期: {{ item.examDate }}</view>
<view class="fen flex justify-start flex-col items-start" v-else>
<text>考试时间段:</text>
<text v-for="(item, index) in JSON.parse(item.examDateList)" :key="index">
{{ item.date.join('~') }}
</text>
</view>
</template>
<view class="fen"
v-if="item.workTypeLists && item.workTypeLists.length > 0 && item.workTypeLists[0].course">考试科目:
{{
item.workTypeLists[0].course.title
}}({{
['初级', '中级', '高级', '技师', '高级技师'][item.workTypeLists[0].course.level]
}})
</view>
<view class="fen" v-if="!item.trainExamPeopleInfo">总分 {{ item.paper.totalPoint }} 合格分
{{ item.paper.passPoint }}
</view>
<view class="fen" v-else>
<template v-if="item.text === '已完成' && item.trainExamPeopleInfo.realScore">
<view v-if="item.type === 0 && item.trainId">
<text>考试得分 {{ item.trainExamPeopleInfo.score }}</text>
<text class="ml-15" v-if="item.trainExamPeopleInfo.inWhiteList === 0">平时分
{{ item.trainExamPeopleInfo.normalScore }}
</text>
<text class="ml-15">总分
{{ item.trainExamPeopleInfo.totalScore }}
</text>
<text class="ml-15">实际得分
{{ item.trainExamPeopleInfo.totalScore }}
</text>
</view>
<view v-else>
<text>考试得分 {{ item.trainExamPeopleInfo.score }}</text>
<text class="ml-15" v-if="item.type === 1">实操得分 {{
item.trainExamPeopleInfo.operateScore
}}
</text>
<text class="ml-15">总分
{{ item.trainExamPeopleInfo.realScore }}
</text>
</view>
<view class="mt-15"
:class="[item.trainExamPeopleInfo.totalScore >= 60 ? 'text-green' : 'text-red']"
v-if="item.showResult">{{
item.trainExamPeopleInfo.totalScore >= 60 ? '合格' : '不合格'
}}
</view>
</template>
</view>
<view class="fen"
v-if="item.trainExamPeopleInfo && item.trainExamPeopleInfo.highLevelStatus > 0">
<text>专家评审结果:</text>
<text class="ml-15"
:class="[item.trainExamPeopleInfo.highLevelStatus === 1 ? 'text-green' : 'text-red']">
{{ ['待审核', '已通过', '未通过'][item.trainExamPeopleInfo.highLevelStatus] }}
</text>
</view>
</view>
<mprogress
:progress="item.progress"
:activeColor="item.color"
:valueColor="item.color"
:valueFontSize="12"
:valueText="item.text"
:width="50"
:borderWidth="4"
></mprogress>
</view>
<view class="look">查看</view>
</view>
</block>
<uv-empty v-if="!examList.length" text="暂无考试任务"/>
</view>
<uv-empty v-if="!trainList.length" text="暂无培训计划"/>
</view>
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
<!-- 培训任务 -->
<view class="layout layout-train">
@ -127,106 +218,27 @@
</view>
<uv-empty v-if="!trainList.length" text="暂无培训任务"/>
</view>
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
<!-- 考试任务 -->
<!-- 培训计划 -->
<view class="layout layout-plan">
<view class="title-box">
<view class="title">考试任务</view>
<view class="link"></view>
<view class="title">培训计划</view>
</view>
<!-- <scroll-view class="tab-box" scroll-x="true">-->
<!-- <view :class="['tab-item',{active:tabIndex === index}]" v-for="(item,index) in tabList" :key="index"-->
<!-- @click="handTab(index)">-->
<!-- {{ item.name }}-->
<!-- </view>-->
<!-- </scroll-view>-->
<view class="exam-box">
<view class="exam-item" v-for="(item,index) in examList"
:key="index"
@click="resultLink(item)">
<view class="info info-1">
<view class="exam-item" v-for="(item, index) in trainList.filter(i => i.courseFile)" :key="index"
@click="openCourseFile(item)">
<view class="info">
<view class="name">
<uv-text :text="item.title" size="24rpx" lineHeight="40rpx" :lines="1" bold></uv-text>
</view>
<view class="fen">考试类型: {{ ['线上', '线下'][item.type] }}</view>
<template v-if="item.type === 1 && item.trainExamPeopleInRoom">
<view v-if="item.trainExamPeopleInRoom.roomConfig" class="fen">考场:
{{ item.trainExamPeopleInRoom.roomConfig.position }}
</view>
<view v-if="item.trainExamPeopleInRoom.examSession" class="fen">考试时间:
{{ item.trainExamPeopleInRoom.examSession.startTime }} ~
{{ item.trainExamPeopleInRoom.examSession.endTime }}
</view>
</template>
<template v-if="item.type === 0">
<view class="fen" v-if="item.examDateMode === 0">考试截止日期: {{ item.examDate }}</view>
<view class="fen flex justify-start flex-col items-start" v-else>
<text>考试时间段:</text>
<text v-for="(item, index) in JSON.parse(item.examDateList)" :key="index">
{{ item.date.join('~') }}
</text>
</view>
</template>
<view class="fen" v-if="item.workTypeLists && item.workTypeLists.length > 0 && item.workTypeLists[0].course">考试科目:
{{
item.workTypeLists[0].course.title
}}({{
['初级', '中级', '高级', '技师', '高级技师'][item.workTypeLists[0].course.level]
}})
</view>
<view class="fen" v-if="!item.trainExamPeopleInfo">总分 {{ item.paper.totalPoint }} 合格分
{{ item.paper.passPoint }}
</view>
<view class="fen" v-else>
<template v-if="item.text === '已完成' && item.trainExamPeopleInfo.realScore">
<view v-if="item.type === 0 && item.trainId">
<text>考试得分 {{ item.trainExamPeopleInfo.score }}</text>
<text class="ml-15" v-if="item.trainExamPeopleInfo.inWhiteList === 0">平时分
{{ item.trainExamPeopleInfo.normalScore }}
</text>
<text class="ml-15">总分
{{ item.trainExamPeopleInfo.totalScore }}
</text>
<text class="ml-15">实际得分
{{ item.trainExamPeopleInfo.totalScore }}
</text>
</view>
<view v-else>
<text>考试得分 {{ item.trainExamPeopleInfo.score }}</text>
<text class="ml-15" v-if="item.type === 1">实操得分 {{ item.trainExamPeopleInfo.operateScore }}</text>
<text class="ml-15">总分
{{ item.trainExamPeopleInfo.realScore }}
</text>
</view>
<view class="mt-15"
:class="[item.trainExamPeopleInfo.totalScore >= 60 ? 'text-green' : 'text-red']"
v-if="item.showResult">{{
item.trainExamPeopleInfo.totalScore >= 60 ? '合格' : '不合格'
}}
</view>
</template>
</view>
<view class="fen"
v-if="item.trainExamPeopleInfo && item.trainExamPeopleInfo.highLevelStatus > 0">
<text>专家评审结果:</text>
<text class="ml-15"
:class="[item.trainExamPeopleInfo.highLevelStatus === 1 ? 'text-green' : 'text-red']">
{{ ['待审核', '已通过', '未通过'][item.trainExamPeopleInfo.highLevelStatus] }}
</text>
<uv-text :text="`${item.workType ? item.workType.title : ''}课表`" size="24rpx" lineHeight="40rpx"
:lines="1"
bold></uv-text>
</view>
</view>
<mprogress
:progress="item.progress"
:activeColor="item.color"
:valueColor="item.color"
:valueFontSize="12"
:valueText="item.text"
:width="50"
:borderWidth="4"
></mprogress>
<view class="look">查看</view>
</view>
<uv-empty v-if="!examList.length" text="暂无考试任务"/>
</view>
<uv-empty v-if="!trainList.length" text="暂无培训计划"/>
</view>
<uv-gap height="30rpx" bgColor="#f4f4f4"></uv-gap>
<!-- 竞赛任务 -->
@ -344,6 +356,9 @@ import isBetween from 'dayjs/plugin/isBetween'
import {listCategory} from "@/api/categoty";
import {userDetailReq} from "@/api/user";
import {$toast} from "@/utils";
import ReviewList from "@/pages/promote/components/ReviewList.vue";
import {messageListReq} from "@/api/shop";
import MessageItem from "@/components/MessageItem.vue";
dayjs.extend(isSameOrBefore)
dayjs.extend(isBetween)
@ -363,6 +378,8 @@ export default {
}
},
components: {
MessageItem,
ReviewList,
mprogress
},
data() {
@ -387,6 +404,7 @@ export default {
],
trainList: [],
examList: [],
showAllExam: false,
trainInfoList: [],
trainTaskList: [],
userTrainList: [],
@ -543,7 +561,14 @@ export default {
uni.navigateTo({url})
},
async getNewsList() {
const {data} = await listArticle({categoryId: 273, page: 1, limit: 10})
// const {data} = await listArticle({categoryId: 273, page: 1, limit: 10})
// this.newsList = data.map(item => {
// item.createTime = dayjs(item.createTime).format('YYYY-MM-DD')
// return item
// })
const {data} = await messageListReq({
sendFrom: 1
})
this.newsList = data.map(item => {
item.createTime = dayjs(item.createTime).format('YYYY-MM-DD')
return item

12
src/pages/promote/result.vue

@ -80,8 +80,8 @@ import {getUserInfo} from "@/utils/user";
const user = getUserInfo()
const paperInfo = ref(null)
const getPaperInfo = async (paperId) => {
const {data} = await paperInfoReq({paperId})
const getPaperInfo = async (id) => {
const {data} = await paperInfoReq({id})
paperInfo.value = data
}
@ -97,7 +97,7 @@ const getResultList = async (paperId, examType, examId) => {
})
totalGetScore.value = 0
resultList.value = data.map(item => {
totalGetScore.value += parseInt(item.getScore)
totalGetScore.value += parseFloat(item.getScore)
return item
})
for (let i in resultList.value) {
@ -105,16 +105,16 @@ const getResultList = async (paperId, examType, examId) => {
if (index === -1) {
const type = resultList.value[i].paperDetail.type
listByType.value.push({
correctNum: parseInt(resultList.value[i].getScore) > 0 ? 1 : 0,
correctNum: parseFloat(resultList.value[i].getScore) > 0 ? 1 : 0,
num: 1,
type,
title: TASK_TYPE_LIST.find(item => item.value === type).label,
getScore: resultList.value[i].getScore
})
} else {
if (parseInt(resultList.value[i].getScore) > 0) listByType.value[index].correctNum++
if (parseFloat(resultList.value[i].getScore) > 0) listByType.value[index].correctNum++
listByType.value[index].num++
listByType.value[index].getScore += parseInt(resultList.value[i].getScore)
listByType.value[index].getScore += parseFloat(resultList.value[i].getScore)
}
}
}

2
src/pages/signUp/info.vue

@ -22,7 +22,7 @@
<view class="p-20">
<uv-button type="primary" shape="circle" @click="showPopup"
v-if="!info.hasJoin" :disabled="info.hasOpen === 1">
{{ info.hasOpen === 1 ? '已开课' : '提交' }}
{{ info.hasOpen === 1 ? '已开课' : '点击填写' }}
</uv-button>
<uv-button type="primary" shape="circle" disabled
v-else-if="info.hasJoin && info.trainSignUpPeople.status === 1">

34
src/pages/signUp/self.vue

@ -22,7 +22,7 @@
<view class="p-20">
<uv-button type="primary" shape="circle" @click="showPopup"
v-if="!info.hasJoin" :disabled="info.hasOpen === 1">
{{ info.hasOpen === 1 ? '已开课' : '提交' }}
{{ info.hasOpen === 1 ? '已开课' : '点击填写' }}
</uv-button>
<uv-button type="primary" shape="circle" disabled
v-else-if="info.hasJoin && info.trainSignUpPeople.status === 1">
@ -641,7 +641,9 @@ const confirmReqWorkType = ({value}) => {
const jobList = ref([])
const getJobList = async () => {
jobList.value = []
const res = await workTypePositionListReq()
const res = await workTypePositionListReq({
groupName: true
})
if (res.data) jobList.value = res.data
}
@ -652,19 +654,27 @@ const openJobPicker = () => {
const confirmJob = ({value}) => {
if (value[0]) {
form.value.job = value[0].position
const children = workTypeListOriginTmp.value.filter(item => item.id === value[0].workTypeId)
const children = workTypeListOriginTmp.value.filter(item => value[0].workTypeIdList.includes(item.id))
const parent = workTypeListOriginTmp.value.find(item => item.id === children[0].parentId)
console.log(children, parent)
// workTypeListOrigin.value = [
// {
// title: parent.title,
// id: parent.id,
// children: [
// {
// title: children[0].title,
// id: children[0].id,
// children: children[0].children
// }
// ]
// }
// ]
workTypeListOrigin.value = [
{
title: parent.title,
id: parent.id,
children: [
{
title: children[0].title,
id: children[0].id,
children: children[0].children
}
]
children
}
]
}
@ -900,8 +910,8 @@ const join = async () => {
if (form.value.titleType !== '无' && !form.value.titlePaper) {
return $toast('请上传职称等级证书')
}
if (form.value.titleType !== '无' && !form.value.paperNo) {
return $toast('请输入职称等级编号')
if (form.value.workTypeName !== '无' && !form.value.paperNo) {
return $toast('请输入工种证书编号')
}
if (!workExp.value.length) {
return $toast('请填写工作经历')

113
src/pages/user/message.vue

@ -1,24 +1,7 @@
<template>
<view class="min-height bg-gray p-20">
<template v-if="list.length">
<view class="card mb-20 flex justify-between items-center pos-r" v-for="(item, index) in list" :key="index"
@click="jump(item, index)">
<view class="dot" v-if="!item.hasRead"></view>
<view class="flex justify-start items-start flex-col">
<template v-if="item.title">
<text class="text-26 font-bold">{{ item.title }}</text>
<!-- <view class="mt-20">-->
<!-- <uv-parse :content="item.content"></uv-parse>-->
<!-- </view>-->
</template>
<text v-else class="text-26 font-bold">{{ TYPE_LIST.find(t => t.type === item.type).title }}</text>
<text class="text-gray text-25 mt-20">{{
dayjs(item.createTime).format('YYYY-MM-DD HH:mm')
}}
</text>
</view>
<uv-icon name="arrow-right"/>
</view>
<MessageItem v-for="(item, index) in list" :key="index" :item="item" :index="index"/>
</template>
<uv-empty v-else></uv-empty>
</view>
@ -29,6 +12,7 @@ import {ref} from 'vue'
import {messageListReq, messageReadReq} from "@/api/shop";
import {onShow} from "@dcloudio/uni-app";
import dayjs from "dayjs";
import MessageItem from "@/components/MessageItem.vue";
const list = ref([])
const getList = async () => {
@ -36,101 +20,8 @@ const getList = async () => {
list.value = data
}
const jump = (item, index) => {
let url
switch (item.type) {
case 'exam' : {
uni.switchTab({url: '/pages/promote/promote'})
}
break;
case 'matchEnd' :
case 'matchStart' : {
url = `/pages/match/ing`
}
break;
case 'trainEnd' :
case 'trainStart' : {
url = `/pages/promote/learn?courseId=${item.train.courseId}&trainId=${item.pk}`
}
break;
case 'express' : {
url = `/pages/user/order/detail?orderId=${item.pk}`
}
break;
case 'activity' : {
url = `/pages/activity/info?id=${item.pk}`
}
break;
case 'signUp' :
case 'signUpSelf' :
case 'activityNotice':
case 'trainEndNotice' : {
url = `/pages/user/trainEndNotice?id=${item.id}`
}
break;
}
if (url) uni.redirectTo({url})
read(item.id, index)
}
const read = async (id, index) => {
await messageReadReq({id, hasRead: 1})
list.value[index].hasRead = true
}
const TYPE_LIST = [
{
type: 'exam',
title: '考试即将开始'
},
{
type: 'matchEnd',
title: '竞赛即将结束'
},
{
type: 'matchStart',
title: '竞赛即将开始'
},
{
type: 'trainEnd',
title: '培训即将结束'
},
{
type: 'trainStart',
title: '培训即将开始'
},
{
type: 'express',
title: '订单已发货'
},
{
type: 'activity',
title: '新活动提醒'
},
{
type: 'signUp',
title: '报名资料待修改'
},
{
type: 'signUpSelf',
title: '自主报名资料待修改'
},
]
onShow(() => {
getList()
})
</script>
<style scoped lang="scss">
.dot {
position: absolute;
left: 10rpx;
top: 10rpx;
width: 5rpx;
height: 5rpx;
border-radius: 5rpx;
background-color: red;
}
</style>

53
src/pages/user/shareList.vue

@ -0,0 +1,53 @@
<template>
<view class="min-height bg-white">
<view class="share-box p-30" v-if="list.length">
<ArticleListComponent :article-list="list" :show-follow="false" show-edit/>
</view>
<uv-empty v-else></uv-empty>
</view>
</template>
<script setup>
import {ref} from "vue";
import {pageMatchArticleForUserReq} from '@/api/article'
import ArticleListComponent from "@/pages/index/components/articleListComponent.vue";
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import updateLocale from 'dayjs/plugin/updateLocale'
dayjs.extend(relativeTime)
dayjs.extend(updateLocale)
dayjs.locale('zh-cn')
dayjs.updateLocale('zh-cn', {
relativeTime: {
future: "in %s",
past: "%s 之前",
s: '几秒',
m: "一分钟",
mm: "%d分钟",
h: "一小时",
hh: "%d小时",
d: "一天",
dd: "%d天",
M: "一个月",
MM: "%d个月",
y: "一年",
yy: "%d年"
}
})
const list = ref([])
const getList = async () => {
const {data} = await pageMatchArticleForUserReq({
page: 1,
limit: 9999
})
list.value = data.list.map(item => {
if (dayjs(item.createTime).diff(dayjs(), 'day') < -3) item.friendlyTime = dayjs(item.createTime).format('YYYY-MM-DD')
else item.friendlyTime = dayjs(item.createTime).fromNow()
return item
})
}
getList()
</script>

133
src/pages/user/signIn.vue

@ -5,7 +5,30 @@
<image src="/static/logo.jpg" style="width: 60%" mode="widthFix"/>
<!-- <view class="text-40 text-center font-bold" style="margin: 30rpx; line-height: 30rpx">百色市高技能人才队伍建设</view>-->
<!-- <view class="text-40 text-center font-bold" style="line-height: 30rpx">人才工作调研</view>-->
<view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">
<text class="required" style="top: 0">*</text>
<text class="text-25 mr-25">账号(手机号)</text>
<uv-input border="none" placeholder="请输入11位手机号" v-model="formData.phone"/>
</view>
<view class="mt-30 pb-20 border-bottom-light flex justify-between items-center w-100p pos-r">
<text class="text-25 mr-25">验证码</text>
<view class="flex justify-between items-center">
<view class="flex-1">
<uv-input border="none" placeholder="请输入验证码" v-model="formData.code" custom-class="w-100p"/>
</view>
<uv-button :disabled="!formData.phone || countDown < 60" size="mini" @click="getCode" type="primary">{{
smsTips
}}
</uv-button>
</view>
</view>
<view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">
<text class="required" style="top: 0">*</text>
<text class="text-25 mr-25">身份证号</text>
<uv-input border="none" placeholder="请输入身份证号" v-model="formData.idCard"/>
<uv-button :disabled="!formData.idCard || !formData.code" size="mini" @click="getInfo" type="primary">获取信息
</uv-button>
</view>
<view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">
<text class="required" style="top: 0">*</text>
<text class="text-25 mr-25">企业名称(全称)</text>
@ -31,33 +54,17 @@
<text class="text-25 mr-25">企业地址</text>
<uv-input border="none" placeholder="请输入企业地址" v-model="formData.address"/>
</view>
<!-- <view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">-->
<!-- <text class="required" style="top: 0">*</text>-->
<!-- <text class="text-25 mr-25">企业负责人联系方式</text>-->
<!-- <uv-input border="none" placeholder="请输入企业负责人联系方式" v-model="formData.orgPhone"/>-->
<!-- </view>-->
<view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">
<text class="required" style="top: 0">*</text>
<text class="text-25 mr-25">账号(手机号)</text>
<uv-input border="none" placeholder="请输入11位手机号" v-model="formData.phone"/>
</view>
<!-- <view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">-->
<!-- <text class="required" style="top: 0">*</text>-->
<!-- <text class="text-25 mr-25">企业负责人联系方式</text>-->
<!-- <uv-input border="none" placeholder="请输入企业负责人联系方式" v-model="formData.orgPhone"/>-->
<!-- </view>-->
<view class="mt-30 pb-20 border-bottom-light flex justify-center items-center w-100p pos-r">
<text class="required" style="top: 0">*</text>
<text class="text-25 mr-25">姓名</text>
<uv-input border="none" placeholder="请输入姓名" v-model="formData.realname"/>
</view>
<view class="mt-30 pb-20 border-bottom-light flex justify-between items-center w-100p pos-r">
<text class="text-25 mr-25">验证码</text>
<view class="flex justify-between items-center">
<view class="flex-1">
<uv-input border="none" placeholder="请输入验证码" v-model="formData.code" custom-class="w-100p"/>
</view>
<uv-button :disabled="!formData.phone || countDown < 60" size="mini" @click="getCode" type="primary">{{
smsTips
}}
</uv-button>
</view>
</view>
<view class="mt-30 pb-20 flex justify-center items-center w-100p border-bottom-light pos-r">
<text class="required" style="top: 0">*</text>
<text class="text-25 mr-25">密码</text>
@ -126,7 +133,7 @@ import {MAIN_BTN_STYLE, SUCCESS_BTN_STYLE} from "@/config/color";
import {loginReq} from "@/api/login";
import {clearUserInfo, setUserInfo} from "@/utils/user";
import {$toast} from "@/utils";
import {areaListReq, checkCodeReq, getCodeReq, regReq} from "@/api/common";
import {areaListReq, checkCodeReq, getCodeReq, regReq, userInfoByIdCardPhoneReq} from "@/api/common";
import * as COLORS from "@/config/color";
import {ref} from "vue";
import {dictionaryPage} from "@/api/dict";
@ -140,6 +147,7 @@ export default {
formData: {
phone: '',
company: '',
idCard: '',
companyCode: '',
organizationType: '',
address: '',
@ -253,13 +261,7 @@ export default {
this.areaStr = `${province.name}${city.name}${area.name}`
},
async getCode() {
if (!this.formData.company) return $toast('请输入公司名称')
if (!this.formData.realname) return $toast('请输入您的姓名')
if (!this.formData.phone) return $toast('请输入手机号')
if (!this.formData.province) return $toast('请选择企业所在地市')
if (!this.formData.address) return $toast('请输入企业地址')
if (!this.formData.organizationType) return $toast('请选择企业类型')
if (!this.formData.companyCode) return $toast('请输入企业统一社会信用代码')
const res = await getCodeReq({phone: this.formData.phone}).catch(err => {
return false
})
@ -278,6 +280,44 @@ export default {
this.countDown = 60
}
},
async getInfo() {
if (!this.formData.phone) return $toast('请输入手机号')
if (!this.formData.code) return $toast('请输入验证码')
if (!this.formData.idCard) return $toast('请输入身份证号')
const checkCodeRes = await checkCodeReq({
phone: this.formData.phone,
code: this.formData.code
})
if (checkCodeRes) {
const res = await userInfoByIdCardPhoneReq({
phone: this.formData.phone,
idCard: this.formData.idCard
})
if (res && res.data) {
this.formData.realname = res.data.realname
this.formData.company = res.data.company
this.formData.companyCode = res.data.companyCode
this.formData.organizationType = res.data.organizationType
this.formData.address = res.data.companyAddress
if (res.data.organizationProvince && res.data.organizationCity && res.data.organizationRegion) {
this.formData.province = res.data.organizationProvince
this.formData.city = res.data.organizationCity
this.formData.region = res.data.organizationRegion
this.areaStr = `${res.data.organizationProvince}${res.data.organizationCity}${res.data.organizationRegion}`
const provinceIndex = this.provinceList.findIndex(item => item.name === res.data.organizationProvince)
this.setCityNArea(provinceIndex)
const cityIndex = this.cityList.findIndex(item => item.name === res.data.organizationCity)
this.setCityNArea(provinceIndex, cityIndex)
const areaIndex = this.areaList.findIndex(item => item.name === res.data.organizationRegion)
this.defaultIndex = [provinceIndex, cityIndex, areaIndex]
}
} else {
$toast('暂无信息')
}
} else {
$toast('验证码错误')
}
},
async signIn() {
const {phone, password} = this.formData
if (!phone) return $toast('请输入手机号')
@ -289,30 +329,29 @@ export default {
if (!this.formData.organizationType) return $toast('请选择企业类型')
if (!this.formData.confirmPassword) return $toast('请输入确认密码')
if (this.formData.password !== this.formData.confirmPassword) return $toast('两次密码不一致')
if (!this.formData.company) return $toast('请输入公司名称')
if (!this.formData.realname) return $toast('请输入您的姓名')
if (!this.formData.province) return $toast('请选择企业所在地市')
if (!this.formData.address) return $toast('请输入企业地址')
const regex = /^[\u4e00-\u9fa5]+$/;
if (!regex.test(this.formData.realname)) return $toast('请输入中文姓名')
const checkCodeRes = await checkCodeReq({
phone: this.formData.phone,
code: this.formData.code
uni.showLoading({
title: '注册中'
})
if (checkCodeRes) {
uni.showLoading({
title: '注册中'
})
this.disabled = true
const res = await regReq(this.formData).catch(() => {
this.disabled = false
uni.hideLoading()
})
this.disabled = true
const res = await regReq(this.formData).catch(() => {
this.disabled = false
uni.hideLoading()
if (res) {
$toast('注册成功')
uni.navigateBack()
}
})
this.disabled = false
uni.hideLoading()
if (res) {
$toast('注册成功')
uni.navigateBack()
}
}
},
onLoad() {
this.getAreaList()

149
src/pages/user/signUp.vue

@ -1,89 +1,120 @@
<template>
<view class="min-height bg-gray p-20">
<view class="city-item card" @click="$jump(`/pages/signUp/info?id=${item.signUpId}`)"
v-for="(item, index) in list" :key="index">
<view class="img">
<uv-image :src="item.signUp.cover" radius="20rpx" width="100%"
height="100%"></uv-image>
</view>
<view class="flex justify-between flex-col items-end w-100p ml-20">
<uv-text :text="item.signUp.title" size="28rpx" lineHeight="48rpx" :lines="1"
color="#333"></uv-text>
<view class="flex justify-end items-center mt-40">
<uv-button size="mini" type="primary" shape="circle">{{
item.status === 0 ? '待审核' : '已通过'
}}</uv-button>
<view class="ml-20">
<uv-button size="mini" :type="item.hasPay === 0 ? 'error' : 'primary'" shape="circle" v-if="item.status === 1">{{
item.hasPay === 0 ? '未支付' : '已支付'
}}</uv-button>
</view>
</view>
</view>
<view class="min-height bg-gray p-20">
<uv-tabs :list="[{name: '认定预约报名'}, {name: '自主预约报名'}]"
:current="tabIndex"
@change="changeTab" :scrollable="false"></uv-tabs>
<view class="city-item card" @click="jump(item)"
v-for="(item, index) in list" :key="index">
<view class="img">
<uv-image :src="item.signUp.cover" radius="20rpx" width="100%"
height="100%"></uv-image>
</view>
<view class="flex justify-between flex-col items-end w-100p ml-20">
<uv-text :text="item.signUp.title" size="28rpx" lineHeight="48rpx" :lines="1"
color="#333"></uv-text>
<view class="flex justify-end items-center mt-40">
<uv-button size="mini" type="primary" shape="circle" v-if="item.status === 0">待审核</uv-button>
<uv-button size="mini" type="success" shape="circle" v-if="item.status === 1">已通过</uv-button>
<uv-button size="mini" type="error" shape="circle" v-if="item.status === 2">已拒绝,去编辑</uv-button>
<view class="ml-20">
<uv-button size="mini" :type="item.hasPay === 0 ? 'error' : 'primary'" shape="circle"
v-if="item.status === 1">{{
item.hasPay === 0 ? '未支付' : '已支付'
}}
</uv-button>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
import {signUpUserListReq} from "@/api/signUp";
import {signUpUserListReq, signUpUserSelfListReq} from "@/api/signUp";
import {onShow} from "@dcloudio/uni-app";
const tabIndex = ref(0)
const changeTab = ({index}) => {
tabIndex.value = index
if (index === 0) getList()
else getSelfList()
}
const list = ref([])
const getList = async () => {
const {data} =await signUpUserListReq()
list.value = data
const {data} = await signUpUserListReq()
list.value = data.filter(item => {
return !!item.signUp
})
}
const getSelfList = async () => {
const {data} = await signUpUserSelfListReq()
list.value = data.filter(item => {
return !!item.signUp
})
}
const jump = (item) => {
let url = ''
if (tabIndex.value === 0) {
url = `/pages/signUp/info?id=${item.signUpId}`
} else {
url = `/pages/signUp/self?id=${item.signUpId}`
}
uni.navigateTo({url})
}
onShow(() => {
getList()
getList()
})
</script>
<style scoped>
.city-item {
display: flex;
align-items: center;
margin-top: 30rpx;
.img {
width: 230rpx;
height: 170rpx;
}
display: flex;
align-items: center;
margin-top: 30rpx;
.info {
flex: 1;
height: 170rpx;
padding-left: 20rpx;
.img {
width: 230rpx;
height: 170rpx;
}
.name {
height: 48rpx;
}
.info {
flex: 1;
height: 170rpx;
padding-left: 20rpx;
.text {
margin-top: 6rpx;
height: 40rpx;
font-size: 24rpx;
line-height: 48rpx;
color: #b4b4b4;
overflow: hidden;
}
.name {
height: 48rpx;
}
.bao {
display: inline-block;
height: 60rpx;
padding: 0 20rpx;
font-size: 26rpx;
font-weight: 600;
line-height: 60rpx;
color: #fff;
border-radius: 30rpx;
background: $orange-color;
.text {
margin-top: 6rpx;
height: 40rpx;
font-size: 24rpx;
line-height: 48rpx;
color: #b4b4b4;
overflow: hidden;
}
}
.bao {
display: inline-block;
height: 60rpx;
padding: 0 20rpx;
font-size: 26rpx;
font-weight: 600;
line-height: 60rpx;
color: #fff;
border-radius: 30rpx;
background: $orange-color;
}
}
.city-item:nth-child(1) {
margin-top: 0 !important;
margin-top: 0 !important;
}
</style>

34
src/pages/user/user.vue

@ -20,9 +20,12 @@
ID:{{ userBase.userId }}
<!-- <text class="yellow">操作工</text>-->
</view>
<view class="p" @click="$jump('/pages/match/pointLog')">
<text class="bold" v-if="userInfo">{{ userInfo.point }}</text>
积分
<view class="flex justify-start items-center" v-if="userInfo">
<view class="p" @click="$jump('/pages/match/pointLog')">
<text>积分: {{ userInfo.point }}</text>
</view>
<text class="mx-15">财富值: {{ userInfo.wealthValue }}</text>
<text>价值估值: {{ userInfo.valueValuation }}</text>
</view>
</view>
<view class="text-white ml-25" v-else @click="toLogin">请登录</view>
@ -40,7 +43,7 @@
<view class="text">钱包</view>
</view>
<!-- #endif -->
<view class="quarter-item" @click="$jump('/pages/user/sign')">
<view class="quarter-item" @click="$jump('/pages/user/sign')">
<view class="icon">
<image src="@/static/image/u-1.png" style="width: 48rpx; height: 48rpx"/>
</view>
@ -70,7 +73,7 @@
<view class="server" style="min-height: 200px">
<uv-list :border="false">
<block v-for="(item, index) in serverList" :key="index">
<uv-list-item :thumb="item.icon" link @click="jump(item.url)">
<uv-list-item :thumb="item.icon" link @click="jump(item.url)" border>
<template v-slot:body>
<view class="slot-box">
<text class="slot-text" :style="{ color: item.color ? item.color : '#333333' }">
@ -107,17 +110,18 @@ export default {
serverList: [
{icon: '/static/image/order.png', title: '我的订单', url: '/pages/user/order/list'},
{icon: '/static/image/profile.png?=1.0', title: '我的资料', url: '/pages/user/userDetail'},
{icon: '/static/image/s-1.png?=1.0', title: '积分兑换', url: 'point'},
{icon: '/static/image/s-2.png?=1.0', title: '我的任务', url: '/pages/promote/progress'},
// {icon: '/static/image/s-1.png?=1.0', title: '', url: 'point'},
{icon: '/static/image/task.png?=1.0', title: '我的任务', url: '/pages/promote/progress'},
{icon: '/static/image/share.png?=1.0', title: '我的分享', url: '/pages/user/shareList'},
{icon: '/static/image/address.png?=1.0', title: '收货地址', url: '/pages/user/address/list'},
// {icon: '/static/image/s-3.png?=1.0', title: '', url: ''},
{icon: '/static/image/s-4.png?=1.0', title: '留言板', url: '/pages/user/msg'},
{icon: '/static/image/board.png?=1.0', title: '留言板', url: '/pages/user/msg'},
{icon: '/static/image/archiveBox.png', title: '我的档案', url: '/pages/user/archive'},
{icon: '/static/image/s-5.png?=1.0', title: '我的活动', url: '/pages/user/activity'},
{icon: '/static/image/s-8.png?=1.0', title: '认定预约报名', url: '/pages/user/signUp'},
{icon: '/static/image/s-9.png?=1.0', title: '我的专利', url: '/pages/user/patent'},
{icon: '/static/image/s-6.png?=1.0', title: '联系客服', url: 'service'},
{icon: '/static/image/s-7.png?=1.0', title: '设置', url: '/pages/user/config'}
{icon: '/static/image/activity.png?=1.0', title: '我的活动', url: '/pages/user/activity'},
{icon: '/static/image/booking.png?=1.0', title: '认定预约报名', url: '/pages/user/signUp'},
{icon: '/static/image/patent.png?=1.0', title: '我的专利', url: '/pages/user/patent'},
{icon: '/static/image/service.png?=1.0', title: '联系客服', url: 'service'},
{icon: '/static/image/setting.png?=1.0', title: '设置', url: '/pages/user/config'}
],
hasLogin: checkLogin(),
userBase: {
@ -144,6 +148,9 @@ export default {
async getUserDetail() {
const {data} = await userInfoReq({userId: this.userBase.userId})
this.userInfo = data
if (this.userInfo.isExamStaff && this.serverList[0].title !== '考试打分') {
this.serverList.unshift({icon: '/static/image/score.png', title: '考试打分', url: '/pages/exam/makeScoreList'})
}
},
jump(url) {
if (url === 'point') uni.switchTab({url: '/pages/shop/shop'})
@ -198,7 +205,6 @@ export default {
if (this.hasLogin) {
getUser().then(({data}) => {
this.userBase = data
console.log(this.userBase)
})
this.getUserDetail()
this.checkMsgHasUnread()

4
src/pages/user/userDetail.vue

@ -721,6 +721,10 @@ const submit = async () => {
toast("请选择入职时间")
return
}
if (!formData.value.position) {
toast("请选择职称")
return
}
if (dayjs(formData.value.workContractStartTime).isAfter(formData.value.workContractEndTime)) {
toast("合同结束时间不能早于开始时间")
return

BIN
src/static/image/activity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
src/static/image/address.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
src/static/image/archiveBox.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/static/image/board.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/static/image/booking.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
src/static/image/order.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/static/image/patent.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
src/static/image/profile.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/static/image/score.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
src/static/image/service.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/static/image/setting.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/static/image/share.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/static/image/task.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

2
src/uni_modules/custom-waterfalls-flow/components/custom-waterfalls-flow/custom-waterfalls-flow.vue

@ -76,7 +76,7 @@
},
msg: 0,
listInitStyle: {
'border-radius': '12rpx',
// 'border-radius': '12rpx',
'margin-bottom': '20rpx',
'background-color': '#fff'
},

Loading…
Cancel
Save