源文件

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,174 @@
<template>
<view class="me-wrapper global-wrapper bgF2">
<JHeaderTitle title="我的" bgColor="#fff" :back="false"></JHeaderTitle>
<view class="me-card">
<view class="me-card-left">
<image :src="userInfo.avatarUrl" mode="scaleToFill" />
<view class="user-info">
<view class="user-name single-text-beyond">{{ userInfo.realname }}</view>
<view class="user-phone">{{ phone(userInfo.telphone) }} </view>
</view>
</view>
<view class="me-card-right">
<view class="user-edit">
<image src="/static/iconImg/icon-edit.svg" mode="scaleToFill"
@tap="jumpPage('/pageWork/setUp/accountSetting')" />
</view>
<view class="user-scan">
<image src="/static/iconImg/scan-code.svg" mode="scaleToFill" @tap="scanCode" />
</view>
</view>
</view>
<view class="list-wrap">
<template v-for="(v, i) in newList" :key="i">
<ListCard v-bind="v" v-if="v.title != ''"></ListCard>
</template>
</view>
<view class="setting-block"></view>
<ListCard title="设置" imgUrl="/static/iconImg/setting.svg" isBorder="isBorder" url="/pageWork/setUp/setUp"></ListCard>
<blcok v-for="v in vdata.adList" :key="v.adverId">
<JeepayBanner :list="v.appContent" :interval='v.changeTime' v-if="v.appPlaceType == 2" />
<JeepayAdCard :list='v.appContent' v-if="v.appPlaceType == 1" />
</blcok>
<view class="setting-block"></view>
<!-- #ifdef APP-PLUS -->
<view style="height: 120rpx;"></view>
<!-- #endif -->
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { $getUserInfo, $scanCodeLogin, $adList } from "@/http/apiManager.js"
import JHeaderTitle from "@/components/newComponents/JHeaderTitle/JHeaderTitle.vue"
import ListCard from "./components/ListCard.vue"
import navList from "../workbench/navList/navList"
onShow(() => {
getUserInfo()
})
const newList = [
{
title: '我的邀请码',
url: '/pages/publicizeCode/publicizeCode',
imgUrl: '/static/indexImg/pub-icon.svg',
},
...navList
]
const userInfo = ref({})
const vdata = reactive({})
const getUserInfo = () => {
$getUserInfo().then(({ bizData }) => {
userInfo.value = bizData
console.log(userInfo.value)
})
}
const phone = (val) => {
if (!val) return
return val.slice(0, 3) + "****" + val.slice(-4)
}
const jumpPage = (url) => {
uni.navigateTo({
url,
})
}
const scanCode = () => {
uni.scanCode({
success: function (res) {
console.log("条码类型:" + res.scanType)
console.log("条码内容:" + res.result)
$scanCodeLogin({
qrcodeNo: res.result,
qrcodeStatus: "scaned",
}).then((val) => {
uni.navigateTo({
url: "./scan?id=" + res.result,
})
})
},
fail(err) {
console.log(err)
},
})
}
// 请求首页广告
$adList({ appPlace: 3 }).then(({ bizData }) => {
bizData.forEach(v => {
v.appContent = JSON.parse(v.appContent)
})
vdata.adList = bizData
console.log(bizData)
})
</script>
<style lang="scss" scoped>
.me-wrapper {
width: 100%;
.me-card {
display: flex;
justify-content: space-between;
align-items: center;
padding: 50rpx;
background-color: #fff;
.me-card-left {
display: flex;
image {
width: 130rpx;
height: 130rpx;
border-radius: 10rpx;
}
.user-info {
display: flex;
flex-direction: column;
justify-content: space-around;
margin-left: 30rpx;
.user-name {
width: 300rpx;
font-size: 33rpx;
}
.user-phone {
font-size: 27rpx;
color: #8c8c8c;
}
}
}
.me-card-right {
display: flex;
view {
position: relative;
width: 70rpx;
height: 70rpx;
border-radius: 10px;
background: rgba(119, 55, 254, 0.15);
&:last-child {
margin-left: 20rpx;
}
}
image {
position: absolute;
top: 50%;
left: 50%;
width: 30rpx;
height: 30rpx;
transform: translate(-50%, -50%);
}
}
}
}
.setting-block {
height: 20rpx;
background-color: #f2f2f2;
}
</style>

View File

@@ -0,0 +1,67 @@
<template>
<view class="list-main bgF" :style="{ marginTop: mTop, marginBottom: mBot }" @tap="jumpPage">
<image :src="imgUrl" mode="scaleToFill" />
<view class="main-info" :class="[isBorder]">
{{ title }}
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</view>
</view>
</template>
<script setup>
const props = defineProps({
mTop: {
type: String,
default: "0",
},
imgUrl: {
type: String,
},
title: {
type: String,
},
url: {
type: String,
},
isBorder: {
type: String,
},
})
const jumpPage = () => {
uni.navigateTo({
url: props.url,
})
}
</script>
<style lang="scss" scoped>
.list-main {
display: flex;
justify-content: space-between;
align-items: center;
height: 110rpx;
font-size: 33rpx;
image {
width: 40rpx;
height: 40rpx;
// margin: 0 50rpx 0 0;
margin-left: 50rpx;
margin-right: 30rpx;
}
.main-info {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
border-bottom: 1rpx solid #e5e5e5;
image {
margin-right: 50rpx;
}
}
}
.isBorder {
border: none !important;
}
</style>

View File

@@ -0,0 +1,88 @@
<template>
<JHeaderTitle title="登录确认" bgColor="#fff" imgUrl="/static/iconImg/icon-x.svg" @back="back"></JHeaderTitle>
<view class="scan-content">
<view class="computer">
<image src="/static/iconImg/computer.svg" mode=""></image>
<text>您正在登录代理商管理系统网站</text>
</view>
<view class="btn confirm" @tap="codeOk('confirmed')">确认登录</view>
<view class="btn cancel" @tap="codeOk('canceled')">取消登录</view>
</view>
</template>
<script setup>
import JHeaderTitle from '@/components/newComponents/JHeaderTitle/JHeaderTitle'
import { ref, reactive } from 'vue'
import { $scanCodeLogin } from '@/http/apiManager.js'
import { onLoad } from '@dcloudio/uni-app'
const code = ref('')
onLoad((option) => {
console.log(option)
code.value = option.id
})
// 点击左上交的取消按钮
const back = () => codeOk('canceled')
const codeOk = (val) => {
$scanCodeLogin({ qrcodeNo: code.value, qrcodeStatus: val })
.then((res) => {
uni.showToast({
title: val == 'confirmed' ? '登录成功' : '已取消'
})
setTimeout(function () {
uni.navigateBack({})
}, 1000)
})
.catch((err) => {
console.log(err)
})
}
</script>
<style scoped lang="scss">
.scan-content {
height: 100%;
width: 100%;
display: flex;
align-items: center;
flex-direction: column;
.computer {
margin-top: 260rpx;
margin-bottom: 150rpx;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
image {
width: 200rpx;
height: 200rpx;
}
text {
line-height: 46px;
font-size: 33rpx;
color: #000000;
}
}
.btn {
display: flex;
align-items: center;
justify-content: center;
width: 360rpx;
height: 110rpx;
border-radius: 20rpx;
background: #4dab68;
font-size: 33rpx;
}
.confirm {
color: #fff;
background-color: $primaryColor;
}
.cancel {
margin-top: 35rpx;
color: #666;
background: transparent;
}
}
</style>

View File

@@ -0,0 +1,15 @@
<template>
<web-view :src="src" />
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
const src = ref('')
onLoad((options) => {
console.log('options.url', options.url)
src.value = options.url
})
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,74 @@
<template>
<!-- #ifdef MP-WEIXIN -->
<StartPage :flag="!!vdata.list.length" />
<!-- #endif -->
<JeepayAdStart ref="refAdStart" :list="vdata.list" :time="10" :url="vdata.url" @openInt="openInt" />
</template>
<script setup>
import { $adList } from '@/http/apiManager.js'
import storageManage from '@/util/storageManage.js'
import { reactive, nextTick } from 'vue'
import { onShow, onLoad } from '@dcloudio/uni-app'
import StartPage from './components/StartPage.vue'
onShow(() => {
nextTick(() => {
if (vdata.list.length > 0 && timeStartFlag && opneInterval) {
opneInterval()
}
})
})
let opneInterval = undefined
const userInfo = storageManage.userInfo()
const vdata = reactive({
list: [],
url: '',
})
let timeStartFlag = false
const params = {
appPlace: 1,
}
const isLogin = (flag) => {
// vdata.url = storageManage.token()
// ? (userInfo && userInfo.isEpUuser) ? ' ' : '/pages/workbench/workbench'
// : '/pages/login/login'
vdata.url = storageManage.token()
? (userInfo && userInfo.isEpUuser) ? ' ' : '/pages/workbench/workbench'
: '/pages/workbench/workbenchCopy'
if (flag) {
if (vdata.url == '/pages/workbench/workbench')
return uni.switchTab({
url: vdata.url,
})
uni.redirectTo({
url: vdata.url,
fail: (info) => {
console.log(info)
},
})
}
}
isLogin()
const getList = async () => {
$adList(params).then(({ bizData }) => {
const adDate = bizData.map((v) => JSON.parse(v.appContent))
vdata.list = [...adDate.flat()]
if (!vdata.list.length) {
isLogin(true)
} else {
opneInterval()
}
}).catch(err => {
opneInterval()
})
}
getList()
const openInt = (fun) => {
opneInterval = fun
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,56 @@
<template>
<view class="start-wrapper" :class="{ 'start-wrapper-hiddren': flag }">
<view class="iamge-box">
<!-- <image class="start-logo" src="/static/logo.png" mode="scaleToFill" /> -->
<image class="mch-name" src="/static/startImg/agent-name.svg" mode="scaleToFill" />
</view>
</view>
</template>
<script setup>
import { ref } from "vue"
const props = defineProps({
flag: { type: Boolean, default: false }
})
</script>
<style lang="scss" scoped>
.start-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999999999;
min-height: 100vh;
background: url("/static/startImg/start-bg.svg") no-repeat top;
background-size: 100%;
// background: #fff;
.iamge-box {
transform: translateY(300rpx);
display: flex;
flex-direction: column;
align-items: center;
.start-logo {
width: 150rpx;
height: 150rpx;
border-radius: 12rpx;
}
.mch-name {
margin-top: 80rpx;
width: 300rpx;
height: 150rpx;
}
}
}
.start-wrapper-hiddren {
transition: 1s cubic-bezier(0.785, 0.135, 0.15, 0.86);
bottom: auto;
top: -100vh;
overflow: hidden;
}
</style>

View File

@@ -0,0 +1,725 @@
<template>
<navigationTitle :postion="false" :title="'工作台'"></navigationTitle>
<view class="content">
<view class="head">
<view class="head-image">
<image :src="vdata.userImg"></image>
</view>
<view class="head-rignt">
<view class="head-text">
<text class="head-title">{{ vdata.userName }}</text>
<text class="head-id">ID{{ vdata.userId }}</text>
</view>
<view class="head-set" @tap="goSetAccount">
<image :src="imageInfo.setting"></image>
</view>
</view>
</view>
<view class="title">
<text>管理工具</text>
</view>
<view class="entrances-body">
<view class="entrances" :class="{ 'grid-box': vdata.isList === false }">
<view class="entrance-box" @tap="toPage('applicationManagement')">
<view class="left">
<image :src="imageInfo.apply"></image>
<text>进件管理</text>
</view>
<view class="right">
<image :src="imageInfo.arrowGray"></image>
</view>
<!-- <view class="border"></view> -->
<view class="grid-border"></view>
</view>
<view class="entrance-box" @tap="toPage('merchantManagement')">
<view class="left">
<image :src="imageInfo.merchant"></image>
<text>商户管理</text>
</view>
<view class="right">
<image :src="imageInfo.arrowGray"></image>
</view>
<!-- <view class="border"></view> -->
<view class="grid-border"></view>
</view>
<view class="entrance-box" @tap="toPage('setUp')">
<view class="left">
<image :src="imageInfo.setUp"></image>
<text>设置</text>
</view>
<view class="right" style="border-bottom: none">
<image :src="imageInfo.arrowGray"></image>
</view>
</view>
</view>
</view>
<view class="title">
<text>数据统计</text>
</view>
<view class="header animation-close" :style="{ height: vdata.isA ? '230rpx' : '110rpx' }">
<view class="date-filter">
<view
class="date"
:class="vdata.selectFlge == item.index ? 'select' : ''"
v-for="(item, index) in vdata.selectList"
:key="index"
@click="onSelsct(index)"
>
<text>{{ item.text }}</text>
</view>
<view class="close" @click="onClose">
<image :class="vdata.isA ? 'animation' : ''" src="../../static/indexImg/down.png" mode=""></image>
</view>
</view>
<view class="time-picker">
<xp-picker @confirm="confirm" mode="ymdhi" :startTime="vdata.startDate">{{ vdata.startDate }}</xp-picker>
<text></text>
<xp-picker @confirm="confirmEnd" mode="ymdhi" :startTime="vdata.endDate">{{ vdata.endDate }}</xp-picker>
</view>
</view>
<view class="statistics" style="margin-top: 20rpx; background-color: #262e4d">
<view class="amount">
<text>收款金额</text>
</view>
<view class="money">
<text>{{ (indexData.payAmount / 100).toFixed(2) }}</text>
</view>
<view class="other">
<view class="deal-amount">
<text>收款笔数</text>
<text style="color: #ffffff; font-size: 28rpx">{{ indexData.payCount }}</text>
</view>
<view class="refund">
<text>退款金额</text>
<text style="color: #ffffff; font-size: 28rpx">{{ (indexData.refundAmount / 100).toFixed(2) }}</text>
</view>
<view class="refund-amount">
<text>退款笔数</text>
<text style="color: #ffffff; font-size: 28rpx">{{ indexData.refundCount }}</text>
</view>
</view>
</view>
<view class="statistics" style="background-color: #3981ff; border-radius: 0 0 20rpx 20rpx">
<view class="amount">
<text>商户总数</text>
</view>
<view class="money" style="color: #ffffff">
<text>{{ vdata.mchCount.mchAllCount }}</text>
</view>
<view class="other">
<view class="deal-amount">
<text>新增商户数</text>
<text style="color: #ffffff; font-size: 28rpx">{{ vdata.mchCount.mchTodayAddCount }}</text>
</view>
<view class="refund">
<text>入网商户数</text>
<text style="color: #ffffff; font-size: 28rpx">{{ vdata.mchCount.mchOnNetCount }}</text>
</view>
<view class="refund-amount">
<text>新增入网商户数</text>
<text style="color: #ffffff; font-size: 28rpx">{{ vdata.mchCount.mchOnNetNewCount }}</text>
</view>
</view>
</view>
<view class="footer"> </view>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { $statistics, $payIfDefines, $getUserInfo, $getPayDayCount, $getPayConfigIfcodes } from "@/http/apiManager.js"
import { onLoad, onBackPress, onShow } from "@dcloudio/uni-app"
import { intNum } from "@/util/intNumber.js"
import { getDay } from "@/util/timeInterval.js"
import navigationTitle from "@/components/jeepayNavigationTitle/jeepayNavigationTitle.vue"
const baseImage = ref("/static/iconImg/")
const blanceInfo = ref({})
const imageInfo = reactive({
setting: baseImage.value + "setting.svg",
close: baseImage.value + "icon-close.svg",
eyeClose: baseImage.value + "eye-close.svg",
list: baseImage.value + "grid.svg",
arrow: baseImage.value + "arrow-right.svg",
arrowGray: baseImage.value + "arrow-right-gray.svg",
apply: "/static/navImg/nav-jinjian.svg",
merchant: "/static/navImg/nav-shangdian.svg",
setUp: "/static/iconImg/setting.svg",
mch: baseImage.value + "store.svg",
})
const indexData = ref({})
const otherData = ref({})
const vdata = reactive({
amount: 0,
isPassword: true,
isList: false,
mchAllCount: 0,
mchTodayAddCount: 0,
userImg: "",
userName: "",
userId: "",
isA: false, //动画
isS: false,
selectFlge: 0, //时间选择框标志符
startDate: "", //开始时间
endDate: "", //结束时间
selectList: [
{ index: 0, value: "today", text: "今天" },
{ index: 1, value: "yesterday", text: "昨天" },
{ index: 2, value: "week", text: "近7天" },
{ index: 3, value: "mounth", text: "近30天" },
{ index: 4, value: "customer", text: "自定义" },
],
searchObj: {
isApp: true,
queryDateRange: "today",
},
staticObj: {
isApp: true,
queryDateRange: "today",
countType: 1,
agentNo: "",
},
mchCount: {},
})
const withdrawalPopup = ref()
onLoad(() => {
vdata.startDate = `${getDay(0, "-")} 00:00`
vdata.endDate = `${getDay(0, "-")} 23:59`
})
onShow(() => {
$getUserInfo().then(({ bizData }) => {
vdata.userImg = bizData.avatarUrl
vdata.userName = bizData.realname
vdata.userId = bizData.sysUserId
})
getStatistics(vdata.staticObj)
})
const getStatistics = (staticObj) => {
$statistics(staticObj).then(({ bizData }) => {
otherData.value = bizData
vdata.mchCount = bizData.mchCount
vdata.orderCount = bizData.orderCount
vdata.agentCount = bizData.agentCount
indexData.value = bizData.orderCount
})
}
const onSelsct = (index) => {
vdata.selectFlge = index
switch (index) {
case 0:
vdata.startDate = `${getDay(0, "-")} 00:00`
vdata.endDate = `${getDay(0, "-")} 23:59`
vdata.staticObj.queryDateRange = "today"
getStatistics(vdata.staticObj)
break
case 1:
vdata.startDate = `${getDay(-1, "-")} 00:00`
vdata.endDate = `${getDay(-1, "-")} 23:59`
vdata.staticObj.queryDateRange = "yesterday"
getStatistics(vdata.staticObj)
break
case 2:
vdata.startDate = `${getDay(-7, "-")} 00:00`
vdata.endDate = `${getDay(0, "-")} 23:59`
vdata.staticObj.queryDateRange = "near2now_7"
getStatistics(vdata.staticObj)
break
case 3:
vdata.startDate = `${getDay(-30, "-")} 00:00`
vdata.endDate = `${getDay(0, "-")} 23:59`
vdata.staticObj.queryDateRange = "near2now_30"
getStatistics(vdata.staticObj)
break
case 4:
if (!vdata.isA) {
vdata.isA = true
}
vdata.startDate = `${getDay(0, "-")} 00:00`
vdata.endDate = `${getDay(0, "-")} 23:59`
break
}
}
//时间选择器确定
const confirm = (e) => {
vdata.startDate = e.value
vdata.selectFlge = 4
// vdata.staticObj.queryDateRange = `customDate_${vdata.startDate}:00_${vdata.endDate}:59`
// getStatistics(vdata.staticObj)
}
const confirmEnd = (e) => {
vdata.endDate = e.value
vdata.selectFlge = 4
vdata.staticObj.queryDateRange = `customDate_${vdata.startDate}:00_${vdata.endDate}:59`
getStatistics(vdata.staticObj)
}
const onClose = () => {
vdata.isA = !vdata.isA
}
function toPage(path) {
if (path === "applicationManagement") {
// 获取进件列表的颜色 和 icon,给下一个页面用,因为异步请求的原因,所以在这里进行处理
let iconList = ref([])
$getPayConfigIfcodes("CURRENT", "agentApplyment", "").then(({ bizData }) => {
bizData.forEach((item) => {
iconList.value.push([item.bgColor, item.ifCode, item.icon])
})
uni.navigateTo({
url: `/pageApply/applyList?iconList=${JSON.stringify(iconList.value)}`,
})
})
return
}
uni.navigateTo({
url: `../../pageWork/${path}/${path}`,
})
}
let isShowSun = ref(false)
// 切换函数 睁眼闭眼 与 管理工具排列
function switchButton(sign) {
if (sign === "eye") {
vdata.isPassword = !vdata.isPassword
if (!vdata.isPassword) {
isShowSun.value = true
imageInfo.eyeClose = "../../static/workImg/eye-open.svg"
} else {
isShowSun.value = false
imageInfo.eyeClose = "../../static/workImg/eye-close.svg"
}
} else if (sign === "format") {
vdata.isList = !vdata.isList
if (!vdata.isList) {
imageInfo.list = "../../static/workImg/grid.svg"
} else {
imageInfo.list = "../../static/workImg/list.svg"
}
}
}
function toTabPage(path) {
uni.switchTab({
url: `../${path}/${path}`,
})
}
function goSetAccount() {
uni.navigateTo({
url: "../../pageWork/setUp/setUp",
})
}
</script>
<style>
page {
background: #f5f6fc;
}
</style>
<style lang="scss" scoped>
.content {
.animation-close {
transition: height 0.5s;
}
.animation {
transform: rotate(-180deg);
}
.select {
padding: 10rpx 10rpx;
border-radius: 10rpx;
background: rgba(57, 129, 255, 0.1);
font-weight: 500;
color: #3981ff;
}
box-sizing: border-box;
// padding: 0 50rpx;
image {
display: block;
}
.head,
.banner-box,
.title,
.entrances-body {
box-sizing: border-box;
padding: 0 50rpx;
}
.head {
display: flex;
width: 100%;
height: 90rpx;
margin: 30rpx 0 50rpx 0;
.head-image {
width: 90rpx;
height: 90rpx;
border-radius: 20rpx;
overflow: hidden;
//margin-right: 10rpx;
flex-shrink: 0;
image {
width: 100%;
height: 100%;
}
}
.head-rignt {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
margin-left: 10rpx;
.head-text {
display: flex;
flex-direction: column;
.head-title {
font-size: 30rpx;
font-weight: 700;
color: #292f46;
}
.head-id {
font-size: 22rpx;
color: #adacb3;
}
}
.head-set {
width: 40rpx;
height: 40rpx;
image {
width: 100%;
height: 100%;
}
}
}
}
.light {
background: #3981ff !important;
}
.title {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 40rpx;
margin: 50rpx 0 30rpx 10rpx;
text {
font-size: 28rpx;
font-weight: 700;
}
image {
width: 40rpx;
height: 40rpx;
}
}
.grid-box {
/* 九宫格 */
display: flex;
flex-wrap: wrap;
.entrance-box {
position: relative;
width: 33.33% !important;
height: 200rpx !important;
box-sizing: border-box !important;
justify-content: center !important;
align-items: center !important;
.left {
flex-direction: column !important;
image {
margin: 0 auto 22rpx auto !important;
}
}
.right {
image {
display: none !important;
}
}
.grid-border {
display: block !important;
position: absolute;
right: 0;
width: 2rpx;
height: 200rpx;
background: #f0f1f7;
}
}
}
.entrances {
border-radius: 20rpx;
overflow: hidden;
.entrance-box {
display: flex;
justify-content: space-between;
padding-left: 30rpx;
height: 110rpx;
background: #fff;
position: relative;
.left {
display: flex;
align-items: center;
image {
margin-right: 20rpx;
width: 50rpx;
height: 50rpx;
}
text {
color: #797b80;
font-size: 27rpx;
font-weight: 500;
}
}
.right {
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 30rpx;
image {
width: 40rpx;
height: 40rpx;
}
}
.border {
position: absolute;
bottom: 0;
right: 0;
width: 550rpx;
height: 2rpx;
background: #f0f1f7;
}
.grid-border {
display: none;
}
}
}
.roll-links {
width: 100%;
height: 650rpx;
.swiper {
width: 100%;
height: 500rpx;
position: relative;
box-sizing: border-box;
.position-item {
position: absolute;
left: -160rpx;
top: 0;
}
.first-item,
.second-item,
.more {
position: relative;
border-radius: 20rpx;
height: 500rpx;
overflow: hidden;
image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.swiper-text-box {
position: relative;
width: 100%;
height: 100%;
z-index: 9;
box-sizing: border-box;
padding: 50rpx 0 0 50rpx;
.swiper-text {
display: flex;
flex-direction: column;
margin-bottom: 40rpx;
.swiper-title {
display: block;
color: rgba(255, 255, 255, 0.5);
font-size: 25rpx;
margin-bottom: 15rpx;
}
.swiper-amount {
font-size: 40rpx;
font-weight: 700;
color: #ffffff;
}
}
}
}
.first-item {
width: 500rpx;
margin-left: 50rpx;
}
.second-item {
width: 570rpx;
display: flex;
image {
width: 325rpx;
border-radius: 20rpx;
}
.more {
width: 330rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #fff;
text {
color: #797b80;
}
}
}
}
}
.header {
box-sizing: border-box;
//height: 335rpx;
width: 650rpx;
background-color: #ffffff;
border-radius: 20rpx;
margin: 20rpx auto;
margin-bottom: 0;
overflow: hidden;
.date-filter {
box-sizing: border-box;
height: 90rpx;
width: 100%;
// background-color: #18BC37;
//border-bottom: 2rpx solid #FAFBFC;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 20rpx;
padding-right: 20rpx;
padding-top: 20rpx;
// padding-bottom: 20rpx;
.date {
//width: 92rpx;
//height: 53rpx;
display: flex;
justify-content: center;
align-items: center;
padding: 10rpx 10rpx;
}
.close {
height: 60rpx;
width: 60rpx;
// background-color: #007AFF;
//transform: rotate(180deg);
image {
height: 60rpx;
width: 60rpx;
transition: transform 0.5s;
}
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
}
.time-picker {
box-sizing: border-box;
width: 610rpx;
height: 72rpx;
border-radius: 10rpx;
background: #f5f6fc;
margin: 36rpx auto;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 20rpx;
padding-right: 20rpx;
font-size: 25rpx;
overflow: hidden;
}
}
.statistics {
box-sizing: border-box;
overflow: hidden;
width: 650rpx;
height: 368rpx;
border-radius: 20rpx;
background: #3981ff;
border-radius: 20rpx 20rpx 0 0;
margin: 0 auto;
display: flex;
flex-direction: column;
padding: 50rpx 35rpx 50rpx 35rpx;
.amount {
height: 40rpx;
font-weight: 500;
font-size: 23rpx;
color: rgba(255, 255, 255, 0.6);
}
.money {
// background-color: #18BC37;
display: flex;
align-items: center;
font-weight: bold;
font-size: 70rpx;
color: #fff;
padding: 10rpx 0 50rpx 0;
}
.other {
height: 100rpx;
width: 100%;
// background-color: #18BC37;
display: flex;
justify-content: space-between;
.deal-amount {
height: 85%;
width: 30%;
//background: #555500;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
font-weight: 500;
font-size: 23rpx;
color: rgba(255, 255, 255, 0.6);
}
.refund {
@extend .deal-amount;
}
.refund-amount {
@extend .deal-amount;
}
}
}
.footer {
height: 1rpx;
width: 100%;
margin-top: 30rpx;
}
}
</style>

View File

@@ -0,0 +1,144 @@
<!--
环境变量切换组件
@author terrfly
@site https://www.jeequan.com
@date 2022/04/12 10:14
-->
<template>
<view>
<!-- 当包含环境变量 && 不是生产环境时 -->
<view
class="login-test"
v-if="
vdata.currentEnvEnum &&
vdata.currentEnvEnum != appConfig.ENV_ENUM.PRODUCTION
"
><text>{{ vdata.currentEnvEnum }}</text></view
>
<!-- 切换环境提示 -->
<uni-popup ref="uniPopupRef" :mask-click="false" :open="false">
<view class="uni-popup-dialog">
<image
@tap="uniClose"
class="uni-dialog-close"
src="/static/img/account-delete.svg"
mode="scaleToFill"
/>
<view class="uni-dialog-button-box">
<view
class="uni-dialog-button"
style="border-bottom: 2rpx solid #e1e1e1"
@click="changeEnvFunc(appConfig.ENV_ENUM.DEVELOPMENT)"
><text>开发环境</text></view
>
<view
class="uni-dialog-button"
style="border-bottom: 2rpx solid #e1e1e1"
@click="changeEnvFunc(appConfig.ENV_ENUM.TEST)"
><text>测试环境</text></view
>
<view
class="uni-dialog-button"
style="border-bottom: 2rpx solid #e1e1e1"
@click="changeEnvFunc(appConfig.ENV_ENUM.DEMO)"
><text>演示环境</text></view
>
<view
class="uni-dialog-button"
@click="changeEnvFunc(appConfig.ENV_ENUM.PRODUCTION)"
><text>生产环境</text></view
>
</view>
</view>
</uni-popup>
</view>
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue'
import appConfig from '@/config/appConfig.js'
import envConfig from '@/env/config.js'
import storageManage from '@/util/storageManage.js'
const uniPopupRef = ref()
const vdata = reactive({
currentEnvEnum: '', // 当前环境变量
count: 0, // 当前点击次数
})
onMounted(() => {
vdata.currentEnvEnum = storageManage.env()
})
// 父组件的点击事件
function tapFunc() {
vdata.count++
if (vdata.count >= 10) {
vdata.count = 0
uniPopupRef.value.open()
}
}
// 改变环境函数
function changeEnvFunc(envMode) {
vdata.currentEnvEnum = envMode //显示信息
envConfig.changeEnv(envMode) //更改请求包
storageManage.env(envMode)
uniPopupRef.value.close() //弹层关闭
}
// 关闭弹窗
function uniClose() {
uniPopupRef.value.close()
}
defineExpose({ tapFunc })
</script>
<style lang="scss" scoped>
.uni-popup-dialog {
position: relative;
box-sizing: border-box;
width: 500rpx;
height: 750rpx;
overflow: hidden;
border-radius: 30rpx;
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: space-around;
.uni-dialog-close {
position: absolute;
top: 30rpx;
right: 30rpx;
width: 50rpx;
height: 50rpx;
}
.uni-dialog-button-box {
width: 100%;
box-sizing: border-box;
display: flex;
justify-content: space-around;
flex-direction: column;
text-align: center;
padding: 0 40rpx;
.uni-dialog-button {
width: 100%;
height: 150rpx;
line-height: 150rpx;
text {
font-size: 40rpx;
}
}
}
}
.login-test {
position: absolute;
bottom: 70rpx;
width: 100%;
text-align: center;
text {
color: #666f80;
}
}
</style>

View File

@@ -0,0 +1,73 @@
<template>
<view class="login-wrapper">
<LoginInput pd="0 50rpx" v-model:value="loginInfo.userName"></LoginInput>
<LoginInput title="密码" place="请输入账号密码" :password="!isOpenEyes" v-model:value="loginInfo.passwordType">
<view class="right-eyes" @tap="isOpenEyes = !isOpenEyes">
<image :src="eyeImg[isOpenEyes ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
<LoginButton @login="login" :forgotPassword="true" :isRegister="true"></LoginButton>
</view>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue"
import LoginInput from "@/components/newComponents/LoginInput/LoginInput"
import LoginButton from "./LoginButton"
import { $login, $getPasswordRules } from "@/http/apiManager.js"
import reg from "@/hooks/validate"
import { Base64 } from "js-base64"
onMounted(() => {
getRules()
})
const eyeImg = reactive(["/static/loginImg/login-eye-close.svg", "/static/loginImg/login-eye-open.svg"])
const emits = defineEmits(["successLogin"])
const selected = ref(false)
const isOpenEyes = ref(false)
const loginInfo = reactive({}) //密码信息
const rules = ref({})
const getRules = () => {
$getPasswordRules().then((res) => {
rules.value.rule = new RegExp(res.bizData.regexpRules)
rules.value.ruleText = res.bizData.errTips
})
}
const login = () => {
if (!loginInfo.userName && !loginInfo.passwordType) {
uni.showToast({
title: "请输入账号和密码",
icon: "none",
})
} else {
$login({
ia: Base64.encode(loginInfo.userName),
ip: Base64.encode(loginInfo.passwordType),
// #ifdef APP-PLUS
lt: Base64.encode("APP"),
// #endif
// #ifdef H5 || MP-WEIXIN
lt: Base64.encode("LITE"),
// #endif
}).then((res) => {
const { bizData } = res
emits("successLogin", bizData.iToken)
})
}
}
</script>
<style lang="scss" scoped>
image {
display: block;
width: 36rpx;
height: 36rpx;
}
.right-eyes {
display: flex;
justify-content: center;
align-items: center;
width: 110rpx;
height: 110rpx;
background-color: transparent;
}
</style>

View File

@@ -0,0 +1,362 @@
<template>
<JPopup ref="popup" @onClose="reset" @onOpen="isFlag">
<view class="register-main bgF" v-if="flag">
<LoginInput
title="手机号"
v-model:value="registerInfo.phone"
place="请输入注册手机号"
type="number"
:rules="{ name: 'phone', rule: 'REG_Phone' }"
pd="50rpx 50rpx 35rpx 50rpx"
>
<view class="sms-tips" v-if="registerInfo.phone.length == 11" @tap="createInterval">
<text v-if="smsNumber != 60">{{ smsNumber }}s</text>
{{ smsNumber !== 60 ? '后可重新发送' : '发送验证码' }}
</view>
</LoginInput>
<LoginInput
title="图形验证码"
v-model:value="registerInfo.vercode"
place="请输入图形验证码"
pd="0rpx 50rpx 35rpx 50rpx"
>
<view style="padding-top: 5px;">
<image :src="registerInfo.imgCodeUrl" style="width: 200rpx; height: 110rpx;margin-left: 10rpx;" @click="getCode" mode=""></image>
</view>
</LoginInput>
<LoginInput
title="验证码"
v-model:value="registerInfo.code"
place="请输入短信验证码"
type="number"
:rules="{ name: 'code', rule: 'REG_NotNUll' }"
pd="0 50rpx 35rpx 50rpx"
></LoginInput>
<LoginInput
title="代理商名称"
v-model:value="registerInfo.agentName"
place="请输入代理商名称"
:rules="{ name: 'agentName', rule: 'REG_NotNUll' }"
pd="0 50rpx 35rpx 50rpx"
></LoginInput>
<LoginInput
title="密码"
v-model:value="registerInfo.password"
place="请输入密码"
:rules="{ name: 'password', rule: 'REG_NotNUll' }"
:password="!isPassword"
pd="0 50rpx 35rpx 50rpx"
>
<view class="right-eyes" @tap="isPassword = !isPassword">
<image :src="eyeImg[isPassword ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
<LoginInput
title="确认密码"
v-model:value="registerInfo.confirmPwd"
:rules="{ name: 'confirmPwd', rule: 'REG_NotNUll' }"
place="请再次输入密码"
:password="!isOpenEyes"
pd="0 50rpx 35rpx 50rpx"
>
<view class="right-eyes" @tap="isOpenEyes = !isOpenEyes">
<image :src="eyeImg[isOpenEyes ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
<LoginInput title="邀请码" v-model:value="registerInfo.inviteCode" place="请输入邀请码(选填)" pd="0 50rpx 70rpx 50rpx"></LoginInput>
<view class="agreement-wrapper">
<button class="agree-item" id="agree-btn" open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handAgree">
<view class="agreement-garden" :class="[selected ? 'selected' : '']" @tap="selected = !selected"></view>
</button>
同意
<view @tap="toPage('/pages/login/serviceAgreement')"> 用户服务协议 </view>
<view @tap="toPrivacy"> 隐私政策 </view>
</view>
<view class="register-button">
<view @tap="close">取消</view>
<view class="confirm" @tap="confirm">确认注册</view>
</view>
</view>
</JPopup>
<JAgree service="/pages/login/serviceAgreement" privacy="/pages/login/privacyPolicy" ref="refAgr" @agree="selected = true"/>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { $sendMessage, $register, $getPasswordRules,$isCode } from '@/http/apiManager.js'
import { Base64 } from 'js-base64'
import { validateArray } from '@/hooks/rules'
import LoginInput from '@/components/newComponents/LoginInput/LoginInput'
import JPopup from '@/components/newComponents/JPopup/JPopup'
onMounted(() => {
getRules()
})
const vdata = reactive({})
const popup = ref(null)
const refAgr = ref(null)
const flag = ref(false)
const rules = ref({}) //密码规则
const registerInfo = ref({
phone: '',
inviteCode: '',
imgCodeUrl:'',
vercodeToken:'',
vercode:'',
})
const eyeImg = reactive(['/static/loginImg/login-eye-close.svg', '/static/loginImg/login-eye-open.svg'])
const selected = ref(false)
const isOpenEyes = ref(false)
const isPassword = ref(false)
const emits = defineEmits(['registerClose'])
const smsNumber = ref(60)
let interval = null
// 创建定时器
let createInterval = () => {
if (interval) return
sendMsg()
interval = setInterval(() => {
openInterval()
}, 1000)
}
const getCode=()=>{
$isCode().then(res=>
{
console.log(res);
registerInfo.value.imgCodeUrl=res.bizData.imageBase64Data
registerInfo.value.vercodeToken=res.bizData.vercodeToken
})
}
const getRules = () => {
$getPasswordRules().then((res) => {
rules.value.rule = new RegExp(res.bizData.regexpRules)
rules.value.ruleText = res.bizData.errTips
})
}
// smsNumber -1 倒计时
const openInterval = () => {
smsNumber.value--
if (smsNumber.value <= 0) {
smsNumber.value = 60
clearInterval(interval)
interval = null
}
}
// 发送短信验证码"
const sendMsg = () => {
if (interval) return
$sendMessage({
phone: registerInfo.value.phone,
smsType: 'register',
vercodeToken:registerInfo.value.vercodeToken,
vercode:registerInfo.value.vercode
})
.then((res) => {
const { bizData } = res
uni.showToast({
title: '发送成功',
icon: 'success',
mask: true,
})
})
.catch((err) => {
clearInterval(interval)
interval = null
})
}
const isFlag = () => {
flag.value = true
}
const open = () => {
popup.value.open()
getCode()
}
const close = () => {
reset()
popup.value.close()
}
const reset = () => {
flag.value = false
registerInfo.value = { phone: '' }
}
// 确认注册
const confirm = () => {
if (validateArray(registerInfo.value)) {
if (registerInfo.value.password !== registerInfo.value.confirmPwd)
return uni.showToast({
title: '两次密码输入不一致',
icon: 'none',
mask: true,
})
if (!rules.value.rule.test(registerInfo.value.confirmPwd))
return uni.showToast({
title: rules.value.ruleText,
icon: 'none',
})
if (!selected.value)
return refAgr.value.open()
uni.showLoading({
title: '正在注册中',
mask: true,
})
$register({
agentName: registerInfo.value.agentName,
phone: Base64.encode(registerInfo.value.phone),
code: Base64.encode(registerInfo.value.code),
confirmPwd: Base64.encode(registerInfo.value.confirmPwd),
inviteCode: registerInfo.value.inviteCode,
}).then((res) => {
uni.hideLoading()
uni.showToast({
title: '注册成功请登录',
icon: 'none',
mask: true,
})
close()
})
}
}
// 隐私政策页面
const toPrivacy = () => {
// #ifdef APP-PLUS
uni.navigateTo({
url: '/pages/login/privacyPolicy',
})
// #endif
// #ifdef MP-WEIXIN
wx.openPrivacyContract(
{
fail: () => {
uni.showToast({
title: '打开失败请稍后重试', // 打开失败
icon: 'none'
})
},
}
)
// #endif
}
// #ifdef MP-WEIXIN
const getPrivacy = () => {
wx.getPrivacySetting({
success: (r) => {
Object.assign(vdata, r)
if (vdata.needAuthorization) {
wx.onNeedPrivacyAuthorization(res => {
vdata.resolve = res
})
}
}
})
}
getPrivacy()
// #endif
const handAgree = () => {
// #ifdef MP-WEIXIN
if (vdata.needAuthorization) {
vdata.resolve({ buttonId: 'agree-btn', event: 'agree' })
}
// #endif
}
const toPage = (url) => {
uni.navigateTo({ url })
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.register-main {
width: 100%;
height: 70vh;
overflow-y: scroll;
border-radius: 32rpx 32rpx 0px 0px;
.register-button {
display: flex;
justify-content: space-between;
padding: 0 30rpx 70rpx 30rpx;
view {
flex: 1;
padding: 32rpx;
margin: 0 20rpx;
border-radius: 20rpx;
background-color: #f2f2f2;
text-align: center;
}
.confirm {
background-color: $primaryColor;
color: #fff;
}
}
}
.agreement-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
font-size: 24rpx;
white-space: nowrap;
transform: translateY(-40rpx);
color: #8c8c8c;
view {
margin: 0 10rpx;
color: $primaryColor;
}
.agreement-garden {
position: relative;
width: 30rpx;
height: 30rpx;
border-radius: 50%;
border: 2rpx solid $primaryColor;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
width: 80%;
height: 80%;
border-radius: 50%;
}
}
}
.selected::after {
background-color: $primaryColor;
}
.sms-tips {
font-size: 28rpx;
color: $primaryColor;
margin-right: 30rpx;
}
.right-eyes {
display: flex;
justify-content: center;
align-items: center;
width: 110rpx;
height: 110rpx;
background-color: transparent;
}
image {
width: 36rpx;
height: 36rpx;
}
.agree-item {
padding: 0;
margin: 0;
line-height: 0;
border-radius: 0;
background-color: transparent;
&::after{
display: none;
}
}
</style>

View File

@@ -0,0 +1,121 @@
<template>
<view class="sms-wrapper">
<LoginInput pd="0 50rpx" v-model:value="loginInfo.phone" title="手机号" type="number" place="请输入登录名/手机号">
<view class="sms-tips" v-if="loginInfo.phone.length == 11" @tap="createInterval">
<text v-if="smsNumber != 60">{{ smsNumber }}s</text>
{{ smsNumber !== 60 ? '后可重新发送' : '发送验证码' }}
</view>
</LoginInput>
<LoginInput
title="图形验证码"
v-model:value="loginInfo.vercode"
place="请输入图形验证码"
pd="50rpx 50rpx 0rpx 50rpx"
>
<view style="padding-top: 5px;">
<image :src="loginInfo.imgCodeUrl" style="width: 200rpx; height: 110rpx;margin-left: 10rpx;" @click="getCode" mode=""></image>
</view>
</LoginInput>
<LoginInput v-model:value="loginInfo.verificationCode" title="短信验证码" type="number" place="请输入短信验证码"></LoginInput>
<LoginButton @login="phoneCodeLogin" :isRegister="true"></LoginButton>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { $sendMessage, $login, $userInfo, $phoneCodeLogin, $getCompanyInfo,$isCode } from '@/http/apiManager.js'
import { Base64 } from 'js-base64'
import LoginInput from '@/components/newComponents/LoginInput/LoginInput'
import LoginButton from './LoginButton'
const emits = defineEmits(['successLogin'])
const loginInfo = reactive({
phone: '',
imgCodeUrl:'',
vercode:'',
vercodeToken:'',
})
const smsNumber = ref(60)
let interval = null
// 创建定时器
let createInterval = () => {
if (interval) return
sendMsg()
interval = setInterval(() => {
openInterval()
}, 1000)
}
const getCode=()=>{
$isCode().then(res=>
{
console.log(res);
loginInfo.imgCodeUrl=res.bizData.imageBase64Data
loginInfo.vercodeToken=res.bizData.vercodeToken
})
}
getCode()
// smsNumber -1 倒计时
const openInterval = () => {
smsNumber.value--
if (smsNumber.value <= 0) {
smsNumber.value = 60
clearInterval(interval)
interval = null
}
}
// 发送短信验证码"
const sendMsg = () => {
if (interval) return
$sendMessage({
phone: loginInfo.phone,
smsType: 'auth',
vercodeToken:loginInfo.vercodeToken,
vercode:loginInfo.vercode
})
.then((res) => {
const { bizData } = res
uni.showToast({
title: '发送成功',
icon: 'success',
mask: true,
})
})
.catch((err) => {
smsNumber.value = 60
clearInterval(interval)
})
}
// 验证码登录
const phoneCodeLogin = () => {
if (!loginInfo.phone.length != 11 && !loginInfo.verificationCode) {
uni.showToast({
title: '请输入手机号和验证码',
icon: 'none',
})
} else {
$phoneCodeLogin({
phone: Base64.encode(loginInfo.phone),
code: Base64.encode(loginInfo.verificationCode),
// #ifdef APP-PLUS
lt: Base64.encode('APP'),
// #endif
// #ifdef H5 || MP-WEIXIN
lt: Base64.encode('LITE'),
// #endif
}).then((res) => {
const { bizData } = res
emits('successLogin', bizData.iToken)
})
}
}
</script>
<style lang="scss" scoped>
.sms-wrapper {
.sms-tips {
font-size: 28rpx;
color: $primaryColor;
margin-right: 30rpx;
}
}
</style>

View File

@@ -0,0 +1,167 @@
<template>
<view class="agreement-wrapper">
<button class="agree-item" id="agree-btn" open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handAgree">
<view class="agreement-garden" :class="[selected ? 'selected' : '']" @tap="selected = !selected"></view>
</button>
同意
<view @tap="toPage('/pages/login/serviceAgreement')"> 用户服务协议 </view>
<view @tap="toPage('/pages/login/privacyPolicy')"> 隐私政策 </view>
<!-- <view @tap="toPrivacy"> 隐私政策 </view> -->
</view>
<JButton pdTop="0" @HandleTouch="login" bottom="30rpx">登录</JButton>
<view class="register-wrapper">
<view v-if="isRegister">还没有账号?<text @tap="register.open()">去注册</text> </view>
<view v-if="forgotPassword"><text @tap="jumpPage">忘记密码</text></view>
</view>
<JRegister ref="register"></JRegister>
<JAgree service="/pages/login/serviceAgreement" privacy="/pages/login/privacyPolicy" ref="refAgr" @agree="selected = true"/>
</template>
<script setup>
import { ref ,reactive,onMounted} from "vue"
import JButton from "@/components/newComponents/JButton/JButton"
import JRegister from "./JRegister.vue"
import { clearRulesArray } from "@/hooks/rules"
const register = ref(null)
const vdata = reactive({})
const props = defineProps({
forgotPassword: {
type: Boolean,
default: false,
},
isRegister: {
type: Boolean,
default: false,
},
})
const refAgr = ref(null)
const selected = ref(false)
const emits = defineEmits(["login"])
onMounted(()=>{
refAgr.value.open()
console.log(uni.getAccountInfoSync().miniProgram);
})
const login = () => {
if (!selected.value)
return refAgr.value.open()
emits("login")
}
const toPage = (url) => {
uni.navigateTo({ url })
}
const jumpPage = () => {
clearRulesArray()
uni.navigateTo({ url: "/pages/login/forgetPassword" })
}
// 隐私政策页面
const toPrivacy = () => {
// #ifdef APP-PLUS
uni.navigateTo({
url: '/pages/login/privacyPolicy',
})
// #endif
// #ifdef MP-WEIXIN
wx.openPrivacyContract(
{
fail: () => {
uni.showToast({
title: '打开失败请稍后重试', // 打开失败
icon: 'none'
})
},
}
)
// #endif
}
// #ifdef MP-WEIXIN
const getPrivacy = () => {
wx.getPrivacySetting({
success: (r) => {
Object.assign(vdata, r)
if (vdata.needAuthorization) {
wx.onNeedPrivacyAuthorization(res => {
vdata.resolve = res
})
}
}
})
}
getPrivacy()
// #endif
const handAgree = () => {
// #ifdef MP-WEIXIN
if (vdata.needAuthorization) {
vdata.resolve({ buttonId: 'agree-btn', event: 'agree' })
}
// #endif
}
</script>
<style lang="scss" scoped>
.agreement-wrapper {
display: flex;
justify-content: center;
align-items: center;
// width: 100%;
font-size: 24rpx;
white-space: nowrap;
color: #8c8c8c;
view {
margin: 0 10rpx;
color: $primaryColor;
}
.agreement-garden {
position: relative;
width: 30rpx;
height: 30rpx;
border-radius: 50%;
border: 2rpx solid $primaryColor;
&::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
width: 80%;
height: 80%;
border-radius: 50%;
}
}
}
.selected::after {
background-color: $primaryColor;
}
.register-wrapper {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 28rpx;
letter-spacing: 0.02em;
view {
margin: 0 50rpx;
color: #8c8c8c;
text {
color: #7737fe;
}
}
}
.agree-item {
padding: 0;
margin: 0;
line-height: 0;
border-radius: 0;
background-color: transparent;
&::after{
display: none;
}
}
</style>

View File

@@ -0,0 +1,138 @@
<template>
<view class="content">
<LoginInput
title="手机号"
v-model:value="forgetInfo.phone"
place="请输入注册手机号"
:rules="{ name: 'phone', rule: 'REG_Phone' }"
pd="50rpx 50rpx 35rpx 50rpx"
>
<view class="sms-tips" v-if="forgetInfo.phone.length == 11" @tap="createInterval">
<text v-if="smsNumber != 60">{{ smsNumber }}s</text>
{{ smsNumber !== 60 ? "后可重新发送" : "发送验证码" }}
</view>
</LoginInput>
<LoginInput
title="图形验证码"
v-model:value="forgetInfo.vercode"
place="请输入图形验证码"
pd="0rpx 50rpx 35rpx 50rpx"
>
<view style="padding-top: 5px;">
<image :src="forgetInfo.imgCodeUrl" style="width: 200rpx; height: 110rpx;margin-left: 10rpx;" @click="getCode" mode=""></image>
</view>
</LoginInput>
<LoginInput
pd="0 50rpx 50rpx 50rpx"
v-model:value="forgetInfo.verificationCode"
:rules="{ name: 'verificationCode', rule: 'REG_NotNUll' }"
title="短信验证码"
place="请输入短信验证码"
></LoginInput>
<JButton pd="0 50rpx 50rpx 50rpx" pdTop="0" @HandleTouch="nextTo">下一步</JButton>
</view>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue"
import { Base64 } from "js-base64"
import { validateArray } from "@/hooks/rules"
import { $sendMessage, $login, $phoneCodeLogin, $retrievePassword,$isCode} from "@/http/apiManager.js";
import LoginInput from "@/components/newComponents/LoginInput/LoginInput.vue";
import JInput from "@/components/newComponents/JInput/JInput.vue"
import LoginTextUp from "@/components/JeepayLogin/LoginTextUp.vue"
import JButton from "@/components/newComponents/JButton/JButton.vue" //自定义按钮
const forgetInfo = ref({
phone: "",
imgCodeUrl:'',
vercodeToken:'',
vercode:'',
verificationCode:'',
})
const smsNumber = ref(60)
let interval = null
// 创建定时器
let createInterval = () => {
if (forgetInfo.value.phone.length != 11)
return uni.showToast({
title: "手机格式不正确",
icon: "error",
mask: true,
})
if (interval) return
console.log("执行")
sendMsg()
interval = setInterval(() => {
openInterval()
}, 1000)
}
const getCode=()=>{
$isCode().then(res=>
{
console.log(res);
forgetInfo.value.imgCodeUrl=res.bizData.imageBase64Data
forgetInfo.value.vercodeToken=res.bizData.vercodeToken
})
}
getCode()
// smsNumber -1 倒计时
const openInterval = () => {
smsNumber.value--
if (smsNumber.value <= 0) {
smsNumber.value = 60
clearInterval(interval)
interval = null
}
}
// 发送短信验证码"
const sendMsg = () => {
if (interval) return
$sendMessage({
phone: forgetInfo.value.phone,
smsType: "retrieve",
vercodeToken:forgetInfo.value.vercodeToken,
vercode:forgetInfo.value.vercode
})
.then((res) => {
const { bizData } = res
uni.showToast({
title: "发送成功",
icon: "success",
mask: true,
})
})
.catch((err) => {
clearInterval(interval)
interval = null
})
}
const nextTo = () => {
if (validateArray(forgetInfo.value)) {
$retrievePassword({
phone: Base64.encode(forgetInfo.value.phone),
code: Base64.encode(forgetInfo.value.verificationCode),
}).then(() => {
uni.navigateTo({
url:
"./setNewPassword" +
"?verificationCode=" +
forgetInfo.value.verificationCode +
"&phone=" +
forgetInfo.value.phone,
})
})
}
}
</script>
<style lang="scss" scoped>
.sms-tips {
font-size: 28rpx;
color: $primaryColor;
margin-right: 30rpx;
}
</style>

View File

@@ -0,0 +1,118 @@
<template>
<view class="login-wrapper bgF">
<view class="login-header-img">
<image src="/static/loginImg/login-Img.svg" mode="scaleToFill" />
<view class="logo-wrapper"> <image :src="logoImg" mode="scaleToFill" @tap="env.tapFunc()" /> </view>
</view>
<view class="login-main">
<JLogin v-if="loginType" @successLogin="loginFinishCallback"></JLogin>
<JSmsLogin v-if="!loginType" @successLogin="loginFinishCallback"></JSmsLogin>
<view class="switch-login" @tap="switchLoginType"
>{{ loginTips }} <image src="/static/iconImg/right-arrow.svg" mode="scaleToFill"
/></view>
<view style="height: 242rpx"></view>
</view>
</view>
<JAgree/>
<EnvChangeTips ref="env" />
</template>
<script setup>
import { ref, reactive } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import JLogin from "./components/JLogin.vue"
import JSmsLogin from "./components/JSmsLogin.vue"
import EnvChangeTips from "./components/EnvChangeTips.vue"
import { $userInfo, $getCompanyInfo,$getUploadImgSize } from "@/http/apiManager.js"
import storageManage from "@/util/storageManage.js"
import { clearRulesArray } from "@/hooks/rules"
onLoad(() => {
$getCompanyInfo().then(({ bizData }) => {
logoImg.value = bizData.agentAppTopImgUrl
})
})
const env = ref(null)
const logoImg = ref("")
const loginTips = ref("短信验证码登录")
const loginType = ref(true)
const switchLoginType = () => {
loginType.value = !loginType.value
loginType.value ? (loginTips.value = "短信验证码登录") : (loginTips.value = "账号密码登录")
}
// 成功登录后的操作
function loginFinishCallback(iToken) {
// 保存token
storageManage.token(iToken)
// 保存当前登录过的用户
// storageManage.loggedInUser(loginInfo.userName)
// 请求用户信息
$userInfo().then(({ bizData }) => {
// 保存用户数据
storageManage.userInfo(bizData)
// 存储上传 图片大小限制
$getUploadImgSize().then(({bizData})=>{
storageManage.uploadImgSize(bizData.applymentImgUploadSize)
})
clearRulesArray()
uni.reLaunch({ url: bizData.userType === 3 ? "../devWorkbench/devWorkbench" : "../workbench/workbench" })
})
}
</script>
<style lang="scss" scoped>
.login-wrapper {
width: 100%;
height: 100%;
.login-header-img {
position: relative;
height: 500rpx;
image {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
}
.logo-wrapper {
position: absolute;
left: 0;
bottom: 32rpx;
z-index: 10;
width: 100%;
height: 248rpx;
// background-color: red;
}
&::after {
content: "";
display: block;
position: absolute;
left: 0;
bottom: 0;
z-index: 10;
width: 100%;
height: 32rpx;
background-color: #fff;
border-radius: 32rpx 32rpx 0 0;
}
}
.login-main {
.switch-login {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
margin-top: 150rpx;
color: #838383;
font-size: 30rpx;
letter-spacing: 0.02em;
image {
width: 32rpx;
height: 32rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,222 @@
<template>
<view class="content">
<!-- #ifdef APP || H5 -->
<web-view src="/static/privacy.html"></web-view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<mp-html :content="content.nodes" />
<!-- #endif -->
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { $getTreaty } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import parseHtml from "@/util/html-parse.js"
let content = reactive({
nodes: ``,
})
function formatTable(content) {
if (content) {
content = content.replace(/<br[^>]*\/>/gi, "")
content = content.replace(/<td[^<>]*>/gi, '<td style="padding:0px;height:auto;word-break:break-all;">')
content = content.replace(/<td[^<>]*>\s*?<p>/gi, "<td>")
content = content.replace(
/<table[^>]*>/gi,
'<table cellpadding="0" cellspacing="0" max-width="100%" border="1" style="font-size:12px;max-width:100%; text-align:left;text-indent: 0em;line-height:12px;"'
)
return content
} else {
return null
}
}
onLoad(() => {
$getTreaty().then(({ bizData }) => {
content.nodes = bizData.agentPrivacyPolicy
})
})
</script>
<style lang="scss" scoped>
.content {
box-sizing: border-box;
padding: 0 50rpx;
.first-title {
text {
font-size: 33rpx;
}
}
.first-title,
.second-title,
.third-title {
margin-bottom: 20rpx;
text {
font-weight: 700;
letter-spacing: 0.07em;
}
}
.second-title {
text {
font-size: 28rpx;
}
}
.third-title {
text {
font-size: 26rpx;
}
}
.paragraph {
margin-bottom: 50rpx;
text {
font-weight: 500;
font-size: 25rpx;
letter-spacing: 0.07em;
line-height: 50rpx;
}
.link {
color: #175be6;
}
}
.three-item {
.item-text {
margin-bottom: 30rpx;
text {
font-weight: 500;
font-size: 25rpx;
}
}
}
.h-table {
margin-bottom: 50rpx;
/* 行 */
.h-tr {
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: stretch;
align-content: center;
border-color: #ccc;
border-style: solid;
border-width: 0;
border-top-width: 1px;
border-left-width: 1px;
border-bottom-width: 1px;
color: #333;
}
/* 单元格 */
.h-td {
font-size: 24rpx;
box-sizing: border-box;
padding: 3px;
word-break: break-all;
border-color: #ccc;
border-style: solid;
border-width: 0;
border-right-width: 1px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
align-content: center;
min-height: 64rpx;
width: 25%;
/* 跨列 */
&-colspan {
flex-grow: 1;
width: 0;
}
/* 内容顶部对齐 */
&-top {
align-items: flex-start;
align-content: flex-start;
}
/* 内容底部对齐 */
&-bottom {
align-items: flex-end;
align-content: flex-end;
}
/* 内容左边对齐 */
&-left {
justify-content: flex-start;
}
/* 内容右边对齐 */
&-right {
justify-content: flex-end;
}
}
/* 表头 */
.h-thead {
background-color: #e6e6e6;
}
/* 表格虚线 */
&-dashed {
.h-tr {
border-top-style: dashed;
border-left-style: dashed;
border-bottom-style: dashed;
}
.h-td {
border-right-style: dashed;
}
}
/* 表格主题 Map颜色摘自 Bootstrap */
$theme-table: (
primary: (
color: #fff,
bgColor: #337ab7,
border: #2e6da4,
),
success: (
color: #fff,
bgColor: #5cb85c,
border: #4cae4c,
),
info: (
color: #fff,
bgColor: #5bc0de,
border: #46b8da,
),
warning: (
color: #fff,
bgColor: #f0ad4e,
border: #eea236,
),
danger: (
color: #fff,
bgColor: #d9534f,
border: #d43f3a,
),
);
/* 生成主题代码 */
$theme-table-keys: map-keys($theme-table);
@each $k in $theme-table-keys {
$item: map-get($theme-table, $k);
&-#{$k} {
.h-tr {
border-top-color: map-get($item, border);
border-left-color: map-get($item, border);
border-bottom-color: map-get($item, border);
color: map-get($item, bgColor);
}
.h-td {
border-right-color: map-get($item, border);
}
.h-thead {
background-color: map-get($item, bgColor);
color: map-get($item, color);
}
}
}
}
}
</style>

View File

@@ -0,0 +1,70 @@
<template>
<view class="content">
<!-- #ifdef APP || H5 -->
<web-view src="/static/service.html"></web-view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<mp-html :content="content.nodes" />
<!-- #endif -->
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import { $getTreaty } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
import parseHtml from "@/util/html-parse.js"
let content = reactive({
nodes: "",
})
onLoad(() => {
$getTreaty().then(({ bizData }) => {
content.nodes = bizData.agentServiceAgreement
})
})
</script>
<style lang="scss" scoped>
.content {
box-sizing: border-box;
padding: 0 50rpx;
.first-title {
text {
font-size: 33rpx;
}
}
.first-title,
.second-title {
margin-bottom: 20rpx;
text {
font-weight: 700;
letter-spacing: 0.07em;
}
}
.second-title {
text {
font-size: 28rpx;
}
}
.paragraph {
margin-bottom: 50rpx;
text {
font-weight: 500;
font-size: 25rpx;
letter-spacing: 0.07em;
line-height: 50rpx;
}
.link {
color: #175be6;
}
}
.three-item {
.item-text {
margin-bottom: 30rpx;
text {
font-weight: 500;
font-size: 25rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,86 @@
<template>
<view class="edit-pwd">
<LoginInput title="新密码" v-model:value="pwdInfo.newPassword" place="请输入新密码" :password="!isOpenEyes">
<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="请再次输入新密码"
pd="0 50rpx 50rpx 50rpx"
:password="!confirmOpenEyes"
>
<view class="right-eyes" @tap="confirmOpenEyes = !confirmOpenEyes">
<image :src="eyeImg[confirmOpenEyes ? 1 : 0]" mode="scaleToFill" />
</view>
</LoginInput>
</view>
<JButton pd="0 50rpx 50rpx 50rpx" @HandleTouch="save">确认</JButton>
</template>
<script setup>
import { ref, reactive } from "vue"
import LoginInput from "@/components/newComponents/LoginInput/LoginInput.vue"
import JButton from "@/components//newComponents/JButton/JButton"
import { Base64 } from "js-base64"
import { $retrievePassword, $getPasswordRules } from "@/http/apiManager.js"
import { onLoad } from "@dcloudio/uni-app"
const eyeImg = reactive(["/static/loginImg/login-eye-close.svg", "/static/loginImg/login-eye-open.svg"])
const isOpenEyes = ref(false)
const confirmOpenEyes = ref(false)
const pwdInfo = ref({})
onLoad((options) => {
pwdInfo.value.verificationCode = options.verificationCode
pwdInfo.value.phone = options.phone
getPasswordRules()
})
function getPasswordRules() {
$getPasswordRules().then((res) => {
pwdInfo.value.rules = new RegExp(res.bizData.regexpRules)
pwdInfo.value.ruleText = res.bizData.errTips
})
}
function save() {
if (pwdInfo.value.newPassword !== pwdInfo.value.confirmPassword) return errorMsg("两次输入密码不一致")
if (!pwdInfo.value.rules.test(pwdInfo.value.newPassword) || !pwdInfo.value.rules.test(pwdInfo.value.confirmPassword))
return errorMsg(pwdInfo.value.ruleText)
$retrievePassword({
phone: Base64.encode(pwdInfo.value.phone),
code: Base64.encode(pwdInfo.value.verificationCode),
newPwd: Base64.encode(pwdInfo.value.confirmPassword),
}).then(() => {
uni.reLaunch({
url: "./login",
})
uni.showToast({
icon: "none",
title: "密码修改成功",
})
})
}
const errorMsg = (err) => {
return uni.showToast({
title: err,
icon: "none",
})
}
</script>
<style scoped lang="scss">
image {
width: 36rpx;
height: 36rpx;
}
.right-eyes {
display: flex;
justify-content: center;
align-items: center;
width: 110rpx;
height: 110rpx;
background-color: transparent;
}
</style>

View File

@@ -0,0 +1,176 @@
<template>
<view class="pub-card">
<view class="pub-title">我的邀请码</view>
<view class="pub-code">{{ userInfo.inviteCode }}<veiw class="copy-code" hover-class="hover-but-style"
@tap="copyCode">复制</veiw>
</view>
<view class="pub-code-img">
<view class="code-img">
<image :src="qrCode.drawImg(userInfo.inviteCodeUrl)" />
</view>
<view class="tips-text"> 使用微信或浏览器扫一扫</view>
<view class="tips-text"> 即可进入商家注册页</view>
</view>
<view class="save-img-but" hover-class="hover-but-style" @tap="saveImg(userInfo.inviteCodeUrl)">保存商家邀请码至相册</view>
<view class="pub-code-img">
<view class="code-img">
<image :src="qrCode.drawImg(userInfo.agtInviteCodeUrl)" />
</view>
<view class="tips-text"> 使用微信或浏览器扫一扫</view>
<view class="tips-text"> 即可进入服务商注册页</view>
</view>
<view class="save-img-but" hover-class="hover-but-style" @tap="saveFwsImg(userInfo.agtInviteCodeUrl)">保存服务商邀请码至相册</view>
</view>
</template>
<script setup>
import { ref, reactive } from "vue"
import storageManage from "@/util/storageManage.js"
import qrCode from '@/util/qrCode.js'
import { saveHeadImgFile } from '@/util/saveImg.js'
const userInfo = reactive({ ...storageManage.userInfo() })
function copyCode () {
uni.setClipboardData({
data: userInfo.inviteCode
}).then(res => {
tips('复制成功')
}).catch(err => {
tips('复制失败')
})
}
function tips (title) {
return uni.showToast({ title, icon: 'none' })
}
function saveImg (codeUrl) {
//#ifdef H5 || APP-PLUS
saveQrcodeImg(qrCode.drawImg(codeUrl))
//#endif
// #ifdef MP-WEIXIN
saveWxQrcodeImg(qrCode.drawImg(codeUrl))
//#endif
}
function saveFwsImg (codeUrl) {
//#ifdef H5 || APP-PLUS
saveQrcodeImg(qrCode.drawImg(codeUrl))
//#endif
// #ifdef MP-WEIXIN
saveWxQrcodeImg(qrCode.drawImg(codeUrl))
//#endif
}
// 保存图片
const saveQrcodeImg = (data) => {
saveHeadImgFile(data, 80)
.then((success) => {
tips('保存成功')
})
.catch((err) => {
console.log(err)
tips('保存失败')
})
}
// #ifdef MP-WEIXIN
const saveWxQrcodeImg = (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) {
//保存成功
tips('保存成功')
},
fail: function (err) {
console.log(err)
//保存失败
tips('保存失败')
},
})
},
fail: (err) => {
tips('保存失败')
},
})
}
//#endif
</script>
<style lang="scss" scoped>
page {
background-color: #f7f7f7;
}
.pub-card {
margin: 50rpx auto;
padding: 10rpx;
width: 690rpx;
background-color: #fff;
border-radius: 32rpx;
.pub-title {
margin: 20rpx;
font-size: 24rpx;
color: #a6a6a6;
}
.pub-code {
display: flex;
align-items: center;
margin: 0 20rpx;
font-weight: 600;
.copy-code {
padding: 5rpx 15rpx;
margin-left: 15rpx;
font-size: 24rpx;
font-weight: 500;
background: rgba(119, 55, 254, 0.15);
color: $primaryColor;
border-radius: 10rpx;
}
}
.pub-code-img {
margin: 80rpx auto;
width: 300rpx;
.code-img {
margin-bottom: 30rpx;
width: 300rpx;
height: 300rpx;
image {
width: 100%;
height: 100%;
}
}
.tips-text {
margin: 15rpx 0;
font-size: 24rpx;
color: #a6a6a6;
text-align: center;
}
}
.save-img-but {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
width: 670rpx;
height: 110rpx;
background-color: $primaryColor;
color: #fff;
border-radius: 15rpx;
}
}
.hover-but-style {
opacity: 0.5;
}
</style>

View File

@@ -0,0 +1,614 @@
<template>
<view class="rekeaseMain">
<view class="main-title">
营销内容
</view>
<view class="banner-mian">
<view class="banner-list" v-for="(img,index) in imgList" :key="img">
<view class="banner-list-title">
{{index+1}}屏广告
</view>
<image :src="img.url" mode="" @click="previewImage(img.url)"></image>
<view class="del-box">
<view class="del-tip" @click="delImg(index)">
<image style="height: 30rpx;width: 30rpx;margin-top:0rpx;" src="../../static/img/del.svg" mode=""></image>
<text>删除</text>
</view>
</view>
</view>
<view class="addimg-box" v-if="imgList.length<5">
<view class="addimg-title" @click="changeImg">
<image src="../../static/img/add.svg" mode=""></image>
<view class="">
加一屏广告
</view>
</view>
</view>
</view>
<view class="">
<button style="background: linear-gradient(45deg, #17c5c6, #15ccb0);color: #fff;border: 0; margin-top: 20rpx; margin-bottom: 60rpx;" @click="releaseImg">发布营销内容</button>
</view>
<view class="main-title">
跑马灯内容
</view>
<view class="PMDtextarea-box" v-show="!changeImgFlag">
<textarea v-model="PMDtextarea" name="" id="" maxlength="20" style="background:#f4f4f4; width:100%;height:150rpx; box-sizing: border-box; border-radius: 10rpx; padding: 20rpx;"></textarea>
<view class="PMDtextarea-num">
{{PMDtextarea.length}}/20
</view>
</view>
<view class="fontColor-select">
<text>选择字体颜色</text>
<view @click="changeFontColor('font')" style="width: 50rpx;height: 50rpx;border-radius: 10rpx; margin-left: 50rpx;" :style="{background:fontColor}"></view>
</view>
<view class="fontColor-select">
<text>选择背景颜色</text>
<view @click="changeFontColor('background')" style="width: 50rpx;height: 50rpx;border-radius: 10rpx; margin-left: 50rpx;" :style="{background:BackgroundColor}"></view>
</view>
<view class="">
<button style="background: linear-gradient(45deg, #17c5c6, #15ccb0);color: #fff;border: 0; margin-top: 20rpx; margin-bottom: 60rpx;" @click="releaseLamp">发布跑马灯</button>
</view>
<view class="">
<button style="background:#d1f3f5;color: #4ac3c3;border: 1px solid #15ccb0; margin-top: 20rpx; margin-bottom: 60rpx;">查看效果</button>
</view>
<view class="upload-image" v-if="changeImgFlag">
<view class="upload-image-body">
<canvas canvas-id="picCanvas"
:style="'position: absolute; width: ' + picSizeW + 'px; height: ' + picSizeH + 'px; left: -' + picSizeW + 'px;'"></canvas>
<view class="pic-preview" @touchstart="touchstart" @touchmove="touchmove">
<scroll-view class='pic-area' @scroll='scroll' scroll-x scroll-y>
<view :style="{ height: `calc(50% - ${areaH * 0.5}vw)` }"></view>
<image :src="picSrc || picUrl" :style="styleImg"></image>
<view :style="{ height: `calc(50% - ${areaH * 0.5}vw)` }"></view>
</scroll-view>
<view class="outside-mask-block" :style="styleV"></view>
<view class="outside-mask-block" :style="styleV" style="bottom: 0;"></view>
<view class="outside-mask-block" :style="styleH" style="left: 0;"></view>
<view class="outside-mask-block" :style="styleH" style="right: 0;"></view>
</view>
<view class="bottom-bar safe-area-inset-bottom">
<block v-if="picSrc != ''">
<view class="rechoose" @click="chooseImage">重选</view>
<button class="button" size="mini" @click="uploadClick">确定</button>
</block>
<view v-else class="choose-btn" @click="chooseImage">选择图片</view>
</view>
</view>
</view>
<picker-color :isShow="showPickerColor" :bottom="0" @callback='getPickerColor'/>
</view>
</template>
<script>
import { $pmdfb,$getImgWH,$initializeImg,$ossFilesForm,$uploadImg} from "@/http/apiManager.js"
import pickerColor from "@/components/helang-pickerColor/helang-pickerColor.vue"
import storageManage from "@/util/storageManage.js"
const AREA_SIZE = 75; // 裁剪框占屏幕尺寸百分比
const IMG_SIZEW = 800; // 裁剪图片默认尺寸
const IMG_SIZEH = 960; // 裁剪图片默认尺寸
export default {
components: {
"picker-color":pickerColor,
},
data() {
return {
// bobyHeight: this.getBobyHeight(),
picSrc: '',
picUrl: '',
dataKey: '',
areaW: AREA_SIZE,
areaH: AREA_SIZE,
width: this.areaW,
height: this.areaH,
old_width: 0,
old_height: 0,
picSizeW: 800,
picSizeH: 960,
x: 0,
y: 0,
distance: 0,
scale: 1,
disable: false,
imgList: [],
changeImgFlag:false,
PMDtextarea:'',
showPickerColor:false,
fontColor:'#000',
BackgroundColor:'#000',
colorType:'',
selectImgData:{},
}
},
onLoad(options) {
this.picSizeW = Number(options.w) || IMG_SIZEW;
this.picSizeH = Number(options.h) || IMG_SIZEH;
this.picUrl = ''; // 初始化图片
this.initAreaSize();
this.getImgWH()
this.getInitializeIMG() //回显图片
},
computed: {
styleImg() {
return `padding: 0 ${50 - this.areaW * 0.5}%;width: ${this.width}%;height: ${this.height}vw;`;
},
styleV() {
// (屏幕高度 - 图片高度) / 2
return `height: calc(50% - ${this.areaH * 0.5}vw);left: ${50 - this.areaW * 0.5}%;right: ${50 - this.areaW * 0.5}%;`;
},
styleH() {
// (屏幕宽度 - 图片宽度) / 2
return `top: 0;bottom: 0;width: ${50 - this.areaW * 0.5}%;`;
},
},
methods: {
async getImgWH(){
let res = await $getImgWH('QR939200003565')
console.log(res);
if(res.code===0){
this.picSizeH=res.bizData.picHeight
this.picSizeW=res.bizData.picWidth
}
},
async getInitializeIMG(){
let res = await $initializeImg('QR939200003565')
console.log(res);
if(res.code===0){
if(res.bizData.length>1){
res.bizData.map(item=>{
this.imgList.push({url:item.picName})
})
}
}
},
async releaseLamp(){
let data={
deviceNo:'QR939200003565',
inputText:this.PMDtextarea,
fontColor:this.fontColor,
bgColor:this.BackgroundColor,
}
let res = await $pmdfb(data)
console.log(res);
},
getPickerColor(color){
if(color){
if(this.colorType==='font'){
this.fontColor=color
}else{
this.BackgroundColor=color
}
}
this.showPickerColor=false
},
changeFontColor(type){
this.colorType=type
this.showPickerColor=true
},
previewImage(url){
console.log(url);
let data={
urls:[]
}
data.urls.push(url)
uni.previewImage(data)
},
changeImg(){
this.changeImgFlag=true
},
delImg(index){
this.imgList.splice(index,1)
},
initAreaSize() {
if (this.picSizeW > this.picSizeH) {
this.areaH = AREA_SIZE * this.picSizeH / this.picSizeW;
} else if (this.picSizeW < this.picSizeH) {
this.areaW = AREA_SIZE * this.picSizeW / this.picSizeH;
}
this.width = this.areaW;
this.height = this.areaH;
},
chooseImage() {
uni.chooseImage({
count: 1,
success: (res) => {
this.resetData();
this.selectImgData={
url:res.tempFiles[0].path,
size:res.tempFiles[0].size
}
this.initImage(res.tempFiles[0].path);
}
});
},
resetData() {
this.picSrc = '';
this.distance = 0;
this.old_width = 0;
this.old_height = 0;
this.x = 0;
this.y = 0;
this.scale = 1;
this.disable = false;
this.initAreaSize();
},
initImage(url,size) {
uni.getImageInfo({
src: url,
success: (res) => {
// #ifdef APP-PLUS || MP
if (['png', 'jpeg', 'jpg'].indexOf(res.type) == -1) {
uni.showModal({
title: '',
content: '仅支持上传png和jpg格式图片',
showCancel: true,
cancelText: '取消',
confirmText: '重选',
success: (res) => {
if (res.confirm) {
this.chooseImage();
}
},
});
return;
}
// #endif
let scale = res.width / res.height;
let areaScale = this.areaW / this.areaH;
this.picSrc = url;
this.scale = scale;
if (scale > 1) { // 横向图片
if (scale >= areaScale) { // 图片宽不小于目标宽,则高固定,宽自适应
this.width = (this.height / res.height) * this.width * (res.width / this
.width);
} else { // 否则宽固定、高自适应
this.height = res.height * this.width / res.width;
}
} else { // 纵向图片
if (scale <= areaScale) { // 图片高不小于目标高,宽固定,高自适应
this.height = (this.width / res.width) * this.height / (this.height / res
.height);
} else { // 否则高固定,宽自适应
this.width = res.width * this.height / res.height;
}
}
// 记录原始宽高,为缩放比列做限制
this.old_width = this.width;
this.old_height = this.height;
},
});
},
touchstart(e) {
if (this.picSrc && e.touches.length == 2) {
let _x = e.touches[1].pageX - e.touches[0].pageX,
_y = e.touches[1].pageY - e.touches[0].pageY,
distance = Math.sqrt(Math.pow(_x, 2) + Math.pow(_y, 2));
this.distance = distance;
}
},
touchmove(e) {
if (this.picSrc && e.touches.length == 2) {
let _x = e.touches[1].pageX - e.touches[0].pageX,
_y = e.touches[1].pageY - e.touches[0].pageY,
old_width = this.old_width,
old_height = this.old_height,
newdistance = Math.sqrt(Math.pow(_x, 2) + Math.pow(_y, 2)),
distance = this.distance,
end_distance = newdistance - distance,
pic_scale = 1 + end_distance * 0.001,
width = this.width * pic_scale,
height = this.height * pic_scale;
let max = width / old_width;
if (max > 2) {
width = old_width * 2;
height = old_height * 2;
} else if (max < 1) {
width = old_width;
height = old_height;
}
this.width = width;
this.height = height;
}
},
scroll(e) {
if (this.picSrc) {
let x = e.detail.scrollLeft,
y = e.detail.scrollTop;
this.x = x;
this.y = y;
}
},
uploadClick(e) {
console.log(e);
uni.showModal({
content: '确定要截取当前可视区域图片并上传吗?',
success: modalRes => {
if (modalRes.confirm) {
uni.showLoading({
title: '上传中...',
mask: true
});
const systemInfo = uni.getSystemInfoSync();
let whScale = systemInfo.screenWidth * 0.01, // 图片宽高vw与px比
// 生成图片的实际尺寸与截取区域比
xScale = this.picSizeW / (systemInfo.screenWidth * this.areaW * 0.01),
yScale = this.picSizeH / (systemInfo.screenWidth * this.areaH * 0.01);
const canvas = uni.createCanvasContext('picCanvas');
// 注意:无法直接绘制网络图片,需要先下载到本地
canvas.drawImage(this.picSrc, -this.x * xScale, -this.y * yScale, this.width *
whScale * xScale, this.height *
whScale * xScale);
canvas.draw(setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: this.picSizeW,
height: this.picSizeH,
destWidth: this.picSizeW, // 必要,保证生成图片宽度不受设备分辨率影响
destHeight: this.picSizeH, // 必要,保证生成图片高度不受设备分辨率影响
canvasId: 'picCanvas',
success: (fileRes) => {
console.log(fileRes,'initImageinitImageinitImage')
uni.hideLoading()
this.imgList.push({url:fileRes.tempFilePath})
let str =fileRes.tempFilePath
str = str.substring(0, str.length - 3)+'jpg'
this.uploadImage(str);
this.changeImgFlag=false
},
fail: function(err) {
console.log(err);
uni.showToast({
title: '上传失败:图片生成过程中遇到错误',
icon: 'none'
});
this.changeImgFlag=false
}
}, this);
}, 1000));
}
}
});
},
uploadImage(tempFilePath) {
// 在H5平台下tempFilePath 为 base64
this.resetData()
$ossFilesForm({
bizType: "applyment",
sourceFileName:'http://tmp/umPJ4jKRMPO370afabf8febe678b66a70f143e34a90d.jpg',
sourceFileSize: this.selectImgData.size,
}).then(({bizData})=>{
let url,
isOss,
ossImgUrl = ""
if (bizData.formActionUrl === "LOCAL_SINGLE_FILE_URL") {
url = appConfig.env.JEEPAY_BASE_URL + props.upLoadUrl
isOss = false
} else {
url = bizData.formActionUrl
ossImgUrl = { data: bizData.ossFileUrl }
isOss = true
}
console.log(ossImgUrl.data);
this.uploadImg(this.selectImgData.url, url, bizData.formParams, isOss, ossImgUrl)
})
},
uploadImg(tempFilePaths, url, formParams, isOss, ossImgUrl){
console.log(tempFilePaths, url, formParams, isOss, ossImgUrl);
const token = storageManage.token()
var successCount = 0 //多图时,上传成功数量
var qualification = [] //多图存储
uni.uploadFile({
url: url,
filePath: tempFilePaths,
name: "file",
header: {
itoken: token,
},
formData: formParams,
// 代表完成的函数 注:此处可以传入三个函数 success (成功)/ fail失败 / complete (完成)
complete(res) {
console.log(res);
$uploadImg({
deviceNo:'QR939200003565',
carouselPicInfo:[{
picName:'https://qilinlife-pub.oss-cn-hangzhou.aliyuncs.com/applyment/ff22fa1c-8d97-4ef6-ae4a-a79d63cc285c.jpg'
}]
}).then(({bizData})=>{
console.log(bizData);
})
}})
}
}
}
</script>
<style lang="scss" scoped>
.rekeaseMain {
padding: 20rpx;
.main-title {
line-height: 60rpx;
position: relative;
padding-left: 20rpx;
}
.main-title::after{
content: '';
display: block;
width: 8rpx;
background: #16c3c3;
height: 30rpx;
position: absolute;
left: 0;
top: 17rpx;
}
.banner-mian {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.banner-list {
width: 48%;
text-align: center;
height: 470rpx;
margin-top: 20rpx;
.banner-list-title {
background: #e7f9f9;
padding: 15rpx;
font-size: 24rpx;
color: #1ac3c7;
border-radius: 10rpx 10rpx 0 0;
height: 40rpx;
}
image {
width: 100%;
border-radius: 10rpx;
margin-top: -10rpx;
height: 340rpx;
}
.del-box{
display: flex;
justify-content: center;
margin-top: 16rpx;
.del-tip {
width: 40%;
background: #fce3df;
color: #f00;
border-radius: 30rpx;
border: 1px solid #f00;
font-size: 26rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 4rpx;
}
}
}
.addimg-box {
width: 48%;
background: #f4f4f4;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
height: 400rpx;
margin-top: 20rpx;
.addimg-title {
display: flex;
flex-direction: column;
align-items: center;
image {
width: 50rpx;
height: 50rpx;
}
}
}
}
.PMDtextarea-box{
position: relative;
.PMDtextarea-num{
position: absolute;
right: 5rpx;
bottom: 10rpx;
}
}
.fontColor-select{
display: flex;
margin: 30rpx 0;
}
}
.upload-image {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
.upload-image-body {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
display: flex;
flex-direction: column;
.pic-preview {
width: 100%;
flex: 1;
position: relative;
.pic-area {
left: 0;
right: 0;
top: 0;
bottom: 0;
font-size: 0;
z-index: 1;
background-color: $uni-bg-color-grey;
position: absolute;
display: flex;
flex-direction: column;
}
.outside-mask-block {
background-color: rgba(51, 51, 51, 0.9);
z-index: 2;
position: absolute;
}
}
.bottom-bar {
display: flex;
flex-direction: row;
position: relative;
background-color: $uni-bg-color-grey;
.rechoose {
color: $uni-color-primary;
padding: 0 $uni-spacing-row-lg;
line-height: 100rpx;
}
.choose-btn {
color: $uni-color-primary;
text-align: center;
line-height: 100rpx;
flex: 1;
}
.button {
margin: auto $uni-spacing-row-lg auto auto;
}
}
.safe-area-inset-bottom {
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
padding-bottom: env(safe-area-inset-bottom); // 兼容 IOS>=11.2
}
}
}
</style>

View File

@@ -0,0 +1,427 @@
<template>
<view class="rekeaseMain">
<view class="main-title">
营销内容
</view>
<view class="banner-mian">
<view class="banner-list" v-for="(img,index) in imgList" :key="img">
<view class="banner-list-title">
{{index+1}}屏广告
</view>
<image :src="img.url" mode="" @click="previewImage(img.url)"></image>
<view class="del-box">
<view class="del-tip" @click="delImg(index)">
<image style="height: 30rpx;width: 30rpx;margin-top:0rpx;" src="../../static/img/del.svg"
mode=""></image>
<text>删除</text>
</view>
</view>
</view>
<view class="addimg-box" v-if="imgList.length<5">
<view class="addimg-title" @click="cjimg">
<image src="../../static/img/add.svg" mode=""></image>
<view class="">
加一屏广告
</view>
</view>
</view>
</view>
<view class="">
<button
style="background: linear-gradient(45deg, #17c5c6, #15ccb0);color: #fff;border: 0; margin-top: 20rpx; margin-bottom: 60rpx;"
@click="beforeUploadImg">发布营销内容</button>
</view>
<view class="main-title">
跑马灯内容
</view>
<view class="PMDtextarea-box" v-show="!changeImgFlag">
<textarea v-model="PMDtextarea" name="" id="" maxlength="20"
style="background:#f4f4f4; width:100%;height:150rpx; box-sizing: border-box; border-radius: 10rpx; padding: 20rpx;"></textarea>
<view class="PMDtextarea-num">
{{PMDtextarea.length}}/20
</view>
</view>
<view class="fontColor-select">
<text>选择字体颜色</text>
<view @click="changeFontColor('font')"
style="width: 50rpx;height: 50rpx;border-radius: 10rpx; margin-left: 50rpx;"
:style="{background:fontColor}"></view>
</view>
<view class="fontColor-select">
<text>选择背景颜色</text>
<view @click="changeFontColor('background')"
style="width: 50rpx;height: 50rpx;border-radius: 10rpx; margin-left: 50rpx;"
:style="{background:BackgroundColor}"></view>
</view>
<view class="">
<button
style="background: linear-gradient(45deg, #17c5c6, #15ccb0);color: #fff;border: 0; margin-top: 20rpx; margin-bottom: 60rpx;"
@click="releaseLamp">发布跑马灯</button>
</view>
<view class="">
<button
style="background:#d1f3f5;color: #4ac3c3;border: 1px solid #15ccb0; margin-top: 20rpx; margin-bottom: 60rpx;">查看效果</button>
</view>
<picker-color :isShow="showPickerColor" :bottom="0" @callback='getPickerColor' />
<view class="">
<l-clipper v-if="show" @success="successImg" @cancel="show = false" :width="800" :height="960" :is-lock-width="true" :is-lock-height="true" />
<!-- <button @tap="show = true">裁剪</button> -->
</view>
</view>
</template>
<script>
import {
$pmdfb,
$getImgWH,
$initializeImg,
$ossFilesForm,
$uploadImg
} from "@/http/apiManager.js"
import pickerColor from "@/components/helang-pickerColor/helang-pickerColor.vue"
export default {
components: {
"picker-color": pickerColor,
},
data() {
return {
imgList: [],
changeImgFlag: false,
PMDtextarea: '',
showPickerColor: false,
fontColor: '#000',
BackgroundColor: '#000',
colorType: '',
selectImgData: {},
imageUrl: 'https://img12.360buyimg.com/pop/s1180x940_jfs/t1/97205/26/1142/87801/5dbac55aEf795d962/48a4d7a63ff80b8b.jpg',
show: false,
url: '',
}
},
onLoad(options) {
this.picUrl = ''; // 初始化图片
this.getImgWH()
this.getInitializeIMG() //回显图片
},
methods: {
cjimg(){
this.show=true
},
successImg(e){
console.log(e);
this.show=false
this.imgList.push({url:e.url})
this.beforeUploadImg()
},
async getImgWH() {
let res = await $getImgWH('QR939200003565')
console.log(res);
if (res.code === 0) {
this.picSizeH = res.bizData.picHeight
this.picSizeW = res.bizData.picWidth
}
},
async getInitializeIMG() {
let res = await $initializeImg('QR939200003565')
console.log(res);
if (res.code === 0) {
if (res.bizData.length > 1) {
res.bizData.map(item => {
this.imgList.push({
url: item.picName
})
})
}
}
},
async releaseLamp() {
let data = {
deviceNo: 'QR939200003565',
inputText: this.PMDtextarea,
fontColor: this.fontColor,
bgColor: this.BackgroundColor,
}
let res = await $pmdfb(data)
console.log(res);
},
getPickerColor(color) {
if (color) {
if (this.colorType === 'font') {
this.fontColor = color
} else {
this.BackgroundColor = color
}
}
this.showPickerColor = false
},
changeFontColor(type) {
this.colorType = type
this.showPickerColor = true
},
previewImage(url) {
console.log(url);
let data = {
urls: []
}
data.urls.push(url)
uni.previewImage(data)
},
changeImg() {
this.changeImgFlag = true
},
delImg(index) {
this.imgList.splice(index, 1)
},
beforeUploadImg() {
this.imgList.forEach(item => {
$ossFilesForm({
bizType: "applyment",
sourceFileName: item.url,
sourceFileSize: 1000,
}).then(({
bizData
}) => {
let url,
isOss,
ossImgUrl = ""
if (bizData.formActionUrl === "LOCAL_SINGLE_FILE_URL") {
url = appConfig.env.JEEPAY_BASE_URL + props.upLoadUrl
isOss = false
} else {
url = bizData.formActionUrl
ossImgUrl = {
data: bizData.ossFileUrl
}
isOss = true
}
this.uploadImg(item.url, url, bizData.formParams, isOss, ossImgUrl)
})
})
},
uploadImg(tempFilePaths, url, formParams, isOss, ossImgUrl) {
console.log(tempFilePaths, url, formParams, isOss, ossImgUrl);
// const token = storageManage.token()
var successCount = 0 //多图时,上传成功数量
var qualification = [] //多图存储
uni.uploadFile({
url: url,
filePath: tempFilePaths,
name: "file",
header: {
itoken: token,
},
formData: formParams,
// 代表完成的函数 注:此处可以传入三个函数 success (成功)/ fail失败 / complete (完成)
complete(res) {
console.log(res);
$uploadImg({
deviceNo: 'QR939200003565',
carouselPicInfo: [{
picName: ossImgUrl.data
}]
}).then(({
bizData
}) => {
console.log(bizData);
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.rekeaseMain {
padding: 20rpx;
.main-title {
line-height: 60rpx;
position: relative;
padding-left: 20rpx;
}
.main-title::after {
content: '';
display: block;
width: 8rpx;
background: #16c3c3;
height: 30rpx;
position: absolute;
left: 0;
top: 17rpx;
}
.banner-mian {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.banner-list {
width: 48%;
text-align: center;
height: 470rpx;
margin-top: 20rpx;
.banner-list-title {
background: #e7f9f9;
padding: 15rpx;
font-size: 24rpx;
color: #1ac3c7;
border-radius: 10rpx 10rpx 0 0;
height: 40rpx;
}
image {
width: 100%;
border-radius: 10rpx;
margin-top: -10rpx;
height: 340rpx;
}
.del-box {
display: flex;
justify-content: center;
margin-top: 16rpx;
.del-tip {
width: 40%;
background: #fce3df;
color: #f00;
border-radius: 30rpx;
border: 1px solid #f00;
font-size: 26rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 4rpx;
}
}
}
.addimg-box {
width: 48%;
background: #f4f4f4;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
height: 400rpx;
margin-top: 20rpx;
.addimg-title {
display: flex;
flex-direction: column;
align-items: center;
image {
width: 50rpx;
height: 50rpx;
}
}
}
}
.PMDtextarea-box {
position: relative;
.PMDtextarea-num {
position: absolute;
right: 5rpx;
bottom: 10rpx;
}
}
.fontColor-select {
display: flex;
margin: 30rpx 0;
}
}
.upload-image {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
.upload-image-body {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
display: flex;
flex-direction: column;
.pic-preview {
width: 100%;
flex: 1;
position: relative;
.pic-area {
left: 0;
right: 0;
top: 0;
bottom: 0;
font-size: 0;
z-index: 1;
background-color: $uni-bg-color-grey;
position: absolute;
display: flex;
flex-direction: column;
}
.outside-mask-block {
background-color: rgba(51, 51, 51, 0.9);
z-index: 2;
position: absolute;
}
}
.bottom-bar {
display: flex;
flex-direction: row;
position: relative;
background-color: $uni-bg-color-grey;
.rechoose {
color: $uni-color-primary;
padding: 0 $uni-spacing-row-lg;
line-height: 100rpx;
}
.choose-btn {
color: $uni-color-primary;
text-align: center;
line-height: 100rpx;
flex: 1;
}
.button {
margin: auto $uni-spacing-row-lg auto auto;
}
}
.safe-area-inset-bottom {
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
padding-bottom: env(safe-area-inset-bottom); // 兼容 IOS>=11.2
}
}
}
</style>

View File

@@ -0,0 +1,76 @@
<template>
<view class="agent-wrapper" :style="{ padding: pd }">
<view class="agent-left">
<image :src="userImg" mode="scaleToFill" />
<view class="agent-info single-text-beyond" :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 {
width: 400rpx;
font-size: 28rpx;
color: #fff;
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
uni.hideTabBar()
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)
}
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,67 @@
<template>
<view class="s-card-wrapper" :class="{ isBorder: isBorder != undefined }">
<view class="s-card-title">{{ title }}</view>
<view class="tips" v-if="tips">{{ tips }}</view>
<view class="s-card-main">
<block v-for="(v, i) in list" :key="i">
<view class="s-card-item">
<view>{{ v.text }}</view>
{{ v.content }}
</view>
</block>
</view>
</view>
</template>
<script setup>
const props = defineProps({
list: {
type: Array,
default: () => [],
},
title: {
type: String,
},
tips: { type: String },
isBorder: { type: String },
})
</script>
<style lang="scss" scoped>
.s-card-wrapper {
margin-left: 70rpx;
margin-bottom: 50rpx;
border-bottom: 1rpx solid #e7e7e7;
.s-card-title {
font-size: 30rpx;
font-weight: 700;
margin-bottom: 50rpx;
}
.tips {
margin-bottom: 30rpx;
transform: translateY(-30rpx);
font-size: 24rpx;
color: #666;
}
.s-card-main {
display: flex;
flex-wrap: wrap;
.s-card-item {
flex: 0 0 50%;
font-size: 33rpx;
// font-weight: 700;
color: #7737fe;
margin-bottom: 50rpx;
view {
margin-bottom: 18rpx;
font-size: 25rpx;
font-weight: 500;
color: #8c8c8c;
}
}
}
}
.isBorder {
border: none;
}
</style>

View File

@@ -0,0 +1,91 @@
<template>
<JPopup ref="popup" @onClose="onClose">
<JMainCard pd="0" wrapPd=" 0 30rpx ">
<block v-for="(v, i) in list" :key="i">
<JLine :name="v.name" :isSelect="v.text == index" :isBorder="true" @tap="agentChange(v)"></JLine>
</block>
<view class="search-agent" @tap="emits('oneAgent')">
<JInput name="选择代理商" :image="true" :isBorder="true" v-if="!index || index == 'onlyOne'">
<image src="/static/iconImg/icon-right-jiantou.svg" mode="scaleToFill" />
</JInput>
<AgentCard v-else v-bind="childrenAgent" pd="30rpx"></AgentCard>
</view>
</JMainCard>
<JButton pd="30rpx 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"
import AgentCard from "./AgentCard.vue"
const emits = defineEmits(["selected", "oneAgent"])
const list = reactive([
{
name: "我与全部子代理商",
text: "",
},
{
name: "仅我自己",
text: "onlyOne",
},
{
name: "单个子代理商",
text: "one",
},
])
const index = ref("")
const popup = ref()
const childrenAgent = ref({
userImg: "/static/iconImg/user-theme.svg",
nameColor: "#000",
textColor: "#8C8C8C",
nameWeight: "700",
})
const open = (val) => {
if (val.agentNo && val.agentNo != "onlyOne") {
childrenAgent.value.name = val.name
childrenAgent.value.agentNo = val.agentNo
index.value = "one"
} else {
index.value = val.agentNo
}
uni.hideTabBar()
popup.value.open()
}
const onClose = () => {
uni.showTabBar()
}
const close = () => {
onClose()
popup.value.close()
}
const agentChange = (val) => {
if (val.text != "one") {
index.value = val.text
emits("selected", val)
close()
} else {
emits("oneAgent")
}
}
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,238 @@
<template>
<JHeaderTitle title="统计" color="#fff" bgColor="#7737FE" :back="false"></JHeaderTitle>
<view class="s-header">
<ScreenTitle @search="onSearch" :index="index" @open="closeTaBar" @close="openTaBar" />
<view class="s-agent bdR20" @tap="selectAgent.open(childrenAgent)">
<template v-if="childrenAgent.agentNo == '' || childrenAgent.agentNo == 'onlyOne'">
<view>
<image src="/static/iconImg/icon-user-business.svg" mode="scaleToFill" />
{{ childrenAgent.name }}
</view>
<image src="/static/iconImg/right-arrow.svg" mode="scaleToFill" />
</template>
<AgentCard v-else v-bind="childrenAgent"></AgentCard>
</view>
<view class="s-money">
<view class="m-collection">
<view class="m-title">成交订单金额</view>
<text></text>{{ statInfo.payAmount ? horn(statInfo.payAmount) : "0.00" }}
</view>
<view class="m-detailed">
<block v-for="(v, i) in orderList" :key="i">
<view class="m-item">
<view class="m-title">{{ v.text }}</view>
<text v-if="v.icon"></text
>{{ v.icon ? (isNaN(v.content / 100) ? "0.00" : (v.content / 100).toFixed(2)) : v.content || "0.00" }}
</view>
</block>
</view>
</view>
</view>
<view class="s-main">
<SCard v-bind="mchList" :isBorder="!childrenAgent.agentNo ? undefined : 'isBorder'"></SCard>
<SCard v-bind="agentList" v-if="childrenAgent.agentNo == '' || childrenAgent.agentNo == 'onlyOne'"></SCard>
<SCard v-bind="equList" isBorder v-if="childrenAgent.agentNo == '' || childrenAgent.agentNo == 'onlyOne'"></SCard>
</view>
<view class="s-block"></view>
<SelectAgent ref="selectAgent" @oneAgent="agent.open(childrenAgent)" @selected="selected"></SelectAgent>
<AgentList ref="agent" @confirm="confirm"></AgentList>
</template>
<script setup>
import { reactive, ref } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { horn } from "@/hooks/handleMoney"
import { $statistics } from "@/http/apiManager.js"
import JHeaderTitle from "@/components//newComponents/JHeaderTitle/JHeaderTitle"
import ScreenTitle from "@/components//newComponents/ScreenTitle/ScreenTitle"
import SCard from "./components/SCard.vue"
import SelectAgent from "./components/SelectAgent.vue"
import AgentList from "./components/AgentList.vue"
import AgentCard from "./components/AgentCard.vue"
onLoad(() => {
getList()
})
// 选择代理商弹窗
const selectAgent = ref(null)
// 选择代理商列表弹窗
const agent = ref()
// 基本信息
const statInfo = ref({})
const index = ref(0)
// 搜索条件
const search = ref({
isApp: true,
countType: 2,
queryDateRange: "today",
agentNo: "",
})
const mchList = reactive({
title: "商户统计",
list: [
{ text: "新增商户数", value: "mchTodayAddCount" },
{ text: "新增入网商户数", value: "mchOnNetNewCount" },
{ text: "商户总数", value: "mchAllCount" },
{ text: "入网商户总数", value: "mchOnNetCount" },
],
})
const agentList = reactive({
title: "代理商统计",
list: [
{ text: "新增代理商数", value: "agentNewCount" },
{ text: "代理商总数", value: "agentAllCount" },
],
})
const equList = reactive({
title: "设备统计",
tips: "设备统计不受筛选参数影响,仅统计自己数据",
list: [
{ text: "码牌总数", value: "qrCodeCardAllCount" },
{ text: "剩余空码数", value: "qrCodeCardUnBindCount" },
{ text: "云喇叭总数", value: "speakerAllCount" },
{ text: "未绑定云喇叭数", value: "speakerUnCount" },
{ text: "云打印总数", value: "printerAllCount" },
{ text: "未绑定云喇叭数", value: "printerUnCount" },
{ text: "扫码POS总数", value: "posAllCount" },
{ text: "未绑定扫码POS数", value: "posUnCount" },
],
})
const orderList = reactive([
{ text: "成交订单笔数", value: "payCount" },
{ text: "交易成功率", value: "" }, //收款成功率 参考运营平台
{ text: "退款笔数", value: "refundCount" },
{ text: "退款金额", value: "refundAmount", icon: true },
])
const getList = () => {
$statistics(search.value).then(({ bizData }) => {
statInfo.value = bizData.orderCount
mchList.list.forEach((v) => {
v.content = bizData.mchCount[v.value]
})
agentList.list.forEach((v) => {
v.content = bizData.agentCount[v.value]
})
equList.list.forEach((v) => {
v.content = bizData[v.value]
})
orderList.forEach((v) => {
v.content = bizData.orderCount[v.value]
})
orderList[1].content = ((bizData.orderCount.payCount / bizData.orderCount.allCount) * 100 || 0).toFixed(2) + "%"
})
}
// 选择代理商回调
const selected = (val) => {
search.value.agentNo = val.text
childrenAgent.value.name = val.name
childrenAgent.value.agentNo = val.text
if (!val.text) {
search.value.countType = 2
} else {
search.value.countType = 1
}
getList()
}
const onSearch = (val) => {
index.value = val.i
if (val.val.value != "customer") {
if (val.val.value.includes("customDate_")) {
uni.showTabBar()
}
search.value.queryDateRange = val.val.value
getList()
}
}
// 子代理商 回调
const childrenAgent = ref({
name: "我与全部子代理商",
agentNo: "",
})
const confirm = (val) => {
childrenAgent.value.name = val.name
childrenAgent.value.agentNo = val.text
search.value.agentNo = val.text
search.value.countType = 3
selectAgent.value.close()
agent.value.close()
getList()
}
const closeTaBar = () => {
uni.hideTabBar()
}
const openTaBar = () => {
uni.showTabBar()
}
</script>
<style lang="scss" scoped>
.s-header {
position: relative;
padding: 20rpx 50rpx 50rpx 50rpx;
background-color: $primaryColor;
&::after {
content: "";
position: absolute;
bottom: -2rpx;
left: 0;
right: 0;
z-index: 1;
height: 47rpx;
border-radius: 32rpx 32rpx 0rpx 0rpx;
background-color: #fff;
}
.s-agent {
display: flex;
justify-content: space-between;
align-items: center;
padding: 40rpx;
margin: 30rpx 0;
background: rgba(0, 0, 0, 0.1);
view {
display: flex;
align-items: center;
font-size: 28rpx;
color: #ffffff;
image {
margin-right: 15rpx;
}
}
image {
width: 40rpx;
height: 40rpx;
}
}
.s-money {
color: #ffffff;
padding-left: 20rpx;
.m-title {
font-size: 25rpx !important;
font-weight: 500 !important;
margin-bottom: 20rpx;
color: rgba(255, 255, 255, 0.7);
}
font-weight: 700;
.m-collection {
font-size: 57rpx;
margin-bottom: 50rpx;
text {
font-size: 36rpx;
}
}
.m-detailed {
display: flex;
flex-wrap: wrap;
.m-item {
flex: 0 0 50%;
font-size: 33rpx;
margin-bottom: 50rpx;
text {
font-size: 23rpx;
}
}
}
}
}
.s-block {
height: 80rpx;
}
</style>

View File

@@ -0,0 +1,59 @@
<template>
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" @change='change' :safe-area="false" @maskClick="emits('cancel')">
<!-- 通用提示弹窗 用于提示用户 数据含义 -->
<view class="card-wrapper">
<view class="card-title flex-center">{{ title }}</view>
<slot />
<view class="card-button flex-center" hover-class="touch-hover" @tap="confirm"> {{ buttonText }}</view>
</view>
</uni-popup>
</template>
<script setup>
import { ref,inject } from 'vue'
const emits = defineEmits(['cancel'])
const props = defineProps({
title: { type: String }, //标题
buttonText: { type: String }, //按钮文字
})
const popup = ref(null)
const open = (val) => {
popup.value.open()
}
const confirm = () => {
emits('cancel')
popup.value.close()
}
let changePageMetaOverflowFunc = inject('changePageMetaOverflowFunc')
const change = (e)=>{
if(changePageMetaOverflowFunc){
changePageMetaOverflowFunc(!e.show)
}
if(e.show) return uni.hideTabBar()
uni.showTabBar()
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.card-wrapper {
border-radius: 32rpx 32rpx 0 0;
background-color: #fff;
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;
}
}
</style>

View File

@@ -0,0 +1,49 @@
export default [
{
title: '进件管理',
url: '/pageApply/applyList',
imgUrl: '/static/navImg/nav-jinjian.svg',
mTop: '20rpx',
},
{
title: '代理商管理',
url: '/pageWork/agentManagement/agentManagement',
imgUrl: '/static/navImg/nav-dailishang.svg',
},
{
title: '商户管理',
url: '/pageWork/merchantManagement/merchantManagement',
imgUrl: '/static/navImg/nav-shangdian.svg',
},
{
title: '门店管理',
url: '/pageWork/storeManagement/storeManagement',
imgUrl: '/static/navImg/nav-mendian.svg',
},
{
title: '拓展员管理',
url: '/pageWork/developerManagement/developerManagement',
imgUrl: '/static/navImg/nav-tuozhan.svg',
},
{
title: '设备管理',
url: '/pageWork/deviceManagement/deviceManagement',
imgUrl: '/static/navImg/nav-shebei.svg',
},
{
title: '交易记录',
url: '/pageWork/transactionRecord/transactionRecord',
imgUrl: '/static/navImg/nav-jiaoyi.svg',
},
{
title: '提现记录',
url: '/pageAccount/withdrawalDetails/withdrawalList',
imgUrl: '/static/navImg/nav-tixian.svg',
},
{
title: '应用管理',
url: '/pageWork/appManage/appList',
imgUrl: '/static/navImg/icon-app.svg',
isBorder: 'isBorder',
},
]

View File

@@ -0,0 +1,360 @@
<template>
<JHeaderTitle bgColor="#7737fe" color="#fff" pdB="70rpx" :back="false" />
<view class="page-wrapper">
<!-- 自定义导航栏 -->
<!-- 钱包卡片 -->
<view class="wallet-wrapper">
<view class="wallet-top">
<view class="wallet-money">钱包余额</view>
<view class="wallet-number">{{
isOpenEyes ? walletInfo.amount || "0.00" : desensitization(walletInfo.amount || "0.00")
}}</view>
<view class="wallet-eyes bdR10">
<image :src="imgEyes[isOpenEyes ? 1 : 0]" mode="scaleToFill" @tap="changeOpen" />
</view>
</view>
<view class="wallet-bottom">
<view>
<view class="wallet-money">提现中金额</view>
<view class="wallet-b-number">{{
isOpenEyes ? walletInfo.unAmount || "0.00" : desensitization(walletInfo.unAmount || "0.00")
}}</view>
</view>
<view>
<view class="wallet-money">在途利润</view>
<view class="wallet-b-number">{{
isOpenEyes
? walletInfo.auditProfitAmount || "0.00"
: desensitization(walletInfo.auditProfitAmount || "0.00")
}}</view>
</view>
<view>
<view class="wallet-money">冻结金额
<uni-icons type="help-filled" size="20" color="#c6c6c6" @tap="openTips()" />
</view>
<view class="wallet-b-number">{{
isOpenEyes
? walletInfo.freezeAmount || "0.00"
: desensitization(walletInfo.freezeAmount || "0.00")
}}</view>
</view>
</view>
</view>
<JButton pd="0 50rpx 50rpx 50rpx" bgColor="#fff" color="#7737fe" pdTop="0"
@HandleTouch="jumpPage('/pageAccount/takeMoney/takeMoney')">提现</JButton>
<JCardContent>
<!-- nav 导航部分 -->
<view class="nav-list">
<view class="nav-item bgF2 bdR16" v-for="(v, i) in list" :key="i" :class="[v.url === 'null' ? 'nav-station' : '']"
@tap="jumpPage(v.url)">
<image :src="v.imgUrl" mode="scaleToFill" v-if="v.imgUrl" />
<text class="nav-text">{{ v.title }}</text>
</view>
</view>
<!-- 广告展示部分 -->
<blcok v-for="v in vdata.adList" :key="v.adverId">
<JeepayBanner :list="v.appContent" :interval='v.changeTime' v-if="v.appPlaceType == 2" mg='40rpx 0' />
<JeepayAdCard :list='v.appContent' v-if="v.appPlaceType == 1" mg='40rpx 0' mgs="40rpx 0"/>
</blcok>
<!-- 公告列表 -->
<template v-if="noticeList.length > 0">
<view class="notice-title fs30 fw700">最新公告</view>
<view class="notice-wrapper bdR16" v-for="v in noticeList" :key="v.articleId"
@tap="jumpPage(`/pageWork/setUp/postDetail?id=${v.articleId}`)">
<view class="notice-content single-text-beyond fs30">{{ v.title }}</view>
<view class="notice-time">{{ v.createdAt }}</view>
</view>
<JContent @HandleTouch="jumpPage('/pageWork/setUp/latestPost')" height="160rpx">查看全部</JContent>
</template>
</JCardContent>
</view>
<JTipsPopupContent ref="tips" title="冻结金额释义" buttonText="我知道了">
<view class="tips-wrapper">
<view class="tips-title">描述<span class="tips-info">冻结金额为不可提现金额</span></view>
</view>
<view class="tips-wrapper">
<view class="tips-title">当前可提现金额为<span class="tips-info">{{ walletInfo.allowTakeAmount }}</span></view>
</view>
<view class="tips-wrapper" v-if="walletInfo.freezeAmount > 0 && walletInfo.freezeDesc">
<view class="tips-title">冻结原因</view>
<view class="tips-info">{{ walletInfo.freezeDesc }}请尽快处理</view>
</view>
</JTipsPopupContent>
<!-- #ifdef APP-PLUS -->
<view style="height: 120rpx;"></view>
<!-- #endif -->
</template>
<script setup>
import { ref, reactive, onBeforeUnmount } from "vue"
import { $statistics, $getNoticeList, $getMainUserInfo, $adList ,$getCompanyInfo, $getUserInfo} from "@/http/apiManager.js"
import { onShow, onPullDownRefresh, onLoad,onShareAppMessage,onShareTimeline } from "@dcloudio/uni-app"
import JHeaderTitle from "@/components//newComponents/JHeaderTitle/JHeaderTitle"
import JButton from "@/components//newComponents/JButton/JButton"
import JCardContent from "@/components//newComponents/JCardContent/JCardContent"
import JContent from "@/components//newComponents/JContent/JContent"
import storageManage from "@/util/storageManage.js"
import { horn } from "@/hooks/handleMoney"
import dayjs from "dayjs"
import list from "./navList/navList"
import JTipsPopupContent from './component/JTipsPopupContent.vue';
onLoad(() => {
$getMainUserInfo().then(({ bizData }) => {
toExamine(bizData.infoState)
})
})
onShow(() => {
userDate()
getNoticeList()
onPullDownRefresh(() => {
userDate()
})
})
const vdata = reactive({
})
// 控制眼睛开关
const imgEyes = reactive(["/static/iconImg/home-eye-close.svg", "/static/iconImg/icon-openEyes.svg"])
const isOpenEyes = ref(false)
const changeOpen = () => {
isOpenEyes.value = !isOpenEyes.value
}
// 钱包信息
const walletInfo = ref({
agentShareImgUrl:''
})
const userDate = () => {
$statistics().then((res) => {
const { bizData } = res
walletInfo.value.amount = horn(bizData.availableBalanceAmount) //钱包余额
walletInfo.value.auditProfitAmount = horn(bizData.auditProfitAmount) //在途金额
walletInfo.value.freezeAmount = horn(bizData.freezeAmount) //钱包冻结金额
walletInfo.value.unAmount = horn(bizData.unAmount) //提现中金额
walletInfo.value.allowTakeAmount = horn(bizData.allowTakeAmount) //最大可提现金额
walletInfo.value.freezeDesc = bizData.freezeDesc // 钱包金额冻结描述
})
uni.stopPullDownRefresh()
}
// 信息转换为*号
const desensitization = (val) => {
if (!val) return //如果为undefined 直接return 出去
return "******"
}
// 提示框
const tips = ref()
// 打开提示弹窗
const openTips = () => {
tips.value.open()
}
// 公告列表
const noticeList = ref([])
const getNoticeList = () => {
$getNoticeList({ pageSize: 3, pageNumber: 1, articleType: 1 }).then((res) => {
const { bizData } = res
noticeList.value = bizData.records.slice(0, 3)
noticeList.value.forEach((v) => {
v.createdAt = formatTime(dayjs(v.createdAt).format("YYYY-MM-DD HH:mm"))
})
uni.stopPullDownRefresh()
})
}
// 把 - 替换成 /
const formatTime = (val) => {
const time = val.split(" ")
time[0] = time[0].split("-").join("/")
return time.join(" ")
}
// 跳转路由
const jumpPage = (url) => {
if (url === "null") return
// 发起提现时判断是否有可提现金额
if(url == '/pageAccount/takeMoney/takeMoney'){
if(walletInfo.value.allowTakeAmount <= 0) {
uni.showToast({
title: "无可提现金额",
icon: "error",
})
return
}
}
uni.navigateTo({
url,
})
}
const toExamine = (val) => {
let url = null
switch (val) {
case 2:
url = "/pageWork/information/information"
break
case 3:
url = "/pageWork/information/information"
break
case 4:
url = "/pageWork/information/information"
break
}
if (!url) return false
uni.reLaunch({ url })
}
$getCompanyInfo().then(({ bizData }) => {
vdata.agentShareImgUrl = bizData.agentShareImgUrl
})
// 微信分享
onShareAppMessage((res) => {
if(res.from == 'menu') return {
title: uni.$appName,
path: '/pages/workbench/workbench',
imageUrl: vdata.agentShareImgUrl
}
})
// 分享到朋友圈
onShareTimeline(() => {
return {
title: uni.$appName,
imageUrl: vdata.agentShareImgUrl
}
})
// 请求首页广告
$adList({ appPlace: 2 }).then(({ bizData }) => {
bizData.forEach(v => {
v.appContent = JSON.parse(v.appContent)
})
vdata.adList = bizData
console.log(bizData)
})
$getUserInfo().then(({ bizData }) => {
storageManage.userInfo(bizData)
})
onBeforeUnmount(() => {
uni.removeInterceptor("switchTab")
})
</script>
<style lang="scss" scoped>
.page-wrapper {
background-color: $primaryColor;
.wallet-wrapper {
padding: 20rpx 50rpx 50rpx 50rpx;
color: #fff;
}
.wallet-money {
font-size: 25rpx;
color: rgba($color: #fff, $alpha: 0.7);
}
.wallet-top {
position: relative;
.wallet-number {
margin: 10rpx 0;
font-size: 63rpx;
}
.wallet-eyes {
display: flex;
position: absolute;
top: 0;
right: 0;
padding: 14rpx;
background-color: rgba($color: #000000, $alpha: 0.2);
image {
width: 40rpx;
height: 40rpx;
}
}
}
.wallet-bottom {
display: flex;
justify-content: space-between;
margin-top: 60rpx;
padding-right: 20rpx;
.wallet-b-number {
margin-top: 10rpx;
}
}
}
// 导航栏 和 公告时间部分 共用一个样式
.nav-text,
.notice-time {
margin-top: 21rpx;
font-size: 28rpx;
}
// 导航
.nav-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-bottom: 30rpx;
.nav-item {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 200rpx;
height: 200rpx;
margin-top: 25rpx;
image {
width: 60rpx;
height: 60rpx;
}
}
.nav-station {
background-color: #fff;
}
}
.notice-wrapper {
margin-top: 20rpx;
padding: 30rpx;
background-color: #f7f7f7;
.notice-content {
white-space: nowrap;
}
.notice-time {
color: #8c8c8c;
}
}
.tips-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 50rpx;
.tips-title {
margin-bottom: 30rpx;
font-size: 30rpx;
}
.tips-info {
font-size: 26rpx;
color: #808080;
}
}
</style>

View File

@@ -0,0 +1,190 @@
<template>
<JHeaderTitle bgColor="#7737fe" color="#fff" pdB="70rpx" :back="false" />
<view class="page-wrapper" @click="toLogin">
<!-- 自定义导航栏 -->
<!-- 钱包卡片 -->
<view class="wallet-wrapper">
<view class="wallet-top">
<view class="wallet-money">钱包余额</view>
<view class="wallet-number">******</view>
<view class="wallet-eyes bdR10">
<image src="/static/iconImg/home-eye-close.svg" mode="scaleToFill"/>
</view>
</view>
<view class="wallet-bottom">
<view>
<view class="wallet-money">提现中金额</view>
<view class="wallet-b-number">0.00</view>
</view>
<view>
<view class="wallet-money">在途利润</view>
<view class="wallet-b-number">0.00</view>
</view>
<view>
<view class="wallet-money">冻结金额
<uni-icons type="help-filled" size="20" color="#c6c6c6"/>
</view>
<view>0.00
</view>
</view>
</view>
</view>
<view style="padding: 30rpx;">
<button style="padding:10rpx 50rpx 10rpx 50rpx; background: #fff; color:#7737fe ;">提现</button>
</view>
<!-- <Button pd="0 50rpx 50rpx 50rpx" bgColor="#fff" color="#7737fe" pdTop="0">提现</JButton> -->
<JCardContent>
<!-- nav 导航部分 -->
<view class="nav-list">
<view class="nav-item bgF2 bdR16" v-for="(v, i) in list" :key="i" :class="[v.url === 'null' ? 'nav-station' : '']">
<image :src="v.imgUrl" mode="scaleToFill" v-if="v.imgUrl" />
<text class="nav-text">{{ v.title }}</text>
</view>
</view>
<!-- 广告展示部分 -->
<blcok v-for="v in vdata.adList" :key="v.adverId">
<JeepayBanner :list="v.appContent" :interval='v.changeTime' v-if="v.appPlaceType == 2" mg='40rpx 0' />
<JeepayAdCard :list='v.appContent' v-if="v.appPlaceType == 1" mg='40rpx 0' mgs="40rpx 0"/>
</blcok>
</JCardContent>
</view>
<!-- #ifdef APP-PLUS -->
<view style="height: 120rpx;"></view>
<!-- #endif -->
</template>
<script setup>
import { ref, reactive, onBeforeUnmount } from "vue"
import list from "./navList/navList"
const noticeList = ref([])
const vdata = reactive({
adList:[]
})
const toLogin=()=>{
uni.reLaunch({
url:'/pages/login/login'
})
}
</script>
<style lang="scss" scoped>
.page-wrapper {
background-color: $primaryColor;
padding-top: 100rpx;
.wallet-wrapper {
padding: 20rpx 50rpx 50rpx 50rpx;
color: #fff;
}
.wallet-money {
font-size: 25rpx;
color: rgba($color: #fff, $alpha: 0.7);
}
.wallet-top {
position: relative;
.wallet-number {
margin: 10rpx 0;
font-size: 63rpx;
}
.wallet-eyes {
display: flex;
position: absolute;
top: 0;
right: 0;
padding: 14rpx;
background-color: rgba($color: #000000, $alpha: 0.2);
image {
width: 40rpx;
height: 40rpx;
}
}
}
.wallet-bottom {
display: flex;
justify-content: space-between;
margin-top: 60rpx;
padding-right: 20rpx;
.wallet-b-number {
margin-top: 10rpx;
}
}
}
// 导航栏 和 公告时间部分 共用一个样式
.nav-text,
.notice-time {
margin-top: 21rpx;
font-size: 28rpx;
}
// 导航
.nav-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-bottom: 30rpx;
background: #fff;
border-radius: 30rpx 30rpx 0 0 ;
padding: 30rpx 45rpx;
.nav-item {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 200rpx;
height: 200rpx;
margin-top: 25rpx;
image {
width: 60rpx;
height: 60rpx;
}
}
.nav-station {
background-color: #fff;
}
}
.notice-wrapper {
margin-top: 20rpx;
padding: 30rpx;
background-color: #f7f7f7;
.notice-content {
white-space: nowrap;
}
.notice-time {
color: #8c8c8c;
}
}
.tips-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 50rpx;
.tips-title {
margin-bottom: 30rpx;
font-size: 30rpx;
}
.tips-info {
font-size: 26rpx;
color: #808080;
}
}
</style>