mirror of
https://gitee.com/bootx/dax-pay-ui
synced 2026-08-11 15:15:34 +08:00
feat(workspace): 新增配置待完成 Widget, 对接 config-check API
工作台新增 config-alert Widget(三栏栅格), 实时展示未完成配置项, 点击跳转对应配置页, 空状态显示「配置已完善」; configCheck.json(10语)初始化分类文案, workspace.json 补 allComplete key。
This commit is contained in:
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "Payment Product",
|
||||
"description": "Some payment products have not completed channel parameter configuration"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "Site Information",
|
||||
"description": "System name, logo, ICP filing and other site display info are not configured"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "You have {n} configuration(s) pending",
|
||||
"viewDetail": "View Details"
|
||||
"viewDetail": "View Details",
|
||||
"allComplete": "All configurations complete"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "Parameter Produk Pembayaran",
|
||||
"description": "Beberapa produk pembayaran belum menyelesaikan konfigurasi parameter saluran"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "Informasi Situs",
|
||||
"description": "Nama sistem, logo, pendaftaran ICP dan info tampilan situs lainnya belum dikonfigurasi"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "{n} konfigurasi tertunda",
|
||||
"viewDetail": "Lihat Detail"
|
||||
"viewDetail": "Lihat Detail",
|
||||
"allComplete": "Semua konfigurasi selesai"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "決済商品パラメータ",
|
||||
"description": "チャネルパラメータの設定が未完了の決済商品があります"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "サイト情報",
|
||||
"description": "システム名、ロゴ、ICP備案などのサイト表示情報が未設定です"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "{n} 件の設定が未完了です",
|
||||
"viewDetail": "詳細を表示"
|
||||
"viewDetail": "詳細を表示",
|
||||
"allComplete": "すべての設定が完了しています"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "결제 상품 매개변수",
|
||||
"description": "채널 매개변수 설정이 완료되지 않은 결제 상품이 있습니다"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "사이트 정보",
|
||||
"description": "시스템 이름, 로고, ICP 신고 등 사이트 표시 정보가 설정되지 않았습니다"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "{n}개의 설정이 미완료입니다",
|
||||
"viewDetail": "상세 보기"
|
||||
"viewDetail": "상세 보기",
|
||||
"allComplete": "모든 설정이 완료되었습니다"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "Parameter Produk Pembayaran",
|
||||
"description": "Sesetengah produk pembayaran belum melengkapkan konfigurasi parameter saluran"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "Maklumat Tapak",
|
||||
"description": "Nama sistem, logo, pendaftaran ICP dan maklumat paparan tapak lain belum dikonfigurasi"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "{n} konfigurasi tertunggak",
|
||||
"viewDetail": "Lihat Butiran"
|
||||
"viewDetail": "Lihat Butiran",
|
||||
"allComplete": "Semua konfigurasi selesai"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "พารามิเตอร์ผลิตภัณฑ์การชำระเงิน",
|
||||
"description": "ผลิตภัณฑ์การชำระเงินบางรายการยังไม่ได้กำหนดค่าพารามิเตอร์ช่องทาง"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "ข้อมูลเว็บไซต์",
|
||||
"description": "ชื่อระบบ โลโก้ การจดทะเบียน ICP และข้อมูลการแสดงผลอื่นๆ ยังไม่ได้กำหนดค่า"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "มีการกำหนดค้าง {n} รายการ",
|
||||
"viewDetail": "ดูรายละเอียด"
|
||||
"viewDetail": "ดูรายละเอียด",
|
||||
"allComplete": "การกำหนดค่าเสร็จสมบูรณ์ทั้งหมด"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "Tham Số Sản Phẩm Thanh Toán",
|
||||
"description": "Một số sản phẩm thanh toán chưa hoàn tất cấu hình tham số kênh"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "Thông Tin Trang Web",
|
||||
"description": "Tên hệ thống, logo, đăng ký ICP và thông tin hiển thị trang khác chưa được cấu hình"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "Có {n} cấu hình chưa hoàn tất",
|
||||
"viewDetail": "Xem chi tiết"
|
||||
"viewDetail": "Xem chi tiết",
|
||||
"allComplete": "Tất cả cấu hình đã hoàn tất"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "支付产品参数",
|
||||
"description": "有支付产品尚未完成通道参数配置"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "站点信息",
|
||||
"description": "系统名称、Logo、ICP 备案等站点展示信息未配置"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "您有 {n} 项配置待完成",
|
||||
"viewDetail": "查看详情"
|
||||
"viewDetail": "查看详情",
|
||||
"allComplete": "配置已完善"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "支付產品參數",
|
||||
"description": "有支付產品尚未完成通道參數配置"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "站點資訊",
|
||||
"description": "系統名稱、Logo、ICP 備案等站點展示資訊未配置"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "您有 {n} 項配置待完成",
|
||||
"viewDetail": "查看詳情"
|
||||
"viewDetail": "查看詳情",
|
||||
"allComplete": "配置已完善"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"payProduct": {
|
||||
"title": "支付產品參數",
|
||||
"description": "有支付產品尚未完成通道參數配置"
|
||||
},
|
||||
"platformWebsite": {
|
||||
"title": "站點資訊",
|
||||
"description": "系統名稱、Logo、ICP 備案等站點展示資訊未配置"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
},
|
||||
"configAlert": {
|
||||
"bannerTitle": "您有 {n} 項配置待完成",
|
||||
"viewDetail": "查看詳情"
|
||||
"viewDetail": "查看詳情",
|
||||
"allComplete": "配置已完善"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { LayoutItem, WidgetMeta } from './types';
|
||||
|
||||
import ConfigAlertWidget from './widgets/config-alert.widget.vue';
|
||||
import NoticeListWidget from './widgets/notice-list.widget.vue';
|
||||
import PayTradeListWidget from './widgets/pay-trade-list.widget.vue';
|
||||
import ProviderDistributionWidget from './widgets/provider-distribution.widget.vue';
|
||||
@@ -33,6 +34,15 @@ export const WIDGET_REGISTRY: WidgetMeta[] = [
|
||||
defaultSpan: 24,
|
||||
defaultOrder: 1,
|
||||
},
|
||||
{
|
||||
// 配置待完成: 提示未完成的平台级配置项, 点击跳转对应配置页
|
||||
id: 'config-alert',
|
||||
component: ConfigAlertWidget,
|
||||
titleKey: 'dashboard.workspace.widget.configAlert',
|
||||
icon: 'lucide:list-checks',
|
||||
defaultSpan: 8,
|
||||
defaultOrder: 2,
|
||||
},
|
||||
{
|
||||
// 交易概览:左栏,三栏并排的第一栏
|
||||
id: 'trade-overview',
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<script lang="ts" setup>
|
||||
import type { DashboardData } from '../types';
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { ConfigCheckItem } from '#/api/payment/check/config-check.api';
|
||||
import { ConfigCheckApi } from '#/api/payment/check/config-check.api';
|
||||
|
||||
interface Props {
|
||||
data?: DashboardData;
|
||||
}
|
||||
|
||||
defineOptions({ name: 'ConfigAlertWidget' });
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
data: undefined,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const loading = ref(false);
|
||||
const items = ref<ConfigCheckItem[]>([]);
|
||||
const totalCount = ref(0);
|
||||
|
||||
// 分类图标映射(与后端 ConfigCheckCategoryEnum.code 对应)
|
||||
const categoryIconMap: Record<string, string> = {
|
||||
channelMerchant: 'lucide:store',
|
||||
mchApp: 'lucide:app-window',
|
||||
mchCredential: 'lucide:key-round',
|
||||
mchNotify: 'lucide:bell-ring',
|
||||
payProduct: 'lucide:credit-card',
|
||||
payRoute: 'lucide:route',
|
||||
platformOss: 'lucide:hard-drive',
|
||||
platformUrl: 'lucide:link',
|
||||
platformWebsite: 'lucide:globe',
|
||||
socialLogin: 'lucide:log-in',
|
||||
};
|
||||
|
||||
function categoryIcon(category: string): string {
|
||||
return categoryIconMap[category] ?? 'lucide:alert-circle';
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const { data } = await ConfigCheckApi.items();
|
||||
items.value = data?.items ?? [];
|
||||
totalCount.value = data?.totalCount ?? 0;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(load);
|
||||
|
||||
// 全部配置已完成
|
||||
const isComplete = computed(() => totalCount.value === 0);
|
||||
|
||||
// routeName 字段实际存储的是前端路由 path, 直接 push
|
||||
function navTo(routePath: string) {
|
||||
router.push(routePath).catch(() => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-card variant="borderless" class="!h-full !bg-card">
|
||||
<template #title>
|
||||
<div class="flex items-center gap-2">
|
||||
<IconifyIcon icon="lucide:list-checks" class="size-4 text-primary" />
|
||||
<span>{{ $t('dashboard.workspace.widget.configAlert') }}</span>
|
||||
<a-tag v-if="totalCount > 0" color="orange" class="!ml-1 !mr-0">
|
||||
{{ totalCount }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template #extra>
|
||||
<a-button type="link" size="small" @click="load">
|
||||
<IconifyIcon icon="lucide:refresh-cw" class="mr-1 size-3.5" />
|
||||
<span>{{ $t('common.refresh') }}</span>
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<a-skeleton v-if="loading" active :paragraph="{ rows: 4 }" />
|
||||
|
||||
<!-- 空状态: 全部已配置 -->
|
||||
<div v-else-if="isComplete" class="flex flex-col items-center justify-center py-6">
|
||||
<IconifyIcon icon="lucide:circle-check-big" class="mb-2 size-10 text-emerald-500" />
|
||||
<span class="text-sm text-foreground/60">{{ $t('dashboard.workspace.configAlert.allComplete') }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 未配置列表 -->
|
||||
<ul v-else class="alert-scroll flex max-h-[230px] flex-col gap-2 overflow-y-auto pr-1">
|
||||
<li
|
||||
v-for="item in items"
|
||||
:key="item.itemKey"
|
||||
class="flex cursor-pointer items-center gap-3 rounded-md p-2 transition-colors hover:bg-accent"
|
||||
@click="navTo(item.routeName)"
|
||||
>
|
||||
<div class="flex size-8 shrink-0 items-center justify-center rounded-md bg-orange-50 text-orange-500">
|
||||
<IconifyIcon :icon="categoryIcon(item.category)" class="size-4" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="truncate text-sm font-medium">
|
||||
{{ $t(item.titleKey) }}
|
||||
</div>
|
||||
<div class="truncate text-xs text-foreground/50">
|
||||
{{ $t(item.descriptionKey) }}
|
||||
</div>
|
||||
</div>
|
||||
<a-tag v-if="item.count !== undefined && item.count > 0" color="orange" class="!m-0 shrink-0">
|
||||
{{ item.count }}
|
||||
</a-tag>
|
||||
<IconifyIcon icon="lucide:chevron-right" class="size-4 shrink-0 text-foreground/30" />
|
||||
</li>
|
||||
</ul>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.alert-scroll::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.alert-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: hsl(var(--border));
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alert-scroll::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user