mirror of
https://gitee.com/bootx/dax-pay-ui
synced 2026-08-13 07:45:41 +08:00
feat(mobile): 管理端移动端应用配置结构化表单
完善管理端移动应用详情: 微信/支付宝/抖音小程序按平台渲染结构化字段, 支持查看/编辑态与 diffForm 敏感字段保护; 管理端移除公众号, 安卓/iOS 暂灰显。
This commit is contained in:
@@ -26,7 +26,7 @@ export const MobileAppApi = {
|
||||
/**
|
||||
* 查询单条详情
|
||||
*/
|
||||
findById(id: number): Promise<Result<MobileAppResult>> {
|
||||
findById(id: string): Promise<Result<MobileAppResult>> {
|
||||
return defHttp.get({ url: '/admin/mobile-app/get', params: { id } });
|
||||
},
|
||||
|
||||
@@ -40,7 +40,7 @@ export const MobileAppApi = {
|
||||
/**
|
||||
* 更新启用状态
|
||||
*/
|
||||
updateEnabled(id: number, enable: boolean): Promise<Result<void>> {
|
||||
updateEnabled(id: string, enable: boolean): Promise<Result<void>> {
|
||||
return defHttp.post({
|
||||
url: '/admin/mobile-app/update-enabled',
|
||||
params: { id, enable },
|
||||
@@ -56,7 +56,7 @@ export interface MobileAppResult extends BaseEntity {
|
||||
platform?: string;
|
||||
/** 应用名称 */
|
||||
appName?: string;
|
||||
/** 平台特有密钥配置(JSON文本) */
|
||||
/** 平台特有密钥配置(JSON文本, 敏感字段脱敏) */
|
||||
appConfig?: string;
|
||||
/** 消息通知配置(JSON文本) */
|
||||
notifyConfig?: string;
|
||||
@@ -71,7 +71,7 @@ export interface MobileAppResult extends BaseEntity {
|
||||
/** 移动端应用配置保存参数 */
|
||||
export interface MobileAppParam {
|
||||
/** 主键(更新时传) */
|
||||
id?: number;
|
||||
id?: string;
|
||||
/** 端类型 */
|
||||
appType?: string;
|
||||
/** 移动平台 */
|
||||
|
||||
@@ -24,6 +24,32 @@
|
||||
"android": "Android App",
|
||||
"ios": "iOS App"
|
||||
},
|
||||
"fields": {
|
||||
"appId": "AppId",
|
||||
"appIdPlaceholder": "Enter AppId",
|
||||
"appIdRequired": "Please enter AppId",
|
||||
"wxAppId": "Mini Program AppId",
|
||||
"wxAppIdPlaceholder": "Enter WeChat Mini Program AppId",
|
||||
"appSecret": "AppSecret",
|
||||
"appSecretPlaceholder": "Enter AppSecret",
|
||||
"appSecretRequired": "Please enter AppSecret",
|
||||
"wxAppSecret": "Mini Program AppSecret",
|
||||
"wxAppSecretPlaceholder": "Enter WeChat Mini Program AppSecret",
|
||||
"originalId": "Original ID",
|
||||
"originalIdPlaceholder": "Enter original ID (gh_..., optional)",
|
||||
"alipayAppId": "Mini Program AppId",
|
||||
"alipayAppIdPlaceholder": "Enter Alipay Mini Program AppId",
|
||||
"privateKey": "App Private Key",
|
||||
"privateKeyPlaceholder": "Enter app private key",
|
||||
"privateKeyRequired": "Please enter app private key",
|
||||
"alipayPublicKey": "Alipay Public Key",
|
||||
"alipayPublicKeyPlaceholder": "Enter Alipay public key",
|
||||
"alipayPublicKeyRequired": "Please enter Alipay public key",
|
||||
"dyAppId": "Mini Program AppId",
|
||||
"dyAppIdPlaceholder": "Enter Douyin Mini Program AppId",
|
||||
"dyAppSecret": "Mini Program AppSecret",
|
||||
"dyAppSecretPlaceholder": "Enter Douyin Mini Program AppSecret"
|
||||
},
|
||||
"detail": {
|
||||
"back": "Back",
|
||||
"appName": "App Name",
|
||||
@@ -39,6 +65,7 @@
|
||||
"save": "Save",
|
||||
"saveSuccess": "Saved successfully",
|
||||
"notSupportedAppType": "Unsupported app type",
|
||||
"emptyPlatformConfig": "No platform config yet, fill in and save to create"
|
||||
"emptyPlatformConfig": "No platform config yet, fill in and save to create",
|
||||
"platformComingSoon": "This platform is not available yet; will be handled when the APP is ready"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,32 @@
|
||||
"android": "安卓APP",
|
||||
"ios": "iOS APP"
|
||||
},
|
||||
"fields": {
|
||||
"appId": "AppId",
|
||||
"appIdPlaceholder": "请输入 AppId",
|
||||
"appIdRequired": "请输入 AppId",
|
||||
"wxAppId": "小程序 AppId",
|
||||
"wxAppIdPlaceholder": "请输入微信小程序 AppId",
|
||||
"appSecret": "AppSecret",
|
||||
"appSecretPlaceholder": "请输入 AppSecret",
|
||||
"appSecretRequired": "请输入 AppSecret",
|
||||
"wxAppSecret": "小程序 AppSecret",
|
||||
"wxAppSecretPlaceholder": "请输入微信小程序 AppSecret",
|
||||
"originalId": "原始 ID",
|
||||
"originalIdPlaceholder": "请输入小程序原始 ID(gh_ 开头, 可选)",
|
||||
"alipayAppId": "小程序 AppId",
|
||||
"alipayAppIdPlaceholder": "请输入支付宝小程序 AppId",
|
||||
"privateKey": "应用私钥",
|
||||
"privateKeyPlaceholder": "请输入应用私钥",
|
||||
"privateKeyRequired": "请输入应用私钥",
|
||||
"alipayPublicKey": "支付宝公钥",
|
||||
"alipayPublicKeyPlaceholder": "请输入支付宝公钥",
|
||||
"alipayPublicKeyRequired": "请输入支付宝公钥",
|
||||
"dyAppId": "小程序 AppId",
|
||||
"dyAppIdPlaceholder": "请输入抖音小程序 AppId",
|
||||
"dyAppSecret": "小程序 AppSecret",
|
||||
"dyAppSecretPlaceholder": "请输入抖音小程序 AppSecret"
|
||||
},
|
||||
"detail": {
|
||||
"back": "返回",
|
||||
"appName": "应用名称",
|
||||
@@ -39,6 +65,7 @@
|
||||
"save": "保存",
|
||||
"saveSuccess": "保存成功",
|
||||
"notSupportedAppType": "不支持的端类型",
|
||||
"emptyPlatformConfig": "暂无平台配置,填写后保存即可创建"
|
||||
"emptyPlatformConfig": "暂无平台配置,填写后保存即可创建",
|
||||
"platformComingSoon": "该平台配置暂未开放,后续 APP 完善时再处理"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -10,30 +10,75 @@
|
||||
type MobileAppParam,
|
||||
MobileAppApi,
|
||||
} from '#/api/payment/config/mobile-app.api';
|
||||
import { useFormEdit } from '#/hooks/useFormEdit';
|
||||
import { useMessage } from '#/hooks/useMessage';
|
||||
|
||||
defineOptions({ name: 'MobileAppDetail' });
|
||||
|
||||
/** 结构化配置字段(各平台共用, 按平台取用) */
|
||||
interface StructuredConfig {
|
||||
appId: string;
|
||||
appSecret: string;
|
||||
originalId: string;
|
||||
privateKey: string;
|
||||
alipayPublicKey: string;
|
||||
}
|
||||
|
||||
/** 已支持结构化表单的平台 */
|
||||
const STRUCTURED_PLATFORMS = new Set(['wx_mini', 'alipay_mini', 'dy_mini']);
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { message } = useMessage();
|
||||
const { confirm, message } = useMessage();
|
||||
const { diffForm } = useFormEdit();
|
||||
|
||||
const appType = ref((route.params.appType as string) || '');
|
||||
const loading = ref(false);
|
||||
const activePlatform = ref('');
|
||||
const saving = ref(false);
|
||||
// 是否处于编辑状态(参考平台配置 WechatMpAuthConfigForm)
|
||||
const isEditing = ref(false);
|
||||
|
||||
// 各端支持的平台(收银台无H5和APP)
|
||||
const PLATFORMS_BY_APP_TYPE: Record<string, string[]> = {
|
||||
admin: ['wx_h5', 'wx_mini', 'alipay_mini', 'dy_mini', 'android', 'ios'],
|
||||
cashier: ['wx_mini', 'alipay_mini', 'dy_mini'],
|
||||
merchant: ['wx_h5', 'wx_mini', 'alipay_mini', 'dy_mini', 'android', 'ios'],
|
||||
// 各端支持的平台: disabled 表示暂不可用(灰显)
|
||||
const PLATFORMS_BY_APP_TYPE: Record<
|
||||
string,
|
||||
{ disabled?: boolean; platform: string }[]
|
||||
> = {
|
||||
admin: [
|
||||
{ platform: 'wx_mini' },
|
||||
{ platform: 'alipay_mini' },
|
||||
{ platform: 'dy_mini' },
|
||||
{ platform: 'android', disabled: true },
|
||||
{ platform: 'ios', disabled: true },
|
||||
],
|
||||
cashier: [
|
||||
{ platform: 'wx_mini' },
|
||||
{ platform: 'alipay_mini' },
|
||||
{ platform: 'dy_mini' },
|
||||
],
|
||||
// 商户端可配微信公众号; 管理端不配(授权回调域名名额被网关/商户端H5占用)
|
||||
merchant: [
|
||||
{ platform: 'wx_h5' },
|
||||
{ platform: 'wx_mini' },
|
||||
{ platform: 'alipay_mini' },
|
||||
{ platform: 'dy_mini' },
|
||||
{ platform: 'android', disabled: true },
|
||||
{ platform: 'ios', disabled: true },
|
||||
],
|
||||
};
|
||||
|
||||
const platforms = computed(() => PLATFORMS_BY_APP_TYPE[appType.value] || []);
|
||||
const platformItems = computed(
|
||||
() => PLATFORMS_BY_APP_TYPE[appType.value] || [],
|
||||
);
|
||||
const platforms = computed(() =>
|
||||
platformItems.value.map((item) => item.platform),
|
||||
);
|
||||
|
||||
// 各平台表单数据(platform -> formData)
|
||||
const formDataMap = reactive<Record<string, MobileAppParam>>({});
|
||||
// 各平台结构化字段
|
||||
const structuredMap = reactive<Record<string, StructuredConfig>>({});
|
||||
const originalStructuredMap = reactive<Record<string, StructuredConfig>>({});
|
||||
|
||||
// 端标题
|
||||
const appTitle = computed(() => {
|
||||
@@ -43,6 +88,23 @@
|
||||
return $t('payment.config.mobileApp.detail.notSupportedAppType');
|
||||
});
|
||||
|
||||
/**
|
||||
* 判断平台是否暂不可用
|
||||
*/
|
||||
function isPlatformDisabled(platform: string): boolean {
|
||||
return (
|
||||
platformItems.value.find((item) => item.platform === platform)
|
||||
?.disabled === true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为结构化表单平台
|
||||
*/
|
||||
function isStructuredPlatform(platform: string): boolean {
|
||||
return STRUCTURED_PLATFORMS.has(platform);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化某平台的空表单
|
||||
*/
|
||||
@@ -52,51 +114,222 @@
|
||||
platform,
|
||||
appName: '',
|
||||
appConfig: '',
|
||||
bindingEnabled: false,
|
||||
enabled: true,
|
||||
notifyConfig: '',
|
||||
remark: '',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化结构化字段
|
||||
*/
|
||||
function initStructured(): StructuredConfig {
|
||||
return {
|
||||
appId: '',
|
||||
appSecret: '',
|
||||
originalId: '',
|
||||
privateKey: '',
|
||||
alipayPublicKey: '',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 appConfig JSON 解析结构化字段
|
||||
*/
|
||||
function parseStructured(appConfig?: string): StructuredConfig {
|
||||
const result = initStructured();
|
||||
try {
|
||||
if (appConfig) {
|
||||
const cfg = JSON.parse(appConfig) as Record<string, string>;
|
||||
result.appId = cfg.appId || '';
|
||||
result.appSecret = cfg.appSecret || '';
|
||||
result.originalId = cfg.originalId || '';
|
||||
result.privateKey = cfg.privateKey || '';
|
||||
result.alipayPublicKey = cfg.alipayPublicKey || '';
|
||||
}
|
||||
} catch {
|
||||
// 非合法 JSON 时保持空
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按平台序列化 appConfig, 敏感字段仅在 diffForm 有新值时写入
|
||||
*/
|
||||
function serializeByPlatform(
|
||||
platform: string,
|
||||
structured: StructuredConfig,
|
||||
sensitive: Partial<StructuredConfig>,
|
||||
): string {
|
||||
const obj: Record<string, string | undefined> = {
|
||||
appId: structured.appId || undefined,
|
||||
};
|
||||
if (platform === 'wx_mini') {
|
||||
obj.originalId = structured.originalId || undefined;
|
||||
if (sensitive.appSecret !== undefined) {
|
||||
obj.appSecret = sensitive.appSecret;
|
||||
}
|
||||
} else if (platform === 'alipay_mini') {
|
||||
if (sensitive.privateKey !== undefined) {
|
||||
obj.privateKey = sensitive.privateKey;
|
||||
}
|
||||
if (sensitive.alipayPublicKey !== undefined) {
|
||||
obj.alipayPublicKey = sensitive.alipayPublicKey;
|
||||
}
|
||||
} else if (platform === 'dy_mini') {
|
||||
if (sensitive.appSecret !== undefined) {
|
||||
obj.appSecret = sensitive.appSecret;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验结构化表单
|
||||
*/
|
||||
function validateStructured(
|
||||
platform: string,
|
||||
structured: StructuredConfig,
|
||||
original: StructuredConfig,
|
||||
): boolean {
|
||||
if (!structured.appId?.trim()) {
|
||||
message.warning($t('payment.config.mobileApp.fields.appIdRequired'));
|
||||
return false;
|
||||
}
|
||||
if (platform === 'wx_mini' || platform === 'dy_mini') {
|
||||
if (!original.appSecret && !structured.appSecret?.trim()) {
|
||||
message.warning(
|
||||
$t('payment.config.mobileApp.fields.appSecretRequired'),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (platform === 'alipay_mini') {
|
||||
if (!original.privateKey && !structured.privateKey?.trim()) {
|
||||
message.warning(
|
||||
$t('payment.config.mobileApp.fields.privateKeyRequired'),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!original.alipayPublicKey && !structured.alipayPublicKey?.trim()) {
|
||||
message.warning(
|
||||
$t('payment.config.mobileApp.fields.alipayPublicKeyRequired'),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载该端所有平台配置
|
||||
*/
|
||||
async function loadData() {
|
||||
async function loadData(keepPlatform = false) {
|
||||
if (!appType.value || !platforms.value.length) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
// 初始化所有平台为空表单
|
||||
for (const p of platforms.value) {
|
||||
formDataMap[p] = initForm(p);
|
||||
structuredMap[p] = initStructured();
|
||||
originalStructuredMap[p] = initStructured();
|
||||
}
|
||||
// 用后端数据填充已存在的配置
|
||||
const { data } = await MobileAppApi.listByAppType(appType.value);
|
||||
for (const item of data || []) {
|
||||
if (item.platform && formDataMap[item.platform]) {
|
||||
Object.assign(formDataMap[item.platform]!, item);
|
||||
const structured = parseStructured(item.appConfig);
|
||||
structuredMap[item.platform] = { ...structured };
|
||||
originalStructuredMap[item.platform] = { ...structured };
|
||||
}
|
||||
}
|
||||
activePlatform.value = platforms.value[0]!;
|
||||
if (!keepPlatform || !activePlatform.value) {
|
||||
const firstEnabled = platformItems.value.find((item) => !item.disabled);
|
||||
activePlatform.value =
|
||||
firstEnabled?.platform || platforms.value[0] || '';
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进入编辑模式
|
||||
*/
|
||||
function handleEdit() {
|
||||
if (isPlatformDisabled(activePlatform.value)) return;
|
||||
isEditing.value = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消编辑, 重新加载数据
|
||||
*/
|
||||
function handleCancel() {
|
||||
confirm({
|
||||
title: $t('common.confirm'),
|
||||
content: $t('common.confirmCancelContent'),
|
||||
okText: $t('common.okText'),
|
||||
cancelText: $t('common.cancelText'),
|
||||
onOk: async () => {
|
||||
isEditing.value = false;
|
||||
await loadData(true);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存当前平台配置
|
||||
*/
|
||||
async function handleSave() {
|
||||
const form = formDataMap[activePlatform.value];
|
||||
const platform = activePlatform.value;
|
||||
if (isPlatformDisabled(platform) || !isEditing.value) return;
|
||||
const form = formDataMap[platform];
|
||||
if (!form) return;
|
||||
saving.value = true;
|
||||
try {
|
||||
await MobileAppApi.save(form);
|
||||
message.success($t('payment.config.mobileApp.detail.saveSuccess'));
|
||||
await loadData();
|
||||
} finally {
|
||||
saving.value = false;
|
||||
|
||||
let submit: MobileAppParam = {
|
||||
...form,
|
||||
appType: appType.value,
|
||||
platform,
|
||||
};
|
||||
|
||||
if (isStructuredPlatform(platform)) {
|
||||
const structured = structuredMap[platform];
|
||||
const originalStructured = originalStructuredMap[platform];
|
||||
if (!structured || !originalStructured) return;
|
||||
if (!validateStructured(platform, structured, originalStructured)) {
|
||||
return;
|
||||
}
|
||||
// 按平台敏感字段做 diffForm
|
||||
const sensitiveKeys =
|
||||
platform === 'alipay_mini'
|
||||
? (['privateKey', 'alipayPublicKey'] as const)
|
||||
: (['appSecret'] as const);
|
||||
const sensitive = diffForm(
|
||||
originalStructured,
|
||||
structured,
|
||||
...sensitiveKeys,
|
||||
);
|
||||
submit = {
|
||||
...submit,
|
||||
appConfig: serializeByPlatform(platform, structured, sensitive),
|
||||
};
|
||||
}
|
||||
|
||||
confirm({
|
||||
title: $t('common.confirm'),
|
||||
content: $t('common.confirmSaveContent'),
|
||||
okText: $t('common.okText'),
|
||||
cancelText: $t('common.cancelText'),
|
||||
onOk: async () => {
|
||||
saving.value = true;
|
||||
try {
|
||||
await MobileAppApi.save(submit);
|
||||
message.success($t('payment.config.mobileApp.detail.saveSuccess'));
|
||||
isEditing.value = false;
|
||||
await loadData(true);
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,6 +339,15 @@
|
||||
router.push({ path: '/payment/config/mobile-app' });
|
||||
}
|
||||
|
||||
// 切 Tab 时退出编辑并重载, 避免脏数据串平台
|
||||
watch(activePlatform, async (next, prev) => {
|
||||
if (!prev || next === prev) return;
|
||||
if (isEditing.value) {
|
||||
isEditing.value = false;
|
||||
await loadData(true);
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
@@ -134,83 +376,193 @@
|
||||
|
||||
<a-spin :spinning="loading">
|
||||
<a-tabs v-model:active-key="activePlatform">
|
||||
<a-tab-pane
|
||||
v-for="p in platforms"
|
||||
:key="p"
|
||||
:tab="$t(`payment.config.mobileApp.platformNames.${p}`)"
|
||||
>
|
||||
<a-form
|
||||
v-if="formDataMap[p]"
|
||||
:model="formDataMap[p]"
|
||||
layout="vertical"
|
||||
class="max-w-2xl"
|
||||
>
|
||||
<a-form-item :label="$t('payment.config.mobileApp.detail.appName')">
|
||||
<a-input
|
||||
v-model:value="formDataMap[p]!.appName"
|
||||
:placeholder="
|
||||
$t('payment.config.mobileApp.detail.appNamePlaceholder')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.detail.appConfig')"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="formDataMap[p]!.appConfig"
|
||||
:rows="6"
|
||||
:placeholder="
|
||||
$t('payment.config.mobileApp.detail.appConfigPlaceholder')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.detail.notifyConfig')"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="formDataMap[p]!.notifyConfig"
|
||||
:rows="4"
|
||||
:placeholder="
|
||||
$t('payment.config.mobileApp.detail.notifyConfigPlaceholder')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<template #label>
|
||||
{{ $t('payment.config.mobileApp.detail.bindingEnabled') }}
|
||||
</template>
|
||||
<a-switch v-model:checked="formDataMap[p]!.bindingEnabled" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<template #label>
|
||||
{{ $t('payment.config.mobileApp.detail.enabled') }}
|
||||
</template>
|
||||
<a-switch v-model:checked="formDataMap[p]!.enabled" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :label="$t('payment.config.mobileApp.detail.remark')">
|
||||
<a-textarea
|
||||
v-model:value="formDataMap[p]!.remark"
|
||||
:rows="2"
|
||||
:placeholder="
|
||||
$t('payment.config.mobileApp.detail.remarkPlaceholder')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<!-- Tabs 右侧: 编辑 / 取消+保存 -->
|
||||
<template #rightExtra>
|
||||
<a-space v-if="!isPlatformDisabled(activePlatform)">
|
||||
<template v-if="!isEditing">
|
||||
<a-button type="primary" @click="handleEdit">
|
||||
{{ $t('common.edit') }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-button @click="handleCancel">
|
||||
{{ $t('common.cancel') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="saving"
|
||||
@click="handleSave"
|
||||
>
|
||||
{{ $t('payment.config.mobileApp.detail.save') }}
|
||||
{{ $t('common.save') }}
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<a-tab-pane
|
||||
v-for="item in platformItems"
|
||||
:key="item.platform"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<template #tab>
|
||||
<span :class="{ 'opacity-50': item.disabled }">
|
||||
{{
|
||||
$t(`payment.config.mobileApp.platformNames.${item.platform}`)
|
||||
}}
|
||||
<a-tag
|
||||
v-if="item.disabled"
|
||||
color="orange"
|
||||
class="ml-1"
|
||||
style="font-size: 11px; line-height: 18px"
|
||||
>
|
||||
{{ $t('payment.config.mobileApp.card.comingSoon') }}
|
||||
</a-tag>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<!-- 暂不可用平台 -->
|
||||
<a-empty
|
||||
v-if="item.disabled"
|
||||
:description="
|
||||
$t('payment.config.mobileApp.detail.platformComingSoon')
|
||||
"
|
||||
/>
|
||||
|
||||
<!-- 结构化表单: wx_mini / alipay_mini / dy_mini -->
|
||||
<a-form
|
||||
v-else-if="
|
||||
isStructuredPlatform(item.platform) &&
|
||||
formDataMap[item.platform] &&
|
||||
structuredMap[item.platform]
|
||||
"
|
||||
:model="formDataMap[item.platform]"
|
||||
layout="vertical"
|
||||
class="max-w-2xl"
|
||||
>
|
||||
<!-- 微信小程序 -->
|
||||
<template v-if="item.platform === 'wx_mini'">
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.wxAppId')"
|
||||
required
|
||||
>
|
||||
<a-input
|
||||
v-model:value="structuredMap[item.platform]!.appId"
|
||||
:disabled="!isEditing"
|
||||
:placeholder="
|
||||
$t('payment.config.mobileApp.fields.wxAppIdPlaceholder')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.wxAppSecret')"
|
||||
required
|
||||
>
|
||||
<a-input
|
||||
v-model:value="structuredMap[item.platform]!.appSecret"
|
||||
:disabled="!isEditing"
|
||||
allow-clear
|
||||
:placeholder="
|
||||
$t(
|
||||
'payment.config.mobileApp.fields.wxAppSecretPlaceholder',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.originalId')"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="structuredMap[item.platform]!.originalId"
|
||||
:disabled="!isEditing"
|
||||
:placeholder="
|
||||
$t(
|
||||
'payment.config.mobileApp.fields.originalIdPlaceholder',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 支付宝小程序 -->
|
||||
<template v-else-if="item.platform === 'alipay_mini'">
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.alipayAppId')"
|
||||
required
|
||||
>
|
||||
<a-input
|
||||
v-model:value="structuredMap[item.platform]!.appId"
|
||||
:disabled="!isEditing"
|
||||
:placeholder="
|
||||
$t(
|
||||
'payment.config.mobileApp.fields.alipayAppIdPlaceholder',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.privateKey')"
|
||||
required
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="structuredMap[item.platform]!.privateKey"
|
||||
:disabled="!isEditing"
|
||||
:rows="4"
|
||||
:placeholder="
|
||||
$t(
|
||||
'payment.config.mobileApp.fields.privateKeyPlaceholder',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.alipayPublicKey')"
|
||||
required
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="
|
||||
structuredMap[item.platform]!.alipayPublicKey
|
||||
"
|
||||
:disabled="!isEditing"
|
||||
:rows="4"
|
||||
:placeholder="
|
||||
$t(
|
||||
'payment.config.mobileApp.fields.alipayPublicKeyPlaceholder',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 抖音小程序 -->
|
||||
<template v-else-if="item.platform === 'dy_mini'">
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.dyAppId')"
|
||||
required
|
||||
>
|
||||
<a-input
|
||||
v-model:value="structuredMap[item.platform]!.appId"
|
||||
:disabled="!isEditing"
|
||||
:placeholder="
|
||||
$t('payment.config.mobileApp.fields.dyAppIdPlaceholder')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('payment.config.mobileApp.fields.dyAppSecret')"
|
||||
required
|
||||
>
|
||||
<a-input
|
||||
v-model:value="structuredMap[item.platform]!.appSecret"
|
||||
:disabled="!isEditing"
|
||||
allow-clear
|
||||
:placeholder="
|
||||
$t(
|
||||
'payment.config.mobileApp.fields.dyAppSecretPlaceholder',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
Reference in New Issue
Block a user