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

66
components/timeline/timeline.vue

@ -1,32 +1,44 @@
<template> <template>
<view> <view>
<view class="cu-timeline"> <view class="cu-timeline">
<view class="cu-time">昨天</view> <!-- <view class="cu-time">昨天</view> -->
<view class="cu-item cur cuIcon-noticefill"> <view :key="index" class="cu-item cur" v-for="(item, index) in userSigns">
<view class="content bg-green shadow-blur"> <view class="content bg-green shadow-blur">
<text>22:22</text>广州市快件已到达地球 <text>{{ generateTime(item.time - 0) }}</text>
</view> {{ item.siteName }} 打卡
</view> </view>
<view class="cu-item text-red cuIcon-attentionforbidfill"> </view>
<view class="content bg-red shadow-blur">这是第一次我家的铲屎官走了这么久久到足足有三天</view> </view>
</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>
</template> </template>
<script> <script>
export default { import { mapState } from 'vuex';
data() {
return {}; 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> </script>

3
config/api/api.js

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

414
pages/basic-info/basic-info.vue

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

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

@ -13,7 +13,12 @@
<!-- 内容区 --> <!-- 内容区 -->
<view class="content"> <view class="content">
<!-- 今日打卡地图显示 --> <!-- 今日打卡地图显示 -->
<history-map v-if="current === 0" /> <history-map
:markers="markers"
:polygons="polygons"
:polyline="polyline"
v-if="current === 0"
/>
<!-- 打卡记录 时间轴显示 --> <!-- 打卡记录 时间轴显示 -->
<timeline v-else /> <timeline v-else />
</view> </view>
@ -21,6 +26,8 @@
</template> </template>
<script> <script>
import { mapState, mapActions } from 'vuex';
export default { export default {
data() { data() {
return { return {
@ -29,9 +36,96 @@ export default {
activeColor: '#0897C7', 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: { methods: {
...mapActions('statistics', ['getUserSigns']),
handleClickNav({ currentIndex }) { handleClickNav({ currentIndex }) {
this.current = 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"> <view class="padding-top-lg">
<template v-if="!success"> <template v-if="!success">
<view class="text-xxl padding text-center margin-top-xl"> <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> </view>
<button @tap="handleSign(siteId)" class="cu-btn lg bg-purple margin sign-btn">{{ typeText }}</button> <button @tap="handleSign(siteId)" class="cu-btn lg bg-purple margin sign-btn">{{ typeText }}</button>
</template> </template>
@ -15,7 +15,7 @@
</template> </template>
<script> <script>
import { mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { formatQuery } from 'utils/util'; import { formatQuery } from 'utils/util';
import { SCAN_SIGN } from 'api/api'; import { SCAN_SIGN } from 'api/api';
@ -23,7 +23,6 @@ export default {
name: 'SignScan', name: 'SignScan',
data() { data() {
return { return {
address: '图书馆',
siteId: '', siteId: '',
siteName: '', siteName: '',
success: false, success: false,
@ -32,6 +31,7 @@ export default {
}, },
computed: { computed: {
...mapState('site', ['site']),
typeText() { typeText() {
return this.type === 0 ? '进场打卡' : '出场打卡'; return this.type === 0 ? '进场打卡' : '出场打卡';
}, },
@ -42,22 +42,29 @@ export default {
const query = formatQuery(decodeURIComponent(options.scene)); const query = formatQuery(decodeURIComponent(options.scene));
console.log('query: ', query); console.log('query: ', query);
const { d, t } = query; const { d, t } = query;
if (!d || !t) {
uni.showToast({
title: '二维码参数错误',
icon: 'none',
duration: 3000,
});
}
this.siteId = d; this.siteId = d;
this.type = +t; this.type = +t;
this.getSiteByQrId({ param: { id: d, type: t } });
} catch (error) { } catch (error) {
console.log('error: ', error); console.log('error: ', error);
} }
}, },
methods: { methods: {
...mapActions('site', ['sign']), ...mapActions('site', ['sign', 'getSiteByQrId']),
/** /**
* 扫码打卡 * 扫码打卡
* @param {string} siteId 场所id * @param {string} siteId 场所id
*/ */
async handleSign(siteId) { async handleSign(siteId) {
try { try {
console.log('打卡');
const params = { param: { siteId } }; const params = { param: { siteId } };
await this.sign(params); await this.sign(params);
this.success = true; this.success = true;

23
store/modules/site/actions.js

@ -1,6 +1,6 @@
import { http } from 'plugins/request/index'; import { http } from 'plugins/request/index';
import { showLoading, hideLoading, showToast, showModal } from 'utils/ui'; 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 = { 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 * @param {*} commit

9
store/modules/site/mutations.js

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

1
store/modules/site/state.js

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

2
store/modules/statistics/actions.js

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

Loading…
Cancel
Save