支持配置后台页面入口

This commit is contained in:
yml2213
2026-06-11 08:00:13 +08:00
parent 7130135e23
commit 6d61a336d6
27 changed files with 157 additions and 85 deletions
@@ -19,6 +19,7 @@ import ChatAttachmentImage from '@/components/ChatAttachmentImage.vue'
import { useChatSSE, type ChatEvent } from '@/features/chats/composables/useChatSSE'
import { useDesktopNotification } from '@/features/chats/composables/useDesktopNotification'
import NotificationSettings from '@/features/chats/components/NotificationSettings.vue'
import { adminPath } from '@/shared/utils/adminPath'
import { formatDateMinute } from '@/shared/utils/time'
import TransferDialog from '../components/TransferDialog.vue'
import QuickReplyDialog from '../components/QuickReplyDialog.vue'
@@ -407,7 +408,7 @@ function getSupportName(item: ChatConversation) {
</div>
<div class="head-actions">
<el-button size="small" @click="transferVisible = true">转接</el-button>
<RouterLink v-if="active.order_id" :to="`/admin/orders/${active.order_id}`">
<RouterLink v-if="active.order_id" :to="adminPath(`orders/${active.order_id}`)">
<el-button size="small">查看订单</el-button>
</RouterLink>
</div>
@@ -18,6 +18,7 @@ import {
import { fetchAdminDashboard, type AdminDashboard } from '@/features/admin/api/adminDashboard'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import { formatCentWithSymbol } from '@/shared/utils/money'
import { adminPath } from '@/shared/utils/adminPath'
import { disputeStatusLabel, orderStatusLabel } from '@/shared/utils/statusLabels'
import { formatDateTime } from '@/shared/utils/time'
@@ -121,7 +122,7 @@ const {
</el-tag>
</div>
<div class="pending-list">
<RouterLink class="pending-row" to="/admin/disputes">
<RouterLink class="pending-row" :to="adminPath('disputes')">
<div class="pending-info">
<span class="pending-label">待仲裁申诉</span>
<span class="pending-desc">需要处理的用户争议</span>
@@ -130,7 +131,7 @@ const {
dashboard.pending.disputes
}}</strong>
</RouterLink>
<RouterLink class="pending-row" to="/admin/listings/review">
<RouterLink class="pending-row" :to="adminPath('listings/review')">
<div class="pending-info">
<span class="pending-label">待审核商品</span>
<span class="pending-desc">新提交的商品审核</span>
@@ -168,27 +169,27 @@ const {
</h2>
</div>
<div class="quick-links">
<RouterLink class="quick-link" to="/admin/users">
<RouterLink class="quick-link" :to="adminPath('users')">
<el-icon><User /></el-icon>
<span>用户管理</span>
</RouterLink>
<RouterLink class="quick-link" to="/admin/orders">
<RouterLink class="quick-link" :to="adminPath('orders')">
<el-icon><Tickets /></el-icon>
<span>订单管理</span>
</RouterLink>
<RouterLink class="quick-link" to="/admin/disputes">
<RouterLink class="quick-link" :to="adminPath('disputes')">
<el-icon><ScaleToOriginal /></el-icon>
<span>仲裁中心</span>
</RouterLink>
<RouterLink class="quick-link" to="/admin/listings">
<RouterLink class="quick-link" :to="adminPath('listings')">
<el-icon><Shop /></el-icon>
<span>商品管理</span>
</RouterLink>
<RouterLink class="quick-link" to="/admin/chats">
<RouterLink class="quick-link" :to="adminPath('chats')">
<el-icon><ChatDotRound /></el-icon>
<span>客服群聊</span>
</RouterLink>
<RouterLink class="quick-link" to="/admin/system-configs">
<RouterLink class="quick-link" :to="adminPath('system-configs')">
<el-icon><Operation /></el-icon>
<span>系统配置</span>
</RouterLink>
@@ -259,7 +260,7 @@ const {
</el-table-column>
<el-table-column label="操作" width="100">
<template #default>
<RouterLink to="/admin/disputes">
<RouterLink :to="adminPath('disputes')">
<el-button size="small" type="primary" link>处理</el-button>
</RouterLink>
</template>
@@ -3,6 +3,7 @@ import { Search } from '@element-plus/icons-vue'
import { onMounted, reactive, ref } from 'vue'
import { fetchFinanceDetails, type FinanceDetail } from '@/features/admin/api/adminFinance'
import { adminPath } from '@/shared/utils/adminPath'
import { formatCentWithSymbol } from '@/shared/utils/money'
import { orderStatusLabel } from '@/shared/utils/statusLabels'
import { formatDateTime } from '@/shared/utils/time'
@@ -197,7 +198,7 @@ function formatInputDate(date: Date) {
<div v-if="details.length > 0" class="finance-grid-body">
<div v-for="row in details" :key="row.order_id" class="finance-grid-row">
<div class="order-cell">
<RouterLink class="order-no" :to="`/admin/orders/${row.order_id}`">
<RouterLink class="order-no" :to="adminPath(`orders/${row.order_id}`)">
{{ row.order_no }}
</RouterLink>
<span class="cell-muted">结算 {{ shortDateTime(row.settled_at) }}</span>
@@ -6,6 +6,7 @@ import { computed, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import { fetchAdminFileBlob } from '@/shared/api/files'
import { adminPath } from '@/shared/utils/adminPath'
import { formatCentWithSymbol } from '@/shared/utils/money'
import {
adminMarkListingAbnormal,
@@ -117,7 +118,7 @@ async function openScreenshot(url: string) {
</div>
<div class="toolbar-actions">
<el-button :icon="CopyDocument" @click="copyListingCode">复制编号</el-button>
<RouterLink to="/admin/listings">
<RouterLink :to="adminPath('listings')">
<el-button>返回列表</el-button>
</RouterLink>
<el-button type="warning" :disabled="!canOperate" @click="openAction('offline')"
@@ -5,6 +5,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { fetchAdminFileBlob } from '@/shared/api/files'
import { adminPath } from '@/shared/utils/adminPath'
import { centToYuan, formatCent, formatMoneyWithSymbol, yuanToCent } from '@/shared/utils/money'
import {
adjustListingReviewPrice,
@@ -667,7 +668,7 @@ async function openScreenshot(url: string) {
<h2>{{ selectedListing.title }}</h2>
</div>
<div class="hero-actions">
<RouterLink :to="`/admin/listings/${selectedListing.id}`">
<RouterLink :to="adminPath(`listings/${selectedListing.id}`)">
<el-button>详情页</el-button>
</RouterLink>
<el-button
@@ -10,6 +10,7 @@ import {
type Listing,
} from '@/features/listings'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import { adminPath } from '@/shared/utils/adminPath'
import { formatCentWithSymbol } from '@/shared/utils/money'
import {
assetRegions,
@@ -558,7 +559,7 @@ function formatQuantity(value: number) {
</el-table-column>
<el-table-column label="详情" width="60">
<template #default="{ row }">
<RouterLink :to="`/admin/listings/${row.id}`">
<RouterLink :to="adminPath(`listings/${row.id}`)">
<el-button size="small">详情</el-button>
</RouterLink>
</template>
@@ -7,6 +7,7 @@ import { useRoute, useRouter } from 'vue-router'
import { fetchAdminCaptcha, type AdminCaptcha } from '@/features/admin'
import { useAdminSessionStore } from '@/stores/adminSession'
import { ADMIN_DASHBOARD_PATH, isAdminPath } from '@/shared/utils/adminPath'
const router = useRouter()
const route = useRoute()
@@ -45,7 +46,7 @@ async function handleLogin() {
)
ElMessage.success('后台登录成功')
const redirect = typeof route.query.redirect === 'string' ? route.query.redirect : ''
await router.push(redirect.startsWith('/admin') ? redirect : '/admin/dashboard')
await router.push(isAdminPath(redirect) ? redirect : ADMIN_DASHBOARD_PATH)
} catch (error) {
ElMessage.error(readError(error, '后台登录失败'))
await loadCaptcha()
@@ -16,6 +16,7 @@ import {
type RefundStatus,
} from '@/features/orders'
import { fetchAdminPayments, type AdminPayment } from '@/features/admin/api/adminPayments'
import { adminPath } from '@/shared/utils/adminPath'
import { centToYuan, formatCentWithSymbol, formatMoney } from '@/shared/utils/money'
import { handoffStatusLabel, orderStatusLabel } from '@/shared/utils/statusLabels'
import { formatDateTime } from '@/shared/utils/time'
@@ -195,7 +196,7 @@ function formatHandoffRecordType(type: string) {
</p>
</div>
<div class="toolbar-actions">
<RouterLink to="/admin/orders">
<RouterLink :to="adminPath('orders')">
<el-button>返回列表</el-button>
</RouterLink>
<el-button type="warning" :disabled="!canOperate" @click="openAction('abnormal')"
@@ -10,6 +10,7 @@ import {
import { formatDateTime } from '@/shared/utils/time'
import { centToYuan, formatMoney } from '@/shared/utils/money'
import { formatListingNo } from '@/shared/utils/listingDisplay'
import { adminPath } from '@/shared/utils/adminPath'
import AdminTablePagination from '../components/AdminTablePagination.vue'
const status = ref('')
@@ -109,7 +110,7 @@ function money(value: unknown) {
</el-table-column>
<el-table-column label="操作" width="100">
<template #default="{ row }">
<RouterLink :to="`/admin/orders/${row.id}`">
<RouterLink :to="adminPath(`orders/${row.id}`)">
<el-button size="small">详情</el-button>
</RouterLink>
</template>
@@ -3,6 +3,7 @@ import { Document, Search } from '@element-plus/icons-vue'
import { computed, onMounted, reactive, ref } from 'vue'
import { fetchAdminPayments, type AdminPayment } from '@/features/admin/api/adminPayments'
import { adminPath } from '@/shared/utils/adminPath'
import { formatCentWithSymbol } from '@/shared/utils/money'
import { formatDateTime } from '@/shared/utils/time'
import AdminTablePagination from '../components/AdminTablePagination.vue'
@@ -196,7 +197,7 @@ function jsonText(value: unknown) {
<el-table-column prop="payment_no" label="支付单号" min-width="220" />
<el-table-column label="订单" min-width="180">
<template #default="{ row }">
<RouterLink v-if="row.order_id" :to="`/admin/orders/${row.order_id}`">{{
<RouterLink v-if="row.order_id" :to="adminPath(`orders/${row.order_id}`)">{{
row.order_no || row.order_id
}}</RouterLink>
<span v-else>-</span>
@@ -3,6 +3,7 @@ import { Search } from '@element-plus/icons-vue'
import { computed, onMounted, reactive, ref } from 'vue'
import { fetchAdminWalletLedger, type AdminWalletLedger } from '@/features/admin/api/adminWallet'
import { adminPath } from '@/shared/utils/adminPath'
import { formatCentWithSymbol } from '@/shared/utils/money'
import { balanceTypeLabel, ledgerDirectionLabel } from '@/shared/utils/statusLabels'
import { formatDateTime } from '@/shared/utils/time'
@@ -136,7 +137,7 @@ function directionLabel(direction: string) {
</el-table-column>
<el-table-column label="订单" min-width="160">
<template #default="{ row }">
<RouterLink v-if="row.order_id" :to="`/admin/orders/${row.order_id}`">{{
<RouterLink v-if="row.order_id" :to="adminPath(`orders/${row.order_id}`)">{{
row.order_no || row.order_id
}}</RouterLink>
<span v-else>-</span>