feat: 租户详情页添加瑞美云配置 Tab
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
- 提供友好的表单界面配置瑞美云连接信息 - 支持保存配置和测试连接 - 私钥加密存储 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -230,8 +230,137 @@ watch(activeTab, (newVal) => {
|
||||
fetchToolConfigs()
|
||||
fetchConfigSchema()
|
||||
}
|
||||
if (newVal === 'ruimeiyun' && !ruimeiyunLoaded.value) {
|
||||
fetchRuimeiyunConfig()
|
||||
}
|
||||
})
|
||||
|
||||
// ========================================
|
||||
// 瑞美云配置
|
||||
// ========================================
|
||||
const ruimeiyunLoading = ref(false)
|
||||
const ruimeiyunLoaded = ref(false)
|
||||
const ruimeiyunTesting = ref(false)
|
||||
const ruimeiyunFormRef = ref(null)
|
||||
const ruimeiyunForm = reactive({
|
||||
base_url: '',
|
||||
account: '',
|
||||
private_key: '',
|
||||
allowed_apis: ''
|
||||
})
|
||||
|
||||
const ruimeiyunRules = {
|
||||
base_url: [{ required: true, message: '请输入睿美云 API 地址', trigger: 'blur' }],
|
||||
account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
|
||||
private_key: [{ required: true, message: '请输入私钥', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
async function fetchRuimeiyunConfig() {
|
||||
ruimeiyunLoading.value = true
|
||||
try {
|
||||
const res = await api.get('/api/tool-configs', {
|
||||
params: { tenant_id: tenantId, tool_code: 'ruimeiyun', size: 100 }
|
||||
})
|
||||
const items = res.data.items || []
|
||||
// 映射配置到表单
|
||||
items.forEach(item => {
|
||||
if (item.config_key === 'ruimeiyun_base_url') {
|
||||
ruimeiyunForm.base_url = item.config_value || ''
|
||||
} else if (item.config_key === 'ruimeiyun_account') {
|
||||
ruimeiyunForm.account = item.config_value || ''
|
||||
} else if (item.config_key === 'ruimeiyun_private_key') {
|
||||
// 加密字段显示占位符
|
||||
ruimeiyunForm.private_key = item.is_encrypted ? '********' : (item.config_value || '')
|
||||
} else if (item.config_key === 'ruimeiyun_allowed_apis') {
|
||||
ruimeiyunForm.allowed_apis = item.config_value || ''
|
||||
}
|
||||
})
|
||||
ruimeiyunLoaded.value = true
|
||||
} catch (e) {
|
||||
console.error('获取瑞美云配置失败:', e)
|
||||
} finally {
|
||||
ruimeiyunLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function saveRuimeiyunConfig() {
|
||||
await ruimeiyunFormRef.value.validate()
|
||||
|
||||
ruimeiyunLoading.value = true
|
||||
try {
|
||||
// 构建配置列表
|
||||
const configs = [
|
||||
{
|
||||
config_type: 'external_api',
|
||||
config_key: 'ruimeiyun_base_url',
|
||||
config_value: ruimeiyunForm.base_url,
|
||||
is_encrypted: 0,
|
||||
description: '睿美云 API 地址'
|
||||
},
|
||||
{
|
||||
config_type: 'external_api',
|
||||
config_key: 'ruimeiyun_account',
|
||||
config_value: ruimeiyunForm.account,
|
||||
is_encrypted: 0,
|
||||
description: '睿美云账号'
|
||||
}
|
||||
]
|
||||
|
||||
// 如果私钥不是占位符,则更新
|
||||
if (ruimeiyunForm.private_key && ruimeiyunForm.private_key !== '********') {
|
||||
configs.push({
|
||||
config_type: 'external_api',
|
||||
config_key: 'ruimeiyun_private_key',
|
||||
config_value: ruimeiyunForm.private_key,
|
||||
is_encrypted: 1,
|
||||
description: '睿美云私钥'
|
||||
})
|
||||
}
|
||||
|
||||
// 如果有接口限制
|
||||
if (ruimeiyunForm.allowed_apis) {
|
||||
configs.push({
|
||||
config_type: 'external_api',
|
||||
config_key: 'ruimeiyun_allowed_apis',
|
||||
config_value: ruimeiyunForm.allowed_apis,
|
||||
is_encrypted: 0,
|
||||
description: '允许调用的接口列表'
|
||||
})
|
||||
}
|
||||
|
||||
await api.post('/api/tool-configs/batch', {
|
||||
tenant_id: tenantId,
|
||||
tool_code: 'ruimeiyun',
|
||||
configs
|
||||
})
|
||||
|
||||
ElMessage.success('保存成功')
|
||||
// 重新加载
|
||||
ruimeiyunLoaded.value = false
|
||||
fetchRuimeiyunConfig()
|
||||
} catch (e) {
|
||||
console.error('保存失败:', e)
|
||||
} finally {
|
||||
ruimeiyunLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function testRuimeiyunConnection() {
|
||||
ruimeiyunTesting.value = true
|
||||
try {
|
||||
const res = await api.get(`/api/ruimeiyun/health/${tenantId}`)
|
||||
if (res.data.status === 'connected') {
|
||||
ElMessage.success(`连接成功!账号: ${res.data.account}`)
|
||||
} else {
|
||||
ElMessage.error(`连接失败: ${res.data.message}`)
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error(`测试失败: ${e.response?.data?.detail || e.message}`)
|
||||
} finally {
|
||||
ruimeiyunTesting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchDetail()
|
||||
})
|
||||
@@ -304,6 +433,73 @@ onMounted(() => {
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 瑞美云配置 Tab -->
|
||||
<el-tab-pane label="瑞美云配置" name="ruimeiyun">
|
||||
<div class="ruimeiyun-container" v-loading="ruimeiyunLoading">
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom: 20px"
|
||||
>
|
||||
<template #title>
|
||||
配置租户的睿美云 TPOS 接口连接信息,配置后可通过 Platform 代理调用睿美云接口
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<el-form
|
||||
ref="ruimeiyunFormRef"
|
||||
:model="ruimeiyunForm"
|
||||
:rules="ruimeiyunRules"
|
||||
label-width="120px"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
<el-form-item label="API 地址" prop="base_url">
|
||||
<el-input
|
||||
v-model="ruimeiyunForm.base_url"
|
||||
placeholder="例如: https://xxx.ruimeiyun.com"
|
||||
/>
|
||||
<div class="form-hint">睿美云 TPOS 接口的基础地址</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="账号" prop="account">
|
||||
<el-input
|
||||
v-model="ruimeiyunForm.account"
|
||||
placeholder="TPOS 接口账号"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="私钥" prop="private_key">
|
||||
<el-input
|
||||
v-model="ruimeiyunForm.private_key"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="RSA 私钥(PEM 格式)"
|
||||
/>
|
||||
<div class="form-hint">用于 TPOS 接口签名的 RSA 私钥,将加密存储</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="接口限制">
|
||||
<el-input
|
||||
v-model="ruimeiyunForm.allowed_apis"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder='可选,JSON 数组格式,例如: ["customer.search", "order.list"]'
|
||||
/>
|
||||
<div class="form-hint">限制租户可调用的接口,留空表示允许所有接口</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="saveRuimeiyunConfig" :loading="ruimeiyunLoading">
|
||||
保存配置
|
||||
</el-button>
|
||||
<el-button @click="testRuimeiyunConnection" :loading="ruimeiyunTesting">
|
||||
测试连接
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 工具配置 Tab -->
|
||||
<el-tab-pane label="工具配置" name="config">
|
||||
<div class="config-container" v-loading="configLoading">
|
||||
@@ -506,4 +702,15 @@ onMounted(() => {
|
||||
color: #909399;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.ruimeiyun-container {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user