Browse Source

feat: 对接测评相关api

develop
song 4 years ago
parent
commit
21451e013b
  1. 3
      CHANGELOG.md
  2. 1
      package.json
  3. 2
      src/apis/yanyuan.js
  4. 9
      src/components/ConfigInfo/components/Info.vue
  5. 10
      src/components/ConfigInfo/components/config.js
  6. 22
      src/components/Evaluated/Evaluated.vue
  7. 31
      src/components/Evaluated/EvaluatedNLCP.vue
  8. 49
      src/components/Evaluated/EvaluatedXLJH.vue
  9. 48
      src/components/EvaluationChart/EvaluationChart.vue
  10. 28
      src/components/NotEvaluated/NotEvaluated.vue
  11. 6
      src/components/Projects/ProjectItem.vue
  12. 13
      src/components/Roles/Roles.vue
  13. 31
      src/components/Test/answerPage.vue
  14. 5
      src/components/Test/components/TestMain.vue
  15. 15
      src/components/Test/promptPage.vue
  16. 2
      src/components/TimeLine/TimeLine.vue
  17. 92
      src/components/TimeLine/component/TimeBox.vue
  18. 439
      src/pagesProject/project/project copy.vue
  19. 66
      src/pagesProject/project/project.vue
  20. 13
      src/pagesYanyuan/add-info/add-info.vue
  21. 81
      src/pagesYanyuan/assess/assess.vue
  22. 9
      src/store/task/mutations.js
  23. 1
      src/store/task/state.js
  24. 18
      src/store/yanyuan/mutations.js
  25. 10
      src/store/yanyuan/state.js

3
CHANGELOG.md

@ -1,4 +1,4 @@
# 0.1.0 (2021-11-15)
# 0.1.0 (2021-11-16)
### 🌟 新功能
范围|描述|commitId
@ -74,6 +74,7 @@
- | 训练归属界面 | [4c34cee](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/4c34cee)
- | 设置小红点 | [9316bcb](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/9316bcb)
- | 设置界面基本信息板块开发 | [bbaded0](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/bbaded0)
- | 试题接口 | [f8c137a](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/f8c137a)
- | 距调整pc端 | [5069aa1](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/5069aa1)
- | 适配小程序 | [9e3c45d](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/9e3c45d)
- | 适配小程序;小程序登录 | [cefc0eb](https://dd.tall.wiki/gitea/binbin0314/yanyuan_js/commits/cefc0eb)

1
package.json

@ -69,6 +69,7 @@
"conventional-changelog-cli": "^2.0.28",
"core-js": "^3.16.3",
"cross-env": "^7.0.3",
"echarts": "^5.2.2",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.4.1",
"eslint-plugin-vue": "^6.2.2",

2
src/apis/yanyuan.js

@ -28,6 +28,8 @@ const install = (Vue, vm) => {
vm.$u.api.getQuestion = param => vm.$u.post(`${yanyuan}/question/get`, param);
// 试题答案保存
vm.$u.api.saveAnswer = param => vm.$u.post(`${yanyuan}/question/saveAnswer`, param);
// 脑力测评结果计算
vm.$u.api.mentalTestCalculate = param => vm.$u.post(`${yanyuan}/mentalTest/calculate`, param);
};
export default { install };

9
src/components/ConfigInfo/components/Info.vue

@ -292,7 +292,13 @@
</view>
<!-- input 文本输入框 -->
<view v-if="colItem.type === 8" class="pr-7">
<u-input placeholder="请输入" v-model="colItem.value" :clearable="false" input-align="right" />
<u-input
placeholder="请输入"
v-model="colItem.value"
:clearable="false"
input-align="right"
@blur="change(colItem.value, index, itemIndex, colItem.type)"
/>
</view>
<!-- 地区选择器 -->
<view v-if="colItem.type === 9">
@ -449,6 +455,7 @@ export default {
break;
}
}
console.log('info++: ', info);
this.$emit('saveInfo', info);
},

10
src/components/ConfigInfo/components/config.js

@ -18,6 +18,14 @@ const bloodPressure = () => {
*/
export const infoList = [
[
{
name: '姓名',
label: 'userName',
showType: 2,
type: 8,
value: null,
show: false,
},
{
name: '性别',
label: 'sex',
@ -354,7 +362,7 @@ export const infoList = [
radioList: [
{ value: '神经内科', label: '神经内科' },
{ value: '精神卫生科', label: '精神卫生科' },
{ value: '老年病科', label: '神经内科' },
{ value: '老年病科', label: '老年病科' },
{ value: '康复科', label: '康复科' },
{ value: '其他', label: '其他' },
],

22
src/components/Evaluated/Evaluated.vue

@ -1,22 +0,0 @@
<template>
<view>
<view class="flex flex-nowrap items-center">
<view class="flex-1 flex flex-nowrap items-center">
<u-rate :count="count" v-model="count" :disabled="true" :size="26" :gutter="2" active-color="#333"></u-rate>
<text class="mx-2">数独</text>
<view class="rounded-full bg-blue-500 w-max u-font-xs text-white px-2 items-center">轻松完成</view>
</view>
<u-icon name="arrow-right" color="#909399"></u-icon>
</view>
</view>
</template>
<script>
export default {
data() {
return { count: 3 };
},
};
</script>
<style></style>

31
src/components/Evaluated/EvaluatedNLCP.vue

@ -0,0 +1,31 @@
<template>
<view>
<text>{{ task.name }}</text>
<EvaluationChart />
<view class="mt-2">
<view>测评结果</view>
<view class="flex justify-between">
<u-rate
:count="task.data.mentalTest.gradeResult"
v-model="task.data.mentalTest.gradeResult"
:disabled="true"
:size="26"
:gutter="2"
active-color="#1890FF"
></u-rate>
<u-icon name="arrow-down" color="#909399"></u-icon>
</view>
</view>
</view>
</template>
<script>
export default {
props: { task: { type: Object, default: null } },
data() {
return {};
},
};
</script>
<style></style>

49
src/components/Evaluated/EvaluatedXLJH.vue

@ -0,0 +1,49 @@
<template>
<view>
<view class="flex flex-nowrap items-center">
<view class="flex-1 flex flex-nowrap items-center">
<u-rate
:count="task.data.train.level"
v-model="task.data.train.level"
:disabled="true"
:size="26"
:gutter="2"
active-color="#333"
></u-rate>
<text class="mx-2">{{ task.name }}</text>
<view
class="rounded-full w-max u-font-xs text-white px-2 items-center"
:class="
Math.ceil(task.data.train.finishResult) === 1
? 'bg-red-500'
: Math.ceil(task.data.train.finishResult) === 2
? 'bg-blue-500'
: 'bg-yellow-500'
"
v-if="task.data.train.finishResult"
>
{{
Math.ceil(task.data.train.finishResult) === 1
? '非常困难'
: Math.ceil(task.data.train.finishResult) === 2
? '略有困难'
: '轻松完成'
}}
轻松完成
</view>
</view>
<u-icon name="arrow-down" color="#909399"></u-icon>
</view>
</view>
</template>
<script>
export default {
props: { task: { type: Object, default: null } },
data() {
return { count: 3 };
},
};
</script>
<style></style>

48
src/components/EvaluationChart/EvaluationChart.vue

@ -0,0 +1,48 @@
<template>
<view> <view id="myChart" :style="{ width: '300px', height: '300px' }" ref="aaa"></view> </view>
</template>
<script>
//
let echarts = require('echarts/lib/echarts');
//
require('echarts/lib/chart/bar');
// title
require('echarts/lib/component/tooltip');
require('echarts/lib/component/title');
export default {
name: 'hello',
data() {
return { msg: 'Welcome to Your Vue.js App' };
},
mounted() {
// this.drawLine();
},
methods: {
drawLine() {
// domecharts
let myChart = echarts.init(document.getElementById('myChart'));
//
myChart.setOption({
title: { text: 'ECharts 入门示例' },
tooltip: {},
xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] },
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
},
],
});
},
},
};
</script>
<style></style>

28
src/components/NotEvaluated/NotEvaluated.vue

@ -1,28 +1,28 @@
<template>
<view class="flex flex-col">
<view class="flex justify-between items-center">
<text class="text-base">脑力测评</text>
<u-icon name="arrow-right"></u-icon>
</view>
<view class="text-base items-center">{{ task.name }}</view>
<view class="text-sm text-gray-400 my-2">
这套脑力测评工具是认知障碍诊疗专家在国际权威 认知测评量表的基础上结合我国老年人生活背景 及多年的临床经验编写而成每次测评包括35个
问题涵盖了各个方面的认知功能您只需要跟随 屏幕提示回答这些问题系统就会对您的认知水平 做一个全面评估根据评估结果系统将会为您量
身定制一套认知训练课程 这些问题有难有易请您别紧张因为老人的视力 不太好我们建议您在平板电脑上或者在台式电脑 上操作.
{{ task.description }}
</view>
<view class="flex flex-nowrap my-2">
<u-button type="primary" size="mini" class="mx-0" @click="startAssess">开始测评</u-button>
<view class="flex-1"></view>
<view v-if="task.data.type === 0 && task.data.mentalTest.finishStatus === 0">
<view class="flex flex-nowrap my-2">
<u-button type="primary" size="mini" class="mx-0" @click="startAssess">开始测评</u-button>
<view class="flex-1"></view>
</view>
<text class="text-xs text-gray-300">每两个周可进行一次测评</text>
</view>
<text class="text-xs text-gray-300">每两个周可进行一次测评</text>
</view>
</template>
<script>
import { mapActions } from 'vuex';
import { mapActions, mapMutations } from 'vuex';
export default {
props: { task: { type: Object, default: null } },
methods: {
...mapActions('yanyuan', ['handleQuestion']),
...mapMutations('task', ['setTask']),
/**
* 开始测评 试题查询
@ -32,9 +32,11 @@ export default {
*/
async startAssess() {
try {
const { task } = this;
this.setTask(task);
const params = {
code: 'NLCP',
reportId: '1458968153773838336',
reportId: task.id,
num: '1',
};
const data = await this.handleQuestion(params);

6
src/components/Projects/ProjectItem.vue

@ -82,7 +82,7 @@
</template>
<script>
import { mapGetters } from 'vuex';
import { mapGetters, mapMutations } from 'vuex';
export default {
props: {
@ -117,9 +117,11 @@ export default {
computed: mapGetters('user', ['userId']),
methods: {
...mapMutations('project', ['setProject']),
//
openProject(project) {
console.log('project: ', project);
this.setProject(project);
const { name, id, url } = project;
url && (uni.$t.domain = url);
this.$u.route('/pagesProject/project/project', {

13
src/components/Roles/Roles.vue

@ -16,7 +16,7 @@
'tab-choice': item.mine == 0 && roleId === item.id,
}"
:key="index"
@click="changeRole(item.id, index, item.type)"
@click="changeRole(item.id, index, item.code)"
class="tab-item"
v-for="(item, index) in roles"
>
@ -28,7 +28,7 @@
</view>
</view>
<!-- 设置 -->
<view
<!-- <view
:class="{
'default-tab-choice': setRole.mine == 1 && roleId === setRole.id,
'default-tab-item': setRole.mine == 1 && roleId !== setRole.id,
@ -43,7 +43,7 @@
>
{{ setRole.name }}
</view>
</view>
</view> -->
</view>
<!-- <u-icon class="m-1" name="xuanxiang" custom-prefix="custom-icon" size="20px" @click="operation"></u-icon> -->
<view class="flex align-center">
@ -160,10 +160,13 @@ export default {
// projectroleId
changeRole(id, index, type) {
try {
if (type === 1) {
if (type === 'Setting') {
//
this.$emit('changeIsSetting');
this.$emit('changeIsSetting', true);
} else {
this.$emit('changeIsSetting', false);
}
// script
// this.clearPluginScript();
this.$nextTick(() => {

31
src/components/Test/answerPage.vue

@ -9,9 +9,10 @@
<u-line class="my-2" color="#c8c7cc" />
</view>
<!-- 只有标题 -->
<view v-if="question.positions.length === 1">
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex" class="flex-1">
<TestMain @setParams="setParams" v-if="option.page === 1" :options="option.positions" />
<TestMain :options="option.positions" />
</view>
</view>
@ -21,14 +22,14 @@
<TitlePosition :item="item" />
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex">
<TestMain @setParams="setParams" v-if="option.page === 1" :options="option.positions" />
<TestMain v-if="option.page === 1" :options="option.positions" />
</view>
</view>
<!-- 选项后 -->
<view v-if="item.position === 2" class="flex flex-col">
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex">
<TestMain @setParams="setParams" v-if="option.page === 1" :options="option.positions" />
<TestMain v-if="option.page === 1" :options="option.positions" />
</view>
<TitlePosition :item="item" />
@ -39,14 +40,14 @@
<TitlePosition :item="item" class="flex-1" />
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex" class="flex-1">
<TestMain @setParams="setParams" v-if="option.page === 1" :options="option.positions" />
<TestMain v-if="option.page === 1" :options="option.positions" />
</view>
</view>
<!-- 选项右 -->
<view v-if="item.position === 4" class="flex flex-nowrap">
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex" class="flex-1">
<TestMain @setParams="setParams" v-if="option.page === 1" :options="option.positions" />
<TestMain v-if="option.page === 1" :options="option.positions" />
</view>
<TitlePosition :item="item" class="flex-1" />
@ -54,7 +55,8 @@
</view>
</view>
<u-button class="mt-5" type="primary" @click="next">下一题</u-button>
<u-button class="mt-5" type="primary" @click="next" v-if="questionInfo.numStatus === 2" :loading="loading">查看测评结果</u-button>
<u-button class="mt-5" type="primary" @click="next" v-else :loading="loading">下一题</u-button>
</view>
</template>
@ -76,17 +78,24 @@ export default {
},
},
data() {
return { loading: false };
},
computed: mapState('yanyuan', ['questionInfo']),
methods: {
//
setParams(optionId) {
this.$emit('setParams', optionId);
},
next() {
this.$emit('nextQuestion');
},
openLoading() {
this.loading = true;
},
closeLoading() {
this.loading = false;
},
},
};
</script>

5
src/components/Test/components/TestMain.vue

@ -17,6 +17,7 @@
</template>
<script>
import { mapMutations } from 'vuex';
export default {
props: {
options: {
@ -30,9 +31,11 @@ export default {
},
methods: {
...mapMutations('yanyuan', ['setOptionId']),
// radioradio-group
radioChange(e) {
this.$emit('setParams', e);
this.setOptionId(e);
},
},
};

15
src/components/Test/promptPage.vue

@ -9,9 +9,10 @@
<u-line class="my-2" color="#c8c7cc" />
</view>
<!-- 只有标题 -->
<view v-if="question.positions.length === 1">
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex" class="flex-1">
<TestMain @setParams="setParams" v-if="option.page === 1" :options="option.positions" />
<TestMain v-if="option.page === 1" :options="option.positions" />
</view>
</view>
@ -21,14 +22,14 @@
<TitlePosition :item="item" />
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex">
<TestMain @setParams="setParams" v-if="option.page === 0" :options="option.positions" />
<TestMain v-if="option.page === 0" :options="option.positions" />
</view>
</view>
<!-- 选项后 -->
<view v-if="item.position === 2" class="flex flex-col">
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex">
<TestMain @setParams="setParams" v-if="option.page === 0" :options="option.positions" />
<TestMain v-if="option.page === 0" :options="option.positions" />
</view>
<TitlePosition :item="item" />
@ -39,14 +40,14 @@
<TitlePosition :item="item" class="flex-1" />
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex" class="flex-1">
<TestMain @setParams="setParams" v-if="option.page === 0" :options="option.positions" />
<TestMain v-if="option.page === 0" :options="option.positions" />
</view>
</view>
<!-- 选项右 -->
<view v-if="item.position === 4" class="flex flex-nowrap">
<view v-for="(option, optionIndex) in questionInfo.options" :key="optionIndex" class="flex-1">
<TestMain @setParams="setParams" v-if="option.page === 0" :options="option.positions" />
<TestMain v-if="option.page === 0" :options="option.positions" />
</view>
<TitlePosition :item="item" class="flex-1" />
@ -74,10 +75,6 @@ export default {
openAnswerPage() {
this.$emit('openAnswerPage');
},
setParams(optionId) {
this.$emit('setParams', optionId);
},
},
};
</script>

2
src/components/TimeLine/TimeLine.vue

@ -111,12 +111,14 @@ export default {
this.$t.storage.setStorageSync('taskId', ''); //
} else {
const item = this.tasks.find(task => task.detailId);
console.log('item: ', item);
if (item) {
this.setScrollToTaskId(`a${item.id}`);
} else {
// taskId
// 线id 线
const task = this.tasks.find(item => this.$moment(+item.planStart).isSame(this.timeNode, this.timeGranularity));
console.log('task: ', task);
task && this.setScrollToTaskId(`a${task.id}`); // task id
}
}

92
src/components/TimeLine/component/TimeBox.vue

@ -3,52 +3,62 @@
<!-- v-if="tasks && tasks.length" -->
<view>
<view :key="task.id" v-for="task in tasks" :id="`a${task.id}`">
<view class="flex">
<TimeStatus :task="task" />
<view class="flex items-center justify-between flex-1 ml-2 task-column">
<view v-if="task.process !== 4">{{ $moment(+task.planStart).format(startTimeFormat) }}</view>
<view v-else>{{ $moment(+task.planStart).format('D日') }}</view>
<!-- 外层 -->
<view v-if="task.name">
<view class="flex">
<TimeStatus :task="task" />
<view class="flex items-center justify-between flex-1 ml-2 task-column">
<view v-if="task.process !== 4">{{ $moment(+task.planStart).format(startTimeFormat) }}</view>
<view v-else>{{ $moment(+task.planStart).format('D日') }}</view>
<!-- 任务功能菜单 -->
<!-- <TaskTools v-if="task.process !== 4" :task="task" /> -->
<!-- 任务功能菜单 -->
<!-- <TaskTools v-if="task.process !== 4" :task="task" /> -->
</view>
</view>
</view>
<view class="border-l-2 border-gray-300 plugin">
<view class="h-3" v-if="task.process === 4"></view>
<view class="ml-3 overflow-hidden shadow-lg task-box">
<u-card
:show-foot="false"
:show-head="false"
:style="{ height: setHeight(task.panel) }"
class="h-16"
margin="0"
v-if="showSkeleton"
>
<view slot="body">
<view>
<skeleton :banner="false" :loading="true" :row="4" animate class="mt-2 u-line-2 skeleton"></skeleton>
<view class="border-l-2 border-gray-300 plugin">
<view class="h-3" v-if="task.process === 4"></view>
<view class="ml-3 overflow-hidden shadow-lg task-box">
<u-card
:show-foot="false"
:show-head="false"
:style="{ height: setHeight(task.panel) }"
class="h-16"
margin="0"
v-if="showSkeleton"
>
<view slot="body">
<view>
<skeleton :banner="false" :loading="true" :row="4" animate class="mt-2 u-line-2 skeleton"></skeleton>
</view>
</view>
</view>
</u-card>
</u-card>
<u-card
@click="onClickTask(task.planStart - 0, task.id)"
:show-foot="false"
:show-head="false"
:style="{ height: setHeight(task.panel) }"
class="h-16"
margin="0"
v-if="tasks && tasks.length && task.process !== 4 && !showSkeleton"
>
<view slot="body">
<view class="p-0 u-col-between">
<Evaluated v-if="isEvaluated" />
<NotEvaluated v-else />
<u-card
@click="onClickTask(task.planStart - 0, task.id)"
:show-foot="false"
:show-head="false"
:style="{ height: setHeight(task.panel) }"
class="h-16"
margin="0"
v-if="tasks && tasks.length && task.process !== 4 && !showSkeleton"
>
<view slot="body">
<!-- 脑力测评 -->
<view class="p-0 u-col-between">
<NotEvaluated :task="task" v-if="task.data.mentalTest.finishStatus === 0" />
<view v-else>
<EvaluatedNLCP :task="task" v-if="task.data.type === 0" />
<EvaluatedXLJH :task="task" v-if="task.data.type === 1" />
</view>
</view>
</view>
</view>
</u-card>
</u-card>
</view>
</view>
</view>
<!-- 内层 -->
<view v-else> 内层 </view>
</view>
</view>
<!-- 局部弹框操作栏 -->
@ -61,10 +71,12 @@ import { mapState, mapMutations, mapGetters, mapActions } from 'vuex';
import Skeleton from '@/components/Skeleton/Skeleton';
import TimeStatus from './TimeStatus.vue';
// import TaskTools from './TaskTools.vue';
import EvaluatedNLCP from 'components/Evaluated/EvaluatedNLCP';
import EvaluatedXLJH from 'components/Evaluated/EvaluatedXLJH';
export default {
name: 'TimeBox',
components: { TimeStatus, Skeleton },
components: { TimeStatus, Skeleton, EvaluatedNLCP, EvaluatedXLJH },
data() {
return {

439
src/pagesProject/project/project copy.vue

@ -0,0 +1,439 @@
<template>
<view :style="{ height: height }" class="flex flex-col overflow-hidden u-font-16">
<!-- 标题栏 -->
<Title />
<view class="container flex flex-col flex-1 overflow-hidden bg-gray-100">
<!-- 角色栏 -->
<Roles @changeIsSetting="changeIsSetting" />
<!-- 日常任务面板 -->
<!-- <Globals /> -->
<!-- 定期任务面板 -->
<!-- <ConfigInfo class="flex-1 overflow-hidden" style="background-color: #f3f3f3" /> -->
<ConfigInfo class="flex-1 overflow-hidden" style="background-color: #f3f3f3" v-if="isSetting" />
<TimeLine @getTasks="getTasks" style="background-color: #f3f3f3" class="flex-1 overflow-hidden" ref="timeLine" v-else />
</view>
<!-- 引导语 -->
<!-- <GuidePage class="w-full h-full" v-if="showGuide" @quitGuide="quitGuide" /> -->
</view>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
import { setPlaceholderTasks, computeFillPlaceholderTaskCount } from '@/utils/task';
import { flatten } from 'lodash';
export default {
data() {
return {
height: '',
show: false,
questionnaires: [],
count: 0,
chooseItem: false,
showGuide: false,
isSetting: false, //
};
},
computed: {
...mapState('user', ['user', 'token']),
...mapState('role', ['visibleRoles', 'roleId']),
...mapState('task', ['timeNode', 'timeUnit', 'tasks', 'regularTask', 'newProjectInfo', 'showSkeleton', 'showScrollTo']),
...mapState('project', ['project']),
...mapGetters('task', ['timeGranularity']),
...mapGetters('project', ['projectId']),
...mapGetters('user', ['userId']),
},
onLoad(options) {
if (options.share && options.share === '1') {
this.shareInit(options);
} else {
this.init(options);
}
},
watch: {
/**
* 当时间基准点发生变化时
* 重新根据时间和角色查询普通日常任务
* 永久日常任务不发生改变
*/
timeNode(val) {
if (val && this.roleId) {
this.clearTasksData();
this.getGlobalData(); //
this.initPlanTasks(); //
}
},
/**
* 当角色发生变化时
* 重新查询永久日常任务和普通日常任务
* 注意: 切换角色后 重新设置了时间基准点 时间基准点一定会变
* 所以监听时间基准点获取 可变日常任务即可 这里不用获取 避免重复获取
*/
roleId(val) {
if (val) {
if (this.isSetting) return;
this.setTimeNode(Date.now());
//
const params = { roleId: val, projectId: this.projectId, templateCode: this.project.templateCode };
this.getPermanent(params);
}
},
//
newProjectInfo(val) {
if (val && val.projectId && val.url) {
this.$u.route('/', { u: this.userId, p: val.projectId, url: val.url });
this.clearTasksData();
this.setRoleId('');
const options = this.$route.query;
this.init(options);
}
},
},
mounted() {
const system = uni.getSystemInfoSync();
this.height = system.windowHeight + 'px';
// TODO:
setTimeout(() => {
this.showGuide = true;
}, 1000);
},
onUnload() {
this.clearTasksData();
this.setRoleId('');
},
methods: {
...mapActions('user', ['getToken']),
...mapActions('task', ['getRegulars', 'getPermanent', 'getGlobal']),
...mapMutations('user', ['setToken']),
...mapMutations('project', ['setProject', 'setProjectName']),
...mapMutations('role', ['setInvisibleRoles', 'setVisibleRoles', 'setRoleId']),
...mapMutations('task', [
'setPermanents',
'setUpTasks',
'setDownTasks',
'setDailyTasks',
'setTimeNode',
'clearTasks',
'clearEndFlag',
'setShowSkeleton',
'setTopEnd',
'setBottomEnd',
'setShowScrollTo',
]),
back() {
uni.navigateBack();
},
changeIsSetting(show) {
this.isSetting = show;
},
//
async initPlanTasks() {
this.setPrevPlaceholderTasks(); //
this.setNextPlaceholderTasks(); //
// // this.$nextTick(() => this.$refs.timeLine.setScrollPosition()); //
await this.getInitTasks(); //
//
let timer = null;
timer = setInterval(() => {
if (this.showScrollTo) {
clearInterval(timer);
this.$nextTick(() => this.$refs.timeLine.setScrollPosition());
}
}, 500);
},
// ||
getInitTasks() {
// id
// this.getTasks({ queryType: 1 }, preloadFn); //
//
this.getTasks({ queryType: 0 }); //
},
/**
* 根据时间基准点和角色查找定期任务
* @param {object} query
* @param {string} query.roleId 角色id
* @param {string} query.timeNode 时间基准点 默认当前
* @param {string} query.timeUnit 时间颗粒度 默认天
* @param {string} query.queryNum 查找颗粒度数量 默认3个
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
getTasks(query) {
this.setShowSkeleton(true);
const params = this.generateGetTaskParam(query);
this.$t.$q.getRegularTask(params, (err, data) => {
this.setShowSkeleton(false);
if (err) {
// TODO:
console.error('err: ', err);
} else {
this.setShowScrollTo(true);
//
//
if (data && data.length) {
this.replacePrevData(data, params.queryType);
params.queryType === 0 ? this.setTopEnd(false) : this.setBottomEnd(false);
} else {
// TODO: 0 -> 1 ->
params.queryType === 0 ? this.setPrevPlaceholderTasks() : this.setNextPlaceholderTasks();
}
}
});
},
/**
* 生成getTasks所用的参数
* @param {object} query getTasks传递的参数
*/
generateGetTaskParam(query) {
const { roleId, timeNode, timeUnit, projectId, project } = this;
return {
roleId,
timeNode: query.timeNode || timeNode,
timeUnit: query.timeUnit || timeUnit,
// queryNum: query.queryNum || 3,
queryNum: 1,
queryType: query.queryType,
projectId,
templateCode: project.templateCode,
};
},
//
setPrevPlaceholderTasks() {
this.setTopEnd(true);
let startTime = '';
const { tasks } = this;
if (!tasks || !tasks.length) {
startTime = Date.now(); //
} else {
startTime = tasks[0].planStart - 0; //
}
const placeholderTasks = setPlaceholderTasks(startTime, true, this.timeGranularity);
this.setUpTasks(placeholderTasks);
},
//
setNextPlaceholderTasks() {
this.setBottomEnd(true);
let startTime = '';
if (!this.tasks || !this.tasks.length) {
startTime = Date.now();
} else {
startTime = +this.tasks[this.tasks.length - 1].planStart;
}
const initData = setPlaceholderTasks(startTime, false, this.timeGranularity);
this.setDownTasks(initData);
},
/**
* 用拿到的新数据 替换 时间刻度/旧数据
* 先对比 新旧数据的 始末时间 补齐刻度
* 再遍历对比 用任务替换刻度
* @param {array} data 服务端返回的新数据 上边已经处理过空值
* @param {number} type 0 -> 向上 1->向下
*/
replacePrevData(data, type) {
const { timeGranularity } = this;
let oldTasks = this.fillPlaceholderTask({ tasks: this.tasks, data, timeGranularity }); //
//
// TODO: tasks
oldTasks.forEach((taskItem, index) => {
const arr = data.filter(dataItem => this.$moment(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity));
console.log('arr: ', arr);
if (arr && arr.length) {
oldTasks.splice(index, 1, [...arr]); // array, [{},{},[],[],{}]
}
});
oldTasks = flatten(oldTasks); // 1
console.log('oldTasks: ', oldTasks);
this.clearTasks(); // setUpTasks setUpTasks
type === 0 ? this.setUpTasks(oldTasks) : this.setDownTasks(oldTasks);
},
/**
* 超出旧数据上下限 补齐时间刻度到新数据的起始时间颗粒度
*/
fillPlaceholderTask({ tasks, data, timeGranularity }) {
const { prev, next } = computeFillPlaceholderTaskCount({ tasks, data, timeGranularity });
if (prev) {
const newTasks = setPlaceholderTasks(+tasks[0].planStart, true, timeGranularity, prev);
this.setUpTasks(newTasks);
}
if (next) {
const newTasks = setPlaceholderTasks(+tasks[tasks.length - 1].planStart, false, timeGranularity, next);
this.setDownTasks(newTasks);
}
return this.tasks;
},
/**
* 初始化
* @param {object | null} options
*/
init(options) {
if (!this.token) {
// tokenuserIdtoken
// token userId
if (!options || !options.u) {
this.$t.ui.showToast('缺少用户信息参数'); // u (userId)
} else {
this.getToken(options.u);
}
}
//
options && options.pname && this.setProjectName(options.pname);
if (!options || !options.p) {
this.$t.ui.showToast('缺少项目信息参数'); // id
} else {
if (options.p !== this.$t.storage.getStorageSync('projectId')) {
this.$t.storage.setStorageSync('roleId', '');
}
// TODO
// this.getProjectById({ projectId: options.p, num: 0 }); // id
// id
this.getRoles({ projectId: options.p, num: 0, templateCode: this.project.templateCode });
}
},
//
async shareInit(options) {
const storageUser = this.$t.storage.getStorageSync('user');
const user = storageUser ? JSON.parse(storageUser) : null;
if (user && user.id) {
await this.getToken(user.id);
const res = await this.clickShare({ code: options.shareId });
if (res && res.projectId) {
let query = { ...this.$route.query };
query = {
u: user.id,
p: res.projectId,
};
this.$router.push({ path: this.$route.path, query });
this.init(query);
}
} else {
this.$t.ui.showToast('缺少用户信息参数,请登录');
}
},
/**
* 点击分享连接
* @param {any} commit
* @param {object} param 请求参数
*/
async clickShare(param) {
try {
const data = await this.$u.api.clickShare(param);
return data;
} catch (error) {
this.$t.ui.showToast(error.msg || '获取失败');
}
},
/**
* 通过项目id获取项目信息
* @param {object} params 提交的参数
*/
async getProjectById(params) {
try {
const data = await uni.$u.api.findProjectById(params);
this.setProject(data);
// id
this.getRoles(params);
} catch (error) {
console.error('error: ', error || '获取项目信息失败');
}
},
/**
* 通过项目id获取角色信息
* @param {string} projectId
* @param {object} params 提交的参数
*/
getRoles(params) {
this.$t.$q.findShowRole(params, (err, data) => {
if (err) {
console.error('err: ', err || '获取角色信息失败');
} else {
this.setInvisibleRoles(data ? data.invisibleList : []);
this.setVisibleRoles(data ? data.visibleList : []);
this.setInitialRoleId(data ? data.visibleList : []);
}
});
},
//
setInitialRoleId(visibleList) {
if (!visibleList || !visibleList.length) return;
const index = visibleList.findIndex(item => +item.mine === 1);
const currentRole = index > 0 ? visibleList[index] : visibleList[0];
const storageRoleId = this.$t.storage.getStorageSync('roleId');
const currentRoleId = storageRoleId ? storageRoleId : currentRole ? currentRole.id : '';
this.setRoleId(currentRoleId);
// storage
this.$t.storage.setStorageSync('roleId', '');
},
//
getGlobalData() {
const { roleId, timeNode, timeUnit, projectId } = this;
const param = { roleId, timeNode, timeUnit, projectId };
this.getGlobal(param);
},
//
clearTasksData() {
//
this.setPermanents([]);
this.setDailyTasks([]);
//
this.clearTasks();
//
//
this.clearEndFlag();
},
// 退
quitGuide() {
this.showGuide = false;
},
},
};
</script>
<style lang="scss" scoped>
.img-box {
width: 750rpx;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 999;
}
.border-b {
border-bottom: 1px solid #e4e7ed;
}
</style>

66
src/pagesProject/project/project.vue

@ -24,7 +24,7 @@
<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
import { setPlaceholderTasks, computeFillPlaceholderTaskCount } from '@/utils/task';
import { flatten } from 'lodash';
// import { flatten } from 'lodash';
export default {
data() {
@ -50,7 +50,6 @@ export default {
},
onLoad(options) {
console.log('options: ', options);
if (options.share && options.share === '1') {
this.shareInit(options);
} else {
@ -65,7 +64,6 @@ export default {
* 永久日常任务不发生改变
*/
timeNode(val) {
console.log('val: ', val);
if (val && this.roleId) {
this.clearTasksData();
this.getGlobalData(); //
@ -82,10 +80,9 @@ export default {
roleId(val) {
if (val) {
if (this.isSetting) return;
console.log('当角色发生变化时: ', val);
this.setTimeNode(Date.now());
//
const params = { roleId: val, projectId: this.projectId };
const params = { roleId: val, projectId: this.projectId, templateCode: this.project.templateCode };
this.getPermanent(params);
}
},
@ -141,9 +138,8 @@ export default {
uni.navigateBack();
},
changeIsSetting() {
this.isSetting = true;
console.log('isSetting: ', this.isSetting);
changeIsSetting(show) {
this.isSetting = show;
},
//
@ -164,37 +160,8 @@ export default {
// ||
getInitTasks() {
//
function preloadFn(that) {
const detailId = that.tasks.findIndex(task => task.detailId);
const arr = [];
that.tasks.forEach(task => {
if (task.detailId) {
arr.push(task);
}
});
if (detailId !== -1) {
// 1
const { pageCount } = that.$t.task;
that.$nextTick(() => {
//
const { tasks, timeGranularity } = that;
that.getTasks({ timeNode: +tasks[detailId].planStart, queryType: 0, queryNum: pageCount });
//
const nextQueryTime = +that.$t.time.add(+arr[arr.length - 1].planStart, 1, timeGranularity);
that.getTasks({ timeNode: nextQueryTime, queryType: 1, queryNum: pageCount });
});
} else {
//
//
// that.setPrevPlaceholderTasks();
// //
// that.setNextPlaceholderTasks();
}
}
console.log('preloadFn: ');
// id
this.getTasks({ queryType: 1 }, preloadFn); //
// this.getTasks({ queryType: 1 }, preloadFn); //
//
this.getTasks({ queryType: 0 }); //
},
@ -208,7 +175,7 @@ export default {
* @param {string} query.queryNum 查找颗粒度数量 默认3个
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
getTasks(query, fn) {
getTasks(query) {
this.setShowSkeleton(true);
const params = this.generateGetTaskParam(query);
this.$t.$q.getRegularTask(params, (err, data) => {
@ -227,9 +194,6 @@ export default {
// TODO: 0 -> 1 ->
params.queryType === 0 ? this.setPrevPlaceholderTasks() : this.setNextPlaceholderTasks();
}
if (this.tasks.length && fn) {
fn(this);
}
}
});
},
@ -239,14 +203,16 @@ export default {
* @param {object} query getTasks传递的参数
*/
generateGetTaskParam(query) {
const { roleId, timeNode, timeUnit, projectId } = this;
const { roleId, timeNode, timeUnit, projectId, project } = this;
return {
roleId,
timeNode: query.timeNode || timeNode,
timeUnit: query.timeUnit || timeUnit,
queryNum: query.queryNum || 3,
// queryNum: query.queryNum || 3,
queryNum: 1,
queryType: query.queryType,
projectId,
templateCode: project.templateCode,
};
},
@ -291,12 +257,15 @@ export default {
// TODO: tasks
oldTasks.forEach((taskItem, index) => {
const arr = data.filter(dataItem => this.$moment(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity));
console.log('arr: ', arr);
if (arr && arr.length) {
oldTasks.splice(index, 1, [...arr]); // array, [{},{},[],[],{}]
}
});
oldTasks = flatten(oldTasks); // 1
// oldTasks = flatten(oldTasks); // 1
console.log('oldTasks: ', oldTasks);
this.clearTasks(); // setUpTasks setUpTasks
type === 0 ? this.setUpTasks(oldTasks) : this.setDownTasks(oldTasks);
},
@ -342,7 +311,10 @@ export default {
this.$t.storage.setStorageSync('roleId', '');
}
// TODO
this.getProjectById({ projectId: options.p, num: 0 }); // id
// this.getProjectById({ projectId: options.p, num: 0 }); // id
// id
this.getRoles({ projectId: options.p, num: 0, templateCode: this.project.templateCode });
}
},
@ -392,7 +364,7 @@ export default {
// id
this.getRoles(params);
} catch (error) {
console.log('error: ', error || '获取项目信息失败');
console.error('error: ', error || '获取项目信息失败');
}
},

13
src/pagesYanyuan/add-info/add-info.vue

@ -26,7 +26,19 @@ export default {
methods: {
//
saveInfo(info) {
//
this.params.apoeGene = 0;
this.params.isInsomnic = 0;
this.params.isSmoke = 0;
this.params.isDrink = 0;
this.params.isTea = 0;
this.params.isStrongFlavour = 0;
this.params.isMoreOil = 0;
console.log('info: ', info);
//
this.params[info.label] = info.value;
//
if (info.value === '其他' && info.showOther && info.otherValue) {
this.params[info.label] = info.otherValue;
@ -89,6 +101,7 @@ export default {
async submit() {
try {
const params = this.params;
console.log('params: ', params);
if (!this.validationRequired(params)) return;
await this.$u.api.addTrainee(params);
if (this.isApplying) {

81
src/pagesYanyuan/assess/assess.vue

@ -1,20 +1,23 @@
<template>
<view class="flex flex-col p-3">
<!-- 全局提示框 -->
<u-top-tips ref="uTips"></u-top-tips>
<!-- 有一页 -->
<view v-if="questionInfo.questions.length === 1">
<answerPage :turnPages="false" @setParams="setParams" @nextQuestion="nextQuestion" />
<answerPage :turnPages="true" :question="questionInfo.questions[0]" ref="child" @nextQuestion="nextQuestion" />
</view>
<!-- 有两页 -->
<view v-if="questionInfo.questions.length === 2">
<promptPage @openAnswerPage="openAnswerPage" @setParams="setParams" v-if="!showAnswerPage" :question="questionInfo.questions[0]" />
<answerPage v-else :turnPages="true" :question="questionInfo.questions[1]" @setParams="setParams" @nextQuestion="nextQuestion" />
<promptPage @openAnswerPage="openAnswerPage" v-if="!showAnswerPage" :question="questionInfo.questions[0]" />
<answerPage v-else :turnPages="true" :question="questionInfo.questions[1]" ref="child" @nextQuestion="nextQuestion" />
</view>
</view>
</template>
<script>
import { mapState, mapGetters, mapMutations } from 'vuex';
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
import promptPage from 'components/Test/promptPage';
import answerPage from 'components/Test/answerPage';
@ -25,14 +28,26 @@ export default {
return { showAnswerPage: false, param: {} };
},
watch: {
questionInfo(val) {
if (val) {
this.showAnswerPage = false;
this.setOptionId('');
}
},
},
computed: {
...mapState('project', ['project']),
...mapState('yanyuan', ['questionInfo']),
...mapState('yanyuan', ['questionInfo', 'optionId']),
...mapState('task', ['task']),
...mapGetters('user', ['userId']),
},
methods: {
...mapMutations('task', ['setIsEvaluated']),
...mapMutations('yanyuan', ['setQuestionInfo', 'setAssessResult', 'setOptionId']),
...mapActions('yanyuan', ['handleQuestion']),
//
openAnswerPage() {
@ -40,13 +55,15 @@ export default {
},
//
setParams(optionId) {
setParams() {
const { optionId, questionInfo, task } = this;
this.param = {
code: 'NLCP',
optionId: optionId ? optionId : '',
questionId: this.questionInfo.id,
reportId: '1458968153773838336',
optionId: optionId,
questionId: questionInfo.id,
reportId: task.id,
};
return this.param;
},
/**
@ -58,17 +75,55 @@ export default {
*/
async nextQuestion() {
try {
await this.$u.api.saveAnswer(this.param);
this.$t.ui.showToast('提交成功');
uni.navigateTo({ url: '/pagesYanyuan/assess/assess' });
this.$refs.child.openLoading();
const param = this.setParams();
await this.$u.api.saveAnswer(param);
await this.next();
this.$refs.child.closeLoading();
} catch (error) {
console.error('error: ', error);
this.$t.ui.showToast(error.msg || '提交失败');
this.$refs.child.closeLoading();
}
},
//
async next() {
const { questionInfo, task } = this;
if (questionInfo.numStatus === 2) {
await this.submitAnswer();
} else {
const params = {
code: 'NLCP',
reportId: task.id,
num: questionInfo.num + 1,
};
await this.handleQuestion(params);
}
},
//
viewResults() {
async submitAnswer() {
try {
const params = { mentalTestId: this.task.id };
const data = await this.$u.api.mentalTestCalculate(params);
this.setAssessResult(data);
this.$refs.uTips.show({
title: '答案提交成功, 即将返回上一页',
type: 'success',
duration: '2000',
});
setTimeout(() => {
this.back();
}, 2000);
} catch (error) {
console.error('error: ', error);
this.$t.ui.showToast(error.msg || '提交失败');
}
},
//
back() {
this.setIsEvaluated(true);
const { name, id, url } = this.project;

9
src/store/task/mutations.js

@ -167,6 +167,15 @@ const mutations = {
state.tasks = [];
},
/**
* 设置时间轴是否继续向下查任务
* @param {Object} state
* @param {object} data
*/
setTask(state, data) {
state.task = data;
},
/**
* 收到消息设置任务状态
* @param {Object} state

1
src/store/task/state.js

@ -17,6 +17,7 @@ const state = {
permanents: [], // 永久日常任务
dailyTasks: [], // 日常任务
tasks: [], // 所有的定期任务
task: {}, // 当前任务
showSkeleton: false, // 定期任务骨架屏
newProjectInfo: {},
showScrollTo: false, // 是否可以设置时间轴自动滚动的位置

18
src/store/yanyuan/mutations.js

@ -79,6 +79,24 @@ const mutations = {
setQuestionInfo(state, data) {
state.questionInfo = data;
},
/**
* 设置测评结果
* @param {boolean} state
* @param {object} data
*/
setAssessResult(state, data) {
state.assessResult = data;
},
/**
* 设置选项id
* @param {boolean} state
* @param {object} data
*/
setOptionId(state, data) {
state.optionId = data;
},
};
export default mutations;

10
src/store/yanyuan/state.js

@ -1,14 +1,16 @@
/* eslint-disable */
const state = {
toolInfo: {}, // 绑定过的工具箱信息
toolInfo: null, // 绑定过的工具箱信息
elderlyInfo: [], // 用户创建的老人信息
showChooseElder: false, // 显示选择老人弹框
personalInfo: {}, // 个人信息
personalInfo: null, // 个人信息
isApplying: false, // 是否正在申请成为家属
keyUserIds: [], // 所选老人的id
applyFamilyInfo: {}, // 申请家属信息
applyFamilyInfo: null, // 申请家属信息
showSetUser: false, // 显示设置使用者弹框
questionInfo: {}, // 试题信息
questionInfo: null, // 试题信息
assessResult: null, // 测评结果
optionId: '', // 选项id
};
export default state;

Loading…
Cancel
Save