728 lines
21 KiB
Vue
728 lines
21 KiB
Vue
<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: 822px; transform: scale(${posterScaleRatio}); transform-origin: left top; position: absolute; left: 0; top: 0;`">
|
||
<l-painter v-if="bgImage" isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:822px;`">
|
||
<l-painter-view :css="`width: 822px; position: relative;`">
|
||
<!-- 直接使用主背景图撑开父容器,移除不必要的 opacity: 0 占位图,避免在大屏渲染时产生黑块 -->
|
||
<l-painter-image :src="bgImage" css="width: 822px; display: block;"></l-painter-image>
|
||
|
||
<!-- 人物图片 -->
|
||
<l-painter-image :src="wuweiData.imgUrl" :css="characterStyle"></l-painter-image>
|
||
<!-- 击败 -->
|
||
<l-painter-text :text="wuweiData.killCount" :css="killCountStyle"></l-painter-text>
|
||
<template v-if="wuweiData.type == 1">
|
||
<!-- 精准射击 -->
|
||
<l-painter-text :text="wuweiData.shooting"
|
||
:css="`${style1TextCommonStyle}; left:151px;`"></l-painter-text>
|
||
<!-- 输出伤害 -->
|
||
<l-painter-text :text="wuweiData.output"
|
||
:css="`${style1TextCommonStyle}; left:221px;`"></l-painter-text>
|
||
<!-- 获得资金 -->
|
||
<l-painter-text :text="wuweiData.harvest"
|
||
:css="`${style1TextCommonStyle}; left:292px;`"></l-painter-text>
|
||
<!-- 三连击败 -->
|
||
<l-painter-text :text="wuweiData.threeKill"
|
||
:css="`${style1TextCommonStyle}; left:362px;`"></l-painter-text>
|
||
</template>
|
||
<template v-if="wuweiData.type == 2">
|
||
<!-- 头像 -->
|
||
<l-painter-image :src="wuweiData.avatar"
|
||
css="position:absolute;left:65.5px;bottom:68.5px;width:42px;height:42px"></l-painter-image>
|
||
<!-- 昵称 -->
|
||
<l-painter-text :text="truncatedNickname"
|
||
css="position: absolute; left: 119px; bottom: 82px; font-size: 13px; font-family: Arial, sans-serif; color: #FFFFFF; width: 117px;"></l-painter-text>
|
||
<!-- 阵败 -->
|
||
<l-painter-text :text="wuweiData.defeatsCount"
|
||
css="position: absolute; left: 152.5px; bottom: 122px; font-size: 18px;font-weight: 700;color: #FFFFFF;line-height: 18px;transform: translateX(-50%)"></l-painter-text>
|
||
<!-- 助攻 -->
|
||
<l-painter-text :text="wuweiData.assistCount"
|
||
css="position: absolute; left: 215px; bottom: 122px; font-size: 18px;font-weight: 700;color: #FFFFFF;line-height: 18px;transform: translateX(-50%)"></l-painter-text>
|
||
<!-- 战斗分 -->
|
||
<l-painter-text :text="`平均战斗评分:${wuweiData.battlePoints}`"
|
||
css="position: absolute; left: 150px; bottom: 153px; font-size:10px;color: #FFFFFF;line-height: 10px;transform: translateX(-50%)"></l-painter-text>
|
||
</template>
|
||
<!-- 水印 -->
|
||
<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_game_wuweiqiyue')">
|
||
<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: wuweiData.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 avatar-form-item">
|
||
<text class="label">人物图片</text>
|
||
<view class=" avatar-uploader img-box" @click="handleChooseImgUrl">
|
||
<view class="avatar-preview" v-if="tempData.imgUrl">
|
||
<image class="preview-img" :src="tempData.imgUrl" mode="widthFix"></image>
|
||
<view class="delete-icon" @click.stop="handleDeleteImgUrl">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<view class="upload-btn" v-else>
|
||
<text class="plus">+</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item avatar-form-item" v-if="tempData.type == 2">
|
||
<text class="label">头像</text>
|
||
<view class="avatar-uploader" @click="handleChooseAvatar">
|
||
<view class="avatar-preview" v-if="tempData.avatar">
|
||
<image class="preview-img" :src="tempData.avatar" mode="aspectFill"></image>
|
||
<view class="delete-icon" @click.stop="handleDeleteAvatar">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<view class="upload-btn" v-else @click="handleChooseAvatar">
|
||
<text class="plus">+</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 2">
|
||
<text class="label">昵称</text>
|
||
<input class="input" type="text" v-model="tempData.nickname" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">击败</text>
|
||
<input class="input" type="number" v-model="tempData.killCount" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 1">
|
||
<text class="label">精准射击</text>
|
||
<input class="input" type="number" v-model="tempData.shooting" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 1">
|
||
<text class="label">输出伤害</text>
|
||
<input class="input" type="number" v-model="tempData.output" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 1">
|
||
<text class="label">获得资金</text>
|
||
<input class="input" type="number" v-model="tempData.harvest" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 1">
|
||
<text class="label">三连击败</text>
|
||
<input class="input" type="number" v-model="tempData.threeKill" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 2">
|
||
<text class="label">阵败</text>
|
||
<input class="input" type="number" v-model="tempData.defeatsCount" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 2">
|
||
<text class="label">助攻</text>
|
||
<input class="input" type="number" v-model="tempData.assistCount" />
|
||
</view>
|
||
<view class="form-item" v-if="tempData.type == 2">
|
||
<text class="label">战斗评分</text>
|
||
<input class="input" type="number" v-model="tempData.battlePoints" />
|
||
</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="aspectFill"></image>
|
||
</view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, computed, watch, onMounted, getCurrentInstance } from 'vue'
|
||
import { onLoad, onReady, onUnload } from '@dcloudio/uni-app'
|
||
import { imgLocal } from '@/utils/common.js';
|
||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||
const instance = getCurrentInstance();
|
||
const { proxy } = getCurrentInstance();
|
||
|
||
// 页面表单数据字段
|
||
const wuweiData = reactive({
|
||
type: 1, // 样式类型 1.2
|
||
avatar: '/static/image/shopping/pdd/avatars/avatars1.jpg', // 头像
|
||
imgUrl: '/static/image/other/game/heping/default.png', // 人物图片
|
||
nickname: '甜喵小贝', // 昵称
|
||
killCount: 24,
|
||
defeatsCount: 2,
|
||
assistCount: 12,
|
||
battlePoints: 3854,
|
||
shooting: 7,
|
||
output: 4109,
|
||
harvest: 41750,
|
||
threeKill: 5
|
||
})
|
||
|
||
const characterImgHeight = ref(350); // 初始高度兜底
|
||
|
||
const characterStyle = computed(() => {
|
||
if (wuweiData.type == 1) {
|
||
return `position: absolute; right: 77px; bottom: 0; width: 300px; height: 350px;`;
|
||
} else {
|
||
return `position: absolute; right: 210px; bottom: 0; width: 300px; height: 350px;`;
|
||
}
|
||
});
|
||
|
||
const killCountStyle = computed(() => {
|
||
if (wuweiData.type == 1) {
|
||
return `position: absolute; left: 81px; bottom:79px; font-size: 16px;color: #FFFFFF;line-height: 16px;transform: translateX(-50%)`;
|
||
} else {
|
||
return `position: absolute; left: 90px; bottom: 122px; font-size: 18px;font-weight: 700;color: #FFFFFF;line-height: 18px;transform: translateX(-50%)`;
|
||
}
|
||
});
|
||
|
||
const style1TextCommonStyle = `position: absolute; bottom:79px; font-size: 16px;color: #FFFFFF;line-height: 16px;transform: translateX(-50%)`;
|
||
|
||
|
||
// 手动处理中英文混合宽度的截断,避免依赖 line-clamp 和底层画布可能引发的居中对齐问题
|
||
const truncatedNickname = computed(() => {
|
||
let name = wuweiData.nickname || '';
|
||
let width = 0;
|
||
let result = '';
|
||
let max = 117 - 15; // 保留大约 15px 的空间给省略号 "..."
|
||
for (let i = 0; i < name.length; i++) {
|
||
let charCode = name.charCodeAt(i);
|
||
if (charCode >= 0 && charCode <= 128) {
|
||
width += 7.5; // 英文及数字近似宽度
|
||
} else {
|
||
width += 13; // 中文字符宽度(font-size: 13px)
|
||
}
|
||
if (width > max) {
|
||
return result + '...';
|
||
}
|
||
result += name[i];
|
||
}
|
||
return name;
|
||
});
|
||
|
||
// 监听人物图片变化,动态获取其原始宽高并计算比例高度,解决画布必须写明尺寸才能渲染的问题
|
||
watch(() => wuweiData.imgUrl, (newUrl) => {
|
||
if (!newUrl) return;
|
||
uni.getImageInfo({
|
||
src: newUrl,
|
||
success: (res) => {
|
||
// 固定宽度 300px,高度等比例计算
|
||
const calcHeight = (300 / res.width) * res.height;
|
||
characterImgHeight.value = Math.round(calcHeight);
|
||
},
|
||
fail: () => {
|
||
characterImgHeight.value = 350; // 获取失败提供兜底高度
|
||
}
|
||
});
|
||
}, { immediate: true });
|
||
|
||
const bgImage = ref('')
|
||
|
||
// 获取系统宽度计算海报缩放比例,代替容易失效的 css calc(),确保全端兼容防截断
|
||
const sysInfo = uni.getSystemInfoSync();
|
||
const windowWidth = sysInfo.windowWidth || 375;
|
||
// 扣除左右共 16px 的 padding,再基于实际画板宽度 822 计算精确缩放比,防止右侧被截断
|
||
const posterScaleRatio = (windowWidth - 16) / 822;
|
||
const posterContainerHeight = 374 * posterScaleRatio;
|
||
|
||
onLoad(async () => {
|
||
const cachedData = uni.getStorageSync('wuweiData');
|
||
if (cachedData) {
|
||
Object.assign(wuweiData, cachedData);
|
||
// 兼容处理:强制把历史缓存里的 .jpg 替换为最新的 .png,防止 404
|
||
if (wuweiData.imgUrl === '/static/image/other/game/heping/default.jpg') {
|
||
wuweiData.imgUrl = '/static/image/other/game/heping/default.png';
|
||
uni.setStorageSync('wuweiData', wuweiData);
|
||
}
|
||
}
|
||
try {
|
||
bgImage.value = await imgLocal.getLocalImage(`other/game/wuwei/bg-${wuweiData.type}.jpg`);
|
||
} catch (e) {
|
||
console.error('获取背景图失败:', e);
|
||
uni.showToast({ title: '背景图加载失败', icon: 'none' });
|
||
}
|
||
|
||
uni.$on('editFormPhoto', (info) => {
|
||
if (currentEditImgField.value) {
|
||
tempData[currentEditImgField.value] = info;
|
||
}
|
||
// #ifndef H5
|
||
if (info && !info.startsWith('/static/')) {
|
||
newAvatars.value.push(info);
|
||
}
|
||
// #endif
|
||
});
|
||
|
||
// 进入页面埋点
|
||
if (proxy && proxy.$apiUserEvent) {
|
||
proxy.$apiUserEvent('all', {
|
||
type: 'click',
|
||
key: 'wuwei',
|
||
prefix: '.uni.other.',
|
||
value: "无畏契约"
|
||
});
|
||
}
|
||
})
|
||
|
||
onUnload(() => {
|
||
uni.$off('editFormPhoto');
|
||
})
|
||
|
||
const rightButtonText = ref("编辑");
|
||
const finalPosterPath = ref('');
|
||
const showPreview = ref(false); // 控制全屏预览
|
||
|
||
const editPopup = ref(null);
|
||
const tempData = reactive({});
|
||
const newAvatars = ref([]);
|
||
const currentEditImgField = ref('');
|
||
|
||
function onRightClick() {
|
||
Object.assign(tempData, JSON.parse(JSON.stringify(wuweiData)));
|
||
newAvatars.value = [];
|
||
editPopup.value.open();
|
||
}
|
||
|
||
const handleChooseAvatar = () => {
|
||
currentEditImgField.value = 'avatar';
|
||
uni.chooseImage({
|
||
count: 1,
|
||
success: (res) => {
|
||
uni.navigateTo({
|
||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=200&height=200`
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
const handleChooseImgUrl = () => {
|
||
currentEditImgField.value = 'imgUrl';
|
||
uni.chooseImage({
|
||
count: 1,
|
||
success: (res) => {
|
||
if (res.tempFilePaths[0]) {
|
||
// 跳转到 qf-image 组件进行 300x350 尺寸(传参150x175)的裁剪,并通过 isMatting=1 触发后续抠图
|
||
uni.navigateTo({
|
||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=150&height=175&isMatting=1`
|
||
});
|
||
}
|
||
|
||
}
|
||
});
|
||
};
|
||
|
||
const handleDeleteAvatar = () => {
|
||
tempData.avatar = '';
|
||
};
|
||
|
||
const handleDeleteImgUrl = () => {
|
||
tempData.imgUrl = '';
|
||
};
|
||
|
||
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 && path !== tempData.imgUrl) {
|
||
uni.removeSavedFile({ filePath: path });
|
||
}
|
||
});
|
||
// 删除被替换掉的原本地头像
|
||
if (wuweiData.avatar !== tempData.avatar && wuweiData.avatar && !wuweiData.avatar.startsWith('/static/')) {
|
||
uni.removeSavedFile({ filePath: wuweiData.avatar });
|
||
}
|
||
if (wuweiData.imgUrl !== tempData.imgUrl && wuweiData.imgUrl && !wuweiData.imgUrl.startsWith('/static/')) {
|
||
uni.removeSavedFile({ filePath: wuweiData.imgUrl });
|
||
}
|
||
// #endif
|
||
|
||
Object.assign(wuweiData, tempData);
|
||
uni.setStorageSync('wuweiData', wuweiData);
|
||
editPopup.value.close();
|
||
|
||
// 数据修改后,重新渲染海报
|
||
finalPosterPath.value = '';
|
||
let tempBg = bgImage.value;
|
||
bgImage.value = ''; // 强制卸载旧画板,确保能重新渲染和生成新海报
|
||
setTimeout(() => {
|
||
bgImage.value = tempBg;
|
||
}, 50);
|
||
}
|
||
|
||
async function handleChangeTheme(typeIndex) {
|
||
// 切换主题时,先清空旧海报,触发界面“加载中”提示
|
||
finalPosterPath.value = '';
|
||
bgImage.value = ''; // 强制卸载旧画板,确保能重新渲染和生成新海报
|
||
wuweiData.type = typeIndex;
|
||
uni.setStorageSync('wuweiData', wuweiData);
|
||
try {
|
||
bgImage.value = await imgLocal.getLocalImage(`other/game/wuwei/bg-${typeIndex}.jpg`);
|
||
} catch (e) {
|
||
console.error('切换主题加载背景图失败:', e);
|
||
uni.showToast({ title: '背景加载失败', icon: 'none' });
|
||
}
|
||
}
|
||
|
||
// 点击画布触发横向预览
|
||
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' })
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 将本地图片路径通过 Canvas 转换为 File 对象
|
||
* @param {string} localPath - 本地图片路径(如从 uni.chooseImage 获取的 tempFilePath)
|
||
* @param {Object} options - 可选参数
|
||
* @param {string} options.format - 输出格式 'image/png' 或 'image/jpeg',默认 'image/png'
|
||
* @param {number} options.quality - 图片质量(仅 jpeg 有效),0~1,默认 0.92
|
||
* @param {number} options.maxWidth - 最大宽度(等比缩放),不填则使用原图尺寸
|
||
* @param {number} options.maxHeight - 最大高度(等比缩放),不填则使用原图尺寸
|
||
* @returns {Promise<File>} 返回一个 Promise,resolve 为 File 对象
|
||
*/
|
||
function convertLocalImageToFile(localPath) {
|
||
return new Promise((resolve, reject) => {
|
||
// 1. 读取本地图片为 Base64(避免 Image 对象直接加载本地路径的兼容问题)
|
||
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
|
||
entry.file((file) => {
|
||
const reader = new plus.io.FileReader();
|
||
reader.onload = (e) => {
|
||
const base64Data = e.target.result; // 格式如 data:image/jpeg;base64,/9j/...
|
||
resolve(e.target.result)
|
||
};
|
||
reader.onerror = (err) => reject(err);
|
||
reader.readAsDataURL(file); // 读取为 DataURL
|
||
}, reject);
|
||
}, reject);
|
||
|
||
});
|
||
}
|
||
</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-flex;
|
||
width: 100%;
|
||
justify-content: center;
|
||
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 {
|
||
max-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;
|
||
}
|
||
}
|
||
}
|
||
|
||
.img-box {
|
||
width: 200rpx !important;
|
||
|
||
.avatar-preview {
|
||
width: 200rpx !important;
|
||
height: auto !important;
|
||
}
|
||
|
||
.preview-img {
|
||
width: 100%;
|
||
border-radius: 0 !important;
|
||
}
|
||
}
|
||
|
||
.input {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
background-color: #F7F7F7;
|
||
border-radius: 12rpx;
|
||
height: 70rpx;
|
||
line-height: 70rpx;
|
||
padding: 0 20rpx;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
.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>
|