重构会员卡数据库

This commit is contained in:
2024-07-13 13:46:11 +08:00
parent e8b3a99607
commit f3c18408d3
55 changed files with 3802 additions and 272 deletions
+4 -4
View File
@@ -1,14 +1,14 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { UserCard, UserCardParam } from './model';
import type { OrderParam } from '@/shop/order/model';
import type { OrderParam } from '@/api/shop/order/model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 查询可用的会员卡
* @param {UserCardParam} params
* @return
*/
* @param {UserCardParam} params
* @return
*/
export async function findUseCard(params: OrderParam) {
const res = await request.get<ApiResult<PageResult<UserCard>>>(
MODULES_API_URL + '/booking/user-card/findUseCard',
+1 -1
View File
@@ -167,7 +167,7 @@ export async function updateUserStatus(userId?: number, status?: number) {
/**
* 修改推荐状态
*/
export async function updateUserRecommend(form) {
export async function updateUserRecommend(form: User) {
const res = await request.put<ApiResult<unknown>>(
SERVER_API_URL + '/system/user/recommend',
form
+17
View File
@@ -0,0 +1,17 @@
<script setup lang="ts">
</script>
<template>
<uni-card title="游泳馆" :border="false" :is-shadow="false">
<view class="flex justify-between">
<text>今日销量 0</text>
<text>今日出售 0</text>
<text>今日退票 0</text>
</view>
</uni-card>
</template>
<style scoped lang="scss">
</style>
+23 -14
View File
@@ -1,6 +1,6 @@
<template>
<view class="container">
<ws-select-merchant :merchantList="merchantList" :merchantId="merchantId" @done="reload" />
<!-- <ws-select-merchant :merchantList="merchantList" :merchantId="merchantId" @done="reload" />-->
<uv-tabs
:list="next7day"
:itemStyle="{ height: '58px' }"
@@ -9,9 +9,10 @@
:inactiveStyle="{ color: '#808080' }"
@change="onDateTime"
></uv-tabs>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-padding-wrap uni-common-mt relative">
<uni-segmented-control :current="current" :values="items" activeColor="#2ba91c" inActiveColor="#ff0000" @clickItem="onType" />
</view>
<uni-data-select :clear="false" style="background-color: #fff; width: 330rpx; position: absolute; right: 16rpx; top: 120rpx;" v-model="value" :localdata="merchantList" @change="change"></uni-data-select>
<!-- 状态说明 -->
<view class="uni-badge-wrap">
<view class="badge-item">
@@ -103,7 +104,6 @@
</uni-card>
<uv-gap height="70"></uv-gap>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
@@ -120,6 +120,7 @@ import { getWeek, getKey } from '@/utils/common';
const carStore = useCarStore();
const { orderInfo, totalPrice, carNum, merchant, type, dateTime, childrenPrice } = storeToRefs(carStore);
const value = uni.getStorageSync('currentId')
export default {
data() {
return {
@@ -161,7 +162,8 @@ export default {
// 是否同意协议
disabled: false,
// 购物车信息
showCarInfo: false
showCarInfo: false,
value
};
},
onLoad() {
@@ -331,7 +333,8 @@ export default {
isStatus: 0,
week,
dateTime: `${this.dateTime}`,
half: this.isHalf
half: this.isHalf,
admin: true
})
.then((list) => {
this.periodList = list;
@@ -344,13 +347,13 @@ export default {
icon: 'none'
});
uni.hideLoading();
if (err.message === '您还有未支付订单,请先支付') {
setTimeout(() => {
return uni.switchTab({
url: '/pages/order/order'
});
}, 1000);
}
// if (err.message === '您还有未支付订单,请先支付') {
// setTimeout(() => {
// return uni.switchTab({
// url: '/pages/order/order'
// });
// }, 1000);
// }
});
},
callPhone(phone) {
@@ -358,6 +361,11 @@ export default {
phoneNumber: phone
});
},
change(index) {
console.log('index>>: ',index);
uni.setStorageSync('currentId', index);
this.reload()
},
openCarInfo() {
// this.showCarInfo = !this.showCarInfo;
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
@@ -386,6 +394,7 @@ export default {
onField(item, period) {
// 已被预定
if (item.sold) {
uni.navigateTo({url: `/package/admin/order-detail?id=${item.orderInfoList[0].orderId}`})
return;
}
const app = this;
@@ -568,7 +577,7 @@ page {
.uni-padding-wrap {
width: 180rpx;
margin: 20rpx auto;
margin: 20rpx;
}
.uni-badge-wrap {
@@ -657,7 +666,7 @@ page {
justify-content: center;
align-items: center;
border-radius: 16rpx;
line-height: 1.3rem;
line-height: 1rem;
position: relative;
color: #333333;
background-color: #ffffff;
+454
View File
@@ -0,0 +1,454 @@
<template>
<view class="order" v-if="form.orderId">
<uni-card title="预定信息" :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :title="`${form.merchantName}`" :label="` `" :cellStyle="{ padding: '0', paddingBottom: '5px' }"
:border="false"/>
<block v-for="(item, index) in form.orderInfo" :key="index">
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.comments}`"
:cellStyle="{ padding: '0', paddingBottom: '5px' }"
:value="`¥${item.price}`"
:border="item.isChildren"
/>
<uv-cell :label="`成人票 ¥50`" :value="`x ${item.adultNum}`" v-if="item.isChildren"
:cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false"/>
<uv-cell :label="`儿童票 ¥35`" :value="`x ${item.childrenNum}`" v-if="item.isChildren"
:cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false"/>
</block>
</uv-cell-group>
</view>
</view>
<view slot="actions" class="card-actions">
<view class="web-text-heading">合计:¥{{ form.totalPrice }}</view>
<view class="web-text-danger">实付:¥{{ form.payPrice }}</view>
</view>
</uni-card>
<block v-if="form.orderNo">
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="web-cell web-cell-align-top">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff', padding: '8px 0' }" :border="false">
<uv-cell :title="`姓名`" :value="`${form.realName}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`手机号码`" :value="`${form.phone}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`订单号`" :value="`${form.orderId}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`订单编号`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<uv-parse :content="form.orderNo" :selectable="true"></uv-parse>
</template>
</uv-cell>
<uv-cell :title="`订单状态`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<view v-if="form.payStatus == 0">
<!-- <uv-count-down :time="form.timestamp" format="mm:ss"></uv-count-down> -->
<span style="color: #ff0000">未支付</span>
</view>
<view v-else>{{ orderStatus[form.orderStatus] }}</view>
</template>
</uv-cell>
<uv-cell :title="`下单时间`" :value="`${form.createTime}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`支付方式`" :value="`${payType[form.payType]}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`优惠说明`" :value="`${form.couponDesc ? form.couponDesc : '无'}`"
:cellStyle="{ padding: '8px' }" :border="false"/>
</uv-cell-group>
</view>
</uni-card>
</block>
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<!-- <uv-button-->
<!-- text="取消订单"-->
<!-- ></uv-button>-->
<uv-button
text="更换场地"
@click="openPicker"
></uv-button>
<!-- <uv-button-->
<!-- text="同意退款"-->
<!-- ></uv-button>-->
<!-- <uv-button-->
<!-- text="不同意退款"-->
<!-- ></uv-button>-->
</view>
<uv-picker ref="picker" :columns="fieldList" keyName="label" @confirm="confirm"></uv-picker>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload"/>
</view>
</template>
<script>
import * as OrderApi from '@/api/shop/order';
import {pageWechatDeposit} from '@/api/shop/wechatDeposit';
import * as PeriodApi from "@/api/booking/period";
import * as FieldApi from "@/api/booking/field";
import * as Api from "@/api/layout";
export default {
components: {},
data() {
return {
isLogin: false,
orderId: 0,
userId: 0,
form: {},
where: {
page: 1
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['全部订单', '未支付', '已支付', '已完成', '押金'],
orderStatus: ['未使用', '已完成', '已取消', '取消中', '退款申请中', '退款被拒绝', '退款成功', '客户端申请退款'],
payType: [
'余额支付',
'微信支付',
'会员卡支付',
'支付宝',
'现金',
'POS机',
'VIP月卡',
'VIP年卡',
'VIP次卡',
'IC月卡',
'IC年卡',
'IC次卡',
'免费',
'VIP充值卡',
'IC充值卡',
'积分支付',
'VIP季卡',
'IC季卡'
],
orderList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
h5_url: '',
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
fieldList: [],
// 服务器时间
serverTime: {},
dateTime: ''
};
},
async onLoad(option) {
this.orderId = option.id;
// 判断是否登录
await this.openLogin();
// 加载数据
await this.reload();
},
onShow() {
// 判断是否登录
this.openLogin();
},
// 触底函数
onReachBottom() {
const app = this;
const {where} = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
async reload() {
const app = this;
const {where, userId, orderId} = this;
if (userId === 0) {
app.openLogin();
return;
}
where.userId = userId;
uni.showLoading({
title: '数据读取中.'
});
await OrderApi.getOrder(orderId).then((data) => {
console.log('data: ', data);
app.form = data;
if(data){
this.getServerTime()
}
// 页面标题
if (data.orderStatus == 1) {
uni.setNavigationBarTitle({
title: '订单详情(已完成)'
});
}
uni.hideLoading();
});
// H5版网址
const h5_url = uni.getStorageSync('h5_url');
const tid = uni.getStorageSync('TenantId');
if (h5_url) {
app.h5_url = h5_url;
} else {
app.h5_url = `http://${tid}.h5.wsdns.cn`;
}
},
async openPicker() {
this.getBookingEmptyField()
this.$refs.picker.open();
},
confirm(e) {
console.log('confirm', e.value[0]);
console.log(this.form.orderId);
},
getBookingEmptyField(dateTime) {
const app = this
const { serverTime,merchantId,isHalf } = this;
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const startTime = serverTime.today === dateTime ? String(hours) + String(minutes) : undefined;
const week = this.week === 0 ? 7 : this.week;
app.fieldList = []
FieldApi.listField({
merchantId,
isStatus: 0,
week,
dateTime,
startTime,
half: isHalf
})
.then((list) => {
const arr = list.map(d => {
return {
label: d.fieldName,
// 其他属性值
id: d.fieldId
}
});
app.fieldList.push(arr);
uni.hideLoading();
})
.catch((err) => {
app.fieldList = [];
uni.showToast({
title: err.message,
icon: 'none'
});
uni.hideLoading();
});
},
getServerTime() {
const app = this
Api.getServerTime()
.then((result) => {
app.serverTime = result
app.form.orderInfo.map((d,i) => {
if(i === 0){
app.dateTime = d.dateTime
app.merchantId = d.merchantId
}
})
console.log(app.merchantId)
console.log(app.dateTime)
})
.catch();
},
navTo(url) {
uni.navigateTo({
url
});
},
onClickItem(e) {
const app = this;
const {where, userId} = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
if (userId == 0) {
app.openLogin();
return;
}
// 全部
if (index == 0) {
where.payStatus = undefined;
where.orderStatus = undefined;
}
// 未支付
if (index == 1) {
where.payStatus = 2;
}
// 已支付
if (index == 2) {
where.payStatus = 1;
}
// 已完成
if (index == 3) {
where.orderStatus = 1;
}
// 押金
if (index == 4) {
pageWechatDeposit({
uid: uni.getStorageSync('user_id')
}).then((res) => {
console.log('res: ', res);
app.orderList = res.list;
});
return false;
}
this.reload();
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom');
return false;
}
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.order {
.order-title {
padding: 20rpx 0;
border-bottom: 1px #eee solid;
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 10px;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
.web-text-heading {
font-size: 30rpx;
font-weight: 500;
}
.web-text-danger {
font-size: 30rpx;
font-weight: 500;
}
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
.close {
top: 60rpx !important;
}
.qrcode {
margin-top: 30rpx;
text-align: center;
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-around;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
</style>
+1
View File
@@ -1,5 +1,6 @@
<template>
<view class="order" v-if="isLogin">
orderNo: {{ orderNo }}
<uni-card title="预定信息" :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
+465
View File
@@ -0,0 +1,465 @@
<template>
<view class="admin-order-detail">
<view>
<uni-search-bar placeholder="订单号" @confirm="reload" :focus="true" v-model="orderId" />
</view>
<view class="order" v-if="form.orderId">
<uni-card title="预定信息" :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :title="`${form.merchantName}`" :label="` `" :cellStyle="{ padding: '0', paddingBottom: '5px' }"
:border="false"/>
<block v-for="(item, index) in form.orderInfo" :key="index">
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.comments}`"
:cellStyle="{ padding: '0', paddingBottom: '5px' }"
:value="`¥${item.price}`"
:border="item.isChildren"
/>
<uv-cell :label="`成人票 ¥50`" :value="`x ${item.adultNum}`" v-if="item.isChildren"
:cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false"/>
<uv-cell :label="`儿童票 ¥35`" :value="`x ${item.childrenNum}`" v-if="item.isChildren"
:cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false"/>
</block>
</uv-cell-group>
</view>
</view>
<view slot="actions" class="card-actions">
<view class="web-text-heading">合计:¥{{ form.totalPrice }}</view>
<view class="web-text-danger">实付:¥{{ form.payPrice }}</view>
</view>
</uni-card>
<block v-if="form.orderNo">
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="web-cell web-cell-align-top">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff', padding: '8px 0' }" :border="false">
<uv-cell :title="`姓名`" :value="`${form.realName}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`手机号码`" :value="`${form.phone}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`订单号`" :value="`${form.orderId}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`订单编号`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<uv-parse :content="form.orderNo" :selectable="true"></uv-parse>
</template>
</uv-cell>
<uv-cell :title="`订单状态`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<view v-if="form.payStatus == 0">
<!-- <uv-count-down :time="form.timestamp" format="mm:ss"></uv-count-down> -->
<span style="color: #ff0000">未支付</span>
</view>
<view v-else>{{ orderStatus[form.orderStatus] }}</view>
</template>
</uv-cell>
<uv-cell :title="`下单时间`" :value="`${form.createTime}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`支付方式`" :value="`${payType[form.payType]}`" :cellStyle="{ padding: '8px' }"/>
<uv-cell :title="`优惠说明`" :value="`${form.couponDesc ? form.couponDesc : '无'}`"
:cellStyle="{ padding: '8px' }" :border="false"/>
</uv-cell-group>
</view>
</uni-card>
</block>
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<!-- <uv-button-->
<!-- text="取消订单"-->
<!-- ></uv-button>-->
<uv-button
text="更换场地"
@click="openPicker"
></uv-button>
<!-- <uv-button-->
<!-- text="同意退款"-->
<!-- ></uv-button>-->
<!-- <uv-button-->
<!-- text="不同意退款"-->
<!-- ></uv-button>-->
</view>
<uv-picker ref="picker" :columns="fieldList" keyName="label" @confirm="confirm"></uv-picker>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload"/>
</view>
</view>
</template>
<script>
import * as OrderApi from '@/api/shop/order';
import {pageWechatDeposit} from '@/api/shop/wechatDeposit';
import * as PeriodApi from "@/api/booking/period";
import * as FieldApi from "@/api/booking/field";
import * as Api from "@/api/layout";
export default {
components: {},
data() {
return {
isLogin: false,
orderId: 0,
userId: 0,
form: {},
where: {
page: 1
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['全部订单', '未支付', '已支付', '已完成', '押金'],
orderStatus: ['未使用', '已完成', '已取消', '取消中', '退款申请中', '退款被拒绝', '退款成功', '客户端申请退款'],
payType: [
'余额支付',
'微信支付',
'会员卡支付',
'支付宝',
'现金',
'POS机',
'VIP月卡',
'VIP年卡',
'VIP次卡',
'IC月卡',
'IC年卡',
'IC次卡',
'免费',
'VIP充值卡',
'IC充值卡',
'积分支付',
'VIP季卡',
'IC季卡'
],
orderList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
h5_url: '',
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
fieldList: [],
// 服务器时间
serverTime: {},
dateTime: ''
};
},
async onLoad(option) {
this.orderId = option.id;
// 判断是否登录
await this.openLogin();
// 加载数据
// await this.reload();
},
onShow() {
// 判断是否登录
this.openLogin();
},
// 触底函数
onReachBottom() {
const app = this;
const {where} = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
async reload() {
const app = this;
const {where, userId, orderId} = this;
if (userId === 0) {
app.openLogin();
return;
}
where.userId = userId;
uni.showLoading({
title: '数据读取中.'
});
await OrderApi.getOrder(orderId).then((data) => {
app.form = data;
if(data){
this.getServerTime()
}
// 页面标题
if (data.orderStatus == 1) {
uni.setNavigationBarTitle({
title: '订单详情'
});
}
uni.hideLoading();
}).catch(err => {
console.log(err)
uni.showToast({
title: '订单不存在',
icon: 'none'
})
uni.hideLoading();
});
// H5版网址
const h5_url = uni.getStorageSync('h5_url');
const tid = uni.getStorageSync('TenantId');
if (h5_url) {
app.h5_url = h5_url;
} else {
app.h5_url = `http://${tid}.h5.wsdns.cn`;
}
},
async openPicker() {
this.getBookingEmptyField()
this.$refs.picker.open();
},
confirm(e) {
console.log('confirm', e.value[0]);
console.log(this.form.orderId);
},
getBookingEmptyField(dateTime) {
const app = this
const { serverTime,merchantId,isHalf } = this;
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const startTime = serverTime.today === dateTime ? String(hours) + String(minutes) : undefined;
const week = this.week === 0 ? 7 : this.week;
app.fieldList = []
FieldApi.listField({
merchantId,
isStatus: 0,
week,
dateTime,
startTime,
half: isHalf
})
.then((list) => {
const arr = list.map(d => {
return {
label: d.fieldName,
// 其他属性值
id: d.fieldId
}
});
app.fieldList.push(arr);
uni.hideLoading();
})
.catch((err) => {
app.fieldList = [];
uni.showToast({
title: err.message,
icon: 'none'
});
uni.hideLoading();
});
},
getServerTime() {
const app = this
Api.getServerTime()
.then((result) => {
app.serverTime = result
app.form.orderInfo.map((d,i) => {
if(i === 0){
app.dateTime = d.dateTime
app.merchantId = d.merchantId
}
})
console.log(app.merchantId)
console.log(app.dateTime)
})
.catch();
},
navTo(url) {
uni.navigateTo({
url
});
},
onClickItem(e) {
const app = this;
const {where, userId} = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
if (userId == 0) {
app.openLogin();
return;
}
// 全部
if (index == 0) {
where.payStatus = undefined;
where.orderStatus = undefined;
}
// 未支付
if (index == 1) {
where.payStatus = 2;
}
// 已支付
if (index == 2) {
where.payStatus = 1;
}
// 已完成
if (index == 3) {
where.orderStatus = 1;
}
// 押金
if (index == 4) {
pageWechatDeposit({
uid: uni.getStorageSync('user_id')
}).then((res) => {
console.log('res: ', res);
app.orderList = res.list;
});
return false;
}
this.reload();
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom');
return false;
}
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.order {
.order-title {
padding: 20rpx 0;
border-bottom: 1px #eee solid;
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 10px;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
.web-text-heading {
font-size: 30rpx;
font-weight: 500;
}
.web-text-danger {
font-size: 30rpx;
font-weight: 500;
}
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
.close {
top: 60rpx !important;
}
.qrcode {
margin-top: 30rpx;
text-align: center;
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-around;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
</style>
+23 -16
View File
@@ -2,9 +2,9 @@
<view class="container">
<!-- deBug信息 -->
<view v-if="merchant" class="web-debug web-text-success" style="display: none;">
场馆ID:{{ merchant.merchantId }} 场馆编号:{{ merchant.merchantCode }} 场馆名称:{{ merchant.merchantName }}
日期:{{ dateTime }}
星期:{{ week }}
场馆ID:{{ merchant.merchantId }} 场馆编号:{{ merchant.merchantCode }} 场馆名称:{{ merchant.merchantName }}
日期:{{ dateTime }}
星期:{{ week }}
订单总金额:{{ totalPrice }}
类型:{{ type }}
场地信息:{{ orderInfo }}
@@ -233,7 +233,7 @@
// 加载预定日期
app.next7day = next7day.map((d, i) => {
if (!app.dateTime && i == 0) {
if (!app.dateTime && i === 0) {
app.dateTime = d.dateTime
app.week = d.week
carStore.dateTime = d.dateTime
@@ -273,11 +273,11 @@
},
onType(e) {
const index = e.currentIndex
if (index == 0) {
if (index === 0) {
this.type = 0;
this.isHalf = 0;
}
if (index == 1) {
if (index === 1) {
this.type = 1;
this.isHalf = 1;
}
@@ -320,13 +320,20 @@
// },
getBookingPeriod() {
const {
serverTime
serverTime,
merchantId
} = this
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes()
const startTime = serverTime.today == this.dateTime ? String(hours) + String(minutes) : undefined
const week = this.week == 0 ? 7 : this.week
let startTime;
startTime = serverTime.today == this.dateTime ? String(hours) + String(minutes) : undefined
// 游泳馆当前21:30前都可以预定
if(merchantId === '3028' && Number(startTime) < 2130){
startTime = undefined
}
PeriodApi.listPeriod({
merchantId: this.merchantId,
isStatus: 0,
@@ -344,7 +351,7 @@
icon: 'none'
})
uni.hideLoading()
if(err.message == '您还有未支付订单,请先支付'){
if(err.message === '您还有未支付订单,请先支付'){
setTimeout(() => {
return uni.switchTab({
url: '/pages/order/order'
@@ -395,7 +402,7 @@
// 场地
// const f = this.fieldList[i2]
const key = getKey(`${this.dateTime}${item.timePeriod}${this.merchantId}${item.fieldId}`)
const index = app.selection.findIndex(d => d.key == key)
const index = app.selection.findIndex(d => d.key === key)
if (index >= 0) {
app.selection.splice(index, 1)
} else {
@@ -457,7 +464,7 @@
console.log('period: ',period);
// 是否支持儿童票
console.log('item.isChildren: ',item.isChildren);
if(item.isChildren == 1){
if(item.isChildren === 1){
console.log('item.isChildren2: ',item.isChildren);
carStore.childrenPrice = period.childrenPrice
}else{
@@ -477,11 +484,11 @@
const startTime = new Date(`${this.dateTime} ${timeText}:00`).getTime()
return startTime / 1000 || 0;
},
isActive(item) {
const index = this.selection.find(d => d.key == getKey(`${this.dateTime}${item.timePeriod}${this.merchantId}${item.fieldId}`))
const index = this.selection.find(d => d.key === getKey(`${this.dateTime}${item.timePeriod}${this.merchantId}${item.fieldId}`))
if(item.sold){
if(item.isHalf == 1){
if(item.isHalf === 1){
return 'web-bg-warning'
}
return 'web-bg-info'
@@ -504,7 +511,7 @@
// }
// },
remove(item) {
const index = this.selection.findIndex(d => d.key == item.key)
const index = this.selection.findIndex(d => d.key === item.key)
this.selection.splice(index, 1)
carStore.orderInfo = this.selection
},
@@ -698,4 +705,4 @@
}
}
}
</style>
</style>
+10 -5
View File
@@ -277,6 +277,8 @@ export default {
}).then((data) => {
if (data) {
app.hideUser = false;
app.userInfo.money = data.money;
console.log('money',app.userInfo.money)
app.userInfo.ouid = data.userId;
app.userInfo = Object.assign({}, app.userInfo, data);
}
@@ -321,12 +323,13 @@ export default {
Promise.all([app.getUserCard(), app.getPayment()]).then((res) => {
const userCard = res[0];
const payment = res[1];
// 当前可用会员卡
app.userCard = userCard;
// 支付方式列表
app.payment = payment.map((d) => {
if (d.type == 0) {
d.name = `${d.name} (余额¥${app.userInfo.balance})`;
d.name = `${d.name} (余额¥${app.userInfo.money || 0})`;
}
if (d.type == 2 && userCard) {
d.name = `${userCard.name}(¥${userCard.remainingMoney})`;
@@ -381,10 +384,12 @@ export default {
// 读取可用的会员卡
async getUserCard() {
const app = this;
const { payPrice } = this
return new Promise((resolve, reject) => {
const { merchantId } = this;
UserCardApi.findUseCard({
sid: merchantId
sid: merchantId,
payPrice
})
.then((result) => {
resolve(result);
@@ -590,7 +595,7 @@ export default {
const orderInfo = data;
// 调起微信支付
if (form.payType == 1) {
if (form.payType === 1) {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
@@ -636,7 +641,7 @@ export default {
// #endif
}
// 使用余额支付
if (form.payType == 0) {
if (form.payType === 0) {
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
@@ -664,7 +669,7 @@ export default {
}
// 使用会员卡支付
if (form.payType == 2) {
if (form.payType === 2) {
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
+48 -26
View File
@@ -2,24 +2,37 @@
<view>
<view class="coupon">
<block v-for="(item,index) in list" :key="index">
<view class="coupon-item web-cell">
<view class="coupon-item web-cell" v-if="item.type === 10">
<view class="coupon-bg">
<view class="title"><span class="price">8</span><span class="unit">元</span></view>
<view class="title"><span class="price">{{ item.reducePrice }}</span><span class="unit">元</span></view>
<view class="desc">满减劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">优惠券名称</view>
<view class="desc web-text-secondary">有效期至:2024-05-29</view>
<view class="title">{{ item.name }}</view>
<view class="desc web-text-secondary text-xs">有效期至:{{ item.endTime }}</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',color: '#ffffff', border: 'none'}"
:text="item.disabled ? '已领取': '领取'" :disabled="item.disabled" @click="save(item,index)"></uv-button>
</view>
</view>
<view class="coupon-item web-cell" v-if="item.type === 20">
<view class="coupon-bg2" v-if="item.type === 20">
<view class="title"><span class="price">{{ item.discount * 0.1 }}</span><span class="unit">折</span></view>
<view class="desc">折扣劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">{{ item.name }}</view>
<view class="desc web-text-secondary text-xs">有效期至:{{ item.endTime }}</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #ffd87b, #f8a900)',color: '#ffffff', border: 'none'}"
:text="item.disabled ? '已领取': '领取'" :disabled="item.disabled" @click="save(item,index)"></uv-button>
</view>
</view>
</block>
<!-- <uv-empty mode="order" v-if="list.length == 0"
icon="https://cdn.uviewui.com/uview/empty/data.png"></uv-empty> -->
<uni-load-more v-if="list.length > 0" :status="loadMore"></uni-load-more>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
@@ -109,22 +122,9 @@
title: '数据读取中.'
})
app.loadMore = 'loading'
const userCouponIds = []
const userCoupons = await app.getUserCoupon({
userId: uni.getStorageSync('user_id')
}).then(list => {
list.map(d => {
userCouponIds.push(d.couponId)
})
})
console.log('userCoupons: ',userCouponIds);
CouponApi.pageCoupon(where).then(res => {
const list = res.list.map(d => {
if(userCouponIds.indexOf(d.id) == 0){
d.disabled = true
}
return d;
});
const list = res.list;
if (app.list.length < res.count) {
app.list = app.list.concat(list)
app.canReset = true
@@ -133,7 +133,7 @@
app.canReset = false;
app.loadMore = 'no-more'
}
console.log('app.list: ',app.list);
uni.hideLoading()
app.isRefresh = false
}).catch(() => {
@@ -222,7 +222,7 @@
const app = this
item.couponId = item.id
app.list[index].disabled = true
UserCouponApi.addUserCoupon(item).then(msg => {
uni.showToast({
title: '领取成功',
@@ -231,7 +231,7 @@
setTimeout(() => {
app.reload()
},2000)
})
}
}
@@ -270,6 +270,7 @@
.coupon {
.coupon-item {
width: 700rpx;
height: 140rpx;
margin: 20rpx auto;
border-radius: 12rpx;
border-bottom: 1px #eee solid;
@@ -292,6 +293,24 @@
}
}
.coupon-bg2{
width: 140rpx;
height: 140rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 26rpx;
color: #fff;
border-radius: 12rpx 0 0 12rpx;
background: linear-gradient(to right, #ffd87b, #f8a900);
.price {
font-size: 50rpx;
}
}
.coupon-info {
padding: 20rpx;
display: flex;
@@ -300,7 +319,7 @@
line-height: 2rem;
}
}
.save-btn{
// margin-right: 20rpx;
}
@@ -367,4 +386,7 @@
font-size: 30rpx !important;
}
}
</style>
.text-xs{
font-size: 25rpx;
}
</style>
+2 -2
View File
@@ -121,7 +121,7 @@
// 获取收货地址列表
MerchantApi.pageMerchant({
merchantIds: app.sid
merchantCodes: app.sid
}).then(res => {
app.list = res.list;
})
@@ -281,4 +281,4 @@
margin-right: 20rpx;
}
}
</style>
</style>
+5 -5
View File
@@ -3,7 +3,7 @@
<!-- 其他功能 -->
<block v-for="(item, index) in list" :key="index">
<uni-card :border="false" :is-shadow="false" :padding="0">
<uv-cell :title="item.comments" :label="item.createTime" :value="`-${item.money}`" :cellStyle="{ padding: '10px 0' }" :border="false"></uv-cell>
<uv-cell :title="item.comments" :label="item.createTime" :value="`${item.price}`" :cellStyle="{ padding: '10px 0' }" :border="false"></uv-cell>
</uni-card>
</block>
<!-- 登录组件 -->
@@ -21,20 +21,20 @@ const userStore = useUserStore();
export default {
data() {
return {
userCardId: 0,
cardId: 0,
list: [],
isLogin: false,
logo: uni.getStorageSync('app_logo'),
};
},
onLoad(o) {
this.userCardId = o.id;
this.cardId = o.id;
this.reload();
},
methods: {
async reload(e) {
const app = this;
const { userCardId } = this;
const { cardId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
@@ -47,7 +47,7 @@ export default {
}
// 获取会员卡使用记录
Api.pageUserCardLog({userCardId}).then((res) => {
Api.pageUserCardLog({cardId}).then((res) => {
app.list = res.list;
});
},
+2 -1
View File
@@ -142,7 +142,8 @@ export default {
return;
}
where.userId = userId;
where.payStatus = 1;
where.status = 1;
where.sceneType = 'myCardAll';
app.loadMore = 'loading';
Api.pageUserCard(where)
.then((res) => {
+57 -15
View File
@@ -6,21 +6,36 @@
</view>
<view class="coupon">
<block v-for="(item,index) in list" :key="index">
<view class="coupon-item web-cell">
<view class="coupon-bg">
<view class="title"><span class="price">8</span><span class="unit">元</span></view>
<view class="desc">满减劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">优惠券名称</view>
<view class="desc web-text-secondary">有效期至:2024-05-29</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',color: '#ffffff', border: 'none'}"
text="去使用" @click="save"></uv-button>
</view>
</view>
<view class="coupon-item web-cell" v-if="item.type === 10">
<view class="coupon-bg">
<view class="title"><span class="price">{{ item.reducePrice }}</span><span class="unit">元</span></view>
<view class="desc">满减劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">{{ item.name }}</view>
<view class="desc web-text-secondary text-xs">有效期至:{{ item.endTime }}</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',color: '#ffffff', border: 'none'}"
text="去使用" :disabled="item.disabled" @click="toUse(`/pages/shop/shop`)"></uv-button>
</view>
</view>
<view class="coupon-item web-cell" v-if="item.type === 20">
<view class="coupon-bg2" v-if="item.type === 20">
<view class="title"><span class="price">{{ item.discount * 0.1 }}</span><span class="unit">折</span></view>
<view class="desc">折扣劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">{{ item.name }}</view>
<view class="desc web-text-secondary text-xs">有效期至:{{ item.endTime }}</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',color: '#ffffff', border: 'none'}"
text="去使用" :disabled="item.disabled" @click="toUse(`/pages/shop/shop`)"></uv-button>
</view>
</view>
</block>
<!-- <uv-empty mode="order" v-if="list.length == 0"
icon="https://cdn.uviewui.com/uview/empty/data.png"></uv-empty> -->
@@ -172,6 +187,11 @@
url
})
},
toUse(url){
uni.switchTab({
url
})
},
toPay(orderId) {
uni.navigateTo({
url: '/package/booking/confirm?id=' + orderId
@@ -246,6 +266,7 @@
.coupon {
.coupon-item {
width: 700rpx;
height: 140rpx;
margin: 20rpx auto;
border-radius: 12rpx;
border-bottom: 1px #eee solid;
@@ -268,6 +289,23 @@
}
}
.coupon-bg2{
width: 140rpx;
height: 140rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 26rpx;
color: #fff;
border-radius: 12rpx 0 0 12rpx;
background: linear-gradient(to right, #ffd87b, #f8a900);
.price {
font-size: 50rpx;
}
}
.coupon-info {
padding: 20rpx;
display: flex;
@@ -343,4 +381,8 @@
font-size: 30rpx !important;
}
}
.text-xs{
font-size: 25rpx;
}
</style>
+22 -14
View File
@@ -6,12 +6,12 @@
<view class="web-cell-content">
<view class="integral-bar web-cell web-cell-content">
<text class="web-text-placeholder">当前积分</text>
<text class="integral web-text-heading">{{ userInfo.points }}</text>
<text class="integral web-text-heading">{{ Math.floor(userInfo.users.integral) }}</text>
</view>
<view class="sign-in-btn">
<uv-button class="btn" :disabled="todaySign"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="签到" @click="onSign"></uv-button>
:text="`${todaySign ? '今日已签到' : '签到'}`" @click="onSign"></uv-button>
</view>
</view>
</view>
@@ -22,7 +22,7 @@
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
@@ -31,15 +31,11 @@
useUserStore
} from '@/store/modules/user';
import * as Api from '@/api/booking/integral';
import {
getWxOpenId
} from '@/api/passport/login';
import * as UserApi from '@/api/booking/users';
import {
openUrl
} from '@/utils/common';
import * as UserApi from '@/api/system/user'
import {
useTenantStore
} from '@/store/modules/tenant';
@@ -93,6 +89,16 @@
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
// 获取用户副表信息
UserApi.getByPhone({
phone: userInfo.phone
}).then((data) => {
if (data) {
app.userInfo.users = data;
app.userInfo.ouid = data.uid;
uni.setStorageSync('ouid',data.uid);
}
});
} else {
app.isLogin = false
}
@@ -102,7 +108,7 @@
dateTime
}).then(res => {
uni.hideLoading()
if (res.message == '您今天已经签到过了') {
if (res.message === '您今天已经签到过了') {
app.todaySign = true
}
app.selected = []
@@ -132,9 +138,11 @@
const app = this
app.openLogin()
app.todaySign = true
Api.addIntegral({}).then(res => {
UserApi.updatePointsBySign()
app.userInfo.points++
Api.addIntegral({
id: app.userInfo.users.id
}).then(res => {
// UserApi.updatePointsBySign()
// app.userInfo.points++
uni.showToast({
title: '签到成功',
icon: 'success'
@@ -168,7 +176,7 @@
}
</style>
<style lang="scss">
.integral-bar {
flex-direction: column;
@@ -189,4 +197,4 @@
margin-bottom: 50rpx;
}
}
</style>
</style>
+33 -16
View File
@@ -1,10 +1,10 @@
<template>
<view class="page" v-if="form">
<view class="flex justify-center"></view>
<button open-type="chooseAvatar" @chooseavatar="chooseAvatar" class="btn">
<uv-avatar :src="form.avatarUrl" size="100"></uv-avatar>
<text class="web-text-placeholder">更换头像</text>
</button>
<!-- <button open-type="chooseAvatar" @chooseavatar="chooseAvatar" class="btn">-->
<!-- <uv-avatar :src="form.avatarUrl" size="100"></uv-avatar>-->
<!-- <text class="web-text-placeholder">更换头像</text>-->
<!-- </button>-->
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
@@ -25,22 +25,38 @@
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.idCard" borderBottom>
<uv-cell title="身份证号码" :value="form.idCard">
<uv-cell title="证件号码" :value="form.idCard">
<template v-slot:value>
<uv-input placeholder="请输入身份证号" v-model="form.idCard" maxlength="18"></uv-input>
<uv-input placeholder="请输入证件号码" v-model="form.idCard"></uv-input>
</template>
<!-- <template v-slot:right-icon>
<uv-icon size="40rpx" name="camera" @click="onIdCard(item)"></uv-icon>
</template> -->
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.idCard" borderBottom>
<uv-cell title="上传证件">
<template v-slot:right-icon>
<uv-icon size="40rpx" name="camera" @click="onIdCard(item)"></uv-icon>
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.idCard" borderBottom>
<uv-cell>
<template v-slot:label>
<image src="https://oss.wsdns.cn/20240502/ec8c13037e7d4d40931b49fd45b23c61.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90" style="width: 80rpx" mode="widthFix" />
</template>
</uv-cell>
<uv-cell>
<template v-slot:label>
<image src="https://oss.wsdns.cn/20240502/ec8c13037e7d4d40931b49fd45b23c61.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90" style="width: 80rpx" mode="widthFix" />
</template>
</uv-cell>
</uv-form-item>
</uv-form>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="save"></uv-button>
text="提交审核" @click="save"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
@@ -130,14 +146,14 @@
const url = detail.avatarUrl
this.form.avatarUrl = await uploadOssByPath(url)
UserApi.updateUsers({
uid: this.form.uid,
id: this.form.id,
avatarUrl: `${this.form.avatarUrl}`
})
},
save() {
const app = this
const { form } = this
if(!uni.$uv.test.idCard(form.idCard)){
uni.showToast({
title: '请填写真实身份证号',
@@ -145,12 +161,13 @@
})
return false
}
UserApi.updateUsers({
phone: form.phone,
username: form.username,
realName: form.realName,
idCard: form.idCard,
uid: form.uid
id: form.id
}).then(res => {
uni.showToast({
title: '保存成功',
@@ -198,8 +215,8 @@
flex-direction: column;
padding: 20rpx 0;
}
.btn::after {
border: none;
}
</style>
</style>
+18
View File
@@ -288,6 +288,24 @@
"navigationBarTitleText": "场地管理",
"enablePullDownRefresh": false
}
},{
"path": "admin/order-detail",
"style": {
"navigationBarTitleText": "订单信息",
"enablePullDownRefresh": false
}
},{
"path": "admin/search",
"style": {
"navigationBarTitleText": "订单查询",
"enablePullDownRefresh": false
}
},{
"path": "admin/count",
"style": {
"navigationBarTitleText": "统计分析",
"enablePullDownRefresh": false
}
},
{
"path": "teacher/detail",
+12 -8
View File
@@ -3,7 +3,7 @@
<!-- 顶部距离 -->
<view class="header" :style="'margin-top: ' + statusBarHeight + 'px'"></view>
<!-- 用户信息 -->
<ws-user-card :data="userInfo" :is-login="isLogin" @openLogin="openLogin" />
<ws-user-card :data="userInfo" :users="users" :is-login="isLogin" @openLogin="openLogin" @done="reload" />
<block v-if="hideTools">
<uni-card :border="false" :padding="'18px 8px'">
<uv-skeleton rows="2" :loading="hideTools" :title="false"></uv-skeleton>
@@ -16,7 +16,7 @@
<!-- 收藏|关注|足迹|作品 -->
<!-- <ws-user-collect></ws-user-collect> -->
<!-- 我的资产 -->
<ws-my-asset :data="userInfo" :is-login="isLogin" @done="openLogin"></ws-my-asset>
<ws-my-asset :data="users" :is-login="isLogin" @done="openLogin"></ws-my-asset>
<!-- 我的订单 -->
<!-- <ws-user-order :order="order" :is-login="isLogin" @done="openLogin"></ws-user-order> -->
<!-- 其他功能 -->
@@ -54,6 +54,7 @@
</view>
</block>
</uni-card>
<!-- <ws-personal :form="users" ref="personal" @done="reload" />-->
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- 退出按钮 -->
@@ -89,7 +90,7 @@ export default {
merchantList: [],
server: [],
order: [],
hideUser: true,
users: {},
hideTools: true,
// 是否拥有场馆管理员权限
hasMerchantRole: false,
@@ -140,10 +141,13 @@ export default {
phone: userInfo.phone
}).then((data) => {
if (data) {
app.hideUser = false;
app.userInfo.ouid = data.uid;
uni.setStorageSync('ouid',data.uid);
app.users = data;
uni.setStorageSync('uid',data.id);
app.userInfo = Object.assign({}, app.userInfo, data);
if(!data.openId){
data.openId = app.userInfo.openid
updateUsers(data);
}
}
});
@@ -157,8 +161,8 @@ export default {
}).then((response) => {
uni.setStorageSync('openid',response.openid);
updateUsers({
uid: app.userInfo.ouid,
openid: response.openid,
id: uni.getStorageSync('uid'),
openId: response.openid,
sessionKey: response.session_key,
unionid: response.unionid
});
+9
View File
@@ -0,0 +1,9 @@
## 1.0.3(2023-07-02)
uv-overlay 由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
## 1.0.2(2023-06-29)
1. 优化,H5端禁止穿透滚动
## 1.0.1(2023-05-16)
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.0(2023-05-10)
1. 新增uv-overlay组件
@@ -0,0 +1,25 @@
export default {
props: {
// 是否显示遮罩
show: {
type: Boolean,
default: false
},
// 层级z-index
zIndex: {
type: [String, Number],
default: 10070
},
// 遮罩的过渡时间,单位为ms
duration: {
type: [String, Number],
default: 300
},
// 不透明度值,当做rgba的第四个参数
opacity: {
type: [String, Number],
default: 0.5
},
...uni.$uv?.props?.overlay
}
}
@@ -0,0 +1,85 @@
<template>
<uv-transition
:show="show"
mode="fade"
custom-class="uv-overlay"
:duration="duration"
:custom-style="overlayStyle"
@click="clickHandler"
@touchmove.stop.prevent="clear"
>
<slot />
</uv-transition>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from './props.js';
/**
* overlay 遮罩
* @description 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景
* @tutorial https://www.uvui.cn/components/overlay.html
* @property {Boolean} show 是否显示遮罩(默认 false )
* @property {String | Number} zIndex zIndex 层级(默认 10070 )
* @property {String | Number} duration 动画时长,单位毫秒(默认 300 )
* @property {String | Number} opacity 不透明度值,当做rgba的第四个参数 (默认 0.5 )
* @property {Object} customStyle 定义需要用到的外部样式
* @event {Function} click 点击遮罩发送事件
* @example <uv-overlay :show="show" @click="show = false"></uv-overlay>
*/
export default {
name: "uv-overlay",
emits: ['click'],
mixins: [mpMixin, mixin, props],
watch: {
show(newVal){
// #ifdef H5
if(newVal){
document.querySelector('body').style.overflow = 'hidden';
}else{
document.querySelector('body').style.overflow = '';
}
// #endif
}
},
computed: {
overlayStyle() {
const style = {
position: 'fixed',
top: 0,
left: 0,
right: 0,
zIndex: this.zIndex,
bottom: 0,
'background-color': `rgba(0, 0, 0, ${this.opacity})`
}
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
}
},
methods: {
clickHandler() {
this.$emit('click')
},
clear() {}
}
}
</script>
<style lang="scss" scoped>
/* #ifndef APP-NVUE */
$uv-overlay-top:0 !default;
$uv-overlay-left:0 !default;
$uv-overlay-width:100% !default;
$uv-overlay-height:100% !default;
$uv-overlay-background-color:rgba(0, 0, 0, .7) !default;
.uv-overlay {
position: fixed;
top:$uv-overlay-top;
left:$uv-overlay-left;
width: $uv-overlay-width;
height:$uv-overlay-height;
background-color:$uv-overlay-background-color;
}
/* #endif */
</style>
+88
View File
@@ -0,0 +1,88 @@
{
"id": "uv-overlay",
"displayName": "uv-overlay 遮罩层 全面兼容小程序、nvue、vue2、vue3等多端",
"version": "1.0.3",
"description": "uv-overlay 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景,uv-popup、uv-toast、uv-tooltip等组件就是用了该组件。",
"keywords": [
"uv-overlay",
"uvui",
"uv-ui",
"overlay",
"遮罩层"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools",
"uv-transition"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"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",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
## Overlay 遮罩层
> **组件名:uv-overlay**
创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景,uv-popup、uv-toast、uv-tooltip等组件就是用了该组件。
### <a href="https://www.uvui.cn/components/overlay.html" target="_blank">查看文档</a>
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
+33
View File
@@ -0,0 +1,33 @@
## 1.0.14(2023-12-29)
1. 修复上个版本引出的BUG
## 1.0.13(2023-12-26)
1. 修复抖音小程序滚到底不触发change的BUG
## 1.0.12(2023-11-20)
1. 修复issues反馈的问题uv-picker在组合式API的自定义组件中,columns动态赋值无法显示选项:https://gitee.com/climblee/uv-ui/issues/I8H0GQ
## 1.0.11(2023-10-11)
1. 将immediate-change默认值改为true,该值在于change回调的及时性,微信小程序生效
## 1.0.10(2023-08-25)
1. 增加round属性设置弹窗圆角,默认为0
## 1.0.9(2023-08-24)
1. 修复cli项目不返回值的问题
## 1.0.8(2023-08-04)
1. 优化
## 1.0.7(2023-08-02)
1. 改组件中删除uv-toolbar组件,请单独下载uv-toolbar组件
## 1.0.6(2023-07-02)
uv-picker 由于弹出层uv-popup的修改,打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/picker.html
## 1.0.5(2023-06-26)
1. 增加color参数
2. 增加activeColor参数
## 1.0.4(2023-06-15)
1. 修改支付宝报错的BUG
## 1.0.3(2023-06-12)
1. setColumnValues的使用统一化,避免某些平台报错
2. 取消change回调回传的组件实例,直接统一通过ref的方式调取setColumnValues方法
## 1.0.2(2023-05-23)
1. uv-toolbar组件新增下边框属性
## 1.0.1(2023-05-16)
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.0(2023-05-10)
uv-picker 选择器
@@ -0,0 +1,95 @@
export default {
props: {
// 是否展示顶部的操作栏
showToolbar: {
type: Boolean,
default: true
},
// 顶部标题
title: {
type: String,
default: ''
},
// 弹窗圆角
round: {
type: [String, Number],
default: 0
},
// 对象数组,设置每一列的数据
columns: {
type: Array,
default: () => []
},
// 是否显示加载中状态
loading: {
type: Boolean,
default: false
},
// 各列中,单个选项的高度
itemHeight: {
type: [String, Number],
default: 44
},
// 取消按钮的文字
cancelText: {
type: String,
default: '取消'
},
// 确认按钮的文字
confirmText: {
type: String,
default: '确定'
},
// 取消按钮的颜色
cancelColor: {
type: String,
default: '#909193'
},
// 确认按钮的颜色
confirmColor: {
type: String,
default: '#3c9cff'
},
// 文字颜色
color: {
type: String,
default: ''
},
// 选中文字的颜色
activeColor: {
type: String,
default: ''
},
// 每列中可见选项的数量
visibleItemCount: {
type: [String, Number],
default: 5
},
// 选项对象中,需要展示的属性键名
keyName: {
type: String,
default: 'text'
},
// 是否允许点击遮罩关闭选择器
closeOnClickOverlay: {
type: Boolean,
default: true
},
// 是否允许点击确认关闭选择器
closeOnClickConfirm: {
type: Boolean,
default: true
},
// 各列的默认索引
defaultIndex: {
type: Array,
default: () => [],
},
// 是否在手指松开时立即触发 change 事件。若不开启则会在滚动动画结束后触发 change 事件,只在微信2.21.1及以上有效
immediateChange: {
type: Boolean,
default: true
},
...uni.$uv?.props?.picker
}
}
@@ -0,0 +1,330 @@
<template>
<uv-popup
ref="pickerPopup"
mode="bottom"
:round="round"
:close-on-click-overlay="closeOnClickOverlay"
@change="popupChange"
>
<view class="uv-picker">
<uv-toolbar
v-if="showToolbar"
:cancelColor="cancelColor"
:confirmColor="confirmColor"
:cancelText="cancelText"
:confirmText="confirmText"
:title="title"
@cancel="cancel"
@confirm="confirm"
></uv-toolbar>
<!-- #ifdef MP-TOUTIAO -->
<picker-view
class="uv-picker__view"
:indicatorStyle="`height: ${$uv.addUnit(itemHeight)}`"
:value="innerIndex"
:immediateChange="immediateChange"
:style="{
height: `${$uv.addUnit(visibleItemCount * itemHeight)}`
}"
@pickend="changeHandler"
>
<!-- #endif -->
<!-- #ifndef MP-TOUTIAO -->
<picker-view
class="uv-picker__view"
:indicatorStyle="`height: ${$uv.addUnit(itemHeight)}`"
:value="innerIndex"
:immediateChange="immediateChange"
:style="{
height: `${$uv.addUnit(visibleItemCount * itemHeight)}`
}"
@change="changeHandler"
>
<!-- #endif -->
<!-- @pickend在这里为了解决抖音等滚到底不触发change兼容性问题 -->
<picker-view-column
v-for="(item, index) in innerColumns"
:key="index"
class="uv-picker__view__column"
>
<text
v-if="$uv.test.array(item)"
class="uv-picker__view__column__item uv-line-1"
v-for="(item1, index1) in item"
:key="index1"
:style="[{
height: $uv.addUnit(itemHeight),
lineHeight: $uv.addUnit(itemHeight),
fontWeight: index1 === innerIndex[index] ? 'bold' : 'normal'
},textStyle(index,index1)]"
>{{ getItemText(item1) }}</text>
</picker-view-column>
</picker-view>
<view
v-if="loading"
class="uv-picker--loading"
>
<uv-loading-icon mode="circle"></uv-loading-icon>
</view>
</view>
</uv-popup>
</template>
<script>
/**
* uv-picker
* @description 选择器
* @property {Boolean} showToolbar 是否显示顶部的操作栏(默认 true )
* @property {String} title 顶部标题
* @property {Array} columns 对象数组,设置每一列的数据
* @property {Boolean} loading 是否显示加载中状态(默认 false )
* @property {String | Number} itemHeight 各列中,单个选项的高度(默认 44 )
* @property {String} cancelText 取消按钮的文字(默认 '取消' )
* @property {String} confirmText 确认按钮的文字(默认 '确定' )
* @property {String} cancelColor 取消按钮的颜色(默认 '#909193' )
* @property {String} confirmColor 确认按钮的颜色(默认 '#3c9cff' )
* @property {String} color 文字颜色(默认 '' )
* @property {String} activeColor 选中文字的颜色(默认 '' )
* @property {String | Number} visibleItemCount 每列中可见选项的数量(默认 5 )
* @property {String} keyName 选项对象中,需要展示的属性键名(默认 'text' )
* @property {Boolean} closeOnClickOverlay 是否允许点击遮罩关闭选择器(默认 false )
* @property {Array} defaultIndex 各列的默认索引
* @property {Boolean} immediateChange 是否在手指松开时立即触发change事件(默认 false )
* @event {Function} close 关闭选择器时触发
* @event {Function} cancel 点击取消按钮触发
* @event {Function} change 当选择值变化时触发
* @event {Function} confirm 点击确定按钮,返回当前选择的值
*/
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from './props.js';
export default {
name: 'uv-picker',
emits: ['confirm','cancel','close','change'],
mixins: [mpMixin, mixin, props],
computed: {
// 为了解决支付宝不生效
textStyle(){
return (index,index1) => {
const style = {};
// #ifndef APP-NVUE
style.display = 'block';
// #endif
if(this.color) {
style.color = this.color;
}
if(this.activeColor && index1 === this.innerIndex[index]) {
style.color = this.activeColor;
}
return style;
}
}
},
data() {
return {
// 上一次选择的列索引
lastIndex: [],
// 索引值 ,对应picker-view的value
innerIndex: [],
// 各列的值
innerColumns: [],
// 上一次的变化列索引
columnIndex: 0,
}
},
watch: {
// 监听默认索引的变化,重新设置对应的值
defaultIndex: {
immediate: true,
handler(n) {
this.setIndexs(n, true)
}
},
// 监听columns参数的变化
columns: {
deep: true,
immediate: true,
handler(n) {
this.setColumns(n)
}
},
},
methods: {
open() {
this.$refs.pickerPopup.open();
},
close() {
this.$refs.pickerPopup.close();
},
popupChange(e) {
if(!e.show) this.$emit('close');
},
// 获取item需要显示的文字,判别为对象还是文本
getItemText(item) {
if (this.$uv.test.object(item)) {
return item[this.keyName]
} else {
return item
}
},
// 点击工具栏的取消按钮
cancel() {
this.$emit('cancel');
this.close();
},
// 点击工具栏的确定按钮
confirm() {
// 在这里使用deepClone拷贝后,vue3会自动转换成原始对象,这样处理是因为cli项目可能出现不返回值的情况
this.$emit('confirm', this.$uv.deepClone({
indexs: this.innerIndex,
value: this.innerColumns.map((item, index) => item[this.innerIndex[index]]),
values: this.innerColumns
}));
if(this.closeOnClickConfirm) {
this.close();
}
},
// 选择器某一列的数据发生变化时触发
changeHandler(e) {
const {
value
} = e.detail
let index = 0,
columnIndex = 0
// 通过对比前后两次的列索引,得出当前变化的是哪一列
for (let i = 0; i < value.length; i++) {
let item = value[i]
if (item !== (this.lastIndex[i] || 0)) { // 把undefined转为合法假值0
// 设置columnIndex为当前变化列的索引
columnIndex = i
// index则为变化列中的变化项的索引
index = item
break // 终止循环,即使少一次循环,也是性能的提升
}
}
this.columnIndex = columnIndex
const values = this.innerColumns
// 将当前的各项变化索引,设置为"上一次"的索引变化值
this.setLastIndex(value)
this.setIndexs(value)
this.$emit('change', {
value: this.innerColumns.map((item, index) => item[value[index]]),
index,
indexs: value,
// values为当前变化列的数组内容
values,
columnIndex
})
},
// 设置index索引,此方法可被外部调用设置
setIndexs(index, setLastIndex) {
this.innerIndex = this.$uv.deepClone(index)
if (setLastIndex) {
this.setLastIndex(index)
}
},
// 记录上一次的各列索引位置
setLastIndex(index) {
// 当能进入此方法,意味着当前设置的各列默认索引,即为“上一次”的选中值,需要记录,是因为changeHandler中
// 需要拿前后的变化值进行对比,得出当前发生改变的是哪一列
this.lastIndex = this.$uv.deepClone(index)
},
// 设置对应列选项的所有值
setColumnValues(columnIndex, values) {
// 替换innerColumns数组中columnIndex索引的值为values,使用的是数组的splice方法
this.innerColumns.splice(columnIndex, 1, values)
// 拷贝一份原有的innerIndex做临时变量,将大于当前变化列的所有的列的默认索引设置为0
let tmpIndex = this.$uv.deepClone(this.innerIndex)
for (let i = 0; i < this.innerColumns.length; i++) {
if (i > this.columnIndex) {
tmpIndex[i] = 0
}
}
// 一次性赋值,不能单个修改,否则无效
this.setIndexs(tmpIndex)
},
// 获取对应列的所有选项
getColumnValues(columnIndex) {
// 进行同步阻塞,因为外部得到change事件之后,可能需要执行setColumnValues更新列的值
// 索引如果在外部change的回调中调用getColumnValues的话,可能无法得到变更后的列值,这里进行一定延时,保证值的准确性
(async () => {
await this.$uv.sleep()
})()
return this.innerColumns[columnIndex]
},
// 设置整体各列的columns的值
setColumns(columns) {
this.innerColumns = this.$uv.deepClone(columns)
// 如果在设置各列数据时,没有被设置默认的各列索引defaultIndex,那么用0去填充它,数组长度为列的数量
if (this.innerIndex.length === 0) {
this.innerIndex = new Array(columns.length).fill(0)
}
},
// 获取各列选中值对应的索引
getIndexs() {
return this.innerIndex
},
// 获取各列选中的值
getValues() {
// 进行同步阻塞,因为外部得到change事件之后,可能需要执行setColumnValues更新列的值
// 索引如果在外部change的回调中调用getValues的话,可能无法得到变更后的列值,这里进行一定延时,保证值的准确性
(async () => {
await this.$uv.sleep()
})()
return this.innerColumns.map((item, index) => item[this.innerIndex[index]])
}
},
}
</script>
<style lang="scss" scoped>
$show-lines: 1;
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
.uv-picker {
position: relative;
&__view {
&__column {
@include flex;
flex: 1;
justify-content: center;
&__item {
@include flex;
justify-content: center;
align-items: center;
font-size: 16px;
text-align: center;
/* #ifndef APP-NVUE */
display: block;
/* #endif */
color: $uv-main-color;
&--disabled {
/* #ifndef APP-NVUE */
cursor: not-allowed;
/* #endif */
opacity: 0.35;
}
}
}
}
&--loading {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
@include flex;
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.87);
z-index: 1000;
}
}
</style>
+90
View File
@@ -0,0 +1,90 @@
{
"id": "uv-picker",
"displayName": "uv-picker 选择器 全面兼容vue3+2、app、h5、小程序等多端",
"version": "1.0.14",
"description": "uv-picker 此选择器用于单列,多列,多列联动的选择场景...",
"keywords": [
"uv-picker",
"uvui",
"uv-ui",
"picker",
"联动选择"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools",
"uv-popup",
"uv-loading-icon",
"uv-toolbar"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"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",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
## Picker 选择器
> **组件名:uv-picker**
此选择器用于单列,多列,多列联动的选择场景。
`uv-datetime-picker`等组件也用到了该组件,功能完善,需要特别注意的是`columns`参数的形式是数组嵌套。
# <a href="https://www.uvui.cn/components/picker.html" target="_blank">查看文档</a>
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
</a>
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
+18
View File
@@ -0,0 +1,18 @@
## 1.0.7(2023-11-20)
修复issues问题:https://gitee.com/climblee/uv-ui/issues/I8HDLO
## 1.0.6(2023-10-13)
1. 优化vue,内容有背景色,设置圆角被遮挡的情况
## 1.0.5(2023-09-10)
1. 修复H5默认层级过高的问题
2. 修复全局设置prop无效的问题
## 1.0.4(2023-08-08)
1. 修复修改zIndex不生效的BUG
## 1.0.3(2023-07-02)
uv-popup 弹出层,代码重构优化,性能翻倍,小程序体验性能更加,避免卡顿。打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/popup.html
## 1.0.2(2023-06-11)
1. 修复zIndex层级问题
## 1.0.1(2023-05-16)
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.0(2023-05-10)
1. 新增uv-popup组件
@@ -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,539 @@
<template>
<view
v-if="showPopup"
class="uv-popup"
:class="[popupClass, isDesktop ? 'fixforpc-z-index' : '']"
:style="[{zIndex: zIndex}]"
>
<view @touchstart="touchstart">
<!-- 遮罩层 -->
<uv-overlay
key="1"
v-if="maskShow && overlay"
:show="showTrans"
:duration="duration"
:custom-style="overlayStyle"
:opacity="overlayOpacity"
:zIndex="zIndex"
@click="onTap"
></uv-overlay>
<uv-transition
key="2"
:mode="ani"
name="content"
:custom-style="transitionStyle"
:duration="duration"
:show="showTrans"
@click="onTap"
>
<view
class="uv-popup__content"
:style="[contentStyle]"
:class="[popupClass]"
@click="clear"
>
<uv-status-bar v-if="safeAreaInsetTop"></uv-status-bar>
<slot />
<uv-safe-bottom v-if="safeAreaInsetBottom"></uv-safe-bottom>
<view
v-if="closeable"
@tap.stop="close"
class="uv-popup__content__close"
:class="['uv-popup__content__close--' + closeIconPos]"
hover-class="uv-popup__content__close--hover"
hover-stay-time="150"
>
<uv-icon
name="close"
color="#909399"
size="18"
bold
></uv-icon>
</view>
</view>
</uv-transition>
</view>
<!-- #ifdef H5 -->
<keypress v-if="maskShow" @esc="onTap" />
<!-- #endif -->
</view>
</template>
<script>
// #ifdef H5
import keypress from './keypress.js'
// #endif
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
/**
* PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://www.uvui.cn/components/popup.html
* @property {String} mode = [top|center|bottom|left|right] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @value left 左侧弹出
* @value right 右侧弹出
* @property {Number} duration 动画时长,默认300
* @property {Boolean} overlay 是否显示遮罩,默认true
* @property {Boolean} overlayOpacity 遮罩透明度,默认0.5
* @property {Object} overlayStyle 遮罩自定义样式
* @property {Boolean} closeOnClickOverlay = [true|false] 蒙版点击是否关闭弹窗,默认true
* @property {Number | String} zIndex 弹出层的层级
* @property {Boolean} safeAreaInsetTop 是否留出顶部安全区(状态栏高度),默认false
* @property {Boolean} safeAreaInsetBottom 是否为留出底部安全区适配,默认true
* @property {Boolean} closeable 是否显示关闭图标,默认false
* @property {Boolean} closeIconPos 自定义关闭图标位置,`top-left`-左上角,`top-right`-右上角,`bottom-left`-左下角,`bottom-right`-右下角,默认top-right
* @property {String} bgColor 主窗口背景色
* @property {String} maskBackgroundColor 蒙版颜色
* @property {Boolean} customStyle 自定义样式
* @event {Function} change 打开关闭弹窗触发,e={show: false}
* @event {Function} maskClick 点击遮罩触发
*/
export default {
name: 'uv-popup',
components: {
// #ifdef H5
keypress
// #endif
},
mixins: [mpMixin, mixin],
emits: ['change', 'maskClick'],
props: {
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
// message: 消息提示 ; dialog : 对话框
mode: {
type: String,
default: 'center'
},
// 动画时长,单位ms
duration: {
type: [String, Number],
default: 300
},
// 层级
zIndex: {
type: [String, Number],
// #ifdef H5
default: 997
// #endif
// #ifndef H5
default: 10075
// #endif
},
bgColor: {
type: String,
default: '#ffffff'
},
safeArea: {
type: Boolean,
default: true
},
// 是否显示遮罩
overlay: {
type: Boolean,
default: true
},
// 点击遮罩是否关闭弹窗
closeOnClickOverlay: {
type: Boolean,
default: true
},
// 遮罩的透明度,0-1之间
overlayOpacity: {
type: [Number, String],
default: 0.4
},
// 自定义遮罩的样式
overlayStyle: {
type: [Object, String],
default: ''
},
// 是否为iPhoneX留出底部安全距离
safeAreaInsetBottom: {
type: Boolean,
default: true
},
// 是否留出顶部安全距离(状态栏高度)
safeAreaInsetTop: {
type: Boolean,
default: false
},
// 是否显示关闭图标
closeable: {
type: Boolean,
default: false
},
// 自定义关闭图标位置,top-left为左上角,top-right为右上角,bottom-left为左下角,bottom-right为右下角
closeIconPos: {
type: String,
default: 'top-right'
},
// mode=center,也即中部弹出时,是否使用缩放模式
zoom: {
type: Boolean,
default: true
},
round: {
type: [Number, String],
default: 0
},
...uni.$uv?.props?.popup
},
watch: {
/**
* 监听type类型
*/
type: {
handler: function(type) {
if (!this.config[type]) return
this[this.config[type]](true)
},
immediate: true
},
isDesktop: {
handler: function(newVal) {
if (!this.config[newVal]) return
this[this.config[this.mode]](true)
},
immediate: true
},
// H5 下禁止底部滚动
showPopup(show) {
// #ifdef H5
// fix by mehaotian 处理 h5 滚动穿透的问题
document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
// #endif
}
},
data() {
return {
ani: [],
showPopup: false,
showTrans: false,
popupWidth: 0,
popupHeight: 0,
config: {
top: 'top',
bottom: 'bottom',
center: 'center',
left: 'left',
right: 'right',
message: 'top',
dialog: 'center',
share: 'bottom'
},
transitionStyle: {
position: 'fixed',
left: 0,
right: 0
},
maskShow: true,
mkclick: true,
popupClass: this.isDesktop ? 'fixforpc-top' : 'top',
direction: ''
}
},
computed: {
isDesktop() {
return this.popupWidth >= 500 && this.popupHeight >= 500
},
bg() {
if (this.bgColor === '' || this.bgColor === 'none' || this.$uv.getPx(this.round)>0) {
return 'transparent'
}
return this.bgColor
},
contentStyle() {
const style = {};
if (this.bgColor) {
style.backgroundColor = this.bg
}
if(this.round) {
const value = this.$uv.addUnit(this.round)
const mode = this.direction?this.direction:this.mode
style.backgroundColor = this.bgColor
if(mode === 'top') {
style.borderBottomLeftRadius = value
style.borderBottomRightRadius = value
} else if(mode === 'bottom') {
style.borderTopLeftRadius = value
style.borderTopRightRadius = value
} else if(mode === 'center') {
style.borderRadius = value
}
}
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
}
},
// #ifndef VUE3
// TODO vue2
destroyed() {
this.setH5Visible()
},
// #endif
// #ifdef VUE3
// TODO vue3
unmounted() {
this.setH5Visible()
},
// #endif
created() {
// TODO 处理 message 组件生命周期异常的问题
this.messageChild = null
// TODO 解决头条冒泡的问题
this.clearPropagation = false
},
methods: {
setH5Visible() {
// #ifdef H5
// fix by mehaotian 处理 h5 滚动穿透的问题
document.getElementsByTagName('body')[0].style.overflow = 'visible'
// #endif
},
/**
* 公用方法,不显示遮罩层
*/
closeMask() {
this.maskShow = false
},
// TODO nvue 取消冒泡
clear(e) {
// #ifndef APP-NVUE
e.stopPropagation()
// #endif
this.clearPropagation = true
},
open(direction) {
// fix by mehaotian 处理快速打开关闭的情况
if (this.showPopup) {
return
}
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
if (!(direction && innerType.indexOf(direction) !== -1)) {
direction = this.mode
}else {
this.direction = direction;
}
if (!this.config[direction]) {
return this.$uv.error(`缺少类型:${direction}`);
}
this[this.config[direction]]()
this.$emit('change', {
show: true,
type: direction
})
},
close(type) {
this.showTrans = false
this.$emit('change', {
show: false,
type: this.mode
})
clearTimeout(this.timer)
// // 自定义关闭事件
this.timer = setTimeout(() => {
this.showPopup = false
}, 300)
},
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
touchstart() {
this.clearPropagation = false
},
onTap() {
if (this.clearPropagation) {
// fix by mehaotian 兼容 nvue
this.clearPropagation = false
return
}
this.$emit('maskClick')
if (!this.closeOnClickOverlay) return
this.close()
},
/**
* 顶部弹出样式处理
*/
top(type) {
this.popupClass = this.isDesktop ? 'fixforpc-top' : 'top'
this.ani = ['slide-top']
this.transitionStyle = {
position: 'fixed',
zIndex: this.zIndex,
left: 0,
right: 0,
backgroundColor: this.bg
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPopup = true
this.showTrans = true
this.$nextTick(() => {
if (this.messageChild && this.mode === 'message') {
this.messageChild.timerClose()
}
})
},
/**
* 底部弹出样式处理
*/
bottom(type) {
this.popupClass = 'bottom'
this.ani = ['slide-bottom']
this.transitionStyle = {
position: 'fixed',
zIndex: this.zIndex,
left: 0,
right: 0,
bottom: 0,
backgroundColor: this.bg
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPopup = true
this.showTrans = true
},
/**
* 中间弹出样式处理
*/
center(type) {
this.popupClass = 'center'
this.ani = this.zoom?['zoom-in', 'fade']:['fade'];
this.transitionStyle = {
position: 'fixed',
zIndex: this.zIndex,
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column',
/* #endif */
bottom: 0,
left: 0,
right: 0,
top: 0,
justifyContent: 'center',
alignItems: 'center'
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPopup = true
this.showTrans = true
},
left(type) {
this.popupClass = 'left'
this.ani = ['slide-left']
this.transitionStyle = {
position: 'fixed',
zIndex: this.zIndex,
left: 0,
bottom: 0,
top: 0,
backgroundColor: this.bg,
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column'
/* #endif */
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPopup = true
this.showTrans = true
},
right(type) {
this.popupClass = 'right'
this.ani = ['slide-right']
this.transitionStyle = {
position: 'fixed',
zIndex: this.zIndex,
bottom: 0,
right: 0,
top: 0,
backgroundColor: this.bg,
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column'
/* #endif */
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPopup = true
this.showTrans = true
}
}
}
</script>
<style lang="scss" scoped>
.uv-popup {
position: fixed;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
&.top,
&.left,
&.right {
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
}
.uv-popup__content {
/* #ifndef APP-NVUE */
display: block;
overflow: hidden;
/* #endif */
position: relative;
&.left,
&.right {
/* #ifdef H5 */
padding-top: var(--window-top);
/* #endif */
/* #ifndef H5 */
padding-top: 0;
/* #endif */
flex: 1;
}
&__close {
position: absolute;
&--hover {
opacity: 0.4;
}
}
&__close--top-left {
top: 15px;
left: 15px;
}
&__close--top-right {
top: 15px;
right: 15px;
}
&__close--bottom-left {
bottom: 15px;
left: 15px;
}
&__close--bottom-right {
right: 15px;
bottom: 15px;
}
}
}
.fixforpc-z-index {
/* #ifndef APP-NVUE */
z-index: 999;
/* #endif */
}
.fixforpc-top {
top: 0;
}
</style>
+92
View File
@@ -0,0 +1,92 @@
{
"id": "uv-popup",
"displayName": "uv-popup 弹出层 全面兼容vue3+2、app、h5、小程序等多端",
"version": "1.0.7",
"description": "uv-popup 弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义。",
"keywords": [
"uv-popup",
"uvui",
"uv-ui",
"popup",
"弹出层"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools",
"uv-overlay",
"uv-transition",
"uv-icon",
"uv-status-bar",
"uv-safe-bottom"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"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",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
## Popup 弹出层
> **组件名:uv-popup**
弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义。
该组件已经放弃原来`uview2.x`的写法,参照了官方`uni-popup`的写法进行重构。在小程序端的性能大大提升,打开和关闭避免延迟,调用方法与之前相比也有所差异,具体请查看文档。
# <a href="https://www.uvui.cn/components/popup.html" target="_blank">查看文档</a>
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
</a>
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
@@ -0,0 +1,11 @@
## 1.0.4(2023-09-14)
1. 飞书小程序支持
## 1.0.3(2023-08-14)
1. 修复百度报错的BUG
## 1.0.2(2023-07-02)
uv-safe-bottom 修复,在百度程序,抖音小程序不生效的BUG
## 1.0.1(2023-05-16)
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.0(2023-05-10)
uv-safe-bottom 底部安全区组件
@@ -0,0 +1,67 @@
<template>
<view
class="uv-safe-bottom"
:style="[style]"
:class="[!isNvue && 'uv-safe-area-inset-bottom']"
>
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
/**
* SafeBottom 底部安全区
* @description 这个适配,主要是针对IPhone X等一些底部带指示条的机型,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。
* @tutorial https://www.uvui.cn/components/safeAreaInset.html
* @property {type} prop_name
* @property {Object} customStyle 定义需要用到的外部样式
*
* @event {Function()}
* @example <uv-status-bar></uv-status-bar>
*/
export default {
name: "uv-safe-bottom",
mixins: [mpMixin, mixin],
data() {
return {
safeAreaBottomHeight: 0,
isNvue: false,
};
},
computed: {
style() {
const style = {};
// #ifdef APP-NVUE || MP-TOUTIAO || MP-LARK
// nvue下,高度使用js计算填充
style.height = this.$uv.addUnit(this.$uv.sys()?.safeAreaInsets?.bottom, 'px');
// #endif
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle));
},
},
mounted() {
// #ifdef APP-NVUE
// 标识为是否nvue
this.isNvue = true;
// #endif
},
};
</script>
<style lang="scss" scoped>
.uv-safe-bottom {
/* #ifndef APP-NVUE */
width: 100%;
/* #endif */
}
/* #ifndef APP-NVUE */
// 历遍生成4个方向的底部安全区
@each $d in top, right, bottom, left {
.uv-safe-area-inset-#{$d} {
padding-#{$d}: 0;
padding-#{$d}: constant(safe-area-inset-#{$d});
padding-#{$d}: env(safe-area-inset-#{$d});
}
}
/* #endif */
</style>
@@ -0,0 +1,87 @@
{
"id": "uv-safe-bottom",
"displayName": "uv-safe-bottom 底部安全区 全面兼容小程序、nvue、vue2、vue3等多端",
"version": "1.0.4",
"description": "这个适配,主要是针对IPhone X等一些底部带指示条的机型,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。",
"keywords": [
"uv-safe-bottom",
"uvui",
"uv-ui",
"bottom",
"底部安全区"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"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",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
## SafeBottom 底部安全区
> **组件名:uv-safe-bottom**
这个适配,主要是针对IPhone X等一些底部带指示条的机型,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。
### <a href="https://www.uvui.cn/guide/safeAreaInset.html" target="_blank">查看文档</a>
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
@@ -0,0 +1,7 @@
## 1.0.2(2023-06-05)
1. 兼容渐变背景色
## 1.0.1(2023-05-16)
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.0(2023-05-10)
1. 新增uv-status-bar组件
@@ -0,0 +1,8 @@
export default {
props: {
bgColor: {
type: String,
default: 'transparent'
}
}
}
@@ -0,0 +1,54 @@
<template>
<view
:style="[style]"
class="uv-status-bar"
>
<slot />
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from './props.js';
/**
* StatbusBar 状态栏占位
* @description 本组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。
* @tutorial https://www.uvui.cn/components/statusBar.html
* @property {String} bgColor 背景色 (默认 'transparent' )
* @property {String | Object} customStyle 自定义样式
* @example <uv-status-bar></uv-status-bar>
*/
export default {
name: 'uv-status-bar',
mixins: [mpMixin, mixin, props],
data() {
return {
}
},
computed: {
style() {
const style = {}
// 状态栏高度,由于某些安卓和微信开发工具无法识别css的顶部状态栏变量,所以使用js获取的方式
style.height = this.$uv.addUnit(this.$uv.sys().statusBarHeight, 'px')
if(this.bgColor){
if (this.bgColor.indexOf("gradient") > -1) {// 渐变色
style.backgroundImage = this.bgColor;
}else{
style.background = this.bgColor;
}
}
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
}
},
}
</script>
<style lang="scss" scoped>
.uv-status-bar {
// nvue会默认100%,如果nvue下,显式写100%的话,会导致宽度不为100%而异常
/* #ifndef APP-NVUE */
width: 100%;
/* #endif */
}
</style>
@@ -0,0 +1,87 @@
{
"id": "uv-status-bar",
"displayName": "uv-status-bar 状态栏占位",
"version": "1.0.2",
"description": "状态栏占位组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。",
"keywords": [
"uv-status-bar",
"uvui",
"uv-ui",
"status-bar",
"状态栏"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"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",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+10
View File
@@ -0,0 +1,10 @@
## StatbusBar 状态栏占位
> **组件名:uv-status-bar**
本组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
+2
View File
@@ -0,0 +1,2 @@
## 1.0.0(2023-08-02)
1. 新增工具条组件
@@ -0,0 +1,40 @@
export default {
props: {
// 是否展示工具条
show: {
type: Boolean,
default: true
},
// 是否显示下边框
showBorder: {
type: Boolean,
default: false
},
// 取消按钮的文字
cancelText: {
type: String,
default: '取消'
},
// 确认按钮的文字
confirmText: {
type: String,
default: '确认'
},
// 取消按钮的颜色
cancelColor: {
type: String,
default: '#909193'
},
// 确认按钮的颜色
confirmColor: {
type: String,
default: '#3c9cff'
},
// 标题文字
title: {
type: String,
default: ''
},
...uni.$uv?.props?.toolbar
}
}
@@ -0,0 +1,109 @@
<template>
<view
:class="['uv-toolbar',{'uv-border-bottom':showBorder}]"
@touchmove.stop.prevent="noop"
v-if="show"
>
<view
class="uv-toolbar__cancel__wrapper"
hover-class="uv-hover-class"
>
<text
class="uv-toolbar__wrapper__cancel"
@tap="cancel"
:style="{
color: cancelColor
}"
>{{ cancelText }}</text>
</view>
<text
class="uv-toolbar__title uv-line-1"
v-if="title"
>{{ title }}</text>
<view
class="uv-toolbar__confirm__wrapper"
hover-class="uv-hover-class"
>
<text
class="uv-toolbar__wrapper__confirm"
@tap="confirm"
:style="{
color: confirmColor
}"
>{{ confirmText }}</text>
</view>
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from './props.js';
/**
* Toolbar 工具条
* @description
* @tutorial https://www.uvui.cn/components/toolbar.html
* @property {Boolean} show 是否展示工具条(默认 true )
* @property {Boolean} showBorder 是否展示工具条下方边框(默认 false )
* @property {String} cancelText 取消按钮的文字(默认 '取消' )
* @property {String} confirmText 确认按钮的文字(默认 '确认' )
* @property {String} cancelColor 取消按钮的颜色(默认 '#909193' )
* @property {String} confirmColor 确认按钮的颜色(默认 '#3c9cff' )
* @property {String} title 标题文字
* @event {Function}
* @example
*/
export default {
name: 'uv-toolbar',
emits: ['confirm', 'cancel'],
mixins: [mpMixin, mixin, props],
methods: {
// 点击取消按钮
cancel() {
this.$emit('cancel')
},
// 点击确定按钮
confirm() {
this.$emit('confirm')
}
}
}
</script>
<style lang="scss" scoped>
$show-lines: 1;
$show-hover: 1;
$show-border: 1;
$show-border-bottom: 1;
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
$uv-tips-color: #909193 !default;
$uv-main-color: #303133 !default;
$uv-primary: #3c9cff !default;
.uv-toolbar {
height: 42px;
@include flex;
justify-content: space-between;
align-items: center;
&__wrapper {
&__cancel {
color: $uv-tips-color;
font-size: 15px;
padding: 0 15px;
}
}
&__title {
color: $uv-main-color;
padding: 0 60rpx;
font-size: 16px;
flex: 1;
text-align: center;
}
&__wrapper {
&__confirm {
color: $uv-primary;
font-size: 15px;
padding: 0 15px;
}
}
}
</style>
+87
View File
@@ -0,0 +1,87 @@
{
"id": "uv-toolbar",
"displayName": "uv-toolbar 工具条",
"version": "1.0.0",
"description": "该组价是仅用于uv-ui中一个公共小工具,提供一个取消和确定的样式,可以设置标题,主要用于弹窗顶部的选择确定工具条",
"keywords": [
"uv-toolbar",
"uvui",
"uv-ui",
"工具条",
"工具"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"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",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+31
View File
@@ -0,0 +1,31 @@
## Toolbar 工具条
> **组件名:uv-toolbar**
该组价是仅用于uv-ui中一个公共小工具,提供一个取消和确定的样式,可以设置标题,主要用于弹窗顶部的选择确定工具条。
### 基本使用
```vue
<uv-toolbar title="标题文字"></uv-toolbar>
```
### Toolbar Props
| 属性名 | 类型 | 默认值 | 说明 |
|:-|:-|:-|:-|
| show | Boolean | true | 是否展示工具条 |
| showBorder | Boolean | false | 是否显示下边框 |
| cancelText | String | '取消' | 取消按钮的文字 |
| confirmText | String | '确定' | 确定按钮的文字 |
| cancelColor | String | '#909193' | 取消按钮的颜色 |
| confirmColor | String | '#3c9cff' | 确认按钮的颜色 |
| title | String | - | 标题文字 |
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
+3
View File
@@ -327,6 +327,9 @@ page {
.justify-between{
justify-content: space-between;
}
.space-around{
justify-content: space-around;
}
.text-gray-800{
color: rgb(31 41 55);
}
@@ -2,19 +2,19 @@
<uni-card :border="false" :padding="0">
<div class="user-asset web-cell">
<div class="web-cell-content web-text-center" @click="navTo(`/package/user/balance-log`)">
<text class="web-text-heading">{{ data.userId ? data.balance : '0.00' }}</text>
<text class="web-text-heading">{{ money }}</text>
<text class="web-text-secondary">余额</text>
</div>
<div class="web-cell-content web-text-center" @click="navTo(`/package/user/integral`)">
<text class="web-text-heading">{{ data.userId ? data.points : 0 }}</text>
<text class="web-text-heading">{{ integral }}</text>
<text class="web-text-secondary">积分</text>
</div>
<div class="web-cell-content web-text-center" @click="navTo(`/package/user/card`)">
<text class="web-text-heading">{{ data.userId ? data.cards : 0 }}</text>
<text class="web-text-heading">{{ cards }}</text>
<text class="web-text-secondary">会员卡</text>
</div>
<div class="web-cell-content web-text-center" @click="navTo(`/package/user/coupon`)">
<text class="web-text-heading">{{ data.userId ? data.coupon : 0 }}</text>
<text class="web-text-heading">{{ coupon }}</text>
<text class="web-text-secondary">优惠券</text>
</div>
</div>
@@ -24,8 +24,8 @@
<script>
import * as Api from '@/api/booking/userCard';
const tabBarLinks = ['/pages/index/index', '/pages/shop/shop', '/pages/order/order', '/pages/user/user'];
import { openUrl } from '@/utils/utils.js';
import * as CouponApi from "@/api/booking/userCoupon";
export default {
name: 'ws-user-order',
emits: ['done'],
@@ -40,19 +40,36 @@ export default {
}
},
data() {
return {};
},
onLoad() {
this.reload()
return {
money: 0,
integral: 0,
cards: 0,
coupon: 0
};
},
watch: {
data(val) {
this.money = val.money;
this.integral = Math.floor(val.integral);
this.reload();
}
},
created() {
const { data } = this;
this.money = data.money;
this.integral = Math.floor(data.integral);
this.reload()
},
methods: {
reload(){
Api.pageUserCard(where).then(res => {
console.log('res: ',res);
})
async reload(){
await Api.pageUserCard({sceneType: 'myCardAll'}).then(res => {
this.cards = res.count;
})
await CouponApi.data().then(res => {
this.coupon = res.toBeUsed;
})
},
navTo(item) {
console.log('item: ',item);
const app = this;
if (!this.isLogin) {
this.$refs.login.open('bottom');
@@ -0,0 +1,104 @@
<template>
<view class="page">
<view class="flex justify-center"></view>
<button open-type="chooseAvatar" @chooseavatar="chooseAvatar" class="btn">
<uv-avatar :src="form.avatarUrl" size="100"></uv-avatar>
<text class="web-text-placeholder">更换头像</text>
</button>
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell-align-top">
<uv-form labelPosition="left" :model="form" :rules="rules" ref="form">
<uv-form-item prop="form.phone" borderBottom>
<uv-cell title="手机号码" :value="form.phone">
<template v-slot:value>
<uv-input placeholder="请输入手机号码" disabled v-model="form.phone" maxlength="11"></uv-input>
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.username" borderBottom>
<uv-cell title="昵称" :value="form.username">
<template v-slot:value>
<uv-input type="nickname" placeholder="微信昵称" v-model="form.username" @change="changeUsername" ></uv-input>
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.realName" borderBottom>
<uv-cell title="真实姓名" :value="form.realName">
<template v-slot:value>
<uv-input placeholder="请输入真实姓名" v-model="form.realName" maxlength="11"></uv-input>
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.idCard" borderBottom>
<uv-cell title="身份证号码" :value="form.idCard">
<template v-slot:value>
<uv-input placeholder="请输入身份证号" v-model="form.idCard" maxlength="18"></uv-input>
</template>
<!-- <template v-slot:right-icon>
<uv-icon size="40rpx" name="camera" @click="onIdCard(item)"></uv-icon>
</template> -->
</uv-cell>
</uv-form-item>
</uv-form>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="save"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as Api from '@/api/booking/userCard';
export default {
name: 'ws-user-order',
emits: ['done'],
props: {
isLogin: {
type: Boolean,
default: false
},
form: {
type: Object,
default: {}
}
},
data() {
return {};
},
onLoad() {
this.reload()
},
methods: {
reload(){
Api.pageUserCard(where).then(res => {
console.log('res: ',res);
})
},
navTo(item) {
console.log('item: ',item);
const app = this;
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url: item
})
}
},
changeUsername(e){
console.log(e)
}
}
};
</script>
<style lang="scss">
</style>
+83
View File
@@ -0,0 +1,83 @@
{
"id": "ws-personal",
"displayName": "ws-personal",
"version": "1.0.0",
"description": "ws-personal",
"keywords": [
"ws-personal"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "",
"data": "",
"permissions": ""
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u",
"alipay": "u"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-vue": "u",
"app-nvue": "u",
"app-uvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
+1
View File
@@ -0,0 +1 @@
# ws-personal
@@ -1,145 +1,284 @@
<template>
<view class="user-card">
<view class="userinfo" @click="openLogin">
<view class="avatar" @click="navTo('/package/user/personal')">
<image v-if="isLogin" :src="data.avatar ? data.avatar : data.avatarUrl" mode="aspectFill"></image>
<!-- <uni-icons v-else type="contact-filled" color="#f3f3f3" size="100"></uni-icons> -->
</view>
<view class="nickname-box" v-if="isLogin">
<view class="nickname">
<text class="nickname-text">{{ data.nickname }}</text>
<block v-for="(item, index) in data.roles" :key="index">
<uni-tag v-if="item.roleName != '注册用户'" :text="item.roleName" type="warning" />
</block>
</view>
<view class="userid">
<view class="text">{{ data.mobile }}</view>
<!-- <uni-icons custom-prefix="iconfont" color="#333333" type="icon-erweima" size="20"></uni-icons> -->
</view>
</view>
<view class="nickname-box" v-else>
<view class="nickname">点击登录</view>
</view>
</view>
<view class="tool-btn" v-if="isLogin">
<!-- <uni-icons type="gear" color="#333333" :size="28"></uni-icons> -->
</view>
</view>
<view class="user-card" @click="openLogin" v-if="form">
<view class="userinfo" @click.stop="openPersonal">
<view class="avatar">
<image v-if="isLogin" :src="form.avatarUrl" mode="aspectFill"></image>
<!-- <uni-icons v-else type="contact-filled" color="#f3f3f3" size="100"></uni-icons> -->
</view>
<view class="nickname-box" v-if="isLogin">
<view class="nickname">
<text class="nickname-text">{{ form.username }}</text>
<block v-for="(item, index) in data.roles" :key="index">
<uni-tag v-if="item.roleName != '注册用户'" :text="item.roleName" type="warning"/>
</block>
</view>
<view class="userid">
<view class="text">{{ data.mobile }}</view>
<!-- <uni-icons custom-prefix="iconfont" color="#333333" type="icon-erweima" size="20"></uni-icons> -->
</view>
</view>
<view class="nickname-box" v-else>
<view class="nickname">点击登录</view>
</view>
</view>
<view class="tool-btn" v-if="isLogin">
<!-- <uni-icons type="gear" color="#333333" :size="28"></uni-icons> -->
</view>
</view>
<uni-popup ref="personal" type="center">
<view class="personal-box">
<view class="flex justify-center"></view>
<button open-type="chooseAvatar" @chooseavatar="chooseAvatar" class="btn">
<uv-avatar :src="form.avatarUrl" size="100"></uv-avatar>
<text class="web-text-placeholder">更换头像</text>
</button>
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell-align-top">
<uv-form labelPosition="left" :model="form" ref="form">
<uv-form-item prop="form.username" borderBottom>
<uv-cell title="昵称:" :value="form.username">
<template v-slot:value>
<input type="nickname" placeholder="微信昵称" v-model="form.username" @change="changeNickname" />
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.phone" borderBottom>
<uv-cell title="手机号码:" :value="form.phone">
<template v-slot:value>
<input placeholder="请输入手机号码" disabled v-model="form.phone" maxlength="11" />
</template>
</uv-cell>
</uv-form-item>
<!-- <uv-form-item prop="form.realName" borderBottom>-->
<!-- <uv-cell title="真实姓名:" :value="form.realName">-->
<!-- <template v-slot:value>-->
<!-- <input placeholder="请输入真实姓名" v-model="form.realName" maxlength="11" />-->
<!-- </template>-->
<!-- </uv-cell>-->
<!-- </uv-form-item>-->
<!-- <uv-form-item prop="form.idCard" borderBottom>-->
<!-- <uv-cell title="身份证号:" :value="form.idCard">-->
<!-- <template v-slot:value>-->
<!-- <input placeholder="请输入身份证号" v-model="form.idCard" maxlength="18" />-->
<!-- </template>-->
<!-- </uv-cell>-->
<!-- </uv-form-item>-->
</uv-form>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="save"></uv-button>
</view>
</view>
</uni-popup>
</template>
<script>
import { getUserInfo } from '@/uni_modules/ws-common/api/layout';
import { useUserStore } from '@/uni_modules/ws-common/store/modules/user';
const userStore = useUserStore();
import {uploadOssByPath} from "@/api/system/file";
import * as UserApi from "@/api/booking/users";
export default {
name: 'ws-user-card',
emits: ['openLogin'],
props: {
isLogin: {
type: Boolean,
default: false
},
data: {
type: Object,
default: {}
}
},
methods: {
openLogin() {
this.$emit('openLogin');
},
navTo(url) {
if (!this.isLogin) {
return false;
}
return uni.navigateTo({
url
});
},
reload() {
this.$emit('done');
}
name: 'ws-user-card',
emits: ['openLogin', 'done'],
props: {
isLogin: {
type: Boolean,
default: false
},
data: {
type: Object,
default: {}
},
users: {
type: Object,
default: {}
}
},
data() {
return {
form: {},
nickname: ''
};
},
watch: {
users(val) {
this.form = val;
}
},
created() {
},
methods: {
openLogin() {
this.$emit('openLogin');
},
openPersonal() {
this.$refs.personal.open('center');
},
navTo(url) {
if (!this.isLogin) {
return false;
}
return uni.navigateTo({
url
});
},
async chooseAvatar({detail}) {
const url = detail.avatarUrl
this.form.avatarUrl = await uploadOssByPath(url)
UserApi.updateUsers({
id: this.form.id,
avatarUrl: `${this.form.avatarUrl}`
})
},
onInput(nickname) {
console.log(nickname, 'nickname')
},
save() {
const app = this
const {form} = this
if (!uni.$uv.test.idCard(form.idCard)) {
uni.showToast({
title: '请填写真实身份证号',
icon: 'none'
})
return false
}
UserApi.updateUsers({
phone: form.phone,
username: form.username,
realName: form.realName,
idCard: form.idCard,
id: form.id
}).then(res => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
setTimeout(() => {
this.$emit('done');
this.$refs.personal.close();
}, 500)
})
},
reload() {
this.$emit('done');
},
changeNickname({detail: {value}}){
// console.log(1, e)
this.form.username = value;
}
}
};
</script>
<style lang="scss" scoped>
.personal-box {
background-color: #ffffff;
padding: 40rpx 10rpx;
border-radius: 20rpx;
}
.user-card {
width: 750rpx;
display: flex;
justify-content: space-between;
width: 750rpx;
display: flex;
justify-content: space-between;
.userinfo {
display: flex;
flex-direction: row;
margin: 0 20rpx;
.userinfo {
display: flex;
flex-direction: row;
margin: 0 20rpx;
.avatar {
width: 156rpx;
height: 156rpx;
border-radius: 100rpx;
background-color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
.avatar {
width: 156rpx;
height: 156rpx;
border-radius: 100rpx;
background-color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
image {
width: 156rpx;
height: 156rpx;
border-radius: 100rpx;
background-color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
}
}
image {
width: 156rpx;
height: 156rpx;
border-radius: 100rpx;
background-color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
}
}
.nickname-box {
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
.nickname-box {
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
.nickname {
font-size: 42rpx;
font-weight: 500;
display: flex;
align-items: center;
.nickname-text {
margin-right: 26rpx;
}
.role-name {
font-size: 24rpx;
}
}
.nickname {
font-size: 42rpx;
font-weight: 500;
display: flex;
align-items: center;
.userid {
display: flex;
align-items: center;
.nickname-text {
margin-right: 26rpx;
}
.text {
font-size: 24rpx;
color: #797979;
margin-right: 30rpx;
}
}
.role-name {
font-size: 24rpx;
}
}
.grade {
display: flex;
font-size: 24rpx;
color: $uni-text-color-placeholder;
.userid {
display: flex;
align-items: center;
.item {
margin-right: 30rpx;
color: $uni-text-color-placeholder;
}
}
}
}
.text {
font-size: 24rpx;
color: #797979;
margin-right: 30rpx;
}
}
.tool-btn {
margin-right: 50rpx;
}
.grade {
display: flex;
font-size: 24rpx;
color: $uni-text-color-placeholder;
.item {
margin-right: 30rpx;
color: $uni-text-color-placeholder;
}
}
}
}
.tool-btn {
margin-right: 50rpx;
}
}
.btn-bar {
width: 500rpx;
margin: auto;
clear: both;
}
.btn {
background: none;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.btn::after {
border: none;
}
</style>
+9 -9
View File
@@ -75,15 +75,15 @@ export const navTo = (url : string, query = {}, modo = 'navigateTo') => {
}
})
// 生成query参数
const queryStr = !util.isEmpty(query) ? '?' + util.urlEncode(query) : ''
// const queryStr = !util.isEmpty(query) ? '?' + util.urlEncode(query) : ''
// 普通页面, 使用navigateTo
modo === 'navigateTo' && uni.navigateTo({
url: `/${url}${queryStr}`
})
// modo === 'navigateTo' && uni.navigateTo({
// url: `/${url}${queryStr}`
// })
// 特殊指定, 使用redirectTo
modo === 'redirectTo' && uni.redirectTo({
url: `/${url}${queryStr}`
})
// modo === 'redirectTo' && uni.redirectTo({
// url: `/${url}${queryStr}`
// })
return true
}
@@ -202,7 +202,7 @@ export const isImage = (fileName : string) => {
});
};
export const getWeek = (text : string | number) => {
export const getWeek = (text : any) => {
const week = [
'星期日',
'星期一',
@@ -284,4 +284,4 @@ export const decrypt = (encrypt : any) => {
CryptoJS.AES.decrypt(encrypt, APP_SECRET);
const bytes = CryptoJS.AES.decrypt(encrypt, APP_SECRET);
return bytes.toString(CryptoJS.enc.Utf8);
};
};