220 lines
5.2 KiB
Vue
220 lines
5.2 KiB
Vue
<template>
|
|
<div v-if="availableApps.length" class="space-y-12">
|
|
<div v-if="publicApps">
|
|
<h2 class="text-sm font-medium leading-6 text-gray-900">
|
|
{{
|
|
!siteOnPublicBench && privateApps
|
|
? '选择市场应用'
|
|
: '选择应用'
|
|
}}
|
|
</h2>
|
|
<div class="mt-2 w-full space-y-2">
|
|
<ObjectList :options="publicApps" />
|
|
</div>
|
|
<SiteAppPlanSelectorDialog
|
|
v-if="selectedApp"
|
|
v-model="showAppPlanSelectorDialog"
|
|
:app="selectedApp"
|
|
@plan-select="
|
|
plan => {
|
|
apps = [...apps, { ...selectedApp, plan }];
|
|
showAppPlanSelectorDialog = false;
|
|
}
|
|
"
|
|
/>
|
|
</div>
|
|
<div v-if="!siteOnPublicBench && privateApps">
|
|
<h2 class="text-sm font-medium leading-6 text-gray-900">
|
|
选择私有应用
|
|
</h2>
|
|
<div class="mt-2 w-full space-y-2">
|
|
<ObjectList :options="privateApps" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { h } from 'vue';
|
|
import DownloadIcon from '~icons/lucide/download';
|
|
import SiteAppPlanSelectorDialog from './SiteAppPlanSelectorDialog.vue';
|
|
import { Badge } from 'jingrow-ui';
|
|
import { icon } from '../../utils/components';
|
|
import ObjectList from '../ObjectList.vue';
|
|
import { toast } from 'vue-sonner';
|
|
|
|
export default {
|
|
props: ['availableApps', 'siteOnPublicBench', 'modelValue'],
|
|
emits: ['update:modelValue'],
|
|
components: {
|
|
ObjectList,
|
|
SiteAppPlanSelectorDialog
|
|
},
|
|
data() {
|
|
return {
|
|
selectedApp: null,
|
|
showAppPlanSelectorDialog: false
|
|
};
|
|
},
|
|
computed: {
|
|
apps: {
|
|
get() {
|
|
return this.modelValue || [];
|
|
},
|
|
set(newApps) {
|
|
this.$emit('update:modelValue', newApps);
|
|
}
|
|
},
|
|
publicApps() {
|
|
if (!this.availableApps) return;
|
|
const publicApps = this.availableApps.filter(
|
|
app => (app.public || app.plans?.length) && app.image
|
|
);
|
|
|
|
if (!publicApps.length) return;
|
|
|
|
this.apps = this.availableApps.filter(app => app.preinstalled === true);
|
|
|
|
return {
|
|
data: () => publicApps,
|
|
columns: [
|
|
{
|
|
label: '应用',
|
|
fieldname: 'app_title',
|
|
type: 'Component',
|
|
component: ({ row }) => {
|
|
return h(
|
|
'a',
|
|
{
|
|
class: 'flex items-center text-sm',
|
|
href: `/${row.route}`,
|
|
target: '_blank'
|
|
},
|
|
[
|
|
h('img', {
|
|
class: 'h-6 w-6 rounded-sm',
|
|
src: row.image
|
|
}),
|
|
h('span', { class: 'ml-2' }, row.title || row.app_title),
|
|
row?.preinstalled
|
|
? h(Badge, {
|
|
class: 'ml-2',
|
|
theme: 'green',
|
|
label: '预装'
|
|
})
|
|
: '',
|
|
row.subscription_type !== 'Free'
|
|
? h(Badge, {
|
|
class: 'ml-2',
|
|
theme: 'gray',
|
|
label: '付费'
|
|
})
|
|
: ''
|
|
]
|
|
);
|
|
}
|
|
},
|
|
{
|
|
label: '安装次数',
|
|
width: 0.2,
|
|
type: 'Component',
|
|
component: ({ row }) => {
|
|
return h(
|
|
'div',
|
|
{
|
|
class: 'flex items-center text-sm text-gray-600'
|
|
},
|
|
[
|
|
h(DownloadIcon, {
|
|
class: 'h-3 w-3'
|
|
}),
|
|
h('span', { class: 'ml-0.5 leading-3' }, [
|
|
this.$format.numberK(row.total_installs || '0')
|
|
])
|
|
]
|
|
);
|
|
}
|
|
},
|
|
{
|
|
label: '',
|
|
width: 0.2,
|
|
align: 'right',
|
|
type: 'Button',
|
|
Button: ({ row: app }) => {
|
|
const isAppAdded = this.apps.map(a => a.app).includes(app.app);
|
|
|
|
return {
|
|
label: isAppAdded ? 'check' : 'plus',
|
|
slots: {
|
|
icon: isAppAdded ? icon('check') : icon('plus')
|
|
},
|
|
variant: isAppAdded ? 'outline' : 'subtle',
|
|
onClick: event => {
|
|
this.toggleApp(app);
|
|
event.stopPropagation();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
]
|
|
};
|
|
},
|
|
privateApps() {
|
|
if (!this.availableApps) return;
|
|
|
|
let privateApps = this.availableApps.filter(
|
|
app => !((app.public || app.plans?.length) && app.image)
|
|
);
|
|
|
|
if (privateApps.length === 0) return;
|
|
|
|
return {
|
|
data: () => privateApps,
|
|
columns: [
|
|
{
|
|
label: '应用',
|
|
fieldname: 'app_title'
|
|
},
|
|
{
|
|
label: '',
|
|
align: 'right',
|
|
type: 'Button',
|
|
Button: ({ row: app }) => {
|
|
const isAppAdded = this.apps
|
|
.map(a => a.app)
|
|
.includes(app.app || app.app_title);
|
|
return {
|
|
label: '添加',
|
|
slots: {
|
|
icon: isAppAdded ? icon('check') : icon('plus')
|
|
},
|
|
variant: isAppAdded ? 'outline' : 'subtle',
|
|
onClick: event => {
|
|
this.toggleApp(app);
|
|
event.stopPropagation();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
]
|
|
};
|
|
}
|
|
},
|
|
methods: {
|
|
toggleApp(app) {
|
|
if (app.preinstalled) {
|
|
toast.error(app.title + ' 是预安装的,无法移除');
|
|
} else if (this.apps.map(a => a.app).includes(app.app)) {
|
|
this.apps = this.apps.filter(a => a.app !== app.app);
|
|
} else {
|
|
if (app.subscription_type && app.subscription_type !== 'Free') {
|
|
this.selectedApp = app;
|
|
this.showAppPlanSelectorDialog = true;
|
|
} else {
|
|
this.apps = [...this.apps, app];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
</script> |