调整iconfont图标缺失

This commit is contained in:
唐明明
2022-02-14 17:16:27 +08:00
71 changed files with 6023 additions and 3894 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -14,6 +14,10 @@
{ {
"launchtype" : "local" "launchtype" : "local"
}, },
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud" "type" : "uniCloud"
} }
] ]

View File

@@ -1,5 +1,7 @@
<script> <script>
import { getVersions } from './apis/interfaces/versions' import {
getVersions
} from './apis/interfaces/versions'
import im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
export default { export default {

View File

@@ -9,9 +9,10 @@ import { request } from '../index'
/** /**
* @description:饮水记录首页 * @description:饮水记录首页
*/ */
const waters = () => { const waters = (data) => {
return request({ return request({
url: 'health/waters', url: 'health/waters',
data:data
}) })
} }
/** /**
@@ -29,10 +30,11 @@ const setWaters = (data) => {
* @description:喝水 * @description:喝水
* @Date: 2022-01-12 125600 * @Date: 2022-01-12 125600
*/ */
const drinkWater = () => { const drinkWater = (data) => {
return request({ return request({
url: 'health/waters/drink', url: 'health/waters/drink',
method: 'POST', method: 'POST',
data:data
}) })
} }
/** /**
@@ -46,10 +48,24 @@ const delDrinkWater = (id) => {
}) })
} }
/**
* @description:饮食运动日历
* @params {日期}
* @method {get}
* @Date: 2022-02-08 11点18分
*/
const dateList = (data) => {
return request({
url: 'health/calendar/water',
data:data
})
}
export { export {
waters, waters,
setWaters, setWaters,
drinkWater, drinkWater,
delDrinkWater delDrinkWater,
dateList
} }

View File

@@ -78,11 +78,24 @@ const delHealthFoods = (intake_id) => {
}) })
} }
/**
* @description:饮食运动日历
* @params {日期}
* @method {get}
* @Date: 2022-02-07 15点18分
*/
const dateList = (data) => {
return request({
url: 'health/calendar/intake',
data:data
})
}
export { export {
positions, positions,
plans, plans,
healthFoods, healthFoods,
addHealthFoods, addHealthFoods,
editHealthFoods, editHealthFoods,
delHealthFoods delHealthFoods,
dateList
} }

View File

@@ -11,6 +11,13 @@ import {
// 获取好友列表 // 获取好友列表
const getFriends = () => { const getFriends = () => {
return request({
url: 'im/friends',
}, true)
}
// 获取好友列表
const getFriendsLetter = () => {
return request({ return request({
url: 'im/friends/letter', url: 'im/friends/letter',
}, true) }, true)
@@ -85,55 +92,121 @@ const pedingFriend = (recipient) => {
}) })
} }
/** // 以下是群组相关业务的接口
* 好友申请数量 const getMyGroups = () => {
*/
const getPendingCount = () => {
return request({ return request({
url: 'im/friends/pending/count' url: 'im/groups'
}) })
} }
/** /**
* 上传聊天附件 * 获取群信息,包含基础信息和 14 个用户
* 图片
* 语音
* 视频
*/ */
// 基础配置 const getGroupInfo = (groupId) => {
const config = { return request({
apiUrl: 'http://api.zh.shangkelian.cn/api/', // 正式环境 url: 'im/groups/' + groupId
timeout: 60000 })
} }
const uploadMessageFile = (file, type) => { /**
config.header = { * 群组基础信息
'Accept': 'application/json', */
'Authorization': store.getters.getToken || '' const getGroupBase = (groupId) => {
} return request({
return new Promise((resolve, reject) => { url: 'im/groups/' + groupId + '/base'
uni.uploadFile({ })
url: config.apiUrl + 'im/upload', }
filePath: file,
name: 'upload', const getGroupUsers = (groupId) => {
formData: { return request({
type url: 'im/groups/' + groupId + '/users'
}, })
header: config.header || {}, }
success: (res) => {
if (res.statusCode === 200) { const getGroupAnnouncements = (groupId) => {
let updData = JSON.parse(res.data) return request({
if (updData.status_code === 200) { url: 'im/groups/' + groupId + '/announcements'
resolve(updData.data) })
} else { }
reject(updData)
} const createGroupAnnouncement = (groupId, content) => {
} return request({
}, method: 'POST',
fail: (err) => { url: 'im/groups/' + groupId + '/announcements',
console.log('ERR', err); data: {
} content: content
}) }
})
}
const deleteGroupAnnouncement = (groupId, announcementId) => {
return request({
method: 'DELETE',
url: 'im/groups/' + groupId + '/announcements/' + announcementId
})
}
/**
* 创建群聊
*/
const createGroup = (data) => {
return request({
method: 'POST',
url: 'im/groups',
data: data
})
}
const updateGroup = (groupId, data) => {
return request({
method: 'PUT',
url: 'im/groups/' + groupId,
data: data
})
}
/**
* 搜索群聊
*/
const searchGroup = (name) => {
return request({
url: 'im/groups/search?name=' + name
})
}
/**
* 加群前,获取的群信息
*/
const joinGroupPre = (groupId) => {
return request({
url: 'im/groups/' + groupId + '/join'
})
}
const joinGroup = (groupId, message) => {
return request({
method: 'POST',
url: 'im/groups/' + groupId + '/join',
data: {
message
}
})
}
const quitGroup = (groupId) => {
return request({
method: 'POST',
url: 'im/groups/' + groupId + '/quit'
})
}
/**
* 解散群聊
*/
const dismissGroup = (groupId) => {
return request({
method: 'DELETE',
url: 'im/groups/' + groupId
}) })
} }
@@ -141,6 +214,7 @@ export {
getImToken, getImToken,
deleteFriend, deleteFriend,
getFriends, getFriends,
getFriendsLetter,
getUserInfo, getUserInfo,
getFriendInfo, getFriendInfo,
getPedings, getPedings,
@@ -148,6 +222,18 @@ export {
rejectFriend, rejectFriend,
searchFriend, searchFriend,
pedingFriend, pedingFriend,
getPendingCount, getMyGroups,
uploadMessageFile createGroup,
updateGroup,
getGroupInfo,
getGroupBase,
getGroupUsers,
getGroupAnnouncements,
createGroupAnnouncement,
deleteGroupAnnouncement,
searchGroup,
joinGroupPre,
joinGroup,
quitGroup,
dismissGroup
} }

View File

@@ -6,6 +6,7 @@
* @LastEditTime: 2022-01-12 17:13:45 * @LastEditTime: 2022-01-12 17:13:45
*/ */
import { request } from '../index' import { request } from '../index'
/** /**
* @description:称量体重模块首页 * @description:称量体重模块首页
*/ */
@@ -15,6 +16,16 @@ const weights = (page) => {
data: { page: page } data: { page: page }
}) })
} }
/**
* @description:获取曲线进度
*/
const curves = () => {
return request({
url: 'health/weights/bight'
})
}
/** /**
* @description:记录体重 * @description:记录体重
* @Date: 2022-01-12 16:46:19 * @Date: 2022-01-12 16:46:19
@@ -26,7 +37,9 @@ const addWeight = (data) => {
data: data data: data
}) })
} }
export { export {
weights, weights,
addWeight addWeight,
curves
} }

View File

@@ -0,0 +1,330 @@
<!--
* @Description:日历模板
* @Author: Aimee·Zhang
* @Date: 2022-02-08 09:06:45
* @LastEditors: Aimee·Zhang
* @LastEditTime: 2022-02-08 09:06:45
-->
<template>
<view class="date">
<u-popup :show="dateShow" zIndex="10099890" @close="closeDate" mode="bottom" :safeAreaInsetBottom="true">
<view class="date-content">
<view class="title"><span @click="datePreNext('before')">上一月</span>{{month}}<span
@click="datePreNext('after')">下一月</span></view>
<view class="date-item">
<view class="week">
<view class="week-item" v-for="(item,index) in weekList" :key="index">{{item}}</view>
</view>
<!-- 饮食模块 -->
<block v-if="type === 'foods'">
<view class="week" style="padding-top: 30rpx;">
<view v-for="item in lists" :key="item.today" @click="dateClick(item)"
:class="['week-item',{'is_past':!item.is_month},{'is_today':item.today === today},{'is_intake0':item.intake === 1},{'is_intake1':item.intake === 2},{'is_intake2':item.intake === 3}]">
{{item.day}}
</view>
</view>
<view class="des">
<block> <view class="des-item">吃少了</view> <view class="des-item">正好</view> <view class="des-item">吃多了</view> </block>
<view class="back" @click="backDate"> 回今天 </view>
</view>
</block>
<!-- 喝水模块 -->
<block v-if="type === 'drink'">
<view class="week" style="padding-top: 30rpx;">
<view v-for="item in lists" :key="item.today" @click="dateClick(item)" :class="['week-item',{'is_past':!item.is_month},{'is_today':item.today === today}]">
{{item.day}}
<u-image class='waterIcon' :src="require('@/static/imgs/water-1.png')" v-if="item.drink === 2" :lazy-load="true" width="20rpx" radius="10rpx" mode="widthFix" />
<u-image class='waterIcon' :src="require('@/static/imgs/water-2.png')" v-if="item.drink === 1" :lazy-load="true" width="20rpx" radius="10rpx" mode="widthFix" />
</view>
</view>
<view class="drink">
<block>
<view class="drink-item">
<u-image class='waterIcon' :src="require('@/static/imgs/water-1.png')" :lazy-load="true" width="22rpx" radius="10rpx" mode="widthFix" />未完成指标
</view>
<view class="drink-item">
<u-image class='waterIcon' :src="require('@/static/imgs/water-2.png')" :lazy-load="true" width="22rpx" radius="10rpx" mode="widthFix" /> 完成指标
</view>
</block>
<view class="back" @click="backDate"> 回今天 </view>
</view>
</block>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import moment from 'moment';
export default {
data() {
return {
weekList: ['日', '一', '二', '三', '四', '五', '六'],
};
},
props: {
/**
* lists 传过来的列表
* type foods食物运动 drink饮水weight体重
* today 勾选时间
* month 勾选日期
* dateShow 页面是否显示
**/
lists: {
type: Array,
default: [],
},
type: {
type: String,
default: "",
},
today: {
type: String,
default: moment(new Date()).format('YYYY-MM-DD')
},
month: {
type: String,
default: moment(new Date()).format('YYYY-MM')
},
dateShow: {
type: Boolean,
default: false
}
},
methods: {
// 选择日期
dateClick(item) {
this.$emit('dateClick', item)
},
// 返回今天
backDate() {
this.$emit('backDate', '')
},
// 点击上一个月或者下一个月 before 上一月 after下一个月
datePreNext(type) {
this.$emit('datePreNext', type)
},
// 关闭日历
closeDate() {
this.$emit('closeDate')
}
},
};
</script>
<style lang="scss" scoped>
.date {
// 日历弹窗
.date-content {
width: 100%;
padding: $padding *2;
min-height: 800rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
.title {
font-size: $title-size + 4;
color: #20845f;
font-weight: bold;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
span {
display: inline-block;
padding: $padding;
font-size: $title-size-m;
color: #cacaca;
font-weight: normal;
}
}
.date-item {
padding-top: $padding;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
.drink {
display: flex;
color: #cacaca;
flex-direction: row;
align-items: center;
box-sizing: border-box;
font-size: $title-size-m;
justify-content: center;
margin-top: $margin;
width: 100%;
.drink-item {
padding-right: 40rpx;
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
u-image{
padding-right: 10rpx;
}
}
}
.des {
display: flex;
color: #cacaca;
flex-direction: row;
align-items: center;
box-sizing: border-box;
font-size: $title-size-m;
justify-content: center;
margin-top: $margin;
width: 100%;
.des-item {
padding-left: 40rpx;
padding-right: 10rpx;
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
&:before {
content: '';
position: absolute;
left: 14rpx;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background: #fa624d;
}
&:nth-child(2):before {
background: #fbbf0f;
}
&:nth-child(1):before {
background: #02c7bd;
}
}
}
.back {
margin-left: 100rpx;
background-color: rgba($color: $main-color, $alpha: 1);
color: #fff;
padding: 10rpx $padding;
border-radius: $radius + 10;
}
}
.week {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
flex-wrap: wrap;
width: 100%;
.week-item {
width: 14.28%;
height: 90rpx;
line-height: 90rpx;
font-size: $title-size-m + 2;
color: #888;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
&::before {
content: '';
width: 14rpx;
height: 14rpx;
border-radius: 50%;
position: absolute;
bottom: 0;
// background: #02c7bd;
}
}
.waterIcon {
position: absolute;
width: 30rpx !important;
bottom: -12rpx;
padding-left: 10rpx;
}
&:nth-child(1),
&:nth-child(7),
&:nth-child(8),
&:nth-child(14),
&:nth-child(15),
&:nth-child(21),
&:nth-child(22),
&:nth-child(28),
&:nth-child(29),
&:nth-child(35),
{
color: rgba($color: #000000, $alpha: 0.4);
}
}
// 吃饭样式
.is_intake0::before {
background: #02c7bd !important;
}
.is_intake1::before {
background: #fbbf0f !important;
}
.is_intake2::before {
background: #fa624d !important;
}
.is_today {
color: #fff !important;
position: relative;
z-index: 1;
&:after {
content: '';
width: 50rpx;
height: 50rpx;
position: absolute;
border-radius: 50%;
background-color: $main-color;
color: #Fff;
z-index: -1;
}
}
.is_past {
color: rgba($color: #000000, $alpha: 0.1) !important;
}
}
}
</style>

View File

@@ -2,8 +2,8 @@
"name" : "ZH-HEALTH", "name" : "ZH-HEALTH",
"appid" : "__UNI__C29473D", "appid" : "__UNI__C29473D",
"description" : "ZH-HEALTH您手上的健康管理专家", "description" : "ZH-HEALTH您手上的健康管理专家",
"versionName" : "1.0.7", "versionName" : "1.0.8",
"versionCode" : 107, "versionCode" : 108,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {

View File

@@ -35,9 +35,8 @@
"path": "pages/record/drink", "path": "pages/record/drink",
"name": "Drink", "name": "Drink",
"style": { "style": {
"navigationBarTitleText": "记录喝水", "navigationBarTitleText": "记录",
"navigationBarBackgroundColor": "#34CE98", "navigationStyle": "custom"
"navigationBarTextStyle": "white"
} }
}, },
{ {
@@ -53,9 +52,8 @@
"path": "pages/record/foods", "path": "pages/record/foods",
"name": "RecordFoods", "name": "RecordFoods",
"style": { "style": {
"navigationBarTitleText": "食物记录", "navigationBarTitleText": "",
"navigationBarBackgroundColor": "#34CE98", "navigationStyle": "custom"
"navigationBarTextStyle": "white"
} }
}, },
{ {
@@ -80,7 +78,7 @@
"path": "pages/evaluation/list", "path": "pages/evaluation/list",
"name": "EvaluationList", "name": "EvaluationList",
"style": { "style": {
"navigationBarTitleText": "评测列表", "navigationBarTitleText": "健康评测",
"navigationBarBackgroundColor": "#34CE98", "navigationBarBackgroundColor": "#34CE98",
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
@@ -369,10 +367,18 @@
"path": "pages/im/index", "path": "pages/im/index",
"name": "IM", "name": "IM",
"style": { "style": {
"navigationBarBackgroundColor": "#FFFFFF",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/im/private/chat",
"style": {
"disableScroll": true,
"navigationBarTitleText": "聊天",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#F3F6FB"
}
},
{ {
"path": "pages/im/private/call", "path": "pages/im/private/call",
"name": "imPrivateCall", "name": "imPrivateCall",
@@ -402,40 +408,110 @@
"path": "pages/im/friends/pending", "path": "pages/im/friends/pending",
"name": "imFriendsPending", "name": "imFriendsPending",
"style": { "style": {
"navigationBarTitleText": "新朋友", "navigationBarTitleText": "新朋友"
"navigationBarBackgroundColor": "#F3F6FB"
} }
}, },
{ {
"path": "pages/im/friends/search", "path": "pages/im/friends/search",
"name": "SearchFriend", "name": "SearchFriend",
"style": { "style": {
"navigationBarTitleText": "好友搜索", "navigationBarTitleText": "好友搜索"
"navigationBarBackgroundColor": "#F3F6FB"
} }
}, },
{ {
"path": "pages/im/friends/info", "path": "pages/im/friends/info",
"name": "imFriendsInfo", "name": "imFriendsInfo",
"style": { "style": {
"navigationBarTitleText": "好友资料", "navigationBarTitleText": "用户资料"
"navigationBarBackgroundColor": "#FFFFFF"
} }
}, },
{ {
"path": "pages/im/friends/mine", "path": "pages/im/friends/mine",
"name": "imFriendsMine", "name": "imFriendsMine",
"style": { "style": {
"navigationBarTitleText": "我的二维码", "navigationBarTitleText": "我的资料"
"navigationBarBackgroundColor": "#34CE98",
"navigationBarTextStyle": "white"
} }
}, },
{ {
"path": "pages/im/group/index", "path": "pages/im/group/index",
"name": "imGroup", "name": "imGroups",
"style": { "style": {
"navigationBarTitleText": "我的群聊" "navigationBarTitleText": "我的群聊",
"app-plus": {
"titleNView": {
"type": "default",
"buttons": [{
"float": "right",
"fontSrc": "/static/iconfont.ttf",
"text": "\ue60a",
"fontSize": "20px"
}]
}
}
}
},
{
"path": "pages/im/group/chat",
"name": "imGroupChat",
"style": {
"navigationBarTitleText": "群聊",
"app-plus": {
"titleNView": {
"type": "default",
"buttons": [{
"float": "right",
"fontSrc": "/static/iconfont.ttf",
"text": "\ue607",
"fontSize": "20px"
}]
}
}
}
},
{
"path": "pages/im/group/apply",
"name": "imGroupApply",
"style": {
"navigationBarTitleText": "申请加群"
}
},
{
"path": "pages/im/group/info",
"name": "imGroupInfo",
"style": {
"navigationBarTitleText": "群信息"
}
},
{
"path": "pages/im/group/users",
"name": "imGroupUsers",
"style": {
"navigationBarTitleText": "群成员"
}
},
{
"path": "pages/im/group/announcement",
"name": "imGroupAnnouncement",
"style": {
"navigationBarTitleText": "群公告",
"app-plus": {
"titleNView": {
"type": "default",
"buttons": [{
"float": "right",
"fontSrc": "/static/iconfont.ttf",
"text": "\ue60a",
"fontSize": "20px"
}]
}
}
}
},
{
"path": "pages/im/group/announceCreate",
"name": "imGroupAnnouncementCreate",
"style": {
"navigationBarTitleText": "发布群公告"
} }
}, },
{ {
@@ -548,14 +624,6 @@
"navigationBarBackgroundColor": "#34CE98", "navigationBarBackgroundColor": "#34CE98",
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
}, {
"path": "pages/im/private/chat",
"style": {
"disableScroll": true,
"navigationBarTitleText": "聊天",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#F3F6FB"
}
} }
], ],
"tabBar": { "tabBar": {

View File

@@ -2,21 +2,10 @@
<view class="content"> <view class="content">
<!-- tool --> <!-- tool -->
<view class="tool-flex"> <view class="tool-flex">
<view <view class="tool-flex-item" @click="$Router.back()">
class="tool-flex-item" <uni-icons type="closeempty" size="22" color="#666"></uni-icons>
@click="$Router.back()"
>
<uni-icons
type="closeempty"
size="22"
color="#666"
></uni-icons>
</view> </view>
<view <view class="tool-flex-item" @click="onKeyAuth()" v-if="$Route.query.keyPhone == 1">一键登录</view>
class="tool-flex-item"
@click="onKeyAuth()"
v-if="$Route.query.keyPhone == 1"
>一键登录</view>
</view> </view>
<!-- 欢迎使用 --> <!-- 欢迎使用 -->
<view class="header"> <view class="header">
@@ -26,34 +15,14 @@
<!-- 输入手机号相关 --> <!-- 输入手机号相关 -->
<view class="inputs phone"> <view class="inputs phone">
<label class="label">+86</label> <label class="label">+86</label>
<input <input type="number" placeholder="输入您的手机号码" maxlength="11" v-model="phone" />
type="number"
placeholder="输入您的手机号码"
maxlength="11"
v-model="phone"
/>
</view> </view>
<view class="inputs sms"> <view class="inputs sms">
<input <input type="number" placeholder="输入短信验证码" maxlength="4" v-model="code" />
type="number" <button class="sms-btn" type="default" size="mini" :disabled="phone == '' || getSms"
placeholder="输入短信验证码" @click="getPhoneCode">{{getSms ? '重新发送' + smsTime + 's': '发送验证码'}}</button>
maxlength="4"
v-model="code"
/>
<button
class="sms-btn"
type="default"
size="mini"
:disabled="phone == '' || getSms"
@click="getPhoneCode"
>{{getSms ? '重新发送' + smsTime + 's': '发送验证码'}}</button>
</view> </view>
<button <button class="btn" type="default" :disabled="phone == '' || code == ''" @click="login">登录</button>
class="btn"
type="default"
:disabled="phone == '' || code == ''"
@click="login"
>登录</button>
<!-- 用户登录注册协议 --> <!-- 用户登录注册协议 -->
<view class="agreement"> <view class="agreement">
未注册的手机号码验证后自动创建账号登录即表示同意接受平台 未注册的手机号码验证后自动创建账号登录即表示同意接受平台
@@ -65,203 +34,220 @@
</template> </template>
<script> <script>
import { getSms, smsAuth } from "@/apis/interfaces/auth"; import {
import userAuth from "@/public/userAuth"; getSms,
export default { smsAuth
data() { } from "@/apis/interfaces/auth";
return { import userAuth from "@/public/userAuth";
phone: "", export default {
code: "", data() {
smsTime: 60, return {
getSms: false, phone: "",
}; code: "",
}, smsTime: 60,
methods: { getSms: false,
// 用户登录 };
login() {
smsAuth({
mobileNo: this.phone,
code: this.code,
}).then((res) => {
console.log(111)
this.$store.commit(
"setToken",
res.token_type + " " + res.access_token
);
this.$Router.back();
}).catch((err) => {
console.log(2222)
uni.showToast({
title: err.message,
icon: "none",
});
});
}, },
// 获取验证码 methods: {
getPhoneCode() { // 用户登录
let outTime; login() {
getSms({ smsAuth({
mobileNo: this.phone, mobileNo: this.phone,
}) code: this.code,
.then((res) => { }).then((res) => {
uni.showToast({ this.$store.commit(
title: res, "setToken",
icon: "none", res.token_type + " " + res.access_token
}); );
this.getSms = true; this.$Router.back();
outTime = setInterval(() => { }).catch((err) => {
if (this.smsTime <= 1) {
this.getSms = false;
this.smsTime = 60;
clearInterval("outTime");
}
this.smsTime -= 1;
}, 1000);
})
.catch((err) => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon: "none", icon: "none",
}); });
}); });
},
// 获取验证码
getPhoneCode() {
let outTime;
getSms({
mobileNo: this.phone,
})
.then((res) => {
uni.showToast({
title: res,
icon: "none",
});
this.getSms = true;
outTime = setInterval(() => {
if (this.smsTime <= 1) {
this.getSms = false;
this.smsTime = 60;
clearInterval("outTime");
}
this.smsTime -= 1;
}, 1000);
})
.catch((err) => {
uni.showToast({
title: err.message,
icon: "none",
});
});
},
// 一键登录
onKeyAuth() {
const Auth = new userAuth();
this.$Router.back();
Auth.Login();
},
}, },
// 一键登录 };
onKeyAuth() {
const Auth = new userAuth();
this.$Router.back();
Auth.Login();
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content { .content {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
padding: $padding * 3; padding: $padding * 3;
box-sizing: border-box; box-sizing: border-box;
background: white;
@extend .vertical;
// 操作栏
.tool-flex {
position: fixed;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
padding-left: $padding * 2;
padding-right: $padding * 2;
background: white; background: white;
@extend .ios-top; @extend .vertical;
&-item {
line-height: 90rpx;
color: $text-gray;
font-size: $title-size-lg;
}
}
// 表单
.inputs {
background: $window-color;
position: relative;
margin-top: $margin;
height: 90rpx;
line-height: 90rpx;
border-radius: 45rpx;
input {
width: 100%;
height: 90rpx;
line-height: 90rpx;
padding: 0 $padding;
border: none;
box-sizing: border-box;
font-size: $title-size-lg;
}
&.phone { // 操作栏
padding-left: 120rpx; .tool-flex {
.label { position: fixed;
position: absolute; top: 0;
left: 0; left: 0;
top: 0; right: 0;
width: 120rpx; display: flex;
text-align: center; justify-content: space-between;
border-right: solid 1rpx $border-color; padding-left: $padding * 2;
padding-right: $padding * 2;
background: white;
@extend .ios-top;
&-item {
line-height: 90rpx;
color: $text-gray;
font-size: $title-size-lg; font-size: $title-size-lg;
} }
} }
&.sms { // 表单
padding-right: 200rpx; .inputs {
.sms-btn[size='mini'] { background: $window-color;
width: 200rpx; position: relative;
height: 90rpx; margin-top: $margin;
line-height: 90rpx; height: 90rpx;
position: absolute; line-height: 90rpx;
top: 0; border-radius: 45rpx;
right: 0;
padding: 0; input {
margin: 0; width: 100%;
border-radius: 0 45rpx 45rpx 0; height: 90rpx;
color: $main-color; line-height: 90rpx;
font-size: $title-size-lg; padding: 0 $padding;
background: $window-color; border: none;
&::after { box-sizing: border-box;
border: none; font-size: $title-size-lg;
} }
&[disabled] {
color: rgba($color: $main-color, $alpha: .6); &.phone {
background: rgba($color: $window-color, $alpha: 0); padding-left: 120rpx;
}
} .label {
} position: absolute;
} left: 0;
// 头部 top: 0;
.header{ width: 120rpx;
text-align: center; text-align: center;
margin-bottom: 5vh; border-right: solid 1rpx $border-color;
.title { font-size: $title-size-lg;
font-size: $title-size + 10; }
font-weight: bold; }
color: $text-color;
line-height: 70rpx; &.sms {
} padding-right: 200rpx;
.sumbit{
line-height: 50rpx; .sms-btn[size='mini'] {
font-size: $title-size-m; width: 200rpx;
color: $text-gray-m; height: 90rpx;
} line-height: 90rpx;
} position: absolute;
// 登录按钮 top: 0;
.btn { right: 0;
margin: 0; padding: 0;
margin-top: $margin*2; margin: 0;
height: 90rpx; border-radius: 0 45rpx 45rpx 0;
line-height: 90rpx; color: $main-color;
padding: 0; font-size: $title-size-lg;
font-size: $title-size; background: $window-color;
border-radius: 45rpx;
background: $main-color; &::after {
color: white; border: none;
font-weight: bold; }
&::after{
display: none; &[disabled] {
} color: rgba($color: $main-color, $alpha: .6);
&[disabled]{ background: rgba($color: $window-color, $alpha: 0);
background: rgba($color: $main-color, $alpha: .5); }
} }
} }
// 协议 }
.agreement {
padding-top: 5vh; // 头部
font-size: $title-size-sm; .header {
color: $text-gray-m; text-align: center;
view { margin-bottom: 5vh;
color: $main-color;
display: inline-block; .title {
padding: 0 10rpx; font-size: $title-size + 10;
} font-weight: bold;
} color: $text-color;
} line-height: 70rpx;
}
.sumbit {
line-height: 50rpx;
font-size: $title-size-m;
color: $text-gray-m;
}
}
// 登录按钮
.btn {
margin: 0;
margin-top: $margin*2;
height: 90rpx;
line-height: 90rpx;
padding: 0;
font-size: $title-size;
border-radius: 45rpx;
background: $main-color;
color: white;
font-weight: bold;
&::after {
display: none;
}
&[disabled] {
background: rgba($color: $main-color, $alpha: .5);
}
}
// 协议
.agreement {
padding-top: 5vh;
font-size: $title-size-sm;
color: $text-gray-m;
view {
color: $main-color;
display: inline-block;
padding: 0 10rpx;
}
}
}
</style> </style>

View File

@@ -11,21 +11,18 @@
<!-- 进度 --> <!-- 进度 -->
<view class="plan"> <view class="plan">
<view class="plan-1"> <view class="plan-1">
<span>基本信息</span> <span>基本信息</span> <u-line-progress :percentage="percentplan1" activeColor="#34ce98" class="line-progress" :showText="false" />
<u-line-progress :percentage="percentplan1" activeColor="#34ce98" class="line-progress" :showText="false" />
</view> </view>
<view class="plan-2"> <view class="plan-2">
<span>健康目标</span> <span>健康目标</span> <u-line-progress :percentage="percentplan2" activeColor="#34ce98" width="200rpx" class="line-progress" :showText="false" />
<u-line-progress :percentage="percentplan2" activeColor="#34ce98" width="200rpx" class="line-progress" :showText="false" />
</view> </view>
<view class="plan-3"> <view class="plan-3">
<span>行为习惯</span> <span>行为习惯</span> <u-line-progress :percentage="percentplan3" activeColor="#34ce98" width="200rpx" class="line-progress" :showText="false" />
<u-line-progress :percentage="percentplan3" activeColor="#34ce98" width="200rpx" class="line-progress" :showText="false" />
</view> </view>
</view> </view>
<!-- 进度1 基本信息 --> <!-- 进度1 基本信息 -->
<view> <block>
<!-- 进度1 基本信息页面展示 性别 --> <!-- 进度1 基本信息页面展示 性别 -->
<view class="plan-content" v-if="sexShow"> <view class="plan-content" v-if="sexShow">
<view class="info-des">生理性别和激素会影响我们的身体代谢食物的方式</view> <view class="info-des">生理性别和激素会影响我们的身体代谢食物的方式</view>
@@ -47,19 +44,7 @@
<view class="age"> <view class="age">
<view class="info-title">你的出生日期是</view> <view class="info-title">你的出生日期是</view>
<view class="year" @change="dateShow = true">{{ showBirthday }}</view> <view class="year" @change="dateShow = true">{{ showBirthday }}</view>
<u-datetime-picker <u-datetime-picker confirmColor="#34ce98" ref="datetimePicker" v-model="birthday" mode="date" :show="dateShow" :formatter="formatter" :minDate="-302688000" :maxDate="maxDate" :closeOnClickOverlay="true" @confirm="confirmBirthday" @cancel="camcelBirthday" />
confirmColor="#34ce98"
ref="datetimePicker"
v-model="birthday"
mode="date"
:show="dateShow"
:formatter="formatter"
:minDate="-302688000"
:maxDate="maxDate"
:closeOnClickOverlay="true"
@confirm="confirmBirthday"
@cancel="camcelBirthday"
/>
</view> </view>
</view> </view>
@@ -68,7 +53,6 @@
<u-image class="sex-item-avatar" width="100rpx" height="100rpx" :src="require('../../static/imgs/avatar-1.png')" :lazy-load="true" shape="circle" /> <u-image class="sex-item-avatar" width="100rpx" height="100rpx" :src="require('../../static/imgs/avatar-1.png')" :lazy-load="true" shape="circle" />
<view class="info-des">身高体重信息对健康信息有重要参考价值</view> <view class="info-des">身高体重信息对健康信息有重要参考价值</view>
<view class="info-title">您的身高是</view> <view class="info-title">您的身高是</view>
<!-- -->
<view class="weight"> <view class="weight">
<view class="count"><span>{{ heightU }}</span>厘米</view> <view class="count"><span>{{ heightU }}</span>厘米</view>
<vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollHeight" :scrollLeft="Number(heightU)" /> <vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollHeight" :scrollLeft="Number(heightU)" />
@@ -84,51 +68,18 @@
<view class="next" @click="weightClick(2)">下一步</view> <view class="next" @click="weightClick(2)">下一步</view>
</view> </view>
</view> </view>
</view> </block>
<!-- 进度2 健康目标 --> <!-- 进度2 健康目标 -->
<view> <block>
<!-- 减脂类型 --> <!-- 减脂类型 -->
<view v-if="targetShow" class="plan-content target-content"> <view v-if="targetShow" class="plan-content target-content">
<u-image class="sex-item-avatar" width="100rpx" height="100rpx" :src="require('../../static/imgs/avatar-1.png')" :lazy-load="true" shape="circle" /> <u-image class="sex-item-avatar" width="100rpx" height="100rpx" :src="require('../../static/imgs/avatar-1.png')" :lazy-load="true" shape="circle" />
<view class="info-title">您的目标是</view> <view class="info-title">您的目标是</view>
<view class="target-type"> <view class="target-type">
<view class="target-type-item"> <view class="target-type-item"> <u-image class="target-img" width="160rpx" height="160rpx" @click="activedTarget = '1'" :src="activedTarget === '1' ? require('../../static/imgs/ic-w-s.png') : require('../../static/imgs/ic-w-n.png')" :lazy-load="true" shape="circle" /> 减肥 </view>
<u-image <view class="target-type-item"> <u-image class="target-img" width="160rpx" height="160rpx" @click="activedTarget = '2'" :src="activedTarget === '2' ? require('../../static/imgs/ic-b-s.png') : require('../../static/imgs/ic-b-n.png')" :lazy-load="true" shape="circle" /> 保持体重 </view>
class="target-img" <view class="target-type-item"> <u-image class="target-img" width="160rpx" height="160rpx" @click="activedTarget = '3'" :src="activedTarget === '3' ? require('../../static/imgs/ic-m-s.png') : require('../../static/imgs/ic-m-n.png')" :lazy-load="true" shape="circle" /> 增肌 </view>
width="160rpx"
height="160rpx"
@click="activedTarget = '1'"
:src="activedTarget === '1' ? require('../../static/imgs/ic-w-s.png') : require('../../static/imgs/ic-w-n.png')"
:lazy-load="true"
shape="circle"
/>
减肥
</view>
<view class="target-type-item">
<u-image
class="target-img"
width="160rpx"
height="160rpx"
@click="activedTarget = '2'"
:src="activedTarget === '2' ? require('../../static/imgs/ic-b-s.png') : require('../../static/imgs/ic-b-n.png')"
:lazy-load="true"
shape="circle"
/>
保持体重
</view>
<view class="target-type-item">
<u-image
class="target-img"
width="160rpx"
height="160rpx"
@click="activedTarget = '3'"
:src="activedTarget === '3' ? require('../../static/imgs/ic-m-s.png') : require('../../static/imgs/ic-m-n.png')"
:lazy-load="true"
shape="circle"
/>
增肌
</view>
</view> </view>
<view class="pre-next"> <view class="pre-next">
<view class="pro" @click="targetClick(1)">上一步</view> <view class="pro" @click="targetClick(1)">上一步</view>
@@ -141,10 +92,7 @@
<view class="info-title">您的打算减脂多少</view> <view class="info-title">您的打算减脂多少</view>
<view class="target-type"> <view class="target-type">
<view class="target-type-item"> <view class="target-type-item">
<view class="count"> <view class="count"> <span>{{ weightTargetU }}</span> 公斤 </view>
<span>{{ weightTargetU }}</span>
公斤
</view>
<vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollTargetWeight" :scrollLeft="Number(weightTargetU)" /> <vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollTargetWeight" :scrollLeft="Number(weightTargetU)" />
</view> </view>
</view> </view>
@@ -153,7 +101,7 @@
<view class="next" @click="targetWeightClick(2)">下一步</view> <view class="next" @click="targetWeightClick(2)">下一步</view>
</view> </view>
</view> </view>
</view> </block>
<!-- 进度3 行为习惯 --> <!-- 进度3 行为习惯 -->
<!-- 减脂类型 --> <!-- 减脂类型 -->
@@ -162,51 +110,19 @@
<view class="info-title">您的运动量是</view> <view class="info-title">您的运动量是</view>
<view class="target-type"> <view class="target-type">
<view class="target-type-item"> <view class="target-type-item">
<u-image <u-image class="target-img" width="120rpx" height="120rpx" @click="activedbehaviarTarget = '1'" :src="activedbehaviarTarget === '1' ? require('../../static/imgs/ic-w-01.png') : require('../../static/imgs/ic-w-02.png')" :lazy-load="true" shape="circle" />
class="target-img"
width="120rpx"
height="120rpx"
@click="activedbehaviarTarget = '1'"
:src="activedbehaviarTarget === '1' ? require('../../static/imgs/ic-w-01.png') : require('../../static/imgs/ic-w-02.png')"
:lazy-load="true"
shape="circle"
/>
久坐不动 久坐不动
</view> </view>
<view class="target-type-item"> <view class="target-type-item">
<u-image <u-image class="target-img" width="120rpx" height="120rpx" @click="activedbehaviarTarget = '2'" :src="activedbehaviarTarget === '2' ? require('../../static/imgs/ic-w-03.png') : require('../../static/imgs/ic-w-04.png')" :lazy-load="true" shape="circle" />
class="target-img"
width="120rpx"
height="120rpx"
@click="activedbehaviarTarget = '2'"
:src="activedbehaviarTarget === '2' ? require('../../static/imgs/ic-w-03.png') : require('../../static/imgs/ic-w-04.png')"
:lazy-load="true"
shape="circle"
/>
少量运动 少量运动
</view> </view>
<view class="target-type-item"> <view class="target-type-item">
<u-image <u-image class="target-img" width="120rpx" height="120rpx" @click="activedbehaviarTarget = '3'" :src="activedbehaviarTarget === '3' ? require('../../static/imgs/ic-w-05.png') : require('../../static/imgs/ic-w-06.png')" :lazy-load="true" shape="circle" />
class="target-img"
width="120rpx"
height="120rpx"
@click="activedbehaviarTarget = '3'"
:src="activedbehaviarTarget === '3' ? require('../../static/imgs/ic-w-05.png') : require('../../static/imgs/ic-w-06.png')"
:lazy-load="true"
shape="circle"
/>
中等运动量 中等运动量
</view> </view>
<view class="target-type-item"> <view class="target-type-item">
<u-image <u-image class="target-img" width="120rpx" height="120rpx" @click="activedbehaviarTarget = '4'" :src="activedbehaviarTarget === '4' ? require('../../static/imgs/ic-w-07.png') : require('../../static/imgs/ic-w-08.png')" :lazy-load="true" shape="circle" />
class="target-img"
width="120rpx"
height="120rpx"
@click="activedbehaviarTarget = '4'"
:src="activedbehaviarTarget === '4' ? require('../../static/imgs/ic-w-07.png') : require('../../static/imgs/ic-w-08.png')"
:lazy-load="true"
shape="circle"
/>
超强度运动 超强度运动
</view> </view>
</view> </view>
@@ -274,7 +190,6 @@ export default {
}, },
computed: { computed: {
showBirthday() { showBirthday() {
console.log(moment(this.birthday).format('YYYY年MM月DD日'));
return moment(this.birthday).format('YYYY年MM月DD日'); return moment(this.birthday).format('YYYY年MM月DD日');
} }
}, },
@@ -297,6 +212,7 @@ export default {
this.percentplan1 = uni.$u.range(0, 100, this.percentplan1 + 33.33); // 增加进度 this.percentplan1 = uni.$u.range(0, 100, this.percentplan1 + 33.33); // 增加进度
this.heightWeightShow = true; // 展示身高体重模块 this.heightWeightShow = true; // 展示身高体重模块
}, },
// 年龄 ----- 取消选择年龄 // 年龄 ----- 取消选择年龄
camcelBirthday() { camcelBirthday() {
this.birthdayShow = false; // // 年龄页面弹窗不显示 this.birthdayShow = false; // // 年龄页面弹窗不显示
@@ -304,6 +220,7 @@ export default {
this.percentplan1 = 0; // 进度为0 this.percentplan1 = 0; // 进度为0
this.sexShow = true; // 显示性别页面 this.sexShow = true; // 显示性别页面
}, },
//年龄------------- 过滤出生年月日 //年龄------------- 过滤出生年月日
formatter(type, value) { formatter(type, value) {
if (type === 'year') {return `${value}`;} if (type === 'year') {return `${value}`;}
@@ -311,6 +228,8 @@ export default {
if (type === 'day') {return `${value}`;} if (type === 'day') {return `${value}`;}
return value; return value;
}, },
// 体重---------标尺滚动 // 体重---------标尺滚动
scrollWeight(msg) { scrollWeight(msg) {
this.weightU = msg; this.weightU = msg;
@@ -332,6 +251,8 @@ export default {
this.targetShow = true; // 目标页面展示 this.targetShow = true; // 目标页面展示
} }
}, },
// 目标 ------------点击 1上一页 2 下一页 // 目标 ------------点击 1上一页 2 下一页
targetClick(type) { targetClick(type) {
if (type === 1) { if (type === 1) {
@@ -368,6 +289,8 @@ export default {
this.behaviorShow = true; // 打开行为习惯页面 this.behaviorShow = true; // 打开行为习惯页面
} }
}, },
// 目标 运动量--------- 1上一页 2 下一页 // 目标 运动量--------- 1上一页 2 下一页
targetBehaviorClick(type) { targetBehaviorClick(type) {
if (type === 1) { if (type === 1) {
@@ -391,7 +314,6 @@ export default {
exercise: this.activedbehaviarTarget, // 运动量 exercise: this.activedbehaviarTarget, // 运动量
days: 1 days: 1
}; };
console.log(params, 'params.....');
recordsHealth(params) recordsHealth(params)
.then(res => { .then(res => {
uni.showModal({ uni.showModal({
@@ -406,10 +328,12 @@ export default {
}); });
}) })
.catch(err => { .catch(err => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon: 'none' icon: "none",
}); duration: 2000,
mask: true
})
}); });
} }
} }

View File

@@ -6,172 +6,175 @@
* @LastEditTime: 2022-01-13 17:16:09 * @LastEditTime: 2022-01-13 17:16:09
--> -->
<template> <template>
<view class="evaluation"> <view class="evaluation">
<!-- 进度 --> <!-- 进度 -->
<view class="percent"> <view class="percent">
<u-icon <u-icon name="arrow-left" :color="colorList[colorIndex]" size="14" label="上一题" :labelColor="colorList[colorIndex]" labelSize="14" :bold="true" space="3" v-if="page !== 1" @click="preQ" />
name="arrow-left" <u-line-progress class="pre-ico" :percentage="percent" height="10" :showText="false" :activeColor="colorList[colorIndex]" />
:color="colorList[colorIndex]" <span :style="{ color: colorList[colorIndex] }">{{ percent }}%</span>
size="14" </view>
label="上一题" <!-- 标题 -->
:labelColor="colorList[colorIndex]" <view class="title">{{ page }}.{{ currentInfo.title }}</view>
labelSize="14" <!-- 题目列表 -->
:bold="true" <view class="lists">
space="3" <view class="list-item">
v-if="page !== 1" <u-radio-group placement="column" @change="groupChange" iconPlacement="right" class="radio-g" :value="currentId">
@click="preQ" <u-radio class="radio-item" :customStyle="{ marginBottom: '8px' }" v-for="(item, index) in currentInfo.options" :key="index" :label="item.title" :name="item.option_id" :activeColor="colorList[colorIndex]" />
/> </u-radio-group>
<u-line-progress class="pre-ico" :percentage="percent" height="10" :showText="false" :activeColor="colorList[colorIndex]" /> </view>
<span :style="{ color: colorList[colorIndex] }">{{ percent }}%</span> <!-- 底部确认按钮 -->
</view> <view class="bottom-btn" :style="{ background: colorList[colorIndex] }" @click="next">下一步</view>
<!-- 标题 --> </view>
<view class="title">{{ page }}.{{ currentInfo.title }}</view> </view>
<!-- 题目列表 -->
<view class="lists">
<view class="list-item">
<u-radio-group placement="column" @change="groupChange" iconPlacement="right" class="radio-g" :value="currentId">
<u-radio
class="radio-item"
:customStyle="{ marginBottom: '8px' }"
v-for="(item, index) in currentInfo.options"
:key="index"
:label="item.title"
:name="item.option_id"
:activeColor="colorList[colorIndex]"
></u-radio>
</u-radio-group>
</view>
<!-- 底部确认按钮 -->
<view class="bottom-btn" :style="{ background: colorList[colorIndex] }" @click="next">下一步</view>
</view>
</view>
</template> </template>
<script> <script>
import { evaluationsQuestion, evaluationsAnswers } from '@/apis/interfaces/evaluation.js'; import {
export default { evaluationsQuestion,
components: {}, evaluationsAnswers
data() { } from '@/apis/interfaces/evaluation.js';
return { export default {
percent: 70, components: {},
colorList: ['#34ce98', '#b6c29a', '#f4d000', '#8a977b', '#e58308', '#dc5712'], data() {
colorIndex: Math.floor(Math.random() * 6), // 基本案列数据 return {
currentInfo: {}, //当前题目的内容 percent: 70,
option_ids: [], // 答案id的数组 colorList: ['#34ce98', '#d04500', '#f4d000', '#55aa00', '#e58308', '#dc5a1d'],
has_more: false, // 是否有下一页 colorIndex: Math.floor(Math.random() * 6), // 基本案列数据
page: 1, currentInfo: {}, //当前题目的内容
currentId: '' // 默认值 option_ids: [], // 答案id的数组
}; has_more: false, // 是否有下一页
}, page: 1,
onShow() { currentId: '' // 默认值
this.getList(); };
uni.setNavigationBarColor({ },
frontColor: '#ffffff', //文字颜色 onShow() {
backgroundColor: `${this.colorList[this.colorIndex]}` //底部背景色 this.getList();
}); uni.setNavigationBarColor({
}, frontColor: '#ffffff', //文字颜色
methods: { backgroundColor: `${this.colorList[this.colorIndex]}` //底部背景色
getList() { });
evaluationsQuestion(this.$Route.query.id, this.page).then(res => { },
this.currentInfo = res.data[0]; methods: {
this.percent = Number(((res.page.current - 1) / res.page.total).toFixed(2)) * 100; // 答题列表
this.has_more = res.page.has_more; getList() {
}); evaluationsQuestion(this.$Route.query.id, this.page).then(res => {
}, this.currentInfo = res.data[0];
groupChange(n) { this.percent = Number(((res.page.current - 1) / res.page.total).toFixed(2)) * 100;
this.currentId = n; this.has_more = res.page.has_more;
}, }).catch(err => {
// 上一题 uni.showToast({
preQ() { title: err.message,
this.option_ids.pop(); icon: "none",
this.currentId = ''; duration: 2000,
this.page = this.page - 1; mask: true
this.getList(); })
}, });
//下一题 },
next() { groupChange(n) {
if (this.has_more) { this.currentId = n;
if (this.currentId === '') { },
uni.showToast({ title: '请选择答案', icon: 'none' }); // 上一题
return; preQ() {
} this.option_ids.pop();
this.option_ids.push(this.currentId); this.currentId = '';
this.currentId = ''; this.page = this.page - 1;
this.page = this.page + 1; this.getList();
this.getList(); },
} else { //下一题
if (this.option_ids.length !== this.page) { next() {
this.option_ids.push(this.currentId); if (this.has_more) {
this.currentId = ''; if (this.currentId === '') {
} uni.showToast({
let data = { title: '请选择答案',
option_ids: this.option_ids.toString(), icon: 'none'
id: this.$Route.query.id });
}; return;
evaluationsAnswers(data) }
.then(res => { this.option_ids.push(this.currentId);
console.log(res); this.currentId = '';
this.parent = 100; this.page = this.page + 1;
uni.showToast({ this.getList();
title: '答题完成,立即查看结果', } else {
icon: 'none', if (this.option_ids.length !== this.page) {
mask: true this.option_ids.push(this.currentId);
}); this.currentId = '';
setTimeout(() => { }
uni.navigateTo({ let data = {
url: `/pages/evaluation/result?id=${this.$Route.query.id}` option_ids: this.option_ids.toString(),
}); id: this.$Route.query.id
}, 1000); };
}) evaluationsAnswers(data)
.catch(err => { .then(res => {
uni.showToast({ this.parent = 100;
title: err.message uni.showToast({
}); title: '答题完成,立即查看结果',
}); icon: 'none',
} mask: true
} });
} setTimeout(() => {
}; uni.navigateTo({
url: `/pages/evaluation/result?id=${this.$Route.query.id}`
});
}, 1000);
})
.catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
}
}
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.evaluation { .evaluation {
padding: $padding $padding $padding * 4 $padding; padding: $padding $padding $padding * 4 $padding;
.percent {
display: flex; .percent {
flex-direction: row; display: flex;
align-items: center; flex-direction: row;
justify-content: center; align-items: center;
box-sizing: border-box; justify-content: center;
font-size: $title-size - 2; box-sizing: border-box;
.pre-ico { font-size: $title-size - 2;
margin: $padding;
} .pre-ico {
} margin: $padding;
.title { }
font-size: $title-size + 10; }
font-weight: bold;
padding-top: $padding; .title {
} font-size: $title-size + 10;
.lists { font-weight: bold;
.radio-g { padding-top: $padding;
padding-top: $padding * 2; }
.radio-item {
background: #f9f9f9; .lists {
padding: $padding; .radio-g {
border-radius: $radius; padding-top: $padding * 2;
flex: 1;
} .radio-item {
} background: #f9f9f9;
.bottom-btn { padding: $padding;
text-align: center; border-radius: $radius;
padding: 24rpx $padding; flex: 1;
border-radius: $radius + 40; }
color: #fff; }
font-size: $title-size;
position: fixed; .bottom-btn {
bottom: $padding; text-align: center;
width: calc(100% - 60rpx); padding: 24rpx $padding;
box-sizing: border-box; border-radius: $radius + 40;
} color: #fff;
} font-size: $title-size;
} position: fixed;
bottom: $padding;
width: calc(100% - 60rpx);
box-sizing: border-box;
}
}
}
</style> </style>

View File

@@ -6,129 +6,138 @@
* @LastEditTime: 2022-01-13 17:26:38 * @LastEditTime: 2022-01-13 17:26:38
--> -->
<template> <template>
<view class="introduce"> <view class="introduce">
<view class="intro-history" v-if="info.is_answer" @click="toResult">测评记录</view> <view class="intro-history" v-if="info.is_answer" @click="toResult">测评记录</view>
<view class="intro-history" v-else @click="toResult">暂未测评</view> <view class="intro-history" v-else @click="toResult">暂未测评</view>
<view class="intro-content"> <view class="intro-content">
<view class="intro-title">{{ info.title }}</view> <view class="intro-title">{{ info.title }}</view>
<u-read-more class="intro-des" :toggle="true" showHeight="140" ref="uReadMore" :shadowStyle="shadowStyle" color="#34ce98" textIndent="0"> <u-read-more class="intro-des" :toggle="true" showHeight="140" ref="uReadMore" :shadowStyle="shadowStyle" color="#34ce98" textIndent="0">
<rich-text :nodes="content"></rich-text> <rich-text :nodes="content"></rich-text>
</u-read-more> </u-read-more>
<u-image class="intro-img" width="100%" radius="20rpx" height="700rpx" :src="info.cover ? info.cover : require('../../static/imgs/indro.png')" :lazy-load="true" /> <u-image class="intro-img" width="100%" radius="20rpx" height="700rpx" :src="info.cover ? info.cover : require('../../static/imgs/indro.png')" :lazy-load="true" />
<view class="answer" @click="nowAn">开始测评</view> <view class="answer" @click="nowAn">开始测评</view>
</view> </view>
<view class="remark">本评测会收集孕产情况健康状况家族病史用药情况信息用于开展相关评测为你生成分析报告</view> <view class="remark">本评测会收集孕产情况健康状况家族病史用药情况信息用于开展相关评测为你生成分析报告</view>
</view> </view>
</template> </template>
<script> <script>
import { evaluationsInfo } from '@/apis/interfaces/evaluation.js'; import {evaluationsInfo} from '@/apis/interfaces/evaluation.js';
export default { export default {
data() { data() {
return { return {
info: {}, info: {},
content: `本测试预计完成时间5-8分钟 content: `本测试预计完成时间5-8分钟
<br/> <br/>
<br/> <br/>
适用于18-65岁存在亚健康或尿酸偏高人群`, 适用于18-65岁存在亚健康或尿酸偏高人群`,
shadowStyle: { shadowStyle: {backgroundImage: 'none',paddingTop: '0',marginTop: '20rpx'}
backgroundImage: 'none', };
paddingTop: '0', },
marginTop: '20rpx' onShow() {
} evaluationsInfo(this.$Route.query.id).then(res => {
}; this.content = res.content;
}, this.info = res;
onShow() { }).catch(err => {
evaluationsInfo(this.$Route.query.id).then(res => { uni.showToast({
this.content = res.content; title: err.message,
this.info = res; icon: "none",
}); duration: 2000,
}, mask: true
methods: { })
nowAn() { });
uni.navigateTo({ },
url: `/pages/evaluation/index?id=${this.$Route.query.id}` methods: {
}); nowAn() {
}, uni.navigateTo({
toResult() { url: `/pages/evaluation/index?id=${this.$Route.query.id}`
console.log('点击了测试'); });
uni.navigateTo({ },
url: `/pages/evaluation/result?id=${this.$Route.query.id}` toResult() {
}); uni.navigateTo({
} url: `/pages/evaluation/result?id=${this.$Route.query.id}`
} });
}; }
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.introduce { .introduce {
background-color: $main-color; background-color: $main-color;
min-height: 100vh; min-height: 100vh;
.intro-history {
padding: $padding * 1.5 $padding; .intro-history {
color: $window-color; padding: $padding * 1.5 $padding;
text-decoration: underline; color: $window-color;
font-size: $title-size-lg; text-decoration: underline;
display: flex; font-size: $title-size-lg;
flex-direction: row; display: flex;
align-items: center; flex-direction: row;
justify-content: flex-end; align-items: center;
box-sizing: border-box; justify-content: flex-end;
} box-sizing: border-box;
// 测评展示 }
.intro-content {
background: rgba($color: #fff, $alpha: 1); // 测评展示
min-height: 30vh; .intro-content {
padding: 0 $padding; background: rgba($color: #fff, $alpha: 1);
margin: $margin * 1.5; min-height: 30vh;
border-radius: $radius; padding: 0 $padding;
position: relative; margin: $margin * 1.5;
box-shadow: 0 0 10rpx 4rpx rgba($color: $main-color, $alpha: 0.1); border-radius: $radius;
// 标题 position: relative;
.intro-title { box-shadow: 0 0 10rpx 4rpx rgba($color: $main-color, $alpha: 0.1);
font-size: $title-size * 1.8;
font-weight: bold; // 标题
color: $text-color; .intro-title {
position: relative; font-size: $title-size * 1.8;
top: -40rpx; font-weight: bold;
} color: $text-color;
// 介绍 position: relative;
.intro-des { top: -40rpx;
line-height: $title-size * 1.8; }
color: $text-color;
position: relative; // 介绍
top: -10rpx; .intro-des {
font-size: $title-size-m; line-height: $title-size * 1.8;
padding-bottom: 20rpx; color: $text-color;
} position: relative;
// 图片 top: -10rpx;
.intro-img { font-size: $title-size-m;
margin-top: $padding * 0.8; padding-bottom: 20rpx;
} }
// 开始测评
.answer { // 图片
position: absolute; .intro-img {
bottom: -30rpx; margin-top: $padding * 0.8;
width: 400rpx; }
height: 90rpx;
line-height: 90rpx; // 开始测评
left: 50%; .answer {
text-align: center; position: absolute;
background: rgba($color: #fff, $alpha: 0.94); bottom: -30rpx;
margin-left: -200rpx; width: 400rpx;
border-radius: $radius-m * 4; height: 90rpx;
font-weight: bold; line-height: 90rpx;
color: $text-color; left: 50%;
font-size: $title-size-m + 6; text-align: center;
} background: rgba($color: #fff, $alpha: 0.94);
} margin-left: -200rpx;
// 备注信息 border-radius: $radius-m * 4;
.remark { font-weight: bold;
color: $text-gray; color: $text-color;
font-size: $title-size - 6; font-size: $title-size-m + 6;
padding: $padding * 2 $padding; }
line-height: $title-size * 1.3; }
}
} // 备注信息
.remark {
color: $text-gray;
font-size: $title-size - 6;
padding: $padding * 2 $padding;
line-height: $title-size * 1.3;
}
}
</style> </style>

View File

@@ -11,44 +11,20 @@
<!-- 评测列表主要内容 标题 图片 描述 --> <!-- 评测列表主要内容 标题 图片 描述 -->
<view class="--content"> <view class="--content">
<u-image class="content-img" width="170rpx" height="170rpx" radius="20rpx" :src="item.cover ? item.cover : require('../../static/imgs/test.png')" :lazy-load="true" /> <u-image class="content-img" width="170rpx" height="170rpx" radius="20rpx" :src="item.cover ? item.cover : require('../../static/imgs/test.png')" :lazy-load="true" />
<view class="title-des"> <view class="title-des"> <view class="title">{{ item.title }}</view> <view class="des">{{ item.description || '--' }}</view> </view>
<view class="title">{{ item.title }}</view>
<view class="des">{{ item.description || '--' }}</view>
</view>
</view> </view>
<!-- 分数 --> <!-- 分数 -->
<view class="score" v-if="item.is_answer"> <view class="score" v-if="item.is_answer"> <span>{{ item.answer.total }}</span> </view>
<span>{{ item.answer.total }}</span>
</view>
<!-- 评测状态 --> <!-- 评测状态 -->
<view class="--status"> <view class="--status">
<!-- 已测试展示 状态--> <!-- 已测试展示 状态-->
<view class="status" v-if="item.is_answer"> <view class="status" v-if="item.is_answer"> <span class="dian">·</span> {{ item.remark }} </view>
<span class="dian">·</span>
{{ item.remark }}
</view>
<view v-if="item.is_answer" class="history" @click="toResult(item)">查看历史结果</view> <view v-if="item.is_answer" class="history" @click="toResult(item)">查看历史结果</view>
<!-- 未测试展示 状态--> <!-- 未测试展示 状态-->
<view class="status" v-if="!item.is_answer"> <view class="status" v-if="!item.is_answer"> <span class="dian">·</span> <span class="person">{{ item.remark }}</span> 人已测 | 约4~8分钟 </view>
<span class="dian">·</span> <u-icon name="arrow-right" :color="item.is_answer ? '#26a377' : '#faa81a'" size="14" :bold="true" :label="item.is_answer ? '重新评测' : '开始测评'" labelPos="left" labelSize="14" space="1" :labelColor="item.is_answer ? '#26a377' : '#faa81a'" @click="nowEva(item)" />
<span class="person">{{ item.remark }}</span>
人已测 | 约4~8分钟
</view>
<u-icon
name="arrow-right"
:color="item.is_answer ? '#26a377' : '#faa81a'"
size="14"
:bold="true"
:label="item.is_answer ? '重新评测' : '开始测评'"
labelPos="left"
labelSize="14"
space="1"
:labelColor="item.is_answer ? '#26a377' : '#faa81a'"
@click="nowEva(item)"
/>
</view> </view>
</view> </view>
<!-- 没有更多 --> <!-- 没有更多 -->
@@ -72,7 +48,14 @@ export default {
getList() { getList() {
evaluations().then(res => { evaluations().then(res => {
this.evalList = res; this.evalList = res;
}); }).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
}, },
// nowEva // nowEva
nowEva(item) { nowEva(item) {

View File

@@ -53,9 +53,7 @@
<!-- 标题 --> <!-- 标题 -->
<view class="title-content"><view class="title">营养建议</view></view> <view class="title-content"><view class="title">营养建议</view></view>
<block v-for="(item, index) in 3" :key="index"> <block v-for="(item, index) in 3" :key="index">
<view class="title2"> <view class="title2"> <span>{{ item }}. 低Gi</span> </view>
<span>{{ item }}. 低Gi</span>
</view>
<!-- 描述 --> <!-- 描述 -->
<view class="des">饮食营养及生活方式对维持面部年轻态影响较大建议注意食材选择逐步清淡口味规律作息逐个改善不良生活习惯帮助改善当前皮肤状态</view> <view class="des">饮食营养及生活方式对维持面部年轻态影响较大建议注意食材选择逐步清淡口味规律作息逐个改善不良生活习惯帮助改善当前皮肤状态</view>
</block> </block>
@@ -63,10 +61,7 @@
<!-- 更多 --> <!-- 更多 -->
<view class="answer-item"> <view class="answer-item">
<!-- 标题 --> <!-- 标题 -->
<view class="title-content"> <view class="title-content"> <view class="title">更多护肤知识</view> <u-icon name="arrow-right" color="#333" size="20" /> </view>
<view class="title">更多护肤知识</view>
<u-icon name="arrow-right" color="#333" size="20" />
</view>
<!-- 横向滚动推荐 --> <!-- 横向滚动推荐 -->
<scroll-view class="scroll-view_H" scroll-x="true"> <scroll-view class="scroll-view_H" scroll-x="true">
<view v-for="(item, index) in 6" :key="index" id="demo1" class="scroll-view-item_H"> <view v-for="(item, index) in 6" :key="index" id="demo1" class="scroll-view-item_H">
@@ -109,7 +104,14 @@ export default {
] ]
}; };
this.loaded = true; this.loaded = true;
}); }).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
}, },
reEva() { reEva() {
uni.navigateTo({ uni.navigateTo({

View File

@@ -0,0 +1,163 @@
<template>
<view>
<view v-for="(item, index) in conversations" :key="index" :class="['message', { 'is-top': item.isTop }]"
:data-item="item" @longpress="onLongPress" @click="toDetail(item)">
<message-cell :item="item" />
</view>
<view class="shade" @click="hidePop" v-show="showPop">
<view class="pop" :style="popStyle" :class="{'show':showPop}">
<view v-for="(item, index) in popButton" :key="index" @click="pickerMenu" :data-index="index">
{{item}}
</view>
</view>
</view>
</view>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import im from '@/utils/im/index.js'
import messageCell from './messageCell'
export default {
props: {
conversations: {
type: Array,
default: function() {
return []
}
}
},
components: {
messageCell
},
data() {
return {
/* 窗口尺寸 */
winSize: {},
/* 显示操作弹窗 */
showPop: false,
/* 弹窗按钮列表 */
popButton: ['置顶聊天', '删除该聊天'],
/* 弹窗定位样式 */
popStyle: "",
pickedItem: {},
}
},
methods: {
// 隐藏功能菜单
hidePop() {
this.showPop = false
this.pickedItem = {}
setTimeout(() => {
this.showShade = false
}, 250)
},
// 点击会话功能菜单
pickerMenu(e) {
const index = Number(e.currentTarget.dataset.index)
if (index == 0) {
RongIMLib.setConversationToTop(this.pickedItem.conversationType, this.pickedItem.targetId, !this
.pickedItem.isTop)
} else {
RongIMLib.removeConversation(this.pickedItem.conversationType, this.pickedItem.targetId)
RongIMLib.deleteMessages(this.pickedItem.conversationType, this.pickedItem.targetId)
}
this.$emit('refresh')
im.setNotifyBadge()
this.hidePop()
},
// 长按会话,展示功能菜单
onLongPress(e) {
let [touches, style, item] = [e.touches[0], "", e.currentTarget.dataset.item]
if (touches.clientY > (this.winSize.height / 2)) {
style = `bottom:${this.winSize.height-touches.clientY}px;`
} else {
style = `top:${touches.clientY}px;`
}
if (touches.clientX > (this.winSize.witdh / 2)) {
style += `right:${this.winSize.witdh-touches.clientX}px`
} else {
style += `left:${touches.clientX}px`
}
this.popButton[0] = item.isTop ? '取消置顶' : '置顶聊天'
this.popStyle = style
this.pickedItem = item
this.$nextTick(() => {
setTimeout(() => {
this.showPop = true;
}, 10)
})
},
toDetail(item) {
if (item.conversationType == 1) {
uni.navigateTo({
url: '/pages/im/private/chat?targetId=' + item.targetId
})
} else if (item.conversationType == 3) {
uni.navigateTo({
url: '/pages/im/group/chat?targetId=' + item.targetId
})
}
this.hidePop()
}
}
}
</script>
<style lang="scss" scoped>
.message {
background: white;
&.is-top {
background: $window-color;
}
}
/* 遮罩 */
.shade {
position: fixed;
width: 100%;
height: 100%;
.pop {
position: fixed;
z-index: 101;
width: 200rpx;
box-sizing: border-box;
font-size: 28rpx;
text-align: left;
color: #333;
background-color: #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
line-height: 80rpx;
transition: transform 0.15s ease-in-out 0s;
user-select: none;
-webkit-touch-callout: none;
transform: scale(0, 0);
&.show {
transform: scale(1, 1);
}
&>view {
padding: 0 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
user-select: none;
-webkit-touch-callout: none;
&:active {
background-color: #f3f3f3;
}
}
}
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<view class="apply--cell u-border-bottom">
<view class="avatar">
<u-avatar :src="user.portraitUrl" shape="square" size="46" />
</view>
<view class="info">
<view class="name">
{{ user.name }}
</view>
<view class="message">
{{ message.message }}
</view>
</view>
<view class="action">
<u-button type="success" size="mini" @click="resolve">通过</u-button>
<u-button type="warning" size="mini" @click="reject">拒绝</u-button>
</view>
</view>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import {
resolveFriend,
rejectFriend
} from '@/apis/interfaces/im.js'
export default {
props: {
message: {
type: Object,
default: {}
}
},
computed: {
user() {
return JSON.parse(this.message.extra)
}
},
methods: {
resolve() {
resolveFriend(this.message.sourceUserId).then(res => {
this.clearMessages()
uni.showToast({
icon: 'none',
title: '通过好友申请'
})
}).catch(err => {
uni.showToast({
icon: 'none',
title: err.message
})
})
},
reject() {
uni.showModal({
title: '拒绝申请',
success: (res) => {
if (res.confirm) {
rejectFriend(this.message.sourceUserId).then(res => {
this.clearMessages()
}).catch(err => {
uni.showToast({
icon: 'none',
title: err.message
})
})
}
}
})
},
// 不管是通过还是拒绝,都要把相关的信息清理
clearMessages() {
RongIMLib.deleteMessages(RongIMLib.ConversationType.SYSTEM, this.message.sourceUserId)
this.$emit('success')
uni.$emit('onContactNotification')
}
}
}
</script>
<style lang="scss" scoped>
.apply--cell {
display: flex;
padding: $padding;
align-items: center;
.info {
flex: 1;
margin-left: $padding;
.name {
font-size: $title-size + 2;
}
.message {
color: $text-gray-m;
font-size: $title-size-m;
margin-top: 10rpx;
}
}
.action {
justify-content: space-between;
.u-button+.u-button {
margin-top: 10rpx;
}
}
}
</style>

View File

@@ -1,15 +1,14 @@
<template> <template>
<view class="friend-apply"> <view class="friend-apply">
<block v-for="item in lists" v-if="lists.length > 0" :key="item.userId"> <block v-for="(item, index) in lists" v-if="lists.length > 0" :key="index">
<view class="lists"> <view class="lists">
<view class="" style="width: 100rpx;height: 100rpx;"> <view class="" style="width: 100rpx;height: 100rpx;">
<u-image class="cover" radius="4" width="100rpx" height="100rpx" :src="item.portraitUrl || require('@/static/user/cover.png')" :lazy-load="true" /> <u-avatar :src="JSON.parse(item.latestMessage.extra).portraitUrl" shape="square" size="44" />
</view> </view>
<view class="right"> <view class="right">
<view class="title"> <view class="title">
<view class="name">{{ item.name }}</view> <view class="name">{{ item.name }}</view>
<view class="des" v-if="isApply">{{ item.address || '这家伙很懒什么都没有添加~' }}</view> <view class="des">{{ item.latestMessage.message }}</view>
<view class="des" v-else>{{ item.remark || '你好,听说你很优秀想认识~' }}</view>
</view> </view>
<view class="agress-btn"> <view class="agress-btn">
<span v-if="isAgree" @click="action('agree', item)">通过</span> <span v-if="isAgree" @click="action('agree', item)">通过</span>
@@ -44,8 +43,8 @@ export default {
default: false default: false
} }
}, },
data() { created() {
return {}; console.log(this.lists);
}, },
methods: { methods: {
action(type, item) { action(type, item) {

View File

@@ -0,0 +1,93 @@
<template>
<view class="message--cell">
<view class="avatar">
<u-badge max="99" shape="horn" absolute :offset="[-5, -8]" :value="item.unreadMessageCount" />
<u-avatar :src="contact(item.targetId).portraitUrl" shape="square" size="44" />
</view>
<view class="content">
<view class="header">
<view class="name">{{ contact(item.targetId).name }} <text v-if="item.conversationType === 3"
class='qun'>[]</text></view>
<view class="time">{{ item.sentTime|timeCustomCN }}</view>
</view>
<message-preview class="preview" :msg="item.latestMessage" :conversationType="item.conversationType"
:user="item.latestMessage.userInfo" />
</view>
</view>
</template>
<script>
import messagePreview from './messagePreview'
export default {
props: {
item: {
type: Object,
default: function() {
return {}
}
}
},
computed: {
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
components: {
messagePreview
}
}
</script>
<style lang="scss" scoped>
.message--cell {
display: flex;
padding: 20rpx 0 0 20rpx;
.avatar {
position: relative;
.u-badge {
z-index: 998;
}
}
.content {
margin-left: 30rpx;
box-sizing: border-box;
position: relative;
flex: 1;
border-bottom-width: 0.5px !important;
border-color: $u-border-color !important;
border-bottom-style: solid;
.header {
display: flex;
justify-content: space-between;
.name {
font-size: $title-size + 2;
color: #454545;
display: flex;
align-items: center;
.qun {
color: $main-color;
font-size: $title-size-m;
margin-left: 4px;
}
}
.time {
font-size: $title-size-sm;
color: $text-gray-m;
position: absolute;
right: 30rpx;
}
}
}
}
</style>

View File

@@ -1,28 +1,28 @@
<template> <template>
<view> <view>
<view v-if="msg.objectName=='RC:TxtMsg'"> <view class="preview" v-if="msg.objectName=='RC:TxtMsg'">
{{ msg.content || '' }} <text v-if="conversationType == 3">{{ user.name }}: </text>{{ msg.content || '' }}
</view> </view>
<view v-if="msg.objectName=='RC:HQVCMsg'"> <view class="preview" v-if="msg.objectName=='RC:HQVCMsg'">
[语音] <text v-if="conversationType == 3">{{ user.name }}: </text>[语音]
</view> </view>
<view v-if="msg.objectName=='RC:ImgMsg'"> <view class="preview" v-if="msg.objectName=='RC:ImgMsg'">
[图片] <text v-if="conversationType == 3">{{ user.name }}: </text>[图片]
</view> </view>
<view v-if="msg.objectName=='RC:GIFMsg'"> <view class="preview" v-if="msg.objectName=='RC:GIFMsg'">
[表情] <text v-if="conversationType == 3">{{ user.name }}: </text>[表情]
</view> </view>
<view v-if="msg.objectName=='RC:FileMsg'"> <view class="preview" v-if="msg.objectName=='RC:FileMsg'">
[文件] <text v-if="conversationType == 3">{{ user.name }}: </text>[文件]
</view> </view>
<view v-if="msg.objectName=='RC:LBSMsg'"> <view class="preview" v-if="msg.objectName=='RC:LBSMsg'">
[位置] <text v-if="conversationType == 3">{{ user.name }}: </text>[位置]
</view> </view>
<view v-if="msg.objectName=='RC:AudioMsg'"> <view class="preview" v-if="msg.objectName=='RC:AudioMsg'">
[语音通话] <text v-if="conversationType == 3">{{ user.name }}: </text>[语音通话]
</view> </view>
<view v-if="msg.objectName=='RC:VideoMsg'"> <view class="preview" v-if="msg.objectName=='RC:VideoMsg'">
[视频通话] <text v-if="conversationType == 3">{{ user.name }}: </text>[视频通话]
</view> </view>
</view> </view>
</template> </template>
@@ -33,11 +33,33 @@
msg: { msg: {
type: Object, type: Object,
default: {} default: {}
},
conversationType: {
type: Number,
default: 0
},
user: {
type: Object,
default: function() {
return {
name: ''
}
}
} }
} }
} }
</script> </script>
<style> <style lang="scss" scoped>
.preview {
word-break: break-all;
color: $text-gray-m;
padding-top: $padding - 20;
padding-bottom: $padding;
font-size: $title-size-m;
height: 32rpx;
line-height: 32rpx;
width: 520rpx;
@extend .nowrap;
}
</style> </style>

View File

@@ -0,0 +1,83 @@
<template>
<view class="">
<!-- footer -->
<view class="footer">
<view class="msg-type" @click="changeMessageType">
<image class="icon" src="@/static/icon/key-icon.png" v-if="chatType === 0" mode="widthFix">
</image>
<image class="icon" src="@/static/icon/msg-icon.png" v-if="chatType === 1" mode="widthFix">
</image>
</view>
<sent-voice v-if="chatType === 0" :conversationType="conversationType" :targetId="targetId"
@success="onSuccess" />
<sent-text v-if="chatType === 1" :conversationType="conversationType" :targetId="targetId"
@success="onSuccess" />
<view class="msg-type msg-popups" @click="showPopups = !showPopups">
<image class="icon" src="@/static/icon/popups-icon.png"></image>
</view>
</view>
<!-- 弹出层 -->
<sent-popups :show="showPopups" :conversationType="conversationType" :targetId="targetId"
@success="() => {showPopups = false, onSuccess()}"></sent-popups>
</view>
</template>
<script>
import sentText from '../components/sentText'
import sentVoice from '../components/sentVoice'
import sentPopups from '../components/sentPopups'
export default {
props: {
conversationType: {
type: Number,
default: 0
},
targetId: {
type: String,
default: ''
}
},
components: {
sentText,
sentVoice,
sentPopups
},
data() {
return {
chatType: 1, // 0 语音1 文本
showPopups: false
}
},
methods: {
// 切换聊天类型,语音/文本
changeMessageType() {
this.chatType = this.chatType === 1 ? 0 : 1
},
onSuccess() {
this.$emit('onSuccess')
}
}
}
</script>
<style lang="scss" scoped>
.footer {
background: white;
padding: 20rpx 30rpx;
display: flex;
justify-content: space-between;
flex-direction: row;
.msg-type {
width: 70rpx;
height: 70rpx;
.icon {
margin: 5rpx;
width: 60rpx;
height: 60rpx;
}
}
}
</style>

View File

@@ -63,6 +63,11 @@
default: '' default: ''
} }
}, },
computed: {
user() {
return this.$store.getters.sender
}
},
methods: { methods: {
singleCall(e) { singleCall(e) {
uni.showToast({ uni.showToast({
@@ -81,10 +86,11 @@
count: 9, count: 9,
sourceType: ['album'], sourceType: ['album'],
success: res => { success: res => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0], ( im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0],
res) => { this.user, (
this.success() res) => {
}) this.success()
})
} }
}) })
break; break;
@@ -92,10 +98,11 @@
uni.chooseImage({ uni.chooseImage({
sourceType: ['camera'], sourceType: ['camera'],
success: res => { success: res => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0], ( im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0],
res) => { this.user, (
this.success() res) => {
}) this.success()
})
} }
}) })
break; break;

View File

@@ -1,15 +1,7 @@
<template> <template>
<view class="sent--text"> <view class="sent--text">
<input <input class="input" type="text" @focus="focus" @blur="blur" v-model="inputTxt" confirm-type="send"
class="input" @confirm="sent" cursor-spacing="10" />
type="text"
@focus="focus"
@blur="blur"
v-model="inputTxt"
confirm-type="send"
@confirm="sent"
cursor-spacing="10"
/>
<!-- <button class="button" size="mini" :disabled="disabled" @click="sent">发送</button> --> <!-- <button class="button" size="mini" :disabled="disabled" @click="sent">发送</button> -->
</view> </view>
</template> </template>
@@ -36,6 +28,9 @@
computed: { computed: {
disabled() { disabled() {
return this.inputTxt.length === 0 return this.inputTxt.length === 0
},
user() {
return this.$store.getters.sender
} }
}, },
created() { created() {
@@ -55,7 +50,7 @@
sent() { sent() {
if (!this.disabled) { if (!this.disabled) {
RongIMLib.clearTextMessageDraft(this.conversationType, this.targetId) RongIMLib.clearTextMessageDraft(this.conversationType, this.targetId)
im.sentText(this.conversationType, this.targetId, this.inputTxt, () => { im.sentText(this.conversationType, this.targetId, this.inputTxt, this.user, () => {
this.$emit('success') this.$emit('success')
this.inputTxt = '' this.inputTxt = ''
}) })
@@ -65,13 +60,13 @@
this.$emit('focus') this.$emit('focus')
}, },
blur() { blur() {
this.$emit('blur') this.$emit('blur')
} }
} }
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="scss">
.sent--text { .sent--text {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -85,20 +80,5 @@
margin-right: 15rpx; margin-right: 15rpx;
padding: 0 20rpx; padding: 0 20rpx;
} }
.button {
border: none;
background: #34CE98;
color: white;
width: 120rpx;
line-height: 70rpx;
text-align: center;
border-radius: 10rpx;
font-size: 30rpx;
font-weight: bold;
}
// .button[disabled] {
// background-color: #555555;
// }
} }
</style> </style>

View File

@@ -35,6 +35,11 @@
recorderManager: null recorderManager: null
} }
}, },
computed: {
user() {
return this.$store.getters.sender
}
},
created() { created() {
this.recorderManager = uni.getRecorderManager() this.recorderManager = uni.getRecorderManager()
}, },
@@ -81,7 +86,7 @@
this.recorderManager.onStop(res => { this.recorderManager.onStop(res => {
im.sentVoice(this.conversationType, this.targetId, res.tempFilePath, (this.maxRecordTime - im.sentVoice(this.conversationType, this.targetId, res.tempFilePath, (this.maxRecordTime -
this this
.recordTime), () => { .recordTime), this.user, () => {
setTimeout(() => { setTimeout(() => {
this.$emit('success') this.$emit('success')
}, 500) }, 500)

View File

@@ -1,6 +1,9 @@
<template> <template>
<view class="msg--image" :class="guest ? 'right': 'left'"> <view class="">
<image class="img" :src="msg.thumbnail" @click="previewImage" mode="widthFix"></image> <text class="name" v-if="!guest && name">{{ name }}</text>
<view class="msg--image" :class="guest ? 'right': 'left'">
<image class="img" :src="msg.thumbnail" @click="previewImage" mode="widthFix"></image>
</view>
</view> </view>
</template> </template>
@@ -23,6 +26,10 @@
guest: { guest: {
type: Boolean, type: Boolean,
default: true default: true
},
name: {
type: String,
default: ''
} }
}, },
methods: { methods: {
@@ -39,17 +46,24 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.name {
font-size: 24rpx;
line-height: 34rpx;
color: $text-gray-m;
padding-bottom: 10rpx;
}
.msg--image { .msg--image {
padding: 20rpx; // padding: 20rpx;
&.left { &.left {
border-radius: 0 20rpx 20rpx 20rpx; border-radius: 0 20rpx 20rpx 20rpx;
background: white; // background: white;
} }
&.right { &.right {
border-radius: 20rpx 0 20rpx 20rpx; border-radius: 20rpx 0 20rpx 20rpx;
background: #34CE98; // background: #34CE98;
} }
.img { .img {

View File

@@ -1,5 +1,6 @@
<template> <template>
<view class="msg--text"> <view class="msg--text">
<text class="name" v-if="!guest && name">{{ name }}</text>
<text class="im--text" :class="guest ? 'right': 'left'">{{ msg.content }}</text> <text class="im--text" :class="guest ? 'right': 'left'">{{ msg.content }}</text>
</view> </view>
</template> </template>
@@ -12,6 +13,10 @@
type: Object, type: Object,
default: {} default: {}
}, },
name: {
type: String,
default: ''
},
guest: { guest: {
type: Boolean, type: Boolean,
default: true default: true
@@ -21,21 +26,30 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.im--text { .msg--text {
max-width: 400rpx; .name {
padding: 20rpx; font-size: 26rpx;
font-size: 28rpx; padding-bottom: 10rpx;
line-height: 40rpx; color: $text-gray-m;
&.left {
border-radius: 0 20rpx 20rpx 20rpx;
background: white;
} }
&.right { .im--text {
border-radius: 20rpx 0 20rpx 20rpx; max-width: 508rpx;
background: $main-color; padding: 20rpx;
color: white; line-height: 46rpx;
font-size: 32rpx;
color: $text-color;
&.left {
border-radius: 0 20rpx 20rpx 20rpx;
background: white;
}
&.right {
border-radius: 20rpx 0 20rpx 20rpx;
background: $main-color;
color: white;
}
} }
} }
</style> </style>

View File

@@ -1,8 +1,11 @@
<template> <template>
<view class="msg--voice" :class="guest ? 'right': 'left'" @click="onPlayMsg"> <view class="">
<image v-if="!guest" class="icon" src="@/static/icon/audio_green.png" mode="widthFix"></image> <text class="name" v-if="!guest && name">{{ name }}</text>
<text class="duration">{{msg.duration}}"</text> <view class="msg--voice" :class="guest ? 'right': 'left'" @click="onPlayMsg">
<image v-if="guest" class="icon" src="@/static/icon/audio_white.png" mode="widthFix"></image> <image v-if="!guest" class="icon" src="@/static/icon/audio_green.png" mode="widthFix"></image>
<text class="duration">{{msg.duration}}"</text>
<image v-if="guest" class="icon" src="@/static/icon/audio_white.png" mode="widthFix"></image>
</view>
</view> </view>
</template> </template>
@@ -21,6 +24,10 @@
} }
} }
}, },
name: {
type: String,
default: ''
},
guest: { guest: {
type: Boolean, type: Boolean,
default: true default: true
@@ -56,6 +63,12 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.name {
font-size: 24rpx;
line-height: 34rpx;
color: $text-gray-m;
}
.msg--voice { .msg--voice {
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;

View File

@@ -1,47 +1,32 @@
<template> <template>
<view> <view>
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98"> <u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
<view> <view class="friend-flex u-border-bottom" @click="toPending">
<view class="friend-flex u-border-bottom" @click="toPending"> <u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_01.png')"></u-avatar>
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_01.png')"></u-avatar> <u-badge max="99" absolute :offset="[23, 20]" :value="pendingCount" />
<view class="name"> <view class="info">新的朋友</view>
新的朋友 ({{ pendingCount }}) </view>
</view> <view class="friend-flex" @click="toGroup">
</view> <u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_00.png')"></u-avatar>
<view class="friend-flex" @click="showToast"> <view class="info">我的群聊</view>
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_00.png')"></u-avatar>
<view class="name">我的群聊</view>
</view>
</view> </view>
<block v-if="friends.length > 0"> <block v-if="friends.length > 0">
<template v-for="(item, friend) in friends"> <u-index-item v-for="(item, fkey) in friends" :key="fkey">
<!-- #ifdef APP-NVUE --> <u-index-anchor :text="indexs[fkey]" bgColor="#F3F6FB" height="20" size="12" color="#666">
<u-index-anchor :text="indexs[friend]" bgColor="#F3F6FB" height="20" size="12" color="#666">
</u-index-anchor> </u-index-anchor>
<!-- #endif -->
<u-index-item> <view v-for="(friendItem, index) in item" :key="index" class="friend-flex u-border-bottom"
<!-- #ifndef APP-NVUE --> @click="toFriend(friendItem.targetId)">
<u-index-anchor :text="indexs[friend]" bgColor="#F3F6FB" height="20" size="12" color="#666"> <u-avatar size="40" shape="square" :src="contact(friendItem.targetId).portraitUrl" />
</u-index-anchor> <view class="info">
<!-- #endif --> <view class="name">{{ contact(friendItem.targetId).name }}</view>
<view v-for="(friendItem, index) in item" :key="friendItem.userId" <view class="address">{{ friendItem.address }}</view>
class="friend-flex u-border-bottom"
@click="$Router.push({ name: 'imFriendsInfo', params: { targetId: friendItem.userId } })">
<block v-if="friendItem.portraitUrl != ''">
<u-avatar class="cover" size="40" shape="square" :src="friendItem.portraitUrl || ''"
:default-url="require('@/static/user/cover.png')"></u-avatar>
</block>
<block v-else>
<u-avatar class="cover" size="40" shape="square"
:src="require('@/static/user/cover.png')"></u-avatar>
</block>
<view class="name">{{ friendItem.name }}</view>
</view> </view>
</u-index-item> </view>
</template> </u-index-item>
</block> </block>
<block v-else> <block v-else>
<u-empty class="pages-null" mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png" text="暂无好友"> <u-empty class="pages-null" mode="data" text="暂无好友">
</u-empty> </u-empty>
</block> </block>
</u-index-list> </u-index-list>
@@ -50,9 +35,9 @@
<script> <script>
import { import {
getFriends, getFriendsLetter
getPendingCount
} from '@/apis/interfaces/im'; } from '@/apis/interfaces/im';
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
export default { export default {
data() { data() {
@@ -62,22 +47,53 @@
pendingCount: 0 pendingCount: 0
}; };
}, },
onShow() { computed: {
getFriends().then(res => { contact() {
this.indexs = res.indexList return function(targetId) {
this.friends = res.itemArr return this.$store.getters.contactInfo(targetId)
}) }
getPendingCount().then(res => { }
console.log(res); },
this.pendingCount = res onLoad() {
this.getFriendList()
this.checkNewFriendPending()
uni.$on('onContactNotification', () => {
this.checkNewFriendPending()
this.getFriendList()
}) })
}, },
onUnload() {
uni.$off('onContactNotification')
},
methods: { methods: {
showToast() { getFriendList() {
uni.showToast({ getFriendsLetter().then(res => {
title: '群聊功能暂未开放,敬请期待', this.indexs = res.indexList
icon: 'none' this.friends = res.itemArr
}); })
},
checkNewFriendPending() {
// 获取是否有新的好友申请
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 1000, 0, (res) => {
if (res.code === 0) {
this.pendingCount = res.conversations.filter((item) => {
return item.objectName == RongIMLib.ObjectName.ContactNotification
}).length
}
})
},
toGroup() {
uni.navigateTo({
url: '/pages/im/group/index',
fail(err) {
console.log(err);
}
})
},
toFriend(targetId) {
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + targetId
})
}, },
// 新朋友 // 新朋友
toPending() { toPending() {
@@ -108,14 +124,21 @@
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
// .cover .info {
.name {
flex: 1; flex: 1;
padding-left: $padding; margin-left: $padding;
font-size: $title-size + 2;
font-size: $title-size + 2; .name {
color: #454545 !important; font-size: $title-size + 2;
@extend .nowrap; font-size: $title-size + 2;
color: #454545 !important;
@extend .nowrap;
}
.address {
color: $text-gray-m;
font-size: $title-size-m - 5;
}
} }
} }
</style> </style>

View File

@@ -2,10 +2,11 @@
<view class="content"> <view class="content">
<!-- 用户信息 --> <!-- 用户信息 -->
<view class="info-flex"> <view class="info-flex">
<u-avatar :src="userInfo.portraitUrl || require('@/static/user/cover.png')" shape="square" size="50" bg-color="#fff"></u-avatar> <u-avatar :src="userInfo.portraitUrl || require('@/static/user/cover.png')" shape="square" size="50"
bg-color="#fff"></u-avatar>
<view class="info-text"> <view class="info-text">
<view class="nickname">{{userInfo.name}}</view> <view class="nickname">{{ userInfo.name }}</view>
<view class="address" @longpress="copyAddress">地址{{userInfo.address}}</view> <view class="address" @longpress="copyAddress">地址{{ userInfo.address }}</view>
</view> </view>
</view> </view>
<!-- 用户资料 --> <!-- 用户资料 -->
@@ -105,10 +106,11 @@
} }
}, },
onLoad(e) { onLoad(e) {
console.log(e);
this.targetId = e.targetId this.targetId = e.targetId
getFriendInfo(e.targetId).then(res => { getFriendInfo(e.targetId).then(res => {
this.userInfo = res this.userInfo = res
// 获取到用户信息之后,去检查一下要不要更新
this.$store.dispatch('updateContact', res)
uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
title: res.name title: res.name
}) })
@@ -125,7 +127,7 @@
if (code == 0) { if (code == 0) {
this.isTop = conversation.isTop this.isTop = conversation.isTop
} }
}); })
}, },
methods: { methods: {
copyAddress() { copyAddress() {
@@ -141,7 +143,7 @@
}, },
toPrivate() { toPrivate() {
uni.redirectTo({ uni.redirectTo({
url: '/pages/im/private/chat?conversationType=1&targetId=' + this.targetId url: '/pages/im/private/chat?targetId=' + this.targetId
}); });
}, },
setRemark() { setRemark() {
@@ -157,6 +159,7 @@
success: e => { success: e => {
if (e.confirm) { if (e.confirm) {
deleteFriend(this.targetId).then(res => { deleteFriend(this.targetId).then(res => {
uni.$emit('onContactNotification')
// 删除聊天记录 // 删除聊天记录
RongIMLib.deleteMessages(1, this.targetId); RongIMLib.deleteMessages(1, this.targetId);
RongIMLib.removeConversation(1, this.targetId); RongIMLib.removeConversation(1, this.targetId);
@@ -313,14 +316,16 @@
background: white; background: white;
margin: $margin; margin: $margin;
border-radius: $radius; border-radius: $radius;
.u-border-bottom{
.u-border-bottom {
border-bottom: solid 1rpx #f9f9f9 !important; border-bottom: solid 1rpx #f9f9f9 !important;
} }
.item { .item {
line-height: 100rpx; line-height: 100rpx;
display: flex; display: flex;
align-items: center; align-items: center;
padding:10rpx $padding; padding: 10rpx $padding;
justify-content: space-between; justify-content: space-between;
font-size: $title-size-lg; font-size: $title-size-lg;

View File

@@ -17,13 +17,13 @@
<view class="text" v-if="infoObj.gender === 2"></view> <view class="text" v-if="infoObj.gender === 2"></view>
</view> </view>
<view class="item"> <view class="item">
<label>HASH</label> <label>地址</label>
<view class="text">{{infoObj.hash}}</view> <view class="text">{{infoObj.address}}</view>
</view> </view>
</view> </view>
<!-- 二维码 --> <!-- 二维码 -->
<view class="info-code"> <view class="info-code">
<uqrcode class="info-code-src" :size="198" ref="uQRCode" :text="qrContent" /> <uqrcode class="info-code-src" :size="198" :text="qrContent" />
<view class="info-code-text"> <view class="info-code-text">
<view>ZH-HEALTH扫一扫上面的二维码</view> <view>ZH-HEALTH扫一扫上面的二维码</view>
<view>添加我的好友</view> <view>添加我的好友</view>
@@ -51,11 +51,10 @@
qrContent: 'ADDFRIEND|' qrContent: 'ADDFRIEND|'
} }
}, },
onLoad(e) {}, onLoad(e) {
mounted() { this.qrContent += e.targetId
getUserInfo(this.$Route.query.targetId).then(res => { getUserInfo(e.targetId).then(res => {
this.infoObj = res this.infoObj = res
this.qrContent += res.userId
}) })
}, },
methods: { methods: {

View File

@@ -1,11 +1,3 @@
<!--
* @Description:新朋友即新增好友申请列表 可以搜索跳转
* @Author: Aimee·Zhang
* @Date: 2022-01-24 10:49:15
* @LastEditors: Aimee·Zhang
* @LastEditTime: 2022-01-25 10:18:26
-->
<template> <template>
<view class="pending"> <view class="pending">
<u-sticky> <u-sticky>
@@ -14,66 +6,36 @@
:disabled="true" :show-action="false" /> :disabled="true" :show-action="false" />
</view> </view>
</u-sticky> </u-sticky>
<block v-if="pedings.length > 0"> <view v-for="(item, index) in pendings" :key="index">
<applyFriend :lists="pedings" :isAgree="true" :isReject="false" @action="action" /> <apply-cell :message="item.latestMessage" @success="getPendingList" />
</block>
<view class="no-lists" v-else>
<u-image class="cover" radius="4" width="400rpx" height="400rpx"
:src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span>暂无申请记录~</span>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { import applyCell from '../components/friendApplyCell'
getPedings, import im from '@/utils/im/index.js'
resolveFriend,
rejectFriend
} from '@/apis/interfaces/im.js'
import * as RongIMLib from "@/uni_modules/RongCloud-IMWrapper/js_sdk/index"
import applyFriend from '@/components/friend-apply-reject-agree'
export default { export default {
components: { components: {
applyFriend applyCell
}, },
data() { data() {
return { return {
pedings: [] pendings: []
} }
}, },
onLoad() { onLoad() {
this.getPeddingList() this.getPendingList()
uni.$on('onContactNotification', this.getPendingList)
},
onUnload() {
uni.$off('onContactNotification')
}, },
methods: { methods: {
// 操作同意或拒绝 getPendingList() {
action(e) { im.getPendingList((pendings) => {
let url = e.type === 'agree' ? resolveFriend : rejectFriend this.pendings = pendings
uni.showModal({
title: e.type === 'agree' ? '通过' : '拒绝',
content: e.type === 'agree' ? '通过后即可与该用户畅所欲言' : '拒绝后将不会收到该用户发来信息',
success: res => {
if (res.confirm) {
url(e.item.userId).then(res => {
this.getPeddingList()
})
}
}
})
},
getPeddingList() {
// 获取系统中的好友关系会话列表
// RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 50, 0, (res) => {
// if (res.code === 0) {
// this.pedings = res.conversations.filter((item) => {
// return item.objectName == RongIMLib.ObjectName.ContactNotification
// })
// }
// })
getPedings().then(res => {
console.log(res)
this.pedings = res
}) })
} }
} }

View File

@@ -12,7 +12,7 @@
<u-sticky> <u-sticky>
<view class="header-search"> <view class="header-search">
<u-search placeholder="输入用户账号、手机号" height="74" searchIcon="search" @custom="search" <u-search placeholder="输入用户账号、手机号" height="74" searchIcon="search" @custom="search"
v-model="searchValue" @search="search" inputAlign="center" bgColor="#f9f9f9" :focus="focused" /> v-model="searchValue" @search="search" bgColor="#f9f9f9" :focus="focused" />
</view> </view>
</u-sticky> </u-sticky>
<block v-if="searchResult.length > 0"> <block v-if="searchResult.length > 0">
@@ -31,7 +31,7 @@
searchFriend, searchFriend,
pedingFriend pedingFriend
} from '@/apis/interfaces/im.js'; } from '@/apis/interfaces/im.js';
import applyFriend from '@/components/friend-apply-reject-agree'; import applyFriend from '../components/friendApplyList.vue';
export default { export default {
components: { components: {
applyFriend applyFriend

View File

@@ -0,0 +1,60 @@
<template>
<view class="create">
<u--textarea v-model="content" count height="200" maxlength="200" placeholder="请输入公告内容"></u--textarea>
<u-button type="primary" text="发布" :disabled="disabled" @click="onCreate" color="#34CE98"></u-button>
</view>
</template>
<script>
import {
createGroupAnnouncement
} from '@/apis/interfaces/im.js'
export default {
data() {
return {
targetId: '',
content: ''
}
},
onLoad(e) {
this.targetId = e.targetId
},
computed: {
disabled() {
return this.content.length == 0 || this.content.length > 200
}
},
methods: {
onCreate() {
createGroupAnnouncement(this.targetId, this.content).then(res => {
uni.$emit('groupAnnouncementCreated')
uni.showToast({
title: '发布成功',
success: () => {
setTimeout(() => {
uni.navigateBack()
}, 1000)
}
})
}).catch(err => {
uni.showToast({
icon: 'none',
title: err.message
})
})
}
}
}
</script>
<style lang="scss" scoped>
.create {
padding: $padding;
.u-button {
margin-top: $padding;
}
}
</style>

View File

@@ -0,0 +1,125 @@
<template>
<view class="announce">
<u-skeleton rows="2" :loading="loading" avatar :rows="5">
<view v-for="(item,index) in announcements" :key="index" class="item">
<view class="header">
<u-avatar :src="item.user.portraitUrl"></u-avatar>
<view class="user">
<view class="name">{{ item.user.name }}</view>
<view class="time">{{ item.created_at }}</view>
</view>
<view class="delete" v-if="isAdmin" @click="onDelete(item.announcement_id)">删除</view>
</view>
<view class="content">{{ item.content }}</view>
</view>
</u-skeleton>
</view>
</template>
<script>
import {
getGroupInfo,
getGroupAnnouncements,
deleteGroupAnnouncement
} from '@/apis/interfaces/im.js'
export default {
data() {
return {
targetId: '',
announcements: [],
loading: true,
isAdmin: false
}
},
onLoad(e) {
this.targetId = e.targetId
getGroupInfo(this.targetId).then(res => {
this.isAdmin = res.group.is_admin
})
this.initData()
uni.$on('groupAnnouncementCreated', this.initData)
},
onUnload() {
uni.$off('groupAnnouncementCreated')
},
onNavigationBarButtonTap() {
if (this.isAdmin) {
uni.navigateTo({
url: '/pages/im/group/announceCreate?targetId=' + this.targetId
})
} else {
uni.showToast({
icon: 'none',
title: '没有权限'
})
}
},
methods: {
initData() {
getGroupAnnouncements(this.targetId).then(res => {
this.announcements = res
this.loading = false
})
},
onDelete(aId) {
uni.showModal({
title: '删除公告',
success: (res) => {
if (res.confirm) {
deleteGroupAnnouncement(this.targetId, aId).then(res => {
uni.showToast({
icon: 'none',
title: '删除成功'
})
this.initData()
})
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
.announce {
padding: 0 $padding $padding $padding;
.item {
border-bottom: solid 1rpx #f9f9f9 !important;
padding-top: $padding;
.header {
display: flex;
flex-direction: row;
align-items: center;
.user {
margin-left: $padding;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {}
.time {
font-size: 24rpx;
color: $text-gray-m;
}
}
.delete {
color: $text-price;
font-size: 28rpx;
}
}
.content {
padding: $padding;
font-size: 34rpx;
}
}
}
</style>

91
pages/im/group/apply.vue Normal file
View File

@@ -0,0 +1,91 @@
<template>
<view class="apply">
<u-avatar :src="group.cover" size="128" shape="square"></u-avatar>
<view class="name">
{{ group.name }}
</view>
<u-button v-if="group.can_join" @click="applyGroup" text="申请加群" :disabled="disabled" color="#34CE98" />
<view class="" v-else>
<view class="" v-if="group.is_full">群已满员</view>
<view class="" v-if="group.deny_apply">禁止申请</view>
<u-button v-if="group.state === 'accepted'" color="#34CE98" text="进入群聊" @click="toGroupChat" />
</view>
<u-modal negativeTop="300" :show="modalShow" title="申请原因" showCancelButton @cancel="onHideModal"
@confirm="onJoinGroup">
<view class="slot-content">
<u--input placeholder="申请原因" border="surround" focus v-model="message"></u--input>
</view>
</u-modal>
</view>
</template>
<script>
import {
joinGroupPre,
joinGroup
} from '@/apis/interfaces/im.js'
export default {
data() {
return {
targetId: '',
group: {},
modalShow: false,
message: '',
disabled: false
}
},
onLoad(e) {
this.targetId = e.targetId
joinGroupPre(this.targetId).then(res => {
console.log(res);
this.group = res
})
},
methods: {
toGroupChat() {
uni.redirectTo({
url: '/pages/im/group/chat?targetId=' + this.targetId
})
},
applyGroup() {
this.modalShow = true
},
onHideModal() {
this.message = ''
this.modalShow = false
},
onJoinGroup() {
joinGroup(this.targetId, this.message).then(res => {
console.log('申请结果', res);
uni.showToast({
icon: 'none',
title: '申请成功'
})
}).catch(err => {
uni.showToast({
icon: 'none',
title: err.message
})
})
this.disabled = true
this.onHideModal()
}
}
}
</script>
<style lang="scss" scoped>
.apply {
display: flex;
flex-direction: column;
align-items: center;
.u-avatar {
width: 200rpx;
height: 200rpx;
}
}
</style>

197
pages/im/group/chat.nvue Normal file
View File

@@ -0,0 +1,197 @@
<template>
<view class="group--chat">
<list class="body" :show-scrollbar="false">
<cell class="cell" v-for="(item, index) in messages" :key="index">
<view class="cell-item" :class="item.messageDirection == 1 ? 'right' : 'left'">
<u-avatar class="avatar" @click="toUser(item)" size="36" shape="square" :src="item.content.userInfo.portraitUrl" />
<view class="msg">
<show-voice v-if="item.objectName === 'RC:HQVCMsg'" :guest="item.messageDirection == 1"
:msg="item.content" :name="item.content.userInfo.name" />
<show-image v-if="item.objectName === 'RC:ImgMsg'" :guest="item.messageDirection == 1"
:msg="item.content" :name="item.content.userInfo.name" />
<show-text v-if="item.objectName === 'RC:TxtMsg'" :guest="item.messageDirection == 1"
:msg="item.content" :name="item.content.userInfo.name" />
</view>
</view>
</cell>
<cell class="cell-footer" ref="chatBottom"></cell>
</list>
<sent-message-bar :conversationType="conversationType" :targetId="targetId" @onSuccess="getMessageList()" />
</view>
</template>
<script>
import {
timeCustomCN
} from '@/utils/filters.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import im from '@/utils/im/index.js'
import showVoice from '../components/showVoice'
import showImage from '../components/showImage'
import showText from '../components/showText'
import sentMessageBar from '../components/sentMessageBar'
const ChatList = uni.requireNativePlugin('dom')
export default {
components: {
showVoice,
showImage,
showText,
sentMessageBar
},
data() {
return {
targetId: '',
conversationType: 3,
messages: [],
groupInfo: {
name: ''
}
}
},
onLoad(e) {
this.targetId = e.targetId
this.groupInfo = this.$store.getters.contactInfo(this.targetId)
uni.setNavigationBarTitle({
title: this.groupInfo.name
})
this.getMessageList()
uni.$on('onReceiveMessage', (msg) => {
if (msg.targetId == this.targetId) {
this.getMessageList()
}
})
uni.$once('cleanGroupMessage', this.getMessageList)
},
onBackPress() {
uni.$off('onReceiveMessage')
console.log('Off onReceiveMessage');
},
onNavigationBarButtonTap() {
uni.navigateTo({
url: '/pages/im/group/info?targetId=' + this.targetId
})
},
methods: {
toUser(item) {
if (item.senderUserId == '__system__') {
return
}
if (item.messageDirection == 1) {
uni.navigateTo({
url: '/pages/im/friends/mine?targetId=' + item.senderUserId
})
} else{
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + item.senderUserId
})
}
},
// 获取消息列表
getMessageList() {
im.getMessageList(
this.conversationType,
this.targetId,
new Date().getTime(),
20,
true,
(messages) => {
this.messages = messages.reverse()
this.scrollBottom()
})
},
// 滚动到底部
scrollBottom(type) {
// 清理当前会话,未读消息数量
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime() + 1100)
// 发送消息已读状态给对方
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
// 更新badge提醒数量
im.setNotifyBadge()
setTimeout(() => {
let el = this.$refs.chatBottom
ChatList.scrollToElement(el, {
offset: 0,
animated: false
})
}, 50)
}
}
}
</script>
<style lang="scss" scoped>
.group--chat {
background: $window-color;
flex: 1;
.body {
flex: 1;
.cell {
padding: 10rpx 30rpx;
.cell-item {
width: 690rpx;
justify-content: flex-start;
align-items: flex-start;
margin-top: 20rpx;
&.left {
flex-direction: row;
}
&.right {
flex-direction: row-reverse;
.state {
flex-direction: row;
justify-content: flex-end;
}
}
.avatar {
width: 78rpx;
height: 78rpx;
background-color: white;
border-radius: 10rpx;
}
.msg {
margin: 0 20rpx;
.user {
font-size: 18rpx;
line-height: 40rpx;
}
}
}
.cell-footer {
height: 20rpx;
}
}
}
.footer {
background: white;
padding: 20rpx 30rpx;
display: flex;
justify-content: space-between;
flex-direction: row;
.msg-type {
width: 70rpx;
height: 70rpx;
.icon {
margin: 5rpx;
width: 60rpx;
height: 60rpx;
}
}
}
}
</style>

View File

@@ -1,11 +1,109 @@
<template> <template>
<view class=""> <view>
<view v-for="(item, index) in groups" :key="index" class="friend-flex u-border-bottom"
@click="toGroup(item.targetId)">
<u-avatar size="40" shape="square" :src="contact(item.targetId).portraitUrl" />
<view class="info">
<view class="name">{{ item.name }}</view>
</view>
</view>
<u-modal negativeTop="300" :show="createModal" title="创建群聊" showCancelButton @cancel="onHideModal"
@confirm="onCreateGroup">
<view class="slot-content">
<u--input placeholder="群名称" border="surround" focus v-model="groupName"></u--input>
</view>
</u-modal>
</view> </view>
</template> </template>
<script> <script>
import {
getMyGroups,
createGroup
} from '@/apis/interfaces/im.js'
export default {
data() {
return {
groups: [],
createModal: false,
groupName: ''
}
},
computed: {
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
onNavigationBarButtonTap() {
this.createModal = true
},
onLoad() {
this.initData()
},
methods: {
initData() {
getMyGroups().then((res) => {
this.groups = res
res.map(item => {
this.$store.dispatch('updateContact', item)
})
})
},
onHideModal() {
this.createModal = false
this.groupName = ''
},
onCreateGroup() {
createGroup({
name: this.groupName
}).then(res => {
uni.showToast({
title: '创建成功'
})
this.initData()
this.onHideModal()
}).catch(err => {
uni.showToast({
icon: 'none',
title: err
})
})
},
toGroup(targetId) {
uni.navigateTo({
url: '/pages/im/group/chat?targetId=' + targetId
})
}
}
}
</script> </script>
<style> <style lang="scss" scoped>
// 好友列表
.friend-flex {
position: relative;
padding: 20rpx $padding;
display: flex;
flex-direction: row;
align-items: center;
.info {
flex: 1;
margin-left: $padding;
.name {
font-size: $title-size + 2;
font-size: $title-size + 2;
color: #454545 !important;
}
.address {
color: $text-gray-m;
font-size: $title-size-m - 5;
}
}
}
</style> </style>

399
pages/im/group/info.vue Normal file
View File

@@ -0,0 +1,399 @@
<template>
<view class="container">
<view class="members u-border-bottom">
<view class="users">
<view class="user" v-for="(item, index) in users" :key="index" @click="toUser(item)">
<u-avatar size="44" shape="square" :src="item.portraitUrl"></u-avatar>
<view class="name">{{ item.name }}</view>
</view>
<view class="user">
<u-avatar @click="inviteUser" size="44" shape="square" icon="plus" bg-color="#eeeeee"
color="#999999"></u-avatar>
<view class="name">邀请好友</view>
</view>
</view>
<view @click="loadMore" v-if="members > users.length" class="loadmore">查看更多群成员 ></view>
</view>
<u-cell-group class="cells">
<u-cell isLink title="群公告" :label="announcement" @click="toAnnouncement"></u-cell>
<u-cell isLink title="二维码" @click="showGroupQrCode"></u-cell>
<u-cell title="聊天置顶">
<u-switch slot="value" size="20" v-model="isTop" activeColor="#34CE98" @change="setTop"></u-switch>
</u-cell>
<u-cell title="免打扰">
<u-switch slot="value" size="20" v-model="status" activeColor="#34CE98" @change="setStatus"></u-switch>
</u-cell>
</u-cell-group>
<u-cell-group class="cells" v-if="group.is_admin">
<u-cell isLink title="修改群聊名称" :value="groupName" @click="onGroupName"></u-cell>
<u-cell isLink title="修改群头像">
<u-avatar slot="value" size="25" shape="square" @click="onGroupAvatar" :src="group.cover"></u-avatar>
</u-cell>
<u-cell isLink v-if="group.is_owner" title="准入方式" :value="joinType" @click="onChangeJoinType"></u-cell>
</u-cell-group>
<view class="cells actions u-border-top" v-if="loaded">
<view class="action u-border-bottom" @click="onClean">清空聊天记录</view>
<view class="action u-border-bottom" v-if="group.is_owner" @click="onDismiss">解散群聊</view>
<view class="action u-border-bottom" v-else @click="onQuite">删除并退出</view>
</view>
<u-modal negativeTop="300" :show="modalShow" title="修改群名称" showCancelButton @cancel="onHideModal"
@confirm="onChangeGroupName">
<view class="slot-content">
<u--input placeholder="群名称" border="surround" focus v-model="groupName"></u--input>
</view>
</u-modal>
<u-modal :show="qrCodeShow" :title="group.name" @confirm="qrCodeShow = false">
<view class="slot-content">
<uqrcode class="info-code-src" :size="198" :text="qrContent" />
</view>
</u-modal>
<u-action-sheet @select="doAction" :actions="joinTypeMap" cancelText="取消" :show="showActions"
@close="showActions=false">
</u-action-sheet>
</view>
</template>
<script>
import {
getGroupInfo,
updateGroup,
quitGroup,
dismissGroup
} from '@/apis/interfaces/im.js'
import {
uploads
} from '@/apis/interfaces/uploading'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
export default {
data() {
return {
targetId: '',
group: {},
conversationType: 3,
announcement: '',
users: [],
status: false,
isTop: false,
loaded: false,
modalShow: false,
groupName: '',
qrCodeShow: false,
qrContent: 'JOINGROUP|',
joinType: '',
joinTypeMap: [],
showActions: false
}
},
onLoad(e) {
this.targetId = e.targetId
this.qrContent += e.targetId
RongIMLib.getConversationNotificationStatus(this.conversationType, this.targetId, ({
status
}) => {
this.status = !Boolean(status)
})
RongIMLib.getConversation(this.conversationType, this.targetId, ({
code,
conversation
}) => {
if (code == 0) {
this.isTop = conversation.isTop
}
})
this.initData()
uni.$on('groupAnnouncementCreated', this.initData)
},
onUnload() {
uni.$off('groupAnnouncementCreated')
},
methods: {
initData() {
getGroupInfo(this.targetId).then(res => {
this.group = res.group
this.groupName = res.group.name
this.announcement = res.announcement
this.users = res.users
this.members = res.members
this.loaded = true
this.joinTypeMap = res.join_type_map.map(item => {
if (item.key == res.join_type) {
item.disabled = true
}
return item
})
this.joinType = res.join_type_map.filter(item => item.key == res.join_type)[0].name
}).catch(err => {
uni.showToast({
icon: 'none',
title: '群不存在'
})
})
},
setStatus() {
RongIMLib.setConversationNotificationStatus(this.conversationType, this.targetId, this.status,
({
status
}) => {
this.status = !Boolean(status)
})
},
setTop() {
RongIMLib.setConversationToTop(this.conversationType, this.targetId, this.isTop, (res) => {
RongIMLib.getConversation(this.conversationType, this.targetId, ({
conversation
}) => {
this.isTop = conversation.isTop
})
})
},
toUser(item) {
if (item.targetId == this.$store.getters.sender.userId) {
uni.navigateTo({
url: '/pages/im/friends/mine?targetId=' + item.targetId
})
} else {
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + item.targetId
})
}
},
inviteUser() {
},
loadMore() {
uni.navigateTo({
url: '/pages/im/group/users?targetId=' + this.targetId
})
},
toAnnouncement() {
uni.navigateTo({
url: '/pages/im/group/announcement?targetId=' + this.targetId
})
},
showGroupQrCode() {
this.qrCodeShow = true
},
onGroupName() {
this.modalShow = true
console.log(this.$refs.groupNameRef);
},
onChangeGroupName() {
if (this.groupName != this.group.name) {
updateGroup(this.targetId, {
name: this.groupName
}).then(res => {
this.modalShow = false
uni.showToast({
icon: 'none',
title: '群名称修改成功'
})
})
} else {
uni.showToast({
icon: 'none',
title: '无修改'
})
}
},
onHideModal() {
this.modalShow = false
this.groupName = this.group.name
},
// 修改群头像
onGroupAvatar() {
console.log('onGroupAvatar');
uni.chooseImage({
count: 1,
sourceType: ['album'],
crop: {
quality: 100,
width: 128,
height: 128,
resize: true
},
success: res => {
console.log(res);
let path = res.tempFiles.map((val, index) => {
return {
name: 'uploads' + index,
uri: val.path
}
})
uploads(path).then(path => {
updateGroup(this.targetId, {
cover: path.path[0]
}).then(res => {
uni.showToast({
icon: 'none',
title: '群头像修改成功'
})
this.modalShow = false
this.group.cover = path.url[0]
})
}).catch(err => {
uni.showToast({
title: err.message,
icon: 'none'
})
})
},
fail: (err) => {
console.log(err);
}
})
},
onChangeJoinType() {
this.showActions = true
},
doAction(e) {
updateGroup(this.targetId, {
join_type: e.key
}).then(res => {
uni.showToast({
icon: 'none',
title: '修改成功'
})
this.joinTypeMap = this.joinTypeMap.map(item => {
if (item.key == e.key) {
item.disabled = true
} else {
item.disabled = false
}
return item
})
this.joinType = e.name
this.showActions = false
}).catch(err => {
console.log(err);
uni.showToast({
icon: 'error',
title: err.message
})
})
},
onClean() {
uni.showModal({
title: '清空聊天记录',
content: '清空聊天记录,只会清空本地的记录,其他成员不会变化',
success: (res) => {
if (res.confirm) {
RongIMLib.deleteMessages(3, this.targetId, () => {
uni.showToast({
icon: 'none',
title: '清空成功'
})
uni.$emit('cleanGroupMessage')
})
}
}
})
},
onDismiss() {
uni.showModal({
title: '解散群聊',
success: (res) => {
if (res.confirm) {
dismissGroup(this.targetId).then(res => {
uni.showToast({
icon: 'none',
title: '解散成功'
})
uni.switchTab({
url: '/pages/im/index'
})
})
}
}
})
},
onQuite() {
uni.showModal({
title: '退出群聊',
success: (res) => {
if (res.confirm) {
quitGroup(this.targetId).then(res => {
uni.showToast({
icon: 'none',
title: '退出群聊成功'
})
uni.switchTab({
url: '/pages/im/index'
})
})
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background: $window-color;
}
.cells {
margin-top: $padding;
background-color: white;
}
.members {
background-color: white;
padding-bottom: 40rpx;
.users {
flex-direction: row;
flex-wrap: wrap;
display: flex;
padding: 20rpx 0;
.user {
width: 126rpx;
margin-left: 20rpx;
margin-bottom: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.name {
color: $text-gray-m;
width: 126rpx;
text-align: center;
font-size: 26rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-word;
}
}
}
.loadmore {
font-size: 26rpx;
color: $text-gray-m;
text-align: center;
}
}
.actions {
margin-top: $padding;
text-align: center;
.action {
padding: $padding;
color: $text-price;
justify-content: center;
}
}
</style>

164
pages/im/group/users.vue Normal file
View File

@@ -0,0 +1,164 @@
<template>
<view class="members">
<view class="users">
<view class="user" v-if="isAdmin">
<u-avatar @click="inviteUser" size="44" shape="square" icon="plus" bg-color="#eeeeee" color="#999999">
</u-avatar>
<view class="name">邀请好友</view>
</view>
<view :class="['user', {'active': item.targetId == currentUser.targetId}]" @longpress="showAction(item)"
v-for="(item, index) in members" :key="index" @click="toUser(item)">
<u-avatar size="44" shape="square" :src="item.portraitUrl"></u-avatar>
<view class="name">{{ item.name }}</view>
</view>
</view>
<view class="loadmore">成员总数{{ members.length }}</view>
<u-action-sheet :actions="userActions" :title="actionTitle" cancelText="取消" @close="hideAction"
@select="doAction" :show="actionShow">
</u-action-sheet>
</view>
</template>
<script>
import {
getGroupBase,
getGroupUsers
} from '@/apis/interfaces/im.js'
export default {
data() {
return {
targetId: '',
members: [],
isOwner: false,
isAdmin: false,
actionShow: false,
userActions: [{
type: 0,
name: '设置管理员',
disabled: false
},
{
type: 1,
name: '解除管理员',
disabled: false
},
{
type: 2,
name: '移除成员',
disabled: false
}
],
actionTitle: '',
currentUser: {}
}
},
onLoad(e) {
this.targetId = e.targetId
getGroupBase(this.targetId).then(res => {
this.isOwner = res.is_owner
this.isAdmin = res.is_admin
if (this.isOwner) {
this.userActions.push({
type: 3,
name: '转移群主',
disabled: false
})
}
})
this.getUserList()
},
methods: {
getUserList() {
getGroupUsers(this.targetId).then(res => {
this.members = res
})
},
toUser(item) {
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + item.targetId
})
},
showAction(item) {
this.currentUser = item
this.actionTitle = item.name
this.actionShow = true
// 根据当前用户,是不是管理,来控制按钮的可用性
this.userActions[0].disabled = true
},
hideAction(item) {
this.actionShow = false
this.actionTitle = ''
this.currentUser = {}
this.userActions[0].disabled = false
this.userActions[1].disabled = false
},
doAction(e) {
switch (e.type) {
case 0:
// 设置管理
break;
case 1:
// 取消管理
break;
case 2:
// 移除成员
break;
case 3:
// 转移管理员
break;
}
this.getUserList()
},
inviteUser() {
}
}
}
</script>
<style lang="scss" scoped>
.members {
background-color: white;
padding-bottom: 40rpx;
.users {
flex-direction: row;
flex-wrap: wrap;
display: flex;
padding: 20rpx 0;
.user {
width: 126rpx;
margin-left: 20rpx;
margin-bottom: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&.active {
background-color: $window-color;
}
.name {
color: $text-gray-m;
width: 126rpx;
text-align: center;
font-size: 26rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-word;
}
}
}
.loadmore {
font-size: 26rpx;
color: $text-gray-m;
text-align: center;
}
}
</style>

View File

@@ -5,60 +5,23 @@
<view class="custom-header"> <view class="custom-header">
<view class="header-flex"> <view class="header-flex">
<view class="tabs"> <view class="tabs">
<view class="item show"> <view class="item active">聊聊</view>
<u-badge max="99" value="99" absolute :offset="[0, -10]"/>私聊
</view>
<view class="item" @click="onNav('', {})">
<u-badge max="99" value="99" absolute :offset="[0, -10]"/>群聊
</view>
</view> </view>
<view class="btns"> <view class="btns">
<view class="item" @click="scanQrCode"> <view class="item" @click="scanQrCode">
<uni-icons color="#555" type="scan" size="22"></uni-icons> <uni-icons color="#555" type="scan" size="22" />
</view> </view>
<view class="item" @click="onNav('imFriends', {})"> <view class="item" @click="toFriendList">
<uni-icons color="#555" custom-prefix="iconfont" type="icon-tuandui" size="22"></uni-icons> <u-badge absolute max="99" :offset="[-5, -5]" :value="hasNewFriends" />
<uni-icons color="#555" custom-prefix="iconfont" type="icon-tuandui" size="22" />
</view> </view>
<!-- <view class="item" @click="onNav('', {})">
<uni-icons color="#555" custom-prefix="iconfont" type="icon-gengduo2" size="22"></uni-icons>
</view> -->
</view> </view>
</view> </view>
</view> </view>
<u-alert type="warning" v-if="connection != 0" description="网络似乎断开了,请检查网络" :show-icon="true" />
<!-- content --> <!-- content -->
<view v-if="$store.state.token != ''"> <view v-if="$store.state.token !== ''">
<block v-if="conversations.length < 1"> <conversation-list @refresh="getConversationList()" :conversations="conversations" />
<view class="vertical null-list">
<u-empty mode="message" textColor="#999" text="暂无好友消息" />
</view>
</block>
<block v-else>
<u-alert type="warning" v-if="connection != 0" description="网络似乎断开了,请检查网络" :show-icon="true" />
<view v-for="(item, index) in conversations" :key="index" :class="['message', { 'is-top': item.isTop }]"
@click="toDetail(item)" @longpress="onLongPress" :data-item="item">
<view class="avatar" @click="toFriend(item.targetId)">
<u-badge numberType="ellipsis" max="99" shape="horn" absolute :offset="[-5, -5]"
:value="item.unreadMessageCount" />
<u-avatar :src="friend(item.targetId).portraitUrl || require('@/static/user/cover.png')"
shape="square" size="44" />
</view>
<view class="content u-border-bottom">
<view class="header">
<view class="name">{{ friend(item.targetId).name || '未知用户' }}</view>
<view class="time">{{ item.sentTime|timeCustomCN }}</view>
</view>
<message-preview class="preview" :msg="item.latestMessage" />
</view>
</view>
<!-- TODO 长按的弹出框怎么点击隐藏没搞明白 -->
<view class="shade" @click="hidePop" v-show="showPop">
<view class="pop" :style="popStyle" :class="{'show':showPop}">
<view v-for="(item, index) in popButton" :key="index" @click="pickerMenu" :data-index="index">
{{item}}
</view>
</view>
</view>
</block>
</view> </view>
<!-- 未登录 --> <!-- 未登录 -->
<view v-else class="vertical null-list"> <view v-else class="vertical null-list">
@@ -72,119 +35,46 @@
</template> </template>
<script> <script>
import * as RongIMLib from "@/uni_modules/RongCloud-IMWrapper/js_sdk/index" import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
import userAuth from '@/public/userAuth' import userAuth from '@/public/userAuth'
import messagePreview from './components/messagePreview' import conversationList from './components/conversationList'
import {
getImToken
} from '@/apis/interfaces/im.js'
export default { export default {
data() { data() {
return { return {
isShown: true, // 当前页面显示状态
conversations: [], // 会话列表 conversations: [], // 会话列表
connection: 0, connection: 0,
/* 窗口尺寸 */ hasNewFriends: 0
winSize: {},
/* 显示操作弹窗 */
showPop: false,
/* 弹窗按钮列表 */
popButton: ['置顶聊天', '删除该聊天'],
/* 弹窗定位样式 */
popStyle: "",
pickedItem: {}
} }
}, },
components: { components: {
messagePreview conversationList
},
computed: {
friend() {
return function(targetId) {
return this.$store.getters.userInfo(targetId)
}
}
}, },
onLoad() { onLoad() {
// 好友申请数量
this.checkNewFriendPending()
uni.$on('onConnectionStatusChange', (status) => { uni.$on('onConnectionStatusChange', (status) => {
this.connection = status this.connection = status
}) })
uni.$on('onContactNotification', this.checkNewFriendPending)
}, },
onShow() { onShow() {
if (this.$store.state.token !== '') { if (this.$store.state.token !== '') {
this.getConversationList() this.getConversationList()
} }
// 监听新消息
uni.$on('onReceiveMessage', (msg) => { uni.$on('onReceiveMessage', (msg) => {
console.log('收到消息,刷新列表');
this.getConversationList() this.getConversationList()
}) })
this.isShown = true
}, },
onHide() { onHide() {
uni.$off('onReceiveMessage') uni.$off('onReceiveMessage')
this.isShown = false
},
onNavigationBarButtonTap(e) {
if (e.index == 0) {
uni.showToast({
title: '开发中暂未开放,敬请期待',
icon: 'none'
})
}
if (e.index == 1) {
if (this.toLogin()) {
this.$Router.push({
name: 'imFriends'
})
}
}
}, },
methods: { methods: {
// 隐藏功能菜单 checkNewFriendPending() {
hidePop() { im.getPendingList((pendings) => {
this.showPop = false this.hasNewFriends = pendings.length
this.pickedItem = {}
setTimeout(() => {
this.showShade = false
}, 250)
},
// 点击会话功能菜单
pickerMenu(e) {
const index = Number(e.currentTarget.dataset.index)
if (index == 0) {
RongIMLib.setConversationToTop(this.pickedItem.conversationType, this.pickedItem.targetId, !this
.pickedItem.isTop)
} else {
RongIMLib.removeConversation(this.pickedItem.conversationType, this.pickedItem.targetId)
}
im.setNotifyBadge()
this.getConversationList()
this.hidePop()
},
// 长按会话,展示功能菜单
onLongPress(e) {
let [touches, style, item] = [e.touches[0], "", e.currentTarget.dataset.item]
if (touches.clientY > (this.winSize.height / 2)) {
style = `bottom:${this.winSize.height-touches.clientY}px;`
} else {
style = `top:${touches.clientY}px;`
}
if (touches.clientX > (this.winSize.witdh / 2)) {
style += `right:${this.winSize.witdh-touches.clientX}px`
} else {
style += `left:${touches.clientX}px`
}
this.popButton[0] = item.isTop ? '取消置顶' : '置顶聊天'
this.popStyle = style
this.pickedItem = item
this.$nextTick(() => {
setTimeout(() => {
this.showPop = true;
}, 10)
}) })
}, },
// 检查登录 // 检查登录
@@ -196,108 +86,48 @@
} }
return true return true
}, },
// 获取私聊的会话列表
getConversationList() { getConversationList() {
const count = 1000 const count = 1000
const timestamp = 0 const timestamp = 0
RongIMLib.getConversationList([RongIMLib.ConversationType.PRIVATE], count, timestamp, (res) => { RongIMLib.getConversationList([1, 3], count, timestamp, (res) => {
if (res.code === 0) { if (res.code === 0) {
console.log(res.conversations);
this.conversations = res.conversations this.conversations = res.conversations
} }
}) })
}, },
// 进入聊天的详情页面,清理未读消息数量
toDetail(item) {
this.hidePop()
uni.navigateTo({
url: '/pages/im/private/chat?targetId=' + item.targetId + '&conversationType=' + item
.conversationType
})
},
toFriend(targetId) {
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + targetId
})
},
// 点击按钮
onNav(name, params) {
if (this.toLogin) {
if (name === '') {
uni.showToast({
title: '开发中,敬请期待',
icon: 'none'
})
return
}
this.$Router.push({
name,
params
})
}
},
// 调起扫码 // 调起扫码
scanQrCode() { scanQrCode() {
uni.scanCode({ uni.scanCode({
success: (res) => { success: (res) => {
if (res.scanType == 'QR_CODE') { if (res.scanType == 'QR_CODE') {
res.result.substr(0, 10) == 'ADDFRIEND|' if (res.result.substr(0, 10) == 'ADDFRIEND|') {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + res.result.substr(10) url: '/pages/im/friends/info?targetId=' + res.result.substr(10)
}) })
} else if (res.result.substr(0, 10) == 'JOINGROUP|') {
uni.navigateTo({
url: '/pages/im/group/apply?targetId=' + res.result.substr(10)
})
} else {
uni.showToast({
title: '暂不支持的二维码'
})
}
} }
} }
}) })
},
toFriendList() {
uni.navigateTo({
url: '/pages/im/friends/index'
})
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// header
.custom-header {
@extend .ios-top;
background: $window-color;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9999;
.header-flex {
padding: 20rpx $padding;
display: flex;
justify-content: space-between;
height: 60rpx;
line-height: 60rpx;
.tabs {
.item {
position: relative;
margin-left: $margin;
display: inline-block;
font-size: $title-size-lg;
color: $text-gray;
padding: 0 ($padding - 10);
border-radius: 30rpx;
&:first-child {
margin: 0;
}
&.show {
background: rgba($color: $main-color, $alpha: .1);
color: $main-color;
font-weight: bold;
}
}
}
.btns {
.item {
display: inline-block;
margin-left: $margin;
}
}
}
}
// contents // contents
.contents { .contents {
background-color: $window-color; background-color: $window-color;
@@ -305,6 +135,50 @@
padding-top: 90rpx + 20rpx; padding-top: 90rpx + 20rpx;
box-sizing: border-box; box-sizing: border-box;
.custom-header {
@extend .ios-top;
background: $window-color;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9999;
.header-flex {
padding: 20rpx $padding;
display: flex;
justify-content: space-between;
height: 60rpx;
line-height: 60rpx;
.tabs {
.item {
position: relative;
display: inline-block;
font-size: $title-size-lg;
color: $text-gray;
padding: 0 ($padding - 10);
border-radius: 30rpx;
&.active {
background: rgba($color: $main-color, $alpha: .1);
color: $main-color;
font-weight: bold;
}
}
}
.btns {
.item {
position: relative;
display: inline-block;
margin-left: $margin;
}
}
}
}
.null-list { .null-list {
height: 100vh; height: 100vh;
text-align: center; text-align: center;
@@ -320,105 +194,6 @@
box-sizing: border-box; box-sizing: border-box;
} }
} }
.message {
background: white;
padding: 20rpx 0 0 20rpx;
position: relative;
display: flex;
&.is-top {
background: $window-color;
border-bottom: #e8e8e8;
}
.avatar {
position: relative;
.u-badge {
z-index: 998;
}
}
.content {
margin-left: 30rpx;
width: calc(100% - 46px);
box-sizing: border-box;
position: relative;
.header {
display: flex;
justify-content: space-between;
.name {
font-size: $title-size + 2;
color: #454545;
color: #454545;
}
.time {
font-size: $title-size-sm;
color: $text-gray-m;
position: absolute;
right: 30rpx;
}
}
.preview {
word-break: break-all;
color: $text-gray-m;
padding-top: $padding - 20;
padding-bottom: $padding;
font-size: $title-size-m;
height: 32rpx;
line-height: 32rpx;
width: 500rpx;
@extend .nowrap;
}
}
}
}
/* 遮罩 */
.shade {
position: fixed;
width: 100%;
height: 100%;
.pop {
position: fixed;
z-index: 101;
width: 200rpx;
box-sizing: border-box;
font-size: 28rpx;
text-align: left;
color: #333;
background-color: #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
line-height: 80rpx;
transition: transform 0.15s ease-in-out 0s;
user-select: none;
-webkit-touch-callout: none;
transform: scale(0, 0);
&.show {
transform: scale(1, 1);
}
&>view {
padding: 0 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
user-select: none;
-webkit-touch-callout: none;
&:active {
background-color: #f3f3f3;
}
}
}
} }
.u-border-bottom { .u-border-bottom {

View File

@@ -7,8 +7,7 @@
<text class="text">{{ customCN(item.sentTime) }}</text> <text class="text">{{ customCN(item.sentTime) }}</text>
</view> </view>
<view class="cell-item" :class="item.messageDirection == 1 ? 'right' : 'left'"> <view class="cell-item" :class="item.messageDirection == 1 ? 'right' : 'left'">
<image class="avatar" :src="userInfo.portraitUrl" mode="aspectFill" <u-avatar class="avatar" size="36" shape="square" @click="showUser(targetId, item.messageDirection)" :src="userInfo.portraitUrl" />
@click="showUser(targetId, item.messageDirection)"></image>
<view class="msg"> <view class="msg">
<show-voice v-if="item.objectName === 'RC:HQVCMsg'" :guest="item.messageDirection == 1" <show-voice v-if="item.objectName === 'RC:HQVCMsg'" :guest="item.messageDirection == 1"
:msg="item.content" /> :msg="item.content" />
@@ -24,24 +23,7 @@
</cell> </cell>
<cell class="cell-footer" ref="chatBottom"></cell> <cell class="cell-footer" ref="chatBottom"></cell>
</list> </list>
<!-- footer --> <sent-message-bar :conversationType="conversationType" :targetId="targetId" @onSuccess="getMessageList()" />
<view class="footer">
<view class="msg-type" @click="changeMessageType">
<image class="icon" src="@/static/icon/key-icon.png" v-if="chatType === 0" mode="widthFix">
</image>
<image class="icon" src="@/static/icon/msg-icon.png" v-if="chatType === 1" mode="widthFix">
</image>
</view>
<sent-voice v-if="chatType === 0" :conversationType="conversationType" :targetId="targetId"
@success="getMessageList" />
<sent-text v-if="chatType === 1" :conversationType="conversationType" :targetId="targetId"
@success="getMessageList" />
<view class="msg-type msg-popups" @click="scrollBottom('msgPopups')">
<image class="icon" src="@/static/icon/popups-icon.png"></image>
</view>
</view>
<!-- 弹出层 -->
<sent-popups :show="showPopups" :conversationType="conversationType" :targetId="targetId" @success="() => {showPopups = false, getMessageList()}"></sent-popups>
</view> </view>
</template> </template>
@@ -54,9 +36,7 @@
import showVoice from '../components/showVoice' import showVoice from '../components/showVoice'
import showImage from '../components/showImage' import showImage from '../components/showImage'
import showText from '../components/showText' import showText from '../components/showText'
import sentText from '../components/sentText' import sentMessageBar from '../components/sentMessageBar'
import sentVoice from '../components/sentVoice'
import sentPopups from '../components/sentPopups'
const ChatList = uni.requireNativePlugin('dom') const ChatList = uni.requireNativePlugin('dom')
@@ -70,31 +50,23 @@
name: '', name: '',
userId: '', userId: '',
portraitUrl: '' portraitUrl: ''
}, }
chatType: 1, // 0 语音1 文本
showPopups: false,
inputFocus: false // 输入框是否获得了焦点
} }
}, },
components: { components: {
sentMessageBar,
showVoice, showVoice,
showImage, showImage,
showText, showText
sentText,
sentVoice,
sentPopups
}, },
onLoad(e) { onLoad(e) {
this.targetId = e.targetId this.targetId = e.targetId
this.conversationType = e.conversationType // 会话类型 this.userInfo = this.$store.getters.contactInfo(this.targetId)
this.userInfo = this.$store.getters.userInfo(this.targetId)
// 获取消息列表
this.initMessageList()
uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
title: this.userInfo.name title: this.userInfo.name
}) })
// 获取消息列表
this.getMessageList()
// 监听消息已读状态 // 监听消息已读状态
uni.$on('onReadReceiptReceived', (data) => { uni.$on('onReadReceiptReceived', (data) => {
if (data.targetId == this.targetId) { if (data.targetId == this.targetId) {
@@ -104,27 +76,17 @@
// 监听收到新消息,判断是否是当前会话,更新会话内容 // 监听收到新消息,判断是否是当前会话,更新会话内容
uni.$on('onReceiveMessage', (msg) => { uni.$on('onReceiveMessage', (msg) => {
if (msg.targetId == this.targetId) { if (msg.targetId == this.targetId) {
this.initMessageList() this.getMessageList()
} }
}) })
}, },
onBackPress() {
uni.$off('onReceiveMessage')
},
methods: { methods: {
initMessageList() {
this.getMessageList()
// 清理当前会话,未读消息数量
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime())
// 发送消息已读状态给对方
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
// 更新badge提醒数量
im.setNotifyBadge()
},
customCN(val) { customCN(val) {
return timeCustomCN(val) return timeCustomCN(val)
}, },
// 切换聊天类型,语音/文本
changeMessageType() {
this.chatType = this.chatType === 1 ? 0 : 1
},
// 获取消息列表 // 获取消息列表
getMessageList() { getMessageList() {
im.getMessageList( im.getMessageList(
@@ -134,7 +96,6 @@
10, 10,
true, true,
(messages) => { (messages) => {
console.log('获取到的消息', messages);
this.messages = messages.reverse() this.messages = messages.reverse()
this.scrollBottom() this.scrollBottom()
}) })
@@ -148,9 +109,12 @@
}, },
// 滚动到底部 // 滚动到底部
scrollBottom(type) { scrollBottom(type) {
if(type === 'msgPopups'){ // 清理当前会话,未读消息数量
this.showPopups = !this.showPopups RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime() + 1100)
} // 发送消息已读状态给对方
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
// 更新badge提醒数量
im.setNotifyBadge()
setTimeout(() => { setTimeout(() => {
let el = this.$refs.chatBottom let el = this.$refs.chatBottom
ChatList.scrollToElement(el, { ChatList.scrollToElement(el, {
@@ -168,14 +132,18 @@
.chat { .chat {
background: $window-color; background: $window-color;
flex: 1; flex: 1;
.body { .body {
flex: 1; flex: 1;
.cell { .cell {
padding: 10rpx 30rpx; padding: 10rpx 30rpx;
.time { .time {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding-bottom: 20rpx; padding-bottom: 20rpx;
.text { .text {
background: #fff; background: #fff;
font-size: 24rpx; font-size: 24rpx;
@@ -204,13 +172,6 @@
} }
} }
.avatar {
width: 78rpx;
height: 78rpx;
background-color: white;
border-radius: 10rpx;
}
.msg { .msg {
margin: 0 20rpx; margin: 0 20rpx;
@@ -230,22 +191,5 @@
} }
} }
} }
.footer {
background: white;
padding: 20rpx 30rpx;
display: flex;
justify-content: space-between;
flex-direction: row;
.msg-type {
width: 70rpx;
height: 70rpx;
.icon {
margin: 5rpx;
width: 60rpx;
height: 60rpx;
}
}
}
} }
</style> </style>

View File

@@ -60,11 +60,17 @@ export default {
healthSports(data).then(res => { healthSports(data).then(res => {
this.lists = this.lists.concat(res.data); this.lists = this.lists.concat(res.data);
this.has_more = res.page.has_more; this.has_more = res.page.has_more;
}); }).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
}, },
// 显示弹窗内容 // 显示弹窗内容
addSport(item) { addSport(item) {
console.log(item);
this.selectSports = item; this.selectSports = item;
this.selectSports.duration = 60; this.selectSports.duration = 60;
this.addSportsShow = true; this.addSportsShow = true;
@@ -99,7 +105,6 @@ export default {
//#region 搜索相关方法 start //#region 搜索相关方法 start
// 点击搜索左侧按钮 // 点击搜索左侧按钮
searchCustom(e) { searchCustom(e) {
console.log(e);
this.name = e; this.name = e;
this.reset(); this.reset();
}, },

View File

@@ -8,186 +8,187 @@
<template> <template>
<view class="add-foods"> <view class="add-foods">
<view class="re"> <view class="re"> <view>低等热量</view> <view>中等热量</view> <view>高等热量</view> </view>
<view>低等热量</view>
<view>中等热量</view>
<view>高等热量</view>
</view>
<!-- 搜索页面 --> <!-- 搜索页面 -->
<u-search <u-search :show-action="true" actionText="搜索" :animation="true" :clearabled="true" placeholder="请输入食品名称"
:show-action="true" @custom="searchCustom" @clear="clearSearch" v-model="name" />
actionText="搜索"
:animation="true"
:clearabled="true"
placeholder="请输入食品名称"
@custom="searchCustom"
@clear="clearSearch"
v-model="name"
/>
<!-- 食品列表 --> <!-- 食品列表 -->
<goodsList <goodsList :lists="lists" type="dian" @addGoods="addGoods" />
:lists="lists"
type="dian"
@addGoods="addGoods"
/>
<!-- 添加食谱弹窗 --> <!-- 添加食谱弹窗 -->
<addFoods <addFoods v-if="addShow" :addShow="addShow" :selectGoods="selectGoods" :decimals="true" @confirm="confirmHandle"
v-if="addShow" @close="closeHandle" @tabGoodsInfo="tabGoodsInfo" max="999" />
:addShow="addShow"
:selectGoods="selectGoods"
:decimals="true"
@confirm="confirmHandle"
@close="closeHandle"
@tabGoodsInfo="tabGoodsInfo"
max="999"
/>
</view> </view>
</template> </template>
<script> <script>
import goodsList from "@/components/foods"; import goodsList from "@/components/foods";
import addFoods from "@/components/add-goods-template/add-goods-template"; import addFoods from "@/components/add-goods-template/add-goods-template";
import { healthFoods, addHealthFoods } from "@/apis/interfaces/foods.js"; import {
import moment from "moment"; healthFoods,
addHealthFoods
} from "@/apis/interfaces/foods.js";
import moment from "moment";
export default { export default {
components: { goodsList, addFoods }, components: {
data() { goodsList,
return { addFoods
addShow: false, // 添加食品显示 },
selectGoods: [], // 选择新增的食品 data() {
editGoodsId: "", // 编辑食物 return {
type: "", // 新增食品时候 1早2午3晚4早加5午加6晚加 addShow: false, // 添加食品显示
lists: [], // 食品列表 selectGoods: [], // 选择新增的食品
page: 1, editGoodsId: "", // 编辑食物
has_more: true, type: "", // 新增食品时候 1早2午3晚4早加5午加6晚加
name: "", // 搜索食品名称 lists: [], // 食品列表
date: moment(new Date()).format("YYYY-MM-DD"), page: 1,
}; has_more: true,
}, name: "", // 搜索食品名称
onShow() { date: moment(new Date()).format("YYYY-MM-DD"),
// 有id就是编辑不需要重新处理type了 };
if (this.$Route.query.id) { },
this.editGoodsId = this.$Route.query.id; onShow() {
return; // 有id就是编辑不需要重新处理type了
} if (this.$Route.query.id) {
//没有id的时候就是新增要处理type this.editGoodsId = this.$Route.query.id;
this.type = this.$Route.query.type; return;
// this.getFoods(); }
}, //没有id的时候就是新增要处理type
onLoad() { this.type = this.$Route.query.type;
this.getFoods(); this.date = this.$Route.query.date;
}, },
// 触底加载更多 onLoad() {
onReachBottom() {
if (!this.has_more) {
uni.showToast({
title: "没有更多啦~",
icon: "none",
});
} else {
this.page = this.page + 1;
this.getFoods(); this.getFoods();
}
},
methods: {
// 获取食品列表
getFoods() {
let data = {
page: this.page,
name: this.name,
};
healthFoods(data).then((res) => {
console.log(res);
this.lists = this.lists.concat(res.data);
this.has_more = res.page.has_more;
});
}, },
// 监听点击键盘触发返回值新增食品 // 触底加载更多
confirmHandle(value) { onReachBottom() {
console.log(value); if (!this.has_more) {
// 新添加食物 uni.showToast({
let data = { title: "没有更多啦~",
type: this.type, icon: "none",
ser: 1, });
weight: value, } else {
food_id: this.selectGoods[0].food_id, this.page = this.page + 1;
date: this.date, this.getFoods();
}; }
this.addHealthFoods(data);
}, },
// 添加食物 methods: {
addHealthFoods(data) { // 获取食品列表
addHealthFoods(data).then((res) => { getFoods() {
console.log(res); let data = {
page: this.page,
name: this.name,
};
healthFoods(data).then((res) => {
this.lists = this.lists.concat(res.data);
this.has_more = res.page.has_more;
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
},
// 监听点击键盘触发返回值新增食品
confirmHandle(value) {
// 新添加食物
let data = {
type: this.type,
ser: 1,
weight: value,
food_id: this.selectGoods[0].food_id,
date: this.date,
};
this.addHealthFoods(data);
},
// 添加食物
addHealthFoods(data) {
addHealthFoods(data).then((res) => {
this.addShow = false;
this.$Router.back();
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration:2000,
mask:true
})
setTimeout(()=>{
this.$Router.back();
},2000)
});
},
closeHandle() {
//键盘关闭的回调函数
this.addShow = false; this.addShow = false;
this.$Router.back(); },
}); // 监听子组件的新增方法
addGoods(e) {
this.addShow = true;
this.selectGoods = [e];
},
// 点击搜索左侧按钮
searchCustom(e) {
this.name = e;
this.reset();
},
// 清空数组重新请求数据
reset() {
this.page = 1;
this.has_more = true;
this.lists = [];
this.getFoods();
},
// 点击搜索后面按钮触发事件事件
clearSearch() {
this.name = "";
this.reset();
},
// 跳转到食品详情
tabGoodsInfo(e) {
this.$Router.push({
name: "rankingDetails",
params: e,
});
},
}, },
closeHandle() { };
//键盘关闭的回调函数
this.addShow = false;
},
// 监听子组件的新增方法
addGoods(e) {
this.addShow = true;
this.selectGoods = [e];
},
// 点击搜索左侧按钮
searchCustom(e) {
console.log(e);
this.name = e;
this.reset();
},
// 清空数组重新请求数据
reset() {
this.page = 1;
this.has_more = true;
this.lists = [];
this.getFoods();
},
// 点击搜索后面按钮触发事件事件
clearSearch() {
this.name = "";
this.reset();
},
// 跳转到食品详情
tabGoodsInfo(e) {
this.$Router.push({
name: "rankingDetails",
params: e,
});
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.add-foods { .add-foods {
padding: $padding; padding: $padding;
.re { .re {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
box-sizing: border-box; box-sizing: border-box;
padding: $padding $padding * 2; padding: $padding $padding * 2;
font-size: $title-size-m; font-size: $title-size-m;
view:before {
width: 20rpx; view:before {
height: 20rpx; width: 20rpx;
border-radius: 50%; height: 20rpx;
display: inline-block; border-radius: 50%;
margin-right: 10rpx; display: inline-block;
content: ""; margin-right: 10rpx;
} content: "";
view:nth-child(3):before {
background: #fa624d; }
}
view:nth-child(2):before { view:nth-child(3):before {
background: #fbbf0f; background: #fa624d;
} }
view:nth-child(1):before {
background: #02c7bd; view:nth-child(2):before {
background: #fbbf0f;
}
view:nth-child(1):before {
background: #02c7bd;
}
} }
} }
}
</style> </style>

View File

@@ -7,402 +7,543 @@
--> -->
<template> <template>
<view class="drink" v-if="loaded"> <view class="drink" v-if="loaded">
<!-- 喝水及水杯文字 --> <!-- 自定义导航部分 -->
<view class="drink-content"> <u-navbar :safeAreaInsetTop="true" :fixed='true' bgColor="#34ce98" :autoBack="true">
<view class="title" v-if="!water.is_complete"> <view class="u-nav-slot" slot="left">
再喝 <u-icon name="arrow-leftward" :bold="true" size="20" color="#fff" />
<span class="num">{{ water.lack.cup }}</span> </view>
<view class="u-nav-slot u-center" slot="center" @click="dateShow = true,dateLists()">
<span class="total">{{ water.lack.value }}ml</span> <u-icon name="play-left-fill" size="14" color="#fff" @click="datePreNext('before')" />
</view> <view class="date">
<view class="title" v-if="water.is_complete"> <u-icon name="calendar" color="#fff" label-color="#fff" width="150" :label="today" label-size="14"
已喝 size="20" />
<span class="num">{{ water.total }}ml</span> </view>
<u-image class="is_complete" :src="require('../../static/imgs/target.png')" :lazy-load="true" mode="widthFix" width="140rpx" /> <u-icon name="play-right-fill" size="14" color="#fff" @click="datePreNext('after')" />
</view> </view>
<!-- 水杯动态图片 --> <view class="u-nav-slot" slot="right">
<view class="wave-content"> <u-icon :name="require('@/static/icon/sign-icon.gif')" :bold="true" size="30"
<u-image class="grass" :src="require('../../static/imgs/gress.png')" :lazy-load="true" mode="scaleToFill" width="320rpx" height="520rpx" /> @click="$Router.push({name:'signIndex'})" />
<view class="wave" :style="{ '--ballPercent': -ballPercent + 40 + '%' }"></view> </view>
</view> </u-navbar>
<!-- 目标 --> <!-- 喝水及水杯文字 -->
<view class="water-target"> <view class="drink-content">
<view class="target-item" @click="targetShow = true"> <view class="title" v-if="!water.is_complete"> 再喝 <span class="num">{{ water.lack.cup }}</span> <span
今日目标 class="total">{{ water.lack.value }}ml</span> </view>
<u-icon <view class="title" v-if="water.is_complete">
class="target-icon" 已喝 <span class="num">{{ water.total }}ml</span>
name="arrow-right" <u-image class="is_complete" :src="require('../../static/imgs/target.png')" :lazy-load="true"
color="#666" mode="widthFix" width="140rpx" />
size="14" </view>
:bold="true" <!-- 水杯动态图片 -->
:label="water.target + 'ml'" <view class="wave-content">
labelPos="left" <u-image class="grass" :src="require('../../static/imgs/gress.png')" :lazy-load="true"
labelSize="16" mode="scaleToFill" width="320rpx" height="520rpx" />
labelColor="#666" <view class="wave" :style="{ '--ballPercent': -ballPercent + 40 + '%' }"></view>
space="6" </view>
/> <!-- 目标 -->
</view> <view class="water-target">
<view class="target-item" @click="waterCShow = true"> <view class="target-item" @click="targetShow = true"> 今日目标
水杯容量 <u-icon class="target-icon" name="arrow-right" color="#666" size="14" :bold="true"
<u-icon class="target-icon" name="arrow-right" color="#666" size="14" :bold="true" :label="water.ml + 'ml'" labelPos="left" labelSize="16" labelColor="#666" space="6" /> :label="water.target + 'ml'" labelPos="left" labelSize="16" labelColor="#666" space="6" />
</view> </view>
</view> <view class="target-item" @click="waterCShow = true"> 水杯容量
<!-- 目标弹出层 --> <u-icon class="target-icon" name="arrow-right" color="#666" size="14" :bold="true"
<view> :label="water.ml + 'ml'" labelPos="left" labelSize="16" labelColor="#666" space="6" />
<u-picker </view>
:show="targetShow" </view>
:columns="tagerts" <!-- 目标弹出层 -->
title="每天喝水目标" <view>
keyName="label" <u-picker :show="targetShow" :columns="tagerts" title="每天喝水目标" keyName="label" confirmColor="#34ce98"
confirmColor="#34ce98" :closeOnClickOverlay="true" @close="targetShow = false" @confirm="targetSure('1', $event)"
:closeOnClickOverlay="true" :defaultIndex="tagertsDefaultIndex" />
@close="targetShow = false" <u-picker :show="waterCShow" :columns="cup_mls" title="设置水杯容量" keyName="label" confirmColor="#34ce98"
@confirm="targetSure('1', $event)" :closeOnClickOverlay="true" @close="waterCShow = false" @confirm="targetSure('2', $event)"
:defaultIndex="tagertsDefaultIndex" :defaultIndex="cupDefaultIndex" />
/> </view>
<u-picker <!-- 加水 -->
:show="waterCShow" <view class="add-water" @click="drinkWater">
:columns="cup_mls" <u-image class="grass" :src="require('../../static/imgs/gress2.png')" :lazy-load="true"
title="设置水杯容量" mode="scaleToFill" width="60rpx" height="80rpx" />
keyName="label" <span>一杯水</span>
confirmColor="#34ce98" <u-icon class="add-icon" name="plus-circle-fill" color="#34ce98" size="24" />
:closeOnClickOverlay="true" </view>
@close="waterCShow = false" </view>
@confirm="targetSure('2', $event)" <!-- 喝水记录 -->
:defaultIndex="cupDefaultIndex" <view class="--history">
/> <view class="title">喝水记录</view>
</view> <template v-if="logs.length > 0">
<!-- 加水 --> <view class="lists" v-for="item in logs" :key="item.water_log_id"
<view class="add-water" @click="drinkWater"> @longpress="delWater(item.water_log_id)">
<u-image class="grass" :src="require('../../static/imgs/gress2.png')" :lazy-load="true" mode="scaleToFill" width="60rpx" height="80rpx" /> <view class="lists-water">
<span>一杯水</span> <u-icon size="30" :name="require('../../static/icon/water-icon.png')" />
<u-icon class="add-icon" name="plus-circle-fill" color="#34ce98" size="24" /> </view>
</view> <view class="list-item">
</view> <view class="list-item-title"> <span>{{ item.time }}</span> </view> {{ item.ml }}ml
<!-- 喝水记录 --> </view>
<view class="--history"> </view>
<view class="title">喝水记录</view> </template>
<template v-if="logs.length > 0"> <view v-else class="no-drink">今天一杯水还没有喝呢来一杯吧~</view>
<view class="lists" v-for="item in logs" :key="item.water_log_id" @longpress="delWater(item.water_log_id)"> </view>
<view class="lists-water"><u-icon size="30" :name="require('../../static/icon/water-icon.png')" /></view>
<view class="list-item"> <!-- 选择日历 -->
<view class="list-item-title"> <dateTemplate :lists="calendarList" :today="today" :month="month" :dateShow="dateShow" type='drink'
@backDate="backDate" @dateClick="dateClick" @closeDate="closeDate" @datePreNext="datePreNext" />
<span>{{ item.time }}</span> </view>
</view>
{{ item.ml }}ml
</view>
</view>
</template>
<view v-else class="no-drink">今天一杯水还没有喝呢来一杯吧~</view>
</view>
</view>
</template> </template>
<script> <script>
import { waters, setWaters, drinkWater, delDrinkWater } from '@/apis/interfaces/drink'; import {
import moment from 'moment'; waters,
export default { setWaters,
data() { drinkWater,
return { delDrinkWater,
ballPercent: 0, // 喝水比例 dateList
logs: [], // 水记录 } from '@/apis/interfaces/drink';
water: {}, // 水基本信息 import moment from 'moment';
targetShow: false, import dateTemplate from '@/components/date-template/index.vue'
tagerts: [], // 目标列表 export default {
tagertsDefaultIndex: ['1'], // 目标默认index components: {
waterCShow: false, dateTemplate
cup_mls: [], // 水杯列表 },
cupDefaultIndex: ['2'], // 目标默认index data() {
loaded: false return {
}; ballPercent: 0, // 喝水比例
}, logs: [], // 水记录
onShow() { water: {}, // 水基本信息
this.getWaters(); targetShow: false,
}, tagerts: [], // 目标列表
methods: { tagertsDefaultIndex: ['1'], // 目标默认index
// 获取喝水页面信息 waterCShow: false,
getWaters() { cup_mls: [], // 水杯列表
waters().then(res => { cupDefaultIndex: ['2'], // 目标默认index
this.cup_mls = [res.cup_mls]; loaded: false,
this.tagerts = [res.tagerts]; today: moment(new Date()).format('YYYY-MM-DD'), // 当前时间
this.water = res.water; month: moment(new Date()).format('YYYY-MM'), //当前月份
this.logs = res.logs; dateShow: false, // 日历展示
this.ballPercent = res.water.lack.ratio; calendarList: [],
this.cupDefaultIndex = [res.cup_mls.findIndex(item => item.number === res.water.ml)]; dateType: '', // before after ''
this.tagertsDefaultIndex = [res.tagerts.findIndex(item => item.number === res.water.target)]; };
this.loaded = true; },
}); onShow() {
}, this.getWaters();
// 确认方法index===1 每日目标 2水杯容量 this.dateLists();
targetSure(index, e) { },
// console.log("触发了targetSure", index, e.value[0]); methods: {
// let date = moment(new Date()).format("YYYY--MM--DD"); // 获取喝水页面信息
let params = {}; getWaters() {
if (index === '1') { let data = {
params = { date: this.today,
type: 'target', // type:this.dateType
ml: e.value[0].number, }
date: moment(new Date()).format('YYYY-MM-DD') waters(data).then(res => {
}; this.cup_mls = [res.cup_mls];
} else { this.tagerts = [res.tagerts];
params = { this.water = res.water;
type: 'ml', this.logs = res.logs;
ml: e.value[0].number, this.ballPercent = res.water.lack.ratio;
date: moment(new Date()).format('YYYY-MM-DD') this.cupDefaultIndex = [res.cup_mls.findIndex(item => item.number === res.water.ml)];
}; this.tagertsDefaultIndex = [res.tagerts.findIndex(item => item.number === res.water
} .target)];
setWaters(params).then(res => { this.loaded = true;
this.getWaters(); }).catch(err => {
this.waterCShow = false; uni.showToast({
this.targetShow = false; title: err.message,
}); icon: "none",
}, duration: 2000,
// 喝水 mask: true
drinkWater() { })
drinkWater().then(res => { });
this.getWaters(); },
}); // 确认方法index===1 每日目标 2水杯容量
}, targetSure(index, e) {
// 删除和喝水记录 let params = {};
delWater(id) { if (index === '1') {
uni.showModal({ params = {
content: '确认删除么?', type: 'target',
confirmText: '确认删除', ml: e.value[0].number,
confirmColor: '#34ce98', date: moment(new Date()).format('YYYY-MM-DD')
cancelText: '再想想', };
cancelColor: '#ddd', } else {
success: res => { params = {
if (res.confirm) { type: 'ml',
delDrinkWater(id) ml: e.value[0].number,
.then(res => { date: moment(new Date()).format('YYYY-MM-DD')
this.getWaters(); };
}) }
.catch(err => { setWaters(params).then(res => {
uni.showToast({ this.getWaters();
title: err.message, this.waterCShow = false;
icon: 'none' this.targetShow = false;
}); }).catch(err => {
}); uni.showToast({
} title: err.message,
} icon: "none",
}); duration: 2000,
} mask: true
} })
}; });
},
// 喝水
drinkWater() {
let data = {
date: this.today
}
drinkWater(data).then(res => {
this.getWaters();
this.dateLists()
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
},
// 删除和喝水记录
delWater(id) {
uni.showModal({
content: '确认删除么?',
confirmText: '确认删除',
confirmColor: '#34ce98',
cancelText: '再想想',
cancelColor: '#ddd',
success: res => {
if (res.confirm) {
delDrinkWater(id)
.then(res => {
this.getWaters();
})
.catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
}
}
});
},
//#region 日历操作相关
// 日历列表
dateLists() {
let data = {
month: this.month,
type: this.dateType
}
dateList(data).then(res => {
this.calendarList = res.calendar
this.dateType = ''
this.month = res.month
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
})
},
// 选择日期
dateClick(item) {
this.today = item.today
this.month = item.today
this.reset()
},
// 返回到今日
backDate() {
this.today = moment(new Date()).format('YYYY-MM-DD')
this.reset()
},
// 上一个月或者下一个月
datePreNext(type) {
this.dateType = type
this.dateLists()
},
// 关闭日历
closeDate() {
this.month = this.today
this.dateShow = false
},
// 重置日历数据
reset() {
this.calendarList = []
this.dateLists()
this.getWaters()
this.closeDate()
}
//#endregion 日历操作相关
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.drink { .drink {
// 喝水 水杯及文字 padding-top: 120rpx;
.drink-content { // 顶部日历筛选部分
display: flex; .u-center {
flex-direction: column; display: flex;
align-items: center; flex-direction: row;
justify-content: center; align-items: center;
box-sizing: border-box; justify-content: center;
// padding: $padding 0; box-sizing: border-box;
position: relative;
// 标题 再喝水
.title {
font-size: $title-size + 4;
color: $main-color;
font-weight: normal;
margin: $margin * 2;
position: relative;
.is_complete {
position: absolute;
top: 30rpx;
right: -120rpx;
}
.num {
font-size: $title-size * 2.3;
padding: 0 $padding * 0.3;
font-weight: bold;
}
.total {
font-size: $title-size;
color: $text-gray-m;
padding-left: $padding * 0.2;
}
}
// 加一杯水
.add-water {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size;
color: $text-color;
margin-top: $margin * 2;
position: relative;
span {
padding-top: $padding * 0.4;
color:$text-gray-m;
font-size: $title-size;
}
.add-icon {
position: absolute;
top: $margin + 8;
right: 0;
}
}
// 目标
.water-target {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
color: $text-gray-m;
font-size: $title-size;
position: absolute;
z-index: 110;
right: $padding * 1.4;
top: 50%;
.target-item {
margin-top: $margin * 1.6;
.target-icon {
padding-top: $padding * 0.5;
}
}
}
}
// 喝水记录
.--history {
padding: $padding;
.no-drink {
color: $text-gray-m;
font-size: $title-size-m;
padding-top: $padding + 10;
}
// 标题
.title {
font-size: $title-size + 4;
font-weight: bold;
color: $text-color;
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
padding-left: $padding;
padding-bottom: $padding;
&::before {
position: absolute;
content: '';
width: 8rpx;
height: 45rpx;
left: 0;
background-color: $main-color;
border-radius: 10rpx;
}
}
// 列表 .date {
.lists { background-color: rgba($color: #000000, $alpha: .1);
// background-color: pink; color: #fff;
display: flex; min-width: 340rpx;
flex-direction: row; display: flex;
align-items: center; flex-direction: row;
justify-content: space-between; align-items: center;
box-sizing: border-box; justify-content: center;
border-bottom: solid 1rpx #f7f7f7; box-sizing: border-box;
.lists-water { padding: 8rpx 20rpx;
background-image: linear-gradient(to right, $main-color, $main-color); border-radius: $radius * 2;
width: 90rpx; margin: 0 10rpx;
height: 90rpx; font-size: $title-size - 2;
border-radius: 50%; }
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.list-item {
flex: 1;
margin-left: $margin * 0.7;
font-size: $title-size;
color: $text-gray-m;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin: $margin 0 $margin $margin * 0.7;
.list-item-title {
font-size: $title-size + 3;
color: $text-color;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
box-sizing: border-box;
font-weight: bold;
span {
margin-top: $margin * 0.4;
background-color: #f7f7f7;
padding: 4rpx 10rpx;
border-radius: 50rpx;
font-weight: normal;
font-size: $title-size - 3;
}
}
}
}
}
}
// 水杯动画
.wave-content {
position: relative;
z-index: 110;
.grass {
position: relative;
z-index: 120099;
}
.wave { .play-right-fill {
position: absolute; padding: $padding !important;
width: 290rpx; background-color: pink;
height: 500rpx; }
background-color: rgba($color: $main-color, $alpha: 0.6); }
background-size: 100%;
overflow: hidden;
top: 10rpx;
left: 20rpx;
z-index: 10;
&::before,
&::after {
content: '';
position: absolute;
width: 1000rpx;
height: 1000rpx;
top: var(--ballPercent);
left: 50%;
background-color: rgba(255, 255, 255, 0.4);
border-radius: 45%;
transform: translate(-50%, -70%) rotate(0);
animation: rotate 4s linear infinite;
z-index: 10;
}
&::after {
border-radius: 47%;
background-color: rgba(255, 255, 255, 0.9);
transform: translate(-50%, -70%) rotate(0);
animation: rotate 6s linear -5s infinite;
z-index: 20;
}
}
@keyframes rotate { // 喝水 水杯及文字
50% {
transform: translate(-50%, -73%) rotate(180deg); .drink-content {
} display: flex;
100% { flex-direction: column;
transform: translate(-50%, -70%) rotate(360deg); align-items: center;
} justify-content: center;
} box-sizing: border-box;
} // padding: $padding 0;
position: relative;
// 标题 再喝水
.title {
font-size: $title-size + 4;
color: $main-color;
font-weight: normal;
margin: $margin * 2;
position: relative;
.is_complete {
position: absolute;
top: 30rpx;
right: -120rpx;
}
.num {
font-size: $title-size * 2.3;
padding: 0 $padding * 0.3;
font-weight: bold;
}
.total {
font-size: $title-size;
color: $text-gray-m;
padding-left: $padding * 0.2;
}
}
// 加一杯水
.add-water {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size;
color: $text-color;
margin-top: $margin * 2;
position: relative;
span {
padding-top: $padding * 0.4;
color: $text-gray-m;
font-size: $title-size;
}
.add-icon {
position: absolute;
top: $margin + 8;
right: 0;
}
}
// 目标
.water-target {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
color: $text-gray-m;
font-size: $title-size;
position: absolute;
z-index: 110;
right: $padding * 1.4;
top: 50%;
.target-item {
margin-top: $margin * 1.6;
.target-icon {
padding-top: $padding * 0.5;
}
}
}
}
// 喝水记录
.--history {
padding: $padding;
.no-drink {
color: $text-gray-m;
font-size: $title-size-m;
padding-top: $padding + 10;
}
// 标题
.title {
font-size: $title-size + 4;
font-weight: bold;
color: $text-color;
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
padding-left: $padding;
padding-bottom: $padding;
&::before {
position: absolute;
content: '';
width: 8rpx;
height: 45rpx;
left: 0;
background-color: $main-color;
border-radius: 10rpx;
}
}
// 列表
.lists {
// background-color: pink;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
border-bottom: solid 1rpx #f7f7f7;
.lists-water {
background-image: linear-gradient(to right, $main-color, $main-color);
width: 90rpx;
height: 90rpx;
border-radius: 50%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.list-item {
flex: 1;
margin-left: $margin * 0.7;
font-size: $title-size;
color: $text-gray-m;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin: $margin 0 $margin $margin * 0.7;
.list-item-title {
font-size: $title-size + 3;
color: $text-color;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
box-sizing: border-box;
font-weight: bold;
span {
margin-top: $margin * 0.4;
background-color: #f7f7f7;
padding: 4rpx 10rpx;
border-radius: 50rpx;
font-weight: normal;
font-size: $title-size - 3;
}
}
}
}
}
}
// 水杯动画
.wave-content {
position: relative;
z-index: 1;
.grass {
position: relative;
z-index: 1;
}
.wave {
position: absolute;
width: 290rpx;
height: 500rpx;
background-color: rgba($color: $main-color, $alpha: 0.6);
background-size: 100%;
overflow: hidden;
top: 10rpx;
left: 20rpx;
z-index: 1;
&::before,
&::after {
content: '';
position: absolute;
width: 1000rpx;
height: 1000rpx;
top: var(--ballPercent);
left: 50%;
background-color: rgba(255, 255, 255, 0.4);
border-radius: 45%;
transform: translate(-50%, -70%) rotate(0);
animation: rotate 4s linear infinite;
z-index: 1;
}
&::after {
border-radius: 47%;
background-color: rgba(255, 255, 255, 0.9);
transform: translate(-50%, -70%) rotate(0);
animation: rotate 6s linear -5s infinite;
z-index: 20;
}
}
@keyframes rotate {
50% {
transform: translate(-50%, -73%) rotate(180deg);
}
100% {
transform: translate(-50%, -70%) rotate(360deg);
}
}
}
</style> </style>

View File

@@ -3,450 +3,551 @@
* @Author: Aimee·Zhang * @Author: Aimee·Zhang
* @Date: 2022-01-11 08:54:49 * @Date: 2022-01-11 08:54:49
* @LastEditors: Aimee·Zhang * @LastEditors: Aimee·Zhang
* @LastEditTime: 2022-01-20 10:05:15 * @LastEditTime: 2022-02-08 10:41:15
--> -->
<template> <template>
<view class="record--foods"> <view class="record--foods">
<!-- 饮食进度条 --> <!-- 自定义导航部分 -->
<view class="cricle-content"> <u-navbar :safeAreaInsetTop="true" :fixed='true' bgColor="#34ce98" :autoBack="true">
<view class="info"> <view class="u-nav-slot" slot="left"> <u-icon name="arrow-leftward" :bold="true" size="20" color="#fff" /> </view>
饮食摄入 <view class="u-nav-slot u-center" slot="center" @click="dateShow = true,dateLists()">
<span>{{ calorys.intake_total }}</span> <u-icon name="play-left-fill" size="14" color="#fff" @click="datePreNext('before')" />
</view> <view class="date"> <u-icon name="calendar" color="#fff" label-color="#fff" width="150" :label="today" label-size="14" size="20" /> </view>
<arprogress <u-icon name="play-right-fill" size="14" color="#fff" @click="datePreNext('after')" />
:percent="calorys.exceeds ? 100 : calorys.ratio" </view>
inactiveColor="#f5f4f9" <view class="u-nav-slot" slot="right"> <u-icon :name="require('@/static/icon/sign-icon.gif')" :bold="true" size="30" @click="$Router.push({name:'signIndex'})" /> </view>
:activeColor="calorys.exceeds ? '#f00' : '#34ce98'" </u-navbar>
width="300"
class="cricle"
borderWidth="20"
>
<span>{{ calorys.exceeds ? '多吃了' : '还可以吃' }}</span>
<span :class="['num', calorys.exceeds ? 'num1' : '']">{{ calorys.amount }}</span>
<span>推荐预算{{ calorys.goal }}</span>
</arprogress>
<view class="info" @click="errToast">
运动消耗
<span>{{ calorys.exercise_total }}</span>
</view>
<view class="ic-left">摄入量推荐</view>
<u-icon class="ic-day" name="checkmark-circle" color="#34ce98" size="10" :label="`${calorys.days}天`" labelColor="#34ce98" labelSize="10" space="3" />
</view>
<!-- 饮食记录 --> <!-- 饮食进度条 -->
<template v-if="intakes.length > 0"> <view class="cricle-content">
<view class="foods-add" v-for="(it, index) in intakes" :key="index"> <view class="info"> 饮食摄入 <span>{{ calorys.intake_total }}</span> </view>
<view class="foods-title"> <arprogress :percent="calorys.exceeds ? 100 : calorys.ratio" inactiveColor="#f5f4f9"
<view class="title-left"> :activeColor="calorys.exceeds ? '#c50000' : '#34ce98'" width="300" class="cricle" borderWidth="20">
{{ it.name }} <span>{{ calorys.exceeds ? '多吃了' : '还可以吃' }}</span>
<span v-if="it.remark">{{ it.remark || '' }}</span> <span :class="['num', calorys.exceeds ? 'num1' : '']">{{ calorys.amount }}</span>
</view> <span>推荐预算{{ calorys.goal }}</span>
<view class="title-right"> </arprogress>
{{ it.total }} <view class="info" @click="errToast"> 运动消耗 <span>{{ calorys.exercise_total }}</span> </view>
<span class="dw">千卡</span> <view class="ic-left">摄入量推荐</view>
<u-icon name="arrow-right" color="#ddd" size="13" :bold="true" /> <u-icon class="ic-day" name="checkmark-circle" color="#34ce98" size="10" :label="`${calorys.days}天`" labelColor="#34ce98" labelSize="10" space="3" />
</view> </view>
</view>
<goodsList :lists="it.intake" type="no-dian" @editGoods="editGoods" @longClickGoods="longClickGoods" />
</view>
</template>
<!-- 运动列表 -->
<template v-if="sportsTotal > 0">
<view class="foods-title" style="padding-top:50rpx;">
<view class="title-left">运动</view>
<view class="title-right">
{{ sportsTotal }}
<span class="dw">千卡</span>
<u-icon name="arrow-right" color="#ddd" size="13" :bold="true" />
</view>
</view>
<sports type="edit" :lists="sports" @editSport="editSport" @longClick="longClick" /> <!-- 有饮食记录 -->
</template> <template v-if="intakes.length > 0">
<view class="foods-add" v-for="(it, index) in intakes" :key="index">
<view class="foods-title">
<view class="title-left"> {{ it.name }} <span v-if="it.remark">{{ it.remark || '' }}</span> </view>
<view class="title-right"> {{ it.total }} <span class="dw">千卡</span> <u-icon name="arrow-right" color="#ddd" size="13" :bold="true" /> </view>
</view>
<goodsList :lists="it.intake" type="no-dian" @editGoods="editGoods" @longClickGoods="longClickGoods" />
</view>
</template>
<!-- 没有饮食记录 --> <!-- 运动列表 -->
<view class="no-foods" v-if="sports.length === 0 && intakes.length === 0"> <template v-if="sportsTotal > 0">
<u-image :src="require('../../static/imgs/no-foods.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="300rpx" class="no-foods-img" /> <view class="foods-title" style="padding-top:50rpx;">
<view>还没有添加今日饮食记录</view> <view class="title-left">运动</view>
<view>请点击屏幕下方按钮来添加</view> <view class="title-right"> {{ sportsTotal }} <span class="dw">千卡</span> <u-icon name="arrow-right" color="#ddd" size="13" :bold="true" /> </view>
</view> </view>
<sports type="edit" :lists="sports" @editSport="editSport" @longClick="longClick" />
</template>
<!-- 加餐模块 --> <!-- 没有饮食记录 -->
<u-action-sheet <view class="no-foods" v-if="sports.length === 0 && intakes.length === 0">
:actions="addEatList" <u-image :src="require('../../static/imgs/no-foods.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="300rpx" class="no-foods-img" />
title="加餐模块" <view>还没有添加今日饮食记录</view>
:closeOnClickOverlay="true" <view>请点击屏幕下方按钮来添加</view>
:closeOnClickAction="true" </view>
@select="selectClick"
cancelText="取消"
:show="addEatShow"
@close="addEatShow = false"
></u-action-sheet>
<!-- 底部 早餐等菜单 -->
<u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true" inactiveColor="#333" @click="tabbarClick">
<u-tabbar-item text="+早餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-1.png')" />
<u-tabbar-item text="+午餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-2.png')" />
<u-tabbar-item text="+晚餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-3.png')" />
<u-tabbar-item text="+加餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-4.png')" />
<u-tabbar-item text="+运动" @click="tabbarClick" :icon="require('../../static/imgs/foods-5.png')" />
</u-tabbar>
<!-- 修改食品弹窗 --> <!-- 加餐模块 -->
<!-- 添加食谱弹窗 --> <u-action-sheet :actions="addEatList" title="加餐模块" :closeOnClickOverlay="true" :closeOnClickAction="true" @select="selectClick" cancelText="取消" :show="addEatShow" @close="addEatShow = false" />
<addFoods
v-if="addShow"
:addShow="addShow"
:selectGoods="selectGoods"
:decimals="true"
@confirm="confirmHandle"
@close="closeHandle"
@delThis="delThis"
@tabGoodsInfo="tabGoodsInfo"
max="999"
/>
<!-- 修改运动弹窗 --> <!-- 底部 早餐等菜单 -->
<addPopup :selectSports="selectSports" :addSportsShow="addSportsShow" @comfirmSport="comfirmSport" @cancleSport="cancleSport" @delSport="delSport" /> <u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true" inactiveColor="#333" @click="tabbarClick">
</view> <u-tabbar-item text="+早餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-1.png')" />
<u-tabbar-item text="+午餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-2.png')" />
<u-tabbar-item text="+晚餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-3.png')" />
<u-tabbar-item text="+加餐" @click="tabbarClick" :icon="require('../../static/imgs/foods-4.png')" />
<u-tabbar-item text="+运动" @click="tabbarClick" :icon="require('../../static/imgs/foods-5.png')" />
</u-tabbar>
<!-- 添加食谱弹窗 -->
<addFoods v-if="addShow" :addShow="addShow" :selectGoods="selectGoods" :decimals="true" @confirm="confirmHandle" @close="closeHandle" @delThis="delThis" @tabGoodsInfo="tabGoodsInfo" max="999" />
<!-- 修改运动弹窗 -->
<addPopup :selectSports="selectSports" :addSportsShow="addSportsShow" @comfirmSport="comfirmSport" @cancleSport="cancleSport" @delSport="delSport" />
<!-- 选择日历 -->
<dateTemplate :lists="calendarList" :today="today" :month="month" :dateShow="dateShow" type='foods' @backDate="backDate" @dateClick="dateClick" @closeDate="closeDate" @datePreNext="datePreNext" />
</view>
</template> </template>
<script> <script>
import arprogress from '@/components/ar-circle-progress/index.vue'; import moment from 'moment';
import goodsList from '@/components/foods'; import sports from '@/components/sports';
import { plans, editHealthFoods, delHealthFoods } from '@/apis/interfaces/foods.js'; import goodsList from '@/components/foods';
import moment from 'moment'; import addPopup from '@/components/sports/addPopup';
import addFoods from '@/components/add-goods-template/add-goods-template'; import arprogress from '@/components/ar-circle-progress/index.vue';
import addPopup from '@/components/sports/addPopup'; import addFoods from '@/components/add-goods-template/add-goods-template';
import sports from '@/components/sports'; import dateTemplate from '@/components/date-template/index.vue'
import { editHealthSports, delHealthSports } from '@/apis/interfaces/sport.js'; import {
export default { editHealthSports,
components: { delHealthSports
arprogress, } from '@/apis/interfaces/sport.js';
goodsList, import {
addFoods, plans,
addPopup, editHealthFoods,
sports delHealthFoods,
}, dateList
data() { } from '@/apis/interfaces/foods.js';
return { export default {
lists: [], components: {
addShow: false, // 添加食品显示 arprogress,
selectGoods: [], // 选择新增的食品 goodsList,
addEatShow: false, // 加餐弹窗默认不显示 addFoods,
addEatList: [ addPopup,
{ sports,
name: '上午加餐', dateTemplate
type: 2 },
}, data() {
{ return {
name: '下午加餐', addShow: false, // 添加食品显示
type: 4 selectGoods: [], // 选择新增的食品
}, addEatShow: false, // 加餐弹窗默认不显示
{ addEatList: [{name: '上午加餐',type: 2},{name: '下午加餐',type: 4},{name: '晚上加餐',type: 6}],
name: '晚上加餐', calorys: {}, // 当日食谱推荐页面的信息
type: 6 intakes: [], // 当日摄入列表
} sports: [], // 运动列表
], sportsTotal: 0,
today: moment(new Date()).format('YYYY-MM-DD'), addSportsShow: false, // 添加运动弹窗显示
calorys: {}, // 当日食谱推荐页面的信息 selectSports: {}, // 选择新增的运动
intakes: [], // 当日摄入列表 today: moment(new Date()).format('YYYY-MM-DD'),// 当前时间
sports: [], // 运动列表 month: moment(new Date()).format('YYYY-MM'), //当前月份
sportsTotal: 0, dateShow: false, // 日历展示
addSportsShow: false, // 添加运动弹窗显示 calendarList: [],
selectSports: {} // 选择新增的运动 dateType: '', // before after ''
}; };
}, },
onShow() { onShow() {
this.getList(); this.getList();
}, this.dateLists(); // 日期列表
methods: { },
// 编辑运动 methods: {
editSport(item) { // 获取当前统计页面基本数据
this.selectSports = { getList() {
name: item.sport.name, plans(this.today).then(res => {
calory: item.sport.calory, this.calorys = res.calorys;
cover: item.sport.cover, this.calorys.ratio = Number(this.calorys.ratio);
duration: item.duration, this.intakes = res.intakes;
sport_id: item.sport.sport_id, this.sports = res.exercises.lists;
exercise_id: item.exercise_id, this.sportsTotal = res.exercises.total;
title: '编辑运动' }).catch(err => {
}; uni.showToast({
// console.log(this.selectSports); title: err.message,
console.log('编辑运动', item); icon: "none",
this.addSportsShow = true; duration: 2000,
}, mask: true
})
});
},
// 弹窗确认按钮新增 这里接口报错了 //#region 运动操作相关
comfirmSport(show, duration) { // 编辑运动
let params = { editSport(item) {
unit: '1', // 时间单位:分钟 1 小时 2 this.selectSports = {
duration: duration, // 时常 name: item.sport.name,
exercise_id: this.selectSports.exercise_id, // calory: item.sport.calory,
sport_id: this.selectSports.sport_id, // 运动id cover: item.sport.cover,
date: this.today // 日期 duration: item.duration,
}; sport_id: item.sport.sport_id,
console.log(params); exercise_id: item.exercise_id,
editHealthSports(params).then(res => { title: '编辑运动'
this.addSportsShow = false; };
this.selectSports = {}; this.addSportsShow = true;
this.getList(); },
}).catch(err=>{ // 弹窗确认按钮新增 这里接口报错了
uni.showToast({ comfirmSport(show, duration) {
title:err.message, let params = {
icon:'none' unit: '1', // 时间单位:分钟 1 小时 2
}) duration: duration, // 时常
}); exercise_id: this.selectSports.exercise_id, //
}, sport_id: this.selectSports.sport_id, // 运动id
date: this.today // 日期
};
editHealthSports(params).then(res => {
this.addSportsShow = false;
this.selectSports = {};
this.getList();
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
},
// 弹窗取消按钮
cancleSport(show) {
this.addSportsShow = show;
},
// 删除运动
delSport() {
let params = {
exercise_id: this.selectSports.exercise_id //
};
delHealthSports(params).then(res => {
this.addSportsShow = false;
this.selectSports = {};
this.getList();
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
},
// 长按删除触发事件运动
longClick(item) {
this.selectSports = item;
uni.showModal({
content: '确认删除么?',
confirmText: '确认删除',
confirmColor: '#34ce98',
cancelText: '再想想',
cancelColor: '#ddd',
success: res => {
if (res.confirm) {
this.delSport();
}
}
});
},
//#endregion 运动操作相关
// 弹窗取消按钮
cancleSport(show) { //#region 食物操作相关
this.addSportsShow = show; // 长按删除食品
}, longClickGoods(e) {
// 删除运动 this.selectGoods = [e];
delSport() { uni.showModal({
let params = { content: '确认删除么?',
exercise_id: this.selectSports.exercise_id // confirmText: '确认删除',
}; confirmColor: '#34ce98',
console.log(params); cancelText: '再想想',
delHealthSports(params).then(res => { cancelColor: '#ddd',
this.addSportsShow = false; success: res => {
this.selectSports = {}; if (res.confirm) {
this.getList(); this.delThis();
}); }
}, }
// 长按删除触发事件运动 });
longClick(item) { },
this.selectSports = item; // 错误提示
uni.showModal({ errToast() {
content: '确认删除么?', uni.showToast({
confirmText: '确认删除', title: '努力开发中~',
confirmColor: '#34ce98', icon: 'none'
cancelText: '再想想', });
cancelColor: '#ddd', },
success: res => { // 底部按钮点击触发的事件 早餐1 午餐3 晚餐5 加餐(早2中4晚6)
if (res.confirm) { tabbarClick(e) {
this.delSport(); this.tabarIndex = e;
} if (e === 3) {
} this.addEatShow = true;
}); } else {
}, if (e === 4) {
// 长按删除食品 // 新增运动
longClickGoods(e) { uni.navigateTo({
this.selectGoods = [e]; url: `/pages/record/addExercises`
uni.showModal({ });
content: '确认删除么?', } else {
confirmText: '确认删除', uni.navigateTo({
confirmColor: '#34ce98', url: `/pages/record/addFoods?type=${e === 0 ? 1 : e === 1 ? 3 : 5}&date=${this.today}`
cancelText: '再想想', });
cancelColor: '#ddd', }
success: res => { }
if (res.confirm) { },
this.delThis(); // 选择了加餐跳转
} selectClick(e) {
} uni.navigateTo({
}); url: `/pages/record/addFoods?type=${e.type}&date=${this.today}`
}, });
// 错误提示 // 选择加餐
errToast() { },
uni.showToast({ // 编辑食品
title: '努力开发中~', editGoods(e) {
icon: 'none' this.selectGoods = [e];
}); this.addShow = true;
}, },
getList() { closeHandle() {
plans(this.today).then(res => { //键盘关闭的回调函数
this.calorys = res.calorys; this.addShow = false;
this.calorys.ratio = Number(this.calorys.ratio); },
this.intakes = res.intakes; // 监听点击键盘触发返回值新增食品
this.sports = res.exercises.lists; confirmHandle(value) {
this.sportsTotal = res.exercises.total; // 新添加食物
}); let data = {
}, ser: 1,
// 底部按钮点击触发的事件 早餐1 午餐3 晚餐5 加餐(早2中4晚6) weight: value,
tabbarClick(e) { food_id: this.selectGoods[0].food_id,
console.log(e); intake_id: this.selectGoods[0].intake_id
this.tabarIndex = e; };
if (e === 3) { this.editHealthFoods(data);
this.addEatShow = true; },
} else { // 添加食物
if (e === 4) { editHealthFoods(data) {
// 新增运动 editHealthFoods(data).then(res => {
uni.navigateTo({ this.addShow = false;
url: `/pages/record/addExercises` this.getList();
}); }).catch(err => {
} else { uni.showToast({
uni.navigateTo({ title: err.message,
url: `/pages/record/addFoods?type=${e === 0 ? 1 : e === 1 ? 3 : 5}` icon: "none",
}); duration: 2000,
} mask: true
} })
}, });
// 选择了加餐跳转 },
selectClick(e) { // 删除该食物
uni.navigateTo({ delThis(e) {
url: `/pages/record/addFoods?type=${e.type}` delHealthFoods(this.selectGoods[0].intake_id).then(res => {
}); this.addShow = false;
// 选择加餐 this.getList();
}, }).catch(err => {
// 编辑食品 uni.showToast({
editGoods(e) { title: err.message,
this.selectGoods = [e]; icon: "none",
this.addShow = true; duration: 2000,
}, mask: true
closeHandle() { })
//键盘关闭的回调函数 });
this.addShow = false; },
}, // 跳转到食品详情
// 监听点击键盘触发返回值新增食品 tabGoodsInfo(e) {
confirmHandle(value) { this.$Router.push({
// 新添加食物 name: 'rankingDetails',
let data = { params: e
ser: 1, });
weight: value, },
food_id: this.selectGoods[0].food_id, //#endregion 食物操作相关
intake_id: this.selectGoods[0].intake_id
}; //#region 日历操作相关
this.editHealthFoods(data); // 日历列表
}, dateLists() {
// 添加食物 let data = {
editHealthFoods(data) { month: this.month,
editHealthFoods(data).then(res => { type: this.dateType
console.log(res); }
this.addShow = false; dateList(data).then(res => {
this.getList(); this.calendarList = res.calendar
}); this.dateType = ''
}, this.month = res.month
// 删除该食物 }).catch(err => {
delThis(e) { uni.showToast({
delHealthFoods(this.selectGoods[0].intake_id).then(res => { title: err.message,
this.addShow = false; icon: "none",
this.getList(); duration: 2000,
}); mask: true
}, })
// 跳转到食品详情 })
tabGoodsInfo(e) { },
this.$Router.push({ // 选择日期
name: 'rankingDetails', dateClick(item) {
params: e this.today = item.today
}); this.month = item.today
} this.reset()
} },
}; // 返回到今日
backDate() {
this.today = moment(new Date()).format('YYYY-MM-DD')
this.reset()
},
// 上一个月或者下一个月
datePreNext(type) {
this.dateType = type
this.dateLists()
},
// 关闭日历
closeDate() {
this.month = this.today
this.dateShow = false
},
// 重置日历数据
reset() {
this.calendarList = []
this.dateLists()
this.getList()
this.closeDate()
}
//#endregion 日历操作相关
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.record--foods { .record--foods {
padding: $padding $padding $padding * 7 $padding; padding: $padding $padding $padding * 7 $padding;
// background: green; // background: green;
} }
// 饮食进度条
.cricle-content { // 顶部日历筛选部分
box-shadow: 0 0 4rpx 4rpx rgba($color: $main-color, $alpha: 0.1); .u-center {
font-size: $title-size-m - 6; display: flex;
padding: $padding * 1.8 $padding; flex-direction: row;
border-radius: $radius; align-items: center;
color: $text-gray-m; justify-content: center;
display: flex; box-sizing: border-box;
flex-direction: row;
align-items: center; .date {
justify-content: space-around; background-color: rgba($color: #000000, $alpha: .1);
box-sizing: border-box; color: #fff;
position: relative; min-width: 340rpx;
.cricle { display: flex;
.num { flex-direction: row;
color: $text-color; align-items: center;
font-size: $title-size * 1.8; justify-content: center;
font-weight: bold; box-sizing: border-box;
padding: $padding * 0.2; padding: 8rpx 20rpx;
} border-radius: $radius * 2;
.num1 { margin: 0 10rpx;
color: #f00; font-size: $title-size - 2;
} }
}
.info { .play-right-fill {
display: flex; padding: $padding !important;
flex-direction: column; background-color: pink;
align-items: center; }
justify-content: center; }
box-sizing: border-box;
span {
font-size: $title-size + 10; // 饮食进度条
font-weight: bold; .cricle-content {
color: $text-color; box-shadow: 0 0 4rpx 4rpx rgba($color: $main-color, $alpha: 0.1);
padding-top: $padding * 0.5; font-size: $title-size-m - 6;
} padding: $padding * 1.8 $padding;
} border-radius: $radius;
.ic-left { color: $text-gray-m;
position: absolute; display: flex;
left: 0; flex-direction: row;
top: 0; align-items: center;
background-image: linear-gradient(to right, #ffebb9, #fbd57b); justify-content: space-around;
color: #664710; box-sizing: border-box;
padding: 10rpx $padding * 0.6; position: relative;
border-radius: 0 0 $radius 0; margin-top: $margin * 5;
}
.ic-day { .cricle {
position: absolute; .num {
right: $padding; color: $text-color;
top: $padding; font-size: $title-size * 1.8;
} font-weight: bold;
} padding: $padding * 0.2;
// 没有饮食记录 }
.no-foods {
display: flex; .num1 {
flex-direction: column; color: #f00;
align-items: center; }
justify-content: center; }
box-sizing: border-box;
font-size: $title-size-m - 4; .info {
color: $text-gray-m; display: flex;
min-height: 40vh; flex-direction: column;
// background: pink; align-items: center;
.no-foods-img { justify-content: center;
opacity: 0.5; box-sizing: border-box;
}
view { span {
padding: $padding * 0.2; font-size: $title-size + 10;
} font-weight: bold;
} color: $text-color;
// 饮食记录 早中晚加餐等 padding-top: $padding * 0.5;
.foods-add { }
border-bottom: solid 1rpx #f7f7f7; }
margin-top: $margin;
} .ic-left {
// 主标题 position: absolute;
.foods-title { left: 0;
display: flex; top: 0;
flex-direction: row; background-image: linear-gradient(to right, #ffebb9, #fbd57b);
align-items: center; color: #664710;
justify-content: space-between; padding: 10rpx $padding * 0.6;
box-sizing: border-box; border-radius: 0 0 $radius 0;
color: $text-color; }
padding: $padding * 0.5 0;
.title-left { .ic-day {
font-size: $title-size; position: absolute;
color: $text-color; right: $padding;
font-weight: bold; top: $padding;
span { }
font-weight: normal; }
font-size: $title-size-m - 6;
color: $text-gray-m; // 没有饮食记录
margin-left: $margin - 10; .no-foods {
} display: flex;
} flex-direction: column;
.title-right { align-items: center;
font-size: $title-size-m - 6; justify-content: center;
display: flex; box-sizing: border-box;
flex-direction: row; font-size: $title-size-m - 4;
align-items: center; color: $text-gray-m;
justify-content: center; min-height: 40vh;
box-sizing: border-box;
color: $main-color; // background: pink;
.dw { .no-foods-img {
margin: 0 $margin * 0.6 0 $margin * 0.4; opacity: 0.5;
color: $text-gray; }
}
} view {
} padding: $padding * 0.2;
}
}
// 饮食记录 早中晚加餐等
.foods-add {
border-bottom: solid 1rpx #f7f7f7;
margin-top: $margin;
}
// 主标题
.foods-title {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
color: $text-color;
padding: $padding * 0.5 0;
.title-left {
font-size: $title-size;
color: $text-color;
font-weight: bold;
span {
font-weight: normal;
font-size: $title-size-m;
color: $text-gray-m;
margin-left: $margin - 10;
}
}
.title-right {
font-size: $title-size-m;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
color: $main-color;
.dw {
margin: 0 $margin * 0.6 0 $margin * 0.4;
color: $text-gray;
}
}
}
</style> </style>

View File

@@ -398,9 +398,6 @@ export default {
*/ */
logs() { logs() {
logs().then(res => { logs().then(res => {
console.log(res.is_login)
this.weight = res.weight; this.weight = res.weight;
this.water = res.water; this.water = res.water;
this.intake_run = res.intake_run; this.intake_run = res.intake_run;
@@ -410,7 +407,14 @@ export default {
this.banner = res.banner; this.banner = res.banner;
this.user = res.user; this.user = res.user;
this.notifications_count = res.notifications_count; this.notifications_count = res.notifications_count;
}); }).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
});
}, },
/** /**
* @description:跳转登录页面 * @description:跳转登录页面

View File

@@ -8,231 +8,303 @@
<template> <template>
<view class="weight"> <view class="weight">
<!-- 体重表 --> <!-- 进度模块 -->
<view class="progress-top"> <block v-if="tabbarId === 0">
<view class="unit"> <!-- 体重表 -->
<span <view class="progress-top">
:class="isJin === 2?'active':''" <view class="unit"> <span :class="isJin === 2?'active':''" @click="isJin = 1"></span> <span :class="isJin === 1?'active':''" @click="isJin = 1">公斤</span> </view>
@click="isJin = 1" <view class="progress">
></span> <view>{{weightInfo.text}}</view>
<span <u-count-to class="uCountTo" :startVal="0" :endVal="weightInfo.change" :decimals="1" color="#333" fontSize="36" :bold="true" />
:class="isJin === 1?'active':''" <view>保持 / 塑性</view>
@click="isJin = 1"
>公斤</span>
</view>
<view class="progress">
<view>{{weightInfo.text}}</view>
<u-count-to
class="uCountTo"
:startVal="0"
:endVal="weightInfo.change"
:decimals="1"
color="#333"
fontSize="36"
:bold="true"
/>
<view>保持 / 塑性</view>
</view>
<view
class="add-weight"
@click="addWeightShow = true"
>记录体重</view>
<view class="des-title">以最后一次记录为主且每日只能更新一次</view>
</view>
<!-- 体重列表 -->
<view
class="weight-list"
v-if="lists.length>0"
>
<view
class="list-item"
v-for="item in lists"
:key="item.wight_id"
>
<view class="list-left">
<view class="list-title">
<span>{{item.weight}}</span>公斤
</view>
测量结果
</view> </view>
<view class="list-right"> <view class="add-weight" @click="addWeightShow = true">记录体重</view>
<span>开始保持 / 塑性</span> <view class="des-title">以最后一次记录为主且每日只能更新一次</view>
{{item.created_at}} </view>
<!-- 体重列表 -->
<view class="weight-list" v-if="lists.length>0">
<view class="list-item">
<view class="list-left"> <view class="list-title"> <span>{{weightInfo.begin}}</span>公斤 </view> 初始体重 </view>
<view class="list-right"> <span>开始保持 / 塑性</span> {{weightInfo.first_weight_time}} </view>
</view>
<view class="list-item" v-for="item in lists" :key="item.wight_id">
<view class="list-left"> <view class="list-title"> <span>{{item.weight}}</span>公斤 </view> 测量结果 </view>
<view class="list-right"> <span>开始保持 / 塑性</span> {{item.created_at}} </view>
</view> </view>
</view> </view>
<view class="no-lists" v-else>还没有体重信息记录下呗~</view>
</block>
<!-- 曲线模块 -->
<view v-if="tabbarId === 1">
<!-- 健康测评 -->
<u-image v-if="chartData.categories.length>0" :src="require('@/static/imgs/health1.png')" class="eval-img" @click="$Router.push({ name: 'EvaluationList' })" :lazy-load="true" radius="10rpx" mode="widthFix" width="100%" />
<view class="curve" v-if="chartData.categories.length>0">
<view class="title"> 体重 <span>单位公斤</span> </view>
<u-icon @click="addWeightShow = true" name="edit-pen-fill" color="#34ce98" size="20" :bold="true" label="更新" labelPos="right" labelSize="13" labelColor="#999" space="4" />
</view>
<view class="charts-box" v-if="chartData.categories.length>0"> <qiun-data-charts type="area" :chartData="chartData" background="none" /> </view>
<view class="progress-top">
<view class="add-weight" @click="addWeightShow = true">记录体重</view>
<view class="des-title">只显示最近七次测量记录</view>
</view>
</view> </view>
<view
class="no-lists"
v-else
>还没有体重信息记录下呗~</view>
<!-- 记录体重弹窗 --> <!-- 记录体重弹窗 -->
<u-popup <u-popup :show="addWeightShow" :round="10" @close="addWeightShow = false" :closeable="true">
:show="addWeightShow"
:round="10"
@close="addWeightShow = false"
:closeable="true"
>
<view class="addWeightContent"> <view class="addWeightContent">
<view class="date">今天</view> <view class="date">今天</view>
<view class='count'><span>{{weight}}</span>公斤</view> <view class='count'><span>{{weight}}</span>公斤</view>
<vue-scale <vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scroll" :scrollLeft="Number(weight)" />
:min="10" <view class="addBtn" @click="addWeight">确认添加</view>
:max="100"
:int="false"
:single="10"
:h="80"
:styles="styles"
@scroll="scroll"
:scrollLeft="Number(weight)"
/>
<view
class="addBtn"
@click="addWeight"
>确认添加</view>
</view> </view>
</u-popup> </u-popup>
<!-- 底部 进度 曲线菜单 -->
<u-tabbar :value="tabbarId" :fixed="true" :placeholder="false" :safeAreaInsetBottom="false" activeColor="#34ce98">
<u-tabbar-item text="进度" :icon="tabbarId === 0 ?require('../../static/imgs/speed-2.png'):require('../../static/imgs/speed-1.png')" @click="tabbarClick" />
<u-tabbar-item text="曲线" :icon="tabbarId === 1 ?require('../../static/imgs/curve-2.png'):require('../../static/imgs/curve-1.png')" @click="tabbarClick" />
</u-tabbar>
</view> </view>
</template> </template>
<script> <script>
import vueScale from "@/components/vueScale"; import vueScale from "@/components/vueScale";
import { weights, addWeight } from "@/apis/interfaces/weight.js"; import {
import moment from "moment"; weights,
import l from "../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"; addWeight,
export default { curves
components: { } from "@/apis/interfaces/weight.js";
vueScale, import moment from "moment";
}, import l from "../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center";
data() { export default {
return { components: {
isJin: 1, // 是公斤 2 是斤 所有用到斤的直接乘以这个字段即可 vueScale,
addWeightShow: false, // 是否添加体重展示
styles: {
line: "#dbdbdb",
bginner: "#fbfbfb",
bgoutside: "#ffffff",
font: "#404040",
fontColor: "#404040",
fontSize: 16,
},
weight: "",
date: "",
weightInfo: {},
lists: [],
has_more: true,
page: 1,
};
},
onShow() {
this.getWeights();
this.date = moment(new Date()).format("YYYY-MM-DD");
},
onReachBottom() {
if (!this.has_more) {
uni.showToast({
title: "没有更多啦~",
icon: "none",
});
} else {
this.page = this.page + 1;
this.getWeights();
}
},
methods: {
//获取体重首页接口
getWeights() {
weights(this.page).then((res) => {
if(res.lists.page.current === 1) {
this.lists = []
}
this.lists = this.lists.concat(res.lists.data);
this.has_more = res.lists.page.has_more;
this.weightInfo = res.weight;
this.weight = res.weight.now;
});
}, },
addWeight() { data() {
let data = { return {
weight: this.weight, isJin: 1, // 是公斤 2 是斤 所有用到斤的直接乘以这个字段即可
date: this.date, addWeightShow: false, // 是否添加体重展示
styles: {
line: "#dbdbdb",
bginner: "#fbfbfb",
bgoutside: "#ffffff",
font: "#404040",
fontColor: "#404040",
fontSize: 16,
},
weight: "",
date: "",
weightInfo: {},
lists: [],
has_more: true,
page: 1,
tabbarId: 0,
chartData: {
// "categories": ["1/1","1/2","1/3","1/4","1/5","1/6","1/7"],
// "series": [{"name": "最近七天进度","data": [55,51,53.3,50.3,53.3]}]
categories:[],
series:[{name: "",data: []}]
}, // 曲线部分 start
}; };
addWeight(data).then((res) => { },
this.addWeightShow = false; onShow() {
this.page = 1; this.getWeights();
this.has_more = true; this.getCurves();
this.lists = []; this.date = moment(new Date()).format("YYYY-MM-DD");
},
onReachBottom() {
if (!this.has_more) {
uni.showToast({
title: "没有更多啦~",
icon: "none",
duration: 1000,
mask: true
});
} else {
this.page = this.page + 1;
this.getWeights(); this.getWeights();
}); }
}, },
// 滚动标尺触发事件
scroll(msg) { methods: {
this.weight = msg; //获取体重首页接口
getWeights() {
weights(this.page).then((res) => {
if (res.lists.page.current === 1) {
this.lists = []
}
this.lists = this.lists.concat(res.lists.data);
this.has_more = res.lists.page.has_more;
this.weightInfo = res.weight;
this.weight = res.weight.now;
}).catch(err=>{
uni.showToast({
title:err.message,
icon:"none",
mask:true,
duration:2000
})
});
},
// 获取曲线
getCurves() {
curves().then((res) => {
this.chartData={
categories:res.categories,
"series": [res.series]
}
}).catch(err=>{
uni.showToast({
title:err.message,
icon:"none",
mask:true,
duration:2000
})
});
},
// 更新体重
addWeight() {
let data = {
weight: this.weight,
date: this.date
};
addWeight(data).then((res) => {
this.addWeightShow = false;
this.page = 1;
this.has_more = true;
this.lists = [];
this.getWeights();
this.getCurves();
}).catch(err=>{
uni.showToast({
title:err.message,
icon:"none",
mask:true,
duration:2000
})
});
},
// 滚动标尺触发事件
scroll(msg) {
this.weight = msg;
},
// 点击底部切换
tabbarClick(e) {
this.tabbarId = Number(e)
}
}, },
}, };
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
//体重top .charts-box{
.progress-top { width: 100%;
padding: $padding * 2 $padding; height:500rpx;
display: flex; margin-top: $margin;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-bottom: solid 1rpx #f7f7f7;
// 单位
.unit {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
width: 100%;
span {
display: inline-block;
width: 100rpx;
font-size: $title-size-m;
color: $border-color;
padding: $padding * 0.5 0;
text-align: center;
border: solid 1rpx $border-color;
border-radius: 50rpx 0 0 50rpx;
}
span:nth-child(1) {
border-radius: 50rpx 0 0 50rpx;
border-style: solid;
border-color: $border-color $main-color $border-color $border-color;
}
span:nth-child(2) {
border-radius: 0 50rpx 50rpx 0;
border-style: solid;
border-color: $border-color $border-color $border-color $main-color;
}
span.active {
background-color: $main-color;
color: #fff;
border: solid 1rpx $main-color;
}
} }
.no-weight{
// 展示圈
.progress {
width: 360rpx;
height: 360rpx;
border: solid $padding * 0.7 #f7f7f7;
border-radius: 50%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-sizing: border-box; box-sizing: border-box;
color: $text-gray-m; color: #999;
font-size: $title-size-m; font-size: $title-size-m;
.uCountTo { }
padding: $padding * 0.5; // curve
.curve{
margin-top: $margin;
padding: $padding $padding + 10;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
font-size: $title-size + 5;
color: #333;
span{
color: #cacaca;
font-size: $title-size-m;
margin-left: 10rpx;
} }
} }
// 记录按钮 // 评测图片
.eval-img {
box-shadow: 0 0 10rpx 4rpx rgba($color: $main-color, $alpha: 0.1);
}
//体重top
.progress-top {
padding: $padding * 2 $padding;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-bottom: solid 1rpx #f7f7f7;
// 单位
.unit {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
width: 100%;
span {
display: inline-block;
width: 100rpx;
font-size: $title-size-m;
color: $border-color;
padding: $padding * 0.5 0;
text-align: center;
border: solid 1rpx $border-color;
border-radius: 50rpx 0 0 50rpx;
}
span:nth-child(1) {
border-radius: 50rpx 0 0 50rpx;
border-style: solid;
border-color: $border-color $main-color $border-color $border-color;
}
span:nth-child(2) {
border-radius: 0 50rpx 50rpx 0;
border-style: solid;
border-color: $border-color $border-color $border-color $main-color;
}
span.active {
background-color: $main-color;
color: #fff;
border: solid 1rpx $main-color;
}
}
// 展示圈
.progress {
width: 360rpx;
height: 360rpx;
border: solid $padding * 0.7 #f7f7f7;
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
color: $text-gray-m;
font-size: $title-size-m;
.uCountTo {
padding: $padding * 0.5;
}
}
// 记录按钮
.add-weight { .add-weight {
font-size: $title-size + 2; font-size: $title-size + 2;
border-radius: $radius * 3; border-radius: $radius * 3;
@@ -242,92 +314,106 @@ export default {
margin-top: $margin * 2; margin-top: $margin * 2;
font-weight: bold; font-weight: bold;
} }
.des-title { .des-title {
padding: $padding;
color: $text-gray-m;
font-size: $title-size-m - 4;
}
}
// 列表
.weight-list {
font-size: $title-size-m;
color: #cacaca;
padding: 0 $padding;
.list-item {
display: flex;
flex-direction: row;
align-items: center;
box-sizing: border-box;
justify-content: space-between;
border-bottom: solid 1rpx #f9f9f9;
padding: 20rpx 0;
font-size: $title-size-m - 2;
.list-title {
color: #555;
font-size: $title-size-m - 2;
span {
font-size: $title-size + 10;
font-weight: 500;
margin-right: 10rpx;
}
}
.list-right {
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: center;
box-sizing: border-box;
margin-top: $margin * 0.4;
color: #999;
span {
margin-bottom: 10rpx;
}
}
}
}
.no-lists {
padding: $padding; padding: $padding;
color: $text-gray-m; color: $text-gray-m;
font-size: $title-size-m - 4; font-size: $title-size-m;
} }
}
// 列表
.weight-list {
font-size: $title-size-m;
color: $text-gray-m;
padding: $padding;
.list-item { // 弹窗
display: flex; .addWeightContent {
flex-direction: row; width: 100%;
align-items: center; height: 54vh;
padding: $padding * 4 0;
box-sizing: border-box;
color: $text-gray;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box; box-sizing: border-box;
justify-content: space-between;
border-bottom: solid 1rpx #f9f9f9;
padding: $padding 0;
.list-title {
color: $text-color;
font-size: $title-size-m;
margin-bottom: $margin * 0.4;
span {
font-size: $title-size + 14;
font-weight: 500;
margin-right: 10rpx;
}
}
.list-right {
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: center;
box-sizing: border-box;
margin-top: $margin * 0.4;
span {
margin-bottom: 10rpx;
}
}
}
}
.no-lists {
padding: $padding;
color: $text-gray-m;
font-size: $title-size-m;
}
// 弹窗 .date {
.addWeightContent { font-size: $title-size + 9;
width: 100%; text-align: center;
height: 54vh; }
padding: $padding * 4 0;
box-sizing: border-box; .count {
color: $text-gray; color: $main-color;
display: flex; text-align: center;
flex-direction: column; margin-top: $margin * 2;
align-items: center; margin-bottom: $margin * 0.1;
justify-content: center; font-size: $title-size + 2;
box-sizing: border-box;
.date { span {
font-size: $title-size + 9; font-weight: bold;
text-align: center; font-size: $title-size * 2.2;
} margin-right: $margin * 0.3;
.count { }
color: $main-color; }
text-align: center;
margin-top: $margin * 2; .addBtn {
margin-bottom: $margin * 0.1; background-color: $main-color;
font-size: $title-size + 2; color: #fff;
span { margin-top: $margin * 2;
font-weight: bold; font-size: $title-size * 1.2;
font-size: $title-size * 2.2; padding: $padding * 0.7 $padding * 4;
margin-right: $margin * 0.3; border-radius: $radius * 3;
font-size: $title-size + 6;
box-shadow: 0 0 10rpx 4rpx rgba($color: $main-color, $alpha: 0.1);
} }
} }
.addBtn {
background-color: $main-color;
color: #fff;
margin-top: $margin * 2;
font-size: $title-size * 1.2;
padding: $padding * 0.7 $padding * 4;
border-radius: $radius * 3;
font-size: $title-size + 6;
box-shadow: 0 0 10rpx 4rpx rgba($color: $main-color, $alpha: 0.1);
}
}
</style> </style>

View File

@@ -3,18 +3,14 @@
<!-- 更多管理 --> <!-- 更多管理 -->
<view class="list"> <view class="list">
<view class="list-item" @click="updImgs"> <view class="list-item" @click="updImgs">
<view class="list-item-left"> <view class="list-item-left"> <span>修改头像</span> </view>
<span>修改头像</span>
</view>
<view class="avatar" > <view class="avatar" >
<image :src="avatar.showPath || require('@/static/user/cover.png')" mode="aspectFill" /> <image :src="avatar.showPath || require('@/static/user/cover.png')" mode="aspectFill" />
<u-icon name="arrow-right" color="#999" size="20"></u-icon> <u-icon name="arrow-right" color="#999" size="20"></u-icon>
</view> </view>
</view> </view>
<view class="list-item"> <view class="list-item">
<view class="list-item-left"> <view class="list-item-left"> <span>修改昵称</span> </view>
<span>修改昵称</span>
</view>
<view class="input"> <view class="input">
<input type="text" :value="nickname" @blur='blur' placeholder="请输入用户的昵称" maxlength="12" /> <input type="text" :value="nickname" @blur='blur' placeholder="请输入用户的昵称" maxlength="12" />
<u-icon name="arrow-right" color="#999" size="20"></u-icon> <u-icon name="arrow-right" color="#999" size="20"></u-icon>
@@ -86,11 +82,13 @@
this.avatar.showPath = pathRes.url[0] this.avatar.showPath = pathRes.url[0]
this.resetUserInfo('avatar',pathRes.url[0]) this.resetUserInfo('avatar',pathRes.url[0])
}).catch(err => { }).catch(err => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon: 'none' icon: "none",
}) duration: 2000,
}) mask: true
})
})
} }
}) })
}, },
@@ -114,11 +112,13 @@
}) })
this.getUserInfo() this.getUserInfo()
}).catch(err => { }).catch(err => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon: 'none' icon: "none",
}) duration: 2000,
}) mask: true
})
})
} }
} }
} }

View File

@@ -1,282 +1,316 @@
<template> <template>
<view class="content"> <view class="content">
<!-- 性别start --> <!-- 性别start -->
<view class="files" @click="sexShow = true"> <view class="files" @click="sexShow = true">
<view class="name">性别</view> <view class="name">性别</view>
<view class="text"> <view class="text">
<u-icon <u-icon class="target-icon" :label="recordsData.sex == 1 ? '男士' : '女士'" name="arrow-right" color="#999"
class="target-icon" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" />
:label="recordsData.sex == 1 ? '男士' : '女士'" </view>
name="arrow-right" </view>
color="#999" <u-action-sheet :actions="sexList" title="你的性别是?" :show="sexShow" cancelText="暂不修改"
size="14" @select=" e => { (this.recordsData.sex = e.id), (this.sexShow = false); } " @close="sexShow = false" />
labelSize="14" <!-- 性别 end -->
labelColor="#666"
labelPos="left"
space="10"
/>
</view>
</view>
<u-action-sheet
:actions="sexList"
title="你的性别是?"
:show="sexShow"
cancelText="暂不修改"
@select=" e => { (this.recordsData.sex = e.id), (this.sexShow = false); } "
@close="sexShow = false"
/>
<!-- 性别 end -->
<!-- 生日 start --> <!-- 生日 start -->
<view class="files" @click="birthdayShow = true"> <view class="files" @click="birthdayShow = true">
<view class="name">生日</view> <view class="name">生日</view>
<view class="text"> <view class="text">
<u-icon class="target-icon" :label="showBirthday" name="arrow-right" color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" /> <u-icon class="target-icon" :label="showBirthday" name="arrow-right" color="#999" size="14"
</view> labelSize="14" labelColor="#666" labelPos="left" space="10" />
</view> </view>
<u-datetime-picker </view>
confirmColor="#34ce98" <u-datetime-picker confirmColor="#34ce98" v-model="recordsData.birthday" mode="date" :show="birthdayShow"
v-model="recordsData.birthday" :formatter="formatter" :minDate="-302688000" :maxDate="maxDate"
mode="date" @confirm=" e => { this.recordsData.birthday = e.value, this.birthdayShow = false } "
:show="birthdayShow" @cancel=" () => { this.birthdayShow = false; } " />
:formatter="formatter" <!-- 生日 end -->
:minDate="-302688000"
:maxDate="maxDate"
@confirm=" e => { this.recordsData.birthday = e.value, this.birthdayShow = false } "
@cancel=" () => { this.birthdayShow = false; } "
/>
<!-- 生日 end -->
<!-- 身高 start--> <!-- 身高 start-->
<view class="files" @click="heightShow = true"> <view class="files" @click="heightShow = true">
<view class="name">身高</view> <view class="name">身高</view>
<view class="text"> <view class="text">
<u-icon class="target-icon" :label="recordsData.height + ` CM`" name="arrow-right" color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" /> <u-icon class="target-icon" :label="recordsData.height + ` CM`" name="arrow-right" color="#999"
</view> size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" />
</view> </view>
<u-popup :show="heightShow" @close="() => { heightShow = false }"> </view>
<view class="v-scale"> <u-popup :show="heightShow" @close="() => { heightShow = false }">
<view class="title"> 你的身高为?</view> <view class="v-scale">
<view class="total"> {{recordsData.height}} CM </view> <view class="title"> 你的身高为?</view>
<vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollAll('height',$event)" :scrollLeft="Number(recordsData.height)" /> <view class="total"> {{recordsData.height}} CM </view>
</view> <vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles"
</u-popup> @scroll="scrollAll('height',$event)" :scrollLeft="Number(recordsData.height)" />
<!-- 身高 end --> </view>
</u-popup>
<!-- 身高 end -->
<!-- 最新体重 start --> <!-- 最新体重 start -->
<view class="files bt30" @click="weightShow = true"> <view class="files bt30" @click="weightShow = true">
<view class="name">最新体重</view> <view class="name">最新体重</view>
<view class="text"> <view class="text">
<u-icon class="target-icon" :label="recordsData.weight + ` KG`" name="arrow-right" color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" /> <u-icon class="target-icon" :label="recordsData.weight + ` KG`" name="arrow-right" color="#999"
</view> size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" />
</view> </view>
<u-popup :show="weightShow" @close="() => { weightShow = false }"> </view>
<view class="v-scale"> <u-popup :show="weightShow" @close="() => { weightShow = false }">
<view class="title"> 你的当前体重为?</view> <view class="v-scale">
<view class="total"> {{recordsData.weight}} KG </view> <view class="title"> 你的当前体重为?</view>
<vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollAll('weight',$event)" :scrollLeft="Number(recordsData.weight)" /> <view class="total"> {{recordsData.weight}} KG </view>
</view> <vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles"
</u-popup> @scroll="scrollAll('weight',$event)" :scrollLeft="Number(recordsData.weight)" />
<!-- 生日 end --> </view>
</u-popup>
<!-- 生日 end -->
<!-- 目标 start --> <!-- 目标 start -->
<view class="files" @click="targetShow = true"> <view class="files" @click="targetShow = true">
<view class="name">目标</view> <view class="name">目标</view>
<view class="text"> <view class="text">
<u-icon class="target-icon" :label="targetList[selectedTargetIndex].name" name="arrow-right" color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" /> <u-icon class="target-icon" :label="targetList[selectedTargetIndex].name" name="arrow-right"
</view> color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" />
</view> </view>
<u-action-sheet </view>
:actions="targetList" <u-action-sheet :actions="targetList" title="你的目标是?" :show="targetShow" cancelText="暂不修改"
title="你的目标是?" @select=" e => { (this.selectedTargetIndex = this.targetList.findIndex(item => e.id === item.id)), (this.targetShow = false); } "
:show="targetShow" @close="targetShow = false" />
cancelText="暂不修改" <!-- 目标 end -->
@select=" e => { (this.selectedTargetIndex = this.targetList.findIndex(item => e.id === item.id)), (this.targetShow = false); } "
@close="targetShow = false"
/>
<!-- 目标 end -->
<!-- 目标体重 start--> <!-- 目标体重 start-->
<view class="files" @click="targetWeightShow = true"> <view class="files" @click="targetWeightShow = true">
<view class="name">目标体重</view> <view class="name">目标体重</view>
<view class="text"><u-icon class="target-icon" :label="recordsData.goal_weight + ` KG`" name="arrow-right" color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" /></view> <view class="text">
</view> <u-icon class="target-icon" :label="recordsData.goal_weight + ` KG`" name="arrow-right" color="#999"
<u-popup :show="targetWeightShow" @close="() => { targetWeightShow = false }"> size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" />
<view class="v-scale"> </view>
<view class="title"> 你的目标体重为?</view> </view>
<view class="total"> {{recordsData.goal_weight}} KG </view> <u-popup :show="targetWeightShow" @close="() => { targetWeightShow = false }">
<vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles" @scroll="scrollAll('goalweight',$event)" :scrollLeft="Number(recordsData.goal_weight)" /> <view class="v-scale">
</view> <view class="title"> 你的目标体重为?</view>
</u-popup> <view class="total"> {{recordsData.goal_weight}} KG </view>
<!-- 目标体重 end --> <vue-scale :min="10" :max="100" :int="false" :single="10" :h="80" :styles="styles"
@scroll="scrollAll('goalweight',$event)" :scrollLeft="Number(recordsData.goal_weight)" />
</view>
</u-popup>
<!-- 目标体重 end -->
<!-- 运动量 start --> <!-- 运动量 start -->
<view class="files" @click="exerciseShow = true"> <view class="files" @click="exerciseShow = true">
<view class="name">运动量</view> <view class="name">运动量</view>
<view class="text"> <view class="text">
<u-icon class="target-icon" :label="exerciseList[selectExerciseIndex].name" name="arrow-right" color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" /> <u-icon class="target-icon" :label="exerciseList[selectExerciseIndex].name" name="arrow-right"
</view> color="#999" size="14" labelSize="14" labelColor="#666" labelPos="left" space="10" />
</view> </view>
<u-action-sheet </view>
:actions="exerciseList" <u-action-sheet :actions="exerciseList" title="你的运动量是?" :show="exerciseShow" cancelText="暂不修改"
title="你的运动量是?" @select=" e => { (this.selectExerciseIndex = this.exerciseList.findIndex(item => e.id === item.id)), (this.exerciseShow = false); } "
:show="exerciseShow" @close="exerciseShow = false" />
cancelText="暂不修改" <!-- 运动量 end -->
@select=" e => { (this.selectExerciseIndex = this.exerciseList.findIndex(item => e.id === item.id)), (this.exerciseShow = false); } " <view class="sureBtn" @click="sureBtn"> 确认修改 </view>
@close="exerciseShow = false" <view class="des">修改资料后可更新并查看最新方案预算热量可能会发生变化</view>
/> </view>
<!-- 运动量 end -->
<view class="sureBtn" @click="sureBtn"> 确认修改 </view>
<view class="des">修改资料后可更新并查看最新方案预算热量可能会发生变化</view>
</view>
</template> </template>
<script> <script>
import { editHealthBefore,editHealth } from '@/apis/interfaces/essentialInfo.js'; import {
import moment from 'moment'; editHealthBefore,
import vueScale from '@/components/vueScale'; // 体重标尺 editHealth
export default { } from '@/apis/interfaces/essentialInfo.js';
components:{ import moment from 'moment';
vueScale import vueScale from '@/components/vueScale'; // 体重标尺
}, export default {
data() { components: {
return { vueScale
recordsData: {}, },
birthdayShow: false, // 出生日期展示 data() {
maxDate: new Date().getTime(), return {
sexShow: false, // 性别弹窗是否显示 recordsData: {},
sexList: [{name: '男士',id: 1},{name: '女士',id: 2}], birthdayShow: false, // 出生日期展示
targetShow: false, // 目标弹窗是否显示 maxDate: new Date().getTime(),
targetList: [{name: '减脂',id: 1},{name: '保持体重',id: 2},{name: '增肌',id: 3}], sexShow: false, // 性别弹窗是否显示
selectedTargetIndex: 0,// 默认选择了那个target sexList: [{
exerciseShow:false,// 运动量弹窗是否显示 name: '男士',
exerciseList:[{name:'久坐不动',id:1},{name:'少量运动',id:2},{name:'中等运动量',id:3},{name:'超强度运动',id:4}], id: 1
selectExerciseIndex:0,//默认选择运动量是久坐不懂得 }, {
heightShow:false, name: '女士',
weightShow:false, id: 2
targetWeightShow:false, }],
styles: { targetShow: false, // 目标弹窗是否显示
line: '#dbdbdb', targetList: [{
bginner: '#fbfbfb', name: '减脂',
bgoutside: '#ffffff', id: 1
font: '#404040', }, {
fontColor: '#404040', name: '保持体重',
fontSize: 16 id: 2
}, }, {
}; name: '增肌',
}, id: 3
computed: { }],
showBirthday() { selectedTargetIndex: 0, // 默认选择了那个target
return moment(this.recordsData.birthday).format('YYYY年MM月DD日'); exerciseShow: false, // 运动量弹窗是否显示
} exerciseList: [{
}, name: '久坐不动',
id: 1
}, {
name: '少量运动',
id: 2
}, {
name: '中等运动量',
id: 3
}, {
name: '超强度运动',
id: 4
}],
selectExerciseIndex: 0, //默认选择运动量是久坐不懂得
heightShow: false,
weightShow: false,
targetWeightShow: false,
styles: {
line: '#dbdbdb',
bginner: '#fbfbfb',
bgoutside: '#ffffff',
font: '#404040',
fontColor: '#404040',
fontSize: 16
},
};
},
computed: {
showBirthday() {
return moment(this.recordsData.birthday).format('YYYY年MM月DD日');
}
},
onShow() { onShow() {
let id = this.$Route.query.id; let id = this.$Route.query.id;
editHealthBefore(id) editHealthBefore(id)
.then(res => { .then(res => {
this.recordsData = res; this.recordsData = res;
this.recordsData.birthday = moment(res.birthday).format('YYYY-MM-DD'); this.recordsData.birthday = moment(res.birthday).format('YYYY-MM-DD');
this.selectExerciseIndex = this.exerciseList.findIndex(item => item.id === res.exercise) this.selectExerciseIndex = this.exerciseList.findIndex(item => item.id === res.exercise)
}) })
.catch(err => { .catch(err => {
conso.log(err); uni.showToast({
}); title: err.message,
}, icon: "none",
methods: { duration: 2000,
// 身高 体重 目标体重 滚动 mask: true
scrollAll(type,value) { })
if(type === 'height'){ });
return this.recordsData.height = value; },
} methods: {
if(type === 'weight'){ // 身高 体重 目标体重 滚动
return this.recordsData.weight = value; scrollAll(type, value) {
} if (type === 'height') {
if(type === 'goalweight'){ return this.recordsData.height = value;
return this.recordsData.goal_weight = value; }
} if (type === 'weight') {
}, return this.recordsData.weight = value;
// 年龄 - 过滤 - 自定义 - 出生年月日 }
formatter(type, value) { if (type === 'goalweight') {
if (type === 'year') {return `${value}`;} return this.recordsData.goal_weight = value;
if (type === 'month') {return `${value}`;} }
if (type === 'day') {return `${value}`;} },
return value; // 年龄 - 过滤 - 自定义 - 出生年月日
}, formatter(type, value) {
// 提交按钮 if (type === 'year') {
sureBtn(){ return `${value}`;
}
let params = { if (type === 'month') {
record_id:this.recordsData.record_id, return `${value}`;
birthday:moment(this.recordsData.birthday).format('YYYY-MM-DD'), }
sex:this.recordsData.sex, if (type === 'day') {
height:this.recordsData.height, return `${value}`;
weight:this.recordsData.weight, }
exercise:this.exerciseList[this.selectExerciseIndex].id, return value;
goal_weight:this.recordsData.goal_weight, },
days:1 // 提交按钮
} sureBtn() {
editHealth(params.record_id,params).then(res=>{ let params = {
this.$Router.back() record_id: this.recordsData.record_id,
}).catch(err=>{ birthday: moment(this.recordsData.birthday).format('YYYY-MM-DD'),
this.$Router.back() sex: this.recordsData.sex,
}) height: this.recordsData.height,
weight: this.recordsData.weight,
} exercise: this.exerciseList[this.selectExerciseIndex].id,
} goal_weight: this.recordsData.goal_weight,
}; days: 1
}
editHealth(params.record_id, params).then(res => {
this.$Router.back()
}).catch(err => {
uni.showToast({
title: err.message,
icon: "none",
duration: 2000,
mask: true
})
this.$Router.back()
})
}
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content { .content {
padding: $padding; padding: $padding;
} }
.files {
display: flex; .files {
padding: $padding + 10 $padding - 20; display: flex;
box-sizing: border-box; padding: $padding + 10 $padding - 20;
border-bottom: #f9f9f9 2rpx solid; box-sizing: border-box;
font-size: $title-size; border-bottom: #f9f9f9 2rpx solid;
&:last-child { font-size: $title-size;
border: none;
} &:last-child {
.name { border: none;
flex: 1; }
}
.text { .name {
color: $text-gray; flex: 1;
} }
}
.v-scale{ .text {
padding: $padding * 2 0; color: $text-gray;
font-size: $title-size; }
.title{ }
text-align: center;
font-size: $title-size + 10; .v-scale {
margin-bottom: $margin; padding: $padding * 2 0;
} font-size: $title-size;
.total{
font-size: $title-size; .title {
color: $main-color; text-align: center;
text-align: center; font-size: $title-size + 10;
} margin-bottom: $margin;
} }
.des {
color: $text-gray-m; .total {
font-size: $title-size-m - 4; font-size: $title-size;
margin-top: $margin * 2; color: $main-color;
text-align: center; text-align: center;
} }
.sureBtn{ }
background-color: $main-color;
color: #fff; .des {
font-size: $title-size; color: $text-gray-m;
text-align: center; font-size: $title-size-m - 4;
padding: $padding; margin-top: $margin * 2;
border-radius: $radius; text-align: center;
margin-top: $margin * 2; }
}
.bt30 { .sureBtn {
border-bottom: #f9f9f9 20rpx solid; background-color: $main-color;
} color: #fff;
font-size: $title-size;
text-align: center;
padding: $padding;
border-radius: $radius;
margin-top: $margin * 2;
}
.bt30 {
border-bottom: #f9f9f9 20rpx solid;
}
</style> </style>

View File

@@ -155,12 +155,10 @@
if (this.$store.state.token === '') return; if (this.$store.state.token === '') return;
info() info()
.then(res => { .then(res => {
console.log(res);
uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
title: res.nickname title: res.nickname
}); });
this.userInfo = res; this.userInfo = res;
console.log(res);
}) })
.catch(err => { .catch(err => {
uni.showToast({ uni.showToast({
@@ -318,7 +316,7 @@
.user-content { .user-content {
padding-left: 158rpx; padding-left: 158rpx;
height: 128rpx; height: 140rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;

View File

@@ -4,16 +4,16 @@ import {
} from 'uni-simple-router'; } from 'uni-simple-router';
import store from '@/store/index' import store from '@/store/index'
// #ifdef APP-NVUE
// CALL 页面必须是nvue但是NVUE 不支持webpack的 ROUTES 注入 // CALL 页面必须是nvue但是NVUE 不支持webpack的 ROUTES 注入
// https://github.com/SilurianYang/uni-read-pages/issues/20 // https://github.com/SilurianYang/uni-read-pages/issues/20
// #ifdef APP-NVUE
const ROUTES = [{ const ROUTES = [{
'path': '/pages/im/private/call', "path": "/pages/im/private/call"
'name': 'imPrivateCall' }, {
},{ "path": "/pages/im/private/chat"
'path': '/pages/im/private/chat', }, {
'name': 'imPrivateChat' "path": "/pages/im/group/chat"
}] }];
// #endif // #endif
const router = createRouter({ const router = createRouter({

View File

@@ -1,6 +1,6 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 2869797 */ font-family: "iconfont"; /* Project id 2869797 */
src: url('@/static/iconfont.ttf') format('truetype'); src: url('@/static/iconfont.ttf');
} }
.iconfont { .iconfont {
@@ -11,6 +11,10 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-jia:before {
content: "\e60a";
}
.icon-dui:before { .icon-dui:before {
content: "\e609"; content: "\e609";
} }

Binary file not shown.

BIN
static/imgs/curve-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
static/imgs/curve-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
static/imgs/no-weight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
static/imgs/speed-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
static/imgs/speed-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
static/imgs/water-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
static/imgs/water-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -2,98 +2,144 @@ import im from "@/utils/im/index.js"
export default { export default {
state: { state: {
friends: {}, contacts: {},
sender: {}, myInfo: {}
}, },
getters: { getters: {
friends(state) { contacts(state) {
return state.friends return state.contacts
}, },
userInfo: (state) => (targetId) => { contactInfo: (state) => (targetId) => {
if (state.friends[targetId]) { if (state.contacts[targetId]) {
return state.friends[targetId] const info = state.contacts[targetId]
return {
name: info.name,
hash: info.hash,
portraitUrl: info.localAvatar ? info.localAvatar : require('@/static/user/cover.png')
}
} else { } else {
console.log('没找到,死循环了,得处理 todo', targetId);
// im.syncUserInfo(targetId)
return { return {
name: '', name: '',
address: '',
hash: '', hash: '',
portraitUrl: '' portraitUrl: ''
} }
} }
}, },
hasUser: (state) => (targetId) => { // 联系人是否存在
return Boolean(state.friends[targetId]) contactIsExist: (state) => (targetId) => {
return Boolean(state.contacts[targetId])
}, },
sender(state) { sender(state) {
return state.sender return state.myInfo
} }
}, },
mutations: { mutations: {
updateFriends(state, userInfo) { updateContactInfo(state, contactInfo) {
Vue.set(state.friends, userInfo.userId, userInfo) Vue.set(state.contacts, contactInfo.targetId, contactInfo)
}, },
SET_state_sender(state, userInfo) { setSenderInfo(state, contactInfo) {
state.sender = userInfo state.myInfo = {
userId: contactInfo.targetId,
name: contactInfo.name,
portraitUrl: contactInfo.portraitUrl
}
} }
}, },
actions: { actions: {
setSenderInfo({ setSenderInfo({
commit commit
}, userInfo) { }, contactInfo) {
commit('SET_state_sender', userInfo) commit('setSenderInfo', contactInfo)
}, },
updateFriends({ // 载入好友信息
launchContact({
commit commit
}, userInfo) { }, data) {
commit('updateFriends', userInfo) commit('updateContactInfo', data)
const model = uni.model.friendModel },
model.find('userId=' + userInfo.userId, (err, user) => { // 更新好友信息这个时候要校验hash值了
if (!err && user.length == 0) { updateContact({
saveAvatar(userInfo, (savedFilePath) => { commit,
model.insert({ dispatch
userId: userInfo.userId, }, contactInfo) {
name: userInfo.name, const model = uni.model.contactModel
hash: userInfo.hash, model.find('targetId="' + contactInfo.targetId + '"', (err, result) => {
address: userInfo.address, if (result.length == 0) {
portraitUrl: savedFilePath, // 没有数据,直接新增一条
}, (err, result) => {}) dispatch('initContact', contactInfo)
userInfo.portraitUrl = savedFilePath } else if (contactInfo.hash != result[0].hash) {
commit('updateFriends', userInfo) commit('updateContactInfo', contactInfo)
}) if (contactInfo.portraitUrl && contactInfo.portraitUrl != result[0].portraitUrl) {
} else if (!err && user[0].hash != userInfo.hash) { saveAvatar(contactInfo, (savedFilePath) => {
saveAvatar(userInfo, (savedFilePath) => { const info = {
model.update('userId=' + userInfo.userId, { targetId: contactInfo.targetId,
name: userInfo.name, name: contactInfo.name,
hash: userInfo.hash, hash: contactInfo.hash,
portraitUrl: savedFilePath, portraitUrl: contactInfo.portraitUrl,
}, (err, result) => {}) localAvatar: savedFilePath
userInfo.portraitUrl = savedFilePath }
commit('updateFriends', userInfo) model.update('targetId="' + contactInfo.targetId + '"', info, (err,
}) res) => {
} else if (!err && user[0].portraitUrl.length > 50) { console.log('UPDATE AVATAR, ERR', err);
saveAvatar(userInfo, (savedFilePath) => { })
model.update('userId=' + userInfo.userId, { commit('updateContactInfo', info)
name: userInfo.name, })
hash: userInfo.hash, } else {
portraitUrl: savedFilePath, const info = {
}, (err, result) => {}) targetId: contactInfo.targetId,
name: contactInfo.name,
userInfo.portraitUrl = savedFilePath hash: contactInfo.hash,
commit('updateFriends', userInfo) portraitUrl: contactInfo.portraitUrl,
}) localAvatar: result[0].localAvatar
}
model.update('targetId="' + contactInfo.targetId + '"', info, (err, res) => {
console.log('UPDATE NAME, ERR', err);
})
}
} else { } else {
console.log('不用操作', user[0]); console.log('updateContact, 无操作');
} }
}) })
},
// 初始化好友信息
initContact({
commit
}, contactInfo) {
// 将好友信息保存到vuex的内存中方便立即使用
commit('updateContactInfo', contactInfo)
const model = uni.model.contactModel
// 用户头像,是否需要下载到本地
if (contactInfo.portraitUrl) {
saveAvatar(contactInfo, (savedFilePath) => {
const info = {
targetId: contactInfo.targetId,
name: contactInfo.name,
hash: contactInfo.hash,
portraitUrl: contactInfo.portraitUrl,
localAvatar: savedFilePath
}
model.insert(info, (err, res) => {})
// 保存头像后,更新信息
commit('updateContactInfo', info)
})
} else {
// 直接将信息,写入数据库
const info = {
targetId: contactInfo.targetId,
name: contactInfo.name,
hash: contactInfo.hash,
portraitUrl: contactInfo.portraitUrl,
localAvatar: ''
}
model.insert(info, (err, res) => {})
}
} }
} }
} }
const saveAvatar = (userInfo, callback) => { const saveAvatar = (contactInfo, callback) => {
uni.downloadFile({ uni.downloadFile({
url: userInfo.portraitUrl, url: contactInfo.portraitUrl,
success: ({ success: ({
tempFilePath tempFilePath
}) => { }) => {
@@ -106,8 +152,6 @@ const saveAvatar = (userInfo, callback) => {
} }
}) })
}, },
fail: (err) => { fail: (err) => {}
console.log('头像保存失败', err);
}
}) })
} }

File diff suppressed because it is too large Load Diff

16
utils/im/data.js Normal file
View File

@@ -0,0 +1,16 @@
// 获取新好友申请数量
const getPendingCount = (callback) => {
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 100, 0, (res) => {
if (res.code === 0) {
const pendingCount = res.conversations.filter((item) => {
return item.objectName == RongIMLib.ObjectName.ContactNotification
}).length
callback(pendingCount)
}
})
}
export default {
getPendingCount
}

View File

@@ -1,23 +0,0 @@
[{
"objectName": "RC:TxtMsg",
"receivedTime": 1643080237399,
"extra": "",
"messageUId": "BUFC-3FSU-OLE4-I31K",
"conversationType": 1,
"messageDirection": 2,
"senderUserId": "10041",
"content": {
"content": "你好,这是 1710 条消息条消息条消息条消息条消息条消息条消息条消息条消息0.97796900 1642741562",
"objectName": "RC:TxtMsg",
"userInfo": {
"userId": "10041",
"name": "我是eth",
"portraitUrl": "http://storage.zh.shangkelian.cn/images/2022/01/12/3d2a103386df6822db7e5290272e8bc2.png"
}
},
"targetId": "10041",
"sentTime": 1642741563003,
"messageId": 2,
"receivedStatus": 1,
"sentStatus": 30
}]

View File

@@ -2,6 +2,7 @@ import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index' import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index'
import store from '@/store/index.js' import store from '@/store/index.js'
import message from './message.js' import message from './message.js'
import listeners from './listeners.js'
import { import {
getFriends, getFriends,
getUserInfo, getUserInfo,
@@ -10,7 +11,7 @@ import {
const initIm = (KEY) => { const initIm = (KEY) => {
RongIMLib.init(KEY) RongIMLib.init(KEY)
CallLib.init() // CallLib.init()
addListeners() addListeners()
// 初始化的时候 自动链接 // 初始化的时候 自动链接
if (store.getters.getToken !== '') { if (store.getters.getToken !== '') {
@@ -47,25 +48,37 @@ const setNotifyBadge = () => {
/** /**
* 连接IM服务 * 连接IM服务
* @param {string} token token * @param {string} token token
* @param {object} userInfo {userId: string, name: string, portraitUrl: string} * @param {object} userInfo {targetId: string, name: string, portraitUrl: string}
*/ */
const connect = (token, userInfo, callback) => { const connect = (token, userInfo, callback) => {
RongIMLib.connect(token, res => { RongIMLib.connect(token, res => {
console.log('连接结果', res);
callback(res) callback(res)
}) // 更新个人信息
store.dispatch('setSenderInfo', userInfo)
// 设置未读消息数量
setNotifyBadge()
// 首次运行获取好友列表
const FK = 'IFT_' + userInfo.targetId
store.dispatch('setSenderInfo', userInfo) uni.getStorage({
key: FK,
setNotifyBadge() success: () => {
const model = uni.model.contactModel
const model = uni.model.friendModel model.find((err, results) => {
results.map(item => {
model.find((err, results) => { store.dispatch('launchContact', item)
console.log('好友列表', results); })
results.map(item => { })
store.dispatch('updateFriends', item) },
fail: () => {
// 程序是首次运行,初始化加载好友信息
getFriends().then(res => {
res.map(item => {
store.dispatch('initContact', item)
})
uni.setStorageSync(FK, userInfo.targetId)
})
}
}) })
}) })
} }
@@ -102,25 +115,42 @@ const notifyMsgTypes = [
function inArray(search, array) { function inArray(search, array) {
for (var i in array) { for (var i in array) {
if (array[i] == search) { if (array[i] == search) {
return true; return true
} }
} }
return false; return false
} }
const addListeners = () => { const addListeners = () => {
// 添加连接状态监听函数 // 添加连接状态监听函数
RongIMLib.addConnectionStatusListener((res) => { RongIMLib.addConnectionStatusListener((res) => {
console.log('连接状态监听', res.data.status); console.log('连接状态监听', res.data.status)
uni.$emit('onConnectionStatusChange', res.data.status) uni.$emit('onConnectionStatusChange', res.data.status)
}) })
// 添加消息监听函数 // 添加消息监听函数
RongIMLib.addReceiveMessageListener((res) => { RongIMLib.addReceiveMessageListener((res) => {
console.log('收到消息', res.data.message);
const message = res.data.message const message = res.data.message
console.log('收到消息', message)
if (inArray(message.objectName, notifyMsgTypes)) { if (inArray(message.objectName, notifyMsgTypes)) {
console.log('new Message'); if (!store.getters.contactIsExist(message.targetId)) {
getUserInfo(message.targetId).then(res => {
store.dispatch('initContact', res)
}).catch(err => {
console.log('ERR', err)
})
}
newMessage(message) newMessage(message)
} else if (message.objectName === RongIMLib.ObjectName.ProfileNotification) {
store.dispatch('updateContact', JSON.parse(message.content.data))
// 调用完更新之后,删除这条消息
RongIMLib.deleteMessagesByIds([message.messageId], ({
code
}) => {
console.log('消息删除结果', code)
})
} else if (message.objectName === RongIMLib.ObjectName.ContactNotification) {
// 触发一个新好友的通知事件
uni.$emit('onContactNotification', message.content)
} }
}) })
@@ -133,40 +163,40 @@ const addListeners = () => {
// 音视频通话相关的 // 音视频通话相关的
// 监听通话呼入 // 监听通话呼入
CallLib.onCallReceived(({ // CallLib.onCallReceived(({
data // data
}) => { // }) => {
uni.navigateTo({ // uni.navigateTo({
url: '/pages/im/private/call?targetId=' + data.targetId + '&mediaType=' + // url: '/pages/im/private/call?targetId=' + data.targetId + '&mediaType=' +
data.mediaType // data.mediaType
}) // })
}) // })
// 通话建立成功 // // 通话建立成功
CallLib.onCallConnected(() => { // CallLib.onCallConnected(() => {
uni.$emit('onCallConnected'); // uni.$emit('onCallConnected')
}) // })
// 外呼 // // 外呼
CallLib.onCallOutgoing((res) => { // CallLib.onCallOutgoing((res) => {
uni.$emit('onCallOutgoing'); // uni.$emit('onCallOutgoing')
}) // })
// 远端响铃 // // 远端响铃
CallLib.onRemoteUserRinging((res) => { // CallLib.onRemoteUserRinging((res) => {
uni.$emit('onRemoteUserRinging'); // uni.$emit('onRemoteUserRinging')
}) // })
// 远端加入 // // 远端加入
CallLib.onRemoteUserJoined((res) => { // CallLib.onRemoteUserJoined((res) => {
uni.$emit('onRemoteUserJoined'); // uni.$emit('onRemoteUserJoined')
}) // })
// 断开链接 // // 断开链接
CallLib.onCallDisconnected((res) => { // CallLib.onCallDisconnected((res) => {
console.log('断开链接', res); // console.log('断开链接', res)
uni.$emit('onCallDisconnected'); // uni.$emit('onCallDisconnected')
}) // })
// 远端挂断 // // 远端挂断
CallLib.onRemoteUserLeft((res) => { // CallLib.onRemoteUserLeft((res) => {
console.log('远端离开', res); // console.log('远端离开', res)
uni.$emit('onRemoteUserLeft'); // uni.$emit('onRemoteUserLeft')
}) // })
} }
// 维护消息列表,检查是否需要通知声音,设置新消息提醒的数量 // 维护消息列表,检查是否需要通知声音,设置新消息提醒的数量
@@ -177,24 +207,13 @@ const newMessage = (msg) => {
}) => { }) => {
if (code === 0) { if (code === 0) {
if (status) { if (status) {
uni.vibrateLong()
triTone() triTone()
} }
} }
});
setNotifyBadge()
if (!store.getters.hasUser(msg.targetId)) {
syncUserInfo(msg.targetId)
}
uni.$emit('onReceiveMessage', msg);
}
function syncUserInfo(targetId) {
getUserInfo(targetId).then(res => {
store.dispatch('updateFriends', res)
}) })
setNotifyBadge()
uni.$emit('onReceiveMessage', msg)
} }
// 播放状态 // 播放状态
@@ -215,23 +234,9 @@ const triTone = () => {
} }
} }
/**
* 同步好友信息,保存头像地址等
*/
const syncFriends = () => {
getFriends().then(res => {
res.map(item => {
console.log('item', item);
store.dispatch('updateFriends', item)
})
})
}
export default { export default {
initIm, initIm,
connect, connect,
setNotifyBadge, setNotifyBadge,
syncFriends,
syncUserInfo,
...message ...message
} }

0
utils/im/listeners.js Normal file
View File

View File

@@ -1,8 +1,9 @@
import store from '@/store/index.js' import store from '@/store/index.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
const getMessageList = (conversationType, targetId, timeStamp, count, isForward, callback) => { const getMessageList = (conversationType, targetId, timeStamp, count, isForward, callback) => {
// 获取消息列表 // 获取消息列表 https://doc.rongcloud.cn/imserver/server/v1/message/objectname#objectName
const objectNames = [ const objectNames = [
'RC:TxtMsg', 'RC:TxtMsg',
'RC:VcMsg', 'RC:VcMsg',
@@ -40,6 +41,21 @@ const getMessageList = (conversationType, targetId, timeStamp, count, isForward,
) )
} }
// 获取好友申请列表
const getPendingList = (callback, total) => {
total = total || 100
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], total, 0, (res) => {
if (res.code === 0) {
const pendings = res.conversations.filter((item) => {
return item.objectName == RongIMLib.ObjectName.ContactNotification &&
item.latestMessage.operation === 'Request'
})
callback(pendings)
}
})
}
/** /**
* 发送文本消息 * 发送文本消息
* @param {number} conversationType 消息类型 * @param {number} conversationType 消息类型
@@ -47,17 +63,17 @@ const getMessageList = (conversationType, targetId, timeStamp, count, isForward,
* @param {string} content 消息内容 * @param {string} content 消息内容
* @param {function} callback 回调函数 * @param {function} callback 回调函数
*/ */
const sentText = (conversationType, targetId, content, callback) => { const sentText = (conversationType, targetId, content, user, callback) => {
console.log('发送');
const msg = { const msg = {
conversationType: conversationType, conversationType: conversationType,
targetId: String(targetId), targetId: String(targetId),
content: { content: {
objectName: 'RC:TxtMsg', objectName: 'RC:TxtMsg',
content: content, content: content,
user: store.getters.sender userInfo: user
} }
} }
RongIMLib.sendMessage(msg, ({ RongIMLib.sendMessage(msg, ({
code, code,
messageId messageId
@@ -65,9 +81,10 @@ const sentText = (conversationType, targetId, content, callback) => {
if (code === 0) { if (code === 0) {
callback(messageId) callback(messageId)
} else { } else {
console.log('发送失败', msg);
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: '发送失败' title: '发送失败' + code
}) })
} }
}) })
@@ -81,14 +98,15 @@ const sentText = (conversationType, targetId, content, callback) => {
* @param {integer} time 录音时长 * @param {integer} time 录音时长
* @param {function} callback 录音时长 * @param {function} callback 录音时长
*/ */
const sentVoice = (conversationType, targetId, voiceUrl, time, callback) => { const sentVoice = (conversationType, targetId, voiceUrl, time, user, callback) => {
const msg = { const msg = {
conversationType: conversationType, conversationType: conversationType,
targetId: String(targetId), targetId: String(targetId),
content: { content: {
objectName: 'RC:HQVCMsg', objectName: 'RC:HQVCMsg',
local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl), local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl),
duration: time duration: time,
userInfo: user
} }
} }
RongIMLib.sendMediaMessage(msg, { RongIMLib.sendMediaMessage(msg, {
@@ -107,13 +125,14 @@ const sentVoice = (conversationType, targetId, voiceUrl, time, callback) => {
}) })
} }
const sentImage = (conversationType, targetId, imageUrl, callback) => { const sentImage = (conversationType, targetId, imageUrl, user, callback) => {
const msg = { const msg = {
conversationType: conversationType, conversationType: conversationType,
targetId: String(targetId), targetId: String(targetId),
content: { content: {
objectName: 'RC:ImgMsg', objectName: 'RC:ImgMsg',
local: 'file:///' + plus.io.convertLocalFileSystemURL(imageUrl) local: 'file:///' + plus.io.convertLocalFileSystemURL(imageUrl),
userInfo: user
} }
} }
RongIMLib.sendMediaMessage(msg, { RongIMLib.sendMediaMessage(msg, {
@@ -186,6 +205,7 @@ const sendFile = (conversationType, targetId, fileUrl, time, callback) => {
export default { export default {
getMessageList, getMessageList,
getPendingList,
sentText, sentText,
sentVoice, sentVoice,
sentImage, sentImage,

View File

@@ -2,21 +2,21 @@ import {
usqlite usqlite
} from '@/uni_modules/onemue-USQLite/js_sdk/usqlite.js' } from '@/uni_modules/onemue-USQLite/js_sdk/usqlite.js'
const friendModel = usqlite.model('friends', { const contactModel = usqlite.model('contacts', {
userId: { targetId: {
type: String, type: String,
primaryKey: true, primaryKey: true,
unique: true unique: true
}, },
name: String, name: String,
address: String,
hash: { hash: {
type: String, type: String,
unique: true unique: true
}, },
portraitUrl: String portraitUrl: String,
localAvatar: String
}) })
export default { export default {
friendModel contactModel
} }

View File

@@ -1,51 +0,0 @@
{
"type": "Engine:OnCallReceived",
"module": "RongCloud-Call-RCUniCall",
"data": {
"endTime": 0,
"users": [{
"userId": "10051",
"enableCamera": false,
"mediaId": "420111350",
"mediaType": 1,
"userType": 0,
"enableMicrophone": false
}, {
"userId": "10047",
"enableCamera": false,
"mediaType": 1,
"userType": 0,
"enableMicrophone": false
}],
"inviter": {
"userId": "10051",
"enableCamera": false,
"mediaId": "420111350",
"mediaType": 1,
"userType": 0,
"enableMicrophone": false
},
"caller": {
"userId": "10051",
"enableCamera": false,
"mediaId": "420111350",
"mediaType": 1,
"userType": 0,
"enableMicrophone": false
},
"connectedTime": 0,
"extra": "",
"startTime": 0,
"mediaType": 1,
"callId": "c28cb9d8-6581-474c-bfa5-9872a4824b65",
"targetId": "10051",
"callType": 0,
"mine": {
"userId": "10047",
"enableCamera": false,
"mediaType": 1,
"userType": 0,
"enableMicrophone": false
}
}
}

View File

@@ -1,51 +0,0 @@
{
"type": "Engine:OnCallReceived",
"module": "RongCloud-Call-RCUniCall",
"data": {
"endTime": 0,
"users": [{
"userId": "10051",
"enableCamera": false,
"mediaId": "420068630",
"mediaType": 0,
"userType": 0,
"enableMicrophone": false
}, {
"userId": "10047",
"enableCamera": true,
"mediaType": 0,
"userType": 0,
"enableMicrophone": false
}],
"inviter": {
"userId": "10051",
"enableCamera": false,
"mediaId": "420068630",
"mediaType": 0,
"userType": 0,
"enableMicrophone": false
},
"caller": {
"userId": "10051",
"enableCamera": false,
"mediaId": "420068630",
"mediaType": 0,
"userType": 0,
"enableMicrophone": false
},
"connectedTime": 0,
"extra": "",
"startTime": 0,
"mediaType": 0,
"callId": "1a1462b8-b63b-40a9-bf95-963e810ac49a",
"targetId": "10051",
"callType": 0,
"mine": {
"userId": "10047",
"enableCamera": true,
"mediaType": 0,
"userType": 0,
"enableMicrophone": false
}
}
}