完成王者主页页面

This commit is contained in:
tangxinyue 2026-06-05 11:24:43 +08:00
parent a47cc2a9cd
commit 65270811da
15 changed files with 847 additions and 21 deletions

View File

@ -29,7 +29,7 @@ export function createApp() {
app.config.globalProperties.$system = plus.os.name;
// #endif
app.config.globalProperties.$systemInfo = systemInfo
uni.setStorageSync('version', '1.0.6.sp3')
uni.setStorageSync('version', '1.0.6.sp4')
app.config.globalProperties.$version = uni.getStorageSync('version')
app.use(globalMethods);
return {

View File

@ -420,6 +420,14 @@
"navigationBarTitleText" : "建设银行",
"navigationStyle": "custom"
}
},
{
"path" : "game/honor-of-kings",
"style" :
{
"navigationBarTitleText" : "王者荣耀",
"navigationStyle": "custom"
}
}
]
},

View File

@ -115,7 +115,8 @@
<image class="title-img" src="/static/image/index/qita.png"></image>
<view class="video-help-box">
<template v-for="item in otherList" :key="item.id">
<view class="video-help-item" :style="{ width: (windowWidth - 32) / 4 + 'px' }" @click="clickMenu(item)" v-if="isShowBankIdCard(item)">
<view class="video-help-item" :style="{ width: (windowWidth - 32) / 4 + 'px' }"
@click="clickMenu(item)" v-if="isShowBankIdCard(item)">
<image class="video-help-img" :src="item.icon"></image>
<text class="video-help-title">{{ item.name }}</text>
</view>
@ -304,6 +305,11 @@ const otherList = [{
name: "银行卡",
path: "/pages/other/bank/index"
},
{
icon: "/static/image/index/qita/game.png",
name: "王者主页",
path: "/pages/other/game/honor-of-kings"
},
]
const data = reactive({
@ -318,8 +324,8 @@ const data = reactive({
vision: "",
platform: '', // 添加平台信息,
qqgroup: {},
idcard:false,
bank:false
idcard: false,
bank: false
})
const {
@ -392,20 +398,20 @@ onShow(() => {
}, 800);
// #endif
})
function isShowBankIdCard(item){
if(item.name=='银行卡'||item.name=='身份证'){
console.log(item.name!='银行卡'||item.name!='身份证')
console.log(item.name=='银行卡'&&data.bank)
console.log(item.name=='银行卡'&&data.bank)
function isShowBankIdCard(item) {
if (item.name == '银行卡' || item.name == '身份证') {
console.log(item.name != '银行卡' || item.name != '身份证')
console.log(item.name == '银行卡' && data.bank)
console.log(item.name == '银行卡' && data.bank)
}
if(item.name!='银行卡'&&item.name!='身份证'){
if (item.name != '银行卡' && item.name != '身份证') {
return true
}else if(item.name=='银行卡'&&data.bank){
} else if (item.name == '银行卡' && data.bank) {
return true
}else if(item.name=='身份证'&&data.idcard){
} else if (item.name == '身份证' && data.idcard) {
return true
}else{
} else {
return false
}
}
@ -422,7 +428,7 @@ const fetchUserData = async () => {
fetchUserInfo(),
fetchUserConfig()
])
// 处理用户信息结果
if (userResult.status === 'fulfilled') {
console.log('用户信息获取成功')
@ -432,16 +438,16 @@ const fetchUserData = async () => {
// 处理用户配置结果
if (configResult.status === 'fulfilled') {
console.log('用户配置获取成功',configResult)
console.log('用户配置获取成功', configResult)
} else {
console.error('获取用户配置失败:', configResult.reason)
}
if(configResult.value.config['client.uniapp.bank']||false){
data.bank=true
if (configResult.value.config['client.uniapp.bank'] || false) {
data.bank = true
}
if(configResult.value.config['client.uniapp.idcard']||false){
data.idcard=true
if (configResult.value.config['client.uniapp.idcard'] || false) {
data.idcard = true
}
// 刷新页面数据
setUserData()

View File

@ -0,0 +1,812 @@
<template>
<view class="honor-of-kings">
<nav-bar title="王者主页" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
@right-click="onRightClick">
</nav-bar>
<view>
<view class="painter-container" @click="handlePreview">
<l-painter isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:750rpx; padding: 24rpx; `">
<l-painter-view :css="`width: 100%; position: relative;`">
<!-- 直接使用主背景图撑开父容器移除不必要的 opacity: 0 占位图避免在大屏渲染时产生黑块 -->
<l-painter-image :src="`/static/image/other/game/wangzhe/style-${honorData.type}.jpg`"
css="width: 100%; display: block;"></l-painter-image>
<!-- 头像 (纯百分比绝对定位完美适配所有大屏分辨率) -->
<l-painter-image :src="honorData.avatar"
css="position: absolute; left: 15.6%; top: 22.5%; width: 8.5%; height: 20%; border-radius: 200rpx; object-fit: cover; display: block;"></l-painter-image>
<!-- 头像框 (压在头像上方) -->
<l-painter-image :src="`/static/image/other/game/wangzhe/avatar-frame-${honorData.type}.png`"
css="position: absolute; left: 0; top: 0; width: 24.3%; height: 9.15%;"></l-painter-image>
<!-- 性别图标 -->
<l-painter-image :src="`/static/image/other/game/wangzhe/${honorData.gender}.png`"
:css="`position: absolute; left: ${honorData.type == 3 ? '29%' : '27%'}; top: 25.5%; width: 1.57%; height: 3.44%;`"></l-painter-image>
<!-- 昵称渐变图片 -->
<l-painter-image v-if="nicknameImage" :src="nicknameImage"
:css="`position: absolute; left: ${honorData.type == 3 ? '30.7%' : '28.7%'}; top: 24.5%; width: ${honorData.nickname.length * 1.99}%;`"></l-painter-image>
<!-- 地区 -->
<l-painter-text :text="honorData.receivedFlowers"
css="position: absolute; left: 47.8%; top: 38.5%; font-size: 9rpx; color: #DAF2FF;transform: translateX(-50%);"></l-painter-text>
<!-- 收到花束 -->
<l-painter-text :text="honorData.receivedFlowers"
css="position: absolute; left: 47.8%; top: 38.5%; font-size: 9rpx; color: #DAF2FF;transform: translateX(-50%);font-family: WangZheFont2;"></l-painter-text>
<!-- 热度数 -->
<l-painter-text :text="honorData.popularityCount"
css="position: absolute; left: 51.5%; top: 38.5%; font-size: 9rpx; color: #DAF2FF;transform: translateX(-50%);font-family: WangZheFont2;"></l-painter-text>
<!-- 点赞数 -->
<l-painter-text :text="honorData.likeCount"
css="position: absolute; left: 55.2%; top: 38.5%; font-size: 9rpx; color: #DAF2FF;transform: translateX(-50%);font-family: WangZheFont2;"></l-painter-text>
<!-- 荣誉一 -->
<l-painter-text :text="honorData.honor1"
css="position: absolute; left: 33%; top: 42.67%; font-size: 9rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 荣誉二 -->
<l-painter-text :text="honorData.honor2"
css="position: absolute; left: 62.5%; top: 52.2%; font-size: 8rpx; color: #71B1D3;transform: scale(0.85),translateX(-50%);"></l-painter-text>
<!-- 巅峰万强 -->
<l-painter-text v-if="honorData.type == 4" :text="honorData.peakStrong"
css="position: absolute; left: 34.3%; top: 56.5%; font-size: 8rpx; color: #E9F5FB;transform: translateX(-50%);"></l-painter-text>
<!-- 对战场次 -->
<l-painter-text :text="honorData.matchCount"
css="position: absolute; left: 18.4%; top: 71%; font-size: 12rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 对战被赞 -->
<l-painter-text :text="honorData.matchLikeCount"
css="position: absolute; left: 26.6%; top: 71%; font-size: 12rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 图鉴等级 -->
<l-painter-text :text="honorData.pokedexLevel"
css="position: absolute; left: 42.6%; top: 70%; font-size:9rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 皮肤数 -->
<l-painter-text :text="honorData.skinCount"
css="position: absolute; left: 50.3%; top: 70%; font-size:9rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 游戏天数 -->
<l-painter-text v-if="honorData.type == 1 || honorData.type == 2" :text="honorData.gameDays"
css="position: absolute; left: 26.95%; top: 82.7%; font-size:10rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 峡谷对战局数 -->
<l-painter-text v-if="honorData.type == 1 || honorData.type == 2"
:text="honorData.riftMatchCount"
css="position: absolute; left: 42.96%; top: 82.7%; font-size:10rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 大乱斗对战局数 -->
<l-painter-text v-if="honorData.type == 1 || honorData.type == 2"
:text="honorData.aramMatchCount"
css="position: absolute; left: 50.65%; top: 82.7%; font-size:10rpx; color: #71B1D3;transform: translateX(-50%);"></l-painter-text>
<!-- 亲密度 -->
<l-painter-text v-if="honorData.type == 3 || honorData.type == 4" :text="honorData.intimacy"
css="position: absolute; left: 46.4%; top: 86.8%; font-size:10rpx; color: #71B1D3;transform: translateX(-50%);font-family: WangZheFont2;"></l-painter-text>
<!-- 水印 -->
<l-painter-image v-if="$isVip()" src="/static/image/other/shuiying.png"
:css="`position: absolute; left: 2.5%; bottom: 5%; width: 145.38rpx;height:42.76rpx`"></l-painter-image>
</l-painter-view>
</l-painter>
</view>
</view>
<!-- 水印 -->
<view v-if="$isVip()">
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_wangzhe')">
<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: honorData.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="number" v-model="tempData.type" placeholder="1-4" />
</view> -->
<view class="form-item avatar-form-item">
<text class="label">头像</text>
<view class="avatar-uploader">
<view class="avatar-preview" v-if="tempData.avatar">
<image class="preview-img" :src="tempData.avatar" mode="aspectFill"></image>
<view class="delete-icon" @click="handleDeleteAvatar">
<text>×</text>
</view>
</view>
<view class="upload-btn" v-else @click="handleChooseAvatar">
<text class="plus">+</text>
</view>
</view>
</view>
<view class="form-item">
<text class="label">昵称</text>
<input class="input" type="text" v-model="tempData.nickname" />
</view>
<view class="form-item">
<text class="label">性别</text>
<view class="radio-group">
<view class="radio-item" @click="tempData.gender = 'man'">
<view class="radio-icon" :class="{ active: tempData.gender === 'man' }"></view>
<text class="radio-text" :class="{ active: tempData.gender === 'man' }"></text>
</view>
<view class="radio-item" @click="tempData.gender = 'female'">
<view class="radio-icon" :class="{ active: tempData.gender === 'female' }"></view>
<text class="radio-text" :class="{ active: tempData.gender === 'female' }"></text>
</view>
</view>
</view>
<view class="form-item">
<text class="label">荣誉一</text>
<input class="input" type="text" v-model="tempData.honor1" />
</view>
<view class="form-item">
<text class="label">荣誉二</text>
<input class="input" type="text" v-model="tempData.honor2" />
</view>
<view class="form-item">
<text class="label">巅峰万强</text>
<input class="input" type="text" v-model="tempData.peakStrong" />
</view>
<view class="form-item">
<text class="label">收到花束</text>
<input class="input" type="text" v-model="tempData.receivedFlowers" />
</view>
<view class="form-item">
<text class="label">热度</text>
<input class="input" type="text" v-model="tempData.popularityCount" />
</view>
<view class="form-item">
<text class="label">点赞数</text>
<input class="input" type="text" v-model="tempData.likeCount" />
</view>
<view class="form-item">
<text class="label">对战场次</text>
<input class="input" type="number" v-model="tempData.matchCount" />
</view>
<view class="form-item">
<text class="label">对战被赞</text>
<input class="input" type="number" v-model="tempData.matchLikeCount" />
</view>
<view class="form-item">
<text class="label">图鉴等级</text>
<input class="input" type="number" v-model="tempData.pokedexLevel" />
</view>
<view class="form-item">
<text class="label">皮肤数</text>
<input class="input" type="number" v-model="tempData.skinCount" />
</view>
<view class="form-item">
<text class="label">游戏天数</text>
<input class="input" type="number" v-model="tempData.gameDays" />
</view>
<view class="form-item">
<text class="label">峡谷对战局数</text>
<input class="input" type="number" v-model="tempData.riftMatchCount" />
</view>
<view class="form-item">
<text class="label">大乱斗局数</text>
<input class="input" type="number" v-model="tempData.aramMatchCount" />
</view>
<view class="form-item">
<text class="label">亲密度</text>
<input class="input" type="number" v-model="tempData.intimacy" />
</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 style="position: absolute; left: -9999px; top: -9999px; width: 0; height: 0; overflow: hidden;">
<canvas canvas-id="gradientTextCanvas" id="gradientTextCanvas" style="width: 300px; height: 60px;"></canvas>
</view>
<!-- 横向全屏放大预览层 -->
<view class="preview-overlay" v-if="showPreview" @click="showPreview = false">
<image class="preview-image" :src="finalPosterPath" mode="aspectFill"></image>
</view>
</view>
</template>
<script setup>
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { onLoad, onReady } from '@dcloudio/uni-app'
const rightButtonText = ref("编辑");
const instance = getCurrentInstance();
const { proxy } = getCurrentInstance();
const nicknameImage = ref('');
const showPreview = ref(false); //
const isMountedReady = ref(false);
const isFontLoaded = ref(false);
//
const honorData = reactive({
type: 1, // 1.2.3.4
avatar: '/static/image/shopping/pdd/avatars/avatars1.jpg', //
nickname: '甜喵小贝', //
gender: 'female', //
region: '重庆市两江新区', //
honor1: '国服第一小乔', // 1
honor2: '888级大师收藏家·珍耀无双', // 2
matchCount: 58965, //
matchLikeCount: 9746, //
gameDays: 3127, //
pokedexLevel: 104, //
skinCount: 444, //
riftMatchCount: 7368, //
aramMatchCount: 5193, //
receivedFlowers: 520, //
popularityCount: '6.0W', //
likeCount: 4883, //
intimacy: '25147',//
peakStrong: '5632'
})
onLoad(() => {
const cachedData = uni.getStorageSync('wangzheHonorData');
if (cachedData) {
Object.assign(honorData, cachedData);
}
//
proxy.$apiUserEvent('all', {
type: 'click',
key: 'wangzhe',
prefix: '.uni.other.',
value: "王者主页"
})
const config = uni.getStorageSync('config')
console.log("---config---", config);
let fontConfig = config.config['client.uniapp.font'];
try {
if (typeof fontConfig === 'string') {
fontConfig = JSON.parse(fontConfig);
}
} catch (e) {
console.error('字体配置解析失败', e);
}
console.log("字体地址信息", fontConfig?.wangzhe);
// Font loading logic
const fontUrl = fontConfig?.wangzhe;
const fontUrl2 = fontConfig?.wangzhe2;
let loadedCount = 0;
const totalFonts = 2;
const checkAllLoaded = () => {
loadedCount++;
if (loadedCount >= totalFonts) {
isFontLoaded.value = true;
if (isMountedReady.value) drawGradientText();
}
};
const loadSingleFont = (url, name, storageKey, onComplete) => {
if (!url) {
console.warn(`未获取到 ${name} 字体地址,回退使用系统默认字体`);
onComplete && onComplete();
return;
}
const doLoad = (path) => {
uni.loadFontFace({
family: name,
source: `url("${path}")`,
success() {
console.log(`${name} 字体加载成功`);
onComplete && onComplete();
},
fail(err) {
console.error(`${name} 字体加载失败`, err);
onComplete && onComplete();
}
});
};
// #ifdef H5
// H5 URL
doLoad(url);
// #endif
// #ifndef H5
// H5 使
const savedPath = uni.getStorageSync(storageKey);
if (savedPath) {
doLoad(savedPath);
} else {
uni.downloadFile({
url: url,
success: (res) => {
if (res.statusCode === 200) {
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
const saved = saveRes.savedFilePath;
uni.setStorageSync(storageKey, saved);
console.log(`${name} 字体保存路径`, saved);
doLoad(saved);
},
fail: (err) => {
console.error(`保存 ${name} 文件失败`, err);
// Fallback:
doLoad(res.tempFilePath);
}
});
} else {
onComplete && onComplete();
}
},
fail: (err) => {
console.error(`下载 ${name} 字体失败`, err);
onComplete && onComplete();
}
});
}
// #endif
};
loadSingleFont(fontUrl, 'WangZheFont', 'wangzhe_font_path', checkAllLoaded);
loadSingleFont(fontUrl2, 'WangZheFont2', 'wangzhe_font2_path', checkAllLoaded);
})
const finalPosterPath = ref('');
const editPopup = ref(null);
const tempData = reactive({});
const newAvatars = ref([]);
function handleChangeTheme(typeIndex) {
honorData.type = typeIndex;
uni.setStorageSync('wangzheHonorData', honorData);
}
function onRightClick() {
Object.assign(tempData, honorData);
newAvatars.value = [];
editPopup.value.open();
}
const handleChooseAvatar = () => {
uni.chooseImage({
count: 1,
crop: {
quality: 100,
width: 400,
height: 400
},
success: (res) => {
const tempPath = res.tempFilePaths[0];
// #ifndef H5
uni.saveFile({
tempFilePath: tempPath,
success: (saveRes) => {
tempData.avatar = saveRes.savedFilePath;
newAvatars.value.push(saveRes.savedFilePath);
}
});
// #endif
// #ifdef H5
tempData.avatar = tempPath;
// #endif
}
});
};
const handleDeleteAvatar = () => {
tempData.avatar = '';
};
function closeEditPopup() {
// #ifndef H5
newAvatars.value.forEach(path => {
uni.removeSavedFile({ filePath: path });
});
// #endif
editPopup.value.close();
}
function confirmEdit() {
const isNicknameChanged = honorData.nickname !== tempData.nickname;
// #ifndef H5
//
newAvatars.value.forEach(path => {
if (path !== tempData.avatar) {
uni.removeSavedFile({ filePath: path });
}
});
//
if (honorData.avatar !== tempData.avatar && honorData.avatar && !honorData.avatar.startsWith('/static/')) {
uni.removeSavedFile({ filePath: honorData.avatar });
}
// #endif
Object.assign(honorData, tempData);
uni.setStorageSync('wangzheHonorData', honorData);
editPopup.value.close();
//
if (isNicknameChanged && isFontLoaded.value) {
drawGradientText();
}
}
//
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;
if (isFontLoaded.value) {
drawGradientText();
}
})
// Canvas
const drawGradientText = () => {
//
const fontSize = 40;
const textLen = honorData.nickname.length;
//
const canvasWidth = fontSize * textLen;
const ctx = uni.createCanvasContext('gradientTextCanvas', instance.proxy);
ctx.clearRect(0, 0, 300, 60);
// 使 WangZheFont
ctx.font = `${fontSize}px "WangZheFont", sans-serif`;
// 线
const grd = ctx.createLinearGradient(0, 0, canvasWidth, 0);
grd.addColorStop(0, '#F9D577');
grd.addColorStop(1, '#FFF5C4');
ctx.setFillStyle(grd);
ctx.setTextBaseline('top');
//
ctx.fillText(honorData.nickname, 0, 0);
ctx.draw(false, () => {
//
setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: 'gradientTextCanvas',
x: 0,
y: 0,
width: canvasWidth,
height: fontSize + 10,
destWidth: canvasWidth * 2, // 2
destHeight: (fontSize + 10) * 2,
success: (res) => {
nicknameImage.value = res.tempFilePath;
}
}, instance.proxy)
}, 200)
})
}
</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 {
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;
}
}
}
}
}
.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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB