源文件

This commit is contained in:
gyq
2024-05-23 14:39:33 +08:00
commit a1128dd791
2997 changed files with 500069 additions and 0 deletions

View File

@@ -0,0 +1,273 @@
<template>
<JeepayWrapper>
<view class="page">
<JHeaderTitle title="云喇叭管理" bgColor="#f2f2f2" />
<JSearchInput @search="searchHandle" @resetSearch="reset" ref="search" place="搜索设备名称、设备号、用户号">
<view class="header-assign" @tap="cancel">
<image src="/static/iconImg/icon-file.svg" mode="scaleToFill" />
划拨
</view>
</JSearchInput>
<view v-for="(item, index) in useDataResult.dataList" :key="item.deviceNo">
<JPreview
v-bind="item.info"
:key="item.deviceNo"
:activeBox="vdata.activeBox"
:isLast="index === useDataResult.dataList.length - 1"
@activeClick="handleActive(item.info)"
@click="toDetail(item.deviceId)"
>
<template #bottom>
<view class="info-wrapper">
<view class="info" v-if="!item.isSelf">
<image src="/static/iconImg/icon-mini-agent.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.agentName }}</view>
<view class="number">{{ item.agentNo }}</view>
</view>
<view class="info" v-if="item.mchNo">
<image src="@/static/equipmentImg/mch-little.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.mchName }}</view>
<view class="number">{{ item.mchNo }}</view>
</view>
</view>
</template>
</JPreview>
</view>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
<view class="footer-button" v-show="vdata.activeBox">
<view class="button-main">
<button @tap="cancel">取消</button>
<button class="confirm" @tap="openNext">下一步</button>
</view>
</view>
</view>
<JSinglePopup :list="selectedList" ref="refSingle" />
<SelectedAgent ref="refSelected" @confirm="toAgent" />
</JeepayWrapper>
</template>
<script setup>
import { reactive, ref, watch, nextTick } from 'vue'
import { $getDeviceList, $getAcountInfo, $updateDeviceDetail, $allotORtakeBack } from '@/http/apiManager.js'
import { onLoad, onBackPress } from '@dcloudio/uni-app'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' //自定义导航栏
import useGetList from '@/hooks/useList.js'
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue'
import JSinglePopup from '@/components/JSinglePopup/JSinglePopup.vue'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from './components/SelectedAgent.vue'
const refSingle = ref(null)
const refSelected = ref(null)
const dataHandle = (data) => {
data.forEach((item) => {
item.info = {
img: item.state == 1 ? '/static/equipmentImg/horn-open.svg' : '/static/equipmentImg/horn-close.svg',
title: item.deviceName ? item.deviceName : '未命名',
qrcId: item.deviceNo,
spot: item.state == 1 ? '#7737FE' : '#B2B2B2',
status: item.state == 1 ? '已启用' : '已禁用',
disabled: !!item.bindState,
deviceId: item.deviceId,
}
})
return data
}
const { useDataResult, getList } = useGetList({
requestFun: $getDeviceList,
params: { deviceType: 1 },
dataHandle: dataHandle,
})
const selectedList = [
{ label: '收回所有已选择设备', value: 'takeBack', confirmText: '确定要收回所有已选设备吗?', fun: takeBackDev },
{
label: '划拨已选设备至代理商',
value: 'toAgent',
fun: () => {
refSelected.value.open()
},
},
]
const vdata = reactive({
activeBox: false,
})
const toDetail = (e) => {
uni.navigateTo({
url: `./updateHorn?deviceId=${e}&deviceType=1`,
})
}
const search = ref(null) // 注册搜索组件
// 搜索
const searchHandle = (val) => getList({ appSearchData: val })
// 重置搜索
const reset = () => getList({ appSearchData: '' })
// 输入框存在内容时,清空文字,列表重置
onBackPress(() => {
if (search.value.searchText != '') {
search.value.searchText = ''
reset()
return true
}
return false
})
// 设备号列表
const devNoList = []
// 勾选
const handleActive = (val) => {
if (val.disabled) return
if (val.active) {
devNoList.splice(
devNoList.findIndex((v) => v == val.deviceId),
1
)
val.active = false
return
}
devNoList.push(val.deviceId)
val.active = true
}
const openNext = () => {
if (devNoList.length == 0) return uni.showToast({ title: '请勾选要进行操作的设备', icon: 'none' })
refSingle.value.open()
}
// 收回划拨
function takeBackDev() {
const data = {
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '收回成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
getList({
pageNumber: 1,
})
})
}
// 划拨
function toAgent(e) {
const data = {
agentNo: e.text,
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '划拨成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
refSelected.value.close()
getList({
pageNumber: 1,
})
})
}
const cancel = () => {
if (!vdata.activeBox) return (vdata.activeBox = true)
useDataResult.dataList.forEach((v) => {
v.info.active = false
})
devNoList.length = 0
vdata.activeBox = false
}
</script>
<style lang="scss" scoped>
.header-assign {
display: flex;
align-items: center;
padding: 0 30rpx;
font-size: 30rpx;
font-weight: 500;
color: #404040;
image {
margin-right: 5rpx;
width: 36rpx;
height: 36rpx;
}
}
.info-wrapper {
margin-top: 20rpx;
width: 100%;
border-radius: 10rpx;
}
.info {
// width: 100%;
display: flex;
justify-content: center;
padding: 20rpx;
box-sizing: border-box;
background-color: #f7f7f7;
.mch-img {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0 10rpx;
width: 350rpx;
color: #000;
font-size: 28rpx;
flex-grow: 1;
}
.number {
white-space: nowrap;
color: #8c8c8c;
font-size: 28rpx;
}
}
.footer-button {
height: 170rpx;
}
.button-main {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
padding: 0 30rpx;
align-items: center;
height: 170rpx;
border-top: 1rpx solid #ededed;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
button {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-size: 33rpx;
font-weight: 500;
color: #575757;
background-color: #e6e6e6;
&::after {
border: none;
}
}
.confirm {
margin-left: 30rpx;
background-color: $primaryColor;
color: #fff;
}
}
</style>

View File

@@ -0,0 +1,270 @@
<template>
<JeepayWrapper>
<view class="page">
<JHeaderTitle title="云打印管理" bgColor="#f2f2f2" />
<JSearchInput @search="searchHandle" @resetSearch="reset" ref="search" place="搜索设备名称、设备号、用户号">
<view class="header-assign" @tap="cancel">
<image src="/static/iconImg/icon-file.svg" mode="scaleToFill" />
划拨
</view>
</JSearchInput>
<view v-for="(item, index) in useDataResult.dataList" :key="item.deviceId">
<JPreview
v-bind="item.info"
:key="item.deviceId"
:activeBox="vdata.activeBox"
:isLast="index === useDataResult.dataList.length - 1"
@activeClick="handleActive(item.info)"
@click="toDetail(item.deviceId)"
>
<template #bottom>
<view class="info-wrapper">
<view class="info" v-if="!item.isSelf">
<image src="/static/iconImg/icon-mini-agent.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.agentName }}</view>
<view class="number">{{ item.agentNo }}</view>
</view>
<view class="info" v-if="!!item.bindState">
<image src="@/static/equipmentImg/mch-little.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.mchName }}</view>
<view class="number">{{ item.mchNo }}</view>
</view>
</view>
</template>
</JPreview>
</view>
<view class="footer-button" v-show="vdata.activeBox">
<view class="button-main">
<button @tap="cancel">取消</button>
<button class="confirm" @tap="openNext">下一步</button>
</view>
</view>
<jeepayListNull :list="useDataResult.dataList.length" :isShow="true" />
<JSinglePopup :list="selectedList" ref="refSingle" />
<SelectedAgent ref="refSelected" @confirm="toAgent" />
</view>
</JeepayWrapper>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { $getDeviceList, $getAcountInfo, $updateDeviceDetail, $allotORtakeBack } from '@/http/apiManager.js'
import { onBackPress, onShow } from '@dcloudio/uni-app'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' //自定义导航栏
import useGetList from '@/hooks/useList.js'
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from './components/SelectedAgent.vue'
const dataHandle = (data) => {
data.forEach((item) => {
item.info = {
img: item.state == 1 ? '/static/equipmentImg/print-open.svg' : '/static/equipmentImg/print-close.svg',
title: item.deviceName ? item.deviceName : '未命名',
qrcId: item.deviceNo,
spot: item.state == 1 ? '#7737FE' : '#B2B2B2',
status: item.state == 1 ? '已启用' : '已禁用',
disabled: !!item.bindState,
deviceId: item.deviceId,
}
if (item.bindState) {
item.info.mchName = item.mchName
item.info.mchNo = item.mchNo
}
})
return data
}
const refSingle = ref(null)
const refSelected = ref(null)
const { useDataResult, getList } = useGetList({
requestFun: $getDeviceList,
params: { deviceType: 2 },
dataHandle,
})
const selectedList = [
{ label: '收回所有已选择设备', value: 'takeBack', confirmText: '确定要收回所有已选设备吗?', fun: takeBackDev },
{
label: '划拨已选设备至代理商',
value: 'toAgent',
fun: () => {
refSelected.value.open()
},
},
]
const vdata = reactive({
activeBox: false,
})
const search = ref(null) // 注册搜索组件
// 搜索
const searchHandle = (val) => getList({ appSearchData: val })
// 重置搜索
const reset = () => getList({ appSearchData: '' })
// 输入框存在内容时,清空文字,列表重置
onBackPress(() => {
if (search.value.searchText != '') {
search.value.searchText = ''
reset()
return true
}
return false
})
const toDetail = (e) => uni.navigateTo({ url: `./updateDevice?deviceId=${e}` + `&deviceType=` + 2 })
// 收回划拨
function takeBackDev() {
const data = {
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '收回成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
getList({
pageNumber: 1,
})
})
}
// 设备号列表
const devNoList = []
// 勾选
const handleActive = (val) => {
if (val.disabled) return
if (val.active) {
devNoList.splice(
devNoList.findIndex((v) => v == val.deviceId),
1
)
val.active = false
return
}
devNoList.push(val.deviceId)
val.active = true
}
const openNext = () => {
if (devNoList.length == 0) return uni.showToast({ title: '请勾选要进行操作的设备', icon: 'none' })
refSingle.value.open()
}
// 划拨
function toAgent(e) {
const data = {
agentNo: e.text,
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '划拨成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
refSelected.value.close()
getList({
pageNumber: 1,
})
})
}
const cancel = () => {
if (!vdata.activeBox) return (vdata.activeBox = true)
useDataResult.dataList.forEach((v) => {
v.info.active = false
})
devNoList.length = 0
vdata.activeBox = false
}
</script>
<style lang="scss" scoped>
.header-assign {
display: flex;
align-items: center;
padding: 0 30rpx;
font-size: 30rpx;
font-weight: 500;
color: #404040;
image {
margin-right: 5rpx;
width: 36rpx;
height: 36rpx;
}
}
.info-wrapper {
margin-top: 20rpx;
width: 100%;
border-radius: 10rpx;
}
.info {
// width: 100%;
display: flex;
justify-content: center;
padding: 20rpx;
box-sizing: border-box;
background-color: #f7f7f7;
.mch-img {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0 10rpx;
width: 350rpx;
color: #000;
font-size: 28rpx;
flex-grow: 1;
}
.number {
white-space: nowrap;
color: #8c8c8c;
font-size: 28rpx;
}
}
.footer-button {
height: 170rpx;
}
.button-main {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
padding: 0 30rpx;
align-items: center;
height: 170rpx;
border-top: 1rpx solid #ededed;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
button {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-size: 33rpx;
font-weight: 500;
color: #575757;
background-color: #e6e6e6;
&::after {
border: none;
}
}
.confirm {
margin-left: 30rpx;
background-color: $primaryColor;
color: #fff;
}
}
</style>

View File

@@ -0,0 +1,415 @@
<template>
<JeepayWrapper>
<!-- 顶部自定义导航栏 -->
<JHeaderTitle title="码牌详情" :bgColor="header.bgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<!-- 码牌URL 码牌名字 ID 和编辑板块 -->
<JEquipmentCode :info="data" @downUrl="downUrl" @editInfo="editInfo" />
<!-- 码牌信息板块 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput
name="码牌名"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
align="flex-start"
:right="data.qrcAlias ? data.qrcAlias : '未命名'"
pd="15rpx 40rpx"
/>
<JInput name="码牌ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.qrcId" pd="15rpx 40rpx" />
<JInput
name="码牌金额"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="data.fixedFlag == 1 ? data.fixedPayAmount / 100 : '任意金额'"
pd="15rpx 40rpx"
/>
<JInput name="码牌状态" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view style="color: #fff; maggin-right: 16rpx; font-size: 30rpx" class="dis-wrapper">
{{ data.qrcState ? '启用' : '禁用' }}
<switch :checked="data.qrcState" style="margin-left: 20rpx; transform: scale(1.2)" color="#BF80FF" @change="switchChange" />
</view>
</JInput>
</JMainCard>
<view class="title">绑定/划拨信息</view>
<!-- 绑定商户 未绑定商户状态 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!data.bindState && data.isSelf">
<JInput icon="/pageWork/static/images/bindMch.svg" @tap="bindMch" :isBorder="true" name="绑定至商户" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<JMainCard wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!data.bindState && data.isSelf">
<JInput icon="/static/iconImg/icon-assign.svg" @tap="selectedAgent.open()" :isBorder="true" name="划拨至代理" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<template v-if="!data.isSelf">
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="代理商名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.agentName" pd="15rpx 40rpx" />
<JInput name="代理商号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.agentNo" pd="15rpx 40rpx" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-takeBack.svg"
@tap="refTakeBack.open('收回后代理商将无法使用该设备!')"
:isBorder="true"
name="收回"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-assign.svg"
@tap="refAgain.open('确认重新划拨吗?')"
name="重新划拨"
borderBg="#7737fe"
textColor="#fff"
size="33rpx"
:img="true"
/>
</JMainCard>
</template>
<!-- 绑定商户状态 -->
<template v-if="data.bindState">
<view class="bind-title">绑定信息</view>
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="商户" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.mchName" pd="40rpx 40rpx 15rpx 40rpx" />
<JInput name="用户号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.mchNo" pd="15rpx 40rpx" />
<JInput name="门店" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="data.storeName" />
<JInput name="门店ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="data.storeId" />
<JInput name="应用名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="data.appName" />
<JInput name="AppID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="data.appId" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/equipmentImg/bind.svg"
@tap="unbinding.open('解绑后商户将无法使用该设备!')"
:isBorder="true"
name="解绑"
textColor="#fff"
size="33rpx"
:img="true"
v-if="entIdList.includes('ENT_DEVICE_QRC_RELIEVE')"
/>
<JInput bgColor="rgba(0,0,0,0.2)" icon="/static/equipmentImg/bind-again.svg" @tap="bindMch" name="重新绑定" borderBg="#7737fe" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<!-- 云喇叭设备列表 -->
<JScroll :requestFun="$getDeviceList" :params="cloudParam" title="受支持的云喇叭列表">
<template v-slot:default="{ info }">
<JInput
bgColor="rgba(0,0,0,0.2)"
:icon="info.state == 1 ? '/static/equipmentImg/horn-white.svg' : '/static/equipmentImg/horn-close.svg'"
:textColor="info.state == 1 ? '#fff' : 'rgba(255, 255, 255, 0.6)'"
rightColor="rgba(255, 255, 255, 0.6)"
:name="info.deviceName"
borderBg="#7737fe"
size="33rpx"
:right="info.deviceNo"
/>
</template>
</JScroll>
</template>
<!-- 更改状态对话框 -->
<jeepayConfirm ref="switchState" />
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancel" />
<JDeletedTips ref="unbinding" @confirm="unbound" />
<JPopup ref="JPopupRef" dir="center" type="top">
<view style="margin-top: 60rpx"></view>
<JMainCard wrapPd="75rpx">
<image :src="data.qrcodeUrl" mode="" class="down-url" />
</JMainCard>
<view class="down-btn" @tap.stop="downImg">
保存至相册
<image src="/static/equipmentImg/down.svg" mode=""></image>
</view>
</JPopup>
<JDeletedTips ref="refTakeBack" @confirm="takeBack" />
<JDeletedTips ref="refAgain" @confirm="selectedAgent.open()" />
<SelectedAgent ref="selectedAgent" @confirm="again" />
</JeepayWrapper>
</template>
<script setup>
import { onLoad, onBackPress, onShow, onPageScroll } from '@dcloudio/uni-app'
import { ref, reactive, toRaw, nextTick } from 'vue'
import {
$upDateQRcodeList,
$getQRcode,
$qrcodeBind,
$getQRcodeDetail,
$getMerList,
$getMchStoreList,
$getMchAppList,
$getDeviceList,
$qrCodeAllotORTakeBack,
} from '@/http/apiManager.js'
import { saveHeadImgFile } from '@/util/saveImg.js'
import jeepayConfirm from '@/components/jeepayConfirm/jeepayConfirm.vue'
import qrcode from '@/util/qrcode.js'
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' // 导航栏
import JEquipmentCode from '@/components/newComponents/JEquipment/JEquipmentCode.vue' // 设备信息
import JPopup from '@/components/newComponents/JPopup/JPopup.vue' // 弹窗
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JInput from '@/components/newComponents/JInput/JInput.vue'
import JLine from '@/components/newComponents/JLine/JLine.vue'
import JScroll from '@/components/newComponents/JScroll/JScroll.vue'
import SelectedAgent from './components/SelectedAgent.vue'
// 获取用户信息
import storageManage from "@/util/storageManage.js"
const entIdList = ref( storageManage.userInfo().entIdList)
const JPopupRef = ref(null)
const switchState = ref(null) //
const data = reactive({})
const switchTips = ref(null) //切换状态弹窗
const unbinding = ref(null) //解绑确认弹窗
const refTakeBack = ref(null)
const refAgain = ref(null)
const selectedAgent = ref(null)
// 请求云喇叭列表的传参
const cloudParam = reactive({ deviceType: 1, mchNo: '' })
// 保存图片
const downUrl = () => JPopupRef.value.open('')
// 跳转至编辑页
const editInfo = () => {
uni.navigateTo({ url: './editCode?id=' + data.qrcId })
}
onLoad((options) => {
data.qrcId = options.id
})
onShow(() => {
nextTick(() => {
getDetail()
})
})
const getDetail = () => {
$getQRcodeDetail(data.qrcId).then(({ bizData }) => {
drawQRcode(bizData.qrUrl)
Object.assign(data, bizData)
cloudParam.mchNo = data.mchNo
})
}
function drawQRcode(url) {
if (url) {
let params = url // 二维码参数
var imgData = qrcode.drawImg(params, {
typeNumber: 4, // 密度
errorCorrectLevel: 'Q', // 纠错等级
size: 175, // 白色边框
})
data.qrcodeUrl = imgData
} else {
data.qrcodeUrl = '../../static/img/nodata.jpg'
}
}
let flag = undefined
// 切换状态
function switchChange(e) {
flag = true
data.qrcState = Number(e.detail.value)
switchTips.value.open('确认修改?')
}
const confirm = () => {
flag = false
$upDateQRcodeList(data.qrcId, { qrcState: data.qrcState }).then(() => {
uni.showToast({
title: '修改成功',
icon: 'success',
})
})
}
const cancel = () => {
if (!flag) return
data.qrcState = Number(!data.qrcState)
}
// 跳转至绑定页
const bindMch = () => {
uni.navigateTo({ url: './publicBind?id=' + data.qrcId + '&tag=code&title=绑定码牌' })
}
// 监听页面滚动 用于给自定义导航栏换背景色
const header = reactive({ bgColor: 'transparent' })
onPageScroll((data) => {
if (data.scrollTop > 20) {
header.bgColor = '$primaryColor'
} else {
header.bgColor = 'transparent'
}
})
// 解绑函数
function unbound() {
$upDateQRcodeList(data.qrcId, { bindState: 0 }).then(({ bizData }) => {
uni.showToast({
icon: 'none',
title: '解绑成功',
})
uni.navigateBack({
delta: 1,
})
})
}
function downImg() {
// #ifdef APP-PLUS
saveHeadImgFile(data.qrcodeUrl, 80)
.then((success) => {
uni.showToast({
title: '保存成功',
})
setTimeout(function () {
JPopupRef.value.close()
}, 1500)
})
.catch((err) => {
uni.showToast({
icon: 'none',
title: '保存失败',
})
})
// #endif
//#ifdef MP-WEIXIN
downloadQR()
//#endif
}
//#ifdef MP-WEIXIN
function downloadQR() {
wx.getSetting({
//获取权限
success(res) {
if (res.authSetting['scope.writePhotosAlbum']) {
download(data.qrcUrl)
} else {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
download(data.qrcodeUrl)
},
})
}
},
})
}
function download(data) {
const fileManager = wx.getFileSystemManager()
const filePath = wx.env.USER_DATA_PATH + '/res.png'
//这块是定义图片的名称,可自定义其他
fileManager.writeFile({
filePath: filePath,
data: data.slice(22),
encoding: 'base64',
success: (res) => {
wx.saveImageToPhotosAlbum({
filePath: filePath,
success: function (res) {
//保存成功
uni.showToast({
title: '保存成功',
})
},
fail: function (err) {
console.log(err)
//保存失败
uni.showToast({
icon: 'none',
title: '保存失败',
})
},
})
},
fail: (err) => {
uni.showToast({
icon: 'none',
title: '保存失败',
})
},
})
}
//#endif
const takeBack = () => {
const params = {
agentNo: data.agentNo,
allotIds: data.qrcId,
allotOrRecover: 'recover',
allotType: 'select',
}
$qrCodeAllotORTakeBack(params).then((res) => {
getDetail()
uni.showToast({ title: '收回成功', icon: 'success' })
})
}
// 重新划拨
const again = (e) => {
const params = {
agentNo: e.text,
allotIds: data.qrcId,
allotOrRecover: 'allot',
allotType: 'select',
}
$qrCodeAllotORTakeBack(params).then((res) => {
uni.showToast({ title: '划拨成功', icon: 'success' })
selectedAgent.value.close()
getDetail()
data.isSelf = false
})
}
</script>
<style lang="scss">
page {
background: $primaryColor;
}
</style>
<style scoped lang="scss">
.down-url {
width: 500rpx;
height: 500rpx;
}
.down-btn {
width: 500rpx;
height: 110rpx;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.8);
padding: 32rpx;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 auto;
margin-top: -20rpx;
image {
width: 36rpx;
height: 36rpx;
}
}
.bind-title {
margin-top: 20rpx;
text-align: center;
font-size: 33rpx;
color: #ffffff;
}
.title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 500;
text-align: center;
color: #fff;
}
</style>

View File

@@ -0,0 +1,268 @@
<template>
<JeepayWrapper>
<JHeaderTitle title="码牌管理" bgColor="#f2f2f2" />
<view class="page">
<JSearchInput @search="searchHandle" @resetSearch="reset" ref="search" place="搜索商户号、名称、设备号">
<view class="header-assign" @tap="cancel">
<image src="/static/iconImg/icon-file.svg" mode="scaleToFill" />
划拨
</view>
</JSearchInput>
<view v-for="(item, index) in useDataResult.dataList" :key="item.qrcId">
<JPreview
v-bind="item.info"
:key="item.qrcId"
:activeBox="vdata.activeBox"
:isLast="index === useDataResult.dataList.length - 1"
@activeClick="handleActive(item.info)"
@click="toDetail(item.qrcId)"
>
<template #bottom>
<view class="info-wrapper">
<view class="info" v-if="!item.isSelf">
<image src="/static/iconImg/icon-mini-agent.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.agentName }}</view>
<view class="number">{{ item.agentNo }}</view>
</view>
<view class="info" v-if="item.mchNo">
<image src="@/static/equipmentImg/mch-little.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.mchName }}</view>
<view class="number">{{ item.mchNo }}</view>
</view>
</view>
</template>
</JPreview>
</view>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
<view class="footer-button" v-show="vdata.activeBox">
<view class="button-main">
<button @tap="cancel">取消</button>
<button class="confirm" @tap="openNext">下一步</button>
</view>
</view>
</view>
<JSinglePopup :list="selectedList" ref="refSingle" />
<SelectedAgent ref="refSelected" @confirm="toAgent" />
</JeepayWrapper>
</template>
<script setup>
import { reactive, toRaw, ref } from 'vue'
import { $getQRcodeList, $qrCodeAllotORTakeBack } from '@/http/apiManager.js'
import { onLoad, onBackPress, onShow } from '@dcloudio/uni-app'
import useGetList from '@/hooks/useList.js'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' //自定义导航栏
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue'
import SelectedAgent from './components/SelectedAgent.vue'
const refSingle = ref(null)
const refSelected = ref(null)
// 过滤请求回来的列表数据
const dataHandle = (data) => {
data.forEach((item) => {
item.info = {
img: item.qrcState == 1 ? '/static/equipmentImg/code-open.svg' : '/static/equipmentImg/code-close.svg',
title: item.qrcAlias ? item.qrcAlias : '未命名',
qrcId: item.qrcId,
spot: item.qrcState == 1 ? '#7737FE' : '#B2B2B2',
status: item.qrcState == 1 ? '已启用' : '已禁用',
disabled: !!item.bindState,
deviceId: item.deviceId,
}
})
return data
}
const vdata = reactive({
activeBox: false,
})
// 初始化列表数据
const { useDataResult, getList } = useGetList({
requestFun: $getQRcodeList,
pageSize: 15,
dataHandle,
})
const toDetail = (id) => uni.navigateTo({ url: `./codeCardDetail?id=${id}` })
const search = ref(null) // 注册搜索组件
// 搜索
const searchHandle = (val) => getList({ appSearchData: val })
// 重置搜索
const reset = () => getList({ appSearchData: '' })
// 输入框存在内容时,清空文字,列表重置
onBackPress(() => {
if (search.value.searchText != '') {
search.value.searchText = ''
reset()
return true
}
return false
})
// 设备号列表
const devNoList = []
// 勾选
const handleActive = (val) => {
if (val.disabled) return
if (val.active) {
devNoList.splice(
devNoList.findIndex((v) => v == val.qrcId),
1
)
val.active = false
return
}
devNoList.push(val.qrcId)
val.active = true
}
const selectedList = [
{ label: '收回所有已选择设备', value: 'takeBack', confirmText: '确定要收回所有已选设备吗?', fun: takeBackDev },
{
label: '划拨已选设备至代理商',
value: 'toAgent',
fun: () => {
refSelected.value.open()
},
},
]
const openNext = () => {
if (devNoList.length == 0) return uni.showToast({ title: '请勾选要进行操作的设备', icon: 'none' })
refSingle.value.open()
}
// 收回划拨
function takeBackDev() {
const data = {
allotIds: devNoList.join(','),
allotOrRecover: 'recover',
allotType: 'select',
}
$qrCodeAllotORTakeBack(data).then((res) => {
uni.showToast({
title: '收回成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
getList({
pageNumber: 1,
})
})
}
// 划拨
function toAgent(e) {
const data = {
agentNo: e.text,
allotIds: devNoList.join(','),
allotOrRecover: 'allot',
allotType: 'select',
}
$qrCodeAllotORTakeBack(data).then((res) => {
uni.showToast({
title: '划拨成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
refSelected.value.close()
getList({
pageNumber: 1,
})
})
}
const cancel = () => {
if (!vdata.activeBox) return (vdata.activeBox = true)
useDataResult.dataList.forEach((v) => {
v.info.active = false
})
devNoList.length = 0
vdata.activeBox = false
}
</script>
<style lang="scss" scoped>
.header-assign {
display: flex;
align-items: center;
padding: 0 30rpx;
font-size: 30rpx;
font-weight: 500;
color: #404040;
image {
margin-right: 5rpx;
width: 36rpx;
height: 36rpx;
}
}
.info-wrapper {
margin-top: 20rpx;
width: 100%;
border-radius: 10rpx;
}
.info {
// width: 100%;
display: flex;
justify-content: center;
padding: 20rpx;
box-sizing: border-box;
background-color: #f7f7f7;
.mch-img {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0 10rpx;
width: 350rpx;
color: #000;
font-size: 28rpx;
flex-grow: 1;
}
.number {
white-space: nowrap;
color: #8c8c8c;
font-size: 28rpx;
}
}
.footer-button {
height: 170rpx;
}
.button-main {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
padding: 0 30rpx;
align-items: center;
height: 170rpx;
border-top: 1rpx solid #ededed;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
button {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-size: 33rpx;
font-weight: 500;
color: #575757;
background-color: #e6e6e6;
&::after {
border: none;
}
}
.confirm {
margin-left: 30rpx;
background-color: $primaryColor;
color: #fff;
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" @change="change" :safe-area="false">
<view class="list-wrapper">
<view class="list-header">
<JSearchInput bgColor="#fff" wrapPd="0" @search="getAgentList" @resetSearch="resetSearch"></JSearchInput>
</view>
<scroll-view class="list-main" scroll-y @scrolltolower="getList">
<block v-for="v in list" :key="v.text">
<JLine v-bind="v" :isSelect="v.text === agentNo.text" @tap="selected(v)"></JLine>
</block>
<jeepayListNull :isShow="true" :list="list.length"></jeepayListNull>
</scroll-view>
<view class="list-footer">
<JButton size="max" pdTop="0" pd="30rpx" @HandleTouch="confirm">确认</JButton>
</view>
</view>
</uni-popup>
</template>
<script setup>
import { inject, onMounted, reactive, ref } from 'vue'
import { $getAgentList } from '@/http/apiManager.js'
import JLine from '@/components/newComponents/JLine/JLine'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput'
import JButton from '@/components/newComponents/JButton/JButton'
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull'
onMounted(() => {
getAgentList('')
})
const wrapperHidden = inject('wrapperHidden')
const emits = defineEmits(['confirm'])
const searchInfo = ref({
pageNumber: 1,
pageSize: 10,
state:1
})
let flag = true
const list = ref([])
const agentNo = ref({})
const popup = ref()
const open = () => {
agentNo.value = {}
popup.value.open()
}
const close = () => {
popup.value.close()
}
const getAgentList = (val) => {
if (val) {
list.value = []
searchInfo.value.unionAgentInfo = val
}
$getAgentList(searchInfo.value).then(({ bizData }) => {
const { records } = bizData
if (records.length <= 0) flag = false
records.forEach((v) => {
let obj = {
iconOn: '/static/navImg/nav-dailishang.svg',
iconClose: '/static/navImg/user-close.svg',
ml: '30rpx',
pd: '32rpx 32rpx 32rpx 0',
}
obj.name = v.agentName
obj.text = v.agentNo
list.value.push(obj)
})
})
}
const getList = () => {
if (!flag) return
searchInfo.value.pageNumber++
getAgentList()
}
const resetSearch = () => {
list.value = []
searchInfo.value.unionAgentInfo = ''
searchInfo.value.pageNumber = 1
searchInfo.value.pageSize = 10
getAgentList()
}
const selected = (v) => {
agentNo.value = JSON.parse(JSON.stringify(v))
}
const confirm = () => {
emits('confirm', agentNo.value)
}
const change = (e) => {
if (wrapperHidden) {
wrapperHidden(e.show)
}
}
defineExpose({ open, close })
</script>
<style lang="scss" scoped>
.list-wrapper {
padding-top: 30rpx;
background-color: #ece8f0;
border-radius: 32rpx 32rpx 0 0;
.list-header {
padding: 0 30rpx 30rpx 30rpx;
.list-title {
display: flex;
align-items: center;
margin-bottom: 30rpx;
image {
width: 50rpx;
height: 50rpx;
margin-right: 20rpx;
}
}
}
.list-main {
height: calc(70vh - 190rpx - 110rpx);
background-color: #fff;
}
.list-footer {
background-color: #fff;
}
}
</style>

View File

@@ -0,0 +1,93 @@
<template>
<view>
<view>
<view class="list-item" @click.stop="toDetail(item.deviceId)" v-for="(item, index) in dataList" :key="index">
<view class="item-content">
<view class="img">
<image :src="icon" v-if="item.state"></image>
<image :src="iconoff" v-else></image>
</view>
<view class="text">
<view class="title" >
<text>{{ item.deviceName }}</text>
</view>
<view class="content">
<text>设备号:{{ item.deviceNo }}</text>
</view>
<view class="content">
<text v-if="item.bindState">已绑定商户: {{ item.mchNo }}</text>
<text v-else>未绑定</text>
</view>
</view>
</view>
<view class="switch" style="border-bottom:none">
<view @click.stop>
<switch :checked="item.state == 1 ? true : false" @change="onChange($event, item)" style="margin-left: 10rpx;" color="#3981FF" />
</view>
</view>
<image src="../../static/img/right.svg" style="width:40rpx; height:40rpx;"></image>
</view>
<jeepayListNull :list="dataList"></jeepayListNull>
<!-- 更改状态对话框 -->
<jeepayConfirm ref="switchStatePopup" />
</view>
</view>
</template>
<script setup>
import { reactive, ref, watch } from 'vue';
import { onBackPress, onShow } from '@dcloudio/uni-app';
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue';
import jeepayConfirm from '@/components/jeepayConfirm/jeepayConfirm.vue'
const emit = defineEmits(['onChange','handleClose','handleConfirm','toDetail'])
const props = defineProps({
dataList:{type:Array},
icon:{type:String},
iconoff:{type:String}
})
const popup = ref();
const switchStatePopup = ref();
const data = reactive({
deviceId: '', //设备Id
placeholder: '搜索商户号、名称、设备号',
phone: '',
startSearch:false
});
const appSearchData = ref('');
const search = ref()
//状态按钮改变的事件
const onChange = (e, item) => {
item.state = Number(e.detail.value)
switchStatePopup.value.comfirmOpen(
function handleConfirm() {
let params ={
deviceId: item.deviceId,
state: item.state
}
emit('handleConfirm',params)
},
undefined,
function handleClose() {
item.state = Number(!e.detail.value)
emit('handleClose')
}
);
emit('onChange',item)
};
const toDetail =(deviceId) =>{
emit('toDetail',deviceId)
}
</script>
<style>
page {
background-color: #f5f7fa;
}
</style>

View File

@@ -0,0 +1,132 @@
<template>
<view class="page">
<!-- 撑高度 -->
<view style="height: 10rpx"></view>
<view v-for="(item, index) in list" :key="index" @tap="toPage(item.path)">
<JMainCard wrapPd="10rpx 30rpx" bgColor="#fff" pd="0">
<JInput :icon="item.icon" :isBorder="true" :name="item.name" align="center" size="33rpx" :img="true"
iconSize="60rpx" />
</JMainCard>
</view>
</view>
</template>
<script setup>
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JInput from '@/components/newComponents/JInput/JInput.vue'
const list = [
{
icon: '/static/equipmentImg/code-open.svg',
name: '码牌管理',
path: 'codeCardManagement'
},
{
icon: '/static/equipmentImg/horn-open.svg',
name: '云喇叭管理',
path: 'cloudHornManagement'
},
{
icon: '/static/equipmentImg/print-open.svg',
name: '云打印管理',
path: 'cloudPrintManagement'
},
{
icon: '/static/equipmentImg/pos-open.svg',
name: '扫码POS管理',
path: 'posMachineManagement'
},
{
icon: '/static/equipmentImg/iqpos-open.svg',
name: '智能POS管理',
path: 'iqPosManagement'
},
{
icon: '/static/equipmentImg/terminal-open.svg',
name: '辅助终端设备',
path: '../terminal/terminalList'
},
{
icon: '/pageWork/static/images/icon-face-1.svg',
name: '刷脸设备',
path:"../face/index"
},
{
icon: '/pageWork/static/images/lite-list.svg',
name: '如意Lite管理',
path:"../liteManager/index"
}
]
function toPage(path) {
uni.navigateTo({
url: `./${path}`
})
}
</script>
<style>
page {
background: #F5F6FC;
}
</style>
<style scoped lang="scss">
.content {
width: 100%;
background-color: #fff;
}
.list {
margin-top: 20rpx;
padding: 0 30rpx;
box-sizing: border-box;
border-top: 1px solid #ededed;
.list-item {
padding: 30rpx 0;
box-sizing: border-box;
border-top: 1px solid #ededed;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.left {
view {
font-size: 30rpx;
color: #000;
}
text {
font-size: 22rpx;
color: #9ea5b3;
}
}
.right {
display: flex;
flex-direction: row;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
margin-top: 6rpx;
}
}
}
.list-item:first-child {
border-top: none;
}
}
.back-color {
background-color: #f5f6fc;
height: 20rpx;
}
.unique {
margin-top: 0;
border: 0;
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<view>
<JHeaderTitle title="编辑信息" bgColor="transparent" />
<JMainCard pd="0" wrapPd="30rpx">
<JInput name="码牌名称" :isBorder="true" v-model:value="vdata.qrcAlias" place="默认为未命名" />
</JMainCard>
<JMainCard pd="0" wrapPd="0 30rpx 40rpx 30rpx">
<JInput name="收款金额" :isBorder="true">
<view @tap="choice">{{ vdata.fixedFlag == 1 ? "自定义金额" : "任意金额" }}</view>
</JInput>
<JInput
type="digit"
v-if="vdata.fixedFlag == 1"
name="自定义金额"
:img="false"
place="请输入自定义金额"
v-model:value="vdata.fixedPayAmount"
/>
</JMainCard>
<JPopup ref="JPopupRef">
<JMainCard pd="0 0 30rpx 0" wrapPd="0 30rpx">
<JLine
iconOn="/pageWork/static/images/no-fixed-on.svg"
iconClose="/pageWork/static/images/no-fixed-close.svg"
name="任意金额"
:isBorder="true"
:isSelect="vdata.fixedFlag != 1"
@tap="changeAmount(0)"
/>
<JLine
iconOn="/static/equipmentImg/fixed-on.svg"
iconClose="/pageWork/static/images/fixed-close.svg"
name="自定义金额"
:isSelect="vdata.fixedFlag == 1"
@tap="changeAmount(1)"
/>
<view class="tiptext"> 选择任意金额将不限制码牌收款金额选择自定义金额可指定该码牌收款固定金额 </view>
</JMainCard>
<JButton
pd="30rpx"
bottom="50rpx"
color="#303030"
bgColor="rgba(255,255,255,0.8)"
pdTop="0"
@HandleTouch="JPopupRef.close()"
>取消</JButton
>
</JPopup>
<JButton pd="30rpx" @HandleTouch="preservation">保存</JButton>
</view>
</template>
<script setup>
import { $upDateQRcodeList, $getQRcodeDetail } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import { ref, reactive, toRaw } from "vue"
import valid from "@/hooks/validate"
import JInput from "@/components/newComponents/JInput/JInput.vue"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JPopup from "@/components/newComponents/JPopup/JPopup.vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" // 导航栏
import JLine from "@/components/newComponents/JLine/JLine.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue"
const vdata = reactive({})
onLoad((option) => {
$getQRcodeDetail(option.id).then(({ bizData }) => {
bizData.qrcAlias ? null : (bizData.qrcAlias = "未命名")
bizData.fixedPayAmount = bizData.fixedPayAmount / 100
Object.assign(vdata, bizData)
})
})
const JPopupRef = ref(null) // 弹窗组件
// 切换金额
const choice = () => JPopupRef.value.open()
// 选择金额
const changeAmount = (data) => {
vdata.fixedFlag = data
JPopupRef.value.close()
}
// 保存
const preservation = () => {
let data = JSON.parse(JSON.stringify(toRaw(vdata)))
// data.fixedPayAmount *= 100 // 金额元转分
// 校验 1默认名称为空则默认为 未命名 2. 自定义金额状态金额不能为0
if (!data.qrcAlias) {
data.qrcAlias = "未命名"
}
if (!valid.takeMoney(data.fixedPayAmount)) {
return uni.showToast({
title: "请输入正确金额正数两位小数",
icon: "none",
})
}
if (data.fixedFlag == 1 && data.fixedPayAmount <= 0) {
return uni.showToast({
title: "自定义金额不能小于等于0",
icon: "none",
})
}
$upDateQRcodeList(data.qrcId, data).then(({ bizData }) => {
uni.showToast({ icon: "none", title: "保存成功" })
uni.navigateBack()
})
}
</script>
<style lang="scss">
page {
background: #f2f2f2;
}
.tiptext {
margin: 10rpx 30rpx 0;
border-radius: 10rpx;
background: #f2f2f2;
padding: 20rpx;
box-sizing: border-box;
font-size: 27rpx;
line-height: 46rpx;
}
</style>

View File

@@ -0,0 +1,54 @@
<template>
<view>
<JHeaderTitle title="编辑信息" bgColor="transparent" />
<JMainCard pd="0" wrapPd="30rpx">
<JInput name="设备名称" :isBorder="true" v-model:value="vdata.deviceName" place="请输入设备名称" />
</JMainCard>
<JButton pd=" 30rpx " pdTop="0" @HandleTouch="preservation">保存</JButton>
</view>
</template>
<script setup>
import { $getDeviceDetail, $updateDeviceDetail } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import { ref, reactive, toRaw } from "vue"
import JInput from "@/components/newComponents/JInput/JInput.vue"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" // 导航栏
import JButton from "@/components/newComponents/JButton/JButton.vue"
const vdata = reactive({})
onLoad((option) => {
$getDeviceDetail(option.id).then(({ bizData }) => {
Object.assign(vdata, bizData)
})
})
// 保存
const preservation = () => {
$updateDeviceDetail(vdata.deviceId, toRaw(vdata)).then(({ bizData }) => {
uni.showToast({ icon: "none", title: "保存成功" })
setTimeout(() => {
uni.navigateBack()
}, 1000)
})
}
</script>
<style lang="scss">
page {
background: #f2f2f2;
}
.tiptext {
margin: 10rpx 30rpx 0;
border-radius: 10rpx;
background: #f2f2f2;
padding: 20rpx;
box-sizing: border-box;
font-size: 27rpx;
line-height: 46rpx;
}
</style>

View File

@@ -0,0 +1,8 @@
<template>
</template>
<script>
</script>
<style>
</style>

View File

@@ -0,0 +1,150 @@
<template>
<view>
<JHeaderTitle title="编辑信息" bgColor="transparent" />
<JMainCard pd="0" wrapPd="30rpx">
<JInput name="设备名称" :isBorder="true" v-model:value="vdata.deviceName" place="请输入设备名称" />
</JMainCard>
<JMainCard pd="0" wrapPd="0 30rpx 40rpx 30rpx">
<JInput name="打印联数" :isBorder="true" type="number" v-model:value="printNum" place="请输入打印联数" />
</JMainCard>
<JMainCard pd="0" wrapPd="0 30rpx 40rpx 30rpx">
<JInput name="打印参数" :isBorder="true" :img="true">
<view @tap="change">{{ printModeText[vdata.bizConfigParams?.printMode] || "请选择" }}</view>
</JInput>
</JMainCard>
<JPopup ref="JPopupRef">
<JMainCard pd="0 0 30rpx 0" wrapPd="30rpx">
<JLine
iconOn="/pageWork/static/images/no-fixed-on.svg"
iconClose="/pageWork/static/images/no-fixed-close.svg"
name="仅打印"
:isBorder="true"
:isSelect="printMode == 1"
@tap="changeAmount('仅打印', 1)"
/>
<JLine
iconOn="/static/equipmentImg/fixed-on.svg"
iconClose="/pageWork/static/images/fixed-close.svg"
name="仅播报"
:isSelect="printMode == 2"
@tap="changeAmount('仅播报', 2)"
/>
<JLine
iconOn="/static/equipmentImg/fixed-on.svg"
iconClose="/pageWork/static/images/fixed-close.svg"
name="打印并播报"
:isSelect="printMode == 3"
@tap="changeAmount('播报并打印', 3)"
/>
</JMainCard>
<JButton pd="0 30rpx 50rpx 30rpx" bottom="50rpx" color="#303030" bgColor="rgba(255,255,255,0.8)" pdTop="0"
>取消</JButton
>
</JPopup>
<JButton pd="30rpx" @HandleTouch="preservation">保存</JButton>
</view>
</template>
<script setup>
import { $upDateQRcodeList, $getDeviceDetail, $updateDeviceDetail } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import { ref, reactive, toRaw, computed } from "vue"
import JInput from "@/components/newComponents/JInput/JInput.vue"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JPopup from "@/components/newComponents/JPopup/JPopup.vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" // 导航栏
import JLine from "@/components/newComponents/JLine/JLine.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue"
const vdata = reactive({})
const printMode = ref("") // 打印参数
const printNum = ref("") // 打印联数
onLoad((option) => {
$getDeviceDetail(option.id).then(({ bizData }) => {
bizData.deviceName ? null : (bizData.deviceName = "未命名")
bizData.bizConfigParams = JSON.parse(bizData.bizConfigParams)
Object.assign(vdata, bizData)
printNum.value = vdata.bizConfigParams.printNum
printMode.value = vdata.bizConfigParams.printMode
// 切换打印参数
// switch (vdata.bizConfigParams.printMode) {
// case 1:
// printMode.value = "仅打印"
// break
// case 2:
// printMode.value = "仅播报"
// break
// case 3:
// printMode.value = "播报并打印"
// break
// default:
// null
// }
})
})
const printModeText = reactive(["", "仅打印", "仅播报", "播报并打印"])
const JPopupRef = ref(null) // 弹窗组件
// 切换金额
const change = () => JPopupRef.value.open()
// 选择金额
const changeAmount = (data, num) => {
printMode.value = num
vdata.bizConfigParams.printMode = num
JPopupRef.value.close()
}
// 保存
const preservation = () => {
// 校验 1.设备名称不为空 2.打印联数不为空,并且是数字
if (!vdata.deviceName) {
return uni.showToast({ title: "请输入设备名称", icon: "none" })
}
if (!printNum.value) {
return uni.showToast({ title: "请输入打印联数", icon: "none" })
}
if (!/^[0-9]*$/.test(printNum.value)) {
return uni.showToast({ title: "打印联数必须是数字", icon: "none" })
}
vdata.bizConfigParams = {
printMode: printMode.value,
printNum: printNum.value,
}
const params = {}
params.deviceName = vdata.deviceName
params.printNum = printNum.value
params.bizConfigParams = vdata.bizConfigParams
$updateDeviceDetail(vdata.deviceId, params).then(({ bizData }) => {
uni.showToast({ icon: "none", title: "保存成功" })
setTimeout(() => {
uni.navigateBack()
}, 1000)
})
}
</script>
<style lang="scss">
page {
background: #f2f2f2;
}
.tiptext {
margin: 10rpx 30rpx 0;
border-radius: 10rpx;
background: #f2f2f2;
padding: 20rpx;
box-sizing: border-box;
font-size: 27rpx;
line-height: 46rpx;
}
</style>

View File

@@ -0,0 +1,273 @@
<template>
<JeepayWrapper>
<view class="page">
<JHeaderTitle title="智能POS管理" bgColor="#f2f2f2" />
<JSearchInput @search="searchHandle" @resetSearch="reset" ref="search" place="搜索商户号、名称、设备号">
<view class="header-assign" @tap="cancel">
<image src="/static/iconImg/icon-file.svg" mode="scaleToFill" />
划拨
</view>
</JSearchInput>
<view v-for="(item, index) in useDataResult.dataList">
<JPreview
v-bind="item.info"
:key="item.deviceId"
:activeBox="vdata.activeBox"
:isLast="index === useDataResult.dataList.length - 1"
@activeClick="handleActive(item.info)"
@click="toDetail(item.deviceId)"
>
<template #bottom>
<view class="info-wrapper">
<view class="info" v-if="!item.isSelf">
<image src="/static/iconImg/icon-mini-agent.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.agentName }}</view>
<view class="number">{{ item.agentNo }}</view>
</view>
<view class="info" v-if="!!item.bindState">
<image src="@/static/equipmentImg/mch-little.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.mchName }}</view>
<view class="number">{{ item.mchNo }}</view>
</view>
</view>
</template>
</JPreview>
</view>
<view class="footer-button" v-show="vdata.activeBox">
<view class="button-main">
<button @tap="cancel">取消</button>
<button class="confirm" @tap="openNext">下一步</button>
</view>
</view>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
<JSinglePopup :list="selectedList" ref="refSingle" />
<SelectedAgent ref="refSelected" @confirm="toAgent" />
</view>
</JeepayWrapper>
</template>
<script setup>
import { reactive, ref, watch } from 'vue'
import { $getDeviceList, $getAcountInfo, $updateDeviceDetail, $allotORtakeBack } from '@/http/apiManager.js'
import { onBackPress, onShow } from '@dcloudio/uni-app'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue'
import useGetList from '@/hooks/useList.js'
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from './components/SelectedAgent.vue'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' //自定义导航栏
const dataHandle = (data) => {
data.forEach((item) => {
item.info = {
img: item.state == 1 ? '/static/equipmentImg/iqpos-open.svg' : '/static/equipmentImg/iqpos-close.svg',
title: item.deviceName ? item.deviceName : '未命名',
qrcId: item.deviceNo,
spot: item.state == 1 ? '#7737FE' : '#B2B2B2',
status: item.state == 1 ? '已启用' : '已禁用',
disabled: !!item.bindState,
deviceId: item.deviceId,
}
if (item.bindState) {
item.info.mchName = item.mchName
item.info.mchNo = item.mchNo
}
})
return data
}
const vdata = reactive({
activeBox: false,
})
const refSingle = ref(null)
const refSelected = ref(null)
const { useDataResult, getList } = useGetList({
requestFun: $getDeviceList,
params: { deviceType: 4 },
dataHandle,
})
const selectedList = [
{ label: '收回所有已选择设备', value: 'takeBack', confirmText: '确定要收回所有已选设备吗?', fun: takeBackDev },
{
label: '划拨已选设备至代理商',
value: 'toAgent',
fun: () => {
refSelected.value.open()
},
},
]
const search = ref(null) // 注册搜索组件
// 搜索
const searchHandle = (val) => getList({ appSearchData: val })
// 重置搜索
const reset = () => getList({ appSearchData: '' })
// 输入框存在内容时,清空文字,列表重置
onBackPress(() => {
if (search.value.searchText != '') {
search.value.searchText = ''
reset()
return true
}
return false
})
const toDetail = (e) => {
uni.navigateTo({
url: `./updateIqPos?deviceId=${e}` + `&deviceType=` + 4,
})
}
// 设备号列表
const devNoList = []
// 勾选
const handleActive = (val) => {
if (val.disabled) return
if (val.active) {
devNoList.splice(
devNoList.findIndex((v) => v == val.deviceId),
1
)
val.active = false
return
}
devNoList.push(val.deviceId)
val.active = true
}
const openNext = () => {
if (devNoList.length == 0) return uni.showToast({ title: '请勾选要进行操作的设备', icon: 'none' })
refSingle.value.open()
}
// 收回划拨
function takeBackDev() {
const data = {
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '收回成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
getList({
pageNumber: 1,
})
})
}
// 划拨
function toAgent(e) {
const data = {
agentNo: e.text,
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '划拨成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
refSelected.value.close()
getList({
pageNumber: 1,
})
})
}
const cancel = () => {
if (!vdata.activeBox) return (vdata.activeBox = true)
useDataResult.dataList.forEach((v) => {
v.info.active = false
})
devNoList.length = 0
vdata.activeBox = false
}
</script>
<style lang="scss" scoped>
.header-assign {
display: flex;
align-items: center;
padding: 0 30rpx;
font-size: 30rpx;
font-weight: 500;
color: #404040;
image {
margin-right: 5rpx;
width: 36rpx;
height: 36rpx;
}
}
.info-wrapper {
margin-top: 20rpx;
width: 100%;
border-radius: 10rpx;
}
.info {
// width: 100%;
display: flex;
justify-content: center;
padding: 20rpx;
box-sizing: border-box;
background-color: #f7f7f7;
.mch-img {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0 10rpx;
width: 350rpx;
color: #000;
font-size: 28rpx;
flex-grow: 1;
}
.number {
white-space: nowrap;
color: #8c8c8c;
font-size: 28rpx;
}
}
.footer-button {
height: 170rpx;
}
.button-main {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
padding: 0 30rpx;
align-items: center;
height: 170rpx;
border-top: 1rpx solid #ededed;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
button {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-size: 33rpx;
font-weight: 500;
color: #575757;
background-color: #e6e6e6;
&::after {
border: none;
}
}
.confirm {
margin-left: 30rpx;
background-color: $primaryColor;
color: #fff;
}
}
</style>

View File

@@ -0,0 +1,274 @@
<template>
<JeepayWrapper>
<view class="page">
<JHeaderTitle title="扫码POS管理" bgColor="#f2f2f2" />
<JSearchInput @search="searchHandle" @resetSearch="reset" ref="search" place="搜索商户号、名称、设备号">
<view class="header-assign" @tap="cancel">
<image src="/static/iconImg/icon-file.svg" mode="scaleToFill" />
划拨
</view>
</JSearchInput>
<view v-for="(item, index) in useDataResult.dataList" :key="index">
<JPreview
v-bind="item.info"
:key="item.deviceId"
:activeBox="vdata.activeBox"
:isLast="index === useDataResult.dataList.length - 1"
@activeClick="handleActive(item.info)"
@click="toDetail(item.deviceId)"
>
<template #bottom>
<view class="info-wrapper">
<view class="info" v-if="!item.isSelf">
<image src="/static/iconImg/icon-mini-agent.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.agentName }}</view>
<view class="number">{{ item.agentNo }}</view>
</view>
<view class="info" v-if="item.mchNo">
<image src="@/static/equipmentImg/mch-little.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ item.mchName }}</view>
<view class="number">{{ item.mchNo }}</view>
</view>
</view>
</template>
</JPreview>
</view>
<view class="footer-button" v-show="vdata.activeBox">
<view class="button-main">
<button @tap="cancel">取消</button>
<button class="confirm" @tap="openNext">下一步</button>
</view>
</view>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
</view>
<JSinglePopup :list="selectedList" ref="refSingle" />
<SelectedAgent ref="refSelected" @confirm="toAgent" />
</JeepayWrapper>
</template>
<script setup>
import { reactive, ref, watch } from 'vue'
import { $getDeviceList, $getAcountInfo, $updateDeviceDetail, $allotORtakeBack } from '@/http/apiManager.js'
import { onBackPress, onShow } from '@dcloudio/uni-app'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue'
import useGetList from '@/hooks/useList.js'
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from './components/SelectedAgent.vue'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' //自定义导航栏
const refSingle = ref(null)
const refSelected = ref(null)
const dataHandle = (data) => {
data.forEach((item) => {
item.info = {
img: item.state == 1 ? '/static/equipmentImg/pos-open.svg' : '/static/equipmentImg/pos-none.svg',
title: item.deviceName ? item.deviceName : '未命名',
qrcId: item.deviceNo,
spot: item.state == 1 ? '#7737FE' : '#B2B2B2',
status: item.state == 1 ? '已启用' : '已禁用',
disabled: !!item.bindState,
deviceId: item.deviceId,
}
if (item.bindState) {
item.info.mchName = item.mchName
item.info.mchNo = item.mchNo
}
})
return data
}
const { useDataResult, getList } = useGetList({
requestFun: $getDeviceList,
params: { deviceType: 3 },
dataHandle: dataHandle,
})
const vdata = reactive({
activeBox: false,
})
const search = ref(null) // 注册搜索组件
// 搜索
const searchHandle = (val) => getList({ appSearchData: val })
// 重置搜索
const reset = () => getList({ appSearchData: '' })
// 输入框存在内容时,清空文字,列表重置
onBackPress(() => {
if (search.value.searchText != '') {
search.value.searchText = ''
reset()
return true
}
return false
})
const toDetail = (e) => {
uni.navigateTo({
url: `./updatePos?deviceId=${e}` + `&deviceType=` + 3,
})
}
const selectedList = [
{ label: '收回所有已选择设备', value: 'takeBack', confirmText: '确定要收回所有已选设备吗?', fun: takeBackDev },
{
label: '划拨已选设备至代理商',
value: 'toAgent',
fun: () => {
refSelected.value.open()
},
},
]
// 设备号列表
const devNoList = []
// 勾选
const handleActive = (val) => {
if (val.disabled) return
if (val.active) {
devNoList.splice(
devNoList.findIndex((v) => v == val.deviceId),
1
)
val.active = false
return
}
devNoList.push(val.deviceId)
val.active = true
}
const openNext = () => {
if (devNoList.length == 0) return uni.showToast({ title: '请勾选要进行操作的设备', icon: 'none' })
refSingle.value.open()
}
// 收回划拨
function takeBackDev() {
const data = {
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '收回成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
getList({
pageNumber: 1,
})
})
}
// 划拨
function toAgent(e) {
const data = {
agentNo: e.text,
allotDeviceIds: devNoList.join(','),
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({
title: '划拨成功',
icon: 'success|none',
})
devNoList.length = 0
vdata.activeBox = false
refSelected.value.close()
getList({
pageNumber: 1,
})
})
}
const cancel = () => {
if (!vdata.activeBox) return (vdata.activeBox = true)
useDataResult.dataList.forEach((v) => {
v.info.active = false
})
devNoList.length = 0
vdata.activeBox = false
}
</script>
<style lang="scss" scoped>
.header-assign {
display: flex;
align-items: center;
padding: 0 30rpx;
font-size: 30rpx;
font-weight: 500;
color: #404040;
image {
margin-right: 5rpx;
width: 36rpx;
height: 36rpx;
}
}
.info-wrapper {
margin-top: 20rpx;
width: 100%;
border-radius: 10rpx;
}
.info {
// width: 100%;
display: flex;
justify-content: center;
padding: 20rpx;
box-sizing: border-box;
background-color: #f7f7f7;
.mch-img {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0 10rpx;
width: 350rpx;
color: #000;
font-size: 28rpx;
flex-grow: 1;
}
.number {
white-space: nowrap;
color: #8c8c8c;
font-size: 28rpx;
}
}
.footer-button {
height: 170rpx;
}
.button-main {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
padding: 0 30rpx;
align-items: center;
height: 170rpx;
border-top: 1rpx solid #ededed;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
button {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-size: 33rpx;
font-weight: 500;
color: #575757;
background-color: #e6e6e6;
&::after {
border: none;
}
}
.confirm {
margin-left: 30rpx;
background-color: $primaryColor;
color: #fff;
}
}
</style>

View File

@@ -0,0 +1,227 @@
<template>
<view>
<JHeaderTitle :title="vdata.title" bgColor="#f2f2f2" />
<!-- 商户 -->
<JMainCard pd="0" wrapPd="30rpx 30rpx 0" v-if="getStore('mchInfo').mchNo" @tap="navigate('mch')">
<JPreview
img="/static/equipmentImg/mch-list.svg"
:title="getStore('mchInfo').mchName"
:qrcId="getStore('mchInfo').mchNo"
:isLast="true"
>
<view class="arrow">
<image src="/static/equipmentImg/arrow.svg" />
</view>
</JPreview>
</JMainCard>
<JMainCard pd="23rpx 0" wrapPd="30rpx 30rpx 0" v-else>
<JInput @tap="navigate('mch')" :isBorder="true" name="请选择商户" textColor="#666" size="33rpx" :img="true" />
</JMainCard>
<!-- 门店 -->
<JMainCard
pd="0"
wrapPd="30rpx 30rpx 0"
v-if="getStore('mchInfo').mchNo && getStore('storeInfo').storeName"
@tap="navigate('store')"
>
<JPreview
img="/static/equipmentImg/store-list.svg"
:title="getStore('storeInfo').storeName"
:qrcId="getStore('storeInfo').storeId"
:isLast="true"
>
<view class="arrow">
<image src="/static/equipmentImg/arrow.svg" />
</view>
</JPreview>
</JMainCard>
<JMainCard pd="23rpx 0" wrapPd="30rpx 30rpx 0" v-if="getStore('mchInfo').mchNo && !getStore('storeInfo').storeName">
<JInput @tap="navigate('store')" :isBorder="true" name="请选择门店" textColor="#666" size="33rpx" :img="true" />
</JMainCard>
<!-- 应用 -->
<JMainCard
pd="0"
wrapPd="30rpx 30rpx 0"
v-if="getStore('mchInfo').mchNo && getStore('appInfo').appName && vdata.isShowApp"
@tap="navigate('app')"
>
<JPreview
img="/static/equipmentImg/app-list.svg"
:title="getStore('appInfo').appName"
:qrcId="getStore('appInfo').appId"
:isLast="true"
>
<view class="arrow">
<image src="/static/equipmentImg/arrow.svg" />
</view>
</JPreview>
</JMainCard>
<JMainCard
pd="23rpx 0"
wrapPd="30rpx 30rpx 0"
v-if="getStore('mchInfo').mchNo && !getStore('appInfo').appName && vdata.isShowApp"
>
<JInput @tap="navigate('app')" :isBorder="true" name="请选择应用" textColor="#666" size="33rpx" :img="true" />
</JMainCard>
<view @tap="bindHandle" class="bind" :class="{ mark: vdata.isMark }">确认绑定</view>
</view>
</template>
<script setup>
import {
$getQRcodeDetail,
$qrcodeBind, // 码牌
$getDeviceDetail,
$bindDevice, // 喇叭/打印机
} from "@/http/apiManager.js"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { ref, reactive, toRaw, watch } from "vue"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JLine from "@/components/newComponents/JLine/JLine.vue"
import JInput from "@/components/newComponents/JInput/JInput.vue"
import useStore from "@/hooks/useStore.js"
import JPreview from "@/components/newComponents/JPreview/JPreview.vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
const { getStore, setStore } = useStore() // 简单的数据存储hook
const vdata = reactive({
params: {}, // 存放设备信息
isMark: true, // 是否去掉按钮的遮罩层
getInfo: "", // 获取设备信息
bindMch: "", // 绑定设备到商户
isShowApp: true, // 是否展示应用 云喇叭云打印不展示
title: "", // 页面标题
})
// 第一次进入页面时 重置商户 门店 应用 的数据
onLoad((option) => {
vdata.qrcId = option.id
vdata.title = option.title // 切换页面title
// 根据tab来确定绑定不同的设备
switch (option.tag) {
case "code":
vdata.getInfo = $getQRcodeDetail // 获取码牌信息
vdata.bindMch = $qrcodeBind // 码牌绑定商户
break
case "device":
vdata.getInfo = $getDeviceDetail // 获取 喇叭/打印机信息
vdata.bindMch = $bindDevice // 喇叭/打印机绑定商户
vdata.isShowApp = false
break
case "pos":
vdata.getInfo = $getDeviceDetail // 获取 喇叭/打印机/pos信息
vdata.bindMch = $bindDevice // 喇叭/打印机/pos绑定商户
break
default:
null
}
setStore("mchInfo", {})
setStore("storeInfo", {})
if (vdata.isShowApp) {
setStore("appInfo", {})
}
vdata.getInfo(option.id).then(({ bizData }) => {
vdata.params = bizData
})
})
// 如果每次进入页面时,可以获取到商户,门店,应用等信息,就可以去掉按钮的遮罩层进行绑定了
onShow(() => {
if (vdata.isShowApp) {
if (getStore("mchInfo").mchNo && getStore("storeInfo").storeId && getStore("appInfo").appId) {
vdata.isMark = false
vdata.params.storeId = getStore("storeInfo").storeId
vdata.params.appId = getStore("appInfo").appId
vdata.params.mchNo = getStore("mchInfo").mchNo
}
} else {
if (getStore("mchInfo").mchNo && getStore("storeInfo").storeId) {
vdata.isMark = false
vdata.params.storeId = getStore("storeInfo").storeId
vdata.params.mchNo = getStore("mchInfo").mchNo
}
}
})
// 绑定函数
const bindHandle = () => {
if (vdata.isMark) return
if (!vdata.isShowApp) vdata.params.bindType = 0 // 绑定到门店传0
vdata.bindMch(vdata.qrcId, toRaw(vdata.params)).then(() => {
uni.showToast({ icon: "none", title: "绑定成功" })
setTimeout(() => {
uni.navigateBack({})
}, 1000)
})
}
// 商户发生变化 重置门店和应用
watch(
() => getStore("mchInfo").mchNo,
() => {
setStore("storeInfo", {})
if (vdata.isShowApp) {
setStore("appInfo", {})
}
vdata.isMark = true
}
)
// 门店发生变化 重置应用
watch(
() => getStore("storeInfo").storeId,
() => {
if (vdata.isShowApp) {
setStore("appInfo", {})
}
vdata.isMark = true
}
)
// 通用跳转
const navigate = (name) => {
uni.navigateTo({ url: "/pageWork/publicSelect/publicSelect?name=" + name })
}
</script>
<style lang="scss">
page {
background: #f2f2f2;
}
</style>
<style scoped lang="scss">
.arrow {
width: 40rpx;
height: 100%;
display: flex;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
}
}
.bind {
margin: 80rpx 30rpx 0 30rpx;
height: 110rpx;
border-radius: 20rpx;
background: $primaryColor;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 33rpx;
}
.mark {
opacity: 0.5;
}
</style>

View File

@@ -0,0 +1,275 @@
<template>
<JeepayWrapper>
<view class="page-wrapper">
<!-- 顶部自定义导航栏 -->
<JHeaderTitle title="云打印详情" :bgColor="header.bgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<JEquiCode
bgImg="/static/equipmentImg/big-print.svg"
icon="/static/equipmentImg/print-white.svg"
:qrcAlias="params.deviceName"
:qrcId="params.deviceNo"
@editInfo="editInfo"
/>
<!-- 信息板块 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput name="设备名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceName" pd="15rpx 40rpx" />
<JInput name="设备号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceNo" pd="15rpx 40rpx" />
<JInput name="设备厂商" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="providerObj[params.provider]" pd="15rpx 40rpx" />
<JInput name="打印联数" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.printNum" pd="15rpx 40rpx" />
<JInput name="打印参数" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.printState" pd="15rpx 40rpx" />
<JInput name="设备状态" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view style="color: #fff; maggin-right: 16rpx; font-size: 30rpx">
{{ params.state ? '启用' : '禁用' }}
<switch :checked="params.state" style="margin-left: 20rpx; transform: scale(1.2)" color="#BF80FF" @change="switchChange" />
</view>
</JInput>
</JMainCard>
<view class="title">绑定/划拨信息</view>
<!-- 绑定商户 未绑定商户状态 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!params.bindState && params.isSelf">
<JInput icon="/pageWork/static/images/bindMch.svg" @tap="bindMch" :isBorder="true" name="绑定至商户" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<JMainCard wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="params.isSelf && !params.bindState">
<JInput icon="/static/iconImg/icon-assign.svg" @tap="selectedAgent.open()" :isBorder="true" name="划拨至代理" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<template v-if="!params.isSelf">
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="代理商名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentName" pd="15rpx 40rpx" />
<JInput name="代理商号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentNo" pd="15rpx 40rpx" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-takeBack.svg"
@tap="refTakeBack.open('收回后代理商将无法使用该设备!')"
:isBorder="true"
name="收回"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-assign.svg"
@tap="refAgain.open('确认重新划拨吗?')"
name="重新划拨"
borderBg="#7737fe"
textColor="#fff"
size="33rpx"
:img="true"
/>
</JMainCard>
</template>
<template v-if="params.bindState">
<!-- <view class="bind-title">绑定信息</view> -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="商户" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchName" pd="15rpx 40rpx" />
<JInput name="用户号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchNo" pd="15rpx 40rpx" />
<JInput name="门店" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeName" />
<JInput name="门店ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeId" />
<JInput bgColor="rgba(0,0,0,0.2)" icon="/static/equipmentImg/bind.svg" @tap="unbound" :isBorder="true" name="解绑" textColor="#fff" size="33rpx" :img="true" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/equipmentImg/bind-again.svg"
@tap="bindMch"
name="重新绑定"
borderBg="#7737fe"
textColor="#fff"
size="33rpx"
:img="true"
/>
</JMainCard>
</template>
<!-- 更改绑定状态对话框 -->
<jeepayConfirm ref="switchStatePopup" />
<!-- 更改状态对话框 -->
<jeepayConfirm ref="switchState" />
<!-- 商户选择弹窗 -->
<JDeletedTips ref="refTakeBack" @confirm="takeBack" />
<JDeletedTips ref="refAgain" @confirm="selectedAgent.open()" />
<SelectedAgent ref="selectedAgent" @confirm="again" />
</view>
</JeepayWrapper>
</template>
<script setup>
import { onLoad, onBackPress, onPageScroll, onShow } from '@dcloudio/uni-app'
import providerObj from '@/util/providerObj.js'
import { ref, reactive, toRaw, nextTick } from 'vue'
import { $updateDeviceDetail, $bindDevice, $getDeviceDetail, $getMerList, $getMchStoreList, $getMchAppList, $getQRcodeList, $allotORtakeBack } from '@/http/apiManager.js'
import JPopup from '@/components/newComponents/JPopup/JPopup.vue'
import jeepayConfirm from '@/components/jeepayConfirm/jeepayConfirm.vue'
import JEquiCode from '@/components/newComponents/JEquipment/JEquiCode.vue' // 设备信息
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' // 导航栏
import JEquipmentCode from '@/components/newComponents/JEquipment/JEquipmentCode.vue' // 设备信息
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JInput from '@/components/newComponents/JInput/JInput.vue'
import JLine from '@/components/newComponents/JLine/JLine.vue'
import JScroll from '@/components/newComponents/JScroll/JScroll.vue'
import JButton from '@/components/newComponents/JButton/JButton.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from './components/SelectedAgent.vue'
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips'
const data = reactive({
printState: '', // 打印参数 1. 仅打印 2. 仅播报 3.打印并播报
printNum: '', // 打印联数
deviceType: '', //设备类型 云打印=2
state: false,
deviceNo: '',
arrowImage: '../../static/img/arrow-right-gray.svg',
radioShow: false, //控制绑定结果的显示
cardList: [],
bindCard: false, //绑定到码牌还是门店
})
const params = ref({}) // 传参对象
const switchStatePopup = ref()
const searchMch = ref()
const searchStore = ref()
const searchApp = ref()
const switchState = ref()
const refTakeBack = ref(null)
const refAgain = ref(null)
const selectedAgent = ref(null)
onLoad((options) => {
data.deviceType = options.deviceType
data.deviceNo = options.deviceId
})
onShow(() => {
nextTick(() => {
getDetails()
})
})
const getDetails = () => {
$getDeviceDetail(data.deviceNo).then(({ bizData }) => {
params.value = bizData
params.value.bizConfigParams = JSON.parse(bizData.bizConfigParams)
data.state = bizData.state
data.printNum = params.value.bizConfigParams.printNum
// 打印参数 1. 仅打印 2. 仅播报 3.打印并播报
switch (params.value.bizConfigParams.printMode) {
case 1:
data.printState = '仅打印'
break
case 2:
data.printState = '仅播报'
break
case 3:
data.printState = '播报并打印'
break
default:
null
}
})
}
// 切换状态
function switchChange(e, item) {
params.value.state = Number(e.detail.value)
switchState.value.comfirmOpen(
() => {
$updateDeviceDetail(params.value.deviceId, { state: params.value.state })
},
undefined,
() => {
params.value.state = Number(!e.detail.value)
}
)
}
// 跳转至绑定页
const bindMch = () => {
uni.navigateTo({ url: './publicBind?id=' + params.value.deviceId + '&tag=device&title=云打印机绑定' })
}
// 跳转至编辑信息
const editInfo = () => {
uni.navigateTo({
url: './editPrint?id=' + params.value.deviceId,
})
}
// 解绑函数 打开提示弹窗
function unbound() {
switchStatePopup.value.comfirmOpen(
() => {
$updateDeviceDetail(params.value.deviceId, { bindState: 0 }).then(({ bizData }) => {
uni.showToast({
icon: 'none',
title: '解绑成功',
})
uni.navigateBack({
delta: 1,
})
})
},
'解绑后商户将无法使用该设备!',
() => {}
)
}
const takeBack = () => {
const data = {
agentNo: params.value.agentNo,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({ title: '收回成功', icon: 'success' })
getDetails()
})
}
// 重新划拨
const again = (e) => {
const data = {
agentNo: e.text,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({ title: '划拨成功', icon: 'success' })
getDetails()
selectedAgent.value.close()
})
}
// 监听页面滚动 用于给自定义导航栏换背景色
const header = reactive({ bgColor: 'transparent' })
onPageScroll((data) => {
if (data.scrollTop > 20) {
header.bgColor = '$primaryColor'
} else {
header.bgColor = 'transparent'
}
})
</script>
<style scoped lang="scss">
.page-wrapper {
min-height: 100vh;
background: $primaryColor;
}
.title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 500;
text-align: center;
color: #fff;
}
</style>

View File

@@ -0,0 +1,371 @@
<template>
<JeepayWrapper>
<!-- 顶部自定义导航栏 -->
<JHeaderTitle title="云喇叭详情" :bgColor="header.bgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<JEquiCode bgImg="/static/equipmentImg/big-horn.svg" icon="/static/equipmentImg/horn-white.svg" :qrcAlias="params.deviceName" :qrcId="params.deviceId" @editInfo="editInfo" />
<!-- 信息板块 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput name="设备名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceName" pd="15rpx 40rpx" />
<JInput name="设备号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceId" pd="15rpx 40rpx" />
<JInput name="设备厂商" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="providerObj[params.provider]" pd="15rpx 40rpx" />
<JInput name="设备状态" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view style="color: #fff; maggin-right: 16rpx; font-size: 30rpx">
{{ params.state ? '启用' : '禁用' }}
<switch :checked="params.state" style="margin-left: 20rpx; transform: scale(1.2)" color="#BF80FF" @change="switchChange" />
</view>
</JInput>
</JMainCard>
<view class="title">绑定/划拨信息</view>
<!-- 绑定商户 未绑定商户状态 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!params.mchNo && params.isSelf">
<JInput icon="/pageWork/static/images/bindMch.svg" @tap="bindMch" :isBorder="true" name="绑定至商户" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<JMainCard wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="params.isSelf && !params.mchNo">
<JInput icon="/static/iconImg/icon-assign.svg" @tap="selectedAgent.open()" :isBorder="true" name="划拨至代理" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<template v-if="!params.isSelf">
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="代理商名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentName" pd="15rpx 40rpx" />
<JInput name="代理商号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentNo" pd="15rpx 40rpx" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-takeBack.svg"
@tap="refTakeBack.open('收回后代理商将无法使用该设备!')"
:isBorder="true"
name="收回"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-assign.svg"
@tap="refAgain.open('确认重新划拨吗?')"
name="重新划拨"
borderBg="#7737fe"
textColor="#fff"
size="33rpx"
:img="true"
/>
</JMainCard>
</template>
<!-- 绑定商户状态 -->
<template v-if="params.mchNo">
<!-- <view class="bind-title">绑定信息</view> -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="商户" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchName" pd="15rpx 40rpx" />
<JInput name="用户号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchNo" pd="15rpx 40rpx" />
<JInput name="门店" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeName" />
<JInput name="门店ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeId" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/equipmentImg/bind.svg"
@tap="unboundTips.open('解绑后商户将无法使用该设备!')"
:isBorder="true"
name="解绑"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput bgColor="rgba(0,0,0,0.2)" icon="/static/equipmentImg/bind-again.svg" @tap="bindMch" name="重新绑定" borderBg="#7737fe" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<JMainCard wrapPd=" 0 50rpx 50rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput bgColor="rgba(0,0,0,0.2)" @tap="storeOrCode" name="绑定至" :isBorder="true" textColor="#fff" size="33rpx" :right="data.bindCard ? '码牌' : '门店'" :img="true" />
</JMainCard>
<!-- 码牌列表 -->
<view class="bind-title" v-if="data.bindCard">受支持的码牌设备</view>
<view class="layout-code" v-if="data.bindCard">
<scroll-view scroll-y="true" style="max-height: 424rpx">
<view v-for="(item, index) in data.codeDataList" @click.stop="toDetail(item.deviceId)" :key="item.batchId">
<!-- preStyle 预制主题色 img 图片 根据 cardList存不存在对应的码牌ID进行切换 -->
<JPreview
v-bind="item.info"
:borderNone="index === data.codeDataList.length - 1"
:preStyle="data.cardList.includes(item.qrcId) ? 'two' : 'one'"
:img="data.cardList.includes(item.qrcId) ? '/static/equipmentImg/code-white.svg' : '/static/equipmentImg/code-close.svg'"
>
<view @click.stop style="display: flex; align-items: center">
<switch
:checked="data.cardList.includes(item.qrcId)"
:disabled="params.bindQrcId == item.qrcId"
style="margin-left: 10rpx"
color="#bf80ff"
@change="onChange($event, item)"
@tap="tipsInfo(item)"
/>
</view>
</JPreview>
</view>
</scroll-view>
</view>
</template>
<JPopup ref="JPopupRef">
<JMainCard pd="30rpx 0" wrapPd="30rpx">
<JLine
iconOn="/pageWork/static/images/store-code.svg"
iconClose="/pageWork/static/images/code-store.svg"
name="绑定至门店"
:isBorder="true"
:isSelect="!data.bindCard"
@tap="changeBind(0)"
/>
<JLine
iconOn="/pageWork/static/images/store-code.svg"
iconClose="/pageWork/static/images/code-store.svg"
name="绑定至码牌"
:isSelect="data.bindCard"
@tap="changeBind(1)"
/>
<view class="tiptext"> 绑定至门店将播报门店下所有设备的收款绑定至码牌则仅播报受支持的码牌的收款 </view>
</JMainCard>
<JButton pd=" 0 30rpx 30rpx 30rpx" color="#303030" bgColor="rgba(255,255,255,0.8)" pdTop="0" @HandleTouch="JPopupRef.close()">取消</JButton>
</JPopup>
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancel" />
<JDeletedTips ref="unboundTips" @confirm="unbound" />
<JDeletedTips ref="refTakeBack" @confirm="takeBack" />
<JDeletedTips ref="refAgain" @confirm="selectedAgent.open()" />
<SelectedAgent ref="selectedAgent" @confirm="again" />
</JeepayWrapper>
</template>
<script setup>
import { onLoad, onBackPress, onPageScroll, onShow } from '@dcloudio/uni-app'
import providerObj from '@/util/providerObj.js'
import { ref, reactive, toRaw, nextTick } from 'vue'
import { $unBind, $bindDevice, $getDeviceDetail, $updateDeviceDetail, $getQRcodeList, $allotORtakeBack } from '@/http/apiManager.js'
import JPopup from '@/components/newComponents/JPopup/JPopup.vue'
import JEquiCode from '@/components/newComponents/JEquipment/JEquiCode.vue' // 设备信息
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' // 导航栏
import JEquipmentCode from '@/components/newComponents/JEquipment/JEquipmentCode.vue' // 设备信息
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JInput from '@/components/newComponents/JInput/JInput.vue'
import JLine from '@/components/newComponents/JLine/JLine.vue'
import JScroll from '@/components/newComponents/JScroll/JScroll.vue'
import JButton from '@/components/newComponents/JButton/JButton.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips'
import SelectedAgent from './components/SelectedAgent.vue'
const data = reactive({
state: false,
radioShow: false, //控制绑定结果的显示
cardList: [],
bindCard: false, //绑定到码牌还是门店
codeDataList: [], // 码牌信息列表
})
const params = ref({}) // 传参对象
const switchState = ref()
const switchStatePopup = ref()
const JPopupRef = ref(null) // 弹窗组件
const switchTips = ref(null)
const unboundTips = ref(null)
const refTakeBack = ref(null)
const refAgain = ref(null)
const selectedAgent = ref(null)
onLoad((options) => {
data.deviceType = options.deviceType //设备类型 云喇叭=1
data.deviceId = options.deviceId //设备编号
})
onShow(() => {
nextTick(() => {
getDetails()
})
})
const getDetails = () => {
$getDeviceDetail(data.deviceId).then(({ bizData }) => {
params.value = bizData // 云喇叭详情
bizData.bindType ? (data.bindCard = true) : (data.bindCard = false) // 绑定到码牌还是门店
;(data.cardList = bizData.qrcIdList ? bizData.qrcIdList : []), // 码牌列表
(data.storeId = bizData.storeId)
if (bizData.storeName) getCode(bizData.storeId) // 请求码牌列表
})
}
// 请求码牌信息
const getCode = (storeId) => {
$getQRcodeList({
pageNumber: -1,
qrcBelongType: 2,
storeId,
}).then(({ bizData }) => {
bizData.records.forEach((item) => {
item.info = {
title: item.qrcAlias ? item.qrcAlias : '未命名',
qrcId: item.qrcId,
}
})
data.codeDataList = bizData.records // 保存码牌列表 用于页面渲染
})
}
// 绑定至码牌还是门店
const storeOrCode = () => JPopupRef.value.open()
// 选择门店或则码牌
const changeBind = (val) => {
params.value.bindType = Number(val) // 1绑定到码牌 或 0 绑定到门店
Number(val) ? (data.bindCard = true) : (data.bindCard = false)
// 如果选择绑定门店则发送请求
if (!data.bindCard) {
params.value.bindType = 0 // 绑定到门店传0
$bindDevice(data.deviceId, params.value)
} else {
// 如果选择绑定到码牌必须存在码牌ID才发送请求
if (data.cardList.length > 0) {
params.value.qrcIdList = data.cardList
$bindDevice(data.deviceId, params.value)
}
}
JPopupRef.value.close()
// 绑定到码牌是要传入 码牌ID列表的所以在下面的逻辑中没开启或关闭一次码牌都要请求一次列表如果是最后一个码牌则不允许关闭
}
//码牌开启关闭, 一开始所有的码牌都是关闭的 ,勾一项开一项, 如果只剩最后一个开启的,那么就不允许在关闭了,必须开一个。
const onChange = (e, item) => {
if (e.detail.value) {
data.cardList.includes(item.qrcId) ? undefined : data.cardList.push(item.qrcId) // 防止重复添加
} else {
let index = data.cardList.indexOf(item.qrcId)
data.cardList.splice(index, 1)
}
params.value.qrcIdList = data.cardList
$bindDevice(data.deviceId, params.value) // 发送新的请求,同时加入所开启的码牌
}
let flag = undefined
// 切换喇叭状态
function switchChange(e, item) {
flag = true
params.value.state = Number(e.detail.value)
switchTips.value.open('确认修改吗?')
}
const confirm = () => {
flag = false
$updateDeviceDetail(data.deviceId, { state: params.value.state }).then(() => {
uni.showToast({
title: '修改成功',
icon: 'success',
})
})
}
const cancel = (val) => {
if (!flag) return
params.value.state = Number(!params.value.state)
}
// 跳转至绑定页
const bindMch = () => {
uni.navigateTo({ url: './publicBind?id=' + data.deviceId + '&tag=device&title=云喇叭绑定' })
}
// 跳转至编辑信息
const editInfo = () => {
uni.navigateTo({
url: './editHorn?id=' + data.deviceId,
})
}
// 解绑函数 打开提示弹窗
function unbound() {
$unBind(params.value.deviceId).then(({ bizData }) => {
uni.showToast({
icon: 'none',
title: '解绑成功',
})
uni.navigateBack({
delta: 1,
})
})
}
const takeBack = () => {
const data = {
agentNo: params.value.agentNo,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
getDetails()
uni.showToast({ title: '收回成功', icon: 'success' })
})
}
// 重新划拨
const again = (e) => {
const data = {
agentNo: e.text,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({ title: '划拨成功', icon: 'success' })
getDetails()
selectedAgent.value.close()
})
}
// 监听页面滚动 用于给自定义导航栏换背景色
const header = reactive({ bgColor: 'transparent' })
onPageScroll((data) => {
if (data.scrollTop > 20) {
header.bgColor = '$primaryColor'
} else {
header.bgColor = 'transparent'
}
})
const tipsInfo = (val) => {
if (params.value.bindQrcId == val.qrcId) {
uni.showToast({ title: '平台下发码牌 不能修改状态', icon: 'none' })
}
}
</script>
<style lang="scss">
page {
background: $primaryColor;
}
</style>
<style scoped lang="scss">
.bind-title {
margin-top: 20rpx;
text-align: center;
font-size: 33rpx;
color: #ffffff;
}
.tiptext {
margin: 10rpx 30rpx 0;
border-radius: 10rpx;
background: #f2f2f2;
padding: 20rpx;
box-sizing: border-box;
font-size: 27rpx;
line-height: 46rpx;
}
.layout-code {
margin: 30rpx 50rpx;
}
.title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 500;
text-align: center;
color: #fff;
}
</style>

View File

@@ -0,0 +1,257 @@
<template>
<JeepayWrapper>
<!-- 顶部自定义导航栏 -->
<JHeaderTitle title="智能POS详情" :bgColor="header.bgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<JEquiCode bgImg="/static/equipmentImg/big-iqpos.svg" icon="/static/equipmentImg/iqpos-white.svg" :qrcAlias="params.deviceName" :qrcId="params.deviceId" :editIsShow="false" />
<!-- 信息板块 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput name="设备名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceName" pd="15rpx 40rpx" />
<JInput name="设备号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceId" pd="15rpx 40rpx" />
<JInput name="设备厂商" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="data.manufacturer" pd="15rpx 40rpx" />
<JInput name="设备状态" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view style="color: #fff; maggin-right: 16rpx; font-size: 30rpx" class="dis-wrapper">
{{ params.state ? '启用' : '禁用' }}
<switch :checked="params.state" style="margin-left: 20rpx; transform: scale(1.2)" color="#BF80FF" @change="switchChange" />
</view>
</JInput>
</JMainCard>
<view class="title">绑定/划拨信息</view>
<!-- 绑定商户 未绑定商户状态 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!params.bindState && params.isSelf">
<JInput icon="/pageWork/static/images/bindMch.svg" @tap="bindMch" :isBorder="true" name="绑定至商户" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<JMainCard wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="params.isSelf && !params.bindState">
<JInput icon="/static/iconImg/icon-assign.svg" @tap="selectedAgent.open()" :isBorder="true" name="划拨至代理" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<template v-if="!params.isSelf">
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="代理商名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentName" pd="15rpx 40rpx" />
<JInput name="代理商号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentNo" pd="15rpx 40rpx" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-takeBack.svg"
@tap="refTakeBack.open('收回后代理商将无法使用该设备!')"
:isBorder="true"
name="收回"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-assign.svg"
@tap="refAgain.open('确认重新划拨吗?')"
name="重新划拨"
borderBg="#7737fe"
textColor="#fff"
size="33rpx"
:img="true"
/>
</JMainCard>
</template>
<template v-if="params.bindState">
<view class="bind-title">绑定信息</view>
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="商户" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchName" pd="15rpx 40rpx" />
<JInput name="用户号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchNo" pd="15rpx 40rpx" />
<JInput name="门店" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeName" />
<JInput name="门店ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeId" />
<JInput name="应用名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.appName" />
<JInput name="AppID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.appId" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/equipmentImg/bind.svg"
@tap="switchStatePopup.open('解绑后商户将无法使用该设备!')"
:isBorder="true"
name="解绑"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput bgColor="rgba(0,0,0,0.2)" icon="/static/equipmentImg/bind-again.svg" @tap="bindMch" name="重新绑定" borderBg="#7737fe" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
</template>
<!-- 商户选择弹窗 -->
<!-- 选择弹窗 -->
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancel" />
<JDeletedTips ref="switchStatePopup" @confirm="unbound" />
<JDeletedTips ref="refTakeBack" @confirm="takeBack" />
<JDeletedTips ref="refAgain" @confirm="selectedAgent.open()" />
<SelectedAgent ref="selectedAgent" @confirm="again" />
</JeepayWrapper>
</template>
<script setup>
import { onLoad, onBackPress, onPageScroll, onShow } from '@dcloudio/uni-app'
import providerObj from '@/util/providerObj.js'
import { ref, reactive, toRaw, nextTick } from 'vue'
import { $updateDeviceDetail, $getDeviceDetail, $payIfDefines, $allotORtakeBack } from '@/http/apiManager.js'
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips'
import JPopup from '@/components/newComponents/JPopup/JPopup.vue'
import JEquiCode from '@/components/newComponents/JEquipment/JEquiCode.vue' // 设备信息
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' // 导航栏
import JEquipmentCode from '@/components/newComponents/JEquipment/JEquipmentCode.vue' // 设备信息
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JInput from '@/components/newComponents/JInput/JInput.vue'
import JLine from '@/components/newComponents/JLine/JLine.vue'
import JScroll from '@/components/newComponents/JScroll/JScroll.vue'
import JButton from '@/components/newComponents/JButton/JButton.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from './components/SelectedAgent.vue'
const data = reactive({
printState: '', // 打印参数 1. 仅打印 2. 仅播报 3.打印并播报
printNum: '', // 打印联数
deviceType: '', //设备类型 云打印=2
state: false,
deviceNo: '',
arrowImage: '../../static/img/arrow-right-gray.svg',
radioShow: false, //控制绑定结果的显示
cardList: [],
bindCard: false, //绑定到码牌还是门店
payCodeList: [], // 渠道名称列表,用于获取设备厂商字段
manufacturer: '', // 厂商字段,
})
const switchTips = ref(null)
const params = ref({}) // 传参对象
const switchStatePopup = ref()
const searchMch = ref()
const searchStore = ref()
const searchApp = ref()
const refTakeBack = ref(null)
const refAgain = ref(null)
const selectedAgent = ref(null)
onLoad((options) => {
data.deviceType = options.deviceType
data.deviceNo = options.deviceId
})
onShow(() => {
nextTick(() => {
// 设备厂商 && 支付接口 ,用于匹配查找设备厂商字段
getDetails()
})
})
const getDetails = () => {
$payIfDefines({ state: 1 })
.then(({ bizData }) => {
data.payCodeList = bizData
return $getDeviceDetail(data.deviceNo)
})
.then(({ bizData }) => {
params.value = bizData
data.state = bizData.state
// 获取厂商
data.manufacturer = data.payCodeList.find((item) => params.value.provider === item.ifCode).ifName
})
}
let flag = undefined
// 切换状态
function switchChange(e, item) {
flag = true
params.value.state = Number(e.detail.value)
switchTips.value.open('确认修改吗?')
}
const confirm = () => {
flag = false
$updateDeviceDetail(params.value.deviceId, { state: params.value.state }).then(() => {
uni.showToast({
title: '修改成功',
icon: 'success',
})
})
}
const cancel = () => {
if (!flag) return
params.value.state = Number(!params.value.state)
}
// 跳转至绑定页
const bindMch = () => {
uni.navigateTo({ url: './publicBind?id=' + params.value.deviceId + '&tag=pos&title=扫码POS绑定' })
}
// 跳转至编辑信息
const editInfo = () => {
uni.navigateTo({
url: './editPrint?id=' + params.value.deviceId,
})
}
// 解绑函数 打开提示弹窗
function unbound() {
$updateDeviceDetail(params.value.deviceId, { bindState: 0 }).then(({ bizData }) => {
uni.showToast({
icon: 'none',
title: '解绑成功',
})
uni.navigateBack({
delta: 1,
})
})
}
const takeBack = () => {
const data = {
agentNo: params.value.agentNo,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
getDetails()
uni.showToast({ title: '收回成功', icon: 'success' })
})
}
// 重新划拨
const again = (e) => {
const data = {
agentNo: e.text,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({ title: '划拨成功', icon: 'success' })
getDetails()
selectedAgent.value.close()
})
}
// 监听页面滚动 用于给自定义导航栏换背景色
const header = reactive({ bgColor: 'transparent' })
onPageScroll((data) => {
if (data.scrollTop > 20) {
header.bgColor = '$primaryColor'
} else {
header.bgColor = 'transparent'
}
})
</script>
<style lang="scss">
page {
background: $primaryColor;
}
</style>
<style scoped lang="scss">
.title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 500;
text-align: center;
color: #fff;
}
</style>

View File

@@ -0,0 +1,241 @@
<template>
<JeepayWrapper>
<!-- 顶部自定义导航栏 -->
<JHeaderTitle title="扫码POS详情" :bgColor="header.bgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<JEquiCode bgImg="/static/equipmentImg/big-pos.svg" icon="/static/equipmentImg/pos-white.svg" :qrcAlias="params.deviceName" :qrcId="params.deviceNo" :editIsShow="false" />
<!-- 信息板块 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput name="设备名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceName" pd="15rpx 40rpx" />
<JInput name="设备号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.deviceNo" pd="15rpx 40rpx" />
<JInput name="设备厂商" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="providerObj[params.provider]" pd="15rpx 40rpx" />
<JInput name="设备状态" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view style="color: #fff; margin-right: 16rpx; font-size: 30rpx">
{{ params.state ? '启用' : '禁用' }}
<switch :checked="params.state" style="margin-left: 20rpx; transform: scale(1.2)" color="#BF80FF" @change="switchChange" />
</view>
</JInput>
</JMainCard>
<view class="title">绑定/划拨信息</view>
<!-- 绑定商户 未绑定商户状态 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!params.bindState && params.isSelf">
<JInput icon="/pageWork/static/images/bindMch.svg" @tap="bindMch" :isBorder="true" name="绑定至商户" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<JMainCard wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!params.bindState && params.isSelf">
<JInput icon="/static/iconImg/icon-assign.svg" @tap="selectedAgent.open()" :isBorder="true" name="划拨至代理" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<template v-if="!params.isSelf">
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="代理商名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentName" pd="15rpx 40rpx" />
<JInput name="代理商号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.agentNo" pd="15rpx 40rpx" />
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-takeBack.svg"
@tap="refTakeBack.open('收回后代理商将无法使用该设备!')"
:isBorder="true"
name="收回"
textColor="#fff"
size="33rpx"
:img="true"
/>
<JInput
bgColor="rgba(0,0,0,0.2)"
icon="/static/iconImg/icon-assign.svg"
@tap="refAgain.open('确认重新划拨吗?')"
name="重新划拨"
borderBg="#7737fe"
textColor="#fff"
size="33rpx"
:img="true"
/>
</JMainCard>
</template>
<template v-if="params.bindState">
<view class="bind-title">绑定信息</view>
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="0">
<JInput name="商户" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchName" pd="15rpx 40rpx" />
<JInput name="用户号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="params.mchNo" pd="15rpx 40rpx" />
<JInput name="门店" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeName" />
<JInput name="门店ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.storeId" />
<JInput name="应用名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.appName" />
<JInput name="AppID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="params.appId" />
<JInput bgColor="rgba(0,0,0,0.2)" icon="/static/equipmentImg/bind.svg" @tap="unbound" :isBorder="true" name="解绑" textColor="#fff" size="33rpx" :img="true" />
<JInput bgColor="rgba(0,0,0,0.2)" icon="/static/equipmentImg/bind-again.svg" @tap="bindMch" name="重新绑定" borderBg="#7737fe" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
</template>
<!-- 更改绑定状态对话框 -->
<jeepayConfirm ref="switchStatePopup" />
<!-- 更改状态对话框 -->
<jeepayConfirm ref="switchState" />
<!-- 商户选择弹窗 -->
<JDeletedTips ref="refTakeBack" @confirm="takeBack" />
<JDeletedTips ref="refAgain" @confirm="selectedAgent.open()" />
<SelectedAgent ref="selectedAgent" @confirm="again" />
</JeepayWrapper>
</template>
<script setup>
import { onLoad, onBackPress, onPageScroll, onShow } from '@dcloudio/uni-app'
import providerObj from '@/util/providerObj.js'
import { ref, reactive, toRaw, nextTick } from 'vue'
import { $updateDeviceDetail, $getDeviceDetail, $payIfDefines, $unBind, $allotORtakeBack } from '@/http/apiManager.js'
import JPopup from '@/components/newComponents/JPopup/JPopup.vue'
import jeepayConfirm from '@/components/jeepayConfirm/jeepayConfirm.vue'
import JEquiCode from '@/components/newComponents/JEquipment/JEquiCode.vue' // 设备信息
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue' // 导航栏
import JEquipmentCode from '@/components/newComponents/JEquipment/JEquipmentCode.vue' // 设备信息
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JInput from '@/components/newComponents/JInput/JInput.vue'
import JLine from '@/components/newComponents/JLine/JLine.vue'
import JScroll from '@/components/newComponents/JScroll/JScroll.vue'
import JButton from '@/components/newComponents/JButton/JButton.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips'
import SelectedAgent from './components/SelectedAgent.vue'
const data = reactive({
printState: '', // 打印参数 1. 仅打印 2. 仅播报 3.打印并播报
printNum: '', // 打印联数
deviceType: '', //设备类型 云打印=2
state: false,
deviceNo: '',
arrowImage: '../../static/img/arrow-right-gray.svg',
radioShow: false, //控制绑定结果的显示
cardList: [],
bindCard: false, //绑定到码牌还是门店
})
const params = ref({}) // 传参对象
const switchStatePopup = ref()
const searchMch = ref()
const searchStore = ref()
const searchApp = ref()
const switchState = ref()
const refTakeBack = ref(null)
const refAgain = ref(null)
const selectedAgent = ref(null)
onLoad((options) => {
data.deviceType = options.deviceType
data.deviceNo = options.deviceId
})
onShow(() => {
nextTick(() => {
getDetails()
})
})
const getDetails = () => {
$getDeviceDetail(data.deviceNo).then(({ bizData }) => {
params.value = bizData
data.state = bizData.state
})
}
// 切换状态
function switchChange(e, item) {
params.value.state = Number(e.detail.value)
switchState.value.comfirmOpen(
() => {
$updateDeviceDetail(params.value.deviceId, params.value)
},
undefined,
() => {
params.value.state = Number(!e.detail.value)
}
)
}
// 跳转至绑定页
const bindMch = () => {
uni.navigateTo({ url: './publicBind?id=' + params.value.deviceId + '&tag=pos&title=扫码POS绑定' })
}
// 跳转至编辑信息
const editInfo = () => {
uni.navigateTo({
url: './editPrint?id=' + params.value.deviceId,
})
}
// 解绑函数 打开提示弹窗
function unbound() {
switchStatePopup.value.comfirmOpen(
() => {
$unBind(params.value.deviceId).then(({ bizData }) => {
uni.showToast({
icon: 'none',
title: '解绑成功',
})
uni.navigateBack({
delta: 1,
})
})
},
'解绑后商户将无法使用该设备!',
() => {}
)
}
const takeBack = () => {
const data = {
agentNo: params.value.agentNo,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
getDetails()
uni.showToast({ title: '收回成功', icon: 'success' })
})
}
// 重新划拨
const again = (e) => {
const data = {
agentNo: e.text,
allotDeviceIds: params.value.deviceId,
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
uni.showToast({ title: '划拨成功', icon: 'success' })
getDetails()
selectedAgent.value.close()
})
}
// 监听页面滚动 用于给自定义导航栏换背景色
const header = reactive({ bgColor: 'transparent' })
onPageScroll((data) => {
if (data.scrollTop > 20) {
header.bgColor = '$primaryColor'
} else {
header.bgColor = 'transparent'
}
})
</script>
<style lang="scss">
page {
background: $primaryColor;
}
</style>
<style scoped lang="scss">
.title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 500;
text-align: center;
color: #fff;
}
</style>