Browse Source

1.我的健康打卡 2.我的行程

remotes/origin/HEAD
songsong428 5 years ago
parent
commit
80195bb1a2
  1. 3
      App.vue
  2. 66
      components/timeline/timeline.vue
  3. 3
      config/api/api.js
  4. 432
      pages/basic-info/basic-info.vue
  5. 96
      pages/my-signs/my-signs.vue
  6. 17
      pages/sign/sign.vue
  7. 23
      store/modules/site/actions.js
  8. 9
      store/modules/site/mutations.js
  9. 1
      store/modules/site/state.js
  10. 2
      store/modules/statistics/actions.js

3
App.vue

@ -18,7 +18,6 @@ export default {
await this.login();
await this.getUserInfo();
await this.getHealthTypeStaus();
this.getSites();
},
computed: mapState('user', ['token']),
@ -26,9 +25,7 @@ export default {
methods: {
...mapMutations('user', ['setStatus','setUserInfo','setHealthCode']),
...mapActions('user', ['login']),
...mapActions('site', ['getSites']),
/**
* 查询个人信息
*/

66
components/timeline/timeline.vue

@ -1,32 +1,44 @@
<template>
<view>
<view class="cu-timeline">
<view class="cu-time">昨天</view>
<view class="cu-item cur cuIcon-noticefill">
<view class="content bg-green shadow-blur">
<text>22:22</text>广州市快件已到达地球
</view>
</view>
<view class="cu-item text-red cuIcon-attentionforbidfill">
<view class="content bg-red shadow-blur">这是第一次我家的铲屎官走了这么久久到足足有三天</view>
</view>
</view>
<view class="cu-timeline">
<view class="cu-time">06-17</view>
<view class="cu-item">
<view class="content">
<text>01:30</text>喵星 MX-12138 已揽收准备发往银河系
</view>
</view>
</view>
</view>
<view>
<view class="cu-timeline">
<!-- <view class="cu-time">昨天</view> -->
<view :key="index" class="cu-item cur" v-for="(item, index) in userSigns">
<view class="content bg-green shadow-blur">
<text>{{ generateTime(item.time - 0) }}</text>
{{ item.siteName }} 打卡
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {};
},
};
import { mapState } from 'vuex';
export default {
data() {
return {};
},
computed: mapState('statistics', ['userSigns']),
methods: {
/**
* 格式化时间为文本
* @param {number} time ms数
*/
generateTime(time) {
let type = 'YYYY-MM-DD HH:mm';
if (this.$moment().isSame(time, 'day')) {
return `今天 ${this.$moment(time).format('HH:mm')}`;
}
if (this.$moment().isSame(time, 'year')) {
type = 'MM-DD HH:mm';
}
return this.$moment(time).format(type);
},
},
};
</script>

3
config/api/api.js

@ -28,6 +28,9 @@ export const USER_SIGNS = `${sites}/info`;
// 获取所有场景信息
export const SITES_INFO = `${sites}/siteInfo`;
// 根据二维码的id获取场所的信息
export const SITE = `${sites}/site`;
// 扫码统计
export const SCHOOL_SIGNS = `${sites}/statistics`;

432
pages/basic-info/basic-info.vue

@ -1,209 +1,243 @@
<template>
<view>
<form class="padding-lr cu-form-group flex-direction">
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm"><span v-show="!userInfo" class="text-red padding-right-xs">*</span>姓名</view>
<input :disabled="userInfo ? true : false" placeholder="请输入真实姓名" name="input" type="text" v-model="name" />
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm"><span v-show="!userInfo" class="text-red padding-right-xs">*</span>身份证</view>
<input :disabled="userInfo ? true : false" placeholder="请输入身份证号" name="input" type="text" v-model="idCard" />
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm"><span v-show="!userInfo" class="text-red padding-right-xs">*</span>联系方式</view>
<input :disabled="userInfo ? true : false" placeholder="请输入手机号码" name="input" type="number" v-model="phone" />
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm"><span v-show="!userInfo" class="text-red padding-right-xs">*</span>身份</view>
<radio-group class="block" @change="RadioChange" v-if="!userInfo">
<view class="flex">
<view class="flex-sub margin-tb-sm" v-for="(identity,index) in identitys" :key="index">
<label class="flex justify-between align-center">
<radio class="round margin-right-xs" :checked="index === current" :value="identity.value"></radio>
<text class="flex-sub" style="font-size: 34rpx;">{{ identity.name }}</text>
</label>
</view>
</view>
</radio-group>
<input v-else disabled name="input" type="text" :value="current === 0 ? '学生' : current === 1 ? '教师' : '工作人员'" />
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm"><span v-show="!userInfo" class="text-red padding-right-xs">*</span>学号</view>
<input :disabled="userInfo ? true : false" placeholder="请输入学号" name="input" type="text" v-model="studentID" />
</view>
</form>
<user-agreement v-if="!userInfo" @changeIntentions='changeIntentions'></user-agreement>
<button v-show="!userInfo" class="bg-cyan margin primary-btn" hover-class="cc-active" @tap="handleSubmitUserInfo">确认提交</button>
</view>
<view>
<form class="padding-lr cu-form-group flex-direction">
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm">
<span class="text-red padding-right-xs" v-show="!userInfo">*</span>姓名
</view>
<input
:disabled="(userinfo && userInfo.id) ? true : false"
name="input"
placeholder="请输入真实姓名"
type="text"
v-model="name"
/>
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm">
<span class="text-red padding-right-xs" v-show="!(userinfo && userInfo.id)">*</span>身份证
</view>
<input
:disabled="(userinfo && userInfo.id) ? true : false"
name="input"
placeholder="请输入身份证号"
type="text"
v-model="idCard"
/>
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm">
<span class="text-red padding-right-xs" v-show="!(userinfo && userInfo.id)">*</span>联系方式
</view>
<input
:disabled="(userinfo && userInfo.id) ? true : false"
name="input"
placeholder="请输入手机号码"
type="number"
v-model="phone"
/>
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm">
<span class="text-red padding-right-xs" v-show="!(userinfo && userInfo.id)">*</span>身份
</view>
<radio-group @change="RadioChange" class="block" v-if="!(userinfo && userInfo.id)">
<view class="flex">
<view :key="index" class="flex-sub margin-tb-sm" v-for="(identity,index) in identitys">
<label class="flex justify-between align-center">
<radio
:checked="index === current"
:value="identity.value"
class="round margin-right-xs"
></radio>
<text class="flex-sub" style="font-size: 34rpx;">{{ identity.name }}</text>
</label>
</view>
</view>
</radio-group>
<input
:value="current === 0 ? '学生' : current === 1 ? '教师' : '工作人员'"
disabled
name="input"
type="text"
v-else
/>
</view>
<view class="cu-form-group flex flex-direction padding-tb">
<view class="title padding-bottom-sm">
<span class="text-red padding-right-xs" v-show="!(userinfo && userInfo.id)">*</span>学号
</view>
<input
:disabled="(userinfo && userInfo.id) ? true : false"
name="input"
placeholder="请输入学号"
type="text"
v-model="studentID"
/>
</view>
</form>
<user-agreement @changeIntentions="changeIntentions" v-if="!(userinfo && userInfo.id)"></user-agreement>
<button
@tap="handleSubmitUserInfo"
class="bg-cyan margin primary-btn"
hover-class="cc-active"
v-show="!(userinfo && userInfo.id)"
>确认提交</button>
</view>
</template>
<script>
import {
showToast
} from 'common/script/util';
import {
SUBMIT_USER_INFO
} from 'api/api';
import { mapState,mapMutations } from 'vuex';
import { showToast } from 'common/script/util';
import { SUBMIT_USER_INFO } from 'api/api';
import { mapState, mapMutations } from 'vuex';
export default {
data() {
return {
name: '',
idCard: '',
phone: '',
identitys: [{
value: '0',
name: '学生',
},
{
value: '1',
name: '教师',
},
{
value: '2',
name: '工作人员',
},
],
studentID: '',
current: 0,
agree: false
};
},
created() {
if(this.userInfo){
this.name = this.userInfo.name;
this.idCard = this.userInfo.idCard;
this.phone = this.userInfo.phone;
this.studentID = this.userInfo.no;
this.current = this.userInfo.post;
}
},
computed: mapState('user', ['userInfo','pagePath']),
methods: {
...mapMutations('user', ['setUserInfo']),
RadioChange: function(evt) {
for (let i = 0; i < this.identitys.length; i++) {
if (this.identitys[i].value === evt.target.value) {
this.current = i;
break;
}
}
},
changeIntentions(data){
this.agree = data;
},
/**
* 提交基本信息
*/
async handleSubmitUserInfo() {
try {
if (!this.checkRules()) return;
const {
name,
idCard,
phone,
studentID,
current
} = this;
const params = {
param: {
idCard,
name,
no: studentID,
phone,
post: current
}
};
export default {
data() {
return {
name: '',
idCard: '',
phone: '',
identitys: [
{
value: '0',
name: '学生',
},
{
value: '1',
name: '教师',
},
{
value: '2',
name: '工作人员',
},
],
studentID: '',
current: 0,
agree: false,
};
},
const res = await this.$http.post(SUBMIT_USER_INFO, params);
const {
success,
code,
msg,
data
} = res.data;
if (success && code === 200) {
this.success = true;
this.setUserInfo(data);
this.openPage(pagePath)
} else {
uni.showToast({
title: msg || '提交基本信息成功',
icon: 'none'
});
}
} catch (error) {
console.log('error: ', error);
if (error.msg) {
uni.showToast({
title: error.msg || '提交基本信息失败',
icon: 'none'
});
}
}
},
//
checkRules() {
const { name,idCard,phone,identitys,studentID,agree } = this;
if (!name) {
showToast('请输入姓名');
return;
}
if (!this.verifyIdCard(idCard)) {
showToast('请输入正确的身份证号');
return;
}
if (!this.verifyPhone(phone)) {
showToast('请输入正确的手机号');
return false;
}
if (!identitys) {
showToast('请选择身份');
return;
}
if (!studentID) {
showToast('请输入学号');
return;
}
if(!agree) {
showToast('请选择是否同意《用户服务协议》和《隐私政策》');
return;
}
return true;
},
/**
* 验证手机号格式
* @param {string} phone 手机号
*/
verifyPhone(phone) {
const phoneExg = /^1\d{10}$/;
return phoneExg.test(phone);
},
/**
* 验证身份证号格式
* @param {string} idCard 身份证号
*/
verifyIdCard(idCard) {
const idCardExg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
return idCardExg.test(idCard);
},
},
};
created() {
if (this.userInfo) {
this.name = this.userInfo.name;
this.idCard = this.userInfo.idCard;
this.phone = this.userInfo.phone;
this.studentID = this.userInfo.no;
this.current = this.userInfo.post;
}
},
computed: mapState('user', ['userInfo', 'pagePath']),
methods: {
...mapMutations('user', ['setUserInfo']),
RadioChange: function(evt) {
for (let i = 0; i < this.identitys.length; i++) {
if (this.identitys[i].value === evt.target.value) {
this.current = i;
break;
}
}
},
changeIntentions(data) {
this.agree = data;
},
/**
* 提交基本信息
*/
async handleSubmitUserInfo() {
try {
if (!this.checkRules()) return;
const { name, idCard, phone, studentID, current } = this;
const params = {
param: {
idCard,
name,
no: studentID,
phone,
post: current,
},
};
const res = await this.$http.post(SUBMIT_USER_INFO, params);
const { success, code, msg, data } = res.data;
if (success && code === 200) {
this.success = true;
this.setUserInfo(data);
this.openPage(pagePath);
} else {
uni.showToast({
title: msg || '提交基本信息成功',
icon: 'none',
});
}
} catch (error) {
console.log('error: ', error);
if (error.msg) {
uni.showToast({
title: error.msg || '提交基本信息失败',
icon: 'none',
});
}
}
},
//
checkRules() {
const { name, idCard, phone, identitys, studentID, agree } = this;
if (!name) {
showToast('请输入姓名');
return;
}
if (!this.verifyIdCard(idCard)) {
showToast('请输入正确的身份证号');
return;
}
if (!this.verifyPhone(phone)) {
showToast('请输入正确的手机号');
return false;
}
if (!identitys) {
showToast('请选择身份');
return;
}
if (!studentID) {
showToast('请输入学号');
return;
}
if (!agree) {
showToast('请选择是否同意《用户服务协议》和《隐私政策》');
return;
}
return true;
},
/**
* 验证手机号格式
* @param {string} phone 手机号
*/
verifyPhone(phone) {
const phoneExg = /^1\d{10}$/;
return phoneExg.test(phone);
},
/**
* 验证身份证号格式
* @param {string} idCard 身份证号
*/
verifyIdCard(idCard) {
const idCardExg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
return idCardExg.test(idCard);
},
},
};
</script>
<style lang="scss" scoped>
.primary-btn {
border-radius: 15rpx;
}
.primary-btn {
border-radius: 15rpx;
}
</style>

96
pages/my-signs/my-signs.vue

@ -13,7 +13,12 @@
<!-- 内容区 -->
<view class="content">
<!-- 今日打卡地图显示 -->
<history-map v-if="current === 0" />
<history-map
:markers="markers"
:polygons="polygons"
:polyline="polyline"
v-if="current === 0"
/>
<!-- 打卡记录 时间轴显示 -->
<timeline v-else />
</view>
@ -21,6 +26,8 @@
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
data() {
return {
@ -29,9 +36,96 @@ export default {
activeColor: '#0897C7',
};
},
computed: {
...mapState('statistics', ['userSigns']),
...mapState('user', ['token']),
//
markers() {
if (!this.userSigns) return null;
const result = [];
this.userSigns.forEach(item => {
const content = `${this.$moment(+item.time).format('YY-MM-DD HH:mm')} \n ${item.siteName}`;
const obj = {
latitude: item.latitude,
longitude: item.longitude,
iconPath: '/static/location.png',
callout: {
content,
color: '#fff',
padding: 4,
bgColor: '#0A97C6',
borderRadius: 2,
textAlign: 'center',
},
};
result.push(obj);
});
return result;
},
// 线
polyline() {
if (!this.userSigns) return null;
const points = [];
this.userSigns.forEach(item => {
const obj = {
latitude: item.latitude,
longitude: item.longitude,
};
points.push(obj);
});
return [{ points, arrowLine: true, dottedLine: true, borderColor: '#cccccc' }];
},
//
polygons() {
if (!this.userSigns) return null;
const points = [];
this.userSigns.forEach(item => {
const obj = {
latitude: item.latitude,
longitude: item.longitude,
};
points.push(obj);
});
return [
{ points, strokeWidth: 0, strokeColor: '#00000000', fillColor: '#cce6ff88', zIndex: 0 },
];
},
},
onLoad() {
const startTime = +this.$moment()
.startOf('day')
.format('x');
const endTime = +this.$moment()
.endOf('day')
.format('x');
const params = { param: { startTime, endTime, token: this.token } };
this.getUserSigns(params);
},
methods: {
...mapActions('statistics', ['getUserSigns']),
handleClickNav({ currentIndex }) {
this.current = currentIndex;
const endTime = +this.$moment()
.endOf('day')
.format('x');
const startTime = +this.$moment('2020-01-01')
.startOf('day')
.format('x');
let param = { startTime, endTime, token: this.token };
if (currentIndex === 0) {
param.startTime = +this.$moment()
.startOf('day')
.format('x');
}
const params = { param };
this.getUserSigns(params);
},
},
};

17
pages/sign/sign.vue

@ -2,7 +2,7 @@
<view class="padding-top-lg">
<template v-if="!success">
<view class="text-xxl padding text-center margin-top-xl">
<text class="text-black text-bold">{{ address }}</text>
<text class="text-black text-bold">{{ site }}</text>
</view>
<button @tap="handleSign(siteId)" class="cu-btn lg bg-purple margin sign-btn">{{ typeText }}</button>
</template>
@ -15,7 +15,7 @@
</template>
<script>
import { mapActions } from 'vuex';
import { mapState, mapActions } from 'vuex';
import { formatQuery } from 'utils/util';
import { SCAN_SIGN } from 'api/api';
@ -23,7 +23,6 @@ export default {
name: 'SignScan',
data() {
return {
address: '图书馆',
siteId: '',
siteName: '',
success: false,
@ -32,6 +31,7 @@ export default {
},
computed: {
...mapState('site', ['site']),
typeText() {
return this.type === 0 ? '进场打卡' : '出场打卡';
},
@ -42,22 +42,29 @@ export default {
const query = formatQuery(decodeURIComponent(options.scene));
console.log('query: ', query);
const { d, t } = query;
if (!d || !t) {
uni.showToast({
title: '二维码参数错误',
icon: 'none',
duration: 3000,
});
}
this.siteId = d;
this.type = +t;
this.getSiteByQrId({ param: { id: d, type: t } });
} catch (error) {
console.log('error: ', error);
}
},
methods: {
...mapActions('site', ['sign']),
...mapActions('site', ['sign', 'getSiteByQrId']),
/**
* 扫码打卡
* @param {string} siteId 场所id
*/
async handleSign(siteId) {
try {
console.log('打卡');
const params = { param: { siteId } };
await this.sign(params);
this.success = true;

23
store/modules/site/actions.js

@ -1,6 +1,6 @@
import { http } from 'plugins/request/index';
import { showLoading, hideLoading, showToast, showModal } from 'utils/ui';
import { SITES_INFO, SCAN_SIGN } from 'api/api';
import { SITES_INFO, SCAN_SIGN, SITE } from 'api/api';
const actions = {
/**
@ -26,6 +26,27 @@ const actions = {
});
},
/**
* 根据二维码id获取场所信息
* @param {*} commit
* @param {object} params 提交服务端的数据
*/
getSiteByQrId({ commit }, params) {
return new Promise((resolve, reject) => {
http
.post(SITE, params)
.then(res => {
const { data } = res.data;
commit('setSite', data);
resolve(data);
})
.catch(data => {
showToast(data.msg || '获取场所信息失败');
reject(data);
});
});
},
/**
* 扫码打卡 提交打卡记录
* @param {*} commit

9
store/modules/site/mutations.js

@ -7,6 +7,15 @@ const mutations = {
setSites(state, data) {
state.sites = data || [];
},
/**
* 设置当前场所的信息
* @param {object} state
* @param {object} data
*/
setSite(state, data) {
state.site = data || null;
},
};
export default mutations;

1
store/modules/site/state.js

@ -1,4 +1,5 @@
const state = {
site: null, // 当前场所信息
sites: [], // 所有的场所信息
};

2
store/modules/statistics/actions.js

@ -16,7 +16,7 @@ const actions = {
.then(res => {
hideLoading();
const { data } = res.data;
commit('setUserSign', data);
commit('setUserSigns', data);
resolve(data);
})
.catch(data => {

Loading…
Cancel
Save