Commit 3741d1a3 authored by 秦威威's avatar 秦威威

start

parents
Pipeline #19 failed with stages
# 忽略UniApp编译生成的小程序相关目录
/unpackage/*
!/unpackage/res/*
/.idea/*
/.hbuilderx/*
/.svn/*
<script>
export default {
onLaunch: function(e) {},
onShow: function() {
this.getWifiInfo();
},
onHide: function() {
},
methods: {
getWifiInfo() {
// uni.getNetworkType({
// success: function (res) {
// console.log(res.networkType);
// if (res.networkType === 'wifi') {
// uni.getConnectedWifi({
// success: function (wifi) {
// console.log(wifi.SSID); // 注意:SSID可能返回undefined或空字符串
// },
// fail: function (error) {
// console.error('获取WiFi信息失败:', error);
// }
// });
// }
// }
// });
}
}
}
</script>
<style lang="scss">
/*每个页面公共css */
@import "@/common/css/public.scss";
@import "@/uni_modules/uview-ui/index.scss";
.navSlot {
display: flex;
align-items: center;
font-weight: bold;
font-size: 36rpx;
color: #333333;
}
</style>
\ No newline at end of file
$app-main-color: #FE2C24;
page {
height: 100%;
}
.container {
box-sizing: border-box; /* padding border 等不增加到宽高上 */
// box-sizing: content-box; /* padding border 等增加到宽高上 */
}
view,
scroll-view,
swiper,
button,
input,
textarea,
label,
navigator,
image {
box-sizing: content-box; /* padding border 等增加到宽高上 */
}
.flex {
display: flex;
}
.flex-wrap {
display: flex;
flex-wrap: wrap;
}
.flex-column {
display: flex;
flex-direction: column;
}
// 横轴
.flex-row-around {
display: flex;
justify-content: space-around;
}
.flex-row-between {
display: flex;
justify-content: space-between;
}
.flex-row-center {
display: flex;
justify-content: center;
}
// 纵轴
.flex-column-center {
display: flex;
align-items: center;
}
// 横轴 纵轴
.flex-around-center{
display: flex;
justify-content: space-around;
align-items: center;
}
.flex-between-center{
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-center-center {
display: flex;
justify-content: center;
align-items: center;
}
// 宽高
@for $i from 1 through 500 {
.w-#{$i} {
width: $i + rpx;
}
.h-#{$i} {
height: $i + rpx;
}
.lh-#{$i} {
line-height: $i + rpx;
}
.wh-#{$i} {
width: $i + rpx;
height: $i + rpx;
}
}
// 字体大小
@for $i from 10 through 60 {
.fs-#{$i} {
font-size: $i + rpx;
}
}
.fw-500 {
font-weight: 500;
}
.fw-600 {
font-weight: 600;
}
.fw-700 {
font-weight: 700;
}
// 圆角
@for $i from 8 through 500 {
.br-#{$i} {
border-radius: $i + rpx;
}
}
// 内边距
@for $i from 5 through 500 {
.pad-#{$i} {
padding: $i + rpx;
}
.pt-#{$i} {
padding-top: $i + rpx;
}
.pr-#{$i} {
padding-right: $i + rpx;
}
.pb-#{$i} {
padding-bottom: $i + rpx;
}
.pl-#{$i} {
padding-left: $i + rpx;
}
.ptb-#{$i} {
padding-top: $i + rpx;
padding-bottom: $i + rpx;
}
.plr-#{$i} {
padding-left: $i + rpx;
padding-right: $i + rpx;
}
}
// 外边距
@for $i from 5 through 500 {
.mar-#{$i} {
margin: $i + rpx;
}
.mt-#{$i} {
margin-top: $i + rpx;
}
.mr-#{$i} {
margin-right: $i + rpx;
}
.mb-#{$i} {
margin-bottom: $i + rpx;
}
.ml-#{$i} {
margin-left: $i + rpx;
}
.mtb-#{$i} {
margin-top: $i + rpx;
margin-bottom: $i + rpx;
}
.mlr-#{$i} {
margin-left: $i + rpx;
margin-right: $i + rpx;
}
}
.center {
text-align: center;
}
// 订单的主要按钮
.main-btn {
width: 160rpx;
height: 72rpx;
border-radius: 60rpx;
text-align: center;
line-height: 72rpx;
color: #FFF;
background-color: $app-main-color;
}
// 订单的次要按钮
.minor-btn {
width: 160rpx;
height: 72rpx;
border: 2rpx solid #999999;
border-radius: 60rpx;
text-align: center;
line-height: 72rpx;
}
.bottom-box {
box-sizing: border-box;
}
// 沾满全屏的按钮
.fullscreen-btn {
width: 100%;
height: 94rpx;
text-align: center;
line-height: 94rpx;
background-color: $app-main-color;
border-radius: 60rpx;
color: #FFF;
}
button::after {
border: none;
}
button {
display: block;
line-height: normal;
background-color: #FFF;
padding-left: 0;
padding-right: 0;
margin: 0;
font-size: 32rpx;
}
\ No newline at end of file
import config from "config"
/**
* http请求
* @author 万世科技
* @param {Object} params
*/
function request(params) {
const token = uni.getStorageSync('token')
return new Promise((resolve, reject) => {
try {
params.url = config.domain + params.url
params.method = params.method || 'POST'
if (params.loadingTip === '' || params.loadingTip) {
uni.showLoading({
title: params.loadingTip
})
}
let header = {
"authorization": token || '',
};
if (params.contentType == 1) {
header["Content-Type"] = "application/x-www-form-urlencoded";
}
uni.request({
...params,
header: header,
success: (res) => {
// 防止组件那边使用showLoading这里提前关闭
// console.log(token);
if (params.loadingTip === '' || params.loadingTip) {
uni.hideLoading()
}
// 这里判断code为1,组件那边不需要再判断then回调就是成功
if (res.statusCode === 200 && res.data.code === 200) {
resolve(res.data)
} else if (res.statusCode === 401 || res.data.code === 401) { // 未登录,或登录过期
// toLogin()
//uni.removeStorageSync("token");
//toLogin();
reject(res.data || {})
} else if (res.statusCode === 200 || res.data.code === 500) { // 未登录,或登录过期
this.$u.toast(res.data.msg)
} else {
reject(res.data || {})
}
},
fail: (err) => {
console.log(err)
console.log('失败')
// console.log(err)
uni.hideLoading()
// if(err.data.code === 401) {
// toLogin()
// }
reject({
msg: "服务器异常"
} || {})
}
})
} catch (err) {
reject({
msg: "服务器异常"
})
}
})
}
function toLogin() {
uni.showModal({
title: '提示',
content: '您的登录失效,是否重新登录?',
success(res) {
if (res.confirm) {
uni.navigateTo({
url: '/pages/login/wechatlogin'
})
} else if (res.cancel) {
}
}
})
}
export default request
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
<template>
<view class="page-content">
<!-- 选择器背景 -->
<view class="page-mask"></view>
<!-- 选择器主体 -->
<view class="page-main" :style="'height:60%'">
<!-- 操作区域 包含取消和确定 -->
<view class="main-operate">
<text class="title-txt" @click.stop="handleCancel">取消</text>
<text class="title-txt" @click.stop="handleSubmit">确定</text>
</view>
<!-- 已选择的地址信息 -->
<view class="main-select" :class="[selectAreaLevelLimit == 3 ? 'w33_percent' : '']">
<text v-if="showIndex == 0 || provinceObj.label" :class="showIndex == 0 ? 'select' : ''"
@click="anewSelect(0)">{{ provinceObj.label || "请选择" }}</text>
<text v-if="showIndex == 1 || cityObj.label" :class="showIndex == 1 ? 'select' : ''"
@click="anewSelect(1)">{{ cityObj.label || "请选择" }}</text>
<text v-if="showIndex == 2 || areaObj.label" :class="showIndex == 2 ? 'select' : ''"
@click="anewSelect(2)">{{ areaObj.label || "请选择" }}</text>
</view>
<!-- 待选择的地址信息 -->
<view class="main-list">
<view v-if="showIndex == 0">
<view class="list-box" :class="provinceObj.value == item.value ? 'active' : ''"
@click="handleSelectAddress(0, item)" v-for="item in provinceData" :key="item.value">
<text>{{ item.label }}</text>
</view>
</view>
<view v-if="showIndex == 1">
<view class="list-box" :class="cityObj.value == item.value ? 'active' : ''"
@click="handleSelectAddress(1, item)" v-for="item in cityData" :key="item.value">
<text>{{ item.label }}</text>
</view>
</view>
<view v-if="showIndex == 2">
<view class="list-box" :class="areaObj.value == item.value ? 'active' : ''"
@click="handleSelectAddress(2, item)" v-for="item in areaData" :key="item.value">
<text>{{ item.label }}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "address-modal",
props: {
areaInfoSelected: {
type: Object,
default: {
},
},
selectAreaLevelLimit: {
type: Number,
default: 3,
}
},
data() {
return {
showIndex: 0, //地区显示
provinceObj: {},
cityObj: {},
areaObj: {},
heightCot: 30, //设置屏幕高度 0 ~ 100
provinceData: "", // 当前展示的省数据
cityData: [], // 当前展示的市数据
areaData: [], //当前展示的区数据
};
},
mounted() {
if (this.areaInfoSelected.fullAreaTextInitial) {
let {
fullAreaTextInitial
} = this.areaInfoSelected;
let _arr = fullAreaTextInitial.split(",");
this.provinceObj = this.areaInfoSelected.provinceObj;
this.cityObj = this.areaInfoSelected.cityObj;
this.areaObj = this.areaInfoSelected.areaObj;
if (_arr.length == 1) {
this.handleGetMap({}, "init");
}
if (_arr.length == 2) {
this.handleGetMap(this.areaInfoSelected.provinceObj, "pro");
}
if (_arr.length == 3) {
this.handleGetMap(this.areaInfoSelected.cityObj, "city");
}
if (_arr.length == 4) {
this.handleGetMap(this.areaInfoSelected.areaObj, "area");
}
} else {
this.handleGetMap({}, "init");
}
this.getScreen();
},
onShow() {},
methods: {
//组件高度自适应
getScreen() {
let that = this;
uni.getSystemInfo({
success: (res) => {
that.heightCot = (res.safeArea.height * 2) / 2;
},
});
},
//取消
handleCancel() {
this.$emit("cancel");
},
//确定
handleSubmit() {
const {
provinceObj,
cityObj,
areaObj
} = this;
console.log(cityObj)
const arr = [provinceObj, cityObj, areaObj];
let _fullAreaText = [];
arr.map((item) => {
if (item.value) {
_fullAreaText.push(item.label);
}
});
if (this.selectAreaLevelLimit == 3) {
if (_fullAreaText.length !== 3) {
uni.showToast({
icon: "none",
title: "地址需精确到地区",
});
return
}
} else {
if (_fullAreaText.length !== this.selectAreaLevelLimit) {
uni.showToast({
icon: "none",
title: "地址需精确到街道",
});
return
}
}
let areaInfoObj = {
fullAreaTextInitial: _fullAreaText.toString(),
fullAreaText: _fullAreaText.toString().replace(/,/g, ""),
provinceCode: provinceObj.value || "",
cityCode: cityObj.value || "",
areaCode: areaObj.value || "",
provinceObj,
cityObj,
areaObj
};
this.$emit("confirm", areaInfoObj);
},
//下拉选择
anewSelect(num) {
console.log(num)
switch (num) {
case 0:
this.showIndex = 0;
this.cityObj = {};
this.areaObj = {};
this.cityData = [];
this.areaData = [];
this.handleGetMap({}, "init");
break;
case 1:
this.showIndex = 1;
this.areaData = [];
// if (!this.areaObj.areaCode) return;
this.areaObj = {};
this.handleGetMap(this.provinceObj, "pro");
break;
case 2:
this.showIndex = 2;
// if (!this.areaObj.areaCode) return;
// this.areaObj = {};
// this.handleGetMap(this.areaObj, "area");
// break;
}
},
handleGetMap(obj, type) {
//name选择名称 type类型
if (type !== "init") {
uni.showLoading({
title: "加载中",
mask: true,
});
}
let queryParam
if (type == 'init') {
queryParam = {
url: '/addons/shop/api.common/area',
}
}
if (type == 'pro') {
queryParam = {
url: '/addons/shop/api.common/area',
data: {
province: obj.value
}
}
}
if (type == 'city') {
queryParam = {
url: '/addons/shop/api.common/area',
data: {
city: obj.value
}
}
}
this.$request(queryParam).then((resp) => {
uni.hideLoading();
if (resp.code == 1) {
let arr = ["init", "pro", "city", "area"];
let _obj = {
init: "provinceData",
pro: "cityData",
city: "areaData"
};
this[_obj[type]] = resp.data;
this.showIndex = arr.indexOf(type);
} else {
uni.hideLoading();
uni.showToast({
icon: "none",
title: resp.msg,
position: "center",
duration: 2000,
});
}
});
},
handleSelectAddress(type, obj) {
switch (type) {
case 0:
//选择省
this.handleGetMap(obj, "pro");
this.provinceObj = obj;
this.showIndex = 1;
this.cityData = [];
this.areaData = [];
break;
case 1:
//选择市
this.handleGetMap(obj, "city");
this.cityObj = obj;
this.showIndex = 2;
this.areaData = [];
break;
case 2:
//选择区
this.areaObj = obj;
this.handleSubmit()
break;
default:
break;
}
},
},
};
</script>
<style lang="scss" scoped>
.page-mask {
position: fixed;
width: 100%;
height: 100vh;
z-index: 998;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.6);
}
.page-main {
height: 100vh;
position: fixed;
z-index: 999;
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
padding: 20rpx;
border-top: 1rpx solid rgba(0, 0, 0, 0.2);
border-radius: 16rpx 16rpx 0 0;
max-height: 60%;
.main-operate {
padding: 0 10rpx 10rpx 10rpx;
display: flex;
justify-content: space-between;
.title-txt {
color: #343434;
font-size: 30rpx;
&:nth-child(2) {
color: #000;
}
}
}
.main-select {
display: flex;
justify-content: flex-start;
color: #343434;
font-size: 30rpx;
height: 100rpx;
line-height: 100rpx;
text {
display: inline-block;
width: 25%;
text-align: center;
overflow: hidden;
-webkit-line-clamp: 1;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
text-align: center;
}
.select {
color: #000;
position: relative;
&::after {
content: "";
width: 100%;
height: 6rpx;
background: #ff4242;
position: absolute;
left: 0;
bottom: -8rpx;
}
}
}
.main-list {
overflow-y: auto;
color: #343434;
font-size: 30rpx;
width: 100%;
height: 72%;
overflow: auto;
.list-box {
display: flex;
flex-direction: column;
height: 100rpx;
line-height: 100rpx;
border-bottom: 2rpx solid #dedede;
}
.list-box:last-child {
border-bottom: none;
}
.active {
color: #000;
}
}
}
</style>
\ No newline at end of file
<template>
<view class="">
<swiper :style="{'height': height + 'rpx'}" @change="$emit('change', e)">
<swiper-item v-for="(item, index) in list">
<view class="classify-box">
<view v-for="(classify, index) in item" :key="index"
:style="{'margin-bottom': index > 4? '0' : '36rpx'}" class="nav-bar-item"
@click="$emit('click', classify)">
<image class="w-80 h-80 mb-17 br-14" :src="classify.image"/>
<view class="fs-24">{{ classify.title }}</view>
</view>
</view>
</swiper-item>
</swiper>
<view v-if="dotShow" class="swiper-dot">
<view v-for="(item, index) in list" class="item"
:class="{'activedot': current === index}"></view>
</view>
</view>
</template>
<script>
/**
* classifySwiper 首页分类轮播组件
* @property {String} height 组件高度,swiper规定必须设置一个高度
* @property {String} classifyList 后端返回的数据源
* @property {String} current 当前轮播的页码
* @property {String} dotShow 是否显示底部滑块,默认显示
*/
export default {
props: {
height: {
type: Number | String,
default: 340
},
classifyList: {
type: Array,
default: []
},
current: {
type: Number | String,
default: 0
},
dotShow: {
type: Boolean,
default: true
}
},
data () {
return {
list: []
}
},
created() {
this.init()
},
methods: {
// 初始化后端返回的数组为二维数组
init(){
const swiperCount = Math.ceil(this.classifyList.length / 10); // 计算需要多少个swiper
const result = [];
for (let i = 0; i < swiperCount; i++) {
const start = i * 10;
const end = Math.min(start + 10, this.classifyList.length);
result.push(this.classifyList.slice(start, end)); // 切片获取当前swiper的数据范围
}
// console.log(result)
this.list = result
}
}
}
</script>
<style scoped>
.classify-box {
display: flex;
flex-wrap: wrap;
}
.nav-bar-item {
width: 20%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.swiper-dot {
display: flex;
justify-content: center;
}
.swiper-dot>.item {
width: 28rpx;
height: 3rpx;
background-color: #ECECEC;
border-radius: 3rpx;
}
.activedot {
background-color: #494949 !important;
}
</style>
<template>
<view class="list">
<view v-for="(item, index) in 5" :key="index" class="item">
<view class="user-info-box">
<view class="left">
<image src="@/static/logo.png"></image>
<view style="display: flex;flex-direction: column;">
<text>秦**黄</text>
<text class="fs-24 mt-20" style="color: #999999;">2023-04-02 12:12</text>
</view>
</view>
<view class="rate-box">
<u-rate :count="5" :readonly="true" size="25" activeColor="#F29600"></u-rate>
</view>
</view>
<view class="comment-imgs">
<image v-for="(img, imgIndex) in 3" :key="imgIndex" @click="onPreviewImage(item.images, imgIndex)"
src="@/static/logo.png"></image>
</view>
<view class="comment-content">
<text>速度快,好评!!!谷歌翻译新增了5种语音的翻译,它们分别是基尼亚卢旺达语(卢旺达)、奥里亚语。</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
score: '',
goodsId: '',
commentList: [],
currentPage: 1,
isEmpty: false,
};
},
onLoad(options) {
this.goodsId = options.goodsId
this.score = options.score
// this.getCommentList()
},
methods: {
// 获取评价列表
getCommentList() {
const params = {
url: '/api/order/comment_list',
data: {
page: this.currentPage,
goods_id: this.goodsId
}
}
this.$request(params).then(res => {
// console.log(res)
this.commentList = this.commentList.concat(res.data.data)
if (this.commentList.length >= res.data.total) {
this.isEmpty = true
}
}).catch(err => {
})
},
scrolltolower(e) {
if (!this.isEmpty) {
this.currentPage += 1
this.getCommentList()
}
},
onPreviewImage(imgList, index){
let imgData = []
imgList.map(item => {
imgData.push(this.$config.domain + item)
})
uni.previewImage({
current: index,
urls: imgData
})
}
},
};
</script>
<style scoped>
.item:first-child {
padding: 0 0 30rpx;
}
.item {
padding: 30rpx 0;
border-bottom: 2rpx solid #F5F5F5;
}
.user-info-box {
display: flex;
justify-content: space-between;
align-items: center;
}
.user-info-box .left {
display: flex;
align-items: center;
}
.user-info-box .left > image {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.rate-box {
}
.comment-content {
margin-top: 20rpx;
}
.comment-imgs {
margin-top: 30rpx;
display: flex;
align-items: center;
}
.comment-imgs > image {
width: 32%;
height: 180rpx;
margin-right: 30rpx;
border-radius: 15rpx;
}
</style>
<template>
<view>
<view class="mt-32 flex-between-center">
<view @click="onOpenStartTime" class="select-time">
<text v-if="!startTimeValue">选择开始时间</text>
<text v-else>{{ startTimeValue }}</text>
</view>
<text class="fs-30" style="color: #999999;">-</text>
<view @click="onOpenEndTime" class="select-time">
<text v-if="!endTimeValue">选择结束时间</text>
<text v-else>{{ endTimeValue }}</text>
</view>
</view>
<!-- 选择开始时间 -->
<u-datetime-picker :show="startTimeShow" v-model="startTime" title="开始时间" mode="datetime" :formatter="formatter"
:closeOnClickOverlay="true" @confirm="onConfirmStartTime"
@close="startTimeShow = false"></u-datetime-picker>
<!-- 选择结束时间 -->
<u-datetime-picker :show="endTimeShow" v-model="endTime" title="结束时间" mode="datetime" :formatter="formatter"
:closeOnClickOverlay="true" @confirm="onConfirmEndTime" @close="endTimeShow = false"></u-datetime-picker>
</view>
</template>
<script>
export default {
data() {
return {
startTimeShow: false,
startTimeValue: '',
startTime: new Date().getTime(),
endTimeShow: false,
endTime: new Date().getTime(),
endTimeValue: ''
}
},
methods: {
formatter(type, value) {
if (type === 'year') {
return `${value}年`
}
if (type === 'month') {
return `${value}月`
}
if (type === 'day') {
return `${value}日`
}
if (type === 'hour') {
return `${value}点`
}
if (type === 'minute') {
return `${value}分`
}
return value
},
onOpenStartTime() {
this.startTimeShow = true
},
onOpenEndTime() {
this.endTimeShow = true
},
onConfirmStartTime(e) {
// console.log(e)
this.startTimeShow = false
this.startTimeValue = this.$wskj.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
this.$emit('onConfirmStartTime', this.startTimeValue)
},
onConfirmEndTime(e) {
this.endTimeShow = false
this.endTimeValue = this.$wskj.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
this.$emit('onConfirmEndTime', this.endTimeValue)
},
}
}
</script>
<style scoped>
.select-time {
width: 322rpx;
height: 84rpx;
text-align: center;
line-height: 84rpx;
background: #f7f7f7;
border-radius: 5px;
font-size: 30rpx;
color: #999999;
}
</style>
\ No newline at end of file
<template>
<view id="drapdown">
<view class="tab-box">
<view
@click="onChangeDrapShow(index)"
:style="currentTab === index? activeStyle : inactiveStyle"
class="tab-item"
v-for="(item, index) in tabList" :key="index"
>
<text>{{ item.label }}</text>
<u-icon :color="getDownIcon(index).color" :size="getDownIcon(index).size" :name="getDownIcon(index).name"></u-icon>
</view>
</view>
<view class="drop-down-popup">
<u-transition :show="drapShow" @click="onClose" :custom-style="overlayStyle" mode="fade">
<view class="child-list" :style="{'height': contentHeight + 'rpx'}">
<view @click="onClickLabel(item, index)" v-for="(item, index) in currentChildList" :key="index" class="label-item">
<text>{{ item.label }}</text>
</view>
</view>
</u-transition>
</view>
</view>
</template>
<script>
export default {
props: {
tabList: { // 数据列表
type: Array,
default: []
},
iconSize: { // 上下图标大小
type: String,
default: '14'
},
activeStyle: { // 菜单选中的样式
type: Object,
default: {'color': '#3c9cff'}
},
inactiveStyle: { // 菜单非选中的样式
type: Object,
default: {'color': '#000'}
}
},
data() {
return {
currentTab: '',// 当前选中的tab
drapShow: false, // 蒙版显示隐藏
overlayStyle: {}, // 蒙版样式
contentHeight: 0 // 内容高度(用于动画)
};
},
computed: {
currentChildList(){ // 蒙版内展示的数据内容
if(this.currentTab !== '') {
return this.tabList[this.currentTab].children
} else {
return []
}
},
getDownIcon() { // 动态设置图标
return (index) => {
const style = {
size: this.iconSize,
color: this.inactiveStyle['color'],
name: 'arrow-up-fill'
}
if (this.drapShow && this.currentTab === index) { // 下拉菜单打开选项变蓝色
style.color = this.activeStyle['color']
style.name = 'arrow-down-fill'
}
return style;
}
}
},
mounted(){
this.init()
},
methods: {
// 初始化样式,决定蒙版位置,放在tab下
init(){
const query = uni.createSelectorQuery().in(this);
query.select('#drapdown').boundingClientRect(data => {
// console.log(data)
console.log(this.$u.sys())
let top = 0
// #ifdef H5
top += this.$u.sys().windowTop;
// #endif
this.overlayStyle = {
position: 'fixed',
top: `${data.top + top + 50}px`, // 50是tablist高度
left: 0,
right: 0,
zIndex: 998,
bottom: 0,
'background-color': `rgba(0, 0, 0, ${0.5})`
}
}).exec();
},
// 打开关闭蒙版
onChangeDrapShow(index){
if(this.drapShow && this.currentTab === index) {
this.currentTab = ''
this.contentHeight = 0
this.drapShow = false
} else {
this.currentTab = index
this.contentHeight = this.currentChildList.length * 90
this.drapShow = true
}
},
// 关闭蒙版
onClose(){
this.currentTab = ''
this.contentHeight = 0
this.drapShow = false
},
// 点击蒙版内数据
onClickLabel(item, index){
this.onClose()
this.$emit('click', item, index)
}
}
};
</script>
<style scoped>
.tab-box {
height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx;
background-color: #FFF;
}
.tab-item {
height: 100%;
display: flex;
align-items: center;
}
.tab-item > text{
margin-right: 10rpx;
}
.child-list {
background-color: #FFF;
overflow: hidden;
transition: all .15s;
}
.label-item {
padding: 24rpx 24rpx;
}
.mask-popup{
transition: opacity 300ms ease-out 0ms, -webkit-transform 300ms ease-out 0ms, transform 300ms ease-out 0ms;
transform-origin: 50% 50%;
}
</style>
<template>
<view class="flex-column flex-column-center">
<image class="w-236 h-236" src="@/static/emptydata.png"></image>
<text class="fs-24" style="color: #AAAAAA;">{{ emptyText }}</text>
</view>
</template>
<script>
export default {
props: {
emptyText: {
type: String,
default: '暂无数据'
}
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<view @click="$emit('click')" class="item" :style="{'height': height + 'rpx'}">
<image src="/static/logo.png" class="br-20 mr-20" :style="{'width': width + 'rpx', 'height': height + 'rpx'}">
</image>
<view class="item-right">
<view>
<view style="color: #333;">{{ $wskj.ellipsisText(title, 30) }}</view>
<view class="fs-24 mt-16 flex-between-center" style="color: #999999;">
<text>{{ sku }}</text>
<text v-if="styleType == 2">×1</text>
</view>
</view>
<view class="flex-between-center">
<text :style="{'color': priceColor}" class="fs-24">¥<text class="fw-600 fs-32">{{ price }}</text></text>
<view v-if="styleType == 1" class="fs-24" style="color: #999999;">数量:{{ number }}</view>
</view>
</view>
</view>
</template>
<script>
/**
* goods 商品信息组件
* @property {String} src 图片地址
* @property {String} width 图片宽度单位rpx
* @property {String} height 图片高度单位rpx
* @property {Boolean} title 商品标题
* @property {Boolean} sku 商品sku
* @property {Boolean} price 商品价格
* @property {Boolean} number 商品数量
* @property {String} styleType 样式,数量是否显示
* @property {String} priceColor 价格文字的颜色
*/
export default {
props: {
src: {
type: String,
default: '/static/logo.png'
},
width: {
type: String,
default: '180'
},
height: {
type: String,
default: '180'
},
title: {
type: String,
default: '太空小伙子'
},
sku: {
type: String,
default: 'M,菁纯版'
},
price: {
type: String | Number,
default: '999.00'
},
priceColor: {
type: String,
default: '#FF3D00'
},
number: {
type: String | Number,
default: 1
},
styleType: { // UI样式 1
type: String | Number,
default: 1
},
},
data() {
return {
}
},
created() {
}
}
</script>
<style scoped>
.item {
display: flex;
align-items: center;
}
.item-right {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>
\ No newline at end of file
<template>
<view class="com-list">
<view v-for="(item, index) in 3" :key="index"
@click="$wskj.authTo('/pages/home/goodsdetails?goodsId=' + item.id)" class="good-item" :style="{'margin-right': (index+1) % 2 === 0? '0' : '30rpx'}">
<image class="good-img" src="@/static/logo.png"></image>
<view class="bottom">
<text>商品标题</text>
<!-- 价格 销量 -->
<view class="sales-box">
<text class="fw-600 fs-40" style="color: #FE2C24;">{{ 100 }}</text>
<text class="fs-24" style="color: #999;">销量:2</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: ['goodsDataList'],
data() {
return {
};
}
};
</script>
<style scoped>
.com-list {
display: flex;
flex-wrap: wrap;
}
.good-item {
width: 47.8%;
display: flex;
flex-direction: column;
margin-bottom: 24rpx;
position: relative;
border-bottom-left-radius: 16rpx;
border-bottom-right-radius: 16rpx;
}
.good-img {
width: 100%;
height: 330rpx;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
}
.bottom {
padding: 20rpx;
display: flex;
flex-direction: column;
background-color: #FFF;
}
.sales-box {
margin-top: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
This diff is collapsed.
## mi-calendar 使用帮助
### 快速开始
使用 uni_modules 安装 (目前仅支持 uni_modules)
下载该文件后,放到uni_modules文件下,然后直接页面使用。
<mi-calendar :leaveDateList="[`2022-1-2`,`2022-1-4`]" :suspensionDateList="[`2022-01-05`]" :normalDateList="[`2022-1-3`]"></mi-calendar>
## leaveDateList
请假日期
## suspensionDateList
停课日期
## normalDateList
正常考勤日期
## change 切换日期
`@change="change"`
```
change(date){
console.log(date); // 日期 eg:'2022-01-01'
}
```
## changeMonth 切换月份
`@change="change"`
```
changeMonth(year, month){
console.log(year, month); // 日期 eg:2022, 6
}
```
<template>
<u-popup :show="show" :closeable="true" round="10" :closeOnClickOverlay="true"
@close="$emit('close')">
<view class="login-container">
<view class="center fw-600">
<text style="color: #333333;">获取您的昵称、头像、手机号</text>
</view>
<view class="center plr-32 mt-24 fs-28">
<text style="color: #999999;">获取用户头像、昵称、手机号信息,主要用于完善个人资料,向用户提供更好使用体验</text>
</view>
<view class="mt-32">
<view class="user-item">
<view class="mr-48">头像</view>
<view style="flex:1;">
<button class="header-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image v-if="!weChatHeaderImg" class="header" src="@/static/login/header.png"></image>
<image v-else class="header" :src="weChatHeaderImg"></image>
</button>
</view>
</view>
<view class="user-item">
<view class="mr-48">昵称</view>
<view style="flex:1;">
<input type="nickname" @input="onWeChatNickNameInput"
v-model="weChatNickName" placeholder="点击获取昵称" />
</view>
</view>
</view>
<view @click="onSaveUserInfo" class="save-btn">
<text>保存</text>
</view>
</view>
</u-popup>
</template>
<script>
export default {
props: ['show'],
data () {
return {
weChatHeaderImg: '',
weChatNickName: ''
}
},
methods: {
async onChooseAvatar(e){
// console.log(e)
const weChatHeaderImg = e.detail.avatarUrl
const result = await this.$wskj.uploadImg(weChatHeaderImg)
// console.log(result.url)
this.weChatHeaderImg = result.fullurl
},
onWeChatNickNameInput(e){
// 这里微信小程序开发者工具获取不到微信昵称
// 真机运行可以
console.log('获取微信昵称', e)
// this.weChatNickName = e.detail.value
},
onSaveUserInfo(){
this.$emit('onSaveUserInfo', { weChatHeaderImg: this.weChatHeaderImg, weChatNickName: this.weChatNickName })
}
}
}
</script>
<style scoped>
.login-container {
padding: 32rpx 0 20rpx;
}
.header {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.user-item {
width: 100%;
padding: 0 64rpx;
height: 120rpx;
border-top: 0.5px solid #CCCCCC;
border-bottom: 0.5px solid #CCCCCC;
display: flex;
align-items: center;
}
.user-item:nth-child(2) {
border-top: none;
}
.header-button {
display: flex;
justify-content: flex-start;
}
button::after {
border: none;
}
button {
display: block;
padding-left: 0px;
padding-right: 0px;
box-sizing: border-box;
text-decoration: none;
background-color: transparent;
border: none;
}
.save-btn {
margin: 52rpx auto 0;
width: 210px;
height: 40px;
text-align: center;
line-height: 40px;
color: #FFF;
background: #07c160;
border-radius: 4px;
}
</style>
<template>
<view>
<!--版本更新弹窗-->
<wskj-modal :show="updateShow" @confirm="onConfirmUpdate" @close="updateShow = false" @cancel="updateShow = false">
<view class="updateVer-box">
<!-- 升级内容 -->
<view class="center fw-600">
<text>版本更新</text>
</view>
<view class="center mt-20">
<text>检测到有新版本,您需要更新才可继续使用v:{{ newVersion }}</text>
</view>
</view>
</wskj-modal>
<!--进度条弹窗-->
<wskj-modal :show="progress" :closeOnClickOverlay="false" :showConfirmButton="false" :showCancelButton="true" @cancel="onPercentageModalCancel">
<view class="progress-modalbox">
<view class="center fw-600">
<text>下载中</text>
</view>
<view class="mt-30">
<u-line-progress style="width: 100%;" :percentage="downLoadPercentage" activeColor="#FF0000"
height="20"></u-line-progress>
</view>
</view>
</wskj-modal>
</view>
</template>
<script>
export default {
props: {
time: {
type: Number,
default: 0
},
packageUrl: { // 下载安装包地址
type: String,
default: ''
},
newVersion: { // 新版本号
type: String,
default: ''
},
force: { // 是否强制更新
type: [Boolean, Number],
default: false
}
},
data() {
return {
updateShow: false, // 是否确认更新弹窗
downloadTask: null, // 下载任务
progress: false, // 下载进度弹窗
downLoadPercentage: 0 // 下载进度
};
},
watch: {
random(newValue, oldValue) {
if(this.packageUrl) {
if(!this.force){ // 不强制更新
this.updateShow = true
} else { // 强制更新
this.updateShow = false
this.downLoadApp()
}
}
}
},
methods: {
// 点击确认更新
onConfirmUpdate() {
this.updateShow = false
this.downLoadApp()
},
// 下载APP
downLoadApp() {
this.progress = true
this.downloadTask = uni.downloadFile({ //执行下载
url: this.packageUrl, // 下载地址
//下载成功 onProgressUpdate监听到下载100这里才执行
success: downloadResult => {
// console.log(downloadResult)
this.progress = false // 关闭下载进度弹窗
if (downloadResult.statusCode == 200) {
uni.showModal({
title: '',
content: '更新成功,确定现在重启吗?',
showCancel: false,
confirmText: '重启',
confirmColor: '#7737FD',
success: (res) => {
if (res.confirm == true) {
plus.runtime.install( //安装
downloadResult.tempFilePath, {
force: true
},
function(res) {
utils.showToast(
'更新成功,重启中');
plus.runtime
.restart(); // 重启
// plus.runtime.quit(); 退出
}
);
}
}
});
} else {
this.$u.toast('下载失败')
}
},
fail: (err) => {
// this.$u.toast('下载失败')
this.progress = false // 关闭下载进度弹窗
},
});
// 监听下载进度
this.downloadTask.onProgressUpdate((res) => {
// console.log('下载进度' + res.progress);
// console.log('已经下载的数据长度' + res.totalBytesWritten);
// console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);
this.downLoadPercentage = res.progress
});
},
// 下载进度弹窗取消
onPercentageModalCancel() {
// console.log('取消')
if (this.enforce) {
this.$u.toast('本次更新不可取消')
} else {
this.downloadTask.abort()
this.progress = false
this.$u.toast('取消下载')
}
},
},
};
</script>
<style scoped>
.updateVer-box {
background-color: #FFF;
padding: 0 40rpx;
border-radius: 20rpx;
width: 500rpx;
}
.progress-modalbox {
width: 500rpx;
padding: 30rpx 40rpx;
background-color: #FFF;
border-radius: 20rpx;
}
</style>
\ No newline at end of file
<template>
<u-upload :capture="['album', 'camera']" :multiple="true" :fileList="fileList"
@afterRead="afterRead($event, 'fileList')" @delete="deletePic($event, 'fileList')" :maxCount="maxCount"
:width="width" :height="height">
<image :style="{'width': width + 'px', 'height': height + 'px'}" src="@/static/upload.png"></image>
</u-upload>
</template>
<script>
export default {
props: {
width: {
type: String,
default: '100'
},
height: {
type: String,
default: '100'
},
maxCount: {
type: String,
default: '9'
},
backUrl: { // 返回数组中哪个字段
type: String,
default: 'fullurl'
},
images: { // 重置fileList把images设为空即可
type: String,
default: ''
}
},
data() {
return {
fileList: [],
isManualUpdate: true
}
},
model: {
prop: 'images',
event: 'upload'
},
watch: {
// 只监听手动赋值,使用 deep 和 immediate
// 只上传成功执行,给images赋值不执行
images: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
if (this.isManualUpdate) {
this.fileList = [];
// console.log(newVal)
if (newVal) {
const urlList = newVal.split(',');
urlList.forEach((item) => {
let url = this.removeUrl(item, this.$config.domain);
const fullurl = url.indexOf('http') === -1 ? this.$config.domain + url : url;
this.fileList.push({
status: 'success',
message: '',
fullurl,
url,
});
});
}
this.isManualUpdate = false;
}
},
}
},
methods: {
// 删除图片
deletePic(event, type) {
this.fileList.splice(event.index, 1)
this.uploadParseData()
},
// 新增图片
async afterRead(event, type) {
let lists = [].concat(event.file)
let fileListLen = this.fileList.length
lists.map((item) => {
this.fileList.push({
...item,
status: 'uploading',
message: '上传中'
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.$wskj.uploadImg(lists[i].url)
let item = this[[type]][fileListLen]
// 这里需要根据后端接口返回的字段修改url,和fullurl的值
this.fileList.splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result,
fullurl: result
}))
fileListLen++
}
this.uploadParseData()
},
uploadParseData() {
console.log(this.fileList)
const images = this.fileList.map(item => item[this.backUrl]).join(",")
console.log(images)
// 标记不是手动更新 images,
this.isManualUpdate = false;
// #ifndef MP-WEIXIN
// this.$emit('upload', images)
// #endif
this.$emit('uploadImages', images)
// 微信小程序不支持使用v-model更新父组件变量的方法,所以小程序需要传递一个方法到子组件
// #ifdef MP-WEIXIN
// #endif
},
removeUrl(str, urlToRemove) {
// 使用正则表达式匹配要删除的URL,确保匹配整个字符串
// 注意:这里我们假设urlToRemove不包含查询字符串或路径,如果包含,需要调整正则表达式
const regex = new RegExp(urlToRemove, 'g');
// 使用replace方法替换匹配的URL为空字符串,即删除它们
return str.replace(regex, '');
},
// 用于图片回显使用,因为小程序无法检测到v-modal的改变
showImage(imgStr) {
const urlList = imgStr.split(',');
urlList.forEach((item) => {
let url = this.removeUrl(item, this.$config.domain);
const fullurl = url.indexOf('http') === -1 ? this.$config.domain + url : url;
this.fileList.push({
status: 'success',
message: '',
fullurl,
url,
});
});
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<u-modal
:show="show"
:title="title"
:confirmText="confirmText"
:cancelText="cancelText"
:showCancelButton="true"
:confirmColor="confirmColor"
:cancelColor="cancelColor"
:closeOnClickOverlay="true"
@confirm="$emit('confirm')"
@cancel="$emit('cancel')"
@close="$emit('close')"
>
<slot></slot>
</u-modal>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
confirmText: {
type: String,
default: '确认'
},
cancelText: {
type: String,
default: '取消'
},
confirmColor: {
type: String,
default: '#2979ff'
},
cancelColor: {
type: String,
default: '#606266'
}
},
created() {
},
};
</script>
<style scoped>
</style>
<template>
<u-overlay :show="show">
<view class="modal-main">
<view class="modal-content">
<slot></slot>
</view>
<view @click="$emit('close')" class="close">
<image src="@/static/close.png"></image>
</view>
</view>
</u-overlay>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
}
}
}
</script>
<style scoped>
.modal-main {
width: 90%;
margin: auto;
}
.modal-content {
min-height: 500rpx;
padding: 32rpx 32rpx 48rpx;
background-color: #FFF;
border-radius: 16rpx;
}
.close {
margin-top: 48rpx;
text-align: center;
}
.close > image {
width: 64rpx;
height: 64rpx;
}
</style>
\ No newline at end of file
<template>
<block>
<!-- #ifdef APP-PLUS -->
<view class="status_bar"></view>
<!-- #endif -->
<view class="navigation"
:style="[style]">
<image @click="$wskj.goBack" class="w-32 h-32 back" src="/static/back.png"></image>
<text>{{ title }}</text>
</view>
</block>
</template>
<script>
/**
* wskj-navigation 自定义导航栏
* @description 此组件一般用于自定义导航栏
* @property {Sting} title 页面标题
* @property {Sting} bgColor 导航栏背景颜色
* @example <wskj-navigation title="组件"></wskj-navigation>
*/
export default {
props: {
title: {
type: String,
default: '开通会员'
},
bgColor: {
type: String,
default: ''
}
},
computed: {
style(){
let style = {}
// #ifdef MP-WEIXIN
style['height'] = this.$wskj.capsulHeight + 'px'
style['paddingTop'] = this.$wskj.capsulTop + 'px'
// #endif
style['background-color'] = this.bgColor
return style
}
}
}
</script>
<style scoped>
.status_bar {
height: var(--status-bar-height);
}
.navigation {
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-weight: 600;
}
.back {
position: absolute;
left: 0;
}
</style>
<template>
<u-popup
:show="show"
:mode="mode"
:closeable="closeable"
:round="round"
@close="$emit('close')"
@open="$emit('open')"
>
<slot></slot>
</u-popup>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false
},
mode: {
type: String,
default: 'bottom'
},
closeable: {
type: Boolean,
default: true
},
round: {
type: String,
default: '10'
}
},
created() {
},
};
</script>
<style scoped>
</style>
export default {
// domain: 'http://192.168.0.191:8866', // 项目域名
// domain: 'http://192.168.0.125:9000', // 项目域名
// domain: 'http://43.138.9.102:80/prod-api', // 项目域名
// domain: 'http://192.168.0.112:8866', // 项目域名本地
domain: 'https://quzhiji.huanfawenhua.cn/prod-api', // 项目域名线上
cdnUrl: '', // 云储蓄静态资源图片域名
amapKey: '', // 高德web服务key
socketUrl: '' // websocket地址
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>
import App from './App'
import Vue from 'vue'
// // #ifndef VUE3
import uView from '@/uni_modules/uview-ui'
import wskj_function from "@/common/wskj_function.js"
import request from "@/common/request.js"
import config from "@/config.js"
//
// import VConsole from 'vconsole';
// let vConsole = new VConsole();
// console.log("test");
// const vconsole = require('vconsole')
// Vue.prototype.$vconsole = new vconsole() // 使用vconsole
import emptydata from "@/components/emptydata"
import comment from "@/components/comment"
import goodslist from "@/components/goodslist"
import wskjmodal from "@/components/wskj-modal"
import wskjpopup from "@/components/wskj-popup"
import uploadimage from "@/components/upload-image"
import wskjmodelclose from "@/components/wskj-model-close"
import goods from "@/components/goods"
// 全局组件
Vue.component("emptydata", emptydata)
Vue.component("comment", comment)
Vue.component("goodslist", goodslist)
Vue.component("wskj-modal", wskjmodal)
Vue.component("wskj-popup", wskjpopup)
Vue.component("upload-image", uploadimage)
Vue.component("wskj-model-close", wskjmodelclose)
Vue.component("goods", goods)
Vue.use(uView)
Vue.prototype.$wskj = wskj_function
Vue.prototype.$request = request
Vue.prototype.$config = config
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
// // #endif
// // #ifdef VUE3
// import {
// createSSRApp
// } from 'vue'
// export function createApp() {
// const app = createSSRApp(App)
// return {
// app
// }
// }
// // #endif
\ No newline at end of file
{
"name": "供纸",
"appid": "__UNI__89DAEC2",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"sassImplementationName": "node-sass",
/* 5+App特有相关 */
"app-plus": {
"permissions": [{
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
},
{
"name": "android.permission.READ_EXTERNAL_STORAGE"
}
],
"usingComponents": true,
"nvueStyleCompiler": "供纸",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": false,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* 模块配置 */
"modules": {
"Maps": {},
"Bluetooth": {},
"Camera": {},
"Geolocation": {}
},
/* 应用发布信息 */
"distribute": {
/* android打包配置 */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>"
],
"minSdkVersion": 21,
"targetSdkVersion": 30
},
/* ios打包配置 */
"ios": {
"idfa": false,
"dSYMs": false,
"privacyDescription": {
"NSBluetoothPeripheralUsageDescription": "使用蓝牙给硬件设备配网",
"NSBluetoothAlwaysUsageDescription": "使用蓝牙给硬件设备配网",
"NSPhotoLibraryUsageDescription": "获取图片",
"NSPhotoLibraryAddUsageDescription": "拍摄图片",
"NSCameraUsageDescription": "拍摄图片"
}
},
/* SDK配置 */
"sdkConfigs": {
"oauth": {
"weixin": {
"appid": "",
"UniversalLinks": ""
}
},
"maps": {
"amap": {
"name": "amapKivdPL7r",
"appkey_ios": "c9cbdc16c5eac4bc71b05bc90cb345c7",
"appkey_android": "c9cbdc16c5eac4bc71b05bc90cb345c7"
}
},
"geolocation": {
"amap": {
"name": "amapKivdPL7r",
"__platform__": ["android"],
"appkey_ios": "",
"appkey_android": "c9cbdc16c5eac4bc71b05bc90cb345c7"
}
},
"ad": {},
"push": {}
},
"icons": {
"android": {
"hdpi": "unpackage/res/icons/72x72.png",
"xhdpi": "unpackage/res/icons/96x96.png",
"xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi": "unpackage/res/icons/192x192.png"
},
"ios": {
"appstore": "unpackage/res/icons/1024x1024.png",
"ipad": {
"app": "unpackage/res/icons/76x76.png",
"app@2x": "unpackage/res/icons/152x152.png",
"notification": "unpackage/res/icons/20x20.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x": "unpackage/res/icons/167x167.png",
"settings": "unpackage/res/icons/29x29.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x": "unpackage/res/icons/80x80.png"
},
"iphone": {
"app@2x": "unpackage/res/icons/120x120.png",
"app@3x": "unpackage/res/icons/180x180.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x": "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* 快应用特有相关 */
"quickapp": {},
/* 小程序特有相关 */
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
"usingComponents": true,
"requiredPrivateInfos": ["getLocation", "chooseLocation"],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置定位"
}
},
"platforms": {
"weixin": {
"plugins": {
"map": {
"appid": "d96d5ccbb9b1780eeb627b5afeae1bfb"
}
}
}
}
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "2",
"h5": {
"sdkConfigs": {
"maps": {
"amap": {
"key": "17fe5039cdeb41a3ab930cc89baa015f",
"securityJsCode": "fafff93aac4d3a0625db37f650fde6df",
"serviceHost": "fafff93aac4d3a0625db37f650fde6df"
}
}
}
}
}
/* ios打包配置 */
/* SDK配置 */
\ No newline at end of file
This diff is collapsed.
{
"devDependencies": {
"sass": "^1.79.5"
},
"dependencies": {
"uview-ui": "^2.0.36",
"vconsole": "^3.15.1"
}
}
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
//蓝牙传输
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/Bluetooth",
"style": {
"navigationBarTitleText": "设置无线"
}
},
{
"path": "pages/map/device",
"style": {
"navigationBarTitleText": "设备列表",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/buzhi",
"style": {
"navigationBarTitleText": "代办",
"navigationStyle": "custom"
}
},
{
"path": "pages/home_index/home",
"style": {
"navigationBarTitleText": "取纸机",
"navigationStyle": "custom"
}
},
{
"path": "pages/home_index/positioning",
"style": {
"navigationBarTitleText": "取纸机",
"navigationStyle": "custom"
}
},
{
"path": "pages/home_index/public_toilets",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/home_index/cruise",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/home_index/personalCenter",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/devicesStatistics/devicesStatistics",
"style": {
"navigationBarTitleText": "设备耗纸统计",
"navigationStyle": "custom"
}
},
{
"path": "pages/devicesStatistics/inspectionRecords",
"style": {
"navigationBarTitleText": "G001公厕巡查记录"
}
},
{
"path": "pages/index/setPatrol",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/index/setRecords",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/index/gcdxc",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/index/gcxcjl",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/index/gclb",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/index/addPublicToilets",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/publicToiletsDetails/publicToiletsDetails",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/personalInfo/personalInfo",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/equipmentStatus/equipmentStatus",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/editPublicToiletsInfo/editPublicToiletsInfo",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/clockIn/clockIn",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/map/map",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/agreement",
"style": {
"navigationBarTitleText": "协议"
}
},
{
"path": "pages/about",
"style": {
"navigationBarTitleText": "关于我们",
"navigationStyle": "custom"
}
},
//通知信息
{
"path": "pages/index/infolist",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/addbuzhi",
"style": {
"navigationBarTitleText": "补纸"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"easycom": {
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
},
"uniIdRouter": {},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#FB262A",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/home_index/home",
"iconPath": "static/tabar/ic_home_def.png",
"selectedIconPath": "static/tabar/ic_home.png",
"text": "首页"
}, {
"pagePath": "pages/home_index/positioning",
"iconPath": "static/tabar/ic_positioning_def.png",
"selectedIconPath": "static/tabar/ic_positioning_sel.png",
"text": "定位"
},
{
"pagePath": "pages/home_index/cruise",
"iconPath": "static/tabar/ic_cruise_def.png",
"selectedIconPath": "static/tabar/ic_ic_cruise_sel.png",
"text": "巡查管理"
},
{
"pagePath": "pages/home_index/public_toilets",
"iconPath": "static/tabar/ic_public_toilets_def.png",
"selectedIconPath": "static/tabar/ic_public_toilets_sel.png",
"text": "公厕管理"
},
{
"pagePath": "pages/home_index/personalCenter",
"iconPath": "static/tabar/ic_my_def.png",
"selectedIconPath": "static/tabar/ic_my_sel.png",
"text": "个人中心"
}
]
}
}
\ No newline at end of file
<template>
<view class="content">
<view class="user_name">
<view class="text_user">无线名称</view>
<u-input class="user_pass" v-model="userInfo.name" border="bottom" placeholder="请输入您的无线名称"></u-input>
<view class="text_user">无线密码</view>
<view class="password">
<u-input class="user_pass" :type="type" border="bottom" v-model="userInfo.password"
placeholder="请输入您的无线密码">
<template slot="suffix">
<u-icon name="eye" @click="showpassword"></u-icon>
</template>
</u-input>
</view>
</view>
<view class="but_login" @click="writeData">下载</view>
</view>
</template>
<script>
export default {
data() {
return {
userInfo: {
name: '',
password: '',
},
type: 'password',
}
},
onLoad() {
// 这里是获取wifi信息的
uni.startWifi({
success: (result) => {
console.log(result)
uni.getConnectedWifi({
success: (res) => {
console.log(res)
this.userInfo.name = res.wifi.SSID
},
fail: (err) => {
console.log('获取Wi-Fi信息失败', err);
}
});
},
fail: (err) => {
console.log('start - Wi-Fi信息失败', err);
}
})
// uni.getNetworkType({
// success: function (res) {
// console.log(res);
// if (res.networkType === 'wifi') {
// uni.getConnectedWifi({
// success: function (wifi) {
// console.log(wifi.SSID); // 注意:SSID可能返回undefined或空字符串
// },
// fail: function (error) {
// console.error('获取WiFi信息失败:', error);
// }
// });
// }
// }
// });
},
onShow() {
},
methods: {
// 下载文件
oneClickDownload(url) {
// 获取缓存目录路径
let cachePath = plus.io.convertLocalFileSystemURL('_doc/') + "PaperTakingMachineConfig.txt"; // 获取应用私有目录下的缓存路径
console.log(cachePath);
// 假设文件路径为 '/path/to/your/PaperTakingMachineConfig.txt'
// const filePath = 'file:///storage/emulated/0/Android/data/com.yozo.vivo.office/cache/yozoCloud';
// /storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/doc/
// const fileSystemManager = uni.getFileSystemManager();
// 删除文件
uni.getSavedFileList({
success: function (res) {
console.log(res);
console.error('Failee');
uni.removeSavedFile({
filePath: res.fileList[0].filePath, // 文件路径
success: function (res) {
console.log('文件删除成功', res);
},
fail: function (err) {
console.error('文件删除失败', err);
}
});
}
});
const desiredFileName = 'PaperTakingMachineConfig.txt'; // 你想要的文件名
// 下载文件资源到本地
uni.downloadFile({
url: url, // 后端返回的线上文件路径
success: function(res) {
if (res.statusCode === 200) {
// 文件到本地
uni.saveFile({
tempFilePath: res.tempFilePath, //临时路径
success: function(data) {
var savedFilePath = data.savedFilePath
const tempFilePath = res.tempFilePath;
// 使用plus.io的文件管理API修改文件名
plus.io.resolveLocalFileSystemURL(savedFilePath, (entry) => {
entry.getParent((parentEntry) => {
// 将文件移动到同一目录但使用新文件名
entry.moveTo(parentEntry, '/' +
desiredFileName, (
newEntry) => {
// 文件名修改成功,newEntry.fullPath是新的文件路径
console.log(
'File renamed to:',
newEntry.fullPath);
// 你可以在这里打开文件或进行其他处理
uni.openDocument({
filePath: newEntry
.fullPath,
fileType: 'txt', // 指定文件类型(如果需要)
success: () => {
console
.log(
'File opened successfully'
);
},
fail: (
err) => {
console
.error(
'Failed to open file:',
err
);
}
});
}, (err) => {
console.error(
'Failed to move file:',
err);
});
});
});
// 在app端执行
// #ifdef APP-PLUS
let osname = plus.os.name
// 如果是安卓的话弹出提示
if (osname == 'Android') {
uni.showToast({
icon: 'none',
mask: true,
title: '保存成功',
duration: 1000
})
}
// #endif
uni.removeSavedFile({
filePath: res.tempFilePath,
complete: () => {
// 删除操作完成
},
});
//ios手机直接打开文件,手动存储文件到手机,Android手机从根目录创建文件夹,保存文件并改名
// setTimeout(() => {
// //打开文档查看
// uni.openDocument({
// filePath: data.savedFilePath,
// success: function(ress) {
// console.log("成功打开文件")
// },
// fail() {
// console.log("打开文件失败")
// }
// })
// }, 1000)
}
})
console.log('下载成功');
}
},
fail: function(res) {
console.log(res.errMsg);
},
complete: function(res) {
console.log(res.statusCode);
},
progress: function(res) {
console.log('下载进度' + res.progress);
}
});
},
writeData() {
let _this = this;
const params = {
url: '/uploadbluetooth',
data: {
id: _this.userInfo.name,
pwd: _this.userInfo.password,
},
};
this.$request(params).then(res => {
this.oneClickDownload(res.data.url)
})
},
login() {
let _this = this;
if (_this.userInfo.name.length == 0) {
this.$u.toast('请输入您的手机号')
return
}
if (_this.userInfo.password.length == 0) {
this.$u.toast('请输入您的密码')
return
}
return
const params = {
url: '/login',
data: {
username: _this.userInfo.name,
password: _this.userInfo.password,
},
}
this.$request(params).then(res => {
uni.setStorageSync('token', res.token);
_this.$wskj.switchTab('/pages/home_index/home');
})
//_this.$wskj.switchTab('/pages/home_index/home');
},
// 密码隐藏显示
showpassword() {
this.type = this.type === 'password' ? 'text' : 'password';
},
}
}
</script>
<style lang="less">
.title {
font-family: PingFangSC, PingFang SC;
font-weight: 600;
font-size: 42rpx;
color: #333333;
text-align: center;
}
.uist {
padding: 0 60rpx;
.item {
display: flex;
align-items: center;
justify-content: space-between;
line-height: 100rpx;
border-bottom: 1px solid #ccc;
text {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 34rpx;
color: #333333;
font-weight: bold;
}
view {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #333333;
}
}
}
/deep/ .u-input {
border: 2rpx solid #dadbde;
border-radius: 10rpx;
}
.wx_login {
display: flex;
justify-content: center;
align-items: center;
margin-top: 28px;
.iv_login {
width: 78rpx;
height: 78rpx;
}
}
.third_party {
display: flex;
margin-left: 66rpx;
margin-top: 120rpx;
align-items: center;
.border {
width: 238rpx;
border-bottom: 2rpx solid #999999;
}
.third {
padding: 0rpx 20rpx;
}
}
.content {
margin-top: 30rpx;
.privacy_policy {
margin-top: 20rpx;
margin-left: 87rpx;
font-size: 24rpx;
.text {
color: #FB4B4E;
}
}
.login_bg {
height: 180px;
width: 100%;
background: linear-gradient(91deg, #FCD4D2 0%, #FDEDEE 100%);
// view 显示一行
display: flex;
// view 俩边撑开
justify-content: space-around;
.login_title {
color: #FFFFFF;
margin-top: 70px;
}
.iv_login {
width: 100px;
height: 100px;
bottom: -30%;
}
}
.but_login {
width: 400rpx;
text-align: center;
justify-content: center;
line-height: 88rpx;
font-weight: 500;
margin: 0 auto;
color: white;
height: 88rpx;
border-radius: 44rpx 44rpx 44rpx 44rpx;
background: linear-gradient(89deg, #FFBFBC 0%, #FB262A 100%);
}
.user_name {
margin-top: -50rpx;
background-color: wheat;
border-radius: 20px 20px 0px 0px;
background: white;
padding: 100rpx 60rpx;
.user_phone {
font-size: 12px;
padding-top: 38rpx;
padding-bottom: 28rpx;
border-bottom: 2rpx solid #999999;
}
.text_user {
margin-top: 60rpx;
font-size: 16px;
font-weight: 600;
}
.user_pass {
margin-top: 20rpx;
font-size: 12px;
}
.password {
display: flex;
.iv_pass {
height: 30rpx;
width: 30rpx;
}
.user_pass {
margin-top: 20rpx;
font-size: 12px;
}
}
}
}
</style>
\ No newline at end of file
This diff is collapsed.
<template>
<view>
<button @click="searchBle">搜索蓝牙</button>
<view class="">
已连接:{{connectDeviceId}}
</view>
<view style="margin-top: 30upx;" :key="index" v-for="(item,index) in devices">
<button style="width: 400upx; color: #000000;" @click="onConn(item)">{{item.name}}</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
//搜索的蓝牙列表
devices: [],
// 连接的蓝牙设备
connectDeviceId: ""
}
},
methods: {
destroyed: function() {
let that = this
// 离开页面断开蓝牙连接
if (that.connectDeviceId != '') {
// 断开与低功耗蓝牙设备的连接
uni.closeBLEConnection({
deviceId: that.connectDeviceId,
success(res) {
that.connectDeviceId=""
}
})
}
},
// 搜索蓝牙
searchBle() {
var that = this
// 初始化蓝牙模块
uni.openBluetoothAdapter({
success(res) {
console.log(res, "初始化蓝牙模块")
// 监听搜索到新设备的事件
that.onDevice()
// 获取本机蓝牙适配器状态
uni.getBluetoothAdapterState({
success: function(res) {
console.log(res, '获取本机蓝牙适配器状态')
// 判断蓝牙适配器是否可用
if (res.available) {
// 是否正在搜索设备
if (res.discovering) {
// 停止搜索
that.stopFindBule()
}
//开始搜寻附近的蓝牙外围设备
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log(res, '开始搜寻附近的蓝牙外围设备')
}
})
} else {
console.log('本机蓝牙不可用')
}
},
})
}
})
},
// 监听搜索到新设备的事件
onDevice() {
console.log("监听搜索到新设备的事件---------------")
var that = this
//监听搜索到新设备的事件
uni.onBluetoothDeviceFound(function(devices) {
console.log('--------------new-----------------------' + JSON.stringify(devices))
var re = JSON.parse(JSON.stringify(devices))
console.log(re.devices[0].name + " " + re.devices[0].deviceId)
let name = re.devices[0].name
if ((name != "未知设备")&&(name != "")&&(name == "PaperTakingMachine")) {
let deviceId = re.devices[0].deviceId
that.devices.push({
name: name,
deviceId: deviceId,
services: []
})
}
})
},
// 停止搜寻附近的蓝牙外围设备
stopFindBule() {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log(res, '停止搜寻附近的蓝牙外围设备')
}
})
},
// 连接蓝牙
onConn(item) {
uni.showLoading()
var that = this
let deviceId = item.deviceId
uni.createBLEConnection({
deviceId: deviceId,
complete(res) {
uni.hideLoading()
if (res.errMsg == "createBLEConnection:ok") {
console.log("连接蓝牙-[" + item.name + "]--成功")
// 当前连接成功的设备ID
that.connectDeviceId = deviceId;
setTimeout(function() {
uni.showLoading({
title:"连接中",
})
// 获取蓝牙设备的所有服务/特征值
that.getBLEServices(deviceId)
}, 2000)
}else{
console.log(res,'createBLEConnection')
}
//连接成功 关闭搜索
that.stopFindBule()
},
})
},
// 获取蓝牙设备的所有服务/特征值
getBLEServices(_deviceId) {
var that = this;
let deviceId = _deviceId
// 获取蓝牙设备的所有服务
uni.getBLEDeviceServices({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: deviceId,
complete(res) {
console.log(res, '获取蓝牙设备' + deviceId + '的所有服务')
for (var s = 0; s < res.services.length; s++) {
let serviceId = res.services[s].uuid
// 获取蓝牙设备指定服务中所有特征值
uni.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId: serviceId,
success: (res) => {
let characteristics = res.characteristics;
console.log(
`deviceId = [${deviceId}] serviceId = [${serviceId}]`);
for (let c = 0; c < characteristics.length; c++) {
if (characteristics[c].properties.write === true) {
let uuid = characteristics[c].uuid;
console.log(
`deviceId = [${deviceId}] serviceId = [${serviceId}] characteristics=[${uuid}]`
);
that.updateDevices(deviceId, serviceId, uuid);
}
}
},
fail: (err) => {
uni.showToast({
title:"连接失败",
icon:"none"
})
console.error(
`Failed to get characteristics for deviceId = [${deviceId}] serviceId = [${serviceId}]`,
err);
}
})
}
},
fail(res) {
console.log(res)
},
})
},
// 更新设备信息
updateDevices(deviceId, serviceId, characteristicId) {
let that = this
for (let index in that.devices) {
if (that.devices[index].deviceId === deviceId) {
that.devices[index].services.push({
serviceId: serviceId,
characteristicId: characteristicId
});
break;
}
}
uni.showToast({
title:"连接成功",
icon:"none"
})
console.log(JSON.stringify(that.devices),'成功1');
}
}
}
</script>
<style>
</style>
\ No newline at end of file
This diff is collapsed.
<template>
<view class='container'>
<u-navbar autoBack placeholder bgColor="transparent"
style="background: linear-gradient(91deg, #FDEDEE 0%, #FFFFFF 100%);">
<view class="navSlot" slot="left">
<u-icon name="arrow-left" size="19"></u-icon>
<text class="title">关于我们</text>
</view>
</u-navbar>
<view class="flex-column flex-center-center pad-40">
<image class="wh-170 br-10 mb-40" :src="datainfo.filePath"></image>
<!-- <text style="color: #999999;font-size: 24rpx;">
{{datainfo.ruleContent}}
</text> -->
<rich-text :nodes="datainfo.ruleContent"></rich-text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
datainfo: {}
};
},
onLoad(options) {
this.getaboutus();
},
methods: {
getaboutus() {
const params = {
url: '/app/system/rule/aboutus',
data: {},
}
this.$request(params).then(res => {
console.log(res.rows[0])
this.datainfo = res.rows[0];
})
},
}
};
</script>
<style scoped>
.flex-column {
padding-top: 180rpx;
}
::v-deep .u-navbar {
width: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 11;
}
</style>
\ No newline at end of file
<template>
<view class='container'>
<u-parse v-if="content" :content="content"></u-parse>
</view>
</template>
<script>
export default {
data() {
return {
content: ''
};
},
onLoad(options) {
uni.setNavigationBarTitle({
title: options.title
})
this.content = decodeURIComponent(options.content)
}
};
</script>
<style scoped>
.container {
padding: 20rpx;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment