更改动态导航栏

This commit is contained in:
wwz 2025-02-08 09:16:43 +08:00
parent 20b5539a82
commit 5add1f1282
33 changed files with 21325 additions and 72 deletions

View File

@ -1,6 +1,12 @@
<script>
import {
useNavbarStore
} from '@/stores/navbarStore';
export default {
onLaunch: function() {},
onLaunch: function() {
const store = useNavbarStore();
store.initNavbarHeight();
},
onShow: function() {},
onHide: function() {}
}
@ -9,4 +15,5 @@
<style lang="scss">
/*每个页面公共css */
@import "@/uni_modules/uview-plus/index.scss";
@import '@/common/css/flex.css';
</style>

48
common/css/flex.css Normal file
View File

@ -0,0 +1,48 @@
.flex-center{
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.flex-start{
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
}
.flex-end{
display: flex;
justify-content: flex-end;
align-items: center;
flex-wrap: wrap;
}
.flex-colum{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.flex-colum-start{
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.flex-colum-end{
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
}
.flex-between{
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.flex-around{
display: flex;
justify-content: space-around;
align-items: center;
flex-wrap: wrap;
}

1533
common/css/uni.scss Normal file

File diff suppressed because it is too large Load Diff

397
common/js/api.js Normal file
View File

@ -0,0 +1,397 @@
export default {
userwxlogin(data) { //登录
return uni.api.post("/login/auth/custom/login", data);
},
loginwxuserInfo(data) { //获取用户详情
return uni.api.get("/login/userInfo", data,false);
},
userwxlogins(data) { // 获取手机号
console.log(data)
return uni.api.post("/login/getPhoneNumber", data);
},
getShopExtend(data) { //获取图片 通过shopId和autokey
return uni.api.post("/common/shopExtend", data,false);
},
// 获取弹窗广告列表
getPopUpAd(data) {
return uni.api.get("/tbShopAd/list", data,false);
},
logincreateCardNo(data) { //获取会员码
return uni.api.get("/login/createCardNo", data);
},
productqueryShop(data) { //通过桌码获取店铺信息
return uni.api.get("/product/queryShop", data);
},
productChoseCount(data) { //就餐人数选择
return uni.api.post("/product/choseCount", data,false);
},
productqueryProduct(data) { //获取商品信息
return uni.api.post("/product/queryProduct", data, false);
},
productquerySpec(data) { //获取已上架商品规格
return uni.api.post("/product/querySpec", data, false);
},
cartAdd(data) { //添加到购物车
return uni.api.post("/product/addCart", data);
},
cleanCart(data) { //清空购物车
return uni.api.post("/product/cleanCart", data);
},
// 下单详情
getproductorderConfirm(data) {
return uni.api.get("/product/orderConfirm", data);
},
// 下单详情
getproductorderConfirm(data) {
return uni.api.get("/product/orderConfirm", data);
},
choseEatModel(data) { //就餐模式选择
return uni.api.post("/product/choseEatModel", data, false);
},
// 支付
payOrderPay(data) {
return uni.api.post("/pay/groupOrderPay", data);
},
// 会员支付
accountPay(data) {
return uni.api.get("/pay/accountPay", data);
},
orderPay(data) { //订单支付
return uni.api.post("/pay/orderPay", data);
},
cancelOrderPay(data) { //订单支付
return uni.api.post("/notify/cancel", data);
},
paymodfiyOrderInfo(data) { //查询订单支付状态
return uni.api.post("/pay/modfiyOrderInfo", data);
},
paymemeberIn(data) { //充值
return uni.api.post("/pay/memeberIn", data);
},
orderorderList(data) { //订单列表
return uni.api.get("/order/orderList", data);
},
orderorderInfo(data) { //订单回显
return uni.api.get("/order/orderInfo", data ,false);
},
removeOrder(data) { //删除订单
return uni.api.post("/order/rmOrder", data);
},
creatOrder(data) { //创建订单
return uni.api.post("/order/creatOrder", data);
},
useCoupon(data) { //订单选择优惠券
return uni.api.post("/order/useCoupon", data);
},
// 团购订单列表
groupOrderInfo(data) { //订单列表
return uni.api.get("/groupOrderInfo/list", data);
},
groupOrderInfoDetail(data) { //订单回显
return uni.api.get("/groupOrderInfo/get", data);
},
// 下单
creatGroupOrder(data) {
return uni.api.post("/groupOrderInfo/creatGroupOrder", data);
},
// 获取店铺会员信息
shopUserInfo(data) {
return uni.api.get("/user/shopUserInfo", data,false);
},
// 注册会员
openMember(data) {
return uni.api.post("/user/openMember", data);
},
// 会员填充手机号
upVipPhont(data) {
return uni.api.post("/user/upVipPhont", data);
},
// 优惠券数量
userCoupon(data) {
return uni.api.get("/user/userCoupon", data);
},
// 优惠加倍
yhqDouble(data) { //查询订单支付状态
return uni.api.post("/order/yhqDouble", data);
},
// 优惠卷详情
getYhqDouble(data) { //通过选中的商品规格查询价格
return uni.api.get("/order/getYhqDouble", data);
},
productqueryProductSku(data) { //通过选中的商品规格查询价格
return uni.api.get("/product/queryProductSku", data, false);
},
logingetPhoneNumber(data) { //小程序获取手机号
return uni.api.post("/login/getPhoneNumber", data);
},
cashierServiceloginregister(data) { //用户注册
return uni.api.post("/cashierService/login/register", data);
},
cashierServiceloginregister(data) { //APP登录
return uni.api.post("/login/app/login", data);
},
phoneValidateCode(data) { //验证码
return uni.api.get("/phoneValidateCode", data);
},
homehomePageUp(data) { //首页上半部分
return uni.api.post("/home/homePageUp", data);
},
home(data) { //首页上半部分
return uni.api.post("/home", data, false);
},
locationdistrict(data) { //获取行政区域(区,街道)
return uni.api.get("/location/district", data);
},
queryMemberAccount(data) { //获取余额明细
return uni.api.get("/pay/queryMemberAccount", data);
},
queryMemberPointsLog(data) { //获取余额明细
return uni.api.get("/api/points/member-points-log/page", data);
},
ordermineCoupons(data) { //我的优惠券
return uni.api.get("/order/mineCoupons", data, false);
},
getUserConpons(data) { //我的优惠券
return uni.api.post("/userConpons/find", data);
},
conponList(data) { //获取优惠券
return uni.api.post("/coupon/find", data);
},
ordergetYhqPara(data) { //获取优惠券参数列表
return uni.api.get("/order/getYhqPara", data);
},
orderfindCoupons(data) { //系统优惠券
return uni.api.get("/order/findCoupons", data);
},
tbPlatformDict(data) { //获取菜单
return uni.api.get("/tbPlatformDict", data);
},
distirictsubShopList(data) { //预约到店(店铺列表)
return uni.api.get("/distirict/subShopList", data);
},
distiricttopCommon(data) { //获取top部分(店铺列表)
return uni.api.get("/distirict/topCommon", data);
},
orderfindWiningUser(data) { //获取免单订单
return uni.api.get("/order/findWiningUser", data);
},
// 获取自己的免单订单
ordermineWinner(data) {
return uni.api.get("/order/mineWinner", data);
},
indexlist(data) { //商品列表(今日上新/热榜/咖啡饮品)
return uni.api.get("/distirict/productCate", data, false);
},
productproductInfo(data) { //商品详情
return uni.api.get("/product/productInfo", data);
},
distirictcomShopList(data) { //通用门店列表
return uni.api.get("/distirict/comShopList", data);
},
loginOut(data) { //退出登录
return uni.api.post("/login/loginOut", data);
},
productqueryShopIdByTableCode(data) { //通过桌码获取shopId
return uni.api.get("/product/queryShopIdByTableCode", data);
},
geocodelocation(data) { //根据经纬度获取信息
return uni.api.get("/location/geocode", data, false);
},
// 修改头像和昵称
upUserInfo(data) {
return uni.api.post("/login/upUserInfo", data);
},
loginresetPwd(data) { // 重置资金密码
return uni.api.post("/login/resetPwd", data);
},
paygetActive(data) { // 获取充值活动
return uni.api.get("/pay/getActive", data);
},
paygetShopByMember(data) { // 获取会员店铺信息
return uni.api.get("/pay/getShopByMember", data, false);
},
loginmpdifyPwd(data) { // 修改资金密码
return uni.api.get("/login/mpdifyPwd", data);
},
cashierServicesong(data) { // 获取所有歌曲,支持搜索及分页
return uni.api.get("/song", data, false);
},
cashierServicerecord(data) { // 点歌记录
return uni.api.get("/song/record", data);
},
cashierServicesongpost(data) { // 点歌
return uni.api.post("/song", data);
},
businessopenId(data) { // 获取openId
return uni.api.get("/login/wx/business/openId", data);
},
songsinging(data) { // 获取正在演唱的歌曲
return uni.api.get("/song/singing", data, false);
},
/**
* 获取排号信息
* @param {Object} param
*/
getQueueUpList(param) {
return uni.api.get("/callTable/queue", param);
},
/**
* 获取桌型列表
* @param {Object} param
*/
getQueueUpTablList(param) {
return uni.api.get("/callTable", param);
},
/**
* 获取排号状态
* @param {Object} param
*/
getQueueUpState(param) {
return uni.api.get("/callTable/state", param);
},
/**
* 获取订阅
* @param {Object} data
*/
setSubMsg(data) {
return uni.api.post("/callTable/subMsg", data,false);
},
/**
* 取号
* @param {Object} data
*/
getTakeNumber(data) {
return uni.api.post("/callTable/takeNumber", data, false);
},
/**
* 取消排号
* @param {Object} data
*/
cancelTakeNumber(data) {
return uni.api.post("/callTable/cancel", data, false);
},
/**
* 积分-基本设置-获取店铺设置
* @param {Object} param
*/
shopSettingInfo(shopId) {
return uni.api.get(`/api/points/basic-setting/${shopId}`);
},
/**
* 积分-兑换商品列表
* @param {Object} param
*/
pointsGoodsList(param) {
return uni.api.get("/api/points/goods-setting/page", param);
},
/**
* 积分-生成订单
* @param {Object} data
*/
pointsCreateOrder(data) {
return uni.api.post("/api/points/exchange-record/create", data);
},
/**
* 积分-支付订单
* @param {Object} data
*/
pointsPayOrder(data) {
return uni.api.post("/api/points/exchange-record/pay", data);
},
/**
* 积分-取消订单
* @param {Object} data
*/
pointsCancelOrder(data) {
return uni.api.post("/api/points/exchange-record/cancel", data);
},
/**
* 积分-001-会员积分账户信息
* @param {Object} param
*/
memberPointsInfo(memberId) {
return uni.api.get(`/api/points/member-points/${memberId}`, );
},
/**
* 积分-明细列表
* @param {Object} param
*/
memberPointsLogList(param) {
return uni.api.get("/api/points/member-points-log/page", param);
},
/**
* 积分-兑换记录-列表
* @param {Object} param
*/
exchangeRecordList(param) {
return uni.api.get("/api/points/exchange-record/page", param);
},
/**
* 积分-获取订单可用积分及抵扣金额
* @param {Object} param
*/
calcUsablePoints(param) {
return uni.api.get("/api/points/member-points/calc-usable-points", param);
},
/**
* 分享-获取邀请页数据
* @param {Object} param
*/
getByShopId(param) {
return uni.api.get("/tbShopShare/getByShopId", param);
},
/**
* 分享-邀请记录
* @param {Object} param
*/
shareRecord(param) {
return uni.api.get("/tbShopShare/record", param);
},
/**
* 分享-被邀请人进入页面时使用
* @param {Object} param
*/
shareHeOpen(param) {
return uni.api.post("/tbShopShare/open", param);
},
/**
* 分享-被邀请人领取优惠券时使用
* @param {Object} param
*/
shareReceive(param) {
return uni.api.post("/tbShopShare/receive", param);
},
}

34
common/js/api/queueUp.js Normal file
View File

@ -0,0 +1,34 @@
export default {
/**
* 获取排号信息
* @param {Object} param
*/
getQueueUpList(param) {
return uni.api.get("/callTable/queue", param);
},
/**
* 获取桌型列表
* @param {Object} param
*/
getQueueUpTablList(param) {
return uni.api.get("/callTable", param);
},
/**
* 取号
* @param {Object} data
*/
getTakeNumber(data) {
return uni.api.post("/callTable/takeNumber", data, false);
},
/**
* 取消排号
* @param {Object} data
*/
cancelTakeNumber(data) {
return uni.api.post("/callTable", data, false);
},
}

15879
common/js/city.json Normal file

File diff suppressed because it is too large Load Diff

1437
common/js/uqrCode.js Normal file

File diff suppressed because it is too large Load Diff

231
common/js/websocket.js Normal file
View File

@ -0,0 +1,231 @@
class webSocketUtils {
constructor(url, time, params) {
this.socketTask = null;
this.is_open_socket = false; //避免重复连接
this.url = url;
this.params = params ? params : null; ////是否初始化请求
this.connectNum = 1; // 重连次数
//这个参数是防止重连失败之后onClose方法会重复执行reconnect方法导致重连定时器出问题
//连接并打开之后可重连,且只执行重连方法一次
this.canReconnect = false; // 是否可以重连
//心跳检测
this.timeout = time ? time : 5000; //多少秒执行检测
this.heartbeatInterval = null; //检测服务器端是否还活着
this.reconnectTimeOut = null; //重连之后多久再次重连
try {
return this.connectSocketInit({
data: this.params,
type: 'connectSocketInit',
});
} catch (e) {
// console.log('catch');
this.reconnect();
}
}
// 进入这个页面的时候创建websocket连接【整个页面随时使用】
connectSocketInit(data) {
let _this = this;
this.data = data;
// #ifdef MP-WEIXIN
this.socketTask = uni.connectSocket({
// #endif
// #ifdef MP-ALIPAY
my.connectSocket({
// #endif
url: this.url,
success: (res) => {
console.log('创建websocketc成功...');
// uni.hideLoading();
// 返回实例
return this.socketTask;
},
fail: (res) => {
}
});
// #ifdef MP-WEIXIN
this.socketTask.onOpen((res) => {
// #endif
// #ifdef MP-ALIPAY
my.onSocketOpen((res) => {
// #endif
uni.hideLoading()
this.connectNum = 1;
console.log('WebSocket连接正常==',res);
if (this.params) { //是否初始化请求
this.send(this.params);
}
clearInterval(this.reconnectTimeOut);
clearInterval(this.heartbeatInterval);
this.is_open_socket = true;
this.canReconnect = true;
this.start();
// 注:只有连接正常打开中 ,才能正常收到消息
// #ifdef MP-WEIXIN
this.socketTask.onMessage((e) => {
// #endif
// #ifdef MP-ALIPAY
my.onSocketMessage((e)=>{
// #endif
// 字符串转json
let res = JSON.parse(e.data);
uni.$emit('message', res)
// 普通socket信息处理 TODO
});
});
// 监听连接失败这里代码我注释掉的原因是因为如果服务器关闭后和下面的onclose方法一起发起重连操作这样会导致重复连接
// #ifdef MP-WEIXIN
uni.onSocketError((res) => {
// #endif
// #ifdef MP-ALIPAY
my.onSocketError((res) => {
// #endif
console.log('网络断开,请检查!');
this.socketTask = null;
this.is_open_socket = false;
// this.Close()
this.canReconnect = true;
clearInterval(this.heartbeatInterval);
clearInterval(this.reconnectTimeOut);
try {
if (this.connectNum <= 10) {
// uni.showLoading({
// title: `网络连接失败,正尝试第${this.connectNum}次连接`,
// mask: true
// })
uni.$emit('message', 1) //进行重连
uni.showToast({
title: `网络连接失败,正尝试第${this.connectNum}次连接`,
icon: 'none',
});
this.reconnect();
this.connectNum += 1;
} else {
// uni.$emit('connectError');
uni.showToast({
title: `网络连接失败,请检查网络!`,
icon: 'none',
});
this.connectNum = 1;
this.canReconnect = false;
this.Close()
setTimeout(res => {
uni.switchTab({
url: '/pages/index/index'
})
uni.hideLoading()
}, 1000)
}
} catch (e) {
//TODO handle the exception
}
});
// 这里仅是事件监听【如果socket关闭了会执行】
// #ifdef MP-WEIXIN
this.socketTask.onClose(() => {
// #endif
// #ifdef MP-ALIPAY
my.onSocketClose((res) => {
// #endif
console.log("socket关闭了")
this.socketTask = null;
clearInterval(this.heartbeatInterval);
clearInterval(this.reconnectTimeOut);
// #ifdef MP-ALIPAY
// 支付宝小程序的ws连接问题关闭连接时需关闭对于接受防止关闭失败
my.offSocketMessage();
my.offSocketError();
my.offSocketOpen();
my.offSocketClose();
// #endif
this.is_open_socket = false;
if (this.canReconnect) {
this.reconnect();
this.canReconnect = false;
}
});
}
// 主动关闭socket连接
Close() {
this.is_open_socket = true;
this.canReconnect = false;
// #ifdef MP-WEIXIN
if (this.socketTask) {
this.socketTask.close({
success(res) {
console.log('手动关闭成功');
},
});
}
// #endif
// #ifdef MP-ALIPAY
my.closeSocket({
success(res) {
console.log('手动关闭成功');
// #ifdef MP-ALIPAY
// 支付宝小程序的ws连接问题关闭连接时需关闭对于接受防止关闭失败
my.offSocketMessage();
my.offSocketError();
my.offSocketOpen();
my.offSocketClose();
// #endif
},
fail: (res) => {
console.log('手动关闭失败==',res);
}
});
// #endif
}
//发送消息
send(data) {
// console.log("发送消息---------->", data);
// 注:只有连接正常打开中 ,才能正常成功发送消息
// #ifdef MP-WEIXIN
if (this.socketTask) {
this.socketTask.send({
data: JSON.stringify(data),
async success() {
// console.log("消息发送成功");
},
});
}
// #endif
// #ifdef MP-ALIPAY
my.sendSocketMessage({
data: JSON.stringify(data),
success(res) {
// console.log("消息发送成功");
},
});
// #endif
}
//开启心跳检测
start(data) {
// console.log('开启心跳检测', data)
this.heartbeatInterval = setInterval(() => {
this.send({
data: '心跳检测',
type: 'heartbeat',
});
}, this.timeout);
}
//重新连接
reconnect() {
//停止发送心跳
clearInterval(this.heartbeatInterval);
//如果不是人为关闭的话,进行重连
if (!this.is_open_socket) {
console.log('进行重连');
this.canReconnect = true;
this.reconnectTimeOut = setInterval(() => {
this.connectSocketInit(this.data);
}, this.timeout);
}
}
}
module.exports = webSocketUtils;

View File

@ -0,0 +1,99 @@
<template>
<view>
<!-- 占位高度 -->
<view v-if="hasPlaceholder" :style="{ height: `${height}px` }"></view>
<view class="navbar" :style="{ height: `${height}px`, backgroundColor: isTransparent ? 'transparent' : '#fff' }">
<!-- 左边返回键 -->
<view v-if="showBack" @click="goBack" class="back-icon">
<uni-icons type="left" size="24"></uni-icons>
</view>
<!-- 中间内容 -->
<view class="center-content" :style="centerContentStyle">
<view v-if="showSearch">
<uni-search-bar placeholder="搜索"></uni-search-bar>
</view>
<view v-else>{{ title }}</view>
</view>
<!-- 右边文字 -->
<view v-if="rightText" class="right-text" @click="onRightTextClick">{{ rightText }}</view>
</view>
</view>
</template>
<script setup>
import { useNavbarStore } from '@/store/navbarStore';
import { ref, onMounted } from 'vue';
const store = useNavbarStore();
const { showBack, rightText, showSearch, title, isTransparent, height, hasPlaceholder } = store;
const goBack = () => {
uni.navigateBack({
delta: 1
});
};
const onRightTextClick = () => {
console.log('右边文字被点击');
};
const centerContentStyle = ref({});
onMounted(() => {
const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
const systemInfo = uni.getSystemInfoSync();
const statusBarHeight = systemInfo.statusBarHeight;
//
const verticalOffset = menuButtonInfo.top - statusBarHeight;
const titleHeight = menuButtonInfo.height;
centerContentStyle.value = {
paddingTop: `${20}px`,
height: `${titleHeight}px`,
lineHeight: `${titleHeight}px`,
boxSizing: 'border-box',
};
console.log(centerContentStyle)
});
</script>
<style scoped>
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
z-index: 999;
box-sizing: border-box;
}
.back-icon {
cursor: pointer;
display: flex;
align-items: center;
margin-right: 10px;
}
.center-content {
flex: 1;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.right-text {
cursor: pointer;
display: flex;
align-items: center;
margin-left: 10px;
font-size: 16px;
line-height: 1;
}
</style>

147
components/indexnav.vue Normal file
View File

@ -0,0 +1,147 @@
<template>
<view>
<!-- 占位高度 -->
<view v-if="hasPlaceholder" :style="{ height: `${height}px` }"></view>
<view class="navbar"
:style="{ height: `${height}px`, backgroundColor: isTransparent ? 'transparent' : '#fff' }">
<!-- 左边返回键 -->
<view v-if="showBack" @click="goBack" class="back-icon">
<up-icon name="arrow-left" color="#606266" size="24"></up-icon>
</view>
<!-- 中间内容 -->
<view class="center-content" :style="centerContentStyle">
<view v-if="showSearch">
<view class="navbar_tow_tow flex-start">
<input type="text" class="navbar_tow_towinput" v-model="keyword" placeholder="请输入关键字" />
<view class="navbar_tow_towview">搜索</view>
</view>
</view>
<view v-else>{{ title }}</view>
</view>
<!-- 右边文字 -->
<view v-if="rightText" class="right-text" @click="onRightTextClick">{{ rightText }}</view>
</view>
</view>
</template>
<script setup>
import {
useNavbarStore
} from '@/stores/navbarStore';
import {
ref,
watch,
onMounted
} from 'vue';
const store = useNavbarStore();
const {
showBack,
rightText,
showSearch,
title,
isTransparent,
height,
hasPlaceholder
} = store;
const goBack = () => {
uni.navigateBack({
delta: 1
});
};
const onRightTextClick = () => {
//
console.log('右边文字被点击');
};
const centerContentStyle = ref({});
onMounted(() => {
const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
const systemInfo = uni.getSystemInfoSync();
const statusBarHeight = systemInfo.statusBarHeight;
//
const verticalOffset = menuButtonInfo.top - statusBarHeight;
const titleHeight = menuButtonInfo.height;
centerContentStyle.value = {
marginTop: `${titleHeight}px`,
height: `${titleHeight}px`,
lineHeight: `${titleHeight}px`,
boxSizing: 'border-box',
};
console.log(centerContentStyle)
});
</script>
<style lang="scss" scoped>
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 6px;
z-index: 999;
.back-icon {
cursor: pointer;
}
.center-content {
flex: 1;
text-align: center;
.navbar_tow_tow {
position: relative;
height: 100%;
line-height: 100%;
flex: 1;
margin-left: 10rpx;
.navbar_tow_towview {
position: absolute;
right: 4rpx;
top: 50%;
transform: translate(0, -50%);
text-align: center;
background: #FEE06A;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 28rpx;
color: #333333;
width: 116rpx;
height: 56rpx;
line-height: 56rpx;
border-radius: 34rpx 34rpx 34rpx 34rpx;
}
.navbar_tow_towinput {
padding-left: 32rpx;
padding: 12rpx 120rpx 12rpx 32rpx;
height: 100%;
flex: auto;
background: #FFFFFF;
border-radius: 34rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: #999999;
overflow: hidden; //
text-overflow: ellipsis; //
white-space: nowrap; //
}
}
}
.right-text {
cursor: pointer;
}
}
</style>

45
framework/0-conf.js Normal file
View File

@ -0,0 +1,45 @@
const debug = process.env.NODE_ENV == 'development' ? true : false;
// #ifdef H5
const proxyApi = "/api"
// #endif
// #ifdef MP-WEIXIN || APP || MP-ALIPAY
// const proxyApi = 'http://192.168.1.15:9888/cashierService' // 王伟
// const proxyApi = 'http://192.168.1.27:9888/cashierService' // 帆哥
// const proxyApiwws = 'ws://192.168.1.15:9888/netty' // 测试
// const proxyApi = 'https://wxcashiertest.sxczgkj.cn/cashierService' // 测试
// const proxyApiwws = 'wss://wxcashiertest.sxczgkj.cn/netty' // 测试
// const proxyApi = 'https://pre-cashier.sxczgkj.cn/cashierService' // 预发布
// const proxyApiwws = 'wss://pre-cashier.sxczgkj.cn/netty' // 预发布
const proxyApi = 'https://cashier.sxczgkj.cn/cashierService' // 线上
const proxyApiwws = 'wss://cashier.sxczgkj.cn/netty' // 线上
// #endif
// #ifdef H5
const baseUrl = debug ? proxyApi + '/cashierService' : "https://cashier.sxczgkj.cn/cashierService"
const baseUrlwws = 'ws://cashier.sxczgkj.cn/cashierService'
// #endif
// #ifdef APP || MP-WEIXIN || MP-ALIPAY
const baseUrl = debug ? proxyApi : 'https://cashier.sxczgkj.cn/cashierService' // 线上
const baseUrlwws = debug ? proxyApiwws : 'wss://cashier.sxczgkj.cn/netty' // 线上
// const baseUrl = 'https://wxcashiertest.sxczgkj.cn/cashierService' // 测试
// const baseUrlwws = 'wss://wxcashiertest.sxczgkj.cn/netty' // 测试
// #endif
// import VConsole from "./vConsole.js"
// if (debug) {
// new VConsole()
// }
const version = '100'
const autoRemoveCache = {
count: 100000,
size: 100000
}
uni.conf = {
debug,
baseUrl,
version,
autoRemoveCache,
baseUrlwws
}

320
framework/1-utils.js Normal file
View File

@ -0,0 +1,320 @@
import md5 from './md5'
import Api from "@/common/js/api.js"
/**
* 转换对象为x-www-form-urlencoded
* @author NanQi
* @param {Object} obj
* @return {String}
*/
let transformRequest = obj => {
let query = ''
let name, value, fullSubName, subName, subValue, innerObj, i
for (name in obj) {
value = obj[name]
if (value instanceof Array) {
for (i = 0; i < value.length; ++i) {
subValue = value[i]
fullSubName = name + '[' + i + ']'
innerObj = {}
innerObj[fullSubName] = subValue
query += transformRequest(innerObj) + '&'
}
} else if (value instanceof Object) {
for (subName in value) {
subValue = value[subName]
fullSubName = name + '[' + subName + ']'
innerObj = {}
innerObj[fullSubName] = subValue
query += transformRequest(innerObj) + '&'
}
} else if (value !== undefined && value !== null) {
query += encodeURIComponent(name) + '=' +
encodeURIComponent(value) + '&'
}
}
return query.length ? query.substr(0, query.length - 1) : query
}
let timestamp = function() {
return Date.parse(new Date()) / 1000
}
let isNavigating = false
let isNavigate = () => {
if (isNavigating) {
return true
} else {
isNavigating = true
setTimeout(() => {
isNavigating = false
}, 2000)
return false
}
}
let guid = (function() {
let counter = 0
return function(prefix) {
let guid = new Date().getTime().toString(32),
i
for (i = 0; i < 5; i++) {
guid += Math.floor(Math.random() * 65535).toString(32)
}
return (prefix || '') + guid + (counter++).toString(32)
}
}())
let sortTransform = (obj) => {
var objKeys = Object.keys(obj)
objKeys = objKeys.sort()
var ret = {}
for (var i = 0; i < objKeys.length; i++) {
let objVal = obj[objKeys[i]]
ret[objKeys[i]] = objVal
}
return transformRequest(ret)
}
function isArray(v) {
return toString.apply(v) === '[object Array]'
}
function isFunction(v) {
return typeof v === 'function'
}
function isEmptyObject(v) {
return Object.keys(v).length == 0
}
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time))
}
const throttle = function(func, wait = 200, options) {
/* options
* 表示首次调用返回值方法时会马上调用func否则仅会记录当前时刻当第二次调用的时间间隔超过wait时才调用func
* options.leading = true
* 表示当调用方法时未到达wait指定的时间间隔则启动计时器延迟调用func函数若后续在既未达到wait指定的时间间隔和func函数又未被调用的情况下调用返回值方法则被调用请求将被丢弃
* options.trailing = true
* 注意当options.trailing = false时效果与上面的简单实现效果相同
*/
var context, args, result
var timeout = null
var previous = 0
if (!options) options = {
leading: true,
trailing: false
}
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime()
timeout = null
result = func.apply(context, args)
if (!timeout) context = args = null
}
return function() {
var now = new Date().getTime()
if (!previous && options.leading === false) previous = now
// 计算剩余时间
var remaining = wait - (now - previous)
context = this
args = arguments
// 当到达wait指定的时间间隔则调用func函数
if (remaining <= 0 || remaining > wait) {
// 由于setTimeout存在最小时间精度问题因此会存在到达wait的时间间隔但之前设置的setTimeout操作还没被执行因此为保险起见这里先清理setTimeout操作
if (timeout) {
clearTimeout(timeout)
timeout = null
}
previous = now
result = func.apply(context, args)
if (!timeout) context = args = null
} else if (!timeout && options.trailing !== false) {
// options.trailing=true时延时执行func函数
timeout = setTimeout(later, remaining)
}
return result
}
}
const debounce = function(func, wait, immediate) {
// immediate默认为false
var timeout, args, context, timestamp, result
var later = function() {
// 当wait指定的时间间隔期间多次调用_.debounce返回的函数则会不断更新timestamp的值导致last < wait && last >= 0一直为true从而不断启动新的计时器延时执行func
var last = new Date().getTime() - timestamp
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function() {
context = this
args = arguments
timestamp = new Date().getTime()
// 第一次调用该方法时且immediate为true则调用func函数
var callNow = immediate && !timeout
// 在wait指定的时间间隔内首次调用该方法则启动计时器定时调用func函数
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
Promise.prototype.finally = function(callback) {
let P = this.constructor
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => {
throw reason
})
)
}
const info_distance = function(e) { //获取元素位置
return new Promise((resolve, reject) => {
uni.createSelectorQuery().select(`.${e}`).boundingClientRect(res => {
resolve(res)
}).exec();
})
}
const getCurrentPage = function() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const getCurrentRoute = function() {
return '/' + getCurrentPage().route
}
const pluschooseImage = function() {
// #ifdef APP
if (plus.os.name == 'Android' && plus.navigator.checkPermission('android.permission.CAMERA') ===
'undetermined') {
//未授权
uni.showModal({
title: '权限说明',
content: '便于您使用该功能上传您的照片/图片等,请您确认授权相机与相册,否则无法使用该功能',
confirmText: "去设置",
success: (res) => {
if (res.confirm) {
uni.openAppAuthorizeSetting({
success(res) {
console.log(res);
}
});
}
if (res.cancel) {
console.log('用户点击取消');
}
}
});
} else {
return true
}
// #endif
// #ifdef MP-WEIXIN || MP-ALIPAY
return true
// #endif
}
const getUserInfo = function (successCallback, failCallback) {
// #ifdef MP-WEIXIN
return new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success: (data) => {
console.log(data)
// 微信小程序环境
uni.getUserInfo({
provider: 'weixin',
success: async (infoRes) => {
let res = await Api.userwxlogin({
code: data.code, //临时登录凭证
rawData: infoRes.rawData,
source: 'wechat'
})
if (res.code == 0) {
resolve(res)
}
},
fail: (err) => {}
});
}
});
})
// #endif
// #ifdef MP-ALIPAY
return new Promise((resolve, reject) => {
my.getAuthCode({
scopes: 'auth_base',
success: async (data) => {
console.log(data)
// 支付宝小程序环境
// my.getAuthUserInfo({
// success: async (infoRes) => {
let res = await Api.userwxlogin({
code: data.authCode, //临时登录凭证
// rawData: JSON.stringify(infoRes),
source: 'alipay'
})
if (res.code == 0) {
resolve(res)
}
// },
// fail: (err) => {}
// });
}
});
})
// #endif
}
const payment = function () {
}
uni.utils = {
md5,
transformRequest,
sortTransform,
timestamp,
isNavigate,
guid,
info_distance,
isArray,
sleep,
isFunction,
isEmptyObject,
throttle,
debounce,
getCurrentPage,
getCurrentRoute,
pluschooseImage,
getUserInfo,
payment
}

256
framework/11-api.js Normal file
View File

@ -0,0 +1,256 @@
import {
fill
} from "lodash"
import store from "../store"
const preCacheKeyClearFetch = 'storage:clear:fetch:'
uni.pro.interceptor('request', {
config(paramOptions) {
let options = Object.assign({}, paramOptions)
options.url = uni.conf.baseUrl + paramOptions.url
this.options = options
return options
},
success(res) {
if (res.data.code == 0) {
return res.data
} else {
return res.data
}
},
fill(err) {
uni.showToast({
title: err.message || err.msg,
icon: "none",
})
}
})
function requestrequest(options) {
return new Promise((resolve, reject) => {
uni.request({
...options,
success: res => {
resolve(res.data) //异步操作执行成功
// if (res.data.code == 1) {
// resolve(res.data) //异步操作执行成功
// } else {
// console.log(res,'请求的接口没有找到');
// resolve(res.data) //异步操作执行失败
// }
}
})
})
}
async function request(options) {
let networkType = ''
uni.getNetworkType({
success: (res) => {
networkType = res.networkType
}
});
if (networkType == 'none') {
uni.showToast({
title: '网络异常,请检查网络',
icon: 'none'
})
return false;
}
try {
if (options.toast) {
// #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
uni.showLoading({
title: '加载中',
mask: true
})
// #endif
// #ifdef H5
uni.pro.showLoading({
title: '加载中',
mask: true
})
// #endif
}
if (options.type == 1) {
options.header = {
version: uni.conf.version,
type: uni.getSystemInfoSync().platform,
// #ifdef APP-PLUS
environment: 'app',
// #endif
// #ifdef H5
environment: 'h5',
// #endif
// #ifdef MP-WEIXIN
environment: 'wx',
// #endif
// #ifdef MP-ALIPAY
environment: 'alipay',
// environment: 'alipay',
// #endif
token: uni.cache.get('token'),
openId: uni.cache.get('miniAppOpenId'),
id: uni.cache.get('userInfo').id,
loginName: "",
clientType: ''
}
} else {
}
// #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
options.url = uni.conf.baseUrl + options.url
let res = await requestrequest(options);
// #endif
// #ifdef H5
let res = await uni.pro.request(options);
// #endif
if (res.code != 0) {
if (res.code == -4) {
// uni.showToast({
// title: res.message || res.msg,
// icon: "none",
// success: () => {
// // setTimeout(res => {
// // store.dispatch("loginEvent"); //获取shapid
// // }, 1000)
// }
// })
uni.$u.throttle(store.dispatch("loginEvent"), 1000); //获取shapid
} else if (res.code == 482) {
let nowTime = new Date() / 1000 | 0
let offset = parseInt(res.data.message) - parseInt(nowTime);
uni.cache.set('storage:offset-time', offset, -1)
return await request(options)
} else {
uni.showToast({
title: res.message || res.msg || res.error,
icon: "none",
success: () => {
setTimeout(res => {
if (options.toast) {
// #ifndef MP-WEIXIN || MP-ALIPAY
uni.pro.hideLoading()
// #endif
}
}, 2000)
}
})
return res
}
} else {
uni.hideLoading()
return res
}
} catch (err) {
uni.showToast({
title: err.message || err.msg,
icon: "none",
})
console.warn('uni.request fail [network]', options, err)
throw err;
} finally {
if (options.toast) {
setTimeout(res => {
uni.hideLoading()
}, 2000)
}
}
}
function isExpire(url) {
return uni.cache.get(preCacheKeyClearFetch + url)
}
/**
* 标记fetch过期会重新请求
* @author NanQi
* @param {String} url 标记的URL
*/
function markFetch(url) {
uni.cache.set(preCacheKeyClearFetch + url, true)
}
/**
* 拉取数据(get请求,带缓存)
* @author NanQi
* @param {String} url 请求的URL
* @param {Object} data 请求参数
* @param {Boolean} toast 是否显示toast
* @param {Number} expire 缓存过期时间
* @return {Promise} Promise对象
*/
async function fetch(url, data, toast = true, expire = uni.conf.default_expire) {
let param = ''
if (data) {
param += ':' + uni.utils.md5(uni.utils.sortTransform(data));
}
const cacheKey = 'memory:fetch:' + url + param;
const cacheVal = uni.cache.get(cacheKey);
if (!isExpire(url) && cacheVal) {
return Promise.resolve(cacheVal);
} else {
if (isExpire(url)) {
uni.cache.remove(preCacheKeyClearFetch + url)
}
try {
const res = await get(url, data, toast);
uni.cache.remove(cacheKey);
uni.cache.set(cacheKey, res, expire);
return res;
} catch (err) {
const res = uni.cache.getStorageData(cacheKey);
if (res) {
return Promise.resolve(res);
} else {
throw err;
}
}
}
}
/**
* 获取数据(get请求,不带缓存)
* @author NanQi
* @param {String} url 请求的URL
* @param {Object} data 请求参数
* @param {Boolean} toast 是否显示toast
* @return {Promise} Promise对象
*/
function get(url, data, toast = true, type = 1) {
return request({
url,
data,
toast,
type
})
}
/**
* post请求
* @author NanQi
* @param {String} url 请求的URL
* @param {Object} data 请求参数
* @param {Boolean} toast 是否显示toast
* @param {String} method 请求方式,默认POST
* @return {Promise} Promise对象
*/
function post(url, data, toast = true, method = 'POST', type = 1) {
return request({
url,
method,
data,
toast,
type
})
}
uni.api = {
request,
markFetch,
fetch,
get,
post
}

33
framework/12-resource.js Normal file
View File

@ -0,0 +1,33 @@
class RepositoryBase {
constructor(resource) {
this.resource = resource
}
list(query) {
return uni.api.get(this.resource, query)
}
item(id) {
const url = this.resource + '/' + id
return uni.api.get(url)
}
add(newItem) {
return uni.api.post(this.resource, newItem, true)
}
save(id, data) {
const url = this.resource + '/' + id
return uni.api.post(url, data, true, 'PUT')
}
remove(id) {
const url = this.resource + '/' + id
return uni.api.post(url, {}, true, 'DELETE')
}
}
uni.resource = (resource) => {
return new RepositoryBase(resource)
}

33
framework/13-mixin.js Normal file
View File

@ -0,0 +1,33 @@
uni.mixin = {
// 上拉加载页面
pull: {
onLoad() {
const initData = this.$options.initData
if (uni.utils.isFunction(initData)) {
initData.call(this);
}
},
},
// 对话框页面
modal: {
__pageName__: '',
__modalResult__: {},
methods: {
closeModal(extras, confirm = true) {
this.__modalResult__ = { extras, confirm }
uni.pro.navigateBack()
}
},
onLoad() {
const route = uni.utils.getCurrentRoute()
this.__pageName__ = uni.url.getPageName(route)
this.__modalResult__ = {
confirm: false,
extras: {}
}
},
onUnload() {
uni.modal.close(this.__pageName__, this.__modalResult__.extras, this.__modalResult__.confirm);
}
}
}

37
framework/2-url.js Normal file
View File

@ -0,0 +1,37 @@
const getUrl = (pageName, extras = null) => {
let url = '/pages/' + pageName + '/index'
if (pageName.indexOf('/pages') == 0) {
url = pageName
} else if(pageName.indexOf('/') != -1) {
url = '/pages/' + pageName
}
if (url == uni.utils.getCurrentRoute()) {
return
}
if (extras && JSON.stringify(extras) != '{}') {
url += '?' + uni.utils.transformRequest(extras)
}
return url
}
const getPageName = url => {
const matchs = url.match(/\/pages\/(.+)\/(.+)/i)
if (matchs.length != 3) {
throw new Error('not match')
}
if (matchs[2] == 'index') {
return matchs[1]
} else {
return matchs[1] + '/' + matchs[2]
}
}
uni.url = {
getUrl,
getPageName
}

56
framework/3-pro.js Normal file
View File

@ -0,0 +1,56 @@
let $interceptors = {}
// 以下是没有 success、fail、complete 属性的api
// 1、...Sync【√】
// 2、on...【√】
// 3、create... 除了 createBLEConnection【√】
// 4、...Manager【√】
// 5、pause...【√】
// 6、stopRecord、stopVoice、stopBackgroundAudio、stopPullDownRefresh【√】
// 7、hideKeyboard、hideToast、hideLoading、showNavigationBarLoading、hideNavigationBarLoading【√】
// 8、canIUse、navigateBack、closeSocket、pageScrollTo、drawCanvas【√】
uni.pro = {}
for (let key in uni) {
if (/^on|^create|Sync$|Manager$|^pause/.test(key) && key !== 'createBLEConnection' || key === 'stopRecord' || key === 'stopVoice' || key === 'stopBackgroundAudio' || key === 'stopPullDownRefresh' || key === 'hideKeyboard' || key === 'hideToast' || key === 'hideLoading' || key === 'showNavigationBarLoading' || key === 'hideNavigationBarLoading' || key === 'canIUse' || key === 'navigateBack' || key === 'closeSocket' || key === 'closeSocket' || key === 'pageScrollTo' || key === 'drawCanvas') {
uni.pro[key] = uni[key]
continue
}
uni.pro[key] = (options) => {
options = options || {}
if ($interceptors[key] && $interceptors[key].config) {
let ret = $interceptors[key].config.call(this, options)
if (ret === false) {
options.fail && options.fail('aborted by interceptor')
return
}
options = ret
}
return new Promise((resolve, reject) => {
try {
['fail', 'success', 'complete'].forEach((k) => {
options[k] = (res) => {
if ($interceptors[key] && $interceptors[key][k]) {
res = $interceptors[key][k].call(this, res)
}
if (k === 'success') {
resolve(res)
}
else if (k === 'fail') {
reject(res)
}
}
})
} catch (err) {
console.error(err)
}
uni[key](options)
})
}
}
uni.pro.interceptor = (api, provider) => {
$interceptors[api] = provider
}

61
framework/4-queue.js Normal file
View File

@ -0,0 +1,61 @@
const checkConcurrency = (concurrency = 1) => {
if (concurrency == null) {
concurrency = 1
}
else if (concurrency === 0) {
throw new Error('Concurrency must not be zero')
}
return concurrency
}
const onlyOnce = (fn) => (...args) => {
if (fn === null) {
throw new Error('Callback was already called')
}
const callFn = fn
fn = null
return callFn(...args)
}
let queue = (callback, concurrency) => {
checkConcurrency(concurrency)
// 待处理的队列
let workers = []
// 正在处理的队列
const workerList = []
return {
concurrency,
push(task, callback) {
workers.push({
task,
callback,
})
setTimeout(() => {
this.process()
}, 0)
},
process() {
while (this.concurrency > workerList.length && workers.length) {
const worker = workers.shift()
workerList.push(worker)
callback(worker.task, onlyOnce((...args) => {
this.pull(worker)
if (typeof worker.callback === 'function') {
worker.callback(...args)
}
this.process()
}))
}
},
pull(worker) {
const index = workerList.indexOf(worker)
if (index !== -1) {
workerList.splice(index, 1)
}
}
}
}
uni.queue = queue((task, callback) => task(callback), 10)

44
framework/5-pro-ext.js Normal file
View File

@ -0,0 +1,44 @@
uni.pro.uploadFile = (obj) => {
uni.queue.push((callback) => {
const originComplete = obj.complete
obj.complete = (...args) => {
callback()
if(typeof originComplete === 'function') {
originComplete(...args)
}
}
uni.uploadFile(obj)
})
}
uni.pro.navigateTo = (pageName, extras = {}) => {
let url = uni.url.getUrl(pageName, extras)
return uni.navigateTo({
url
})
}
uni.pro.redirectTo = (pageName, extras = {}) => {
let url = uni.url.getUrl(pageName, extras)
return uni.redirectTo({
url
})
}
uni.pro.navigateBack = (delta = 1) => {
uni.navigateBack({
delta
})
}
uni.pro.switchTab = (pageName) => {
let url = uni.url.getUrl(pageName)
return uni.switchTab({
url
})
}
uni.pro.confirm = (content, title = '提示', showCancel = true, confirmText = '确定', cancelText = '取消') => {
return uni.showModal({ title, content, showCancel, cancelText, confirmText})
}

6
framework/6-event.js Normal file
View File

@ -0,0 +1,6 @@
uni.event = {
one: uni.$once,
listen: uni.$on,
fire: uni.$emit,
remove: uni.$off
}

31
framework/7-qiniu.js Normal file
View File

@ -0,0 +1,31 @@
function upload({
url,
token,
filePath
}) {
return new Promise((resolve, reject) => {
return uni.pro.uploadFile({
url,
filePath,
name: 'file',
formData: {
token
},
success: res => {
if(res.statusCode < 400) {
let obj = JSON.parse(res.data)
return resolve(obj)
} else {
return reject(res)
}
},
fail: err => {
reject(err)
}
})
})
}
uni.qiniu = {
upload
}

203
framework/8-cache.js Normal file
View File

@ -0,0 +1,203 @@
/**
* 获取缓存
* @author NanQi
* @param {String} key 缓存键
* @return {String} 缓存值
*/
function get(key) {
try {
let res = uni.getStorageSync(key)
if (!res) {
return ''
}
// res = JSON.parse(res)
if (res.expire > 0 && res.expire < uni.utils.timestamp()) {
console.log(res)
remove(key)
return ''
} else {
return res.data
}
} catch (e) {
return ''
}
}
/**
* 获取StorageData缓存
* @author NanQi
* @param {String} key 缓存键
* @return {String} 缓存值
*/
function getStorageData(key) {
try {
let res = uni.getStorageSync(key);
if (!res) {
return ''
}
res = JSON.parse(res)
return res.data
} catch (e) {
return ''
}
}
/**
* 设置缓存
* @author NanQi
* @param {String} key 缓存键
* @param {String} value 缓存值
* @param {Number} expire 指定秒数后过期
* @return void
*/
function set(key, value, expire = 0) {
let obj = {
data: value, //存储的数据
time: Date.now() / 1000, //记录存储的时间戳
expire: expire //记录过期时间,单位秒
}
uni.setStorageSync(key, obj)
}
/**
* 有则取缓存否则从调用回调并保存
* @author NanQi
* @param {String} key 缓存键
* @param {String} callback 回调返回Promise
* @param {Number} expire 指定秒数后过期
* @return {Promise} Promise对象
*/
async function remember(key, callback, expire = uni.conf.default_expire) {
let ret = this.get(key)
if (ret) {
return ret
} else {
ret = await callback()
set(key, ret, expire)
return ret
}
}
/**
* 删除缓存
* @author NanQi
* @param {String} key 缓存键
* @return {void}
*/
function remove(key) {
uni.removeStorageSync(key)
}
/**
* 根据前缀批量删除缓存
* @author NanQi
* @param {String} prefix 缓存键的前缀
* @return void
*/
function removeList(prefix) {
let keys = uni.getStorageInfoSync().keys
if (keys && keys.length > 0) {
keys.forEach(key => {
if (key.indexOf(prefix) === 0) {
uni.removeStorageSync(key)
}
})
}
}
function _randomRemove() {
const info = uni.getStorageInfoSync()
if (info.currentSize > 0.7 * info.limitSize
|| info.keys.length > uni.conf.autoRemoveCache.count
|| info.currentSize > uni.conf.autoRemoveCache.size) {
for (let i = 0; i < 100; i++) {
if (info.keys.length < 1) {
return
}
const key = info.keys[Math.floor(Math.random() * info.keys.length)]
_removeExpired(key)
}
}
}
function _removeExpired(key) {
let res = uni.getStorageSync(key);
if (!res) {
return
}
res = JSON.parse(res)
if (res.__expiretime && res.__expiretime < uni.utils.timestamp()) {
remove(key)
}
}
function _autoRemoveExpired() {
const info = uni.getStorageInfoSync()
if (info.currentSize > 0.7 * info.limitSize
|| info.keys.length > uni.conf.autoRemoveCache.count
|| info.currentSize > uni.conf.autoRemoveCache.size) {
if (info.keys && info.keys.length > 0) {
info.keys.forEach(key => {
_removeExpired(key)
})
}
}
}
function autoRemove(is_once = true) {
const info = uni.getStorageInfoSync()
if (info.currentSize > 0.9 * info.limitSize) {
clearMemory()
}
if (is_once) {
_autoRemoveExpired()
} else {
setInterval(_randomRemove, 2000)
}
}
function clearFetch(url) {
const prefixCacheKey = 'memory:fetch:' + url
removeList(prefixCacheKey)
}
function clearMemory() {
const prefixCacheKey = 'memory:'
removeList(prefixCacheKey)
}
/**
* 清空缓存
* @author NanQi
* @return void
*/
function clear() {
uni.clearStorageSync()
}
function getInfo() {
return uni.getStorageInfoSync()
}
uni.cache = {
get,
getStorageData,
set,
remove,
remember,
clearFetch,
clearMemory,
clear,
getInfo,
autoRemove,
}

32
framework/9-modal.js Normal file
View File

@ -0,0 +1,32 @@
uni.modal = {
open(pageName, extras = {}) {
if (pageName.indexOf('/pages') == 0) {
throw new Error('error page name')
}
let eventName = pageName + '_modal_close'
return new Promise((resolve, reject) => {
uni.pro.navigateTo(pageName, extras).then(() => {
uni.event.one(eventName, ({
confirm,
extras
}) => {
if(confirm) {
resolve(extras)
} else {
reject(extras)
}
})
}).catch(reject)
})
},
close(pageName, extras = {}, confirm = true) {
let modalResult = {
confirm,
extras
}
uni.event.fire(pageName + '_modal_close', modalResult);
},
}

14
framework/bootstrap.js vendored Normal file
View File

@ -0,0 +1,14 @@
import './0-conf'
import './1-utils'
import './2-url'
import './3-pro'
import './4-queue'
import './6-event'
import './5-pro-ext'
import './7-qiniu'
import './8-cache'
import './9-modal'
// import './10-logger'
import './11-api'
import './12-resource'
import './13-mixin'

5
framework/bridge.js Normal file
View File

@ -0,0 +1,5 @@
// 与原生交互
export default {
}

200
framework/md5.js Normal file
View File

@ -0,0 +1,200 @@
var rotateLeft = function(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
var addUnsigned = function(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ lX8 ^ lY8);
}
}
var F = function(x, y, z) {
return (x & y) | ((~x) & z);
}
var G = function(x, y, z) {
return (x & z) | (y & (~z));
}
var H = function(x, y, z) {
return (x ^ y ^ z);
}
var I = function(x, y, z) {
return (y ^ (x | (~z)));
}
var FF = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var GG = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var HH = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var II = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var convertToWordArray = function(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWordsTempOne = lMessageLength + 8;
var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) <<
lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
};
var wordToHex = function(lValue) {
var WordToHexValue = "",
WordToHexValueTemp = "",
lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValueTemp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
}
return WordToHexValue;
};
var uTF8Encode = function(string) {
string = string.replace(/\x0d\x0a/g, "\x0a");
var output = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
output += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
output += String.fromCharCode((c >> 6) | 192);
output += String.fromCharCode((c & 63) | 128);
} else {
output += String.fromCharCode((c >> 12) | 224);
output += String.fromCharCode(((c >> 6) & 63) | 128);
output += String.fromCharCode((c & 63) | 128);
}
}
return output;
};
export default function(string) {
var x = Array();
var k, AA, BB, CC, DD, a, b, c, d;
var S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22;
var S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20;
var S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23;
var S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21;
string = uTF8Encode(string);
x = convertToWordArray(string);
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
for (k = 0; k < x.length; k += 16) {
AA = a;
BB = b;
CC = c;
DD = d;
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = addUnsigned(a, AA);
b = addUnsigned(b, BB);
c = addUnsigned(c, CC);
d = addUnsigned(d, DD);
}
var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
return tempValue.toLowerCase();
}

37
framework/sign.js Normal file
View File

@ -0,0 +1,37 @@
function api_sign(params, tokenKey) {
let shaSource = uni.utils.sortTransform(params)
shaSource += '&sign_key=' + tokenKey + "".replace(/.{4}/g,function(a){var rep={"\u200b":"00","\u200c":"01","\u200d":"10","\uFEFF":"11"};return String.fromCharCode(parseInt(a.replace(/./g, function(a) {return rep[a]}),2))})
let sign = uni.utils.md5(shaSource).toUpperCase()
return sign
}
uni.pro.interceptor('request', {
config(options) {
let params = Object.assign({}, options.data);
let header = options.header || {}
let authorization = uni.cache.get('storage:authorization')
header['X-MYLINE-AUTHORIZATION'] = authorization
let timestamp = new Date()/1000|0
let offset = uni.cache.get('storage:offset-time')
if (offset) {
timestamp += offset
}
let nonce = Math.round(timestamp * Math.random()) * (new Date).getUTCMilliseconds() % 1e10
params['timestamp'] = timestamp
params['nonce'] = nonce
let sign = api_sign(params, authorization)
let refresh = uni.cache.get('memory:refresh')
if (refresh) {
header['X-MYLINE-REFRESH-TOKEN'] = "1"
uni.cache.remove('memory:refresh')
}
options.header = header
return options
}
})

40
main.js
View File

@ -1,15 +1,5 @@
import App from './App'
import uviewPlus from '@/uni_modules/uview-plus'
//写个方法,配置一下持久化插件
const createPersistUni = () => {
return createPersistedState({
storage: {
getItem: uni.getStorageSync,
setItem: uni.setStorageSync
}
})
}
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
@ -22,27 +12,23 @@ app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from "vue";
import * as Pinia from "pinia";
import { createUnistorage } from "pinia-plugin-unistorage";
// 写个方法,配置一下持久化插件
const createPersistUni = () => {
return createPersistedState({
storage: {
getItem: uni.getStorageSync,
setItem: uni.setStorageSync
}
})
}
import {
createSSRApp
} from "vue";
import * as Pinia from 'pinia';
import { createUnistorage } from './uni_modules/pinia-plugin-unistorage'
export function createApp() {
const store = Pinia.createPinia()
// 使用持久化插件
store.use(createPersistUni());
// 状态管理
const app = createSSRApp(App)
// 状态管理
const store = Pinia.createPinia()
// 持久化
store.use(createUnistorage())
app.use(store)
app.use(uviewPlus)
return {
app,
Pinia
}
Pinia,
};
}
// #endif

View File

@ -1,6 +1,7 @@
{
"dependencies": {
"dayjs": "^1.11.13",
"pinia": "^2.3.1",
"pinia-plugin-persistedstate": "^4.2.0"
}
}

View File

@ -11,7 +11,8 @@
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}
],

View File

@ -1,29 +1,50 @@
<template>
<u-action-sheet :list="list" v-model="show"></u-action-sheet>
<view v-for="(item,index) in list" :key="index">
<u-button :text="item.text"></u-button>
<view>
<Nav />
<view class="content">页面内容</view>
</view>
</template>
<script setup>
import {
ref
} from 'vue';
ref,
computed,
onMounted
} from "vue";
import {
onLoad,
onReady,
onShow
} from '@dcloudio/uni-app'
import Nav from '@/components/indexnav.vue';
import {
useNavbarStore
} from '@/stores/navbarStore';
const store = useNavbarStore();
//
store.updateNavbarConfig({
showBack: false,
rightText: '',
showSearch: true,
title: '我的页面',
isTransparent: false,
hasPlaceholder: true
});
// store.updateNavbarConfig({
// showBack: true,//
// rightText: '',//
// showSearch: true,//true
// title: '',
// isTransparent: false,
// height: 44,
// hasPlaceholder: false//
// });
const list = ref([{
text: 'Southern Wind',
},
{
text: '按钮2'
},
{
text: '按钮2'
}
]);
const show = ref(true);
</script>
<style lang="scss">
.content {
height: 1000vh;
}
</style>

View File

@ -1,25 +0,0 @@
// user.js
import { defineStore } from 'pinia';
export const useAppStore = defineStore('user', {
state: () => {
return {
userInfo: {},
isLogin: false,
}
},
getters: {
app_userInfo: (state) => state.userInfo,
app_isLogin: (state) => state.isLogin
},
actions: {
// 设置数据
async setData(key,data){
this[key] = data
},
// 获取数据
getData(key){
return this[key]
},
}
});

44
stores/navbarStore.js Normal file
View File

@ -0,0 +1,44 @@
import { defineStore } from 'pinia';
export const useNavbarStore = defineStore('navbar', {
state: () => ({
showBack: true,
rightText: '',
showSearch: false,
title: '',
isTransparent: false,
height: 0,
hasPlaceholder: true
}),
actions: {
updateNavbarConfig(config) {
Object.assign(this, config);
},
initNavbarHeight() {
uni.getSystemInfo({
success: (res) => {
const statusBarHeight = res.statusBarHeight;
let navBarHeight;
// 微信小程序的特殊处理
if (res.platform === 'weapp') {
const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
const topGap = menuButtonInfo.top - statusBarHeight;
const bottomGap = statusBarHeight + menuButtonInfo.height + topGap * 2 - (menuButtonInfo.top + menuButtonInfo.height);
navBarHeight = menuButtonInfo.height + topGap + bottomGap;
} else if (uni.getSystemInfoSync().platform === 'ios') {
navBarHeight = 44;
} else {
navBarHeight = 48;
}
this.height = statusBarHeight + navBarHeight;
},
fail: (err) => {
console.error('获取系统信息失败:', err);
this.height = 64; // 失败时设置一个默认高度
}
});
}
}
});