@@ -19,7 +19,8 @@ export const apiDevelopment = { | |||||
CurrentTask, | CurrentTask, | ||||
UploadFile, | UploadFile, | ||||
SubmitTask, | SubmitTask, | ||||
TaskDetail | |||||
TaskDetail, | |||||
AchieveList //成就列表 | |||||
}; | }; | ||||
export default apiDevelopment; | export default apiDevelopment; | ||||
@@ -81,7 +82,7 @@ function TaskDetail(params) { | |||||
method: 'get', | method: 'get', | ||||
params: { | params: { | ||||
personId: personId, | personId: personId, | ||||
...params | |||||
...params | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -96,7 +97,7 @@ function SubmitTask(param) { | |||||
method: 'post', | method: 'post', | ||||
data: { | data: { | ||||
personId: personId, | personId: personId, | ||||
...param | |||||
...param | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -106,11 +107,11 @@ function SubmitTask(param) { | |||||
*/ | */ | ||||
function UploadFile(param) { | function UploadFile(param) { | ||||
return http({ | return http({ | ||||
url: "/api/File/Upload", | |||||
method: "post", | |||||
url: '/api/File/Upload', | |||||
method: 'post', | |||||
data: param, | data: param, | ||||
headers: { "Content-Type": "multipart/form-data" }, | |||||
transformRequest: function(data) { | |||||
headers: { 'Content-Type': 'multipart/form-data' }, | |||||
transformRequest: function (data) { | |||||
const formData = new FormData(); | const formData = new FormData(); | ||||
let i = data.formData.entries(); | let i = data.formData.entries(); | ||||
let j = i.next(); | let j = i.next(); | ||||
@@ -122,3 +123,15 @@ function UploadFile(param) { | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* | |||||
*/ | |||||
function AchieveList() { | |||||
return http({ | |||||
url: '/api/Level/AchieveList', | |||||
method: 'get', | |||||
params: { | |||||
personId: personId | |||||
} | |||||
}); | |||||
} |
@@ -8,7 +8,8 @@ export const APIHealthUser = { | |||||
getHomeData, //今日体征感知 | getHomeData, //今日体征感知 | ||||
getHisData, //体征历史数据 | getHisData, //体征历史数据 | ||||
getCalendar, //体征历史数据日历 | getCalendar, //体征历史数据日历 | ||||
getReportData //洞悉 | |||||
getReportData, //洞悉 | |||||
saveDiary //保存情绪日记 | |||||
}; | }; | ||||
export default APIHealthUser; | export default APIHealthUser; | ||||
function addPerson(params) { | function addPerson(params) { | ||||
@@ -76,3 +77,10 @@ function getReportData(params) { | |||||
data: params | data: params | ||||
}); | }); | ||||
} | } | ||||
function saveDiary(params) { | |||||
return request({ | |||||
url: `/api/HealthyData/SaveDiary`, | |||||
method: 'post', | |||||
data: params | |||||
}); | |||||
} |
@@ -74,6 +74,18 @@ export const constantRouterMap = [ | |||||
component: () => import('@/views/development/taskWearing'), | component: () => import('@/views/development/taskWearing'), | ||||
meta: { title: '佩戴任务', keepAlive: false } | meta: { title: '佩戴任务', keepAlive: false } | ||||
}, | }, | ||||
{ | |||||
path: '/achieveList', | |||||
name: 'achieveList', | |||||
component: () => import('@/views/development/achieveList'), | |||||
meta: { title: '成就列表', keepAlive: false } | |||||
}, | |||||
{ | |||||
path: '/achieveDetails', | |||||
name: 'achieveDetails', | |||||
component: () => import('@/views/development/achieveDetails'), | |||||
meta: { title: '成就详情', keepAlive: false } | |||||
}, | |||||
{ | { | ||||
path: '/familyNumber', | path: '/familyNumber', | ||||
name: 'familyNumber', | name: 'familyNumber', | ||||
@@ -0,0 +1,358 @@ | |||||
<!-- --> | |||||
<template> | |||||
<div class="pageContent achieveDetails"> | |||||
<NavBar title="成就详情" @on-click-left="$router.back()"></NavBar> | |||||
<div class="content" v-if="detail"> | |||||
<div class="banner"> | |||||
<div class="item"> | |||||
<div class="left"> | |||||
<img :src="detail.imgPath" alt=""> | |||||
<p v-if="detail.isText">{{ detail.target }}</p> | |||||
</div> | |||||
<div class="right"> | |||||
<p class="percent"> | |||||
<span>{{ calcStatus(detail.status) }}</span><span class="notAchievedText">{{ | |||||
(detail.taskData.percent.toFixed(1)) | |||||
* 100 | |||||
}}%</span> | |||||
</p> | |||||
<div class="result"> | |||||
<div class="reach" v-if="detail.status == 2"> | |||||
<p>达成<span>REACH</span></p> | |||||
</div> | |||||
<div class="notAchieved" v-else> | |||||
<span>NOT ACHIEVED</span> | |||||
</div> | |||||
</div> | |||||
<div class="progress"> | |||||
<div class="progressIn" :style="{ width: detail.taskData.percent * 100 + '%' }"></div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="main"> | |||||
<div class="left"> | |||||
<img :src="achieve.leftImg" alt=""> | |||||
<p>{{ detail.completionDesc }}</p> | |||||
</div> | |||||
<div class="right"> | |||||
<div class="taskList"> | |||||
<div class="taskItem" v-for="item in detail.taskData.taskList" :key="item.id"> | |||||
<div class="top"> | |||||
<img :src="activeImg" alt="" v-if="item.status === 2"> | |||||
<img :src="unActiveImg" alt="" v-else> | |||||
<p>{{ item.name }}</p> | |||||
</div> | |||||
<div class="taskBottom"> | |||||
<div class="taskCheck"> | |||||
<p>任务回看</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="bottom"> | |||||
<p class="title">目标</p> | |||||
<p class="text">{{ detail.target }}</p> | |||||
<p class="title">目标解释</p> | |||||
<div class="text explain" v-for="(item, index) in tasks" :key="index">{{ item }}</div> | |||||
<!-- <p class="text explain">{{ detail.targetDesc }}</p> --> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import NavBar from '@/components/NavBar'; | |||||
import develeopMent from '@/api/development'; | |||||
export default { | |||||
components: { | |||||
NavBar | |||||
}, | |||||
computed: { | |||||
tasks() { | |||||
return this.detail ? this.detail.targetDesc.split('\r\n') : []; | |||||
} | |||||
}, | |||||
data() { | |||||
return { | |||||
achieve: { | |||||
percent: 0.22, | |||||
status: 1, | |||||
isText: false, | |||||
imgPath: require('@/assets/development/images/achieve/1.png'), | |||||
target: '美好开始', | |||||
leftImg: require('@/assets/development/images/achieve/d_01.png') | |||||
}, | |||||
detail: null, | |||||
activeImg: require('@/assets/development/images/active.png'), | |||||
unActiveImg: require('@/assets/development/images/unactive.png'), | |||||
id: '' | |||||
} | |||||
}, | |||||
created() { | |||||
}, | |||||
mounted() { | |||||
this.id = this.$route.query.id; | |||||
this.initData() | |||||
}, | |||||
methods: { | |||||
calcStatus(value) { | |||||
let result = ''; | |||||
switch (value) { | |||||
case 1: | |||||
result = '进行中'; | |||||
break; | |||||
case 0: | |||||
result = '未开始'; | |||||
break; | |||||
case 2: | |||||
result = '已完成'; | |||||
break; | |||||
default: | |||||
break; | |||||
}; | |||||
return result | |||||
}, | |||||
async initData() { | |||||
this.$toast.loading({ | |||||
message: '加载中' | |||||
}) | |||||
let re = await develeopMent.LevelDetail({ | |||||
levelId: this.id | |||||
}); | |||||
if (re) { | |||||
if (re.succeed) { | |||||
this.detail = re.data; | |||||
this.detail.imgPath = require(`@/assets/development/images/achieve/${re.data.level}.png`); | |||||
this.detail.isText = re.data.level !== 1 && re.data.level !== 10; | |||||
this.$toast.success({ | |||||
message: '加载完成' | |||||
}) | |||||
console.log("this.detail", this.detail); | |||||
} else { | |||||
this.$toast(re.message); | |||||
} | |||||
} | |||||
} | |||||
}, | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
@import './include.scss'; | |||||
/* @import url(); 引入css类 */ | |||||
.achieveDetails { | |||||
.content { | |||||
.banner { | |||||
.item { | |||||
height: 300px; | |||||
padding: 30px 50px; | |||||
margin: 30px 0; | |||||
border-radius: 60px; | |||||
background-color: #000000; | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
.left { | |||||
height: 100%; | |||||
width: 35%; | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: center; | |||||
flex-direction: column; | |||||
img { | |||||
height: 80%; | |||||
width: 100%; | |||||
object-fit: contain; | |||||
} | |||||
p { | |||||
font-size: 24px; | |||||
color: #fff; | |||||
font-weight: bold; | |||||
/* padding: 20px 0; */ | |||||
} | |||||
} | |||||
.right { | |||||
height: 100%; | |||||
width: 60%; | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: flex-end; | |||||
flex-direction: column; | |||||
color: $green; | |||||
font-weight: bold; | |||||
p { | |||||
font-size: 52px; | |||||
} | |||||
.percent { | |||||
@include center(); | |||||
color: $green; | |||||
span { | |||||
font-size: 42px; | |||||
color: #fff; | |||||
} | |||||
.notAchievedText { | |||||
margin-left: 10px; | |||||
font-size: 52px; | |||||
} | |||||
} | |||||
.result { | |||||
font-size: 42px; | |||||
.reach { | |||||
span { | |||||
font-size: 52px; | |||||
color: #fff; | |||||
margin-left: 10px; | |||||
} | |||||
} | |||||
.notAchieved { | |||||
font-size: 42px; | |||||
color: gray; | |||||
} | |||||
} | |||||
.progress { | |||||
position: relative; | |||||
margin-top: 20px; | |||||
height: 40px; | |||||
width: 100%; | |||||
background-color: gray; | |||||
border-radius: 30px; | |||||
.progressIn { | |||||
position: absolute; | |||||
top: 0; | |||||
left: 0; | |||||
height: 40px; | |||||
width: 60%; | |||||
background-color: $green; | |||||
border-radius: 30px; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
.main { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
.left { | |||||
width: 25%; | |||||
/* padding-top: 100px; */ | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: center; | |||||
flex-direction: column; | |||||
img { | |||||
object-fit: contain; | |||||
} | |||||
p { | |||||
padding-top: 10px; | |||||
font-size: 36px; | |||||
color: $green; | |||||
} | |||||
} | |||||
.right { | |||||
width: 75%; | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: center; | |||||
flex-direction: column; | |||||
.taskList { | |||||
.taskItem { | |||||
.top { | |||||
display: flex; | |||||
justify-content: flex-start; | |||||
align-items: center; | |||||
padding: 10px 0; | |||||
img { | |||||
height: 50px; | |||||
width: 50px; | |||||
margin-right: 20px; | |||||
object-fit: contain; | |||||
} | |||||
p { | |||||
font-size: 32px; | |||||
font-weight: bold; | |||||
} | |||||
} | |||||
.taskBottom { | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: center; | |||||
.taskCheck { | |||||
width: 60%; | |||||
border-radius: 40px; | |||||
background-color: #000; | |||||
color: #fff; | |||||
font-size: 32px; | |||||
padding: 10px 30px; | |||||
text-align: right; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
.bottom { | |||||
margin-top: 60px; | |||||
padding: 30px; | |||||
border-radius: 40px; | |||||
border: 5px solid #000; | |||||
.title { | |||||
font-size: 36px; | |||||
font-weight: bold; | |||||
} | |||||
.text { | |||||
font-size: 32px; | |||||
color: #434144; | |||||
padding-top: 10px; | |||||
padding-bottom: 20px; | |||||
&.explain { | |||||
padding-bottom: 0; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
</style> |
@@ -0,0 +1,245 @@ | |||||
<!-- --> | |||||
<template> | |||||
<div class="pageContent achieveList"> | |||||
<NavBar title="成就列表" @on-click-left="$router.back()"></NavBar> | |||||
<div class="content"> | |||||
<div class="list"> | |||||
<div class="item" v-for="item in conList" :key="item.id" @click="onRouterTo(item.id)"> | |||||
<div class="left"> | |||||
<img :src="item.imgPath" alt=""> | |||||
<p v-if="item.isText">{{ item.target }}</p> | |||||
</div> | |||||
<div class="right"> | |||||
<p class="percent"> | |||||
<span>{{ calcStatus(item.status) }}</span><span class="notAchievedText">{{ (item.percent) * 100 | |||||
}}%</span> | |||||
</p> | |||||
<div class="result"> | |||||
<div class="reach" v-if="item.status == 2"> | |||||
<p>达成<span>REACH</span></p> | |||||
</div> | |||||
<div class="notAchieved" v-else> | |||||
<span>NOT ACHIEVED</span> | |||||
</div> | |||||
</div> | |||||
<div class="progress"> | |||||
<div class="progressIn" :style="{ width: item.percent * 100 + '%' }"></div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import NavBar from '@/components/NavBar'; | |||||
import develeopMent from '@/api/development'; | |||||
export default { | |||||
components: { | |||||
NavBar | |||||
}, | |||||
data() { | |||||
return { | |||||
conList: null | |||||
} | |||||
}, | |||||
computed: { | |||||
personId() { | |||||
return this.$store.getters.personId | |||||
} | |||||
}, | |||||
created() { | |||||
}, | |||||
mounted() { | |||||
this.getAchieveList(); | |||||
}, | |||||
methods: { | |||||
calcStatus(value) { | |||||
let result = ''; | |||||
switch (value) { | |||||
case 1: | |||||
result = '进行中'; | |||||
break; | |||||
case 0: | |||||
result = '未开始'; | |||||
break; | |||||
case 2: | |||||
result = '已完成'; | |||||
break; | |||||
default: | |||||
break; | |||||
}; | |||||
return result | |||||
}, | |||||
async getAchieveList() { | |||||
this.$toast.loading({ | |||||
message: '加载中' | |||||
}) | |||||
let re = await develeopMent.AchieveList({ | |||||
personId: this.personId | |||||
}); | |||||
if (re) { | |||||
if (re.succeed) { | |||||
console.log("成就列表", re); | |||||
// 创建一个新的数组,将arr1和arr2对应项合并 | |||||
let list = re.data.map(item => { | |||||
return { | |||||
id: item.id, | |||||
level: item.level, | |||||
percent: item.percent, | |||||
target: item.target, | |||||
isText: item.id !== 1 && item.id !== 10, | |||||
imgPath: require(`@/assets/development/images/achieve/${item.level}.png`), | |||||
status: item.status, | |||||
}; | |||||
}); | |||||
this.conList = list | |||||
this.$toast.success({ | |||||
message: '加载完成' | |||||
}) | |||||
console.log("新数组", this.conList); | |||||
} else { | |||||
this.$toast(re.message); | |||||
} | |||||
} | |||||
}, | |||||
onRouterTo(id) { | |||||
this.$router.push({ | |||||
name: 'achieveDetails', | |||||
query: { | |||||
id: id | |||||
} | |||||
}) | |||||
} | |||||
}, | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
@import './include.scss'; | |||||
/* @import url(); 引入css类 */ | |||||
.achieveList { | |||||
.content { | |||||
/* padding: 0 40px; */ | |||||
.list { | |||||
overflow: scroll; | |||||
.item { | |||||
height: 300px; | |||||
padding: 30px 50px; | |||||
margin: 30px 0; | |||||
border-radius: 60px; | |||||
background-color: #000000; | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
.left { | |||||
height: 100%; | |||||
width: 35%; | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: center; | |||||
flex-direction: column; | |||||
img { | |||||
height: 80%; | |||||
width: 100%; | |||||
object-fit: contain; | |||||
} | |||||
p { | |||||
font-size: 24px; | |||||
color: #fff; | |||||
/* padding: 20px 0; */ | |||||
} | |||||
} | |||||
.right { | |||||
height: 100%; | |||||
width: 60%; | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: flex-end; | |||||
flex-direction: column; | |||||
color: $green; | |||||
font-weight: bold; | |||||
p { | |||||
font-size: 52px; | |||||
} | |||||
.percent { | |||||
@include center(); | |||||
color: $green; | |||||
span { | |||||
font-size: 42px; | |||||
color: #fff; | |||||
} | |||||
.notAchievedText { | |||||
margin-left: 10px; | |||||
font-size: 52px; | |||||
} | |||||
} | |||||
.result { | |||||
font-size: 42px; | |||||
.reach { | |||||
span { | |||||
font-size: 52px; | |||||
color: #fff; | |||||
margin-left: 10px; | |||||
} | |||||
} | |||||
.notAchieved { | |||||
font-size: 42px; | |||||
color: gray; | |||||
} | |||||
} | |||||
.progress { | |||||
position: relative; | |||||
margin-top: 20px; | |||||
height: 40px; | |||||
width: 100%; | |||||
background-color: gray; | |||||
border-radius: 30px; | |||||
.progressIn { | |||||
position: absolute; | |||||
top: 0; | |||||
left: 0; | |||||
height: 40px; | |||||
width: 60%; | |||||
background-color: $green; | |||||
border-radius: 30px; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
</style> |
@@ -3,16 +3,19 @@ | |||||
padding: 0; | padding: 0; | ||||
box-sizing: border-box; | box-sizing: border-box; | ||||
} | } | ||||
.image { | .image { | ||||
width: 100%; | width: 100%; | ||||
height: 100%; | height: 100%; | ||||
img { | img { | ||||
width: 100%; | width: 100%; | ||||
height: 100%; | height: 100%; | ||||
} | } | ||||
} | } | ||||
.gap { | .gap { | ||||
padding-top: 40px; | |||||
/* padding-top: 40px; */ | |||||
} | } | ||||
.pageContent { | .pageContent { | ||||
@@ -21,4 +24,4 @@ | |||||
padding-top: 100px; | padding-top: 100px; | ||||
padding-bottom: 150px; | padding-bottom: 150px; | ||||
box-sizing: border-box; | box-sizing: border-box; | ||||
} | |||||
} |
@@ -9,6 +9,14 @@ | |||||
<div class="button min-text">了解详情</div> | <div class="button min-text">了解详情</div> | ||||
</div> | </div> | ||||
</router-link> | </router-link> | ||||
<!-- 成就 --> | |||||
<router-link to="/achieveList"> | |||||
<div class="bannar achieve"> | |||||
<div class="image"> | |||||
<img src="@/assets/development/images/achieve_banner.png" alt="" /> | |||||
</div> | |||||
</div> | |||||
</router-link> | |||||
<div v-if="task"> | <div v-if="task"> | ||||
<div class="gap">当前任务</div> | <div class="gap">当前任务</div> | ||||
<div class="task"> | <div class="task"> | ||||
@@ -49,17 +57,11 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="levels"> | <div class="levels"> | ||||
<div | |||||
class="level radius" | |||||
v-for="(item, index) in levels" | |||||
:key="index" | |||||
:class="{ | |||||
unlock: item.status === 3, | |||||
now: item.status === 1, | |||||
active: item.status === 2 | |||||
}" | |||||
@click="toDetail(item)" | |||||
> | |||||
<div class="level radius" v-for="(item, index) in levels" :key="index" :class="{ | |||||
unlock: item.status === 3, | |||||
now: item.status === 1, | |||||
active: item.status === 2 | |||||
}" @click="toDetail(item)"> | |||||
<div class="bg"> | <div class="bg"> | ||||
<div class="image"> | <div class="image"> | ||||
<img :src="item.image" alt="" /> | <img :src="item.image" alt="" /> | ||||
@@ -71,14 +73,14 @@ | |||||
<div class="level-info-status"> | <div class="level-info-status"> | ||||
{{ | {{ | ||||
item.status === 0 | item.status === 0 | ||||
? '未解锁' | |||||
: item.status === 3 | |||||
? '未解锁' | |||||
: item.status === 3 | |||||
? '可查看' | ? '可查看' | ||||
: item.status === 1 | : item.status === 1 | ||||
? '进行中' | |||||
: item.status === 2 | |||||
? '已完成' | |||||
: '未知' | |||||
? '进行中' | |||||
: item.status === 2 | |||||
? '已完成' | |||||
: '未知' | |||||
}} | }} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -112,7 +114,7 @@ export default { | |||||
levels: [] | levels: [] | ||||
}; | }; | ||||
}, | }, | ||||
created() {}, | |||||
created() { }, | |||||
mounted() { | mounted() { | ||||
// 写死一个用户Id | // 写死一个用户Id | ||||
this.$store.commit( | this.$store.commit( | ||||
@@ -210,6 +212,14 @@ export default { | |||||
} | } | ||||
if (item.submitType === 2) { | if (item.submitType === 2) { | ||||
this.$toast('问卷调查'); | this.$toast('问卷调查'); | ||||
this.$router.push({ | |||||
name: 'questionnaire', | |||||
query: { | |||||
id: item.id, | |||||
rankId: item.rankId | |||||
} | |||||
}); | |||||
} else if (item.submitType === 0) { | } else if (item.submitType === 0) { | ||||
this.$router.push({ | this.$router.push({ | ||||
name: 'taskWearing', | name: 'taskWearing', | ||||
@@ -241,23 +251,29 @@ export default { | |||||
</script> | </script> | ||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
@import './include.scss'; | @import './include.scss'; | ||||
.min-text { | .min-text { | ||||
font-size: 25px; | font-size: 25px; | ||||
font-weight: 400; | font-weight: 400; | ||||
} | } | ||||
.mid-text { | .mid-text { | ||||
font-size: 28px; | font-size: 28px; | ||||
font-weight: 400; | font-weight: 400; | ||||
} | } | ||||
.radius { | .radius { | ||||
border-radius: 60px; | border-radius: 60px; | ||||
} | } | ||||
.bold { | .bold { | ||||
font-weight: bold; | font-weight: bold; | ||||
} | } | ||||
.gap { | .gap { | ||||
padding-left: 35px; | padding-left: 35px; | ||||
} | } | ||||
.devlopment { | .devlopment { | ||||
padding-top: 30px; | padding-top: 30px; | ||||
font-weight: bold; | font-weight: bold; | ||||
@@ -267,6 +283,7 @@ export default { | |||||
position: relative; | position: relative; | ||||
width: 100%; | width: 100%; | ||||
min-height: 200px; | min-height: 200px; | ||||
.button { | .button { | ||||
position: absolute; | position: absolute; | ||||
right: 5%; | right: 5%; | ||||
@@ -278,6 +295,10 @@ export default { | |||||
} | } | ||||
} | } | ||||
.achieve { | |||||
@include center(); | |||||
} | |||||
.task { | .task { | ||||
overflow: hidden; | overflow: hidden; | ||||
position: relative; | position: relative; | ||||
@@ -292,6 +313,7 @@ export default { | |||||
top: 0; | top: 0; | ||||
z-index: 1; | z-index: 1; | ||||
} | } | ||||
.task-detail { | .task-detail { | ||||
position: absolute; | position: absolute; | ||||
left: 0; | left: 0; | ||||
@@ -305,10 +327,12 @@ export default { | |||||
justify-content: space-between; | justify-content: space-between; | ||||
align-items: flex-end; | align-items: flex-end; | ||||
padding: 20px 40px; | padding: 20px 40px; | ||||
.mid-text { | .mid-text { | ||||
font-size: 30px; | font-size: 30px; | ||||
} | } | ||||
} | } | ||||
.task-times { | .task-times { | ||||
display: flex; | display: flex; | ||||
flex-direction: column; | flex-direction: column; | ||||
@@ -329,6 +353,7 @@ export default { | |||||
.task-time-text { | .task-time-text { | ||||
letter-spacing: 5px; | letter-spacing: 5px; | ||||
} | } | ||||
.task-time-button { | .task-time-button { | ||||
align-self: flex-end; | align-self: flex-end; | ||||
padding: 0px 30px; | padding: 0px 30px; | ||||
@@ -337,6 +362,7 @@ export default { | |||||
border-radius: 40px; | border-radius: 40px; | ||||
} | } | ||||
} | } | ||||
.task-time-icon { | .task-time-icon { | ||||
width: 50px; | width: 50px; | ||||
height: 50px; | height: 50px; | ||||
@@ -346,6 +372,7 @@ export default { | |||||
width: 100%; | width: 100%; | ||||
height: 100%; | height: 100%; | ||||
} | } | ||||
.image { | .image { | ||||
position: relative; | position: relative; | ||||
} | } | ||||
@@ -358,6 +385,7 @@ export default { | |||||
.levels { | .levels { | ||||
position: relative; | position: relative; | ||||
padding-top: 20px; | padding-top: 20px; | ||||
.level { | .level { | ||||
overflow: hidden; | overflow: hidden; | ||||
position: relative; | position: relative; | ||||
@@ -373,6 +401,7 @@ export default { | |||||
height: 100%; | height: 100%; | ||||
z-index: 1; | z-index: 1; | ||||
} | } | ||||
.level-info { | .level-info { | ||||
position: absolute; | position: absolute; | ||||
display: flex; | display: flex; | ||||
@@ -387,16 +416,19 @@ export default { | |||||
font-size: 50px; | font-size: 50px; | ||||
letter-spacing: 2px; | letter-spacing: 2px; | ||||
} | } | ||||
.level-info-status { | .level-info-status { | ||||
font-size: 25px; | font-size: 25px; | ||||
font-weight: 400; | font-weight: 400; | ||||
} | } | ||||
} | } | ||||
.level-info-title { | .level-info-title { | ||||
font-size: 34px; | font-size: 34px; | ||||
letter-spacing: 2px; | letter-spacing: 2px; | ||||
} | } | ||||
} | } | ||||
.tip { | .tip { | ||||
position: absolute; | position: absolute; | ||||
right: 20px; | right: 20px; | ||||
@@ -406,12 +438,15 @@ export default { | |||||
z-index: 3; | z-index: 3; | ||||
} | } | ||||
} | } | ||||
.unlock { | .unlock { | ||||
background: #ff5f8b; | background: #ff5f8b; | ||||
} | } | ||||
.now { | .now { | ||||
background: #8dc21f; | background: #8dc21f; | ||||
} | } | ||||
.active { | .active { | ||||
background: #179b3b; | background: #179b3b; | ||||
} | } | ||||
@@ -1,63 +1,33 @@ | |||||
<template> | <template> | ||||
<div class="questionnaire"> | <div class="questionnaire"> | ||||
<van-nav-bar | |||||
title="调查问卷" | |||||
left-text="" | |||||
right-text="提交" | |||||
left-arrow | |||||
@click-left="onClickLeft" | |||||
@click-right="onClickRight" | |||||
/> | |||||
<van-nav-bar title="调查问卷" left-text="返回" right-text="提交" left-arrow @click-left="onClickLeft" | |||||
@click-right="onClickRight" /> | |||||
<van-form> | <van-form> | ||||
<div v-for="(item, index) in formData" :key="index"> | <div v-for="(item, index) in formData" :key="index"> | ||||
<!-- 单选 --> | <!-- 单选 --> | ||||
<van-field | |||||
v-if="item.type == 0" | |||||
:name="'radio_' + item.questionId" | |||||
:label="item.subject" | |||||
> | |||||
<van-field v-if="item.type == 0" :name="'radio_' + item.questionId" :label="item.subject"> | |||||
<template #input> | <template #input> | ||||
<van-radio-group v-model="item.answer" direction="horizontal"> | <van-radio-group v-model="item.answer" direction="horizontal"> | ||||
<van-radio | |||||
v-for="(list, key) in item.answerItems" | |||||
:key="key" | |||||
:name="list.serialNo" | |||||
> | |||||
<van-radio v-for="(list, key) in item.answerItems" :key="key" :name="list.serialNo"> | |||||
{{ list.answerItem }} | {{ list.answerItem }} | ||||
</van-radio> | </van-radio> | ||||
</van-radio-group> | </van-radio-group> | ||||
</template> | </template> | ||||
</van-field> | </van-field> | ||||
<!-- 复选框 --> | <!-- 复选框 --> | ||||
<van-field | |||||
v-if="item.type == 1" | |||||
:name="'multipleChoice_' + item.questionId" | |||||
:label="item.subject" | |||||
> | |||||
<van-field v-if="item.type == 1" :name="'multipleChoice_' + item.questionId" :label="item.subject"> | |||||
<template #input> | <template #input> | ||||
<van-checkbox-group v-model="item.answer" direction="horizontal"> | <van-checkbox-group v-model="item.answer" direction="horizontal"> | ||||
<van-checkbox | |||||
v-for="(list, key) in item.answerItems" | |||||
:key="key" | |||||
:name="list.serialNo" | |||||
shape="square" | |||||
> | |||||
<van-checkbox v-for="(list, key) in item.answerItems" :key="key" :name="list.serialNo" | |||||
shape="square"> | |||||
{{ list.answerItem }} | {{ list.answerItem }} | ||||
</van-checkbox> | </van-checkbox> | ||||
</van-checkbox-group> | </van-checkbox-group> | ||||
</template> | </template> | ||||
</van-field> | </van-field> | ||||
<!-- 文本输入 --> | <!-- 文本输入 --> | ||||
<van-field | |||||
v-if="item.type == 2" | |||||
v-model="item.answer" | |||||
rows="3" | |||||
autosize | |||||
:name="'textBox_' + item.questionId" | |||||
:label="item.subject" | |||||
type="textarea" | |||||
placeholder="" | |||||
/> | |||||
<van-field v-if="item.type == 2" v-model="item.answer" rows="3" autosize | |||||
:name="'textBox_' + item.questionId" :label="item.subject" type="textarea" placeholder="" /> | |||||
<!-- 单行文本 --> | <!-- 单行文本 --> | ||||
<!-- <van-field | <!-- <van-field | ||||
v-if="item.type == 2" | v-if="item.type == 2" | ||||
@@ -102,19 +72,20 @@ export default { | |||||
// 初始化问卷 | // 初始化问卷 | ||||
this.init(); | this.init(); | ||||
}, | }, | ||||
mounted() {}, | |||||
mounted() { }, | |||||
methods: { | methods: { | ||||
onClickLeft(value) { | onClickLeft(value) { | ||||
console.log(value) | console.log(value) | ||||
this.$router.back() | |||||
}, | }, | ||||
onClickRight() { | onClickRight() { | ||||
// 提交问卷 | // 提交问卷 | ||||
if ( this.validate() ) { | |||||
if (this.validate()) { | |||||
let questionnaireData = []; | let questionnaireData = []; | ||||
this.formData.forEach(element => { | this.formData.forEach(element => { | ||||
let answer = ""; | let answer = ""; | ||||
if ( element.type == 1 ) { | |||||
if (element.type == 1) { | |||||
answer = element.answer.join("|"); | answer = element.answer.join("|"); | ||||
} else { | } else { | ||||
answer = element.answer | answer = element.answer | ||||
@@ -145,8 +116,8 @@ export default { | |||||
.then(res => { | .then(res => { | ||||
this.formData = res.data.data.subjectItems; | this.formData = res.data.data.subjectItems; | ||||
this.formData.forEach(element => { | this.formData.forEach(element => { | ||||
if ( element.type == 1 ) { | |||||
if ( element.answer !== "" ) { | |||||
if (element.type == 1) { | |||||
if (element.answer !== "") { | |||||
element.answer = element.answer.split('|'); | element.answer = element.answer.split('|'); | ||||
} else { | } else { | ||||
element.answer = []; | element.answer = []; | ||||
@@ -161,13 +132,13 @@ export default { | |||||
validate() { | validate() { | ||||
let is = true; | let is = true; | ||||
this.formData.forEach(element => { | this.formData.forEach(element => { | ||||
if ( element.type == 0 && element.answer == "" ) { | |||||
if (element.type == 0 && element.answer == "") { | |||||
this.$notify({ type: 'warning', message: "单选项请选择一个选项" }); | this.$notify({ type: 'warning', message: "单选项请选择一个选项" }); | ||||
is = false; | is = false; | ||||
} else if ( element.type == 1 && element.answer.length == 0 ) { | |||||
} else if (element.type == 1 && element.answer.length == 0) { | |||||
this.$notify({ type: 'warning', message: "多选项至少选择一项" }); | this.$notify({ type: 'warning', message: "多选项至少选择一项" }); | ||||
is = false; | is = false; | ||||
} else if ( element.type == 2 && element.answer == "" ) { | |||||
} else if (element.type == 2 && element.answer == "") { | |||||
this.$notify({ type: 'warning', message: "文本内容不能为空" }); | this.$notify({ type: 'warning', message: "文本内容不能为空" }); | ||||
is = false; | is = false; | ||||
} | } | ||||
@@ -178,5 +149,5 @@ export default { | |||||
}; | }; | ||||
</script> | </script> | ||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
@import './scss/index.scss'; | |||||
@import './scss/index.scss'; | |||||
</style> | </style> |
@@ -1,18 +1,19 @@ | |||||
<!-- 今日 --> | <!-- 今日 --> | ||||
<template> | <template> | ||||
<div class="today"> | <div class="today"> | ||||
<div class="devicesSwitch" v-if="false"> | <div class="devicesSwitch" v-if="false"> | ||||
<!-- <i :class="[{on: isClear},'news']" @click="newsClick" v-show="true"></i> --> | <!-- <i :class="[{on: isClear},'news']" @click="newsClick" v-show="true"></i> --> | ||||
<div :class="[ | <div :class="[ | ||||
'imgArea', | |||||
{ | |||||
cut: currentPerson.deviceStatus ? currentPerson.deviceStatus.online != 0 : false | |||||
} | |||||
]" @click="imgAreaClick" v-show="personList !== null && personList.length"> | |||||
'imgArea', | |||||
{ | |||||
cut: currentPerson.deviceStatus ? currentPerson.deviceStatus.online != 0 : false | |||||
} | |||||
]" @click="imgAreaClick" v-show="personList !== null && personList.length"> | |||||
<img :src="currentPerson.avatar" /> | <img :src="currentPerson.avatar" /> | ||||
<span style="font-weight: bolder" v-show="currentPerson && currentPerson.nickName">{{ | <span style="font-weight: bolder" v-show="currentPerson && currentPerson.nickName">{{ | ||||
currentPerson.nickName | |||||
}}</span> | |||||
currentPerson.nickName | |||||
}}</span> | |||||
<span>切换</span> | <span>切换</span> | ||||
</div> | </div> | ||||
<!-- 点击宝贝切换出现 --> | <!-- 点击宝贝切换出现 --> | ||||
@@ -20,14 +21,14 @@ | |||||
<div class="list" v-for="(item, index) in personList" :key="`list_index_${index}`" | <div class="list" v-for="(item, index) in personList" :key="`list_index_${index}`" | ||||
@click="imageListClick(item, index)"> | @click="imageListClick(item, index)"> | ||||
<div :class="[ | <div :class="[ | ||||
{ active: item.id == $store.getters.personId }, | |||||
'imgA', | |||||
{ | |||||
online: { | |||||
online: item.deviceStatus ? item.deviceStatus.online && item.deviceStatus.online == 1 : 'false' | |||||
} | |||||
} | |||||
]"> | |||||
{ active: item.id == $store.getters.personId }, | |||||
'imgA', | |||||
{ | |||||
online: { | |||||
online: item.deviceStatus ? item.deviceStatus.online && item.deviceStatus.online == 1 : 'false' | |||||
} | |||||
} | |||||
]"> | |||||
<img :src="item.avatar" /> | <img :src="item.avatar" /> | ||||
</div> | </div> | ||||
<div :class="['Myname', { active: item.id == $store.getters.personId }]"> | <div :class="['Myname', { active: item.id == $store.getters.personId }]"> | ||||
@@ -44,8 +45,8 @@ | |||||
</div> --> | </div> --> | ||||
<!-- 今日状态 --> | <!-- 今日状态 --> | ||||
<div @click="conAreaShow = false" :style="{ | <div @click="conAreaShow = false" :style="{ | ||||
paddingBottom: isShowBind ? '40px' : 0 | |||||
}"> | |||||
paddingBottom: isShowBind ? '40px' : 0 | |||||
}"> | |||||
<div class="today-status"> | <div class="today-status"> | ||||
<img class="img" :src="calcTodayStatus(todayLevel, 'img')" /> | <img class="img" :src="calcTodayStatus(todayLevel, 'img')" /> | ||||
<!-- <img | <!-- <img | ||||
@@ -152,17 +153,27 @@ | |||||
<p>情绪日记</p> | <p>情绪日记</p> | ||||
<div> | <div> | ||||
<div> | <div> | ||||
<p>保存</p> | |||||
<p @click="onSaveDiary">保存</p> | |||||
<van-icon name="arrow" size="18" /> | <van-icon name="arrow" size="18" /> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="main"> | <div class="main"> | ||||
<van-checkbox-group v-model="result"> | |||||
<van-checkbox name="a" shape="square" checked-color="#179b3b"> | |||||
<img src="@/assets/today/icons/2_72.png" /> | |||||
</van-checkbox> | |||||
<van-checkbox name="b" shape="square" checked-color="#179b3b"> | |||||
<van-radio-group v-model="result"> | |||||
<van-radio v-for="(item, index) in moodList" :key="index" :name="item.con" shape="square" icon-size="14" | |||||
checked-color="#179b3b"> | |||||
<template #default> | |||||
<div class="checkbox-label"> | |||||
<img :src="item.imgPath" /> | |||||
<div class="text"> | |||||
<span>{{ item.text }}</span> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
</van-radio> | |||||
<!-- <van-checkbox name="b" shape="square" checked-color="#179b3b"> | |||||
<img src="@/assets/today/icons/2_59.png" /> | <img src="@/assets/today/icons/2_59.png" /> | ||||
</van-checkbox> | </van-checkbox> | ||||
<van-checkbox name="c" shape="square" checked-color="#179b3b"> | <van-checkbox name="c" shape="square" checked-color="#179b3b"> | ||||
@@ -176,10 +187,10 @@ | |||||
</van-checkbox> | </van-checkbox> | ||||
<van-checkbox name="f" shape="square" checked-color="#179b3b"> | <van-checkbox name="f" shape="square" checked-color="#179b3b"> | ||||
<img src="@/assets/today/icons/2_70.png" /> | <img src="@/assets/today/icons/2_70.png" /> | ||||
</van-checkbox> | |||||
</van-checkbox-group> | |||||
</van-checkbox> --> | |||||
</van-radio-group> | |||||
<div class="textarea"> | <div class="textarea"> | ||||
<textarea placeholder="我要写亲密日记" rows="5"></textarea> | |||||
<textarea placeholder="我要写亲密日记" rows="5" v-model="diary" ref="myTextarea"></textarea> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -212,7 +223,7 @@ | |||||
<!-- <overlay-loading :showOverlay="showOverlay"></overlay-loading> --> | <!-- <overlay-loading :showOverlay="showOverlay"></overlay-loading> --> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import APIAlarm from '@/api/core'; | import APIAlarm from '@/api/core'; | ||||
import APIPsy from '@/api/psychological'; | import APIPsy from '@/api/psychological'; | ||||
@@ -232,6 +243,15 @@ export default { | |||||
{ className: 'sameas', active: false, value: 1 }, | { className: 'sameas', active: false, value: 1 }, | ||||
{ className: 'excellent', active: false, value: 0 } | { className: 'excellent', active: false, value: 0 } | ||||
], | ], | ||||
moodList: [ | |||||
{ name: 'a', imgPath: require('@/assets/today/icons/2_72.png'), text: '平静', con: '🙂' }, | |||||
{ name: 'b', imgPath: require('@/assets/today/icons/2_59.png'), text: '开心', con: '😀' }, | |||||
{ name: 'c', imgPath: require('@/assets/today/icons/2_54.png'), text: '生病', con: '😢' }, | |||||
{ name: 'd', imgPath: require('@/assets/today/icons/2_67.png'), text: '生气', con: '☹️' }, | |||||
{ name: 'e', imgPath: require('@/assets/today/icons/2_72.png'), text: '失落', con: '😔' }, | |||||
{ name: 'f', imgPath: require('@/assets/today/icons/2_70.png'), text: '难过', con: '😞' }, | |||||
], | |||||
todayResult: {}, | todayResult: {}, | ||||
todayLevel: '', | todayLevel: '', | ||||
dateList: [ | dateList: [ | ||||
@@ -300,7 +320,8 @@ export default { | |||||
noDataImg: require('@/assets/today/images/no_data_01.png'), | noDataImg: require('@/assets/today/images/no_data_01.png'), | ||||
showOverlay: true, | showOverlay: true, | ||||
isPageShow: false, | isPageShow: false, | ||||
encouragingLanguage: '' | |||||
encouragingLanguage: '', | |||||
diary: '', //情绪日记内容 | |||||
}; | }; | ||||
}, | }, | ||||
computed: { | computed: { | ||||
@@ -839,12 +860,50 @@ export default { | |||||
} | } | ||||
} | } | ||||
return color; | return color; | ||||
}, | |||||
onSaveDiary() { | |||||
if (this.$own.isNull(this.diary)) { | |||||
return ToastService.fail({ | |||||
message: '日记内容不能为空' | |||||
}) | |||||
} | |||||
ToastService.loading(); | |||||
let reqBody = { | |||||
personId: Number(this.$store.getters.personId), | |||||
mood: "", | |||||
content: this.diary | |||||
}; | |||||
APIHealthUser.saveDiary(reqBody).then(res => { | |||||
console.log("保存情绪日记结果", res); | |||||
let data = res.data; | |||||
if (data.stateCode === 1) { | |||||
ToastService.success({ | |||||
message: '保存成功' | |||||
}) | |||||
} else { | |||||
ToastService.fail({ | |||||
message: `${data.message}` | |||||
}) | |||||
} | |||||
}).catch(e => { | |||||
ToastService.fail({ | |||||
message: `${e.message}` | |||||
}) | |||||
}) | |||||
}, | |||||
// TODO 实现表情输入 | |||||
onChange() { | |||||
console.log("表情", this.result); | |||||
// 获取当前光标位置 | |||||
let start = this.$refs.myTextarea.selectionStart; | |||||
let end = this.$refs.myTextarea.selectionEnd; | |||||
this.$refs.myTextarea.value = this.$refs.myTextarea.value.slice(0, start) + this.result + this.$refs.myTextarea.value.slice(end); | |||||
this.$refs.myTextarea.setSelectionRange(start + 1, start + 1); | |||||
} | } | ||||
} | } | ||||
}; | |||||
} | |||||
</script> | </script> | ||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
@import './scss/index.scss'; | @import './scss/index.scss'; | ||||
</style> | |||||
</style> |
@@ -654,24 +654,57 @@ | |||||
.main { | .main { | ||||
width: 100%; | width: 100%; | ||||
.van-checkbox-group { | |||||
.van-radio-group { | |||||
width: 100%; | width: 100%; | ||||
margin-top: 50px; | margin-top: 50px; | ||||
display: flex; | |||||
flex-wrap: wrap; | |||||
align-items: center; | |||||
align-content: space-between; | |||||
justify-content: space-between; | |||||
display: grid; | |||||
grid-template-columns: repeat(3, 1fr); | |||||
/* 或者固定宽度,例如:repeat(4, 1fr) */ | |||||
gap: 10px; | |||||
} | } | ||||
.van-checkbox { | |||||
width: 26%; | |||||
min-width: 88px; | |||||
.van-radio { | |||||
width: 100%; | |||||
&:nth-of-type(n+4) { | &:nth-of-type(n+4) { | ||||
margin-top: 40px; | margin-top: 40px; | ||||
} | } | ||||
.checkbox-label { | |||||
width: 100%; | |||||
display: flex !important; | |||||
justify-content: flex-start !important; | |||||
align-items: center !important; | |||||
img { | |||||
width: 25px; | |||||
height: 25px; | |||||
object-fit: contain; | |||||
} | |||||
.text { | |||||
position: relative; | |||||
height: 27px; | |||||
padding: 0 10px; | |||||
background-image: url('@/assets/today/images/text.png'); | |||||
background-repeat: no-repeat; | |||||
/* 防止背景图片重复 */ | |||||
background-size: 50px 27px; | |||||
background-position: center; | |||||
/* 水平和垂直居中 */ | |||||
@include center(); | |||||
color: #333; | |||||
font-size: 14px; | |||||
} | |||||
} | |||||
.van-checkbox__label img { | .van-checkbox__label img { | ||||
width: 30px; | width: 30px; | ||||
} | } | ||||
@@ -689,6 +722,8 @@ | |||||
font-size: 28px; | font-size: 28px; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||