厨房秤功能
|
|
@ -0,0 +1,392 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="content_box">
|
||||
<view class="date"></view>
|
||||
<!-- 早午晚餐 -->
|
||||
<view class="everyDay">
|
||||
<view class="title">
|
||||
<view><text class="quan"></text>卡路里分析</view>
|
||||
</view>
|
||||
<div class="chart-wrap">
|
||||
<qiun-data-charts type="ring" :opts="opts" :chartData="chartData" :cHeight="320" :cWidth="320" />
|
||||
</div>
|
||||
<view class="foodtools">
|
||||
<view class="type" v-for="(item,index) in foodInfo.list">
|
||||
<view class="name">
|
||||
<text :style="{background:item.color}"></text>
|
||||
<view>{{item.name}}</view>
|
||||
</view>
|
||||
<view>{{item.val||0}}{{item.unit}}<text>|</text>{{item.kcal_proportion}}%</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!--营养元素分析 -->
|
||||
<view class="everyDay">
|
||||
<view class="title">
|
||||
<view><text class="quan"></text>营养元素能量占比</view>
|
||||
</view>
|
||||
<div class="chart-wrap">
|
||||
<qiun-data-charts type="ring" :opts="opts2" :chartData="chartData2" :cHeight="320" :cWidth="320" />
|
||||
</div>
|
||||
<view class="foodtools">
|
||||
<view class="top">
|
||||
<view>营养分类</view>
|
||||
<view>摄入</view>
|
||||
</view>
|
||||
<view class="type">
|
||||
<view class="name">
|
||||
<text :style="{background:details.carbohydrate.color}"></text>
|
||||
<image :src="details.carbohydrate.icon"></image>
|
||||
<view>{{details.carbohydrate.name}}</view>
|
||||
</view>
|
||||
<view>
|
||||
{{details.carbohydrate.val}}{{details.carbohydrate.unit}}<text>|</text>{{details.carbohydrate.proportion}}%
|
||||
</view>
|
||||
</view>
|
||||
<view class="type">
|
||||
<view class="name">
|
||||
<text :style="{background:details.fat.color}"></text>
|
||||
<image :src="details.fat.icon"></image>
|
||||
<view>{{details.fat.name}}</view>
|
||||
</view>
|
||||
<view>{{details.fat.val}}{{details.fat.unit}}<text>|</text>{{details.fat.proportion}}%</view>
|
||||
</view>
|
||||
<view class="type">
|
||||
<view class="name">
|
||||
<text :style="{background:details.protein.color}"></text>
|
||||
<image :src="details.protein.icon"></image>
|
||||
<view>{{details.protein.name}}</view>
|
||||
</view>
|
||||
<view>
|
||||
{{details.protein.val}}{{details.protein.unit}}<text>|</text>{{details.protein.proportion}}%
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!--营养元素排行榜 -->
|
||||
<view class="everyDay">
|
||||
<view class="title">
|
||||
<view><text class="quan"></text>营养元素排行榜</view>
|
||||
</view>
|
||||
<view class="foodtools rank_list">
|
||||
<view class="topname">{{details.carbohydrate.name}}</view>
|
||||
<view class="type" v-for="(item,index) in details.carbohydrate.rank_list">
|
||||
<view class="name">
|
||||
<image :src="item.icon"></image>
|
||||
<image :src="item.pic_url" class="pic" v-if="item.pic_url"></image>
|
||||
<view>{{item.name?item.name:'--'}}</view>
|
||||
</view>
|
||||
<view>{{item.weight||0}}g</view>
|
||||
</view>
|
||||
<view class="topname">{{details.fat.name}}</view>
|
||||
<view class="type" v-for="(item,index) in details.fat.rank_list">
|
||||
<view class="name">
|
||||
<image :src="item.icon"></image>
|
||||
<image :src="item.pic_url" class="pic" v-if="item.pic_url"></image>
|
||||
<view>{{item.name?item.name:'--'}}</view>
|
||||
</view>
|
||||
<view>{{item.weight||0}}g</view>
|
||||
</view>
|
||||
<view class="topname">{{details.protein.name}}</view>
|
||||
<view class="type" v-for="(item,index) in details.protein.rank_list">
|
||||
<view class="name">
|
||||
<image :src="item.icon"></image>
|
||||
<image :src="item.pic_url" class="pic" v-if="item.pic_url"></image>
|
||||
<view>{{item.name?item.name:'--'}}</view>
|
||||
</view>
|
||||
<view>{{item.weight||0}}g</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 营养元素 -->
|
||||
<view class="jishiqi">
|
||||
<view class="right">
|
||||
<view class="item" v-for="(ite,ind) in foodInfo.nutrients_four">
|
||||
<view class="left-icon">
|
||||
<view class="name">
|
||||
<image :src="ite.icon"></image>
|
||||
<text class="name">{{ite.name}}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text class="weight">{{ite.today_intake||0}}{{ite.unit}}</text> / {{ite.suggestion||0}}g
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-info">
|
||||
<view class="right-info-bottom">
|
||||
<view class="val" :style="{ width: ite.proportion + '%',background:ite.color}"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="item" v-for="(ite,ind) in foodInfo.trace_elements_all_day">
|
||||
<view class="left-icon">
|
||||
<view class="name">
|
||||
<text class="name">{{ite.name_ch}}</text>
|
||||
</view>
|
||||
<view>
|
||||
{{ite.value||0}}{{ite.unit}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts.vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
opts: {
|
||||
color: [],
|
||||
title: {
|
||||
name: "",
|
||||
}
|
||||
},
|
||||
opts2: {
|
||||
color: [],
|
||||
subtitle: {
|
||||
name: "",
|
||||
}
|
||||
},
|
||||
chartData: {},
|
||||
chartData2: {},
|
||||
foodInfo: {},
|
||||
details: {}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
qiunDataCharts
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "countFoodInfo"]),
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.handleList()
|
||||
},
|
||||
methods: {
|
||||
handleList() {
|
||||
let that = this
|
||||
let chart_data = []
|
||||
let chart_data2 = []
|
||||
that.opts.color = []
|
||||
that.opts2.color = []
|
||||
that.foodInfo = that.countFoodInfo
|
||||
that.details = that.countFoodInfo.details
|
||||
for (let i = 0; i < that.foodInfo.list.length; ++i) {
|
||||
that.opts.color.push(that.foodInfo.list[i].color)
|
||||
chart_data.push({
|
||||
name: that.foodInfo.list[i].name,
|
||||
value: Number(that.foodInfo.list[i].kcal_proportion),
|
||||
})
|
||||
}
|
||||
that.opts.title.name = that.foodInfo.nutrients_four[0].today_intake
|
||||
that.chartData = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
data: chart_data
|
||||
}]
|
||||
}));
|
||||
for (let key in that.details) {
|
||||
if (that.details.hasOwnProperty(key)) {
|
||||
that.opts2.color.push(that.details[key].color)
|
||||
chart_data2.push({
|
||||
name: that.details[key].name,
|
||||
value: Number(that.details[key].proportion),
|
||||
})
|
||||
}
|
||||
}
|
||||
that.chartData2 = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
data: chart_data2
|
||||
}]
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background-color: #f7f7f7;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.content_box {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chart-wrap {
|
||||
position: relative;
|
||||
width: 320rpx;
|
||||
height: 320rpx;
|
||||
margin: -30rpx auto 0;
|
||||
|
||||
.uchart-val {
|
||||
margin-top: 70rpx;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 48rpx;
|
||||
width: 320rpx;
|
||||
font-size: 46rpx;
|
||||
text-align: center;
|
||||
z-index: 9;
|
||||
}
|
||||
}
|
||||
|
||||
.everyDay {
|
||||
background: #fff;
|
||||
padding: 10px 10px 0;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
|
||||
.quan {
|
||||
width: 60rpx;
|
||||
height: 40rpx;
|
||||
position: relative;
|
||||
margin-right: 70rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.foodtools {
|
||||
|
||||
text {
|
||||
margin: 0 15rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.type {
|
||||
display: flex;
|
||||
line-height: 45px;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
|
||||
.name {
|
||||
width: 80%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.pic {
|
||||
border: 1px solid #f7f7f7;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
text {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
margin-right: 10px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rank_list {
|
||||
.topname {
|
||||
position: relative;
|
||||
padding-left: 15px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.topname::after {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 7px;
|
||||
background-color: #666;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.type {
|
||||
border-bottom: none;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.jishiqi {
|
||||
margin: 0 10px;
|
||||
|
||||
.right {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: auto;
|
||||
background: #fff;
|
||||
padding: 2px 15px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.left-icon {
|
||||
width: 100%;
|
||||
float: left;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: inherit;
|
||||
|
||||
image {
|
||||
margin-right: 5px;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.weight {
|
||||
margin-right: 5px;
|
||||
color: $maincolor;
|
||||
}
|
||||
}
|
||||
|
||||
.right-info {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #f3f7f5;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,467 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="content_box">
|
||||
<view class="box">
|
||||
<!-- 类型 -->
|
||||
<view class="top">
|
||||
<image :src="bgimage" mode="aspectFill">
|
||||
<view class="name">{{info.name}}</view>
|
||||
<view class="time">{{time}}</view>
|
||||
</image>
|
||||
</view>
|
||||
<!-- 成分统计 -->
|
||||
<view class="everyDay">
|
||||
<view class="title">
|
||||
<view><text class="quan"></text>成分统计</view>
|
||||
</view>
|
||||
<view class="progress">
|
||||
<div class="chart-wrap">
|
||||
<qiun-data-charts type="ring" :opts="opts" canvasId="foodCharts" :chartData="chartData"
|
||||
:cHeight="280" :cWidth="280" :canvas2d="true" />
|
||||
</div>
|
||||
<view class="info" v-if="info.nutrients_four">
|
||||
<view class="info-item" v-for="(item,index) in info.nutrients_four.slice(1)" :key="index">
|
||||
<view>
|
||||
<view class="color" :style="{'background-color':`${item.color}`}"></view>
|
||||
<view>{{item.name}}</view>
|
||||
</view>
|
||||
<view>
|
||||
<view>{{item.value}}{{item.unit}}<text>|</text>{{item.proportion}}%</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 早午晚餐 -->
|
||||
<view class="foodtools">
|
||||
<view class="type">
|
||||
<view class="title">
|
||||
<view><text class="quan"></text>食物类型</view>
|
||||
</view>
|
||||
<view class="list" v-if="info.list.length">
|
||||
<uni-swipe-action>
|
||||
<uni-swipe-action-item v-for="(ite,ind) in info.list" :key="ind"
|
||||
:right-options="actionOptions" @click="delAcitionItem(ite)">
|
||||
<view class="item" @click="showFoodDetail(ite)">
|
||||
<image :src="ite.pic_url" mode="aspectFill"></image>
|
||||
<view class="weight">
|
||||
<view>{{ite.name}}</view>
|
||||
<view class="size12 c999">{{ite.weight}}<text>|</text>{{ite.val}}kcal</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
</view>
|
||||
<view v-else class="nolist">
|
||||
<image src="/static/none.png"></image>
|
||||
<view>暂无食物</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 添加食物 -->
|
||||
<view class="add" @click="handleAddFood()">
|
||||
<text>+</text>添加食物
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 营养含量分析 -->
|
||||
<view v-if="drawerVisible" class="drawerVisible">
|
||||
<view class="bgVisible" @click="handleDrawerClose"></view>
|
||||
<view class="infoVisible">
|
||||
<scroll-view style="height: 100%;" scroll-y="true">
|
||||
<view class="foodDetail">
|
||||
<view class="foodInfo">
|
||||
<image :src="activeFoodDetail.pic_url" mode="aspectFill"></image>
|
||||
<view class="info">
|
||||
<view class="name">{{activeFoodDetail.name}}</view>
|
||||
<view class="kcal">{{activeFoodDetail.val}}千卡</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="foodContent">
|
||||
<view class="title">热量和营养</view>
|
||||
<view class="progress">
|
||||
<div class="chart-wrap">
|
||||
<qiun-data-charts v-if="chartVisible" type="ring" :opts="opts2"
|
||||
:chartData="chartData2" :cHeight="280" :cWidth="280" />
|
||||
</div>
|
||||
<view class="info" v-if="activeFoodDetail.nutrients_four">
|
||||
<view class="info-item"
|
||||
v-for="(item,index) in activeFoodDetail.nutrients_four.slice(1)" :key="index">
|
||||
<view class="color" :style="{'background-color':`${item.color}`}">
|
||||
</view>
|
||||
<view>{{item.name}}:{{item.proportion}}%</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<text>营养素</text>
|
||||
<text>{{activeFoodDetail.weight}}含量</text>
|
||||
</view>
|
||||
<view class="foodDetailList">
|
||||
<view class="foodDetailItem" v-for="(item,index) in activeFoodDetail.nutrients_list"
|
||||
:key="index">
|
||||
<view class="name">{{item.name_ch}}</view>
|
||||
<view class="value">{{item.value}}{{item.unit}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
let next = 0
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts.vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
opts: {
|
||||
color: [],
|
||||
title: {
|
||||
name: "",
|
||||
}
|
||||
},
|
||||
opts2: {
|
||||
color: [],
|
||||
title: {
|
||||
name: "",
|
||||
}
|
||||
},
|
||||
chartData: {},
|
||||
chartData2: {},
|
||||
activeFoodDetail: {},
|
||||
drawerVisible: false,
|
||||
chartVisible: false, // 单独控制图表显示
|
||||
actionOptions: [{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#dd524d',
|
||||
borderRadius: '10rpx'
|
||||
}
|
||||
}],
|
||||
time: "",
|
||||
bgimage: "",
|
||||
index: "",
|
||||
info: {
|
||||
date: "",
|
||||
list: [],
|
||||
nutrients_four: [],
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
qiunDataCharts
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "countFoodInfo", "configInfo"]),
|
||||
foodItem() {
|
||||
return this.configInfo.meal_list
|
||||
},
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.index = options.index
|
||||
that.bgimage = that.foodItem[options.index].icon_bg
|
||||
that.handleInfo()
|
||||
},
|
||||
watch: {
|
||||
user() {
|
||||
this.handleInfo()
|
||||
},
|
||||
countFoodInfo() {
|
||||
this.handleInfo()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInfo() {
|
||||
let that = this
|
||||
that.time = that.countFoodInfo.date
|
||||
that.info = that.countFoodInfo.list[that.index]
|
||||
let chart_data = []
|
||||
that.opts.color = []
|
||||
for (let i = 1; i < that.info.nutrients_four.length; ++i) {
|
||||
this.opts.color.push(that.info.nutrients_four[i].color)
|
||||
chart_data.push({
|
||||
name: that.info.nutrients_four[i].name,
|
||||
value: Number(that.info.nutrients_four[i].proportion),
|
||||
})
|
||||
}
|
||||
this.opts.title.name = that.info.val
|
||||
this.chartData = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
data: chart_data
|
||||
}]
|
||||
}));
|
||||
},
|
||||
// 详情
|
||||
showFoodDetail(item) {
|
||||
console.log("item", item)
|
||||
let that = this
|
||||
let chart_data = []
|
||||
this.activeFoodDetail = item
|
||||
this.drawerVisible = true;
|
||||
this.opts2.color = []
|
||||
for (let i = 1; i < item.nutrients_four.length; ++i) {
|
||||
this.opts2.color.push(item.nutrients_four[i].color)
|
||||
chart_data.push({
|
||||
name: item.nutrients_four[i].name,
|
||||
value: Number(item.nutrients_four[i].proportion),
|
||||
})
|
||||
}
|
||||
this.opts2.title.name = that.activeFoodDetail.val
|
||||
this.chartData2 = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
data: chart_data
|
||||
}]
|
||||
}));
|
||||
that.$nextTick(() => {
|
||||
// 延迟显示图表,确保容器已渲染
|
||||
setTimeout(() => {
|
||||
that.chartVisible = true
|
||||
}, 100)
|
||||
})
|
||||
},
|
||||
handleDrawerClose() {
|
||||
// 先隐藏图表,再隐藏抽屉
|
||||
this.chartVisible = false
|
||||
this.drawerVisible = false;
|
||||
},
|
||||
// 添加食物
|
||||
handleAddFood() {
|
||||
uni.navigateTo({
|
||||
url: "/Food/count/search?name=" + this.info.name + "&time=" + this.time
|
||||
})
|
||||
},
|
||||
// 删除食材
|
||||
delAcitionItem(item) {
|
||||
let that = this
|
||||
uni.showModal({
|
||||
content: `是否删除[${item.name}]?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.$model.delCEatAction({
|
||||
aud_id: that.user.aud_id,
|
||||
eat_log_id: item.id
|
||||
}).then(res => {
|
||||
// 删除最新一天食物
|
||||
that.$store.dispatch("getCountFoodInfo", {
|
||||
aud_id: that.user.aud_id,
|
||||
time: that.time
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
min-height: 100vh;
|
||||
background: #f7f7f7;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.content_box {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.quan {
|
||||
margin-right: 70rpx;
|
||||
}
|
||||
|
||||
.top {
|
||||
width: 100%;
|
||||
height: 280rpx;
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #dfdfdf;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
view {
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
image {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.everyDay {
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
margin: 15px 0 0;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
.progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.chart-wrap {
|
||||
position: relative;
|
||||
width: 280rpx;
|
||||
height: 280rpx;
|
||||
margin-top: -30rpx;
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-size: 24rpx;
|
||||
width: calc(100% - 270rpx);
|
||||
height: 200rpx;
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
|
||||
view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #ccc;
|
||||
margin: 0px 5px;
|
||||
}
|
||||
|
||||
.color {
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
margin-right: 10rpx;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.foodtools {
|
||||
margin-top: 15px;
|
||||
|
||||
.type {
|
||||
background: #fff;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
padding: 10px 10px 0;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
view {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.detail {
|
||||
color: #999;
|
||||
display: flex;
|
||||
font-size: 24rpx;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
margin-top: 15px;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
|
||||
image {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #f7f7f7;
|
||||
}
|
||||
|
||||
.weight {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-left: 10px;
|
||||
|
||||
text {
|
||||
margin: 0 10px;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nolist {
|
||||
image {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
view {
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin: 30rpx 0;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
height: 80vh !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<!-- -->
|
||||
<view class="kcal">
|
||||
<view class="set">
|
||||
<input type="digit" v-model="weight" placeholder="请输入" :focus="focus" @blur="handleBlur">
|
||||
<uni-icons v-if="weight!=''" type="close" size="24" class="uni-iocns" color="#999"
|
||||
@click="handleclear"></uni-icons>
|
||||
<view class="num">
|
||||
{{kcal.suggestion_kcal_unit}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="desc">
|
||||
{{kcal.suggestion_kcal_range_val}}
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="kcal">
|
||||
<view class="text">
|
||||
营养占比
|
||||
</view>
|
||||
<view class="slider">
|
||||
<llt-slider-range :model-value="rangeValue" @change="handleChange" />
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="item" v-for="(ite,ind) in nutrition.list">
|
||||
<icon class="iconfont" :class="ite.icon"></icon>
|
||||
<text>{{ite.name}}</text>
|
||||
<text>{{ite.proportion}}%</text>
|
||||
<view class="val">{{ite.val}}{{ite.unit}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="num">
|
||||
<view class="item" v-for="(ite,ind) in nutrition.describe">
|
||||
<text>{{ite}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="subbtn" @click="handleEditKcal">保存</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import lltSliderRange from '@/uni_modules/llt-slider-range/components/llt-slider-range/llt-slider-range.vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
weight: "",
|
||||
kcal: {},
|
||||
nutrition: {},
|
||||
focus: false,
|
||||
carbohydrate_v: 0,
|
||||
protein_v: 0,
|
||||
fat_v: 0,
|
||||
carbohydrate_p: 0,
|
||||
protein_p: 0,
|
||||
fat_p: 0,
|
||||
rangeValue: [0, 0]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user"]),
|
||||
info() {
|
||||
return this.user
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.handleList()
|
||||
},
|
||||
components: {
|
||||
lltSliderRange
|
||||
},
|
||||
methods: {
|
||||
handleList() {
|
||||
let that = this
|
||||
that.$model.getCountSetKcal({
|
||||
aud_id: that.user.aud_id
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
that.kcal = res.data.kcal
|
||||
that.nutrition = res.data.nutrition
|
||||
that.weight = res.data.kcal.suggestion_kcal_val
|
||||
that.rangeValue[0] = Number(that.nutrition.list[0].proportion)
|
||||
that.rangeValue[1] = Number(that.nutrition.list[0].proportion) + Number(that.nutrition
|
||||
.list[1].proportion)
|
||||
console.log("that.rangeValue", that.rangeValue)
|
||||
that.handleProportion()
|
||||
}
|
||||
})
|
||||
},
|
||||
handleChange(val) {
|
||||
let that = this
|
||||
that.rangeValue = val
|
||||
that.weight = that.weight ? that.weight : Number(that.kcal.suggestion_kcal_val)
|
||||
that.handleProportion()
|
||||
},
|
||||
handleProportion() {
|
||||
let that = this
|
||||
that.nutrition.list.forEach(ite => {
|
||||
if (ite.key_v == "carbohydrate") {
|
||||
ite.proportion = that.rangeValue[0]
|
||||
ite.val = Number(that.weight * ite.proportion / 100 / 4).toFixed(2)
|
||||
that.carbohydrate_v = ite.val
|
||||
that.carbohydrate_p = ite.proportion
|
||||
}
|
||||
if (ite.key_v == "protein") {
|
||||
ite.proportion = that.rangeValue[1] - that.rangeValue[0]
|
||||
ite.val = Number(that.weight * ite.proportion / 100 / 4).toFixed(2)
|
||||
that.protein_v = ite.val
|
||||
that.protein_p = ite.proportion
|
||||
|
||||
}
|
||||
if (ite.key_v == "fat") {
|
||||
ite.proportion = 100 - that.rangeValue[1]
|
||||
ite.val = Number(that.weight * ite.proportion / 100 / 9).toFixed(2)
|
||||
that.fat_v = ite.val
|
||||
that.fat_p = ite.proportion
|
||||
}
|
||||
})
|
||||
},
|
||||
handleBlur() {
|
||||
let that = this
|
||||
that.weight = that.weight ? that.weight : Number(that.kcal.suggestion_kcal_val)
|
||||
that.handleProportion()
|
||||
},
|
||||
handleEditKcal() {
|
||||
let that = this
|
||||
if (that.weight == '' || Number(that.weight) <= 0) {
|
||||
that.$tools.msg("请输入卡路里")
|
||||
return
|
||||
}
|
||||
that.$model.getCountSetUserKcal({
|
||||
aud_id: that.user.aud_id,
|
||||
set_kcal: that.weight,
|
||||
carbohydrate_v: that.carbohydrate_v,
|
||||
protein_v: that.protein_v,
|
||||
fat_v: that.fat_v,
|
||||
carbohydrate_p: that.carbohydrate_p,
|
||||
protein_p: that.protein_p,
|
||||
fat_p: that.fat_p,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
that.$tools.msg("设置成功")
|
||||
that.$store.dispatch('getUserInfo', {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
setTimeout(function() {
|
||||
uni.navigateBack()
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
},
|
||||
handleclear() {
|
||||
this.focus = true
|
||||
this.weight = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 30rpx;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.kcal {
|
||||
width: calc(100% - 40rpx);
|
||||
background: #fff;
|
||||
margin-bottom: 30rpx;
|
||||
padding: 20rpx;
|
||||
border-radius: 10px;
|
||||
|
||||
.set {
|
||||
width: calc(100% - 40rpx);
|
||||
background: #f7f7f7;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
position: relative;
|
||||
height: 45px;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.num {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.uni-iocns {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
line-height: 40rpx;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.slider {
|
||||
background: #f7f7f7;
|
||||
margin-top: 15px;
|
||||
border-radius: 10px;
|
||||
padding: -10px 0;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 15px;
|
||||
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 30%;
|
||||
background-color: #f7f7f7;
|
||||
justify-content: center;
|
||||
border-radius: 10px;
|
||||
|
||||
icon {
|
||||
font-size: 40px;
|
||||
color: $uni-color-warning;
|
||||
border-radius: 30%;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.val {
|
||||
width: 100%;
|
||||
background: #f7f7f7;
|
||||
border-radius: 10px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
padding: 2px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.num {
|
||||
display: flex;
|
||||
font-size: 24rpx;
|
||||
flex-direction: column;
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.subbtn {
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
border-radius: 20rpx;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
margin: 15px 0;
|
||||
background-color: #f0ae43;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,720 @@
|
|||
<template>
|
||||
<view class="content addFood" :class="[isBle?'maxheight':'']">
|
||||
<!-- 封面 -->
|
||||
<view class="topimg">
|
||||
<image :src="info.cover_pic_url" mode="aspectFill"></image>
|
||||
</view>
|
||||
<!-- 信息 -->
|
||||
<view class="title">
|
||||
<view class="table">{{info.title}}</view>
|
||||
<view class="user">
|
||||
<view class="left">
|
||||
<image :src="info.create_user_head_pic"></image>
|
||||
<text>{{info.create_user_nickname}}</text>
|
||||
</view>
|
||||
<view class="right">
|
||||
<uni-icons :type="info.collect_status=='yes'?'heart-filled':'heart'" size="20"
|
||||
:color="info.collect_status=='yes'?'red':'#999'"></uni-icons>
|
||||
<text class="ml-5">{{info.likes_num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="title title2">
|
||||
<view class="">菜谱类型:</view>
|
||||
<view>{{menu[cookIndex].name}}</view>
|
||||
</view>
|
||||
<!-- 食材 -->
|
||||
<view class="food">
|
||||
<view class="desc">
|
||||
{{info.description}}
|
||||
</view>
|
||||
<view class="h4">
|
||||
<view class="tags">
|
||||
<view class="tags-item" :class="[index ==ind?'active':'']" v-for="(item,ind) in info.tags"
|
||||
:key="ind" @click="handleToggle(ind)">{{item.title}}</view>
|
||||
</view>
|
||||
<view class="close" @click="handleWeight">
|
||||
<image src="../../static/lianjie.png"></image>
|
||||
连接测量
|
||||
</view>
|
||||
</view>
|
||||
<view class="foodlist">
|
||||
<view class="item" v-for="(ite,ind) in info.tags[index].list" :key="ind"
|
||||
v-if="info.tags&&info.tags[index].list.length">
|
||||
<view class="name" style="flex: 1;">{{ite.name}}</view>
|
||||
<view class="weight">
|
||||
{{ite.weight}}{{ite.unit}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 步骤 -->
|
||||
<view class="step">
|
||||
<view class="stepList" v-for="(ite,ind) in info.step_list" :key="ind"
|
||||
v-if="info.step_list&&info.step_list.length">
|
||||
<view class="top">
|
||||
<text>{{ite.step_num}}</text>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="desc">
|
||||
{{ite.description}}
|
||||
</view>
|
||||
<view class="image" v-for="(it,id) in ite.pic_url_list">
|
||||
<image :src="it" mode="aspectFill" class="mt-10"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 底部操作 -->
|
||||
<view class="foot">
|
||||
<view class="item" @click="handleCang()">
|
||||
<uni-icons :type="info.collect_status=='yes'?'heart-filled':'heart'" size="20"
|
||||
:color="info.collect_status=='yes'?'red':'#999'"></uni-icons>
|
||||
<text>收藏</text>
|
||||
</view>
|
||||
<!-- <view class="item" v-if="type=='我的菜谱'" @click="handleEdit()">
|
||||
<icon class="iconfont icon-bianji"></icon>
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="item" v-if="type=='我的菜谱'" @click="handledel()">
|
||||
<icon class="iconfont icon-ashbin"></icon>
|
||||
<text>删除</text>
|
||||
</view> -->
|
||||
</view>
|
||||
<!--蓝牙连接区 -->
|
||||
<view class="wrapper" v-if="isBle">
|
||||
<view class="bg" @click="isBle = false">
|
||||
<view class="box weightBox">
|
||||
<icon class="iconfont icon-error" @click='isBle = false'></icon>
|
||||
<view class="foodlist" @click.stop>
|
||||
<view class="text">
|
||||
<text style="width: 30%;">食材</text>
|
||||
<text style="width: 18%;">建议</text>
|
||||
<view class="kcal">
|
||||
<text>重量</text>
|
||||
<text>热量</text>
|
||||
<text>重秤</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite,ind) in info.tags[0].list" :key="ind"
|
||||
v-if="info.tags&&info.tags[0].list.length"
|
||||
:class="[activeType.id&&activeType.id ==ite.id&&!ite.newweight?'active2':'']">
|
||||
<view class="name">{{ite.name}}</view>
|
||||
<view class="num" style="width: 18%;">
|
||||
{{ite.weight}}{{ite.unit}}
|
||||
</view>
|
||||
<view class="kcal" v-if="activeType.id&&activeType.id ==ite.id&&!ite.newweight">
|
||||
正在测量...
|
||||
</view>
|
||||
<view class="kcal" v-else>
|
||||
<view class="num" v-if="ite.newweight">
|
||||
{{ite.newweight}}{{ite.newunit}}
|
||||
</view>
|
||||
<view class="num" v-if="ite.newkcal">
|
||||
{{ite.newkcal}}
|
||||
</view>
|
||||
<view class="refreshempty
|
||||
" @click="handlechongzhi(ite,ind)" v-if="ite.newweight">
|
||||
<uni-icons type="refreshempty" size="22"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="blue-tooth" :style="{display: (!isWeightType&&iSWeightSub) ? '' : 'none'}" @click.stop>
|
||||
<blue-tooth ref="blueTooth" @handleDetailNext="handleDetailNext"
|
||||
@handleDetailSub="handleDetailSub" :weightKcal="weightKcal" :name="activeType.name"
|
||||
:isLast="isLast" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="saveFood" v-if="showSaveFood">
|
||||
<view class="saveFoodInner">
|
||||
<view class="title">是否保存至“计食”为今日饮食?</view>
|
||||
<view class="types">
|
||||
<view class="type-item" :class="{'active':selectSaveType == index}" v-for="(item,index) in foodItem"
|
||||
:key="index" @click="selectSaveType=index">{{item.name}}</view>
|
||||
</view>
|
||||
<view class="btn-wrap">
|
||||
<view class="confirm" @click="confirmSaveFood">确定</view>
|
||||
<view class="cancel" @click="showSaveFood=false">取消</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import blueTooth from "@/components/foodIndex/bluetooth.vue"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
type: "",
|
||||
info: {},
|
||||
id: null,
|
||||
index: 0,
|
||||
isLast: false,
|
||||
weightKcal: null,
|
||||
weightType: 0,
|
||||
activeType: {},
|
||||
isBle: false,
|
||||
isWeightType: true,
|
||||
iSWeightSub: true,
|
||||
listInd: 0,
|
||||
cookIndex: null,
|
||||
showSaveFood: false,
|
||||
selectSaveType: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "configInfo", "bleValue"]),
|
||||
menu() {
|
||||
return this.configInfo.cookbook_label
|
||||
},
|
||||
foodItem() {
|
||||
return this.configInfo.meal_list
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
},
|
||||
components: {
|
||||
blueTooth
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
let info = {}
|
||||
if (options && options.info) {
|
||||
info = JSON.parse(options.info)
|
||||
that.type = info.pageName
|
||||
that.info = info
|
||||
} else {
|
||||
that.type = options.title
|
||||
}
|
||||
that.id = options.id
|
||||
that.handleHomeInfo(options.id)
|
||||
},
|
||||
methods: {
|
||||
handleToggle(ind) {
|
||||
this.index = ind
|
||||
},
|
||||
handleHomeInfo(id) {
|
||||
let that = this
|
||||
that.$model.getCookListDetails({
|
||||
cookbook_id: id,
|
||||
aud_id: that.user.aud_id
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.info = res.data
|
||||
console.log("11111111",that.menu,res.data.cook_label)
|
||||
that.cookIndex = that.menu.findIndex(ite => ite.id == res.data.cook_label)
|
||||
if (that.bleValue.serviceId != '') {
|
||||
that.handleWeight()
|
||||
}
|
||||
})
|
||||
},
|
||||
//连接测量
|
||||
handleWeight() {
|
||||
let that = this
|
||||
if (that.isBle) {
|
||||
return
|
||||
}
|
||||
that.listInd = 0
|
||||
that.isBle = true
|
||||
that.isLast = false
|
||||
that.iSWeightSub = true
|
||||
that.isWeightType = false
|
||||
that.activeType = that.info.tags[0].list[0]
|
||||
that.weightKcal = Number(Number(that.activeType.kcal) / 100).toFixed(2)
|
||||
if (that.info.tags[0].list.length == 1) {
|
||||
that.isLast = true
|
||||
}
|
||||
},
|
||||
// 下一位
|
||||
handleDetailNext(weight, dw, kcal) {
|
||||
let that = this
|
||||
let ind = that.info.tags[0].list.findIndex(ite => ite.id == that.activeType.id)
|
||||
that.info.tags[0].list[ind].newweight = weight
|
||||
that.info.tags[0].list[ind].newunit = dw
|
||||
that.info.tags[0].list[ind].newkcal = kcal
|
||||
that.listInd = that.listInd + 1
|
||||
that.activeType = that.info.tags[0].list[ind + 1]
|
||||
that.weightKcal = Number(Number(that.activeType.kcal) / 100).toFixed(2)
|
||||
that.info.tags[0].list[that.listInd].newweight = ""
|
||||
that.info.tags[0].list[that.listInd].newunit = ""
|
||||
that.info.tags[0].list[that.listInd].newkcal = ""
|
||||
if (that.listInd == that.info.tags[0].list.length - 1 || that.listInd == that.info.tags[0].list.length) {
|
||||
that.isLast = true
|
||||
console.log('已经测量完成')
|
||||
}
|
||||
},
|
||||
// 结束测量
|
||||
handleDetailSub(weight, dw, kcal) {
|
||||
let that = this
|
||||
let ind = that.info.tags[0].list.findIndex(ite => ite.id == that.activeType.id)
|
||||
that.info.tags[0].list[ind].newweight = weight
|
||||
that.info.tags[0].list[ind].newunit = dw
|
||||
that.info.tags[0].list[ind].newkcal = kcal
|
||||
that.showSaveFood = true
|
||||
},
|
||||
//重置
|
||||
handlechongzhi(ite, ind) {
|
||||
let that = this
|
||||
let weight = that.info.tags[0].list[ind].newweight
|
||||
that.listInd = ind
|
||||
that.isLast = false
|
||||
that.activeType = ite
|
||||
that.weightKcal = Number(Number(ite.kcal) / 100).toFixed(2)
|
||||
that.info.tags[0].list[ind].newweight = ""
|
||||
that.info.tags[0].list[ind].newunit = ""
|
||||
that.info.tags[0].list[ind].newkcal = ""
|
||||
if (that.listInd == that.info.tags[0].list.length - 1 || that.listInd == that.info.tags[0].list.length) {
|
||||
that.isLast = true
|
||||
}
|
||||
},
|
||||
//保存测量结果到计时器
|
||||
confirmSaveFood() {
|
||||
let that = this
|
||||
let newFoodList = []
|
||||
for (let i = 0; i < that.info.tags[0].list.length; ++i) {
|
||||
if (that.info.tags[0].list[i].newweight) {
|
||||
newFoodList.push({
|
||||
meals_type: that.foodItem[that.selectSaveType].name,
|
||||
id: that.info.tags[0].list[i].id,
|
||||
weight: that.info.tags[0].list[i].newweight,
|
||||
unit: that.info.tags[0].list[i].newunit
|
||||
})
|
||||
}
|
||||
}
|
||||
console.log("newFoodList", that.info.tags[0].list, newFoodList)
|
||||
if (newFoodList.length > 0) {
|
||||
that.$model.getAddIntakeFood({
|
||||
aud_id: that.user.aud_id,
|
||||
food_list: newFoodList,
|
||||
time: that.$tools.getDate("start")
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.$store.dispatch("getUserInfoFood")
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// uni.switchTab({
|
||||
// url: "/pages/count/count"
|
||||
// })
|
||||
})
|
||||
}
|
||||
that.showSaveFood = false
|
||||
that.iSWeightSub = false
|
||||
that.isBle = false
|
||||
},
|
||||
handleCang() {
|
||||
let that = this
|
||||
that.$model.getCookLike({
|
||||
cookbook_id: that.id,
|
||||
aud_id: that.user.aud_id
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.info.likes_num = res.data.likes_num
|
||||
that.info.collect_status = res.data.collect_status
|
||||
})
|
||||
},
|
||||
handleEdit() {
|
||||
uni.navigateTo({
|
||||
url: "/Food/me/menuEdit?info=" + JSON.stringify(this.info)
|
||||
})
|
||||
},
|
||||
handledel() {
|
||||
let that = this
|
||||
uni.showModal({
|
||||
title: '友情提示',
|
||||
content: '是否删除当前菜谱?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
that.$model.getMyCookbookDel({
|
||||
aud_id: that.user.aud_id,
|
||||
cookbook_id: that.id,
|
||||
}).then((res) => {
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.message)
|
||||
return
|
||||
}
|
||||
that.$tools.msg("删除成功")
|
||||
uni.navigateBack()
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
that.$tools.msg("您已取消操作!");
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.maxheight {
|
||||
max-height: 90vh !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topimg {
|
||||
width: 100%;
|
||||
height: 340rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
margin: 20rpx 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.iconfont {
|
||||
font-size: 60rpx;
|
||||
color: $maincolor;
|
||||
}
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.step {
|
||||
.image {
|
||||
height: 340rpx;
|
||||
margin: auto;
|
||||
background: #f7f7f7;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
display: inline-table;
|
||||
}
|
||||
|
||||
icon {
|
||||
font-size: 60rpx;
|
||||
color: #ff4c4f;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 20rpx;
|
||||
|
||||
.table {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 30rpx;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-right: 5px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
width: 100%;
|
||||
line-height: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.h4 {
|
||||
margin: 20rpx 0;
|
||||
padding-top: 20rpx;
|
||||
border-top: 1px solid #f7f7f7;
|
||||
|
||||
.tags {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.tags-item {
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-bottom: 2px solid #ff4c4f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.close {
|
||||
color: #fff;
|
||||
width: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 20rpx;
|
||||
background-color: $maincolor;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step {
|
||||
margin-bottom: 85px;
|
||||
}
|
||||
|
||||
.foodlist {
|
||||
border-radius: 20rpx;
|
||||
background: #fff;
|
||||
|
||||
.item {
|
||||
margin-top: 0 !important;
|
||||
border-radius: 0px !important;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
}
|
||||
|
||||
.name {
|
||||
border-right: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 5px 0px 40rpx;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
|
||||
.item {
|
||||
width: 25%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
icon,
|
||||
image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
.weightBox {
|
||||
top: 40px;
|
||||
background: #dfdfdf;
|
||||
|
||||
.icon-error {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
top: -40rpx;
|
||||
background: #fff;
|
||||
font-size: 80rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.foodlist {
|
||||
border-radius: 0;
|
||||
height: 40%;
|
||||
overflow: scroll;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
margin-top: 30rpx;
|
||||
font-size: 14px;
|
||||
|
||||
.text {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: calc(30% - 10px);
|
||||
text-align: left !important;
|
||||
white-space: nowrap;
|
||||
overflow-x: auto;
|
||||
font-weight: inherit;
|
||||
font-size: 28rpx;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.kcal {
|
||||
width: 52% !important;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.blue-tooth {
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
position: relative;
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.groupbtn {
|
||||
position: absolute;
|
||||
left: 30rpx;
|
||||
right: 30rpx;
|
||||
width: auto;
|
||||
bottom: 100rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.saveFood {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
z-index: 99999;
|
||||
|
||||
.saveFoodInner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80%;
|
||||
padding: 30rpx 20rpx;
|
||||
padding-bottom: 0;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.types {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
width: 100%;
|
||||
|
||||
.type-item {
|
||||
width: 22%;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
border: 1px solid #f1f1f1;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
&.active {
|
||||
border-color: #ff4c4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-wrap {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin-top: 30rpx;
|
||||
border-top: 1px solid #f1f1f1;
|
||||
|
||||
view {
|
||||
width: 50%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
view:first-child {
|
||||
border-right: 1px solid #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.active2 {
|
||||
color: #8284f0;
|
||||
font-weight: bold;
|
||||
background: #ecedff;
|
||||
}
|
||||
|
||||
.title2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<!-- 搜索 -->
|
||||
<search @handleSearch="handleSearch"></search>
|
||||
<!-- 食谱 -->
|
||||
<view class="footlist footbox" v-if="menuList.length">
|
||||
<view class="list" v-for="(it,id) in menuList" :key="it" @click="handleDetail(it.id)">
|
||||
<view class="topimg">
|
||||
<image :src="it.cover_url" class="img" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="title">{{it.title}}</view>
|
||||
<view class="name">
|
||||
<image :src="it.create_user_head_pic"></image>
|
||||
<text class="overflow">{{it.create_user_nickname}}</text>
|
||||
</view>
|
||||
<view class="zan" @click="handleZan(it)">
|
||||
<image class="mr-5 xin" :src="it.is_me_like_it=='yes'?'/static/xin2.png':'/static/xin.png'">
|
||||
</image>
|
||||
<text>{{it.likes_num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="endtext" v-if="(!lastPage || page >= lastPage)&&menuList.length">—— 到底了,看看别的吧 ——</view>
|
||||
<view v-if="!menuList.length" class="nolist">
|
||||
<icon class="iconfont icon-wancan"></icon>
|
||||
<text>还没有记录哦</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import search from "@/components/foodIndex/search.vue"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
type: "",
|
||||
name: "",
|
||||
page: 1,
|
||||
menuList: [],
|
||||
lastPage: '',
|
||||
}
|
||||
},
|
||||
components: {
|
||||
search
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user"]),
|
||||
info() {
|
||||
return this.user
|
||||
}
|
||||
},
|
||||
onLoad(option) {
|
||||
let that = this
|
||||
that.type = option.pageName
|
||||
uni.setNavigationBarTitle({
|
||||
title: option.pageName
|
||||
});
|
||||
|
||||
},
|
||||
onShow() {
|
||||
let that = this
|
||||
that.name = ""
|
||||
that.page = 1
|
||||
that.menuList = []
|
||||
that.handleCooklist()
|
||||
},
|
||||
onReachBottom() {
|
||||
let that = this
|
||||
if (!this.lastPage || this.page >= this.lastPage) {
|
||||
uni.showToast({
|
||||
title: '没有更多数据!',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.page++
|
||||
this.handleCooklist(this.page)
|
||||
},
|
||||
methods: {
|
||||
handleCooklist() {
|
||||
let that = this
|
||||
that.$model.getUserCollectList({
|
||||
page: that.page,
|
||||
aud_id: that.user.aud_id,
|
||||
search_data: that.name
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.menuList = res.data.content_list
|
||||
that.lastPage = res.data.page_total
|
||||
})
|
||||
},
|
||||
// 商品详情
|
||||
handleDetail(id) {
|
||||
uni.navigateTo({
|
||||
url: "/Food/me/menudetail?id=" + id + '&title=' + this.type
|
||||
})
|
||||
},
|
||||
// 搜索
|
||||
handleSearch(ite) {
|
||||
let that = this
|
||||
that.page = 1
|
||||
that.name = ite
|
||||
that.menuList = []
|
||||
that.lastPage = ""
|
||||
that.handleCooklist()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.xin {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
/deep/.serachBox {
|
||||
padding-top: 20rpx !important;
|
||||
}
|
||||
|
||||
.footlist {
|
||||
position: relative;
|
||||
margin-top: 68px;
|
||||
padding: 30rpx;
|
||||
width: calc(100% - 60rpx);
|
||||
background: #fff;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
|
||||
.item {
|
||||
background: #f7f7f7 !important;
|
||||
border-top: 1px solid #f7f7f7;
|
||||
}
|
||||
}
|
||||
|
||||
.nolist {
|
||||
margin-top: 50%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<!-- 列表 -->
|
||||
<view class="box">
|
||||
<view class="list" v-for="(item,ind) in infoList" :key="ind" @click="handleDetail(item)">
|
||||
<view class="time">{{item.time}}</view>
|
||||
<view class="kcal">
|
||||
<view>摄入卡路里<text>{{item.val}}</text>{{item.unit}}</view>
|
||||
<view class="status">
|
||||
<text class="quan0" :style="'background:'+item.color"></text>
|
||||
{{item.describe}}
|
||||
</view>
|
||||
<uni-icons type="forward" size="20" color="#666"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="endtext" v-if="!lastPage || page >= lastPage">—— 到底了,看看别的吧 ——</view>
|
||||
<view v-if="!infoList.length" class="nolist">
|
||||
<icon class="iconfont icon-wancan"></icon>
|
||||
<text>还没有记录哦</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
page: 1,
|
||||
lastPage: '',
|
||||
infoList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user"]),
|
||||
end() {
|
||||
return this.$tools.getTime()
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
that.page = 1
|
||||
that.handleList()
|
||||
},
|
||||
onReachBottom() {
|
||||
let that = this
|
||||
if (!this.lastPage || this.page >= this.lastPage) {
|
||||
uni.showToast({
|
||||
title: '没有更多数据!',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.page++
|
||||
this.handleList(this.page)
|
||||
},
|
||||
methods: {
|
||||
handleList() {
|
||||
let that = this
|
||||
that.$model.getMyLogList({
|
||||
aud_id: that.user.aud_id,
|
||||
page: that.page,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
that.infoList = that.infoList.concat(res.data.content_list)
|
||||
that.lastPage = res.data.page_total
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDetail(item) {
|
||||
let that = this
|
||||
that.$store.dispatch("getCountFoodInfo", {
|
||||
aud_id: that.user.aud_id,
|
||||
time: item.time
|
||||
})
|
||||
uni.navigateTo({
|
||||
url: '/Food/me/recordetail'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="scoped" lang="scss">
|
||||
.content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-top: 30rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.list {
|
||||
color: #999;
|
||||
width: calc(100% - 60rpx);
|
||||
background: #fff;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 30rpx;
|
||||
padding: 20rpx 30rpx;
|
||||
|
||||
|
||||
.time {
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.kcal {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin: 0 3px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.status {
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
.quan0 {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background: $uni-color-warning;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<template>
|
||||
<view>
|
||||
<food></food>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import food from "@/components/foodIndex/foodHome.vue"
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
food,
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "countFoodInfo"]),
|
||||
foodInfo() {
|
||||
return this.countFoodInfo
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<search :name="search_value"></search>
|
||||
<view class="footbox footlist" v-if="food_search_list.length">
|
||||
<view class="list" v-for="(it,ind) in food_search_list" :key="ind" @click="handleDetail(it.id)">
|
||||
<view class="topimg">
|
||||
<image :src="it.cover" class="img" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="title">{{it.title}}</view>
|
||||
<view class="name">
|
||||
<image :src="it.create_user_head_pic"></image>
|
||||
<text class="overflow">{{it.create_user_nickname}}</text>
|
||||
</view>
|
||||
<view class="zan">
|
||||
<uni-icons :type="it.is_me_like_it=='yes'?'heart-filled':'heart'" size="20" :color="it.is_me_like_it=='yes'?'red':'#999'"></uni-icons>
|
||||
<text>{{it.likes_num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="endtext" v-if="!lastPage || Page >= lastPage">—— 到底了,看看别的吧 ——</view>
|
||||
<view v-if="!food_search_list.length" class="nolist">
|
||||
<icon class="iconfont icon-wancan"></icon>
|
||||
<text>还没有记录哦</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import search from '@/components/foodIndex/search2.vue';
|
||||
export default {
|
||||
name: "list",
|
||||
data() {
|
||||
return {
|
||||
Page: 1,
|
||||
lastPage: 1,
|
||||
search_value: "",
|
||||
food_search_list: [],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
components: {
|
||||
search
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user"]),
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.search_value = options.name
|
||||
that.handleSearchColumn()
|
||||
},
|
||||
onReachBottom() {
|
||||
let that = this
|
||||
console.log("onReachBottom", this.lastPage)
|
||||
if (!this.lastPage || this.Page >= this.lastPage) {
|
||||
uni.showToast({
|
||||
title: '没有更多数据!',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.Page++
|
||||
this.handleSearchColumn()
|
||||
},
|
||||
methods: {
|
||||
handleSearchColumn() {
|
||||
let that = this
|
||||
that.$model.getMenuSearchColumn({
|
||||
page: that.Page,
|
||||
aud_id: that.user.aud_id,
|
||||
search_data: that.search_value
|
||||
}).then(res => {
|
||||
if (res.code != 0 || res.data instanceof Array) return
|
||||
that.food_search_list = that.food_search_list.concat(res.data.content_list)
|
||||
that.lastPage = res.data.page_total
|
||||
})
|
||||
},
|
||||
// 商品详情
|
||||
handleDetail(id) {
|
||||
let that = this
|
||||
if (that.user.aud_id == '') {
|
||||
that.$tools.msg("完善资料后查看更多")
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: "/Food/me/menudetail?id=" + id
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
background: #fff;
|
||||
min-height: calc(100vh - 40rpx);
|
||||
}
|
||||
|
||||
.footlist {
|
||||
position: relative;
|
||||
margin-top: 68px;
|
||||
padding: 30rpx;
|
||||
width: calc(100% - 60rpx);
|
||||
background: #fff;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
}
|
||||
|
||||
|
||||
.list {
|
||||
border: 1px solid #f7f7f7;
|
||||
|
||||
.item {
|
||||
background: #f7f7f7;
|
||||
border-top: 1px solid #f7f7f7;
|
||||
}
|
||||
}
|
||||
|
||||
.topimg {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="search">
|
||||
<input type="text" v-model="search_value" placeholder="输入关键字匹配食谱" />
|
||||
<icon v-if="search_value" class="iconfont icon-error" @click="handlecolse"></icon>
|
||||
<image src="/static/28.png" @click="handleSearchHistory(search_value)"></image>
|
||||
</view>
|
||||
|
||||
<view class="content-box">
|
||||
<!-- 历史搜索 -->
|
||||
<view v-if="history_food.length" class="search-history">
|
||||
<view class="title">
|
||||
<view class="quan mr-5"></view>历史搜索
|
||||
</view>
|
||||
<view class="button-container" @click="showAll =! showAll" v-if="history_food.length>8">
|
||||
<image :src="showAll?'/static/arrow-up.png':'/static/arrow-down.png'"></image>
|
||||
</view>
|
||||
<view class="history-list">
|
||||
<view class="history-list-item"
|
||||
v-for="(item,index) in showAll?history_food:history_food.slice(0, 8)"
|
||||
@click="handleSearchHistory(item.keyword)">
|
||||
{{item.keyword}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 猜你想搜 -->
|
||||
<view class="popular-container">
|
||||
<view class="title">
|
||||
<view class="quan mr-5"></view>猜你想搜
|
||||
</view>
|
||||
<view class="popular-food-item" v-for="(ite,index) in popular_food" :key="index">
|
||||
<view class="food-title">{{ite.title}}</view>
|
||||
<view class="popular-food-inner">
|
||||
<text class="popular-food-subitem" v-for="(sub_item,sub_index) in ite.list"
|
||||
@click="handleSearchHistory(sub_item.name)" :key="sub_index">{{sub_item.name}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 语音 -->
|
||||
<view class="footBtn">
|
||||
<view class="mic-icon" @touchstart="onVoiceTouchStart" @touchend="onVoiceTouchEnd"
|
||||
@touchcancel="cancelRecording">
|
||||
<uni-icons type="mic-filled" size="20" color="#fff"></uni-icons>
|
||||
语音搜索
|
||||
</view>
|
||||
</view>
|
||||
<!-- 语音弹框 -->
|
||||
<view class="wrapper" v-if="showAutoSearchDlg">
|
||||
<view class="auto-search-dialog">
|
||||
<view class="auto-search-inner">
|
||||
<view class="voice-wave">
|
||||
<view class="wave-bar"></view>
|
||||
<view class="wave-bar"></view>
|
||||
<view class="wave-bar"></view>
|
||||
<view class="wave-bar"></view>
|
||||
<view class="wave-bar"></view>
|
||||
<view class="wave-bar"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
const plugin = requirePlugin("WechatSI")
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
index: 0,
|
||||
Page: 1,
|
||||
showAll: false,
|
||||
search_value: '',
|
||||
showAutoSearchDlg: false,
|
||||
voiceManager: null,
|
||||
popular_food: [],
|
||||
history_food: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user"]),
|
||||
// popular_food() {
|
||||
// return this.configInfo.search_guess.cookbook
|
||||
// },
|
||||
// history_food() {
|
||||
// return this.configInfo.search_history.cookbook
|
||||
// }
|
||||
},
|
||||
onShow() {
|
||||
this.handleList()
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
that.voiceManager = plugin.getRecordRecognitionManager()
|
||||
that.voiceManager.onStop = function(res) {
|
||||
that.handleSearchHistory(res.result.replace('。', ''))
|
||||
}
|
||||
that.voiceManager.onError = function(res) {
|
||||
console.error("error msg", res.retcode)
|
||||
}
|
||||
that.voiceManager.stop()
|
||||
},
|
||||
methods: {
|
||||
//
|
||||
handleList() {
|
||||
let that = this
|
||||
that.$model.getCountSearchmsg({
|
||||
aud_id: that.user.aud_id
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
that.history_food = res.data.search_history.cookbook
|
||||
that.popular_food = res.data.search_guess.cookbook
|
||||
}
|
||||
})
|
||||
},
|
||||
// 切换显示全部/部分
|
||||
toggleShowAll() {
|
||||
this.showAll = !this.showAll
|
||||
},
|
||||
onVoiceTouchStart() {
|
||||
let that = this
|
||||
that.showAutoSearchDlg = true
|
||||
that.voiceManager.start({
|
||||
duration: 60000,
|
||||
lang: "zh_CN"
|
||||
})
|
||||
},
|
||||
onVoiceTouchEnd() {
|
||||
let that = this
|
||||
that.showAutoSearchDlg = false
|
||||
that.voiceManager.stop()
|
||||
},
|
||||
// 取消录音
|
||||
cancelRecording() {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (this.voiceManager) {
|
||||
this.voiceManager.stop()
|
||||
this.showAutoSearchDlg = false
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
handlecolse() {
|
||||
console.log("取消搜索")
|
||||
this.search_value = ""
|
||||
this.search_list = []
|
||||
},
|
||||
// 历史搜索
|
||||
handleSearchHistory(text) {
|
||||
let that = this
|
||||
if (text == "") {
|
||||
that.$tools.msg("输入关键字后搜索")
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: "/Food/search/list?name=" + text
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
.search {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding-bottom: 35px;
|
||||
padding-top: 20rpx;
|
||||
background-color: $maincolor;
|
||||
|
||||
|
||||
input {
|
||||
width: calc(100% - 80rpx);
|
||||
background: #fff;
|
||||
height: 39px;
|
||||
line-height: 38px;
|
||||
border-radius: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.input:hover {
|
||||
box-shadow: 0 1rpx 20rpx #ccc;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
position: absolute;
|
||||
right: 40rpx;
|
||||
top: 18px;
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
.content-box {
|
||||
background: #fff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
position: relative;
|
||||
z-index: 99;
|
||||
width: 100%;
|
||||
padding-top: -13px;
|
||||
margin: -40rpx 0 70px;
|
||||
}
|
||||
|
||||
.search-history {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
uni-icons {
|
||||
color: #333333;
|
||||
font-size: 60rpx;
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
right: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.history-list {
|
||||
width: calc(100% - 40rpx);
|
||||
margin: 20rpx 20rpx 0;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.history-list-item {
|
||||
border: 1px solid #dfdfdf;
|
||||
padding: 3px 24rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 90%;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
margin-top: 30rpx;
|
||||
margin-left: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.popular-container {
|
||||
width: 100%;
|
||||
|
||||
.popular-food-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 20rpx;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 20rpx;
|
||||
background: linear-gradient(#EDFFF4, #ffffff 80%);
|
||||
|
||||
.food-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.popular-food-inner {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.popular-food-subitem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
background-color: #fff;
|
||||
margin-right: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 1px solid #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search_list {
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 90px;
|
||||
margin-top: 30rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.search_list_item {
|
||||
width: 30%;
|
||||
margin-top: 30rpx;
|
||||
text-align: center;
|
||||
|
||||
image {
|
||||
width: 220rpx;
|
||||
height: 220rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.auto-search-dialog {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
bottom: 60px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
|
||||
.auto-search-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: 50%;
|
||||
padding: 60rpx 0;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 0 20rpx #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.footBtn {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
padding-top: 30rpx;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
z-index: 99;
|
||||
justify-content: space-around;
|
||||
|
||||
view {
|
||||
color: #fff;
|
||||
width: 80%;
|
||||
padding: 8px 40rpx;
|
||||
background: $maincolor;
|
||||
margin-bottom: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-container {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 30rpx;
|
||||
font-size: 40rpx;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-error {
|
||||
color: #888484;
|
||||
position: absolute;
|
||||
right: 120rpx;
|
||||
top: 18px;
|
||||
z-index: 999;
|
||||
font-size: 24px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<!-- tabbar -->
|
||||
<!-- 曲线 -->
|
||||
<view class="charts">
|
||||
<view class="TrendPage">
|
||||
<!-- 时间选择 -->
|
||||
<view class="boxTime">
|
||||
<picker mode="date" :end="endDate" @change="handStartTimeH" :fields="fields"
|
||||
:value="startTime?startTime:startDate">
|
||||
<view class="uni-input mr-10">{{startTime?startTime:startDate}}
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="center">~</view>
|
||||
<picker mode="date" :end="endDate" @change="handEndTimeH" :fields="fields"
|
||||
:value="endTime?endTime:endDate">
|
||||
<view class="uni-input mr-10">{{endTime?endTime:endDate}}
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
<!-- 曲线图 -->
|
||||
<view class="box" v-if="weightList.length">
|
||||
<view class="listC">
|
||||
<view :class="{active2:index==active1}" class="name" v-for="(item,index) in weightList"
|
||||
:key="index" @click="showbox(index)">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="blockC">
|
||||
<view v-if="handTrue&&lineData.categories&&lineData.categories.length">
|
||||
<qiunDataCharts type="area" :chartData="lineData" :canvas2d="true" canvasId="charts09"
|
||||
:animation="false" :Width="340" :Height="250"
|
||||
:opts="{enableScroll:true,xAxis:{scrollShow:false,itemCount:3}}" :ontouch="true" />
|
||||
</view>
|
||||
<view class="box" v-else>
|
||||
<view class="nolist">
|
||||
<image src="../../static/none.png"></image>
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box" v-else>
|
||||
<view class="nolist">
|
||||
<image src="../../static/none.png"></image>
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 目标-->
|
||||
<view class="gridList">
|
||||
<view class="data">
|
||||
<view class="item" @click="handleClick(1)">
|
||||
<view class="val">
|
||||
{{target_weight}}<text>kg</text>
|
||||
</view>
|
||||
<view class="name">目标体重<uni-icons class="iconfont icon-bianji" color="#FEC407"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="val">
|
||||
{{Math.abs(calculate_val)}}<text>kg</text>
|
||||
</view>
|
||||
<view class="name" v-if="Number(calculate_val)>0">累计增重</view>
|
||||
<view class="name" v-else>累计减重</view>
|
||||
</view>
|
||||
<view class="item" @click="handleClick(2)">
|
||||
<view class="val">
|
||||
{{initial_weight}}<text>kg</text>
|
||||
</view>
|
||||
<view class="name">初始体重<uni-icons class="iconfont icon-bianji" color="#FEC407"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="val">
|
||||
{{calculate_time}}<text>天</text>
|
||||
</view>
|
||||
<view class="name">减重天数</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 初始 -->
|
||||
<firstweight @handleLabelList="handleLabelList"></firstweight>
|
||||
<!-- 目标 -->
|
||||
<targetWeight @handleLabelList="handleLabelList"></targetWeight>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import firstweight from '@/components/bodyIndex/firstweight.vue';
|
||||
import targetWeight from '@/components/bodyIndex/targetWeight.vue'
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
fields: "",
|
||||
active1: 0,
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
lineData: {},
|
||||
weightList: [],
|
||||
handTrue: true,
|
||||
target_weight: 0, //目标体重
|
||||
initial_weight: 0, //初始体重
|
||||
calculate_val: 0, //累计减重
|
||||
calculate_time: 0, //减重天数
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
firstweight,
|
||||
targetWeight,
|
||||
qiunDataCharts,
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
that.handleLabelList(that.endDate, that.startDate)
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
let that = this
|
||||
that.handleLabelList(that.endDate, that.startDate)
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
}, 1000);
|
||||
},
|
||||
methods: {
|
||||
handleLabelList(startTime, endDate) {
|
||||
let that = this
|
||||
that.$model.getTrendList({
|
||||
aud_id: that.user.aud_id,
|
||||
s_time: endDate,
|
||||
e_time: startTime
|
||||
}).then(res => {
|
||||
console.log("趋势", res)
|
||||
if (res.code == 0) {
|
||||
that.weightList = res.data.curve_list
|
||||
that.target_weight = res.data.target_weight
|
||||
that.calculate_val = res.data.calculate_val
|
||||
that.initial_weight = res.data.initial_weight
|
||||
that.calculate_time = res.data.calculate_time
|
||||
that.showbox(0)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
showbox(index) {
|
||||
let that = this
|
||||
that.handTrue = false
|
||||
that.$nextTick(function() {
|
||||
that.handTrue = true
|
||||
that.lineData = that.weightList.length ? that.weightList[index].line : {},
|
||||
console.log("11111", that.lineData)
|
||||
})
|
||||
that.active1 = index
|
||||
},
|
||||
//开始
|
||||
handStartTimeH(e) {
|
||||
let that = this
|
||||
if (that.endTime) {
|
||||
if (Date.parse(e.detail.value) > Date.parse(that.endTime)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (Date.parse(e.detail.value) > Date.parse(that.endDate)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
}
|
||||
that.startTime = e.detail.value
|
||||
let endtime = that.endTime ? that.endTime : that.endDate
|
||||
that.handleLabelList(endtime, that.startTime)
|
||||
that.showbox(0)
|
||||
},
|
||||
// 结束
|
||||
handEndTimeH(e) {
|
||||
let that = this
|
||||
if (that.startTime) {
|
||||
if (Date.parse(e.detail.value) < Date.parse(that.startTime)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (Date.parse(e.detail.value) < Date.parse(that.startDate)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
}
|
||||
that.endTime = e.detail.value
|
||||
let startTime = that.startTime ? that.startTime : that.startDate
|
||||
that.handleLabelList(that.endTime, startTime)
|
||||
that.showbox(0)
|
||||
},
|
||||
handleClick(ind) {
|
||||
if (ind == 1) {
|
||||
this.$store.commit("changeTarget", true);
|
||||
} else {
|
||||
this.$store.commit("changeFirst", true);
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/scss/body.scss";
|
||||
|
||||
.content {
|
||||
padding: 15px;
|
||||
font-size: 32rpx;
|
||||
width: calc(100% - 30px);
|
||||
background-color: #F5F6FA;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.listC {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
<template>
|
||||
<view class="common">
|
||||
<view class="history" v-if="ranklist.length">
|
||||
<view class="list" v-for="(item, index) in ranklist" :key="index" @click="clickItemMethod(item)">
|
||||
<uni-swipe-action>
|
||||
<uni-swipe-action-item :right-options="item.options" @click="swipeClick($event, index)">
|
||||
<view class="time">
|
||||
<icon class="t-icon t-icon-shijian-mianxing-0"></icon>
|
||||
<text>{{item.record_time}}</text>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view>{{item.v1}}<text>{{item.v1_name}}</text></view>
|
||||
<view v-if="item.v2">{{item.v2}}<text>{{item.v2_name}}</text></view>
|
||||
<view v-if="item.v3">{{item.v3}}<text>{{item.v3_name}}</text></view>
|
||||
<uni-icons type="right" v-if="acd_id!=6"></uni-icons>
|
||||
</view>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
</view>
|
||||
<view class="endtext" v-if="!lastPage || page >= lastPage">—— 到底了,看看别的吧 ——</view>
|
||||
</view>
|
||||
<view class="nolist" v-if="!ranklist.length||!lastPage">
|
||||
<image src="../../static/none.png"></image>
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ranklist: [],
|
||||
page: 1,
|
||||
isDelete: false,
|
||||
lastPage: '',
|
||||
isActive: null,
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.getList()
|
||||
},
|
||||
onReachBottom() {
|
||||
let that = this
|
||||
console.log("onReachBottom", this.lastPage)
|
||||
if (!this.lastPage || this.page >= this.lastPage) {
|
||||
uni.showToast({
|
||||
title: '没有更多数据!',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.page++
|
||||
this.getList(this.page)
|
||||
},
|
||||
methods: {
|
||||
swipeClick(e, index) {
|
||||
let that = this
|
||||
let id = that.ranklist[index].id
|
||||
uni.showModal({
|
||||
title: '友情提示',
|
||||
content: '是否删除当前测量记录?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
that.$model.gethistorydelete({
|
||||
id: id,
|
||||
}).then((res) => {
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.ranklist.splice(index, 1)
|
||||
if (that.user.measure_model == "1") {
|
||||
that.$store.dispatch("getUserInfo", {
|
||||
aud_id: uni.getStorageSync('userid')
|
||||
})
|
||||
}
|
||||
if (that.acd_id == 2) {
|
||||
that.$store.dispatch("getResult", {
|
||||
aud_id: uni.getStorageSync('userid')
|
||||
})
|
||||
} else {
|
||||
that.isDelete = true
|
||||
}
|
||||
|
||||
that.$tools.msg("删除成功")
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
that.$tools.msg("您已取消操作!");
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
clickItemMethod(item) {
|
||||
let that = this
|
||||
uni.navigateTo({
|
||||
url: "/body/history/historyDetail?id=" + item.id
|
||||
})
|
||||
},
|
||||
getList(page) {
|
||||
let that = this
|
||||
that.$model.gethistory({
|
||||
aud_id: that.user.aud_id,
|
||||
page: that.page,
|
||||
}).then((res) => {
|
||||
console.log("历史记录", res)
|
||||
if (res.code != 0) return
|
||||
let options = [{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#dd524d'
|
||||
}
|
||||
}]
|
||||
res.data.rows.forEach(item => {
|
||||
item.options = options
|
||||
})
|
||||
this.ranklist = this.ranklist.concat(res.data.rows)
|
||||
this.lastPage = res.data.totalpage
|
||||
})
|
||||
},
|
||||
handleEdit(id) {
|
||||
let that = this
|
||||
that.isActive = that.isActive == id ? null : id
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped="scoped" lang="scss">
|
||||
.common {
|
||||
width: 100%;
|
||||
min-height: 100.5vh; // 重点
|
||||
overflow-y: scroll;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.history {
|
||||
width: calc(100% - 30px);
|
||||
height: auto;
|
||||
margin: 15px 15px 0;
|
||||
padding-bottom: 40px;
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
position: relative;
|
||||
|
||||
.item {
|
||||
width: calc(100% - 20px);
|
||||
height: auto;
|
||||
background: #fff;
|
||||
padding: 6px 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-radius: 10px;
|
||||
align-items: center;
|
||||
font-weight: 700;
|
||||
line-height: 50rpx;
|
||||
font-size: 36rpx !important;
|
||||
|
||||
text {
|
||||
display: block;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
|
||||
icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 32rpx;
|
||||
margin-top: 3px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
<template>
|
||||
<view>
|
||||
<view class="box">
|
||||
<view class="form lanBox">
|
||||
<view class="lan border-bottom" v-for="(item,index) in ranklist">
|
||||
<view class="left">
|
||||
<view class="view">
|
||||
<view class="t-icon" :class="'t-icon-'+item.key_name" v-if="item.key_name!='score'&&item.key_name!='head_circumference'"></view>
|
||||
<view class="score" v-if="item.key_name=='score'">A</view>
|
||||
<image src="../../static/head.png" v-if="item.key_name=='head_circumference'"></image>
|
||||
</view>
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="right">{{item.value?item.value:"0"}}{{item.unit}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import {
|
||||
// mapState
|
||||
// } from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
id: "",
|
||||
type: "",
|
||||
ranklist: []
|
||||
};
|
||||
},
|
||||
// computed: {
|
||||
// ...mapState([])
|
||||
// },
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.id = options.id
|
||||
that.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
let that = this
|
||||
that.$model.gethistorydetail({
|
||||
id: that.id,
|
||||
}).then((res) => {
|
||||
console.log("历史记录详情", res)
|
||||
this.ranklist = res.data
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped="scoped" lang="scss">
|
||||
.box {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.lanBox {
|
||||
padding: 0px 15px 0;
|
||||
}
|
||||
|
||||
.lan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
font-size: 32rpx;
|
||||
padding-left: 30px;
|
||||
|
||||
.view {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
padding: 2px;
|
||||
background-color: #c7c7c7;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.t-icon,
|
||||
image {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
width: 50%;
|
||||
min-height: 38px;
|
||||
box-sizing: border-box;
|
||||
line-height: 36px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
<template>
|
||||
<view class="content indexCarList">
|
||||
<view class="tagList">
|
||||
<scroll-view class="scroll-view_H" scroll-x="true" :scroll-into-view="toView">
|
||||
<text class="scroll-view-item_H" v-for="(ite,ind) in tagList" @click="handlePageScrollTo(ite.key,ind)"
|
||||
:class="[ind == index?'active':'']" :id="'Body_'+ite.key">
|
||||
{{ite.name}}
|
||||
</text>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 身体数据 -->
|
||||
<view class="report">
|
||||
<view class="box" v-if="list.length" v-for="(item,index) in list" :id="item.key_name">
|
||||
<view class="data data2">
|
||||
<view class="left">
|
||||
<view class="name bold">
|
||||
<image :src="item.icon"></image>
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="val" v-if="item.key_name=='body_level'||item.key_name=='body_type'"> - </view>
|
||||
<view class="val" v-else>{{item.value?item.value:'0'}}{{item.unit}}</view>
|
||||
<view class="level">
|
||||
<view class="btnf"
|
||||
:style="{backgroundColor:(item.standard=='异常'?'#FFF':item.standard_color)}"
|
||||
:class="[item.standard=='异常'?'btnC':'']">
|
||||
{{item.standard=='异常'?'-':item.standard}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="desc">
|
||||
<view v-if="item.description" class="ming size12">{{item.description}}</view>
|
||||
<view :class="[item.standard_list.length?'statuevue':'']" v-if="item.standard_list">
|
||||
<view class="bi" v-if="item.title!='基础代谢'">
|
||||
<view :style="'left:'+item.offset+'%'" class="peobox">
|
||||
<view class="xx"></view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite , ind) in item.standard_list" :key="ind"
|
||||
:style="{backgroundColor:ite.color}">
|
||||
<view class="span1">{{ite.text}}</view>
|
||||
<view class="span" v-if="ind<item.standard_list.length-1">{{ite.max_val}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="kcalClass" v-if="item.standard_list&&item.standard_list.length">
|
||||
标准值:{{item.standard_list[0].max_val}}kcal
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
to: "",
|
||||
toView: "",
|
||||
index: 0,
|
||||
list: [],
|
||||
tagList: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user', "configInfo"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
onLoad(options) {
|
||||
this.to = options.to
|
||||
console.log("to", this.to)
|
||||
this.handleResultDetail()
|
||||
},
|
||||
methods: {
|
||||
handlePageScrollTo(to, ind) {
|
||||
this.index = ind
|
||||
uni.createSelectorQuery().select('#' + to).boundingClientRect(function(rect) {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: rect.top - 50,
|
||||
duration: 500
|
||||
})
|
||||
}).exec();
|
||||
},
|
||||
handleResultDetail() {
|
||||
let list = []
|
||||
let that = this
|
||||
that.$model.getResultDetail({
|
||||
aud_id: that.user.aud_id
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
that.list = res.data
|
||||
res.data.forEach(ite => {
|
||||
list.push({
|
||||
key: ite.key_name,
|
||||
name: ite.name
|
||||
})
|
||||
})
|
||||
that.tagList = list
|
||||
const index = res.data.findIndex(ite => ite.key_name == that.to)
|
||||
setTimeout(() => {
|
||||
that.handlePageScrollTo(that.to, index)
|
||||
that.toView = 'Body_' + res.data[index].key_name
|
||||
}, 500);
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/scss/body.scss";
|
||||
|
||||
.content {
|
||||
font-size: 32rpx;
|
||||
width: 100%;
|
||||
padding-bottom: 15px;
|
||||
background-color: #F5F6FA;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #000 !important;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.scroll-view_H {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
|
||||
.scroll-view-item_H {
|
||||
display: inline-block;
|
||||
height: 45rpx;
|
||||
line-height: 45rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.tagList {
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
|
||||
text {
|
||||
color: #666;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.title:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 20px;
|
||||
left: -5px;
|
||||
border-radius: 5px;
|
||||
background-color: #fea606;
|
||||
}
|
||||
|
||||
.bleTips {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
margin: -10px 10px 10px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
}
|
||||
|
||||
.bleTips2 {
|
||||
background: #fea606;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.report {
|
||||
margin: 60px 0 15px;
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
.left {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 33%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.tools {
|
||||
display: flex;
|
||||
padding: 0 15px;
|
||||
margin-top: 15px;
|
||||
justify-content: space-between;
|
||||
|
||||
view {
|
||||
display: flex;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
width: 40%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<!-- <view class="bg"></view> -->
|
||||
<view class="login">
|
||||
<view class="editem">
|
||||
<view class="item">
|
||||
<view class="text">手机号/邮箱</view>
|
||||
<view class="input">
|
||||
<input v-model="phone" type="text"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item ">
|
||||
<view class="text">验证码</view>
|
||||
<view class="input yanzhengma">
|
||||
<input class="uni-input" v-model="code" />
|
||||
<button class="code" type="none" @click="handleCode" v-model="code"
|
||||
:disabled="disabled">{{second<60 ? second+'S后重发':'验证码'}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text">密码</view>
|
||||
<view class="input">
|
||||
<input class="uni-input" v-model="password" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text">确认密码</view>
|
||||
<view class="input">
|
||||
<input class="uni-input" v-model="password2" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="xieyi">
|
||||
<checkbox-group @change="checkboxChange" class="group">
|
||||
<label>
|
||||
<checkbox :value="1" style="transform:scale(0.7)" />{{$t("login.agreement")}}
|
||||
<text @click="handlexieyi" @click.stop>{{$t("login.agreementContnt")}}</text>
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view> -->
|
||||
<view class="btnlogin" @click="handleTelLogin">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
phone: "",
|
||||
code: "",
|
||||
password: "",
|
||||
password2: "",
|
||||
disabled: false,
|
||||
second: 60,
|
||||
value: 1,
|
||||
type: ""
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.type = options.type //1
|
||||
},
|
||||
methods: {
|
||||
checkboxChange(e) {
|
||||
this.value = e.detail.value.length ? e.detail.value[0] : "0"
|
||||
},
|
||||
// 登录、
|
||||
handleTelLogin() {
|
||||
let that = this
|
||||
let phoneType = that.phone.indexOf("@") !== -1
|
||||
if (that.value == 0) {
|
||||
that.$tools.msg("请先确认勾选协议")
|
||||
return
|
||||
}
|
||||
if (!phoneType && !(/^1[3456789]\d{9}$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的手机号")
|
||||
return
|
||||
}
|
||||
if (phoneType && !(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的邮箱")
|
||||
return
|
||||
}
|
||||
if (!that.code) {
|
||||
that.$tools.msg("请填写验证码")
|
||||
return
|
||||
}
|
||||
if (!that.password) {
|
||||
that.$tools.msg("请填写密码")
|
||||
return
|
||||
}
|
||||
if (!that.password2) {
|
||||
that.$tools.msg("请确认密码")
|
||||
return
|
||||
}
|
||||
if (that.password2 != that.password) {
|
||||
that.$tools.msg("请确认两次密码填写一致")
|
||||
return
|
||||
}
|
||||
let account = {
|
||||
data: that.phone,
|
||||
password: that.password,
|
||||
c_password: that.password2,
|
||||
code: that.code
|
||||
}
|
||||
let https = that.type == 'register' ? that.$model.getregister(account) : that.$model.getResetPassword(
|
||||
account)
|
||||
return https.then(res => {
|
||||
console.log("注册", res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
uni.setStorageSync('token', res.data.token)
|
||||
uni.setStorageSync('aan_id', res.data.aan_id)
|
||||
that.$tools.msg("设置成功,进入程序中")
|
||||
setTimeout(function() {
|
||||
uni.reLaunch({
|
||||
url: "/pages/home/home?type=1"
|
||||
})
|
||||
}, 1000)
|
||||
}).catch(err => {})
|
||||
},
|
||||
// 获取验证码
|
||||
handleCode() {
|
||||
let that = this
|
||||
let phoneType = that.phone.indexOf("@") !== -1
|
||||
if (!phoneType && !(/^1[3456789]\d{9}$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的手机号")
|
||||
return
|
||||
}
|
||||
if (phoneType && !(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的邮箱")
|
||||
return
|
||||
}
|
||||
//
|
||||
that.$model.getSendCode({
|
||||
data: that.phone,
|
||||
type: that.type
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.disabled = true
|
||||
let interval = setInterval(() => {
|
||||
--that.second
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
clearInterval(interval)
|
||||
that.disabled = false
|
||||
that.second = 60
|
||||
}, 60000)
|
||||
}).catch(err => {})
|
||||
},
|
||||
handlexieyi() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
}
|
||||
|
||||
.bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
z-index: 9;
|
||||
// background: $maincolor;
|
||||
}
|
||||
|
||||
.login {
|
||||
width: calc(100% - 30px);
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
background-color: #fff;
|
||||
z-index: 99;
|
||||
// position: relative;
|
||||
// margin-left: calc(10% - 40px);
|
||||
// box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
|
||||
.title {
|
||||
text-align: left;
|
||||
color: #333;
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
.editem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.text {
|
||||
width: 240rpx;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: calc(100% - 240rpx);
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
border: #dfdfdf 1px solid;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: 0px;
|
||||
z-index: 88;
|
||||
font-size:28rpx;
|
||||
}
|
||||
|
||||
.yanzhengma {
|
||||
input {
|
||||
right: 220rpx;
|
||||
font-size:28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.code {
|
||||
width: 220rpx;
|
||||
background: #dfdfdf;
|
||||
font-size: 28rpx;
|
||||
margin: 0;
|
||||
line-height: 40px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.forget {
|
||||
width: 80px;
|
||||
background: #fff;
|
||||
color: $textcolor;
|
||||
}
|
||||
}
|
||||
|
||||
.btngroup {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
text {
|
||||
display: block;
|
||||
color: $textcolor;
|
||||
}
|
||||
}
|
||||
|
||||
.btnlogin {
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
background: $btncolor;
|
||||
font-weight: 700;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
.xieyi {
|
||||
font-size: 32rpx;
|
||||
color: $textcolor;
|
||||
|
||||
text {
|
||||
border-bottom: 1px solid $textcolor;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="bg"></view>
|
||||
<view class="top">
|
||||
<image src="../../static/logo2.png"></image>
|
||||
<text>Reedaw</text>
|
||||
</view>
|
||||
<view class="login box_shadow">
|
||||
<view class="title">登录</view>
|
||||
<view class="toggle cblue" @click="handleToggle">
|
||||
切换登录
|
||||
</view>
|
||||
<view class="editem">
|
||||
<view class="item">
|
||||
<view class="text">手机号/邮箱</view>
|
||||
<view class="input">
|
||||
<input v-model="phone" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 验证码登录 -->
|
||||
<view class="item " v-if="isCode">
|
||||
<view class="text">验证码</view>
|
||||
<view class="input yanzhengma">
|
||||
<input class="uni-input" v-model="code" />
|
||||
<button class="code" type="none" @click="handleCode" v-model="code"
|
||||
:disabled="disabled">{{second<60 ? second+'S后重发':'获取验证码'}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 密码登录 -->
|
||||
<view class="item " v-else>
|
||||
<view class="text">密码</view>
|
||||
<view class="input">
|
||||
<input class="uni-input" v-model="password" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="forget " v-if="!isCode">
|
||||
<text @click="handlePassword('forgetPassword')">忘记密码?</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="xieyi">
|
||||
<checkbox-group @change="checkboxChange" class="group">
|
||||
<label>
|
||||
<checkbox :value="1" style="transform:scale(0.7)" />阅读并同意
|
||||
<!-- <text @click.stop @click="handleUserXieyi" class="blue">《用户协议》</text>和 -->
|
||||
<text @click.stop @click="handlexieyi" class="blue">《隐私协议》</text>
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
<view class="btnlogin" @click="handleTelLogin">登录</view>
|
||||
<view class="btngroup" @click="handlePassword('register')">
|
||||
<text>注册</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="wxbtn">
|
||||
<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" v-if="value==1">
|
||||
<view>
|
||||
<image src="../../static/phone.png"></image>
|
||||
</view>
|
||||
<text>手机号快捷登录</text>
|
||||
</button>
|
||||
<button v-else @click="handleIsTel">
|
||||
<view>
|
||||
<image src="../../static/phone.png"></image>
|
||||
</view>
|
||||
<text>手机号快捷登录</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
phone: "",
|
||||
code: "",
|
||||
password: "",
|
||||
disabled: false,
|
||||
second: 60,
|
||||
value: 0,
|
||||
isCode: true,
|
||||
loginCode: ""
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// #ifdef MP-WEIXIN
|
||||
this.login()
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
// 勾选协议
|
||||
checkboxChange(e) {
|
||||
this.value = e.detail.value.length ? e.detail.value[0] : "0"
|
||||
},
|
||||
// 登录、
|
||||
handleTelLogin() {
|
||||
let that = this
|
||||
let phoneType = that.phone.indexOf("@") !== -1
|
||||
if (that.value == 0) {
|
||||
that.$tools.msg("请先确认勾选协议")
|
||||
return
|
||||
}
|
||||
if (!phoneType && !(/^1[3456789]\d{9}$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的手机号")
|
||||
return
|
||||
}
|
||||
if (phoneType && !(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的邮箱")
|
||||
return
|
||||
}
|
||||
if (that.isCode && !that.code) {
|
||||
that.$tools.msg("请输入验证码")
|
||||
return
|
||||
}
|
||||
if (!that.isCode && !that.password) {
|
||||
that.$tools.msg('请输入正确密码')
|
||||
return
|
||||
}
|
||||
this.$model.getonlogin({
|
||||
data: that.phone,
|
||||
validate_data: that.isCode ? that.code : that.password,
|
||||
validate_type: that.isCode ? 'code' : 'password'
|
||||
}).then(res => {
|
||||
console.log("data", res.data)
|
||||
that.$tools.msg(res.msg)
|
||||
if (res.code != 0) return
|
||||
that.$tools.msg("登录成功")
|
||||
uni.setStorageSync('token', res.data.token)
|
||||
uni.setStorageSync('aan_id', res.data.aan_id)
|
||||
that.$store.dispatch('getFamilyList', {
|
||||
type: 2
|
||||
})
|
||||
setTimeout(function() {
|
||||
uni.reLaunch({
|
||||
url: "/pages/home/home"
|
||||
})
|
||||
}, 1000)
|
||||
}).catch(err => {})
|
||||
},
|
||||
// 获取验证码
|
||||
handleCode() {
|
||||
let that = this
|
||||
let phoneType = that.phone.indexOf("@") !== -1
|
||||
if (!phoneType && !(/^1[3456789]\d{9}$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的手机号")
|
||||
return
|
||||
}
|
||||
if (phoneType && !(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的邮箱")
|
||||
return
|
||||
}
|
||||
//
|
||||
that.$model.getSendCode({
|
||||
data: that.phone,
|
||||
type: "login"
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.disabled = true
|
||||
let interval = setInterval(() => {
|
||||
--that.second
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
clearInterval(interval)
|
||||
that.disabled = false
|
||||
that.second = 60
|
||||
}, 60000)
|
||||
}).catch(err => {})
|
||||
},
|
||||
//
|
||||
handleIsTel() {
|
||||
if (this.value == 0) {
|
||||
this.$tools.msg("请先确认勾选协议")
|
||||
return
|
||||
}
|
||||
},
|
||||
// 获取code
|
||||
login() {
|
||||
let that = this
|
||||
uni.login({
|
||||
success(res) {
|
||||
if (res.code) {
|
||||
if (res.errMsg = "login:ok") {
|
||||
that.loginCode = res.code
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 授权
|
||||
getPhoneNumber(res) {
|
||||
const that = this
|
||||
if (res.detail.errMsg == 'getPhoneNumber:ok') {
|
||||
this.$model.getRegisterPhone({
|
||||
code: that.loginCode,
|
||||
encryptedData: res.detail.encryptedData,
|
||||
iv: res.detail.iv,
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.value = 1
|
||||
uni.setStorageSync('token', res.data.token)
|
||||
uni.setStorageSync('aan_id', res.data.aan_id)
|
||||
setTimeout(function() {
|
||||
uni.reLaunch({
|
||||
url: "/pages/index/index"
|
||||
})
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
},
|
||||
handleToggle() {
|
||||
this.phone = ""
|
||||
this.isCode = !this.isCode
|
||||
},
|
||||
handlePassword(text) {
|
||||
uni.navigateTo({
|
||||
url: "/pageTwo/login/forgetPassword?type=" + text
|
||||
})
|
||||
},
|
||||
handlexieyi() {
|
||||
let that = this
|
||||
uni.navigateTo({
|
||||
url: "/pageTwo/webview/webview?url=http://tc.pcxbc.com/technology/privacy_index"
|
||||
})
|
||||
},
|
||||
handleUserXieyi() {
|
||||
let that = this
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/scss/login.scss";
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.xieyi {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
margin-left: 10px;
|
||||
|
||||
text {
|
||||
color: $maincolor;
|
||||
}
|
||||
}
|
||||
|
||||
.href {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.wxbtn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
margin-top: 30px;
|
||||
top: 80%;
|
||||
|
||||
icon {
|
||||
font-size: 25px;
|
||||
color: #28c445;
|
||||
}
|
||||
|
||||
|
||||
text {
|
||||
display: block;
|
||||
// width: 100%;
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
// color: #666;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid blue;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
button {
|
||||
line-height: initial;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
button::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
view {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view class="logo">
|
||||
<image src="../../static/logo2.png"></image>
|
||||
<view>Reedaw</view>
|
||||
<text>V{{phoneInfo.info.version}}</text>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="item" @click="handleVersion">
|
||||
<view class="left">版本更新</view>
|
||||
<view class="right">
|
||||
<text class="new" v-if="version==-1">新版本{{phoneInfo.versionUrl.version}}</text>
|
||||
<uni-icons type="right"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<a href="http://tc.pcxbc.com/technology/privacy_index" class="href">
|
||||
<text class="left">隐私协议</text>
|
||||
<uni-icons type="right"></uni-icons>
|
||||
</a>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="xieyi">
|
||||
<a>《隐私协议》</a>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
let dtask;
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 0版本号相通,1,:第一个版本号大于第二个版本号,-1:第一个版本号小于第二个版本号
|
||||
version: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["phoneInfo"]),
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
if (!that.phoneInfo.versionUrl) {
|
||||
console.log("111")
|
||||
that.handleoginversion()
|
||||
} else {
|
||||
console.log("222")
|
||||
that.version = that.$tools.compareVersions(that.phoneInfo.info.version, that.phoneInfo.versionUrl.version)
|
||||
}
|
||||
},
|
||||
onBackPress() {
|
||||
console.log("dtask", dtask)
|
||||
if (dtask != undefined) {
|
||||
dtask.onProgressUpdate((res) => {
|
||||
if (res.progress != 100) {
|
||||
dtask.abort();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleVersion() {
|
||||
let that = this
|
||||
if (that.version == -1) {
|
||||
if (that.phoneInfo.platform === 'android') {
|
||||
uni.setStorageSync('VERSION', that.phoneInfo.versionUrl.version)
|
||||
let showLoading = plus.nativeUI.showWaiting('正在下载')
|
||||
dtask = uni.downloadFile({
|
||||
url: that.phoneInfo.versionUrl.url,
|
||||
success: (downloadRes) => {
|
||||
if (downloadRes.statusCode === 200) {
|
||||
plus.nativeUI.closeWaiting()
|
||||
plus.runtime.install(
|
||||
downloadRes.tempFilePath, {
|
||||
force: false
|
||||
},
|
||||
function() {
|
||||
console.log('install success...');
|
||||
plus.runtime.restart();
|
||||
},
|
||||
function(e) {
|
||||
console.error('install fail...');
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '升级失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
dtask.onProgressUpdate((res) => {
|
||||
showLoading.setTitle(" 正在下载" + res.progress + "% ");
|
||||
// console.log('下载进度' + res.progress + '%');
|
||||
});
|
||||
} else {
|
||||
plus.runtime.launchApplication({
|
||||
action: `itms-apps://itunes.apple.com/cn/app/id6654906497?mt=8`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
that.$tools.msg("已经是最新版本了!")
|
||||
}
|
||||
},
|
||||
// 版本信息
|
||||
handleoginversion() {
|
||||
let that = this
|
||||
that.$model.getloginversion({}).then(res => {
|
||||
that.version = that.$tools.compareVersions(that.phoneInfo.info.version, res.data.version)
|
||||
that.$store.commit('changePhoneInfo', {
|
||||
versionUrl: res.data
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
min-height: calc(100vh - 30px);
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.info {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 40rpx;
|
||||
line-height: 35px;
|
||||
|
||||
image {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
text {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
width: calc(100% - 20px);
|
||||
margin: 50px 0;
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 0 10px;
|
||||
justify-content: space-between;
|
||||
|
||||
.new {
|
||||
color: #fff;
|
||||
background-color: red;
|
||||
font-size: 32rpx;
|
||||
border-radius: 10px;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.href {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.xieyi {
|
||||
color: $textcolor;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<template>
|
||||
<view class="common">
|
||||
<view class="add" @click="handleAddUser">
|
||||
<icon class="iconfont icon-tianjia"></icon>添加成员
|
||||
</view>
|
||||
<view class="box" v-if="familayList.lenght!=0">
|
||||
<view class="list">
|
||||
<uni-swipe-action>
|
||||
<uni-swipe-action-item v-for="(item ,index) in familayList" :key="index"
|
||||
:right-options="item.options" @click="handleDeldet($event, index)">
|
||||
<view class="item">
|
||||
<view class="left">
|
||||
<image :src="item.head_pic" class="image1" />
|
||||
<view class="name">
|
||||
<view class="title">
|
||||
{{item.nickname}}
|
||||
</view>
|
||||
<view class="title2">
|
||||
<text>{{item.gender==1?'男':'女'}}</text>
|
||||
<text>{{item.age}}岁</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right" @click.stop>
|
||||
<view class="blueBtn" @click="editorInfo(item)">编辑</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
没有数据了!
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["familayList"])
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
let that = this
|
||||
that.handleUserList()
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
}, 1000);
|
||||
},
|
||||
methods: {
|
||||
//删除
|
||||
handleDeldet(e, ind) {
|
||||
let that = this
|
||||
let id = that.familayList[ind].id
|
||||
uni.showModal({
|
||||
title: '友情提示',
|
||||
content: '确定删除该成员吗',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
that.$model.getDelUser({
|
||||
aud_id: id,
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.$tools.msg("删除成功!");
|
||||
that.familayList.splice(ind, 1)
|
||||
that.handleUserList()
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
that.$tools.msg("您已取消删除!");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleUserList() {
|
||||
let that = this
|
||||
that.$model.getUserList({
|
||||
type: 2
|
||||
}).then(res => {
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.$store.commit('changeFamilay', res.data.user_list)
|
||||
if (res.data.length) {
|
||||
uni.setStorageSync('userid', res.data.user_list[0].id)
|
||||
that.$store.dispatch('getUserInfo', {
|
||||
aud_id: res.data.user_list[0].id
|
||||
})
|
||||
that.handlePublicRecord(res.data.user_list[0].id)
|
||||
}
|
||||
}).catch(err => {})
|
||||
},
|
||||
// 公共手动记录内容
|
||||
handlePublicRecord(id) {
|
||||
let that = this
|
||||
that.$model.getPublicRecord({
|
||||
aud_id: id
|
||||
}).then(res => {
|
||||
console.log("公共手动记录", res)
|
||||
if (res.code == 0) {
|
||||
that.$store.commit('changePublicRecord', res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
//编辑
|
||||
editorInfo(item) {
|
||||
uni.navigateTo({
|
||||
url: "/body/my/userInfo?info=" + JSON.stringify(item)
|
||||
})
|
||||
},
|
||||
//添加
|
||||
handleAddUser() {
|
||||
uni.navigateTo({
|
||||
url: "/body/my/userInfo"
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="scoped" lang="scss">
|
||||
.common {
|
||||
padding: 15px;
|
||||
background-color: #f7f7f7;
|
||||
min-height: calc(100vh - 30px);
|
||||
}
|
||||
|
||||
.add {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 10px;
|
||||
color: #fff;
|
||||
border-radius: 15px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background: $btncolor;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 15px 0;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
font-size: 36rpx;
|
||||
|
||||
.item {
|
||||
background: #fff;
|
||||
padding: 10px 15px;
|
||||
width: calc(100% - 30px);
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.left {
|
||||
width: 75%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.image1 {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 15px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: calc(100% - 70px);
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.title2 {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
margin-top: 15px;
|
||||
|
||||
text {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.blueBtn {
|
||||
width: auto;
|
||||
font-size: 32rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
<template>
|
||||
<view class="box">
|
||||
<view class="lanBox">
|
||||
<view class="headbox">
|
||||
<view class="touxiang">
|
||||
<image v-if="headimg" :src="headimg" class="headimage" />
|
||||
<icon v-else class="iconfont icon-user-filling headimage"></icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lan border-bottom">
|
||||
<view class="left">姓名</view>
|
||||
<view class="right">
|
||||
<input name="name" type="text" v-model="memInfo.nickname" placeholder="请输入姓名" />
|
||||
<uni-icons type="clear" color="#999" v-if="memInfo.nickname" @click="memInfo.nickname=''"
|
||||
size="20"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lan border-bottom">
|
||||
<view class="left">性别</view>
|
||||
<view class="right">
|
||||
<view class="radio">
|
||||
<uni-icons :type="memInfo.gender==1?'checkbox-filled':'circle'" @click="memInfo.gender=1"
|
||||
size="24" :color="memInfo.gender==1?'#fea606':'#dfdfdf'"></uni-icons>男
|
||||
</view>
|
||||
<view class="radio ml-15">
|
||||
<uni-icons :type="memInfo.gender==2?'checkbox-filled':'circle'" @click="memInfo.gender=2"
|
||||
size="24" :color="memInfo.gender==2?'#fea606':'#dfdfdf'"></uni-icons>女
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lan border-bottom">
|
||||
<view class="left">身高</view>
|
||||
<view class="right">
|
||||
<input name="name" class="mr-5" type="digit" v-model="memInfo.height" placeholder="请输入身高" />CM
|
||||
<uni-icons type="clear" color="#999" v-if="memInfo.height" @click="memInfo.height=''"
|
||||
size="20"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lan border-bottom">
|
||||
<view class="left">体重</view>
|
||||
<view class="right">
|
||||
<input name="name" type="digit" class="mr-5" v-model="memInfo.weight" placeholder="请输入体重" />KG
|
||||
<uni-icons type="clear" color="#999" v-if="memInfo.weight" @click="memInfo.weight=''"
|
||||
size="20"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lan border-bottom">
|
||||
<view class="left">出生日期</view>
|
||||
<view class="right">
|
||||
<picker mode="date" :end="endDate" @change="maskClick"
|
||||
:value="memInfo.birthday?memInfo.birthday:endDate" :fields="fields">
|
||||
<view class="uni-input">{{memInfo.birthday?memInfo.birthday:'请选择'}}</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lan border-bottom">
|
||||
<view class="left">活动系数</view>
|
||||
<view class="right">
|
||||
<picker mode="selector" @change="changeClickType" :range="activityLevel" range-key="name"
|
||||
:value="levelInd">
|
||||
<view>
|
||||
{{memInfo.activity_level?activityLevel[levelInd].name:'请选择'}}
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn" @click="confirmInfo">提交</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
sexItem: [
|
||||
"男",
|
||||
"女"
|
||||
],
|
||||
memInfo: {
|
||||
birthday: "",
|
||||
height: "",
|
||||
weight: "",
|
||||
gender: 0,
|
||||
nickname: "",
|
||||
activity_level: "",
|
||||
},
|
||||
fields: "",
|
||||
levelInd: 0,
|
||||
isEdit: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "familayList", "configInfo"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
activityLevel() {
|
||||
return this.configInfo.activity_level
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
if (options.info) { //编辑
|
||||
let info = JSON.parse(options.info)
|
||||
that.memInfo = info
|
||||
that.isEdit = true
|
||||
console.log("that.memInfo ", that.memInfo)
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
watch: {
|
||||
familayList() {
|
||||
let that = this
|
||||
let userid = ""
|
||||
let found = that.familayList.find(e => e.id == that.userId);
|
||||
userid = found !== undefined ? that.userId : that.familayList[0].id
|
||||
uni.setStorageSync('userid', found !== undefined ? found.id : userid)
|
||||
uni.setStorageSync('gender', found !== undefined ? found.gender : that.familayList[0].gender)
|
||||
that.$store.commit('changeUser', found !== undefined ? found : that.familayList[0])
|
||||
that.$store.dispatch("getResult", {
|
||||
aud_id: userid
|
||||
})
|
||||
if (!that.isEdit && that.familayList.length == 1) {
|
||||
uni.switchTab({
|
||||
url: "/pages/home/home"
|
||||
})
|
||||
} else {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 提交
|
||||
confirmInfo() {
|
||||
let that = this
|
||||
if (!that.memInfo.nickname) {
|
||||
that.$tools.msg("请输入姓名")
|
||||
return;
|
||||
}
|
||||
if (!that.memInfo.height) {
|
||||
that.$tools.msg("请选择身高")
|
||||
return;
|
||||
}
|
||||
if (!that.memInfo.weight) {
|
||||
that.$tools.msg("请选择体重")
|
||||
return;
|
||||
}
|
||||
if (!that.memInfo.birthday) {
|
||||
that.$tools.msg("请选择出生日期")
|
||||
return;
|
||||
}
|
||||
if (!that.memInfo.activity_level) {
|
||||
that.$tools.msg("请选择活动系数")
|
||||
return;
|
||||
}
|
||||
let https = that.isEdit ? that.$model.getEditUser(that.memInfo) : that.$model.getAddUser(that.memInfo)
|
||||
return https.then(res => {
|
||||
console.log("成功", res)
|
||||
if (res.code == 0) {
|
||||
that.$tools.msg("提交成功");
|
||||
that.userId = res.data.aud_id
|
||||
that.$store.dispatch('getFamilyList', {
|
||||
type: 2
|
||||
})
|
||||
} else {
|
||||
that.$tools.msg(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 公共手动记录内容
|
||||
handlePublicRecord(id) {
|
||||
let that = this
|
||||
that.$model.getPublicRecord({
|
||||
aud_id: id
|
||||
}).then(res => {
|
||||
console.log("公共手动记录", res)
|
||||
if (res.code == 0) {
|
||||
that.$store.commit('changePublicRecord', res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
//确定年龄
|
||||
maskClick(e) {
|
||||
console.log("出生日期", e.detail.value)
|
||||
this.memInfo.birthday = e.detail.value
|
||||
},
|
||||
//确定性别
|
||||
onsexArr(e) {
|
||||
this.memInfo.gender = this.sexItem[e.target.value] == "男" ? 1 : 2
|
||||
},
|
||||
changeClickType(e) {
|
||||
this.levelInd = e.target.value
|
||||
this.memInfo.activity_level = this.activityLevel[e.target.value].val
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped="scoped" lang="scss">
|
||||
.box {
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
input {
|
||||
border: none;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.headbox {
|
||||
height: 180rpx;
|
||||
padding-top: 10px;
|
||||
border-radius: 0 0 5px 5px;
|
||||
background: $maincolor;
|
||||
}
|
||||
|
||||
.headimage {
|
||||
display: block;
|
||||
padding-top: 10px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
font-size: 140rpx;
|
||||
margin: auto;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.lan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
padding: 5px 0;
|
||||
margin: 5px 15px;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
}
|
||||
|
||||
.left {
|
||||
width: 24%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
width: 72%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
text-align: right;
|
||||
|
||||
.radio {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
picker {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
border: none;
|
||||
margin-right: 15px;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/deep/input {
|
||||
height: 35px;
|
||||
padding-top: 1px;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: auto;
|
||||
margin: 40px 15px 0;
|
||||
background: $btncolor !important;
|
||||
}
|
||||
|
||||
.visible {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 9999;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
|
||||
.groupBtn {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 15px;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 45%;
|
||||
z-index: 999;
|
||||
|
||||
view {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
background-color: #dfdfdf;
|
||||
border-radius: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.sure {
|
||||
background-color: $textcolor;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
width: 100%;
|
||||
height: 45%;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.item {
|
||||
line-height: 45px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,800 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="date">{{depthInfo.user_data.record_time}}</view>
|
||||
<view class="header">
|
||||
<view class="top">
|
||||
<view class="left">
|
||||
<image :src="depthInfo.user_data.head_pic"></image>
|
||||
<view>
|
||||
<text class="bold size14 name">{{depthInfo.user_data.nickname}}</text>
|
||||
<text>性别:{{depthInfo.user_data.gender==2?'女':'男'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="rightChart">
|
||||
<view class="charts-box">
|
||||
<qiun-data-charts type="arcbar" :opts="opts2" canvasId="foodCharts107"
|
||||
:chartData="chartData2" :canvas2d="true" :cHeight="300" :cWidth="300" />
|
||||
</view>
|
||||
<view class="score">
|
||||
<text>{{depthInfo.user_data.score}}</text>
|
||||
健康评分
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="text_l">
|
||||
<text>年龄</text>
|
||||
<text class="size20 bold">{{depthInfo.user_data.age}}</text>
|
||||
</view>
|
||||
<view class="line text_c">
|
||||
<text>身高</text>
|
||||
<text class="size20 bold">{{depthInfo.user_data.height}}</text>
|
||||
</view>
|
||||
<view class="text_r">
|
||||
<text class="text_c">体重</text>
|
||||
<text class="size20 bold">{{depthInfo.user_data.weight}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 心脏健康 -->
|
||||
<view v-if="depthInfo.heart_rate&&depthInfo.heart_rate.value">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.heart_rate.icon"></image>
|
||||
{{depthInfo.heart_rate.title_name}}
|
||||
</view>
|
||||
<view class="heartRate bgfff ">
|
||||
<view class="stand">
|
||||
<view><text>{{depthInfo.heart_rate.value}}</text>{{depthInfo.heart_rate.unit}}</view>
|
||||
<view class="bold size16" :style="{'color':depthInfo.heart_rate.standard_color}">
|
||||
{{depthInfo.heart_rate.standard}}
|
||||
</view>
|
||||
</view>
|
||||
<image src="/static/31.png" mode="widthFix"></image>
|
||||
<view class="report" style="margin-top: -45px;">
|
||||
<view class="Xitem myinfoPage">
|
||||
<view class="box">
|
||||
<view class="desc desc2">
|
||||
<view class="statuevue">
|
||||
<view class="bi">
|
||||
<view :style="'left:'+depthInfo.heart_rate.offset+'%'" class="peobox">
|
||||
<view class="xx"></view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite,ind) in depthInfo.heart_rate.standard_list"
|
||||
:key="ind" :style="{backgroundColor:ite.color}">
|
||||
<view class="span1">{{ite.text}}</view>
|
||||
<view class="span" v-if="ind<depthInfo.heart_rate.standard_list.length-1">
|
||||
{{ite.max_val}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 身体成分分析 -->
|
||||
<view v-if="depthInfo.body_data&&depthInfo.body_data.title_name">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.body_data.icon"></image>
|
||||
{{depthInfo.body_data.title_name}}
|
||||
</view>
|
||||
<view class="info bgfff">
|
||||
<view class="infoTitle">
|
||||
<text class="size16 bold">{{depthInfo.body_data.title}}</text>
|
||||
<text class="size12 c999">{{depthInfo.body_data.description}}</text>
|
||||
</view>
|
||||
<view class="Qlist">
|
||||
<view class="QItem" v-for="(ite,ind) in depthInfo.body_data.list">
|
||||
<view class="left">
|
||||
<view class="yuan" :style="{'backgroundColor':ite.color}"></view>
|
||||
<view class="name">
|
||||
<text class="bold">{{ite.name}}</text>
|
||||
<text class="size12 c999">{{ite.scope}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="size16 bold value">{{ite.value}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="huan">
|
||||
<qiun-data-charts type="ring" :opts="opts" canvasId="foodCharts209" :chartData="chartData"
|
||||
:cHeight="320" :cWidth="320" :canvas2d="true" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 肌肉脂肪分析 -->
|
||||
<view v-if="depthInfo.muscle_fat&&depthInfo.muscle_fat.list">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.muscle_fat.icon"></image>
|
||||
{{depthInfo.muscle_fat.title_name}}
|
||||
</view>
|
||||
<view class="table bgfff report">
|
||||
<view class="Xitem myinfoPage">
|
||||
<view class="box" v-for="(item,index) in depthInfo.muscle_fat.list">
|
||||
<view class="data data2">
|
||||
<view class="name bold">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="val">{{item.value?item.value:'0'}}{{item.unit}}</view>
|
||||
<view class="level">
|
||||
<view class="btnf"
|
||||
:style="{backgroundColor:(item.standard=='异常'?'#FFF':item.standard_color)}"
|
||||
:class="[item.standard=='异常'?'btnC':'']">
|
||||
{{item.standard=='异常'?'-':item.standard}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="desc">
|
||||
<view v-if="item.description" class="ming size12">{{item.description}}</view>
|
||||
<view :class="[item.list.length?'statuevue':'']" v-if="item.list">
|
||||
<view class="bi">
|
||||
<view :style="'left:'+item.offset+'%'" class="peobox">
|
||||
<view class="xx"></view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite , ind) in item.list" :key="ind"
|
||||
:style="{backgroundColor:ite.color}">
|
||||
<view class="span1">{{ite.text}}</view>
|
||||
<view class="span" v-if="ind<item.list.length-1">{{ite.max_val}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 节段脂肪分析 -->
|
||||
<view v-if="depthInfo.segment_fat&&depthInfo.segment_fat.list" class="w100">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.segment_fat.icon"></image>
|
||||
{{depthInfo.segment_fat.title_name}}
|
||||
</view>
|
||||
<view class="bodyimg bgfff">
|
||||
<image :src="depthInfo.segment_fat.bg_img"></image>
|
||||
<view class="L1" v-for="(ite,ind) in depthInfo.segment_fat.list">
|
||||
{{ite.name}}{{ite.value}}{{ite.unit}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!--肌肉平衡 -->
|
||||
<view v-if="depthInfo.segment_muscle&&depthInfo.segment_muscle.list" class="w100">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.segment_muscle.icon"></image>
|
||||
{{depthInfo.segment_muscle.title_name}}
|
||||
</view>
|
||||
<view class="bodyimg bgfff">
|
||||
<image :src="depthInfo.segment_muscle.bg_img"></image>
|
||||
<view class="L1" v-for="(ite,ind) in depthInfo.segment_muscle.list">
|
||||
{{ite.name}}{{ite.value}}{{ite.unit}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 肥胖分析 -->
|
||||
<view v-if="depthInfo.fat_analysis">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.fat_analysis.icon"></image>
|
||||
{{depthInfo.fat_analysis.title_name}}
|
||||
</view>
|
||||
<view class="table bgfff report">
|
||||
<view class="Xitem myinfoPage">
|
||||
<view class="box" v-for="(item,index) in depthInfo.fat_analysis.list">
|
||||
<view class="data data2">
|
||||
<view class="name bold">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="val">{{item.value?item.value:'0'}}{{item.unit}}</view>
|
||||
<view class="level">
|
||||
<view class="btnf"
|
||||
:style="{backgroundColor:(item.standard=='异常'?'#FFF':item.standard_color)}"
|
||||
:class="[item.standard=='异常'?'btnC':'']">
|
||||
{{item.standard=='异常'?'-':item.standard}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="desc">
|
||||
<view v-if="item.description" class="ming size12">{{item.description}}</view>
|
||||
<view :class="[item.list.length?'statuevue':'']" v-if="item.list">
|
||||
<view class="bi">
|
||||
<view :style="'left:'+item.offset+'%'" class="peobox">
|
||||
<view class="xx"></view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite , ind) in item.list" :key="ind"
|
||||
:style="{backgroundColor:ite.color}">
|
||||
<view class="span1">{{ite.text}}</view>
|
||||
<view class="span" v-if="ind<item.list.length-1">{{ite.max_val}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 体重控制 -->
|
||||
<view v-if="depthInfo.weight_controller" class="w100">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.weight_controller.icon"></image>
|
||||
{{depthInfo.weight_controller.title_name}}
|
||||
</view>
|
||||
<view class="table2 bgfff">
|
||||
<view class="Xlist" v-for="(ite,ind) in depthInfo.weight_controller.list">
|
||||
<view class="name">{{ite.name}}</view>
|
||||
<view>{{ite.value}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 身体类型 -->
|
||||
<view v-if="depthInfo.body_type" class="w100">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.body_type.icon"></image>
|
||||
{{depthInfo.body_type.title_name}}
|
||||
</view>
|
||||
<view class="type">
|
||||
<view class="typeItem">
|
||||
<view class="bold">{{depthInfo.body_type.l_line_color.name}} </view>
|
||||
<view class="Tlist">
|
||||
<view class="line line1"
|
||||
:style="{ backgroundImage: 'linear-gradient(to bottom, '+depthInfo.body_type.l_line_color.standard_list[2].color+','+depthInfo.body_type.l_line_color.standard_list[2].color+','+depthInfo.body_type.l_line_color.standard_list[0].color+')' }">
|
||||
</view>
|
||||
<view class="ge">
|
||||
<view v-for="(ite,ind) in depthInfo.body_type.box_list"
|
||||
:class="[depthInfo.body_type.value==ite?'active':'']">{{ite}}</view>
|
||||
</view>
|
||||
<view class="line line2"
|
||||
:style="{ backgroundImage: 'linear-gradient(to right, '+depthInfo.body_type.r_line_color.standard_list[0].color+','+depthInfo.body_type.r_line_color.standard_list[1].color+','+depthInfo.body_type.r_line_color.standard_list[2].color+')' }">
|
||||
</view>
|
||||
</view>
|
||||
<view class="bold text_r">{{depthInfo.body_type.r_line_color.name}} </view>
|
||||
</view>
|
||||
<view class="Tinfo">
|
||||
<view class="bold">{{depthInfo.body_type.r_line_color.name}}:</view>
|
||||
<view v-for="(ite,ind) in depthInfo.body_type.r_line_color.standard_list" class="TinfoList">
|
||||
<text :style="{'backgroundColor':ite.color}"></text>{{ite.name}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="Tinfo">
|
||||
<view class="bold">{{depthInfo.body_type.l_line_color.name}}:</view>
|
||||
<view v-for="(ite,ind) in depthInfo.body_type.l_line_color.standard_list" class="TinfoList">
|
||||
<text :style="{'backgroundColor':ite.color}"></text>{{ite.name}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 其他指标 -->
|
||||
<view v-if="depthInfo.other_data" class="w100">
|
||||
<view class="title">
|
||||
<image :src="depthInfo.other_data.icon"></image>
|
||||
{{depthInfo.other_data.title_name}}
|
||||
</view>
|
||||
<view class="table2 bgfff">
|
||||
<view class="Xlist" v-for="(ite,ind) in depthInfo.other_data.list">
|
||||
<view class="name">{{ite.name}}</view>
|
||||
<view>{{ite.value}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts.vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
opts2: {
|
||||
color: ["#54d87c"],
|
||||
title: {
|
||||
name: "",
|
||||
},
|
||||
extra: {
|
||||
arcbar: {
|
||||
type: "default",
|
||||
width: 12,
|
||||
backgroundColor: "#d0ffde",
|
||||
startAngle: 0.95,
|
||||
endAngle: 0.05,
|
||||
gap: 2,
|
||||
linearType: "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
opts: {
|
||||
color: [],
|
||||
title: {
|
||||
name: "",
|
||||
},
|
||||
subtitle: {
|
||||
name: "体重(kg)"
|
||||
}
|
||||
},
|
||||
chartData: {},
|
||||
chartData2: {},
|
||||
depthInfo: {
|
||||
body_data: {},
|
||||
body_type: {},
|
||||
fat_analysis: {},
|
||||
muscle_fat: {},
|
||||
other_data: {},
|
||||
segment_fat: {},
|
||||
segment_muscle: {},
|
||||
user_data: {},
|
||||
weight_controller: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
qiunDataCharts,
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user"]),
|
||||
info() {
|
||||
return this.user
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
this.handleLabelList()
|
||||
},
|
||||
methods: {
|
||||
handleLabelList() {
|
||||
let that = this
|
||||
that.$model.getResultDepth({
|
||||
aud_id: that.user.aud_id
|
||||
}).then(res => {
|
||||
console.log("深度报告", res)
|
||||
if (res.code == 0) {
|
||||
that.depthInfo = res.data
|
||||
let chart_data = []
|
||||
let list = that.depthInfo.body_data.list
|
||||
that.opts.color = []
|
||||
for (let i = 0; i < list.length; ++i) {
|
||||
this.opts.color.push(list[i].color)
|
||||
chart_data.push({
|
||||
name: list[i].name,
|
||||
value: Number(list[i].offset),
|
||||
})
|
||||
}
|
||||
this.opts.title.name = that.depthInfo.body_data.value
|
||||
this.chartData = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
data: chart_data
|
||||
}]
|
||||
}));
|
||||
|
||||
this.chartData2 = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
name: "健康评分",
|
||||
data: Number(that.depthInfo.user_data.score) / 100
|
||||
}]
|
||||
}));
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/scss/body.scss";
|
||||
|
||||
.content {
|
||||
padding: 0 10px 20px;
|
||||
}
|
||||
|
||||
.size12 {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.w100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.desc2 {
|
||||
width: 100% !important;
|
||||
padding: 0 !important;
|
||||
background: inherit !important;
|
||||
}
|
||||
|
||||
.date {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 20px;
|
||||
height: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
width: calc(100% - 20px);
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
height: 55px;
|
||||
|
||||
.left {
|
||||
width: calc(100% - 180px);
|
||||
display: flex;
|
||||
|
||||
image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
view {
|
||||
width: calc(100% - 60px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 160px;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: -35px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
|
||||
.rightChart {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.charts-box {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
.score {
|
||||
position: absolute;
|
||||
width: 140px;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
top: 0;
|
||||
|
||||
text {
|
||||
color: $maincolor;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
|
||||
view {
|
||||
width: 28%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 40%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.line::after,
|
||||
.line::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 30px;
|
||||
background: #b6fdcc;
|
||||
border-radius: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.line::before {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.line::after {
|
||||
right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.heartRate {
|
||||
width: calc(100% - 20px);
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
|
||||
.stand {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
|
||||
text {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin: 0 5px;
|
||||
color: $maincolor;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
border-radius: 10px;
|
||||
width: calc(100% - 20px);
|
||||
justify-content: space-between;
|
||||
|
||||
.infoTitle {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.Qlist {
|
||||
width: calc(100% - 140px);
|
||||
margin-top: 10px;
|
||||
|
||||
.QItem {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
padding-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.left {
|
||||
width: calc(100% - 60px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.yuan {
|
||||
background-color: #3E7AF6;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 15px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.value {
|
||||
width: 60px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.QItem:nth-child(even) {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
|
||||
.huan {
|
||||
width: 160px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
margin-top: 35px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bodyimg {
|
||||
padding: 20px 30px;
|
||||
width: calc(100% - 60px);
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
width: 13.75rem;
|
||||
height: 13.2rem;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.L1:nth-child(2) {
|
||||
left: 26px;
|
||||
top: 35px;
|
||||
}
|
||||
|
||||
.L1:nth-child(3) {
|
||||
right: 25px;
|
||||
top: 35px;
|
||||
}
|
||||
|
||||
.L1:nth-child(4) {
|
||||
left: 25px;
|
||||
top: 95px;
|
||||
}
|
||||
|
||||
.L1:nth-child(5) {
|
||||
left: 25px;
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
.L1:nth-child(6) {
|
||||
right: 25px;
|
||||
bottom: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.report {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.table,
|
||||
.table2 {
|
||||
width: calc(100% - 20px);
|
||||
padding: 10px;
|
||||
|
||||
.Xlist {
|
||||
display: flex;
|
||||
line-height: 40px;
|
||||
|
||||
view {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.name::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 40px;
|
||||
background: #f7f7f7;
|
||||
top: 0px;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.Xlist:nth-child(odd) {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
|
||||
.Xlist:nth-child(1) {
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
border-radius: 10px 10px 0 0;
|
||||
background-color: $maincolor !important;
|
||||
}
|
||||
}
|
||||
|
||||
.table2 {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.type {
|
||||
width: calc(100% - 20px);
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
|
||||
.Tlist {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
height: 235px;
|
||||
|
||||
.line {
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 92%;
|
||||
background: #dfdfdf;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.line1 {
|
||||
top: 0;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.line2 {
|
||||
width: 92%;
|
||||
height: 5px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.ge {
|
||||
width: calc(100% - 25px);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
|
||||
view {
|
||||
width: 30%;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
background: #f7f7f7;
|
||||
border: 1px solid $maincolor;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #fff;
|
||||
background: $maincolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Tinfo {
|
||||
display: flex;
|
||||
padding: 5px 0;
|
||||
|
||||
.TinfoList {
|
||||
color: #666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 15%;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
text {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="login">
|
||||
<view class="editem">
|
||||
<view class="item">
|
||||
<view class="text">邮箱</view>
|
||||
<view class="input">
|
||||
<input v-model="phone" placeholder="请输入邮箱"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item ">
|
||||
<view class="text">验证码</view>
|
||||
<view class="input yanzhengma">
|
||||
<input class="uni-input" v-model="code" />
|
||||
<button class="code" type="none" @click="handleCode" v-model="code"
|
||||
:disabled="disabled">{{second<60 ? second+'S后重发':$t("login.sendcode")}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btnlogin" @click="handleTelLogin">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
phone: "",
|
||||
code: "",
|
||||
disabled: false,
|
||||
second: 60,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 登录、
|
||||
handleTelLogin() {
|
||||
let that = this
|
||||
if (!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的邮箱")
|
||||
return
|
||||
}
|
||||
if (!that.code) {
|
||||
that.$tools.msg("请填写验证码")
|
||||
return
|
||||
}
|
||||
that.$model.getAccountMsg({
|
||||
data: that.phone,
|
||||
code: that.code,
|
||||
}).then(res => {
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
} else {
|
||||
that.$tools.msg("设置成功!")
|
||||
that.$store.commit('changeAccountNumber', {
|
||||
my_email: that.phone
|
||||
})
|
||||
uni.redirectTo({
|
||||
url: "/pageTwo/setting/setting"
|
||||
})
|
||||
}
|
||||
}).catch(err => {})
|
||||
},
|
||||
// 获取验证码
|
||||
handleCode() {
|
||||
let that = this
|
||||
if (!that.phone) {
|
||||
that.$tools.msg("请输入邮箱")
|
||||
return
|
||||
}
|
||||
if (!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的邮箱")
|
||||
return
|
||||
}
|
||||
//
|
||||
that.$model.getSendCode({
|
||||
data: that.phone,
|
||||
// type: that.type
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.disabled = true
|
||||
let interval = setInterval(() => {
|
||||
--that.second
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
clearInterval(interval)
|
||||
that.disabled = false
|
||||
that.second = 60
|
||||
}, 60000)
|
||||
}).catch(err => {})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.login {
|
||||
width: calc(100% - 30px);
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
background-color: #fff;
|
||||
z-index: 99;
|
||||
|
||||
.title {
|
||||
text-align: left;
|
||||
color: #333;
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
.editem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.text {
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: calc(100% - 100px);
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
border: #dfdfdf 1px solid;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: 0px;
|
||||
z-index: 88;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.yanzhengma {
|
||||
input {
|
||||
right: 120px;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.code {
|
||||
width: 110px;
|
||||
background: #dfdfdf;
|
||||
font-size: 32rpx;
|
||||
margin: 0;
|
||||
line-height: 40px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.btnlogin {
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
background: $btncolor;
|
||||
font-weight: 700;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="login">
|
||||
<view class="editem">
|
||||
<view class="item">
|
||||
<view class="text">密码</view>
|
||||
<view class="input">
|
||||
<input class="uni-input" v-model="password" placeholder="请输入密码"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text">确认密码</view>
|
||||
<view class="input">
|
||||
<input class="uni-input" v-model="password2" placeholder="请输入确认密码"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btnlogin" @click="handleTelLogin">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
password: "",
|
||||
password2: "",
|
||||
}
|
||||
},
|
||||
onLoad() {},
|
||||
methods: {
|
||||
// 登录、
|
||||
handleTelLogin() {
|
||||
let that = this
|
||||
if (!that.password) {
|
||||
that.$tools.msg("请填写密码")
|
||||
return
|
||||
}
|
||||
if (!that.password2) {
|
||||
that.$tools.msg("请确认密码")
|
||||
return
|
||||
}
|
||||
if (that.password2 != that.password) {
|
||||
that.$tools.msg("请确认两次密码填写一致")
|
||||
return
|
||||
}
|
||||
that.$model.getAccountPassword({
|
||||
password: that.password,
|
||||
c_password: that.password2,
|
||||
}).then(res => {
|
||||
console.log("注册", res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
} else {
|
||||
that.$tools.msg("密码设置成功")
|
||||
uni.navigateBack()
|
||||
}
|
||||
}).catch(err => {})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.login {
|
||||
width: calc(100% - 30px);
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
background-color: #fff;
|
||||
z-index: 99;
|
||||
|
||||
.editem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size:28rpx;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.text {
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: calc(100% - 100px);
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
border: #dfdfdf 1px solid;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: 0px;
|
||||
z-index: 88;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btnlogin {
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
background: $btncolor;
|
||||
font-weight: 700;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="login">
|
||||
<view class="editem">
|
||||
<view class="item">
|
||||
<view class="text">手机号</view>
|
||||
<view class="input">
|
||||
<input v-model="phone" placeholder="请输入手机号" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="item ">
|
||||
<view class="text">验证码</view>
|
||||
<view class="input yanzhengma">
|
||||
<input class="uni-input" v-model="code" />
|
||||
<button class="code" type="none" @click="handleCode" v-model="code"
|
||||
:disabled="disabled">{{second<60 ? second+'S后重发':$t("login.sendcode")}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btnlogin" @click="handleTelLogin">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
phone: "",
|
||||
code: "",
|
||||
disabled: false,
|
||||
second: 60,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 登录、
|
||||
handleTelLogin() {
|
||||
let that = this
|
||||
if (!phoneType && !(/^1[3456789]\d{9}$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的手机号")
|
||||
return
|
||||
}
|
||||
if (!that.code) {
|
||||
that.$tools.msg("请填写验证码")
|
||||
return
|
||||
}
|
||||
that.$model.getAccountMsg({
|
||||
data: that.phone,
|
||||
code: that.code,
|
||||
}).then(res => {
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
} else {
|
||||
that.$tools.msg("设置成功!")
|
||||
that.$store.commit('changeAccountNumber', {
|
||||
my_tel: that.phone
|
||||
})
|
||||
uni.redirectTo({
|
||||
url: "/pageTwo/setting/setting"
|
||||
})
|
||||
}
|
||||
}).catch(err => {})
|
||||
},
|
||||
// 获取验证码
|
||||
handleCode() {
|
||||
let that = this
|
||||
if (!that.phone) {
|
||||
that.$tools.msg("请输入手机号")
|
||||
return
|
||||
}
|
||||
if (!phoneType && !(/^1[3456789]\d{9}$/.test(that.phone))) {
|
||||
that.$tools.msg("请输入正确的手机号")
|
||||
return
|
||||
}
|
||||
//
|
||||
that.$model.getSendCode({
|
||||
data: that.phone,
|
||||
// type: that.type
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.disabled = true
|
||||
let interval = setInterval(() => {
|
||||
--that.second
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
clearInterval(interval)
|
||||
that.disabled = false
|
||||
that.second = 60
|
||||
}, 60000)
|
||||
}).catch(err => {})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.login {
|
||||
width: calc(100% - 30px);
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
background-color: #fff;
|
||||
z-index: 99;
|
||||
|
||||
.title {
|
||||
text-align: left;
|
||||
color: #333;
|
||||
font-size:40rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
.editem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size:28rpx;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.text {
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size:28rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: calc(100% - 100px);
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
border: #dfdfdf 1px solid;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: 0px;
|
||||
z-index: 88;
|
||||
font-size:28rpx;
|
||||
}
|
||||
|
||||
.yanzhengma {
|
||||
input {
|
||||
right: 120px;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.code {
|
||||
width: 110px;
|
||||
background: #dfdfdf;
|
||||
font-size: 32rpx;
|
||||
margin: 0;
|
||||
line-height: 40px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.btnlogin {
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
background: $btncolor;
|
||||
font-weight: 700;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="caritem">
|
||||
<view class="text">头像</view>
|
||||
<image :src="user.head_pic" class="image"></image>
|
||||
</view>
|
||||
<view class="caritem">
|
||||
<view class="text">昵称</view>
|
||||
<view class="text_r">
|
||||
<text v-if="!isEdit">{{user.nickname}}</text>
|
||||
<input v-else type="text" v-model='nickname' @blur="handleBlur" />
|
||||
<uni-icons type="compose" color="#FEC407" @click="isEdit=true" class="ml-10" size="22"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="caritem" @click="navTo('/pageTwo/setting/phone')">
|
||||
<view class="text">手机号</view>
|
||||
<view class="text_r">
|
||||
<text>{{user.my_tel}}</text>
|
||||
<uni-icons type="right"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="caritem" @click="navTo('/pageTwo/setting/email')">
|
||||
<view class="text">邮箱</view>
|
||||
<view class="text_r">
|
||||
<text>{{user.my_email}}</text>
|
||||
<uni-icons type="right"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="caritem" @click="navTo('/pageTwo/setting/password')">
|
||||
<view class="text">设置密码</view>
|
||||
<uni-icons type="right"></uni-icons>
|
||||
</view>
|
||||
<view class="btn mb-15" @click="handleOutLogin">删除账号</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isEdit: false,
|
||||
headimg: null,
|
||||
nickname: ""
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["accountNumber"]),
|
||||
user() {
|
||||
return this.accountNumber
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleOutLogin() {
|
||||
let that = this
|
||||
uni.showModal({
|
||||
title: '友情提示',
|
||||
confirmText: '删除',
|
||||
content: '删除成功后,该账号的所有关联信息将被清空且无法找回,是否删除?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
that.$model.getdeleteAccount({}).then((res) => {
|
||||
if (res.code != 0) return
|
||||
that.$tools.msg("删除成功!");
|
||||
uni.setStorageSync('token', null)
|
||||
uni.setStorageSync('aan_id', null)
|
||||
uni.clearStorageSync()
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: "/pageTwo/login/login"
|
||||
})
|
||||
}, 3000);
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
that.$tools.msg("您已取消操作!");
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
// 修改昵称
|
||||
handleBlur() {
|
||||
let that = this
|
||||
return that.$model.getAccountNickname({
|
||||
nickname: that.nickname,
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.user.nickname = that.nickname
|
||||
that.$store.commit('changeAccountNumber', {
|
||||
nickname: that.nickname
|
||||
})
|
||||
that.isEdit = false
|
||||
})
|
||||
},
|
||||
navTo(url) {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
background-color: #F3F4F6;
|
||||
padding: 15px;
|
||||
min-height: 100vh;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
|
||||
.image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.text_r {
|
||||
width: 70%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
text {
|
||||
width: calc(100% - 30px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 80%;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
background: #999;
|
||||
margin: 50px 15px 0 15px;
|
||||
}
|
||||
|
||||
.caritem {
|
||||
width: calc(100% - 20px);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 0 10px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.uni-icons {
|
||||
width: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<web-view :src="webviewUrl"></web-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
webviewUrl: ''
|
||||
};
|
||||
},
|
||||
// 页面加载时接收URL参数并解码
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
let token = uni.getStorageSync('token')
|
||||
let url = options.url + '?token=' + token + '&id=' + options.id
|
||||
that.webviewUrl = decodeURIComponent(url);
|
||||
console.log("11111", options, url, this.webviewUrl)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
<template>
|
||||
<view class="body">
|
||||
<view class="top">
|
||||
<view class="info box_shadow" v-for="(ite,ind) in Measure.top_list"
|
||||
:style="{'backgroundColor':ite.bk_color}" @click="handelCurveDetailed">
|
||||
<view class="title">
|
||||
<view class="bold">{{ite.name}}</view>
|
||||
<view class="c999">
|
||||
{{ite.time}}
|
||||
<uni-icons type="right" class="ml-10" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weight">
|
||||
<view class="left">
|
||||
<view class="number"><text class="size26 bold">{{ite.value}}</text>{{ite.unit}}</view>
|
||||
<view class="standard bold size16" :style="{'color':ite.standard_color}">{{ite.standard}}</view>
|
||||
</view>
|
||||
<view class="charts">
|
||||
<qiun-data-charts type="area" :chartData="ite.curve_list.line" :canvas2d="true" :opts="opts"
|
||||
:canvasId="ite.key_name+'charts09'" :Width="140" :Height="85" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="Ideal c999" v-if="ite.ideal_weight">
|
||||
<text>理想{{ite.name}}</text>
|
||||
<text>{{ite.ideal_weight}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="function mt-15">
|
||||
<view @click="handlerRecord">
|
||||
<image src="/static/shoudong.png" mode="widthFix"></image>
|
||||
</view>
|
||||
<view @click="handReport">
|
||||
<image src="/static/shendu.png" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="tools">
|
||||
<view class="item box_shadow" v-for="(ite,ind) in Measure.card_list" @click="handleTools(ite.key_name)">
|
||||
<view class="top">
|
||||
<image :src="ite.icon"></image>{{ite.name}}
|
||||
</view>
|
||||
<view class="number">
|
||||
<text class="bold"
|
||||
:class="[ite.key_name=='body_level'||ite.key_name=='body_type'?'size14':'size20']">{{ite.value}}</text>{{ite.unit}}
|
||||
</view>
|
||||
<view class="bold size14" :style="{'color':ite.standard_color}">{{ite.standard}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 手动记录 -->
|
||||
<record></record>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import record from '@/components/bodyIndex/record.vue';
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts.vue'
|
||||
export default {
|
||||
name: "body",
|
||||
components: {
|
||||
record,
|
||||
qiunDataCharts,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
opts: {
|
||||
padding: [0, 0, 0, 0],
|
||||
dataLabel: false,
|
||||
dataPointShape: false,
|
||||
enableScroll: false,
|
||||
xAxis: {
|
||||
disabled: true,
|
||||
axisLine: false,
|
||||
disableGrid: true,
|
||||
},
|
||||
yAxis: {
|
||||
gridType: "dash",
|
||||
dashLength: 2,
|
||||
disabled: true,
|
||||
axisLine: false,
|
||||
disableGrid: true,
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "MeasureResult"]),
|
||||
info() {
|
||||
return this.user
|
||||
},
|
||||
Measure() {
|
||||
return this.MeasureResult
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 详情
|
||||
handleTools(name) {
|
||||
uni.navigateTo({
|
||||
url: "/body/home/body?to=" + name
|
||||
})
|
||||
},
|
||||
// 深度
|
||||
handReport() {
|
||||
uni.navigateTo({
|
||||
url: "/body/report/report"
|
||||
})
|
||||
},
|
||||
// 趋势
|
||||
handelCurveDetailed(){
|
||||
uni.navigateTo({
|
||||
url: "/body/curve/curve"
|
||||
})
|
||||
},
|
||||
// 手动
|
||||
handlerRecord() {
|
||||
this.$store.commit('changeRecord', true)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.body {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin: 15px 10px;
|
||||
padding: 10px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.weight {
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left {
|
||||
width: 40%;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.target {
|
||||
color: #999;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.charts {
|
||||
width: 50%;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.function {
|
||||
display: flex;
|
||||
margin: 0 5px;
|
||||
width: calc(100% - 10px);
|
||||
justify-content: space-between;
|
||||
|
||||
view {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.tools {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 0 10px;
|
||||
padding-left: 3%;
|
||||
width: 97%;
|
||||
background: #f7f7f7;
|
||||
box-shadow: none;
|
||||
justify-content: space-between;
|
||||
|
||||
.item {
|
||||
width: 40%;
|
||||
background: #fff;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 10px;
|
||||
padding: 10px 3%;
|
||||
margin-right: 3%;
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.number {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
<template>
|
||||
<view class="wrapper" v-if="isDrawe">
|
||||
<view class="bg" @click="clear"></view>
|
||||
<view class="wrapper_box">
|
||||
<view class="top">
|
||||
<image class="headimage mt-10" v-if="userinfo.head_pic" :src="userinfo.head_pic"></image>
|
||||
<view class="overflow">{{userinfo.nickname}}</view>
|
||||
</view>
|
||||
<view class="drawerList">
|
||||
<view class="drawerList_item" v-for="(item, index) in List" :key="index" @click="toggle(item)"
|
||||
v-if="List.length">
|
||||
<image v-if="item.head_pic" :src="item.head_pic" class="image1"></image>
|
||||
<view class="right">
|
||||
<view class="name">
|
||||
<view class="overflow">
|
||||
{{item.nickname}}
|
||||
</view>
|
||||
<view class="dangqian" v-if="item.id == userinfo.id">当前</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view>{{item.gender==1?'男':'女'}}</view>
|
||||
<view>{{item.age}}岁</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="add" @click="addInfo()">
|
||||
+
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "familayList", "isDrawe"]),
|
||||
userinfo() {
|
||||
return this.user
|
||||
},
|
||||
List() {
|
||||
return this.familayList
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 切换用户
|
||||
toggle(val) {
|
||||
let that = this
|
||||
uni.setStorageSync('userid', val.id)
|
||||
uni.setStorageSync('gender', val.gender)
|
||||
that.$store.commit('changeUser', val)
|
||||
that.$store.dispatch("getResult", {
|
||||
aud_id: val.id
|
||||
})
|
||||
that.$store.commit("changeDrawe", false);
|
||||
// that.handlePublicRecord(val.id)
|
||||
},
|
||||
// 公共手动记录内容
|
||||
handlePublicRecord(id) {
|
||||
let that = this
|
||||
that.$model.getPublicRecord({
|
||||
aud_id: id
|
||||
}).then(res => {
|
||||
console.log("公共手动记录", res)
|
||||
if (res.code == 0) {
|
||||
that.$store.commit('changePublicRecord', res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
//添加
|
||||
addInfo() {
|
||||
let that = this
|
||||
uni.navigateTo({
|
||||
url: "/pageTwo/my/userInfo"
|
||||
})
|
||||
that.$store.commit("changeDrawe", false);
|
||||
},
|
||||
clear() {
|
||||
this.$store.commit("changeDrawe", false);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 999;
|
||||
|
||||
.bg {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.headimage {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: auto;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.dangqian {
|
||||
font-size: 24upx !important;
|
||||
}
|
||||
|
||||
@keyframes wrapper_box {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
<template>
|
||||
<view v-if="isFirst" class="wrapper wrapperbg">
|
||||
<view class="bg" @click="onTap">
|
||||
<view class="edit" @click.stop>
|
||||
<view class="title">初始体重</view>
|
||||
<view class="editem">
|
||||
<view class="name">日期</view>
|
||||
<view class="right">
|
||||
<picker mode="date" :end="endDate" @change="changeLog" :fields="fields">
|
||||
<view class="uni-input">{{regTime?regTime:'请选择'}}</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="editem">
|
||||
<view class="name">体重</view>
|
||||
<view class="right">
|
||||
<input v-model="weight" type="digit" placeholder="请输入" />kg
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn close" @click="onTap()">取消</view>
|
||||
<view class="btn" @click="handleTarget">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
regTime: "",
|
||||
weight: "",
|
||||
fields: "",
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "isFirst"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
// 初始体重
|
||||
handleTarget() {
|
||||
let that = this
|
||||
if (!that.regTime) {
|
||||
that.$tools.msg("请选择测量日期")
|
||||
return
|
||||
}
|
||||
if (!that.weight) {
|
||||
that.$tools.msg("请输入测量体重")
|
||||
return
|
||||
}
|
||||
that.$model.getfirstweight({
|
||||
aud_id: that.user.aud_id,
|
||||
time: that.regTime,
|
||||
weight: that.weight,
|
||||
}).then(res => {
|
||||
that.$tools.msg(res.msg)
|
||||
if (res.code == 0) {
|
||||
that.$store.commit("changeFirst", false);
|
||||
that.$emit("handleLabelList", that.endDate, that.startDate)
|
||||
// that.$store.dispatch('getUserInfo', {
|
||||
// aud_id: that.user.aud_id
|
||||
// })
|
||||
that.regTime = ""
|
||||
that.weight = ""
|
||||
}
|
||||
})
|
||||
},
|
||||
//
|
||||
changeLog(e) {
|
||||
this.regTime = e.detail.value
|
||||
},
|
||||
onTap() {
|
||||
this.weight = ""
|
||||
this.regTime = ""
|
||||
this.$store.commit("changeFirst", false);
|
||||
},
|
||||
hideKeyboard() {
|
||||
uni.hideKeyboard()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.btn {
|
||||
width: 40%;
|
||||
float: right;
|
||||
margin-top: 15px;
|
||||
background: $maincolor !important;
|
||||
}
|
||||
|
||||
.edit {
|
||||
top: 20%
|
||||
}
|
||||
|
||||
.close {
|
||||
background: #fff !important;
|
||||
float: left;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
<template>
|
||||
<view class="wrapper" v-if="isRecord">
|
||||
<view class="bg" @click="onTap">
|
||||
<view class="edit" @click.stop>
|
||||
<view class="title">手动记录</view>
|
||||
<view class="editem">
|
||||
<view class="left">日期</view>
|
||||
<view class="right">
|
||||
<picker mode="date" :end="endDate" @change="changeLog" :fields="fields">
|
||||
<view class="uni-input">{{regTime?regTime:'请选择'}}</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 身体 -->
|
||||
<view>
|
||||
<view class="editem" v-if="userInfo&&userInfo.height">
|
||||
<view class="name">身高</view>
|
||||
<view class="right">
|
||||
<input type="digit" v-model="height" placeholder="请输入身高" />cm
|
||||
</view>
|
||||
</view>
|
||||
<view class="editem" v-if="userInfo&&userInfo.weight">
|
||||
<view class="name">体重</view>
|
||||
<view class="right">
|
||||
<input type="digit" v-model="weight" placeholder="请输入体重">kg
|
||||
</view>
|
||||
</view>
|
||||
<view class="editem" v-if="userInfo.stage=='婴儿'">
|
||||
<view class="left">头围</view>
|
||||
<view class="right">
|
||||
<input v-model="head" type="digit" placeholder="请输入" />cm
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn close" @click="onTap()">取消</view>
|
||||
<view class="btn" @click="handleinsertmeasure()">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
props: {
|
||||
rtype: null,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
regTime: '',
|
||||
weight: "",
|
||||
height: '',
|
||||
fields: "",
|
||||
head: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "isRecord"]),
|
||||
userInfo() {
|
||||
return this.user
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
// 身体
|
||||
handleinsertmeasure() {
|
||||
let that = this
|
||||
if (!that.regTime) {
|
||||
that.$tools.msg("请选择测量日期")
|
||||
return
|
||||
}
|
||||
if (!that.height) {
|
||||
that.$tools.msg("请输入测量身高")
|
||||
return
|
||||
}
|
||||
if (!that.weight) {
|
||||
that.$tools.msg("请输入测量体重")
|
||||
return
|
||||
}
|
||||
that.$model.getinsertmeasure({
|
||||
aud_id: that.user.aud_id,
|
||||
time: that.regTime,
|
||||
weight: that.weight,
|
||||
height: that.height,
|
||||
head_data: that.head ? that.head : 0
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.$tools.msg(res.msg)
|
||||
that.$store.dispatch("getResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
that.$store.dispatch("getUserInfo", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
that.onTap()
|
||||
})
|
||||
},
|
||||
changeLog(e) {
|
||||
this.regTime = e.detail.value
|
||||
},
|
||||
onTap() {
|
||||
let that = this
|
||||
that.weight = ""
|
||||
that.height = ""
|
||||
that.regTime = ""
|
||||
that.$store.commit("changeRecord", false);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.btn {
|
||||
width: 40%;
|
||||
float: right;
|
||||
margin-top: 15px;
|
||||
background: $maincolor !important;
|
||||
}
|
||||
|
||||
.close {
|
||||
background: #dfdfdf !important;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
<template>
|
||||
<view v-if="isTarget" class="wrapper">
|
||||
<view class="bg" @click="onTap">
|
||||
<view class="edit" @click.stop>
|
||||
<view class="title">目标体重</view>
|
||||
<view class="editem">
|
||||
<view class="left">目标体重</view>
|
||||
<view class="right">
|
||||
<input class="text" type="digit" placeholder="请输入" v-model="inputvalue" />kg
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn close" @click="onTap()">取消</view>
|
||||
<view class="btn" @click="handleWeight">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
inputvalue: "",
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "isTarget"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 目标体重
|
||||
handleWeight() {
|
||||
let that = this
|
||||
if (!that.inputvalue) {
|
||||
that.$tools.msg("请输入目标体重")
|
||||
return
|
||||
}
|
||||
that.$model.getTargetweight({
|
||||
aud_id: that.user.aud_id,
|
||||
weight: that.inputvalue,
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.$tools.msg(res.msg)
|
||||
that.$store.commit("changeTarget", false);
|
||||
that.$emit("handleLabelList", that.endDate, that.startDate)
|
||||
// that.$store.dispatch('getUserInfo', {
|
||||
// aud_id: that.user.aud_id
|
||||
// })
|
||||
that.inputvalue = ""
|
||||
})
|
||||
},
|
||||
onTap() {
|
||||
this.inputvalue = ""
|
||||
this.$store.commit("changeTarget", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrapper {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 999;
|
||||
|
||||
.bg {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.edit {
|
||||
width: 15rem;
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
position: relative;
|
||||
top: 15%;
|
||||
margin: auto;
|
||||
z-index: 99999;
|
||||
overflow: hidden;
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
color: #333;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.editem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
font-size: 32rpx;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
height: 40px;
|
||||
justify-content: space-between;
|
||||
background: #eee;
|
||||
padding: 0px 10px;
|
||||
align-items: center;
|
||||
|
||||
.radioimg {
|
||||
font-size: 44rpx;
|
||||
color: $btncolor;
|
||||
}
|
||||
|
||||
.radio {
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: 4rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 60%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: right;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
|
||||
input {
|
||||
margin-right: 10px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
picker {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uni-input {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: right;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.value {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
width: 3rem;
|
||||
text-align: center;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 40%;
|
||||
float: right;
|
||||
margin-top: 15px;
|
||||
background: $maincolor !important;
|
||||
}
|
||||
|
||||
.edit {
|
||||
top: 20%
|
||||
}
|
||||
|
||||
.close {
|
||||
background: #dfdfdf !important;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
<template>
|
||||
<view class="cardContent">
|
||||
<view class="cardList">
|
||||
<view class="caritem" @click="handleNavTol('/pageTwo/charts/charts')">
|
||||
<image src="/static/q5.png"></image>
|
||||
<view>曲线</view>
|
||||
</view>
|
||||
<view class="caritem" @click="handleNavTol('/pageTwo/compk/contrast')">
|
||||
<image src="/static/q3.png"></image>
|
||||
<view>数据对比</view>
|
||||
</view>
|
||||
<view class="caritem" @click="handlerRecord">
|
||||
<image src="/static/q7.png"></image>
|
||||
<view>添加记录</view>
|
||||
</view>
|
||||
<view class="caritem" @click="handleNavTol('/pageTwo/history/history')">
|
||||
<image src="/static/q8.png"></image>
|
||||
<view>历史记录</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="cardListchosen">
|
||||
<view class="item" v-for="(ite,ind) in cardList.chosen_fixed" @click="handleNavTol(ite.page_jump)">
|
||||
<view class="info">
|
||||
<image :src="ite.icon"></image>
|
||||
<view>{{ite.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite,ind) in cardList.chosen_yes" @click="handleNavTol(ite.page_jump)">
|
||||
<view class="info">
|
||||
<image :src="ite.icon"></image>
|
||||
<view>{{ite.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="setCard" @click="handleSetCard">
|
||||
工具设置
|
||||
</view>
|
||||
<!-- 手动记录 -->
|
||||
<record></record>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import record from '@/components/cardIndex/record.vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
record,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user', "CardList"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
cardList() {
|
||||
return this.CardList
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 手动
|
||||
handlerRecord() {
|
||||
this.$store.commit('changeTsPublicRecord', true)
|
||||
},
|
||||
handleNavTol(url) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
},
|
||||
handleSetCard() {
|
||||
uni.navigateTo({
|
||||
url: "/pageTwo/cardList/card"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.cardContent {
|
||||
background: #F7F7F7;
|
||||
padding: 5px 0 15PX;
|
||||
}
|
||||
|
||||
.cardList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
background: #fff;
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
|
||||
.caritem {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cardListchosen {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin: 15px 10px;
|
||||
|
||||
.item {
|
||||
width: 47%;
|
||||
background-color: #fff;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
border-radius: 5px;
|
||||
|
||||
.info {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: #f2f2f2;
|
||||
margin-right: 10px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setCard {
|
||||
color: $maincolor;
|
||||
margin: 15px;
|
||||
text-align: center;
|
||||
border: 1px solid $maincolor;
|
||||
border-radius: 10px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
<template>
|
||||
<view class="wrapper" v-if="isPublicRecord">
|
||||
<view class="bg" @click="onTap">
|
||||
<view class="edit" @click.stop>
|
||||
<view class="title">添加记录</view>
|
||||
<view class="editem">
|
||||
<view class="left">选择项目</view>
|
||||
<view class="right">
|
||||
<picker mode="selector" @change="bindPickerChange" :value="index" :range="publicRecordInfo"
|
||||
range-key="name">
|
||||
<view class="uni-input">{{index!=-1?publicRecordInfo[index].name:'请选择'}}</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 项目内容 -->
|
||||
<view class="editem" v-for="(ite,ind) in RecordList">
|
||||
<view class="left">{{ite.name}}</view>
|
||||
<!-- 日期选择器 -->
|
||||
<view class="right" v-if="ite.type == 'date'">
|
||||
<picker mode="date" :end="endDate" @change="changeLog($event,ind)" :fields="fields"
|
||||
:value="RecordList[ind].value">
|
||||
<view class="uni-input">
|
||||
{{RecordList[ind].value?RecordList[ind].value:'请选择'}}
|
||||
</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
<!-- 分秒选择器 -->
|
||||
<view class="right" v-if="ite.type == 'multiSelector'">
|
||||
<picker mode="multiSelector" :value="timesTndex" :range="timeList"
|
||||
@change="bindTimeChange($event,ind)">
|
||||
<view class="size16">
|
||||
{{RecordList[ind].value?RecordList[ind].value:'请选择'}}{{ite.unit}}
|
||||
</view>
|
||||
</picker>
|
||||
<uni-icons type="bottom" class="ml-15 c666"></uni-icons>
|
||||
</view>
|
||||
<!-- 数字输入框 -->
|
||||
<view class="right" v-if="ite.type == 'number'">
|
||||
<input type="number" v-model="ite.value" placeholder="请输入">{{ite.unit}}
|
||||
</view>
|
||||
<!-- 小数输入框 -->
|
||||
<view class="right" v-if="ite.type == 'digit'">
|
||||
<input type="digit" v-model="ite.value" placeholder="请输入">{{ite.unit}}
|
||||
</view>
|
||||
<!-- 文本输入框 -->
|
||||
<view class="right" v-if="ite.type == 'text'">
|
||||
<input type="text" v-model="ite.value" placeholder="请输入">{{ite.unit}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="btn close" @click="onTap()">取消</view>
|
||||
<view class="btn" @click="handlepublicmeasure">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
//
|
||||
fields: "",
|
||||
index: 0,
|
||||
timeList: [],
|
||||
RecordList: [],
|
||||
timesTndex: [1, 0],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "isPublicRecord", "PublicRecord"]),
|
||||
userInfo() {
|
||||
return this.user
|
||||
},
|
||||
publicRecordInfo() {
|
||||
let that = this
|
||||
return that.PublicRecord
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
that.timeList = that.$tools.gethms()
|
||||
that.RecordList = that.PublicRecord[that.index].list
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
bindPickerChange(e) {
|
||||
let that = this
|
||||
for (let i = 0; i < that.RecordList.length; i++) {
|
||||
that.RecordList[i].value = ""
|
||||
}
|
||||
that.index = e.detail.value
|
||||
that.RecordList = that.publicRecordInfo[that.index].list
|
||||
},
|
||||
changeLog(e, ind) {
|
||||
let that = this
|
||||
that.RecordList[ind].value = e.detail.value
|
||||
},
|
||||
bindTimeChange(e, ind) {
|
||||
let that = this
|
||||
let m = e.target.value[0]
|
||||
let s = e.target.value[1]
|
||||
that.timesTndex = e.target.value
|
||||
that.RecordList[ind].value = that.timeList[0][m].substring(0, 2) + ':' + that.timeList[1][s].substring(0,
|
||||
2)
|
||||
},
|
||||
handlepublicmeasure() {
|
||||
let that = this
|
||||
if (that.index == -1) {
|
||||
that.$tools.msg("请选择项目")
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < that.RecordList.length; i++) {
|
||||
if (that.RecordList[i].value == "") {
|
||||
that.$tools.msg("请输入正确信息")
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
that.$model.getpublicmeasure({
|
||||
aud_id: that.user.aud_id,
|
||||
type: that.publicRecordInfo[that.index].key_word,
|
||||
data: that.RecordList
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
that.$tools.msg(res.msg)
|
||||
that.onTap()
|
||||
})
|
||||
},
|
||||
onTap() {
|
||||
let that = this
|
||||
that.index = 0
|
||||
that.RecordList = that.publicRecordInfo[that.index].list
|
||||
for (let i = 0; i < that.RecordList.length; i++) {
|
||||
that.RecordList[i].value = ""
|
||||
}
|
||||
that.$store.commit("changeTsPublicRecord", false);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.btn {
|
||||
width: 40%;
|
||||
float: right;
|
||||
margin-top: 15px;
|
||||
background: $maincolor !important;
|
||||
}
|
||||
|
||||
.close {
|
||||
background: #dfdfdf !important;
|
||||
float: left;
|
||||
}
|
||||
|
||||
picker {
|
||||
font-size: 32rpx !important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,458 @@
|
|||
<template>
|
||||
<view class="weightPages">
|
||||
<view class="table">
|
||||
<view class="text">
|
||||
<image src="/static/zhong.png"></image>
|
||||
<text @click="openBluetoothAdapter">{{bleTipsText}}</text>
|
||||
</view>
|
||||
<view class="duan" @click="handleBack" v-if="isShow&&isConnection == 2">
|
||||
断开连接
|
||||
</view>
|
||||
</view>
|
||||
<view class="name">{{name}}</view>
|
||||
<!-- 蓝牙称重 -->
|
||||
<view class="weight-wrap">
|
||||
<view class="weight" @click="inputDialogToggle">
|
||||
<text class="val">{{weight == '' ? '0.0':weight}}</text>
|
||||
<text class="unit">{{unitConversion(unit)}}</text>
|
||||
</view>
|
||||
<view class="weight">
|
||||
<text class="val">{{kcal?kcal:0}}</text>
|
||||
<text class="unit">kcal</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="groupbtn">
|
||||
<view class="btn danwei">
|
||||
<view class="lan border-bottom">
|
||||
<view class="right">
|
||||
<picker mode="selector" :range="unitA" range-key="name" @change="changleUnits"
|
||||
:value="unitListIndex">
|
||||
<view class="uni-input">
|
||||
单位
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn" @click="handleDetailSub" :style="{'width':!stopblue?'20%':'45%'}">保存</view>
|
||||
<view class="btn" @click="handleDetailNext" v-if="!stopblue">下一味</view>
|
||||
<view class="btn qingling" @click="handleqingling">清零</view>
|
||||
</view>
|
||||
<view>
|
||||
<uni-popup ref="popup" type="dialog">
|
||||
<uni-popup-dialog mode="input" title="重量" placeholder="请输入食物重量" @close="close"
|
||||
@confirm="confirm"></uni-popup-dialog>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
kcal: "",
|
||||
weightALL: "",
|
||||
bleTipsText: "",
|
||||
unit: 'g',
|
||||
unitA: [],
|
||||
stopblue: false,
|
||||
unitListIndex: 0,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
weightKcal: {
|
||||
type: Number,
|
||||
default: 0 //当前测量食物每g含的kcal
|
||||
},
|
||||
isLast: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "isBluetoothTyle", "bleValue"]),
|
||||
weight() {
|
||||
let weightNew = this.convertToGrams(this.bleValue.countWeight, this.bleValue.unit)
|
||||
this.kcal = (Number(this.weightKcal) * weightNew).toFixed(1)
|
||||
this.unit = this.bleValue.unit
|
||||
return this.bleValue.countWeight
|
||||
},
|
||||
isConnection() {
|
||||
this.bleTipsText = this.bleValue.bleTipsText
|
||||
return this.bleValue.isConnectStatus
|
||||
},
|
||||
isShow() {
|
||||
return this.bleValue.serviceId != '' ? true : false
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
uni.onBluetoothAdapterStateChange(function(res) {
|
||||
// that.$store.commit("changeBluetooth", res.available);
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
isBluetoothTyle: function() {
|
||||
let that = this
|
||||
if (!that.isBluetoothTyle) {
|
||||
that.handleBack()
|
||||
}
|
||||
},
|
||||
isLast: {
|
||||
handler(newVal, oldVal) {
|
||||
this.stopblue = newVal
|
||||
},
|
||||
// deep: true,
|
||||
immediate: true
|
||||
|
||||
},
|
||||
bleValue: {
|
||||
handler(newVal, oldVal) {
|
||||
this.unitA = newVal.unitList
|
||||
this.unitListIndex = newVal.unitList.findIndex(ite => ite.unit == newVal.unit)
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 初始化蓝牙
|
||||
openBluetoothAdapter() {
|
||||
let that = this
|
||||
if (that.isConnection == 0) return
|
||||
that.kcal = ""
|
||||
that.$store.commit('changeBluetoothValue', {
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
notify: '',
|
||||
write: '',
|
||||
unit: "g",
|
||||
type: 1,
|
||||
unitList: that.$json.unitMinus,
|
||||
countWeight: "",
|
||||
bleTipsText: "蓝牙搜索中",
|
||||
isConnectStatus: 0,
|
||||
})
|
||||
that.$ble.openBluetoothAdapter()
|
||||
},
|
||||
changleUnits(e) {
|
||||
let that = this
|
||||
let name = that.unitA[e.detail.value].name
|
||||
let val = that.unitA[e.detail.value].unit
|
||||
if (that.isShow && that.unit != name) {
|
||||
that.handletoggleUnit(that.unitConversion2(val))
|
||||
}
|
||||
if (that.bleValue.serviceId == '') {
|
||||
that.unitListIndex = [e.detail.value]
|
||||
that.$store.commit('changeBluetoothValue', {
|
||||
unit: that.unitA[e.detail.value].unit,
|
||||
})
|
||||
}
|
||||
},
|
||||
convertToGrams(value, fromUnit) {
|
||||
const conversionFactors = {
|
||||
'lb': 453.59237, // 1磅 = 453.59237克
|
||||
'oz': 28.349523125, // 1盎司 = 28.349523125克
|
||||
'kg': 1000, // 1公斤 = 1000克
|
||||
'g': 1,
|
||||
'ml': 1,
|
||||
'斤': 500,
|
||||
'Waterml': 1,
|
||||
'milkml': 1.03
|
||||
};
|
||||
|
||||
if (!conversionFactors.hasOwnProperty(fromUnit)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return value * conversionFactors[fromUnit];
|
||||
},
|
||||
unitConversion2(unit) {
|
||||
if (unit == 'kg') {
|
||||
return 0x00
|
||||
} else if (unit == '斤') {
|
||||
return 0x01
|
||||
} else if (unit == 'st:lb') {
|
||||
return 0x02
|
||||
} else if (unit == 'lb') {
|
||||
return 0x03
|
||||
} else if (unit == 'g') {
|
||||
return 0x04
|
||||
} else if (unit == 'ml') {
|
||||
return 0x05
|
||||
} else if (unit == 'Waterml') {
|
||||
return 0x06
|
||||
} else if (unit == 'milkml') {
|
||||
return 0x07
|
||||
} else if (unit == 'oz') {
|
||||
return 0x08
|
||||
} else if (unit == 'floz') {
|
||||
return 0x09
|
||||
} else if (unit == 'lboz') {
|
||||
return 0x0A
|
||||
}
|
||||
return unit
|
||||
},
|
||||
// 下发单位
|
||||
handletoggleUnit(unit) {
|
||||
let that = this
|
||||
let checksum = 0;
|
||||
const bytes = [0xC5, 0x03, 0x05, 0x11]
|
||||
bytes[4] = unit
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
checksum ^= bytes[i];
|
||||
}
|
||||
bytes[5] = checksum
|
||||
that.sendData(new Uint8Array(bytes).buffer)
|
||||
},
|
||||
handleqingling() {
|
||||
let that = this
|
||||
let str = "C503071100D0"
|
||||
let buf = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function(h) {
|
||||
return parseInt(h, 16)
|
||||
}))
|
||||
that.sendData(buf.buffer)
|
||||
},
|
||||
sendData(buffer) {
|
||||
let that = this
|
||||
uni.writeBLECharacteristicValue({
|
||||
deviceId: that.bleValue.deviceId,
|
||||
serviceId: that.bleValue.serviceId,
|
||||
characteristicId: that.bleValue.write,
|
||||
value: buffer,
|
||||
success: res => {
|
||||
console.log('下发指令成功', res.errMsg)
|
||||
},
|
||||
fail: res => {
|
||||
console.log("下发指令失败", res);
|
||||
},
|
||||
})
|
||||
},
|
||||
handleBack() {
|
||||
let that = this
|
||||
that.$store.commit("changeBluetoothValue", {
|
||||
bleTipsText: "连接失败,点击重新连接",
|
||||
unitList: that.$json.unitMinus,
|
||||
isConnectStatus: 1,
|
||||
})
|
||||
that.$ble.stopBluetoothDevicesDiscovery() //取消蓝牙搜索
|
||||
that.$ble.closeBLEConnection(that.bleValue.deviceId)
|
||||
that.$ble.closeBluetoothAdapter()
|
||||
},
|
||||
|
||||
unitConversion(unit) {
|
||||
if (unit == 'kg') {
|
||||
return '千克'
|
||||
} else if (unit == '斤') {
|
||||
return '斤'
|
||||
} else if (unit == 'stlb') {
|
||||
return 'stlb'
|
||||
} else if (unit == 'lb') {
|
||||
return '磅'
|
||||
} else if (unit == 'g') {
|
||||
return '克'
|
||||
} else if (unit == 'ml') {
|
||||
return '毫升'
|
||||
} else if (unit == 'Waterml') {
|
||||
return 'Waterml'
|
||||
} else if (unit == 'milkml') {
|
||||
return 'milkml'
|
||||
} else if (unit == 'oz') {
|
||||
return '盎司'
|
||||
} else if (unit == 'floz') {
|
||||
return 'floz'
|
||||
} else if (unit == 'lboz') {
|
||||
return 'lboz'
|
||||
}
|
||||
return unit
|
||||
},
|
||||
// 备料完成
|
||||
handleDetailSub() {
|
||||
let that = this
|
||||
if (Number(that.weight) > 0) {
|
||||
that.$emit("handleDetailSub", that.weight, that.unit, that.kcal)
|
||||
} else {
|
||||
that.$tools.msg("数据异常,请清零后重新测量!")
|
||||
}
|
||||
},
|
||||
//备料下一个
|
||||
handleDetailNext() {
|
||||
let that = this
|
||||
if (Number(that.weight) > 0) {
|
||||
that.$emit("handleDetailNext", that.weight, that.unit, that.kcal)
|
||||
} else {
|
||||
that.$tools.msg("数据异常,请清零后重新测量!")
|
||||
}
|
||||
},
|
||||
confirm(value) {
|
||||
console.log(value)
|
||||
let that = this
|
||||
this.$store.commit("changeBluetoothValue", {
|
||||
countWeight: value,
|
||||
unit: this.unitA[this.unitListIndex].unit
|
||||
})
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
close() {
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
inputDialogToggle() {
|
||||
this.$refs.popup.open()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.table {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.text {
|
||||
color: #8284f0;
|
||||
display: flex;
|
||||
|
||||
image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.weightPages {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 30rpx;
|
||||
top: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.weight {
|
||||
background: #fff;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
flex-wrap: wrap;
|
||||
text-align: center;
|
||||
|
||||
view {
|
||||
width: 60%;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
margin-left: 25%;
|
||||
align-items: flex-end;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
text {
|
||||
width: 80px;
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
margin: 0 20rpx;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #f0ae43;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.tips {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.groupbtn {
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn {
|
||||
width: 20%;
|
||||
color: $maincolor;
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid $maincolor;
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
|
||||
view {
|
||||
border: none !important;
|
||||
width: auto !important;
|
||||
height: 40px !important;
|
||||
line-height: 40px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.weight-wrap {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
height: 60px;
|
||||
border-radius: 10px;
|
||||
|
||||
.weight {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 48%;
|
||||
padding: 30rpx 0;
|
||||
border-radius: 20rpx;
|
||||
background-color: #F8F8F8;
|
||||
|
||||
.val {
|
||||
font-size: 54rpx;
|
||||
color: #F0AE43;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.unit {
|
||||
padding: 10rpx;
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
background-color: #F0AE43;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.duan {
|
||||
width: fit-content;
|
||||
background: linear-gradient(-90deg, #d4f5c4, #a7d5e4 80%, );
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
padding: 3px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,451 @@
|
|||
<template>
|
||||
<view class="weightPages">
|
||||
<view class="table">
|
||||
<view class="text">
|
||||
<image src="/static/zhong.png"></image>
|
||||
<text @click="openBluetoothAdapter">{{bleTipsText}}</text>
|
||||
</view>
|
||||
<view class="duan" @click="handleBack" v-if="isShow&&isConnection == 2">
|
||||
断开连接
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="weight-wrap">
|
||||
<!-- 蓝牙称重 -->
|
||||
<view class="weight" @click="inputDialogToggle">
|
||||
<text class="val">{{weight == '' ? '0.0':weight}}</text>
|
||||
<text class="unit">{{unitConversion(unit)}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="groupbtn">
|
||||
<view class="btn danwei">
|
||||
<view class="lan border-bottom">
|
||||
<view class="right">
|
||||
<picker mode="selector" :range="unitA" range-key="name" @change="changleUnits"
|
||||
:value="unitListIndex">
|
||||
<view class="uni-input">
|
||||
单位
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn addbtn size14" @click="handlesub" v-if="btnType==2">保存</view>
|
||||
<view class="btn addbtn" @click="handleAddFood" v-if="btnType==1">+</view>
|
||||
<view class="btn qingling" @click="handleqingling">清零</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view>
|
||||
<uni-popup ref="popup" type="dialog">
|
||||
<uni-popup-dialog mode="input" title="重量" placeholder="请输入食物重量" @close="close"
|
||||
@confirm="confirm"></uni-popup-dialog>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
let myTime
|
||||
let nextCnt = 0
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
kcal: 0,
|
||||
unit: '',
|
||||
inputDialog: false,
|
||||
unitA: [],
|
||||
unitListIndex: 0,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
weightKcal: {
|
||||
type: Number,
|
||||
default: 0 //当前测量食物每100g含的kcal
|
||||
},
|
||||
btnType: {
|
||||
type: Number,
|
||||
default: 1 //1添加食材,2保存测量
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["bleValue", "isBluetoothTyle", "countFoodInfo"]),
|
||||
weight() {
|
||||
let weightNew = this.convertToGrams(this.bleValue.countWeight, this.bleValue.unit)
|
||||
this.kcal = (Number(this.weightKcal) / 100 * weightNew).toFixed(1)
|
||||
this.unit = this.bleValue.unit
|
||||
return this.bleValue.countWeight
|
||||
},
|
||||
isConnection() {
|
||||
return this.bleValue.isConnectStatus
|
||||
},
|
||||
isShow() {
|
||||
return this.bleValue.serviceId != '' ? true : false
|
||||
},
|
||||
bleTipsText() {
|
||||
return this.bleValue.bleTipsText
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
uni.onBluetoothAdapterStateChange(function(res) {
|
||||
// that.$store.commit("changeBluetooth", res.available);
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
// this.isConnection = 1
|
||||
// this.closeBLEConnection()
|
||||
// this.closeBluetoothAdapter()
|
||||
},
|
||||
watch: {
|
||||
isBluetoothTyle: function() {
|
||||
let that = this
|
||||
if (!that.isBluetoothTyle) {
|
||||
that.handleBack()
|
||||
}
|
||||
},
|
||||
bleValue: {
|
||||
handler(newVal, oldVal) {
|
||||
this.unitA = newVal.unitList
|
||||
this.unitListIndex = newVal.unitList.findIndex(ite => ite.unit == newVal.unit)
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 初始化蓝牙
|
||||
openBluetoothAdapter() {
|
||||
let that = this
|
||||
if (that.isConnection == 2) return
|
||||
that.kcal = ""
|
||||
that.$store.commit('changeBluetoothValue', {
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
notify: '',
|
||||
write: '',
|
||||
unit: "g",
|
||||
type: 1,
|
||||
unitList: that.$json.unitMinus,
|
||||
countWeight: "",
|
||||
bleTipsText: "蓝牙搜索中",
|
||||
isConnectStatus: 0,
|
||||
})
|
||||
that.$ble.openBluetoothAdapter()
|
||||
},
|
||||
changleUnits(e) {
|
||||
let that = this
|
||||
let name = that.unitA[e.detail.value].name
|
||||
let val = that.unitA[e.detail.value].unit
|
||||
if (that.isShow && that.unit != name) {
|
||||
that.handletoggleUnit(that.unitConversion2(val))
|
||||
}
|
||||
if (that.bleValue.serviceId == '') {
|
||||
that.unitListIndex = [e.detail.value]
|
||||
that.$store.commit('changeBluetoothValue', {
|
||||
unit: that.unitA[e.detail.value].unit,
|
||||
})
|
||||
}
|
||||
},
|
||||
convertToGrams(value, fromUnit) {
|
||||
const conversionFactors = {
|
||||
'lb': 453.59237, // 1磅 = 453.59237克
|
||||
'oz': 28.349523125, // 1盎司 = 28.349523125克
|
||||
'kg': 1000, // 1公斤 = 1000克
|
||||
'g': 1,
|
||||
'ml': 1,
|
||||
'斤': 500,
|
||||
'Waterml': 1,
|
||||
'milkml': 1.03
|
||||
// "stlb": "floz": "lboz":
|
||||
};
|
||||
|
||||
if (!conversionFactors.hasOwnProperty(fromUnit)) {
|
||||
return ''
|
||||
}
|
||||
return value * conversionFactors[fromUnit];
|
||||
},
|
||||
unitConversion2(unit) {
|
||||
if (unit == 'kg') {
|
||||
return 0x00
|
||||
} else if (unit == '斤') {
|
||||
return 0x01
|
||||
} else if (unit == 'st:lb') {
|
||||
return 0x02
|
||||
} else if (unit == 'lb') {
|
||||
return 0x03
|
||||
} else if (unit == 'g') {
|
||||
return 0x04
|
||||
} else if (unit == 'ml') {
|
||||
return 0x05
|
||||
} else if (unit == 'Waterml') {
|
||||
return 0x06
|
||||
} else if (unit == 'milkml') {
|
||||
return 0x07
|
||||
} else if (unit == 'oz') {
|
||||
return 0x08
|
||||
} else if (unit == 'floz') {
|
||||
return 0x09
|
||||
} else if (unit == 'lboz') {
|
||||
return 0x0A
|
||||
}
|
||||
return unit
|
||||
},
|
||||
// 下发单位
|
||||
handletoggleUnit(unit) {
|
||||
let that = this
|
||||
let checksum = 0;
|
||||
const bytes = [0xC5, 0x03, 0x05, 0x11]
|
||||
bytes[4] = unit
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
checksum ^= bytes[i];
|
||||
}
|
||||
bytes[5] = checksum
|
||||
that.sendData(new Uint8Array(bytes).buffer)
|
||||
},
|
||||
// 清零
|
||||
handleqingling() {
|
||||
let that = this
|
||||
let str = "C503071100D0"
|
||||
let buf = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function(h) {
|
||||
return parseInt(h, 16)
|
||||
}))
|
||||
that.sendData(buf.buffer)
|
||||
},
|
||||
sendData(buffer) {
|
||||
let that = this
|
||||
uni.writeBLECharacteristicValue({
|
||||
deviceId: that.bleValue.deviceId,
|
||||
serviceId: that.bleValue.serviceId,
|
||||
characteristicId: that.bleValue.write,
|
||||
value: buffer,
|
||||
success: res => {
|
||||
console.log('下发指令成功', res.errMsg)
|
||||
},
|
||||
fail: res => {
|
||||
console.log("下发指令失败", res);
|
||||
},
|
||||
})
|
||||
},
|
||||
// 保存测量结果
|
||||
handlesub() {
|
||||
let that = this
|
||||
console.log("测量保存", that.weight, that.unit, that.kcal)
|
||||
if (Number(that.weight) > 0) {
|
||||
that.$emit("handleBle", that.weight, that.unit, that.kcal)
|
||||
} else {
|
||||
that.$tools.msg("数据异常,请清零后重新测量!")
|
||||
}
|
||||
},
|
||||
handleBack() {
|
||||
let that = this
|
||||
that.$store.commit("changeBluetoothValue", {
|
||||
bleTipsText: "连接失败,点击重新连接",
|
||||
unitList: that.$json.unitMinus,
|
||||
isConnectStatus: 1,
|
||||
})
|
||||
that.$ble.stopBluetoothDevicesDiscovery() //取消蓝牙搜索
|
||||
that.$ble.closeBLEConnection(that.bleValue.deviceId)
|
||||
that.$ble.closeBluetoothAdapter()
|
||||
},
|
||||
|
||||
unitConversion(unit) {
|
||||
if (unit == 'kg') {
|
||||
return '千克'
|
||||
} else if (unit == '斤') {
|
||||
return '斤'
|
||||
} else if (unit == 'stlb') {
|
||||
return 'stlb'
|
||||
} else if (unit == 'lb') {
|
||||
return '磅'
|
||||
} else if (unit == 'g') {
|
||||
return '克'
|
||||
} else if (unit == 'ml') {
|
||||
return '毫升'
|
||||
} else if (unit == 'Waterml') {
|
||||
return 'Waterml'
|
||||
} else if (unit == 'milkml') {
|
||||
return 'milkml'
|
||||
} else if (unit == 'oz') {
|
||||
return '盎司'
|
||||
} else if (unit == 'floz') {
|
||||
return 'floz'
|
||||
} else if (unit == 'lboz') {
|
||||
return 'lboz'
|
||||
}
|
||||
return unit
|
||||
},
|
||||
// 添加食物
|
||||
handleAddFood() {
|
||||
uni.navigateTo({
|
||||
url: "/Food/count/search?name=早餐&time=" + this.countFoodInfo.date
|
||||
})
|
||||
},
|
||||
inputDialogToggle() {
|
||||
this.$refs.popup.open()
|
||||
},
|
||||
// 手动输入
|
||||
confirm(value) {
|
||||
console.log(value)
|
||||
let that = this
|
||||
this.$store.commit("changeBluetoothValue", {
|
||||
countWeight: value,
|
||||
unit: this.unitA[this.unitListIndex].unit
|
||||
})
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
close() {
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.more {
|
||||
padding: 6rpx 10rpx;
|
||||
border-radius: 12rpx;
|
||||
color: #fff;
|
||||
background-color: #f0ae43;
|
||||
}
|
||||
|
||||
.weightPages {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
margin: 10px;
|
||||
justify-content: space-around;
|
||||
|
||||
.weight-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
height: 60px;
|
||||
margin: 10px 0;
|
||||
|
||||
.weight,
|
||||
.kcal {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 70%;
|
||||
padding: 30rpx 0;
|
||||
border-radius: 20rpx;
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
|
||||
.weight {
|
||||
.val {
|
||||
font-size: 54rpx;
|
||||
color: #F0AE43;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.unit {
|
||||
padding: 10rpx;
|
||||
margin-left: 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
background-color: #F0AE43;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.groupbtn {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn {
|
||||
width: 30%;
|
||||
color: $maincolor;
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid $maincolor;
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.addbtn {
|
||||
width: 30%;
|
||||
color: #fff;
|
||||
font-size: 45px;
|
||||
line-height: 38px;
|
||||
background: $maincolor;
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.text {
|
||||
color: #8284f0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 1120rpx;
|
||||
height: 1120rpx;
|
||||
margin: auto;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.duan {
|
||||
width: fit-content;
|
||||
background: linear-gradient(-90deg, #d4f5c4, #a7d5e4 80%, );
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
padding: 3px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 30rpx;
|
||||
margin-left: 30rpx;
|
||||
display: flex;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,470 @@
|
|||
<template>
|
||||
<view class="content-box">
|
||||
<!-- 日期选择 -->
|
||||
<view class="data">
|
||||
<picker mode="date" :end="endDate" @change="changeClickDate" :value="data?data:endDate">
|
||||
<view>
|
||||
{{data?data:"请选择"}}
|
||||
<image src="/static/qie.png"></image>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 称重 -->
|
||||
<view class="blue-tooth" v-if="user.aud_id!=''">
|
||||
<blue-tooth :btnType="'1'"></blue-tooth>
|
||||
</view>
|
||||
<!-- 能量摄入 -->
|
||||
<view class="everyDay">
|
||||
<view class="title">
|
||||
<view><text class="quan"></text>热量摄入</view>
|
||||
<view class="icon" @click="handleSet">
|
||||
<uni-icons type="gear" size="26"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="jishiqi">
|
||||
<view class="left">
|
||||
<view class="chart-wrap">
|
||||
<qiun-data-charts type="arcbar" :chartData="chartData" :cHeight="280" :cWidth="280"
|
||||
:canvas2d="true" canvasId="countCharts" v-if="handTrue" />
|
||||
<view class="center">
|
||||
摄入
|
||||
<text>{{foodInfo.nutrients_four[0].today_intake}}</text>
|
||||
<view class="unit">Kcal</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mubiao">
|
||||
目标:<text>{{foodInfo.nutrients_four[0].suggestion}}</text>kcal
|
||||
</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="item" v-for="(ite,ind) in foodInfo.nutrients_four.slice(1)">
|
||||
<view class="left-icon">
|
||||
<image :src="ite.icon"></image>
|
||||
<view class="val" :style="{color:ite.color}">{{ite.proportion_fp||0}}%</view>
|
||||
</view>
|
||||
<view class="right-info">
|
||||
<view class="right-info-top">
|
||||
<text class="name">{{ite.name}}</text>
|
||||
<text class="">
|
||||
{{ite.today_intake||0}}/{{ite.suggestion||0}}g
|
||||
</text>
|
||||
</view>
|
||||
<view class="right-info-bottom">
|
||||
<view class="val" :style="{ width: ite.proportion + '%',background:ite.color}">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 早午晚餐 -->
|
||||
<view class="foodtools">
|
||||
<view class="type" v-for="(item,index) in foodInfo.list">
|
||||
<view class="title" @click="handledetail(index)">
|
||||
<view class="text">
|
||||
<image :src="item.icon"></image>
|
||||
<view>{{item.name}}</view>
|
||||
<text>{{item.val}}{{item.unit}}</text>
|
||||
</view>
|
||||
<view class="detail">
|
||||
餐食详情
|
||||
<uni-icons type="forward" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<uni-swipe-action>
|
||||
<uni-swipe-action-item v-for="(ite,ind) in item.list" :key="ind" :right-options="actionOptions"
|
||||
@click="delAcitionItem(ite)">
|
||||
<view class="item" @click="showFoodDetail(ite)">
|
||||
<image :src="ite.pic_url" mode="aspectFill"></image>
|
||||
<view class="weight">
|
||||
<view>{{ite.name}}</view>
|
||||
<view class="size12 c999">{{ite.weight}}<text>|</text>{{ite.val}}kcal</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
<view class="add" @click="handleAddFood(item.name)">
|
||||
<text>+</text>添加食物
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fenxi" @click="navTo('/Food/count/everyDay?page=count')">
|
||||
<image src="/static/fenxi.png"></image>
|
||||
营养分析
|
||||
</view>
|
||||
|
||||
<!-- 搜索 -->
|
||||
<view class="serachBox">
|
||||
<view class="title">
|
||||
<view class="quan mr-5"></view>教你做
|
||||
</view>
|
||||
<view class="searchInput">
|
||||
<div class="search-wrap" @click="navTo('/Food/search/search')">
|
||||
<text>输入食材快速搜索菜谱</text>
|
||||
<image src="/static/28.png"></image>
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 营养含量分析 -->
|
||||
<view v-if="drawerVisible" class="drawerVisible">
|
||||
<view class="bgVisible" @click="handleDrawerClose"></view>
|
||||
<view class="infoVisible">
|
||||
<scroll-view style="height: 100%;" scroll-y="true">
|
||||
<view class="foodDetail">
|
||||
<view class="foodInfo">
|
||||
<image :src="activeFoodDetail.pic_url" mode="aspectFill"></image>
|
||||
<view class="info">
|
||||
<view class="name">{{activeFoodDetail.name}}</view>
|
||||
<view class="kcal">{{activeFoodDetail.val}}千卡</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="foodContent">
|
||||
<view class="title">热量和营养</view>
|
||||
<view class="progress">
|
||||
<div class="chart-wrap">
|
||||
<qiun-data-charts v-if="chartVisible" type="ring" :opts="opts"
|
||||
:chartData="chartData2" :cHeight="280" :cWidth="280" />
|
||||
</div>
|
||||
<view class="info" v-if="activeFoodDetail.nutrients_four">
|
||||
<view class="info-item"
|
||||
v-for="(item,index) in activeFoodDetail.nutrients_four.slice(1)" :key="index">
|
||||
<view class="color" :style="{'background-color':`${item.color}`}">
|
||||
</view>
|
||||
<view>{{item.name}}:{{item.proportion}}%</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<text>营养素</text>
|
||||
<text>{{activeFoodDetail.weight}}含量</text>
|
||||
</view>
|
||||
<view class="foodDetailList">
|
||||
<view class="foodDetailItem" v-for="(item,index) in activeFoodDetail.nutrients_list"
|
||||
:key="index">
|
||||
<view class="name">{{item.name_ch}}</view>
|
||||
<view class="value">{{item.value}}{{item.unit}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import blueTooth from "@/components/foodIndex/bluetooth_food.vue"
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts.vue';
|
||||
export default {
|
||||
name: "food",
|
||||
data() {
|
||||
return {
|
||||
token: "",
|
||||
index: 0,
|
||||
opts: {
|
||||
background: "transparent",
|
||||
title: {
|
||||
name: "",
|
||||
},
|
||||
},
|
||||
chartData: {
|
||||
series: [{
|
||||
data: 0,
|
||||
color: "#3CB383"
|
||||
}]
|
||||
},
|
||||
data: '',
|
||||
isBle: true,
|
||||
handTrue: false,
|
||||
chartData2: {},
|
||||
activeFoodDetail: {},
|
||||
drawerVisible: false,
|
||||
chartVisible: false, // 单独控制图表显示
|
||||
actionOptions: [{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#dd524d',
|
||||
borderRadius: '10rpx'
|
||||
}
|
||||
}]
|
||||
};
|
||||
},
|
||||
components: {
|
||||
blueTooth,
|
||||
qiunDataCharts
|
||||
},
|
||||
computed: {
|
||||
...mapState(["configInfo", "user", "countFoodInfo", "bleValue"]),
|
||||
info() {
|
||||
return this.user
|
||||
},
|
||||
kcalVal() {
|
||||
return this.configInfo.kcal_data
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
foodInfo() {
|
||||
let that = this
|
||||
this.handTrue = false
|
||||
that.$nextTick(() => {
|
||||
that.handTrue = true
|
||||
that.chartData.series[0].data = that.user.aud_id ? Number(that.countFoodInfo.nutrients_four[0]
|
||||
.proportion) / 100 : 0
|
||||
})
|
||||
that.data = that.user.aud_id ? that.countFoodInfo.date : that.$tools.getDate("start")
|
||||
return that.user.aud_id ? that.countFoodInfo : that.configInfo.default_count_foot
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 详情
|
||||
showFoodDetail(item) {
|
||||
console.log("item", item)
|
||||
let that = this
|
||||
let chart_data = []
|
||||
that.drawerVisible = true;
|
||||
that.opts.color = []
|
||||
that.activeFoodDetail = item
|
||||
for (let i = 1; i < item.nutrients_four.length; ++i) {
|
||||
that.opts.color.push(item.nutrients_four[i].color)
|
||||
chart_data.push({
|
||||
name: item.nutrients_four[i].name,
|
||||
value: Number(item.nutrients_four[i].proportion),
|
||||
})
|
||||
}
|
||||
that.opts.title.name = that.activeFoodDetail.val
|
||||
that.chartData2 = JSON.parse(JSON.stringify({
|
||||
series: [{
|
||||
data: chart_data
|
||||
}]
|
||||
}));
|
||||
that.$nextTick(() => {
|
||||
// 延迟显示图表,确保容器已渲染
|
||||
setTimeout(() => {
|
||||
that.chartVisible = true
|
||||
}, 100)
|
||||
})
|
||||
},
|
||||
// 餐食详情
|
||||
handledetail(index) {
|
||||
uni.navigateTo({
|
||||
url: "/Food/count/everyMeal?index=" + index
|
||||
})
|
||||
},
|
||||
// 设置
|
||||
handleSet() {
|
||||
uni.navigateTo({
|
||||
url: "/Food/count/setting"
|
||||
})
|
||||
},
|
||||
changeClickDate(e) {
|
||||
this.data = e.detail.value
|
||||
this.$store.dispatch("getCountFoodInfo", {
|
||||
aud_id: this.info.aud_id,
|
||||
time: e.detail.value
|
||||
})
|
||||
},
|
||||
// 添加食物
|
||||
handleAddFood(name) {
|
||||
this.isShow = false
|
||||
uni.navigateTo({
|
||||
url: "/Food/count/search?name=" + name + "&time=" + this.date
|
||||
})
|
||||
},
|
||||
// 功能页面跳转
|
||||
navTo(url) {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
},
|
||||
handleDrawerClose() {
|
||||
// 先隐藏图表,再隐藏抽屉
|
||||
this.chartVisible = false
|
||||
this.drawerVisible = false;
|
||||
},
|
||||
// 删除食材
|
||||
delAcitionItem(item) {
|
||||
let that = this
|
||||
uni.showModal({
|
||||
content: `是否删除[${item.name}]?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.$model.delCEatAction({
|
||||
aud_id: that.info.aud_id,
|
||||
eat_log_id: item.id
|
||||
}).then(res => {
|
||||
// 删除最新一天食物
|
||||
if (that.foodInfo.date == that.info.food_count.date) {
|
||||
that.$store.dispatch("getUserInfoFood")
|
||||
} else {
|
||||
that.$store.dispatch("getCountFoodInfo", {
|
||||
aud_id: that.info.aud_id,
|
||||
time: that.foodInfo.date
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content-box {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.serachBox {
|
||||
position: initial;
|
||||
margin-bottom: 10px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
.searchInput {
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
width: calc(100% - 20px);
|
||||
position: initial;
|
||||
margin: 10px 0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.data {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
height: 90rpx;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
margin: 10px;
|
||||
width: calc(100% - 20px);
|
||||
border-radius: 10px;
|
||||
margin-top: 0;
|
||||
|
||||
picker {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
|
||||
view {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
bottom: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.blue-tooth {
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
margin: 0 10px;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
}
|
||||
|
||||
.foodtools {
|
||||
margin-top: 30rpx;
|
||||
|
||||
.type {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
image {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
view {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail {
|
||||
color: #999;
|
||||
display: flex;
|
||||
font-size: 24rpx;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
margin-top: 30rpx;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
|
||||
image {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #f7f7f7;
|
||||
}
|
||||
|
||||
.weight {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-left: 20rpx;
|
||||
|
||||
text {
|
||||
margin: 0 20rpx;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
width: 100%;
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
<template>
|
||||
<!-- 搜索 -->
|
||||
<view class="serachBox">
|
||||
<view class="serach-box">
|
||||
<view class="searchInput">
|
||||
<input placeholder="请输入..." class="city-serach-input" v-model="name" />
|
||||
<icon v-if="name" class="iconfont icon-error" @click="handlecolse"></icon>
|
||||
<view class="voice" v-if="voice && !name">
|
||||
<uni-icons class="mic" type="mic-filled" size="26" @click="onMic"></uni-icons>
|
||||
<uni-icons class="camera" type="camera-filled" size="26" @click="onCamera"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="searchBtn">
|
||||
<view @click="handleSerach">搜索</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "search",
|
||||
props: {
|
||||
voice: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
name: ""
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 搜索
|
||||
handleSerach() {
|
||||
this.$emit("handleSearch", this.name)
|
||||
},
|
||||
//取消搜索
|
||||
handlecolse() {
|
||||
this.name = ""
|
||||
this.$emit("handleSearch", "")
|
||||
},
|
||||
onMic() {
|
||||
this.$emit("mic")
|
||||
},
|
||||
onCamera() {
|
||||
this.$emit("camera")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.serachBox {
|
||||
height: 80rpx;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 30rpx 20rpx;
|
||||
z-index: 99;
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.serach-box {
|
||||
height: 80rpx;
|
||||
border-radius: 20rpx;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.searchInput {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 120rpx;
|
||||
height: 80rpx;
|
||||
|
||||
icon {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
top: 20rpx;
|
||||
display: flex;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.voice {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 150rpx;
|
||||
display: flex;
|
||||
z-index: 99999;
|
||||
|
||||
.mic {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.searchBtn {
|
||||
position: absolute;
|
||||
width: 120rpx;
|
||||
right: 0px;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: $maincolor;
|
||||
border-radius: 0 20rpx 20rpx 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 80rpx;
|
||||
padding: 0 5px;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
border-radius: 20rpx;
|
||||
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 100rpx;
|
||||
height: 80rpx;
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<!-- 搜索 -->
|
||||
<view class="search" @click="handleSearch">
|
||||
<input type="text" :placeholder="name" />
|
||||
<icon v-if="name" class="iconfont icon-error" @click="handleSearch"></icon>
|
||||
<image src="/static/28.png"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "search",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 搜索
|
||||
handleSearch() {
|
||||
uni.redirectTo({
|
||||
url: '/Food/search/search'
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding-bottom: 35px;
|
||||
padding-top: 20rpx;
|
||||
background-color: $maincolor;
|
||||
|
||||
|
||||
input {
|
||||
width: calc(100% - 80rpx);
|
||||
background: #fff;
|
||||
height: 39px;
|
||||
line-height: 38px;
|
||||
border-radius: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.input:hover {
|
||||
box-shadow: 0 1rpx 20rpx #ccc;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
position: absolute;
|
||||
right: 40rpx;
|
||||
top: 16px;
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-error {
|
||||
color: #888484;
|
||||
position: absolute;
|
||||
right: 120rpx;
|
||||
top: 15px;
|
||||
font-size: 24px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"addfoodList": [{
|
||||
"name": "早加餐",
|
||||
"id": 3
|
||||
},
|
||||
{
|
||||
"name": "午加餐",
|
||||
"id": 4
|
||||
}, {
|
||||
"name": "晚加餐",
|
||||
"id": 5
|
||||
}
|
||||
],
|
||||
"unitArray": [{
|
||||
"name": "千克",
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"name": "斤",
|
||||
"unit": "斤"
|
||||
},
|
||||
{
|
||||
"name": "stlb",
|
||||
"unit": "stlb"
|
||||
},
|
||||
{
|
||||
"name": "磅",
|
||||
"unit": "lb"
|
||||
}, {
|
||||
"name": "克",
|
||||
"unit": "g"
|
||||
}, {
|
||||
"name": "毫升",
|
||||
"unit": "ml"
|
||||
},
|
||||
{
|
||||
"name": "Waterml",
|
||||
"unit": "Waterml"
|
||||
},
|
||||
{
|
||||
"name": "milkml",
|
||||
"unit": "milkml"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "盎司",
|
||||
"unit": "oz"
|
||||
},
|
||||
{
|
||||
"name": "floz",
|
||||
"unit": "floz"
|
||||
},
|
||||
{
|
||||
"name": "lboz",
|
||||
"unit": "lboz"
|
||||
}
|
||||
],
|
||||
"unitMinus": [{
|
||||
"name": "千克",
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"name": "磅",
|
||||
"unit": "lb"
|
||||
}, {
|
||||
"name": "克",
|
||||
"unit": "g"
|
||||
}, {
|
||||
"name": "毫升",
|
||||
"unit": "ml"
|
||||
},
|
||||
{
|
||||
"name": "盎司",
|
||||
"unit": "oz"
|
||||
}
|
||||
|
||||
],
|
||||
"units": ["kg", "斤", "stlb", "lb", "g", "ml", "Waterml", "milkml", "oz", "floz", "lboz"]
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
<template>
|
||||
<view id="select-ruler" class="select-ruler">
|
||||
<!-- 遮罩层 -->
|
||||
<view class="tap-mask" v-if="disable"></view>
|
||||
<!-- 线 -->
|
||||
<view class="line"></view>
|
||||
<view class="row-line"></view>
|
||||
<!-- 左右渐变遮罩 -->
|
||||
<view class="mask mask-left"></view>
|
||||
<view class="mask mask-right"></view>
|
||||
<!-- 刻度尺 -->
|
||||
<scroll-view :scroll-x="true" enhanced :show-scrollbar="false" @scroll="handleScroll" @scrolltolower="scrolltolower" @scrolltoupper="scrolltoupper" :scroll-left="scroll_left">
|
||||
<span :style="{'margin-left': index == 0 ? `${el_width+10}px`:'','margin-right':index==max?`${el_width-20}px`:''}"
|
||||
class="ruler-item span-item" v-for="(item, index) in (max - min + 1)">
|
||||
<span>{{((index + min)/multiple).toFixed(point)}}</span>
|
||||
</span>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "select-ruler",
|
||||
data() {
|
||||
return {
|
||||
number: 0,
|
||||
scroll_left: 1,
|
||||
last_scroll_left: 0,
|
||||
el_width: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
scroll: {
|
||||
detail: {},
|
||||
},
|
||||
};
|
||||
},
|
||||
props: {
|
||||
// 最小值
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 最大值
|
||||
max: {
|
||||
type: Number,
|
||||
default: 500
|
||||
},
|
||||
// 缩放比例
|
||||
multiple: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
// 默认值
|
||||
defaultValue: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 是否禁用
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 小数点后保留位数
|
||||
point: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 等待滚动条初始化完成
|
||||
this.setDefault(this.defaultValue);
|
||||
},
|
||||
methods: {
|
||||
// 刻度尺滚动监听
|
||||
handleScroll(e) {
|
||||
this.scroll = e;
|
||||
console.log(e.detail.scrollLeft)
|
||||
this.number = Math.round(e.detail.scrollLeft / 10)
|
||||
if (this.number > this.max) {
|
||||
this.number = this.max
|
||||
} else {
|
||||
}
|
||||
this.$emit('change', ((this.number + this.min) / this.multiple).toFixed(this.point));
|
||||
},
|
||||
scrolltoupper() {
|
||||
this.number = 0
|
||||
this.$emit('change', this.number);
|
||||
},
|
||||
scrolltolower() {
|
||||
this.number = this.max
|
||||
this.$emit('change', this.number);
|
||||
},
|
||||
// 初始化刻度尺
|
||||
initScroll() {
|
||||
this.scroll_left = this.number * 10
|
||||
this.last_scroll_left = this.scroll_left
|
||||
},
|
||||
// 设置默认值
|
||||
setDefault(number) {
|
||||
const query = wx.createSelectorQuery().in(this)
|
||||
query.select('#select-ruler').boundingClientRect(rect => {
|
||||
if (rect) {
|
||||
this.el_width = rect.width / 2
|
||||
if (number < this.min || number > this.max) {
|
||||
uni.showToast({
|
||||
title: `数值超出范围(${this.min/this.multiple}-${this.max/this.multiple})`,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
if (number < this.min) number = this.min;
|
||||
if (number > this.max) number = this.max;
|
||||
this.number = number - this.min;
|
||||
this.initScroll();
|
||||
}
|
||||
}).exec()
|
||||
|
||||
},
|
||||
// 增加
|
||||
plusValue(step) {
|
||||
this.setDefault(this.number + this.min + Math.floor(step));
|
||||
},
|
||||
// 减少
|
||||
reduceValue(step) {
|
||||
this.setDefault(this.number + this.min - Math.floor(step));
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.select-ruler {
|
||||
width: 100%;
|
||||
height: 150rpx;
|
||||
margin-top: 20rpx;
|
||||
position: relative;
|
||||
|
||||
.tap-mask {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
left: 366rpx;
|
||||
top: 40rpx;
|
||||
text-align: center;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
width: 6rpx;
|
||||
height: 80rpx;
|
||||
background: #00BC00;
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
|
||||
.row-line {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: rgba(#3A414B, .07);
|
||||
top: 40rpx;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mask {
|
||||
width: 150rpx;
|
||||
height: 120rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
|
||||
&.mask-left {
|
||||
left: 0;
|
||||
background-image: linear-gradient(to right, #fff, rgba(#fff, 0));
|
||||
}
|
||||
|
||||
&.mask-right {
|
||||
right: 0;
|
||||
background-image: linear-gradient(to right, rgba(#fff, 0), #fff);
|
||||
}
|
||||
}
|
||||
|
||||
scroll-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
.slot {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ruler-item {
|
||||
width: 10px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding-top: 40rpx;
|
||||
|
||||
// &:first-child {
|
||||
// margin-left: 370rpx;
|
||||
// }
|
||||
// &:last-child {
|
||||
// margin-right: 370rpx;
|
||||
// }
|
||||
&:before {
|
||||
content: '';
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
background: rgba(#3A414B, .15);
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
top: -10rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: #3D3D3D;
|
||||
font-size: 18px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:nth-child(10n+1) {
|
||||
&::before {
|
||||
width: 1px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="editem">
|
||||
<view class="name">身高</view>
|
||||
<view class="right">
|
||||
<input type="digit" v-model="PostData.height" placeholder="请输入身高"
|
||||
placeholder-style="font-size:13px;color:#666" />cm
|
||||
</view>
|
||||
</view>
|
||||
<view class="editem">
|
||||
<view class="name">体重</view>
|
||||
<view class="right">
|
||||
<input type="digit" v-model="PostData.weight" placeholder="请输入体重"
|
||||
placeholder-style="font-size:13px;color:#666" />kg
|
||||
</view>
|
||||
</view>
|
||||
<view class="editem">
|
||||
<view class="name">性别</view>
|
||||
<view class="right radio2">
|
||||
<view class="radio" @click="PostData.sex = 1">
|
||||
<uni-icons :type="PostData.sex==1?'checkbox-filled':'circle'" size="24"
|
||||
:color="PostData.sex==1?'#fea606':'#dfdfdf'"></uni-icons>男
|
||||
</view>
|
||||
<view class="radio ml-15" @click="PostData.sex = 2">
|
||||
<uni-icons :type="PostData.sex==2?'checkbox-filled':'circle'" size="24"
|
||||
:color="PostData.sex==2?'#fea606':'#dfdfdf'"></uni-icons>女
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="editem">
|
||||
<view class="name">出生日期</view>
|
||||
<view class="right">
|
||||
<picker mode="date" :value="PostData.birthday" :end="endDate" @change="bindDateChange" :fields="fields">
|
||||
<view class="text">{{PostData.birthday?PostData.birthday:"请选择出生日期"}}</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box_con mb-15" v-if="iscalced">
|
||||
<view class="BMIlist">
|
||||
<view class="block">
|
||||
<view class="name">
|
||||
BMI
|
||||
</view>
|
||||
<view class="val">
|
||||
{{resdata.bmi?resdata.bmi:'0'}}
|
||||
</view>
|
||||
<view class="btnf" :style="{backgroundColor:resdata.bmilevelcolor}">
|
||||
{{resdata.bmilevel}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="desc">
|
||||
<view class="statuevue">
|
||||
<view class="bi">
|
||||
<view :style="'left:'+resdata.offset+'%'" class="peobox">
|
||||
<view class="xx"></view>
|
||||
</view>
|
||||
<view class="item" v-for="(ite,ind) in resdata.bmilevellist" :key="ind"
|
||||
:style="{backgroundColor:ite.color}">
|
||||
<view class="span1">{{ite.text}}</view>
|
||||
<view class="span" v-if="ind<resdata.bmilevellist.length-1">{{ite.max_val}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tip">
|
||||
BMI是身体质量指数,是目前国际上常用的衡量人体胖瘦程度以及是否健康的一个标准.
|
||||
<view class="text" v-for="(ite,ind) in configInfo.literature.bmi_evaluation"
|
||||
v-if="configInfo.literature.bmi_evaluation.length">
|
||||
{{ite}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn mt-20" @click="submit"> 立即计算</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
//提交的数据
|
||||
PostData: {
|
||||
weight: '',
|
||||
height: '',
|
||||
sex: 0,
|
||||
birthday: null
|
||||
},
|
||||
resdata: {
|
||||
bmi: 0,
|
||||
bmilevel: '',
|
||||
bmilevelcolor: '',
|
||||
bmilevellist: [],
|
||||
offset: ""
|
||||
},
|
||||
leftval: 0,
|
||||
iscalced: false,
|
||||
fields: "",
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["configInfo"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
//年龄选择
|
||||
bindDateChange(e) {
|
||||
this.PostData.birthday = e.target.value
|
||||
},
|
||||
//bmi计算
|
||||
submit() {
|
||||
var that = this;
|
||||
if (!that.PostData.weight) {
|
||||
this.$tools.msg("请输入体重")
|
||||
return;
|
||||
}
|
||||
if (!that.PostData.height) {
|
||||
this.$tools.msg("请输入身高")
|
||||
return;
|
||||
}
|
||||
if (!that.PostData.sex) {
|
||||
this.$tools.msg("请选择性别")
|
||||
return;
|
||||
}
|
||||
if (!that.PostData.birthday) {
|
||||
this.$tools.msg("请选择年龄")
|
||||
return;
|
||||
}
|
||||
that.$model.calcbmi(that.PostData).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.resdata = res.data;
|
||||
this.iscalced = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 15px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
line-height: 22px
|
||||
}
|
||||
|
||||
.editem {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 15px;
|
||||
justify-content: space-between;
|
||||
background: #eee;
|
||||
padding-left: 15px;
|
||||
|
||||
.name {
|
||||
width: 30%;
|
||||
float: left;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 58%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 15px;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
|
||||
.radio2 {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.radio {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.text,
|
||||
/deep/input {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 0;
|
||||
left: 40%;
|
||||
z-index: 9999;
|
||||
color: #666;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/deep/input {
|
||||
padding-left: 0px;
|
||||
margin-top: 0px;
|
||||
font-size: 30rpx !important;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
background-color: $maincolor;
|
||||
}
|
||||
|
||||
.box_con {
|
||||
margin: 15px 0;
|
||||
padding: 10px 15px 15px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0px 0px 5px 0px #c3c3c3;
|
||||
font-size: 26rpx;
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
.desc {
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
width: calc(100%-20px);
|
||||
height: auto;
|
||||
border-radius: 5px;
|
||||
font-size: 30rpx;
|
||||
color: #999;
|
||||
padding: 10px;
|
||||
background: #f7f7f7;
|
||||
|
||||
|
||||
.statuevue {
|
||||
height: 35px;
|
||||
position: relative;
|
||||
width: 100% !important;
|
||||
margin: 20px auto 10px;
|
||||
|
||||
.bi {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: auto;
|
||||
padding-top: 10px;
|
||||
|
||||
.peobox {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: -1px;
|
||||
z-index: 999;
|
||||
|
||||
.xx {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
border: 2px solid #1b2086;
|
||||
top: 9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
height: 5px;
|
||||
color: #666;
|
||||
font-size: 30rpx;
|
||||
|
||||
.span1 {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: -23px;
|
||||
}
|
||||
|
||||
.span {
|
||||
margin-top: 8px;
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.block {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btnf {
|
||||
background-color: #ff5656;
|
||||
padding: 3px 8px;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.yuanxing {
|
||||
display: inline-block;
|
||||
background: #f19601;
|
||||
width: 8px;
|
||||
height: 12px;
|
||||
margin-right: 5px;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="tagList">
|
||||
<scroll-view class="scroll-view_H" scroll-x="true">
|
||||
<text class="scroll-view-item_H" v-for="(ite,ind) in publicRecordInfo"
|
||||
@click="handlePageScrollTo(ite.id,ind)" :class="[ind == index?'active':'']">
|
||||
{{ite.name}}
|
||||
</text>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="TrendPage">
|
||||
<view class="listC">
|
||||
<view @click="handleActive(1)" :class="[active==1?'active':'']">当天</view>
|
||||
<view @click="handleActive(2)" :class="[active==2?'active':'']">月度</view>
|
||||
<view @click="handleActive(3)" :class="[active==3?'active':'']">年度</view>
|
||||
</view>
|
||||
<view class="box">
|
||||
<!-- 时间选择 -->
|
||||
<view class="boxTime">
|
||||
<picker mode="date" class="f-l" :value="startDate" @change="handStartTimeH"
|
||||
:fields="active==1?'day':active==2?'month':'year'">
|
||||
<view class="uni-input">{{time}}<uni-icons type="bottom"></uni-icons></view>
|
||||
</picker>
|
||||
</view>
|
||||
<!-- 曲线图 -->
|
||||
<view class="boxLine">
|
||||
<view class="line" v-for="(item,index) in weightList">
|
||||
<view v-if="item.line.categories.length">
|
||||
<qiunDataCharts type="column" :chartData="item.line" :canvas2d="true" :canvasId="item.id"
|
||||
:Width="340" :Height="250" :animation="false"
|
||||
:opts="{enableScroll:true,xAxis:{scrollShow:false,itemCount:3}}" :ontouch="true" />
|
||||
</view>
|
||||
<view class="line" v-else>
|
||||
<view class="nolist mb-15">
|
||||
<image src="../../static/none.png"></image>
|
||||
<text>暂无数据,请手动添加~</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
weightList: [],
|
||||
handTrue: true,
|
||||
active: 1,
|
||||
index: 0,
|
||||
time: "",
|
||||
}
|
||||
},
|
||||
components: {
|
||||
qiunDataCharts,
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "PublicRecord"]),
|
||||
userInfo() {
|
||||
return this.user
|
||||
},
|
||||
publicRecordInfo() {
|
||||
let that = this
|
||||
return that.PublicRecord
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.getDate("start")
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
that.active = 1
|
||||
that.index = 0
|
||||
that.time = that.startDate
|
||||
that.getList()
|
||||
},
|
||||
methods: {
|
||||
handlePageScrollTo(id, ind) {
|
||||
let that = this
|
||||
that.index = ind
|
||||
that.active = 1
|
||||
that.time = that.startDate
|
||||
that.getList()
|
||||
},
|
||||
getList() {
|
||||
let list = []
|
||||
let that = this
|
||||
that.$model.getPublicTrendList({
|
||||
aud_id: that.user.aud_id,
|
||||
time: that.time,
|
||||
type: that.publicRecordInfo[that.index].key_word,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
that.weightList = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
handleActive(ite) {
|
||||
let that = this
|
||||
that.handTrue = false
|
||||
that.time = ite == 1 ? this.startDate : ite == 2 ? this.$tools.getDate("month") : this.$tools.getDate(
|
||||
"year")
|
||||
that.getList()
|
||||
that.$nextTick(function() {
|
||||
that.handTrue = true
|
||||
})
|
||||
that.active = ite
|
||||
},
|
||||
handStartTimeH(e) {
|
||||
let that = this
|
||||
that.time = e.target.value
|
||||
that.getList()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tagList {
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
|
||||
.active {
|
||||
color: $maincolor;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.scroll-view_H {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
|
||||
.scroll-view-item_H {
|
||||
display: inline-block;
|
||||
height: 45rpx;
|
||||
line-height: 45rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
text {
|
||||
color: #666;
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
.TrendPage{
|
||||
margin-top: 50px;
|
||||
width: calc(1005 - 30px);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<view class="weightPages">
|
||||
<view class="content ">
|
||||
<view class="status">{{UseBlueConfig.BleConnectMsg}}</view>
|
||||
<view class="status">{{bleTipsText}}</view>
|
||||
<view class="text">{{text}}</view>
|
||||
<view class="image">
|
||||
<image src="/pageTwo/static/HC.png" class="image3"></image>
|
||||
|
|
@ -54,35 +54,39 @@
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "UseBlueConfig"]),
|
||||
...mapState(["user", "bleValue"]),
|
||||
userInfo() {
|
||||
return this.user
|
||||
}
|
||||
},
|
||||
onUnload: function() {
|
||||
let that = this
|
||||
that.useBluetooth.clearBluetoothStatus()
|
||||
console.log("页面返回onUnload")
|
||||
bleTipsText() {
|
||||
return this.bleValue.bleTipsText
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.weight = that.userInfo.weight
|
||||
that.deviceId = options.deviceId
|
||||
that.useBluetooth.createBLEConnection("FFF0")
|
||||
that.useBluetooth.onBLEConnectionStateChange()
|
||||
that.useBluetooth.onBluetoothAdapterStateChange()
|
||||
that.$ble.createBLEConnection("FFF0")
|
||||
that.$ble.onBLEConnectionStateChange()
|
||||
that.$ble.onBluetoothAdapterStateChange()
|
||||
},
|
||||
watch: {
|
||||
'UseBlueConfig.isUseConnect'() {
|
||||
'bleValue.isBluetoothTyle'() {
|
||||
let that = this
|
||||
if (!that.UseBlueConfig.isUseConnect) {
|
||||
if (!that.bleValue.isBluetoothTyle) {
|
||||
that.$tools.showModal('蓝牙连接已断开,请重新连接后测量')
|
||||
setTimeout(function() {
|
||||
uni.switchTab({
|
||||
url: "/pages/index/index"
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
'UseBlueConfig.serviceId'() {
|
||||
'bleValue.serviceId'() {
|
||||
let that = this
|
||||
if (that.UseBlueConfig.serviceId) {
|
||||
that.getBLEDeviceCharacteristics(that.UseBlueConfig.serviceId)
|
||||
if (that.bleValue.serviceId) {
|
||||
console.log("serviceId", that.bleValue.serviceId)
|
||||
that.getBLEDeviceCharacteristics(that.bleValue.serviceId)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -105,9 +109,11 @@
|
|||
that.write = item.uuid
|
||||
}
|
||||
}
|
||||
that.$store.commit("getIsUseBluetooth", {
|
||||
BleConnectMsg: "蓝牙连接成功,请开始测量",
|
||||
});
|
||||
that.$store.commit("changeBluetoothValue", {
|
||||
type: 1,
|
||||
isConnectStatus: 2,
|
||||
bleTipsText: "蓝牙连接成功,请上秤测量",
|
||||
})
|
||||
uni.notifyBLECharacteristicValueChange({
|
||||
deviceId: that.deviceId,
|
||||
serviceId: serviceId,
|
||||
|
|
@ -196,21 +202,25 @@
|
|||
adc: 0,
|
||||
weight: that.weight,
|
||||
height: height,
|
||||
aud_id: that.userInfo.id
|
||||
aud_id: that.user.aud_id,
|
||||
lefthand: 0,
|
||||
righthand: 0,
|
||||
leftfoot: 0,
|
||||
rightfoot: 0,
|
||||
heart_rate: 0,
|
||||
}).then(res => {
|
||||
that.isHeight = false
|
||||
console.log("报告", res)
|
||||
|
||||
if (res.code == 0) {
|
||||
// that.$store.dispatch('getUserInfo', {
|
||||
// aud_id: uni.getStorageSync('userid')
|
||||
// })
|
||||
that.$store.dispatch('getUserInfo', {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
that.$tools.msg("测量成功")
|
||||
} else {
|
||||
that.$tools.msg("测量失败")
|
||||
}
|
||||
uni.switchTab({
|
||||
url: "/pages/body/body"
|
||||
url: "/pages/index/index"
|
||||
})
|
||||
})
|
||||
},
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@
|
|||
that.handleAudioStart()
|
||||
that.$Bluetooth.onBLEConnectionStateChange()
|
||||
uni.onBluetoothAdapterStateChange(function(res) {
|
||||
that.$store.commit("changeBluetooth", res.available);
|
||||
// that.$store.commit("changeBluetooth", res.available);
|
||||
})
|
||||
},
|
||||
onUnload: function() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,173 @@
|
|||
<template>
|
||||
<view class="weightPages">
|
||||
<view class="content ">
|
||||
<view class="title">连接成功,开始测量</view>
|
||||
<view class="text">{{text}}</view>
|
||||
<view class="image">
|
||||
<image src="/pageTwo/static/PCL.gif" class="image3"></image>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<view>提示:</view>
|
||||
<text>1.请确定设备已开机</text>
|
||||
<text>2.请确定手机蓝牙及位置信息已打开</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btnGroup" v-if="!stopblue">
|
||||
<view class="Blue-btn Blue-close" @click="handleBack">返回上一页</view>
|
||||
<view class="Blue-btn" @click="handleGetMeasure">结束测量</view>
|
||||
</view>
|
||||
|
||||
<!-- 手动记录 -->
|
||||
<!-- <view class="wrapper" v-if="isHeight">
|
||||
<view class="bg"></view>
|
||||
<view class="Blue">
|
||||
<view class="h4">测量结果提示</view>
|
||||
<view class="Blue-box">
|
||||
本次测量体重为:<text>{{weight}}{{unit}}</text>
|
||||
</view>
|
||||
<view class="Blue-box">
|
||||
上次测量身高为:<input v-model="height" type="digit" placeholder="请输入身高" />cm
|
||||
</view>
|
||||
<view class="Blue-btn Blue-close" @click="handleBack">取消</view>
|
||||
<view class="Blue-btn" @click="handleGetMeasure">保存测量结果</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
text: "",
|
||||
imp: "",
|
||||
weight: "",
|
||||
height: "",
|
||||
deviceId: "",
|
||||
unit: "kg",
|
||||
Unload: false,
|
||||
isHeight: false,
|
||||
stopblue: true,
|
||||
HeartRateList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "isUseBluetooth"]),
|
||||
info() {
|
||||
return this.user
|
||||
},
|
||||
},
|
||||
onUnload: function() {
|
||||
let that = this
|
||||
if (!that.Unload) {
|
||||
that.useBluetooth.stopSearchBluetooth()
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.text = ""
|
||||
that.deviceId = options.deviceId
|
||||
that.height = that.user.height
|
||||
uni.onBluetoothDeviceFound(handleDeviceFound)
|
||||
},
|
||||
watch: {
|
||||
isUseBluetooth: function() {
|
||||
let that = this
|
||||
if (!that.isUseBluetooth) {
|
||||
that.$tools.showModal('蓝牙连接已断开,请重新连接后测量')
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 发现外围设备
|
||||
*/
|
||||
handleDeviceFound(res) {
|
||||
var that = this;
|
||||
res.devices.forEach(device => {
|
||||
device.advertisData = device.advertisData ? device.advertisData : ''
|
||||
if (device.name.toLowerCase().indexOf('pc-x01') != -1 && device.deviceId.indexOf(
|
||||
that.deviceId) != -1) {
|
||||
let value = that.$tools.ab2hex(device.advertisData, "")
|
||||
let data = parseInt(value.substring(2, 6), 16) / 100
|
||||
let HeartRate = parseInt(value.substring(10, 12), 16)
|
||||
let type = value.substring(0, 2) //d0实时,e0稳定
|
||||
console.log("1111111111", value, data, HeartRate)
|
||||
that.text = "您的实时体重是:" + data + that.unit
|
||||
if (type == "e0") {
|
||||
that.text = "您的稳定体重是:" + data + that.unit
|
||||
that.imp = parseInt(value.substring(6, 10), 16)
|
||||
that.weight = data
|
||||
if (HeartRate != 0) {
|
||||
that.HeartRateList.push(HeartRate)
|
||||
}
|
||||
that.stopblue = false
|
||||
return
|
||||
}
|
||||
return;
|
||||
}
|
||||
})
|
||||
},
|
||||
// 保存测量结果
|
||||
handleGetMeasure() {
|
||||
let that = this
|
||||
that.$tools.msg("测量结束")
|
||||
that.handleBack()
|
||||
console.log("结束", that.weight, that.HeartRateList)
|
||||
return
|
||||
|
||||
if (!that.height) {
|
||||
this.$tools.msg("请输入身高")
|
||||
return
|
||||
}
|
||||
that.$model.getmeasurefunit({
|
||||
adc: that.imp,
|
||||
weight: that.weight + that.unit,
|
||||
height: that.height,
|
||||
aud_id: that.info.id
|
||||
}).then(res => {
|
||||
that.isHeight = false
|
||||
console.log("res", res, that.imp)
|
||||
if (res.code == 0) {
|
||||
|
||||
that.$store.dispatch("getResult", {
|
||||
aud_id: uni.getStorageSync('userid')
|
||||
})
|
||||
that.$tools.msg("测量成功")
|
||||
} else {
|
||||
that.$tools.msg("测量失败")
|
||||
}
|
||||
setTimeout(function() {
|
||||
uni.switchTab({
|
||||
url: "/pages/body/body"
|
||||
})
|
||||
}, 200)
|
||||
})
|
||||
},
|
||||
//返回上一页
|
||||
handleBack() {
|
||||
let that = this
|
||||
that.text = ""
|
||||
that.$store.commit("getIsUseBluetooth", {
|
||||
isBleLink: true,
|
||||
BleBodyMsg: "开始测量",
|
||||
isUseConnect: false,
|
||||
});
|
||||
that.useBluetooth.stopSearchBluetooth() //取消蓝牙搜索
|
||||
uni.switchTab({
|
||||
url: "/pages/body/body"
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.image3 {
|
||||
width: 200px !important;
|
||||
height: 340px !important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="top">
|
||||
<text>成年身高预测</text>
|
||||
为保证数据准确定,请认真填写真实信息
|
||||
</view>
|
||||
<view class="table">
|
||||
<view class="tr">
|
||||
<view class="text">性别</view>
|
||||
<view class="td">
|
||||
<view class="radio">
|
||||
<uni-icons :type="sex==1?'checkbox-filled':'circle'" @click="sex=1" size="24"
|
||||
:color="sex==1?'#fea606':'#dfdfdf'"></uni-icons>男
|
||||
</view>
|
||||
<view class="radio ml-10">
|
||||
<uni-icons :type="sex==2?'checkbox-filled':'circle'" @click="sex=2" size="24"
|
||||
:color="sex==2?'#fea606':'#dfdfdf'"></uni-icons>女
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tr">
|
||||
<view class="text">出生日期</view>
|
||||
<view class="td">
|
||||
<picker mode="date" :end="endDate" @change="maskClick" :value="birthday?birthday:endDate"
|
||||
:fields="fields">
|
||||
<view class="uni-input">
|
||||
{{birthday?birthday:'请选择'}}
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tr">
|
||||
<view class="text">爸爸身高</view>
|
||||
<view class="td">
|
||||
<input class="input" type="digit" v-model="dadheight " placeholder="请输入">cm
|
||||
</view>
|
||||
</view>
|
||||
<view class="tr">
|
||||
<view class="text">妈妈身高</view>
|
||||
<view class="td">
|
||||
<input class="input" type="digit" v-model="momheight" placeholder="请输入">cm
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="table table2">
|
||||
<view class="text">当前标准身高</view>
|
||||
<view class="text">成年身高预测</view>
|
||||
<view class="td">
|
||||
<text>{{geneticheight}}</text>cm
|
||||
</view>
|
||||
<view class="td">
|
||||
<text>{{adultheight}}</text>
|
||||
<text class="text2" v-if="errorvalue">±{{errorvalue}}</text> cm
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn mb-15" @click="handleClick">立即计算</view>
|
||||
<view class="title mt-20">
|
||||
<view class="h5">如果当前实际身高﹤当前标准身高</view>
|
||||
<view class="con">孩子后天生长环境不利长高。请从饮食、睡眠、运动、情绪等方面排查。加强后天因素管理,让孩子处于最佳长高状态。</view>
|
||||
<view class="h5">如果当前实际身高﹥当前标准身高</view>
|
||||
<view class="con">孩子后天生长环境有利长高。请继续保持,加强后天因素管理,孩子成年可比标准高10cm以上。</view>
|
||||
<view class="con" v-for="(ite,ind) in configInfo.literature.height_prediction"
|
||||
v-if="configInfo.literature.height_prediction.length">
|
||||
{{ite}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
sex: 1,
|
||||
errorvalue: 0,
|
||||
adultheight: 0,
|
||||
geneticheight: 0,
|
||||
dadheight: "",
|
||||
momheight: "",
|
||||
birthday: "",
|
||||
fields: "",
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "configInfo"]),
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
let that = this
|
||||
if (!that.dadheight) {
|
||||
that.$tools.msg("请输入爸爸身高!");
|
||||
return
|
||||
}
|
||||
if (!that.momheight) {
|
||||
that.$tools.msg("请输入妈妈身高!");
|
||||
return
|
||||
}
|
||||
uni.showLoading({
|
||||
title: '计算中'
|
||||
});
|
||||
that.$model.GetPredictheight({
|
||||
dadHeight: that.dadheight,
|
||||
momHeight: that.momheight,
|
||||
birthday: that.birthday,
|
||||
sex: that.sex,
|
||||
}).then(res => {
|
||||
if (res.code != 0) return
|
||||
setTimeout(function() {
|
||||
uni.hideLoading();
|
||||
}, 1000);
|
||||
that.adultheight = res.data.adultheight
|
||||
that.geneticheight = res.data.geneticheight
|
||||
that.errorvalue = res.data.errorvalue
|
||||
})
|
||||
},
|
||||
//确定年龄
|
||||
maskClick(e) {
|
||||
this.birthday = e.detail.value
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 15px 10px;
|
||||
background: #fff;
|
||||
min-height: calc(100vh - 30px);
|
||||
|
||||
.radio {
|
||||
display: flex;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
picker {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
border: none;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.top {
|
||||
width: 100%;
|
||||
line-height: 30px;
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
color: #999;
|
||||
|
||||
text {
|
||||
width: 100%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 40rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.h5 {
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.con {
|
||||
margin-top: 5px;
|
||||
color: #999;
|
||||
line-height: 22px;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.table,
|
||||
.table2 {
|
||||
width: 100%;
|
||||
border: 1px solid #d69231;
|
||||
border-bottom: none;
|
||||
box-sizing: border-box;
|
||||
border-spacing: inherit;
|
||||
font-size: 28rpx;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
border-right: none;
|
||||
|
||||
.tr {
|
||||
width: 50%;
|
||||
float: left;
|
||||
|
||||
.text {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.td {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
float: left;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
background: #ffcf85;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #d69231;
|
||||
border-right: 1px solid #d69231;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.td {
|
||||
box-sizing: border-box;
|
||||
background: #e4cdac21;
|
||||
display: flex;
|
||||
float: left;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
border-bottom: 1px solid #d69231;
|
||||
border-right: 1px solid #d69231;
|
||||
text-align: center;
|
||||
|
||||
|
||||
/deep/input {
|
||||
width: 95%;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
font-size: 30rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.table2 {
|
||||
margin: 50rpx auto;
|
||||
border-right: none;
|
||||
text-align: center;
|
||||
|
||||
.text {
|
||||
width: 50%;
|
||||
border-right: 1px solid #d69231;
|
||||
}
|
||||
|
||||
.td {
|
||||
height: 50px;
|
||||
width: 50%;
|
||||
line-height: 50px;
|
||||
display: inherit;
|
||||
border-right: 1px solid #d69231;
|
||||
|
||||
.text2 {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 15px;
|
||||
background-color: $maincolor;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<!-- -->
|
||||
<view class="skiptop">
|
||||
<!-- <view class="status" @click="$Bluetooth.handleDevicesMac(isdevice,acd_id)"><text>设备连接</text></view> -->
|
||||
<view class="item">
|
||||
<view class="item-ite">平均吸气肺活量<text>{{info?info.average:'--'}}</text></view>
|
||||
<view class="item-ite">吸气速度<text>--</text></view>
|
||||
<view class="item-ite">是否达标<text>{{info?info.level:'--'}}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
<!--自由训练 -->
|
||||
<view class="box1">
|
||||
<view class="time">{{info?info.time:''}}</view>
|
||||
<!-- <view class="LiuS">吸气速度 <text class="cgreen ml-5">{{info?info.flow_val:'--'}}L/min</text></view> -->
|
||||
<view class="item">
|
||||
<view class="image">
|
||||
<image src="../../static/bae.png" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="center mt-15">
|
||||
<view class="level"></view>
|
||||
<view class="level level-bg" :style="{'top':info?Number(100 - info.offset)+'%':'100%'}"></view>
|
||||
<view class="level-item" v-if="info">
|
||||
<view class="ite" v-for="(ite,ind) in info.list" :style="{'height':100/info.list.length+'%'}">
|
||||
{{ite.text}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="val" v-if="info">
|
||||
<text>{{info.average}}</text>
|
||||
吸气肺活量平均值
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
LiuS: 0,
|
||||
isdevice: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["MeasureLung", "user"]),
|
||||
info() {
|
||||
return this.MeasureLung
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.$store.dispatch("getLungResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
let that = this
|
||||
that.$store.dispatch("getLungResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
}, 1000);
|
||||
},
|
||||
methods: {
|
||||
// 历史数据删除时重新加载接口
|
||||
reload() {
|
||||
let that = this
|
||||
console.log('重新加载');
|
||||
this.$nextTick(() => {
|
||||
that.$store.dispatch("getLungResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
})
|
||||
},
|
||||
navTo(url) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/scss/lunging.scss";
|
||||
|
||||
.skiptop {
|
||||
margin-top: 15px;
|
||||
width: calc(100% - 40px);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,593 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="lan box_shadow" @click="visible = true">
|
||||
<view class="left">地区:</view>
|
||||
<view class="right">{{region?region:'请选择'}}<uni-icons type="bottom"></uni-icons></view>
|
||||
</view>
|
||||
<view class="lan box_shadow">
|
||||
<view class="left">性别</view>
|
||||
<view class="right">
|
||||
<picker mode="selector" :range="sexItem" @change="onsexArr">
|
||||
<view class="uni-input">{{gender==1?'男':'女'}}</view>
|
||||
<icon class="iconfont icon-arrow-down-bold"></icon>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 估分 -->
|
||||
<view class="box">
|
||||
<view class="title bold">本次估分成绩为</view>
|
||||
<view class="charts mt-15">
|
||||
<qiun-data-charts type="arcbar" :chartData="chartData" :Height="140" :Width="140" :canvas2d="true" />
|
||||
<view class="name">{{score?score:'--'}}</view>
|
||||
</view>
|
||||
<view class="title bold Max_score" v-if="Max_score">该地区体育总成绩为:{{Max_score}}分</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view v-if="selectllist.length" style="width: 100%;">
|
||||
<view v-for="(item,index) in selectllist">
|
||||
<view class="titleName bold mt-15 ml-15 size16">{{item.name}}</view>
|
||||
<view class="indexCarList">
|
||||
<view class="card" v-for="(ite,ind) in item.list">
|
||||
<view class="title">
|
||||
<view class="name ">{{ite.name}}</view>
|
||||
</view>
|
||||
<!-- 列表 -->
|
||||
<view class="item3" v-for="(it,ik) in ite.list" :key="ik" v-if="!isresult">
|
||||
<!-- 单选 -->
|
||||
<uni-icons :type="it.choice_state==1?'circle-filled':'circle'"
|
||||
:color="it.choice_state==1?'#FEC407':'#dfdfdf'" size="22"
|
||||
v-if="Number(ite.is_choice)>=1" @click="handleActiveState(ite,it,ik)"></uni-icons>
|
||||
|
||||
|
||||
<view class="name" @click="handleTips(it.describe)">
|
||||
<text>{{it.name}}</text>
|
||||
<uni-icons type="info" color="#f0ad4e" size="20" v-if="it.describe"></uni-icons>
|
||||
</view>
|
||||
|
||||
<view class="weight">
|
||||
<view class="input">
|
||||
<!-- 整数类型 -->
|
||||
<input type="number" v-model="it.value" confirm-type="done" placeholder="请输入"
|
||||
v-if="it.type ==1" :style="{'color':it.inputStyle}"
|
||||
@input="changeDisabled(it)" />
|
||||
<!-- 小数类型 -->
|
||||
<input type="digit" v-model="it.value" confirm-type="done" placeholder="请输入"
|
||||
maxlength="4" v-else-if="it.type ==2||it.type ==3"
|
||||
:style="{'color':it.inputStyle}" @input="changeDisabled(it)" />
|
||||
<!-- 分秒类型 -->
|
||||
<picker mode="multiSelector" :range="timeList" @change="bindTimeChange($event,it)"
|
||||
v-else-if="it.type ==4" :style="{'color':it.inputStyle}"
|
||||
@input="changeDisabled(it)">
|
||||
<view>{{it.value?it.value:'请选择'}}</view>
|
||||
<uni-icons type="down" color="#999" size="20" class="down"></uni-icons>
|
||||
</picker>
|
||||
<uni-icons type="clear" color="#999" v-if="it.value &&it.type !='4'"
|
||||
@click="handleValue(it)" size="24" class="uni-icons"></uni-icons>
|
||||
</view>
|
||||
<text :style="{'color':it.inputStyle}" @input="changeDisabled(it)">{{it.unit}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 结果展示 -->
|
||||
<view class="result item3" v-for="(ita,idx) in ite.list" :key="idx"
|
||||
v-if="isresult&&ite.list.length>1">
|
||||
<view class="name">{{ita.name}}</view>
|
||||
<view class="weight">
|
||||
<view style="width: 40%;">{{ita.value?ita.value:'-'}}</view>
|
||||
<view class="cblue bold">{{ita.proportion_value?ita.proportion_value:'-'}}</view>
|
||||
<view class="cblue bold">{{ita.total_score?ita.total_score:'-'}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="gfbtn" v-if="isSports" @click="handleNewScore()">重新估分</view>
|
||||
<view class="gfbtn" @click="handlescore()" v-else>开始估分</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="nolist" v-else>
|
||||
<image src="../../static/none.png"></image>
|
||||
<text>{{msg}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 占比 -->
|
||||
<uslider></uslider>
|
||||
<!-- 弹框 -->
|
||||
<view class="wrapper" v-if="isDrawe">
|
||||
<view class="bg" @click="onTap"></view>
|
||||
|
||||
<!-- 单选 -->
|
||||
<view class="edit" @click.stop>
|
||||
<view class="title">请选择<text class="choice">({{List.length}}选{{choice}})</text></view>
|
||||
<view class="item" v-for="(item, index) in List" :key="index" @click="toggle(item)">
|
||||
<!-- d单选 -->
|
||||
<uni-icons :type="isActive.name==item.name?'circle-filled':'circle'" size="22"
|
||||
:color="isActive.name==item.name?'#FEC407':'#dfdfdf'" v-if="choice==1"></uni-icons>
|
||||
|
||||
<!-- 多选 -->
|
||||
<uni-icons :type="isActiveNameList.indexOf(item.name)!=-1?'checkbox-filled':'circle'" size="22"
|
||||
:color="isActiveNameList.indexOf(item.name)!=-1?'#FEC407':'#dfdfdf'"
|
||||
v-if="choice>1"></uni-icons>
|
||||
|
||||
<view class="name">
|
||||
<view class="overflow">
|
||||
{{item.name}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn close" @click="onTap">取消</view>
|
||||
<view class="btn" @click="handleTarget">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view v-if="visible" class="visible" @click="visible=false">
|
||||
<view @click.stop class="item">
|
||||
<view class="groupBtn">
|
||||
<view @click="visible=false">取消</view>
|
||||
<view @click="handlesure()" class="sure">确定</view>
|
||||
</view>
|
||||
<picker-view @change="bindChange" :value="value" class="picker-view" :indicator-style="indicatorStyle">
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item,index) in province" :key="index">{{item.name}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item,index) in city" :key="index">{{item}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<view class="uni-stat-tooltip" v-if="isTips">
|
||||
{{tips}}
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uslider from "@/element/slider-fraction.vue";
|
||||
import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tips: "",
|
||||
isTips: false,
|
||||
chartData: {
|
||||
series: [{
|
||||
name: "正确率",
|
||||
color: "#4687F9",
|
||||
data: 0.8
|
||||
}]
|
||||
},
|
||||
sexItem: [
|
||||
"男",
|
||||
"女"
|
||||
],
|
||||
value: [1, 0],
|
||||
visible: false,
|
||||
region: "",
|
||||
province: [], //省
|
||||
city: [], //市
|
||||
area: [], //区
|
||||
indicatorStyle: `height: 45px;`,
|
||||
gender: 1,
|
||||
sportsList: [],
|
||||
List: [],
|
||||
score: 0,
|
||||
Max_score: 0,
|
||||
isDrawe: false,
|
||||
selectllist: [],
|
||||
isActive: {},
|
||||
isActiveList: [],
|
||||
isActiveNameList: [],
|
||||
region_list: {},
|
||||
timeList: [],
|
||||
timesTndex: [0, 0],
|
||||
isSports: false,
|
||||
msg: "暂无信息",
|
||||
isresult: false,
|
||||
choice: 0,
|
||||
isRefresh: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "configInfo"]),
|
||||
userId() {
|
||||
return this.user.aud_id
|
||||
},
|
||||
},
|
||||
components: {
|
||||
uslider,
|
||||
qiunDataCharts
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
that.province = that.configInfo.area_list
|
||||
that.city = that.province[1].list
|
||||
let defaultRegion = [that.province[that.value[0]].name, that.city[that.value[1]]]
|
||||
that.region = defaultRegion.join(",");
|
||||
that.score = 0
|
||||
that.tips = ""
|
||||
that.isTips = false
|
||||
that.selectllist = []
|
||||
that.sportsList = []
|
||||
that.timeList = that.$tools.gethms()
|
||||
that.getList(0)
|
||||
console.log("onLoad")
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
let that = this
|
||||
that.tips = ""
|
||||
that.isTips = false
|
||||
that.score = 0
|
||||
that.choice = 0
|
||||
that.Max_score = 0
|
||||
that.selectllist = []
|
||||
that.sportsList = []
|
||||
that.isRefresh = true
|
||||
that.timeList = that.$tools.gethms()
|
||||
that.getList(0)
|
||||
setTimeout(() => {
|
||||
that.isRefresh = false
|
||||
uni.stopPullDownRefresh()
|
||||
}, 200);
|
||||
console.log("刷新")
|
||||
},
|
||||
onShow() {},
|
||||
watch: {
|
||||
isTips() {
|
||||
let that = this
|
||||
if (that.isTips) {
|
||||
setTimeout(() => {
|
||||
that.isTips = false
|
||||
}, 4000);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
bindChange: function(e) {
|
||||
let that = this
|
||||
if (e.detail.value[0] != that.value[0]) {
|
||||
e.detail.value[1] = 0
|
||||
}
|
||||
that.value = e.detail.value
|
||||
that.city = that.province[that.value[0]].list
|
||||
},
|
||||
handlesure() {
|
||||
let that = this
|
||||
let defaultRegion = [that.province[that.value[0]].name, that.city[that.value[1]]]
|
||||
that.region = defaultRegion.join(",");
|
||||
that.visible = false
|
||||
that.score = 0
|
||||
that.isresult = false
|
||||
that.selectllist = []
|
||||
that.sportsList = []
|
||||
that.isActiveList = []
|
||||
that.isActiveNameList = []
|
||||
that.getList(0)
|
||||
},
|
||||
// 地区
|
||||
handleCityList() {
|
||||
let that = this
|
||||
that.value = [2, 0]
|
||||
that.city = that.configInfo.area_list[2].list
|
||||
},
|
||||
//
|
||||
getList(ind) {
|
||||
let that = this
|
||||
that.isresult = false
|
||||
that.isSports = false
|
||||
that.$model.getSportsListAll({
|
||||
gender: that.gender,
|
||||
parameter_data: that.region,
|
||||
}).then((res) => {
|
||||
console.log("全部项目", res)
|
||||
if (res.code != 0) {
|
||||
that.msg = res.msg
|
||||
return
|
||||
}
|
||||
res.data.forEach(item => {
|
||||
item.list.forEach(list => {
|
||||
list.list.forEach(val => {
|
||||
val.inputStyle = "#999"
|
||||
if (list.is_choice == 2 && val.choice_state == 1) {
|
||||
that.isActiveList.push(val.name)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
that.score = 0
|
||||
that.Max_score = 0
|
||||
that.selectllist = res.data
|
||||
that.chartData.series[0].data = 0.8
|
||||
that.tips = ""
|
||||
that.isTips = false
|
||||
})
|
||||
},
|
||||
// 重新估分
|
||||
handleNewScore() {
|
||||
let that = this
|
||||
that.isActive = {}
|
||||
that.selectllist = []
|
||||
that.sportsList = []
|
||||
that.isActiveList = []
|
||||
that.isActiveNameList = []
|
||||
that.getList(0)
|
||||
},
|
||||
changeDisabled(item) {
|
||||
item.inputStyle = '#333'
|
||||
},
|
||||
//确定性别
|
||||
onsexArr(e) {
|
||||
this.gender = this.sexItem[e.target.value] == "男" ? 1 : 2
|
||||
},
|
||||
// 多项选择
|
||||
handleActiveState(item, ite, ind) {
|
||||
let that = this
|
||||
// 单选
|
||||
if (Number(item.is_choice) == 1) {
|
||||
item.list.forEach(list => {
|
||||
list.choice_state = 0
|
||||
})
|
||||
ite.choice_state = ite.choice_state == 1 ? 0 : 1
|
||||
}
|
||||
// 多选
|
||||
let isActive = []
|
||||
if (Number(item.is_choice) >= 2) {
|
||||
if (that.isActiveList.indexOf(ite.name) == -1) {
|
||||
that.isActiveList.push(ite.name);
|
||||
} else {
|
||||
that.isActiveList.splice(that.isActiveList.indexOf(ite.name), 1);
|
||||
}
|
||||
if (that.isActiveList.length > 2) {
|
||||
that.isActiveList.splice(0, 1)
|
||||
}
|
||||
item.list.forEach(list => {
|
||||
list.choice_state = 0
|
||||
that.isActiveList.forEach(it => {
|
||||
if (list.name == it) {
|
||||
list.choice_state = 1
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
bindTimeChange(e, it) {
|
||||
let that = this
|
||||
let minute = e.target.value[0]
|
||||
let second = e.target.value[1]
|
||||
it.value = that.timeList[0][minute].substring(0, 2) + ':' + that.timeList[1][second].substring(
|
||||
0, 2)
|
||||
},
|
||||
handleTips(text) {
|
||||
if (text == null || text == '') return
|
||||
// #ifndef APP-PLUS
|
||||
this.tips = text
|
||||
this.isTips = true
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
uni.showToast({
|
||||
title: text,
|
||||
duration: 4000,
|
||||
icon: 'none'
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
handleValue(item) {
|
||||
item.value = ""
|
||||
},
|
||||
// 开始估分
|
||||
handlescore() {
|
||||
let that = this
|
||||
console.log("selectllist", that.selectllist)
|
||||
that.selectllist.forEach(item => {
|
||||
item.list.forEach(ite => {
|
||||
ite.list.forEach(it => {
|
||||
it.value = it.value == "" ? "0" : it.value
|
||||
})
|
||||
})
|
||||
})
|
||||
that.$model.getSportsData({
|
||||
gender: that.gender,
|
||||
aud_id: that.user.aud_id,
|
||||
parameter_data: that.region,
|
||||
result_data: that.selectllist,
|
||||
}).then((res) => {
|
||||
console.log("开始估分", res)
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.isSports = true
|
||||
that.isresult = true
|
||||
that.selectllist = res.data.list
|
||||
that.score = res.data.total_score
|
||||
that.Max_score = res.data.max_score
|
||||
that.chartData.series[0].data = Number(res.data.total_score) / res.data.max_score
|
||||
})
|
||||
},
|
||||
// 项目项目
|
||||
handleHistory(item) {
|
||||
let that = this
|
||||
that.List = []
|
||||
that.region_list = item
|
||||
that.sportsList.forEach(ite => {
|
||||
if (ite.key == item.key) {
|
||||
that.List = ite.list
|
||||
that.choice = item.is_choice
|
||||
}
|
||||
})
|
||||
console.log("添加项目", item)
|
||||
that.isDrawe = true
|
||||
},
|
||||
// 选择项目
|
||||
toggle(item) {
|
||||
let that = this
|
||||
// 单选
|
||||
if (that.choice == 1) {
|
||||
that.isActive = that.isActive.name == item.name ? {} : item
|
||||
return
|
||||
}
|
||||
// 多选
|
||||
if (that.isActiveNameList.indexOf(item.name) == -1) {
|
||||
that.isActiveNameList.push(item.name)
|
||||
that.isActiveList.push(item)
|
||||
} else {
|
||||
for (var n = 0; n < that.isActiveNameList.length; n++) {
|
||||
if (item.name == that.isActiveNameList[n]) {
|
||||
if (that.isActiveNameList.indexOf(item.name) == -1) {
|
||||
that.isActiveNameList.push(item.name)
|
||||
that.isActiveList.push(item);
|
||||
}
|
||||
that.isActiveNameList.splice(n, 1)
|
||||
that.isActiveList.splice(n, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (that.isActiveList.length > that.choice) {
|
||||
that.isActiveList.splice(0, 1)
|
||||
that.isActiveNameList.splice(0, 1)
|
||||
}
|
||||
console.log("isActiveList", item.name, that.isActiveList, that.region_list.list)
|
||||
},
|
||||
// 确定选择项目
|
||||
handleTarget() {
|
||||
let that = this
|
||||
that.selectllist.forEach(item => {
|
||||
item.list.forEach(it => {
|
||||
if (it.key == that.region_list.key) {
|
||||
it.list = []
|
||||
}
|
||||
})
|
||||
})
|
||||
if (that.choice == 1) {
|
||||
if (Object.keys(that.isActive).length != 0) {
|
||||
that.region_list.list.push(that.isActive)
|
||||
}
|
||||
} else {
|
||||
that.region_list.list = that.isActiveList
|
||||
}
|
||||
that.isDrawe = false
|
||||
},
|
||||
// 取消选择
|
||||
onTap() {
|
||||
let that = this
|
||||
// 单选
|
||||
if (that.choice == 1) {
|
||||
if (Object.keys(that.isActive).length == 0) {
|
||||
that.region_list.list = []
|
||||
that.selectllist.forEach(item => {
|
||||
item.list.forEach(it => {
|
||||
if (it.key == that.region_list.key) {
|
||||
it.list = []
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
that.isDrawe = false
|
||||
console.log("取消", Object.keys(that.isActive).length, this.isActive)
|
||||
},
|
||||
navTo(url) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/scss/score.scss";
|
||||
|
||||
.lan {
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
padding: 0 10px;
|
||||
margin: 15px 10px 0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.left {
|
||||
width: 50%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
width: 70%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
text-align: right;
|
||||
|
||||
picker {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
border: none;
|
||||
margin-right: 15px;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: 100vh;
|
||||
padding-bottom: 15px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.Max_score {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.Lastdata {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
margin-top: 15px;
|
||||
font-size: 28rpx;
|
||||
padding: 0 10px;
|
||||
background: #FEC407 !important;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.uni-stat-tooltip {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
overflow: scroll;
|
||||
word-break: break-word;
|
||||
position: fixed;
|
||||
margin: auto;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
color: #fff;
|
||||
z-index: 999;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
top: 33%;
|
||||
left: 10%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,701 @@
|
|||
<template>
|
||||
<view class="content skipping">
|
||||
<!-- -->
|
||||
<view class="skiptop">
|
||||
<view class="status" @click="handleisSdevice()">
|
||||
<text>{{textLink}}</text>
|
||||
<image v-if="islink!=1" :class="[islink==-1?'':'icon_link']" src="../../static/zhuan.png"></image>
|
||||
<image v-if="islink==1" src="../../static/dui.png"></image>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="item-ite">今日个数<text>{{info?info.today_jump_num:'--'}}</text></view>
|
||||
<view class="item-ite">今日时长<text>{{info?info.today_jump_time:'--'}}</text></view>
|
||||
<view class="item-ite">卡路里/kcal<text>{{info?info.today_jump_kcal:'--'}}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="tabbar">
|
||||
<view @click="active=1" :class="[active==1?'active':'']">自由跳</view>
|
||||
<view @click="active=3" :class="[active==3?'active':'']">倒计数</view>
|
||||
<view @click="active=2" :class="[active==2?'active':'']">倒计时</view>
|
||||
</view>
|
||||
<!--自由训练 -->
|
||||
<view class="box1 box" v-if="active==1">
|
||||
<view class="item">
|
||||
<text class="item-set item-set0">自由</text>
|
||||
<text class="tips">无限制</text>
|
||||
</view>
|
||||
<view :class="[islink==1?'start':'start Nstart']" @click="handleStart(1)">开始</view>
|
||||
</view>
|
||||
<!--定时训练 -->
|
||||
<view class="box1 box" v-if="active==2">
|
||||
<view class="item">
|
||||
<view class="item-set">
|
||||
<text @click="handleTimeEdit('减')">-</text>
|
||||
<text>{{time_m}}:{{time_s}}</text>
|
||||
<text @click="handleTimeEdit('加')">+</text>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<picker mode="multiSelector" :range="timeList" :value="timesTndex" @change="bindTimeChange">
|
||||
<view>调整目标</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="[isConnection?'start':'start Nstart']" @click="handleStart(2)">开始</view>
|
||||
</view>
|
||||
<!--定数训练 -->
|
||||
<view class="box1 box" v-if="active==3">
|
||||
<view class="item">
|
||||
<view class="item-set">
|
||||
<text @click="handleWeightEdit('减')">-</text>
|
||||
<text v-if="!disabled">{{weight>50?weight:50}}</text>
|
||||
<input type="number" v-model="weight" focus="true" v-else @blur="disabled=false">
|
||||
<text @click="handleWeightEdit('加')">+</text>
|
||||
</view>
|
||||
<text class="tips" @click="disabled=true">调整目标</text>
|
||||
</view>
|
||||
<view :class="[isConnection?'start':'start Nstart']" @click="handleStart(3)">开始</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let myTime;
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
active: 1,
|
||||
acd_id: 6,
|
||||
weight: 50,
|
||||
disabled: false,
|
||||
isDevice: 0,
|
||||
isConnection: false,
|
||||
time_m: "",
|
||||
time_s: "",
|
||||
timeList: [],
|
||||
devicesList: [],
|
||||
timesTndex: [1, 0],
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
write: "",
|
||||
notify: "",
|
||||
islink: 0, //0连接中,1成功,-1失败
|
||||
textLink: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user', "MeasureSkip", "isConnected", "isBluetoothTyle"]),
|
||||
info() {
|
||||
return this.MeasureSkip
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
that.timeList = that.$tools.gethms()
|
||||
that.time_m = that.timeList[0][1].substring(0, 2)
|
||||
that.time_s = that.timeList[1][0].substring(0, 2)
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
// 首页进入
|
||||
if (options && options.deviceId) {
|
||||
that.deviceId = options.deviceId
|
||||
setTimeout(function() {
|
||||
that.createBLEConnection()
|
||||
}, 500)
|
||||
}
|
||||
if (options && options.acd_id) {
|
||||
that.$Bluetooth.stopBluetoothDevicesDiscovery()
|
||||
setTimeout(function() {
|
||||
that.handleisSdevice()
|
||||
}, 500)
|
||||
}
|
||||
that.$store.dispatch("getSkipResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
that.isConnection = that.isConnected
|
||||
that.onBLEConnectionStateChange()
|
||||
uni.onBluetoothAdapterStateChange(function(res) {
|
||||
that.$store.commit("changeBluetooth", res.available);
|
||||
})
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
}, 1000);
|
||||
},
|
||||
onShow() {
|
||||
let that = this
|
||||
// 跳绳页返回
|
||||
uni.$on('updateData', function(info) {
|
||||
let data = JSON.parse(info)
|
||||
that.acd_id = data.acd_id
|
||||
that.isDevice = data.device
|
||||
that.active = data.active
|
||||
that.deviceId = data.deviceId
|
||||
that.serviceId = data.serviceId
|
||||
that.write = data.write
|
||||
that.notify = data.notify
|
||||
that.islink = !that.isConnected ? -1 : 1
|
||||
that.isConnection = that.isConnected
|
||||
that.notifyBLECharacteristicValue()
|
||||
if (data.isSuccessful) {
|
||||
that.$store.dispatch("getSkipResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
}
|
||||
that.onBLEConnectionStateChange()
|
||||
uni.onBluetoothAdapterStateChange(function(res) {
|
||||
that.$store.commit("changeBluetooth", res.available);
|
||||
})
|
||||
console.log('监听到事件来自 updateData', data);
|
||||
})
|
||||
},
|
||||
onUnload: function() {
|
||||
let that = this
|
||||
clearTimeout(myTime);
|
||||
that.islink = -1
|
||||
that.isConnection = false
|
||||
that.closeBLEConnection()
|
||||
that.closeBluetoothAdapter()
|
||||
uni.$off("updateData")
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
}, 300)
|
||||
console.log("返回首页onUnload")
|
||||
},
|
||||
watch: {
|
||||
isConnected() {
|
||||
let that = this
|
||||
if (!that.isConnected) {
|
||||
that.islink = -1
|
||||
that.textLink = "重新连接"
|
||||
}
|
||||
that.isConnection = that.isConnected
|
||||
console.log("蓝牙是否连接", that.isConnected)
|
||||
},
|
||||
isBluetoothTyle() {
|
||||
let that = this
|
||||
if (!that.isBluetoothTyle) {
|
||||
that.isConnection = false
|
||||
that.textLink = "请打开手机蓝牙"
|
||||
that.islink = -1
|
||||
}
|
||||
console.log("蓝牙是否打开", that.isBluetoothTyle)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 初始化蓝牙
|
||||
handleisSdevice() {
|
||||
let that = this
|
||||
if (that.isConnected) return
|
||||
that.devicesList = []
|
||||
that.$Bluetooth.stopBluetoothDevicesDiscovery()
|
||||
uni.openBluetoothAdapter({
|
||||
success: e => {
|
||||
that.islink = 0
|
||||
that.handleMyTime()
|
||||
that.textLink = "蓝牙搜索中"
|
||||
that.startBluetoothDeviceDiscovery()
|
||||
that.$store.commit("changeBluetooth", true)
|
||||
console.log('初始化蓝牙成功:' + e.errMsg);
|
||||
},
|
||||
fail: e => {
|
||||
that.islink = -1
|
||||
that.textLink = that.$tools.getBluetoothAdapter(e)
|
||||
return
|
||||
}
|
||||
});
|
||||
},
|
||||
// 开始搜寻附近的蓝牙外围设备
|
||||
startBluetoothDeviceDiscovery() {
|
||||
let that = this
|
||||
uni.startBluetoothDevicesDiscovery({
|
||||
allowDuplicatesKey: true,
|
||||
interval: 200, //上报设备的间隔
|
||||
services: [],
|
||||
success: res => {
|
||||
that.onBluetoothDeviceFound();
|
||||
},
|
||||
fail: res => {}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 发现外围设备
|
||||
*/
|
||||
onBluetoothDeviceFound() {
|
||||
var that = this;
|
||||
uni.onBluetoothDeviceFound(res => {
|
||||
res.devices.forEach(device => {
|
||||
if (!device.name && !device.localName) {
|
||||
return
|
||||
}
|
||||
if (device.name.indexOf('YPC') != -1) {
|
||||
device.deviceId = device.deviceId
|
||||
that.deviceId = device.deviceId
|
||||
that.$Bluetooth.stopBluetoothDevicesDiscovery()
|
||||
that.handleDevice(device)
|
||||
return
|
||||
}
|
||||
})
|
||||
});
|
||||
that.handleMyTime()
|
||||
},
|
||||
handleDevice(device) {
|
||||
let that = this
|
||||
const foundDevices = that.devicesList
|
||||
const idx = that.$tools.inArray(foundDevices, "deviceId", device.deviceId)
|
||||
if (idx === -1) {
|
||||
that.devicesList.push(device);
|
||||
that.createBLEConnection()
|
||||
}
|
||||
},
|
||||
// 连接蓝牙
|
||||
createBLEConnection() {
|
||||
let that = this;
|
||||
uni.createBLEConnection({
|
||||
deviceId: that.deviceId,
|
||||
success: res => {
|
||||
that.textLink = "蓝牙连接中"
|
||||
setTimeout(function() {
|
||||
that.islink = 1
|
||||
that.getBLEDeviceServices()
|
||||
}, 1000)
|
||||
},
|
||||
fail: res => {
|
||||
that.textLink = "重新连接"
|
||||
console.log("设备连接失败,请重新连接", res, that.deviceId);
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 获取设备的UUID
|
||||
*/
|
||||
getBLEDeviceServices() {
|
||||
let serviceList = [];
|
||||
let that = this;
|
||||
uni.getBLEDeviceServices({
|
||||
deviceId: that.deviceId,
|
||||
success: res => {
|
||||
console.log("获取设备的UUID成功", res)
|
||||
serviceList = res.services;
|
||||
for (let i = 0; i < serviceList.length; i++) {
|
||||
let service = serviceList[i];
|
||||
if (service.uuid.indexOf("FFE0") != -1) {
|
||||
that.serviceId = service.uuid;
|
||||
that.isConnection = true
|
||||
that.textLink = "连接成功"
|
||||
that.getBLEDeviceCharacteristics();
|
||||
console.log("设备的FFE0的serviceId: " + that.serviceId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
console.log('获取设备的UUID失败:', res)
|
||||
that.islink = -1
|
||||
that.textLink = "重新连接"
|
||||
clearTimeout(myTime);
|
||||
that.isConnection = false
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取指定服务的特征值
|
||||
*/
|
||||
getBLEDeviceCharacteristics() {
|
||||
let characteristicsList = [];
|
||||
let that = this;
|
||||
uni.getBLEDeviceCharacteristics({
|
||||
deviceId: that.deviceId,
|
||||
serviceId: that.serviceId,
|
||||
success: res => {
|
||||
console.log("服务的特征值成功", res)
|
||||
// * 读read: true, //,写write: true, //,通知notify: true
|
||||
for (let i = 0; i < res.characteristics.length; i++) {
|
||||
let item = res.characteristics[i];
|
||||
if (item.uuid.indexOf('0000FF12') != -1) {
|
||||
that.write = item.uuid
|
||||
|
||||
} else if (item.uuid.indexOf('0000FFE4') != -1) {
|
||||
that.notify = item.uuid
|
||||
}
|
||||
}
|
||||
setTimeout(function() {
|
||||
let j = Number(165 + 10 + 1 + 8 + 8 + 8 + 8 + 8 + 8).toString(16)
|
||||
let str = "A50A01080808080808" + j.substr(j.length - 2, 2)
|
||||
that.SendData(str)
|
||||
}, 300)
|
||||
// 体重
|
||||
setTimeout(function() {
|
||||
that.handleStart(4)
|
||||
}, 600)
|
||||
uni.notifyBLECharacteristicValueChange({
|
||||
deviceId: that.deviceId,
|
||||
serviceId: that.serviceId,
|
||||
characteristicId: that.notify,
|
||||
state: true,
|
||||
})
|
||||
uni.notifyBLECharacteristicValueChange({
|
||||
deviceId: that.deviceId,
|
||||
serviceId: that.serviceId,
|
||||
characteristicId: that.write,
|
||||
state: true,
|
||||
})
|
||||
that.notifyBLECharacteristicValue()
|
||||
},
|
||||
fail: res => {
|
||||
console.log('获取特征值失败:', JSON.stringify(res))
|
||||
}
|
||||
})
|
||||
},
|
||||
notifyBLECharacteristicValue() {
|
||||
let that = this;
|
||||
uni.notifyBLECharacteristicValueChange({
|
||||
state: true, // 启用 notify 功能
|
||||
deviceId: that.deviceId,
|
||||
serviceId: that.serviceId,
|
||||
characteristicId: that.notify,
|
||||
success(res) {
|
||||
uni.onBLECharacteristicValueChange(function(res) {
|
||||
let value = that.$tools.ab2hex(res.value, "");
|
||||
if (value == '5a05090169') { //模式设置成功
|
||||
let info = {
|
||||
active: that.active,
|
||||
deviceId: that.deviceId,
|
||||
serviceId: that.serviceId,
|
||||
notify: that.notify,
|
||||
write: that.write,
|
||||
acd_id: that.acd_id,
|
||||
isDevice: that.isDevice,
|
||||
isSuccessful: false
|
||||
}
|
||||
setTimeout(function() {
|
||||
uni.$off("updateData")
|
||||
uni.navigateTo({
|
||||
url: "/pageTwo/devices/PCT01?info=" + JSON
|
||||
.stringify(info)
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
console.log("value", value, that.active)
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 开启蓝牙主动上报模式
|
||||
SendData(str) {
|
||||
let that = this
|
||||
let buf = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function(h) {
|
||||
return parseInt(h, 16)
|
||||
}))
|
||||
console.log("xiafa", str)
|
||||
uni.writeBLECharacteristicValue({
|
||||
deviceId: that.deviceId,
|
||||
serviceId: that.serviceId,
|
||||
characteristicId: that.write,
|
||||
value: buf.buffer,
|
||||
success: res => {
|
||||
console.log('下发指令成功', res.errMsg)
|
||||
},
|
||||
fail: res => {
|
||||
console.log("下发指令失败", res);
|
||||
},
|
||||
})
|
||||
},
|
||||
// 模式切换
|
||||
handleStart(ind) {
|
||||
let that = this
|
||||
let m = null
|
||||
let send = null
|
||||
if (!that.isConnected) {
|
||||
that.$tools.msg("请先连接设备!")
|
||||
return
|
||||
}
|
||||
if (ind == 1) { // 1自由
|
||||
m = Number(165 + 8 + 9).toString(16)
|
||||
send = "A5080900000000" + m.substr(m.length - 2, 2)
|
||||
}
|
||||
if (ind == 2) { //2定时
|
||||
let time = Number(that.time_m) * 60 + Number(that.time_s)
|
||||
m = Number(165 + 8 + 9 + time).toString(16)
|
||||
send = "A508090000" + that.$tools.toHex(time, 4) + m.substr(m.length - 2, 2)
|
||||
}
|
||||
if (ind == 3) { //3定数
|
||||
let weight = that.$tools.toHex(that.weight, 4)
|
||||
m = Number(165 + 8 + 9 + that.weight).toString(16)
|
||||
send = "A50809" + weight + "0000" + m.substr(m.length - 2, 2)
|
||||
}
|
||||
if (ind == 4) { //体重
|
||||
|
||||
let weight = Number(that.user.weight) * 2
|
||||
let num = parseInt(weight).toString();
|
||||
m = Number(165 + 5 + 8 + Number(num)).toString(16)
|
||||
send = "A50508" + Number(num).toString(16) + m.substr(m.length - 2, 2)
|
||||
}
|
||||
that.SendData(send)
|
||||
that.$Bluetooth.stopBluetoothDevicesDiscovery()
|
||||
},
|
||||
// 历史数据删除时重新加载接口
|
||||
reload() {
|
||||
let that = this
|
||||
this.$nextTick(() => {
|
||||
that.$store.dispatch("getSkipResult", {
|
||||
aud_id: that.user.aud_id
|
||||
})
|
||||
})
|
||||
},
|
||||
// 定时训练
|
||||
//
|
||||
bindTimeChange(e) {
|
||||
let that = this
|
||||
let m = e.target.value[0]
|
||||
let s = e.target.value[1]
|
||||
that.timesTndex = e.target.value
|
||||
let time_m = Number(that.timeList[0][m].substring(0, 2)) * 60
|
||||
let time_s = Number(that.timeList[1][s].substring(0, 2))
|
||||
if (Number(time_m + time_s) < 30) {
|
||||
that.time_m = '00'
|
||||
that.time_s = '30'
|
||||
} else {
|
||||
that.time_m = that.timeList[0][m].substring(0, 2)
|
||||
that.time_s = that.timeList[1][s].substring(0, 2)
|
||||
}
|
||||
},
|
||||
handleTimeEdit(text) {
|
||||
let that = this
|
||||
let time_m = Number(that.time_m) * 60
|
||||
let time_s = Number(that.time_s)
|
||||
let minutes = null
|
||||
let seconds = null
|
||||
|
||||
if (Number(time_m + time_s) >= 3570 && text == '加') {
|
||||
that.time_m = '59'
|
||||
that.time_s = '59'
|
||||
return
|
||||
}
|
||||
if (Number(time_m + time_s) <= 30 && text == '减') {
|
||||
that.time_m = '00'
|
||||
that.time_s = '30'
|
||||
return
|
||||
}
|
||||
if (text == '减') {
|
||||
minutes = Math.floor((Number(time_m + time_s - 30) % 3600) / 60)
|
||||
seconds = Number(time_m + time_s - 30) % 60
|
||||
}
|
||||
if (text == '加') {
|
||||
minutes = Math.floor((Number(time_m + time_s + 30) % 3600) / 60)
|
||||
seconds = Number(time_m + time_s + 30) % 60
|
||||
}
|
||||
that.time_m = minutes > 9 ? minutes : '0' + minutes;
|
||||
that.time_s = seconds > 9 ? seconds : '0' + seconds;
|
||||
that.timesTndex = [Number(that.time_m), Number(that.time_s)]
|
||||
},
|
||||
handleWeightEdit(text) {
|
||||
let that = this
|
||||
if (text == '减') {
|
||||
that.weight = Number(that.weight) - 50 > 50 ? Number(that.weight) - 50 : 50
|
||||
}
|
||||
if (text == '加') {
|
||||
that.weight = Number(that.weight) + 50
|
||||
}
|
||||
},
|
||||
// 蓝牙搜索记时
|
||||
handleMyTime() {
|
||||
let that = this
|
||||
myTime = setTimeout(function() {
|
||||
if (!that.devicesList.length) {
|
||||
that.islink = -1
|
||||
that.textLink = "重新搜索"
|
||||
that.$tools.showModal("没有查找到设备")
|
||||
}
|
||||
clearTimeout(myTime)
|
||||
that.$Bluetooth.stopBluetoothDevicesDiscovery()
|
||||
}, 20000);
|
||||
},
|
||||
// 监听蓝牙连接状态
|
||||
onBLEConnectionStateChange() {
|
||||
let that = this
|
||||
uni.onBLEConnectionStateChange(function(res) {
|
||||
console.log("监听蓝牙连接状态", res.connected)
|
||||
that.$store.commit("changeConnected", res.connected);
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 断开蓝牙模块
|
||||
*/
|
||||
closeBluetoothAdapter() {
|
||||
let that = this;
|
||||
uni.closeBluetoothAdapter({
|
||||
success: res => {
|
||||
console.log('蓝牙模块关闭成功');
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 断开蓝牙连接
|
||||
*/
|
||||
closeBLEConnection() {
|
||||
var that = this;
|
||||
uni.closeBLEConnection({
|
||||
deviceId: that.deviceId,
|
||||
success: res => {
|
||||
console.log('断开蓝牙连接成功');
|
||||
that.$store.commit("changeConnected", false);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background-color: #F5F6FA;
|
||||
}
|
||||
|
||||
.skiptop {
|
||||
width: calc(100% - 40px);
|
||||
margin-top: 15px;
|
||||
|
||||
}
|
||||
|
||||
.tabbar {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
|
||||
view {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.active:after {
|
||||
content: "";
|
||||
height: 3px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
left: 0;
|
||||
border-radius: 5px;
|
||||
background: $maincolor;
|
||||
}
|
||||
}
|
||||
|
||||
.box1 {
|
||||
background-color: #fff;
|
||||
padding: 10px !important;
|
||||
color: #999;
|
||||
margin: 15px;
|
||||
border-radius: 10px;
|
||||
width: calc(100% - 40px);
|
||||
|
||||
.time {
|
||||
width: 100%;
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
color: #333;
|
||||
font-size: 44rpx;
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
|
||||
text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.item-ite {
|
||||
font-size: 36rpx;
|
||||
margin-bottom: 15px;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.item-set {
|
||||
width: calc(100% - 30px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
font-size: 60rpx;
|
||||
margin-bottom: 5px;
|
||||
background-color: #f7f7f7;
|
||||
padding: 0 15px;
|
||||
justify-content: space-between;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
|
||||
/deep/input {
|
||||
font-size: 60rpx;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-set0 {
|
||||
background-color: #fff;
|
||||
justify-content: center
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.start {
|
||||
color: #fff;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
background: $textcolor;
|
||||
margin: 15px auto;
|
||||
}
|
||||
|
||||
.Nstart {
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
background-color: #fff;
|
||||
|
||||
image {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.icon_link {
|
||||
animation: rotation 0.6s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
58
pages.json
|
|
@ -260,6 +260,64 @@
|
|||
"style": {
|
||||
"navigationBarTitleText": "记录详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/search",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/G02",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/PCL",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}, {
|
||||
"path": "devices/PCV02",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/PCT01",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/B20",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/PCL22",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "devices/PCL22S",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,314 @@
|
|||
<template>
|
||||
<view class="box">
|
||||
<!-- 头部 -->
|
||||
<view class="header" v-if="token">
|
||||
<view class="top" v-if="userList.length">
|
||||
<image :src="info.head_pic" class="headimg" @click="handleAddUser(1)"></image>
|
||||
<view class="info" @click="handleAddUser(1)">
|
||||
<view class="size18 bold">{{info.nickname}}</view>
|
||||
<view class="mt-5">
|
||||
<text class="mr-10">性别:{{info.gender==1?'男':info.gender==2?'女':'未知'}}</text>
|
||||
<text class="ml-10">年龄:{{info.age}}岁</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-icon t-icon-qiehuan1" @click="$store.commit('changeDrawe', true)"></view>
|
||||
</view>
|
||||
<view class="top" v-else @click="handleAddUser(2)">
|
||||
<view class="info">
|
||||
暂无成员,请先添加~
|
||||
</view>
|
||||
<view class="add">
|
||||
+
|
||||
</view>
|
||||
</view>
|
||||
<!-- 蓝牙 -->
|
||||
<view class="bluetooth" v-if="userList.length">
|
||||
<view class="bleTips" @click="openBluetoothAdapter">
|
||||
{{bleTipsText}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="header" v-else @click="handleLogin">
|
||||
<view class="top top2">
|
||||
登录后查看更多
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据 -->
|
||||
<view class="toggle">
|
||||
<view :class="{'active':toolsIndex==0}" class="toolsItem" @click="toolsIndex=0">身体数据</view>
|
||||
<view :class="{'active':toolsIndex==1}" class="toolsItem" @click="toolsIndex=1">饮食数据</view>
|
||||
<view :class="{'active':toolsIndex==2}" class="toolsItem" @click="toolsIndex=2">健康工具</view>
|
||||
</view>
|
||||
<view v-if="token">
|
||||
<body v-if="toolsIndex==0"></body>
|
||||
<food v-if="toolsIndex==1"></food>
|
||||
<card v-if="toolsIndex==2"></card>
|
||||
</view>
|
||||
<view class="nolist" v-else>
|
||||
<image src="/static/none.png"></image>
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
<!-- -->
|
||||
<drawer></drawer>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
import body from "@/components/bodyIndex/bodyHome.vue"
|
||||
import food from "@/components/foodIndex/foodHome.vue"
|
||||
import card from "@/components/cardIndex/cardHome.vue"
|
||||
import drawer from "@/components/bodyIndex/drawer.vue"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
token: "",
|
||||
toolsIndex: 0
|
||||
}
|
||||
},
|
||||
components: {
|
||||
food,
|
||||
body,
|
||||
card,
|
||||
drawer,
|
||||
},
|
||||
computed: {
|
||||
...mapState(["user", "familayList", 'MeasureResult', "configInfo", "bleValue"]),
|
||||
info() {
|
||||
return this.user
|
||||
},
|
||||
userList() {
|
||||
return this.familayList
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
isConnection() {
|
||||
return this.bleValue.isConnectStatus
|
||||
},
|
||||
bleTipsText() {
|
||||
return this.bleValue.bleTipsText
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
let that = this
|
||||
that.token = uni.getStorageSync("token")
|
||||
that.$store.dispatch("getHomeConfig")
|
||||
that.handleUserList()
|
||||
that.$ble.onBLEConnectionStateChange()
|
||||
uni.onBluetoothAdapterStateChange(function(res) {
|
||||
that.$store.commit("changeBluetoothValue", {
|
||||
isBluetoothTyle: res.available
|
||||
});
|
||||
})
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
let that = this
|
||||
that.handleUserList()
|
||||
that.$ble.onBLEConnectionStateChange()
|
||||
uni.stopPullDownRefresh()
|
||||
},
|
||||
watch: {
|
||||
isBluetoothTyle: function() {
|
||||
let that = this
|
||||
if (!that.isBluetoothTyle) {
|
||||
that.handleBack()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 成员列表
|
||||
handleUserList() {
|
||||
let that = this
|
||||
that.$model.getUserList({
|
||||
type: 2
|
||||
}).then(res => {
|
||||
that.isShow = true
|
||||
if (res.code != 0) {
|
||||
that.$tools.msg(res.msg)
|
||||
return
|
||||
}
|
||||
that.$store.commit('changeFamilay', res.data.user_list)
|
||||
if (res.data.user_list.length) {
|
||||
let userid = ""
|
||||
if (uni.getStorageSync('userid')) {
|
||||
let found = res.data.user_list.find(e => e.id == uni.getStorageSync('userid'));
|
||||
if (found !== undefined) {
|
||||
userid = found.id
|
||||
} else {
|
||||
userid = res.data.user_list[0].id
|
||||
uni.setStorageSync('userid', res.data.user_list[0].id)
|
||||
}
|
||||
} else {
|
||||
userid = res.data.user_list[0].id
|
||||
uni.setStorageSync('userid', res.data.user_list[0].id)
|
||||
}
|
||||
// 用户信息接口
|
||||
that.$store.dispatch('getUserInfo', {
|
||||
aud_id: userid
|
||||
})
|
||||
// 厨房秤接口
|
||||
that.$store.dispatch("getCountFoodInfo", {
|
||||
aud_id: userid,
|
||||
time: that.$tools.getDate("start")
|
||||
})
|
||||
// 全部卡片
|
||||
that.$store.dispatch("getCardAllList", {
|
||||
aud_id: userid
|
||||
})
|
||||
//
|
||||
that.$store.dispatch("getResult", {
|
||||
aud_id: userid
|
||||
})
|
||||
that.handlePublicRecord(userid)
|
||||
that.$ble.openBluetoothAdapter()
|
||||
}
|
||||
}).catch(err => {})
|
||||
},
|
||||
// 公共手动记录内容
|
||||
handlePublicRecord(id) {
|
||||
let that = this
|
||||
that.$model.getPublicRecord({
|
||||
aud_id: id
|
||||
}).then(res => {
|
||||
console.log("公共手动记录", res)
|
||||
if (res.code == 0) {
|
||||
that.$store.commit('changePublicRecord', res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 初始化蓝牙
|
||||
openBluetoothAdapter() {
|
||||
let that = this
|
||||
if (that.isConnection == 2) return
|
||||
that.$store.commit('changeBluetoothValue', {
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
// notify: '',
|
||||
// write: '',
|
||||
// unit: "g",
|
||||
// type: 1,
|
||||
// unitList: that.$json.unitMinus,
|
||||
// countWeight: "",
|
||||
isBleLink: false, //是否可以点击
|
||||
bleTipsText: "蓝牙搜索中",
|
||||
isConnectStatus: 0,
|
||||
})
|
||||
that.$ble.openBluetoothAdapter()
|
||||
},
|
||||
handleBack() {
|
||||
let that = this
|
||||
that.$store.commit("changeBluetoothValue", {
|
||||
bleTipsText: "连接失败,点击重新连接",
|
||||
isConnectStatus: 1,
|
||||
})
|
||||
that.$ble.stopBluetoothDevicesDiscovery() //取消蓝牙搜索
|
||||
that.$ble.closeBLEConnection(that.bleValue.deviceId)
|
||||
that.$ble.closeBluetoothAdapter()
|
||||
},
|
||||
|
||||
// 添加成员
|
||||
handleAddUser(ind) {
|
||||
let that = this
|
||||
if (uni.getStorageSync('token')) {
|
||||
uni.navigateTo({
|
||||
url: ind == 1 ? "/body/my/userInfo?info=" + JSON.stringify(this.user) : "/body/my/userInfo"
|
||||
})
|
||||
} else {
|
||||
that.$tools("登录后查看更多")
|
||||
}
|
||||
},
|
||||
handleLogin() {
|
||||
uni.redirectTo({
|
||||
url: "/pageTwo/login/login"
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
background: $maincolor;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top2 {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.headimg {
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
border-radius: 50%;
|
||||
margin: 0 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.info {
|
||||
width: calc(100% - 120px);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.t-icon-qiehuan1 {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.bluetooth {
|
||||
width: calc(100% - 20px);
|
||||
background: #fff;
|
||||
padding: 8px 0;
|
||||
margin-top: 15px;
|
||||
margin-left: 10px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
display: flex;
|
||||
width: calc(100% - 20px);
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0;
|
||||
margin-top: 8px;
|
||||
|
||||
.toolsItem {
|
||||
color: #999;
|
||||
margin: 0 10px;
|
||||
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #333;
|
||||
position: relative
|
||||
}
|
||||
|
||||
.active:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 20px;
|
||||
height: 4px;
|
||||
background: #54d87c;
|
||||
border-radius: 5px;
|
||||
left: calc(50% - 10px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
<template>
|
||||
<view class="content ">
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
fields: "",
|
||||
active: 1,
|
||||
acd_id: 2,
|
||||
ind: 0,
|
||||
active1: 0,
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
lineData: {},
|
||||
handTrue: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user', "MeasureResult", "Trend"]),
|
||||
weightList() {
|
||||
let that = this
|
||||
that.showbox(0)
|
||||
return that.Trend
|
||||
},
|
||||
userInfo() {
|
||||
return this.MeasureResult
|
||||
},
|
||||
endDate() {
|
||||
return this.$tools.getDate("start")
|
||||
},
|
||||
startDate() {
|
||||
return this.$tools.GetDateStr(-90);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
},
|
||||
onLoad(options) {
|
||||
let that = this
|
||||
that.acd_id = options.acd_id
|
||||
that.$store.dispatch("GetBodyTrendList", {
|
||||
aud_id: uni.getStorageSync('userid'),
|
||||
s_time: that.startDate,
|
||||
e_time: that.endDate
|
||||
})
|
||||
// #ifdef APP-PLUS
|
||||
that.fields = "time"
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
that.fields = "day"
|
||||
// #endif
|
||||
},
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
let that = this
|
||||
that.$store.dispatch("GetBodyTrendList", {
|
||||
aud_id: uni.getStorageSync('userid'),
|
||||
s_time: that.startDate,
|
||||
e_time: that.endDate
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
}, 1000);
|
||||
},
|
||||
methods: {
|
||||
showbox(index) {
|
||||
let that = this
|
||||
that.handTrue = false
|
||||
that.$nextTick(function() {
|
||||
that.handTrue = true
|
||||
that.lineData = that.weightList.length ? that.weightList[index].line : {}
|
||||
})
|
||||
that.active1 = index
|
||||
},
|
||||
//开始
|
||||
handStartTimeH(e) {
|
||||
let that = this
|
||||
if (that.endTime) {
|
||||
if (Date.parse(e.detail.value) > Date.parse(that.endTime)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (Date.parse(e.detail.value) > Date.parse(that.endDate)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
}
|
||||
that.startTime = e.detail.value
|
||||
let endtime = that.endTime ? that.endTime : that.endDate
|
||||
that.$store.dispatch("GetBodyTrendList", {
|
||||
aud_id: that.user.id,
|
||||
s_time: that.startTime,
|
||||
e_time: that.endTime ? that.endTime : that.endDate
|
||||
})
|
||||
that.showbox(0)
|
||||
},
|
||||
// 结束
|
||||
handEndTimeH(e) {
|
||||
let that = this
|
||||
if (that.startTime) {
|
||||
if (Date.parse(e.detail.value) < Date.parse(that.startTime)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (Date.parse(e.detail.value) < Date.parse(that.startDate)) {
|
||||
that.$tools.msg("请选择正确的时间")
|
||||
return
|
||||
}
|
||||
}
|
||||
that.endTime = e.detail.value
|
||||
let startTime = that.startTime ? that.startTime : that.startDate
|
||||
that.$store.dispatch("GetBodyTrendList", {
|
||||
aud_id: uni.getStorageSync('userid'),
|
||||
s_time: startTime,
|
||||
e_time: that.endTime
|
||||
})
|
||||
that.showbox(0)
|
||||
},
|
||||
handleClick(ind) {
|
||||
let that = this
|
||||
if (!uni.getStorageSync('token')) {
|
||||
that.$tools.msg("登录后查看更多!")
|
||||
return
|
||||
}
|
||||
this.ind = ind
|
||||
this.$store.commit("changeFirst", true);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/scss/body.scss";
|
||||
|
||||
.listC {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
142
scss/common.scss
|
|
@ -1118,3 +1118,145 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测量也
|
||||
.weightPages {
|
||||
.text {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
margin-top: 20px;
|
||||
color: $textcolor;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.image {
|
||||
text-align: center;
|
||||
|
||||
image {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tips {
|
||||
width: auto;
|
||||
margin-top: 25px;
|
||||
padding-left: 20px;
|
||||
line-height: 30px;
|
||||
font-size:28rpx;
|
||||
color: #999;
|
||||
|
||||
text {
|
||||
display: block;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
|
||||
.Blue {
|
||||
width: 75%;
|
||||
padding: 15px;
|
||||
background: #fff;
|
||||
z-index: 999;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
|
||||
.h4 {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.Blue-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
text {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
margin: 0 5px;
|
||||
color: $textcolor;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
width: 85px;
|
||||
background: #f7f7f7;
|
||||
padding: 7px 5px;
|
||||
margin-right: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.Blue-btn {
|
||||
width: 45%;
|
||||
background: $textcolor;
|
||||
border-radius: 5px;
|
||||
font-size: 32rpx;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
float: right;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.Blue-close {
|
||||
background: #dfdfdf !important;
|
||||
float: left !important;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btnGroup {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
.btnClose,
|
||||
.baocun {
|
||||
width: 150px;
|
||||
background-color: $textcolor;
|
||||
border: 1px solid #f7f7f7;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 7px;
|
||||
border-radius: 10px;
|
||||
margin: 15px auto;
|
||||
}
|
||||
|
||||
.btnClose {
|
||||
background-color: #dfdfdf;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,776 @@
|
|||
.everyDay {
|
||||
background: #fff;
|
||||
padding: 20rpx 20rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
margin: 30rpx 20rpx 20rpx;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-weight: bold;
|
||||
font-size: 30rpx;
|
||||
|
||||
.quan {
|
||||
margin-right: 70rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jishiqi {
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
margin-top: 15px;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.detail {
|
||||
color: #3CB383;
|
||||
width: auto;
|
||||
padding: 3px 10px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #3CB383;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
width: 270rpx;
|
||||
height: 320rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.chart-wrap {
|
||||
position: relative;
|
||||
width: 250rpx;
|
||||
height: 250rpx;
|
||||
margin-top: -30rpx;
|
||||
margin-left: -5px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.center {
|
||||
border: none;
|
||||
width: 280rpx;
|
||||
height: 210rpx;
|
||||
position: absolute;
|
||||
top: 64rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.mubiao {
|
||||
width: 100%;
|
||||
margin-top: 32rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
width: calc(100% - 290rpx);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
float: left;
|
||||
height: 300rpx;
|
||||
margin-left: 20rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
font-size: 26rpx;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.left-icon {
|
||||
width: 90rpx;
|
||||
float: left;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.right-info {
|
||||
width: calc(100% - 100rpx);
|
||||
float: left;
|
||||
height: 74rpx;
|
||||
margin-left: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.right-info-top {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.right-info-bottom {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background-color: #f3f7f5;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
|
||||
.val {
|
||||
width: 45%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 9;
|
||||
height: 16rpx;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 添加食谱
|
||||
.addFood {
|
||||
|
||||
|
||||
.title,
|
||||
.textarea {
|
||||
width: calc(100% - 40rpx);
|
||||
margin-bottom: 20rpx;
|
||||
background: #fff;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 20rpx;
|
||||
|
||||
}
|
||||
|
||||
.food,
|
||||
.step {
|
||||
width: calc(100% - 40rpx);
|
||||
margin-bottom: 20rpx;
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.h4 {
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
justify-content: space-between;
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
border: 1px solid #dfdfdf;
|
||||
border-radius: 30rpx;
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.foodlist {
|
||||
column-count: 1;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: calc(100% - 40rpx);
|
||||
background: #f7f7f7;
|
||||
border-radius: 20rpx;
|
||||
padding: 8px 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: 30%;
|
||||
border-right: 1px solid #999;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 30%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.edit {
|
||||
width: 30%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
icon {
|
||||
display: flex;
|
||||
margin-right: 5px;
|
||||
color: $uni-color-warning;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.shang {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.add {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
background: $maincolor;
|
||||
margin-top: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.step {
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 20rpx 0;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
margin-top: 20rpx;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.add {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #f0ad4e;
|
||||
}
|
||||
}
|
||||
|
||||
.groupbtn {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
view {
|
||||
width: 45%;
|
||||
background-color: #fff;
|
||||
border: 1px solid #f0ad4e;
|
||||
text-align: center;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.subbtn {
|
||||
color: #fff;
|
||||
border-color: $maincolor;
|
||||
background-color: $maincolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
.foodDetail {
|
||||
background-color: #F7F7F7;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.foodInfo {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
box-sizing: 0 0 20rpx #f1f1f1;
|
||||
|
||||
image {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 15rpx;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-left: 30rpx;
|
||||
|
||||
.name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.kcal {
|
||||
width: 100% !important;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.foodContent {
|
||||
width: 100%;
|
||||
padding: 30rpx;
|
||||
margin-top: 16rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
box-sizing: 0 0 20rpx #f1f1f1;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.chart-wrap {
|
||||
position: relative;
|
||||
width: 280rpx;
|
||||
height: 280rpx;
|
||||
margin-top: -30rpx;
|
||||
margin-left: -20px;
|
||||
|
||||
// .uchart-kcal {
|
||||
// position: absolute;
|
||||
// left: 60rpx;
|
||||
// top: 120rpx;
|
||||
// width: 130rpx;
|
||||
// font-size: 40rpx;
|
||||
// text-align: center;
|
||||
// z-index: 9;
|
||||
// }
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-size: 26rpx;
|
||||
height: 200rpx;
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.color {
|
||||
width: 6rpx;
|
||||
height: 20rpx;
|
||||
margin-right: 10rpx;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
padding: 16rpx 0;
|
||||
font-size: 26rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.foodDetailList {
|
||||
margin-top: 10rpx;
|
||||
|
||||
.foodDetailItem {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.name {
|
||||
font-size: 26rpx;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.val {
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.set {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 20rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
|
||||
.icon {
|
||||
background: #d1f2ed;
|
||||
border-radius: 50%;
|
||||
font-size: 56rpx;
|
||||
color: #66cccc;
|
||||
text-align: center;
|
||||
padding: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tools {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx 0;
|
||||
display: flex;
|
||||
margin-bottom: 30rpx;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0px 1px 5px 2px #dfe2e1fc;
|
||||
|
||||
.type {
|
||||
width: 20%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
image {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #f7f7f7;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
|
||||
icon {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list2 {
|
||||
margin-top: 45%;
|
||||
|
||||
.btn {
|
||||
color: #fff;
|
||||
height: 64rpx;
|
||||
line-height: 64rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.fenxi {
|
||||
color: $maincolor;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
margin: 0 20rpx 20rpx;
|
||||
height: 45px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.serachBox {
|
||||
height: 80rpx;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 30rpx 20rpx;
|
||||
z-index: 99;
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.searchInput {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 120rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.search-wrap {
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border: 1px solid $maincolor;
|
||||
border-radius: 30rpx;
|
||||
padding: 0 20rpx;
|
||||
background: #fff;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.f_banner {
|
||||
width: 100% !important;
|
||||
height: 450rpx;
|
||||
margin: 30rpx auto;
|
||||
|
||||
/deep/swiper {
|
||||
height: 450rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: 100%;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.quan {
|
||||
width: 60rpx;
|
||||
height: 40rpx;
|
||||
position: relative;
|
||||
margin-right: 70rpx;
|
||||
}
|
||||
.quan::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
left: 0px;
|
||||
z-index: 22;
|
||||
background: #3CB383;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.quan::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
left: 17rpx;
|
||||
z-index: 11;
|
||||
background: #9CDCBF;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.drawerVisible {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
z-index: 999;
|
||||
|
||||
.bgVisible {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.infoVisible {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 300px;
|
||||
bottom: 0;
|
||||
background-color: #ffffff;
|
||||
transition: -webkit-transform 0.3s ease;
|
||||
transition: transform 0.3s ease;
|
||||
transition: transform 0.3s ease, -webkit-transform 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// .列表样式
|
||||
.footlist {
|
||||
margin: 30rpx 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
column-gap: 20rpx;
|
||||
column-count:2;
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
// justify-content: space-between;
|
||||
|
||||
.list {
|
||||
margin-bottom: 20rpx;
|
||||
// height: auto;
|
||||
overflow: auto;
|
||||
break-inside: avoid;
|
||||
border-radius: 15rpx;
|
||||
overflow: hidden;
|
||||
-webkit-column-break-inside: avoid;
|
||||
|
||||
.item {
|
||||
color: #666;
|
||||
width: calc(100% - 20rpx);
|
||||
position: initial;
|
||||
background: #fff;
|
||||
border-radius: 0 0 5px 5px;
|
||||
font-size: 14px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
.topimg{
|
||||
height:320rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.zan {
|
||||
.iconfont {
|
||||
font-size: 32rpx;
|
||||
position: inherit !important;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.footbox {
|
||||
// width: calc(100% - 60rpx);
|
||||
// margin-top: 80rpx;
|
||||
position: relative;
|
||||
|
||||
.item {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
color: #fff;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
background: #403f3f5c;
|
||||
padding: 5px;
|
||||
font-size: 30rpx;
|
||||
z-index: 999999;
|
||||
border-radius:0 0 20rpx 20rpx;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 26rpx;
|
||||
float: left;
|
||||
width: 70%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
text{
|
||||
width: calc(100% - 60rpx);
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.zan {
|
||||
width: 30%;
|
||||
float: left;
|
||||
font-size: 26rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
justify-content: flex-end;
|
||||
|
||||
.iconfont {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
bottom: 20rpx;
|
||||
text-align: right;
|
||||
z-index: 99;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-icon3 {
|
||||
color: $maincolor;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
|
@ -47,16 +47,19 @@ export default new Vuex.Store({
|
|||
bleValue: {
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
notify: "",
|
||||
write: "",
|
||||
unit: "g",
|
||||
type: 1,
|
||||
unitList: json.unitArray,
|
||||
isSendVal: false,
|
||||
oldCountWeight: 0,
|
||||
countWeight: 100,
|
||||
bleTipsText: "",
|
||||
isConnectStatus: 0,
|
||||
isBleLink: false,
|
||||
bleTipsText: "", //蓝牙提示语
|
||||
isConnectStatus: 0, //蓝牙连接状态 0搜索中,1失败,2成功
|
||||
isBluetoothTyle: false, //蓝牙状态
|
||||
// notify: "",
|
||||
// write: "",
|
||||
// unit: "g",
|
||||
// type: 1,
|
||||
// unitList: json.unitArray,
|
||||
// isSendVal: false,
|
||||
// oldCountWeight: 0,
|
||||
// countWeight: 100,
|
||||
|
||||
},
|
||||
// 计食器
|
||||
countFoodInfo: {
|
||||
|
|
@ -104,6 +107,7 @@ export default new Vuex.Store({
|
|||
MeasureLung: null,
|
||||
familayList: [],
|
||||
PublicRecord: [],
|
||||
LungLevel: [], //肺活量标准
|
||||
CardList: {
|
||||
chosen_fixed: [],
|
||||
chosen_yes: [],
|
||||
|
|
@ -114,15 +118,6 @@ export default new Vuex.Store({
|
|||
isFirst: false, //初始体重
|
||||
isRecord: false, //手动记录
|
||||
isPublicRecord: false, //公共手动记录弹框
|
||||
UseBlueConfig: {
|
||||
isBleLink: false, //是否可以点击
|
||||
BleBodyMsg: "", //body页面蓝牙状态提示
|
||||
BleConnectMsg: "", //测量页蓝牙状态提示
|
||||
serviceId: "",
|
||||
isUseConnect: false, //蓝牙是否连接
|
||||
},
|
||||
LungLevel: [], //肺活量标准
|
||||
|
||||
},
|
||||
mutations: {
|
||||
// 账户信息
|
||||
|
|
@ -209,8 +204,6 @@ export default new Vuex.Store({
|
|||
state.isPublicRecord = newData
|
||||
},
|
||||
|
||||
|
||||
|
||||
// 计时
|
||||
changeConfigInfo(state, newData) {
|
||||
state.configInfo = newData
|
||||
|
|
@ -219,18 +212,10 @@ export default new Vuex.Store({
|
|||
changeCountFoodInfo(state, newData) {
|
||||
state.countFoodInfo = newData
|
||||
},
|
||||
// 蓝牙起否连接
|
||||
getIsUseBluetooth(state, newData) {
|
||||
Object.assign(state.UseBlueConfig, newData)
|
||||
},
|
||||
// 蓝牙信息
|
||||
changeBluetoothValue(state, newData) {
|
||||
Object.assign(state.bleValue, newData)
|
||||
},
|
||||
//蓝牙状态
|
||||
changeBluetooth(state, newData) {
|
||||
state.isBluetoothTyle = newData
|
||||
},
|
||||
},
|
||||
// 模块化vuex
|
||||
modules: {},
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ import useBluetooth from '@/toolJs/Bluetooth.js'
|
|||
import $tools from '@/toolJs/tools.js'
|
||||
import $data from '@/content.json'
|
||||
// // 蓝牙连接
|
||||
let unitList = []
|
||||
let deviceId = ""
|
||||
let devicesList = []
|
||||
let searchTimer = null
|
||||
let UNIT_MAP = $data.units
|
||||
|
||||
export default {
|
||||
openBluetoothAdapter,
|
||||
startBluetoothDeviceDiscovery,
|
||||
|
|
@ -25,14 +23,15 @@ export default {
|
|||
// // 初始化蓝牙
|
||||
function openBluetoothAdapter() {
|
||||
devicesList = []
|
||||
unitList = []
|
||||
clearTimeout(searchTimer);
|
||||
uni.openBluetoothAdapter({
|
||||
success: e => {
|
||||
$store.commit("changeBluetoothValue", {
|
||||
bleTipsText: "蓝牙搜索中",
|
||||
isConnectStatus: 0,
|
||||
unitList: $data.unitMinus,
|
||||
isBleLink: false,
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
})
|
||||
startBluetoothDeviceDiscovery()
|
||||
},
|
||||
|
|
@ -40,7 +39,9 @@ function openBluetoothAdapter() {
|
|||
$store.commit("changeBluetoothValue", {
|
||||
bleTipsText: "连接超时,点击重新连接",
|
||||
isConnectStatus: 1,
|
||||
unitList: $data.unitMinus,
|
||||
isBleLink: false,
|
||||
deviceId: "",
|
||||
serviceId: "",
|
||||
})
|
||||
}
|
||||
});
|
||||
|
|
@ -94,13 +95,14 @@ function onBluetoothDeviceFound() {
|
|||
if (device.name.toLowerCase().indexOf('pc-c06pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c02pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c09pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c10pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c07pro') != -1 ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c07pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c10pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c06pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c02pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c09pro') != -1)) {
|
||||
clearTimeout(searchTimer);
|
||||
const bytes = new Uint8Array(device.advertisData);
|
||||
const macBytes = bytes.slice(6, 12);
|
||||
device.macAddr = $tools.ab2hex(macBytes, ':').toUpperCase()
|
||||
stopBluetoothDevicesDiscovery()
|
||||
Bluetoothfilter(device)
|
||||
return
|
||||
|
|
@ -113,9 +115,6 @@ function onBluetoothDeviceFound() {
|
|||
device.name.toLowerCase().indexOf('pcf01') != -1 ||
|
||||
device.name.toLowerCase().indexOf('Yihejia_Lung') != -1) {
|
||||
clearTimeout(searchTimer);
|
||||
const bytes = new Uint8Array(device.advertisData);
|
||||
const macBytes = bytes.slice(6, 12);
|
||||
device.macAddr = $tools.ab2hex(macBytes, ':').toUpperCase()
|
||||
stopBluetoothDevicesDiscovery()
|
||||
Bluetoothfilter(device)
|
||||
return
|
||||
|
|
@ -129,6 +128,7 @@ function Bluetoothfilter(device) {
|
|||
const idx = $tools.inArray(foundDevices, "deviceId", device.deviceId)
|
||||
if (idx === -1) {
|
||||
devicesList.push(device);
|
||||
deviceId = device.deviceId
|
||||
// 体脂秤
|
||||
if (device.name.toLowerCase().indexOf("pcl") != -1) {
|
||||
uni.navigateTo({
|
||||
|
|
@ -181,7 +181,14 @@ function Bluetoothfilter(device) {
|
|||
//厨房秤
|
||||
if (device.name.toLowerCase().indexOf('pc-c06pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c02pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c09pro') != -1) {
|
||||
device.name.toLowerCase().indexOf('pc-c09pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c10pro') != -1 ||
|
||||
device.name.toLowerCase().indexOf('pc-c07pro') != -1 ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c07pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c10pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c06pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c02pro') != -1) ||
|
||||
(device.localName && device.localName.toLowerCase().indexOf('pc-c09pro') != -1)) {
|
||||
handleDevType(device)
|
||||
return
|
||||
}
|
||||
|
|
@ -207,12 +214,12 @@ function handleDevType(device) {
|
|||
})
|
||||
}
|
||||
//连接设备
|
||||
function createBLEConnection(device_id) {
|
||||
function createBLEConnection(serviceId) {
|
||||
uni.createBLEConnection({
|
||||
deviceId: device_id,
|
||||
deviceId: deviceId,
|
||||
success: res => {
|
||||
setTimeout(function() {
|
||||
getBLEDeviceServices(device_id)
|
||||
getBLEDeviceServices(serviceId)
|
||||
}, 200)
|
||||
},
|
||||
fail: res => {
|
||||
|
|
@ -227,18 +234,24 @@ function createBLEConnection(device_id) {
|
|||
/**
|
||||
* 获取设备的UUID
|
||||
*/
|
||||
function getBLEDeviceServices(device_id) {
|
||||
function getBLEDeviceServices(serviceId) {
|
||||
let serviceList = [];
|
||||
uni.getBLEDeviceServices({
|
||||
deviceId: device_id,
|
||||
deviceId: deviceId,
|
||||
success: res => {
|
||||
console.log("获取设备的UUID成功", res)
|
||||
stopBluetoothDevicesDiscovery();
|
||||
serviceList = res.services;
|
||||
for (let i = 0; i < serviceList.length; i++) {
|
||||
let service = serviceList[i];
|
||||
if (service.uuid.indexOf("FFF0") != -1) {
|
||||
getBLEDeviceCharacteristics(device_id, service.uuid);
|
||||
if (service.uuid.indexOf(serviceId) != -1) {
|
||||
$store.commit("changeBluetoothValue", {
|
||||
type: 1,
|
||||
isConnectStatus: 0,
|
||||
deviceId: deviceId,
|
||||
serviceId: service.uuid,
|
||||
bleTipsText: "蓝牙链接中",
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -450,7 +463,9 @@ function onBLEConnectionStateChange() {
|
|||
closeBLEConnection()
|
||||
closeBluetoothAdapter()
|
||||
}
|
||||
$store.commit("changeBluetooth", res.connected);
|
||||
$store.commit("changeBluetoothValue", {
|
||||
isBluetoothTyle: res.connected
|
||||
});
|
||||
})
|
||||
}
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
## 1.0.7(2025-03-17)
|
||||
修复vue3 bug
|
||||
## 1.0.6(2025-01-08)
|
||||
更新文档
|
||||
## 1.0.5(2024-12-26)
|
||||
优化显示
|
||||
## 1.0.4(2024-12-26)
|
||||
优化显示
|
||||
## 1.0.3(2024-12-25)
|
||||
- 更新依赖
|
||||
## 1.0.2(2024-12-25)
|
||||
- 优化滑块相近时tip显示
|
||||
|
||||
## 1.0.1(2024-12-25)
|
||||
- 优化逻辑
|
||||
|
||||
## 1.0.0(2024-12-25)
|
||||
新增:
|
||||
- 双滑块范围选择器基础功能
|
||||
- 支持设置最小值(min)和最大值(max)
|
||||
- 支持自定义步长(step)设置
|
||||
- 支持禁用状态(disabled)
|
||||
- 自定义样式功能:
|
||||
- 滑动条背景色(backgroundColor)
|
||||
- 选中范围颜色(activeColor)
|
||||
- 滑块大小(blockSize)
|
||||
- 滑块颜色(blockColor)
|
||||
- 值格式化功能(format)
|
||||
- 支持移动端触摸操作
|
||||
- v-model双向绑定支持
|
||||
|
|
@ -0,0 +1,467 @@
|
|||
<template>
|
||||
<!-- 滑块范围选择器容器 -->
|
||||
<view class="slider-range" :class="{disabled}" :style="sliderStyle">
|
||||
<view class="slider-range-inner">
|
||||
<!-- 滑块条 -->
|
||||
<view class="slider-bar">
|
||||
<!-- 背景条 -->
|
||||
<view class="slider-bar-bg" :style="{backgroundColor}" />
|
||||
<!-- 选中区域条 -->
|
||||
<view class="slider-bar-inner" :style="barInnerStyle" />
|
||||
</view>
|
||||
|
||||
<!-- 左右两个滑块按钮 -->
|
||||
<view
|
||||
v-for="block in ['lowerBlock', 'higherBlock']"
|
||||
:key="block"
|
||||
class="slider-handle-block"
|
||||
:style="block === 'lowerBlock' ? leftHandleStyle : rightHandleStyle"
|
||||
:data-tag="block"
|
||||
@touchstart="handleDragStart"
|
||||
@touchmove="handleDragMove"
|
||||
@touchend="onBlockTouchEnd"
|
||||
@mousedown="onMouseDown"
|
||||
/>
|
||||
|
||||
<!-- 滑块值提示 -->
|
||||
<!-- <view class="range-tip" :style="leftTipStyle">{{ formatValue(selectedRange[0]) }}</view>
|
||||
<view class="range-tip" :style="rightTipStyle">{{ formatValue(selectedRange[1]) }}</view> -->
|
||||
|
||||
<!-- 刻度线 -->
|
||||
<!-- <view
|
||||
v-for="n in scaleCount + 1"
|
||||
:key="n"
|
||||
class="slider-scale"
|
||||
:style="{left: `${(n / scaleCount) * 100}%`}"
|
||||
/> -->
|
||||
<!-- 最小最大值显示 -->
|
||||
<!-- <view class="slider-value" style="left: 0">{{ min }}</view>
|
||||
<view class="slider-value" style="right: 0">{{ max }}</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import throttle from './throttle'
|
||||
// 默认刻度数量
|
||||
const DEFAULT_SCALE_COUNT = 24
|
||||
// 默认滑块大小(rpx)
|
||||
const DEFAULT_BLOCK_SIZE = 48
|
||||
|
||||
/**
|
||||
* 滑块范围选择器
|
||||
* @description 一个可以选择数值范围的滑块组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=21575
|
||||
* @property {Array} modelValue 双向绑定的值,默认[0, 100]
|
||||
* @property {Number} min 最小值,默认0
|
||||
* @property {Number} max 最大值,默认100
|
||||
* @property {Number} step 步长,默认1
|
||||
* @property {Function} format 格式化显示的值的函数
|
||||
* @property {Boolean} disabled 是否禁用,默认false
|
||||
* @property {String} backgroundColor 背景颜色,默认#F6F6F6
|
||||
* @property {String} activeColor 激活颜色,默认#4DB8F6
|
||||
* @property {Number} blockSize 滑块大小,默认48
|
||||
* @property {String} blockColor 滑块颜色,默认#fff
|
||||
* @event {Function} update:modelValue 值变化时触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'llt-slider-range',
|
||||
// 支持v-model双向绑定
|
||||
model: {
|
||||
prop: 'modelValue',
|
||||
event: 'update:modelValue'
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => [0, 100]
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
format: {
|
||||
type: Function,
|
||||
default: val => val
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#f0ae43'
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: '#3CB383'
|
||||
},
|
||||
blockSize: {
|
||||
type: Number,
|
||||
default: DEFAULT_BLOCK_SIZE
|
||||
},
|
||||
blockColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
}
|
||||
},
|
||||
|
||||
emits: ['update:modelValue', 'change'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
selectedRange: this.modelValue, // 当前选中的值
|
||||
dragStartPosition: 0, // 开始拖动时的位置
|
||||
dragStartValue: 0, // 开始拖动时的值
|
||||
activeBlock: '', // 当前拖动的滑块
|
||||
scaleCount: DEFAULT_SCALE_COUNT, // 刻度数量
|
||||
isDragging: false // 是否正在拖动
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
// 计算左侧滑块位置
|
||||
leftHandlePosition() {
|
||||
return this.calculateHandlePosition(this.selectedRange[0])
|
||||
},
|
||||
|
||||
// 计算右侧滑块位置
|
||||
rightHandlePosition() {
|
||||
return this.calculateHandlePosition(this.selectedRange[1])
|
||||
},
|
||||
|
||||
// 左侧滑块样式
|
||||
leftHandleStyle() {
|
||||
return this.generateHandleStyle('lowerBlock')
|
||||
},
|
||||
|
||||
// 右侧滑块样式
|
||||
rightHandleStyle() {
|
||||
return this.generateHandleStyle('higherBlock')
|
||||
},
|
||||
|
||||
// 左侧提示样式
|
||||
leftTipStyle() {
|
||||
return this.generateTipStyle('lowerBlock')
|
||||
},
|
||||
|
||||
// 右侧提示样式
|
||||
rightTipStyle() {
|
||||
return this.generateTipStyle('higherBlock')
|
||||
},
|
||||
|
||||
// 滑块容器样式
|
||||
sliderStyle() {
|
||||
const padding = this.blockSize / 2
|
||||
return `padding-left: ${padding}rpx;padding-right: ${padding}rpx`
|
||||
},
|
||||
|
||||
// 选中区域样式
|
||||
barInnerStyle() {
|
||||
const width = ((this.selectedRange[1] - this.selectedRange[0]) / (this.max - this.min)) * 100
|
||||
return `width: ${width}%;left: ${this.leftHandlePosition}%;background-color: ${this.activeColor}`
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
// 监听modelValue变化
|
||||
modelValue: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (!this.valuesEqual(val)) {
|
||||
this.updateValues(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 格式化显示值
|
||||
formatValue(val) {
|
||||
if (typeof this.format === 'function') {
|
||||
return this.format(val)
|
||||
}
|
||||
return val
|
||||
},
|
||||
|
||||
// 计算滑块位置百分比
|
||||
calculateHandlePosition(value) {
|
||||
return ((value - this.min) / (this.max - this.min)) * 100
|
||||
},
|
||||
|
||||
// 生成滑块样式
|
||||
generateHandleStyle(block) {
|
||||
const position = block === 'lowerBlock' ? this.leftHandlePosition : this.rightHandlePosition
|
||||
let zIndex = this.activeBlock === block ? 20 : 12
|
||||
|
||||
if ((position < 1 && block === 'lowerBlock') || (position > 99 && block === 'higherBlock')) {
|
||||
zIndex = 11
|
||||
}
|
||||
|
||||
return `background-color: ${this.blockColor};width: ${this.blockSize}rpx;height: ${this.blockSize}rpx;left: ${position}%;z-index:${zIndex}`
|
||||
},
|
||||
|
||||
// 生成提示样式
|
||||
generateTipStyle(type) {
|
||||
const position = type === 'lowerBlock' ? this.leftHandlePosition : this.rightHandlePosition
|
||||
// 计算最大显示距离,根据右侧值的字符长度乘以8得到基准距离
|
||||
const maxDistance = String(this.selectedRange[1]).length * 8
|
||||
// 计算实际距离,用最大距离减去两个滑块之间的距离
|
||||
const distance = maxDistance - (this.rightHandlePosition - this.leftHandlePosition)
|
||||
|
||||
// 如果实际距离大于0,说明两个滑块太近,需要调整提示位置避免重叠
|
||||
if (distance > 0) {
|
||||
// 根据滑块类型计算偏移量,左滑块向左偏移,右滑块向右偏移
|
||||
const diff = type === 'lowerBlock' ? -distance : distance
|
||||
return `left: calc(${position}% + ${diff}rpx)`
|
||||
}
|
||||
|
||||
return position < 90
|
||||
? `left: ${position}%`
|
||||
: `right: ${100 - position}%; transform: translate(50%, -100%)`
|
||||
},
|
||||
|
||||
// 更新选中值
|
||||
updateValues(newVal) {
|
||||
if (this.step >= this.max - this.min) {
|
||||
throw new RangeError('Invalid slider step or slider range')
|
||||
}
|
||||
|
||||
if (!this.isValidValues(newVal)) {
|
||||
this.selectedRange = []
|
||||
this.$emit('update:modelValue', [], 'update')
|
||||
this.$emit('change', [])
|
||||
return
|
||||
}
|
||||
|
||||
const newValues = this.calculateNewValues(newVal)
|
||||
if (this.valuesEqual(newValues)) return
|
||||
|
||||
this.selectedRange = this.validateValues(newValues)
|
||||
this.$emit('update:modelValue', [...this.selectedRange], 'update')
|
||||
this.$emit('change', [...this.selectedRange])
|
||||
},
|
||||
|
||||
// 计算新的值
|
||||
calculateNewValues(val) {
|
||||
return [
|
||||
Math.round((val[0] - this.min) / this.step) * this.step + this.min,
|
||||
Math.round((val[1] - this.min) / this.step) * this.step + this.min
|
||||
]
|
||||
},
|
||||
|
||||
// 验证并修正值的范围
|
||||
validateValues(values) {
|
||||
let [lower, higher] = values
|
||||
|
||||
lower = Math.max(lower, this.min)
|
||||
higher = Math.min(higher, this.max)
|
||||
|
||||
if (lower >= higher) {
|
||||
if (lower === this.selectedRange[0]) {
|
||||
higher = lower + this.step
|
||||
} else {
|
||||
lower = higher - this.step
|
||||
}
|
||||
}
|
||||
|
||||
return [lower, higher]
|
||||
},
|
||||
|
||||
// 判断两个值数组是否相等
|
||||
valuesEqual(newValues) {
|
||||
return Array.isArray(newValues) &&
|
||||
Array.isArray(this.selectedRange) &&
|
||||
newValues.length === this.selectedRange.length &&
|
||||
newValues.every((val, index) => val === this.selectedRange[index])
|
||||
},
|
||||
|
||||
// 开始拖动事件处理
|
||||
handleDragStart(event) {
|
||||
if (this.disabled) return
|
||||
|
||||
const tag = event.target.dataset.tag
|
||||
this.activeBlock = tag
|
||||
const { pageX } = event.changedTouches?.[0] || event
|
||||
this.dragStartPosition = pageX
|
||||
this.dragStartValue = tag === 'lowerBlock' ? this.selectedRange[0] : this.selectedRange[1]
|
||||
this.isDragging = true
|
||||
},
|
||||
|
||||
// 拖动移动事件处理
|
||||
handleDragMove(event) {
|
||||
if (!this.isDragging || this.disabled) return
|
||||
throttle(this.processDrag(event), 500)
|
||||
},
|
||||
|
||||
// 结束拖动事件处理
|
||||
onBlockTouchEnd() {
|
||||
this.isDragging = false
|
||||
},
|
||||
|
||||
// 拖动处理
|
||||
processDrag(event) {
|
||||
const view = uni.createSelectorQuery().in(this).select('.slider-range-inner')
|
||||
view.boundingClientRect(data => {
|
||||
const sliderWidth = data.width
|
||||
const { pageX } = event.changedTouches?.[0] || event
|
||||
const diff = ((pageX - this.dragStartPosition) / sliderWidth) * (this.max - this.min)
|
||||
const nextVal = this.dragStartValue + diff
|
||||
|
||||
const values = this.activeBlock === 'lowerBlock'
|
||||
? [nextVal, this.selectedRange[1]]
|
||||
: [this.selectedRange[0], nextVal]
|
||||
|
||||
this.updateValues(values)
|
||||
}).exec()
|
||||
},
|
||||
|
||||
// 验证值是否有效
|
||||
isValidValues(values) {
|
||||
return Array.isArray(values) && values.length === 2
|
||||
},
|
||||
|
||||
// 添加鼠标按下事件处理
|
||||
onMouseDown(event) {
|
||||
if (this.disabled) return
|
||||
|
||||
const tag = event.target.dataset.tag
|
||||
this.activeBlock = tag
|
||||
this.dragStartPosition = event.pageX
|
||||
this.dragStartValue = tag === 'lowerBlock' ? this.selectedRange[0] : this.selectedRange[1]
|
||||
this.isDragging = true
|
||||
|
||||
// 添加鼠标移动和抬起的事件监听
|
||||
document.addEventListener('mousemove', this.onMouseMove)
|
||||
document.addEventListener('mouseup', this.onMouseUp)
|
||||
},
|
||||
|
||||
// 添加鼠标移动事件处理
|
||||
onMouseMove(event) {
|
||||
if (!this.isDragging || this.disabled) return
|
||||
event.preventDefault() // 防止拖动时选中文本
|
||||
throttle(this.handleMouseDrag(event), 500)
|
||||
},
|
||||
|
||||
// 添加鼠标抬起事件处理
|
||||
onMouseUp() {
|
||||
this.isDragging = false
|
||||
// 移除事件监听
|
||||
document.removeEventListener('mousemove', this.onMouseMove)
|
||||
document.removeEventListener('mouseup', this.onMouseUp)
|
||||
},
|
||||
|
||||
// 处理鼠标拖动
|
||||
handleMouseDrag(event) {
|
||||
const view = uni.createSelectorQuery().in(this).select('.slider-range-inner')
|
||||
view.boundingClientRect(data => {
|
||||
const sliderWidth = data.width
|
||||
const diff = ((event.pageX - this.dragStartPosition) / sliderWidth) * (this.max - this.min)
|
||||
const nextVal = this.dragStartValue + diff
|
||||
|
||||
const values = this.activeBlock === 'lowerBlock'
|
||||
? [nextVal, this.selectedRange[1]]
|
||||
: [this.selectedRange[0], nextVal]
|
||||
|
||||
this.updateValues(values)
|
||||
}).exec()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.slider-range {
|
||||
position: relative;
|
||||
padding-top: 40rpx;
|
||||
|
||||
&-inner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.slider-bar-inner {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.slider-handle-block {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slider-bar {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 15rpx;
|
||||
transform: translateY(-30%);
|
||||
|
||||
&-inner,
|
||||
&-bg {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10000px;
|
||||
}
|
||||
|
||||
&-inner {
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
&-bg {
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.slider-handle-block {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0rpx 0rpx 10rpx 0rpx rgba(91, 91, 91, 0.2);
|
||||
z-index: 12;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.range-tip {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
transform: translate(-30%, -100%);
|
||||
}
|
||||
|
||||
.slider-scale {
|
||||
position: absolute;
|
||||
bottom: 30rpx;
|
||||
width: 1rpx;
|
||||
height: 14rpx;
|
||||
background: #e2e2e2;
|
||||
}
|
||||
|
||||
.slider-value {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
font-size: 21rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
let timer; let
|
||||
flag
|
||||
/**
|
||||
* 节流原理:在一定时间内,只能触发一次
|
||||
*
|
||||
* @param {Function} func 要执行的回调函数
|
||||
* @param {Number} wait 延时的时间
|
||||
* @param {Boolean} immediate 是否立即执行
|
||||
* @return null
|
||||
*/
|
||||
function throttle(func, wait = 500, immediate = true) {
|
||||
if (immediate) {
|
||||
if (!flag) {
|
||||
flag = true
|
||||
// 如果是立即执行,则在wait毫秒内开始时执行
|
||||
typeof func === 'function' && func()
|
||||
timer = setTimeout(() => {
|
||||
flag = false
|
||||
}, wait)
|
||||
}
|
||||
} else if (!flag) {
|
||||
flag = true
|
||||
// 如果是非立即执行,则在wait毫秒内的结束处执行
|
||||
timer = setTimeout(() => {
|
||||
flag = false
|
||||
typeof func === 'function' && func()
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
export default throttle
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
"id": "llt-slider-range",
|
||||
"displayName": "slider range双滑块范围选择器",
|
||||
"version": "1.0.7",
|
||||
"description": "一个功能强大的双滑块范围选择器组件,可用于价格区间、数值范围等场景的选择。支持自定义样式、步长设置,具有良好的移动端适配性和交互体验。",
|
||||
"keywords": [
|
||||
"slider",
|
||||
"range",
|
||||
"slider-range",
|
||||
"区间滑块"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.8.6"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n",
|
||||
"app-uvue": "n",
|
||||
"app-harmony": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "y",
|
||||
"快手": "y",
|
||||
"飞书": "y",
|
||||
"京东": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
# SliderRange 双滑块范围选择器
|
||||
|
||||
> 一个轻量级但功能强大的双滑块范围选择器组件,完美适配移动端和PC端,为您的项目提供直观的范围选择体验。
|
||||
|
||||
## 🌟 特性
|
||||
|
||||
- ✨ 灵活的范围设置 - 支持自定义最大最小值
|
||||
- 📏 精确的步长控制 - 可设置数值变化的最小单位
|
||||
- 🎨 丰富的样式定制 - 支持自定义滑块、轨道样式
|
||||
- 📱 完美的跨端适配 - 支持H5/App/小程序多端使用
|
||||
- 🔄 双向绑定支持 - 支持v-model语法
|
||||
- 🎯 刻度线显示 - 直观的数值参考
|
||||
- ⌨️ 键盘操作支持 - 提升无障碍体验
|
||||
- 🚫 禁用状态 - 支持只读模式
|
||||
|
||||
## 📦 安装
|
||||
|
||||
### 下载使用
|
||||
将 `llt-slider-range` 组件复制到你的项目中即可。
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### H5/App使用示例
|
||||
```vue
|
||||
<template>
|
||||
<llt-slider-range v-model="rangeValue" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
rangeValue: [30, 50] // 设置初始范围值
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 微信小程序使用示例
|
||||
```vue
|
||||
<template>
|
||||
<llt-slider-range
|
||||
:model-value="rangeValue"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
rangeValue: [30, 50]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange(val) {
|
||||
this.rangeValue = val
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 📝 API文档
|
||||
|
||||
### Props 属性
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
|--------|------|--------|------|
|
||||
| modelValue/v-model | Array | [0, 100] | 当前选中的范围值 |
|
||||
| min | Number | 0 | 最小可选值 |
|
||||
| max | Number | 100 | 最大可选值 |
|
||||
| step | Number | 1 | 步长,必须大于0 |
|
||||
| disabled | Boolean | false | 是否禁用 |
|
||||
| backgroundColor | String | '#F6F6F6' | 滑动条背景色 |
|
||||
| activeColor | String | '#4DB8F6' | 选中范围的颜色 |
|
||||
| blockSize | Number | 48 | 滑块大小(rpx) |
|
||||
| blockColor | String | '#fff' | 滑块颜色 |
|
||||
| format | Function | val => val | 数值格式化函数 |
|
||||
|
||||
### Events 事件
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|--------|------|----------|
|
||||
| update:modelValue | 值更新时触发 | (value: number[]) |
|
||||
| change | 值变化时触发 | (value: number[]) |
|
||||
|
||||
## 💡 高级用法
|
||||
|
||||
### 价格范围选择器
|
||||
```vue
|
||||
<template>
|
||||
<llt-slider-range
|
||||
v-model="priceRange"
|
||||
:min="0"
|
||||
:max="10000"
|
||||
:step="100"
|
||||
:format="formatPrice"
|
||||
active-color="#FF6B6B"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
priceRange: [1000, 5000]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatPrice(val) {
|
||||
return `¥${val}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 温度选择器
|
||||
```vue
|
||||
<template>
|
||||
<llt-slider-range
|
||||
v-model="tempRange"
|
||||
:min="-20"
|
||||
:max="40"
|
||||
:format="val => `${val}°C`"
|
||||
active-color="#2196F3"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. 确保传入的范围值在 min 和 max 之间
|
||||
2. step 值必须为正数
|
||||
3. 移动端使用时建议适当增大 blockSize 以提升触控体验
|
||||
4. 小程序端需使用 model-value + change 事件方式实现双向绑定
|
||||
5. 建议在父容器设置合适的宽度,以获得最佳显示效果
|
||||
|
||||
## 🔗 相关链接
|
||||
|
||||
- [GitHub 仓库](https://github.com/llt3677/slider-range)
|
||||
- [插件市场](https://ext.dcloud.net.cn/plugin?id=21575)
|
||||
- [问题反馈](https://github.com/llt3677/slider-range/issues)
|
||||
|
||||
## 📄 License
|
||||
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
---
|
||||
|
||||
如果这个组件对你有帮助,欢迎 star ⭐️ 支持一下!
|
||||
|
|
@ -0,0 +1,549 @@
|
|||
<template>
|
||||
<view class="calendar_all">
|
||||
<view class="date" @click="handleisCalen">
|
||||
{{startDay?startDay:startdate}}
|
||||
</view>
|
||||
<view class="wrapper Calen" v-if="isCalen">
|
||||
<view class="bg" @click='isCalen=false'>
|
||||
<view class="addfood" @click.stop>
|
||||
<!-- -->
|
||||
<view class="calendar-wrapper">
|
||||
<view class="header">
|
||||
<view class="pre" @click="changeMonth('pre')">
|
||||
<uni-icons type="back" size="20"></uni-icons>
|
||||
</view>
|
||||
<view>{{y+'年'+formatNum(m)+'月'}}</view>
|
||||
<view class="next" @click="changeMonth('next')">
|
||||
<uni-icons type="forward" size="20"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="week">
|
||||
<view class="week-day" v-for="(item, index) in weekDay" :key="index">{{ item }}</view>
|
||||
</view>
|
||||
<view :class="{ hide: !monthOpen }" class="content0" :style="{ height: height }">
|
||||
<view :style="{ top: positionTop + 'rpx' }" class="days">
|
||||
<view class="item" v-for="(item, index) in dates" :key="index">
|
||||
<view class="day" @click="selectOne(item, $event)" :class="{
|
||||
choose: choose == `${item.year}-${item.month}-${item.date}`&&item.isCurM,
|
||||
nolm: !item.isCurM,
|
||||
today: isToday(item.year, item.month, item.date),
|
||||
isWorkDay: isWorkDay(item.year, item.month, item.date)
|
||||
}">
|
||||
{{ Number(item.date) }}
|
||||
</view>
|
||||
<view class="markDay error"
|
||||
v-if="isMarkDay(item.year, item.month, item.date,'error')&&item.isCurM">
|
||||
</view>
|
||||
<view class="markDay success"
|
||||
v-if="isMarkDay(item.year, item.month, item.date,'success')&&item.isCurM">
|
||||
</view>
|
||||
<view class="markDay warning"
|
||||
v-if="isMarkDay(item.year, item.month, item.date,'warning')&&item.isCurM">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="level">
|
||||
<view><text></text>超标</view>
|
||||
<view><text></text>达标</view>
|
||||
<view><text></text>未达标</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ren-calendar',
|
||||
props: {
|
||||
// 星期几为第一天(0为星期日)
|
||||
weekstart: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 标记的日期
|
||||
// markDays: {
|
||||
// type: Array,
|
||||
// default: () => {
|
||||
// return [];
|
||||
// }
|
||||
// },
|
||||
markDays: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
//是否展示月份切换按钮
|
||||
headerBar: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否展开
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//是否可收缩
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//未来日期是否不可点击
|
||||
disabledAfter: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 初始日期
|
||||
startDay: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
weektext: ['日', '一', '二', '三', '四', '五', '六'],
|
||||
y: new Date().getFullYear(), // 年
|
||||
m: new Date().getMonth() + 1, // 月
|
||||
dates: [], // 当前月的日期数据
|
||||
positionTop: 0,
|
||||
monthOpen: true,
|
||||
choose: '',
|
||||
month: null,
|
||||
isCalen: false,
|
||||
startdate: ""
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.startdate = this.$tools.getDate("start")
|
||||
this.dates = this.monthDay(this.y, this.m);
|
||||
!this.open && this.toggle();
|
||||
},
|
||||
mounted() {
|
||||
this.y = new Date().getFullYear()
|
||||
this.m = new Date().getMonth() + 1
|
||||
this.month = this.$tools.getMonth(this.$tools.getTime(), 0)
|
||||
this.choose = this.getToday().date;
|
||||
},
|
||||
computed: {
|
||||
// 顶部星期栏
|
||||
weekDay() {
|
||||
return this.weektext.slice(this.weekstart).concat(this.weektext.slice(0, this.weekstart));
|
||||
},
|
||||
height() {
|
||||
return (this.dates.length / 7) * 80 + 'rpx';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleisCalen() {
|
||||
console.log("店家")
|
||||
this.isCalen = !this.isCalen
|
||||
},
|
||||
formatNum(num) {
|
||||
let res = Number(num);
|
||||
return res < 10 ? '0' + res : res;
|
||||
},
|
||||
getToday() {
|
||||
let date = new Date();
|
||||
let y = date.getFullYear();
|
||||
let m = date.getMonth();
|
||||
let d = date.getDate();
|
||||
let week = new Date().getDay();
|
||||
let weekText = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
let formatWeek = '星期' + weekText[week];
|
||||
let today = {
|
||||
date: y + '-' + this.formatNum(m + 1) + '-' + this.formatNum(d),
|
||||
week: formatWeek
|
||||
};
|
||||
return today;
|
||||
},
|
||||
// 获取当前月份数据
|
||||
monthDay(y, month) {
|
||||
let dates = [];
|
||||
let m = Number(month);
|
||||
let firstDayOfMonth = new Date(y, m - 1, 1).getDay(); // 当月第一天星期几
|
||||
let lastDateOfMonth = new Date(y, m, 0).getDate(); // 当月最后一天
|
||||
let lastDayOfLastMonth = new Date(y, m - 1, 0).getDate(); // 上一月的最后一天
|
||||
let weekstart = this.weekstart == 7 ? 0 : this.weekstart;
|
||||
let startDay = (() => {
|
||||
// 周初有几天是上个月的
|
||||
if (firstDayOfMonth == weekstart) {
|
||||
return 0;
|
||||
} else if (firstDayOfMonth > weekstart) {
|
||||
return firstDayOfMonth - weekstart;
|
||||
} else {
|
||||
return 7 - weekstart + firstDayOfMonth;
|
||||
}
|
||||
})();
|
||||
let endDay = 7 - ((startDay + lastDateOfMonth) % 7); // 结束还有几天是下个月的
|
||||
if (endDay == 7) {
|
||||
endDay = 0;
|
||||
}
|
||||
for (let i = 1; i <= startDay; i++) {
|
||||
dates.push({
|
||||
date: this.formatNum(lastDayOfLastMonth - startDay + i),
|
||||
day: weekstart + i - 1 || 7,
|
||||
month: m - 1 >= 0 ? this.formatNum(m - 1) : 12,
|
||||
year: m - 1 >= 0 ? y : y - 1
|
||||
});
|
||||
}
|
||||
for (let j = 1; j <= lastDateOfMonth; j++) {
|
||||
dates.push({
|
||||
date: this.formatNum(j),
|
||||
day: (j % 7) + firstDayOfMonth - 1 || 7,
|
||||
month: this.formatNum(m),
|
||||
year: y,
|
||||
isCurM: true //是否当前月份
|
||||
});
|
||||
}
|
||||
for (let k = 1; k <= endDay; k++) {
|
||||
dates.push({
|
||||
date: this.formatNum(k),
|
||||
day: (lastDateOfMonth + startDay + weekstart + k - 1) % 7 || 7,
|
||||
month: m + 1 <= 11 ? this.formatNum(m + 1) : 0,
|
||||
year: m + 1 <= 11 ? y : y + 1
|
||||
});
|
||||
}
|
||||
return dates;
|
||||
},
|
||||
isWorkDay(y, m, d) {
|
||||
//是否工作日
|
||||
let ymd = `${y}-${m}-${d}`;
|
||||
let formatDY = new Date(ymd.replace(/-/g, '/'));
|
||||
let week = formatDY.getDay();
|
||||
if (week == 0 || week == 6) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
isFutureDay(y, m, d) {
|
||||
//是否未来日期
|
||||
let ymd = `${y}-${m}-${d}`;
|
||||
let formatDY = new Date(ymd.replace(/-/g, '/'));
|
||||
let showTime = formatDY.getTime();
|
||||
let curTime = new Date().getTime();
|
||||
if (showTime > curTime) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
// 标记日期
|
||||
isMarkDay(y, m, d, type) {
|
||||
let that = this
|
||||
let flag = false;
|
||||
let markDays = that.markDays[type]
|
||||
for (let i = 0; i < markDays.length; i++) {
|
||||
let dy = `${y}-${m}-${d}`;
|
||||
if (markDays[i] == dy) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// console.log("isMarkDay", this.markDays, type, markDays)
|
||||
return flag;
|
||||
},
|
||||
isToday(y, m, d) {
|
||||
let checkD = y + '-' + m + '-' + d;
|
||||
let today = this.getToday().date;
|
||||
if (checkD == today) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
// 展开收起
|
||||
toggle() {
|
||||
this.monthOpen = !this.monthOpen;
|
||||
if (this.monthOpen) {
|
||||
this.positionTop = 0;
|
||||
} else {
|
||||
let index = -1;
|
||||
this.dates.forEach((i, x) => {
|
||||
this.isToday(i.year, i.month, i.date) && (index = x);
|
||||
});
|
||||
this.positionTop = -((Math.ceil((index + 1) / 7) || 1) - 1) * 80;
|
||||
}
|
||||
},
|
||||
// 点击回调
|
||||
selectOne(i, event) {
|
||||
let date = `${i.year}-${i.month}-${i.date}`;
|
||||
let selectD = new Date(date).getTime();
|
||||
let curTime = new Date().getTime();
|
||||
let week = new Date(date).getDay();
|
||||
let weekText = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
let formatWeek = '星期' + weekText[week];
|
||||
let response = {
|
||||
date: date,
|
||||
week: formatWeek
|
||||
};
|
||||
if (!i.isCurM) {
|
||||
// console.log('不在当前月范围内');
|
||||
return false;
|
||||
}
|
||||
if (selectD > curTime) {
|
||||
if (this.disabledAfter) {
|
||||
console.log('未来日期不可选');
|
||||
return false;
|
||||
} else {
|
||||
this.choose = date;
|
||||
this.$emit('maskClick', response);
|
||||
}
|
||||
} else {
|
||||
this.choose = date;
|
||||
this.$emit('maskClick', response);
|
||||
}
|
||||
this.startdate = response.date
|
||||
this.isCalen = false
|
||||
},
|
||||
//改变年月
|
||||
changYearMonth(y, m) {
|
||||
this.dates = this.monthDay(y, m);
|
||||
this.y = y;
|
||||
this.m = m;
|
||||
},
|
||||
changeMonth(type) {
|
||||
let that = this
|
||||
// if (!uni.getStorageSync('token')) {
|
||||
// this.$store.commit("changeUserLogin", true);
|
||||
// return
|
||||
// }
|
||||
console.log("type", type)
|
||||
if (type == 'pre') {
|
||||
if (that.m + 1 == 2) {
|
||||
that.m = 12;
|
||||
that.y = that.y - 1;
|
||||
} else {
|
||||
that.m = that.m - 1;
|
||||
}
|
||||
that.month = this.$tools.getMonth(that.month, -1)
|
||||
that.$emit('onMonthClickPre', that.month)
|
||||
} else {
|
||||
|
||||
if (this.m + 1 == 13) {
|
||||
this.m = 1;
|
||||
this.y = this.y + 1;
|
||||
} else {
|
||||
this.m = this.m + 1;
|
||||
}
|
||||
that.month = this.$tools.getMonth(that.month, +1)
|
||||
that.$emit('onMonthClickPre', that.month)
|
||||
}
|
||||
this.dates = this.monthDay(this.y, this.m);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.date {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.Calen {
|
||||
top: 50px;
|
||||
|
||||
.bg {
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
.addfood {
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-wrapper {
|
||||
color: #bbb7b7;
|
||||
// border-radius: 10px;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
padding-bottom: 10rpx;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 88rpx;
|
||||
color: #42464A;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
justify-content: space-around;
|
||||
|
||||
.pre,
|
||||
.next {
|
||||
color: $maincolor;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.week {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.2);
|
||||
|
||||
view {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.content0 {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: height 0.4s ease;
|
||||
|
||||
.days {
|
||||
transition: top 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
width: calc(100% / 7);
|
||||
|
||||
.day {
|
||||
font-style: normal;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 60rpx;
|
||||
|
||||
&.choose {
|
||||
background-color: $maincolor;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.nolm {
|
||||
color: #fff;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
.isWorkDay {
|
||||
color: #42464a;
|
||||
}
|
||||
|
||||
.notSigned {
|
||||
font-style: normal;
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
background: #fa7268;
|
||||
border-radius: 10rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.today {
|
||||
color: #fff;
|
||||
background-color: #a8c0ff;
|
||||
}
|
||||
|
||||
.workDay {
|
||||
font-style: normal;
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
background: #4d7df9;
|
||||
border-radius: 10rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.markDay {
|
||||
font-style: normal;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #fa7268;
|
||||
border-radius: 10rpx;
|
||||
position: absolute;
|
||||
left: 42%;
|
||||
bottom: -8px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: $uni-color-success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hide {
|
||||
height: 70rpx !important;
|
||||
}
|
||||
|
||||
.weektoggle {
|
||||
width: 85rpx;
|
||||
height: 32rpx;
|
||||
position: relative;
|
||||
bottom: -42rpx;
|
||||
|
||||
&.down {
|
||||
transform: rotate(180deg);
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
.level {
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
margin-top: -20px;
|
||||
|
||||
view {
|
||||
width: 25%;
|
||||
text-align: left;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
|
||||
|
||||
text {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: red;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
:nth-child(2) text {
|
||||
background: $uni-color-success
|
||||
}
|
||||
|
||||
:nth-child(3) text {
|
||||
background: $uni-color-warning
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
## 1.2.1(2021-11-22)
|
||||
- 修复 vue3中个别scss变量无法找到的问题
|
||||
## 1.2.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-drawer](https://uniapp.dcloud.io/component/uniui/uni-drawer)
|
||||
## 1.1.1(2021-07-30)
|
||||
- 优化 vue3下事件警告的问题
|
||||
## 1.1.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.0.7(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.0.6(2021-02-04)
|
||||
- 调整为uni_modules目录规范
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// document.removeEventListener('keyup', listener)
|
||||
// })
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
<template>
|
||||
<view :style="{'display':visibleSync?'block':'none'}" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear">
|
||||
<view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" />
|
||||
<view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}">
|
||||
<slot />
|
||||
</view>
|
||||
<!-- #ifdef H5 -->
|
||||
<keypress @esc="close('mask')" />
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef H5
|
||||
import keypress from './keypress.js'
|
||||
// #endif
|
||||
/**
|
||||
* Drawer 抽屉
|
||||
* @description 抽屉侧滑菜单
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=26
|
||||
* @property {Boolean} mask = [true | false] 是否显示遮罩
|
||||
* @property {Boolean} maskClick = [true | false] 点击遮罩是否关闭
|
||||
* @property {Boolean} mode = [left | right] Drawer 滑出位置
|
||||
* @value left 从左侧滑出
|
||||
* @value right 从右侧侧滑出
|
||||
* @property {Number} width 抽屉的宽度 ,仅 vue 页面生效
|
||||
* @event {Function} close 组件关闭时触发事件
|
||||
*/
|
||||
export default {
|
||||
name: 'UniDrawer',
|
||||
components: {
|
||||
// #ifdef H5
|
||||
keypress
|
||||
// #endif
|
||||
},
|
||||
emits:['change'],
|
||||
props: {
|
||||
/**
|
||||
* 显示模式(左、右),只在初始化生效
|
||||
*/
|
||||
mode: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 蒙层显示状态
|
||||
*/
|
||||
mask: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 遮罩是否可点击关闭
|
||||
*/
|
||||
maskClick:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 抽屉宽度
|
||||
*/
|
||||
width: {
|
||||
type: Number,
|
||||
default: 220
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibleSync: false,
|
||||
showDrawer: false,
|
||||
rightMode: false,
|
||||
watchTimer: null,
|
||||
drawerWidth: 220
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// #ifndef APP-NVUE
|
||||
this.drawerWidth = this.width
|
||||
// #endif
|
||||
this.rightMode = this.mode === 'right'
|
||||
},
|
||||
methods: {
|
||||
clear(){},
|
||||
close(type) {
|
||||
// fixed by mehaotian 抽屉尚未完全关闭或遮罩禁止点击时不触发以下逻辑
|
||||
if((type === 'mask' && !this.maskClick) || !this.visibleSync) return
|
||||
this._change('showDrawer', 'visibleSync', false)
|
||||
},
|
||||
open() {
|
||||
// fixed by mehaotian 处理重复点击打开的事件
|
||||
if(this.visibleSync) return
|
||||
this._change('visibleSync', 'showDrawer', true)
|
||||
},
|
||||
_change(param1, param2, status) {
|
||||
this[param1] = status
|
||||
if (this.watchTimer) {
|
||||
clearTimeout(this.watchTimer)
|
||||
}
|
||||
this.watchTimer = setTimeout(() => {
|
||||
this[param2] = status
|
||||
this.$emit('change',status)
|
||||
}, status ? 50 : 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$uni-mask: rgba($color: #000000, $alpha: 0.4) ;
|
||||
// 抽屉宽度
|
||||
$drawer-width: 220px;
|
||||
|
||||
.uni-drawer {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.uni-drawer__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: $drawer-width;
|
||||
bottom: 0;
|
||||
background-color: $uni-bg-color;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.uni-drawer--left {
|
||||
left: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
transform: translateX(-$drawer-width);
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
transform: translateX(-100%);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-drawer--right {
|
||||
right: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
transform: translateX($drawer-width);
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
transform: translateX(100%);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-drawer__content--visible {
|
||||
transform: translateX(0px);
|
||||
}
|
||||
|
||||
|
||||
.uni-drawer__mask {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: $uni-mask;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.uni-drawer__mask--visible {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"id": "uni-drawer",
|
||||
"displayName": "uni-drawer 抽屉",
|
||||
"version": "1.2.1",
|
||||
"description": "抽屉式导航,用于展示侧滑菜单,侧滑导航。",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"drawer",
|
||||
"抽屉",
|
||||
"侧滑导航"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
|
||||
## Drawer 抽屉
|
||||
> **组件名:uni-drawer**
|
||||
> 代码块: `uDrawer`
|
||||
|
||||
抽屉侧滑菜单。
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-drawer)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
## 1.0.4(2023-03-29)
|
||||
- 修复 手动上传删除一个文件后不能再上传的bug
|
||||
## 1.0.3(2022-12-19)
|
||||
- 新增 sourceType 属性, 可以自定义图片和视频选择的来源
|
||||
## 1.0.2(2022-07-04)
|
||||
- 修复 在uni-forms下样式不生效的bug
|
||||
## 1.0.1(2021-11-23)
|
||||
- 修复 参数为对象的情况下,url在某些情况显示错误的bug
|
||||
## 1.0.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
|
||||
## 0.2.16(2021-11-08)
|
||||
- 修复 传入空对象 ,显示错误的Bug
|
||||
## 0.2.15(2021-08-30)
|
||||
- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug
|
||||
## 0.2.14(2021-08-23)
|
||||
- 新增 参数中返回 fileID 字段
|
||||
## 0.2.13(2021-08-23)
|
||||
- 修复 腾讯云传入fileID 不能回显的bug
|
||||
- 修复 选择图片后,不能放大的问题
|
||||
## 0.2.12(2021-08-17)
|
||||
- 修复 由于 0.2.11 版本引起的不能回显图片的Bug
|
||||
## 0.2.11(2021-08-16)
|
||||
- 新增 clearFiles(index) 方法,可以手动删除指定文件
|
||||
- 修复 v-model 值设为 null 报错的Bug
|
||||
## 0.2.10(2021-08-13)
|
||||
- 修复 return-type="object" 时,无法删除文件的Bug
|
||||
## 0.2.9(2021-08-03)
|
||||
- 修复 auto-upload 属性失效的Bug
|
||||
## 0.2.8(2021-07-31)
|
||||
- 修复 fileExtname属性不指定值报错的Bug
|
||||
## 0.2.7(2021-07-31)
|
||||
- 修复 在某种场景下图片不回显的Bug
|
||||
## 0.2.6(2021-07-30)
|
||||
- 修复 return-type为object下,返回值不正确的Bug
|
||||
## 0.2.5(2021-07-30)
|
||||
- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题
|
||||
## 0.2.3(2021-07-28)
|
||||
- 优化 调整示例代码
|
||||
## 0.2.2(2021-07-27)
|
||||
- 修复 vue3 下赋值错误的Bug
|
||||
- 优化 h5平台下上传文件导致页面卡死的问题
|
||||
## 0.2.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 0.1.1(2021-07-02)
|
||||
- 修复 sourceType 缺少默认值导致 ios 无法选择文件
|
||||
## 0.1.0(2021-06-30)
|
||||
- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改
|
||||
## 0.0.11(2021-06-30)
|
||||
- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题
|
||||
## 0.0.10(2021-06-29)
|
||||
- 优化 文件上传后进度条消失时机
|
||||
## 0.0.9(2021-06-29)
|
||||
- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug
|
||||
## 0.0.8(2021-06-15)
|
||||
- 修复 删除文件时无法触发 v-model 的Bug
|
||||
## 0.0.7(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 0.0.6(2021-04-09)
|
||||
- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug
|
||||
## 0.0.5(2021-04-09)
|
||||
- 优化 更新组件示例
|
||||
## 0.0.4(2021-04-09)
|
||||
- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔
|
||||
## 0.0.3(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
'use strict';
|
||||
|
||||
const ERR_MSG_OK = 'chooseAndUploadFile:ok';
|
||||
const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
|
||||
|
||||
function chooseImage(opts) {
|
||||
const {
|
||||
count,
|
||||
sizeType = ['original', 'compressed'],
|
||||
sourceType,
|
||||
extension
|
||||
} = opts
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseImage({
|
||||
count,
|
||||
sizeType,
|
||||
sourceType,
|
||||
extension,
|
||||
success(res) {
|
||||
resolve(normalizeChooseAndUploadFileRes(res, 'image'));
|
||||
},
|
||||
fail(res) {
|
||||
reject({
|
||||
errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function chooseVideo(opts) {
|
||||
const {
|
||||
camera,
|
||||
compressed,
|
||||
maxDuration,
|
||||
sourceType,
|
||||
extension
|
||||
} = opts;
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseVideo({
|
||||
camera,
|
||||
compressed,
|
||||
maxDuration,
|
||||
sourceType,
|
||||
extension,
|
||||
success(res) {
|
||||
const {
|
||||
tempFilePath,
|
||||
duration,
|
||||
size,
|
||||
height,
|
||||
width
|
||||
} = res;
|
||||
resolve(normalizeChooseAndUploadFileRes({
|
||||
errMsg: 'chooseVideo:ok',
|
||||
tempFilePaths: [tempFilePath],
|
||||
tempFiles: [
|
||||
{
|
||||
name: (res.tempFile && res.tempFile.name) || '',
|
||||
path: tempFilePath,
|
||||
size,
|
||||
type: (res.tempFile && res.tempFile.type) || '',
|
||||
width,
|
||||
height,
|
||||
duration,
|
||||
fileType: 'video',
|
||||
cloudPath: '',
|
||||
}, ],
|
||||
}, 'video'));
|
||||
},
|
||||
fail(res) {
|
||||
reject({
|
||||
errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function chooseAll(opts) {
|
||||
const {
|
||||
count,
|
||||
extension
|
||||
} = opts;
|
||||
return new Promise((resolve, reject) => {
|
||||
let chooseFile = uni.chooseFile;
|
||||
if (typeof wx !== 'undefined' &&
|
||||
typeof wx.chooseMessageFile === 'function') {
|
||||
chooseFile = wx.chooseMessageFile;
|
||||
}
|
||||
if (typeof chooseFile !== 'function') {
|
||||
return reject({
|
||||
errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
|
||||
});
|
||||
}
|
||||
chooseFile({
|
||||
type: 'all',
|
||||
count,
|
||||
extension,
|
||||
success(res) {
|
||||
resolve(normalizeChooseAndUploadFileRes(res));
|
||||
},
|
||||
fail(res) {
|
||||
reject({
|
||||
errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeChooseAndUploadFileRes(res, fileType) {
|
||||
res.tempFiles.forEach((item, index) => {
|
||||
if (!item.name) {
|
||||
item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
|
||||
}
|
||||
if (fileType) {
|
||||
item.fileType = fileType;
|
||||
}
|
||||
item.cloudPath =
|
||||
Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
|
||||
});
|
||||
if (!res.tempFilePaths) {
|
||||
res.tempFilePaths = res.tempFiles.map((file) => file.path);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function uploadCloudFiles(files, max = 5, onUploadProgress) {
|
||||
files = JSON.parse(JSON.stringify(files))
|
||||
const len = files.length
|
||||
let count = 0
|
||||
let self = this
|
||||
return new Promise(resolve => {
|
||||
while (count < max) {
|
||||
next()
|
||||
}
|
||||
|
||||
function next() {
|
||||
let cur = count++
|
||||
if (cur >= len) {
|
||||
!files.find(item => !item.url && !item.errMsg) && resolve(files)
|
||||
return
|
||||
}
|
||||
const fileItem = files[cur]
|
||||
const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
|
||||
fileItem.url = ''
|
||||
delete fileItem.errMsg
|
||||
|
||||
uniCloud
|
||||
.uploadFile({
|
||||
filePath: fileItem.path,
|
||||
cloudPath: fileItem.cloudPath,
|
||||
fileType: fileItem.fileType,
|
||||
onUploadProgress: res => {
|
||||
res.index = index
|
||||
onUploadProgress && onUploadProgress(res)
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
fileItem.url = res.fileID
|
||||
fileItem.index = index
|
||||
if (cur < len) {
|
||||
next()
|
||||
}
|
||||
})
|
||||
.catch(res => {
|
||||
fileItem.errMsg = res.errMsg || res.message
|
||||
fileItem.index = index
|
||||
if (cur < len) {
|
||||
next()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function uploadFiles(choosePromise, {
|
||||
onChooseFile,
|
||||
onUploadProgress
|
||||
}) {
|
||||
return choosePromise
|
||||
.then((res) => {
|
||||
if (onChooseFile) {
|
||||
const customChooseRes = onChooseFile(res);
|
||||
if (typeof customChooseRes !== 'undefined') {
|
||||
return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
|
||||
res : chooseRes);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
})
|
||||
.then((res) => {
|
||||
if (res === false) {
|
||||
return {
|
||||
errMsg: ERR_MSG_OK,
|
||||
tempFilePaths: [],
|
||||
tempFiles: [],
|
||||
};
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
function chooseAndUploadFile(opts = {
|
||||
type: 'all'
|
||||
}) {
|
||||
if (opts.type === 'image') {
|
||||
return uploadFiles(chooseImage(opts), opts);
|
||||
}
|
||||
else if (opts.type === 'video') {
|
||||
return uploadFiles(chooseVideo(opts), opts);
|
||||
}
|
||||
return uploadFiles(chooseAll(opts), opts);
|
||||
}
|
||||
|
||||
export {
|
||||
chooseAndUploadFile,
|
||||
uploadCloudFiles
|
||||
};
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
<template>
|
||||
<view class="uni-file-picker">
|
||||
<view v-if="title" class="uni-file-picker__header">
|
||||
<text class="file-title">{{ title }}</text>
|
||||
<text class="file-count">{{ filesList.length }}/{{ limitLength }}</text>
|
||||
</view>
|
||||
<upload-image v-if="fileMediatype === 'image' && showType === 'grid'" :readonly="readonly"
|
||||
:image-styles="imageStyles" :files-list="filesList" :limit="limitLength" :disablePreview="disablePreview"
|
||||
:delIcon="delIcon" @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
|
||||
<slot>
|
||||
<view class="is-add">
|
||||
<view class="icon-add"></view>
|
||||
<view class="icon-add rotate"></view>
|
||||
</view>
|
||||
</slot>
|
||||
</upload-image>
|
||||
<upload-file v-if="fileMediatype !== 'image' || showType !== 'grid'" :readonly="readonly"
|
||||
:list-styles="listStyles" :files-list="filesList" :showType="showType" :delIcon="delIcon"
|
||||
@uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
|
||||
<slot><button type="primary" size="mini">选择文件</button></slot>
|
||||
</upload-file>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
chooseAndUploadFile,
|
||||
uploadCloudFiles
|
||||
} from './choose-and-upload-file.js'
|
||||
import {
|
||||
get_file_ext,
|
||||
get_extname,
|
||||
get_files_and_is_max,
|
||||
get_file_info,
|
||||
get_file_data
|
||||
} from './utils.js'
|
||||
import uploadImage from './upload-image.vue'
|
||||
import uploadFile from './upload-file.vue'
|
||||
let fileInput = null
|
||||
/**
|
||||
* FilePicker 文件选择上传
|
||||
* @description 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=4079
|
||||
* @property {Object|Array} value 组件数据,通常用来回显 ,类型由return-type属性决定
|
||||
* @property {Boolean} disabled = [true|false] 组件禁用
|
||||
* @value true 禁用
|
||||
* @value false 取消禁用
|
||||
* @property {Boolean} readonly = [true|false] 组件只读,不可选择,不显示进度,不显示删除按钮
|
||||
* @value true 只读
|
||||
* @value false 取消只读
|
||||
* @property {String} return-type = [array|object] 限制 value 格式,当为 object 时 ,组件只能单选,且会覆盖
|
||||
* @value array 规定 value 属性的类型为数组
|
||||
* @value object 规定 value 属性的类型为对象
|
||||
* @property {Boolean} disable-preview = [true|false] 禁用图片预览,仅 mode:grid 时生效
|
||||
* @value true 禁用图片预览
|
||||
* @value false 取消禁用图片预览
|
||||
* @property {Boolean} del-icon = [true|false] 是否显示删除按钮
|
||||
* @value true 显示删除按钮
|
||||
* @value false 不显示删除按钮
|
||||
* @property {Boolean} auto-upload = [true|false] 是否自动上传,值为true则只触发@select,可自行上传
|
||||
* @value true 自动上传
|
||||
* @value false 取消自动上传
|
||||
* @property {Number|String} limit 最大选择个数 ,h5 会自动忽略多选的部分
|
||||
* @property {String} title 组件标题,右侧显示上传计数
|
||||
* @property {String} mode = [list|grid] 选择文件后的文件列表样式
|
||||
* @value list 列表显示
|
||||
* @value grid 宫格显示
|
||||
* @property {String} file-mediatype = [image|video|all] 选择文件类型
|
||||
* @value image 只选择图片
|
||||
* @value video 只选择视频
|
||||
* @value all 选择所有文件
|
||||
* @property {Array} file-extname 选择文件后缀,根据 file-mediatype 属性而不同
|
||||
* @property {Object} list-style mode:list 时的样式
|
||||
* @property {Object} image-styles 选择文件后缀,根据 file-mediatype 属性而不同
|
||||
* @event {Function} select 选择文件后触发
|
||||
* @event {Function} progress 文件上传时触发
|
||||
* @event {Function} success 上传成功触发
|
||||
* @event {Function} fail 上传失败触发
|
||||
* @event {Function} delete 文件从列表移除时触发
|
||||
*/
|
||||
export default {
|
||||
name: 'uniFilePicker',
|
||||
components: {
|
||||
uploadImage,
|
||||
uploadFile
|
||||
},
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
emits: ['select', 'success', 'fail', 'progress', 'delete', 'update:modelValue', 'input'],
|
||||
props: {
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
type: [Array, Object],
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
|
||||
// #ifndef VUE3
|
||||
value: {
|
||||
type: [Array, Object],
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disablePreview: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
delIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 自动上传
|
||||
autoUpload: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 步骤序列号
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 最大选择个数 ,h5只能限制单选或是多选
|
||||
limit: {
|
||||
type: [Number, String],
|
||||
default: 9
|
||||
},
|
||||
// 列表样式 grid | list | list-card
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'grid'
|
||||
},
|
||||
// 选择文件类型 image/video/all
|
||||
fileMediatype: {
|
||||
type: String,
|
||||
default: 'image'
|
||||
},
|
||||
// 文件类型筛选
|
||||
fileExtname: {
|
||||
type: [Array, String],
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
listStyles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
// 是否显示边框
|
||||
border: false,
|
||||
// 是否显示分隔线
|
||||
dividline: false,
|
||||
// 线条样式
|
||||
borderStyle: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
imageStyles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
width: 'auto',
|
||||
height: 'auto'
|
||||
}
|
||||
}
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
returnType: {
|
||||
type: String,
|
||||
default: 'array'
|
||||
},
|
||||
sizeType: {
|
||||
type: Array,
|
||||
default () {
|
||||
return ['original', 'compressed']
|
||||
}
|
||||
},
|
||||
sourceType: {
|
||||
type: Array,
|
||||
default () {
|
||||
return ['album', 'camera']
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
files: [],
|
||||
localValue: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// #ifndef VUE3
|
||||
value: {
|
||||
handler(newVal, oldVal) {
|
||||
this.setValue(newVal, oldVal)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
handler(newVal, oldVal) {
|
||||
this.setValue(newVal, oldVal)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
filesList() {
|
||||
let files = []
|
||||
this.files.forEach(v => {
|
||||
files.push(v)
|
||||
})
|
||||
return files
|
||||
},
|
||||
showType() {
|
||||
if (this.fileMediatype === 'image') {
|
||||
return this.mode
|
||||
}
|
||||
return 'list'
|
||||
},
|
||||
limitLength() {
|
||||
if (this.returnType === 'object') {
|
||||
return 1
|
||||
}
|
||||
if (!this.limit) {
|
||||
return 1
|
||||
}
|
||||
if (this.limit >= 9) {
|
||||
return 9
|
||||
}
|
||||
return this.limit
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// TODO 兼容不开通服务空间的情况
|
||||
if (!(uniCloud.config && uniCloud.config.provider)) {
|
||||
this.noSpace = true
|
||||
uniCloud.chooseAndUploadFile = chooseAndUploadFile
|
||||
}
|
||||
this.form = this.getForm('uniForms')
|
||||
this.formItem = this.getForm('uniFormsItem')
|
||||
if (this.form && this.formItem) {
|
||||
if (this.formItem.name) {
|
||||
this.rename = this.formItem.name
|
||||
this.form.inputChildrens.push(this)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 公开用户使用,清空文件
|
||||
* @param {Object} index
|
||||
*/
|
||||
clearFiles(index) {
|
||||
if (index !== 0 && !index) {
|
||||
this.files = []
|
||||
this.$nextTick(() => {
|
||||
this.setEmit()
|
||||
})
|
||||
} else {
|
||||
this.files.splice(index, 1)
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.setEmit()
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 公开用户使用,继续上传
|
||||
*/
|
||||
upload() {
|
||||
let files = []
|
||||
this.files.forEach((v, index) => {
|
||||
if (v.status === 'ready' || v.status === 'error') {
|
||||
files.push(Object.assign({}, v))
|
||||
}
|
||||
})
|
||||
return this.uploadFiles(files)
|
||||
},
|
||||
async setValue(newVal, oldVal) {
|
||||
const newData = async (v) => {
|
||||
const reg = /cloud:\/\/([\w.]+\/?)\S*/
|
||||
let url = ''
|
||||
if (v.fileID) {
|
||||
url = v.fileID
|
||||
} else {
|
||||
url = v.url
|
||||
}
|
||||
if (reg.test(url)) {
|
||||
v.fileID = url
|
||||
v.url = await this.getTempFileURL(url)
|
||||
}
|
||||
if (v.url) v.path = v.url
|
||||
return v
|
||||
}
|
||||
if (this.returnType === 'object') {
|
||||
if (newVal) {
|
||||
await newData(newVal)
|
||||
} else {
|
||||
newVal = {}
|
||||
}
|
||||
} else {
|
||||
if (!newVal) newVal = []
|
||||
for (let i = 0; i < newVal.length; i++) {
|
||||
let v = newVal[i]
|
||||
await newData(v)
|
||||
}
|
||||
}
|
||||
this.localValue = newVal
|
||||
if (this.form && this.formItem && !this.is_reset) {
|
||||
this.is_reset = false
|
||||
this.formItem.setValue(this.localValue)
|
||||
}
|
||||
let filesData = Object.keys(newVal).length > 0 ? newVal : [];
|
||||
this.files = [].concat(filesData)
|
||||
},
|
||||
|
||||
/**
|
||||
* 选择文件
|
||||
*/
|
||||
choose() {
|
||||
|
||||
if (this.disabled) return
|
||||
if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType ===
|
||||
'array') {
|
||||
uni.showToast({
|
||||
title: `您最多选择 ${this.limitLength} 个文件`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.chooseFiles()
|
||||
},
|
||||
|
||||
/**
|
||||
* 选择文件并上传
|
||||
*/
|
||||
chooseFiles() {
|
||||
const _extname = get_extname(this.fileExtname)
|
||||
// 获取后缀
|
||||
uniCloud
|
||||
.chooseAndUploadFile({
|
||||
type: this.fileMediatype,
|
||||
compressed: false,
|
||||
sizeType: this.sizeType,
|
||||
sourceType: this.sourceType,
|
||||
// TODO 如果为空,video 有问题
|
||||
extension: _extname.length > 0 ? _extname : undefined,
|
||||
count: this.limitLength - this.files.length, //默认9
|
||||
onChooseFile: this.chooseFileCallback,
|
||||
onUploadProgress: progressEvent => {
|
||||
this.setProgress(progressEvent, progressEvent.index)
|
||||
}
|
||||
})
|
||||
.then(result => {
|
||||
this.setSuccessAndError(result.tempFiles)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('选择失败', err)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 选择文件回调
|
||||
* @param {Object} res
|
||||
*/
|
||||
async chooseFileCallback(res) {
|
||||
const _extname = get_extname(this.fileExtname)
|
||||
const is_one = (Number(this.limitLength) === 1 &&
|
||||
this.disablePreview &&
|
||||
!this.disabled) ||
|
||||
this.returnType === 'object'
|
||||
// 如果这有一个文件 ,需要清空本地缓存数据
|
||||
if (is_one) {
|
||||
this.files = []
|
||||
}
|
||||
|
||||
let {
|
||||
filePaths,
|
||||
files
|
||||
} = get_files_and_is_max(res, _extname)
|
||||
if (!(_extname && _extname.length > 0)) {
|
||||
filePaths = res.tempFilePaths
|
||||
files = res.tempFiles
|
||||
}
|
||||
|
||||
let currentData = []
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (this.limitLength - this.files.length <= 0) break
|
||||
files[i].uuid = Date.now()
|
||||
let filedata = await get_file_data(files[i], this.fileMediatype)
|
||||
filedata.progress = 0
|
||||
filedata.status = 'ready'
|
||||
this.files.push(filedata)
|
||||
currentData.push({
|
||||
...filedata,
|
||||
file: files[i]
|
||||
})
|
||||
}
|
||||
this.$emit('select', {
|
||||
tempFiles: currentData,
|
||||
tempFilePaths: filePaths,
|
||||
index: this.index
|
||||
})
|
||||
res.tempFiles = files
|
||||
// 停止自动上传
|
||||
if (!this.autoUpload || this.noSpace) {
|
||||
res.tempFiles = []
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 批传
|
||||
* @param {Object} e
|
||||
*/
|
||||
uploadFiles(files) {
|
||||
files = [].concat(files)
|
||||
return uploadCloudFiles.call(this, files, 5, res => {
|
||||
this.setProgress(res, res.index, true)
|
||||
})
|
||||
.then(result => {
|
||||
this.setSuccessAndError(result)
|
||||
return result;
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 成功或失败
|
||||
*/
|
||||
async setSuccessAndError(res, fn) {
|
||||
let successData = []
|
||||
let errorData = []
|
||||
let tempFilePath = []
|
||||
let errorTempFilePath = []
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const item = res[i]
|
||||
const index = item.uuid ? this.files.findIndex(p => p.uuid === item.uuid) : item.index
|
||||
|
||||
if (index === -1 || !this.files) break
|
||||
if (item.errMsg === 'request:fail') {
|
||||
this.files[index].url = item.path
|
||||
this.files[index].status = 'error'
|
||||
this.files[index].errMsg = item.errMsg
|
||||
// this.files[index].progress = -1
|
||||
errorData.push(this.files[index])
|
||||
errorTempFilePath.push(this.files[index].url)
|
||||
} else {
|
||||
this.files[index].errMsg = ''
|
||||
this.files[index].fileID = item.url
|
||||
const reg = /cloud:\/\/([\w.]+\/?)\S*/
|
||||
if (reg.test(item.url)) {
|
||||
this.files[index].url = await this.getTempFileURL(item.url)
|
||||
} else {
|
||||
this.files[index].url = item.url
|
||||
}
|
||||
|
||||
this.files[index].status = 'success'
|
||||
this.files[index].progress += 1
|
||||
successData.push(this.files[index])
|
||||
tempFilePath.push(this.files[index].fileID)
|
||||
}
|
||||
}
|
||||
|
||||
if (successData.length > 0) {
|
||||
this.setEmit()
|
||||
// 状态改变返回
|
||||
this.$emit('success', {
|
||||
tempFiles: this.backObject(successData),
|
||||
tempFilePaths: tempFilePath
|
||||
})
|
||||
}
|
||||
|
||||
if (errorData.length > 0) {
|
||||
this.$emit('fail', {
|
||||
tempFiles: this.backObject(errorData),
|
||||
tempFilePaths: errorTempFilePath
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取进度
|
||||
* @param {Object} progressEvent
|
||||
* @param {Object} index
|
||||
* @param {Object} type
|
||||
*/
|
||||
setProgress(progressEvent, index, type) {
|
||||
const fileLenth = this.files.length
|
||||
const percentNum = (index / fileLenth) * 100
|
||||
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
|
||||
let idx = index
|
||||
if (!type) {
|
||||
idx = this.files.findIndex(p => p.uuid === progressEvent.tempFile.uuid)
|
||||
}
|
||||
if (idx === -1 || !this.files[idx]) return
|
||||
// fix by mehaotian 100 就会消失,-1 是为了让进度条消失
|
||||
this.files[idx].progress = percentCompleted - 1
|
||||
// 上传中
|
||||
this.$emit('progress', {
|
||||
index: idx,
|
||||
progress: parseInt(percentCompleted),
|
||||
tempFile: this.files[idx]
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param {Object} index
|
||||
*/
|
||||
delFile(index) {
|
||||
this.$emit('delete', {
|
||||
tempFile: this.files[index],
|
||||
tempFilePath: this.files[index].url
|
||||
})
|
||||
this.files.splice(index, 1)
|
||||
this.$nextTick(() => {
|
||||
this.setEmit()
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取文件名和后缀
|
||||
* @param {Object} name
|
||||
*/
|
||||
getFileExt(name) {
|
||||
const last_len = name.lastIndexOf('.')
|
||||
const len = name.length
|
||||
return {
|
||||
name: name.substring(0, last_len),
|
||||
ext: name.substring(last_len + 1, len)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理返回事件
|
||||
*/
|
||||
setEmit() {
|
||||
let data = []
|
||||
if (this.returnType === 'object') {
|
||||
data = this.backObject(this.files)[0]
|
||||
this.localValue = data ? data : null
|
||||
} else {
|
||||
data = this.backObject(this.files)
|
||||
if (!this.localValue) {
|
||||
this.localValue = []
|
||||
}
|
||||
this.localValue = [...data]
|
||||
}
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue', this.localValue)
|
||||
// #endif
|
||||
// #ifndef VUE3
|
||||
this.$emit('input', this.localValue)
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理返回参数
|
||||
* @param {Object} files
|
||||
*/
|
||||
backObject(files) {
|
||||
let newFilesData = []
|
||||
files.forEach(v => {
|
||||
newFilesData.push({
|
||||
extname: v.extname,
|
||||
fileType: v.fileType,
|
||||
image: v.image,
|
||||
name: v.name,
|
||||
path: v.path,
|
||||
size: v.size,
|
||||
fileID: v.fileID,
|
||||
url: v.url,
|
||||
// 修改删除一个文件后不能再上传的bug, #694
|
||||
uuid: v.uuid,
|
||||
status: v.status,
|
||||
cloudPath: v.cloudPath
|
||||
})
|
||||
})
|
||||
return newFilesData
|
||||
},
|
||||
async getTempFileURL(fileList) {
|
||||
fileList = {
|
||||
fileList: [].concat(fileList)
|
||||
}
|
||||
const urls = await uniCloud.getTempFileURL(fileList)
|
||||
return urls.fileList[0].tempFileURL || ''
|
||||
},
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getForm(name = 'uniForms') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false;
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.uni-file-picker {
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uni-file-picker__header {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 10px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.file-title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.file-count {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.is-add {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-add {
|
||||
width: 50px;
|
||||
height: 5px;
|
||||
background-color: #f1f1f1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.rotate {
|
||||
position: absolute;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
<template>
|
||||
<view class="uni-file-picker__files">
|
||||
<view v-if="!readonly" class="files-button" @click="choose">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- :class="{'is-text-box':showType === 'list'}" -->
|
||||
<view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
|
||||
<!-- ,'is-list-card':showType === 'list-card' -->
|
||||
|
||||
<view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
|
||||
'files-border':index !== 0 && styles.dividline}"
|
||||
:style="index !== 0 && styles.dividline &&borderLineStyle">
|
||||
<view class="uni-file-picker__item">
|
||||
<!-- :class="{'is-text-image':showType === 'list'}" -->
|
||||
<!-- <view class="files__image is-text-image">
|
||||
<image class="header-image" :src="item.logo" mode="aspectFit"></image>
|
||||
</view> -->
|
||||
<view class="files__name">{{item.name}}</view>
|
||||
<view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
|
||||
<view class="icon-del icon-files"></view>
|
||||
<view class="icon-del rotate"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
|
||||
<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
|
||||
:backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
|
||||
</view>
|
||||
<view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
|
||||
点击重试
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "uploadFile",
|
||||
emits:['uploadFiles','choose','delFile'],
|
||||
props: {
|
||||
filesList: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
delIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
limit: {
|
||||
type: [Number, String],
|
||||
default: 9
|
||||
},
|
||||
showType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
listStyles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
// 是否显示边框
|
||||
border: true,
|
||||
// 是否显示分隔线
|
||||
dividline: true,
|
||||
// 线条样式
|
||||
borderStyle: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
readonly:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
list() {
|
||||
let files = []
|
||||
this.filesList.forEach(v => {
|
||||
files.push(v)
|
||||
})
|
||||
return files
|
||||
},
|
||||
styles() {
|
||||
let styles = {
|
||||
border: true,
|
||||
dividline: true,
|
||||
'border-style': {}
|
||||
}
|
||||
return Object.assign(styles, this.listStyles)
|
||||
},
|
||||
borderStyle() {
|
||||
let {
|
||||
borderStyle,
|
||||
border
|
||||
} = this.styles
|
||||
let obj = {}
|
||||
if (!border) {
|
||||
obj.border = 'none'
|
||||
} else {
|
||||
let width = (borderStyle && borderStyle.width) || 1
|
||||
width = this.value2px(width)
|
||||
let radius = (borderStyle && borderStyle.radius) || 5
|
||||
radius = this.value2px(radius)
|
||||
obj = {
|
||||
'border-width': width,
|
||||
'border-style': (borderStyle && borderStyle.style) || 'solid',
|
||||
'border-color': (borderStyle && borderStyle.color) || '#eee',
|
||||
'border-radius': radius
|
||||
}
|
||||
}
|
||||
let classles = ''
|
||||
for (let i in obj) {
|
||||
classles += `${i}:${obj[i]};`
|
||||
}
|
||||
return classles
|
||||
},
|
||||
borderLineStyle() {
|
||||
let obj = {}
|
||||
let {
|
||||
borderStyle
|
||||
} = this.styles
|
||||
if (borderStyle && borderStyle.color) {
|
||||
obj['border-color'] = borderStyle.color
|
||||
}
|
||||
if (borderStyle && borderStyle.width) {
|
||||
let width = borderStyle && borderStyle.width || 1
|
||||
let style = borderStyle && borderStyle.style || 0
|
||||
if (typeof width === 'number') {
|
||||
width += 'px'
|
||||
} else {
|
||||
width = width.indexOf('px') ? width : width + 'px'
|
||||
}
|
||||
obj['border-width'] = width
|
||||
|
||||
if (typeof style === 'number') {
|
||||
style += 'px'
|
||||
} else {
|
||||
style = style.indexOf('px') ? style : style + 'px'
|
||||
}
|
||||
obj['border-top-style'] = style
|
||||
}
|
||||
let classles = ''
|
||||
for (let i in obj) {
|
||||
classles += `${i}:${obj[i]};`
|
||||
}
|
||||
return classles
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
uploadFiles(item, index) {
|
||||
console.log("1111", item, index)
|
||||
this.$emit("uploadFiles", {
|
||||
item,
|
||||
index
|
||||
})
|
||||
},
|
||||
choose() {
|
||||
this.$emit("choose")
|
||||
},
|
||||
delFile(index) {
|
||||
this.$emit('delFile', index)
|
||||
},
|
||||
value2px(value) {
|
||||
if (typeof value === 'number') {
|
||||
value += 'px'
|
||||
} else {
|
||||
value = value.indexOf('px') !== -1 ? value : value + 'px'
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-file-picker__files {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.files-button {
|
||||
// border: 1px red solid;
|
||||
}
|
||||
|
||||
.uni-file-picker__lists {
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.file-picker__mask {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.uni-file-picker__lists-box {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.uni-file-picker__item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
padding-right: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.files-border {
|
||||
border-top: 1px #eee solid;
|
||||
}
|
||||
|
||||
.files__name {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-right: 25px;
|
||||
/* #ifndef APP-NVUE */
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.icon-files {
|
||||
/* #ifndef APP-NVUE */
|
||||
position: static;
|
||||
background-color: initial;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
// .icon-files .icon-del {
|
||||
// background-color: #333;
|
||||
// width: 12px;
|
||||
// height: 1px;
|
||||
// }
|
||||
|
||||
|
||||
.is-list-card {
|
||||
border: 1px #eee solid;
|
||||
margin-bottom: 5px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.files__image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.header-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.is-text-box {
|
||||
border: 1px #eee solid;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.is-text-image {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.rotate {
|
||||
position: absolute;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.icon-del-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
margin: auto 0;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0;
|
||||
right: 5px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
// border-radius: 50%;
|
||||
// background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 2;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.icon-del {
|
||||
width: 15px;
|
||||
height: 1px;
|
||||
background-color: #333;
|
||||
// border-radius: 1px;
|
||||
}
|
||||
|
||||
/* #ifdef H5 */
|
||||
@media all and (min-width: 768px) {
|
||||
.uni-file-picker__files {
|
||||
max-width: 375px;
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
<template>
|
||||
<view class="uni-file-picker__container">
|
||||
<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
|
||||
<view class="file-picker__box-content" :style="borderStyle">
|
||||
<image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
|
||||
<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
|
||||
<view class="icon-del"></view>
|
||||
<view class="icon-del rotate"></view>
|
||||
</view>
|
||||
<!-- <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
|
||||
<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
|
||||
:backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
|
||||
</view> -->
|
||||
<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
|
||||
点击重试
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
|
||||
<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
|
||||
<slot>
|
||||
<view class="icon-add"></view>
|
||||
<view class="icon-add rotate"></view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "uploadImage",
|
||||
emits:['uploadFiles','choose','delFile'],
|
||||
props: {
|
||||
filesList: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
disabled:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disablePreview: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
limit: {
|
||||
type: [Number, String],
|
||||
default: 9
|
||||
},
|
||||
imageStyles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
border: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
delIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
readonly:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
styles() {
|
||||
let styles = {
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
border: {}
|
||||
}
|
||||
return Object.assign(styles, this.imageStyles)
|
||||
},
|
||||
boxStyle() {
|
||||
const {
|
||||
width = 'auto',
|
||||
height = 'auto'
|
||||
} = this.styles
|
||||
let obj = {}
|
||||
if (height === 'auto') {
|
||||
if (width !== 'auto') {
|
||||
obj.height = this.value2px(width)
|
||||
obj['padding-top'] = 0
|
||||
} else {
|
||||
obj.height = 0
|
||||
}
|
||||
} else {
|
||||
obj.height = this.value2px(height)
|
||||
obj['padding-top'] = 0
|
||||
}
|
||||
|
||||
if (width === 'auto') {
|
||||
if (height !== 'auto') {
|
||||
obj.width = this.value2px(height)
|
||||
} else {
|
||||
obj.width = '33.3%'
|
||||
}
|
||||
} else {
|
||||
obj.width = this.value2px(width)
|
||||
}
|
||||
|
||||
let classles = ''
|
||||
for(let i in obj){
|
||||
classles+= `${i}:${obj[i]};`
|
||||
}
|
||||
return classles
|
||||
},
|
||||
borderStyle() {
|
||||
let {
|
||||
border
|
||||
} = this.styles
|
||||
let obj = {}
|
||||
const widthDefaultValue = 1
|
||||
const radiusDefaultValue = 3
|
||||
if (typeof border === 'boolean') {
|
||||
obj.border = border ? '1px #eee solid' : 'none'
|
||||
} else {
|
||||
let width = (border && border.width) || widthDefaultValue
|
||||
width = this.value2px(width)
|
||||
let radius = (border && border.radius) || radiusDefaultValue
|
||||
radius = this.value2px(radius)
|
||||
obj = {
|
||||
'border-width': width,
|
||||
// 'border-style': (border && border.style) || 'solid',
|
||||
// 'border-color': (border && border.color) || '#eee',
|
||||
'border-radius': radius
|
||||
}
|
||||
}
|
||||
let classles = ''
|
||||
for(let i in obj){
|
||||
classles+= `${i}:${obj[i]};`
|
||||
}
|
||||
return classles
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
uploadFiles(item, index) {
|
||||
this.$emit("uploadFiles", item)
|
||||
},
|
||||
choose() {
|
||||
this.$emit("choose")
|
||||
},
|
||||
delFile(index) {
|
||||
this.$emit('delFile', index)
|
||||
},
|
||||
prviewImage(img, index) {
|
||||
let urls = []
|
||||
if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
|
||||
this.$emit("choose")
|
||||
}
|
||||
if(this.disablePreview) return
|
||||
this.filesList.forEach(i => {
|
||||
urls.push(i.url)
|
||||
})
|
||||
|
||||
uni.previewImage({
|
||||
urls: urls,
|
||||
current: index
|
||||
});
|
||||
},
|
||||
value2px(value) {
|
||||
if (typeof value === 'number') {
|
||||
value += 'px'
|
||||
} else {
|
||||
if (value.indexOf('%') === -1) {
|
||||
value = value.indexOf('px') !== -1 ? value : value + 'px'
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-file-picker__container {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-wrap: wrap;
|
||||
// margin: -5px;
|
||||
}
|
||||
|
||||
.file-picker__box {
|
||||
position: relative;
|
||||
// flex: 0 0 33.3%;
|
||||
width: 33.3%;
|
||||
height: 0;
|
||||
padding-top: 33.33%;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.file-picker__box-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
// margin: 5px;
|
||||
// border: 1px #eee solid;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.file-picker__progress {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* border: 1px red solid; */
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.file-picker__progress-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-picker__mask {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.file-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.is-add {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-add {
|
||||
width: 50px;
|
||||
height: 5px;
|
||||
background-color: #f1f1f1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.rotate {
|
||||
position: absolute;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.icon-del-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 2;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.icon-del {
|
||||
width: 15px;
|
||||
height: 2px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* 获取文件名和后缀
|
||||
* @param {String} name
|
||||
*/
|
||||
export const get_file_ext = (name) => {
|
||||
const last_len = name.lastIndexOf('.')
|
||||
const len = name.length
|
||||
return {
|
||||
name: name.substring(0, last_len),
|
||||
ext: name.substring(last_len + 1, len)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取扩展名
|
||||
* @param {Array} fileExtname
|
||||
*/
|
||||
export const get_extname = (fileExtname) => {
|
||||
if (!Array.isArray(fileExtname)) {
|
||||
let extname = fileExtname.replace(/(\[|\])/g, '')
|
||||
return extname.split(',')
|
||||
} else {
|
||||
return fileExtname
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件和检测是否可选
|
||||
*/
|
||||
export const get_files_and_is_max = (res, _extname) => {
|
||||
let filePaths = []
|
||||
let files = []
|
||||
if(!_extname || _extname.length === 0){
|
||||
return {
|
||||
filePaths,
|
||||
files
|
||||
}
|
||||
}
|
||||
res.tempFiles.forEach(v => {
|
||||
let fileFullName = get_file_ext(v.name)
|
||||
const extname = fileFullName.ext.toLowerCase()
|
||||
if (_extname.indexOf(extname) !== -1) {
|
||||
files.push(v)
|
||||
filePaths.push(v.path)
|
||||
}
|
||||
})
|
||||
if (files.length !== res.tempFiles.length) {
|
||||
uni.showToast({
|
||||
title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`,
|
||||
icon: 'none',
|
||||
duration: 5000
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
filePaths,
|
||||
files
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取图片信息
|
||||
* @param {Object} filepath
|
||||
*/
|
||||
export const get_file_info = (filepath) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getImageInfo({
|
||||
src: filepath,
|
||||
success(res) {
|
||||
resolve(res)
|
||||
},
|
||||
fail(err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 获取封装数据
|
||||
*/
|
||||
export const get_file_data = async (files, type = 'image') => {
|
||||
// 最终需要上传数据库的数据
|
||||
let fileFullName = get_file_ext(files.name)
|
||||
const extname = fileFullName.ext.toLowerCase()
|
||||
let filedata = {
|
||||
name: files.name,
|
||||
uuid: files.uuid,
|
||||
extname: extname || '',
|
||||
cloudPath: files.cloudPath,
|
||||
fileType: files.fileType,
|
||||
url: files.path || files.path,
|
||||
size: files.size, //单位是字节
|
||||
image: {},
|
||||
path: files.path,
|
||||
video: {}
|
||||
}
|
||||
if (type === 'image') {
|
||||
const imageinfo = await get_file_info(files.path)
|
||||
delete filedata.video
|
||||
filedata.image.width = imageinfo.width
|
||||
filedata.image.height = imageinfo.height
|
||||
filedata.image.location = imageinfo.path
|
||||
} else {
|
||||
delete filedata.image
|
||||
}
|
||||
return filedata
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"id": "uni-file-picker",
|
||||
"displayName": "uni-file-picker 文件选择上传",
|
||||
"version": "1.0.4",
|
||||
"description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"图片上传",
|
||||
"文件上传"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
## FilePicker 文件选择上传
|
||||
|
||||
> **组件名:uni-file-picker**
|
||||
> 代码块: `uFilePicker`
|
||||
|
||||
|
||||
文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
## 1.9.11(2025-08-20)
|
||||
- 修复 uni-popup-dialog组件设置 borderRadius 不生效的 Bug
|
||||
## 1.9.10(2025-07-18)
|
||||
- 修复 nvue 下弹窗样式错乱的问题 ,更新依赖 uni-transition 组件
|
||||
- 更新 示例取消 borderRadius 属性 ,如需内容圆角,用户应该直接在内容插槽中实现
|
||||
## 1.9.9(2025-06-11)
|
||||
- 修复 uni-popup-dialog 中 setVal 方法报错的问题
|
||||
- 修复 uni-popup-dialog 数据双向绑定问题。
|
||||
## 1.9.8(2025-04-16)
|
||||
- 修复 更新组件示例 ,解决更新数据或保存项目导致弹窗消失的问题
|
||||
## 1.9.7(2025-04-14)
|
||||
- 修复 uni-popup-dialog 弹出框在vue3中双向绑定问题
|
||||
## 1.9.6(2025-01-08)
|
||||
- 修复 示例中过期图片地址
|
||||
## 1.9.5(2024-10-15)
|
||||
- 修复 微信小程序中的getSystemInfo警告
|
||||
## 1.9.2(2024-09-21)
|
||||
- 修复 uni-popup在android上的重复点击弹出位置不正确的bug
|
||||
## 1.9.1(2024-04-02)
|
||||
- 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法)
|
||||
## 1.9.0(2024-03-28)
|
||||
- 修复 uni-popup-dialog 双向绑定时初始化逻辑修正
|
||||
## 1.8.9(2024-03-20)
|
||||
- 修复 uni-popup-dialog 数据输入时修正为双向绑定
|
||||
## 1.8.8(2024-02-20)
|
||||
- 修复 uni-popup 在微信小程序下出现文字向上闪动的bug
|
||||
## 1.8.7(2024-02-02)
|
||||
- 新增 uni-popup-dialog 新增属性focus:input模式下,是否自动自动聚焦
|
||||
## 1.8.6(2024-01-30)
|
||||
- 新增 uni-popup-dialog 新增属性maxLength:限制输入框字数
|
||||
## 1.8.5(2024-01-26)
|
||||
- 新增 uni-popup-dialog 新增属性showClose:控制关闭按钮的显示
|
||||
## 1.8.4(2023-11-15)
|
||||
- 新增 uni-popup 支持uni-app-x 注意暂时仅支持 `maskClick` `@open` `@close`
|
||||
## 1.8.3(2023-04-17)
|
||||
- 修复 uni-popup 重复打开时的 bug
|
||||
## 1.8.2(2023-02-02)
|
||||
- uni-popup-dialog 组件新增 inputType 属性
|
||||
## 1.8.1(2022-12-01)
|
||||
- 修复 nvue 下 v-show 报错
|
||||
## 1.8.0(2022-11-29)
|
||||
- 优化 主题样式
|
||||
## 1.7.9(2022-04-02)
|
||||
- 修复 弹出层内部无法滚动的bug
|
||||
## 1.7.8(2022-03-28)
|
||||
- 修复 小程序中高度错误的bug
|
||||
## 1.7.7(2022-03-17)
|
||||
- 修复 快速调用open出现问题的Bug
|
||||
## 1.7.6(2022-02-14)
|
||||
- 修复 safeArea 属性不能设置为false的bug
|
||||
## 1.7.5(2022-01-19)
|
||||
- 修复 isMaskClick 失效的bug
|
||||
## 1.7.4(2022-01-19)
|
||||
- 新增 cancelText \ confirmText 属性 ,可自定义文本
|
||||
- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色
|
||||
- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题
|
||||
## 1.7.3(2022-01-13)
|
||||
- 修复 设置 safeArea 属性不生效的bug
|
||||
## 1.7.2(2021-11-26)
|
||||
- 优化 组件示例
|
||||
## 1.7.1(2021-11-26)
|
||||
- 修复 vuedoc 文字错误
|
||||
## 1.7.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup)
|
||||
## 1.6.2(2021-08-24)
|
||||
- 新增 支持国际化
|
||||
## 1.6.1(2021-07-30)
|
||||
- 优化 vue3下事件警告的问题
|
||||
## 1.6.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.5.0(2021-06-23)
|
||||
- 新增 mask-click 遮罩层点击事件
|
||||
## 1.4.5(2021-06-22)
|
||||
- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.4(2021-06-18)
|
||||
- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.3(2021-06-08)
|
||||
- 修复 错误的 watch 字段
|
||||
- 修复 safeArea 属性不生效的问题
|
||||
- 修复 点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.2(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.4.1(2021-04-29)
|
||||
- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
|
||||
## 1.4.0 (2021-04-29)
|
||||
- 新增 type 属性的 left\right 值,支持左右弹出
|
||||
- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
|
||||
- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
|
||||
- 新增 safeArea 属性,是否适配底部安全区
|
||||
- 修复 App\h5\微信小程序底部安全区占位不对的Bug
|
||||
- 修复 App 端弹出等待的Bug
|
||||
- 优化 提升低配设备性能,优化动画卡顿问题
|
||||
- 优化 更简单的组件自定义方式
|
||||
## 1.2.9(2021-02-05)
|
||||
- 优化 组件引用关系,通过uni_modules引用组件
|
||||
## 1.2.8(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
## 1.2.7(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 新增 支持 PC 端
|
||||
- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
document.removeEventListener('keyup', listener)
|
||||
})
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
||||
|
|
@ -0,0 +1,330 @@
|
|||
<template>
|
||||
<view class="uni-popup-dialog" :style="{ borderRadius }">
|
||||
<view class="uni-dialog-title">
|
||||
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
|
||||
</view>
|
||||
<view v-if="mode === 'base'" class="uni-dialog-content">
|
||||
<slot>
|
||||
<text class="uni-dialog-content-text">{{content}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
<view v-else class="uni-dialog-content">
|
||||
<slot>
|
||||
<input class="uni-dialog-input" :maxlength="maxlength" v-model="val" :type="inputType"
|
||||
:placeholder="placeholderText" :focus="focus">
|
||||
</slot>
|
||||
</view>
|
||||
<view class="uni-dialog-button-group">
|
||||
<view class="uni-dialog-button" v-if="showClose" @click="closeDialog">
|
||||
<text class="uni-dialog-button-text">{{closeText}}</text>
|
||||
</view>
|
||||
<view class="uni-dialog-button" :class="showClose?'uni-border-left':''" @click="onOk">
|
||||
<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from '../uni-popup/i18n/index.js'
|
||||
const {
|
||||
t
|
||||
} = initVueI18n(messages)
|
||||
/**
|
||||
* PopUp 弹出层-对话框样式
|
||||
* @description 弹出层-对话框样式
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} value input 模式下的默认值
|
||||
* @property {String} placeholder input 模式下输入提示
|
||||
* @property {Boolean} focus input模式下是否自动聚焦,默认为true
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} mode = [base|input] 模式、
|
||||
* @value base 基础对话框
|
||||
* @value input 可输入对话框
|
||||
* @showClose {Boolean} 是否显示关闭按钮
|
||||
* @property {String} content 对话框内容
|
||||
* @property {Boolean} beforeClose 是否拦截取消事件
|
||||
* @property {Number} maxlength 输入
|
||||
* @event {Function} confirm 点击确认按钮触发
|
||||
* @event {Function} close 点击取消按钮触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "uniPopupDialog",
|
||||
mixins: [popup],
|
||||
emits: ['confirm', 'close', 'update:modelValue', 'input'],
|
||||
props: {
|
||||
inputType: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
showClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// #ifdef VUE2
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
// #endif
|
||||
|
||||
|
||||
placeholder: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'error'
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'base'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: -1,
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
borderRadius: {
|
||||
type: String,
|
||||
default: '11px',
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogType: 'error',
|
||||
val: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
okText() {
|
||||
return this.confirmText || t("uni-popup.ok")
|
||||
},
|
||||
closeText() {
|
||||
return this.cancelText || t("uni-popup.cancel")
|
||||
},
|
||||
placeholderText() {
|
||||
return this.placeholder || t("uni-popup.placeholder")
|
||||
},
|
||||
titleText() {
|
||||
return this.title || t("uni-popup.title")
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
type(val) {
|
||||
this.dialogType = val
|
||||
},
|
||||
mode(val) {
|
||||
if (val === 'input') {
|
||||
this.dialogType = 'info'
|
||||
}
|
||||
},
|
||||
value(val) {
|
||||
this.setVal(val)
|
||||
},
|
||||
// #ifdef VUE3
|
||||
modelValue(val) {
|
||||
this.setVal(val)
|
||||
},
|
||||
// #endif
|
||||
val(val) {
|
||||
// #ifdef VUE2
|
||||
// TODO 兼容 vue2
|
||||
this.$emit('input', val);
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
// TODO 兼容 vue3
|
||||
this.$emit('update:modelValue', val);
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 对话框遮罩不可点击
|
||||
this.popup.disableMask()
|
||||
// this.popup.closeMask()
|
||||
if (this.mode === 'input') {
|
||||
this.dialogType = 'info'
|
||||
this.val = this.value;
|
||||
// #ifdef VUE3
|
||||
this.val = this.modelValue;
|
||||
// #endif
|
||||
} else {
|
||||
this.dialogType = this.type
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 给val属性赋值
|
||||
*/
|
||||
setVal(val) {
|
||||
if (this.maxlength != -1 && this.mode === 'input') {
|
||||
this.val = val.slice(0, this.maxlength);
|
||||
} else {
|
||||
this.val = val
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
onOk() {
|
||||
if (this.mode === 'input') {
|
||||
this.$emit('confirm', this.val)
|
||||
} else {
|
||||
this.$emit('confirm')
|
||||
}
|
||||
if (this.beforeClose) return
|
||||
this.popup.close()
|
||||
},
|
||||
/**
|
||||
* 点击取消按钮
|
||||
*/
|
||||
closeDialog() {
|
||||
this.$emit('close')
|
||||
if (this.beforeClose) return
|
||||
this.popup.close()
|
||||
},
|
||||
close() {
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-popup-dialog {
|
||||
width: 300px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.uni-dialog-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.uni-dialog-title-text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.uni-dialog-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.uni-dialog-content-text {
|
||||
font-size: 14px;
|
||||
color: #6C6C6C;
|
||||
}
|
||||
|
||||
.uni-dialog-button-group {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
border-top-color: #f5f5f5;
|
||||
border-top-style: solid;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.uni-border-left {
|
||||
border-left-color: #f0f0f0;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button-text {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.uni-button-color {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.uni-dialog-input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
border: 1px #eee solid;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
border-radius: 5px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
color: #4cd964;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
color: #f0ad4e;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
color: #dd524d;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<view class="uni-popup-message">
|
||||
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
|
||||
<slot>
|
||||
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
/**
|
||||
* PopUp 弹出层-消息提示
|
||||
* @description 弹出层-消息提示
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} message 消息提示文字
|
||||
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'uniPopupMessage',
|
||||
mixins:[popup],
|
||||
props: {
|
||||
/**
|
||||
* 主题 success/warning/info/error 默认 success
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
/**
|
||||
* 消息文字
|
||||
*/
|
||||
message: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
},
|
||||
maskShow:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {
|
||||
this.popup.maskShow = this.maskShow
|
||||
this.popup.messageChild = this
|
||||
},
|
||||
methods: {
|
||||
timerClose(){
|
||||
if(this.duration === 0) return
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(()=>{
|
||||
this.popup.close()
|
||||
},this.duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" >
|
||||
.uni-popup-message {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-popup-message__box {
|
||||
background-color: #e1f3d8;
|
||||
padding: 10px 15px;
|
||||
border-color: #eee;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
.fixforpc-width {
|
||||
margin-top: 20px;
|
||||
border-radius: 4px;
|
||||
flex: none;
|
||||
min-width: 380px;
|
||||
/* #ifndef APP-NVUE */
|
||||
max-width: 50%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
max-width: 500px;
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
|
||||
.uni-popup-message-text {
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
background-color: #e1f3d8;
|
||||
}
|
||||
|
||||
.uni-popup__success-text {
|
||||
color: #67C23A;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
background-color: #faecd8;
|
||||
}
|
||||
|
||||
.uni-popup__warn-text {
|
||||
color: #E6A23C;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
background-color: #fde2e2;
|
||||
}
|
||||
|
||||
.uni-popup__error-text {
|
||||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
background-color: #F2F6FC;
|
||||
}
|
||||
|
||||
.uni-popup__info-text {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
<template>
|
||||
<view class="uni-popup-share">
|
||||
<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
|
||||
<view class="uni-share-content">
|
||||
<view class="uni-share-content-box">
|
||||
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
|
||||
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
|
||||
<text class="uni-share-text">{{item.text}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-share-button-box">
|
||||
<button class="uni-share-button" @click="close">{{cancelText}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from '../uni-popup/i18n/index.js'
|
||||
const { t } = initVueI18n(messages)
|
||||
export default {
|
||||
name: 'UniPopupShare',
|
||||
mixins:[popup],
|
||||
emits:['select'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// TODO 替换为自己的图标
|
||||
bottomData: [{
|
||||
text: '微信',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'wx'
|
||||
},
|
||||
{
|
||||
text: '支付宝',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'ali'
|
||||
},
|
||||
{
|
||||
text: 'QQ',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'qq'
|
||||
},
|
||||
{
|
||||
text: '新浪',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'sina'
|
||||
},
|
||||
// {
|
||||
// text: '百度',
|
||||
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
|
||||
// name: 'copy'
|
||||
// },
|
||||
// {
|
||||
// text: '其他',
|
||||
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
|
||||
// name: 'more'
|
||||
// }
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
computed: {
|
||||
cancelText() {
|
||||
return t("uni-popup.cancel")
|
||||
},
|
||||
shareTitleText() {
|
||||
return this.title || t("uni-popup.shareTitle")
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 选择内容
|
||||
*/
|
||||
select(item, index) {
|
||||
this.$emit('select', {
|
||||
item,
|
||||
index
|
||||
})
|
||||
this.close()
|
||||
|
||||
},
|
||||
/**
|
||||
* 关闭窗口
|
||||
*/
|
||||
close() {
|
||||
if(this.beforeClose) return
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" >
|
||||
.uni-popup-share {
|
||||
background-color: #fff;
|
||||
border-top-left-radius: 11px;
|
||||
border-top-right-radius: 11px;
|
||||
}
|
||||
.uni-share-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
}
|
||||
.uni-share-title-text {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.uni-share-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.uni-share-content-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.uni-share-content-item {
|
||||
width: 90px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-share-content-item:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.uni-share-image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.uni-share-text {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #3B4144;
|
||||
}
|
||||
|
||||
.uni-share-button-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.uni-share-button {
|
||||
flex: 1;
|
||||
border-radius: 50px;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uni-share-button::after {
|
||||
border-radius: 50px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uni-popup.cancel": "cancel",
|
||||
"uni-popup.ok": "ok",
|
||||
"uni-popup.placeholder": "pleace enter",
|
||||
"uni-popup.title": "Hint",
|
||||
"uni-popup.shareTitle": "Share to"
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uni-popup.cancel": "取消",
|
||||
"uni-popup.ok": "确定",
|
||||
"uni-popup.placeholder": "请输入",
|
||||
"uni-popup.title": "提示",
|
||||
"uni-popup.shareTitle": "分享到"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uni-popup.cancel": "取消",
|
||||
"uni-popup.ok": "確定",
|
||||
"uni-popup.placeholder": "請輸入",
|
||||
"uni-popup.title": "提示",
|
||||
"uni-popup.shareTitle": "分享到"
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// document.removeEventListener('keyup', listener)
|
||||
// })
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.popup = this.getParent()
|
||||
},
|
||||
methods:{
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getParent(name = 'uniPopup') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<view class="popup-root" v-if="isOpen" v-show="isShow" @click="clickMask">
|
||||
<view @click.stop>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
type CloseCallBack = ()=> void;
|
||||
let closeCallBack:CloseCallBack = () :void => {};
|
||||
export default {
|
||||
emits:["close","clickMask"],
|
||||
data() {
|
||||
return {
|
||||
isShow:false,
|
||||
isOpen:false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 设置show = true 时,如果没有 open 需要设置为 open
|
||||
isShow:{
|
||||
handler(isShow) {
|
||||
// console.log("isShow",isShow)
|
||||
if(isShow && this.isOpen == false){
|
||||
this.isOpen = true
|
||||
}
|
||||
},
|
||||
immediate:true
|
||||
},
|
||||
// 设置isOpen = true 时,如果没有 isShow 需要设置为 isShow
|
||||
isOpen:{
|
||||
handler(isOpen) {
|
||||
// console.log("isOpen",isOpen)
|
||||
if(isOpen && this.isShow == false){
|
||||
this.isShow = true
|
||||
}
|
||||
},
|
||||
immediate:true
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
open(){
|
||||
// ...funs : CloseCallBack[]
|
||||
// if(funs.length > 0){
|
||||
// closeCallBack = funs[0]
|
||||
// }
|
||||
this.isOpen = true;
|
||||
},
|
||||
clickMask(){
|
||||
if(this.maskClick == true){
|
||||
this.$emit('clickMask')
|
||||
this.close()
|
||||
}
|
||||
},
|
||||
close(): void{
|
||||
this.isOpen = false;
|
||||
this.$emit('close')
|
||||
closeCallBack()
|
||||
},
|
||||
hiden(){
|
||||
this.isShow = false
|
||||
},
|
||||
show(){
|
||||
this.isShow = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.popup-root {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 750rpx;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||