移动端页面适配

This commit is contained in:
2025-12-10 14:17:31 +08:00
parent 403e2c28c0
commit ffbdcb29c4
13 changed files with 3169 additions and 645 deletions

View File

@@ -74,20 +74,21 @@
</div>
<div v-else class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
<el-table
:data="subscriptions"
style="width: 100%"
:header-cell-style="{
background: '#f8fafc',
color: '#475569',
fontWeight: '600',
fontSize: '14px'
}"
:cell-style="{
fontSize: '14px',
color: '#1e293b'
}"
>
<div :class="['table-container', { 'mobile-table-container': isMobile }]">
<el-table
:data="subscriptions"
:style="isMobile ? { width: '100%', minWidth: '600px' } : { width: '100%' }"
:header-cell-style="{
background: '#f8fafc',
color: '#475569',
fontWeight: '600',
fontSize: isMobile ? '12px' : '14px'
}"
:cell-style="{
fontSize: isMobile ? '12px' : '14px',
color: '#1e293b'
}"
>
<el-table-column prop="product.name" label="产品名称" min-width="200">
<template #default="{ row }">
<div>
@@ -96,7 +97,12 @@
</template>
</el-table-column>
<el-table-column prop="product.category.name" label="产品分类" width="120">
<el-table-column
v-if="!isMobile"
prop="product.category.name"
label="产品分类"
width="120"
>
<template #default="{ row }">
<el-tag size="small" type="info" effect="light">
{{ row.product?.category?.name || '未分类' }}
@@ -104,13 +110,22 @@
</template>
</el-table-column>
<el-table-column prop="product.code" label="产品编码" width="120">
<el-table-column
v-if="!isMobile"
prop="product.code"
label="产品编码"
width="120"
>
<template #default="{ row }">
<span class="font-mono text-sm text-gray-600">{{ row.product?.code || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="price" label="订阅价格" width="120">
<el-table-column
prop="price"
label="订阅价格"
:width="isMobile ? 100 : 120"
>
<template #default="{ row }">
<span class="font-semibold text-green-600">¥{{ formatPrice(row.price) }}</span>
</template>
@@ -122,18 +137,28 @@
</template>
</el-table-column> -->
<el-table-column prop="created_at" label="订阅时间" width="160">
<el-table-column
prop="created_at"
label="订阅时间"
:width="isMobile ? 120 : 160"
>
<template #default="{ row }">
<div class="text-sm">
<div class="text-gray-900">{{ formatDate(row.created_at) }}</div>
<div class="text-gray-500">{{ formatTime(row.created_at) }}</div>
<div v-if="!isMobile" class="text-gray-500">{{ formatTime(row.created_at) }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="400" fixed="right">
<el-table-column
label="操作"
:width="isMobile ? 120 : 400"
:fixed="isMobile ? false : 'right'"
class-name="action-column"
>
<template #default="{ row }">
<div class="flex items-center space-x-2">
<!-- 桌面端显示所有按钮 -->
<div v-if="!isMobile" class="flex items-center space-x-2 action-buttons-desktop">
<el-button
size="small"
type="primary"
@@ -163,9 +188,43 @@
取消订阅
</el-button>
</div>
<!-- 移动端主要操作 + 下拉菜单 -->
<div v-else class="action-buttons-mobile">
<el-button
size="small"
type="primary"
@click="handleViewProduct(row.product)"
class="mobile-primary-btn"
>
查看
</el-button>
<el-dropdown @command="(cmd) => handleMobileAction(cmd, row)" trigger="click" placement="bottom-end">
<el-button size="small" type="info" class="mobile-more-btn">
更多
<el-icon class="el-icon--right">
<ArrowDown />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="usage">
使用情况
</el-dropdown-item>
<el-dropdown-item command="debug">
在线调试
</el-dropdown-item>
<el-dropdown-item command="cancel" divided>
取消订阅
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
@@ -226,9 +285,12 @@ import { subscriptionApi } from '@/api'
import FilterItem from '@/components/common/FilterItem.vue'
import FilterSection from '@/components/common/FilterSection.vue'
import ListPageLayout from '@/components/common/ListPageLayout.vue'
import { useMobileTable } from '@/composables/useMobileTable'
import { ArrowDown } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const router = useRouter()
const { isMobile } = useMobileTable()
// 响应式数据
const loading = ref(false)
@@ -411,6 +473,21 @@ const goToApiDebugger = (product) => {
}
}
// 处理移动端操作
const handleMobileAction = (command, row) => {
switch (command) {
case 'usage':
handleViewUsage(row)
break
case 'debug':
goToApiDebugger(row.product)
break
case 'cancel':
handleCancelSubscription(row)
break
}
}
// 取消订阅
const handleCancelSubscription = async (subscription) => {
if (!subscription || !subscription.id) {
@@ -574,6 +651,30 @@ const handleCancelSubscription = async (subscription) => {
font-weight: 600;
}
/* 表格容器 */
.table-container {
width: 100%;
overflow-x: auto;
}
.mobile-table-container {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.mobile-table-container::-webkit-scrollbar {
height: 6px;
}
.mobile-table-container::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 3px;
}
.mobile-table-container::-webkit-scrollbar-track {
background: #f1f5f9;
}
/* 表格样式优化 */
:deep(.el-table) {
border-radius: 8px;
@@ -593,7 +694,33 @@ const handleCancelSubscription = async (subscription) => {
background: #f8fafc !important;
}
/* 响应式设计 */
/* 操作列样式 */
.action-buttons-desktop {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.action-buttons-mobile {
display: flex;
align-items: center;
gap: 4px;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.mobile-primary-btn,
.mobile-more-btn {
flex: 1;
min-width: 50px;
padding: 6px 8px;
font-size: 12px;
white-space: nowrap;
}
/* 移动端表格优化 */
@media (max-width: 768px) {
.stat-item {
padding: 12px 16px;
@@ -619,5 +746,76 @@ const handleCancelSubscription = async (subscription) => {
.usage-stat-label {
font-size: 13px;
}
/* 移动端表格样式 */
.table-container {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
:deep(.el-table) {
font-size: 12px;
min-width: 600px;
}
:deep(.el-table th),
:deep(.el-table td) {
padding: 8px 4px;
}
:deep(.el-table .cell) {
padding: 0 4px;
word-break: break-word;
line-height: 1.4;
}
/* 移动端产品名称列 */
:deep(.el-table-column[prop='product.name']) {
min-width: 150px;
}
/* 移动端操作列 */
.action-buttons-mobile {
gap: 4px;
flex-direction: row;
width: 100%;
}
.mobile-primary-btn,
.mobile-more-btn {
padding: 4px 6px;
font-size: 11px;
min-width: 45px;
flex: 1;
}
/* 移动端隐藏固定列阴影 */
:deep(.el-table__fixed-right) {
box-shadow: none !important;
}
}
@media (max-width: 480px) {
.action-buttons-mobile {
gap: 3px;
flex-direction: row;
}
.mobile-primary-btn,
.mobile-more-btn {
padding: 3px 4px;
font-size: 10px;
min-width: 40px;
flex: 1;
}
:deep(.el-table th),
:deep(.el-table td) {
padding: 6px 2px;
}
:deep(.el-table .cell) {
padding: 0 2px;
}
}
</style>