实现部分页面前后端相通
This commit is contained in:
@@ -24,15 +24,11 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="period-selector">
|
||||
<text class="period-label">时段</text>
|
||||
<scroll-view class="period-scroll" scroll-x>
|
||||
<view v-for="(period, idx) in periods" :key="idx" class="period-item"
|
||||
:class="{ active: currentPeriod === period.value }" @click="selectPeriod(period.value)">
|
||||
<text class="period-symbol">{{ period.symbol }}</text>
|
||||
<text>{{ period.label }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="period-row">
|
||||
<view v-for="(period, idx) in periods" :key="idx" class="period-item"
|
||||
:class="{ active: currentPeriod === period.value }" @click="selectPeriod(period.value)">
|
||||
<text>{{ period.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -58,34 +54,48 @@
|
||||
|
||||
<scroll-view class="course-list" scroll-y :style="{ height: 'calc(100vh - ' + totalHeaderHeight + 'px - 104px)' }">
|
||||
<view class="course-list-inner">
|
||||
<view v-for="(course, idx) in filteredCourses" :key="idx" class="course-card" @click="goToDetail(course)">
|
||||
<view class="course-cover">
|
||||
<text class="cover-text">{{ course.typeChar }}</text>
|
||||
</view>
|
||||
<view class="course-body">
|
||||
<text class="course-name">{{ course.courseName }}</text>
|
||||
<view class="course-row">
|
||||
<text class="course-coach">教练 {{ course.coachName }}</text>
|
||||
<text class="course-difficulty" :class="'diff-' + course.difficultyLevel">{{ course.difficultyLabel }}</text>
|
||||
</view>
|
||||
<view class="course-row">
|
||||
<text class="course-time">日期 {{ course.startTime }}</text>
|
||||
</view>
|
||||
<view class="course-row">
|
||||
<text class="course-location">{{ course.location }}</text>
|
||||
<text class="course-capacity">{{ course.currentMembers }}/{{ course.maxMembers }}人</text>
|
||||
</view>
|
||||
<view class="course-bottom">
|
||||
<text class="course-price" :class="{ free: course.storedValueAmount === 0 }">
|
||||
{{ course.storedValueAmount > 0 ? course.storedValueAmount + '元/次' : '免费' }}
|
||||
</text>
|
||||
<button class="btn-book" :class="{ disabled: course.isFull }" :disabled="course.isFull"
|
||||
@click.stop="bookCourse(course)">
|
||||
{{ course.isFull ? '已约满' : '预约' }}
|
||||
</button>
|
||||
<view v-for="(course, idx) in filteredCourses" :key="idx" class="course-item" @click="goToDetail(course)">
|
||||
<view class="course-card">
|
||||
<view class="course-cover">
|
||||
<view class="cover-skeleton" v-if="course.coverImage && !course.coverLoaded && !course.coverError"></view>
|
||||
<image v-if="course.coverImage" class="cover-img" :class="{ loaded: course.coverLoaded }" :src="course.coverImage" mode="aspectFill" @load="onCoverLoad(course)" @error="onCoverError(course)"></image>
|
||||
<text class="cover-text" v-if="(!course.coverImage || course.coverError) && course.typeName">{{ course.typeName.slice(0, 2) }}</text>
|
||||
</view>
|
||||
<view class="course-body">
|
||||
<view class="course-top">
|
||||
<text class="course-name">{{ course.courseName }}</text>
|
||||
<view class="course-tags">
|
||||
<text class="course-category">{{ course.category }}</text>
|
||||
<text class="course-difficulty" :class="'diff-' + course.difficultyLevel">{{ course.difficultyLabel }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="course-meta">
|
||||
<text class="course-date">{{ course.shortDate }}</text>
|
||||
<text class="course-time">{{ course.shortTime }} - {{ course.endShortTime }}</text>
|
||||
<text class="course-duration" v-if="course.duration">{{ course.duration }}</text>
|
||||
</view>
|
||||
<view class="course-meta">
|
||||
<text class="course-location">{{ course.location }}</text>
|
||||
</view>
|
||||
<view class="course-meta">
|
||||
<text class="course-capacity">已预约 {{ course.currentMembers }}/{{ course.maxMembers }}人</text>
|
||||
</view>
|
||||
<view class="course-labels" v-if="course.labels">
|
||||
<text v-for="(label, li) in course.labels" :key="li" class="course-label"
|
||||
:style="{ background: label.color + '1a', color: label.color }">{{ label.labelName }}</text>
|
||||
</view>
|
||||
<text class="course-price" :class="{ free: course.storedValueAmount === 0 }">
|
||||
{{ course.storedValueAmount > 0 ? '¥' + course.storedValueAmount + '/次' : '免费' }}
|
||||
</text>
|
||||
<view class="course-bottom">
|
||||
<button class="btn-book" :class="{ disabled: !course.canBook }" :disabled="!course.canBook"
|
||||
@click.stop="bookCourse(course)">
|
||||
{{ course.canBook ? '立即预约' : course.statusLabel }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredCourses.length === 0" class="empty-state">
|
||||
<text class="empty-symbol">⊙</text>
|
||||
@@ -99,40 +109,35 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const courseApi = require('../../api/course')
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 0,
|
||||
navBarHeight: 44,
|
||||
totalHeaderHeight: 44,
|
||||
loading: true,
|
||||
searchKeyword: '', startDate: '', endDate: '',
|
||||
currentPeriod: 'all', currentFilter: 'all', currentSort: 'time',
|
||||
periods: [
|
||||
{ label: '全部', value: 'all', symbol: '◴' },
|
||||
{ label: '早晨', value: 'morning', symbol: '☀' },
|
||||
{ label: '上午', value: 'forenoon', symbol: '☀' },
|
||||
{ label: '下午', value: 'afternoon', symbol: '☼' },
|
||||
{ label: '晚间', value: 'evening', symbol: '☾' }
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '早晨', value: 'morning' },
|
||||
{ label: '上午', value: 'forenoon' },
|
||||
{ label: '下午', value: 'afternoon' },
|
||||
{ label: '晚间', value: 'evening' }
|
||||
],
|
||||
filterTabs: [
|
||||
{ label: '全部', value: 'all' }, { label: '力量区', value: 'strength' },
|
||||
{ label: '有氧', value: 'cardio' }, { label: '瑜伽', value: 'yoga' },
|
||||
{ label: '私教', value: 'pt' }, { label: '团课', value: 'group' },
|
||||
{ label: '免费', value: 'free' }
|
||||
{ label: '全部', value: 'all' }, { label: '有氧运动', value: '有氧运动' },
|
||||
{ label: '高强度', value: '高强度' }, { label: '柔韧平衡', value: '柔韧平衡' },
|
||||
{ label: '力量训练', value: '力量训练' }, { label: '免费', value: 'free' }
|
||||
],
|
||||
sortOptions: [
|
||||
{ label: '时间', value: 'time' },
|
||||
{ label: '难度', value: 'difficulty' },
|
||||
{ label: '热度', value: 'popular' }
|
||||
],
|
||||
courses: [
|
||||
{ id: 1, courseName: '综合力量训练', coachName: '张教练', location: '力量区', category: 'strength', typeChar: '力', startTime: '07-15 10:00', endTime: '07-15 10:45', maxMembers: 20, currentMembers: 8, isFull: false, difficulty: 5, difficultyLevel: 'mid', difficultyLabel: '中等', period: 'forenoon', storedValueAmount: 0 },
|
||||
{ id: 2, courseName: '流瑜伽 · 中级', coachName: '李教练', location: '3号教室', category: 'yoga', typeChar: '瑜', startTime: '07-15 14:00', endTime: '07-15 15:00', maxMembers: 15, currentMembers: 15, isFull: true, difficulty: 5, difficultyLevel: 'mid', difficultyLabel: '中等', period: 'afternoon', storedValueAmount: 0 },
|
||||
{ id: 3, courseName: '动感单车 · 冲刺', coachName: '王教练', location: '单车房', category: 'cardio', typeChar: '车', startTime: '07-15 18:00', endTime: '07-15 18:40', maxMembers: 25, currentMembers: 12, isFull: false, difficulty: 4, difficultyLevel: 'low', difficultyLabel: '入门', period: 'evening', storedValueAmount: 0 },
|
||||
{ id: 4, courseName: 'HIIT训练', coachName: '赵教练', location: '多功能厅', category: 'cardio', typeChar: 'HI', startTime: '07-15 12:00', endTime: '07-15 12:30', maxMembers: 15, currentMembers: 10, isFull: false, difficulty: 7, difficultyLevel: 'high', difficultyLabel: '困难', period: 'forenoon', storedValueAmount: 0 },
|
||||
{ id: 5, courseName: '普拉提', coachName: '李教练', location: '2号教室', category: 'yoga', typeChar: '普', startTime: '07-15 16:00', endTime: '07-15 16:50', maxMembers: 12, currentMembers: 5, isFull: false, difficulty: 4, difficultyLevel: 'low', difficultyLabel: '入门', period: 'afternoon', storedValueAmount: 0 },
|
||||
{ id: 6, courseName: '搏击操', coachName: '刘教练', location: '搏击区', category: 'cardio', typeChar: '搏', startTime: '07-15 07:00', endTime: '07-15 07:45', maxMembers: 20, currentMembers: 6, isFull: false, difficulty: 5, difficultyLevel: 'mid', difficultyLabel: '中等', period: 'morning', storedValueAmount: 0 }
|
||||
]
|
||||
courses: []
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
@@ -148,32 +153,112 @@
|
||||
this.statusBarHeight = statusBarHeight
|
||||
this.navBarHeight = navBarHeight
|
||||
this.totalHeaderHeight = statusBarHeight + navBarHeight
|
||||
this.loadCourses()
|
||||
},
|
||||
computed: {
|
||||
filteredCourses() {
|
||||
let list = this.courses
|
||||
let list = this.courses.map(c => {
|
||||
const bd = c.baseDifficulty || c.calculatedDifficulty || 5
|
||||
const st = c.startTime || ''
|
||||
const et = c.endTime || ''
|
||||
// 兼容 "2026-07-15T16:45:00" 和 "2026-07-15 16:45:00" 两种格式
|
||||
const dt = st ? new Date(st.replace(/ /, 'T')) : null
|
||||
const edt = et ? new Date(et.replace(/ /, 'T')) : null
|
||||
const hh = dt && !isNaN(dt) ? String(dt.getHours()).padStart(2, '0') : '--'
|
||||
const mm = dt && !isNaN(dt) ? String(dt.getMinutes()).padStart(2, '0') : '--'
|
||||
const md = dt && !isNaN(dt) ? String(dt.getMonth() + 1).padStart(2, '0') : '--'
|
||||
const dd = dt && !isNaN(dt) ? String(dt.getDate()).padStart(2, '0') : '--'
|
||||
const ehh = edt && !isNaN(edt) ? String(edt.getHours()).padStart(2, '0') : '--'
|
||||
const emm = edt && !isNaN(edt) ? String(edt.getMinutes()).padStart(2, '0') : '--'
|
||||
|
||||
// 计算持续时间(分钟)
|
||||
let durationStr = ''
|
||||
if (dt && edt && !isNaN(dt) && !isNaN(edt)) {
|
||||
const diffMin = Math.round((edt - dt) / 60000)
|
||||
if (diffMin > 0) {
|
||||
const hours = Math.floor(diffMin / 60)
|
||||
const mins = diffMin % 60
|
||||
durationStr = hours > 0 ? hours + '小时' + (mins > 0 ? mins + '分钟' : '') : diffMin + '分钟'
|
||||
}
|
||||
}
|
||||
const statusStr = c.status != null ? Number(c.status) : 0
|
||||
const curMembers = c.currentMembers != null ? c.currentMembers : 0
|
||||
const maxMems = c.maxMembers != null ? c.maxMembers : 0
|
||||
const isFull = maxMems > 0 && curMembers >= maxMems
|
||||
|
||||
let statusLabel = '正常'
|
||||
let canBook = statusStr === 0 && !isFull
|
||||
if (statusStr === 1) statusLabel = '已取消'
|
||||
else if (statusStr === 2) statusLabel = '已结束'
|
||||
else if (statusStr !== 0) statusLabel = '已关闭'
|
||||
if (!canBook && statusStr === 0 && isFull) statusLabel = '已约满'
|
||||
|
||||
return {
|
||||
...c,
|
||||
currentMembers: curMembers,
|
||||
maxMembers: maxMems,
|
||||
isFull: isFull,
|
||||
canBook: canBook,
|
||||
difficultyLevel: bd <= 3 ? 'low' : bd <= 6 ? 'mid' : 'high',
|
||||
difficultyLabel: bd <= 3 ? '入门' : bd <= 6 ? '中等' : '困难',
|
||||
baseDifficulty: bd,
|
||||
shortDate: md + '-' + dd,
|
||||
shortTime: hh + ':' + mm,
|
||||
endShortTime: ehh + ':' + emm,
|
||||
duration: durationStr,
|
||||
period: dt && !isNaN(dt) ? (hh < 8 ? 'morning' : hh < 12 ? 'forenoon' : hh < 17 ? 'afternoon' : 'evening') : 'all',
|
||||
category: c.category || c.typeCategory || '',
|
||||
typeName: c.typeName || (c.typeInfo && c.typeInfo.typeName) || '',
|
||||
coachName: c.coachName || (c.typeInfo && c.typeInfo.coachName) || '',
|
||||
location: c.location || '',
|
||||
status: statusStr,
|
||||
statusLabel: statusLabel,
|
||||
storedValueAmount: c.storedValueAmount != null ? c.storedValueAmount : 0,
|
||||
labels: c.labels || [],
|
||||
coverImage: c.coverImage || ''
|
||||
}
|
||||
})
|
||||
if (this.searchKeyword) {
|
||||
const kw = this.searchKeyword.toLowerCase()
|
||||
list = list.filter(c => c.courseName.toLowerCase().includes(kw) || c.coachName.toLowerCase().includes(kw) || c.location.toLowerCase().includes(kw))
|
||||
list = list.filter(c =>
|
||||
(c.courseName || '').toLowerCase().includes(kw) ||
|
||||
(c.coachName || '').toLowerCase().includes(kw) ||
|
||||
(c.location || '').toLowerCase().includes(kw)
|
||||
)
|
||||
}
|
||||
if (this.currentFilter === 'free') list = list.filter(c => c.storedValueAmount === 0)
|
||||
else if (this.currentFilter !== 'all') list = list.filter(c => c.category === this.currentFilter)
|
||||
if (this.currentPeriod !== 'all') list = list.filter(c => c.period === this.currentPeriod)
|
||||
if (this.currentSort === 'difficulty') list = [...list].sort((a, b) => a.difficulty - b.difficulty)
|
||||
else if (this.currentSort === 'popular') list = [...list].sort((a, b) => b.currentMembers - a.currentMembers)
|
||||
if (this.currentSort === 'difficulty') list = [...list].sort((a, b) => a.baseDifficulty - b.baseDifficulty)
|
||||
else if (this.currentSort === 'popular') list = [...list].sort((a, b) => (b.currentMembers || 0) - (a.currentMembers || 0))
|
||||
return list
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadCourses() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await courseApi.getCoursesByPage({ page: 0, size: 50 })
|
||||
// 兼容 PageResponse 格式 { content: [...], totalElements, ... } 或直接数组
|
||||
const list = Array.isArray(res) ? res : (res.content || [])
|
||||
this.courses = list
|
||||
} catch (e) {
|
||||
console.error('加载课程列表失败:', e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
onSearchInput() {},
|
||||
clearSearch() { this.searchKeyword = '' },
|
||||
onCoverLoad(course) { course.coverLoaded = true },
|
||||
onCoverError(course) { course.coverError = true },
|
||||
openStartDatePicker() { uni.showToast({ title: '选择开始日期', icon: 'none' }) },
|
||||
openEndDatePicker() { uni.showToast({ title: '选择结束日期', icon: 'none' }) },
|
||||
selectPeriod(value) { this.currentPeriod = value },
|
||||
switchFilter(value) { this.currentFilter = value },
|
||||
switchSort(value) { this.currentSort = value },
|
||||
goToDetail(course) { uni.navigateTo({ url: '/pages/course-detail/course-detail?id=' + course.id }) },
|
||||
bookCourse(course) { if (!course.isFull) uni.navigateTo({ url: '/pages/course-detail/course-detail?id=' + course.id }) }
|
||||
bookCourse(course) { if (course.canBook) uni.navigateTo({ url: '/pages/course-detail/course-detail?id=' + course.id }) }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -184,7 +269,7 @@
|
||||
.nav-bar { background: #1A1A1A; padding: 0 20px; display: flex; align-items: center; }
|
||||
.nav-title { font-size: 18px; font-weight: 700; color: #FFFFFF; }
|
||||
|
||||
.search-area { background: #1A1A1A; padding: 0 16px 20px; }
|
||||
.search-area { background: #1A1A1A; padding: 18px 16px 20px; }
|
||||
.search-box { background: rgba(255,255,255,0.12); border-radius: 40px; padding: 0 16px; display: flex; align-items: center; height: 42px; margin-bottom: 14px; }
|
||||
.search-symbol { font-size: 15px; color: rgba(255,255,255,0.5); flex-shrink: 0; margin-right: 8px; }
|
||||
.search-input { flex: 1; font-size: 14px; color: #FFFFFF; height: 100%; }
|
||||
@@ -197,12 +282,9 @@
|
||||
.range-value.placeholder { color: rgba(255,255,255,0.35); font-weight: 400; }
|
||||
.range-sep { color: rgba(255,255,255,0.5); font-size: 14px; flex-shrink: 0; margin-right: 10px; }
|
||||
|
||||
.period-selector { display: flex; align-items: center; }
|
||||
.period-label { font-size: 13px; color: rgba(255,255,255,0.6); flex-shrink: 0; margin-right: 10px; }
|
||||
.period-scroll { flex: 1; display: flex; white-space: nowrap; }
|
||||
.period-item { display: inline-flex; align-items: center; padding: 6px 14px; border-radius: 40px; font-size: 13px; color: rgba(255,255,255,0.7); background: rgba(255,255,255,0.08); margin-right: 8px; }
|
||||
.period-row { display: flex; }
|
||||
.period-item { flex: 1; text-align: center; padding: 7px 0; border-radius: 40px; font-size: 13px; color: rgba(255,255,255,0.7); background: rgba(255,255,255,0.08); margin: 0 3px; }
|
||||
.period-item.active { background: #00E676; color: #1A1A1A; font-weight: 600; }
|
||||
.period-symbol { font-size: 13px; margin-right: 4px; }
|
||||
|
||||
.filter-tabs { background: #FFFFFF; display: flex; white-space: nowrap; border-bottom: 1px solid #EEEEEE; }
|
||||
.filter-tabs-inner { padding: 14px 16px; display: flex; white-space: nowrap; }
|
||||
@@ -216,21 +298,35 @@
|
||||
.sort-item.active { color: #00C853; font-weight: 600; }
|
||||
|
||||
.course-list-inner { padding: 12px 16px 0; }
|
||||
.course-card { background: #FFFFFF; border-radius: 20px; padding: 14px; margin-bottom: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.06); display: flex; }
|
||||
.course-cover { width: 72px; height: 72px; border-radius: 12px; background: rgba(0,230,118,0.15); display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-right: 14px; }
|
||||
.cover-text { font-size: 24px; font-weight: 700; color: #00C853; }
|
||||
.course-body { flex: 1; display: flex; flex-direction: column; }
|
||||
.course-name { font-size: 16px; font-weight: 700; color: #1E1E1E; }
|
||||
.course-row { display: flex; align-items: center; font-size: 12px; color: #7A7E84; }
|
||||
.course-row > * { margin-right: 12px; }
|
||||
.course-item { margin-bottom: 12px; border-radius: 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.06); overflow: hidden; }
|
||||
.course-card { background: #FFFFFF; border-radius: 20px; padding: 14px; display: flex; }
|
||||
.course-cover { width: 72px; height: 72px; border-radius: 12px; background: rgba(0,230,118,0.12); display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-right: 14px; overflow: hidden; position: relative; }
|
||||
.cover-skeleton { position: absolute; inset: 0; background: linear-gradient(90deg, #E8E8E8 25%, #F0F0F0 50%, #E8E8E8 75%); background-size: 200% 100%; animation: shimmer 1.5s infinite; z-index: 1; }
|
||||
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
|
||||
.cover-img { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.3s; z-index: 0; }
|
||||
.cover-img.loaded { opacity: 1; z-index: 2; }
|
||||
.cover-text { font-size: 22px; font-weight: 700; color: #00C853; }
|
||||
.course-body { flex: 1; display: flex; flex-direction: column; min-width: 0; }
|
||||
.course-top { display: flex; justify-content: space-between; align-items: flex-start; }
|
||||
.course-name { font-size: 16px; font-weight: 700; color: #1E1E1E; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.course-tags { display: flex; flex-shrink: 0; margin-left: 6px; }
|
||||
.course-category { font-size: 11px; color: #00C853; background: rgba(0,230,118,0.12); padding: 1px 8px; border-radius: 20px; font-weight: 500; margin-right: 4px; }
|
||||
.course-difficulty { padding: 1px 8px; border-radius: 20px; font-size: 11px; font-weight: 600; }
|
||||
.diff-low { background: rgba(0,230,118,0.15); color: #00C853; }
|
||||
.diff-mid { background: rgba(255,165,2,0.15); color: #FFA502; }
|
||||
.diff-high { background: rgba(255,82,82,0.15); color: #FF5252; }
|
||||
.course-bottom { display: flex; justify-content: space-between; align-items: center; margin-top: 4px; }
|
||||
.course-price { font-size: 13px; font-weight: 600; color: #00C853; }
|
||||
.course-meta { display: flex; align-items: center; font-size: 12px; color: #7A7E84; margin-top: 4px; }
|
||||
.course-date { flex-shrink: 0; }
|
||||
.course-time { margin-left: 8px; }
|
||||
.course-duration { margin-left: 8px; color: #00C853; font-weight: 500; }
|
||||
.course-location { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.course-capacity { color: #7A7E84; }
|
||||
.course-labels { display: flex; flex-wrap: wrap; margin-top: 6px; }
|
||||
.course-label { font-size: 10px; padding: 1px 6px; border-radius: 10px; margin-right: 4px; margin-bottom: 2px; }
|
||||
.course-bottom { text-align: right; margin-top: 6px; }
|
||||
.course-price { font-size: 18px; font-weight: 700; color: #00C853; display: block; margin-top: 6px; }
|
||||
.course-price.free { color: #00C853; }
|
||||
.btn-book { background: #00E676; color: #1A1A1A; border: none; padding: 6px 16px; border-radius: 40px; font-weight: 700; font-size: 13px; line-height: 1.4; box-shadow: 0 2px 6px rgba(0,230,118,0.3); }
|
||||
.btn-book { background: #00E676; color: #1A1A1A; border: none; padding: 6px 16px; border-radius: 40px; font-weight: 700; font-size: 13px; line-height: 1.4; box-shadow: 0 2px 8px rgba(0,230,118,0.3); }
|
||||
.btn-book::after { border: none; }
|
||||
.btn-book.disabled { background: #E0E0E0; color: #BDBDBD; box-shadow: none; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user