优化路由逻辑,根据用户类型动态重定向到不同的默认页面,增强登录后的用户体验;更新退单管理界面,改进搜索功能和响应式设计,提升移动端用户体验。
This commit is contained in:
@@ -177,3 +177,4 @@ src/
|
||||
---
|
||||
|
||||
*最后更新时间: 2024年1月*
|
||||
|
||||
|
||||
@@ -20,7 +20,20 @@ export const routes = [
|
||||
path: '/',
|
||||
component: AdminLayout,
|
||||
children: [
|
||||
{ path: '', redirect: '/users' },
|
||||
{
|
||||
path: '',
|
||||
redirect: (to) => {
|
||||
// 根据用户类型重定向到不同的默认页面
|
||||
const { getCurrentUserType } = require('@/utils/permission')
|
||||
const userType = getCurrentUserType()
|
||||
|
||||
if (userType?.toLowerCase() === 'agent') {
|
||||
return '/links' // 代理商跳转到链接管理
|
||||
} else {
|
||||
return '/users' // 管理员跳转到用户管理
|
||||
}
|
||||
}
|
||||
},
|
||||
{ path: 'users', name: 'Users', component: UserList, meta: { title: '用户管理' } },
|
||||
{ path: 'settings', name: 'Settings', component: Settings, meta: { title: '系统设置' } },
|
||||
{ path: 'links', name: 'Links', component: LinkGenerate, meta: { title: '链接管理' } },
|
||||
@@ -44,7 +57,17 @@ router.beforeEach((to, from, next) => {
|
||||
|
||||
// 检查路由权限
|
||||
if (to.name && !canAccessRoute(to.name)) {
|
||||
return next({ name: 'Users' }) // 无权限时跳转到用户管理
|
||||
// 根据用户类型跳转到有权限的默认页面
|
||||
const { getCurrentUserType } = require('@/utils/permission')
|
||||
const userType = getCurrentUserType()
|
||||
|
||||
if (userType?.toLowerCase() === 'agent') {
|
||||
// 代理商跳转到链接管理页面
|
||||
return next({ name: 'Links' })
|
||||
} else {
|
||||
// 管理员或其他用户跳转到用户管理
|
||||
return next({ name: 'Users' })
|
||||
}
|
||||
}
|
||||
|
||||
next()
|
||||
|
||||
@@ -127,8 +127,19 @@ async function onSubmit() {
|
||||
showSuccessMessage('登录成功')
|
||||
persistRemember()
|
||||
console.debug('login response:', res.data)
|
||||
const redirect = route.query.redirect || '/'
|
||||
router.replace(String(redirect))
|
||||
|
||||
// 如果有 redirect 参数,直接跳转
|
||||
if (route.query.redirect) {
|
||||
router.replace(String(route.query.redirect))
|
||||
} else {
|
||||
// 根据用户类型跳转到合适的默认页面
|
||||
const userType = data?.userType?.toLowerCase()
|
||||
if (userType === 'agent') {
|
||||
router.replace('/links') // 代理商跳转到链接管理
|
||||
} else {
|
||||
router.replace('/users') // 管理员跳转到用户管理
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showErrorMessage(e, '登录失败')
|
||||
} finally {
|
||||
|
||||
@@ -5,47 +5,74 @@
|
||||
<p class="page-description">管理用户的退单申请,支持按链接编号查询和执行退单操作</p>
|
||||
</div>
|
||||
|
||||
<!-- 搜索区域 -->
|
||||
<!-- 搜索区域(响应式) -->
|
||||
<div class="search-section">
|
||||
<el-card>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-input
|
||||
v-model="searchForm.codeNo"
|
||||
placeholder="请输入链接编号"
|
||||
clearable
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #prepend>链接编号</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-select
|
||||
v-model="searchForm.status"
|
||||
placeholder="选择状态"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option label="全部状态" value="" />
|
||||
<el-option label="新建" value="NEW" />
|
||||
<el-option label="使用中" value="USING" />
|
||||
<el-option label="已登录" value="LOGGED_IN" />
|
||||
<el-option label="已完成" value="COMPLETED" />
|
||||
<el-option label="已退单" value="REFUNDED" />
|
||||
<el-option label="已过期" value="EXPIRED" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-button type="primary" @click="handleSearch" :loading="loading">
|
||||
<el-icon><Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button @click="handleReset">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form :model="searchForm" @submit.prevent>
|
||||
<el-row :gutter="12">
|
||||
<!-- 链接编号:手机端独占一行,桌面端占较宽比例 -->
|
||||
<el-col :xs="24" :sm="12" :md="10" :lg="10">
|
||||
<div class="code-input-wrap">
|
||||
<el-input
|
||||
v-model="searchForm.codeNo"
|
||||
size="large"
|
||||
clearable
|
||||
placeholder="请输入链接编号(支持粘贴后回车)"
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Link /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-tooltip content="从剪贴板粘贴" placement="top">
|
||||
<el-button
|
||||
class="paste-btn"
|
||||
:icon="DocumentCopy"
|
||||
size="large"
|
||||
@click="pasteFromClipboard"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 状态筛选:可选,主要用于查看信息时做个提示筛选(不影响后端查询) -->
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="6">
|
||||
<el-select
|
||||
v-model="searchForm.status"
|
||||
size="large"
|
||||
placeholder="选择状态"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option label="全部状态" value="" />
|
||||
<el-option label="新建" value="NEW" />
|
||||
<el-option label="使用中" value="USING" />
|
||||
<el-option label="已登录" value="LOGGED_IN" />
|
||||
<el-option label="已完成" value="COMPLETED" />
|
||||
<el-option label="已退单" value="REFUNDED" />
|
||||
<el-option label="已过期" value="EXPIRED" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
|
||||
<!-- 按钮区:手机端纵向铺满 -->
|
||||
<el-col :xs="24" :sm="4" :md="6" :lg="8">
|
||||
<div class="btn-group">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="handleSearch"
|
||||
:loading="loading"
|
||||
:disabled="!searchForm.codeNo.trim()"
|
||||
>
|
||||
<el-icon class="mr-6"><Search /></el-icon> 查询
|
||||
</el-button>
|
||||
<el-button size="large" @click="handleReset">
|
||||
<el-icon class="mr-6"><Refresh /></el-icon> 重置
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
@@ -54,7 +81,20 @@
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>链接信息</span>
|
||||
<div class="code-and-status">
|
||||
<span>链接信息</span>
|
||||
<span class="code-chip">
|
||||
<span class="mono">{{ linkInfo.codeNo }}</span>
|
||||
<el-tooltip content="复制链接编号" placement="top">
|
||||
<el-button
|
||||
:icon="DocumentCopy"
|
||||
circle
|
||||
size="small"
|
||||
@click="copyCodeNo(linkInfo.codeNo)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
<el-tag :type="getStatusTagType(linkInfo.status)">
|
||||
{{ getStatusText(linkInfo.status) }}
|
||||
</el-tag>
|
||||
@@ -62,7 +102,9 @@
|
||||
</template>
|
||||
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="链接编号">{{ linkInfo.codeNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="链接编号">
|
||||
<span class="mono">{{ linkInfo.codeNo }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="当前状态">
|
||||
<el-tag :type="getStatusTagType(linkInfo.status)">
|
||||
{{ getStatusText(linkInfo.status) }}
|
||||
@@ -70,10 +112,14 @@
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ formatDateTime(linkInfo.createdAt) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">{{ formatDateTime(linkInfo.updatedAt) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="代理ID">{{ linkInfo.agentId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="关联设备">{{ linkInfo.machineId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="总点数">{{ linkInfo.totalPoints || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="当前点数">{{ linkInfo.currentPoints || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="代理ID">
|
||||
<span class="mono">{{ linkInfo.agentId || '-' }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="关联设备">
|
||||
<span class="mono">{{ linkInfo.machineId || '-' }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总点数">{{ linkInfo.totalPoints ?? '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="当前点数">{{ linkInfo.currentPoints ?? '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="linkInfo.refundAt" label="退单时间">
|
||||
{{ formatDateTime(linkInfo.refundAt) }}
|
||||
</el-descriptions-item>
|
||||
@@ -87,24 +133,13 @@
|
||||
@click="handleRefund"
|
||||
:loading="refunding"
|
||||
>
|
||||
<el-icon><RefreshLeft /></el-icon>
|
||||
执行退单
|
||||
<el-icon class="mr-6"><RefreshLeft /></el-icon> 执行退单
|
||||
</el-button>
|
||||
<el-button
|
||||
v-else-if="linkInfo.status === 'REFUNDED'"
|
||||
disabled
|
||||
type="info"
|
||||
>
|
||||
<el-icon><Check /></el-icon>
|
||||
已退单
|
||||
<el-button v-else-if="linkInfo.status === 'REFUNDED'" disabled type="info">
|
||||
<el-icon class="mr-6"><Check /></el-icon> 已退单
|
||||
</el-button>
|
||||
<el-button
|
||||
v-else
|
||||
disabled
|
||||
type="info"
|
||||
>
|
||||
<el-icon><Warning /></el-icon>
|
||||
当前状态不允许退单
|
||||
<el-button v-else disabled type="info">
|
||||
<el-icon class="mr-6"><Warning /></el-icon> 当前状态不允许退单
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -162,18 +197,22 @@
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 退单确认对话框 -->
|
||||
<!-- 退单确认对话框(移动端全屏) -->
|
||||
<el-dialog
|
||||
v-model="refundDialogVisible"
|
||||
title="确认退单"
|
||||
width="500px"
|
||||
:width="isMobile ? '96vw' : '500px'"
|
||||
:fullscreen="isMobile"
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="handleRefundDialogClose"
|
||||
top="8vh"
|
||||
>
|
||||
<div class="refund-confirm">
|
||||
<el-icon class="warning-icon"><WarningFilled /></el-icon>
|
||||
<div class="confirm-content">
|
||||
<h3>确认要对以下链接执行退单操作吗?</h3>
|
||||
<p class="link-code">链接编号:<strong>{{ linkInfo?.codeNo }}</strong></p>
|
||||
<p class="link-code">链接编号:<strong class="mono">{{ linkInfo?.codeNo }}</strong></p>
|
||||
<p class="warning-text">
|
||||
<el-icon><Warning /></el-icon>
|
||||
退单操作不可逆,执行后链接将无法继续使用
|
||||
@@ -183,22 +222,25 @@
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="refundDialogVisible = false">取消</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="confirmRefund"
|
||||
:loading="refunding"
|
||||
>
|
||||
确认退单
|
||||
</el-button>
|
||||
<el-button type="danger" @click="confirmRefund" :loading="refunding">确认退单</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Search, Refresh, RefreshLeft, Check, Warning, WarningFilled } from '@element-plus/icons-vue'
|
||||
import { ref, reactive, onMounted, onUnmounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
Search,
|
||||
Refresh,
|
||||
RefreshLeft,
|
||||
Check,
|
||||
Warning,
|
||||
WarningFilled,
|
||||
Link,
|
||||
DocumentCopy
|
||||
} from '@element-plus/icons-vue'
|
||||
import { getLinkStatus, refundLink } from '@/api/links'
|
||||
|
||||
export default {
|
||||
@@ -209,92 +251,135 @@ export default {
|
||||
RefreshLeft,
|
||||
Check,
|
||||
Warning,
|
||||
WarningFilled
|
||||
WarningFilled,
|
||||
Link,
|
||||
DocumentCopy
|
||||
},
|
||||
setup() {
|
||||
// 响应式数据
|
||||
// 视口与状态
|
||||
const isMobile = ref(false)
|
||||
const loading = ref(false)
|
||||
const refunding = ref(false)
|
||||
const refundDialogVisible = ref(false)
|
||||
const linkInfo = ref(null)
|
||||
|
||||
// 表单
|
||||
const searchForm = reactive({
|
||||
codeNo: '',
|
||||
status: ''
|
||||
})
|
||||
|
||||
// 查询链接信息
|
||||
// 自适应
|
||||
const updateIsMobile = () => {
|
||||
isMobile.value = window.innerWidth <= 768
|
||||
}
|
||||
onMounted(() => {
|
||||
updateIsMobile()
|
||||
window.addEventListener('resize', updateIsMobile)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', updateIsMobile)
|
||||
})
|
||||
|
||||
// 粘贴剪贴板
|
||||
const pasteFromClipboard = async () => {
|
||||
try {
|
||||
if (!navigator.clipboard) {
|
||||
ElMessage.warning('当前环境不支持剪贴板读取')
|
||||
return
|
||||
}
|
||||
const text = await navigator.clipboard.readText()
|
||||
if (!text) {
|
||||
ElMessage.info('剪贴板为空')
|
||||
return
|
||||
}
|
||||
searchForm.codeNo = text.trim()
|
||||
// 自动触发查询(可按需注释)
|
||||
if (searchForm.codeNo) handleSearch()
|
||||
} catch (err) {
|
||||
ElMessage.error('读取剪贴板失败,请手动粘贴')
|
||||
}
|
||||
}
|
||||
|
||||
// 复制编号
|
||||
const copyCodeNo = async (code) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(code || '')
|
||||
ElMessage.success('已复制链接编号')
|
||||
} catch {
|
||||
ElMessage.error('复制失败,请手动选择复制')
|
||||
}
|
||||
}
|
||||
|
||||
// 查询
|
||||
const handleSearch = async () => {
|
||||
if (!searchForm.codeNo.trim()) {
|
||||
ElMessage.warning('请输入链接编号')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
const response = await getLinkStatus(searchForm.codeNo)
|
||||
const response = await getLinkStatus(searchForm.codeNo.trim())
|
||||
linkInfo.value = response.data
|
||||
|
||||
// 如果选择了状态筛选,仅做前端提示
|
||||
if (linkInfo.value && searchForm.status && linkInfo.value.status !== searchForm.status) {
|
||||
ElMessage.info(`已找到链接,但状态为「${getStatusText(linkInfo.value.status)}」`)
|
||||
}
|
||||
|
||||
if (!linkInfo.value) {
|
||||
ElMessage.warning('未找到相关链接信息')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('查询链接失败:', error)
|
||||
linkInfo.value = null
|
||||
|
||||
// 根据错误状态显示不同消息
|
||||
if (error.response?.status === 404) {
|
||||
if (error?.response?.status === 404) {
|
||||
ElMessage.error('链接不存在')
|
||||
} else if (error.response?.status === 403) {
|
||||
} else if (error?.response?.status === 403) {
|
||||
ElMessage.error('无权限查看此链接')
|
||||
} else {
|
||||
ElMessage.error('查询失败,请稍后重试')
|
||||
ElMessage.error(error?.response?.data?.message || '查询失败,请稍后重试')
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
// 重置
|
||||
const handleReset = () => {
|
||||
searchForm.codeNo = ''
|
||||
searchForm.status = ''
|
||||
linkInfo.value = null
|
||||
}
|
||||
|
||||
// 判断是否可以退单
|
||||
const canRefund = (status) => {
|
||||
return ['NEW', 'USING', 'LOGGED_IN'].includes(status)
|
||||
}
|
||||
// 资格判断
|
||||
const canRefund = (status) => ['NEW', 'USING', 'LOGGED_IN'].includes(status)
|
||||
|
||||
// 处理退单按钮点击
|
||||
// 打开确认弹窗
|
||||
const handleRefund = () => {
|
||||
if (!linkInfo.value) return
|
||||
|
||||
refundDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 确认退单
|
||||
const confirmRefund = async () => {
|
||||
if (!linkInfo.value) return
|
||||
|
||||
refunding.value = true
|
||||
try {
|
||||
await refundLink(linkInfo.value.codeNo)
|
||||
|
||||
// 更新本地状态
|
||||
linkInfo.value.status = 'REFUNDED'
|
||||
linkInfo.value.refundAt = new Date().toISOString()
|
||||
linkInfo.value.updatedAt = new Date().toISOString()
|
||||
|
||||
const nowISO = new Date().toISOString()
|
||||
linkInfo.value = {
|
||||
...linkInfo.value,
|
||||
status: 'REFUNDED',
|
||||
refundAt: nowISO,
|
||||
updatedAt: nowISO
|
||||
}
|
||||
refundDialogVisible.value = false
|
||||
ElMessage.success('退单操作成功')
|
||||
|
||||
} catch (error) {
|
||||
console.error('退单失败:', error)
|
||||
|
||||
// 根据错误状态显示不同消息
|
||||
if (error.response?.status === 400) {
|
||||
if (error?.response?.status === 400) {
|
||||
const errorCode = error.response.data?.code
|
||||
switch (errorCode) {
|
||||
case 'LINK_003':
|
||||
@@ -309,53 +394,50 @@ export default {
|
||||
default:
|
||||
ElMessage.error(error.response.data?.message || '退单失败')
|
||||
}
|
||||
} else if (error.response?.status === 403) {
|
||||
} else if (error?.response?.status === 403) {
|
||||
ElMessage.error('无权限操作此链接')
|
||||
} else {
|
||||
ElMessage.error('退单失败,请稍后重试')
|
||||
ElMessage.error(error?.response?.data?.message || '退单失败,请稍后重试')
|
||||
}
|
||||
} finally {
|
||||
refunding.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭退单对话框
|
||||
// 关闭弹窗
|
||||
const handleRefundDialogClose = () => {
|
||||
if (!refunding.value) {
|
||||
refundDialogVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取状态标签类型
|
||||
// 状态展示
|
||||
const getStatusTagType = (status) => {
|
||||
const statusTypes = {
|
||||
'NEW': 'info',
|
||||
'USING': 'warning',
|
||||
'LOGGED_IN': 'primary',
|
||||
'COMPLETED': 'success',
|
||||
'REFUNDED': 'info',
|
||||
'EXPIRED': 'danger'
|
||||
const map = {
|
||||
NEW: 'info',
|
||||
USING: 'warning',
|
||||
LOGGED_IN: 'primary',
|
||||
COMPLETED: 'success',
|
||||
REFUNDED: 'info',
|
||||
EXPIRED: 'danger'
|
||||
}
|
||||
return statusTypes[status] || 'info'
|
||||
return map[status] || 'info'
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status) => {
|
||||
const statusTexts = {
|
||||
'NEW': '新建',
|
||||
'USING': '使用中',
|
||||
'LOGGED_IN': '已登录',
|
||||
'COMPLETED': '已完成',
|
||||
'REFUNDED': '已退单',
|
||||
'EXPIRED': '已过期'
|
||||
const map = {
|
||||
NEW: '新建',
|
||||
USING: '使用中',
|
||||
LOGGED_IN: '已登录',
|
||||
COMPLETED: '已完成',
|
||||
REFUNDED: '已退单',
|
||||
EXPIRED: '已过期'
|
||||
}
|
||||
return statusTexts[status] || status
|
||||
return map[status] || status
|
||||
}
|
||||
|
||||
// 格式化时间
|
||||
// 时间格式化
|
||||
const formatDateTime = (dateTime) => {
|
||||
if (!dateTime) return '-'
|
||||
|
||||
try {
|
||||
const date = new Date(dateTime)
|
||||
return date.toLocaleString('zh-CN', {
|
||||
@@ -366,23 +448,29 @@ export default {
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
})
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return dateTime
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// state
|
||||
isMobile,
|
||||
loading,
|
||||
refunding,
|
||||
refundDialogVisible,
|
||||
linkInfo,
|
||||
searchForm,
|
||||
// actions
|
||||
pasteFromClipboard,
|
||||
copyCodeNo,
|
||||
handleSearch,
|
||||
handleReset,
|
||||
canRefund,
|
||||
handleRefund,
|
||||
confirmRefund,
|
||||
handleRefundDialogClose,
|
||||
// helpers
|
||||
getStatusTagType,
|
||||
getStatusText,
|
||||
formatDateTime
|
||||
@@ -399,35 +487,60 @@ export default {
|
||||
.page-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.page-header h2 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #303133;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.page-description {
|
||||
margin: 0;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 搜索区样式 */
|
||||
.search-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.code-input-wrap {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.code-input-wrap .paste-btn {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
/* 结果卡片 */
|
||||
.link-info-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
gap: 8px;
|
||||
}
|
||||
.code-and-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.code-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
.mono {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.action-buttons {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
@@ -435,24 +548,23 @@ export default {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 帮助卡片 */
|
||||
.help-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.help-list {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.help-list li {
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.help-list .el-tag {
|
||||
margin-right: 8px;
|
||||
}
|
||||
@@ -463,87 +575,67 @@ export default {
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.warning-icon {
|
||||
font-size: 24px;
|
||||
color: #e6a23c;
|
||||
flex-shrink: 0;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.confirm-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.confirm-content h3 {
|
||||
margin: 0 0 12px 0;
|
||||
font-size: 16px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.link-code {
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.link-code strong {
|
||||
color: #409eff;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.warning-text {
|
||||
margin: 12px 0 0 0;
|
||||
color: #e6a23c;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
/* 按钮组(响应式) */
|
||||
.btn-group {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.refund-management {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.page-header h2 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-descriptions {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.refund-confirm {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.warning-icon {
|
||||
align-self: center;
|
||||
}
|
||||
/* 手机端按钮纵向排列更易点按 */
|
||||
.btn-group {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色主题适配 */
|
||||
.dark .page-header h2 {
|
||||
color: #e5eaf3;
|
||||
}
|
||||
.dark .page-header h2 { color: #e5eaf3; }
|
||||
.dark .page-description { color: #a3a6ad; }
|
||||
.dark .confirm-content h3 { color: #e5eaf3; }
|
||||
.dark .link-code { color: #a3a6ad; }
|
||||
|
||||
.dark .page-description {
|
||||
color: #a3a6ad;
|
||||
}
|
||||
|
||||
.dark .confirm-content h3 {
|
||||
color: #e5eaf3;
|
||||
}
|
||||
|
||||
.dark .link-code {
|
||||
color: #a3a6ad;
|
||||
}
|
||||
/* 小图标间隔 */
|
||||
.mr-6 { margin-right: 6px; }
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user