237 lines
6.2 KiB
Vue
237 lines
6.2 KiB
Vue
<template>
|
||
<Dialog
|
||
v-model="show"
|
||
:options="{
|
||
title: '在您的站点上安装应用',
|
||
size: '4xl'
|
||
}"
|
||
>
|
||
<template #body-content>
|
||
<ObjectList :options="listOptions" />
|
||
</template>
|
||
</Dialog>
|
||
</template>
|
||
|
||
<script>
|
||
import { getCachedDocumentResource, createResource } from 'jingrow-ui';
|
||
import { defineAsyncComponent, h } from 'vue';
|
||
import { toast } from 'vue-sonner';
|
||
import { renderDialog } from '../../utils/components';
|
||
import router from '../../router';
|
||
import ObjectList from '../ObjectList.vue';
|
||
import { getToastErrorMessage } from '../../utils/toast';
|
||
|
||
export default {
|
||
props: {
|
||
site: {
|
||
type: String,
|
||
required: true
|
||
}
|
||
},
|
||
emits: ['installed'],
|
||
components: {
|
||
ObjectList
|
||
},
|
||
data() {
|
||
return {
|
||
show: true,
|
||
currentApp: null,
|
||
retryCount: 0
|
||
};
|
||
},
|
||
resources: {
|
||
// 添加API资源定义:检查应用是否可安装
|
||
checkAppInstallable() {
|
||
return {
|
||
url: 'jcloud.api.site.check_app_installable',
|
||
params: {
|
||
name: this.site,
|
||
app: this.currentApp
|
||
},
|
||
auto: false
|
||
};
|
||
}
|
||
},
|
||
computed: {
|
||
$site() {
|
||
return getCachedDocumentResource('Site', this.site);
|
||
},
|
||
listOptions() {
|
||
const handleInstall = async row => {
|
||
if (this.$site.installApp.loading) return;
|
||
|
||
// 设置当前应用以便资源可以使用
|
||
this.currentApp = row.app;
|
||
this.retryCount = 0
|
||
|
||
// 打印关键变量进行调试
|
||
console.log('=== 安装应用调试信息 ===');
|
||
console.log('站点名称:', this.site);
|
||
console.log('应用ID:', this.currentApp);
|
||
console.log('站点对象:', this.$site);
|
||
console.log('站点plan:', this.$site.pg?.plan);
|
||
console.log('=== 调试信息结束 ===');
|
||
|
||
try {
|
||
// 尝试获取应用安装权限信息,最多重试2次
|
||
let checkResult = null;
|
||
let apiCalled = false;
|
||
|
||
while (!checkResult && this.retryCount < 3) {
|
||
console.log(`正在调用check_app_installable API... (尝试 ${this.retryCount + 1}/3)`);
|
||
apiCalled = true;
|
||
|
||
await this.$resources.checkAppInstallable.submit();
|
||
|
||
console.log('API调用完成,状态:', {
|
||
loading: this.$resources.checkAppInstallable.loading,
|
||
error: this.$resources.checkAppInstallable.error
|
||
});
|
||
|
||
// 获取检查结果
|
||
checkResult = this.$resources.checkAppInstallable.data;
|
||
console.log('API返回结果:', checkResult);
|
||
|
||
// 如果返回结果为null且未达到最大重试次数,等待500ms后重试
|
||
if (!checkResult && this.retryCount < 2) {
|
||
this.retryCount++;
|
||
console.log(`API返回null,将在500ms后重试(${this.retryCount}/2)...`);
|
||
await new Promise(resolve => setTimeout(resolve, 500));
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 检查返回结果是否有效
|
||
if (!checkResult) {
|
||
console.error('API返回结果无效,已达到最大重试次数');
|
||
toast.error('应用安装权限验证失败,安装已取消');
|
||
return;
|
||
}
|
||
|
||
// 检查应用是否可安装
|
||
console.log('应用可安装?', checkResult.installable);
|
||
console.log('required_plan_level:', checkResult.required_plan_level);
|
||
console.log('current_plan_level:', checkResult.current_plan_level);
|
||
|
||
// 如果结果显示不可安装,显示错误信息并退出
|
||
if (checkResult.installable !== true) {
|
||
console.log('应用不可安装,显示错误信息');
|
||
|
||
const subscriptionTypeMap = {
|
||
2: 'Pro',
|
||
3: 'Business',
|
||
4: 'Enterprise',
|
||
5: 'Ultimate'
|
||
};
|
||
|
||
const requiredPlan = subscriptionTypeMap[checkResult.required_plan_level] ||
|
||
`Level ${checkResult.required_plan_level}`;
|
||
|
||
toast.error(`无法安装此应用,需要${requiredPlan}或更高级别的站点计划。请先升级您的站点计划。`);
|
||
return;
|
||
}
|
||
|
||
// 如果可安装,执行安装
|
||
console.log('应用可安装,开始安装流程');
|
||
await toast.promise(
|
||
this.$site.installApp.submit({
|
||
app: row.app
|
||
}),
|
||
{
|
||
loading: '正在创建安装任务...',
|
||
success: jobId => {
|
||
console.log('安装任务创建成功,jobId:', jobId);
|
||
this.$emit('installed');
|
||
this.show = false;
|
||
|
||
try {
|
||
if (jobId) {
|
||
router.push({
|
||
name: 'Site Job',
|
||
params: {
|
||
name: this.site,
|
||
id: String(jobId)
|
||
}
|
||
}).catch(err => {
|
||
console.error('导航到作业页面失败:', err);
|
||
});
|
||
}
|
||
} catch (err) {
|
||
console.error('处理作业ID时出错:', err);
|
||
}
|
||
|
||
return '应用安装任务已创建';
|
||
},
|
||
error: e => {
|
||
console.error('安装过程中出错:', e);
|
||
return getToastErrorMessage(e);
|
||
}
|
||
}
|
||
);
|
||
|
||
} catch (error) {
|
||
console.error('检查应用安装权限失败:', error);
|
||
toast.error('无法验证安装权限,安装已取消');
|
||
}
|
||
};
|
||
|
||
return {
|
||
label: '应用',
|
||
fieldname: 'app',
|
||
fieldtype: 'ListSelection',
|
||
emptyStateMessage:
|
||
'未找到应用' +
|
||
(!this.$site.pg?.group_public
|
||
? '。请从您的工作台添加它们。'
|
||
: ''),
|
||
columns: [
|
||
{
|
||
label: '标题',
|
||
fieldname: 'title',
|
||
class: 'font-medium',
|
||
width: 2,
|
||
format: (value, row) => value || row.app_title
|
||
},
|
||
{
|
||
label: '仓库',
|
||
fieldname: 'repository_owner',
|
||
class: 'text-gray-600',
|
||
width: '10rem'
|
||
},
|
||
{
|
||
label: '版本',
|
||
fieldname: 'branch',
|
||
class: 'text-gray-600',
|
||
width: '20rem'
|
||
},
|
||
{
|
||
label: '',
|
||
fieldname: '',
|
||
align: 'right',
|
||
type: 'Button',
|
||
width: '5rem',
|
||
Button({ row }) {
|
||
return {
|
||
label: '安装',
|
||
onClick: () => {
|
||
handleInstall(row);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
],
|
||
resource: () => {
|
||
return {
|
||
url: 'jcloud.api.site.available_apps',
|
||
params: {
|
||
name: this.site
|
||
},
|
||
auto: true
|
||
};
|
||
}
|
||
};
|
||
}
|
||
}
|
||
};
|
||
</script> |