feat(admin): 收银台配置页增加小程序场景

一级 Tab 增加小程序,二级按微信/支付宝/云闪付/抖音分桶;
对齐后端 mini 类型与 clientEnv 白名单,补全多语 typeMini 与字典。
This commit is contained in:
DaxPay Dev
2026-07-15 17:05:57 +08:00
parent 8ca2edc3d0
commit 5aece99c7d
24 changed files with 105 additions and 43 deletions

View File

@@ -56,9 +56,9 @@ export const CashierConfigApi = {
export interface CashierItemResult extends BaseEntity {
appId?: string;
mchNo?: string;
/** 收银台类型: h5/web */
/** 收银台类型: h5/web/mini */
cashierType?: string;
/** H5 终端场景; WEB 为空 */
/** H5 五档 / MINI 四档(含云闪付); WEB 为空 */
clientEnv?: string;
name?: string;
icon?: string;

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5收银台",
"pc": "PC收银台",
"mini_app": "小程序收银台"
"h5": "H5 Cashier",
"web": "WEB Cashier",
"mini": "Mini Program Cashier"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "Please access cashier config from app management",
"typeH5": "H5",
"typeWeb": "WEB",
"typeMini": "Mini Program",
"addItem": "Add Payment Item",
"empty": "No payment items for this open environment",
"confirmDelete": "Delete this payment item?",

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5收银台",
"pc": "PC adalah sebuah sistem",
"mini_app": "小程序收银台"
"h5": "Kasir H5",
"web": "Kasir WEB",
"mini": "Kasir Mini Program"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "Silakan akses konfigurasi kasir dari manajemen aplikasi",
"typeH5": "H5",
"typeWeb": "WEB",
"typeMini": "Mini Program",
"addItem": "Tambahkan Item Pembayaran",
"empty": "Tidak ada item pembayaran untuk lingkungan terbuka ini",
"confirmDelete": "Hapus item pembayaran ini?",

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5收银台",
"pc": "PC收银台",
"mini_app": "小程序收银台"
"h5": "H5レジ",
"web": "WEBレジ",
"mini": "ミニプログラムレジ"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "アプリ管理からレジ設定にアクセスしてください",
"typeH5": "H5",
"typeWeb": "ウェブ",
"typeMini": "ミニプログラム",
"addItem": "支払いアイテムの追加",
"empty": "このオープン環境には支払いアイテムはありません",
"confirmDelete": "この支払いアイテムを削除しますか?",

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5 차량",
"pc": "PC 장치",
"mini_app": "小程序收银台"
"h5": "H5 계산대",
"web": "WEB 계산대",
"mini": "미니프로그램 계산대"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "앱 관리에서 계산원 구성에 액세스하세요.",
"typeH5": "H5",
"typeWeb": "편물",
"typeMini": "미니프로그램",
"addItem": "결제 항목 추가",
"empty": "이 개방형 환경에는 결제 항목이 없습니다.",
"confirmDelete": "이 결제 항목을 삭제하시겠습니까?",

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5收银台",
"pc": "PC收银台",
"mini_app": "小程序收银台"
"h5": "Juruwang H5",
"web": "Juruwang WEB",
"mini": "Juruwang Mini Program"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "Sila akses konfigurasi juruwang daripada pengurusan aplikasi",
"typeH5": "H5",
"typeWeb": "WEB",
"typeMini": "Mini Program",
"addItem": "Tambah Item Pembayaran",
"empty": "Tiada item pembayaran untuk persekitaran terbuka ini",
"confirmDelete": "Padamkan item pembayaran ini?",

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5收银台",
"pc": "พีซี 收银台",
"mini_app": "小程序收银台"
"h5": "แคชเชียร์ H5",
"web": "แคชเชียร์ WEB",
"mini": "แคชเชียร์มินิโปรแกรม"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "โปรดเข้าถึงการกำหนดค่าแคชเชียร์จากการจัดการแอป",
"typeH5": "H5",
"typeWeb": "เว็บ",
"typeMini": "มินิโปรแกรม",
"addItem": "เพิ่มรายการชำระเงิน",
"empty": "ไม่มีรายการชำระเงินสำหรับสภาพแวดล้อมแบบเปิดนี้",
"confirmDelete": "ลบรายการชำระเงินนี้ใช่ไหม",

View File

@@ -307,9 +307,9 @@
"union_pay": "银联支付"
},
"gateway_cashier_type": {
"h5": "H5 银台",
"pc": "Máy tính PC",
"mini_app": "小程序收银台"
"h5": "Thu ngân H5",
"web": "Thu ngân WEB",
"mini": "Thu ngân Mini Program"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "Vui lòng truy cập cấu hình thu ngân từ quản lý ứng dụng",
"typeH5": "H5",
"typeWeb": "TRANG WEB",
"typeMini": "Mini Program",
"addItem": "Thêm mục thanh toán",
"empty": "Không có mục thanh toán nào cho môi trường mở này",
"confirmDelete": "Xóa mục thanh toán này?",

View File

@@ -308,8 +308,8 @@
},
"gateway_cashier_type": {
"h5": "H5收银台",
"pc": "PC收银台",
"mini_app": "小程序收银台"
"web": "WEB收银台",
"mini": "小程序收银台"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "请从应用管理进入收银台配置",
"typeH5": "H5",
"typeWeb": "WEB",
"typeMini": "小程序",
"addItem": "新增支付项",
"empty": "当前打开环境暂无支付项",
"confirmDelete": "确定删除该支付项吗?",

View File

@@ -308,8 +308,8 @@
},
"gateway_cashier_type": {
"h5": "H5收銀台",
"pc": "PC收銀台",
"mini_app": "小程序收銀台"
"web": "WEB收銀台",
"mini": "小程序收銀台"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "請從應用管理進入收銀台配置",
"typeH5": "H5",
"typeWeb": "WEB",
"typeMini": "小程序",
"addItem": "新增支付項",
"empty": "當前打開環境暫無支付項",
"confirmDelete": "確定刪除該支付項嗎?",

View File

@@ -307,9 +307,9 @@
"union_pay": "銀聯支付"
},
"gateway_cashier_type": {
"h5": "H5收銀",
"pc": "PC收銀",
"mini_app": "小程式收銀"
"h5": "H5收銀",
"web": "WEB收銀",
"mini": "小程式收銀"
},
"aggregate_bar_pay_type": {
"wechat_pay": "微信支付",

View File

@@ -4,6 +4,7 @@
"missingAppContext": "請從應用管理進入收銀臺配置",
"typeH5": "H5",
"typeWeb": "WEB",
"typeMini": "小程式",
"addItem": "新增支付項",
"empty": "當前開啟環境暫無支付項",
"confirmDelete": "確定刪除該支付項嗎?",

View File

@@ -21,9 +21,10 @@
import CashierItemEdit from './CashierItemEdit.vue';
import {
CASHIER_H5_CLIENT_ENVS,
CASHIER_TYPE,
RESOLVE_MODE,
cashierTypeRequiresClientEnv,
clientEnvsForCashierType,
type CashierType,
} from './shared/constants';
@@ -64,12 +65,15 @@
// 一级 / 二级 Tab
const activeType = ref<CashierType>(CASHIER_TYPE.H5);
const activeClientEnv = ref(CASHIER_H5_CLIENT_ENVS[0]!.clientEnv);
const activeClientEnv = ref('browser');
const itemEditRef = ref<InstanceType<typeof CashierItemEdit>>();
const canManage = computed(() => hasPermission(PermCodes.Merchant.GatewayCashier.MANAGE));
/** 当前一级类型对应的 clientEnv 二级列表 */
const activeClientEnvOptions = computed(() => clientEnvsForCashierType(activeType.value));
/** 场景 i18n */
function clientEnvLabel(clientEnv: string) {
return $t(`payment.merchant.cashier.cashier.clientEnvs.${clientEnv}`);
@@ -150,7 +154,7 @@
appId: appId.value,
cashierType: activeType.value,
};
if (activeType.value === CASHIER_TYPE.H5) {
if (cashierTypeRequiresClientEnv(activeType.value)) {
params.clientEnv = activeClientEnv.value;
}
const { data } = await CashierConfigApi.list(params);
@@ -174,7 +178,7 @@
mchNo: mchNo.value,
appId: appId.value,
cashierType: activeType.value,
clientEnv: activeType.value === CASHIER_TYPE.H5 ? activeClientEnv.value : undefined,
clientEnv: cashierTypeRequiresClientEnv(activeType.value) ? activeClientEnv.value : undefined,
});
}
@@ -184,7 +188,7 @@
mchNo: mchNo.value,
appId: appId.value,
cashierType: activeType.value,
clientEnv: activeType.value === CASHIER_TYPE.H5 ? activeClientEnv.value : undefined,
clientEnv: cashierTypeRequiresClientEnv(activeType.value) ? activeClientEnv.value : undefined,
record: row,
});
}
@@ -202,6 +206,17 @@
});
}
// 切换一级类型时,校正二级 clientEnv 落在当前列表内
watch(activeType, (type) => {
const options = clientEnvsForCashierType(type);
if (options.length === 0) {
return;
}
if (!options.some((o) => o.clientEnv === activeClientEnv.value)) {
activeClientEnv.value = options[0]!.clientEnv;
}
});
watch([activeType, activeClientEnv], () => {
if (!routeContext.isValid.value) return;
loadList();
@@ -243,7 +258,7 @@
</a-button>
</template>
<!-- 一级: H5 / WEB -->
<!-- 一级: H5 / WEB / 小程序 -->
<div class="mb-4">
<a-radio-group v-model:value="activeType" button-style="solid">
<a-radio-button :value="CASHIER_TYPE.H5">{{
@@ -252,13 +267,20 @@
<a-radio-button :value="CASHIER_TYPE.WEB">{{
$t('payment.merchant.cashier.cashier.typeWeb')
}}</a-radio-button>
<a-radio-button :value="CASHIER_TYPE.MINI">{{
$t('payment.merchant.cashier.cashier.typeMini')
}}</a-radio-button>
</a-radio-group>
</div>
<!-- H5 二级终端 -->
<div v-if="activeType === CASHIER_TYPE.H5" class="mb-4">
<!-- H5 五档 / 小程序四档(含云闪付) 二级终端 -->
<div v-if="cashierTypeRequiresClientEnv(activeType)" class="mb-4">
<a-radio-group v-model:value="activeClientEnv" button-style="solid">
<a-radio-button v-for="sc in CASHIER_H5_CLIENT_ENVS" :key="sc.clientEnv" :value="sc.clientEnv">
<a-radio-button
v-for="sc in activeClientEnvOptions"
:key="sc.clientEnv"
:value="sc.clientEnv"
>
{{ clientEnvLabel(sc.clientEnv) }}
</a-radio-button>
</a-radio-group>

View File

@@ -20,6 +20,7 @@
CASHIER_ICON_OPTIONS,
CASHIER_TYPE,
RESOLVE_MODE,
cashierTypeRequiresClientEnv,
type CashierType,
} from './shared/constants';
@@ -93,7 +94,9 @@
mchNo: context.value.mchNo,
appId: context.value.appId,
cashierType: context.value.cashierType,
clientEnv: context.value.cashierType === CASHIER_TYPE.H5 ? context.value.clientEnv : undefined,
clientEnv: cashierTypeRequiresClientEnv(context.value.cashierType)
? context.value.clientEnv
: undefined,
name: '',
icon: undefined,
recommend: false,
@@ -294,7 +297,7 @@
mchNo: opts.mchNo,
appId: opts.appId,
cashierType: opts.cashierType,
clientEnv: opts.cashierType === CASHIER_TYPE.H5 ? opts.clientEnv : undefined,
clientEnv: cashierTypeRequiresClientEnv(opts.cashierType) ? opts.clientEnv : undefined,
name: row.name || '',
icon: row.icon || undefined,
recommend: !!row.recommend,
@@ -327,7 +330,9 @@
mchNo: context.value.mchNo,
appId: context.value.appId,
cashierType: context.value.cashierType,
clientEnv: context.value.cashierType === CASHIER_TYPE.H5 ? context.value.clientEnv : undefined,
clientEnv: cashierTypeRequiresClientEnv(context.value.cashierType)
? context.value.clientEnv
: undefined,
recommend: !!formState.value.recommend,
sortNo: formState.value.sortNo ?? 0,
};

View File

@@ -2,6 +2,7 @@
export const CASHIER_TYPE = {
H5: 'h5',
WEB: 'web',
MINI: 'mini',
} as const;
export type CashierType = (typeof CASHIER_TYPE)[keyof typeof CASHIER_TYPE];
@@ -15,7 +16,7 @@ export const RESOLVE_MODE = {
export type ResolveMode = (typeof RESOLVE_MODE)[keyof typeof RESOLVE_MODE];
/**
* H5 客户端环境
* 客户端环境
* clientEnv: 后端 ClientEnvEnum 编码
* provider: 对应支付渠道(用于 DIRECT 候选过滤browser 无固定 provider)
*/
@@ -33,6 +34,30 @@ export const CASHIER_H5_CLIENT_ENVS: ClientEnvConfig[] = [
{ clientEnv: 'douyin', provider: 'douyin' },
];
/** 小程序客户端环境桶(无 browser含微信/支付宝/云闪付/抖音) */
export const CASHIER_MINI_CLIENT_ENVS: ClientEnvConfig[] = [
{ clientEnv: 'wechat_pay', provider: 'wechat' },
{ clientEnv: 'alipay', provider: 'alipay' },
{ clientEnv: 'union_pay', provider: 'union_pay' },
{ clientEnv: 'douyin', provider: 'douyin' },
];
/** 是否按 clientEnv 分桶H5 / MINI */
export function cashierTypeRequiresClientEnv(type: CashierType): boolean {
return type === CASHIER_TYPE.H5 || type === CASHIER_TYPE.MINI;
}
/** 当前类型对应的 clientEnv 二级列表 */
export function clientEnvsForCashierType(type: CashierType): ClientEnvConfig[] {
if (type === CASHIER_TYPE.MINI) {
return CASHIER_MINI_CLIENT_ENVS;
}
if (type === CASHIER_TYPE.H5) {
return CASHIER_H5_CLIENT_ENVS;
}
return [];
}
/**
* 图标选项(值与 PayProviderEnum.code 完全对齐)
* 选支付方式/通道商户时 icon = provider 直接赋值,实现联动