Merge branch 'Branch_1' of https://git.u8t.cn/tangxinyue/alipay-emulator into Branch_1
|
|
@ -0,0 +1,97 @@
|
||||||
|
<template>
|
||||||
|
<text
|
||||||
|
class="custom-icon"
|
||||||
|
:class="iconClass"
|
||||||
|
:style="{ color: color, fontSize: size + 'px' }"
|
||||||
|
@click="$emit('click')"
|
||||||
|
></text>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "my-icon",
|
||||||
|
props: {
|
||||||
|
// 图标名称,例如 'icon-home'
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
// 图标颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: "#333333"
|
||||||
|
},
|
||||||
|
// 图标大小,单位 rpx
|
||||||
|
size: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iconClass() {
|
||||||
|
// 这里的 'custom-icon' 必须和下面 font-family 的定义或者样式前缀对应
|
||||||
|
const name = `icon-${this.name}`;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 1. 引入并定义字体名称 */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'myIconFont';
|
||||||
|
/* 微信小程序若本地引用报错,可换成 base64 字符串或网络绝对路径 */
|
||||||
|
src: url('@/static/font/iconfont.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. 定义基础样式 */
|
||||||
|
.custom-icon {
|
||||||
|
font-family: "myIconFont" !important;
|
||||||
|
font-size: inherit;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-sanjiaozhou-maohao:before {
|
||||||
|
content: "\e630";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-fengexian:before {
|
||||||
|
content: "\e631";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-douhao:before {
|
||||||
|
content: "\e626";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-0:before {
|
||||||
|
content: "\e629";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-1:before {
|
||||||
|
content: "\e627";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-2:before {
|
||||||
|
content: "\e62b";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-3:before {
|
||||||
|
content: "\e62c";
|
||||||
|
}
|
||||||
|
.icon-a-sanjiaozhou-4:before {
|
||||||
|
content: "\e62f";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-5:before {
|
||||||
|
content: "\e62d";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-6:before {
|
||||||
|
content: "\e628";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-7:before {
|
||||||
|
content: "\e625";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-8:before {
|
||||||
|
content: "\e62a";
|
||||||
|
}
|
||||||
|
.icon-sanjiaozhou-9:before {
|
||||||
|
content: "\e62e";
|
||||||
|
}
|
||||||
|
</style>
|
||||||
24
pages.json
|
|
@ -429,6 +429,22 @@
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path" : "game/sanjiaozhou",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "三角洲",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "game/index",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "游戏首页",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path" : "wx-payment-success/wx-payment-success",
|
"path" : "wx-payment-success/wx-payment-success",
|
||||||
"style" :
|
"style" :
|
||||||
|
|
@ -476,6 +492,14 @@
|
||||||
"navigationBarTitleText" : "广东",
|
"navigationBarTitleText" : "广东",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "video-chat/video-chat",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "视频单聊",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,11 @@ const otherList = [{
|
||||||
name: "视频群聊",
|
name: "视频群聊",
|
||||||
path: "/pages/other/video-group-chat/video-group-chat"
|
path: "/pages/other/video-group-chat/video-group-chat"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: "/static/image/index/qita/shipinqunliao.png",
|
||||||
|
name: "视频单聊",
|
||||||
|
path: "/pages/other/video-chat/video-chat"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: "/static/image/index/qita/zhifuchenggong-wx.png",
|
icon: "/static/image/index/qita/zhifuchenggong-wx.png",
|
||||||
name: "微信支付",
|
name: "微信支付",
|
||||||
|
|
@ -297,8 +302,8 @@ const otherList = [{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "/static/image/index/qita/game.png",
|
icon: "/static/image/index/qita/game.png",
|
||||||
name: "王者主页",
|
name: "游戏",
|
||||||
path: "/pages/other/game/honor-of-kings"
|
path: "/pages/other/game/index"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "/static/image/other/certificate/certificate.png",
|
icon: "/static/image/other/certificate/certificate.png",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<nav-bar title="游戏平台" bgColor="#F0F4F9"></nav-bar>
|
||||||
|
<view class="menu-container">
|
||||||
|
<view class="card" v-for="(item, index) in menuList" :key="index" style=" background: #ffffff ">
|
||||||
|
<text class="card-title">{{ item.name }}</text>
|
||||||
|
<view class="icon-wrapper">
|
||||||
|
<view class="icon-shadow" :style="{ background: item.shadowColor }"></view>
|
||||||
|
<image class="icon-img" :src="`/static/image/other/game/${item.icon}.png`" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<view class="btn" style="background: linear-gradient( 327deg, #1777FF 0%, #17CDFF 100%);"
|
||||||
|
@click="goTo(item.url)">立即进入</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
getCurrentInstance
|
||||||
|
} from 'vue';
|
||||||
|
import {
|
||||||
|
onLoad
|
||||||
|
} from '@dcloudio/uni-app'
|
||||||
|
|
||||||
|
const {
|
||||||
|
proxy
|
||||||
|
} = getCurrentInstance();
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
proxy.$apiUserEvent('all', {
|
||||||
|
type: 'event',
|
||||||
|
key: 'game',
|
||||||
|
prefix: '.uni.other.',
|
||||||
|
value: '游戏'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const menuList = ref([{
|
||||||
|
name: "王者荣耀",
|
||||||
|
icon: "wangzhe",
|
||||||
|
shadowColor: "#FF604F",
|
||||||
|
url: "/pages/other/game/honor-of-kings"
|
||||||
|
}, {
|
||||||
|
name: "三角洲",
|
||||||
|
icon: "sanjiaozhou",
|
||||||
|
shadowColor: "#12C96A",
|
||||||
|
url: "/pages/other/game/sanjiaozhou"
|
||||||
|
}, {
|
||||||
|
name: "和平精英",
|
||||||
|
icon: "hepingjingying",
|
||||||
|
shadowColor: "#4992F2",
|
||||||
|
url: ""
|
||||||
|
}, {
|
||||||
|
name: "无畏契约",
|
||||||
|
icon: "wuweiqiyue",
|
||||||
|
shadowColor: "#FF3333",
|
||||||
|
url: ""
|
||||||
|
}]);
|
||||||
|
|
||||||
|
const goTo = (url) => {
|
||||||
|
if (url) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: "开发中",
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
page {
|
||||||
|
background-color: #F0F4F9;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: calc(50% - 14rpx);
|
||||||
|
border-radius: 28rpx 28rpx 28rpx 28rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 48rpx;
|
||||||
|
padding-bottom: 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #1A1A1A;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-wrapper {
|
||||||
|
margin-top: 40rpx;
|
||||||
|
margin-bottom: 62rpx;
|
||||||
|
position: relative;
|
||||||
|
width: 116rpx;
|
||||||
|
height: 116rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-img {
|
||||||
|
width: 116rpx;
|
||||||
|
height: 116rpx;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-shadow {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10rpx;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 8rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
filter: blur(5px);
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 0 20rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
line-height: 56rpx;
|
||||||
|
border-radius: 16rpx 16rpx 16rpx 16rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,833 @@
|
||||||
|
<template>
|
||||||
|
<view class="honor-of-kings">
|
||||||
|
<nav-bar title="三角洲结算页" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
|
||||||
|
@right-click="onRightClick">
|
||||||
|
</nav-bar>
|
||||||
|
<view style="padding: 8px;box-sizing: border-box;">
|
||||||
|
<view class="painter-container" @click="handlePreview"
|
||||||
|
:style="`width:calc(100vw - 16px) ; height: ${posterContainerHeight}px; overflow: hidden; position: relative; transform: translateZ(0);`">
|
||||||
|
<!-- 运用 js 算出的无误差纯数字 scale 来实现高清画板的等比缩小,彻底兼容所有老旧内核,不再被截断 -->
|
||||||
|
<view
|
||||||
|
:style="`width: 750px; transform: scale(${posterScaleRatio}); transform-origin: left top; position: absolute; left: 0; top: 0;`">
|
||||||
|
<l-painter isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:750px;`">
|
||||||
|
<l-painter-view :css="`width: 750.0px; position: relative;`">
|
||||||
|
<!-- 直接使用主背景图撑开父容器,移除不必要的 opacity: 0 占位图,避免在大屏渲染时产生黑块 -->
|
||||||
|
<l-painter-image :src="`/static/image/other/game/sanjiaozhou/style-${data.type}.jpg`"
|
||||||
|
css="width: 750.0px; display: block;"></l-painter-image>
|
||||||
|
|
||||||
|
<l-painter-view css="position: absolute; left: 73px; top: 113px; white-space: nowrap;">
|
||||||
|
<!-- 地图 -->
|
||||||
|
<l-painter-image :src="`/static/image/other/game/sanjiaozhou/line.png`"
|
||||||
|
css="display: inline-block; vertical-align: middle; height: 22px; width: 1px;"></l-painter-image>
|
||||||
|
<l-painter-view
|
||||||
|
css="display: inline-block; vertical-align: middle; padding-left: 4px; min-width: 60px;">
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:6px; line-height:6px; margin-bottom: 4px; white-space: nowrap;"
|
||||||
|
:text="data.map.level"></l-painter-text>
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:10px; line-height:10px; white-space: nowrap;"
|
||||||
|
:text="data.map.name"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
<!-- 撤离点 -->
|
||||||
|
<l-painter-image :src="`/static/image/other/game/sanjiaozhou/line.png`"
|
||||||
|
css="display: inline-block; vertical-align: middle; height: 22px; width: 1px;margin-left: 2px;"></l-painter-image>
|
||||||
|
<l-painter-view
|
||||||
|
css="display: inline-block; vertical-align: middle; padding-left: 4px; min-width: 60px;">
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:6px; line-height:6px; margin-bottom: 4px; white-space: nowrap;"
|
||||||
|
text="撤离点"></l-painter-text>
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:10px; line-height:10px; white-space: nowrap;"
|
||||||
|
:text="data.extractionPoint"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
<!-- 时长 -->
|
||||||
|
<l-painter-image :src="`/static/image/other/game/sanjiaozhou/line.png`"
|
||||||
|
css="display: inline-block; vertical-align: middle; height: 22px; width: 1px;margin-left: 2px;"></l-painter-image>
|
||||||
|
<l-painter-view
|
||||||
|
css="display: inline-block; vertical-align: middle; padding-left: 4px; min-width: 60px;">
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:6px; line-height:6px; margin-bottom: 4px; white-space: nowrap;"
|
||||||
|
text="时长"></l-painter-text>
|
||||||
|
<l-painter-text v-for="(char, idx) in String(data.duration).split('')"
|
||||||
|
:key="'durationNum_' + idx" :css="getTimeCharStyle(char, idx, $system)"
|
||||||
|
:text="getDefeatIconText(char)"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
<!-- 对局时间 -->
|
||||||
|
<l-painter-image :src="`/static/image/other/game/sanjiaozhou/line.png`"
|
||||||
|
css="display: inline-block; vertical-align: middle; height: 22px; width: 1px;margin-left: 2px;"></l-painter-image>
|
||||||
|
<l-painter-view
|
||||||
|
css="display: inline-block; vertical-align: middle; padding-left: 4px; min-width: 60px;">
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:6px; line-height:6px; margin-bottom: 4px; white-space: nowrap;"
|
||||||
|
text="对局时间"></l-painter-text>
|
||||||
|
<!-- <l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:10px; line-height:10px; white-space: nowrap;"
|
||||||
|
:text="data.map.name"></l-painter-text> -->
|
||||||
|
<l-painter-text v-for="(char, idx) in String(data.matchTime).split('')"
|
||||||
|
:key="'matchTimeNum_' + idx" :css="getTimeCharStyle(char, idx, $system)"
|
||||||
|
:text="getDefeatIconText(char)"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
|
||||||
|
</l-painter-view>
|
||||||
|
|
||||||
|
<!-- 本局收获 -->
|
||||||
|
<l-painter-view
|
||||||
|
css="position: absolute; left: 73px; top: 175px; white-space: nowrap; display: block;">
|
||||||
|
<l-painter-text
|
||||||
|
v-for="(char, idx) in String(data.harvest).replace(/\B(?=(\d{3})+(?!\d))/g, ',').split('')"
|
||||||
|
:key="'harvestNum_' + idx" :css="getHarvestCharStyle(char, idx, $system)"
|
||||||
|
:text="getDefeatIconText(char)"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
|
||||||
|
<!-- 击败干员 -->
|
||||||
|
<l-painter-view
|
||||||
|
css="position: absolute; left: 73px; top: 250px; white-space: nowrap; display: block;">
|
||||||
|
<l-painter-text v-for="(char, idx) in String(data.defeat).split('')"
|
||||||
|
:key="'bigNum_' + idx"
|
||||||
|
:css="`display: inline-block; color:#DBE5E6; font-size:22px; line-height:6px; margin-bottom: 4px; font-family: myIconFont; margin-left: ${idx === 0 ? '0' : '-2px'};`"
|
||||||
|
:text="getDefeatIconText(char)"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
|
||||||
|
<!-- 高光击败 -->
|
||||||
|
<l-painter-view v-for="(item, index) in data.defeatInfo" :key="index"
|
||||||
|
:css="`display: inline-block; vertical-align: middle;position: absolute; left: 73px; top: ${295 + index * 16}px; `">
|
||||||
|
<l-painter-view css="display: inline-block;">
|
||||||
|
<l-painter-image src="/static/image/other/game/sanjiaozhou/kill.png"
|
||||||
|
css="width: 12px; height: 12px; display: inline-block;margin-right:2px"></l-painter-image>
|
||||||
|
<l-painter-text
|
||||||
|
css="display: inline-block; color:#DBE5E6; font-size:9px; line-height:6px; margin-bottom: 4px; white-space: nowrap;"
|
||||||
|
:text="`${item.name} [${item.rank}]`"></l-painter-text>
|
||||||
|
</l-painter-view>
|
||||||
|
</l-painter-view>
|
||||||
|
|
||||||
|
<!-- 玩家名称 -->
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:10px; line-height:10px; white-space: nowrap;transform:rotate(10deg);position:absolute;left:424px;top:310px;"
|
||||||
|
:text="data.name"></l-painter-text>
|
||||||
|
|
||||||
|
<l-painter-text
|
||||||
|
css="display: block; color:#CDCDCD; font-size:7px; line-height:10px; white-space: nowrap;transform:rotate(10deg);position:absolute;left:422px;top:321px;opacity: 0.6;"
|
||||||
|
text="信守不渝"></l-painter-text>
|
||||||
|
|
||||||
|
<!-- 水印 -->
|
||||||
|
<l-painter-image v-if="$isVip()" src="/static/image/other/shuiying.png"
|
||||||
|
:css="`position: absolute; left: 18.8px; bottom: 17.1px; width: 145.38px;height:42.76px`"></l-painter-image>
|
||||||
|
</l-painter-view>
|
||||||
|
</l-painter>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 水印 -->
|
||||||
|
<view v-if="$isVip()">
|
||||||
|
<liu-drag-button :canDocking="false"
|
||||||
|
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_sanjiaozhou')">
|
||||||
|
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||||
|
</liu-drag-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="save-action">
|
||||||
|
<button class="save-btn" @click="handleSave">保存</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 主题选择区域 -->
|
||||||
|
<view class="theme-selector">
|
||||||
|
<scroll-view scroll-x="true" class="theme-scroll" :show-scrollbar="false">
|
||||||
|
<view class="theme-list">
|
||||||
|
<view class="theme-item" v-for="(item, index) in ['样式一', '样式二', '样式三', '样式四']" :key="index + 1"
|
||||||
|
:class="{ active: data.type == index + 1 }" @click="handleChangeTheme(index + 1)">
|
||||||
|
<text class="theme-text">{{ item }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 数据编辑弹窗 -->
|
||||||
|
<uni-popup ref="editPopup" type="center">
|
||||||
|
<view class="edit-popup-content">
|
||||||
|
<view class="popup-header">
|
||||||
|
<text class="title">编辑主页数据</text>
|
||||||
|
</view>
|
||||||
|
<scroll-view scroll-y class="popup-scroll">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">玩家名称</text>
|
||||||
|
<input class="input" type="text" v-model="tempData.name" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">地图级别</text>
|
||||||
|
<view class="button-group">
|
||||||
|
<view class="button-item" :class="{ active: tempData.map.level === '普通' }"
|
||||||
|
@click="tempData.map.level = '普通'">普通</view>
|
||||||
|
<view class="button-item" :class="{ active: tempData.map.level === '机密' }"
|
||||||
|
@click="tempData.map.level = '机密'">机密</view>
|
||||||
|
<view class="button-item" :class="{ active: tempData.map.level === '绝密' }"
|
||||||
|
@click="tempData.map.level = '绝密'">绝密</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">地图名称</text>
|
||||||
|
<input class="input" type="text" v-model="tempData.map.name" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">撤离点</text>
|
||||||
|
<input class="input" type="text" v-model="tempData.extractionPoint" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">对局时间</text>
|
||||||
|
<picker mode="multiSelector" :range="matchTimeRange" :value="matchTimeIndex"
|
||||||
|
@change="onMatchTimeChange" class="input"
|
||||||
|
style="height: 36px; line-height: 36px; display: flex; align-items: center;">
|
||||||
|
<text>{{ tempData.matchTime || '请选择时间' }}</text>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">时长</text>
|
||||||
|
<picker mode="multiSelector" :range="durationRange" :value="durationIndex"
|
||||||
|
@change="onDurationChange" class="input"
|
||||||
|
style="height: 36px; line-height: 36px; display: flex; align-items: center;">
|
||||||
|
<text>{{ tempData.duration || '请选择时长' }}</text>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">本局收获</text>
|
||||||
|
<input class="input" type="text" v-model="tempData.harvest" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">击败干员</text>
|
||||||
|
<input class="input" type="text" v-model="tempData.defeat" @input="onDefeatChange" />
|
||||||
|
</view>
|
||||||
|
<view style="border: 1px dashed #007aff;padding: 10px;border-radius: 8px;"
|
||||||
|
v-if="tempData.defeatInfo && tempData.defeatInfo.length > 0">
|
||||||
|
<view v-for="(item, index) in tempData.defeatInfo" :key="'defeat_' + index"
|
||||||
|
style="margin-bottom: 10px;">
|
||||||
|
<view
|
||||||
|
style="display: flex; justify-content: flex-end; gap: 15px; margin-bottom: 5px; font-size: 12px; height: 16px;"
|
||||||
|
v-if="tempData.defeatInfo.length > 1">
|
||||||
|
<text v-if="index > 0" @click="moveDefeatUp(index)"
|
||||||
|
style="color: #007aff; cursor: pointer;">↑ 上移</text>
|
||||||
|
<text v-if="index < tempData.defeatInfo.length - 1" @click="moveDefeatDown(index)"
|
||||||
|
style="color: #007aff; cursor: pointer;">↓ 下移</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">被击败者{{ index + 1 }}昵称</text>
|
||||||
|
<input class="input" type="text" v-model="item.name" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item" style="margin-bottom: 0;">
|
||||||
|
<text class="label">被击败者{{ index + 1 }}段位</text>
|
||||||
|
<input class="input" type="text" v-model="item.rank" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</scroll-view>
|
||||||
|
<view class="popup-footer">
|
||||||
|
<button class="cancel-btn" @click="closeEditPopup">取消</button>
|
||||||
|
<button class="confirm-btn" @click="confirmEdit">确定</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<!-- 横向全屏放大预览层 -->
|
||||||
|
<view class="preview-overlay" v-if="showPreview" @click="showPreview = false">
|
||||||
|
<image class="preview-image" :src="finalPosterPath" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||||
|
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||||
|
const rightButtonText = ref("编辑");
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const showPreview = ref(false); // 控制全屏预览
|
||||||
|
const isMountedReady = ref(false);
|
||||||
|
|
||||||
|
// 获取系统宽度计算海报缩放比例,代替容易失效的 css calc(),确保全端兼容防截断
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
const windowWidth = sysInfo.windowWidth || 375;
|
||||||
|
const posterScaleRatio = windowWidth / 750;
|
||||||
|
const posterContainerHeight = 430 * posterScaleRatio;
|
||||||
|
|
||||||
|
// 页面表单数据字段
|
||||||
|
const data = reactive({
|
||||||
|
type: 1, // 样式类型 1.2.3.4
|
||||||
|
name: '大坝猛攻哥',
|
||||||
|
map: {
|
||||||
|
name: '零号大坝',
|
||||||
|
level: '机密'
|
||||||
|
},
|
||||||
|
extractionPoint: '工业电梯',
|
||||||
|
duration: "00:25:19",
|
||||||
|
matchTime: '02-32 21:02',
|
||||||
|
harvest: '13526559',
|
||||||
|
defeat: '1',
|
||||||
|
defeatInfo: [
|
||||||
|
{
|
||||||
|
name: '大坝贪吃鼠',
|
||||||
|
rank: "黑鹰II"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// 数字到 my-icon iconfont Unicode 的映射字典
|
||||||
|
const digitIconMap = {
|
||||||
|
'0': '\ue629', '1': '\ue627', '2': '\ue62b', '3': '\ue62c', '4': '\ue62f',
|
||||||
|
'5': '\ue62d', '6': '\ue628', '7': '\ue625', '8': '\ue62a', '9': '\ue62e',
|
||||||
|
',': '\ue626', ':': '\ue630',
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDefeatIconText = (defeatStr) => {
|
||||||
|
if (!defeatStr && defeatStr !== 0) return '';
|
||||||
|
return String(defeatStr).split('').map(char => digitIconMap[char] || char).join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTimeCharStyle = (char, idx, system) => {
|
||||||
|
const fontSize = char === '-' ? 12 : (char === ':' ? 4 : 10);
|
||||||
|
let marginLeft = '-2px';
|
||||||
|
if (idx === 0 || system === 'iOS') {
|
||||||
|
marginLeft = char === '-' ? '2px' : '0px';
|
||||||
|
}
|
||||||
|
let marginRight = '0';
|
||||||
|
if ([' ', '-', ':'].includes(char)) {
|
||||||
|
if (char === '-' && system === 'Android') {
|
||||||
|
marginLeft = '0px'
|
||||||
|
}
|
||||||
|
if (char === ':' && system === 'Android') {
|
||||||
|
marginRight = '-1px';
|
||||||
|
marginLeft = '-1px'
|
||||||
|
} else if (char === ' ' && system === 'Android') {
|
||||||
|
marginRight = '2px';
|
||||||
|
} else {
|
||||||
|
marginRight = '1rpx';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `display: inline-block; vertical-align: bottom; color:#CDCDCD; font-size:${fontSize}px; line-height:6px; margin-bottom: 4px; font-family:myIconFont; margin-left: ${marginLeft}; margin-right: ${marginRight};`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHarvestCharStyle = (char, idx, system) => {
|
||||||
|
const fontSize = char === ',' ? 6 : 22;
|
||||||
|
let marginLeft = idx === 0 ? '0' : (char === ',' ? (system === 'iOS' ? '3px' : '1px') : (system === 'iOS' ? '2px' : '-3px'));
|
||||||
|
let marginRight = char === ',' && system === 'Android' ? '2px' : '0';
|
||||||
|
let marginTop = char === ',' ? '3px' : '0';
|
||||||
|
return `display: inline-block; vertical-align: bottom; color:#DBE5E6; font-size:${fontSize}px; margin-bottom: 4px; font-family: myIconFont; margin-left: ${marginLeft}; margin-right: ${marginRight}; margin-top: ${marginTop};`;
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
const cachedData = uni.getStorageSync('sanjiaozhouData');
|
||||||
|
if (cachedData) {
|
||||||
|
Object.assign(data, cachedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.$on('editFormPhoto', (info) => {
|
||||||
|
tempData.avatar = info;
|
||||||
|
// #ifndef H5
|
||||||
|
if (info && !info.startsWith('/static/')) {
|
||||||
|
newAvatars.value.push(info);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
});
|
||||||
|
|
||||||
|
// 进入页面埋点
|
||||||
|
proxy.$apiUserEvent('all', {
|
||||||
|
type: 'click',
|
||||||
|
key: 'sanjiaozhou',
|
||||||
|
prefix: '.uni.other.',
|
||||||
|
value: "三角洲结算页"
|
||||||
|
})
|
||||||
|
|
||||||
|
// 加载海报需要用到的自定义数字字体
|
||||||
|
uni.loadFontFace({
|
||||||
|
family: 'myIconFont',
|
||||||
|
source: `url("/static/font/iconfont.ttf")`,
|
||||||
|
success() {
|
||||||
|
console.log('myIconFont 字体加载成功');
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error('myIconFont 字体加载失败', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
uni.$off('editFormPhoto');
|
||||||
|
})
|
||||||
|
|
||||||
|
const finalPosterPath = ref('');
|
||||||
|
|
||||||
|
const editPopup = ref(null);
|
||||||
|
const tempData = reactive({
|
||||||
|
map: {},
|
||||||
|
defeatInfo: [{}]
|
||||||
|
});
|
||||||
|
const newAvatars = ref([]);
|
||||||
|
|
||||||
|
const onDefeatChange = (e) => {
|
||||||
|
const val = parseInt(e.detail.value) || 0;
|
||||||
|
const maxAllowed = Math.min(3, Math.max(0, val));
|
||||||
|
|
||||||
|
if (tempData.defeatInfo.length < maxAllowed) {
|
||||||
|
const toAdd = maxAllowed - tempData.defeatInfo.length;
|
||||||
|
for (let i = 0; i < toAdd; i++) {
|
||||||
|
tempData.defeatInfo.push({ name: '', rank: '' });
|
||||||
|
}
|
||||||
|
} else if (tempData.defeatInfo.length > maxAllowed) {
|
||||||
|
tempData.defeatInfo.splice(maxAllowed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveDefeatUp = (index) => {
|
||||||
|
if (index > 0) {
|
||||||
|
const item = tempData.defeatInfo.splice(index, 1)[0];
|
||||||
|
tempData.defeatInfo.splice(index - 1, 0, item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveDefeatDown = (index) => {
|
||||||
|
if (index < tempData.defeatInfo.length - 1) {
|
||||||
|
const item = tempData.defeatInfo.splice(index, 1)[0];
|
||||||
|
tempData.defeatInfo.splice(index + 1, 0, item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 时长选择器数据
|
||||||
|
const durationRange = ref([
|
||||||
|
Array.from({ length: 100 }, (_, i) => (i < 10 ? '0' + i : i + '')),
|
||||||
|
Array.from({ length: 60 }, (_, i) => (i < 10 ? '0' + i : i + '')),
|
||||||
|
Array.from({ length: 60 }, (_, i) => (i < 10 ? '0' + i : i + ''))
|
||||||
|
]);
|
||||||
|
const durationIndex = ref([0, 0, 0]);
|
||||||
|
|
||||||
|
const onDurationChange = (e) => {
|
||||||
|
const val = e.detail.value;
|
||||||
|
durationIndex.value = val;
|
||||||
|
tempData.duration = `${durationRange.value[0][val[0]]}:${durationRange.value[1][val[1]]}:${durationRange.value[2][val[2]]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 对局时间选择器数据
|
||||||
|
const matchTimeRange = ref([
|
||||||
|
Array.from({ length: 12 }, (_, i) => (i + 1 < 10 ? '0' + (i + 1) : (i + 1) + '')),
|
||||||
|
Array.from({ length: 31 }, (_, i) => (i + 1 < 10 ? '0' + (i + 1) : (i + 1) + '')),
|
||||||
|
Array.from({ length: 24 }, (_, i) => (i < 10 ? '0' + i : i + '')),
|
||||||
|
Array.from({ length: 60 }, (_, i) => (i < 10 ? '0' + i : i + ''))
|
||||||
|
]);
|
||||||
|
const matchTimeIndex = ref([0, 0, 0, 0]);
|
||||||
|
|
||||||
|
const onMatchTimeChange = (e) => {
|
||||||
|
const val = e.detail.value;
|
||||||
|
matchTimeIndex.value = val;
|
||||||
|
tempData.matchTime = `${matchTimeRange.value[0][val[0]]}-${matchTimeRange.value[1][val[1]]} ${matchTimeRange.value[2][val[2]]}:${matchTimeRange.value[3][val[3]]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const initPickerIndexes = () => {
|
||||||
|
if (tempData.duration) {
|
||||||
|
const parts = tempData.duration.split(':');
|
||||||
|
if (parts.length === 3) {
|
||||||
|
durationIndex.value = [parseInt(parts[0]) || 0, parseInt(parts[1]) || 0, parseInt(parts[2]) || 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tempData.matchTime) {
|
||||||
|
const spaceSplit = tempData.matchTime.split(' ');
|
||||||
|
if (spaceSplit.length === 2) {
|
||||||
|
const dateParts = spaceSplit[0].split('-');
|
||||||
|
const timeParts = spaceSplit[1].split(':');
|
||||||
|
if (dateParts.length === 2 && timeParts.length === 2) {
|
||||||
|
matchTimeIndex.value = [(parseInt(dateParts[0]) || 1) - 1, (parseInt(dateParts[1]) || 1) - 1, parseInt(timeParts[0]) || 0, parseInt(timeParts[1]) || 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleChangeTheme(typeIndex) {
|
||||||
|
// 切换主题时,先清空旧海报,触发界面“加载中”提示
|
||||||
|
finalPosterPath.value = '';
|
||||||
|
data.type = typeIndex;
|
||||||
|
uni.setStorageSync('sanjiaozhouData', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRightClick() {
|
||||||
|
Object.assign(tempData, JSON.parse(JSON.stringify(data)));
|
||||||
|
initPickerIndexes();
|
||||||
|
newAvatars.value = [];
|
||||||
|
editPopup.value.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeEditPopup() {
|
||||||
|
// #ifndef H5
|
||||||
|
newAvatars.value.forEach(path => {
|
||||||
|
uni.removeSavedFile({ filePath: path });
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
editPopup.value.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmEdit() {
|
||||||
|
// #ifndef H5
|
||||||
|
// 删除多余的新上传文件
|
||||||
|
newAvatars.value.forEach(path => {
|
||||||
|
if (path !== tempData.avatar) {
|
||||||
|
uni.removeSavedFile({ filePath: path });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 删除被替换掉的原本地头像
|
||||||
|
if (data.avatar !== tempData.avatar && data.avatar && !data.avatar.startsWith('/static/')) {
|
||||||
|
uni.removeSavedFile({ filePath: data.avatar });
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
Object.assign(data, tempData);
|
||||||
|
uni.setStorageSync('sanjiaozhouData', data);
|
||||||
|
editPopup.value.close();
|
||||||
|
|
||||||
|
// 数据修改后,清空旧海报触发“加载中”提示,等待重新生成
|
||||||
|
finalPosterPath.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击画布触发横向预览
|
||||||
|
const handlePreview = () => {
|
||||||
|
if (!finalPosterPath.value) {
|
||||||
|
uni.showToast({ title: '海报仍在生成中,请稍候', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showPreview.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 画布生成成功后触发,保存最终的海报路径
|
||||||
|
const onPainterSuccess = (path) => {
|
||||||
|
finalPosterPath.value = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击保存按钮,将带有渐变字体的最终图片存入相册
|
||||||
|
const handleSave = () => {
|
||||||
|
if (!finalPosterPath.value) {
|
||||||
|
uni.showToast({ title: '图片仍在生成中,请稍候', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.saveImageToPhotosAlbum({
|
||||||
|
filePath: finalPosterPath.value,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.showToast({ title: '保存失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
isMountedReady.value = true;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.preview-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #000;
|
||||||
|
z-index: 99999;
|
||||||
|
/* 抛弃 flex 布局,防止 width: 100vh 被父级限制而发生坍缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-overlay .preview-image {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 100vh;
|
||||||
|
height: 100vw;
|
||||||
|
/* 先拉回自身中心点,再围绕中心点旋转 90 度 */
|
||||||
|
transform: translate(-50%, -50%) rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.honor-of-kings {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.painter-container {
|
||||||
|
/* 强制画板缩放到设备屏幕宽度,避免物理 px 超出屏幕 */
|
||||||
|
padding: 8px;
|
||||||
|
zoom: calc(100vw / 798);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1000px;
|
||||||
|
/* 限制PC/iPad端的最大宽度 */
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-action {
|
||||||
|
margin-top: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 220rpx;
|
||||||
|
/* 留出底部主题固定栏的安全空间 */
|
||||||
|
|
||||||
|
.save-btn {
|
||||||
|
margin-top: 60rpx;
|
||||||
|
width: 316rpx;
|
||||||
|
background: #1777FF;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 56rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-selector {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 20rpx;
|
||||||
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
.theme-scroll {
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-list {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
|
||||||
|
.theme-item {
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: top;
|
||||||
|
margin: 0 10rpx;
|
||||||
|
padding: 0 40rpx;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 2rpx solid transparent;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #3B7BFF;
|
||||||
|
|
||||||
|
.theme-text {
|
||||||
|
color: #3B7BFF;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-popup-content {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
width: 85vw;
|
||||||
|
|
||||||
|
.popup-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40rpx 0 20rpx 0;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-scroll {
|
||||||
|
height: 55vh;
|
||||||
|
padding: 20rpx 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
padding-bottom: 16rpx;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 200rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-uploader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.upload-btn {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #999DA7;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.plus {
|
||||||
|
font-size: 60rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 300;
|
||||||
|
margin-top: -6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
.preview-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: -4rpx;
|
||||||
|
right: -4rpx;
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
background-color: red;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
line-height: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 40rpx;
|
||||||
|
|
||||||
|
.radio-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.radio-icon {
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid #d9d9d9;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-color: #3B7BFF;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 14rpx;
|
||||||
|
height: 14rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #3B7BFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #3B7BFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
.button-item {
|
||||||
|
padding: 4rpx 16rpx;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
color: #666;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
border: 2rpx solid transparent;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #3B7BFF;
|
||||||
|
background-color: rgba(59, 123, 255, 0.1);
|
||||||
|
border-color: #3B7BFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20rpx 40rpx 40rpx;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 46%;
|
||||||
|
height: 76rpx;
|
||||||
|
line-height: 76rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
background-color: #F4F4F4;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #3B7BFF;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,18 +2,22 @@
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<nav-bar bgColor="transparent" :isBack="false">
|
<nav-bar bgColor="transparent" :isBack="false">
|
||||||
<template v-slot:center>
|
<template v-slot:center>
|
||||||
<view class="flex-cneter title-box flex">
|
<view class="flex-cneter title-box flex" style="margin-top: 24rpx;">
|
||||||
<image class="wx-logo" src="/static/image/other/payment-success/payment-success.png"></image>
|
<image class="wx-logo" src="/static/image/other/payment-success/payment-success.png"></image>
|
||||||
<text class="title">支付成功</text>
|
<text class="title">支付成功</text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</nav-bar>
|
</nav-bar>
|
||||||
<view class="content-box flex-column flex-cneter" @click="editPaymentInfo">
|
<view class="content-box flex-column flex-cneter" @click="editPaymentInfo">
|
||||||
|
<image v-if="paymetInfo.userImg" class="user-img" :src="paymetInfo.userImg"></image>
|
||||||
<text class="product-name">{{ paymetInfo.productName }}</text>
|
<text class="product-name">{{ paymetInfo.productName }}</text>
|
||||||
<view class="money flex wx-font-medium">
|
<view class="money flex wx-font-medium" :style="{ 'margin-top': paymetInfo.userImg ? '78rpx' : '46rpx' }">
|
||||||
<image class="symbol" src="/static/image/other/payment-success/symbol-yuan.png"></image>{{
|
<image class="symbol" src="/static/image/other/payment-success/symbol-yuan.png"></image>{{
|
||||||
Number(paymetInfo.money).toFixed(2) }}
|
Number(paymetInfo.money).toFixed(2) }}
|
||||||
</view>
|
</view>
|
||||||
|
<image v-if="paymetInfo.isAd" class="ad-img" src="/static/image/other/payment-success/ad-img.png"
|
||||||
|
mode="widthFix">
|
||||||
|
</image>
|
||||||
</view>
|
</view>
|
||||||
<view class="finish-butn" @click="util.goBack()">完成</view>
|
<view class="finish-butn" @click="util.goBack()">完成</view>
|
||||||
|
|
||||||
|
|
@ -21,6 +25,18 @@
|
||||||
<uni-popup ref="editPaymentInfoPopup" type="center">
|
<uni-popup ref="editPaymentInfoPopup" type="center">
|
||||||
<view class="edit-popup">
|
<view class="edit-popup">
|
||||||
<view class="title">修改支付信息</view>
|
<view class="title">修改支付信息</view>
|
||||||
|
<view class="input-item flex-align-center">
|
||||||
|
<text class="label">用户头像</text>
|
||||||
|
<view class="avatar-uploader flex-1">
|
||||||
|
<view class="avatar-preview" v-if="paymetInfo.userImg">
|
||||||
|
<image class="preview-img" :src="paymetInfo.userImg" mode="aspectFill"></image>
|
||||||
|
<view class="delete-icon" @click="handleDeleteAvatar">×</view>
|
||||||
|
</view>
|
||||||
|
<view class="upload-btn" v-else @click="handleChooseAvatar">
|
||||||
|
<text class="plus">+</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view class="input-item flex-align-center">
|
<view class="input-item flex-align-center">
|
||||||
<text class="label"><text style="color: #FF3B30;">*</text>商品名称</text>
|
<text class="label"><text style="color: #FF3B30;">*</text>商品名称</text>
|
||||||
<input class="flex-1" type="text" v-model="paymetInfo.productName" placeholder="请输入商品名称" />
|
<input class="flex-1" type="text" v-model="paymetInfo.productName" placeholder="请输入商品名称" />
|
||||||
|
|
@ -29,6 +45,11 @@
|
||||||
<text class="label"><text style="color: #FF3B30;">*</text>支付金额</text>
|
<text class="label"><text style="color: #FF3B30;">*</text>支付金额</text>
|
||||||
<input class="flex-1" type="digit" v-model="paymetInfo.money" placeholder="请输入支付金额" />
|
<input class="flex-1" type="digit" v-model="paymetInfo.money" placeholder="请输入支付金额" />
|
||||||
</view>
|
</view>
|
||||||
|
<view class="input-item flex-align-center">
|
||||||
|
<text class="label">展示广告</text>
|
||||||
|
<switch class="flex-1" :checked="paymetInfo.isAd" @change="paymetInfo.isAd = $event.detail.value"
|
||||||
|
color="#16B264" style="transform:scale(0.8);transform-origin:left center;" />
|
||||||
|
</view>
|
||||||
<view class="btn-group flex">
|
<view class="btn-group flex">
|
||||||
<view class="btn cancel flex-1" @click="editPaymentInfoPopup.close()">取消</view>
|
<view class="btn cancel flex-1" @click="editPaymentInfoPopup.close()">取消</view>
|
||||||
<view style="width: 30rpx;"></view>
|
<view style="width: 30rpx;"></view>
|
||||||
|
|
@ -64,6 +85,38 @@ const editPaymentInfo = () => {
|
||||||
editPaymentInfoPopup.value.open('center');
|
editPaymentInfoPopup.value.open('center');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleChooseAvatar = () => {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: (res) => {
|
||||||
|
const tempFilePath = res.tempFilePaths[0];
|
||||||
|
// #ifndef H5
|
||||||
|
uni.saveFile({
|
||||||
|
tempFilePath: tempFilePath,
|
||||||
|
success: (saveRes) => {
|
||||||
|
if (paymetInfo.value.userImg && !paymetInfo.value.userImg.startsWith('/static/')) {
|
||||||
|
uni.removeSavedFile({ filePath: paymetInfo.value.userImg });
|
||||||
|
}
|
||||||
|
paymetInfo.value.userImg = saveRes.savedFilePath;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
// #ifdef H5
|
||||||
|
paymetInfo.value.userImg = tempFilePath;
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteAvatar = () => {
|
||||||
|
// #ifndef H5
|
||||||
|
if (paymetInfo.value.userImg && !paymetInfo.value.userImg.startsWith('/static/')) {
|
||||||
|
uni.removeSavedFile({ filePath: paymetInfo.value.userImg });
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
paymetInfo.value.userImg = '';
|
||||||
|
};
|
||||||
|
|
||||||
const confirmEditPaymentInfo = () => {
|
const confirmEditPaymentInfo = () => {
|
||||||
editPaymentInfoPopup.value.close();
|
editPaymentInfoPopup.value.close();
|
||||||
storage.set('wx_payment_success_info', paymetInfo.value);
|
storage.set('wx_payment_success_info', paymetInfo.value);
|
||||||
|
|
@ -80,8 +133,10 @@ const buttonGroup = [
|
||||||
|
|
||||||
|
|
||||||
const paymetInfo = ref({
|
const paymetInfo = ref({
|
||||||
|
userImg: '',
|
||||||
productName: '王者荣耀',
|
productName: '王者荣耀',
|
||||||
money: 298
|
money: 298,
|
||||||
|
isAd: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
|
@ -95,7 +150,7 @@ onShow(() => {
|
||||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||||
util.setAndroidSystemBarColor('#FFFFFF')
|
util.setAndroidSystemBarColor('#FFFFFF')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
plus.navigator.setStatusBarStyle("light");
|
plus.navigator.setStatusBarStyle("dark");
|
||||||
}, 500)
|
}, 500)
|
||||||
// #endif
|
// #endif
|
||||||
})
|
})
|
||||||
|
|
@ -131,6 +186,15 @@ onLoad(async () => {
|
||||||
|
|
||||||
.content-box {
|
.content-box {
|
||||||
margin-top: 162rpx;
|
margin-top: 162rpx;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.user-img {
|
||||||
|
width: 94rpx;
|
||||||
|
height: 94rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #D8D8D8;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
.product-name {
|
.product-name {
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
|
|
@ -154,6 +218,11 @@ onLoad(async () => {
|
||||||
margin-right: 20rpx;
|
margin-right: 20rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ad-img {
|
||||||
|
margin-top: 100rpx;
|
||||||
|
width: 654rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.finish-butn {
|
.finish-butn {
|
||||||
|
|
@ -207,6 +276,57 @@ onLoad(async () => {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #1A1A1A;
|
color: #1A1A1A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-uploader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.upload-btn {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 2rpx dashed #CCCCCC;
|
||||||
|
|
||||||
|
.plus {
|
||||||
|
font-size: 60rpx;
|
||||||
|
color: #999;
|
||||||
|
font-weight: 300;
|
||||||
|
margin-top: -6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
.preview-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: -4rpx;
|
||||||
|
right: -4rpx;
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
background-color: red;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
line-height: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group {
|
.btn-group {
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 112 B |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 458 B |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 4.1 KiB |