源文件
This commit is contained in:
403
jeepay-ui-uapp-face/pages/aliIndex/index.vue
Normal file
403
jeepay-ui-uapp-face/pages/aliIndex/index.vue
Normal file
@@ -0,0 +1,403 @@
|
||||
<template>
|
||||
<view class="index-wrapper">
|
||||
<poster id="ali-poster" posid="idle_pos" :audible="true" style="width: 100%; height: 88vh"
|
||||
onSuccess="onDisplaySuccess" onFail="onDisplayFail" onChange="onPosterChange"
|
||||
v-if="!vdata.userInfo.realname || !vdata.adList.length" />
|
||||
<JeepayBanner v-else :list="vdata.adList" :interval="vdata.changeTime" />
|
||||
<!-- <view style="width: 100%; height: 88vh"></view> -->
|
||||
<view class="idnex-wrapper">
|
||||
<view class="left">
|
||||
<view class="tips-title">请等待商家发起收款</view>
|
||||
<view class="store-name">付款给:{{ vdata.userInfo.realname }}</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="more-but log-in" hover-class="hover-more" hover-stay-time="50" v-if="!vdata.userInfo.realname"
|
||||
@tap="toLogin">请登录</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-drawer ref="refShowRight" mode="right" @change="change">
|
||||
<view class="list-wrapper" :style="{ '--text-color': calcWorkState().value == 1 ? ' #108ee9' : 'tomato' }">
|
||||
<blocke v-for="(v, i) in vdata.navList" :key="i">
|
||||
<view class="list-item" hover-class="hover-more" hover-stay-time="50" @tap="tapNav(v)"
|
||||
v-if="v.value.includes(vdata.modelType)">
|
||||
{{ v.title }}
|
||||
<view class="list-item-right">
|
||||
<view class="face-model" v-if="v.title == '切换模式'">当前模式:{{ vdata.modelType == 'pos' ? 'POS' : '独立收银' }}模式
|
||||
</view>
|
||||
<image src="/static/right.svg" mode="scaleToFill" v-if="i != vdata.navList.length - 1" />
|
||||
<image src="/static/logout.svg" mode="scaleToFill" v-else />
|
||||
</view>
|
||||
</view>
|
||||
</blocke>
|
||||
</view>
|
||||
</uni-drawer>
|
||||
<SwitchModelCard ref="refSwitch" @makClose="open" v-model:value="vdata.modelType" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { req, $appPay, $workRecords, $userInfo, API_URL_PAY_ORDER_LIST, $adBannerList } from '@/http/apiManager'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
// 生命周期 进入页面
|
||||
onLoad(() => {
|
||||
if (storageManage.token()) {
|
||||
getAd()
|
||||
}
|
||||
})
|
||||
// 初始化 modelType
|
||||
if (!storageManage.faceModel()) {
|
||||
storageManage.faceModel('cashier')
|
||||
}
|
||||
const refShowRight = ref(null)
|
||||
const refSwitch = ref(null)
|
||||
const vdata = reactive({
|
||||
userInfo: storageManage.userInfo(), //取出用户信息
|
||||
navList: [
|
||||
{ title: '订单', url: '/pages/order/order', value: 'cashier' },
|
||||
{ title: '统计', url: '/pages/stat/stat', value: 'cashier' },
|
||||
{ title: `${calcWorkState().value == 1 ? '上班' : '下班'}打卡`, fun: working, value: 'cashier' },
|
||||
{ title: '交班', url: '/pages/handover/handover', value: 'cashier' },
|
||||
{ title: '切换模式', fun: switchModel, value: 'cashierpos' },
|
||||
{ title: '系统设置', fun: () => { my.ix.startApp({ appName: 'settings' }) }, value: 'cashierpos' },
|
||||
{ title: '刷新广告数据', fun: getAd, value: 'cashierpos' },
|
||||
{ title: '退出登录', fun: loginOut, value: 'cashier' }
|
||||
],
|
||||
modelType: storageManage.faceModel(), //取出本地存储的模式类型
|
||||
adList:[]
|
||||
})
|
||||
|
||||
my.ix.onKeyEventChange(r => {
|
||||
// console.log('r', r)
|
||||
const timeStamp = new Date().getTime()
|
||||
switch (r.keyCode) {
|
||||
case 134:
|
||||
if (!storageManage.token()) return uni.$J.showErrorToast('请先登录')
|
||||
if (vdata.isShow) return my.ix.startApp({ appName: 'settings' })
|
||||
open()
|
||||
break
|
||||
case 132:
|
||||
if (storageManage.faceModel() && storageManage.faceModel() == 'pos') return posCashier()
|
||||
break
|
||||
case 131: //收款按键
|
||||
if (storageManage.faceModel() && storageManage.faceModel() == 'pos') return posCashier()
|
||||
my.ix
|
||||
.startApp({
|
||||
appId: '2021002172674746',
|
||||
appName: 'cashier',
|
||||
bizNo: timeStamp,
|
||||
totalAmount: r.amount,
|
||||
showScanPayResult: true,
|
||||
scanLoadingTimeout: '10'
|
||||
})
|
||||
.then(res => {
|
||||
my.ix.writeHID({
|
||||
protocol: 'barcode',
|
||||
value: res.barCode,
|
||||
success: r => {
|
||||
console.log('r', r)
|
||||
},
|
||||
fail: err => {
|
||||
console.log('err', err)
|
||||
}
|
||||
})
|
||||
$appPay(res.totalAmount, res.barCode).then(r => {
|
||||
findOrderState(r.bizData)
|
||||
console.log('支付后结果', r)
|
||||
//扫码付支付成功主动调起结果页
|
||||
if (res.codeType == 'C' && r.bizData.orderState == 2) {
|
||||
my.ix.startApp({
|
||||
appName: 'scanPayResult',
|
||||
bizNo: timeStamp,
|
||||
totalAmount: res.totalAmount,
|
||||
success: r => {
|
||||
console.log(r)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('err', err)
|
||||
})
|
||||
break
|
||||
case 133:
|
||||
close()
|
||||
break
|
||||
|
||||
}
|
||||
})
|
||||
// 展示成功回调
|
||||
const onDisplaySuccess = () => {
|
||||
console.log('poster display success')
|
||||
}
|
||||
// 展示失败回调
|
||||
const onDisplayFail = e => {
|
||||
console.log('poster display fail, error = ' + e.detail.error)
|
||||
}
|
||||
// 广告可用性变化回调
|
||||
const onPosterChange = e => {
|
||||
console.log('poster availability changed, now has poster = ' + e.detail.hasPoster)
|
||||
}
|
||||
// 打开抽屉
|
||||
const open = () => {
|
||||
refShowRight.value.open()
|
||||
}
|
||||
// 关闭抽屉
|
||||
const close = () => {
|
||||
refShowRight.value.close()
|
||||
}
|
||||
// pos 收银模式
|
||||
function posCashier() {
|
||||
const timeStamp = new Date().getTime()
|
||||
my.ix
|
||||
.startApp({
|
||||
appId: '2021002172674746',
|
||||
appName: 'cashier',
|
||||
bizNo: timeStamp,
|
||||
showScanPayResult: true,
|
||||
scanLoadingTimeout: '10'
|
||||
})
|
||||
.then(res => {
|
||||
my.ix.writeHID({
|
||||
protocol: 'barcode',
|
||||
value: res.barCode,
|
||||
success: r => {
|
||||
console.log('r', r)
|
||||
},
|
||||
fail: err => {
|
||||
console.log('err', err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 退出等领域
|
||||
function loginOut() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否确认退出登录',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
storageManage.cleanByLogout()
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 打卡函数
|
||||
function working() {
|
||||
uni.showModal({
|
||||
title: `提示:${calcWorkState().value == 1 ? '上班' : '下班'}打卡`,
|
||||
content: '是否确认打卡?',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
$workRecords(calcWorkState().value).then(res => {
|
||||
uni.showToast({
|
||||
title: '打卡成功',
|
||||
icon: 'success',
|
||||
mask: true
|
||||
})
|
||||
// 重新请求用户信息
|
||||
$userInfo().then(({ bizData }) => {
|
||||
// 更新用户数据
|
||||
storageManage.userInfo(bizData)
|
||||
// 更新用户数据
|
||||
vdata.userInfo = bizData
|
||||
vdata.navList[2].title = (calcWorkState().value == 1 ? '上班' : '下班') + '打卡'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 切换模式函数、
|
||||
function switchModel() {
|
||||
refShowRight.value.close()
|
||||
refSwitch.value.open()
|
||||
}
|
||||
/****
|
||||
* @param {v} Object url 跳转地址 fun 执行函数
|
||||
* */
|
||||
const tapNav = v => {
|
||||
if (v.url)
|
||||
return uni.navigateTo({
|
||||
url: v.url
|
||||
})
|
||||
v.fun()
|
||||
}
|
||||
// 计算状态上班还是下班 0 未知 1上班 2下班
|
||||
function calcWorkState() {
|
||||
return computed(() => {
|
||||
const state = storageManage.userInfo().workState
|
||||
return state == 0 ? '1' : state == 1 ? 2 : 1
|
||||
})
|
||||
}
|
||||
// 定向到登录页
|
||||
const toLogin = () => uni.reLaunch({ url: '/pages/login/login' })
|
||||
function findOrderState(val) {
|
||||
switch (val.orderState) {
|
||||
case 2:
|
||||
break
|
||||
case 3:
|
||||
uni.$J.showToast('支付失败' + val.errMsg)
|
||||
break
|
||||
case 4:
|
||||
uni.$J.showToast('订单撤销')
|
||||
break
|
||||
case 1:
|
||||
// 支付中 进行查单操作
|
||||
console.log('订单状态1进行查单 操作 ')
|
||||
findOrder(val.payOrderId)
|
||||
break
|
||||
}
|
||||
}
|
||||
let num = 1
|
||||
function findOrder(payOrderId) {
|
||||
if (num > 20)
|
||||
return uni.showModal({
|
||||
title: '确认订单状态',
|
||||
content: '订单状态查询失败 请与客户确认订单状态 点击确认跳转订单列表页面',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/order'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
uni.$J.showToast(`支付中正在进行第${num}次订单查询`).then(res => {
|
||||
req.getById(API_URL_PAY_ORDER_LIST, payOrderId).then(({ bizData }) => {
|
||||
num += 1
|
||||
console.log('查单结果', bizData)
|
||||
bizData.orderState = bizData.state
|
||||
findOrderState(bizData)
|
||||
})
|
||||
})
|
||||
}
|
||||
function getAd() {
|
||||
$adBannerList().then(({ bizData }) => {
|
||||
if(!bizData){
|
||||
vdata.adList =[]
|
||||
uni.showToast({title:'请求广告数据成功',icon:'success'})
|
||||
return false
|
||||
}
|
||||
vdata.adList = bizData?.appContent ? JSON.parse(bizData.appContent) : []
|
||||
vdata.changeTime = bizData.changeTime
|
||||
uni.showToast({title:'请求广告数据成功',icon:'success'})
|
||||
|
||||
})
|
||||
}
|
||||
// 抽屉打开状态
|
||||
const change = (e) => {
|
||||
vdata.isShow = e
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.idnex-wrapper {
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
height: 11.8vh;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #108ee9;
|
||||
|
||||
.tips-title {
|
||||
font-size: 38rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.store-name {
|
||||
color: #2c2c2c;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.more-but {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 80rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 7rpx;
|
||||
background-color: rgba($color: #108ee9, $alpha: 0.3);
|
||||
|
||||
view {
|
||||
width: 4rpx;
|
||||
height: 4rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #108ee9;
|
||||
}
|
||||
|
||||
view:nth-child(2) {
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-wrapper {
|
||||
margin-top: 100rpx;
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx 10rpx 30rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba($color: #108ee9, $alpha: 0.05);
|
||||
color: #108ee9;
|
||||
|
||||
image {
|
||||
width: 60rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.list-item-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.face-model {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item:nth-child(3) {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.list-item:nth-child(8) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
color: tomato;
|
||||
background-color: rgba(255, 99, 71, 0.05);
|
||||
|
||||
image {
|
||||
svg {
|
||||
fill: tomato !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hover-more {
|
||||
background-color: rgba($color: #000000, $alpha: 0.07) !important;
|
||||
}
|
||||
|
||||
.log-in {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 5rpx 15rpx;
|
||||
}
|
||||
</style>
|
||||
97
jeepay-ui-uapp-face/pages/front/front.vue
Normal file
97
jeepay-ui-uapp-face/pages/front/front.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<view class="front-wrapper">
|
||||
<view class="tips-title" v-if="!vdata.adList.length">等待商家发起收款</view>
|
||||
<JeepayBanner v-else :list="vdata.adList" :interval="vdata.changeTime" height="calc(100vh - 150rpx)" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onReady, onLoad } from '@dcloudio/uni-app'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
import { $adBannerList } from '@/http/apiManager'
|
||||
import envConfig from '@/env/config.js'
|
||||
|
||||
// 接收 后屏 通讯 去支付页面
|
||||
onReady(() => {
|
||||
wxfaceapp.onRemoteMessage(function (res) {
|
||||
const content = JSON.parse(res.content)
|
||||
if (content.type == 'toPay')
|
||||
return uni.navigateTo({
|
||||
url: '/pages/frontPay/frontPay',
|
||||
})
|
||||
if (content.type == 'adBanner') {
|
||||
envConfig.changeEnv(content.env)
|
||||
console.log('content.env', content.env)
|
||||
envConfig.changeEnv(content.env)
|
||||
storageManage.token(content.token) //存入token
|
||||
return getAd()
|
||||
}
|
||||
})
|
||||
// 关闭扫码器
|
||||
wxfaceapp.stopCodeScanner({})
|
||||
})
|
||||
const vdata = reactive({})
|
||||
|
||||
function getAd () {
|
||||
$adBannerList().then(({ bizData }) => {
|
||||
if (!bizData) return vdata.adList = []
|
||||
vdata.adList = JSON.parse(bizData.appContent) || []
|
||||
vdata.changeTime = bizData.changeTime
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.front-wrapper {
|
||||
// padding: 0.01rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
display: block;
|
||||
height: 100%;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.swiper-list {
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.uni-common-mt {
|
||||
margin-top: 60rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.info {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.uni-padding-wrap {
|
||||
width: 550rpx;
|
||||
padding: 0 100rpx;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 160rpx auto;
|
||||
width: 85%;
|
||||
height: 180rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 2rpx;
|
||||
color: #fff;
|
||||
border-radius: 14rpx;
|
||||
background-color: rgba($color: #64ec46, $alpha: .7);
|
||||
}
|
||||
</style>
|
||||
207
jeepay-ui-uapp-face/pages/frontPay/frontPay.vue
Normal file
207
jeepay-ui-uapp-face/pages/frontPay/frontPay.vue
Normal file
@@ -0,0 +1,207 @@
|
||||
<template>
|
||||
<!-- <view class="front-wrapper">
|
||||
<view class="pay-amount" v-if="vdata.isShow">
|
||||
请支付<view>¥{{ vdata.amount }}(元)</view>
|
||||
</view>
|
||||
<view class="pay-but">
|
||||
<JButton @tap="facePay">使用刷脸支付</JButton>
|
||||
</view>
|
||||
<view class="pay-tips">请将付款码对准右下角识别区,距离10厘米左右。</view>
|
||||
</view> -->
|
||||
<view class="wait-pay-top" v-if="vdata.isShow">
|
||||
<view class="pay-info">
|
||||
<view class="pay-num">¥{{ vdata.amount }}</view>
|
||||
<view class="pay-wait-title">请支付</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="face-button" @tap="facePay">
|
||||
<image src="/static/fronyImg/face-icon.svg" mode="scaleToFill" />
|
||||
刷脸支付
|
||||
</view>
|
||||
<view class="face-scan-tips">
|
||||
<view class="scan-title">
|
||||
<image src="/static/fronyImg/scan-code.svg" mode="scaleToFill" />
|
||||
扫码支付
|
||||
</view>
|
||||
<view class="sub-tips"> 请将付款码对准右下角识别区,距离10厘米左右。 <image src="/static/fronyImg/icon-down.svg" mode="scaleToFill" /> </view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onReady, onLoad } from '@dcloudio/uni-app'
|
||||
onLoad(() => {
|
||||
vdata.isShow = true
|
||||
//接受 后屏信息
|
||||
wxfaceapp.onRemoteMessage(function (res) {
|
||||
console.log('后屏消息', res)
|
||||
analysisMsg(JSON.parse(res.content))
|
||||
})
|
||||
wxfaceapp.startCodeScanner({
|
||||
success: (res) => {
|
||||
console.log('打开扫码器成功')
|
||||
console.log(res.replyCode)
|
||||
console.log(res.reply)
|
||||
//声明监听扫码器 使用 扫码器 扫描 后 调用 扫码器 回调事件 获取支付code
|
||||
wxfaceapp.listenCodePayment({
|
||||
success(res) {
|
||||
//被扫码回调事件
|
||||
wxfaceapp.onCodePayEvent(function (r) {
|
||||
console.log('onCodePayEvent code scanned = ' + r)
|
||||
console.log('扫码器', r)
|
||||
postMsg(r)
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
fail: (res) => {
|
||||
console.log('打开扫码器失败')
|
||||
console.log(res.replyCode)
|
||||
console.log(res.reply)
|
||||
},
|
||||
})
|
||||
})
|
||||
/**
|
||||
* 页面初始化完成 监听数据串口 输入事件
|
||||
* */
|
||||
// onReady(() => {
|
||||
// wxfaceapp.startSerialPortObserver({
|
||||
// success: (r) => {
|
||||
// console.log('开启监听串口输入成功', r)
|
||||
// },
|
||||
// fail: (err) => {
|
||||
// console.log('开启监听串口输入失败:', err)
|
||||
// },
|
||||
// })
|
||||
// })
|
||||
const vdata = reactive({
|
||||
amount: '0.00',
|
||||
isShow: true,
|
||||
})
|
||||
// 微信刷脸 刷脸成功后 使用回调 换取支付code
|
||||
const facePay = () => {
|
||||
wxfaceapp.facePay({
|
||||
requireFaceCode: true, //是否需要获取付款码返回给小程序
|
||||
success(res) {
|
||||
console.log('success [launchFaceApp]')
|
||||
console.log('前屏刷脸结果', res)
|
||||
wxfaceapp.onFacePayPassEvent(function (r) {
|
||||
console.log('微信支付回调', r)
|
||||
postMsg(r)
|
||||
})
|
||||
},
|
||||
fail(res) {
|
||||
console.log('fail [launchFaceApp]')
|
||||
console.log(res.replyCode)
|
||||
console.log(res.reply)
|
||||
},
|
||||
})
|
||||
}
|
||||
// 发送给后屏
|
||||
const postMsg = (content) => {
|
||||
wxfaceapp.postMsg({
|
||||
targetAppid: 'wx4710a1619fbb3714',
|
||||
content: JSON.stringify(content),
|
||||
success(res) {
|
||||
console.log('sendMsgResult suc', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('sendMsgResult failed error = ' + res)
|
||||
},
|
||||
})
|
||||
}
|
||||
/*
|
||||
* 解析后屏 发送的消息
|
||||
* type 值 amount 金额 toBanner 去广告页面
|
||||
*
|
||||
* */
|
||||
function analysisMsg(msg) {
|
||||
console.log('msg', msg)
|
||||
switch (msg.type) {
|
||||
case 'amount':
|
||||
vdata.amount = msg.amount
|
||||
break
|
||||
case 'toBanner':
|
||||
wxfaceapp.stopCodeScanner({})
|
||||
uni.navigateTo({
|
||||
url: '/pages/front/front',
|
||||
})
|
||||
break
|
||||
case 'hideAmount':
|
||||
vdata.isShow = false
|
||||
break
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wait-pay-top {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 60vh;
|
||||
background: url('/static/fronyImg/front-bg.svg') no-repeat center / cover;
|
||||
.pay-info {
|
||||
transform: translateY(-80rpx);
|
||||
color: #fff;
|
||||
.pay-num {
|
||||
font-weight: 700;
|
||||
font-size: 62rpx;
|
||||
font-family: wechat sans;
|
||||
}
|
||||
.pay-wait-title {
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: rgba($color: #fff, $alpha: 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
.face-button {
|
||||
background-color: $v-primary;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 65rpx 40rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 15rpx;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
box-shadow: 0 50rpx 50rpx -50rpx rgba(0, 206, 107, 0.5);
|
||||
image {
|
||||
width: 50rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.face-scan-tips {
|
||||
box-sizing: border-box;
|
||||
padding: 20rpx 0;
|
||||
padding-top: 40rpx;
|
||||
margin-top: 20rpx;
|
||||
height: calc(100vh - 60vh - 250rpx);
|
||||
background-color: rgba($color: $v-primary, $alpha: 0.2);
|
||||
.scan-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
color: $v-primary;
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.sub-tips {
|
||||
margin-top: 25rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
font-size: 22rpx;
|
||||
image {
|
||||
width: 25rpx;
|
||||
height: 25rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
135
jeepay-ui-uapp-face/pages/handover/handover.vue
Normal file
135
jeepay-ui-uapp-face/pages/handover/handover.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<!-- 门店展示 暂时接口不满足 -->
|
||||
<!-- <view class="hand-item">
|
||||
<view class="hand-title">门店</view>
|
||||
<view class="hand-info">小伙计</view>
|
||||
</view> -->
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">收银员</view>
|
||||
<view class="hand-info">{{ vdata.realname || vdata.userInfo.realname }}</view>
|
||||
</view>
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">上班时间</view>
|
||||
<view class="hand-info">{{ vdata.workStartTime }}</view>
|
||||
</view>
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">下班时间</view>
|
||||
<view class="hand-info">{{ vdata.workEndTime }}</view>
|
||||
</view>
|
||||
<view class="line"></view>
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">收款金额</view>
|
||||
<view class="hand-info">¥{{ vdata.payAmount }}</view>
|
||||
</view>
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">收款笔数</view>
|
||||
<view class="hand-info">{{ vdata.payCount }}</view>
|
||||
</view>
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">退款金额</view>
|
||||
<view class="hand-info">¥{{ vdata.refundAmount }}</view>
|
||||
</view>
|
||||
<view class="hand-item">
|
||||
<view class="hand-title">退款笔数</view>
|
||||
<view class="hand-info">{{ vdata.refundCount }}</view>
|
||||
</view>
|
||||
<view class="footer-but" v-if="vdata.userInfo.realname">
|
||||
<view @tap="handHandover">交班</view>
|
||||
<view class="record" @tap="toHandoverList">交班记录</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { $handover, $workRecords, $getHandoverById } from '@/http/apiManager'
|
||||
import { reactive, ref } from 'vue'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import cal from '@/commons/utils/cal.js'
|
||||
import dayjs from 'dayjs'
|
||||
onLoad((options) => {
|
||||
getHandoverInfo(options.id)
|
||||
})
|
||||
const vdata = reactive({
|
||||
userInfo: storageManage.userInfo(),
|
||||
})
|
||||
const getHandoverInfo = (id) => {
|
||||
if (id) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: '交班详情',
|
||||
})
|
||||
$getHandoverById(id).then(({ bizData }) => {
|
||||
bizData = cal.yuan(bizData, ['refundAmount', 'payAmount'])
|
||||
Object.assign(vdata, bizData)
|
||||
console.log(bizData)
|
||||
})
|
||||
return
|
||||
}
|
||||
$handover().then(({ bizData }) => {
|
||||
bizData = cal.yuan(bizData, ['refundAmount', 'payAmount'])
|
||||
Object.assign(vdata, bizData)
|
||||
})
|
||||
}
|
||||
|
||||
const handHandover = () => {
|
||||
uni.showModal({
|
||||
title: '是否确认交班?',
|
||||
content: '交班自动下班 并 退出登录',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
$workRecords('2').then((res) => {
|
||||
uni.$J.showToast('交班成功即将退登录').then((r) => {
|
||||
storageManage.cleanByLogout()
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/login',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const toHandoverList = () => uni.navigateTo({ url: '/pages/handover/handoverList' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.hand-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
// border-bottom: 1rpx solid #ededed;
|
||||
.hand-info {
|
||||
color: #bbb;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 15rpx;
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
.footer-but {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 60rpx;
|
||||
|
||||
view {
|
||||
flex: 0 0 30%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70rpx;
|
||||
background-color: $v-primary;
|
||||
border-radius: 14rpx;
|
||||
color: #fff;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.record {
|
||||
background-color: rgba($color: $v-primary, $alpha: 0.7);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
155
jeepay-ui-uapp-face/pages/handover/handoverList.vue
Normal file
155
jeepay-ui-uapp-face/pages/handover/handoverList.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<view class="page-wrapper">
|
||||
<view class="custom-content">
|
||||
<view class="start-time" :style="{ color: vdata.startTime ? '#000' : '#666' }" @tap="refStartTime.show">{{
|
||||
vdata.startTime || '请选择开始时间'
|
||||
}}</view>
|
||||
<view class="endTime-time" :style="{ color: vdata.endTime ? '#000' : '#666' }" @tap="refEndTime.show">{{
|
||||
vdata.endTime || '请选择结束时间'
|
||||
}}</view>
|
||||
</view>
|
||||
<block v-for="v in vdata.list" :key="v.id">
|
||||
<view class="list-main" @tap="toDetails(v.id)">
|
||||
<view class="left">
|
||||
<view class="title">{{ v.realname }}</view>
|
||||
<view class="time">{{ v.workStartTime }}</view>
|
||||
</view>
|
||||
<view class="line">—</view>
|
||||
<view class="right">
|
||||
<view class="amount title">¥{{ (v.successAmount / 100).toFixed(2) }}</view>
|
||||
<view class="time">{{ v.workEndTime || '未下班' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="list-null" v-if="!vdata.hasNext">暂无更多数据</view>
|
||||
</view>
|
||||
<xp-picker mode="ymdhi" ref="refStartTime" @confirm="timeConfirm($event, 'startTime')">
|
||||
<view></view>
|
||||
</xp-picker>
|
||||
<xp-picker mode="ymdhi" ref="refEndTime" @confirm="timeConfirm($event, 'endTime')">
|
||||
<view></view>
|
||||
</xp-picker>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad, onReachBottom, onUnload } from '@dcloudio/uni-app'
|
||||
import { $handoverList } from '@/http/apiManager'
|
||||
import dayjs from 'dayjs'
|
||||
const refStartTime = ref(null)
|
||||
const refEndTime = ref(null)
|
||||
const vdata = reactive({
|
||||
list: [],
|
||||
hasNext: true,
|
||||
})
|
||||
const params = {
|
||||
pageSize: 10,
|
||||
pageNumber: 1,
|
||||
queryDateRange: '',
|
||||
}
|
||||
const getList = () => {
|
||||
if (!vdata.hasNext) return
|
||||
$handoverList(params).then(({ bizData }) => {
|
||||
vdata.list.push(...bizData.records)
|
||||
vdata.hasNext = bizData.hasNext
|
||||
})
|
||||
}
|
||||
getList()
|
||||
onReachBottom(() => {
|
||||
params.pageNumber += 1
|
||||
getList()
|
||||
})
|
||||
/**
|
||||
* @param {e} Object 组件原生 回调 时间戳 日期
|
||||
* @param {key} String vdata 对象的 key 值 赋值使用
|
||||
* */
|
||||
const timeConfirm = (e, key) => {
|
||||
vdata[key] = dayjs(e.timestamp).format('YYYY-MM-DD hh:mm')
|
||||
|
||||
if (key == 'endTime' || (vdata.endTime != undefined && dayjs(vdata.startTime).isAfter(vdata.endTime))) {
|
||||
console.log('进入请求')
|
||||
params.queryDateRange = `customDateTime_${vdata.startTime + ':00'}_${vdata.endTime + ':00'}`
|
||||
vdata.list = []
|
||||
params.pageNumber = 1
|
||||
vdata.hasNext = true
|
||||
getList()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {id} String 用于 和后端交互请求详情
|
||||
* */
|
||||
const toDetails = (id) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/handover/handover?id=' + id,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 15rpx;
|
||||
margin: 30rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 14rpx;
|
||||
|
||||
.title {
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.amount {
|
||||
color: $v-primary;
|
||||
}
|
||||
|
||||
.line {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.time,
|
||||
.line {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-content {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 30rpx;
|
||||
|
||||
view {
|
||||
flex: 0 0 30%;
|
||||
padding: 10rpx 0;
|
||||
background-color: #ded7d7;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list-null {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
margin: 30rpx 0;
|
||||
padding: 0 30rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 35%;
|
||||
height: 2rpx;
|
||||
background-color: #ededed;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
492
jeepay-ui-uapp-face/pages/index/index.vue
Normal file
492
jeepay-ui-uapp-face/pages/index/index.vue
Normal file
@@ -0,0 +1,492 @@
|
||||
<template>
|
||||
<view class="page-wrapper">
|
||||
<uni-nav-bar statusBar :border="false" leftWidth="50%" backgroundColor="transparent">
|
||||
<template #left>
|
||||
<view class="user-info">
|
||||
<image :src="vdata.userInfo.avatarUrl" mode="scaleToFill" />
|
||||
<view class="user-nickname">{{ vdata.userInfo.realname }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<!-- 卡片部分 -->
|
||||
<view class="index-card">
|
||||
<view class="index-content">
|
||||
<view class="index-main">
|
||||
<view class="index-num">¥{{ vdata.indexData.payAmount }}</view>
|
||||
<view class="index-title">今日总收益(元)</view>
|
||||
</view>
|
||||
<view class="index-main">
|
||||
<view class="index-num">¥{{ vdata.indexData.refundAmount }}</view>
|
||||
<view class="index-title">退款金额(元)</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="index-card-footer">
|
||||
<view>收益详情</view>
|
||||
<view @tap="more">查看更多 ></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 发起收款 -->
|
||||
<view class="pay-card" @tap="jumpPage('/pages/payment/payment')">
|
||||
<image src="/static/indexImg/pay.png" mode="scaleToFill" />
|
||||
<view class="pay-text">发起收款</view>
|
||||
</view>
|
||||
<!-- nav 导航部分 -->
|
||||
<view class="index-nav">
|
||||
<view class="nav-content">
|
||||
<block v-for="(v, i) in navList" :key="i">
|
||||
<view class="nav-main" @tap="jumpPage(v.url)">
|
||||
<image :src="v.img" mode="scaleToFill" />
|
||||
<view class="nav-title">{{ v.navTitle }}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="but-content">
|
||||
<view>
|
||||
<JButton @tap="switchOpen" bgColor="rgba(0, 200, 0,0.15)" color="#00C800" bdColor="#00C800" :size="24">切换收款模式
|
||||
</JButton>
|
||||
</view>
|
||||
<view>
|
||||
<JButton @tap="open"
|
||||
:bgColor="vdata.userInfo.workState == 2 ? 'rgba(0, 128, 255,0.15)' : 'rgba(255, 0, 43,0.15)'"
|
||||
:color="vdata.userInfo.workState == 2 ? '#0080FF' : '#FF002B'"
|
||||
:bdColor="vdata.userInfo.workState == 2 ? '#0080FF' : '#FF002B'" :size="24">{{
|
||||
vdata.userInfo.workState == 1 ? '下班' : vdata.userInfo.workState == 2 ? '上班' : '上班' }}打卡</JButton>
|
||||
</view>
|
||||
<view>
|
||||
<JButton bgColor="rgba(255, 170, 0,0.15)" color="#FFAA00" bdColor="#FFAA00" :size="24" @tap='getFrontAd'>刷新前屏广告
|
||||
</JButton>
|
||||
</view>
|
||||
</view>
|
||||
<view style="height: 20rpx"></view>
|
||||
<JButton @tap="loginOut" bgColor="transparent" bdColor="rgba(0,0,0,0.1)" color="#FF002B">退出登录</JButton>
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup ref="refWorker" type="center">
|
||||
<view class="worker-content">
|
||||
<view class="title">{{ vdata.userInfo.workState == 1 ? '下班' : vdata.userInfo.workState == 2 ? '上班' : '上班' }}打卡
|
||||
</view>
|
||||
<view class="worker-time">请确认打卡时间:{{ dayjs().format('YYYY-MM-DD hh:mm') }}</view>
|
||||
<view class="footer-but">
|
||||
<view @tap="close">取消</view>
|
||||
<view class="confirm"
|
||||
@tap="confirmWorker(vdata.userInfo.workState == 1 ? '2' : vdata.userInfo.workState == 2 ? '1' : '1')">确认 </view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
<uni-popup ref="refSwitch" type="center">
|
||||
<view class="switch-model">
|
||||
<view class="title">切换模式</view>
|
||||
<view class="sub-title">独立收银模式:<view class="model-tag">当前正在使用</view>
|
||||
</view>
|
||||
<view class="tips">接入电源后即可使用,后屏输入收款金额,前屏支持刷脸支付和扫码支付。</view>
|
||||
<view class="sub-title">POS模式:</view>
|
||||
<view class="tips">需要连接收银机或PC使用,即插即用,收款将会进入您的现有收银软件账户。</view>
|
||||
<view class="pay-model" hover-class="hover-model" hover-stay-time="50" @tap="toPos">
|
||||
<image src="/static/iconImg/switch-model.svg" mode="scaleToFill" />
|
||||
切换至POS模式
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { $indexPayment, $workRecords, $userInfo, $adBannerList } from '@/http/apiManager'
|
||||
import { onLoad, onReady, onUnload, onShow } from '@dcloudio/uni-app'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
import cal from '@/commons/utils/cal.js'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
onLoad(() => {
|
||||
getFrontAd()
|
||||
if (storageManage.faceModel() && storageManage.faceModel() == 'pos') return uni.reLaunch({ url: '/pages/payModel/payModel' })
|
||||
})
|
||||
onShow(() => {
|
||||
getIndexDate()
|
||||
})
|
||||
const refWorker = ref(null)
|
||||
const refSwitch = ref(null)
|
||||
|
||||
// 导航栏列表
|
||||
const navList = [
|
||||
{
|
||||
img: '/static/indexImg/order.png',
|
||||
url: '/pages/order/order',
|
||||
navTitle: '订单',
|
||||
},
|
||||
{
|
||||
img: '/static/indexImg/handover.png',
|
||||
url: '/pages/handover/handover',
|
||||
navTitle: '交班',
|
||||
},
|
||||
{
|
||||
img: '/static/indexImg/statics.png',
|
||||
url: '/pages/stat/stat',
|
||||
navTitle: '统计',
|
||||
},
|
||||
]
|
||||
const vdata = reactive({
|
||||
userInfo: storageManage.userInfo(), //取出用户信息
|
||||
indexData: {},
|
||||
})
|
||||
// 查询 当天 收益情况
|
||||
const getIndexDate = () => {
|
||||
$indexPayment().then(({ bizData }) => {
|
||||
const { dayCount } = bizData
|
||||
vdata.indexData = cal.yuan(dayCount, ['payAmount', 'refundAmount']) //分转元
|
||||
})
|
||||
}
|
||||
|
||||
const open = () => refWorker.value.open()
|
||||
const close = () => refWorker.value.close()
|
||||
const switchOpen = () => refSwitch.value.open()
|
||||
// 确认打卡
|
||||
const confirmWorker = (state) => {
|
||||
$workRecords(state).then((res) => {
|
||||
uni.showToast({
|
||||
title: '打卡成功',
|
||||
icon: 'success|none',
|
||||
mask: true,
|
||||
})
|
||||
// 请求用户信息
|
||||
return $userInfo().then(({ bizData }) => {
|
||||
// 更新用户数据
|
||||
storageManage.userInfo(bizData)
|
||||
// 更新用户数据
|
||||
vdata.userInfo = bizData
|
||||
//跳转首页
|
||||
close()
|
||||
})
|
||||
})
|
||||
}
|
||||
const loginOut = () => {
|
||||
uni.showModal({
|
||||
title: '确认推出登录吗',
|
||||
content: '',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
storageManage.cleanByLogout()
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/login',
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
const toFront = () => uni.navigateTo({ url: '/pages/front/front' })
|
||||
const jumpPage = (url) => uni.navigateTo({ url })
|
||||
uni.addInterceptor('navigateTo', {
|
||||
invoke(args) {
|
||||
if (vdata.userInfo.workState != 1 && args.url == '/pages/handover/handover') {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '当前状态为,未上班状态,不能进入交班页面,点击确认按钮打卡上班。 ',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
refWorker.value.open()
|
||||
}
|
||||
},
|
||||
})
|
||||
return false
|
||||
}
|
||||
},
|
||||
})
|
||||
const toPos = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否切换为 POS模式?',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
storageManage.faceModel('pos')
|
||||
uni.reLaunch({ url: '/pages/payModel/payModel' })
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const more = () => {
|
||||
uni.navigateTo({ url: '/pages/stat/stat' })
|
||||
}
|
||||
const getFrontAd = () => {
|
||||
const content = { type: 'adBanner', token: storageManage.token(), env: storageManage.env() }
|
||||
wxfaceapp.postMsg({
|
||||
targetAppid: 'wx4710a1619fbb3714',
|
||||
content: JSON.stringify(content),
|
||||
success(res) {
|
||||
uni.$J.showToast('通知前屏获取广告成功')
|
||||
console.log('通信成功', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('通信失败 ', res)
|
||||
},
|
||||
})
|
||||
}
|
||||
onUnload(() => {
|
||||
uni.removeInterceptor('navigateTo')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-wrapper {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
background: url('/static/indexImg/index-bg.png') no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
|
||||
.user-nickname {
|
||||
margin-left: 20rpx;
|
||||
font-weight: 700;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 收益卡片
|
||||
.index-card {
|
||||
margin: 30rpx;
|
||||
background: url('/static/indexImg/databg.png') no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.index-content {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.index-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 50rpx;
|
||||
color: #fff;
|
||||
|
||||
.index-num {
|
||||
margin-bottom: 15rpx;
|
||||
font-size: 45rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.index-title {
|
||||
font-size: 24rpx;
|
||||
color: rgba($color: #fff, $alpha: 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.index-card-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx;
|
||||
|
||||
view {
|
||||
font-size: 24rpx;
|
||||
color: rgba($color: #fff, $alpha: 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 发起收款
|
||||
.pay-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 30rpx 30rpx;
|
||||
margin-top: 60rpx;
|
||||
height: 145rpx;
|
||||
background: url('/static/indexImg/paybg.png') no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
color: #fff;
|
||||
border-radius: 22rpx;
|
||||
|
||||
image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.pay-text {
|
||||
font-weight: 900;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// nav 导航
|
||||
.index-nav {
|
||||
position: absolute;
|
||||
bottom: 30rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
// background-color: tomato;
|
||||
background-color: transparent;
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
padding: 0 30rpx;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 50rpx;
|
||||
|
||||
.nav-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 25%;
|
||||
height: 180rpx;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 15rpx;
|
||||
color: #fff;
|
||||
|
||||
&:nth-child(1) {
|
||||
background: url('/static/indexImg/orderbg.png') no-repeat center center;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
background: url('/static/indexImg/handoverbg.png') no-repeat center center;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
background: url('/static/indexImg/staticsbg.png') no-repeat center center;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 65rpx;
|
||||
height: 65rpx;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-weight: 600;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.worker-content {
|
||||
padding: 0.1rpx;
|
||||
width: 420rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 14rpx;
|
||||
|
||||
.title {
|
||||
margin: 20rpx 0;
|
||||
text-align: center;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.worker-time {
|
||||
transform: translateY(25rpx);
|
||||
margin-left: 20rpx;
|
||||
font-size: 18rpx;
|
||||
}
|
||||
|
||||
.footer-but {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 0 30rpx;
|
||||
margin: 40rpx 0;
|
||||
margin-top: 65rpx;
|
||||
|
||||
view {
|
||||
flex: 0 0 35%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
letter-spacing: 2rpx;
|
||||
height: 55rpx;
|
||||
background-color: rgba($color: #35d757, $alpha: 0.6);
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.confirm {
|
||||
background-color: #35d757;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.but-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
view {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.switch-model {
|
||||
padding: 0.1rpx 20rpx;
|
||||
padding-bottom: 30rpx;
|
||||
width: 470rpx;
|
||||
min-height: 300rpx;
|
||||
border-radius: 14rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.title {
|
||||
margin: 30rpx 0;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-size: 18rpx;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
|
||||
.model-tag {
|
||||
float: right;
|
||||
background-color: #27dc70;
|
||||
color: #fff;
|
||||
padding: 5rpx 10rpx;
|
||||
border-radius: 5rpx;
|
||||
font-size: 14rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #595959;
|
||||
font-size: 15rpx;
|
||||
margin: 20rpx 0;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.pay-model {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
height: 60rpx;
|
||||
border: 1rpx solid #1ab345;
|
||||
border-radius: 5rpx;
|
||||
background-color: rgba(241, 255, 245, 0.3);
|
||||
color: #1ab245;
|
||||
font-size: 18rpx;
|
||||
letter-spacing: 2rpx;
|
||||
|
||||
image {
|
||||
margin-right: 8rpx;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.hover-model {
|
||||
background-color: #1ab345;
|
||||
color: #fff;
|
||||
}
|
||||
}</style>
|
||||
151
jeepay-ui-uapp-face/pages/login/components/EnvChangeTips.vue
Normal file
151
jeepay-ui-uapp-face/pages/login/components/EnvChangeTips.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<!--
|
||||
环境变量切换组件
|
||||
|
||||
@author terrfly
|
||||
@site https://www.jeequan.com
|
||||
@date 2022/04/12 10:14
|
||||
-->
|
||||
<template>
|
||||
<view>
|
||||
<!-- 当包含环境变量 && 不是生产环境时 -->
|
||||
<view
|
||||
class="login-test"
|
||||
v-if="
|
||||
vdata.currentEnvEnum &&
|
||||
vdata.currentEnvEnum != appConfig.ENV_ENUM.PRODUCTION
|
||||
"
|
||||
><text>{{ vdata.currentEnvEnum }}</text></view
|
||||
>
|
||||
<!-- 切换环境提示 -->
|
||||
<uni-popup ref="uniPopupRef" :mask-click="false" :open="true">
|
||||
<view class="uni-popup-dialog">
|
||||
<image
|
||||
@tap="uniClose"
|
||||
class="uni-dialog-close"
|
||||
src="/static/indexImg/del.svg"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
<view class="uni-dialog-button-box">
|
||||
<view
|
||||
class="uni-dialog-button"
|
||||
style="border-bottom: 2rpx solid #e1e1e1"
|
||||
@click="changeEnvFunc(appConfig.ENV_ENUM.DEVELOPMENT)"
|
||||
><text>开发环境</text></view
|
||||
>
|
||||
<view
|
||||
class="uni-dialog-button"
|
||||
style="border-bottom: 2rpx solid #e1e1e1"
|
||||
@click="changeEnvFunc(appConfig.ENV_ENUM.TEST)"
|
||||
><text>测试环境</text></view
|
||||
>
|
||||
<view
|
||||
class="uni-dialog-button"
|
||||
style="border-bottom: 2rpx solid #e1e1e1"
|
||||
@click="changeEnvFunc(appConfig.ENV_ENUM.DEMO)"
|
||||
><text>演示环境</text></view
|
||||
>
|
||||
<view
|
||||
class="uni-dialog-button"
|
||||
@click="changeEnvFunc(appConfig.ENV_ENUM.PRODUCTION)"
|
||||
><text>生产环境</text></view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import appConfig from '@/config/appConfig.js'
|
||||
import envConfig from '@/env/config.js'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
|
||||
|
||||
const uniPopupRef = ref()
|
||||
|
||||
// emit
|
||||
const emit = defineEmits(['change'])
|
||||
|
||||
const vdata = reactive({
|
||||
currentEnvEnum: '', // 当前环境变量
|
||||
count: 0, // 当前点击次数
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
vdata.currentEnvEnum = storageManage.env()
|
||||
})
|
||||
|
||||
// 父组件的点击事件
|
||||
function tapFunc() {
|
||||
vdata.count++
|
||||
if (vdata.count >= 10) {
|
||||
vdata.count = 0
|
||||
uniPopupRef.value.open()
|
||||
}
|
||||
}
|
||||
|
||||
// 改变环境函数
|
||||
function changeEnvFunc(envMode) {
|
||||
vdata.currentEnvEnum = envMode //显示信息
|
||||
envConfig.changeEnv(envMode) //更改请求包
|
||||
storageManage.env(envMode) // 改变存储
|
||||
|
||||
|
||||
|
||||
uniPopupRef.value.close() //弹层关闭
|
||||
}
|
||||
// 关闭弹窗
|
||||
function uniClose() {
|
||||
uniPopupRef.value.close()
|
||||
}
|
||||
defineExpose({ tapFunc })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-dialog {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 500rpx;
|
||||
height: 600rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 30rpx;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
.uni-dialog-close {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
.uni-dialog-button-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
padding: 0 40rpx;
|
||||
.uni-dialog-button {
|
||||
width: 100%;
|
||||
height: 150rpx;
|
||||
line-height: 150rpx;
|
||||
text {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-test {
|
||||
position: absolute;
|
||||
bottom: 70rpx;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
text {
|
||||
color: #666f80;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
115
jeepay-ui-uapp-face/pages/login/login.vue
Normal file
115
jeepay-ui-uapp-face/pages/login/login.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<view class="login-header">
|
||||
<image src="/static/logo.png" mode="scaleToFill" @tap="switchEnv" />
|
||||
<view class="login-title">计全收银Pro</view>
|
||||
</view>
|
||||
<LoginInput title="账号" place="请输入登录名/手机号" require ref="refAccount" v-model:value="vdata.username" />
|
||||
<LoginInput title="密码" password place="请输入密码" require type="password" ref="refPwd" v-model:value="vdata.pwd" />
|
||||
<view class="button-main">
|
||||
<JButton @click="submit">登录</JButton>
|
||||
</view>
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<view class="support-content">
|
||||
<view class="sup-title">技术支持:</view>
|
||||
<view class="phone-number">{{ vdata.phone || '18611727422' }}</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<EnvChangeTips ref="refEnv" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { $login, $userInfo, $getCompanyInfos } from '@/http/apiManager'
|
||||
import EnvChangeTips from './components/EnvChangeTips.vue'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
const refAccount = ref(null)
|
||||
const refPwd = ref(null)
|
||||
const refEnv = ref(null)
|
||||
const vdata = reactive({})
|
||||
onMounted(() => {
|
||||
// #ifdef MP-WEIXIN
|
||||
wxfaceapp.checkWxFacePayOsInfo({
|
||||
success(res) {
|
||||
console.log('success [checkWxFacePayOsInfo]', res)
|
||||
storageManage.deviceNo(res.osSerialNumber) //本地存储写入 设备号
|
||||
console.log(storageManage.deviceNo())
|
||||
},
|
||||
fail(err) {
|
||||
console.log('fail [checkWxFacePayOsInfo]', err)
|
||||
},
|
||||
})
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
my.ix.getSysProp({
|
||||
key: 'ro.serialno',
|
||||
success: (r) => {
|
||||
console.log('r', r)
|
||||
storageManage.deviceNo(r.value) //本地存储写入 设备号
|
||||
},
|
||||
})
|
||||
// #endif
|
||||
$getCompanyInfos().then(({ bizData }) => {
|
||||
const { siteInfo } = bizData
|
||||
vdata.phone = siteInfo.companyTel
|
||||
})
|
||||
})
|
||||
const submit = () => {
|
||||
console.log('submit')
|
||||
if (refAccount.value.check() && refPwd.value.check()) {
|
||||
$login(vdata).then(({ bizData }) => {
|
||||
// 保存 token
|
||||
storageManage.token(bizData.iToken)
|
||||
// 请求用户信息
|
||||
return $userInfo().then(({ bizData }) => {
|
||||
// 保存用户数据
|
||||
storageManage.userInfo(bizData)
|
||||
// 存储设备号
|
||||
// #ifdef MP-WEIXIN
|
||||
//跳转首页
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index',
|
||||
})
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
console.log('执行')
|
||||
uni.reLaunch({
|
||||
url: '/pages/aliIndex/index',
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
const switchEnv = () => refEnv.value.tapFunc()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
margin-top: 80rpx;
|
||||
width: 260rpx;
|
||||
height: 260rpx;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
margin-bottom: 50rpx;
|
||||
font-weight: 700;
|
||||
font-size: 46rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.button-main {
|
||||
margin-top: 80rpx;
|
||||
}
|
||||
.support-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 50rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
102
jeepay-ui-uapp-face/pages/order/components/OrderCard.vue
Normal file
102
jeepay-ui-uapp-face/pages/order/components/OrderCard.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<view class="card-wrapper" @tap="emits('click')">
|
||||
<view class="img-box" :style="{ backgroundColor: payImg(wayCodeType).bgColor }">
|
||||
<image :src="payImg(wayCodeType).imgUrl" mode="scaleToFill" />
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<view class="card-title">
|
||||
<view class="title">收款</view>
|
||||
<view class="num">+{{ (amount / 100).toFixed(2) }}</view>
|
||||
</view>
|
||||
<view class="order-number">
|
||||
<view class="order-title">订单编号:</view>
|
||||
{{ payOrderId }}
|
||||
</view>
|
||||
<view class="card-time">
|
||||
<view class="created-time">{{ createdAt }}</view>
|
||||
<view class="card-state" :style="{ backgroundColor: payState(state).color }">{{ payState(state).text }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const emits = defineEmits(['click'])
|
||||
const props = defineProps({
|
||||
payOrderId: { type: String }, //订单编号
|
||||
createdAt: { type: String }, //创建 时间
|
||||
amount: { type: [String, Number] }, //收款金额
|
||||
wayCodeType: { type: String }, // 支付方式
|
||||
state: { type: [String, Number] }, // 状态
|
||||
})
|
||||
const payImg = uni.$J.dataMap.payImg
|
||||
const payState = uni.$J.dataMap.payStateMap
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-wrapper {
|
||||
display: flex;
|
||||
|
||||
margin: 30rpx;
|
||||
padding: 20rpx 0 20rpx 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 15rpx;
|
||||
|
||||
.img-box {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 30rpx;
|
||||
width: 20%;
|
||||
border-radius: 14rpx;
|
||||
|
||||
image {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.card-info {
|
||||
flex: 1;
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
|
||||
.num {
|
||||
margin-right: 20rpx;
|
||||
color: rgba(45, 218, 119, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.order-number {
|
||||
display: flex;
|
||||
margin: 20rpx 0;
|
||||
font-size: 18rpx;
|
||||
color: rgba(102, 102, 102, 1);
|
||||
}
|
||||
|
||||
.card-time {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.created-time {
|
||||
font-size: 18rpx;
|
||||
color: rgba(179, 179, 179, 1);
|
||||
}
|
||||
|
||||
.card-state {
|
||||
padding: 8rpx 30rpx;
|
||||
background-color: rgba(45, 218, 119, 1);
|
||||
border-radius: 20rpx 0 0 20rpx;
|
||||
font-size: 12rpx;
|
||||
color: #fff;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
173
jeepay-ui-uapp-face/pages/order/components/OrderScreen.vue
Normal file
173
jeepay-ui-uapp-face/pages/order/components/OrderScreen.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<uni-drawer ref="refDrawer" mode="right">
|
||||
<uni-nav-bar statusBar :border="false" backgroundColor="transparent" />
|
||||
<view class="title">根据时间筛选</view>
|
||||
<view class="time-wrapper">
|
||||
<view class="time-star" @tap="refStarTime.show" :style="{ color: vdata.starTime ? '#000' : '#999' }">{{ vdata.starTime || '开始时间' }}</view>
|
||||
---
|
||||
<view class="time-end" @tap="refEndTime.show" :style="{ color: vdata.endTime ? '#000' : '#999' }">{{ vdata.endTime || '结束时间' }}</view>
|
||||
</view>
|
||||
<view class="title">支付方式</view>
|
||||
<view class="pay-model">
|
||||
<block v-for="v in payModelList" :key="v.value">
|
||||
<view class="model-item" :class="{ 'selected-item': vdata.payModel.includes(v.value) }" @tap="selectedItem(v.value, 'payModel')">{{ v.label }}</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="title">订单状态</view>
|
||||
<view class="state-list pay-model">
|
||||
<block v-for="v in stateList" :key="v.value">
|
||||
<view class="state-item model-item" :class="{ 'selected-item': vdata.payState.includes(v.value) }" @tap="selectedItem(v.value, 'payState')">{{ v.label }}</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="footer-button">
|
||||
<view @tap="reset">重置</view>
|
||||
<view class="confirm" @tap="confirm">确认</view>
|
||||
</view>
|
||||
</uni-drawer>
|
||||
<xp-picker ref="refStarTime" mode="ymdhi" v-model="vdata.starTime" @confirm="confirmStart"><view></view></xp-picker>
|
||||
<xp-picker ref="refEndTime" mode="ymdhi" v-model="vdata.endTime" @confirm="confirmEnd"><view></view></xp-picker>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject, onMounted, reactive, ref } from 'vue'
|
||||
import { startAndEndTime } from '@/commons/utils/timeInspect'
|
||||
import dayjs from 'dayjs'
|
||||
const params = inject('params') //引入 父级注入的依赖
|
||||
const emits = defineEmits(['confirm'])
|
||||
const payModelList = [
|
||||
{ label: '云闪付', value: 'YSFPAY' },
|
||||
{ label: '支付宝', value: 'ALIPAY' },
|
||||
{ label: '银联', value: 'UNIONPAY' },
|
||||
{ label: '微信', value: 'WECHAT' },
|
||||
{ label: '其他', value: 'OTHER' },
|
||||
]
|
||||
const stateList = [
|
||||
{ label: '订单生成', value: '0' },
|
||||
{ label: '支付中', value: '1' },
|
||||
{ label: '支付成功', value: '2' },
|
||||
{ label: '支付失败', value: '3' },
|
||||
{ label: '已撤销', value: '4' },
|
||||
{ label: '已退款', value: '5' },
|
||||
{ label: '订单关闭', value: '6' },
|
||||
]
|
||||
const vdata = reactive({
|
||||
starTime: '',
|
||||
endTime: '',
|
||||
payModel: [],
|
||||
payState: [],
|
||||
})
|
||||
const refStarTime = ref(null)
|
||||
const refEndTime = ref(null)
|
||||
const refDrawer = ref(null)
|
||||
const open = () => {
|
||||
refDrawer.value.open()
|
||||
}
|
||||
const close = () => {
|
||||
refDrawer.value.close()
|
||||
}
|
||||
const confirmStart = (e) => {
|
||||
vdata.starTime = dayjs(e.timestamp).format('YYYY-MM-DD hh:mm')
|
||||
console.log(e)
|
||||
}
|
||||
const confirmEnd = (e) => {
|
||||
vdata.endTime = dayjs(e.timestamp).format('YYYY-MM-DD hh:mm')
|
||||
}
|
||||
const selectedItem = (v, key) => {
|
||||
if (vdata[key].includes(v))
|
||||
return vdata[key].splice(
|
||||
vdata[key].findIndex((item) => item == v),
|
||||
1
|
||||
)
|
||||
|
||||
vdata[key].push(v)
|
||||
}
|
||||
const confirm = () => {
|
||||
if (vdata.starTime || vdata.endTime) {
|
||||
if (!startAndEndTime(vdata.starTime, vdata.endTime)) return
|
||||
params.queryDateRange = `customDateTime_${vdata.starTime + ':00'}_${vdata.endTime + ':00'}`
|
||||
}
|
||||
params.unionOrderState = vdata.payState.join(',')
|
||||
params.unionWayCodeType = vdata.payModel.join(',')
|
||||
emits('confirm')
|
||||
close()
|
||||
}
|
||||
const reset = () => {
|
||||
vdata.starTime = ''
|
||||
vdata.endTime = ''
|
||||
vdata.payModel = []
|
||||
vdata.payState = []
|
||||
}
|
||||
defineExpose({ open, close })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
margin-top: 20rpx;
|
||||
margin-left: 30rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
.time-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 20rpx;
|
||||
font-size: 16rpx;
|
||||
letter-spacing: 2rpx;
|
||||
.time-star,
|
||||
.time-end {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 30rpx;
|
||||
height: 50rpx;
|
||||
background-color: rgb(235, 227, 227);
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
}
|
||||
.pay-model {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 10rpx;
|
||||
.model-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin: 20rpx;
|
||||
height: 50rpx;
|
||||
width: 24%;
|
||||
font-size: 16rpx;
|
||||
letter-spacing: 2rpx;
|
||||
background-color: rgba($color: #000000, $alpha: 0.15);
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
}
|
||||
.footer-button {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx;
|
||||
margin-top: 80rpx;
|
||||
color: #fff;
|
||||
font-size: 18rpx;
|
||||
letter-spacing: 2rpx;
|
||||
view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 220rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 10rpx;
|
||||
background-color: rgba($color: #666666, $alpha: 0.3);
|
||||
}
|
||||
.confirm {
|
||||
background-color: $v-primary;
|
||||
}
|
||||
}
|
||||
.selected-item {
|
||||
background-color: $v-primary !important;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
138
jeepay-ui-uapp-face/pages/order/order.vue
Normal file
138
jeepay-ui-uapp-face/pages/order/order.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<view class="page-content">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<uni-nav-bar statusBar :border="false" leftIcon="left" fixed title="订单列表" backgroundColor="#f5f7f5"
|
||||
@clickLeft="navBack" />
|
||||
<!-- #endif -->
|
||||
<!--#ifdef MP-ALIPAY -->
|
||||
<uni-nav-bar statusBar :border="false" title="订单列表" fixed backgroundColor="#f5f7f5" @clickLeft="navBack" />
|
||||
<!-- #endif -->
|
||||
<view class="order-search-content">
|
||||
<view class="order-search">
|
||||
<image src="/static/iconImg/icon-search.svg" mode="scaleToFill" />
|
||||
<input type="text" v-model="vdata.unionOrderId" confirm-type="search" @confirm="search"
|
||||
placeholder="请输入订单号查询" />
|
||||
</view>
|
||||
<image class="screen" src="/static/iconImg/icon-screen.svg" mode="scaleToFill" @tap="refScreen.open" />
|
||||
</view>
|
||||
<!-- 卡片部分 -->
|
||||
<block v-for="v in vdata.orderList" :key="v.payOrderId">
|
||||
<OrderCard v-bind="v" @click="toDetails(v.payOrderId)" />
|
||||
</block>
|
||||
<view class="list-null" v-if="!vdata.hasNext">暂无更多数据</view>
|
||||
</view>
|
||||
<OrderScreen ref="refScreen" @confirm="search" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { provide, reactive, ref } from 'vue'
|
||||
import { onLoad, onReachBottom, onUnload } from '@dcloudio/uni-app'
|
||||
import { req, API_URL_PAY_ORDER_LIST } from '@/http/apiManager.js'
|
||||
import OrderScreen from './components/OrderScreen'
|
||||
import OrderCard from './components/OrderCard.vue'
|
||||
const refScreen = ref(null)
|
||||
const vdata = reactive({
|
||||
orderList: [],
|
||||
unionOrderId: '',
|
||||
hasNext: true,
|
||||
})
|
||||
const params = { pageSize: 10, pageNumber: 1, queryDateRange: '' }
|
||||
provide('params', params)
|
||||
const getList = () => {
|
||||
if (!vdata.hasNext) return
|
||||
req.list(API_URL_PAY_ORDER_LIST, params).then(({ bizData }) => {
|
||||
vdata.orderList.push(...bizData.records)
|
||||
vdata.hasNext = bizData.hasNext
|
||||
})
|
||||
}
|
||||
getList()
|
||||
const search = () => {
|
||||
params.unionOrderId = vdata.unionOrderId
|
||||
vdata.orderList = []
|
||||
params.pageNumber = 1
|
||||
vdata.hasNext = true
|
||||
getList()
|
||||
}
|
||||
onReachBottom(() => {
|
||||
params.pageNumber += 1
|
||||
getList()
|
||||
})
|
||||
// 跳转详情页
|
||||
const toDetails = (orderId) => uni.navigateTo({ url: '/pages/order/orderDetails?orderId=' + orderId })
|
||||
uni.$on('ORDER_LIST', (data) => {
|
||||
console.log('刷新列表');
|
||||
vdata.orderList = []
|
||||
params.pageNumber = 1
|
||||
getList()
|
||||
})
|
||||
const navBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
onUnload(() => {
|
||||
uni.$off('ORDER_LIST')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
padding: 0.1rpx;
|
||||
min-height: calc(100vh - 5rpx);
|
||||
background-color: #f5f7f5;
|
||||
|
||||
.order-search-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.order-search {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 30rpx;
|
||||
margin-bottom: 0;
|
||||
height: 80rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 15rpx;
|
||||
|
||||
image {
|
||||
margin-left: 20rpx;
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 22rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.screen {
|
||||
margin-right: 30rpx;
|
||||
transform: translateY(15rpx);
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-null {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
margin: 30rpx 0;
|
||||
padding: 0 30rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 35%;
|
||||
height: 2rpx;
|
||||
background-color: #ededed;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
133
jeepay-ui-uapp-face/pages/order/orderDetails.vue
Normal file
133
jeepay-ui-uapp-face/pages/order/orderDetails.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<view class="details-header-card">
|
||||
<view class="order-num">
|
||||
<view class="img-box" :style="{ backgroundColor: payModel(vdata.wayCodeType).bgColor }">
|
||||
<image :src="payModel(vdata.wayCodeType).imgUrl" mode="scaleToFill" />
|
||||
</view>
|
||||
<view class="payment">¥{{ (vdata.amount / 100).toFixed(2) }}</view>
|
||||
</view>
|
||||
<view class="card-text">收款金额</view>
|
||||
<view class="refund" v-if="vdata.refundState != 2" @tap="toRefund">退款</view>
|
||||
</view>
|
||||
<view class="line" style="height: 20rpx"></view>
|
||||
<view class="order-info">
|
||||
<view class="title">订单金额</view>
|
||||
<view class="info">¥{{ (vdata.amount / 100).toFixed(2) }}</view>
|
||||
</view>
|
||||
<view class="order-info">
|
||||
<view class="title">退款金额</view>
|
||||
<view class="info">¥{{ (vdata.refundAmount / 100).toFixed(2) }}</view>
|
||||
</view>
|
||||
<view class="order-info">
|
||||
<view class="title">订单号</view>
|
||||
<view class="info">{{ vdata.payOrderId }}</view>
|
||||
</view>
|
||||
<view class="order-info">
|
||||
<view class="title">订单时间</view>
|
||||
<view class="info">{{ vdata.createdAt }}</view>
|
||||
</view>
|
||||
<view class="line"></view>
|
||||
<view class="order-info">
|
||||
<view class="title">支付方式</view>
|
||||
<view class="info">{{ payModel(vdata.wayCodeType).title }}</view>
|
||||
</view>
|
||||
<view class="order-info">
|
||||
<view class="title">订单状态</view>
|
||||
<view class="info">{{ payState(vdata.state).text }}</view>
|
||||
</view>
|
||||
<view class="line"></view>
|
||||
<view class="order-info">
|
||||
<view class="title">门店名称</view>
|
||||
<view class="info">{{ vdata.storeName }}</view>
|
||||
</view>
|
||||
<view class="order-info">
|
||||
<view class="title">操作员名称</view>
|
||||
<view class="info">{{ vdata.storeUserName }}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import { req, API_URL_PAY_ORDER_LIST } from '@/http/apiManager.js'
|
||||
onLoad((options) => {
|
||||
getDetails(options.orderId)
|
||||
})
|
||||
const vdata = reactive({})
|
||||
const payModel = uni.$J.dataMap.payImg
|
||||
const payState = uni.$J.dataMap.payStateMap
|
||||
const getDetails = (id) => {
|
||||
req.getById(API_URL_PAY_ORDER_LIST, id).then(({ bizData }) => {
|
||||
Object.assign(vdata, bizData)
|
||||
})
|
||||
}
|
||||
const toRefund = (oderId) => uni.navigateTo({ url: '/pages/orderRefund/orderRefund?orderId=' + vdata.payOrderId })
|
||||
uni.$on('ORDER_DETAILS', (data) => {
|
||||
getDetails(vdata.payOrderId)
|
||||
})
|
||||
onUnload(() => {
|
||||
uni.$off('ORDER_DETAILS')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.details-header-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 280rpx;
|
||||
.order-num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.img-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 20rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 14rpx;
|
||||
image {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
.payment {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-size: 40rpx;
|
||||
font-weight: 700;
|
||||
color: rgba(45, 218, 119, 1);
|
||||
}
|
||||
}
|
||||
.card-text {
|
||||
margin-top: 30rpx;
|
||||
color: #666;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 2rpx;
|
||||
background-color: #ededed;
|
||||
}
|
||||
.order-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 30rpx 20rpx;
|
||||
font-size: 22rpx;
|
||||
.info {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
.refund {
|
||||
padding: 15rpx 30rpx;
|
||||
background-color: tomato;
|
||||
margin-top: 30rpx;
|
||||
border-radius: 14rpx;
|
||||
color: rgba($color: #fff, $alpha: 0.7);
|
||||
font-size: 20rpx;
|
||||
}
|
||||
</style>
|
||||
218
jeepay-ui-uapp-face/pages/orderRefund/orderRefund.vue
Normal file
218
jeepay-ui-uapp-face/pages/orderRefund/orderRefund.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<view class="refund-amount">
|
||||
<view class="amount">¥{{ (vdata.amount / 100).toFixed(2) }}</view>
|
||||
<view class="title">收款金额</view>
|
||||
</view>
|
||||
<view class="refund">
|
||||
<view>已退金额</view>
|
||||
<view>¥{{ (vdata.refundAmount / 100).toFixed(2) }}</view>
|
||||
</view>
|
||||
<view class="refund">
|
||||
<view>可退金额</view>
|
||||
<view>¥{{ ((vdata.amount - vdata.refundAmount) / 100).toFixed(2) }}</view>
|
||||
</view>
|
||||
<view class="line"></view>
|
||||
<view class="input-title">输入退款金额(元)</view>
|
||||
<view class="input-refund">
|
||||
<input type="digit" placeholder="请输入退款金额" v-model="vdata.refundAmountNum" />
|
||||
<view class="input-but" @tap="sumOrReset">
|
||||
{{ vdata.refundAmountNum ? '取消' : '全额' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="remarks-input">
|
||||
<view class="remarks">退款原因:</view>
|
||||
<input type="text" placeholder="请输入退款原因" maxlength="50" v-model="vdata.refundReason" />
|
||||
</view>
|
||||
<view class="refund-button" @tap="open">退款</view>
|
||||
|
||||
<uni-popup ref="refPopup" type="center">
|
||||
<view class="refund-pwd">
|
||||
<view class="title">退款密码</view>
|
||||
<view class="input-box">
|
||||
<input type="number" maxlength="6" password v-model="vdata.refundPassword" focus
|
||||
style="flex-grow: 1; width: 100%" />
|
||||
</view>
|
||||
<view class="button-box">
|
||||
<view @tap="close">取消</view>
|
||||
<view class="confirm" @tap="confirmRefund">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { req, API_URL_PAY_ORDER_LIST, $payOrderRefund } from '@/http/apiManager.js'
|
||||
onLoad((options) => {
|
||||
getDetails(options.orderId)
|
||||
})
|
||||
const vdata = reactive({})
|
||||
const refPopup = ref(null)
|
||||
const getDetails = (id) => {
|
||||
req.getById(API_URL_PAY_ORDER_LIST, id).then(({ bizData }) => {
|
||||
Object.assign(vdata, bizData)
|
||||
})
|
||||
}
|
||||
const sumOrReset = () => {
|
||||
return vdata.refundAmountNum ? (vdata.refundAmountNum = '') : (vdata.refundAmountNum = ((vdata.amount - vdata.refundAmount) / 100).toFixed(2))
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
if (!vdata.refundReason) return errText('请输入退款原因')
|
||||
refPopup.value.open()
|
||||
}
|
||||
const close = () => refPopup.value.close()
|
||||
const confirmRefund = () => {
|
||||
if (!vdata.refundPassword) return errText('请输入密码')
|
||||
uni.showLoading({
|
||||
title: '请稍等',
|
||||
mask: true,
|
||||
})
|
||||
$payOrderRefund(vdata)
|
||||
.then((res) => {
|
||||
uni.showLoading()
|
||||
uni.$emit('ORDER_DETAILS')
|
||||
uni.$emit('ORDER_LIST')
|
||||
uni.$J.showToast('退款成功').then((res) => {
|
||||
close()
|
||||
uni.navigateBack()
|
||||
})
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading()
|
||||
})
|
||||
}
|
||||
const errText = (title) => uni.showToast({ title, icon: 'none' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.refund-amount {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.amount {
|
||||
margin-top: 30rpx;
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: rgba(45, 218, 119, 1);
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 30rpx;
|
||||
font-size: 18rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.refund {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 10rpx;
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
.input-title {
|
||||
margin: 30rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-refund {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #ededed;
|
||||
padding: 10rpx 30rpx;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-but {
|
||||
color: $v-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.remarks-input {
|
||||
display: flex;
|
||||
margin: 20rpx 0;
|
||||
padding: 10rpx 30rpx;
|
||||
height: 160rpx;
|
||||
background-color: #ededed;
|
||||
|
||||
/* #ifdef MP-ALIPAY */
|
||||
input {
|
||||
transform: translateY(-7rpx);
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.refund-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
width: 260rpx;
|
||||
height: 60rpx;
|
||||
background-color: rgba(242, 77, 77, 1);
|
||||
color: #fff;
|
||||
font-size: 22rpx;
|
||||
letter-spacing: 2rpx;
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.refund-pwd {
|
||||
padding: 15rpx;
|
||||
width: 420rpx;
|
||||
height: 260rpx;
|
||||
border-radius: 14rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.title {
|
||||
margin-bottom: 50rpx;
|
||||
font-size: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
border-bottom: 1rpx solid #000;
|
||||
|
||||
input {
|
||||
padding: 10rpx 0;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.button-box {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 60rpx;
|
||||
|
||||
view {
|
||||
flex: 0 0 38%;
|
||||
height: 55rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
color: $v-primary;
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.confirm {
|
||||
background-color: $v-primary;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
249
jeepay-ui-uapp-face/pages/payModel/payModel.vue
Normal file
249
jeepay-ui-uapp-face/pages/payModel/payModel.vue
Normal file
@@ -0,0 +1,249 @@
|
||||
<template>
|
||||
<view class="model-wrapper">
|
||||
<view class="model-content">
|
||||
<view class="title">您已切换至POS模式 </view>
|
||||
<view class="sub-text">请在收银设备上输入收款金额</view>
|
||||
<view class="sub-title">独立收银模式:
|
||||
</view>
|
||||
<view class="tips">接入电源后即可使用,后屏输入收款金额,前屏支持刷脸支付和扫码支付。</view>
|
||||
<view class="sub-title">POS模式:<view class="model-tag">当前正在使用</view>
|
||||
</view>
|
||||
<view class="tips">需要连接收银机或PC使用,即插即用,收款将会进入您的现有收银软件账户。</view>
|
||||
<view class="pay-model" hover-class="hover-model" hover-stay-time="50" @tap="switchCashier">
|
||||
<image src="/static/iconImg/switch-model.svg" mode="scaleToFill" />
|
||||
切换至独立收银模式
|
||||
</view>
|
||||
</view>
|
||||
<view class="selected-cas-model">
|
||||
<view class="cas-title">设置收银机刷脸兼容模式</view>
|
||||
<view class="cas-sub-tips">请注意此设置可能会影响收银机刷脸收款请在专业人员指导下设置</view>
|
||||
<view class="cas-sub-tips">如需设置收银机扫码兼容模式 请在系统设置中设置</view>
|
||||
<radio-group @change="radioChange">
|
||||
<view class="radio-wrapper">
|
||||
<label class="radio">
|
||||
<radio value="n" checked="true" />code+n
|
||||
</label>
|
||||
<label class="radio">
|
||||
<radio value="r" />code+r
|
||||
</label>
|
||||
<label class="radio">
|
||||
<radio value="rn" />code+rn
|
||||
</label>
|
||||
<label class="radio">
|
||||
<radio value="" />code
|
||||
</label>
|
||||
</view>
|
||||
</radio-group>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import { onLoad, onReady } from '@dcloudio/uni-app'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
/***
|
||||
*前后屏 通信 通知前屏 跳转到待支付页面
|
||||
* */
|
||||
onLoad(() => {
|
||||
wxfaceapp.postMsg({
|
||||
targetAppid: 'wx4710a1619fbb3714',
|
||||
content: JSON.stringify({ type: 'toPay' }),
|
||||
success(res) {
|
||||
console.log('通信成功', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('通信失败 ', res)
|
||||
},
|
||||
})
|
||||
})
|
||||
let code = '\n'
|
||||
/**
|
||||
* 页面初始化完成 监听 前屏 向后屏通信 将支付码 写入数据串口
|
||||
* */
|
||||
onReady(() => {
|
||||
wxfaceapp.onRemoteMessage(function (res) {
|
||||
const data = JSON.parse(res.content)
|
||||
if (data.faceCode) {
|
||||
wxfaceapp.writeToSerialPort({
|
||||
msgToFlush: data.faceCode + code,
|
||||
success(res) {
|
||||
console.log('success [writeToSerialPort]', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('fail [writeToSerialPort]', res)
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
postFrontMsg({ type: 'hideAmount' })
|
||||
})
|
||||
const switchCashier = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否切换为 独立收银模式?',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
storageManage.faceModel('cashier')
|
||||
postFrontMsg({ type: 'toBanner' })
|
||||
uni.reLaunch({ url: '/pages/index/index' })
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function postFrontMsg(content) {
|
||||
wxfaceapp.postMsg({
|
||||
targetAppid: 'wx4710a1619fbb3714',
|
||||
content: JSON.stringify(content),
|
||||
success(res) {
|
||||
console.log('通信成功', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('通信失败 ', res)
|
||||
},
|
||||
})
|
||||
}
|
||||
const radioChange = (e) => {
|
||||
const v = e.detail.value
|
||||
switch (v) {
|
||||
case 'r':
|
||||
code = '\r'
|
||||
break
|
||||
case 'n':
|
||||
code = '\n'
|
||||
break
|
||||
case 'rn':
|
||||
code = '\r\n'
|
||||
break
|
||||
default:
|
||||
code = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.model-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 15vh;
|
||||
min-height: 100vh;
|
||||
|
||||
.model-content {
|
||||
width: 70%;
|
||||
|
||||
.title {
|
||||
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-size: 29rpx;
|
||||
}
|
||||
|
||||
.sub-text {
|
||||
line-height: 3;
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.switch-but {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
margin-top: 60rpx;
|
||||
width: 60%;
|
||||
height: 50rpx;
|
||||
border: 1rpx solid rgba($color: #000000, $alpha: 0.1);
|
||||
border-radius: 5rpx;
|
||||
background-color: rgba($color: #409eff, $alpha: 0.175);
|
||||
color: #409eff;
|
||||
font-size: 18rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
|
||||
.model-tag {
|
||||
float: right;
|
||||
background-color: #27DC70;
|
||||
color: #fff;
|
||||
padding: 5rpx 10rpx;
|
||||
border-radius: 5rpx;
|
||||
font-size: 14rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #595959;
|
||||
font-size: 15rpx;
|
||||
margin: 20rpx 0;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.pay-model {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
margin-top: 60rpx;
|
||||
height: 60rpx;
|
||||
border: 1rpx solid #1AB345;
|
||||
border-radius: 5rpx;
|
||||
background-color: rgba(241, 255, 245, .3);
|
||||
;
|
||||
color: #1AB245;
|
||||
font-size: 18rpx;
|
||||
letter-spacing: 2rpx;
|
||||
|
||||
image {
|
||||
margin-right: 8rpx;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.hover-model {
|
||||
background-color: #1AB345;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.selected-cas-model {
|
||||
margin-top: 5vh;
|
||||
|
||||
.cas-title {
|
||||
width: 100vw;
|
||||
padding-top: 30rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
border-top: 2rpx solid #ededed;
|
||||
}
|
||||
|
||||
.cas-sub-tips {
|
||||
margin-top: 20rpx;
|
||||
color: #666;
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.radio-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
70
jeepay-ui-uapp-face/pages/paySuc/paySuc.vue
Normal file
70
jeepay-ui-uapp-face/pages/paySuc/paySuc.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<view class="page-wrapper">
|
||||
<view class="pay-main">
|
||||
<view class="pay-title">支付成功</view>
|
||||
<view class="pay-amount">支付金额:{{ vdata.amount }}元</view>
|
||||
</view>
|
||||
<view class="but-box">
|
||||
<JButton @tap="toIndexPage(true)">返回首页({{ vdata.num }})</JButton>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
onLoad((options) => {
|
||||
console.log('支付成功页', options)
|
||||
vdata.amount = options.amount
|
||||
vdata.num = 10
|
||||
toIndexPage()
|
||||
})
|
||||
const vdata = reactive({
|
||||
num: 10,
|
||||
})
|
||||
let timeOut = undefined
|
||||
function toIndexPage(flag) {
|
||||
if (flag || vdata.num <= 0) {
|
||||
clearTimeout(timeOut)
|
||||
return uni.redirectTo({
|
||||
url: '/pages/index/index',
|
||||
})
|
||||
}
|
||||
timeOut = setTimeout(() => {
|
||||
vdata.num -= 1
|
||||
toIndexPage()
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-wrapper {
|
||||
padding: 0.1rpx;
|
||||
min-height: calc(100vh - 2rpx);
|
||||
}
|
||||
.pay-main {
|
||||
padding: 0.1rpx;
|
||||
margin: 180rpx auto;
|
||||
width: 80%;
|
||||
|
||||
background: linear-gradient(135deg, rgba(86, 222, 114, 1) 0%, rgba(58, 233, 174, 1) 100%);
|
||||
color: #fff;
|
||||
border-radius: 14rpx;
|
||||
.pay-title {
|
||||
margin: 30rpx 0;
|
||||
text-align: center;
|
||||
font-size: 42rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 3rpx;
|
||||
}
|
||||
.pay-amount {
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
.but-box {
|
||||
transform: translateY(200rpx);
|
||||
}
|
||||
</style>
|
||||
143
jeepay-ui-uapp-face/pages/payWait/payWait.vue
Normal file
143
jeepay-ui-uapp-face/pages/payWait/payWait.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<view class="page-wrapper">
|
||||
<view class="pay-wait">
|
||||
<view class="pay-number">
|
||||
<text class="icon">¥</text>
|
||||
{{ vdata.payment }}
|
||||
</view>
|
||||
等待用户付款
|
||||
</view>
|
||||
<view class="but-content">
|
||||
<JButton @tap="cancel">取消付款</JButton>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { req, $appPay, API_URL_PAY_ORDER_LIST } from '@/http/apiManager'
|
||||
import wxTextToSpeach from '@/commons/utils/wxTextToSpeach'
|
||||
import { onLoad, onReady } from '@dcloudio/uni-app'
|
||||
onLoad((options) => {
|
||||
vdata.payment = options.payment
|
||||
})
|
||||
onReady(() => {
|
||||
wxfaceapp.onRemoteMessage(function (res) {
|
||||
console.log('刷脸结果:' + res.content)
|
||||
const data = JSON.parse(res.content)
|
||||
$appPay(vdata.payment, data.faceCode || data.code).then((r) => {
|
||||
console.log('支付后结果', r)
|
||||
findOrderState(r.bizData)
|
||||
})
|
||||
})
|
||||
postFront({ type: 'amount', amount: vdata.payment }) // 通知 支付页面 支付金额
|
||||
})
|
||||
const vdata = reactive({
|
||||
payment: '0.00',
|
||||
})
|
||||
const cancel = () => {
|
||||
postFront({ type: 'toBanner' })
|
||||
uni.navigateBack()
|
||||
}
|
||||
const postFront = (content) => {
|
||||
wxfaceapp.postMsg({
|
||||
targetAppid: 'wx4710a1619fbb3714',
|
||||
content: JSON.stringify(content),
|
||||
success(res) {
|
||||
console.log('通信成功', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('通信失败 ', res)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function findOrderState(val) {
|
||||
switch (val.orderState) {
|
||||
case 2:
|
||||
if (val.payDataType == 'aliapp' || val.wayCode == 'ALIPAY') {
|
||||
wxTextToSpeach(`支付宝支付成功金额${vdata.payment}元`)
|
||||
}
|
||||
if (val.payDataType == 'ysfapp' || val.wayCode == 'YSFPAY') {
|
||||
wxTextToSpeach(`云闪付支付成功金额${vdata.payment}元`)
|
||||
}
|
||||
uni.$J.showToast('支付成功').then((res) => {
|
||||
uni.redirectTo({
|
||||
url: '/pages/paySuc/paySuc?amount=' + vdata.payment,
|
||||
})
|
||||
postFront({ type: 'toBanner' }) //支付成功后 返回支付页面
|
||||
})
|
||||
break
|
||||
case 3:
|
||||
uni.$J.showToast('支付失败' + val.errMsg)
|
||||
break
|
||||
case 4:
|
||||
uni.$J.showToast('订单撤销')
|
||||
break
|
||||
case 1:
|
||||
// 支付中 进行查单操作
|
||||
console.log('订单状态1进行查单 操作 ')
|
||||
findOrder(val.payOrderId)
|
||||
break
|
||||
}
|
||||
}
|
||||
let num = 1
|
||||
function findOrder(payOrderId) {
|
||||
if (num > 15)
|
||||
return uni.showModal({
|
||||
title: '确认订单状态',
|
||||
content: '订单状态查询失败 请与客户确认订单状态 点击确认跳转订单列表页面',
|
||||
showCancel: true,
|
||||
success: ({ confirm, cancel }) => {
|
||||
if (confirm) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/order',
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
uni.$J.showToast(`支付中正在进行第${num}次订单查询`).then((res) => {
|
||||
req.getById(API_URL_PAY_ORDER_LIST, payOrderId).then(({ bizData }) => {
|
||||
num += 1
|
||||
console.log('查单结果', bizData)
|
||||
bizData.orderState = bizData.state
|
||||
findOrderState(bizData)
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-wrapper {
|
||||
padding: 0.1rpx 30rpx;
|
||||
|
||||
.pay-wait {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 140rpx;
|
||||
height: 220rpx;
|
||||
background: linear-gradient(135deg, rgba(86, 222, 114, 1) 0%, rgba(58, 233, 174, 1) 100%);
|
||||
border-radius: 15rpx;
|
||||
color: #fff;
|
||||
|
||||
.pay-number {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
margin-bottom: 15rpx;
|
||||
font-size: 60rpx;
|
||||
font-weight: 700;
|
||||
|
||||
.icon {
|
||||
transform: translateY(-7rpx);
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.but-content {
|
||||
transform: translateY(400rpx);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
138
jeepay-ui-uapp-face/pages/payment/payment.vue
Normal file
138
jeepay-ui-uapp-face/pages/payment/payment.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<view class="page-wrapper">
|
||||
<view class="pay-number">
|
||||
<view class="pay-icon">¥</view>
|
||||
{{ vdata.payment }}
|
||||
</view>
|
||||
<view class="keyboard-list">
|
||||
<block v-for="v in keyboardList" :key="v.value">
|
||||
<view class="keyboard-item" hover-class="hover-button" hover-stay-time="50" @tap="changeKey(v.value)">
|
||||
<image v-if="v.value == 'del'" :src="v.key" mode="scaleToFill" />
|
||||
<text v-else>{{ v.key }}</text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="pay-submit" hover-class="hover-submit" hover-stay-time="50" @tap="jumpPage">
|
||||
<image src="/static/indexImg/pay.png" mode="scaleToFill" />
|
||||
普通收款
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const keyboardList = [
|
||||
{ key: '1', value: '1' },
|
||||
{ key: '2', value: '2' },
|
||||
{ key: '3', value: '3' },
|
||||
{ key: '4', value: '4' },
|
||||
{ key: '5', value: '5' },
|
||||
{ key: '6', value: '6' },
|
||||
{ key: '7', value: '7' },
|
||||
{ key: '8', value: '8' },
|
||||
{ key: '9', value: '9' },
|
||||
{ key: '.', value: '.' },
|
||||
{ key: '0', value: '0' },
|
||||
{ key: '/static/iconImg/escB.png', value: 'del' },
|
||||
]
|
||||
const vdata = reactive({
|
||||
payment: '0.00',
|
||||
})
|
||||
|
||||
const changeKey = (v) => {
|
||||
if (v == 'del') {
|
||||
vdata.payment = vdata.payment.slice(0, vdata.payment.length - 1)
|
||||
if (vdata.payment == '') vdata.payment = '0.00'
|
||||
return
|
||||
}
|
||||
if (vdata.payment == '0.00' && (v == '.' || v == '0')) return (vdata.payment = '0.')
|
||||
if (vdata.payment == '0.00') return (vdata.payment = v)
|
||||
if (vdata.payment.includes('.') && v == '.') return uni.$J.showToast('只能包含一位小数点')
|
||||
if (vdata.payment.includes('.') && vdata.payment.split('.')[1].length == 2) return uni.$J.showToast('只能包含小数点后两位')
|
||||
return (vdata.payment += v)
|
||||
}
|
||||
const jumpPage = () => {
|
||||
wxfaceapp.postMsg({
|
||||
targetAppid: 'wx4710a1619fbb3714',
|
||||
content: JSON.stringify({ type: 'toPay' }),
|
||||
success(res) {
|
||||
console.log('通信成功', res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log('通信失败 ', res)
|
||||
},
|
||||
})
|
||||
uni.navigateTo({ url: '/pages/payWait/payWait?payment=' + vdata.payment })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-wrapper {
|
||||
padding: 0.1rpx 30rpx;
|
||||
min-height: calc(100vh - 5rpx);
|
||||
background: url('/static/indexImg/index-bg.png') no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
.pay-number {
|
||||
margin-top: 60rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 180rpx;
|
||||
background-color: #35d757;
|
||||
border-radius: 22rpx;
|
||||
font-size: 60rpx;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
.pay-icon {
|
||||
font-size: 28rpx;
|
||||
transform: translateY(30%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.keyboard-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin-top: 60rpx;
|
||||
.keyboard-item {
|
||||
flex: 0 0 31.5%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 15rpx;
|
||||
height: 110rpx;
|
||||
font-weight: 700;
|
||||
font-size: 36rpx;
|
||||
border-radius: 22rpx;
|
||||
background-color: #fff;
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pay-submit {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 70rpx;
|
||||
background-color: #35d757;
|
||||
border-radius: 22rpx;
|
||||
height: 120rpx;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
image {
|
||||
margin-right: 10rpx;
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
transform: translateY(5rpx);
|
||||
}
|
||||
}
|
||||
.hover-button {
|
||||
background-color: rgba($color: #ccc, $alpha: 0.3) !important;
|
||||
}
|
||||
.hover-submit {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
131
jeepay-ui-uapp-face/pages/stat/components/PayTypeCard.vue
Normal file
131
jeepay-ui-uapp-face/pages/stat/components/PayTypeCard.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<view class="type-card" :style="{ backgroundColor: rgba }">
|
||||
<view class="type-header" :style="{ backgroundColor: bgColor }" @tap="emits('upOrDown')">
|
||||
<view> {{ typeName }} </view>
|
||||
<view class="type-num">¥{{ (allAmount / 100).toFixed(2) }} /{{ allCount }}笔
|
||||
<image src="/static/iconImg/down.svg" style="transition: 0.3s linear" :class="{ 'img-up': !isShow }"
|
||||
mode="scaleToFill" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-main" :style="{ maxHeight: isShow ? '40vh' : '0' }">
|
||||
<view class="type-item">
|
||||
<view class="type-num">
|
||||
<view> ¥{{ (allAmount / 100).toFixed(2) }}</view>
|
||||
<view class="title"> 成交金额 </view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-item">
|
||||
<view class="type-num">
|
||||
<view> ¥{{ ((payAmount - refundAmount) / 100).toFixed(2) }}</view>
|
||||
<view class="title"> 实收金额</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-item">
|
||||
<view class="type-num">
|
||||
<view> ¥{{ payCount }}/{{ allCount }}</view>
|
||||
<view class="title"> 成交笔数/总笔数 </view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-item">
|
||||
<view class="type-num">
|
||||
<view> ¥{{ (refundAmount / 100).toFixed(2) }}</view>
|
||||
<view class="title"> 退款金额</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-item">
|
||||
<view class="type-num">
|
||||
<view> {{ refundCount }}</view>
|
||||
<view class="title"> 退款笔数 </view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-item">
|
||||
<view class="type-num">
|
||||
<view> {{ round }}%</view>
|
||||
<view class="title"> 成功率</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import { reactive, ref } from 'vue'
|
||||
const emits = defineEmits(['upOrDown'])
|
||||
const props = defineProps({
|
||||
typeName: { type: String },
|
||||
allCount: { type: [String, Number] },
|
||||
allAmount: { type: [String, Number] },
|
||||
bgColor: { type: String },
|
||||
rgba: { type: String },
|
||||
isShow: { type: Boolean },
|
||||
refundAmount: { type: [String, Number] },
|
||||
round: { type: [String, Number] },
|
||||
payCount: { type: [String, Number] },
|
||||
payAmount: { type: [String, Number] },
|
||||
refundCount: { type: [String, Number] },
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.type-card {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
width: 95%;
|
||||
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.type-header {
|
||||
padding: 25rpx 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
|
||||
.type-num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
image {
|
||||
margin-left: 10rpx;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.type-main {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
padding: 0 20rpx;
|
||||
overflow: hidden;
|
||||
// max-height: 0;
|
||||
transition: 0.3s linear;
|
||||
|
||||
.type-item {
|
||||
flex: 0 0 30%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
|
||||
.title {
|
||||
margin-top: 10rpx;
|
||||
color: rgba($color: #fff, $alpha: 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.img-up {
|
||||
transform: rotate(-180deg);
|
||||
}</style>
|
||||
230
jeepay-ui-uapp-face/pages/stat/stat.vue
Normal file
230
jeepay-ui-uapp-face/pages/stat/stat.vue
Normal file
@@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<view class="stat-wrapper">
|
||||
<view class="time-header">
|
||||
<block v-for="(v, i) in timeList" :key="i">
|
||||
<view class="time-item" :class="{ 'selected-time': v.value == vdata.selectedTime }" @tap="switchTime(v.value)">{{ v.label }}</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="custom-content" :class="{ 'selected-custom': vdata.selectedTime == 'custom' }">
|
||||
<view class="start-time" :style="{ color: vdata.startTime ? '#000' : '#666' }" @tap="refStartTime.show">{{ vdata.startTime || '请选择开始时间' }}</view>
|
||||
<view class="endTime-time" :style="{ color: vdata.endTime ? '#000' : '#666' }" @tap="refEndTime.show">{{ vdata.endTime || '请选择结束时间' }}</view>
|
||||
</view>
|
||||
<view class="amount-list">
|
||||
<view class="amount-item">
|
||||
<view class="amount-num">{{ (vdata.payStat.allAmount / 100).toFixed(2) }}</view>
|
||||
成交金额
|
||||
</view>
|
||||
<view class="amount-item">
|
||||
<view class="amount-num">{{ (vdata.payStat.payAmount / 100).toFixed(2) }}</view>
|
||||
实收金额
|
||||
</view>
|
||||
<view class="amount-item">
|
||||
<view class="amount-num">{{ vdata.payStat.payCount }} /{{ vdata.payStat.allCount }} </view>
|
||||
成交笔数/总笔数
|
||||
</view>
|
||||
<view class="amount-item">
|
||||
<view class="amount-num">{{ (vdata.payStat.refundAmount / 100).toFixed(2) }}</view>
|
||||
退款金额
|
||||
</view>
|
||||
<view class="amount-item">
|
||||
<view class="amount-num">{{ vdata.payStat.refundCount }}</view>
|
||||
退款笔数
|
||||
</view>
|
||||
<view class="amount-item">
|
||||
<view class="amount-num">{{ vdata.payStat.round }} %</view>
|
||||
成功率
|
||||
</view>
|
||||
</view>
|
||||
<view class="pay-title"> 支付方式 </view>
|
||||
<block v-for="(v, i) in vdata.payList" :key="v.wayType">
|
||||
<PayTypeCard v-bind="v" @upOrDown="upOrDown(v)" />
|
||||
</block>
|
||||
<view style="height: 60rpx"></view>
|
||||
</view>
|
||||
<xp-picker mode="ymdhi" ref="refStartTime" @confirm="timeConfirm($event, 'startTime')">
|
||||
<view></view>
|
||||
</xp-picker>
|
||||
<xp-picker mode="ymdhi" ref="refEndTime" @confirm="timeConfirm($event, 'endTime')">
|
||||
<view></view>
|
||||
</xp-picker>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { $payTypeStat, $payTypeStatAll } from '@/http/apiManager'
|
||||
import PayTypeCard from './components/PayTypeCard'
|
||||
import dayjs from 'dayjs'
|
||||
const timeList = [
|
||||
{ label: '昨天', value: 'yesterday' },
|
||||
{ label: '今天', value: 'today' },
|
||||
{ label: '近7天', value: 'near2now_7' },
|
||||
{ label: '近30天', value: 'near2yesterday_30' },
|
||||
{ label: '自定义', value: 'custom' },
|
||||
]
|
||||
const vdata = reactive({
|
||||
selectedTime: 'today',
|
||||
payList: [],
|
||||
payStat: {},
|
||||
})
|
||||
const refStartTime = ref(null)
|
||||
const refEndTime = ref(null)
|
||||
const params = {
|
||||
method: 'wayCodeType',
|
||||
queryDateRange: 'today',
|
||||
}
|
||||
const getPayType = () => {
|
||||
$payTypeStat(params).then(({ bizData }) => {
|
||||
bizData.records.forEach((v, i) => {
|
||||
v.bgColor = uni.$J.dataMap.payImg(v.wayType).bgColor
|
||||
v.rgba = uni.$J.dataMap.payImg(v.wayType).rgba
|
||||
v.typeName = uni.$J.dataMap.payImg(v.wayType).title
|
||||
if (i == 0) return (v.isShow = true)
|
||||
v.isShow = false
|
||||
})
|
||||
vdata.payList = bizData.records
|
||||
})
|
||||
}
|
||||
getPayType()
|
||||
const getStatAll = () => {
|
||||
$payTypeStatAll(params).then(({ bizData }) => {
|
||||
vdata.payStat = bizData
|
||||
})
|
||||
}
|
||||
getStatAll()
|
||||
/****
|
||||
* 切换 卡片收起 展开状态
|
||||
* @param {v} Object 点击的卡片全部数据
|
||||
* */
|
||||
const upOrDown = (v) => {
|
||||
v.isShow = true
|
||||
vdata.payList.forEach((ite) => {
|
||||
if (ite.wayType != v.wayType) {
|
||||
ite.isShow = false
|
||||
}
|
||||
})
|
||||
}
|
||||
/***
|
||||
* 切换时间选择器
|
||||
* @param {val} STring 时间选择的 value 值
|
||||
* val = custom 需要展示自定义 时间选择框
|
||||
* */
|
||||
const switchTime = (val) => {
|
||||
vdata.selectedTime = val
|
||||
if (val == 'custom') return
|
||||
params.queryDateRange = val
|
||||
getStatAll()
|
||||
getPayType()
|
||||
}
|
||||
/**
|
||||
* @param {e} Object 组件原生 回调 时间戳 日期
|
||||
* @param {key} String vdata 对象的 key 值 赋值使用
|
||||
* */
|
||||
const timeConfirm = (e, key) => {
|
||||
vdata[key] = dayjs(e.timestamp).format('YYYY-MM-DD hh:mm')
|
||||
if (key == 'endTime' || (vdata.endTime != undefined && dayjs(vdata.startTime).isAfter(vdata.endTime))) {
|
||||
params.queryDateRange = `customDateTime_${vdata.startTime + ':00'}_${vdata.endTime + ':00'}`
|
||||
getStatAll()
|
||||
getPayType()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.stat-wrapper {
|
||||
min-height: 100vh;
|
||||
background-color: #ebf2ed;
|
||||
.time-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx;
|
||||
view {
|
||||
flex: 0 0 18%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 45rpx;
|
||||
border-radius: 14rpx;
|
||||
background-color: #d9dfda;
|
||||
font-size: 18rpx;
|
||||
color: #666;
|
||||
}
|
||||
.selected-time {
|
||||
background-color: $v-primary;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 18rpx;
|
||||
color: rgba($color: #fff, $alpha: 0.6);
|
||||
}
|
||||
.stat-num {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
margin: 0 auto;
|
||||
margin-top: 35rpx;
|
||||
width: 65%;
|
||||
height: 120rpx;
|
||||
border-radius: 22rpx 22rpx 0 0;
|
||||
background-color: $v-primary;
|
||||
.num {
|
||||
font-size: 35rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.amount-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
margin-top: 30rpx;
|
||||
padding: 15rpx 0;
|
||||
width: 92%;
|
||||
// height: 110rpx;
|
||||
background-color: $v-primary;
|
||||
border-radius: 14rpx;
|
||||
.amount-item {
|
||||
flex: 0 0 33%;
|
||||
margin: 15rpx 0;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
color: rgba($color: #fff, $alpha: 0.6);
|
||||
font-size: 20rpx;
|
||||
.amount-num {
|
||||
margin-bottom: 15rpx;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pay-title {
|
||||
margin-top: 35rpx;
|
||||
margin-bottom: 15rpx;
|
||||
margin-left: 30rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.custom-content {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
overflow: hidden;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 60rpx;
|
||||
max-height: 0;
|
||||
transition: 0.3s linear;
|
||||
view {
|
||||
flex: 0 0 30%;
|
||||
padding: 10rpx 0;
|
||||
background-color: #ded7d7;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
}
|
||||
.selected-custom {
|
||||
max-height: 20vh;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user