源文件

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,242 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<view class="mch-header">
<JHeaderTitle :title="selected.headerTitle" :isFocus="true" bgColor="#f2f2f2" />
<view class="search bgF2">
<JSearchInput :place="selected.place" @search="search" @resetSearch="resetSearch"
/></view>
</view>
<block v-for="(v, i) in list" :key="i">
<view class="page-main bgF" @tap="selectedData(v)">
<image :src="selected.imgList" mode="scaleToFill" />
<view class="page-left">
<view class="page-text">
{{ v[selected.title] }}
<text>{{ v[selected.text] }}</text>
</view>
<image
src="/static/equipmentImg/check.svg"
mode="scaleToFill"
v-if="index == v[selected.index] && selected.index"
/>
</view>
</view>
</block>
<jeepayListNull :list="list.length" :isShow="true" />
<view class="page-block"> </view>
<view class="page-button ButtonBor">
<JButton pdTop="0" v-if="selected?.type != 'search'" pd="30rpx 30rpx 50rpx 30rpx" @HandleTouch="back"
>确认</JButton
>
</view>
</view>
</template>
<script setup>
import { ref } from "vue"
import { onPullDownRefresh, onReachBottom, onLoad } from "@dcloudio/uni-app"
import { $getTeams, $getMerList, $getMchStoreList, $getMchAppList, $getDeviceList, $getDev } from "@/http/apiManager.js"
import useGetList from "@/hooks/useList.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" // 导航栏
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue"
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull"
import useStore from "@/hooks/useStore.js"
const { setStore } = useStore()
onLoad((options) => {
params.value = { pageSize: 10, pageNumber: 1 }
selected.value = selectedInfo[options.title]
if (options.search && options.search != "undefined") {
let search = JSON.parse(options.search)
Object.assign(params.value, search)
}
index.value = options.selected
getList()
})
onPullDownRefresh(() => {
resetSearch()
})
const flag = ref(true)
const list = ref([])
const index = ref("")
const params = ref({
pageSize: 10,
pageNumber: 1,
})
const info = ref({})
const selected = ref({})
const selectedInfo = {
team: {
imgList: "/static/iconImg/expand-fill.svg",
headerTitle: "选择团队",
place: "请输入团队名称",
getList: $getTeams,
searchName: "teamName",
title: "teamName",
text: "teamId",
index: "teamId",
key: "team",
},
mch: {
imgList: "/static/equipmentImg/mch-list.svg",
headerTitle: "选择商户",
place: "请输入商户名称",
getList: $getMerList,
searchName: "mchName",
title: "mchName",
text: "mchNo",
index: "mchNo",
key: "mch",
},
store: {
imgList: "/static/navImg/nav-mendian.svg",
headerTitle: "选择门店",
place: "请输入门店名称",
getList: $getMchStoreList,
searchName: "storeName",
title: "storeName",
text: "storeId",
index: "storeId",
key: "store",
},
appId: {
imgList: "/static/iconImg/icon-app-selected.svg",
headerTitle: "请选择应用",
place: "搜索应用",
getList: $getMchAppList,
searchName: "storeName",
title: "appName",
text: "appId",
index: "appId",
key: "appId",
},
POS: {
imgList: "/static/equipmentImg/pos-open.svg",
headerTitle: "请选择扫码POS",
place: "搜索设备名称、设备号、用户号",
getList: $getDeviceList,
searchName: "appSearchData",
title: "deviceName",
text: "deviceNo",
index: "deviceId",
key: "POS",
},
expand: {
type: "search", //只搜索 拓展员搜索
imgList: "/static/iconImg/expand-member.svg",
headerTitle: "搜索拓展员",
place: "搜索拓展员姓名、手机号",
getList: $getDev,
searchName: "queryNameOrPhone",
title: "realname",
text: "telphone",
url: "/pageWork/developerManagement/developerDetail?id=",
id: "sysUserId",
flag: "show",
},
}
console.log(11111);
const selectedData = (val) => {
if (selected.value.url)
return uni.navigateTo({
url: selected.value.url + val[selected.value.id],
fail: (err) => {
console.log(err)
},
})
info.value = val
index.value = val[selected.value.index]
}
const getList = () => {
if (selected.value.flag && selected.value.flag == "show") return
if (!flag.value) return
uni.showLoading({ title: "加载中..." })
selected.value.getList(params.value).then(({ bizData }) => {
uni.hideLoading()
uni.stopPullDownRefresh()
list.value.push(...bizData.records)
if (bizData.records.length === 0) return (flag.value = false)
})
}
// 搜索
const search = (val) => {
selected.value.flag = ""
params.value[selected.value.searchName] = val
params.value.pageNumber = 1
list.value = []
getList()
}
// 重置搜索
const resetSearch = () => {
list.value = []
params.value.pageNumber = 1
params.value[selected.value.searchName] = ""
flag.value = true
getList()
}
const back = () => {
console.log(selected.value.key,info.value);
setStore(selected.value.key, info.value)
uni.navigateBack()
}
onReachBottom(() => {
params.value.pageNumber++
getList()
})
</script>
<style lang="scss" scoped>
.page-wrapper {
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.page-main {
display: flex;
align-items: center;
padding-left: 30rpx;
image {
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
}
.page-left {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-bottom: 1rpx solid #f9f9f9;
.page-text {
display: flex;
flex-direction: column;
font-size: 33rpx;
text {
margin-top: 15rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
image {
width: 50rpx;
height: 50rpx;
}
}
}
.page-block {
height: 220rpx;
}
.page-button {
position: fixed;
right: 0;
left: 0;
bottom: 0;
backdrop-filter: blur(30px);
}
}
</style>

View File

@@ -0,0 +1,139 @@
<template>
<view class="global-wrapper bgF2">
<view class="mch-header">
<JHeaderTitle title="创建代理商" bgColor="#f2f2f2" />
</view>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput
name="代理商全称"
:isBorder="true"
v-model:value="agentInfo.agentName"
:rules="{ name: 'agentName', rule: 'REG_NotNUll' }"
place="请输入商代理商全称"
></JInput>
<JInput
name="代理商简称"
v-model:value="agentInfo.agentShortName"
:rules="{ name: 'agentShortName', rule: 'REG_NotNUll' }"
place="请输入代理商简称"
></JInput>
<JInput
name="代理商登录名"
v-model:value="agentInfo.loginUsername"
:rules="{ name: 'loginUsername', rule: 'REG_LoginName' }"
place="字母开头6到18位"
></JInput>
<JInput name="是否允许发展下级">
<switch
:checked="agentInfo.addAgentFlag == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe"
@change="switchState($event, 'addAgentFlag')"
/>
</JInput>
<JInput name="代理商状态">
<switch
:checked="agentInfo.state == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe"
@change="switchState($event, 'state')"
/>
</JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput
name="联系人姓名"
:isBorder="true"
v-model:value="agentInfo.contactName"
:rules="{ name: 'contactName', rule: 'REG_NotNUll' }"
place="请输入联系人姓名"
></JInput>
<JInput
name="联系人手机号"
v-model:value="agentInfo.contactTel"
:rules="{ name: 'contactTel', rule: 'REG_Phone' }"
place="请输入联系人手机号"
></JInput>
<JInput name="联系人邮箱" v-model:value="agentInfo.contactEmail" place="请输入联系人邮箱"></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput name="是否发送开通提醒" :isBorder="true">
<switch
:checked="agentInfo.isNotify == 1 ? true : false"
style="margin-left: 15rpx; transform: scale(1.2)"
color="#7737FE"
@change="switchState($event, 'isNotify')"
/>
</JInput>
<JInput name="是否使用默认密码">
<switch
:checked="agentInfo.defaultPass == 1 ? true : false"
style="margin-left: 15rpx; transform: scale(1.2)"
color="#7737FE"
@change="switchState($event, 'defaultPass')"
/>
</JInput>
<JInput
name="自定义密码"
v-model:value="agentInfo.loginPassword"
:rules="{ name: 'loginPassword', rule: 'REG_NotNUll' }"
place="请输入自定义密码"
v-if="!agentInfo.defaultPass == 1"
></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput name="备注" v-model:value="agentInfo.remark" place="请输入备注"></JInput>
</JMainCard>
<JButton size="max" pd="30rpx" pdTop="0" @HandleTouch="createAgent">创建代理商</JButton>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { $addAgent, $getPasswordRules } from "@/http/apiManager.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import { validateArray } from "@/hooks/rules"
import valid from "@/hooks/validate"
onLoad(() => {
getRules()
})
const agentInfo = reactive({
defaultPass: 1,
isNotify: 0,
state: 1,
addAgentFlag: 1,
})
const switchState = (e, v) => {
agentInfo[v] = e.detail.value ? 1 : 0
}
const rules = ref({})
const getRules = () => {
$getPasswordRules().then((res) => {
rules.value.rule = new RegExp(res.bizData.regexpRules)
rules.value.ruleText = res.bizData.errTips
})
}
const createAgent = () => {
if (validateArray(agentInfo)) {
if (!!agentInfo.contactEmail) {
if (!valid.REG_Email(agentInfo.contactEmail)) return uni.showToast({ title: "邮箱格式不正确", icon: "none" })
}
if (agentInfo.loginPassword && !rules.value.rule.test(agentInfo.loginPassword)) {
return uni.showToast({
title: rules.value.ruleText,
icon: "none",
})
}
$addAgent(agentInfo).then((res) => {
uni.showToast({
icon: "success",
title: "创建成功",
})
uni.navigateBack()
})
}
}
</script>

View File

@@ -0,0 +1,325 @@
<template>
<view class="page-wrapper global-wrapper" :class="{ 'page-show': agentInfo.state }">
<JHeaderTitle title="代理商详情" :bgColor="headerBgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<image src="/static/iconImg/agent-bg-img .svg" class="bg-image" mode="scaleToFill" />
<view class="expand-header">
<image src="/static/iconImg/icon-agent-img.svg" mode="scaleToFill" />
<view class="expand-title">{{ agentInfo.agentName }}</view>
<view class="expand-phone">{{ agentInfo.agentNo }}</view>
<view class="expand-edit bgF bdR10" @tap="editAgent">
<image src="/static/iconImg/expand-edit.svg" mode="scaleToFill" />
编辑信息
</view>
</view>
<JMainCard pd="0" bgColor="rgba(0,0,0,0.1)">
<JInput name="代理商全称" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.agentName }}</text></JInput
>
<JInput name="代理商简称" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.agentShortName }}</text></JInput
>
<JInput name="代理商号" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.agentNo }}</text></JInput
>
<JInput name="联系人姓名" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.contactName }}</text></JInput
>
<JInput name="联系人手机号" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.contactTel }}</text></JInput
>
<JInput name="联系人邮箱" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.contactEmail }}</text></JInput
>
<JInput name="创建时间" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ agentInfo.createdAt?.split("-").join("/") }}</text></JInput
>
<JInput name="代理商状态" pd="0 40rpx 30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<view v-if="agentInfo.state == 1 || agentInfo.state == 0" class="dis-wrapper">
<text v-if="agentInfo.state == 1">启用</text>
<text v-else>禁用</text>
<switch
:checked="agentInfo.state == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
@change="change"
/>
</view>
<view class="agent-tips" v-else
>{{ tipsList[agentInfo.state]?.text }}
<text class="tips-color" :style="{ backgroundColor: tipsList[agentInfo.state]?.bgColor }"></text>
</view>
</JInput>
</JMainCard>
<template v-if="agentInfo.state == 1 || agentInfo.state == 0">
<view class="page-title">经营统计</view>
<JMainCard pd="0" wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.1)">
<ScreenTitle bdR="20rpx 20rpx 0 0" @search="searchTime" :index="index" />
<view class="mch-info">
<view class="mch-many">
<text>收款金额</text>
{{ (orderCount.payAmount / 100).toFixed(2) }}
</view>
<view class="mch-footer payCount">
<view>
<text>收款笔数</text>
{{ orderCount.payCount }}
</view>
</view>
<view class="mch-footer">
<view>
<text>退款金额</text>
{{ (orderCount.refundAmount / 100).toFixed(2) }}
</view>
<view>
<text>退款笔数</text>
{{ orderCount.refundCount }}
</view>
</view>
</view>
</JMainCard>
<JMainCard pd="8rpx" wrapPd="30rpx 50rpx " bgColor="rgba(0,0,0,0.1)">
<view class="mch-info">
<view class="mch-footer">
<view>
<text>商户总数</text>
{{ orderCount.mchAllCount }}
</view>
<view>
<text>新增商户数</text>
{{ orderCount.refundCount }}
</view>
</view>
</view>
</JMainCard>
</template>
<JButton color="#FF4D6A" bgColor="rgba(255,255,255,0.85)" size="medium" pdTop="0" @HandleTouch="deletedTips.open()"
>删除代理商</JButton
>
</view>
<JDeletedTips ref="deletedTips" @confirm="deleted" />
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancel" />
</template>
<script setup>
import { reactive, ref } from "vue"
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app"
import { formatData } from "@/hooks/formatData"
import { $findAgent, $getStatic, $editAgent, $delAgent } from "@/http/apiManager.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
import ScreenTitle from "@/components/newComponents/ScreenTitle/ScreenTitle"
onLoad((option) => {
params.agentNo = option.agentNo
})
onShow(() => {
getAgentInfo()
})
const tipsList = reactive([
{},
{},
{
text: "认证中",
bgColor: "#FFCA80",
},
{
text: "认证驳回",
bgColor: "#FF4D6A",
},
{
text: "待认证",
bgColor: "rgba(255, 255, 255, 0.3)",
},
])
const switchTips = ref(null)
const agentInfo = ref({})
const orderCount = ref({})
const index = ref(0)
const params = {
queryDateRange: "",
countType: 3,
agentNo: "",
}
const deletedTips = ref(null)
const deleted = () => {
$delAgent(params.agentNo).then((res) => {
uni.showToast({
title: "删除成功",
icon: "success",
})
uni.navigateBack()
})
}
const getAgentInfo = () => {
getStatic()
$findAgent(params.agentNo).then(({ bizData }) => {
formatData(bizData)
agentInfo.value = bizData
})
}
const getStatic = (data) => {
$getStatic(params).then(({ bizData }) => {
orderCount.value = bizData.orderCount
orderCount.value.mchAllCount = bizData.mchCount.mchAllCount
orderCount.value.mchOnNetCount = bizData.mchCount.mchOnNetCount
})
}
const searchTime = (data) => {
index.value = data.i
if (data.val.value != "customer") {
params.queryDateRange = data?.val.value
getStatic()
}
}
let flag = undefined
const change = (e) => {
flag = true
agentInfo.value.state = e.detail.value ? 1 : 0
switchTips.value.open("确认修改吗?")
}
const confirm = () => {
flag = false
$editAgent(agentInfo.value.agentNo, { state: agentInfo.value.state }).then(() => {
uni.showToast({
title: "修改成功",
icon: "success",
})
})
}
const cancel = (val) => {
if (!flag) return
agentInfo.value.state = Number(!agentInfo.value.state)
}
function editAgent() {
uni.navigateTo({
url: "./editAgent?agentNo=" + params.agentNo,
})
}
const headerBgColor = ref("transparent")
onPageScroll((data) => {
if (data.scrollTop > 20) {
headerBgColor.value = "$primaryColor"
} else {
headerBgColor.value = "transparent"
}
})
</script>
<style lang="scss" scoped>
.page-wrapper {
position: relative;
background-color: $primaryColor;
opacity: 0;
text {
color: #fff;
}
.bg-image {
position: absolute;
top: -40rpx;
right: 0;
width: 100%;
height: 650rpx;
}
.expand-header {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50rpx;
image {
width: 93rpx;
height: 93rpx;
}
.expand-title {
width: 500rpx;
margin: 20rpx auto 0;
word-break: break-all;
text-align: center;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
.expand-phone {
margin: 30rpx 0;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
}
.expand-edit {
position: relative;
z-index: 30;
padding: 20rpx 41rpx;
font-size: 28rpx;
color: $primaryColor;
image {
width: 26.25rpx;
height: 26.25rpx;
}
}
}
.right-color {
color: #fff;
font-size: 30rpx;
}
.title-name {
display: block;
width: 400rpx;
}
.page-title {
padding-bottom: 30rpx;
text-align: center;
font-size: 33rpx;
color: #fff;
}
.mch-info {
padding: 60rpx;
view {
display: flex;
flex-direction: column;
}
text {
margin-bottom: 20rpx;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
font-weight: 500;
}
.mch-many {
color: #fff;
font-size: 56rpx;
font-weight: 700;
}
.mch-footer {
display: flex;
flex-direction: row;
view {
flex: 1;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
}
.payCount {
margin: 48rpx 0;
}
}
}
.agent-tips {
font-size: 30rpx;
color: #fff;
.tips-color {
display: inline-block;
width: 35rpx;
height: 35rpx;
margin-left: 10rpx;
vertical-align: sub;
border-radius: 50%;
background-color: #ffca80;
}
}
.page-show {
opacity: 1;
transition: opacity 0.3s linear;
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<view class="store-wrapper global-wrapper">
<view class="mch-header">
<JHeaderTitle title="代理商管理" bgColor="#f2f2f2" />
<JSearchInput
@search="searchList"
@resetSearch="searchList"
ref="search"
place="搜索代理商名称、代理商号、手机号"
>
</JSearchInput>
</view>
<block v-for="v in useDataResult.dataList" :key="v.agentNo">
<JPreview
:title="v.agentName"
:qrcId="v.agentNo"
:img="imgList[v.state == 1 ? 1 : 0]"
:spot="tipsList[v.state].bgColor"
:status="tipsList[v.state].text"
:isLast="useDataResult.dataList.length - 1 == i"
@tap="toDetail(v.agentNo)"
></JPreview>
</block>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
<view class="button-block"></view>
<view class="mch-footers">
<JButton pd="30rpx 30rpx 50rpx 30rpx" pdTop="0" @HandleTouch="toPage">创建代理商</JButton>
</view>
</view>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from "vue"
import { onBackPress, onShow } from "@dcloudio/uni-app"
import { $getAgentList, $editAgent } from "@/http/apiManager.js"
import useGetList from "@/hooks/useList.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" //自定义导航栏
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue" //自定义搜索框
import JButton from "@/components/newComponents/JButton/JButton.vue" //自定义按钮
import JPreview from "@/components/newComponents/JPreview/JPreview.vue" //列表展示
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull" //最后一条数据提示
const { useDataResult, getList } = useGetList({
requestFun: $getAgentList,
})
// 图片列表
const imgList = reactive(["/static/navImg/disable-dailishang.svg", "/static/navImg/nav-dailishang.svg"])
const tipsList = reactive([
{ text: "已禁用", bgColor: "#B2B2B2" },
{ text: "已启用", bgColor: "#7737FE" },
{ text: "认证中", bgColor: "#FFCA80" },
{ text: "认证驳回", bgColor: "#FF4D6A" },
{ text: "待认证", bgColor: "rgba(255, 255, 255, 0.3)" },
])
// 返回前清除搜索数据
const search = ref()
onBackPress(() => {
if (search.value.searchText != "") {
search.value.searchText = ""
list(search.value.searchText)
return true
} else {
return false
}
})
// 搜索回调
const searchList = (data) => {
if (data === "reset") data = ""
getList({ unionAgentInfo: data })
}
// 详情
const toDetail = (agentNo) => {
uni.navigateTo({
url: "./agentDetail?agentNo=" + agentNo,
})
}
// 跳转 添加代理商
const toPage = () => {
uni.navigateTo({
url: "./addAgent",
})
}
</script>
<style lang="scss" scoped>
.store-wrapper {
width: 100%;
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.button-block {
height: 210rpx;
}
.mch-footers {
position: fixed;
left: 0;
right: 0;
bottom: 0;
backdrop-filter: blur(30px);
border-top: 1px solid rgba($color: #000000, $alpha: 0.1);
}
}
</style>

View File

@@ -0,0 +1,124 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle title="编辑代理商信息" bgColor="#f2f2f2" />
<JMainCard pd="0" wrapPd="30rpx">
<JInput
v-model:value="agentInfo.agentName"
name="代理商全称"
place="请输入代理商全称"
:rules="{ name: 'agentName', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="agentInfo.agentShortName"
name="代理商简称"
place="请输入代理商简称"
:rules="{ name: 'agentShortName', rule: 'REG_NotNUll' }"
></JInput>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="0">
<JInput
v-model:value="agentInfo.contactName"
name="联系人姓名"
place="请输入联系人姓名"
:rules="{ name: 'contactName', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="agentInfo.contactTel"
name="联系人手机号"
place="请输入联系人手机号"
:rules="{ name: 'contactTel', rule: 'REG_NotNUll' }"
></JInput>
<JInput v-model:value="agentInfo.contactEmail" name="联系人邮箱" place="请输入联系人邮箱"></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx">
<JInput v-model:value="agentInfo.remark" name="备注" place="请输入备注" :isBorder="true"></JInput>
</JMainCard>
<JButton size="max" pd="30rpx" @HandleTouch="saveAgent" pdTop="0">保存</JButton>
</view>
</template>
<script setup>
import { ref, reactive, nextTick } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import { $editAgent, $findAgent } from "@/http/apiManager.js"
import { validateArray } from "@/hooks/rules" //校验函数
onLoad((options) => {
if (options.agentNo) return getInfo(options.agentNo)
})
const agentInfo = ref({})
const getInfo = (val) => {
$findAgent(val).then(({ bizData }) => {
agentInfo.value = bizData
})
}
const saveAgent = () => {
if (validateArray(agentInfo.value)) {
$editAgent(agentInfo.value.agentNo, agentInfo.value).then((res) => {
uni.showToast({
title: "保存成功",
icon: "success",
})
uni.navigateBack()
})
}
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.place-text {
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 33rpx;
color: #a6a6a6;
image {
width: 40rpx;
height: 40rpx;
transform: translateX(20rpx);
}
}
.selected-text {
color: #000;
}
}
.team-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
}
view {
display: flex;
align-items: center;
image {
width: 93rpx;
height: 93rpx;
margin-right: 15rpx;
}
view {
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 10rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
}
}
</style>

View File

@@ -0,0 +1,218 @@
<template>
<view class="page-wrapper">
<JHeaderTitle title="应用详情页" :bgColor="vdata.headerBgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<image class="header-bg-img" src="/pageWork/static/images/app-bg-img.svg" mode="scaleToFill" />
<view class="header-card">
<image src="/pageWork/static/images/icon-app-white.svg" mode="scaleToFill" />
<view class="app-name">{{ appInfo.appName }}</view>
<view class="app-no">{{ appInfo.appId }}</view>
<view class="app-edit" @tap="toEdit(appInfo.appName, appInfo.appId)">
<image src="/static/iconImg/expand-edit.svg" mode="scaleToFill" />
编辑信息
</view>
</view>
<view class="app-info">
<view class="app-item">
<view class="title">应用名称</view>
<view class="info app-list-name single-text-beyond">{{ appInfo.appName }}</view>
</view>
<view class="app-item">
<view class="title">AppId</view>
<view class="info">{{ appInfo.appId }}</view>
</view>
<view class="app-item">
<view class="title">是否默认</view>
<view class="info">{{ appInfo.defaultFlag == 1 ? '是' : '否' }}</view>
</view>
<view class="app-item">
<view class="title">应用状态</view>
<view class="info">
<switch :checked="appInfo.state == 1" style="margin: 0; transform: scale(1.2); padding: 0" color="#BF80FF" @change="stateChange" />
</view>
</view>
</view>
<view class="app-button" @tap="toPayChannel(appInfo.appId)"> 支付渠道配置 </view>
</view>
<JPopupCard ref="refPay" />
<jeepayConfirm ref="refConfirm" />
</template>
<script setup>
import { reactive, ref } from 'vue'
import { onLoad, onPageScroll, onUnload } from '@dcloudio/uni-app'
import { $getAppDetails, $savePayConfig, $editApp } from '@/http/apiManager.js'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle'
import JPopupCard from './components/JPopupCard.vue'
onLoad((options) => {
getDetails(options.appId)
uni.$on('upDateAppDetails', () => {
getDetails(appInfo.appId)
uni.$emit('upDateList')
})
})
const vdata = reactive({
headerBgColor: 'transparent',
})
const refConfirm = ref(null)
const appInfo = reactive({})
const refPay = ref(null)
// 获取详情
const getDetails = (appId) => {
$getAppDetails(appId).then(({ bizData }) => {
Object.assign(appInfo, bizData)
})
}
// 支付渠道配置页面
const toPayChannel = (appId) => uni.navigateTo({ url: '/pageWork/appManage/payChannel?appId=' + appId })
// 编辑应用页面
const toEdit = (name, appId) => {
uni.navigateTo({
url: `/pageWork/appManage/editAdd?appName=${name}&appId=${appId}`,
})
}
// 保存支付渠道配置
const saveConfig = (data) => {
$savePayConfig(data).then((res) => {
uni.showToast({
title: '保存成功',
icon: 'success|none',
mask: true,
})
})
}
const stateChange = (e) => {
appInfo.state = Number(e.detail.value)
refConfirm.value.comfirmOpen(
() => {
$editApp({
appId: appInfo.appId,
state: appInfo.state,
}).then((res) => {
uni.showToast({
title: '修改成功',
icon: 'success|none',
mask: true,
})
uni.$emit('upDateList')
})
},
'确认修改状态吗?',
() => {
appInfo.state = Number(!e.detail.value)
}
)
}
onPageScroll((data) => {
if (data.scrollTop > 20) {
vdata.headerBgColor = '$primaryColor'
} else {
vdata.headerBgColor = 'transparent'
}
})
// 页面卸载移除事件侦听
onUnload(() => {
uni.$off(['upDateAppDetails'])
})
</script>
<style lang="scss" scoped>
.page-wrapper {
position: relative;
background-color: $primaryColor;
min-height: 100vh;
.header-bg-img {
position: absolute;
top: 0;
right: 0;
left: 50;
width: 100%;
height: 600rpx;
}
.header-card {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 75rpx;
image {
width: 93rpx;
height: 93rpx;
}
.app-name {
margin: 20rpx 0 15rpx 0;
width: 500rpx;
text-align: center;
font-size: 33rpx;
font-weight: 500;
color: #fff;
}
.app-no {
color: rgba(255, 255, 255, 0.6);
font-size: 26rpx;
font-weight: 500;
}
.app-edit {
position: relative;
z-index: 40;
display: flex;
justify-content: center;
align-items: center;
margin-top: 30rpx;
width: 236rpx;
height: 90rpx;
border-radius: 10rpx;
font-size: 28rpx;
font-weight: 500;
color: $primaryColor;
background-color: #fff;
image {
margin-right: 10rpx;
width: 26rpx;
height: 26rpx;
}
}
}
.app-info {
margin: 50rpx 50rpx 35rpx 50rpx;
padding: 10rpx 0;
height: 338rpx;
border-radius: 20rpx;
background: rgba(0, 0, 0, 0.1);
.app-item {
display: flex;
justify-content: space-between;
margin: 30rpx 0;
padding: 0 40rpx;
font-size: 30rpx;
font-weight: 500;
.title {
white-space: nowrap;
color: rgba(255, 255, 255, 0.6);
}
.info {
flex: 1;
text-align: right;
color: #fff;
}
}
}
.app-button {
display: flex;
justify-content: center;
align-items: center;
margin: 0 50rpx;
height: 110rpx;
border-radius: 20rpx;
font-size: 33rpx;
font-weight: 500;
color: $primaryColor;
background-color: #fff;
}
}
.app-list-name {
width: 440rpx;
margin-left: 15rpx;
}
</style>

View File

@@ -0,0 +1,107 @@
<template>
<view class="page-wrapper">
<view class="search-header">
<JSearchInput place="搜索应用名称、应用AppId、用户号、用户名称" @search="searchApp" @resetSearch="resetSearch" />
</view>
<template v-for="v in appList" :key="v.appId">
<appCard v-bind="v" @tap="toDetails(v.appId)" />
</template>
<jeepayListNull :isShow="!hasNext" :list="[]" />
<view class="select-footer">
<JButton pd="30rpx 30rpx 50rpx 30rpx" @HandleTouch="toCreated">创建应用</JButton>
</view>
</view>
</template>
<script setup>
import { onLoad, onUnload, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue' //自定义搜索框
import { $getAppList } from '@/http/apiManager.js'
import appCard from './components/appCard.vue'
import JButton from '@/components/newComponents/JButton/JButton'
import { reactive } from 'vue'
const appList = reactive([])
const params = {
pageNumber: 1,
pageSize: 10,
}
// 是否有下一页
let hasNext = undefined
const getList = () => {
$getAppList(params).then(({ bizData }) => {
hasNext = bizData.hasNext
appList.push(...bizData.records)
uni.stopPullDownRefresh()
})
}
const toDetails = (appId) => {
uni.navigateTo({
url: '/pageWork/appManage/appDetails?appId=' + appId,
success: () => {},
})
}
// 搜索
const searchApp = (val) => {
params.unionSearchId = val
params.pageNumber = 1
appList.length = 0
getList()
}
// 重置搜索
const resetSearch = () => {
params.unionSearchId = ''
params.pageNumber = 1
appList.length = 0
getList()
}
onPullDownRefresh(() => {
params.pageNumber = 1
appList.length = 0
getList()
})
onLoad(() => {
getList()
uni.$on('upDateList', () => {
params.pageNumber = 1
appList.length = 0
console.log('appList', appList)
getList()
})
})
// 去创建应用页面
const toCreated = () => {
uni.navigateTo({
url: '/pageWork/appManage/createdAppId',
})
}
// 页面卸载移除事件侦听
onUnload(() => {
uni.$off(['upDateList'])
})
onReachBottom(() => {
if (!hasNext) return
params.pageNumber++
getList()
})
</script>
<style lang="scss" scoped>
.page-wrapper {
background-color: #f7f7f7;
min-height: calc(100vh - 88rpx);
}
.search-header {
position: sticky;
top: 0;
right: 0;
left: 0;
z-index: 10;
background-color: #f7f7f7;
}
.select-footer {
position: fixed;
right: 0;
left: 0;
bottom: 0;
}
</style>

View File

@@ -0,0 +1,134 @@
<template>
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" :safe-area="false">
<!-- 通用弹窗 -->
<view class="card-wrapper">
<view class="card-title disFlexCenter">选择支付渠道</view>
<view class="card-main">
<block v-for="v in payConfigList" :key="v.ifCode">
<payCard :ifName="v.ifName" :paywayFee="v.paywayFee" :bgColor="v.bgColor" :icon="v.icon">
<template #right>
<view class="state"> <switch :checked="v.configState == 1" style="margin: 0; transform: scale(1.2)" color="#7737fe" @change="stateChange($event, v)" /> </view>
</template>
</payCard>
</block>
</view>
</view>
</uni-popup>
<jeepayConfirm ref="refConfirm" />
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { $getPayChannelList, $savePayConfig } from '@/http/apiManager.js'
import payCard from './payCard.vue'
const emits = defineEmits(['upDataList'])
// 支付应用的列表
const payConfigList = reactive([])
const refConfirm = ref(null)
const popup = ref(null)
const params = {
appId: undefined,
wayCode: undefined,
}
let index = undefined
const open = (appId, wayCode, i) => {
index = i
params.appId = appId
params.wayCode = wayCode
getConfigList(appId, wayCode)
}
const stateChange = (e, val) => {
val.configState = Number(e.detail.value)
refConfirm.value.comfirmOpen(
() => {
$savePayConfig({
appId: params.appId,
wayCode: params.wayCode,
ifCode: val.ifCode,
state: val.configState,
}).then((res) => {
uni.showToast({
title: '保存成功',
icon: 'success|none',
mask: true,
})
getConfigList(params.appId, params.wayCode, true)
emits('upDataList', { index, state: val.configState })
})
},
`${val.configState == 1 ? '确认启用该通道?开启后将会将其他通道关闭' : '确认关闭该渠道?'}`,
() => {
val.configState = Number(!e.detail.value)
}
)
}
// 获取可配置渠道
const getConfigList = (appId, wayCode, ifOpen) => {
$getPayChannelList(appId, wayCode).then(({ bizData }) => {
if (bizData.records.length != 0) {
payConfigList.length = 0
Object.assign(payConfigList, bizData.records)
if (ifOpen) return
popup.value.open()
} else {
uni.showToast({ title: '暂无可配置渠道', icon: 'none' })
}
})
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.card-wrapper {
max-height: 70vh;
border-radius: 32rpx 32rpx 0 0;
background-color: #fff;
.card-main {
height: calc(70vh - 110rpx - 170rpx);
padding-bottom: 60rpx;
overflow-y: auto;
}
.card-title {
margin-bottom: 10rpx;
height: 110rpx;
font-size: 30rpx;
font-weight: 400;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.07);
}
.card-button {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30rpx;
height: 170rpx;
border-top: 1rpx solid #ededed;
button {
flex: 1;
height: 110rpx;
border-radius: 20rpx;
font-size: 33rpx;
font-weight: 500;
&::after {
border: none;
}
}
.cancel {
margin-right: 30rpx;
color: rgba(0, 0, 0, 0.5);
background-color: #f7f7f7;
}
.confirm {
color: #fff;
background: linear-gradient(270deg, rgba(35, 143, 252, 1) 0%, rgba(26, 102, 255, 1) 100%);
}
}
}
.disFlexCenter {
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -0,0 +1,114 @@
<template>
<view class="card-wrapper" :style="{ '--state-bg-color': state == 1 ? '#7737FE' : '#B3B3B3' }">
<view class="app-header">
<image src="/static/navImg/icon-app.svg" mode="scaleToFill" />
<view class="app-info">
<view class="app-title">
<view class="app-name single-text-beyond">{{ appName }}</view>
<view class="app-state">{{ state == 1 ? '已启用' : '已禁用' }}</view>
</view>
<view class="sub-title">{{ appId }}</view>
</view>
</view>
<view class="mch-info">
<view class="left">
<image src="/pageWork/static/images/icon-mch-black.svg" mode="scaleToFill" />
<view class="mch-title"> {{ mchName }} </view>
</view>
<view class="right"> {{ mchNo }}</view>
</view>
</view>
</template>
<script setup>
const props = defineProps({
appName: { type: String }, //应用名称
mchNo: { type: String }, // 用户号
state: [String, Number], //状态
appId: { type: String }, //应用id
mchName: { type: String }, // 用户名称
})
</script>
<style lang="scss" scoped>
.card-wrapper {
padding: 0.1rpx 30rpx;
height: 257rpx;
background-color: #fff;
border-bottom: 1rpx solid #ededed;
.app-header {
display: flex;
margin-top: 30rpx;
height: 92rpx;
image {
margin-right: 20rpx;
width: 92rpx;
height: 92rpx;
}
.app-info {
flex: 1;
.app-title {
display: flex;
justify-content: space-between;
font-size: 30rpx;
font-weight: 400;
text {
font-size: 33rpx;
font-weight: 500;
}
}
.app-name{
width: 440rpx;
}
.app-state {
display: flex;
align-items: center;
white-space: nowrap;
font-size: 30rpx;
color: #666;
&::before {
content: '';
display: block;
margin-right: 15rpx;
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background-color: var(--state-bg-color);
}
}
}
.sub-title {
margin-top: 15rpx;
font-size: 26rpx;
font-weight: 400;
color: #808080;
}
}
.mch-info {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx;
margin-top: 20rpx;
height: 80rpx;
background-color: #f7f7f7;
border-radius: 10rpx;
font-size: 29rpx;
.left {
display: flex;
align-items: center;
image {
margin-right: 10rpx;
width: 40rpx;
height: 40rpx;
}
.mch-title {
width: 232rpx;
}
}
.right {
color: #8c8c8c;
}
}
}
</style>

View File

@@ -0,0 +1,73 @@
<template>
<view class="pay-wrapper">
<view class="pay-info">
<view class="pay-logo disFlexCenter" :style="{ backgroundColor: bgColor }">
<image :src="icon" mode="scaleToFill" />
</view>
<view class="info-main">
<view class="pay-title">
<text>{{ ifName }}</text>
<slot name="right" />
</view>
<view class="pay-rate">单笔费率{{ paywayFee.feeRate * 100 }}%</view>
</view>
</view>
</view>
</template>
<script setup>
const props = defineProps({
ifName: { typ: String }, //通道标题
bgColor: { type: String }, //logo 背景颜色
icon: { type: String }, // logo地址
paywayFee: { type: Object, default: () => ({}) }, //费率
})
</script>
<style lang="scss" scoped>
.pay-wrapper {
display: flex;
align-items: center;
padding: 0 40rpx;
height: 170rpx;
.pay-info {
flex: 1;
display: flex;
.pay-logo {
margin-right: 20rpx;
width: 90rpx;
height: 90rpx;
border-radius: 20rpx;
background-color: #07112d;
image {
width: 50rpx;
height: 50rpx;
}
}
.info-main {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.pay-title {
display: flex;
justify-content: space-between;
font-size: 30rpx;
font-weight: 400;
}
.pay-rate {
margin-top: 15rpx;
font-size: 26rpx;
font-weight: 400;
color: #999;
}
}
}
.disFlexCenter {
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@@ -0,0 +1,171 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<view class="select-title">商户</view>
<JMainCard pd="0" wrapPd="30rpx">
<view class="select-wrapper" @tap="jumpPage('mch')">
<view class="select-mch" v-if="vdata.mchNo == undefined"> 请选择商户 </view>
<view class="mch-info" v-else>
<image src="/static/equipmentImg/mch-list.svg" mode="scaleToFill" />
<view>{{ vdata.mchName }} <text>{{ vdata.mchNo }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput name="应用名称" :isBorder="true" v-model:value="vdata.appName" place="请输入应用名称"></JInput>
<JInput name="备注" v-model:value="vdata.remark" place="请输入备注"></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput name="是否设置为默认应用" :isBorder="true">
<switch :checked="vdata.defaultFlag == 1 ? true : false" style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe" @change="switchState($event, 'defaultFlag')" />
</JInput>
<JInput name="状态">
<switch :checked="vdata.state == 1 ? true : false" style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe" @change="switchState($event, 'state')" />
</JInput>
</JMainCard>
<!-- <input placeholder="请输入" v-model="vdata.appName" /> -->
<JButton pd="30rpx 30rpx 50rpx 30rpx" @HandleTouch="submit">确认创建</JButton>
</view>
</template>
<script setup>
import { reactive } from 'vue'
import { onShow, onLoad, onUnload } from '@dcloudio/uni-app'
import { $addApp } from '@/http/apiManager.js'
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue'
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from '@/components/newComponents/JButton/JButton'
import useStore from '@/hooks/useStore.js'
const { getStore, clearItem } = useStore()
onShow(() => {
if (getStore('mch') && getStore('mch').mchNo && getStore('mch').mchNo !== vdata.mchNo) {
delete getStore('mch').remark
Object.assign(vdata, getStore('mch'))
}
})
const vdata = reactive({
appName: '',
state: 1,
defaultFlag: 1,
})
function randomKey (randomFlag, min, max) { // 生成随机128位私钥
let str = ''
let range = min
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
// 随机产生
if (randomFlag) {
range = Math.round(Math.random() * (max - min)) + min
}
for (var i = 0; i < range; i++) {
var pos = Math.round(Math.random() * (arr.length - 1))
str += arr[pos]
}
return str
}
const switchState = (e, v) => {
vdata[v] = e.detail.value ? 1 : 0
}
const jumpPage = (val) => {
uni.navigateTo({
url: `/pageWork/SelectedList/SelectedList?title=${val}&selected=${vdata.mchNo}`,
})
}
const submit = () => {
const params = {
appSignType: 'MD5',
mchNo: vdata.mchNo,
appName: vdata.appName,
appSecret: randomKey(false, 128, 0),
defaultFlag: vdata.defaultFlag,
state: vdata.state,
}
console.log(params);
$addApp(params).then(r => {
uni.showToast({
title: '创建成功',
icon: 'none',
duration: 2000,
success: () => {
uni.$emit('upDateList')
uni.navigateBack()
},
})
})
}
onUnload(() => {
clearItem('mch')
})
</script>
<style lang="scss" scoped>
.page-wrapper {
padding: .1rpx;
box-sizing: border-box;
}
.select-title {
margin-top: 30rpx;
margin-left: 50rpx;
font-size: 33rpx;
}
.select-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
.select-mch {
margin: 20rpx;
}
.mch-info {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 10rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 15rpx;
color: #8c8c8c;
font-size: 25rpx;
font-weight: 500;
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
image {
width: 60rpx;
height: 66rpx;
}
}
}
</style>

View File

@@ -0,0 +1,45 @@
<template>
<view class="page-wrapper">
<JMainCard wrapPd="0 30rpx" pd="0">
<JInput v-model:value="appInfo.appName" name="应用名称" place="请输入应用名称" :isBorder="true"></JInput>
</JMainCard>
<JButton pd="30rpx" @HandleTouch="saveApp" pdTop="30rpx">保存</JButton>
</view>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { $editApp } from '@/http/apiManager.js'
import JMainCard from '@/components/newComponents/JMainCard/JMainCard'
import JInput from '@/components/newComponents/JInput/JInput'
import JButton from '@/components/newComponents/JButton/JButton'
onLoad((options) => {
appInfo.appName = options.appName
appInfo.appId = options.appId
})
const appInfo = reactive({
appName: '',
})
// 保存App
const saveApp = () => {
$editApp(appInfo).then((res) => {
// 修改成功 通知 详情页面更新
uni.$emit('upDateAppDetails')
uni.navigateBack({
success: () => {
uni.showToast({
title: '保存成功',
})
},
})
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
min-height: calc(100vh - 88rpx);
background-color: #f7f7f7;
}
</style>

View File

@@ -0,0 +1,127 @@
<template>
<view class="page-wrapper">
<view class="page-header">
<JHeaderTitle title="应用支付配置" bgColor="#f7f7f7" />
<JSearchInput place="搜索应用支付方式代码、名称" @search="searchChannel" @resetSearch="resetSearch" />
</view>
<block v-for="(v, i) in configList" key="v.wayType">
<view class="pay-wrapper" @tap="refPay.open(params.appId, v.wayCode, i)">
<view class="title">
<view class="name">{{ v.wayName }}</view>
<view class="state" :class="{ 'no-config': v.isConfig == 0 }">{{ v.isConfig == 1 ? '已配置' : '未配置' }}</view>
</view>
<view class="sub-title">{{ v.wayCode }}</view>
</view>
</block>
<jeepayListNull :isShow="!hasNext" :list="[]" />
</view>
<JPopupCard ref="refPay" @upDataList="upDataList" />
</template>
<script setup>
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'
import { reactive, ref } from 'vue'
import { $getPayConfig, $getPayChannelList } from '@/http/apiManager.js'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue' //自定义搜索框
import JPopupCard from './components/JPopupCard.vue'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle'
onLoad((options) => {
params.appId = options.appId
getPayList()
})
const refPay = ref(null)
const configList = reactive([])
const params = {
pageSize: 10,
pageNumber: 1,
}
// 是否有下一页
let hasNext = undefined
const getPayList = () => {
$getPayConfig(params).then(({ bizData }) => {
hasNext = bizData.hasNext
configList.push(...bizData.records)
uni.stopPullDownRefresh()
})
}
// 更新列表
const upDataList = (val) => {
configList[val.index].isConfig = val.state
}
// 搜索
const searchChannel = (val) => {
configList.length = 0
params.pageNumber = 1
params.unionSearchId = val
getPayList()
}
// 重置搜索
const resetSearch = () => {
configList.length = 0
params.pageNumber = 1
params.unionSearchId = ''
getPayList()
}
onPullDownRefresh(() => {
configList.length = 0
params.pageNumber = 1
getPayList()
})
onReachBottom(() => {
if (!hasNext) return
params.pageNumber++
getPayList()
})
</script>
<style lang="scss" scoped>
.page-wrapper {
min-height: calc(100vh - 80rpx);
background-color: #f7f7f7;
.page-header {
position: sticky;
top: 0;
left: 0;
right: 0;
background-color: #f7f7f7;
}
.pay-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 40rpx;
height: 170rpx;
background-color: #fff;
.title {
display: flex;
justify-content: space-between;
.name {
font-size: 30rpx;
}
.state {
display: flex;
align-items: center;
font-size: 30rpx;
color: #808080;
&::after {
content: '';
display: block;
margin-left: 20rpx;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #168fff;
}
}
.no-config::after {
background-color: #d9d9d9;
}
}
.sub-title {
margin-top: 16rpx;
font-size: 26rpx;
color: #999;
}
}
}
</style>

View File

@@ -0,0 +1,232 @@
<template>
<view class="e-card-wrapper" @tap="isOpen">
<view class="e-card-left">
<image :src="imgList[0]" mode="scaleToFill" />
<view class="expand-info">
{{ teamName }}
<text>成员数量{{ userList.length }}</text>
</view>
</view>
<view class="e-card-right">
<image src="/static/iconImg/top-arrow.svg" :class="{ rotate: flag }" mode="scaleToFill" />
</view>
</view>
<view class="expand-card-list" v-if="flag">
<view class="expand-card-main bdR20">
<view class="expand-main-left">
<view>
拓展商户总数
<text>{{ totalMchCount }}</text>
</view>
<view>
商户交易总额
<text>{{ totalOrderAmount }}</text>
</view>
</view>
<view class="expand-main-right" @tap="jumpPage">
<image src="/static/iconImg/edit-team.svg" mode="scaleToFill" />
编辑团队
</view>
</view>
<block v-for="v in userList" :key="v.sysUserId">
<view class="expand-team bdR20" @tap="detail(v.sysUserId)">
<view class="expand-team-top">
<view class="e-team-t-left">
<image :src="imgList[v.state ? 2 : 3]" mode="scaleToFill" />
<view>
{{ v.realname }}
<text>{{ v.telphone }}</text>
</view>
</view>
<view class="e-team-t-right" :class="{ isStateNone: !v.state }">
{{ v.state ? "已启用" : "已禁用" }}
</view>
</view>
<view class="expand-team-bottom">
<view
>拓展商户数 <text>{{ v.mchCount }}</text>
</view>
<view
>商户交易额 <text>{{ v.orderCount }}</text>
</view>
</view>
</view>
</block>
</view>
</template>
<script setup>
import { reactive, ref } from "vue"
const emits = defineEmits(["isOpen", "jumpPage", "detail"])
const props = defineProps({
teamName: { type: String },
flag: { type: Boolean },
state: { type: Number },
userList: { type: Array, default: [] },
totalMchCount: { type: Number },
totalOrderAmount: { type: Number },
teamId: { type: Number },
state: { type: Number },
})
const imgList = reactive([
"/static/iconImg/expand-fill.svg",
"/static/iconImg/expand-team-close.svg",
"/static/iconImg/expand-member.svg",
"/static/iconImg/expand-member-close.svg",
])
const isOpen = () => {
emits("isOpen")
}
const jumpPage = (val) => {
emits("jumpPage")
}
const detail = (val) => {
uni.navigateTo({ url: "/pageWork/developerManagement/developerDetail?id=" + val })
}
</script>
<style lang="scss" scoped>
.e-card-wrapper {
display: flex;
justify-content: space-between;
padding: 30rpx;
.e-card-left {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
}
.expand-info {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 12rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
}
.e-card-right {
display: flex;
image {
width: 40rpx;
height: 40rpx;
margin-left: 20rpx;
transform: rotate(180deg);
transition: 0.3s linear;
}
.rotate {
transform: rotate(0deg);
transition: 0.3s linear;
}
}
}
.expand-card-list {
padding: 0 30rpx;
padding-bottom: 30rpx;
.expand-card-main {
display: flex;
overflow: hidden;
background: rgba(81, 36, 178, 0.1);
.expand-main-left {
padding: 30rpx;
flex: 1;
view {
display: flex;
justify-content: space-between;
color: rgba(81, 36, 178, 0.7);
text {
color: #5124b2;
}
&:last-child {
margin-top: 20rpx;
}
}
}
.expand-main-right {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 30rpx;
font-size: 25rpx;
color: #ffffff;
background-color: #5124b3;
image {
width: 40rpx;
height: 40rpx;
margin-bottom: 20rpx;
}
}
}
.expand-team {
padding: 30rpx 0 30rpx 30rpx;
margin-top: 30rpx;
background: #f7f7f7;
.expand-team-top {
display: flex;
justify-content: space-between;
padding-bottom: 30rpx;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.1);
.e-team-t-left {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 30rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
color: #000000;
text {
margin-top: 15rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
}
.e-team-t-right {
margin-right: 30rpx;
font-size: 30rpx;
color: #666666;
&::before {
content: "";
display: inline-block;
vertical-align: middle;
width: 10rpx;
height: 10rpx;
margin-right: 10rpx;
border-radius: 50%;
background-color: $primaryColor;
}
}
.isStateNone::before {
background-color: #999 !important;
}
}
.expand-team-bottom {
margin-top: 30rpx;
view {
font-size: 28rpx;
color: #8c8c8c;
text {
margin-left: 30rpx;
color: #000000;
}
&:last-child {
margin-top: 25rpx;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,35 @@
<template>
<JPopup ref="popup">
<JMainCard wrapPd="0 30rpx" pd="0">
<block v-for="(v, i) in sexList" :key="i">
<JLine :name="v" :isSelect="index === i" @tap="selected(i)"></JLine>
</block>
</JMainCard>
<JButton pd="30rpx" pdTop="0" bgColor="rgba(255,255,255,0.8)" @HandleTouch="popup.close()" color="#000"
>取消</JButton
>
</JPopup>
</template>
<script setup>
import { reactive, ref } from "vue"
import JPopup from "@/components/newComponents/JPopup/JPopup"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JLine from "@/components/newComponents/JLine/JLine"
import JButton from "@/components/newComponents/JButton/JButton"
const sexList = reactive(["未知", "男", "女"])
const emits = defineEmits(["selected"])
const index = ref(undefined)
const popup = ref()
const open = (i) => {
index.value = i
popup.value.open()
}
const selected = (i) => {
emits("selected", i)
popup.value.close()
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,285 @@
<template>
<view class="page-wrapper">
<JHeaderTitle title="拓展员详情" :bgColor="headerBgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<image src="/static/iconImg/bg-tuozhanyuan.svg" class="bg-image" mode="scaleToFill" />
<view class="expand-header">
<image src="/static/iconImg/expand-img.svg" mode="scaleToFill" />
<view class="expand-title">{{ expandInfo.realname }}</view>
<view class="expand-phone">{{ expandInfo.telphone }}</view>
<view class="expand-edit bgF bdR10" @tap="jumpPage">
<image src="/static/iconImg/expand-edit.svg" mode="scaleToFill" />
编辑信息
</view>
</view>
<JMainCard pd="0" bgColor="rgba(0,0,0,0.1)">
<JInput name="拓展员姓名" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ expandInfo.realname }}</text></JInput
>
<JInput name="性别" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ expandInfo.sex == 1 ? "男" : expandInfo.sex == 2 ? "女" : "未知" }}</text></JInput
>
<JInput name="编号" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ expandInfo.userNo }}</text></JInput
>
<JInput name="所属团队" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ expandInfo.teamName }}</text></JInput
>
<JInput name="创建时间" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ expandInfo.createdAt }}</text></JInput
>
<JInput name="是否队长" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<view class="dis-wrapper">
<text v-if="expandInfo.isTeamLeader == 1"></text>
<text v-else></text>
<switch
:checked="expandInfo.isTeamLeader == 1 ? true : false"
@change="change($event, 'isTeamLeader')"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
/>
</view>
</JInput>
<JInput name="拓展员状态" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<view class="dis-wrapper">
<text v-if="expandInfo.state == 1">启用</text>
<text v-else>禁用</text>
<switch
:checked="expandInfo.state == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
@change="change($event, 'state')"
/>
</view>
</JInput>
</JMainCard>
<view class="page-title">数据统计</view>
<JMainCard pd="0" bgColor="rgba(0,0,0,0.1)" wrapPd="0 50rpx">
<ScreenTitle bdR="20rpx 20rpx 0 0" @search="screening" :index="index" />
<view class="mch-info">
<view class="mch-many">
<text>商户交易额</text>
{{ (mchInfo.payAmount / 100).toFixed(2) }}
</view>
<view class="mch-footer">
<view>
<text>新增商户数</text>
{{ mchInfo.mchOnNetCount }}
</view>
<view>
<text>新增入网商户数</text>
{{ mchInfo.mchOnNetNewCount }}
</view>
</view>
</view>
</JMainCard>
<JMainCard pd="0" bgColor="rgba(0,0,0,0.1)">
<view class="mch-info">
<view class="mch-many">
<text>商户交易总额</text>
{{ (mchInfo.payAllAmount / 100).toFixed(2) }}
</view>
<view class="mch-footer">
<view>
<text>商户总数</text>
{{ mchInfo.mchTodayAddCount }}
</view>
<view>
<text>入网商户总数</text>
{{ mchInfo.mchOnNetNewCount }}
</view>
</view>
</view>
</JMainCard>
<JButton
color="#FF4D6A"
bgColor="rgba(255,255,255,0.85)"
pd="0 50rpx 50rpx"
pdTop="0"
@HandleTouch="deletedTips.open()"
>删除拓展员</JButton
>
</view>
<JDeletedTips ref="deletedTips" @confirm="deleted" />
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancel" />
</template>
<script setup>
import { reactive, ref, onUnmounted } from "vue"
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app"
import { $devDetail, $editDev, $getDevDetail, $delSysUser } from "@/http/apiManager.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
import ScreenTitle from "@/components/newComponents/ScreenTitle/ScreenTitle"
onLoad((options) => {
console.log("options", options)
params.sysUserId = options.id
})
onShow(() => {
if (params.sysUserId) {
getInfo(params.sysUserId)
getDevDetail()
}
})
const expandInfo = ref({})
const mchInfo = ref({})
const deletedTips = ref(null)
const switchTips = ref(null)
const index = ref(0)
const params = {
queryDateRange: "",
}
const deleted = () => {
$delSysUser(expandInfo.value.sysUserId).then((res) => {
uni.showToast({
title: "删除成功",
icon: "success|none",
mask: true,
})
uni.navigateBack()
})
}
const getInfo = (val) => {
$devDetail(val).then(({ bizData }) => {
expandInfo.value = bizData
})
}
const screening = (data) => {
index.value = data.i
if (data.val.value != "customer") {
params.queryDateRange = data?.val.value
getDevDetail()
}
}
const getDevDetail = () => {
$getDevDetail(params).then((res) => {
mchInfo.value = res.bizData
})
}
let keys = null
const change = (e, val) => {
keys = val
expandInfo.value[val] = e.detail.value ? 1 : 0
switchTips.value.open("确认修改吗?")
}
const confirm = () => {
const data = {}
data[keys] = expandInfo.value[keys]
keys = null
$editDev(expandInfo.value.sysUserId, data).then(() => {
Object.assign(data, expandInfo.value)
uni.showToast({
title: "修改成功",
icon: "success",
})
})
}
const cancel = () => {
if (!keys) return
expandInfo.value[keys] = Number(!expandInfo.value[keys])
}
const jumpPage = () => {
uni.navigateTo({ url: "/pageWork/developerManagement/editDeveloper?id=" + expandInfo.value.sysUserId })
}
const headerBgColor = ref("transparent")
onPageScroll((data) => {
if (data.scrollTop > 20) {
headerBgColor.value = "$primaryColor"
} else {
headerBgColor.value = "transparent"
}
})
</script>
<style lang="scss" scoped>
.page-wrapper {
position: relative;
width: 100%;
min-height: 100%;
background-color: $primaryColor;
text {
color: #fff;
font-weight: 400;
}
.bg-image {
position: absolute;
top: -40rpx;
right: 0;
width: 100%;
height: 650rpx;
}
.expand-header {
display: flex;
flex-direction: column;
align-items: center;
image {
width: 93rpx;
height: 93rpx;
}
.expand-title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
.expand-phone {
margin: 30rpx 0;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
}
.expand-edit {
position: relative;
z-index: 30;
padding: 20rpx 41rpx;
font-size: 28rpx;
color: $primaryColor;
image {
width: 26.25rpx;
height: 26.25rpx;
}
}
}
.right-color {
color: #fff;
font-size: 30rpx;
}
.page-title {
margin-bottom: 30rpx;
text-align: center;
font-size: 33rpx;
color: #fff;
}
.mch-info {
border-top: 1rpx solid rgba(0, 0, 0, 0.1);
padding: 60rpx;
view {
display: flex;
flex-direction: column;
}
text {
margin-bottom: 20rpx;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
font-weight: 500;
}
.mch-many {
color: #fff;
font-size: 56rpx;
font-weight: 700;
}
.mch-footer {
display: flex;
flex-direction: row;
margin-top: 50rpx;
view {
flex: 1;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,203 @@
<template>
<div class="global-wrapper bgF2">
<view class="mch-header">
<JHeaderTitle bgColor="#f2f2f2" title="拓展员管理" />
<view class="search bgF2">
<JSearchInput place="搜索拓展员姓名、手机号" wrapPd="0 30rpx" ref="search" :isDisabled="true" @tap="toSearch" />
<view class="switch-title">
<view :class="{ 'active-title': titleFlag }" @tap="titleFlag = true">全部拓展员</view>
<view :class="{ 'active-title': !titleFlag }" @tap="titleFlag = false">按团队分组</view>
</view>
</view>
</view>
<view class="expand-wrapper bgF">
<template v-if="titleFlag">
<block v-for="v in useDataResult.dataList" :key="v.sysUserId">
<view class="page-main bgF" @tap="toDetails(v.sysUserId)">
<image :src="imgList[v.state ? 0 : 1]" />
<view class="page-left">
<view class="page-text">
{{ v.realname }}
<view class="text-but">
<text>{{ v.telphone }}</text>
<!-- <text class="team-name single-text-beyond">团队名称</text> -->
</view>
</view>
</view>
<view class="state-flag" :class="{ 'state-active': v.state == 1, 'state-none': v.state == 0 }">{{
v.state == 1 ? "已启用" : "已禁用"
}}</view>
</view>
</block>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
</template>
<template v-else>
<block v-for="v in dataList.dataList" :key="v.teamId">
<ExpandCard
v-bind="v"
@isOpen="v.flag = !v.flag"
@jumpPage="jumpPage('/pageWork/developerManagement/newTeam', v)"
/>
</block>
<jeepayListNull :isShow="true" :list="dataList.dataList.length" />
</template>
</view>
<view class="add-block"></view>
<view class="add-wrapper ButtonBor bgF2">
<view class="add-expand">
<view @tap="jumpPage('/pageWork/developerManagement/newTeam')">创建团队</view>
<view @tap="jumpPage('/pageWork/developerManagement/newDeveloper')">创建拓展员</view>
</view>
</view>
</div>
</template>
<script setup>
import { reactive, ref, onUnmounted } from "vue"
import { onBackPress } from "@dcloudio/uni-app"
import { $getTeams, $getDev } from "@/http/apiManager.js"
import useStore from "@/hooks/useStore.js"
import useGetList from "@/hooks/useList.js"
const { setStore } = useStore()
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull" //最后一条数据提示
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput"
import ExpandCard from "./components/ExpandCard"
const imgList = reactive(["/static/iconImg/expand-member.svg", "/static/iconImg/expand-member-close.svg"])
const titleFlag = ref(true)
const { useDataResult, getList } = useGetList({
requestFun: $getDev,
params: {
userType: 3,
},
})
const { useDataResult: dataList } = useGetList({
requestFun: $getTeams,
})
const list = ref([])
const params = {}
const searchList = (data) => {
params.queryNameOrPhone = data == "reset" ? "" : data
getList(params)
}
const jumpPage = (url, val) => {
setStore("teamInfo", val)
uni.navigateTo({ url })
}
const toSearch = () => {
uni.navigateTo({ url: `/pageWork/SelectedList/SelectedList?title=expand&search=${JSON.stringify({ userType: 3 })}` })
}
const toDetails = (sysUserId) => {
uni.navigateTo({ url: `/pageWork/developerManagement/developerDetail?id=${sysUserId}` })
}
// 获取搜索组件暴露出来的数据
const search = ref()
onBackPress(() => {
if (search.value.searchText != "") {
search.value.searchText = ""
list(search.value.searchText)
return true
} else {
return false
}
})
</script>
<style lang="scss" scoped>
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.add-block {
height: 220rpx;
}
.add-wrapper {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 30rpx 30rpx 55rpx 30rpx;
.add-expand {
display: flex;
text-align: center;
color: #fff;
border-radius: 20rpx;
overflow: hidden;
background: #5124b2;
view {
flex: 1;
padding: 32rpx;
&:last-child {
border-radius: 20rpx;
background: #7737fe;
}
}
}
}
.switch-title {
display: flex;
justify-content: space-around;
align-items: center;
height: 100rpx;
.active-title {
color: $primaryColor;
font-weight: 700;
}
view {
color: #a6a6a6;
}
}
.page-main {
display: flex;
align-items: center;
padding-left: 30rpx;
image {
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
}
.page-left {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-bottom: 1rpx solid #f9f9f9;
.page-text {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
.text-but {
text {
margin-top: 15rpx;
font-size: 25rpx;
font-weight: 500;
color: #a6a6a6;
}
.team-name {
margin-left: 15rpx;
}
}
}
}
.state-flag {
display: flex;
align-items: center;
align-self: flex-start;
margin-right: 15rpx;
transform: translateY(30rpx);
}
.state-active::before {
content: "";
display: block;
width: 8rpx;
height: 8rpx;
margin-right: 8rpx;
border-radius: 50%;
background-color: $primaryColor;
}
}
</style>

View File

@@ -0,0 +1,204 @@
<template>
<view>
<view class="search">
<JeepaySearch
ref="search"
v-model:value="data.queryNameOrPhone"
@searchHandle="searchHandle"
:placeholder="data.placeholder"
@focusHandle="focusHandle"
:isFocus="data.isFocus"
>
</JeepaySearch>
</view>
<view class="list">
<view
class="list-item"
v-for="(item, index) in useDataResult.dataList"
@click="toDevDetail(item.sysUserId)"
:key="index"
>
<view class="item-left">
<view class="avatar">
<image :src="item.avatarUrl" mode=""></image>
</view>
<view class="devinfo">
<text style="font-weight: bold; font-size: 27rpx; color: #000">{{ item.realname }}</text>
<text>{{ item.telphone }}</text>
</view>
</view>
<view class="item-right">
<view class="dealinfo">
<text>拓展商户数{{ item.mchCount }}</text>
<text
>商户交易额{{
typeof item.orderAmount === "undefined" ? "0.00" : (item.orderAmount / 100).toFixed(2)
}}</text
>
</view>
<view class="icon">
<image src="../../static/indexImg/up.svg" mode=""></image>
</view>
</view>
</view>
</view>
<jeepayListNull :list="useDataResult.dataList"></jeepayListNull>
</view>
</template>
<script setup>
import JeepaySearch from "@/components/jeepaySearch/jeepaySearch.vue"
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull.vue"
import { reactive, watch, ref } from "vue"
import { onLoad, onShow, onBackPress } from "@dcloudio/uni-app"
import { $getDev } from "@/http/apiManager.js"
import useGetList from "@/hooks/useGetList.js"
const { useDataResult, getList } = useGetList($getDev, undefined, {}, false)
const data = reactive({
queryNameOrPhone: "",
placeholder: "搜索拓展员姓名、手机号…",
isA: false, //动画
isPlus: false, //添加键的动画
isFocus: false, //聚焦
flag: false,
startSearch: false,
})
onLoad(() => {
data.isFocus = false // 每次都要初始化 focus 属性
setTimeout(() => {
data.isFocus = true
}, 0)
uni.hideTabBar()
})
// watch(() => data, (newValue, oldValue) => {
// //监听这个数组,要是没内容就重新请求列表
// if(newValue.flag){
// if(newValue.queryNameOrPhone === ''){
// // getList({ queryNameOrPhone: newValue.queryNameOrPhone,loginType:'APP',userType:3 })
// }
// }
// }, {deep: true})
const searchHandle = () => {
data.flag = true
data.startSearch = true
getList({
queryNameOrPhone: data.queryNameOrPhone,
loginType: "APP",
userType: 3,
})
}
const toDevDetail = (sysUserId) => {
uni.navigateTo({
url: "./developerDetail?sysUserId=" + sysUserId,
})
}
const search = ref()
onBackPress(() => {
if (data.startSearch || search.value.backPressHandel()) {
if (data.queryNameOrPhone !== "" && data.startSearch === true) {
// getList({ queryNameOrPhone: '',
// loginType:'APP',
// userType:3 })
}
data.startSearch = false
data.queryNameOrPhone = ""
return true
} else {
return false
}
})
</script>
<style>
page {
background-color: #f5f6fc;
}
</style>
<style lang="less" scoped>
.search {
height: 93rpx;
}
.list-item {
height: 138rpx;
width: 100%;
background-color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1rpx solid #f5f6fc;
.item-left {
box-sizing: border-box;
height: 100%;
width: 40%;
//background-color: beige;
padding: 33rpx 0 33rpx 30rpx;
display: flex;
justify-content: space-between;
align-items: center;
.avatar {
height: 72rpx;
width: 72rpx;
//background-color: #345;
image {
height: 100%;
width: 100%;
}
}
.devinfo {
height: 72rpx;
width: 172rpx;
// background-color: aqua;
display: flex;
flex-direction: column;
justify-content: space-between;
font-weight: Medium;
font-size: 22rpx;
color: #8d95a6;
}
}
.item-right {
box-sizing: border-box;
height: 100%;
width: 45%;
//background-color: #345;
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 30rpx;
.dealinfo {
height: 72rpx;
width: 292rpx;
//background-color: #8d95a6;
margin-right: 20rpx;
font-weight: Medium;
font-size: 22rpx;
color: #8d95a6;
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: center;
}
.icon {
height: 20rpx;
width: 20rpx;
//background-color: #5500ff;
margin-bottom: 30rpx;
//margin-left: 20rpx;
image {
height: 100%;
width: 100%;
transform: rotate(90deg);
}
}
}
}
</style>

View File

@@ -0,0 +1,162 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle title="编辑拓展员" bgColor="#f2f2f2" />
<JMainCard pd="0" wrapPd="0 30rpx">
<JInput
v-model:value="member.realname"
name="拓展员姓名"
place="请输入拓展员姓名"
:rules="{ name: 'realname', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="member.userNo"
name="拓展员编号"
place="请输入拓展员编号"
:rules="{ name: 'userNo', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput name="拓展员性别" :isBorder="true">
<view class="place-text" :class="{ 'selected-text': member.sex > 0 }" @tap="sex.open(member.sex)">
{{ sexList[member.sex] }}
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JInput>
<JInput
v-model:value="member.loginUsername"
name="登录名"
place="请输入登录名"
:rules="{ name: 'loginUsername', rule: 'REG_LoginName' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="member.telphone"
name="拓展员手机号"
place="请输入拓展员手机号"
:rules="{ name: 'telphone', rule: 'REG_Phone' }"
:isBorder="true"
></JInput>
</JMainCard>
<JMainCard wrapPd="30rpx" pd="30rpx">
<view
class="team-wrapper"
@tap="jumpPage('/pageWork/SelectedList/SelectedList?title=team&&selected=' + member.teamId)"
>
<view>
<image src="/static/iconImg/expand-fill.svg" mode="scaleToFill" />
<view>
{{ member.teamName }}
<text>{{ member.teamId }}</text>
</view>
</view>
<image src="/static/iconImg/icon-right-jiantou.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JButton pd="30rpx" @HandleTouch="editExpand" pdTop="0">保存</JButton>
</view>
<SelectSex ref="sex" @selected="selectedSex" />
</template>
<script setup>
import { ref, reactive } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import SelectSex from "./components/SelectSex.vue"
import { $devDetail, $editDev } from "@/http/apiManager.js"
import { validateArray } from "@/hooks/rules" //校验函数
import useStore from "@/hooks/useStore.js"
const { getStore } = useStore()
onLoad((options) => {
console.log(options.id)
if (options.id) return getInfo(options.id)
})
onShow(() => {
if (getStore("team").teamId) {
member.value.teamId = getStore("team").teamId
member.value.teamName = getStore("team").teamName
}
})
const sexList = reactive(["请选择拓展员性别", "男", "女"])
const member = ref({})
const sex = ref()
const getInfo = (val) => {
$devDetail(val).then(({ bizData }) => {
member.value = bizData
})
}
const editExpand = () => {
if (validateArray(member.value)) {
$editDev(member.value.sysUserId, member.value).then((res) => {
uni.showToast({
title: "保存成功",
icon: "success|none",
mask: true,
})
uni.navigateBack()
})
}
}
const selectedSex = (val) => {
member.value.sex = val
}
const jumpPage = (url) => {
uni.navigateTo({
url,
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.place-text {
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 33rpx;
color: #a6a6a6;
image {
width: 40rpx;
height: 40rpx;
transform: translateX(20rpx);
}
}
.selected-text {
color: #000;
}
}
.team-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
}
view {
display: flex;
align-items: center;
image {
width: 93rpx;
height: 93rpx;
margin-right: 15rpx;
}
view {
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 10rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
}
}
</style>

View File

@@ -0,0 +1,221 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle title="创建拓展员" bgColor="#f2f2f2" />
<JMainCard pd="0" wrapPd="0 30rpx">
<JInput
v-model:value="member.realname"
name="拓展员姓名"
place="请输入拓展员姓名"
:rules="{ name: 'realname', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="member.userNo"
name="拓展员编号"
place="请输入拓展员编号"
:rules="{ name: 'userNo', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput name="拓展员性别" :isBorder="true">
<view class="place-text" :class="{ 'selected-text': member.sex > 0 }" @tap="sex.open(member.sex)">
{{ sexList[member.sex] }}
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JInput>
<JInput
v-model:value="member.loginUsername"
name="登录名"
place="字母开头6到18位"
:rules="{ name: 'loginUsername', rule: 'REG_LoginName' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="member.telphone"
name="拓展员手机号"
place="请输入拓展员手机号"
:rules="{ name: 'telphone', rule: 'REG_Phone' }"
:isBorder="true"
></JInput>
<JInput name="拓展员状态" :isBorder="true">
<view class="dis-wrapper">
<text v-if="member.state">启用</text>
<text v-else>禁用</text>
<switch
:checked="member.state == 1 ? true : false"
@change="change($event, 'state')"
style="margin-left: 15rpx; transform: scale(1.2)"
color="#7737FE"
/>
</view>
</JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx">
<view
class="select-wrapper"
@tap="jumpPage('/pageWork/SelectedList/SelectedList?title=team&&selected=' + member.teamId)"
>
<view class="select-mch" v-if="!member.teamId"> 请选择团队 </view>
<view class="mch-info" v-else>
<image src="/static/iconImg/expand-fill.svg" mode="scaleToFill" />
<view
>{{ member.teamName }} <text>{{ member.teamId }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JMainCard pd="0" wrapPd="0 30rpx">
<JInput name="是否发送开通提醒" :isBorder="true">
<view class="dis-wrapper">
<text v-if="member.isNotify">启用</text>
<text v-else>禁用</text>
<switch
:checked="member.isNotify == 1 ? true : false"
@change="change($event, 'isNotify')"
style="margin-left: 15rpx; transform: scale(1.2)"
color="#7737FE"
/>
</view>
</JInput>
<JInput name="是否使用默认密码" :isBorder="true">
<view class="dis-wrapper">
<switch
:checked="member.defaultPass == 1 ? true : false"
@change="change($event, 'defaultPass')"
style="margin-left: 15rpx; transform: scale(1.2)"
color="#7737FE"
/>
</view>
</JInput>
<JInput
name="自定义密码"
v-model:value="member.loginPassword"
:rules="{ name: 'loginPassword', rule: 'REG_NotNUll' }"
place="请输入自定义密码"
v-if="!member.defaultPass == 1"
></JInput>
</JMainCard>
<JButton pdTop="0" pd="30rpx 30rpx 50rpx" @HandleTouch="addMember">创建成员</JButton>
<SelectSex ref="sex" @selected="selectedSex" />
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import { $addDev, $devDetail } from "@/http/apiManager.js"
import { validateArray } from "@/hooks/rules" //校验函数
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import SelectSex from "./components/SelectSex.vue"
import useStore from "@/hooks/useStore.js"
const { getStore, clearItem } = useStore()
onShow(() => {
if (getStore("team").teamId) {
member.value.teamId = getStore("team").teamId
member.value.teamName = getStore("team").teamName
clearItem("team")
}
})
const member = ref({
state: 1,
isNotify: 0,
defaultPass: 1,
sex: 0,
userType: 3,
isTeamLeader: 0,
})
const sexList = reactive(["请选择拓展员性别", "男", "女"])
const sex = ref()
const change = (e, val) => {
member.value[val] = e.detail.value ? 1 : 0
}
const selectedSex = (val) => {
member.value.sex = val
}
const jumpPage = (url) => {
uni.navigateTo({
url,
})
}
const addMember = () => {
if (validateArray(member.value)) {
uni.showLoading({ title: "添加中..." })
$addDev(member.value).then((res) => {
uni.hideLoading()
uni.showToast({ title: "新增成功", icon: "success" })
uni.navigateBack()
})
}
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.place-text {
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 33rpx;
color: #a6a6a6;
image {
width: 40rpx;
height: 40rpx;
transform: translateX(20rpx);
}
}
.selected-text {
color: #000;
}
.select-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
.select-mch {
margin: 20rpx;
}
.mch-info {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 10rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 15rpx;
color: #8c8c8c;
font-size: 25rpx;
font-weight: 500;
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
image {
width: 60rpx;
height: 66rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,81 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle :title="team.teamId ? '编辑团队' : '创建团队'" bgColor="#f2f2f2" />
<JMainCard pd="0" wrapPd="0 30rpx">
<JInput
v-model:value="team.teamName"
name="团队名称"
place="请输入团队名称"
:isBorder="true"
:rules="{ name: 'teamName', rule: 'REG_NotNUll' }"
></JInput>
<JInput
v-model:value="team.teamNo"
name="团队编号"
place="请输入团队编号"
:rules="{ name: 'teamNo', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
</JMainCard>
<JMainCard wrapPd="30rpx" pd="0">
<JInput name="备注" place="请输入团队备注" v-model:value="team.remark" :isBorder="true"> </JInput>
</JMainCard>
<JButton pd="0 30rpx 50rpx" @HandleTouch="addTeam">{{ team.teamId ? "保存" : "创建团队" }}</JButton>
</view>
</template>
<script setup>
import { ref } from "vue"
import { $addTeam, $editTeam } from "@/http/apiManager.js"
import { onLoad, onShow } from "@dcloudio/uni-app"
import useStore from "@/hooks/useStore.js"
const { getStore } = useStore()
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import { validateArray } from "@/hooks/rules"
onShow(() => {
if (getStore("teamInfo")) {
team.value = getStore("teamInfo")
}
})
const team = ref({
state: 1,
statRangeType: "year",
})
const change = (val) => {
team.value.state = val.detail.value ? 1 : 0
}
const addTeam = () => {
if (team.value.teamId) return editTeam()
if (validateArray(team.value)) {
uni.showLoading({
title: "创建中",
mask: true,
})
$addTeam(team.value).then((res) => {
uni.hideLoading()
uni.showToast({
title: "创建成功",
icon: "success",
mask: true,
})
uni.navigateBack()
})
}
}
const editTeam = () => {
if (validateArray(team.value)) {
$editTeam(team.value).then((res) => {
uni.showToast({
title: "修改成功",
icon: "success",
mask: true,
})
uni.navigateBack()
})
}
}
</script>

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>

View File

@@ -0,0 +1,258 @@
<template>
<view class="page-wrapper global-wrapper">
<JHeaderTitle title="刷脸设备详情" bgColor="transparent" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<image src="/pageWork/static/images/face-bg.svg" class="bg-image" mode="scaleToFill" />
<view class="expand-header">
<image src="/pageWork/static/images/icon-face-white.svg" mode="scaleToFill" />
<view class="expand-title">{{ vdata.deviceName }}</view>
<view class="expand-phone">{{ vdata.deviceId }}</view>
</view>
<!-- 信息板块 -->
<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="vdata.deviceName" pd="15rpx 40rpx" />
<JInput name="设备号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="vdata.deviceId" pd="15rpx 40rpx" />
<JInput
name="设备厂商"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="vdata.provider == 'wxpayQWPro' ? '青蛙刷脸Pro' : '蜻蜓F4'"
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">
{{ vdata.state ? '启用' : '禁用' }}
<switch :checked="vdata.state" style="margin-left: 20rpx; transform: scale(1.2)" color="#BF80FF" @change="stateChange" />
</view>
</JInput>
</JMainCard>
<view class="title">绑定/划拨信息</view>
<!-- 绑定商户 未绑定商户状态 -->
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.2)" pd="0" v-if="!vdata.bindState && vdata.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="vdata.isSelf && !vdata.bindState">
<JInput icon="/static/iconImg/icon-assign.svg" @tap="selectedAgent.open()" :isBorder="true" name="划拨至代理" textColor="#fff" size="33rpx" :img="true" />
</JMainCard>
<template v-if="!vdata.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="vdata.agentName" pd="15rpx 40rpx" />
<JInput name="代理商号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="vdata.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="vdata.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="vdata.mchName" pd="15rpx 40rpx" />
<JInput name="用户号" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" :right="vdata.mchNo" pd="15rpx 40rpx" />
<JInput name="门店" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="vdata.storeName" />
<JInput name="门店ID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="vdata.storeId" />
<JInput name="应用名称" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="vdata.appName" />
<JInput name="AppID" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx" :right="vdata.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>
</view>
<jeepayConfirm ref="refConfirm" />
<JDeletedTips ref="switchStatePopup" @confirm="unbound" />
<SelectedAgent ref="selectedAgent" @confirm="again" />
<JDeletedTips ref="refTakeBack" @confirm="takeBack" />
<JDeletedTips ref="refAgain" @confirm="selectedAgent.open()" />
</template>
<script setup>
import { onLoad, onShow } from '@dcloudio/uni-app'
import { ref, reactive, nextTick } from 'vue'
import { $faceDetails, $unBind, $allotORtakeBack, $updateFace, $updateDeviceDetail } from '@/http/apiManager'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle'
import JInput from '@/components/newComponents/JInput/JInput'
import JMainCard from '@/components/newComponents/JMainCard/JMainCard.vue' // 卡片
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips'
import SelectedAgent from '../deviceManagement/components/SelectedAgent.vue'
const refConfirm = ref(null)
const switchStatePopup = ref(null)
const selectedAgent = ref(null)
const refTakeBack = ref(null)
const refAgain = ref(null)
const vdata = reactive({})
let id = undefined //设备Id
onLoad((options) => {
id = options.deviceId
})
onShow(() => {
if (id) {
getDetails()
}
})
const getDetails = () => {
$faceDetails(id).then(({ bizData }) => {
if (!bizData.isSelf) bizData.isSelf = false
Object.assign(vdata, bizData)
})
}
// 切换状态
const stateChange = (e) => {
vdata.state = Number(e.detail.value)
refConfirm.value.comfirmOpen(
() => {
$updateFace(vdata).then((res) => {
uni.showToast({
title: '修改成功',
icon: 'success|none',
mask: true,
})
})
},
'确认修改状态吗?',
() => {
vdata.state = Number(!e.detail.value)
}
)
}
// 跳转至绑定页
const bindMch = () => {
uni.navigateTo({ url: '../deviceManagement/publicBind?id=' + vdata.deviceId + '&tag=pos&title=刷脸设备绑定' })
}
// 解绑函数 打开提示弹窗
function unbound() {
$updateDeviceDetail(vdata.deviceId, { bindState: 0 }).then(({ bizData }) => {
uni.showToast({
icon: 'none',
title: '解绑成功',
})
uni.navigateBack()
})
}
// 重新划拨
const again = (e) => {
const data = {
agentNo: e.text,
allotDeviceIds: vdata.deviceId,
allotOrRecover: 'allot',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
nextTick(() => {
getDetails()
})
uni.showToast({ title: '划拨成功', icon: 'success' })
selectedAgent.value.close()
})
}
// 收回划拨设备
const takeBack = () => {
const data = {
agentNo: vdata.agentNo,
allotDeviceIds: vdata.deviceId,
allotOrRecover: 'recover',
allotType: 'select',
}
$allotORtakeBack(data).then((res) => {
getDetails()
uni.showToast({ title: '收回成功', icon: 'success' })
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
position: relative;
background-color: $primaryColor;
.bg-image {
position: absolute;
top: -40rpx;
right: 0;
width: 100%;
height: 650rpx;
}
.expand-header {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50rpx;
image {
width: 93rpx;
height: 93rpx;
}
.expand-title {
width: 500rpx;
margin: 20rpx auto 0;
word-break: break-all;
text-align: center;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
.expand-phone {
margin: 30rpx 0;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
}
.expand-edit {
position: relative;
z-index: 30;
padding: 20rpx 41rpx;
font-size: 28rpx;
color: $primaryColor;
image {
width: 26.25rpx;
height: 26.25rpx;
}
}
}
}
.title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 500;
text-align: center;
color: #fff;
}
</style>

View File

@@ -0,0 +1,266 @@
<template>
<view class="page">
<view class="mch-header">
<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>
<view v-for="(v, index) in useDataResult.dataList" :key="v.deviceId">
<JPreview
:activeBox="vdata.activeBox"
:isLast="index === useDataResult.dataList.length - 1"
:img="imageList[v.state]"
:title="v.deviceName"
:qrcId="v.deviceId"
:active="v.active"
:spot="v.state == 0 ? '#b2b2b2' : '#7737FE'"
:status="v.state == 1 ? '已启用' : '已禁用'"
:disabled="!!v.bindState"
@activeClick="handleActive(v)"
@click="toDetail(v.deviceId)"
>
<template #titleTag>
<JeepayTag :type="v.provider == 'wxpayQWPro' ? 'green-rgba' : 'blue'">{{ v.provider == 'wxpayQWPro' ? '青蛙刷脸Pro' : '蜻蜓F4' }}</JeepayTag>
</template>
<template #bottom>
<view class="info-wrapper">
<view class="info" v-if="!v.isSelf">
<image src="/static/iconImg/icon-mini-agent.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ v.agentName }}</view>
<view class="number">{{ v.agentNo }}</view>
</view>
<view class="info" v-if="v.bindState">
<image src="@/static/equipmentImg/mch-little.svg" mode="aspectFit" class="mch-img" />
<view class="name">{{ v.mchName }}</view>
<view class="number">{{ v.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" />
</template>
<script setup>
import { reactive, ref } from 'vue'
import { $faceList, $unBind, $allotORtakeBack } from '@/http/apiManager'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue'
import JSearchInput from '@/components/newComponents/JSearchInput/JSearchInput.vue'
import JPreview from '@/components/newComponents/JPreview/JPreview.vue'
import SelectedAgent from '../deviceManagement/components/SelectedAgent.vue'
import useGetList from '@/hooks/useList.js'
// 展示图片列表
const imageList = ['/pageWork/static/images/icon-face-0.svg', '/pageWork/static/images/icon-face-1.svg']
// 初始化列表数据
const { useDataResult, getList } = useGetList({
requestFun: $faceList,
pageSize: 15,
params: { deviceType: 6 },
})
const refSingle = ref(null)
const refSelected = ref(null)
const vdata = reactive({
activeBox: false,
})
const params = {
pageSize: 10,
pageNumber: 1,
deviceType: 6,
}
const selectedList = [
{ label: '收回所有已选择设备', value: 'takeBack', confirmText: '确定要收回所有已选设备吗?', fun: takeBackDev },
{
label: '划拨已选设备至代理商',
value: 'toAgent',
fun: () => {
refSelected.value.open()
},
},
]
// 跳转详情页
const toDetail = (deviceId) => uni.navigateTo({ url: `/pageWork/face/details?deviceId=${deviceId}` })
// 划拨功能区
const devNoList = []
const openNext = () => {
if (devNoList.length == 0) return uni.showToast({ title: '请勾选要进行操作的设备', icon: 'none' })
refSingle.value.open()
}
const cancel = () => {
if (!vdata.activeBox) return (vdata.activeBox = true)
useDataResult.dataList.forEach((v) => {
v.active = false
})
devNoList.length = 0
vdata.activeBox = false
}
// 勾选
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
}
// 收回划拨
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,
})
})
}
</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;
}
}
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.mch-footers {
position: fixed;
left: 0;
right: 0;
bottom: 0;
backdrop-filter: blur(30px);
border-top: 1px solid rgba($color: #000000, $alpha: 0.1);
}
.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,165 @@
<template>
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" :safe-area="false" @maskClick="emits('cancel')">
<!-- 通用提示弹窗 用于提示用户 数据含义 -->
<view class="card-wrapper">
<view class="card-title flex-center">手持承诺函</view>
<view class="image-wrapper">
<view class="tips-title">手持承诺函示例图</view>
<image src="/pageWork/static/images/authorize.svg" mode="aspectFit" />
<view class="download" @tap="downLoad">模板下载</view>
</view>
<view class="card-button flex-center" hover-class="touch-hover" @tap="confirm"> 我知道了</view>
</view>
</uni-popup>
<JeepayPopupConfirm ref="confirmSave" />
</template>
<script setup>
import { onMounted, reactive, ref, inject } from 'vue'
const emits = defineEmits(['cancel'])
const vdata = reactive({})
const popup = ref(null)
const confirmSave = ref(null)
const open = (url) => {
vdata.url = url
console.log('url', url)
popup.value.open()
}
const confirm = () => {
emits('cancel')
popup.value.close()
}
const downLoad = () => {
popup.value.close()
// #ifdef APP-PLUS
confirmSave.value.open('确认下载模板吗?').then((res) => {
uni.downloadFile({
url: vdata.url, //仅为示例,并非真实的资源
success: (res) => {
uni.saveFile({
tempFilePath: res.tempFilePath,
success: function (val) {
uni.openDocument({
filePath: val.savedFilePath,
success: function (res) {
uni.showToast({
title: '保存成功',
})
},
fail: function (err) {},
})
},
})
},
})
})
// #endif
//#ifdef MP-WEIXIN
confirmSave.value
.open('确认下载模板吗?')
.then((res) => {
uni.setClipboardData({ data: vdata.url }).then((res) => {
uni.showToast({ title: '下载链接复制成功,请到浏览器中粘贴下载', icon: 'none' })
})
// downloadQR(vdata.url)
})
.catch(() => {
popup.value.open()
})
//#endif
}
//#ifdef MP-WEIXIN
function downloadQR() {
wx.getSetting({
//获取权限
success(res) {
if (res.authSetting['scope.writePhotosAlbum']) {
download(vdata.url)
} else {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
download(vdata.url)
},
})
}
},
})
}
function download(data) {
wx.downloadFile({
url: data,
success: (res) => {
const FileSystemManager = wx.getFileSystemManager()
FileSystemManager.saveFile({
tempFilePath: res.tempFilePath,
filePath: wx.env.USER_DATA_PATH + '/' + '授权函模板' + '.docx',
success: function (val) {
console.log('val', val)
console.log('val.savedFilePath', val.savedFilePath)
uni.showToast({
title: '下载成功保存路径' + val.savedFilePath,
icon: 'none',
mask: true,
})
uni.vibrateShort()
},
fail: function (err) {
console.log('err', err)
uni.showToast({
title: '下载失败',
icon: 'error|none',
mask: true,
})
},
})
},
})
}
//#endif
defineExpose({ open })
</script>
<style lang="scss" scoped>
.card-wrapper {
border-radius: 32rpx 32rpx 0 0;
background-color: #fff;
padding-bottom: 60rpx;
max-height: 70vh;
.card-title {
margin-bottom: 20rpx;
height: 110rpx;
font-size: 30rpx;
font-weight: 400;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.07);
}
.card-button {
margin-top: 20rpx;
height: 110rpx;
font-size: 32rpx;
color: #2980fd;
border-top: 20rpx solid #f7f7f7;
}
}
.image-wrapper {
display: flex;
flex-direction: column;
align-items: center;
image {
width: 200rpx;
height: 200rpx;
border-radius: 10rpx;
}
.tips-title {
margin: 20rpx 0;
font-size: 25rpx;
color: #888;
}
.download {
margin: 30rpx 0;
font-size: 32rpx;
color: #2980fd;
}
}
</style>

View File

@@ -0,0 +1,80 @@
<template>
<JPopup ref="popup">
<JMainCard wrapPd="30rpx" pd="0" @tap.stop v-if="selectType.type === 0">
<JLine
name="个人"
iconOn="/static/iconImg/user-active.svg"
iconClose="/static/iconImg/user.svg"
:isBorder="true"
:isSelect="selectType.value === 1"
@tap="selected(1)"
></JLine>
<JLine
name="企业"
iconOn="/static/iconImg/building-active.svg"
iconClose="/static/iconImg/building.svg"
:isSelect="selectType.value === 2"
@tap="selected(2)"
></JLine>
<view class="content"> 选择企业后可设置收款账户为对公账户但需要上传营业执照及法人信息 </view>
</JMainCard>
<JMainCard wrapPd="30rpx" pd="0" @tap.stop v-if="selectType.type === 1">
<JLine
name="对私账户"
:isBorder="true"
:isSelect="selectType.value === 'BANK_PRIVATE'"
@tap="selected('BANK_PRIVATE')"
></JLine>
<JLine
name="对公账户"
:isSelect="selectType.value === 'BANK_PUBLIC'"
@tap="selected('BANK_PUBLIC')"
v-if="selectType.agentType === 2"
></JLine>
<!-- <JLine name="个人微信" :isSelect="selectType.value === 'WX_CASH'" @tap="selected('WX_CASH')"></JLine> -->
<JLine name="个人支付宝" :isSelect="selectType.value === 'ALIPAY_CASH'" @tap="selected('ALIPAY_CASH')"></JLine>
</JMainCard>
<JButton pd="0 30rpx 50rpx 30rpx" bgColor="rgba(255, 255, 255, 0.8)" pdTop="0" @HandleTouch="popup.close()"
>取消</JButton
>
</JPopup>
</template>
<script setup>
import { ref } from "vue"
import JPopup from "@/components/newComponents/JPopup/JPopup"
import JMainCard from "@/components//newComponents/JMainCard/JMainCard"
import JLine from "@/components//newComponents/JLine/JLine"
import JButton from "@/components//newComponents/JButton/JButton"
const emits = defineEmits(["synData"])
const popup = ref()
const selectType = ref({})
const open = (val) => {
selectType.value = val
popup.value.open()
}
const selected = (val) => {
selectType.value.value = val
emits("synData", selectType.value)
popup.value.close()
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.content {
margin: 0 30rpx 30rpx 30rpx;
background-color: #f2f2f2;
padding: 20rpx;
border-radius: 10px;
font-size: 27rpx;
color: #666666;
}
.confirm {
padding: 32rpx 0;
text-align: center;
font-size: 33rpx;
color: $primaryColor;
}
</style>

View File

@@ -0,0 +1,212 @@
<template>
<view class="page-wrapper bgF2">
<JHeaderTitle :back="false" :logOut="true" title="完善资料" :bgColor="userInfo.state == 3 ? '#ff4c5b' : '#f2f2f2'"></JHeaderTitle>
<view class="page-header" v-if="userInfo.state == 3">
<image src="/static/iconImg/icon-striped.svg" mode="scaleToFill" />
<view class="tips">您的资料审核失败请修改后重新提交</view>
<view class="why">驳回原因{{ userInfo.auditRemark }}</view>
</view>
<JMainCard wrapPd="0 30rpx" pd="0x">
<JInput name="代理商类型" v-model:value="userInfo.agentType" :img="true" :isBorder="true" @tap="select.open({ type: 0, value: userInfo.agentType })">
<view class="agent-type">{{ userInfo.agentType == 1 ? '个人' : '企业' }}</view>
</JInput>
</JMainCard>
<JMainCard wrapPd="30rpx" pd="0">
<template v-if="userInfo.agentType === 1">
<JInput name="代理商全称" v-model:value="userInfo.agentName" :rules="{ name: 'agentName', rule: 'REG_NotNUll' }" place="请输入代理商全称"></JInput>
<JInput name="代理商简称" v-model:value="userInfo.agentShortName" :rules="{ name: 'agentShortName', rule: 'REG_NotNUll' }" place="请输入代理商简称"></JInput>
</template>
<template v-if="userInfo.agentType === 2">
<JInput name="企业全称" v-model:value="userInfo.agentName" :rules="{ name: 'agentName', rule: 'REG_NotNUll' }" place="请输入企业全称"></JInput>
<JInput name="企业简称" v-model:value="userInfo.agentShortName" :rules="{ name: 'agentShortName', rule: 'REG_NotNUll' }" place="请输入代理商简称"></JInput>
</template>
<JInput name="联系人姓名" v-model:value="userInfo.contactName" :rules="{ name: 'contactName', rule: 'REG_NotNUll' }" place="请输入联系人姓名"></JInput>
<JInput name="联系人邮箱" v-model:value="userInfo.contactEmail" place="请输入邮箱"></JInput>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="0">
<template v-if="userInfo.agentType === 1">
<JUpLoad name="联系人身份证人像面" v-model:value="userInfo.idcard1Img"></JUpLoad>
<JUpLoad name="联系人身份证国徽面" v-model:value="userInfo.idcard2Img" :rules="{ name: 'idcard2Img', rule: 'REG_NotNUll' }"></JUpLoad>
<JUpLoad v-model:value="userInfo.idcardInHandImg" :rules="{ name: 'idcardInHandImg', rule: 'REG_NotNUll' }">
<template #title>
<view class="title">
<text>[联系人]手持承诺函照片</text>
<uni-icons type="help-filled" size="22" color="#c6c6c6" @tap="refTips.open(userInfo.promiseFile)" />
</view>
</template>
</JUpLoad>
</template>
<template v-if="userInfo.agentType === 2">
<JUpLoad name="营业执照" v-model:value="userInfo.licenseImg" :rules="{ name: 'licenseImg', rule: 'REG_NotNUll' }" borderNone></JUpLoad>
<JUpLoad name="法人身份证人像面" v-model:value="userInfo.idcard1Img" :rules="{ name: 'idcard1Img', rule: 'REG_NotNUll' }"></JUpLoad>
<JUpLoad name="法人身份证国徽面" v-model:value="userInfo.idcard2Img" :rules="{ name: 'idcard2Img', rule: 'REG_NotNUll' }"></JUpLoad>
<JUpLoad v-model:value="userInfo.idcardInHandImg" :rules="{ name: 'idcardInHandImg', rule: 'REG_NotNUll' }">
<template #title>
<view class="title">
<text>[联系人]手持承诺函照片</text>
<uni-icons type="help-filled" size="22" color="#c6c6c6" @tap="refTips.open(userInfo.promiseFile)" />
</view>
</template>
</JUpLoad>
</template>
</JMainCard>
<JMainCard wrapPd="30rpx 30rpx 40rpx 30rpx" pd="0">
<JInput
name="收款账户类型"
v-model:value="userInfo.settAccountType"
:img="true"
:isBorder="true"
@tap="select.open({ type: 1, value: userInfo.settAccountType, agentType: userInfo.agentType })"
>
<view class="agent-type">{{ settAccountType[userInfo.settAccountType] }}</view>
</JInput>
<template v-if="userInfo.settAccountType" >
<JInput name="账户姓名" v-model:value="userInfo.settAccountName" :rules="{ name: 'settAccountName', rule: 'REG_NotNUll' }" place="请输入账户姓名" ></JInput>
</template>
<template v-if="userInfo.settAccountType === 'BANK_PRIVATE'">
<JUpLoad name="收款银行卡照片" v-model:value="userInfo.bankCardImg"></JUpLoad>
<JInput name="开户银行名称" v-model:value="userInfo.settAccountBank" :rules="{ name: 'settAccountBank', rule: 'REG_NotNUll' }" place="请输入开户银行名称"></JInput>
<JInput name="收款银行卡号" v-model:value="userInfo.settAccountNo" :rules="{ name: 'settAccountNo', rule: 'REG_NotNUll' }" place="请输入收款银行卡号"></JInput>
</template>
<template v-if="userInfo.settAccountType === 'WX_CASH'">
<JInput name="个人微信号" v-model:value="userInfo.settAccountNo" :rules="{ name: 'settAccountNo', rule: 'REG_NotNUll' }" place="请输入个人微信号"></JInput>
</template>
<template v-if="userInfo.settAccountType === 'ALIPAY_CASH'">
<JInput name="支付宝账号" v-model:value="userInfo.settAccountNo" :rules="{ name: 'settAccountNo', rule: 'REG_NotNUll' }" place="请输入支付宝账号"></JInput>
</template>
<template v-if="userInfo.settAccountType === 'BANK_PUBLIC'">
<JUpLoad name="开户许可证照片" v-model:value="userInfo.permitImg" :rules="{ name: 'permitImg', rule: 'REG_NotNUll' }"></JUpLoad>
<JInput name="对公账号" v-model:value="userInfo.settAccountNo" :rules="{ name: 'settAccountNo', rule: 'REG_NotNUll' }" place="请输入对公账号"></JInput>
<JInput name="开户银行名称" v-model:value="userInfo.settAccountBank" :rules="{ name: 'settAccountBank', rule: 'REG_NotNUll' }" place="请输入开户银行名称"></JInput>
<JInput
name="开户行支行名称"
v-model:value="userInfo.settAccountSubBank"
:rules="{ name: 'settAccountSubBank', rule: 'REG_NotNUll' }"
place="请输入开户行支行名称"
></JInput>
</template>
</JMainCard>
<JButton
pd="0 30rpx 50rpx 30rpx"
@HandleTouch="tips.open('选择企业后可设置收款账户为对公账户,但需要上传营业执照及法人信息。')"
:bgColor="userInfo.state == 3 ? '#ff4c5b' : '$primaryColor'"
>
{{ userInfo.state == 3 ? '重新提交' : '提交' }}
</JButton>
</view>
<Selected ref="select" @synData="synData"></Selected>
<JDeletedTips ref="tips" @confirm="submit" />
<JTipsPopupContent ref="refTips" />
</template>
<script setup>
import { reactive, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { $getMainUserInfo, $auditInfo } from '@/http/apiManager.js';
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue';
import JMainCard from '@/components/newComponents/JMainCard/JMainCard';
import JInput from '@/components/newComponents/JInput/JInput';
import JUpLoad from '@/components/newComponents/JUpLoad/JUpLoad';
import JButton from '@/components/newComponents/JButton/JButton';
import JDeletedTips from '@/components/newComponents/JDeletedTips/JDeletedTips';
import Selected from './component/Selected';
import JTipsPopupContent from './component/JTipsPopupContent.vue';
import { validateArray } from '@/hooks/rules';
onLoad(() => {
getMainUserInfo();
});
const select = ref(null);
const tips = ref(null);
const refTips = ref(null);
const userInfo = ref({
agentType: 1,
settAccountType: 'BANK_PRIVATE'
});
const settAccountType = reactive({
BANK_PRIVATE: '对私账户',
BANK_PUBLIC: '对公账户',
WX_CASH: '个人微信',
ALIPAY_CASH: '个人支付宝'
});
const synData = data => {
switch (data.type) {
case 0:
userInfo.value.agentType = data.value;
break;
case 1:
userInfo.value.settAccountType = data.value;
break;
}
};
const getMainUserInfo = () => {
$getMainUserInfo().then(({ bizData }) => {
userInfo.value = bizData;
if (userInfo.value.state == 2 || userInfo.value.state == 1) {
return uni.reLaunch({ url: './readOnlyInformation' });
}
});
};
const submit = () => {
if (validateArray(userInfo.value)) {
uni.showLoading({
title: '提交中',
mask: true
});
$auditInfo(userInfo.value).then(res => {
uni.hideLoading();
uni.showToast({ title: '提交成功', icon: 'success', mask: true });
getMainUserInfo();
});
}
};
</script>
<style lang="scss" scoped>
.page-wrapper {
width: 100%;
.page-header {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #ff4c5b;
// padding-bottom: 47rpx;
margin-bottom: 20rpx;
image {
width: 48.76rpx;
height: 57.67rpx;
}
view {
font-size: 28rpx;
color: #ffd9dc;
}
.tips {
margin: 50rpx 0;
}
.why {
flex-grow: 1;
min-width: 626rpx;
word-break: break-all;
padding: 30rpx 62rpx;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 32rpx 32rpx 0px 0px;
}
}
.agent-type {
font-size: 33rpx;
color: #666666;
}
}
.title {
display: flex;
align-items: center;
vertical-align: middle;
text {
margin-right: 5rpx;
vertical-align: middle;
}
}
</style>

View File

@@ -0,0 +1,197 @@
<template>
<view class="page-wrapper bgF">
<JHeaderTitle :back="false" :logOut="true" title="完善资料" :bgColor="userInfo.state == 1 ? '#1dcc64' : '#FFCC66'"></JHeaderTitle>
<view class="page-header" :style="{ backgroundColor: userInfo.state == 1 ? '#1dcc64' : '#FFCC66' }">
<image v-if="userInfo.state != 1" :class="[animation]" src="/static/iconImg/icon-examine.svg" mode="scaleToFill" />
<view v-if="userInfo.state != 1">您的资料正在审核中请耐心等待</view>
<view v-if="userInfo.state === 1" class="login bdR20" @tap="loginOut">审核通过请点击重新登录</view>
</view>
<view class="page-main">
<JMainCard wrapPd="30rpx" pd="0" bgColor="#f2f2f2">
<JInput name="代理商类型" :img="true" :isBorder="true">
<view class="agent-type">{{ userInfo.agentType == 1 ? '个人' : '企业' }}</view>
</JInput>
</JMainCard>
<JMainCard wrapPd="30rpx" pd="0" bgColor="#f2f2f2">
<template v-if="userInfo.agentType === 1">
<JInput name="代理商全称" :isBorder="true">{{ userInfo.agentName }}</JInput>
<JInput name="代理商简称" borderBg="#D9D9D9">{{ userInfo.agentShortName }}</JInput>
</template>
<template v-if="userInfo.agentType === 2">
<JInput name="企业全称" borderBg="#D9D9D9">
{{ userInfo.agentName }}
</JInput>
<JInput name="企业简称" borderBg="#D9D9D9">
{{ userInfo.agentShortName }}
</JInput>
</template>
<JInput name="联系人姓名" borderBg="#D9D9D9">
{{ userInfo.contactName }}
</JInput>
<JInput name="联系人邮箱" borderBg="#D9D9D9">
{{ userInfo.contactEmail }}
</JInput>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="0" bgColor="#f2f2f2">
<JUpLoad name="联系人身份证人像面" :imgUrl="userInfo.idcard1Img || imgUrl" borderNone></JUpLoad>
<JUpLoad name="联系人身份证国徽面" :imgUrl="userInfo.idcard2Img || imgUrl"></JUpLoad>
<JUpLoad :imgUrl="userInfo.idcardInHandImg || imgUrl">
<template #title>
<view class="title"><text>[联系人]手持承诺函照片</text> <uni-icons type="help-filled" size="22" color="#c6c6c6" @tap="refTips.open(userInfo.promiseFile)" /> </view>
</template>
</JUpLoad>
</JMainCard>
<JMainCard wrapPd="30rpx 30rpx 40rpx 30rpx" pd="0" bgColor="#f2f2f2">
<JInput name="收款账户类型" :img="true" :isBorder="true">
<view class="agent-type">{{ settAccountType[userInfo.settAccountType] }}</view>
</JInput>
<template v-if="userInfo.settAccountType === 'BANK_PRIVATE'">
<JUpLoad name="收款银行卡照片" :imgUrl="userInfo.bankCardImg || imgUrl"></JUpLoad>
<JInput name="开户银行名称">{{ userInfo.settAccountBank }}</JInput>
<JInput name="收款银行卡号">{{ userInfo.settAccountNo }}</JInput>
</template>
<template v-if="userInfo.settAccountType === 'WX_CASH'">
<JInput name="个人微信号">{{ userInfo.settAccountNo }}</JInput>
</template>
<template v-if="userInfo.settAccountType === 'ALIPAY_CASH'">
<JInput name="支付宝账号">{{ userInfo.settAccountNo }}</JInput>
</template>
<template v-if="userInfo.settAccountType === 'BANK_PUBLIC'">
<JUpLoad name="开户许可证照片" :imgUrl="userInfo.permitImg || imgUrl"></JUpLoad>
<JInput name="对公账户名称">{{ userInfo.settAccountName }}</JInput>
<JInput name="对公账号">{{ userInfo.settAccountNo }}</JInput>
<JInput name="开户银行名称">{{ userInfo.settAccountBank }}</JInput>
<JInput name="开户行支行名称">{{ userInfo.settAccountSubBank }}</JInput>
</template>
</JMainCard>
</view>
</view>
<JTipsPopupContent ref="refTips" />
</template>
<script setup>
import { onBeforeUnmount, reactive, ref } from 'vue'
import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app'
import user from '@/hooks/user.js'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue'
import JInput from '@/components/newComponents/JInput/JInput'
import JMainCard from '@/components/newComponents/JMainCard/JMainCard'
import JUpLoad from '@/components/newComponents/JUpLoad/JUpLoad'
import { $getMainUserInfo } from '@/http/apiManager.js'
import JTipsPopupContent from './component/JTipsPopupContent.vue'
const imgUrl = ref('/static/iconImg/defaultImg.svg')
onLoad(() => {
getUserInfo()
})
let timeOut = undefined
const getUserInfo = () => {
$getMainUserInfo().then(({ bizData }) => {
userInfo.value = bizData
uni.stopPullDownRefresh()
timeOut = setTimeout(() => {
animation.value = ''
audit()
}, 1500)
})
}
const refTips = ref(null)
const userInfo = ref({})
const animation = ref('')
const settAccountType = reactive({
BANK_PRIVATE: '对私账户',
BANK_PUBLIC: '对公账户',
WX_CASH: '个人微信',
ALIPAY_CASH: '个人支付宝',
})
onPullDownRefresh(() => {
getUserInfo()
animation.value = 'animation'
})
const audit = () => {
if (userInfo.value.state === 3)
return uni.showToast({
title: '审核未通过',
icon: 'error',
mask: true,
success: () => {
uni.reLaunch({
url: '/pageWork/information/information',
})
},
})
}
const loginOut = () => {
user.logout()
uni.showToast({
icon: 'none',
title: '退出成功',
})
}
onBeforeUnmount(() => {
clearTimeout(timeOut)
})
</script>
<style lang="scss" scoped>
.page-wrapper {
width: 100%;
min-height: 100%;
.page-header {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
// background-color: #ffcc66;
padding-bottom: 47rpx;
image {
width: 45rpx;
height: 52.5rpx;
}
view {
padding: 50rpx 0;
font-size: 28rpx;
color: #906a1f;
}
.login {
padding: 30rpx 50rpx;
margin: 30rpx 0;
background-color: rgba(255, 255, 255, 0.2);
letter-spacing: 4rpx;
color: #fff;
}
&::after {
content: '';
display: block;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 47rpx;
background-color: #fff;
border-radius: 32rpx 32rpx 0px 0px;
}
}
}
.animation {
animation: rotate 1.5s linear;
}
@keyframes rotate {
to {
transform: rotate(0deg);
}
from {
transform: rotate(-720deg);
}
}
.title {
display: flex;
align-items: center;
vertical-align: middle;
text {
margin-right: 5rpx;
vertical-align: middle;
}
}
</style>

View File

@@ -0,0 +1,273 @@
<template>
<JeepayWrapper>
<view class="page">
<JHeaderTitle title="如意Lite管理" 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 '../deviceManagement/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: 7 },
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: `./view?deviceId=${e}` + `&deviceType=` + 7,
})
}
// 设备号列表
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,257 @@
<template>
<JeepayWrapper>
<!-- 顶部自定义导航栏 -->
<JHeaderTitle title="如意Lite详情" :bgColor="header.bgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<JEquiCode bgImg="/pageWork/static/images/lite-bg.svg" icon="/pageWork/static/images/lite-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 '../deviceManagement/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: '../deviceManagement/publicBind?id=' + params.value.deviceId + '&tag=pos&title=如意Lite绑定' })
}
// 跳转至编辑信息
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,125 @@
<template>
<view class="bgF2 global-wrapper">
<view class="mch-header">
<JHeaderTitle title="创建商户" bgColor="#f2f2f2" />
</view>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput
name="商户全称"
:isBorder="true"
v-model:value="mchInfo.mchName"
:rules="{ name: 'mchName', rule: 'REG_NotNUll' }"
place="请输入商户全称"
></JInput>
<JInput
name="商户简称"
v-model:value="mchInfo.mchShortName"
:rules="{ name: 'mchShortName', rule: 'REG_NotNUll' }"
place="请输入商户简称"
></JInput>
<JInput
name="商户登录名"
v-model:value="mchInfo.loginUsername"
:rules="{ name: 'loginUsername', rule: 'REG_LoginName' }"
place="字母开头6到18位"
></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput
name="联系人姓名"
:isBorder="true"
v-model:value="mchInfo.contactName"
:rules="{ name: 'contactName', rule: 'REG_NotNUll' }"
place="请输入联系人姓名"
></JInput>
<JInput
name="联系人手机号"
v-model:value="mchInfo.contactTel"
:rules="{ name: 'contactTel', rule: 'REG_Phone' }"
place="请输入联系人手机号"
></JInput>
<JInput name="联系人邮箱" v-model:value="mchInfo.contactEmail" place="请输入联系人邮箱"></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput name="是否发送开通提醒" :isBorder="true">
<switch
:checked="mchInfo.isNotify == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe"
@change="switchState($event, 'isNotify')"
/>
</JInput>
<JInput name="是否使用默认密码">
<switch
:checked="mchInfo.defaultPass == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe"
@change="switchState($event, 'defaultPass')"
/>
</JInput>
<JInput
name="自定义密码"
v-model:value="mchInfo.loginPassword"
:rules="{ name: 'loginPassword', rule: 'REG_NotNUll' }"
place="请输入自定义密码"
v-if="!mchInfo.defaultPass"
></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="15rpx 30rpx">
<JInput name="备注" v-model:value="mchInfo.remark" place="请输入备注"></JInput>
</JMainCard>
<JButton pd="15rpx 30rpx 50rpx 30rpx" bottom="50rpx" @HandleTouch="createMch">创建商户</JButton>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { $addMer, $getPasswordRules } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import { validateArray } from "@/hooks/rules"
import valid from "@/hooks/validate"
onLoad(() => {
getRules()
})
const mchInfo = reactive({
defaultPass: 1,
isNotify: 0,
state: 1,
})
const switchState = (e, v) => {
mchInfo.value[v] = e.detail.value ? 1 : 0
}
const rules = ref({})
const getRules = () => {
$getPasswordRules().then((res) => {
rules.value.rule = new RegExp(res.bizData.regexpRules)
rules.value.ruleText = res.bizData.errTips
})
}
const createMch = () => {
if (!!mchInfo.contactEmail) {
if (!valid.REG_Email(mchInfo.contactEmail)) return uni.showToast({ title: "邮箱格式不正确", icon: "none" })
}
if (validateArray(mchInfo)) {
if (mchInfo.loginPassword && !rules.value.rule.test(mchInfo.passwordType)) {
return uni.showToast({
title: rules.value.ruleText,
icon: "none",
})
}
$addMer(mchInfo).then((res) => {
if (res.code === 0) {
uni.showToast({
icon: "success",
title: "添加成功",
})
uni.navigateBack()
}
})
}
}
</script>

View File

@@ -0,0 +1,119 @@
<template>
<view class="page-wrapper bgF2 global-wrapper">
<JHeaderTitle title="编辑商户信息" bgColor="#f2f2f2" />
<JMainCard wrapPd="0 30rpx" pd="0">
<JInput
v-model:value="mchInfo.mchName"
name="用户名称"
place="请输入商户名称"
:rules="{ name: 'mchName', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput
v-model:value="mchInfo.mchShortName"
name="商户简称"
place="请输入商户简称"
:rules="{ name: 'mchShortName', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
</JMainCard>
<JMainCard wrapPd="30rpx" pd="0">
<JInput
v-model:value="mchInfo.contactName"
name="联系人姓名"
place="请输入联系人姓名"
:rules="{ name: 'contactName', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput v-model:value="mchInfo.contactEmail" name="联系人邮箱" place="请输入联系人邮箱" :isBorder="true"></JInput>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="0">
<JInput v-model:value="mchInfo.remark" name="备注" place="请输入备注" :isBorder="true"></JInput>
</JMainCard>
<JButton pd="30rpx" @HandleTouch="saveMch" pdTop="30rpx">保存</JButton>
</view>
</template>
<script setup>
import { ref, reactive, nextTick } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import { $editMer, $findMer } from "@/http/apiManager.js"
import { validateArray } from "@/hooks/rules" //校验函数
onLoad((options) => {
if (options.mchNo) return getInfo(options.mchNo)
})
const mchInfo = ref({})
const getInfo = (val) => {
$findMer(val).then(({ bizData }) => {
mchInfo.value = bizData
})
}
const saveMch = () => {
if (validateArray(mchInfo.value)) {
$editMer(mchInfo.value.mchNo, mchInfo.value).then((res) => {
uni.showToast({
title: "保存成功",
icon: "success",
})
uni.navigateBack()
})
}
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.place-text {
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 33rpx;
color: #a6a6a6;
image {
width: 40rpx;
height: 40rpx;
transform: translateX(20rpx);
}
}
.selected-text {
color: #000;
}
}
.team-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
}
view {
display: flex;
align-items: center;
image {
width: 93rpx;
height: 93rpx;
margin-right: 15rpx;
}
view {
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 10rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
}
}
</style>

View File

@@ -0,0 +1,260 @@
<template>
<view class="page-wrapper">
<JHeaderTitle title="商户详情" :bgColor="headerBgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<image src="/static/iconImg/mch-bg-Img.svg" class="bg-image" mode="scaleToFill" />
<view class="expand-header">
<image src="/static/iconImg/icon-mch.svg" mode="scaleToFill" />
<view class="expand-title">{{ mchInfo.mchName }}</view>
<view class="expand-phone">{{ mchInfo.mchNo }}</view>
<view class="expand-edit bgF bdR10" @tap="editMch">
<image src="/static/iconImg/expand-edit.svg" mode="scaleToFill" />
编辑信息
</view>
</view>
<JMainCard pd="0" bgColor="rgba(0,0,0,0.1)">
<JInput name="商户全称" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.mchName }}</text></JInput
>
<JInput name="商户简称" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.mchShortName }}</text></JInput
>
<JInput name="用户号" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.mchNo }}</text></JInput
>
<JInput name="联系人姓名" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.contactName }}</text></JInput
>
<JInput name="联系人手机号" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.contactTel }}</text></JInput
>
<JInput name="联系人邮箱" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.contactEmail }}</text></JInput
>
<JInput name="创建时间" pd="30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ mchInfo.createdAt?.split("-").join("/") }}</text></JInput
>
<JInput name="商户状态" pd="0 40rpx 30rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<view class="dis-wrapper">
<text v-if="mchInfo.state == 1">启用</text>
<text v-else>禁用</text>
<switch
:checked="mchInfo.state == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
@change="change"
/>
</view>
</JInput>
</JMainCard>
<view class="page-title">经营统计</view>
<JMainCard pd="0" wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.1)">
<ScreenTitle bdR="20rpx 20rpx 0 0" :index="index" @search="getStatic" />
<view class="mch-info">
<view class="mch-many">
<text>收款金额</text>
{{ (orderCount.payAmount / 100).toFixed(2) }}
</view>
<view class="mch-footer">
<view>
<text>收款笔数</text>
{{ orderCount.payCount }}
</view>
</view>
<view class="mch-footer">
<view>
<text>退款金额</text>
{{ (orderCount.refundAmount / 100).toFixed(2) }}
</view>
<view>
<text>退款笔数</text>
{{ orderCount.refundCount }}
</view>
</view>
</view>
</JMainCard>
<JButton color="#FF4D6A" bgColor="rgba(255,255,255,0.85)" size="max" pdTop="0" @HandleTouch="deletedTips.open()"
>删除商户</JButton
>
</view>
<JDeletedTips ref="deletedTips" @confirm="deleted" />
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancel" />
</template>
<script setup>
import { ref } from "vue"
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app"
import { $getQRcodeList, $findMer, $getQRcode, $delMchInfo, $getStatic, $editMer } from "@/http/apiManager.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
import ScreenTitle from "@/components/newComponents/ScreenTitle/ScreenTitle"
onLoad((option) => {
params.mchNo = option.mchNo
})
onShow(() => {
getMchInfo()
})
const switchTips = ref(null)
const mchInfo = ref({})
const orderCount = ref({})
const index = ref(0)
const params = {
queryDateRange: "",
countType: 1,
mchNo: "",
}
const deletedTips = ref(null)
const deleted = () => {
$delMchInfo(params.mchNo).then((res) => {
uni.showToast({
title: "删除成功",
icon: "success",
})
uni.navigateBack()
})
}
const getMchInfo = () => {
getStatic()
$findMer(params.mchNo).then(({ bizData }) => {
mchInfo.value = bizData
})
}
const getStatic = (data) => {
if (data) {
index.value = data.i
if (data.val.value != "customer") {
params.queryDateRange = data?.val.value
}
}
$getStatic(params).then(({ bizData }) => {
orderCount.value = bizData.orderCount
})
}
let flag = undefined
const change = (e) => {
flag = true
mchInfo.value.state = e.detail.value ? 1 : 0
switchTips.value.open("确认修改吗?")
}
const confirm = () => {
flag = false
$editMer(mchInfo.value.mchNo, { state: mchInfo.value.state }).then(() => {
uni.showToast({
title: "修改成功",
icon: "success",
})
})
}
const cancel = (val) => {
if (!flag) return
mchInfo.value.state = Number(!mchInfo.value.state)
}
const editMch = () => {
uni.navigateTo({
url: "./editMerchant?mchNo=" + params.mchNo,
})
}
const headerBgColor = ref("transparent")
onPageScroll((data) => {
if (data.scrollTop > 20) {
headerBgColor.value = "$primaryColor"
} else {
headerBgColor.value = "transparent"
}
})
</script>
<style lang="scss" scoped>
.page-wrapper {
position: relative;
width: 100%;
min-height: 100%;
background-color: $primaryColor;
text {
color: #fff;
font-weight: 400;
}
.bg-image {
position: absolute;
top: -40rpx;
right: 0;
width: 100%;
height: 650rpx;
}
.expand-header {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50rpx;
image {
width: 93rpx;
height: 93rpx;
}
.expand-title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
.expand-phone {
margin: 30rpx 0;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
}
.expand-edit {
position: relative;
z-index: 40;
padding: 20rpx 41rpx;
font-size: 28rpx;
color: $primaryColor;
image {
width: 26.25rpx;
height: 26.25rpx;
}
}
}
.right-color {
color: #fff;
font-size: 30rpx;
}
.page-title {
margin-bottom: 30rpx;
text-align: center;
font-size: 33rpx;
color: #fff;
}
.mch-info {
border-top: 1rpx solid rgba(0, 0, 0, 0.1);
padding: 60rpx;
view {
display: flex;
flex-direction: column;
}
text {
margin-bottom: 20rpx;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
}
.mch-many {
color: #fff;
font-size: 56rpx;
font-weight: 700;
}
.mch-footer {
display: flex;
flex-direction: row;
margin-top: 50rpx;
view {
flex: 1;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,101 @@
<template>
<view class="mch-wrapper bgF2">
<view class="mch-header">
<JHeaderTitle title="商户管理" bgColor="#f2f2f2" />
<JSearchInput
@search="searchList"
place="搜索商户名、用户号、联系人手机号"
@resetSearch="searchList"
ref="search"
></JSearchInput>
</view>
<block v-for="(v, i) in useDataResult.dataList" :key="v.agentNo">
<JPreview
:title="v.mchName"
:qrcId="v.mchNo"
:img="imgList[v.state]"
:spot="v.state === 1 ? '#7737FE':'#B2B2B2'"
:status="v.state === 1 ? '已启用' : '已禁用'"
:isLast="useDataResult.dataList.length - 1 == i"
@tap="toDetail(v.mchNo)"
></JPreview>
</block>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
<view class="button-block"></view>
<view class="mch-footers">
<JButton pd="30rpx 30rpx 50rpx 30rpx" pdTop="0" @HandleTouch="createMch">创建商户</JButton>
</view>
</view>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from "vue"
import { onBackPress, onShow } from "@dcloudio/uni-app"
import { $getMerList } from "@/http/apiManager.js"
import useGetList from "@/hooks/useList.js"
import JButton from "@/components/newComponents/JButton/JButton.vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue"
import JPreview from "@/components/newComponents/JPreview/JPreview.vue"
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull"
const { useDataResult, getList } = useGetList({
requestFun: $getMerList,
})
// 获取搜索组件暴露出来的数据
const search = ref()
onBackPress(() => {
if (search.value.searchText != "") {
search.value.searchText = ""
list(search.value.searchText)
return true
} else {
return false
}
})
// 下拉 加载数据
// 搜索回调
const searchList = (data) => {
if (data === "reset") data = ""
getList({ unionMchInfo: data })
}
const imgList = reactive(["/static/navImg/disable-shangdian.svg", "/static/navImg/nav-shangdian.svg"])
// 跳转创建商户
const createMch = () => {
uni.navigateTo({
url: "./addMch",
})
}
function toDetail(mchNo) {
uni.navigateTo({
url: "./merchantDetail?mchNo=" + mchNo,
})
}
</script>
<style lang="scss" scoped>
.mch-wrapper {
width: 100%;
min-height: 100vh;
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.button-block {
height: 210rpx;
}
.mch-footers {
position: fixed;
left: 0;
right: 0;
bottom: 0;
backdrop-filter: blur(30px);
border-top: 1px solid rgba($color: #000000, $alpha: 0.1);
}
}
</style>

View File

@@ -0,0 +1,252 @@
<template>
<view>
<JHeaderTitle :title="vdata.title" bgColor="#f2f2f2" />
<JSearchInput :place="vdata.text" @search="search" @resetSearch="resetSearch" ref="JSearchRef" />
<view v-for="(item, index) in vdata.dataList" :key="index" @click.stop="select(item)">
<JPreview
:img="vdata.icon"
:title="item[vdata.renderName]"
:qrcId="item[vdata.renderId]"
:isLast="index === vdata.dataList.length - 1"
>
<view class="check" v-if="isCheck(item[vdata.renderId])">
<image src="/static/equipmentImg/check.svg" />
</view>
</JPreview>
</view>
</view>
</template>
<script setup>
import { onLoad, onBackPress, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app"
import { ref, reactive, toRaw } from "vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.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 JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue"
import JPreview from "@/components/newComponents/JPreview/JPreview.vue"
import useStore from "@/hooks/useStore.js"
import { $getMerList, $getMchStoreList, $getMchAppList, $getTeams } from "@/http/apiManager.js"
const { getStore, setStore } = useStore()
const vdata = reactive({
title: "", // 导航栏标题
searchHandle: "", // 搜索函数
tag: "", // 搜索内容 商户or门店or应用orPOS机
icon: "", // 左侧渲染的图标
iconClose: "", // pos 会有未启用状态
renderName: "", // 用于列表渲染的字段 (上)
renderId: "", // 用于列表渲染的字段 (下)
dataList: [], // 用于保存请求后的列表
isLoad: false, // 是否为上拉加载
titlePage: "", // 总页数
listTipText: "加载更多", // 提示文字
})
const mchInfo = {
title: "选择商户",
searchHandle: $getMerList,
tag: "mch",
text: "搜索商户",
renderName: "mchName", // 用于列表渲染的字段 (上)
renderId: "mchNo", // 用于列表渲染的字段 (下)
icon: "/static/equipmentImg/mch-list.svg", // 左侧渲染的图标
}
const storeInfo = {
title: "选择门店",
searchHandle: $getMchStoreList,
tag: "store",
text: "搜索门店",
renderName: "storeName", // 用于列表渲染的字段 (上)
renderId: "storeId", // 用于列表渲染的字段 (下)
icon: "/static/equipmentImg/store-list.svg", // 左侧渲染的图标
}
const appInfo = {
title: "选择应用",
searchHandle: $getMchAppList,
tag: "app",
text: "搜索应用名称",
renderName: "appName", // 用于列表渲染的字段 (上)
renderId: "appId", // 用于列表渲染的字段 (下)
icon: "/static/equipmentImg/app-list.svg", // 左侧渲染的图标
}
const posInfo = {
title: "选择扫码POS",
searchHandle: $getMchStoreList,
tag: "pos",
text: "搜索设备名称",
renderName: "deviceName", // 用于列表渲染的字段 (上)
renderId: "deviceNo", // 用于列表渲染的字段 (下)
iconOn: "/static/equipmentImg/opse-open.svg", // 左侧渲染的图标
iconClose: "/static/equipmentImg/opse-close.svg", // 左侧渲染的图标
}
const teamInfo = {
title: "选择团队",
searchHandle: $getTeams,
tag: "team",
text: "搜索团队名称",
renderName: "teamName", // 用于列表渲染的字段 (上)
renderId: "teamId", // 用于列表渲染的字段 (下)
iconOn: "/static/iconImg/expand-fill.svg", // 左侧渲染的图标
iconClose: "/static/iconImg/expand-team-close.svg", // 左侧渲染的图标
}
// 判断右侧 勾选标志是否展示, 只要ID一致就显示否则都是false
const isCheck = (id) => {
if ([getStore("mchInfo").mchNo, getStore("storeInfo").storeId, getStore("appInfo").appId].includes(id)) {
return true
}
return false
}
onLoad((option) => {
switch (option.name) {
case "mch":
Object.assign(vdata, mchInfo)
break
case "store":
Object.assign(vdata, storeInfo)
break
case "app":
Object.assign(vdata, appInfo)
break
case "team":
Object.assign(vdata, teamInfo)
break
default:
null
}
// 请求列表
getList()
})
// 选择函数,选择后返回,同时将值赋值给对应的对象中
const select = (item) => {
setStore(`${vdata.tag}Info`, toRaw(item))
uni.navigateBack({})
}
const store = reactive({
mchInfo: {}, // 商户信息
storeInfo: {}, // 门店信息
application: {}, // 应用信息
bindMch: {}, // 商户绑定信息
})
// 请求列表默认参数
const params = reactive({
pageNumber: 1, // 默认是1
pageSize: 10, // 默认10条可传参修改
})
// 请求列表函数
const getList = (searchText) => {
// 根据不同的搜索内容 增加不同的搜索条件
switch (vdata.tag) {
case "mch":
searchText ? (params.mchName = searchText) : (params.mchName = "")
break
case "store":
params.mchNo = getStore("mchInfo").mchNo
searchText ? (params.storeName = searchText) : (params.storeName = "")
break
case "app":
params.mchNo = getStore("mchInfo").mchNo
searchText ? (params.appName = searchText) : (params.appName = "")
break
case "pos":
params.deviceType = 3
params.mchNo = getStore("mchInfo").mchNo
params.storeId = getStore("storeInfo").storeId
params.appId = getStore("appInfo").appId
searchText ? (params.appSearchData = searchText) : (params.appSearchData = "")
break
case "team":
params.teamName = ""
break
default:
null
}
vdata.listTipText = "加载中..."
uni.showLoading({ title: "加载中..." })
vdata.searchHandle(toRaw(params)).then(({ bizData }) => {
uni.hideLoading()
uni.stopPullDownRefresh() // 请求成功停止下拉刷新
vdata.titlePage = Math.ceil(bizData.total / params.pageSize)
if (vdata.titlePage == params.pageNumber || bizData.records.length == 0) {
vdata.listTipText = "暂无更多"
}
let data = bizData.records ? bizData.records : bizData
if (vdata.isLoad) {
vdata.dataList.push(...data)
} else {
vdata.dataList = data
}
})
}
// 搜索
const search = (e) => {
vdata.isLoad = false // 搜索时,不是上拉加载,此时应将状态改为,请求后重置列表数据
getList(e)
}
// 取消搜索 清空字段
const resetSearch = () => {
getList()
}
// 下拉刷新
onPullDownRefresh(() => {
params.pageNumber = 1
vdata.isLoad = false
getList()
})
// 上拉加载
onReachBottom(() => {
params.pageNumber++
if (params.pageNumber > vdata.titlePage) {
params.pageNumber = params.pageNumber
return (vdata.isLoad = false)
}
vdata.isLoad = true
getList()
})
// 返回前清除搜索数据
const JSearchRef = ref(null)
onBackPress(() => {
if (JSearchRef.value.searchText != "") {
JSearchRef.value.searchText = ""
getList()
return true
}
return false
})
</script>
<style lang="scss">
page {
background: #f2f2f2;
}
</style>
<style scoped lang="scss">
.check {
width: 50rpx;
height: 100%;
display: flex;
align-items: center;
image {
width: 50rpx;
height: 50rpx;
}
}
</style>

View File

@@ -0,0 +1,141 @@
<template>
<view class="page-wrapper global-wrapper">
<JHeaderTitle
title="关于我们"
bgColor="#7737fe"
color="#fff"
imgUrl="/static/iconImg/left-white.svg"
></JHeaderTitle>
<view class="header-card">
<!-- #ifdef APP-PLUS -->
<view>{{ edition }}</view>
<!-- #endif-->
</view>
<JMainCard bgColor="rgba(0, 0, 0, 0.1)" wrapPd="50rpx 50rpx 0 50rpx" pd="40rpx">
<view class="company-info">
<view class="company-title">公司名称</view>
<view>{{ companyInfo.companyName }}</view>
</view>
<view class="company-info">
<view class="company-title" @tap="callPhone(companyInfo.companyTel)">联系电话</view>
<view>{{ companyInfo.companyTel }}</view>
</view>
<view class="company-info">
<view class="company-title">电子邮箱</view>
<view>{{ companyInfo.companyEmail }}</view>
</view>
</JMainCard>
<JMainCard bgColor="rgba(0, 0, 0, 0.1)" wrapPd="30rpx 50rpx" pd="0">
<view class="service-wrapper" @tap="jumpPage('/pages/login/serviceAgreement')">
服务协议 <image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
<view class="service-wrapper privacy" @tap="jumpPage('/pages/login/privacyPolicy')">
隐私政策 <image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<!-- #ifdef APP-PLUS -->
<JMainCard bgColor="rgba(0, 0, 0, 0.1)" wrapPd="0 50rpx" pd="0">
<view class="service-wrapper" @tap="checkCurrVersion(1)">
检查更新
<view class="edition">v{{ edition }} <image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" /></view>
</view>
</JMainCard>
<!-- #endif -->
</view>
</template>
<script setup>
import { ref } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { $getCompanyInfo } from "@/http/apiManager.js"
import JHeaderTitle from "@/components//newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components//newComponents/JMainCard/JMainCard"
import { checkCurrVersion, getCurrentVersionPromise } from "@/util/versionManage.js"
onLoad(() => {
getCompanyInfo()
// #ifdef APP-PLUS
getCurrentVersionPromise().then((res) => {
edition.value = res.version
})
// #endif
})
const companyInfo = ref({})
const edition = ref("v1.0.0")
const getCompanyInfo = () => {
$getCompanyInfo().then(({ bizData }) => {
companyInfo.value = bizData
})
}
const callPhone = (phoneNumber) => {
uni.makePhoneCall({
phoneNumber,
})
}
const jumpPage = (url) => {
uni.navigateTo({
url,
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
background-color: $primaryColor;
.header-card {
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: center;
align-items: center;
image {
width: 150rpx;
height: 150rpx;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.3);
}
view {
color: rgba(255, 255, 255, 0.6);
font-size: 27rpx;
}
.header-title {
font-size: 33rpx;
color: #ffffff;
margin: 20rpx 0;
}
}
.company-info {
display: flex;
justify-content: space-between;
margin-bottom: 40rpx;
font-size: 30rpx;
view {
color: #fff;
}
.company-title {
color: rgba(255, 255, 255, 0.6);
}
&:last-child {
margin-bottom: 0;
}
}
.service-wrapper {
display: flex;
justify-content: space-between;
padding: 32rpx 53rpx 32rpx 40rpx;
font-size: 33rpx;
color: #ffffff;
image {
width: 40rpx;
height: 40rpx;
}
}
.privacy {
border-top: 1rpx solid #5f2ccb;
}
.edition {
display: flex;
align-items: center;
color: rgba(255, 255, 255, 0.6);
}
}
</style>

View File

@@ -0,0 +1,81 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JMainCard wrapPd="30rpx" pd="32rpx">
<view class="photo-wrapper">
头像
<!-- <image :src="userInfo.avatarUrl" mode="scaleToFill" @tap="editAvatar" /> -->
<JeepayUpLoad
ref="upLoad"
:imgUrl="userInfo.avatarUrl"
:userIsShowClear="false"
@uploadSuccess="uploadSuccess"
/>
</view>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="32rpx">
<view class="photo-wrapper">
名称
<input type="text" v-model="userInfo.realname" />
</view>
</JMainCard>
<JButton pd="30rpx" @HandleTouch="modifyUserInfo">保存</JButton>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { $modifyUser, $userInfo } from "@/http/apiManager.js"
import JMainCard from "@/components//newComponents/JMainCard/JMainCard"
import JButton from "@/components//newComponents/JButton/JButton"
import JeepayUpLoad from "@/components/JeepayUpLoad/JeepayUpLoad.vue"
import jeepyPreview from "@/components/jeepayUpLoad/enlarge.vue"
onLoad(() => {
getUserInfo()
})
const userInfo = ref({})
const getUserInfo = () => {
$userInfo().then(({ bizData }) => {
userInfo.value = bizData
})
}
const uploadSuccess = (res) => {
userInfo.value.avatarUrl = res.data
}
const modifyUserInfo = () => {
uni.showLoading({
title: "正在保存",
mask: true,
})
$modifyUser({
realname: userInfo.value.realname,
avatarUrl: userInfo.value.avatarUrl,
}).then((res) => {
uni.hideLoading()
uni.showToast({
title: "保存成功",
icon: "success|none",
mask: true,
})
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.photo-wrapper {
display: flex;
justify-content: space-between;
font-size: 33rpx;
image {
width: 150rpx;
height: 150rpx;
border-radius: 10rpx;
}
input {
text-align: right;
}
}
}
</style>

View File

@@ -0,0 +1,60 @@
<template>
<view class="post-list" v-for="item in useDataResult.dataList" @tap="toDetail(item.articleId)">
<text>{{ item.title }}</text>
<text>{{ item.createdAt ? item.createdAt.slice(0, 10) : '' }}</text>
</view>
<jeepayListNull :list="useDataResult.dataList"></jeepayListNull>
</template>
<script setup>
import { ref, reactive, watch } from 'vue'
import { onBackPress } from '@dcloudio/uni-app'
import useGetList from '@/hooks/useGetList.js'
import { $getNoticeList } from '@/http/apiManager.js'
import jeepayListNull from '@/components/jeepayListNull/jeepayListNull.vue'
const switchStatePopup = ref()
const { useDataResult, getList } = useGetList($getNoticeList, undefined, { articleType: 1 })
let vdata = reactive({})
// 跳转
const toDetail = (articleId) => {
uni.navigateTo({
url: './postDetail?id=' + articleId
})
}
</script>
<style>
page {
background: #f5f6fc;
}
</style>
<style scoped lang="scss">
.post-list {
box-sizing: border-box;
width: 750rpx;
height: 150rpx;
background: #fff;
margin-top: 2rpx;
padding: 30rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
text {
&:nth-child(1) {
font-weight: bold;
font-size: 30rpx;
color: #000;
overflow: hidden;
text-overflow: ellipsis; //溢出用省略号显示
white-space: nowrap;
}
&:nth-child(2) {
font-weight: 500;
font-size: 23rpx;
color: #a6a6a6;
}
}
}
</style>

View File

@@ -0,0 +1,153 @@
<template>
<view class="page-wrapper global-wrapper bgF2" v-if="flag">
<JHeaderTitle title="修改密码" bgColor="#f2f2f2"></JHeaderTitle>
<view class="origin-pwd">
<LoginInput
title="原密码"
v-model:value="pwdInfo.oldPassword"
bgColor="#fff"
pd="30rpx 30rpx 20rpx 30rpx"
place="请输入原密码"
:password="!oldPasswordEyes"
:rules="{ name: 'oldPassword', rule: 'REG_NotNUll' }"
>
<view class="right-eyes" @tap="oldPasswordEyes = !oldPasswordEyes">
<image :src="eyeImg[oldPasswordEyes ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
<view class="forget" @tap="jumpPage">忘记原密码</view>
</view>
<view class="edit-pwd">
<LoginInput
title="新密码"
v-model:value="pwdInfo.newPassword"
place="请输入新密码"
bgColor="#fff"
pd="50rpx 30rpx 30rpx 30rpx"
:password="!isOpenEyes"
:rules="{ name: 'newPassword', rule: 'REG_NotNUll' }"
>
<view class="right-eyes" @tap="isOpenEyes = !isOpenEyes">
<image :src="eyeImg[isOpenEyes ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
<LoginInput
title=""
v-model:value="pwdInfo.confirmPassword"
place="请再次输入新密码"
bgColor="#fff"
pd="0 30rpx"
:password="!confirmOpenEyes"
:rules="{ name: 'confirmPassword', rule: 'REG_NotNUll' }"
>
<view class="right-eyes" @tap="confirmOpenEyes = !confirmOpenEyes">
<image :src="eyeImg[confirmOpenEyes ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
</view>
<JButton pd="30rpx" @HandleTouch="editPwd.open()">确认修改</JButton>
</view>
<JPopup ref="editPwd">
<JCard @confirm="confirm" title="确认修改" @tap.stop>
密码修改成功后当前账号将退出登录重新登录需使用更新后的密码</JCard
>
<JButton pd="0 30rpx 30rpx 30rpx" bgColor="rgba(255, 255, 255, 0.8)" color="#000" @HandleTouch="editPwd.close()"
>取消</JButton
>
</JPopup>
</template>
<script setup>
import { ref, reactive } from "vue"
import { $modifyPwd, $getPasswordRules } from "../../http/apiManager.js"
import { onShow } from "@dcloudio/uni-app"
import JMainCard from "@/components//newComponents/JMainCard/JMainCard"
import LoginInput from "@/components//newComponents/LoginInput/LoginInput"
import JButton from "@/components//newComponents/JButton/JButton"
import JPopup from "@/components//newComponents/JPopup/JPopup"
import JCard from "@/components/newComponents/JCard/JCard"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import user from "@/hooks/user.js"
import { validateArray, clearRulesArray } from "@/hooks/rules"
import { Base64 } from "js-base64"
onShow(() => {
flag.value = true
getRules()
})
const eyeImg = reactive(["/static/loginImg/login-eye-close.svg", "/static/loginImg/login-eye-open.svg"])
const isOpenEyes = ref(false)
const confirmOpenEyes = ref(false)
const oldPasswordEyes = ref(false)
const editPwd = ref()
const pwdInfo = reactive({})
const flag = ref(true)
const rules = ref({})
const getRules = () => {
$getPasswordRules().then((res) => {
rules.value.rule = new RegExp(res.bizData.regexpRules)
rules.value.ruleText = res.bizData.errTips
})
}
const confirm = () => {
if (validateArray(pwdInfo)) {
if (pwdInfo.newPassword !== pwdInfo.confirmPassword)
return uni.showToast({
title: "两次密码输入不一致",
icon: "error",
mask: true,
})
if (!rules.value.rule.test(pwdInfo.newPassword))
return uni.showToast({
title: rules.value.ruleText,
icon: "none",
})
uni.showLoading({
title: "修改中",
mask: true,
})
$modifyPwd({
originalPwd: Base64.encode(pwdInfo.oldPassword),
confirmPwd: Base64.encode(pwdInfo.newPassword),
}).then((res) => {
uni.hideLoading()
uni.showToast({
title: "修改成功",
icon: "success",
mask: true,
})
clearRulesArray()
editPwd.value.close()
user.logout()
})
}
}
const jumpPage = () => {
flag.value = false
uni.navigateTo({ url: "/pages/login/forgetPassword" })
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.origin-pwd {
font-size: 33rpx;
.forget {
margin-left: 50rpx;
font-size: 27rpx;
color: $primaryColor;
}
}
}
.right-eyes {
display: flex;
justify-content: center;
align-items: center;
width: 110rpx;
height: 110rpx;
background-color: transparent;
}
image {
width: 36rpx;
height: 36rpx;
}
</style>

View File

@@ -0,0 +1,60 @@
<template>
<view class="content">
<view class="title">
<span>{{ content.title }}</span>
</view>
<view class="updatedAt">
<span>作者{{ content.publisher }}</span>
&nbsp&nbsp
<span>时间{{ content.updatedAt }}</span>
</view>
<!-- map-html 解析时出现横向滚动条 -->
<!-- <mp-html :content="content.content" /> -->
<view class="content-text" v-html="content.content"></view>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { $noticeDetail } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import parseHtml from "@/util/html-parse.js"
const content = ref({})
onLoad((options) => {
$noticeDetail(options.id).then(({ bizData }) => {
content.value = bizData
})
})
</script>
<style lang="scss" scoped>
.content {
box-sizing: border-box;
padding: 0 50rpx 40rpx 50rpx;
.title {
// height: 60rpx;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
font-size: 35rpx;
padding: 20rpx 0;
font-weight: 700;
color: rgba(0, 0, 0, 0.8);
}
.updatedAt {
padding: 0rpx 0 40rpx 0;
color: #969696;
font-size: 20rpx;
span {
&:nth-child(2) {
margin-left: 30rpx;
}
}
}
}
.content-text {
img {
width: 100% !important;
}
}
</style>

View File

@@ -0,0 +1,58 @@
<template>
<view class="page-wrapper bgF2">
<JHeaderTitle title="密码与安全" bgColor="#f2f2f2"></JHeaderTitle>
<block v-for="(v, i) in list" :key="i">
<view class="setting-wrapper bgF" @tap="jumpPage(v.url)">
<view class="setting-main" :class="[v.isBorder]">
{{ v.title }}
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</view>
</block>
</view>
</template>
<script setup>
import { reactive } from 'vue'
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle.vue'
const list = reactive([
{
title: '登录密码',
url: '/pageWork/setUp/passwordSetting'
},
{
title: '支付密码',
url: '/pageWork/setUp/takeMoneyPwd'
}
])
const jumpPage = (url) => {
uni.navigateTo({
url
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
width: 100%;
height: 100%;
.setting-wrapper {
padding-left: 32rpx;
.setting-main {
display: flex;
justify-content: space-between;
align-items: center;
height: 110rpx;
border-bottom: 1rpx solid #f2f2f2;
image {
width: 40rpx;
height: 40rpx;
margin-right: 50rpx;
}
}
.isBorder {
border: none;
}
}
}
</style>

View File

@@ -0,0 +1,111 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle title="设置" bgColor="#f2f2f2"></JHeaderTitle>
<block v-for="(v, i) in list" :key="i">
<view class="setting-wrapper bgF" @tap="phoneOpen(v.title), jumpPage(v.url)">
<view class="setting-main" :class="[v.isBorder]">
{{ v.title }}
<image src="/static/iconImg/right-arrow.svg" mode="aspectFill" />
</view>
</view>
</block>
<view class="login-uot bgF" @tap="logOut.open('账号退出后,系统不会主动删除任何数据,您仍可使用本账号再次登录。')"
>退出登录</view
>
</view>
<JPopup ref="phone" type="center" dir="center">
<callPhone @cancel="phone.close()" :phoneNumber="phoneNumber" @tap.stop></callPhone>
</JPopup>
<JDeletedTips ref="logOut" @confirm="confirm" />
</template>
<script setup>
import { reactive, ref } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import user from "@/hooks/user.js"
import { $getCompanyInfo } from "@/http/apiManager.js"
import JPopup from "@/components/newComponents/JPopup/JPopup"
import JCard from "@/components/newComponents/JCard/JCard"
import JButton from "@/components/newComponents/JButton/JButton"
import callPhone from "@/components/newComponents/callPhone/callPhone"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
import { clearRulesArray } from "@/hooks/rules"
onLoad(() => {
getPhoneNumber()
})
const logOut = ref(null)
const list = reactive([
{
title: "账号设置",
url: "/pageWork/setUp/accountSetting",
},
{
title: "密码与安全",
url: "/pageWork/setUp/pwSetting",
},
{
title: "注销账号",
},
{
title: "关于我们",
url: "/pageWork/setUp/aboutUs",
isBorder: "isBorder",
},
])
const loginOut = ref()
const phone = ref()
const phoneNumber = ref("")
const confirm = () => {
user.logout()
uni.showToast({
icon: "none",
title: "退出成功",
})
}
const phoneOpen = (v) => {
if (v === "注销账号") return phone.value.open()
}
const getPhoneNumber = () => {
$getCompanyInfo().then(({ bizData }) => {
phoneNumber.value = bizData.companyTel
})
}
const jumpPage = (url) => {
if (!url) return
clearRulesArray()
uni.navigateTo({ url })
}
</script>
<style lang="scss" scoped>
.page-wrapper {
font-size: 33rpx;
.setting-wrapper {
padding-left: 32rpx;
.setting-main {
display: flex;
justify-content: space-between;
align-items: center;
height: 110rpx;
border-bottom: 1rpx solid #f2f2f2;
image {
width: 40rpx;
height: 40rpx;
margin-right: 50rpx;
}
}
.isBorder {
border: none;
}
}
.login-uot {
height: 110rpx;
line-height: 110rpx;
margin-top: 20rpx;
text-align: center;
color: #ff4433;
}
}
</style>

View File

@@ -0,0 +1,280 @@
<template>
<view class="border"></view>
<!-- v-if="vdata.index === 0" -->
<view class="pw-box" v-if="vdata.index === 0">
<view class="disc">
<text>验证密码</text>
<text>请输入支付密码以验证身份</text>
</view>
<view class="">
<verification-code-style
:latticeNum="6"
ref="verCode"
@getInputVerification="getInputVerification1"
ciphertextSty="1"
></verification-code-style>
</view>
</view>
<view class="pw-box" v-if="vdata.index === 1">
<view class="disc">
<text>设置新密码</text>
<text>请输入新的支付密码</text>
</view>
<view class="">
<verification-code-style
:latticeNum="6"
@getInputVerification="getInputVerification2"
ciphertextSty="1"
></verification-code-style>
</view>
</view>
<view class="" style="width: 580rpx; margin: 0 auto" v-if="vdata.index === 2">
<view class="pw-box">
<view class="disc">
<text>验证新密码</text>
<text>请再输入一次新的支付密码</text>
</view>
<view class="">
<verification-code-style
:latticeNum="6"
ref="newVerCode"
@getInputVerification="getInputVerification3"
ciphertextSty="1"
></verification-code-style>
</view>
<view class="left" @click="back"> <text style="margin-left: 10rpx">重新设置密码</text> </view>
</view>
<!-- <view class="btn" @click="change">
<text>确认修改</text>
</view> -->
</view>
<JDeletedTips ref="tips" @confirm="phoneConfirm" />
</template>
<script setup>
import { ref, reactive, getCurrentInstance } from "vue"
import { $isAgentSipw, $updateAgentSipw, $isSipw } from "../../http/apiManager.js"
import { onLoad, onBackPress } from "@dcloudio/uni-app"
import { Base64 } from "js-base64"
import verificationCodeStyle from "@/components/verification-code-style2/verification-code-style2"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
const vdata = reactive({
oldPwd: "",
index: 0,
newPwd: "",
confirmPwd: "",
allowChange: false,
isBack: false, //是否允许退出
})
const { ctx } = getCurrentInstance()
const tips = ref(null)
onBackPress(() => {
if (vdata.isBack) {
return false
} else {
tips.value.open("是否退出支付密码修改?退出将不会保存您所做的修改")
return true
}
})
onLoad((options) => {
//判断是否有密码
let ispwd = ""
$isSipw()
.then((res) => {
console.log(res.bizData)
ispwd = res.bizData
if (options.pwd === "0" || !ispwd) {
vdata.index = 1
} else {
vdata.index = 0
}
})
.catch((err) => {
console.log(err)
})
})
const phoneConfirm = () => {
vdata.isBack = true
uni.navigateBack({
delta: 1,
})
}
const getInputVerification1 = (e) => {
// console.log(e)
if (e && e.length === 6) {
vdata.oldPwd = e
$isAgentSipw({
originalPwd: Base64.encode(e),
}).then((res) => {
if (res.bizData) {
vdata.index = 1
} else {
uni.showToast({
icon: "none",
title: "密码验证错误",
})
ctx.$refs.verCode.cleanVal()
}
})
}
}
const getInputVerification2 = (e) => {
if (e.length === 6) {
vdata.index = 2
vdata.newPwd = e
}
}
const getInputVerification3 = (e) => {
if (e.length === 6) {
if (e !== vdata.newPwd) {
uni.showToast({
icon: "none",
title: "两次输入的密码不一致",
})
ctx.$refs.newVerCode.cleanVal()
} else {
vdata.allowChange = true
vdata.confirmPwd = e
change()
}
}
}
const change = () => {
if (vdata.allowChange) {
$updateAgentSipw({
originalPwd: Base64.encode(vdata.oldPwd),
confirmPwd: Base64.encode(vdata.newPwd),
}).then((res) => {
uni.showToast({
icon: "success",
title: "修改成功",
})
vdata.isBack = true
uni.navigateBack({
delta: 1,
})
})
}
}
const back = () => {
vdata.index = 1
}
</script>
<style>
page {
background: #fff;
}
</style>
<style lang="scss" scoped>
.border {
height: 1rpx;
width: 100%;
background-color: #f5f6fc;
}
.swiper {
background-color: #ff5500;
margin-top: 154rpx;
height: 80vh;
.swiper-item {
width: 100%;
background-color: #3981ff;
}
}
.btn {
width: 393rpx;
height: 120rpx;
border-radius: 20rpx;
background: $primaryColor;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
font-weight: 500;
font-size: 33rpx;
color: #fff;
margin-top: 500rpx;
}
.pw-box {
// height: 400rpx;
width: 580rpx;
// background-color: aqua;
margin: 0 auto;
margin-top: 156rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
.disc {
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: column;
margin-bottom: 182rpx;
text {
&:nth-child(1) {
font-weight: bold;
font-size: 40rpx;
color: #000;
margin-bottom: 30rpx;
}
&:nth-child(2) {
font-weight: bold;
font-size: 33rpx;
color: #2e2e2e;
}
}
}
.left {
display: flex;
justify-content: center;
align-items: center;
color: #2735b4;
font-size: 25rpx;
margin-top: 53rpx;
}
}
.popview {
box-sizing: border-box;
width: 630rpx;
height: 412rpx;
border-radius: 20rpx;
background: #fff;
padding: 50rpx 50rpx 30rpx 50rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
position: absolute;
top: -500rpx;
left: -310rpx;
.title {
font-weight: bold;
font-size: 33rpx;
color: #000;
}
.content {
height: 30%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.op {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
button {
width: 45%;
height: 110rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
}
</style>

View File

@@ -0,0 +1,18 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 600" class="design-iconfont">
<g clip-path="url(#i7qr1qpp5__clip0_281_1223)">
<mask id="i7qr1qpp5__q47syx7zma" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="750" height="600">
<path fill="#D8D8D8" d="M0 0H750V600H0z"/>
</mask>
<g opacity=".05" clip-path="url(#i7qr1qpp5__clip1_281_1223)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M415.313 43.9783C411.001 27.8838 420.552 11.3403 436.647 7.02781C452.741 2.71536 469.285 12.2667 473.597 28.3612C477.91 44.4553 468.358 60.9992 452.264 65.3116C436.17 69.624 419.626 60.0724 415.313 43.9783ZM425.492 -34.6035C386.405 -24.1303 363.209 16.0462 373.682 55.1333C382.214 86.975 410.459 108.271 441.768 109.41L473.962 229.56L385.053 318.469C369.102 309.75 349.901 306.917 330.957 311.993C291.87 322.466 268.674 362.643 279.147 401.73C289.62 440.816 329.797 464.013 368.884 453.539C407.971 443.066 431.167 402.889 420.694 363.803C419.325 358.696 417.45 353.862 415.137 349.337L504.439 260.036L626.43 292.723C626.688 297.797 627.482 302.922 628.85 308.027C639.323 347.114 679.5 370.31 718.587 359.837C757.673 349.364 780.87 309.186 770.396 270.1C759.923 231.014 719.746 207.817 680.66 218.29C661.714 223.367 646.502 235.422 637.048 250.948L515.594 218.405L483.4 98.2553C509.947 81.6153 523.761 49.0488 515.228 17.2061C504.755 -21.881 464.578 -45.0766 425.492 -34.6035ZM288.568 153.794C272.473 158.107 262.922 174.65 267.234 190.745C271.547 206.839 288.09 216.39 304.185 212.078C320.279 207.766 329.83 191.222 325.518 175.128C321.206 159.033 304.662 149.482 288.568 153.794ZM225.603 201.9C215.13 162.813 238.325 122.636 277.413 112.163C316.499 101.69 356.676 124.886 367.149 163.972C377.622 203.059 354.426 243.236 315.34 253.709C276.253 264.183 236.076 240.986 225.603 201.9ZM320.779 390.575C316.466 374.48 326.017 357.937 342.112 353.624C358.206 349.312 374.75 358.863 379.062 374.958C383.375 391.052 373.823 407.596 357.729 411.908C341.635 416.221 325.091 406.669 320.779 390.575ZM543.735 406.688C527.641 411 518.09 427.544 522.402 443.638C526.714 459.733 543.258 469.284 559.353 464.972C575.447 460.659 584.998 444.116 580.686 428.021C576.373 411.927 559.83 402.376 543.735 406.688ZM480.771 454.794C470.298 415.707 493.494 375.53 532.58 365.057C571.667 354.584 611.844 377.78 622.317 416.866C632.79 455.953 609.594 496.13 570.508 506.603C531.421 517.076 491.244 493.88 480.771 454.794ZM670.481 296.872C666.169 280.778 675.721 264.234 691.815 259.922C707.909 255.609 724.453 265.161 728.765 281.255C733.078 297.349 723.526 313.893 707.432 318.206C691.338 322.518 674.794 312.966 670.481 296.872ZM638.27 60.0916C622.176 64.404 612.625 80.9479 616.937 97.042C621.249 113.136 637.793 122.688 653.887 118.375C669.982 114.063 679.533 97.5191 675.221 81.4249C670.908 65.3308 654.364 55.7792 638.27 60.0916ZM575.306 108.197C564.833 69.1106 588.029 28.9335 627.115 18.4603C666.202 7.98713 706.379 31.1834 716.852 70.2699C727.325 109.356 704.129 149.533 665.042 160.007C625.956 170.48 585.779 147.284 575.306 108.197Z" fill="#fff"/>
</g>
</g>
<defs>
<clipPath id="i7qr1qpp5__clip0_281_1223">
<path fill="#fff" d="M0 0H750V600H0z"/>
</clipPath>
<clipPath id="i7qr1qpp5__clip1_281_1223">
<path fill="#fff" transform="rotate(-15 121.90476006 -439.62837427)" d="M0 0H620.638V620.638H0z"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 47 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -0,0 +1,15 @@
<svg width="750" height="600" viewBox="0 0 750 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_406_29)">
<g clip-path="url(#clip1_406_29)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M270.831 -29.0049L524.237 -96.9049C542.89 -101.904 558.558 -106.102 571.587 -108.123C585.283 -110.247 598.576 -110.426 611.764 -105.364C619.193 -102.512 626.127 -98.5089 632.311 -93.501C643.29 -84.6111 649.781 -73.0095 654.789 -60.0866C659.554 -47.7922 663.752 -32.1246 668.749 -13.4712L745.061 271.329C750.06 289.982 754.258 305.649 756.279 318.679C758.403 332.375 758.582 345.668 753.52 358.856C750.668 366.285 746.665 373.219 741.657 379.403C732.767 390.381 721.166 396.873 708.243 401.881C695.95 406.645 680.284 410.842 661.634 415.839L661.633 415.839L661.632 415.839L661.631 415.84L661.627 415.841L555.852 444.183L564.264 475.576L763.083 422.302C774.642 419.205 786.522 426.064 789.619 437.623C792.716 449.181 785.857 461.062 774.299 464.159L334.802 581.921C323.244 585.018 311.363 578.159 308.266 566.601C305.169 555.042 312.029 543.162 323.587 540.065L522.407 486.791L513.995 455.398L408.22 483.741L408.216 483.742L408.215 483.742L408.214 483.742L408.213 483.743C389.563 488.74 373.898 492.938 360.87 494.959C347.174 497.083 333.881 497.262 320.693 492.2C313.264 489.348 306.33 485.345 300.146 480.337C289.168 471.447 282.676 459.845 277.668 446.922C272.903 434.628 268.706 418.96 263.708 400.306L187.396 115.508C182.398 96.8542 178.199 81.1867 176.178 68.1569C174.054 54.4612 173.875 41.1682 178.937 27.9802C181.789 20.5512 185.792 13.6172 190.8 7.43301C199.69 -3.5451 211.292 -10.0367 224.215 -15.0449C236.509 -19.8096 252.177 -24.0072 270.831 -29.0049ZM239.873 25.3603C230.408 29.0284 226.662 32.0041 224.476 34.7036C222.33 37.3539 220.615 40.3256 219.392 43.5095C218.148 46.7524 217.443 51.4842 218.999 61.5152C220.618 71.9492 224.175 85.3397 229.557 105.425L305.261 387.958C310.643 408.043 314.258 421.418 318.073 431.264C321.741 440.729 324.717 444.475 327.416 446.661C330.067 448.807 333.038 450.522 336.222 451.745C339.465 452.989 344.197 453.694 354.228 452.138C364.662 450.519 378.053 446.962 398.138 441.58L649.278 374.287C669.363 368.906 682.739 365.291 692.584 361.476C702.049 357.807 705.795 354.832 707.981 352.132C710.127 349.482 711.843 346.51 713.065 343.326C714.31 340.083 715.014 335.352 713.458 325.321C711.84 314.887 708.282 301.496 702.901 281.411L627.196 -1.12231C621.814 -21.2075 618.2 -34.5825 614.384 -44.4278C610.716 -53.8928 607.74 -57.6387 605.041 -59.8247C602.39 -61.9709 599.419 -63.6866 596.235 -64.9088C592.992 -66.1537 588.26 -66.8577 578.229 -65.3019C567.795 -63.6835 554.405 -60.1264 534.32 -54.7446L283.179 12.5484C263.094 17.9302 249.719 21.5448 239.873 25.3603ZM433.984 73.0797C364.633 91.6621 323.478 162.946 342.06 232.296C360.643 301.647 431.926 342.803 501.277 324.22C570.628 305.638 611.783 234.354 593.201 165.004C574.618 95.6529 503.335 54.4972 433.984 73.0797ZM300.203 243.512C275.427 151.045 330.301 55.9995 422.769 31.2229C515.236 6.44629 610.281 61.3206 635.058 153.788C659.834 246.255 604.96 341.301 512.492 366.077C420.025 390.854 324.98 335.979 300.203 243.512ZM564.075 184.266C562.31 172.431 551.285 164.268 539.449 166.033C527.614 167.798 519.451 178.823 521.216 190.658C522.864 201.711 521.053 213.004 516.031 222.987C511.01 232.971 503.023 241.157 493.166 246.423C483.309 251.689 472.065 253.778 460.975 252.402C449.884 251.027 439.491 246.255 431.219 238.74C422.362 230.694 408.659 231.351 400.613 240.209C392.567 249.066 393.224 262.768 402.081 270.815C416.97 284.341 435.679 292.93 455.641 295.406C475.604 297.882 495.844 294.123 513.586 284.644C531.329 275.164 545.705 260.43 554.744 242.459C563.783 224.489 567.042 204.162 564.075 184.266Z" fill="white" fill-opacity="0.05"/>
</g>
</g>
<defs>
<clipPath id="clip0_406_29">
<rect width="750" height="600" fill="white"/>
</clipPath>
<clipPath id="clip1_406_29">
<rect width="650" height="650" fill="white" transform="translate(78 0.232422) rotate(-15)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -0,0 +1,3 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 93 93" class="design-iconfont">
<path fill-rule="evenodd" clip-rule="evenodd" d="M41.9779 15.5002C41.9779 13.0034 44.002 10.9793 46.4987 10.9793C48.9954 10.9793 51.0195 13.0034 51.0195 15.5002C51.0195 17.9969 48.9954 20.021 46.4987 20.021C44.002 20.021 41.9779 17.9969 41.9779 15.5002ZM46.4987 4.521C40.4352 4.521 35.5195 9.43651 35.5195 15.5002C35.5195 20.4398 38.7818 24.6177 43.2693 25.9967V44.6358L26.9524 54.0563C24.9819 52.1758 22.3126 51.021 19.3737 51.021C13.31 51.021 8.39453 55.9366 8.39453 62.0002C8.39453 68.0637 13.31 72.9793 19.3737 72.9793C25.4373 72.9793 30.3529 68.0637 30.3529 62.0002C30.3529 61.208 30.269 60.4355 30.1096 59.691L46.4985 50.2289L62.8878 59.6912C62.7284 60.4357 62.6445 61.2081 62.6445 62.0002C62.6445 68.0637 67.5601 72.9793 73.6237 72.9793C79.6872 72.9793 84.6029 68.0637 84.6029 62.0002C84.6029 55.9366 79.6872 51.021 73.6237 51.021C70.6847 51.021 68.0154 52.1758 66.0448 54.0565L49.7277 44.6358V25.9968C54.2154 24.6179 57.4779 20.44 57.4779 15.5002C57.4779 9.43651 52.5622 4.521 46.4987 4.521ZM19.3737 26.4793C16.8769 26.4793 14.8529 28.5034 14.8529 31.0002C14.8529 33.4969 16.8769 35.521 19.3737 35.521C21.8704 35.521 23.8945 33.4969 23.8945 31.0002C23.8945 28.5035 21.8704 26.4793 19.3737 26.4793ZM8.39453 31.0002C8.39453 24.9366 13.31 20.021 19.3737 20.021C25.4373 20.021 30.3529 24.9366 30.3529 31.0002C30.3529 37.0637 25.4373 41.9793 19.3737 41.9793C13.31 41.9793 8.39453 37.0637 8.39453 31.0002ZM14.8529 62.0002C14.8529 59.5034 16.8769 57.4793 19.3737 57.4793C21.8704 57.4793 23.8945 59.5035 23.8945 62.0002C23.8945 64.4969 21.8704 66.521 19.3737 66.521C16.8769 66.521 14.8529 64.4969 14.8529 62.0002ZM46.4987 72.9793C44.002 72.9793 41.9779 75.0034 41.9779 77.5002C41.9779 79.9969 44.002 82.021 46.4987 82.021C48.9954 82.021 51.0195 79.9969 51.0195 77.5002C51.0195 75.0034 48.9954 72.9793 46.4987 72.9793ZM35.5195 77.5002C35.5195 71.4366 40.4351 66.521 46.4987 66.521C52.5622 66.521 57.4779 71.4366 57.4779 77.5002C57.4779 83.5637 52.5622 88.4793 46.4987 88.4793C40.4351 88.4793 35.5195 83.5637 35.5195 77.5002ZM69.1029 62.0002C69.1029 59.5035 71.127 57.4793 73.6237 57.4793C76.1204 57.4793 78.1445 59.5035 78.1445 62.0002C78.1445 64.4969 76.1204 66.521 73.6237 66.521C71.127 66.521 69.1029 64.4969 69.1029 62.0002ZM73.6237 26.4793C71.127 26.4793 69.1029 28.5035 69.1029 31.0002C69.1029 33.4969 71.127 35.521 73.6237 35.521C76.1204 35.521 78.1445 33.4969 78.1445 31.0002C78.1445 28.5035 76.1204 26.4793 73.6237 26.4793ZM62.6445 31.0002C62.6445 24.9366 67.5601 20.021 73.6237 20.021C79.6872 20.021 84.6029 24.9366 84.6029 31.0002C84.6029 37.0637 79.6872 41.9793 73.6237 41.9793C67.5601 41.9793 62.6445 37.0637 62.6445 31.0002Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,3 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.8917 2H42.1083C43.8909 1.99995 45.3881 1.9999 46.5982 2.131C47.8701 2.26881 49.0596 2.57044 50.1145 3.33689C50.7088 3.76864 51.2314 4.29124 51.6631 4.88551C52.4296 5.94043 52.7312 7.12995 52.869 8.40184C53.0001 9.61184 53.0001 11.109 53 12.8915V12.8916V12.8916V12.8917V12.8917V40.1083V40.1083V40.1084V40.1084V40.1085C53.0001 41.891 53.0001 43.3882 52.869 44.5982C52.7312 45.8701 52.4296 47.0596 51.6631 48.1145C51.2314 48.7088 50.7088 49.2314 50.1145 49.6631C49.0596 50.4296 47.8701 50.7312 46.5982 50.869C45.3882 51.0001 43.891 51.0001 42.1085 51H42.1084H42.1084H42.1083H42.1083H32V54H51C52.1046 54 53 54.8954 53 56C53 57.1046 52.1046 58 51 58H32H28H9C7.89543 58 7 57.1046 7 56C7 54.8954 7.89543 54 9 54H28V51H17.8917H17.8917H17.8916H17.8916H17.8915C16.109 51.0001 14.6118 51.0001 13.4018 50.869C12.1299 50.7312 10.9404 50.4296 9.88551 49.6631C9.29124 49.2314 8.76864 48.7088 8.33689 48.1145C7.57044 47.0596 7.26881 45.8701 7.131 44.5982C6.9999 43.3881 6.99995 41.8909 7 40.1083V12.8917C6.99995 11.1091 6.9999 9.61188 7.131 8.40184C7.26881 7.12995 7.57044 5.94043 8.33689 4.88551C8.76864 4.29124 9.29124 3.76864 9.88551 3.33689C10.9404 2.57044 12.1299 2.26881 13.4018 2.131C14.6119 1.9999 16.1091 1.99995 17.8917 2ZM13.8327 6.10773C12.9011 6.20866 12.4961 6.38449 12.2366 6.57295C11.982 6.75799 11.758 6.98196 11.573 7.23665C11.3845 7.49605 11.2087 7.90113 11.1077 8.83269C11.0027 9.80168 11 11.0806 11 13V40C11 41.9194 11.0027 43.1983 11.1077 44.1673C11.2087 45.0989 11.3845 45.504 11.573 45.7634C11.758 46.018 11.982 46.242 12.2366 46.4271C12.4961 46.6155 12.9011 46.7913 13.8327 46.8923C14.8017 46.9973 16.0806 47 18 47H42C43.9194 47 45.1983 46.9973 46.1673 46.8923C47.0989 46.7913 47.504 46.6155 47.7634 46.4271C48.018 46.242 48.242 46.018 48.4271 45.7634C48.6155 45.504 48.7913 45.0989 48.8923 44.1673C48.9973 43.1983 49 41.9194 49 40V13C49 11.0806 48.9973 9.80168 48.8923 8.83269C48.7913 7.90113 48.6155 7.49605 48.4271 7.23665C48.242 6.98196 48.018 6.75799 47.7634 6.57295C47.504 6.38449 47.0989 6.20866 46.1673 6.10773C45.1983 6.00275 43.9194 6 42 6H18C16.0806 6 14.8017 6.00275 13.8327 6.10773ZM30 15C23.3726 15 18 20.3726 18 27C18 33.6274 23.3726 39 30 39C36.6274 39 42 33.6274 42 27C42 20.3726 36.6274 15 30 15ZM14 27C14 18.1634 21.1634 11 30 11C38.8366 11 46 18.1634 46 27C46 35.8366 38.8366 43 30 43C21.1634 43 14 35.8366 14 27ZM38.9429 28.0217C39.0682 26.9242 38.2803 25.9329 37.1828 25.8075C36.0854 25.6822 35.0941 26.4702 34.9687 27.5676C34.8516 28.5925 34.4204 29.5561 33.7341 30.3263C33.0479 31.0965 32.1402 31.6355 31.1355 31.8696C30.1308 32.1037 29.0784 32.0212 28.1224 31.6336C27.1664 31.246 26.3537 30.5722 25.7957 29.7046C25.1982 28.7756 23.9607 28.5068 23.0317 29.1043C22.1027 29.7018 21.8339 30.9393 22.4314 31.8683C23.4358 33.43 24.8986 34.6429 26.6194 35.3405C28.3402 36.0382 30.2347 36.1866 32.0431 35.7653C33.8515 35.344 35.4853 34.3736 36.7206 32.9873C37.9558 31.601 38.7321 29.8665 38.9429 28.0217Z" fill="#CCCCCC"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,9 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.8917 2H42.1083C43.8909 1.99995 45.3881 1.9999 46.5982 2.131C47.8701 2.26881 49.0596 2.57044 50.1145 3.33689C50.7088 3.76864 51.2314 4.29124 51.6631 4.88551C52.4296 5.94043 52.7312 7.12995 52.869 8.40184C53.0001 9.61184 53.0001 11.109 53 12.8915V12.8916V12.8916V12.8917V12.8917V40.1083V40.1083V40.1084V40.1084V40.1085C53.0001 41.891 53.0001 43.3882 52.869 44.5982C52.7312 45.8701 52.4296 47.0596 51.6631 48.1145C51.2314 48.7088 50.7088 49.2314 50.1145 49.6631C49.0596 50.4296 47.8701 50.7312 46.5982 50.869C45.3882 51.0001 43.891 51.0001 42.1085 51H42.1084H42.1084H42.1083H42.1083H32V54H51C52.1046 54 53 54.8954 53 56C53 57.1046 52.1046 58 51 58H32H28H9C7.89543 58 7 57.1046 7 56C7 54.8954 7.89543 54 9 54H28V51H17.8917H17.8917H17.8916H17.8916H17.8915C16.109 51.0001 14.6118 51.0001 13.4018 50.869C12.1299 50.7312 10.9404 50.4296 9.88551 49.6631C9.29124 49.2314 8.76864 48.7088 8.33689 48.1145C7.57044 47.0596 7.26881 45.8701 7.131 44.5982C6.9999 43.3881 6.99995 41.8909 7 40.1083V12.8917C6.99995 11.1091 6.9999 9.61188 7.131 8.40184C7.26881 7.12995 7.57044 5.94043 8.33689 4.88551C8.76864 4.29124 9.29124 3.76864 9.88551 3.33689C10.9404 2.57044 12.1299 2.26881 13.4018 2.131C14.6119 1.9999 16.1091 1.99995 17.8917 2ZM13.8327 6.10773C12.9011 6.20866 12.4961 6.38449 12.2366 6.57295C11.982 6.75799 11.758 6.98196 11.573 7.23665C11.3845 7.49605 11.2087 7.90113 11.1077 8.83269C11.0027 9.80168 11 11.0806 11 13V40C11 41.9194 11.0027 43.1983 11.1077 44.1673C11.2087 45.0989 11.3845 45.504 11.573 45.7634C11.758 46.018 11.982 46.242 12.2366 46.4271C12.4961 46.6155 12.9011 46.7913 13.8327 46.8923C14.8017 46.9973 16.0806 47 18 47H42C43.9194 47 45.1983 46.9973 46.1673 46.8923C47.0989 46.7913 47.504 46.6155 47.7634 46.4271C48.018 46.242 48.242 46.018 48.4271 45.7634C48.6155 45.504 48.7913 45.0989 48.8923 44.1673C48.9973 43.1983 49 41.9194 49 40V13C49 11.0806 48.9973 9.80168 48.8923 8.83269C48.7913 7.90113 48.6155 7.49605 48.4271 7.23665C48.242 6.98196 48.018 6.75799 47.7634 6.57295C47.504 6.38449 47.0989 6.20866 46.1673 6.10773C45.1983 6.00275 43.9194 6 42 6H18C16.0806 6 14.8017 6.00275 13.8327 6.10773ZM30 15C23.3726 15 18 20.3726 18 27C18 33.6274 23.3726 39 30 39C36.6274 39 42 33.6274 42 27C42 20.3726 36.6274 15 30 15ZM14 27C14 18.1634 21.1634 11 30 11C38.8366 11 46 18.1634 46 27C46 35.8366 38.8366 43 30 43C21.1634 43 14 35.8366 14 27ZM38.9429 28.0217C39.0682 26.9242 38.2803 25.9329 37.1828 25.8075C36.0854 25.6822 35.0941 26.4702 34.9687 27.5676C34.8516 28.5925 34.4204 29.5561 33.7341 30.3263C33.0479 31.0965 32.1402 31.6355 31.1355 31.8696C30.1308 32.1037 29.0784 32.0212 28.1224 31.6336C27.1664 31.246 26.3537 30.5722 25.7957 29.7046C25.1982 28.7756 23.9607 28.5068 23.0317 29.1043C22.1027 29.7018 21.8339 30.9393 22.4314 31.8683C23.4358 33.43 24.8986 34.6429 26.6194 35.3405C28.3402 36.0382 30.2347 36.1866 32.0431 35.7653C33.8515 35.344 35.4853 34.3736 36.7206 32.9873C37.9558 31.601 38.7321 29.8665 38.9429 28.0217Z" fill="url(#paint0_linear_516_209)"/>
<defs>
<linearGradient id="paint0_linear_516_209" x1="53" y1="29.9558" x2="7" y2="29.9558" gradientUnits="userSpaceOnUse">
<stop stop-color="#7737FE"/>
<stop offset="1" stop-color="#7737FE"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.8917 2H42.1083C43.8909 1.99995 45.3881 1.9999 46.5982 2.131C47.8701 2.26881 49.0596 2.57044 50.1145 3.33689C50.7088 3.76864 51.2314 4.29124 51.6631 4.88551C52.4296 5.94043 52.7312 7.12995 52.869 8.40184C53.0001 9.61184 53.0001 11.109 53 12.8915V12.8916V12.8916V12.8917V12.8917V40.1083V40.1083V40.1084V40.1084V40.1085C53.0001 41.891 53.0001 43.3882 52.869 44.5982C52.7312 45.8701 52.4296 47.0596 51.6631 48.1145C51.2314 48.7088 50.7088 49.2314 50.1145 49.6631C49.0596 50.4296 47.8701 50.7312 46.5982 50.869C45.3882 51.0001 43.891 51.0001 42.1085 51H42.1084H42.1084H42.1083H42.1083H32V54H51C52.1046 54 53 54.8954 53 56C53 57.1046 52.1046 58 51 58H32H28H9C7.89543 58 7 57.1046 7 56C7 54.8954 7.89543 54 9 54H28V51H17.8917H17.8917H17.8916H17.8916H17.8915C16.109 51.0001 14.6118 51.0001 13.4018 50.869C12.1299 50.7312 10.9404 50.4296 9.88551 49.6631C9.29124 49.2314 8.76864 48.7088 8.33689 48.1145C7.57044 47.0596 7.26881 45.8701 7.131 44.5982C6.9999 43.3881 6.99995 41.8909 7 40.1083V12.8917C6.99995 11.1091 6.9999 9.61188 7.131 8.40184C7.26881 7.12995 7.57044 5.94043 8.33689 4.88551C8.76864 4.29124 9.29124 3.76864 9.88551 3.33689C10.9404 2.57044 12.1299 2.26881 13.4018 2.131C14.6119 1.9999 16.1091 1.99995 17.8917 2ZM13.8327 6.10773C12.9011 6.20866 12.4961 6.38449 12.2366 6.57295C11.982 6.75799 11.758 6.98196 11.573 7.23665C11.3845 7.49605 11.2087 7.90113 11.1077 8.83269C11.0027 9.80168 11 11.0806 11 13V40C11 41.9194 11.0027 43.1983 11.1077 44.1673C11.2087 45.0989 11.3845 45.504 11.573 45.7634C11.758 46.018 11.982 46.242 12.2366 46.4271C12.4961 46.6155 12.9011 46.7913 13.8327 46.8923C14.8017 46.9973 16.0806 47 18 47H42C43.9194 47 45.1983 46.9973 46.1673 46.8923C47.0989 46.7913 47.504 46.6155 47.7634 46.4271C48.018 46.242 48.242 46.018 48.4271 45.7634C48.6155 45.504 48.7913 45.0989 48.8923 44.1673C48.9973 43.1983 49 41.9194 49 40V13C49 11.0806 48.9973 9.80168 48.8923 8.83269C48.7913 7.90113 48.6155 7.49605 48.4271 7.23665C48.242 6.98196 48.018 6.75799 47.7634 6.57295C47.504 6.38449 47.0989 6.20866 46.1673 6.10773C45.1983 6.00275 43.9194 6 42 6H18C16.0806 6 14.8017 6.00275 13.8327 6.10773ZM30 15C23.3726 15 18 20.3726 18 27C18 33.6274 23.3726 39 30 39C36.6274 39 42 33.6274 42 27C42 20.3726 36.6274 15 30 15ZM14 27C14 18.1634 21.1634 11 30 11C38.8366 11 46 18.1634 46 27C46 35.8366 38.8366 43 30 43C21.1634 43 14 35.8366 14 27ZM38.9429 28.0217C39.0682 26.9242 38.2803 25.9329 37.1828 25.8075C36.0854 25.6822 35.0941 26.4702 34.9687 27.5676C34.8516 28.5925 34.4204 29.5561 33.7341 30.3263C33.0479 31.0965 32.1402 31.6355 31.1355 31.8696C30.1308 32.1037 29.0784 32.0212 28.1224 31.6336C27.1664 31.246 26.3537 30.5722 25.7957 29.7046C25.1982 28.7756 23.9607 28.5068 23.0317 29.1043C22.1027 29.7018 21.8339 30.9393 22.4314 31.8683C23.4358 33.43 24.8986 34.6429 26.6194 35.3405C28.3402 36.0382 30.2347 36.1866 32.0431 35.7653C33.8515 35.344 35.4853 34.3736 36.7206 32.9873C37.9558 31.601 38.7321 29.8665 38.9429 28.0217Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,18 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" class="design-iconfont">
<g clip-path="url(#qk95ibn7t__clip0_281_1155)">
<mask id="qk95ibn7t__lyhifhlt8a" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="40" height="40">
<path fill="#fff" d="M0 0H40V40H0z"/>
</mask>
<g mask="url(#qk95ibn7t__lyhifhlt8a)" fill="#262626">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.33203 17.1731V10.6668C3.33203 9.93045 3.92898 9.3335 4.66536 9.3335H35.332C36.0684 9.3335 36.6654 9.93045 36.6654 10.6668V17.1731C36.6654 17.6289 36.4325 18.0532 36.0479 18.2979L34.9757 18.9803C34.9757 18.9803 33.3735 20.0002 31.4987 20.0002C31.4987 20.0002 29.6239 20.0002 28.0216 18.9803L27.6654 18.7536L27.3091 18.9803C27.3091 18.9803 25.7069 20.0002 23.832 20.0002C23.832 20.0002 21.9572 20.0002 20.3549 18.9803L19.9987 18.7536L19.6424 18.9803C19.6424 18.9803 18.0402 20.0002 16.1654 20.0002C16.1654 20.0002 14.2905 20.0002 12.6883 18.9803L12.332 18.7536L11.9757 18.9803C11.9757 18.9803 10.3735 20.0002 8.4987 20.0002C8.4987 20.0002 6.62386 20.0002 5.0216 18.9803L3.94947 18.2979C3.56491 18.0532 3.33203 17.6289 3.33203 17.1731ZM6.45354 16.7307L5.9987 16.4412V12.0002H33.9987V16.4412L33.5439 16.7307C33.5439 16.7307 32.5968 17.3335 31.4987 17.3335C31.4987 17.3335 30.4006 17.3335 29.4535 16.7307L28.3813 16.0483C27.9445 15.7703 27.3863 15.7703 26.9495 16.0483L25.8773 16.7307C25.8773 16.7307 24.9302 17.3335 23.832 17.3335C23.832 17.3335 22.7339 17.3335 21.7869 16.7307L20.7146 16.0483C20.2778 15.7703 19.7196 15.7703 19.2828 16.0483L18.2106 16.7307C18.2106 16.7307 17.2635 17.3335 16.1654 17.3335C16.1654 17.3335 15.0672 17.3335 14.1202 16.7307L13.0479 16.0483C12.6111 15.7703 12.0529 15.7703 11.6161 16.0483L10.5439 16.7307C10.5439 16.7307 9.59683 17.3335 8.4987 17.3335C8.4987 17.3335 7.40057 17.3335 6.45354 16.7307Z"/>
<path d="M33.3346 35.3335V18.6668C33.3346 17.9304 32.7377 17.3335 32.0013 17.3335C31.2649 17.3335 30.668 17.9304 30.668 18.6668V34.0002H9.33464V19.0372C9.33464 18.3008 8.73768 17.7039 8.0013 17.7039C7.26492 17.7039 6.66797 18.3008 6.66797 19.0372V35.3335C6.66797 36.0699 7.26492 36.6668 8.0013 36.6668H32.0013C32.7377 36.6668 33.3346 36.0699 33.3346 35.3335Z"/>
<path d="M30.668 6.00016V10.6668C30.668 11.4032 31.2649 12.0002 32.0013 12.0002C32.7377 12.0002 33.3346 11.4032 33.3346 10.6668V4.66683C33.3346 3.93045 32.7377 3.3335 32.0013 3.3335H8.0013C7.26492 3.3335 6.66797 3.93045 6.66797 4.66683V10.5335C6.66797 11.2699 7.26492 11.8668 8.0013 11.8668C8.73768 11.8668 9.33464 11.2699 9.33464 10.5335V6.00016H30.668Z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.668 25.9998V35.3332C14.668 36.0695 15.2649 36.6665 16.0013 36.6665H24.0013C24.7377 36.6665 25.3346 36.0695 25.3346 35.3332V25.9998C25.3346 25.2635 24.7377 24.6665 24.0013 24.6665H16.0013C15.2649 24.6665 14.668 25.2635 14.668 25.9998ZM17.3346 27.3332H22.668V33.9998H17.3346V27.3332Z"/>
</g>
</g>
<defs>
<clipPath id="qk95ibn7t__clip0_281_1155">
<path fill="#fff" d="M0 0H40V40H0z"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,20 @@
<svg width="750" height="600" viewBox="0 0 750 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_630_423)">
<mask id="mask0_630_423" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="750" height="600">
<rect width="750" height="600" fill="#D8D8D8"/>
</mask>
<g mask="url(#mask0_630_423)">
</g>
<g opacity="0.05" clip-path="url(#clip1_630_423)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M518.516 -64.7935L361.707 -22.7767C335.325 -15.7081 313.841 -9.95171 297.096 -3.55206C279.722 3.08836 265.043 11.2698 253.853 24.5107C247.365 32.1877 242.15 40.773 238.401 49.9513C231.935 65.7815 231.825 81.9479 234.469 99.5603C237.017 116.534 242.524 137.084 249.286 162.319L326.919 452.047C333.68 477.282 339.186 497.833 345.466 513.807C351.983 530.382 360.161 544.327 373.676 554.803C381.512 560.877 390.32 565.705 399.778 569.11C416.089 574.982 432.892 574.728 451.259 571.791C468.96 568.961 490.444 563.204 516.825 556.135L673.635 514.118C700.017 507.049 721.501 501.293 738.246 494.893C755.62 488.253 770.298 480.072 781.489 466.831C787.977 459.154 793.191 450.568 796.94 441.39C803.407 425.56 803.517 409.393 800.872 391.781C798.324 374.807 792.818 354.257 786.056 329.023L708.423 39.2933C701.662 14.0586 696.156 -6.49161 689.875 -22.4654C683.359 -39.0403 675.181 -52.986 661.666 -63.4621C653.83 -69.5362 645.021 -74.364 635.564 -77.7685C619.252 -83.6402 602.45 -83.3864 584.083 -80.4499C566.382 -77.62 544.898 -71.8629 518.516 -64.7935ZM287.042 50.2368C291.477 44.9891 298.306 40.2567 312.228 34.9359C326.529 29.47 345.736 24.2941 373.591 16.8304L528.028 -24.5508C555.882 -32.0144 575.104 -37.1355 590.223 -39.5526C604.939 -41.9055 613.22 -41.2218 619.685 -38.8947C624.939 -37.0033 629.832 -34.3212 634.186 -30.9467C639.542 -26.7948 644.309 -20.3269 649.531 -7.04593C654.895 6.59735 659.848 24.9688 666.987 51.6123L695.545 158.191L535.422 143.979C535.422 143.979 539.716 132.772 541.495 112.182C543.761 91.4612 541.967 80.8794 541.967 80.8794L486.407 95.2639L481.504 76.9674L548.484 58.5173L544.964 45.3815L477.859 63.3624L469.939 33.8054L436.873 42.6655L444.667 71.7532L380.966 88.8219L384.485 101.958L447.088 84.6804L452.368 104.385L402.282 117.805L405.048 128.126L508.623 100.373C508.623 100.373 509.913 109.079 508.789 120.443C507.178 131.937 505.677 141.893 505.677 141.893C505.677 141.893 452.65 138.502 426.878 145.408C401.105 152.314 372.75 170.974 377.5 200.374C382.25 229.774 404.03 241.034 430.338 240.02C456.16 239.134 477.506 227.381 494.929 212.656C512.353 197.932 526.146 171.608 526.146 171.608L710.81 215.162L713.523 225.286L337.866 325.943L291.33 152.269C284.191 125.626 279.295 107.239 277.118 92.7417C275 78.6293 275.895 70.6443 278.457 64.3704C280.54 59.2714 283.437 54.5018 287.042 50.2368ZM348.563 365.868L368.354 439.729C375.494 466.372 380.447 484.744 385.811 498.387C391.032 511.668 395.8 518.136 401.156 522.288C405.509 525.662 410.403 528.345 415.657 530.236C422.122 532.563 430.402 533.247 445.119 530.894C460.237 528.477 479.459 523.356 507.314 515.892L661.751 474.511C689.605 467.047 708.813 461.871 723.114 456.405C737.036 451.085 743.865 446.352 748.3 441.104C751.905 436.839 754.801 432.07 756.884 426.971C759.447 420.697 760.342 412.712 758.223 398.6C756.047 384.102 751.151 365.715 744.012 339.072L724.221 265.211L348.563 365.868ZM400.046 405.562C397.092 394.537 404.131 383.072 415.768 379.954L563.269 340.431C574.906 337.313 586.735 343.723 589.689 354.748C592.643 365.773 585.604 377.238 573.967 380.356L426.466 419.879C414.829 422.997 403 416.587 400.046 405.562ZM436.232 449.355C423.632 452.732 415.813 464.406 418.767 475.431C421.721 486.456 434.33 492.657 446.93 489.28L481.152 480.111C493.752 476.735 501.571 465.06 498.617 454.035C495.663 443.01 483.054 436.81 470.454 440.186L436.232 449.355ZM538.542 443.338C535.588 432.313 542.13 420.98 553.155 418.026L583.099 410.003C594.124 407.049 605.456 413.591 608.411 424.616C611.365 435.641 604.822 446.974 593.797 449.928L563.853 457.951C552.828 460.905 541.496 454.362 538.542 443.338ZM647.555 317.847C634.692 321.293 626.66 333.025 629.614 344.05C632.568 355.075 645.39 361.218 658.253 357.772L681.542 351.531C694.405 348.085 702.437 336.353 699.483 325.328C696.529 314.304 683.707 308.16 670.844 311.606L647.555 317.847ZM648.335 413.918C645.381 402.893 653.414 391.162 666.276 387.715L689.566 381.475C702.428 378.029 715.25 384.172 718.204 395.197C721.158 406.222 713.126 417.953 700.263 421.4L676.974 427.64C664.111 431.087 651.29 424.943 648.335 413.918ZM390.428 201.937C393.696 214.136 405.642 229.54 442.112 219.767C478.582 209.995 499.537 165.662 499.537 165.662C499.537 165.662 451.559 153.879 421.426 163.964C391.294 174.049 387.159 189.739 390.428 201.937Z" fill="white"/>
</g>
</g>
<defs>
<clipPath id="clip0_630_423">
<rect width="750" height="600" fill="white"/>
</clipPath>
<clipPath id="clip1_630_423">
<rect width="620" height="620" fill="white" transform="translate(138 26.4678) rotate(-15)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,3 @@
<svg width="90" height="90" viewBox="0 0 90 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M56.7828 1.5H33.2172H33.2172C29.2525 1.49994 26.0238 1.49989 23.4355 1.76812C20.7499 2.04644 18.3844 2.64213 16.3179 4.07827C15.1197 4.91095 14.066 5.91882 13.1955 7.0649C11.694 9.04158 11.0713 11.3042 10.7803 13.8731C10.4999 16.3488 10.4999 19.4372 10.5 23.2295V23.2295V66.7705C10.4999 70.5628 10.4999 73.6512 10.7803 76.1269C11.0713 78.6958 11.694 80.9584 13.1955 82.9351C14.066 84.0812 15.1197 85.0891 16.3179 85.9217C18.3844 87.3579 20.7499 87.9536 23.4355 88.2319C26.0238 88.5001 29.2525 88.5001 33.2171 88.5H56.7828C60.7475 88.5001 63.9762 88.5001 66.5645 88.2319C69.2501 87.9536 71.6156 87.3579 73.6821 85.9217C74.8803 85.0891 75.934 84.0812 76.8045 82.9351C78.306 80.9584 78.9287 78.6958 79.2197 76.1269C79.5001 73.6514 79.5001 70.5634 79.5 66.7717V66.7715V66.7714V66.7712V66.771V66.7709V66.7707V66.7706V23.2294V23.2293V23.2291V23.229V23.2289V23.2287V23.2286V23.2284C79.5001 19.4366 79.5001 16.3486 79.2197 13.8731C78.9287 11.3042 78.306 9.04158 76.8045 7.0649C75.934 5.91882 74.8803 4.91095 73.6821 4.07827C71.6156 2.64213 69.2501 2.04644 66.5645 1.76812C63.9762 1.49989 60.7475 1.49994 56.7828 1.5H56.7828ZM20.0049 8.93238C20.8239 8.3632 21.9592 7.95622 24.1112 7.73321C26.3218 7.50412 29.2094 7.5 33.3955 7.5H56.6045C60.7906 7.5 63.6782 7.50412 65.8888 7.73321C68.0408 7.95622 69.1761 8.3632 69.9951 8.93238C70.6608 9.39497 71.2462 9.9549 71.7298 10.5916C72.3248 11.375 72.7503 12.461 72.9835 14.5194C73.223 16.6339 73.2273 19.396 73.2273 23.4V39.4168L51.3097 31.4082C51.3097 31.4082 52.3327 29.9982 53.3558 27.178C54.4519 24.3577 54.598 22.8066 54.598 22.8066L46.2672 22.7361V19.9865L56.3519 19.9159V17.9419H46.2672V13.5H41.2979V17.8714H31.7248V19.8454L41.1517 19.7749V22.7361H33.6248V24.2872H49.1903C49.1903 24.2872 49.0441 25.5563 48.4594 27.1075C47.8018 28.6586 47.2172 29.9982 47.2172 29.9982C47.2172 29.9982 39.9094 27.5305 36.0363 27.5305C32.1633 27.5305 27.4862 29.0817 27.0477 33.3825C26.6093 37.6833 29.2401 40.0804 32.9669 40.9265C36.6209 41.7725 40.0554 40.9265 43.0517 39.5165C46.0479 38.1065 48.9709 34.9337 48.9709 34.9337L73.2273 47.9785V49.5H16.7727V23.4C16.7727 19.396 16.777 16.6339 17.0165 14.5194C17.2497 12.461 17.6752 11.375 18.2702 10.5916C18.7538 9.9549 19.3392 9.39497 20.0049 8.93238ZM16.7727 55.5V66.6C16.7727 70.604 16.777 73.3661 17.0165 75.4806C17.2497 77.539 17.6752 78.625 18.2702 79.4084C18.7538 80.0451 19.3392 80.605 20.0049 81.0676C20.8239 81.6368 21.9592 82.0438 24.1112 82.2668C26.3218 82.4959 29.2094 82.5 33.3955 82.5H56.6045C60.7906 82.5 63.6782 82.4959 65.8888 82.2668C68.0408 82.0438 69.1761 81.6368 69.9951 81.0676C70.6608 80.605 71.2462 80.0451 71.7298 79.4084C72.3248 78.625 72.7503 77.539 72.9835 75.4806C73.223 73.3661 73.2273 70.604 73.2273 66.6V55.5H16.7727ZM22.5 63C22.5 61.3431 23.9178 60 25.6667 60H47.8333C49.5822 60 51 61.3431 51 63C51 64.6569 49.5822 66 47.8333 66H25.6667C23.9178 66 22.5 64.6569 22.5 63ZM25.9286 70.5C24.035 70.5 22.5 71.8431 22.5 73.5C22.5 75.1569 24.035 76.5 25.9286 76.5H31.0714C32.965 76.5 34.5 75.1569 34.5 73.5C34.5 71.8431 32.965 70.5 31.0714 70.5H25.9286ZM40.5 73.5C40.5 71.8432 41.8431 70.5 43.5 70.5H48C49.6569 70.5 51 71.8432 51 73.5C51 75.1569 49.6569 76.5 48 76.5H43.5C41.8431 76.5 40.5 75.1569 40.5 73.5ZM60.5 60C58.567 60 57 61.3431 57 63C57 64.6569 58.567 66 60.5 66H64C65.933 66 67.5 64.6569 67.5 63C67.5 61.3431 65.933 60 64 60H60.5ZM57 73.5C57 71.8431 58.567 70.5 60.5 70.5H64C65.933 70.5 67.5 71.8431 67.5 73.5C67.5 75.1569 65.933 76.5 64 76.5H60.5C58.567 76.5 57 75.1569 57 73.5ZM28.8017 34.0873C28.8017 35.9206 29.898 38.5292 35.3787 38.5292C40.8595 38.5292 45.4634 33.1003 45.4634 33.1003C45.4634 33.1003 39.1788 29.6456 34.5748 29.9276C29.9709 30.2095 28.8017 32.2541 28.8017 34.0873Z" fill="#7737FE"/>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,3 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M63.0933 1.66663H36.9093C32.5041 1.66656 28.9166 1.66651 26.0408 1.96454C23.0567 2.27378 20.4284 2.93566 18.1322 4.53137C16.8009 5.45657 15.6302 6.57643 14.6629 7.84985C12.9947 10.0462 12.3027 12.5602 11.9794 15.4145C11.6678 18.1653 11.6679 21.5968 11.668 25.8105V74.1894C11.6679 78.4031 11.6678 81.8346 11.9794 84.5854C12.3027 87.4397 12.9947 89.9538 14.6629 92.1501C15.6302 93.4235 16.8009 94.5434 18.1322 95.4686C20.4284 97.0643 23.0567 97.7261 26.0408 98.0354C28.9166 98.3334 32.504 98.3334 36.9092 98.3333H63.0934C67.4986 98.3334 71.086 98.3334 73.9618 98.0354C76.9459 97.7261 79.5742 97.0643 81.8704 95.4686C83.2017 94.5434 84.3724 93.4235 85.3397 92.1501C87.0079 89.9538 87.6999 87.4397 88.0232 84.5854C88.3348 81.8346 88.3347 78.4032 88.3346 74.1895V25.8105C88.3347 21.5968 88.3348 18.1653 88.0232 15.4145C87.6999 12.5602 87.0079 10.0462 85.3397 7.84985C84.3724 6.57643 83.2017 5.45657 81.8704 4.53137C79.5742 2.93566 76.9459 2.27378 73.9618 1.96454C71.086 1.66651 67.4985 1.66656 63.0933 1.66663ZM22.2289 9.92482C23.139 9.2924 24.4005 8.84021 26.7915 8.59242C29.2478 8.33787 32.4562 8.3333 37.1074 8.3333H62.8952C67.5464 8.3333 70.7549 8.33787 73.2111 8.59242C75.6021 8.84021 76.8637 9.2924 77.7737 9.92482C78.5133 10.4388 79.1637 11.061 79.7011 11.7684C80.3622 12.6389 80.835 13.8455 81.094 16.1326C81.3602 18.4821 81.3649 21.551 81.3649 26V43.7964L57.012 34.898C57.012 34.898 58.1488 33.3313 59.2855 30.1977C60.5034 27.0641 60.6657 25.3406 60.6657 25.3406L51.4093 25.2623V22.2071L62.6145 22.1288V19.9354H51.4093V15H45.8879V19.857H35.2511V22.0504L45.7254 21.9721V25.2623H37.3622V26.9858H54.6572C54.6572 26.9858 54.4947 28.3959 53.8451 30.1194C53.1144 31.8428 52.4649 33.3313 52.4649 33.3313C52.4649 33.3313 44.3451 30.5894 40.0417 30.5894C35.7382 30.5894 30.5416 32.3129 30.0543 37.0916C29.5671 41.8703 32.4903 44.5338 36.6312 45.4738C40.6911 46.4139 44.5073 45.4739 47.8365 43.9072C51.1656 42.3405 54.4134 38.8152 54.4134 38.8152L81.3649 53.3094V55H18.6377V26C18.6377 21.551 18.6425 18.4821 18.9086 16.1326C19.1676 13.8455 19.6404 12.6389 20.3015 11.7684C20.8389 11.061 21.4893 10.4388 22.2289 9.92482ZM18.6377 61.6666V74C18.6377 78.4489 18.6425 81.5178 18.9086 83.8673C19.1676 86.1544 19.6404 87.3611 20.3015 88.2315C20.8389 88.939 21.4893 89.5611 22.2289 90.0751C23.139 90.7075 24.4005 91.1597 26.7915 91.4075C29.2478 91.662 32.4562 91.6666 37.1074 91.6666H62.8952C67.5464 91.6666 70.7548 91.662 73.2111 91.4075C75.6021 91.1597 76.8637 90.7075 77.7737 90.0751C78.5133 89.5611 79.1637 88.939 79.7011 88.2315C80.3622 87.3611 80.835 86.1544 81.094 83.8673C81.3602 81.5178 81.3649 78.4489 81.3649 74V61.6666H18.6377ZM25.0013 70C25.0013 68.159 26.5766 66.6666 28.5198 66.6666H53.1494C55.0927 66.6666 56.668 68.159 56.668 70C56.668 71.8409 55.0927 73.3333 53.1494 73.3333H28.5198C26.5766 73.3333 25.0013 71.8409 25.0013 70ZM28.8108 78.3333C26.7069 78.3333 25.0013 79.8257 25.0013 81.6666C25.0013 83.5076 26.7069 85 28.8108 85H34.5251C36.6291 85 38.3346 83.5076 38.3346 81.6666C38.3346 79.8257 36.6291 78.3333 34.5251 78.3333H28.8108ZM45.0013 81.6666C45.0013 79.8257 46.4937 78.3333 48.3346 78.3333H53.3346C55.1756 78.3333 56.668 79.8257 56.668 81.6666C56.668 83.5076 55.1756 85 53.3346 85H48.3346C46.4937 85 45.0013 83.5076 45.0013 81.6666ZM67.2235 66.6666C65.0757 66.6666 63.3346 68.159 63.3346 70C63.3346 71.8409 65.0757 73.3333 67.2235 73.3333H71.1124C73.2602 73.3333 75.0013 71.8409 75.0013 70C75.0013 68.159 73.2602 66.6666 71.1124 66.6666H67.2235ZM63.3346 81.6666C63.3346 79.8257 65.0757 78.3333 67.2235 78.3333H71.1124C73.2602 78.3333 75.0013 79.8257 75.0013 81.6666C75.0013 83.5076 73.2602 85 71.1124 85H67.2235C65.0757 85 63.3346 83.5076 63.3346 81.6666ZM32.0032 37.8748C32.0032 39.9117 33.2213 42.8102 39.311 42.8102C45.4008 42.8102 50.5162 36.778 50.5162 36.778C50.5162 36.778 43.5333 32.9395 38.4177 33.2528C33.3023 33.5661 32.0032 35.8379 32.0032 37.8748Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -0,0 +1,246 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle :title="storeInfo.storeId ? '编辑门店信息' : '创建门店'" bgColor="#f2f2f2" />
<JMainCard pd="0" wrapPd="30rpx" v-if="!storeInfo.storeId">
<view class="select-wrapper" @tap="jumpPage('mch')">
<view class="select-mch" v-if="mchInfo.mchNo == undefined"> 请选择商户 </view>
<view class="mch-info" v-else>
<image src="/static/equipmentImg/mch-list.svg" mode="scaleToFill" />
<view
>{{ mchInfo.mchName }} <text>{{ mchInfo.mchNo }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JMainCard wrapPd=" 0 30rpx" pd="0">
<JInput
v-model:value="storeInfo.storeName"
name="门店名称"
place="请输入门店名称"
:rules="{ name: 'storeName', rule: 'REG_NotNUll' }"
:isBorder="true"
></JInput>
<JInput v-model:value="storeInfo.contactPhone" name="联系人手机号" place="请输入联系人手机号"></JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx">
<JUpLoad name="门店logo" v-model:value="storeInfo.storeLogo" borderNone />
<JUpLoad name="门头照" v-model:value="storeInfo.storeOuterImg" />
<JUpLoad name="门店内景照" v-model:value="storeInfo.storeInnerImg" />
</JMainCard>
<JMainCard wrapPd=" 0 30rpx" pd="0">
<JInput name="门店地址" :isBorder="true">
<view @tap="getAddress" class="place-text address" v-if="!storeInfo.address"
>请选择位置 <view class="gps-img"> <image src="/static/iconImg/icon-gps.svg" mode="scaleToFill" /></view
></view>
<view @tap="getAddress" v-else class="place-text address" style="color: #000"
>{{ storeInfo.address }}
<view class="gps-img"> <image src="/static/iconImg/icon-gps.svg" mode="scaleToFill" /></view>
</view>
</JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx">
<JInput name="省市区">
<uni-data-picker
:localdata="address"
@change="dataPickerChange($event, 'areaCode')"
v-slot:default="{ data, error, options }"
>
<view class="place-text" v-if="storeInfo.areaCode.length == 0"
>请选择省市区
<image src="/static/iconImg/icon-right-jiantou.svg" mode="scaleToFill" />
</view>
<view v-else style="font-size: 33rpx">{{ storeInfo.addressInfo || "请选择省市区" }}</view>
</uni-data-picker>
</JInput>
<JInput name="经纬度">
<view class="place-text" v-if="!storeInfo.lng">选择位置后自动生成</view>
<view style="font-size: 33rpx" v-else>{{ storeInfo.lng }},{{ storeInfo.lat }}</view>
</JInput>
</JMainCard>
<JButton pd="0 30rpx 50rpx" pdTop="0" @HandleTouch="saveStore">{{
storeInfo.storeId ? "保存" : "创建门店"
}}</JButton>
</view>
</template>
<script setup>
import { ref } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import { $addMchStore, $updateMchStore, $storeDetails, $mapKey } from "@/http/apiManager.js"
import tool from "@/util/tool.js" // 工具类函数
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" //自定义导航栏
import JInput from "@/components/newComponents/JInput/JInput.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue" //自定义按钮
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JUpLoad from "@/components/newComponents/JUpLoad/JUpLoad.vue"
import address from "@/components/applyJson/address.json" // 地址
import { getMapKey } from "@/hooks/mapInfo.js"
import useStore from "@/hooks/useStore.js"
import { validateArray } from "@/hooks/rules"
const { getStore, clearItem } = useStore()
onLoad((options) => {
if (options.id) return getStoreInf(options.id)
})
onShow(() => {
if (getStore("mch")?.mchNo) {
mchInfo.value = getStore("mch")
storeInfo.value.mchNo = getStore("mch").mchNo
clearItem("mch")
}
})
const title = ref("创建门店")
const mchInfo = ref({})
const storeInfo = ref({
state: 1,
areaCode: [],
addressInfo: "", //只做数据回显使用非必传值
})
const switchState = (e, v) => {
agentInfo[v] = e.detail.value ? 1 : 0
}
const dataPickerChange = (e, name) => {
storeInfo.value.addressInfo = ""
storeInfo.value.areaCode = []
e.detail.value.forEach((v, i) => {
storeInfo.value.areaCode.push(v.value)
storeInfo.value.addressInfo += i == e.detail.value.length - 1 ? v.text : v.text + "/"
})
const address = storeInfo.value.addressInfo.split("/").join("")
getMapKey(address, 1).then((res) => {
storeInfo.value.lng = parseFloat(res.lon).toFixed(6)
storeInfo.value.lat = parseFloat(res.lat).toFixed(6)
storeInfo.value.address = address
})
}
function getAddress() {
uni.chooseLocation({
latitude: storeInfo.value.lat || undefined,
longitude: storeInfo.value.lng || undefined,
success: (res) => {
storeInfo.value.lng = res.longitude.toFixed(6)
storeInfo.value.lat = res.latitude.toFixed(6)
storeInfo.value.location = res.longitude + "/" + res.latitude
storeInfo.value.address = res.address
getMapKey(res.address, 0).then((res) => {
storeInfo.value.addressInfo = res.text
storeInfo.value.areaCode = res.code
})
},
fail: (err) => {
console.log(err, "error")
},
})
}
const saveStore = () => {
if (validateArray(storeInfo.value)) {
if (!storeInfo.value.addressInfo) {
uni.showToast({ title: "请选省市区", icon: "error" })
return
} else {
if (!storeInfo.value.storeId) {
$addMchStore(storeInfo.value).then(() => {
uni.showToast({
title: "新增成功",
})
uni.navigateBack()
})
} else {
$updateMchStore(storeInfo.value.storeId, storeInfo.value).then(() => {
uni.showToast({
title: "修改成功",
})
uni.navigateBack()
})
}
}
}
}
// 请求门店详情
const getStoreInf = (val) => {
$storeDetails(val).then(({ bizData }) => {
storeInfo.value = bizData
storeInfo.value.addressInfo = tool.addressBack(storeInfo.value.areaCode, address)
})
}
// 跳转到通用选择页面
const jumpPage = (val) => {
uni.navigateTo({
url: `/pageWork/SelectedList/SelectedList?title=${val}&selected=${storeInfo.value.mchNo}`,
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.select-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
.select-mch {
margin: 20rpx;
}
.mch-info {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 10rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 15rpx;
color: #8c8c8c;
font-size: 25rpx;
font-weight: 500;
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
image {
width: 60rpx;
height: 66rpx;
}
}
}
.place-text {
font-size: 33rpx;
color: #a6a6a6;
image {
width: 40rpx;
height: 40rpx;
}
}
}
.address {
align-self: flex-start;
display: flex;
justify-content: flex-end;
align-items: center;
.gps-img {
align-self: flex-start;
display: flex;
justify-content: center;
align-items: center;
width: 50rpx;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,266 @@
<template>
<view class="page-wrapper">
<JHeaderTitle title="门店详情" :bgColor="headerBgColor" color="#fff" imgUrl="/static/iconImg/left-white.svg" />
<image src="/static/iconImg/store-bg-img.svg" class="bg-image" mode="scaleToFill" />
<view class="expand-header">
<image src="/static/iconImg/icon-store-img.svg" mode="scaleToFill" />
<view class="expand-title">{{ storeInfo.storeName }}</view>
<view class="expand-phone">{{ storeInfo.storeId }}</view>
<view class="expand-edit bgF bdR10" @tap="editStore">
<image src="/static/iconImg/expand-edit.svg" mode="scaleToFill" />
编辑信息
</view>
</view>
<JMainCard pd="0" wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.1)">
<JUpLoad
name="门店logo"
pdLeft="0"
pd="40rpx"
:imgUrl="storeInfo.storeLogo || imgUrl"
borderNone
textColor="rgba(255,255,255,0.6)"
/>
<JInput name="门店名称" pd="0 40rpx 40rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.storeName }}</text></JInput
>
<JInput name="门店ID" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.storeId }}</text></JInput
>
<JInput name="所属商户" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.mchName }}</text></JInput
>
<JInput name="用户号" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.mchNo }}</text></JInput
>
<JInput name="联系人手机号" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.contactPhone }}</text></JInput
>
<JInput name="门店地址" pd="0 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.address }}</text></JInput
>
<JInput name="经纬度" pd="40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.lng }}/{{ storeInfo.lat }}</text></JInput
>
<JUpLoad
name="门头照"
pd="0 40rpx"
pdLeft="0"
:imgUrl="storeInfo.storeOuterImg || imgUrl"
borderNone
textColor="rgba(255,255,255,0.6)"
/>
<JUpLoad
name="门店内景照"
pd="40rpx"
pdLeft="0"
:imgUrl="storeInfo.storeInnerImg || imgUrl"
borderNone
textColor="rgba(255,255,255,0.6)"
/>
<JInput name="创建时间" pd="0 40rpx 40rpx 40rpx" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<text class="right-color">{{ storeInfo.createdAt?.split("-").join("/") }}</text></JInput
>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx 50rpx 0 50rpx" bgColor="rgba(0,0,0,0.1)">
<JInput name="是否默认门店" textColor="rgba(255,255,255,0.6)" :isBorder="true">
<view class="tips" v-if="storeInfo.defaultFlag == 1"
><text
class="tips-color"
:style="{ backgroundColor: storeInfo.defaultFlag == 1 ? '#FFCA80' : 'rgba(255, 255, 255, 0.3)' }"
></text
></view>
<view v-else>
<switch
:checked="storeInfo.defaultFlag"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
@change="change"
/>
</view>
</JInput>
</JMainCard>
<JButton color="#FF4D6A" bgColor="rgba(255,255,255,0.85)" size="max" pdTop="0" @HandleTouch="deletedTips.open()"
>删除门店</JButton
>
</view>
<JDeletedTips ref="deletedTips" @confirm="deleted" />
<JDeletedTips ref="switchState" @confirm="confirm" @cancel="cancel" />
<!-- 更改状态对话框 -->
</template>
<script setup>
import { nextTick, ref } from "vue"
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app"
import { $storeDetails, $delStore, $updateMchStore } from "@/http/apiManager.js"
import { formatData } from "@/hooks/formatData"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import JUpLoad from "@/components/newComponents/JUpLoad/JUpLoad"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
onLoad((option) => {
storeId = option?.id || storeId
})
onShow(() => {
getStoreInfo(storeId)
})
let storeId = undefined
const storeInfo = ref({})
const switchState = ref(null)
const imgUrl = ref("/static/iconImg/defaultImg.svg")
const deletedTips = ref(null)
const deleted = () => {
$delStore(storeInfo.value.storeId).then((res) => {
uni.showToast({
title: "删除成功",
icon: "success",
})
uni.navigateBack()
})
}
const getStoreInfo = (val) => {
$storeDetails(val).then(({ bizData }) => {
formatData(bizData)
storeInfo.value = bizData
})
}
let flag = undefined
const change = (e) => {
flag = true
storeInfo.value.defaultFlag = Number(e.detail.value)
switchState.value.open("是否修改门店为默认门店?")
}
const confirm = () => {
flag = false
$updateMchStore(storeInfo.value.storeId, { defaultFlag: storeInfo.value.defaultFlag }).then((res) => {
uni.showToast({
title: "修改成功",
icon: "none",
})
})
}
const cancel = () => {
if (!flag) return
storeInfo.value.defaultFlag = Number(!storeInfo.value.defaultFlag)
}
const editStore = () => {
uni.navigateTo({
url: "./addOrEditStore?id=" + storeInfo.value.storeId,
})
}
const headerBgColor = ref("transparent")
onPageScroll((data) => {
if (data.scrollTop > 20) {
headerBgColor.value = "$primaryColor"
} else {
headerBgColor.value = "transparent"
}
})
</script>
<style lang="scss" scoped>
.page-wrapper {
position: relative;
width: 100%;
min-height: 100%;
background-color: $primaryColor;
text {
color: #fff;
font-weight: 400;
}
.bg-image {
position: absolute;
top: -40rpx;
right: 0;
width: 100%;
height: 650rpx;
}
.expand-header {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50rpx;
image {
width: 93rpx;
height: 93rpx;
}
.expand-title {
margin-top: 20rpx;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
.expand-phone {
margin: 30rpx 0;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
}
.expand-edit {
position: relative;
z-index: 40;
padding: 20rpx 41rpx;
margin-bottom: 48rpx;
font-size: 28rpx;
color: $primaryColor;
image {
width: 26.25rpx;
height: 26.25rpx;
}
}
}
.right-color {
color: #fff;
font-size: 30rpx;
}
.page-title {
margin: 50rpx 0 30rpx 0;
text-align: center;
font-size: 33rpx;
color: #fff;
}
.mch-info {
border-top: 1rpx solid rgba(0, 0, 0, 0.1);
padding: 60rpx;
view {
display: flex;
flex-direction: column;
}
text {
margin-bottom: 20rpx;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
font-weight: 500;
}
.mch-many {
color: #fff;
font-size: 56rpx;
font-weight: 700;
}
.mch-footer {
display: flex;
flex-direction: row;
margin-top: 50rpx;
view {
flex: 1;
font-size: 33rpx;
font-weight: 700;
color: #fff;
}
}
}
}
.tips {
color: #fff;
.tips-color {
display: inline-block;
width: 35rpx;
height: 35rpx;
margin-left: 10rpx;
vertical-align: middle;
border-radius: 50%;
}
}
</style>

View File

@@ -0,0 +1,92 @@
<template>
<view class="store-wrapper global-wrapper bgF2">
<view class="mch-header">
<JHeaderTitle title="门店管理" bgColor="#f2f2f2" />
<JSearchInput @search="searchList" @resetSearch="searchList" ref="search" place="搜索门店名称、ID">
</JSearchInput>
</view>
<block v-for="v in useDataResult.dataList" :key="v.agentNo">
<JPreview
:title="v.storeName"
:qrcId="v.storeId"
:img="imgList[1]"
:isLast="useDataResult.dataList.length - 1 == i"
@tap="toStoreDetails(v.storeId)"
></JPreview>
</block>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
<view class="button-block"></view>
<view class="mch-footers ButtonBor">
<JButton pd="30rpx 30rpx 50rpx 30rpx" pdTop="0" @HandleTouch="addOrEditStore">创建门店</JButton>
</view>
</view>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from "vue"
import { onBackPress, onShow } from "@dcloudio/uni-app"
import { $getMchStoreList } from "@/http/apiManager.js"
import useGetList from "@/hooks/useList.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" //自定义导航栏
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue" //自定义搜索框
import JButton from "@/components/newComponents/JButton/JButton.vue" //自定义按钮
import JPreview from "@/components/newComponents/JPreview/JPreview.vue" //列表展示
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull" //最后一条数据提示
const { useDataResult, getList } = useGetList({
requestFun: $getMchStoreList,
})
// 图片列表
const imgList = reactive(["/static/navImg/disable-mendian.svg", "/static/navImg/nav-mendian.svg"])
// 返回前清除搜索数据
const search = ref()
onBackPress(() => {
if (search.value.searchText != "") {
search.value.searchText = ""
list(search.value.searchText)
return true
} else {
return false
}
})
// 搜索回调
const searchList = (data) => {
if (data === "reset") data = ""
getList({ unionStoreInfo: data })
}
const addOrEditStore = () => {
uni.navigateTo({
url: "./addOrEditStore",
})
}
const toStoreDetails = (storeId) => {
uni.navigateTo({
url: "./storeDetails?id=" + storeId,
})
}
</script>
<style lang="scss" scoped>
.store-wrapper {
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.button-block {
height: 210rpx;
}
.mch-footers {
position: fixed;
left: 0;
right: 0;
bottom: 0;
backdrop-filter: blur(30px);
border-top: 1px solid rgba($color: #000000, $alpha: 0.1);
}
}
</style>

View File

@@ -0,0 +1,147 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle title="创建辅助终端" bgColor="#f2f2f2" />
<JMainCard pd="0" wrapPd="30rpx">
<view class="select-wrapper" @tap="jumpPage('mch', mchInfo.mchNo)">
<view class="select-mch" v-if="!mchInfo.mchNo"> 请选择商户 </view>
<view class="mch-info" v-else>
<image src="/static/equipmentImg/mch-list.svg" mode="scaleToFill" />
<view
>{{ mchInfo.mchName }} <text>{{ mchInfo.mchNo }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="0" v-if="mchInfo.mchNo">
<view class="select-wrapper" @tap="jumpPage('store', storeInfo.storeId, { mchNo: mchInfo.mchNo })">
<view class="select-mch" v-if="!storeInfo.agentNo"> 请选择门店 </view>
<view class="mch-info" v-else>
<image src="/static/navImg/nav-mendian.svg" mode="scaleToFill" />
<view
>{{ storeInfo.storeName }} <text>{{ storeInfo.agentNo }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx" v-if="mchInfo.mchNo">
<view class="select-wrapper" @tap="jumpPage('appId', appInfo.appId, { mchNo: mchInfo.mchNo })">
<view class="select-mch" v-if="!appInfo.appId"> 请选择应用 </view>
<view class="mch-info" v-else>
<image src="/static/iconImg/icon-app-selected.svg" mode="scaleToFill" />
<view
>{{ appInfo.appName }} <text>{{ appInfo.appId }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JButton pdTop="0" pd="0 30rpx 50rpx" bottom="55rpx" @HandleTouch="next">下一步</JButton>
</view>
</template>
<script setup>
import { ref } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import useStore from "@/hooks/useStore.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue"
const { getStore, setStore, clearItem } = useStore()
onShow(() => {
if (getStore("mch")) {
if (mchInfo.value.mchNo != getStore("mch").mchNo) {
clearItem("store")
clearItem("appId")
}
mchInfo.value = getStore("mch")
}
if (getStore("store")) {
storeInfo.value = getStore("store")
}
if (getStore("appId")) {
appInfo.value = getStore("appId")
}
})
const mchInfo = ref({}) //商户信息
const storeInfo = ref({}) //门店信息
const appInfo = ref({}) //门店信息
const next = () => {
if (mchInfo.value.mchNo && storeInfo.value.storeId && appInfo.value.appId) {
setStore("createINfo", { mchNo: mchInfo.value.mchNo, storeId: storeInfo.value.storeId, appId: appInfo.value.appId })
uni.navigateTo({
url: "/pageWork/terminal/addTerminalNext",
success: () => {
clearItem("store")
clearItem("appId")
clearItem("mch")
},
})
} else {
uni.showToast({
title: "请选择门店 商户 应用信息",
icon: "none",
})
}
}
// 跳转到通用选择页面
const jumpPage = (val, selected, search) => {
if (search) search = JSON.stringify(search)
uni.navigateTo({
url: `/pageWork/SelectedList/SelectedList?title=${val}&selected=${selected}&&search=${search}`,
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
.select-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
.select-mch {
margin: 20rpx;
}
.mch-info {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 10rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 15rpx;
color: #8c8c8c;
font-size: 25rpx;
font-weight: 500;
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
image {
width: 60rpx;
height: 66rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,336 @@
<template>
<view class="page-wrapper global-wrapper bgF2">
<JHeaderTitle :title="createInfo.trmId ? '修改辅助终端' : '创建辅助终端'" bgColor="#f2f2f2" />
<JMainCard pd="0" :wrapPd="createInfo.trmType == 2 ? '30rpx' : '0 30rpx'">
<JInput name="终端类型">
<view class="tips" :class="{ selected: typeInfo.name }" @tap="sType.open(typeInfo.i)"
>{{ typeInfo.name || "请选择终端类型" }}
<image src="/static/iconImg/icon-right-jiantou.svg" mode="scaleToFill" />
</view>
</JInput>
</JMainCard>
<JMainCard wrapPd="0 30rpx" pd="0" v-if="createInfo.trmType == 2">
<view
class="select-wrapper"
@tap="
jumpPage('POS', posInfo.deviceId, {
deviceType: 3,
mchNo: information.mchNo,
storeId: information.storeId,
appId: information.appId,
})
"
>
<view class="select-mch" v-if="!posInfo.appId"> 请选择扫码POS </view>
<view class="mch-info" v-else>
<image src="/static/equipmentImg/pos-open.svg" mode="scaleToFill" />
<view
>{{ posInfo.deviceName }} <text>{{ posInfo.deviceNo }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx" v-if="createInfo.trmType">
<JInput
name="设备名称"
place="请输入设备名称"
v-model:value="createInfo.trmName"
:isBorder="true"
:rules="{ name: 'trmName', rule: 'REG_NotNUll' }"
></JInput>
<JInput
name="设备号"
v-if="createInfo.trmType == 1"
v-model:value="createInfo.trmNo"
place="请输入设备号"
:rules="{ name: 'trmNo', rule: 'REG_NotNUll' }"
></JInput>
<JInput name="是否门店默认" v-if="!createInfo.trmId">
<view class="state-text">
{{ createInfo.defaultFlag == 1 ? "是" : "否" }}
<switch
:checked="createInfo.defaultFlag == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe"
@change="change($event, 'defaultFlag')"
/>
</view>
</JInput>
<JInput name="设备状态">
<view class="state-text">
{{ createInfo.state == 1 ? "启用" : "禁用" }}
<switch
:checked="createInfo.state == 1 ? true : false"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#7737fe"
@change="change($event, 'state')"
/>
</view>
</JInput>
</JMainCard>
<JMainCard wrapPd=" 0 30rpx" pd=" 0" v-if="createInfo.trmType">
<JInput name="布放位置" :isBorder="true" :rules="{ name: 'detailAddress', rule: 'REG_NotNUll' }">
<view @tap="getAddress" class="place-text address" v-if="!createInfo.detailAddress"
>请选择位置 <view class="gps-img"> <image src="/static/iconImg/icon-gps.svg" mode="scaleToFill" /></view
></view>
<view @tap="getAddress" v-else class="place-text address" style="color: #000"
>{{ createInfo.detailAddress }}
<view class="gps-img"> <image src="/static/iconImg/icon-gps.svg" mode="scaleToFill" /></view>
</view>
</JInput>
</JMainCard>
<JMainCard pd="0" wrapPd="30rpx" v-if="createInfo.trmType">
<JInput name="省市区" :isBorder="true">
<uni-data-picker
:localdata="address"
@change="dataPickerChange($event, 'areaCode')"
v-slot:default="{ data, error, options }"
>
<view class="place-text" v-if="createInfo.areaCode?.length == 0"
>请选择省市区
<image src="/static/iconImg/icon-right-jiantou.svg" mode="scaleToFill" />
</view>
<view v-else style="font-size: 33rpx">{{ createInfo.addressInfo }}</view>
</uni-data-picker>
</JInput>
<JInput name="经纬度" v-if="createInfo.trmType">
<view class="place-text" v-if="!createInfo.lng">选择位置后自动生成</view>
<view style="font-size: 33rpx" v-else>{{ createInfo.lng }},{{ createInfo.lat }}</view>
</JInput>
</JMainCard>
<JButton
pdTop="0"
pd="0 30rpx 50rpx 30rpx"
bottom="55rpx"
v-if="createInfo.trmType"
@HandleTouch="confirmCreated"
>{{ createInfo.trmId ? "确认修改" : "确认创建" }}</JButton
>
</view>
<SelectedType ref="sType" @selected="selected" />
</template>
<script setup>
import { ref } from "vue"
import { onShow, onLoad } from "@dcloudio/uni-app"
import useStore from "@/hooks/useStore.js"
import { $addTerminal, $updateTerminal, $terminalInfo } from "@/http/apiManager.js"
import { validateArray } from "@/hooks/rules"
import tool from "@/util/tool.js" // 工具类函数
import address from "@/components/applyJson/address.json" // 地址
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue"
import JInput from "@/components/newComponents/JInput/JInput.vue"
import SelectedType from "./components/SelectedType.vue"
import { getMapKey } from "@/hooks/mapInfo.js"
const { getStore } = useStore()
onLoad((options) => {
if (options.trmId) return getList(options.trmId)
})
onShow(() => {
if (getStore("createINfo")) {
information.value = getStore("createINfo")
Object.assign(createInfo.value, information.value)
}
if (getStore("POS")?.appId) {
posInfo.value = getStore("POS")
createInfo.value.trmName = posInfo.value.deviceName
createInfo.value.trmNo = posInfo.value.deviceNo
}
})
const createInfo = ref({
areaCode: [],
areacodeNames: [],
defaultFlag: 0,
state: 1,
addressInfo: "",
detailAddress: undefined,
})
const sType = ref(null)
const typeInfo = ref({})
const posInfo = ref({})
const information = ref({})
const change = (e, val) => {
createInfo.value[val] = e.detail.value ? 1 : 0
}
const selected = (val) => {
typeInfo.value = val
createInfo.value.trmType = val.i + 1
}
const confirmCreated = () => {
if (createInfo.value.trmType == 2 && !createInfo.value.trmNo) {
return uni.showToast({
title: "请选择扫码POS",
icon: "none",
})
}
if (!createInfo.value.addressInfo && createInfo.value.location) {
return uni.showToast({
title: "请选择省市区和布放位置",
icon: "none",
})
} else {
if (validateArray(createInfo.value)) {
if (createInfo.value.trmId) {
$updateTerminal(createInfo.value.trmId, createInfo.value).then(() => {
uni.showToast({
title: "修改成功",
icon: "success",
mask: true,
})
})
uni.navigateBack()
} else {
$addTerminal(createInfo.value).then(() => {
uni.showToast({
title: "创建成功",
icon: "success",
mask: true,
})
})
uni.navigateBack({
delta: 2,
})
}
}
}
}
const getList = (val) => {
$terminalInfo(val).then(({ bizData }) => {
typeInfo.value.name = bizData.trmType == 1 ? "终端" : "扫码POS"
createInfo.value = bizData
createInfo.value.addressInfo = tool.addressBack(JSON.parse(bizData.areacode), address)
})
}
function getAddress() {
uni.chooseLocation({
latitude: createInfo.value.lat || undefined,
longitude: createInfo.value.lng || undefined,
success: (res) => {
createInfo.value.lng = res.longitude.toFixed(6)
createInfo.value.lat = res.latitude.toFixed(6)
createInfo.value.location = res.longitude + "/" + res.latitude
createInfo.value.detailAddress = res.address
getMapKey(res.address, 0).then((res) => {
createInfo.value.addressInfo = res.text
createInfo.value.areaCode = res.code
})
},
fail: (err) => {
console.log(err, "error")
},
})
}
const dataPickerChange = async (e, name) => {
createInfo.value.addressInfo = ""
createInfo.value.areaCode = []
e.detail.value.forEach((v, i) => {
createInfo.value.areaCode.push(v.value)
createInfo.value.addressInfo += i == e.detail.value.length - 1 ? v.text : v.text + "/"
})
const address = createInfo.value.addressInfo.split("/").join("")
getMapKey(address, 1).then((res) => {
createInfo.value.lng = parseFloat(res.lon).toFixed(6)
createInfo.value.lat = parseFloat(res.lat).toFixed(6)
createInfo.value.detailAddress = address
})
}
// 跳转到通用选择页面
const jumpPage = (val, selected, search) => {
if (search) search = JSON.stringify(search)
uni.navigateTo({
url: `/pageWork/SelectedList/SelectedList?title=${val}&selected=${selected}&&search=${search}`,
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
image {
width: 40rpx;
height: 40rpx;
vertical-align: bottom;
}
.select-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
.select-mch {
margin: 20rpx;
}
.mch-info {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 10rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 15rpx;
color: #8c8c8c;
font-size: 25rpx;
font-weight: 500;
}
}
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
image {
width: 60rpx;
height: 66rpx;
}
}
}
}
.tips {
font-size: 33rpx;
color: #a6a6a6;
}
.selected {
color: #000;
}
.place-text {
font-size: 33rpx;
color: #a6a6a6;
image {
width: 40rpx;
height: 40rpx;
margin-left: 10rpx;
vertical-align: middle;
}
}
.state-text {
font-size: 33rpx;
color: #666;
}
.address {
align-self: flex-start;
display: flex;
justify-content: flex-end;
align-items: center;
.gps-img {
align-self: flex-start;
display: flex;
justify-content: center;
align-items: center;
width: 50rpx;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,45 @@
<template>
<JPopup ref="popup" @onClose="onClose">
<JMainCard pd="0" wrapPd='30rpx'>
<block v-for="(v, i) in list" :key="i">
<JLine :name="v.name" :isSelect="i == index" :isBorder="true" @tap="selected({ name: v.name, i })"></JLine>
</block>
</JMainCard>
<JButton pd='0 30rpx 50rpx 30rpx' bgColor="#f2f2f2" color="#000" pdTop="0" @HandleTouch="popup.close()">取消</JButton>
</JPopup>
</template>
<script setup>
import { reactive, ref } from "vue"
import JPopup from "@/components/newComponents/JPopup/JPopup"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JLine from "@/components/newComponents/JLine/JLine"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
const emits = defineEmits(["selected"])
const list = reactive([
{
name: "终端",
},
{
name: "扫码POS",
},
])
const index = ref(undefined)
const popup = ref()
const selected = (val) => {
index.value = val.i
emits("selected", val)
close()
}
const open = (val) => {
if (val) index.value = val
popup.value.open()
}
const close = () => {
popup.value.close()
}
defineExpose({ open, close })
</script>

View File

@@ -0,0 +1,419 @@
<template>
<!-- 顶部自定义导航栏 -->
<JHeaderTitle
title="辅助终端设备详情"
:bgColor="header.bgColor"
color="#fff"
imgUrl="/static/iconImg/left-white.svg"
/>
<JEquiCode
bgImg="/static/equipmentImg/big-terminal.svg"
icon="/pageWork/static/images/terminal-white.svg"
:qrcAlias="terminalInfo.trmName"
:qrcId="terminalInfo.trmNo"
@editInfo="editInfo"
/>
<!-- 信息板块 -->
<JMainCard wrapPd="0 50rpx 30rpx " bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput
name="设备名称"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.trmName"
align="flex-start"
pd="15rpx 40rpx"
/>
<JInput
name="设备号"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.trmNo"
pd="15rpx 40rpx"
/>
<JInput name="设备类型" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view class="ter-type">
<image src="/static/equipmentImg/terminal-white.svg" />
{{ terminalInfo.trmType == 1 ? "终端设备" : "扫码POS" }}
</view>
</JInput>
<JInput
name="布放位置"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.detailAddress"
align="flex-start"
pd="15rpx 40rpx"
/>
<JInput name="经纬度" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<text style="color: #fff">{{ terminalInfo.lat + "/" + terminalInfo.lng }}</text>
</JInput>
<view class="line"></view>
<JInput
name="商户"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.mchName"
pd="15rpx 40rpx"
/>
<JInput
name="用户号"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.mchNo"
pd="15rpx 40rpx"
/>
<JInput
name="门店"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.storeName"
pd="15rpx 40rpx"
/>
<JInput
name="门店ID"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.storeId"
pd="15rpx 40rpx"
/>
<JInput
name="应用名称"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.appName"
pd="15rpx 40rpx"
/>
<JInput
name="AppId"
textColor="rgba(255, 255,255, 0.6)"
:isBorder="true"
size="30rpx"
:right="terminalInfo.appId"
pd="15rpx 40rpx"
/>
</JMainCard>
<!-- 信息板块 -->
<JMainCard wrapPd="0 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0">
<JInput name="是否默认" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view class="default">
<text>{{ terminalInfo.defaultFlag == 1 ? "是" : "否" }}</text>
<switch
v-if="terminalInfo.defaultFlag != 1"
:checked="terminalInfo.defaultFlag"
@change="stateChange($event, 'defaultFlag')"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
/>
<view class="state" v-else></view>
</view>
</JInput>
<JInput name="设备状态" textColor="rgba(255, 255,255, 0.6)" :isBorder="true" size="30rpx" pd="15rpx 40rpx">
<view class="item-right dis-wrapper">
<text style="margin-right: 10rpx; color: #fff">{{ terminalInfo.state == 1 ? "启用" : "禁用" }}</text>
<switch
:checked="terminalInfo.state"
@change="stateChange($event, 'state')"
style="margin-left: 20rpx; transform: scale(1.2)"
color="#BF80FF"
/>
</view>
</JInput>
</JMainCard>
<view class="bind-title" style="margin-top: 50rpx" v-if="channelList.length > 0">报备管理</view>
<JMainCard wrapPd="30rpx 50rpx" bgColor="rgba(0,0,0,0.1)" pd="25rpx 0" v-if="channelList.length > 0">
<scroll-view class="scroll-list" :scroll-y="true">
<view v-for="(item, index) in channelList" @tap="sendup(item)" class="channel-list" :key="index">
<!-- :textColor="item.textColor" -->
<JLayout
:bgColor="item.bgColor"
:icon="item.icon"
:ifName="item.ifName"
:stateColor="item.stateColor"
:stateText="item.stateText"
/>
</view>
</scroll-view>
</JMainCard>
<JButton
pd="20rpx 50rpx 50rpx 50rpx"
@HandleTouch="delTerminal"
pdTop="0"
color="#FF4D6A"
bgColor="rgba(255, 255, 255, 0.85)"
>删除终端</JButton
>
<!-- 通用二次弹窗组件 -->
<jeepayConfirm ref="jeepayConfirmRef" />
<!-- 渠道报备弹窗 -->
<JPopup ref="JPopupRef">
<JMainCard pd="0" wrapPd="0 30rpx" bgColor="transparent">
<view class="pop-body">
<view class="text">{{ sendText }}</view>
<JLayout
:bgColor="sendInfo.bgColor"
:icon="sendInfo.icon"
:ifName="sendInfo.ifName"
:stateColor="sendInfo.stateColor"
:stateText="sendInfo.stateText"
leftColor="#333"
:rightColor="sendInfo.state == 1 ? 'rgba(0, 0, 0, 0.4)' : 'rgba(0, 0, 0, 0.6)'"
:preBig="true"
:isImg="false"
/>
</view>
<view class="filing" @tap="filing" :style="{ color: sendInfo.state == 1 ? '#7737FE' : '#FF4C6A' }">{{
sendInfo.channelBindInfo?.state == 0
? "确认报备"
: sendInfo.channelBindInfo?.state == 2
? "重新报备"
: "确认注销"
}}</view>
{{ sendInfo.channelBindInfo?.state }}
</JMainCard>
<JButton pd="30rpx" bottom="50rpx" color="#303030" bgColor="rgba(255,255,255,0.8)" pdTop="0" @HandleTouch="cancel"
>取消</JButton
>
</JPopup>
<JDeletedTips ref="switchTips" @confirm="confirm" @cancel="cancelSwitchTips" />
</template>
<script setup>
import { onLoad, onPageScroll, onShow } from "@dcloudio/uni-app"
import { ref, reactive, nextTick, toRaw } from "vue"
import {
$getMchTermChannelBindInfos,
$mchTermChannelSendup,
$delTerminal,
$updateTerminal,
$updateMchTermDefault,
$terminalInfo,
} from "@/http/apiManager.js"
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull.vue"
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 JLayout from "@/components/newComponents/JLayout/JLayout.vue"
import JDeletedTips from "@/components/newComponents/JDeletedTips/JDeletedTips"
const terminalInfo = reactive({}) // 终端设备信息
let trmId = ref("") // 设备ID
const jeepayConfirmRef = ref() // 二次弹窗组件
const JPopupRef = ref() // 弹窗组件
onShow(() => {
$terminalInfo(trmId.value).then(({ bizData }) => {
bizData.appName ? bizData.appName : (bizData.appName = "默认应用")
Object.assign(terminalInfo, bizData)
})
})
const switchTips = ref(null)
onLoad((option) => {
trmId.value = option.id // 得到设备ID
// 请求可报备的渠道列表
getChannelList()
})
let keys = null
// 更换状态
const stateChange = (e, key) => {
keys = key
let val = e.detail.value
terminalInfo[keys] = Number(val)
switchTips.value.open("确认修改吗?")
}
const confirm = () => {
const data = {}
data[keys] = terminalInfo[keys]
keys = null
$updateTerminal(terminalInfo.trmId, data).then(() => {
uni.showToast({
title: "修改成功",
icon: "success",
})
})
}
const cancelSwitchTips = (val) => {
if (!keys) return
terminalInfo[keys] = Number(!terminalInfo[keys])
}
// 更改默认状态
const flagChange = (e) => {
let val = Number(e.detail.value)
terminalInfo.defaultFlag = val
jeepayConfirmRef.value.comfirmOpen(
() => {
$updateMchTermDefault(terminalInfo.trmId, val).then((res) => {
uni.showToast({ title: "更新成功", icon: "none" })
})
},
"是否更改为默认设备",
() => (terminalInfo.defaultFlag = Number(!val))
)
}
// 请求可报备的渠道列表
let channelList = ref([])
const getChannelList = () => {
$getMchTermChannelBindInfos(trmId.value).then(({ bizData }) => {
bizData.forEach((item) => {
if (item.channelBindInfo.state == 0 || !item.channelBindInfo?.state) {
item.stateText = "未报备"
item.stateColor = "rgba(0,0,0,.5)"
} else if (item.channelBindInfo.state == 1) {
item.stateText = "报备成功"
item.stateColor = "#80f2ff"
} else if (item.channelBindInfo.state == 2) {
item.stateText = "报备失败"
item.stateColor = "#ff8095"
}
})
channelList.value = bizData
})
}
// 报备
let sendText = ref("{}") // 报备信息
let sendInfo = reactive({}) // 要报的备渠道信息
const sendup = (info) => {
Object.assign(sendInfo, info)
info.channelBindInfo.state == 1
? (sendText.value = "是否注销当前设备所选渠道的报备?")
: (sendText.value = "是否对当前设备所选渠道进行报备?")
JPopupRef.value.open() // 开启弹窗
}
// 确认 and 取消报备
const filing = () => {
JPopupRef.value.close() // 关闭弹窗
$mchTermChannelSendup(trmId.value, sendInfo.ifCode, sendInfo.state).then((res) => {
// 刷新报备列表
getChannelList()
uni.hideLoading()
uni.showToast({ title: "操作成功", icon: "none" })
})
}
const cancel = () => JPopupRef.value.close() // 关闭弹窗
// 跳转至编辑详情
const toEdit = () => uni.navigateTo({ url: "./addTerminal?id=" + trmId.value })
// 删除终端
const delTerminal = () => {
jeepayConfirmRef.value.comfirmOpen(() => {
$delTerminal(terminalInfo.trmId).then((res) => {
uni.showToast({ title: "删除成功", icon: "none" })
})
uni.navigateBack({}) // 删除完毕返回上一页
}, "是否进行删除")
}
const editInfo = () => {
uni.navigateTo({
url: "./addTerminalNext?trmId=" + terminalInfo.trmId,
})
}
// 监听页面滚动 用于给自定义导航栏换背景色
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">
.ter-type {
display: flex;
align-items: center;
justify-content: flex-end;
color: #fff;
font-size: 30rpx;
image {
width: 36rpx;
height: 36rpx;
margin-right: 10rpx;
}
}
// 中间的分割线
.line {
border-top: 1rpx solid #6858ec;
margin: 25rpx 40rpx;
}
.default {
display: flex;
align-items: center;
justify-content: flex-end;
text {
margin-right: 10rpx;
color: #fff;
}
.state {
width: 42rpx;
height: 42rpx;
border-radius: 50%;
background-color: #bf80ff;
}
}
.scroll-list {
max-height: 50vh;
}
.channel-list {
box-sizing: border-box;
padding: 0 40rpx;
overflow: hidden;
}
.filing {
text-align: center;
font-size: 33rpx;
line-height: 110rpx;
height: 110rpx;
border-top: 1rpx solid rgba($color: #000000, $alpha: 0.3);
border-radius: 0 0 20rpx 20rpx;
// background: rgba(255, 255, 255, 0.8);
background: rgba(255, 255, 255);
}
.pop-body {
padding: 30rpx;
background-color: #fff;
.text {
font-size: 27rpx;
color: #333;
margin-bottom: 30rpx;
}
}
</style>

View File

@@ -0,0 +1,85 @@
<template>
<view class="page">
<view class="mch-header">
<JHeaderTitle title="辅助终端设备" bgColor="#f2f2f2" />
<JSearchInput @search="searchHandle" @resetSearch="reset" ref="search" place="搜索商户号、名称、设备号" />
</view>
<view v-for="(item, index) in useDataResult.dataList" :key="item.agentNo" @click.stop="toDetail(item.trmId)">
<JPreview v-bind="item.info" :key="item.trmNo" :isLast="index === useDataResult.dataList.length - 1" />
</view>
<jeepayListNull :list="useDataResult.dataList.length" :isShow="true" />
<view class="mch-footers">
<JButton pd="30rpx 30rpx 50rpx 30rpx" pdTop="0" @HandleTouch="createAux">创建辅助终端</JButton>
</view>
</view>
</template>
<script setup>
import { reactive, ref, toRaw } from "vue"
import { $terminalList } from "@/http/apiManager.js"
import { onShow, onBackPress } from "@dcloudio/uni-app"
import JButton from "@/components/newComponents/JButton/JButton.vue"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull.vue"
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue"
import useGetList from "@/hooks/useList.js"
import JPreview from "@/components/newComponents/JPreview/JPreview.vue"
const dataHandle = (data) => {
data.forEach((item) => {
item.info = {
img: item.state == 1 ? "/static/equipmentImg/terminal-open.svg" : "/static/equipmentImg/terminal-close.svg",
title: item.trmName ? item.trmName : "未命名",
qrcId: item.trmNo,
spot: item.state == 1 ? "#7737FE" : "#B2B2B2",
status: item.state == 1 ? "已启用" : "已禁用",
mchName: item.mchName,
mchNo: item.mchNo,
}
})
return data
}
const { useDataResult, getList } = useGetList({
requestFun: $terminalList,
dataHandle,
})
const search = ref(null) // 注册搜索组件
// 搜索
const searchHandle = (val) => getList({ unionSearchId: val })
// 重置搜索
const reset = () => getList({ unionSearchId: "" })
// 输入框存在内容时,清空文字,列表重置
onBackPress(() => {
if (search.value.searchText != "") {
search.value.searchText = ""
reset()
return true
}
return false
})
// 跳转至新增终端
const createAux = () => uni.navigateTo({ url: "./addTerminal" })
// 跳转至详情
const toDetail = (id) => uni.navigateTo({ url: "./terminalDetil?id=" + id })
</script>
<style lang="scss" scoped>
.mch-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #f2f2f2;
}
.mch-footers {
position: fixed;
left: 0;
right: 0;
bottom: 0;
backdrop-filter: blur(30px);
border-top: 1px solid rgba($color: #000000, $alpha: 0.1);
}
</style>

View File

@@ -0,0 +1,74 @@
<template>
<view class="agent-wrapper" :style="{ padding: pd }">
<view class="agent-left">
<image :src="userImg" mode="scaleToFill" />
<view class="agent-info" :style="{ color: nameColor, fontWeight: nameWeight }">
{{ name }}
<view :style="{ color: textColor }">{{ agentNo }}</view>
</view>
</view>
<image :src="arrowImg" mode="scaleToFill" />
</view>
</template>
<script setup>
const props = defineProps({
userImg: {
type: String,
default: "/static/iconImg/user-white.svg",
},
arrowImg: {
type: String,
default: "/static/iconImg/right-arrow.svg",
},
name: {
type: String,
},
agentNo: {
type: String,
},
pd: {
type: String,
},
textColor: {
type: String,
},
nameColor: {
type: String,
},
nameWeight: {
type: String,
},
})
</script>
<style lang="scss" scoped>
.agent-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
box-sizing: border-box;
.agent-left {
display: flex;
align-items: center;
image {
width: 82rpx;
height: 82rpx;
margin-right: 20rpx;
}
.agent-info {
font-size: 28rpx;
view {
margin-top: 10rpx;
font-size: 23rpx;
color: rgba(255, 255, 255, 0.6);
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
}
</style>

View File

@@ -0,0 +1,121 @@
<template>
<JPopup ref="popup" @onClose="onClose">
<view class="list-wrapper">
<view class="list-header">
<view class="list-title">
<image src="/static/iconImg/left-black.svg" mode="scaleToFill" @tap="popup.close()" />
单个子代理商
</view>
<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" @HandleTouch="confirm">确认</JButton>
</view>
</view>
</JPopup>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue"
import { $getAgentList } from "@/http/apiManager.js"
import JPopup from "@/components/newComponents/JPopup/JPopup"
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 emits = defineEmits(["confirm"])
const searchInfo = ref({
pageNumber: 1,
pageSize: 10,
})
let flag = true
const list = ref([])
const agentNo = ref({})
const popup = ref()
const open = (val) => {
if (val) agentNo.value.text = val.agentNo
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)
close()
}
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: 500rpx;
background-color: #fff;
}
.list-footer {
padding: 30rpx 0 50rpx 0;
background-color: #fff;
}
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<view class="o-c-wrapper">
<image :src="imgObj[wayCodeType]" mode="scaleToFill" />
<view class="o-c-info">
<view class="i-top">
{{ (amount / 100).toFixed(2) }}
<view class="t-state" v-if="refundState == 1 || refundState == 2"
><text class="s-spot" :style="{ backgroundColor: refundStateList[refundState].bgColor }"></text>
{{ refundStateList[refundState].text }}</view
>
<view class="t-state" v-else
><text class="s-spot" :style="{ backgroundColor: stateList[state].bgColor }"></text>
{{ stateList[state].text }}</view
>
</view>
<view class="i-time">{{ createdAt.split("-").join("/") }}</view>
<view class="i-refund" v-if="refundState == 1 || refundState == 2">
<view>退款{{ (refundAmount / 100).toFixed(2) }}</view>
<view class="i-last">剩余{{ ((amount - refundAmount) / 100).toFixed(2) }}</view>
</view>
</view>
</view>
</template>
<script setup>
import { reactive, ref } from "vue"
const props = defineProps({
wayCodeType: { type: String }, //图片地址
state: { type: Number }, //订单状态
amount: { type: String }, //订单金额
createdAt: { type: String }, //订单创建时间
refundState: { type: String }, //退款状态 0 为退款 1部分退款 2全额退款
refundAmount: { type: String }, //退款金额
})
const imgObj = reactive({
WECHAT: "/static/orderImg/wechat.svg",
ALIPAY: "/static/orderImg/zfb.svg",
YSFPAY: "/static/orderImg/ysf.svg",
UNIONPAY: "/static/orderImg/union-pay.svg",
OTHER: "/static/orderImg/default-pay.svg",
})
const stateList = reactive([
{
text: "订单生成",
bgColor: "#FFA900",
},
{
text: "支付中",
bgColor: "#FFA900",
},
{
text: "支付成功",
bgColor: "#175be6",
},
{
text: "支付失败",
bgColor: "#ff0000",
},
{
text: "已撤销",
bgColor: "",
},
{
text: "已退款",
bgColor: "",
},
{
text: "订单关闭",
bgColor: "#9EA5B3",
},
])
const refundStateList = reactive([
{},
{
text: "部分退款",
bgColor: "#FD2821",
},
{
text: "全额退款",
bgColor: "#FD2821",
},
])
</script>
<style lang="scss" scoped>
.o-c-wrapper {
display: flex;
padding: 30rpx 0 0 30rpx;
image {
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
border-radius: 16rpx;
}
.o-c-info {
flex: 1;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.1);
.i-top {
display: flex;
justify-content: space-between;
font-size: 23rpx;
font-weight: 900;
.t-state {
margin-right: 30rpx;
font-size: 30rpx;
font-weight: 500;
.s-spot {
display: inline-block;
width: 10rpx;
height: 10rpx;
vertical-align: middle;
margin-right: 10rpx;
border-radius: 50%;
background-color: #06c05f;
}
}
}
.i-time {
margin: 25rpx 0;
font-size: 25rpx;
color: #8c8c8c;
}
.i-refund {
display: flex;
margin-bottom: 30rpx;
font-size: 25rpx;
.i-last {
margin-left: 28rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,328 @@
<template>
<JPopup ref="popup" @onOpen="emits('onOpen')" @onClose="emits('onClose')">
<JMainCard pd="0" wrapPd="30rpx">
<ScreenTitle bgColor="#7737FE" :list="timeList" bdR="20rpx 20rpx 0 0" :index="timeIndex.i" @search="search" />
<view class="screen-wrapper">
<view class="src-main bgF">
<view class="select-wrapper bgF2" @tap="sAgent.open(agentInfo)">
<view class="select-mch" v-if="agentInfo.text == '' || agentInfo.text == 'onlyOne'">
<image src="/static/navImg/disable-dailishang.svg" mode="scaleToFill" /> {{ agentInfo.name }}
</view>
<view class="mch-info" v-else>
<image src="/static/navImg/nav-dailishang.svg" mode="scaleToFill" />
<view
>{{ agentInfo.name }} <text>{{ agentInfo.text }}代理商</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
<view class="select-wrapper select-agent bgF2" v-if="agentInfo.text == 'onlyOne'" @tap="sMch.open()">
<view class="select-mch" v-if="!mchInfo.text">
<image src="/static/iconImg/icon-selected-mch.svg" mode="scaleToFill" /> 全部子商户
</view>
<view class="mch-info" v-else>
<image src="/static/equipmentImg/mch-list.svg" mode="scaleToFill" />
<view
>{{ mchInfo.name }} <text>{{ mchInfo.text }}</text>
</view>
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
<view class="title">订单状态</view>
<view class="order-wrapper">
<block v-for="(v, i) in stateList" :key="i">
<view class="order-item" :class="{ 'selected-state': stateIndex.includes(i) }" @tap="stateChange(v, i)">{{
v
}}</view>
</block>
</view>
<view class="title">支付方式</view>
<view class="order-wrapper">
<block v-for="(v, i) in payList" :key="i">
<view
class="order-item"
@tap="selectedPay(v.value, i)"
:class="{
'selected-state': payIndex.includes(v.value) && v.value,
'selected-none': payList.length - 1 == i,
}"
>{{ v.text }}</view
>
</block>
</view>
</view>
</view>
</JMainCard>
<view class="scr-footer">
<view @tap="reset">重置</view>
<view class="confirm" @tap="confirm">确认筛选</view>
</view>
</JPopup>
<selectMch ref="sMch" @confirm="mchConfirm" />
<selectAgent ref="sAgent" @selected="agentSelected" @oneAgent="onAgent" />
<AgentList ref="AList" @confirm="agentListC" />
</template>
<script setup>
import { onMounted, reactive, ref, watch, watchEffect } from "vue"
import JPopup from "@/components/newComponents/JPopup/JPopup"
import ScreenTitle from "@/components/newComponents/ScreenTitle/ScreenTitle"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import selectMch from "./selectMch.vue"
import selectAgent from "./selectAgent.vue"
import AgentList from "./AgentList.vue"
const emits = defineEmits(["confirm", "onOpen", "onClose"])
const timeList = reactive([
{ value: "", text: "全部" },
{ value: "today", text: "今天" },
{ value: "yesterday", text: "昨天" },
{ value: "currMonth", text: "本月" },
{ value: "prevMonth", text: "上月" },
{ value: "customer", text: "自定义" },
])
const payList = reactive([
{ value: "WECHAT", text: "微信支付" },
{ value: "ALIPAY", text: "支付宝" },
{ value: "YSFPAY", text: "云闪付" },
{ value: "UNIONPAY", text: "银联" },
{ value: "OTHER", text: "其他" },
{ value: "", text: "" },
])
const stateList = reactive(["订单生成", "支付中", "支付成功", "支付失败", "已撤销", "已退款", "订单关闭"])
// 获取组件身上的方法
const popup = ref(null)
const sMch = ref(null)
const sAgent = ref(null)
const AList = ref(null)
const index = ref("all")
const stateIndex = ref([5, 2])
const timeIndex = ref({ val: { text: "全部", value: "" }, i: 0 })
const payIndex = ref([])
// 商户详情
const mchInfo = ref({})
// 代理商详情
const agentInfo = ref({ name: "我与全部子代理商", text: "" })
const search = (val) => {
if (val.val.text == "自定义" && val.val.time) {
val.val.value = val.val.time
}
timeIndex.value = val
}
const stateChange = (v, i) => {
if (stateIndex.value.findIndex((val) => val == i) != -1) {
stateIndex.value.splice(
stateIndex.value.findIndex((val) => val == i),
1
)
} else {
stateIndex.value.push(i)
}
}
const selectedPay = (v, i) => {
if (payIndex.value.findIndex((val) => val == v) != -1) {
payIndex.value.splice(
payIndex.value.findIndex((val) => val == v),
1
)
} else {
if (v == "none") return
payIndex.value.push(v)
}
}
const open = (val) => {
stateIndex.value = []
payIndex.value = []
val.forEach((v) => {
switch (v.type) {
case 0:
stateIndex.value.push(v.value)
break
case 2:
payIndex.value.push(v.value)
break
}
})
payIndex.value = val.find((v) => v.type == 2) ? payIndex.value : payList.map((v) => v.value)
if (payIndex.value.findIndex((v) => !v) != -1) {
payIndex.value.splice(
payIndex.value.findIndex((v) => !v),
1
)
}
timeIndex.value = val.find((v) => v.type == 1)?.value ? timeIndex.value : { val: { text: "全部", value: "" }, i: 0 }
stateIndex.value = stateIndex.value.length == 0 ? (stateIndex.value = [2, 5]) : stateIndex.value
popup.value.open()
}
// 选择商户回调
const mchConfirm = (val) => {
mchInfo.value = val
confirm()
}
// 选择代理商回调
const agentSelected = (val) => {
agentInfo.value = val
confirm()
}
// 列表选择回调
const agentListC = (val) => {
agentInfo.value = val
confirm()
}
const confirm = () => {
const list = []
stateIndex.value.forEach((v) => {
list.push({
text: stateList[v],
value: v,
type: 0,
})
})
list.push({
text:
timeIndex.value.val.text == "自定义"
? timeIndex.value.val.value.split("_")[1] + "/" + timeIndex.value.val.value.split("_")[2]
: timeIndex.value.val.text,
value: timeIndex.value.val.value,
type: 1,
})
payIndex.value.forEach((v) => {
list.push({
text: payList.find((val) => val.value === v).text,
value: v,
type: 2,
})
})
emits("confirm", { data: list, mch: mchInfo.value.text, agent: agentInfo.value.text })
popup.value.close()
sAgent.value.close()
}
// 重置 数据
const reset = () => {
timeIndex.value = { val: { text: "全部", value: "" }, i: 0 }
stateIndex.value = [5, 2]
payIndex.value = payList.map((v) => v.value)
payIndex.value.splice(payIndex.value.length - 1, 1)
agentInfo.value = { text: "", name: "我与全部子代理商" }
mchInfo.value = { text: "", name: "全部商户" }
}
const onAgent = (val) => {
AList.value.open(val)
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.screen-wrapper {
height: calc(100vh - 700rpx);
overflow-y: scroll;
}
.selected {
padding: 20rpx;
border-radius: 7rpx;
color: $primaryColor;
background-color: #fff;
}
.src-main {
padding: 30rpx;
.select-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
.select-mch {
margin: 20rpx;
image {
vertical-align: bottom;
}
}
.mch-info {
display: flex;
image {
width: 93rpx;
height: 93rpx;
margin-right: 10rpx;
}
view {
display: flex;
flex-direction: column;
font-size: 33rpx;
font-weight: 700;
text {
margin-top: 15rpx;
color: #8c8c8c;
font-size: 25rpx;
font-weight: 500;
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
width: 93rpx;
height: 93rpx;
margin-right: 20rpx;
image {
width: 60rpx;
height: 66rpx;
}
}
}
.select-agent {
margin-top: 30rpx;
}
.title {
margin: 35rpx 0 20rpx 0;
font-size: 30rpx;
font-weight: 700;
}
.order-wrapper {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
view {
flex: 0 0 32%;
padding: 20rpx 0;
margin-bottom: 15rpx;
box-sizing: border-box;
background-color: #f2f2f2;
border-radius: 10rpx;
text-align: center;
font-size: 28rpx;
color: #666;
}
.selected-state {
border: 2rpx solid $primaryColor;
color: $primaryColor;
}
.selected-none {
background-color: transparent;
}
}
}
.scr-footer {
display: flex;
justify-content: space-between;
padding: 0 30rpx 75rpx 30rpx;
font-size: 33rpx;
view {
flex: 1;
text-align: center;
padding: 31rpx;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 20rpx;
}
.confirm {
margin-left: 20rpx;
color: $primaryColor;
}
}
</style>

View File

@@ -0,0 +1,84 @@
<template>
<JPopup ref="popup">
<JMainCard pd="0" wrapPd=" 0 30rpx ">
<block v-for="(v, i) in list" :key="i">
<JLine :name="v.name" :isSelect="v.text == index.text" :isBorder="true" @tap="agentChange(v)"></JLine>
</block>
<view class="search-agent" @tap="emits('oneAgent', childrenAgent)">
<JInput name="选择代理商" :image="true" :isBorder="true" v-if="!index.text || index.text == 'onlyOne'">
<image src="/static/iconImg/icon-right-jiantou.svg" mode="scaleToFill" />
</JInput>
<AgentCard v-else v-bind="childrenAgent" pd="30rpx"></AgentCard>
</view>
</JMainCard>
<JButton size="max" bgColor="#f2f2f2" color="#000" pdTop="0" @HandleTouch="popup.close()">取消</JButton>
</JPopup>
</template>
<script setup>
import { reactive, ref } from "vue"
import JPopup from "@/components/newComponents/JPopup/JPopup"
import JMainCard from "@/components/newComponents/JMainCard/JMainCard"
import JLine from "@/components/newComponents/JLine/JLine"
import JInput from "@/components/newComponents/JInput/JInput"
import JButton from "@/components/newComponents/JButton/JButton"
import AgentCard from "./AgentCArd"
const emits = defineEmits(["selected", "oneAgent"])
const list = reactive([
{
name: "我与全部子代理商",
text: "",
},
{
name: "仅我自己",
text: "onlyOne",
},
{
name: "单个子代理商",
text: "one",
},
])
const agentList = ref()
const index = ref("")
const popup = ref()
const childrenAgent = ref({
userImg: "/static/iconImg/user-theme.svg",
nameColor: "#000",
textColor: "#8C8C8C",
nameWeight: "700",
})
const open = (val) => {
const value = JSON.parse(JSON.stringify(val))
if (value.text && value.text != "onlyOne") {
childrenAgent.value.name = value.name
childrenAgent.value.agentNo = value.text
index.value.text = "one"
}
index.value = value
popup.value.open()
}
const agentChange = (val) => {
if (!val.text || val.text != "one") {
index.value = val
emits("selected", val)
} else {
emits("oneAgent", val)
}
close()
}
const close = () => {
popup.value.close()
}
defineExpose({ open, close })
</script>
<style lang="scss" scoped>
.search-agent {
margin: 0 30rpx 30rpx 30rpx;
border-radius: 10rpx;
background-color: #f2f2f2;
image {
width: 40rpx;
height: 40rpx;
}
}
</style>

View File

@@ -0,0 +1,137 @@
<template>
<JPopup ref="popup" @onClose="onClose">
<view class="list-wrapper">
<view class="list-header">
<view class="list-title">
<image src="/static/iconImg/left-black.svg" mode="scaleToFill" @tap="popup.close()" />
单个商户
</view>
<JSearchInput
bgColor="#fff"
wrapPd="0"
@search="getAgentList"
place="请搜索商户名,用户号,联系人手机号"
@resetSearch="resetSearch"
></JSearchInput>
</view>
<scroll-view class="list-main" scroll-y @scrolltolower="getList">
<JLine
iconOn="/static/navImg/nav-shangdian.svg"
iconClose="/static/navImg/disable-shangdian.svg"
ml="30rpx"
pd="32rpx 32rpx 32rpx 0"
text="全部"
name="全部商户"
:isSelect="agentNo.text === ''"
@tap="selected({ text: '' })"
></JLine>
<block v-for="v in list" :key="v.text">
<JLine v-bind="v" :isSelect="agentNo.text === v.text" @tap="selected(v)"></JLine>
</block>
<jeepayListNull :isShow="true" :list="list.length"></jeepayListNull>
</scroll-view>
<view class="list-footer">
<JButton size="max" pdTop="0" @HandleTouch="confirm">确认</JButton>
</view>
</view>
</JPopup>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue"
import { $getMerList } from "@/http/apiManager.js"
import JPopup from "@/components/newComponents/JPopup/JPopup"
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 emits = defineEmits(["confirm"])
const searchInfo = ref({
pageNumber: 1,
pageSize: 10,
})
let flag = true
const list = ref([])
const agentNo = ref({})
const popup = ref()
const open = (val) => {
if (val) agentNo.value.text = val.agentNo
popup.value.open()
}
const close = () => {
popup.value.close()
}
const getAgentList = (val) => {
if (val) {
list.value = []
searchInfo.value.unionMchInfo = val
}
$getMerList(searchInfo.value).then(({ bizData }) => {
const { records } = bizData
if (records.length <= 0) flag = false
records.forEach((v) => {
let obj = {
iconOn: "/static/navImg/nav-shangdian.svg",
iconClose: "/static/navImg/disable-shangdian.svg",
ml: "30rpx",
pd: "32rpx 32rpx 32rpx 0",
}
obj.name = v.mchName
obj.text = v.mchNo
list.value.push(obj)
})
})
}
const getList = () => {
if (!flag) return
searchInfo.value.pageNumber++
getAgentList()
}
const resetSearch = () => {
list.value = []
searchInfo.value.unionMchInfo = ""
searchInfo.value.pageNumber = 1
searchInfo.value.pageSize = 10
getAgentList()
}
const selected = (v) => {
agentNo.value = v
}
const confirm = () => {
emits("confirm", agentNo.value)
close()
}
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: 500rpx;
background-color: #fff;
}
.list-footer {
padding: 30rpx 0 50rpx 0;
background-color: #fff;
}
}
</style>

View File

@@ -0,0 +1,258 @@
<template>
<JHeaderTitle title="订单详情" bgColor="#f2f2f2" />
<view class="page-wrapper global-wrapper bgF2">
<view class="o-header bdr-after border-f2 bdr-before bgF bdR20">
<image :src="imgObj[orderInfo.wayCodeType]" mode="scaleToFill" />
<view class="h-info">
<view class="h-top"><text></text>{{ (orderInfo.amount / 100).toFixed(2) }}</view>
<view class="h-num">
{{ orderInfo.payOrderId }}<text class="bdR10" @tap="copy(orderInfo.payOrderId)">复制</text></view>
</view>
</view>
<view class="o-info bdr-after bdr-before border-f2 bgF">
<view>
<view class="title">交易状态</view>
<text>{{
orderInfo.state == 2 && orderInfo.refundState
? refundStateList[orderInfo.refundState]?.text
: stateList[orderInfo.state]?.text
}}</text>
</view>
<view style="margin: 30rpx 0">
<view class="title">商户名</view> <text>{{ orderInfo.mchName }}</text>
</view>
<view style="margin-bottom: 30rpx">
<view class="title">支付方式</view>
<text>{{ pay[orderInfo.wayCodeType] }}</text>
</view>
<view style="margin-bottom: 30rpx">
<view class="title">顾客备注</view> <text>{{ orderInfo.buyerRemark }}</text>
</view>
<view>
<view class="title">创建时间</view> <text>{{ orderInfo.createdAt?.split("-").join("/") }}</text>
</view>
</view>
<view class="o-num bdr-after bdr-before border-f2 bgF">
<view style="margin-bottom: 30rpx">
<view class="title">商户订单号</view> <text>{{ orderInfo.mchOrderNo }}</text>
</view>
<view>
<view class="title">支付订单号</view> <text>{{ orderInfo.payOrderId }}</text>
</view>
</view>
<view class="o-price bdR20 bgF" :class="{
'bdr-after': orderInfo.state == 2 && orderInfo.refundState,
'bdr-before': orderInfo.state == 2 && orderInfo.refundState,
'border-f2': orderInfo.state == 2 && orderInfo.refundState,
}">
<view>
<view class="title">订单金额</view> <text>{{ (orderInfo.amount / 100).toFixed(2) }}</text>
</view>
<view style="margin: 30rpx 0">
<view class="title">商户手续费</view> <text>{{ (orderInfo.mchFeeAmount / 100).toFixed(2) }}</text>
</view>
<view>
<view class="title">我的佣金</view>
<text>{{ orderInfo?.profitAmount ? (orderInfo?.profitAmount / 100).toFixed(2) : "0.00" }}</text>
</view>
</view>
<view class="o-refund bdR20" v-if="orderInfo.state == 2 && orderInfo.refundState">
<view>
<view class="r-title">退款金额</view>
{{ (orderInfo.refundAmount / 100).toFixed(2) }}
</view>
<view>
<view class="r-title">剩余金额</view>
{{ ((orderInfo.amount - orderInfo.refundAmount) / 100).toFixed(2) }}
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { onBackPress, onLoad } from "@dcloudio/uni-app"
import { $getPayOrder } from "@/http/apiManager.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" //自定义导航栏
onLoad((option) => {
if (option.payOrderId) return getOrderDetail(option.payOrderId)
})
const orderInfo = ref({})
const imgObj = reactive({
WECHAT: "/static/orderImg/wechat.svg",
ALIPAY: "/static/orderImg/zfb.svg",
YSFPAY: "/static/orderImg/ysf.svg",
UNIONPAY: "/static/orderImg/union-pay.svg",
OTHER: "/static/orderImg/default-pay.svg",
})
const stateList = reactive([
{
text: "订单生成",
bgColor: "#FFA900",
},
{
text: "支付中",
bgColor: "#FFA900",
},
{
text: "支付成功",
bgColor: "#175be6",
},
{
text: "支付失败",
bgColor: "#ff0000",
},
{
text: "已撤销",
bgColor: "",
},
{
text: "已退款",
bgColor: "",
},
{
text: "订单关闭",
bgColor: "#9EA5B3",
},
])
const refundStateList = reactive([
{},
{
text: "部分退款",
bgColor: "#FD2821",
},
{
text: "全额退款",
bgColor: "#FD2821",
},
])
const pay = reactive({
WECHAT: "微信支付",
ALIPAY: "支付宝",
YSFPAY: "云闪付",
UNIONPAY: "银联",
OTHER: "其他",
})
const copy = (val) => {
uni.setClipboardData({
data: val,
})
}
const getOrderDetail = (payOrderId) => {
$getPayOrder(payOrderId).then(({ bizData }) => {
orderInfo.value = bizData
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
padding: 0 30rpx;
padding-bottom: 130rpx;
.o-header {
position: relative;
display: flex;
align-items: center;
padding: 50rpx;
image {
width: 93rpx;
height: 93rpx;
margin-right: 30rpx;
border-radius: 16rpx;
}
.h-info {
.h-top {
font-size: 33rpx;
font-weight: 700;
text {
font-size: 23rpx;
}
}
.h-num {
font-size: 25rpx;
color: #8c8c8c;
text {
display: inline-block;
padding: 13rpx 19rpx;
margin-left: 20rpx;
border: 1rpx solid rgba(0, 0, 0, 0.1);
}
}
}
}
.o-info,
.o-num,
.o-price {
position: relative;
padding: 50rpx;
view {
display: flex;
font-size: 30rpx;
color: #8c8c8c;
.title {
width: 160rpx;
}
text {
flex: 1;
margin-left: 48rpx;
color: #000;
}
}
}
.o-refund {
display: flex;
padding: 50rpx;
background-color: #f7392f;
view {
flex: 1;
color: #fff;
font-size: 33rpx;
font-weight: 700;
.r-title {
margin-bottom: 20rpx;
color: rgba(255, 255, 255, 0.6);
font-size: 25rpx;
font-weight: 500;
}
}
}
}
.border-f2 {
border-bottom: 2px dashed #f2f2f2;
}
.bdr-after::after,
.bdr-before::before {
content: "";
display: block;
position: absolute;
bottom: -25rpx;
z-index: 99;
width: 50rpx;
height: 50rpx;
background-color: #f2f2f2;
border-radius: 50%;
}
.bdr-after::after {
left: -25rpx;
}
.bdr-before::before {
right: -25rpx;
}</style>

View File

@@ -0,0 +1,161 @@
<template>
<page-meta :page-style="`overflow:${pageScrollFlag ? 'visible' : 'hidden'}`"></page-meta>
<view class="global-wrapper">
<view class="mch-header">
<JHeaderTitle title="交易记录" bgColor="#f2f2f2" />
<JSearchInput
@search="searchList"
@resetSearch="searchList($event, 'reset')"
ref="search"
@screen="scr.open(statePay)"
place="搜索订单号"
:screen="true"
/>
<view class="tips-wrapper" v-if="statePay.length > 0">
<view class="tips-list">
<block v-for="(v, i) in statePay" :key="i">
<view class="tips-item" v-if="v.text != '全部'"
>{{ v.text }}
<image @tap="delSearchTitle(i)" src="/static/iconImg/icon-deleted-order.svg" mode="scaleToFill"
/></view>
</block>
</view>
<view class="tips-right" @tap="clearScr">清空筛选</view>
</view>
</view>
<!-- 列表部分 -->
<view class="order-list">
<block v-for="v in useDataResult.dataList" :key="v.payOrderId">
<OrderCard v-bind="v" @tap="toDetail(v.payOrderId)" />
</block>
<jeepayListNull :isShow="true" :list="useDataResult.dataList.length" />
</view>
<screening ref="scr" @confirm="confirmGetList" @onOpen="pageScrollFlag = false" @onClose="pageScrollFlag = true" />
</view>
</template>
<script setup>
import { reactive, ref } from "vue"
import { onBackPress, onShow } from "@dcloudio/uni-app"
import { $getOrderList } from "@/http/apiManager.js" // 导入获取数据接口
import useGetList from "@/hooks/useList.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue" //自定义导航栏
import JSearchInput from "@/components/newComponents/JSearchInput/JSearchInput.vue" //自定义搜索框
import jeepayListNull from "@/components/jeepayListNull/jeepayListNull" //最后一条数据提示
import Screening from "./components/Screening"
import OrderCard from "./components/OrderCard"
const OrderId = ref(undefined)
const { useDataResult, getList } = useGetList({
requestFun: $getOrderList,
onshow: false,
params: {
unionOrderId: "",
unionOrderState: "5,2",
unionWayCodeType: "",
queryDateRange: "", //时间
mchNo: "", //商户Id
agentNo: "",
},
})
const statePay = ref([])
const pageScrollFlag = ref(true)
const filterState = (val) => {
const list = []
statePay.value.forEach((v) => {
if (v.type === val) {
list.push(v.value)
}
})
return list.join(",")
}
const scr = ref(null)
onShow(() => {
if (OrderId.value) {
getList({ unionOrderId: OrderId.value })
}
})
const delSearchTitle = (i) => {
statePay.value.splice(i, 1)
getList({
unionOrderState: filterState(0),
queryDateRange: statePay.value.find((v) => v.type == 1)?.value || "",
unionWayCodeType: filterState(2),
})
}
const clearScr = () => {
statePay.value = []
getList({
pageNumber: 1,
unionOrderId: "",
unionOrderState: "1,2",
unionWayCodeType: "",
queryDateRange: "", //时间
mchNo: "", //商户Id
agentNo: "",
})
}
const searchList = (data, val) => {
if (val == "reset") {
data = ""
OrderId.value = undefined
}
OrderId.value = data
getList({ unionOrderId: data })
}
// 跳转订单详情页
const toDetail = (payOrderId) => {
uni.navigateTo({
url: "./orderDetail?payOrderId=" + payOrderId,
})
}
const confirmGetList = (val) => {
statePay.value = val.data
getList({
unionOrderState: filterState(0) || "",
queryDateRange: statePay.value.find((v) => v.type == 1)?.value || "",
unionWayCodeType: filterState(2) || "",
mchNo: val.mch || "",
agentNo: val.agent || "",
})
}
</script>
<style lang="scss" scoped>
.mch-header {
position: sticky;
top: 0;
z-index: 40;
background-color: #f2f2f2;
.tips-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1rpx solid rgba(0, 0, 0, 0.1);
font-size: 28rpx;
.tips-list {
flex: 1;
display: flex;
padding-left: 20rpx;
overflow-x: scroll;
.tips-item {
padding: 20rpx;
margin: 0 10rpx;
white-space: nowrap;
border-radius: 16rpx;
background: rgba(0, 0, 0, 0.05);
image {
width: 36rpx;
height: 36rpx;
vertical-align: bottom;
margin-left: 15rpx;
}
}
}
.tips-right {
padding: 33rpx 20rpx;
color: #f23051;
border-left: 1rpx solid rgba(0, 0, 0, 0.1);
}
}
}
</style>