style(uiux): 严格对齐UIUX设计约束规范,全面替换系统Emoji为电竞矢量SVG图标并修复H5居中自适应
这个提交包含在:
@@ -26,7 +26,7 @@ view, text, image, input, button {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 触控反馈标准类 (满足 UI/UX Pro Max 规范) */
|
||||
/* 触控反馈标准类 (严格满足 UI/UX 规范:100ms 内微缩放与透明度反馈,无布局位移) */
|
||||
.btn-active:active, .card-active:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.9;
|
||||
@@ -40,4 +40,46 @@ view, text, image, input, button {
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
/* H5 PC 模式响应式移动端容器居中(如在浏览器访问 http://localhost:5174/ 时) */
|
||||
/* #ifdef H5 */
|
||||
html, body {
|
||||
background-color: #050811 !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
uni-app {
|
||||
max-width: 450px !important;
|
||||
margin: 0 auto !important;
|
||||
min-height: 100vh !important;
|
||||
box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.9) !important;
|
||||
position: relative !important;
|
||||
background-color: #0A0F1D !important;
|
||||
}
|
||||
|
||||
uni-page-head {
|
||||
max-width: 450px !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
uni-tabbar, .uni-tabbar {
|
||||
position: fixed !important;
|
||||
bottom: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
margin: 0 auto !important;
|
||||
max-width: 450px !important;
|
||||
width: 100% !important;
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
|
||||
uni-tabbar .uni-tabbar__bd {
|
||||
background-color: #151D30 !important;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
189
pwuniapp/common/icons.js
普通文件
189
pwuniapp/common/icons.js
普通文件
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* 电竞暗夜流光矢量 SVG 图标库 (Cyber-Esports SVG Icons)
|
||||
* 严格遵照 UI/UX 规范:杜绝系统 Emoji,全矢量渲染,支持无损缩放与跨端显示
|
||||
*/
|
||||
|
||||
function svgToUri(svg) {
|
||||
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg.trim());
|
||||
}
|
||||
|
||||
export const ICONS = {
|
||||
// 基础与通用
|
||||
search: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
// 游戏分类
|
||||
gameAll: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#818CF8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="6" width="20" height="12" rx="4"></rect>
|
||||
<line x1="6" y1="12" x2="10" y2="12"></line>
|
||||
<line x1="8" y1="10" x2="8" y2="14"></line>
|
||||
<circle cx="15" cy="11" r="1" fill="#818CF8"></circle>
|
||||
<circle cx="18" cy="13" r="1" fill="#818CF8"></circle>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
gameCrown: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M2 4l3 12h14l3-12-6 7-4-7-4 7-6-7z"></path>
|
||||
<circle cx="12" cy="19" r="1" fill="#F59E0B"></circle>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
gameCrosshair: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#10B981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="9"></circle>
|
||||
<line x1="12" y1="3" x2="12" y2="7"></line>
|
||||
<line x1="12" y1="17" x2="12" y2="21"></line>
|
||||
<line x1="3" y1="12" x2="7" y2="12"></line>
|
||||
<line x1="17" y1="12" x2="21" y2="12"></line>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
gameSwords: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#60A5FA" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="14.5 17.5 3 6 3 3 6 3 17.5 14.5"></polyline>
|
||||
<line x1="13" y1="19" x2="19" y2="13"></line>
|
||||
<line x1="16" y1="16" x2="20" y2="20"></line>
|
||||
<line x1="19" y1="21" x2="21" y2="19"></line>
|
||||
<polyline points="14.5 6.5 18 3 21 3 21 6 17.5 9.5"></polyline>
|
||||
<line x1="5" y1="14" x2="10" y2="19"></line>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
gameTarget: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#EC4899" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<circle cx="12" cy="12" r="6"></circle>
|
||||
<circle cx="12" cy="12" r="2" fill="#EC4899"></circle>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
gameBlade: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#A78BFA" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M4 20l4-4m0 0l12-12a2 2 0 0 0-2.83-2.83L5.17 13.17M8 16l-4 4"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
gameTrophy: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M6 9H4a2 2 0 0 1-2-2V5h4m12 4h2a2 2 0 0 0 2-2V5h-4M6 5h12v4a6 6 0 0 1-12 0V5zm3 10v4h6v-4m-7 4h8"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
// 金刚区与功能
|
||||
teamUp: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#8B5CF6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="9" cy="7" r="4"></circle>
|
||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
|
||||
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
ticket: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#10B981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 7v2a3 3 0 0 0 0 6v2a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-2a3 3 0 0 0 0-6V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z"></path>
|
||||
<line x1="9" y1="6" x2="9" y2="18" stroke-dasharray="2 2"></line>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
orderList: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#6366F1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||
<polyline points="14 2 14 8 20 8"></polyline>
|
||||
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||
<polyline points="10 9 9 9 8 9"></polyline>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
expertBadge: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
// 动作与状态
|
||||
bolt: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
clock: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<polyline points="12 6 12 12 16 14"></polyline>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
mic: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#818CF8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
|
||||
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
|
||||
<line x1="12" y1="19" x2="12" y2="23"></line>
|
||||
<line x1="8" y1="23" x2="16" y2="23"></line>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
chat: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#60A5FA" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
headphones: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#818CF8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 18v-6a9 9 0 0 1 18 0v6"></path>
|
||||
<path d="M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
shield: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#10B981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
bell: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
settings: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
share: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#8B5CF6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="5" r="3"></circle>
|
||||
<circle cx="6" cy="12" r="3"></circle>
|
||||
<circle cx="18" cy="19" r="3"></circle>
|
||||
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line>
|
||||
<line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
play: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#818CF8" stroke="none">
|
||||
<polygon points="6 4 20 12 6 20 6 4"></polygon>
|
||||
</svg>
|
||||
`),
|
||||
|
||||
pause: svgToUri(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#818CF8" stroke="none">
|
||||
<rect x="6" y="4" width="4" height="16"></rect>
|
||||
<rect x="14" y="4" width="4" height="16"></rect>
|
||||
</svg>
|
||||
`)
|
||||
};
|
||||
@@ -1,11 +1,13 @@
|
||||
import { ICONS } from './icons.js';
|
||||
|
||||
export const GAMES_LIST = [
|
||||
{ id: 'all', name: '全部', icon: '🎮', hot: true },
|
||||
{ id: 'wzry', name: '王者荣耀', icon: '👑', hot: true },
|
||||
{ id: 'hpjy', name: '和平精英', icon: '🎯', hot: true },
|
||||
{ id: 'lol', name: '英雄联盟', icon: '⚔️', hot: true },
|
||||
{ id: 'val', name: '无畏契约', icon: '🔫', hot: true },
|
||||
{ id: 'yjjw', name: '永劫无间', icon: '🗡️', hot: false },
|
||||
{ id: 'pubg', name: '绝地求生', icon: '🏆', hot: false },
|
||||
{ id: 'all', name: '全部', icon: ICONS.gameAll, hot: true },
|
||||
{ id: 'wzry', name: '王者荣耀', icon: ICONS.gameCrown, hot: true },
|
||||
{ id: 'hpjy', name: '和平精英', icon: ICONS.gameCrosshair, hot: true },
|
||||
{ id: 'lol', name: '英雄联盟', icon: ICONS.gameSwords, hot: true },
|
||||
{ id: 'val', name: '无畏契约', icon: ICONS.gameTarget, hot: true },
|
||||
{ id: 'yjjw', name: '永劫无间', icon: ICONS.gameBlade, hot: false },
|
||||
{ id: 'pubg', name: '绝地求生', icon: ICONS.gameTrophy, hot: false },
|
||||
];
|
||||
|
||||
export const BANNERS = [
|
||||
@@ -18,7 +20,7 @@ export const EXPERTS_LIST = [
|
||||
{
|
||||
id: 'exp_101',
|
||||
nickname: '月色浅浅',
|
||||
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200&h=200&fit=crop&crop=faces',
|
||||
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=300&h=300&fit=crop&crop=faces',
|
||||
coverImage: 'https://images.unsplash.com/photo-1542751371-adc38448a05e?w=800&h=400&fit=crop',
|
||||
gender: 'female',
|
||||
age: 21,
|
||||
@@ -47,7 +49,7 @@ export const EXPERTS_LIST = [
|
||||
{
|
||||
id: 'exp_102',
|
||||
nickname: '夜鹰狙神',
|
||||
avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop&crop=faces',
|
||||
avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop&crop=faces',
|
||||
coverImage: 'https://images.unsplash.com/photo-1511512578047-dfb367046420?w=800&h=400&fit=crop',
|
||||
gender: 'male',
|
||||
age: 23,
|
||||
@@ -75,7 +77,7 @@ export const EXPERTS_LIST = [
|
||||
{
|
||||
id: 'exp_103',
|
||||
nickname: '软软喵',
|
||||
avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop&crop=faces',
|
||||
avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=300&h=300&fit=crop&crop=faces',
|
||||
coverImage: 'https://images.unsplash.com/photo-1538481199705-c710c4e965fc?w=800&h=400&fit=crop',
|
||||
gender: 'female',
|
||||
age: 20,
|
||||
@@ -97,7 +99,7 @@ export const EXPERTS_LIST = [
|
||||
{
|
||||
id: 'exp_104',
|
||||
nickname: '瞬移者雷克',
|
||||
avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=200&h=200&fit=crop&crop=faces',
|
||||
avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&h=300&fit=crop&crop=faces',
|
||||
coverImage: 'https://images.unsplash.com/photo-1550745165-9bc0b252726f?w=800&h=400&fit=crop',
|
||||
gender: 'male',
|
||||
age: 22,
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<!-- 底部固定操作栏 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="ticket-link btn-active" @click="goToMyTicket">
|
||||
<text class="ticket-icon">🎟️</text>
|
||||
<image class="ticket-svg" :src="ICONS.ticket" mode="aspectFit" />
|
||||
<text class="ticket-text">我的门票</text>
|
||||
</view>
|
||||
<button class="btn-join btn-active" @click="handleJoin">
|
||||
@@ -107,6 +107,7 @@
|
||||
import { ref } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ACTIVITIES_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const activity = ref(ACTIVITIES_LIST[0]);
|
||||
|
||||
@@ -441,6 +442,8 @@ const handleJoin = () => {
|
||||
padding: 0 32rpx;
|
||||
gap: 24rpx;
|
||||
z-index: 100;
|
||||
max-width: 450px;
|
||||
margin: 0 auto;
|
||||
|
||||
.ticket-link {
|
||||
display: flex;
|
||||
@@ -449,12 +452,14 @@ const handleJoin = () => {
|
||||
justify-content: center;
|
||||
width: 120rpx;
|
||||
|
||||
.ticket-icon {
|
||||
font-size: 34rpx;
|
||||
.ticket-svg {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
.ticket-text {
|
||||
font-size: 20rpx;
|
||||
color: #94A3B8;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="activity-container">
|
||||
<!-- 顶部模式切换选项卡 -->
|
||||
<!-- 顶部模式切换选项卡 (矢量SVG模式图标) -->
|
||||
<view class="tab-header">
|
||||
<view
|
||||
class="tab-item btn-active"
|
||||
@@ -15,7 +15,8 @@
|
||||
:class="{ active: currentTab === 'AA' }"
|
||||
@click="switchTab('AA')"
|
||||
>
|
||||
<text class="tab-text">⚡ AA制车队</text>
|
||||
<image class="tab-svg" :src="ICONS.bolt" mode="aspectFit" />
|
||||
<text class="tab-text">AA制车队</text>
|
||||
<view class="tab-indicator" v-if="currentTab === 'AA'"></view>
|
||||
</view>
|
||||
<view
|
||||
@@ -23,15 +24,16 @@
|
||||
:class="{ active: currentTab === 'PROJECT' }"
|
||||
@click="switchTab('PROJECT')"
|
||||
>
|
||||
<text class="tab-text">🏆 项目制赛事</text>
|
||||
<image class="tab-svg" :src="ICONS.gameTrophy" mode="aspectFit" />
|
||||
<text class="tab-text">项目制赛事</text>
|
||||
<view class="tab-indicator" v-if="currentTab === 'PROJECT'"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 顶部状态小提示 -->
|
||||
<!-- 顶部状态小提示 (矢量盾牌图标) -->
|
||||
<view class="tips-bar">
|
||||
<text class="tips-icon">💡</text>
|
||||
<text class="tips-text">AA制活动人均AA平摊,项目制为房主全额悬赏或奖池分配</text>
|
||||
<image class="tips-svg" :src="ICONS.shield" mode="aspectFit" />
|
||||
<text class="tips-text">AA制活动人均AA平摊,项目制为房主全额悬赏或赛事奖池</text>
|
||||
</view>
|
||||
|
||||
<!-- 活动列表 -->
|
||||
@@ -56,14 +58,14 @@
|
||||
<!-- 卡片标题 -->
|
||||
<view class="activity-title">{{ act.title }}</view>
|
||||
|
||||
<!-- 详细信息条 -->
|
||||
<!-- 详细信息条 (矢量时钟与麦克风) -->
|
||||
<view class="meta-row">
|
||||
<view class="meta-item">
|
||||
<text class="meta-icon">⏰</text>
|
||||
<image class="meta-svg" :src="ICONS.clock" mode="aspectFit" />
|
||||
<text class="meta-val">{{ act.startTime }}</text>
|
||||
</view>
|
||||
<view class="meta-item">
|
||||
<text class="meta-icon">🎙️</text>
|
||||
<image class="meta-svg" :src="ICONS.mic" mode="aspectFit" />
|
||||
<text class="meta-val">{{ act.location }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -114,6 +116,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ACTIVITIES_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const activities = ref(ACTIVITIES_LIST);
|
||||
const currentTab = ref('ALL');
|
||||
@@ -159,11 +162,19 @@ const createActivity = () => {
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
padding: 18rpx 0;
|
||||
position: relative;
|
||||
border-radius: 14rpx;
|
||||
|
||||
.tab-svg {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 26rpx;
|
||||
color: #94A3B8;
|
||||
@@ -202,9 +213,11 @@ const createActivity = () => {
|
||||
padding: 12rpx 20rpx;
|
||||
margin-bottom: 28rpx;
|
||||
|
||||
.tips-icon {
|
||||
font-size: 24rpx;
|
||||
.tips-svg {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tips-text {
|
||||
font-size: 22rpx;
|
||||
@@ -293,9 +306,11 @@ const createActivity = () => {
|
||||
font-size: 22rpx;
|
||||
color: #94A3B8;
|
||||
|
||||
.meta-icon {
|
||||
font-size: 22rpx;
|
||||
.meta-svg {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 8rpx;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,14 +250,14 @@ const goBack = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 0 20rpx rgba(16, 185, 129, 0.3);
|
||||
box-shadow: 0 0 24rpx rgba(16, 185, 129, 0.45);
|
||||
|
||||
.digit-text {
|
||||
font-size: 64rpx;
|
||||
font-weight: 800;
|
||||
color: #10B981;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
text-shadow: 0 0 12rpx rgba(16, 185, 129, 0.6);
|
||||
text-shadow: 0 0 16rpx rgba(16, 185, 129, 0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,6 +305,7 @@ const goBack = () => {
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #10B981;
|
||||
box-shadow: 0 0 8rpx #10B981;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
@@ -339,6 +340,7 @@ const goBack = () => {
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
border-radius: 44rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(99, 102, 241, 0.4);
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
|
||||
@@ -33,13 +33,13 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 专属打招呼试听语音 -->
|
||||
<!-- 专属打招呼试听语音 (矢量SVG播放条) -->
|
||||
<view class="voice-card btn-active" @click="toggleVoice">
|
||||
<view class="voice-icon-wrap">
|
||||
<text class="play-icon">{{ isPlayingVoice ? '⏸' : '▶' }}</text>
|
||||
<image class="play-svg" :src="isPlayingVoice ? ICONS.pause : ICONS.play" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="voice-info">
|
||||
<text class="voice-title">{{ isPlayingVoice ? '正在连麦试听语音...' : '点击试听打招呼语音' }}</text>
|
||||
<text class="voice-title">{{ isPlayingVoice ? '正在连麦试听语音...' : '点击试听打招呼原声' }}</text>
|
||||
<view class="voice-wave" v-if="isPlayingVoice">
|
||||
<view class="bar b1"></view>
|
||||
<view class="bar b2"></view>
|
||||
@@ -125,10 +125,10 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部固定栏 -->
|
||||
<!-- 底部固定栏 (限制居中与安全区) -->
|
||||
<view class="bottom-bar">
|
||||
<view class="icon-action btn-active" @click="chatOnline">
|
||||
<text class="action-icon">💬</text>
|
||||
<image class="action-svg" :src="ICONS.chat" mode="aspectFit" />
|
||||
<text class="action-text">私聊</text>
|
||||
</view>
|
||||
<view class="price-summary">
|
||||
@@ -144,6 +144,7 @@
|
||||
import { ref, computed } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { EXPERTS_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const expert = ref(EXPERTS_LIST[0]);
|
||||
const selectedServiceId = ref(EXPERTS_LIST[0].services[0] ? EXPERTS_LIST[0].services[0].id : null);
|
||||
@@ -173,7 +174,7 @@ const selectService = (srv) => {
|
||||
const toggleVoice = () => {
|
||||
isPlayingVoice.value = !isPlayingVoice.value;
|
||||
if (isPlayingVoice.value) {
|
||||
uni.showToast({ title: '正在播放大神语音打招呼', icon: 'none' });
|
||||
uni.showToast({ title: '正在播放大神打招呼原声', icon: 'none' });
|
||||
setTimeout(() => {
|
||||
isPlayingVoice.value = false;
|
||||
}, 4000);
|
||||
@@ -181,7 +182,7 @@ const toggleVoice = () => {
|
||||
};
|
||||
|
||||
const chatOnline = () => {
|
||||
uni.showToast({ title: '已开启即时连麦通道', icon: 'none' });
|
||||
uni.showToast({ title: '已开启即时加密连麦通道', icon: 'none' });
|
||||
};
|
||||
|
||||
const previewImage = (index) => {
|
||||
@@ -261,6 +262,7 @@ const goToOrder = () => {
|
||||
|
||||
&.online {
|
||||
background: #10B981;
|
||||
box-shadow: 0 0 8rpx #10B981;
|
||||
}
|
||||
|
||||
.pulse-dot {
|
||||
@@ -351,9 +353,9 @@ const goToOrder = () => {
|
||||
justify-content: center;
|
||||
margin-right: 18rpx;
|
||||
|
||||
.play-icon {
|
||||
color: #FFF;
|
||||
font-size: 24rpx;
|
||||
.play-svg {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,6 +571,8 @@ const goToOrder = () => {
|
||||
padding: 0 32rpx;
|
||||
gap: 20rpx;
|
||||
z-index: 100;
|
||||
max-width: 450px;
|
||||
margin: 0 auto;
|
||||
|
||||
.icon-action {
|
||||
display: flex;
|
||||
@@ -576,12 +580,14 @@ const goToOrder = () => {
|
||||
align-items: center;
|
||||
width: 80rpx;
|
||||
|
||||
.action-icon {
|
||||
font-size: 32rpx;
|
||||
.action-svg {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
.action-text {
|
||||
font-size: 18rpx;
|
||||
color: #94A3B8;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<view class="index-container">
|
||||
<!-- 顶部搜索栏 -->
|
||||
<!-- 顶部搜索栏 (矢量SVG搜索图标,满足无Emoji规范) -->
|
||||
<view class="header-search">
|
||||
<view class="search-box">
|
||||
<text class="search-icon">🔍</text>
|
||||
<image class="search-icon-img" :src="ICONS.search" mode="aspectFit" />
|
||||
<input class="search-input" placeholder="搜索陪玩大神、游戏昵称或项目" placeholder-class="placeholder-text" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 游戏分类滑动栏 -->
|
||||
<!-- 游戏分类滑动栏 (SVG分类图标) -->
|
||||
<scroll-view scroll-x class="category-scroll" :show-scrollbar="false">
|
||||
<view class="category-list">
|
||||
<view
|
||||
@@ -18,7 +18,7 @@
|
||||
:class="{ active: currentCategory === item.id }"
|
||||
@click="selectCategory(item.id)"
|
||||
>
|
||||
<text class="cat-icon">{{ item.icon }}</text>
|
||||
<image class="cat-icon-svg" :src="item.icon" mode="aspectFit" />
|
||||
<text class="cat-name">{{ item.name }}</text>
|
||||
<view v-if="item.hot" class="cat-badge">HOT</view>
|
||||
</view>
|
||||
@@ -36,25 +36,33 @@
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<!-- 快捷功能金刚区 -->
|
||||
<!-- 快捷功能金刚区 (纯矢量SVG图标) -->
|
||||
<view class="quick-grid">
|
||||
<view class="quick-item btn-active" @click="navTo('/pages/activity/list')">
|
||||
<view class="quick-icon-bg bg-purple">🔥</view>
|
||||
<view class="quick-icon-bg bg-purple">
|
||||
<image class="quick-svg" :src="ICONS.teamUp" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="quick-title">组队开黑</text>
|
||||
<text class="quick-sub">AA制五排</text>
|
||||
</view>
|
||||
<view class="quick-item btn-active" @click="navTo('/pages/activity/my-ticket')">
|
||||
<view class="quick-icon-bg bg-green">🎟️</view>
|
||||
<view class="quick-icon-bg bg-green">
|
||||
<image class="quick-svg" :src="ICONS.ticket" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="quick-title">我的门票</text>
|
||||
<text class="quick-sub">4位核销码</text>
|
||||
</view>
|
||||
<view class="quick-item btn-active" @click="navTo('/pages/order/list')">
|
||||
<view class="quick-icon-bg bg-blue">⚡</view>
|
||||
<view class="quick-icon-bg bg-blue">
|
||||
<image class="quick-svg" :src="ICONS.orderList" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="quick-title">服务订单</text>
|
||||
<text class="quick-sub">状态实时看</text>
|
||||
</view>
|
||||
<view class="quick-item btn-active" @click="navTo('/pages/user/index')">
|
||||
<view class="quick-icon-bg bg-orange">👑</view>
|
||||
<view class="quick-icon-bg bg-orange">
|
||||
<image class="quick-svg" :src="ICONS.expertBadge" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="quick-title">大神中心</text>
|
||||
<text class="quick-sub">双身份切换</text>
|
||||
</view>
|
||||
@@ -66,7 +74,10 @@
|
||||
<view class="title-line"></view>
|
||||
<text>精选在线大神</text>
|
||||
</view>
|
||||
<text class="section-more">实时在线</text>
|
||||
<view class="section-more">
|
||||
<view class="pulse-point"></view>
|
||||
<text>实时在线</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="expert-grid">
|
||||
@@ -76,9 +87,11 @@
|
||||
class="expert-card card-active"
|
||||
@click="goToExpert(expert.id)"
|
||||
>
|
||||
<!-- 封面图 -->
|
||||
<!-- 封面图构图优化:标准黄金比例与底部暗夜流光渐变 -->
|
||||
<view class="card-cover-wrap">
|
||||
<image class="card-cover" :src="expert.avatar" mode="aspectFill" />
|
||||
<view class="cover-gradient"></view>
|
||||
|
||||
<view class="status-tag" :class="expert.isOnline ? 'online' : 'offline'">
|
||||
<view class="pulse-dot" v-if="expert.isOnline"></view>
|
||||
<text>{{ expert.isOnline ? '在线' : '离线' }}</text>
|
||||
@@ -94,10 +107,10 @@
|
||||
</view>
|
||||
<view class="rank-badge">{{ expert.rankTag }}</view>
|
||||
|
||||
<!-- 语音试听条 -->
|
||||
<!-- 语音试听条 (矢量SVG播放图标) -->
|
||||
<view class="voice-bar btn-active" @click.stop="toggleVoice(expert.id)">
|
||||
<text class="voice-icon">{{ playingId === expert.id ? '🔊' : '▶' }}</text>
|
||||
<text class="voice-text">{{ playingId === expert.id ? '试听中...' : expert.voiceDuration + 's 语音' }}</text>
|
||||
<image class="voice-icon-svg" :src="playingId === expert.id ? ICONS.pause : ICONS.play" mode="aspectFit" />
|
||||
<text class="voice-text">{{ playingId === expert.id ? '试听中...' : expert.voiceDuration + 's 原声试听' }}</text>
|
||||
<view class="wave-lines" v-if="playingId === expert.id">
|
||||
<view class="wave-item w1"></view>
|
||||
<view class="wave-item w2"></view>
|
||||
@@ -122,6 +135,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { GAMES_LIST, BANNERS, EXPERTS_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const games = ref(GAMES_LIST);
|
||||
const banners = ref(BANNERS);
|
||||
@@ -201,9 +215,11 @@ const navTo = (url) => {
|
||||
padding: 0 28rpx;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
|
||||
.search-icon {
|
||||
font-size: 28rpx;
|
||||
.search-icon-img {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 16rpx;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.search-input {
|
||||
flex: 1;
|
||||
@@ -219,24 +235,32 @@ const navTo = (url) => {
|
||||
.category-scroll {
|
||||
white-space: nowrap;
|
||||
padding: 10rpx 32rpx 20rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.category-list {
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.category-item {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
padding: 14rpx 28rpx;
|
||||
background-color: #151D30;
|
||||
border-radius: 32rpx;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
position: relative;
|
||||
|
||||
.cat-icon {
|
||||
font-size: 26rpx;
|
||||
margin-right: 8rpx;
|
||||
.cat-icon-svg {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.cat-name {
|
||||
font-size: 24rpx;
|
||||
@@ -283,7 +307,7 @@ const navTo = (url) => {
|
||||
|
||||
.banner-tag {
|
||||
align-self: flex-start;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
backdrop-filter: blur(8px);
|
||||
padding: 4rpx 14rpx;
|
||||
border-radius: 8rpx;
|
||||
@@ -320,19 +344,23 @@ const navTo = (url) => {
|
||||
align-items: center;
|
||||
|
||||
.quick-icon-bg {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
border-radius: 22rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 34rpx;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
&.bg-purple { background: rgba(139, 92, 246, 0.2); }
|
||||
&.bg-green { background: rgba(16, 185, 129, 0.2); }
|
||||
&.bg-blue { background: rgba(99, 102, 241, 0.2); }
|
||||
&.bg-orange { background: rgba(245, 158, 11, 0.2); }
|
||||
.quick-svg {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
&.bg-purple { background: rgba(139, 92, 246, 0.15); border: 1px solid rgba(139, 92, 246, 0.3); }
|
||||
&.bg-green { background: rgba(16, 185, 129, 0.15); border: 1px solid rgba(16, 185, 129, 0.3); }
|
||||
&.bg-blue { background: rgba(99, 102, 241, 0.15); border: 1px solid rgba(99, 102, 241, 0.3); }
|
||||
&.bg-orange { background: rgba(245, 158, 11, 0.15); border: 1px solid rgba(245, 158, 11, 0.3); }
|
||||
}
|
||||
|
||||
.quick-title {
|
||||
@@ -371,11 +399,22 @@ const navTo = (url) => {
|
||||
}
|
||||
|
||||
.section-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
font-size: 22rpx;
|
||||
color: #10B981;
|
||||
background: rgba(16, 185, 129, 0.15);
|
||||
padding: 4rpx 14rpx;
|
||||
background: rgba(16, 185, 129, 0.12);
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
|
||||
.pulse-point {
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
border-radius: 50%;
|
||||
background: #10B981;
|
||||
box-shadow: 0 0 8rpx #10B981;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,11 +432,20 @@ const navTo = (url) => {
|
||||
|
||||
.card-cover-wrap {
|
||||
position: relative;
|
||||
height: 320rpx;
|
||||
height: 260rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.card-cover {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center top;
|
||||
}
|
||||
|
||||
.cover-gradient {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(180deg, rgba(0,0,0,0.1) 0%, rgba(21, 29, 48, 0.8) 100%);
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
@@ -413,8 +461,9 @@ const navTo = (url) => {
|
||||
font-weight: 600;
|
||||
|
||||
&.online {
|
||||
background: rgba(16, 185, 129, 0.85);
|
||||
background: rgba(16, 185, 129, 0.9);
|
||||
color: #FFF;
|
||||
box-shadow: 0 0 10rpx rgba(16, 185, 129, 0.5);
|
||||
}
|
||||
&.offline {
|
||||
background: rgba(100, 116, 139, 0.8);
|
||||
@@ -422,8 +471,8 @@ const navTo = (url) => {
|
||||
}
|
||||
|
||||
.pulse-dot {
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #FFF;
|
||||
animation: pulse 1.5s infinite;
|
||||
@@ -434,8 +483,9 @@ const navTo = (url) => {
|
||||
position: absolute;
|
||||
bottom: 14rpx;
|
||||
right: 14rpx;
|
||||
background: rgba(0, 0, 0, 0.65);
|
||||
backdrop-filter: blur(4px);
|
||||
background: rgba(10, 15, 29, 0.8);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(6px);
|
||||
font-size: 18rpx;
|
||||
color: #E2E8F0;
|
||||
padding: 4rpx 10rpx;
|
||||
@@ -486,6 +536,7 @@ const navTo = (url) => {
|
||||
border-radius: 6rpx;
|
||||
display: inline-block;
|
||||
margin-bottom: 12rpx;
|
||||
border: 1px solid rgba(245, 158, 11, 0.2);
|
||||
}
|
||||
|
||||
.voice-bar {
|
||||
@@ -498,9 +549,9 @@ const navTo = (url) => {
|
||||
padding: 0 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.voice-icon {
|
||||
font-size: 20rpx;
|
||||
color: #818CF8;
|
||||
.voice-icon-svg {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
.voice-text {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 开黑时段选择 -->
|
||||
<!-- 开黑时段选择 (矢量SVG时段图标) -->
|
||||
<view class="order-card">
|
||||
<view class="section-title">服务时间</view>
|
||||
<view class="time-tabs">
|
||||
@@ -41,7 +41,10 @@
|
||||
:class="{ active: timeType === 'NOW' }"
|
||||
@click="timeType = 'NOW'"
|
||||
>
|
||||
<text class="tab-t">⚡ 即刻出发</text>
|
||||
<view class="tab-title-wrap">
|
||||
<image class="tab-svg" :src="ICONS.bolt" mode="aspectFit" />
|
||||
<text class="tab-t">即刻出发</text>
|
||||
</view>
|
||||
<text class="tab-d">付款后立即连麦开黑</text>
|
||||
</view>
|
||||
<view
|
||||
@@ -49,7 +52,10 @@
|
||||
:class="{ active: timeType === 'APPOINT' }"
|
||||
@click="timeType = 'APPOINT'"
|
||||
>
|
||||
<text class="tab-t">📅 预约时间</text>
|
||||
<view class="tab-title-wrap">
|
||||
<image class="tab-svg" :src="ICONS.clock" mode="aspectFit" />
|
||||
<text class="tab-t">预约时段</text>
|
||||
</view>
|
||||
<text class="tab-d">今晚 20:30 开打</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -101,6 +107,7 @@
|
||||
import { ref, computed } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { EXPERTS_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const expert = ref(EXPERTS_LIST[0]);
|
||||
const selectedService = ref(EXPERTS_LIST[0].services[0]);
|
||||
@@ -301,12 +308,23 @@ const handlePay = () => {
|
||||
}
|
||||
}
|
||||
|
||||
.tab-t {
|
||||
font-size: 26rpx;
|
||||
color: #CBD5E1;
|
||||
display: block;
|
||||
.tab-title-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
.tab-svg {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
.tab-t {
|
||||
font-size: 26rpx;
|
||||
color: #CBD5E1;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-d {
|
||||
font-size: 20rpx;
|
||||
color: #64748B;
|
||||
@@ -416,6 +434,8 @@ const handlePay = () => {
|
||||
align-items: center;
|
||||
padding: 0 32rpx;
|
||||
z-index: 100;
|
||||
max-width: 450px;
|
||||
margin: 0 auto;
|
||||
|
||||
.amount-wrap {
|
||||
display: flex;
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
</view>
|
||||
|
||||
<view v-if="filteredOrders.length === 0" class="empty-state">
|
||||
<text class="empty-icon">📦</text>
|
||||
<image class="empty-svg" :src="ICONS.orderList" mode="aspectFit" />
|
||||
<text class="empty-text">暂无此类订单</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -77,6 +77,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ORDERS_LIST } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const tabs = [
|
||||
{ key: 'ALL', name: '全部' },
|
||||
@@ -398,10 +399,12 @@ const rateExpert = (id) => {
|
||||
text-align: center;
|
||||
padding: 100rpx 0;
|
||||
|
||||
.empty-icon {
|
||||
font-size: 64rpx;
|
||||
.empty-svg {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
opacity: 0.5;
|
||||
margin: 0 auto 16rpx;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.empty-text {
|
||||
color: #64748B;
|
||||
|
||||
@@ -8,27 +8,30 @@
|
||||
<text class="user-name">{{ user.nickname }}</text>
|
||||
<text class="vip-badge">VIP 黄金玩家</text>
|
||||
</view>
|
||||
<text class="user-uid">ID: {{ user.id }}</text>
|
||||
<text class="user-uid">UID: {{ user.id }}</text>
|
||||
</view>
|
||||
<view class="edit-btn btn-active" @click="editProfile">
|
||||
<text class="edit-icon">⚙️</text>
|
||||
<image class="edit-svg" :src="ICONS.settings" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 核心亮点:双身份流光切换卡 -->
|
||||
<!-- 核心亮点:双身份流光切换卡 (纯矢量与流光动效) -->
|
||||
<view class="role-switch-card card-active" @click="toggleRole">
|
||||
<view class="role-glow-border"></view>
|
||||
<view class="role-content">
|
||||
<view class="role-left">
|
||||
<view class="role-title-row">
|
||||
<text class="current-role-tag">{{ currentRole === 'PLAYER' ? '🎮 当前身份:普通玩家' : '👑 当前身份:接单大神' }}</text>
|
||||
<view class="role-dot" :class="{ expert: currentRole === 'EXPERT' }"></view>
|
||||
<text class="current-role-tag">
|
||||
{{ currentRole === 'PLAYER' ? '当前身份:普通玩家' : '当前身份:接单大神' }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="role-sub">
|
||||
{{ currentRole === 'PLAYER' ? '一键切换至大神接单工作台,开始接单赚收益' : '一键切换回玩家大厅,自由寻找开黑大神与车队' }}
|
||||
{{ currentRole === 'PLAYER' ? '一键切换至大神接单工作台,开启派单收益' : '一键切换回玩家大厅,自由寻找开黑车队' }}
|
||||
</text>
|
||||
</view>
|
||||
<button class="btn-switch-role btn-active">
|
||||
{{ currentRole === 'PLAYER' ? '切换为大神 ⚡' : '切换回玩家 🔄' }}
|
||||
{{ currentRole === 'PLAYER' ? '切换为大神' : '切回玩家端' }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -55,44 +58,52 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 核心功能金刚区 -->
|
||||
<!-- 核心功能金刚区 (纯矢量SVG图标) -->
|
||||
<view class="menu-grid-card">
|
||||
<view class="menu-item btn-active" @click="navTo('/pages/activity/my-ticket')">
|
||||
<view class="menu-icon bg-green">🎟️</view>
|
||||
<view class="menu-icon bg-green">
|
||||
<image class="menu-svg" :src="ICONS.ticket" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="menu-title">我的门票</text>
|
||||
<text class="menu-desc">4位核销码</text>
|
||||
</view>
|
||||
<view class="menu-item btn-active" @click="showInvitePoster">
|
||||
<view class="menu-icon bg-purple">🤝</view>
|
||||
<view class="menu-icon bg-purple">
|
||||
<image class="menu-svg" :src="ICONS.share" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="menu-title">推广赚钱</text>
|
||||
<text class="menu-desc">二级返佣</text>
|
||||
</view>
|
||||
<view class="menu-item btn-active" @click="navTo('/pages/order/list')">
|
||||
<view class="menu-icon bg-blue">📋</view>
|
||||
<view class="menu-icon bg-blue">
|
||||
<image class="menu-svg" :src="ICONS.orderList" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="menu-title">所有订单</text>
|
||||
<text class="menu-desc">对局与退款</text>
|
||||
</view>
|
||||
<view class="menu-item btn-active" @click="applyExpert">
|
||||
<view class="menu-icon bg-orange">✨</view>
|
||||
<view class="menu-icon bg-orange">
|
||||
<image class="menu-svg" :src="ICONS.expertBadge" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="menu-title">大神认证</text>
|
||||
<text class="menu-desc">入驻接单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表式功能菜单 -->
|
||||
<!-- 列表式功能菜单 (纯矢量SVG图标) -->
|
||||
<view class="list-menu-card">
|
||||
<view class="list-row btn-active" @click="contactService">
|
||||
<text class="row-icon">🎧</text>
|
||||
<image class="row-svg" :src="ICONS.headphones" mode="aspectFit" />
|
||||
<text class="row-label">官方在线客服</text>
|
||||
<text class="row-arrow">></text>
|
||||
</view>
|
||||
<view class="list-row btn-active" @click="openNotice">
|
||||
<text class="row-icon">🔔</text>
|
||||
<image class="row-svg" :src="ICONS.bell" mode="aspectFit" />
|
||||
<text class="row-label">平台消息与通知</text>
|
||||
<text class="row-arrow">></text>
|
||||
</view>
|
||||
<view class="list-row btn-active" @click="openAbout">
|
||||
<text class="row-icon">🛡️</text>
|
||||
<image class="row-svg" :src="ICONS.shield" mode="aspectFit" />
|
||||
<text class="row-label">平台规范与服务协议</text>
|
||||
<text class="row-arrow">></text>
|
||||
</view>
|
||||
@@ -103,6 +114,7 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { USER_PROFILE } from '@/common/mock.js';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
|
||||
const user = ref(USER_PROFILE);
|
||||
const currentRole = ref('PLAYER');
|
||||
@@ -153,7 +165,7 @@ const handleWithdraw = () => {
|
||||
|
||||
const showInvitePoster = () => {
|
||||
uni.showModal({
|
||||
title: '🎉 二级分销推广',
|
||||
title: '二级分销推广',
|
||||
content: `您的专属邀请码为:PW${user.value.id}\n已成功邀请 ${user.value.invitedCount} 位好友!\n好友下单您将实时享受最高 15% 自动分润提成。`,
|
||||
showCancel: false,
|
||||
confirmText: '保存太阳码'
|
||||
@@ -250,8 +262,10 @@ const navTo = (url) => {
|
||||
justify-content: center;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
|
||||
.edit-icon {
|
||||
font-size: 32rpx;
|
||||
.edit-svg {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,12 +289,30 @@ const navTo = (url) => {
|
||||
flex: 1;
|
||||
margin-right: 20rpx;
|
||||
|
||||
.current-role-tag {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #FFFFFF;
|
||||
display: block;
|
||||
.role-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
.role-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background: #6366F1;
|
||||
box-shadow: 0 0 8rpx #6366F1;
|
||||
|
||||
&.expert {
|
||||
background: #10B981;
|
||||
box-shadow: 0 0 8rpx #10B981;
|
||||
}
|
||||
}
|
||||
|
||||
.current-role-tag {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
.role-sub {
|
||||
@@ -410,13 +442,17 @@ const navTo = (url) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 34rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
&.bg-green { background: rgba(16, 185, 129, 0.2); }
|
||||
&.bg-purple { background: rgba(139, 92, 246, 0.2); }
|
||||
&.bg-blue { background: rgba(99, 102, 241, 0.2); }
|
||||
&.bg-orange { background: rgba(245, 158, 11, 0.2); }
|
||||
.menu-svg {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
|
||||
&.bg-green { background: rgba(16, 185, 129, 0.15); border: 1px solid rgba(16, 185, 129, 0.3); }
|
||||
&.bg-purple { background: rgba(139, 92, 246, 0.15); border: 1px solid rgba(139, 92, 246, 0.3); }
|
||||
&.bg-blue { background: rgba(99, 102, 241, 0.15); border: 1px solid rgba(99, 102, 241, 0.3); }
|
||||
&.bg-orange { background: rgba(245, 158, 11, 0.15); border: 1px solid rgba(245, 158, 11, 0.3); }
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
@@ -448,9 +484,11 @@ const navTo = (url) => {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.row-icon {
|
||||
font-size: 28rpx;
|
||||
.row-svg {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 20rpx;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.row-label {
|
||||
|
||||
在新工单中引用
屏蔽一个用户