1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-14 01:34:47 +08:00

feat: 应用商店支持使用自定的应用包 (#6697)

This commit is contained in:
zhengkunwang 2024-10-14 10:37:34 +08:00 committed by GitHub
parent 72311617d9
commit 07bdcdc91b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 227 additions and 74 deletions

View File

@ -45,6 +45,7 @@ type AppDto struct {
Github string `json:"github"` Github string `json:"github"`
Website string `json:"website"` Website string `json:"website"`
GpuSupport bool `json:"gpuSupport"` GpuSupport bool `json:"gpuSupport"`
Recommend int `json:"recommend"`
} }
type TagDTO struct { type TagDTO struct {

View File

@ -30,6 +30,7 @@ type IAppRepo interface {
Create(ctx context.Context, app *model.App) error Create(ctx context.Context, app *model.App) error
Save(ctx context.Context, app *model.App) error Save(ctx context.Context, app *model.App) error
BatchDelete(ctx context.Context, apps []model.App) error BatchDelete(ctx context.Context, apps []model.App) error
DeleteByIDs(ctx context.Context, ids []uint) error
} }
func NewIAppRepo() IAppRepo { func NewIAppRepo() IAppRepo {
@ -91,7 +92,7 @@ func (a AppRepo) Page(page, size int, opts ...DBOption) (int64, []model.App, err
var apps []model.App var apps []model.App
db := getDb(opts...).Model(&model.App{}) db := getDb(opts...).Model(&model.App{})
count := int64(0) count := int64(0)
db = db.Count(&count) db = db.Count(&count).Debug()
err := db.Limit(size).Offset(size * (page - 1)).Preload("AppTags").Find(&apps).Error err := db.Limit(size).Offset(size * (page - 1)).Preload("AppTags").Find(&apps).Error
return count, apps, err return count, apps, err
} }
@ -137,3 +138,7 @@ func (a AppRepo) Save(ctx context.Context, app *model.App) error {
func (a AppRepo) BatchDelete(ctx context.Context, apps []model.App) error { func (a AppRepo) BatchDelete(ctx context.Context, apps []model.App) error {
return getTx(ctx).Omit(clause.Associations).Delete(&apps).Error return getTx(ctx).Omit(clause.Associations).Delete(&apps).Error
} }
func (a AppRepo) DeleteByIDs(ctx context.Context, ids []uint) error {
return getTx(ctx).Where("id in (?)", ids).Delete(&model.App{}).Error
}

View File

@ -19,6 +19,7 @@ type IAppDetailRepo interface {
Update(ctx context.Context, detail model.AppDetail) error Update(ctx context.Context, detail model.AppDetail) error
BatchCreate(ctx context.Context, details []model.AppDetail) error BatchCreate(ctx context.Context, details []model.AppDetail) error
DeleteByAppIds(ctx context.Context, appIds []uint) error DeleteByAppIds(ctx context.Context, appIds []uint) error
DeleteByIDs(ctx context.Context, appIds []uint) error
GetBy(opts ...DBOption) ([]model.AppDetail, error) GetBy(opts ...DBOption) ([]model.AppDetail, error)
BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error
BatchDelete(ctx context.Context, appDetails []model.AppDetail) error BatchDelete(ctx context.Context, appDetails []model.AppDetail) error
@ -64,6 +65,10 @@ func (a AppDetailRepo) DeleteByAppIds(ctx context.Context, appIds []uint) error
return getTx(ctx).Where("app_id in (?)", appIds).Delete(&model.AppDetail{}).Error return getTx(ctx).Where("app_id in (?)", appIds).Delete(&model.AppDetail{}).Error
} }
func (a AppDetailRepo) DeleteByIDs(ctx context.Context, appIds []uint) error {
return getTx(ctx).Where("id in (?)", appIds).Delete(&model.AppDetail{}).Error
}
func (a AppDetailRepo) GetBy(opts ...DBOption) ([]model.AppDetail, error) { func (a AppDetailRepo) GetBy(opts ...DBOption) ([]model.AppDetail, error) {
var details []model.AppDetail var details []model.AppDetail
err := getDb(opts...).Find(&details).Error err := getDb(opts...).Find(&details).Error

View File

@ -2,6 +2,7 @@ package repo
import ( import (
"context" "context"
"gorm.io/gorm"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
) )
@ -15,12 +16,21 @@ type IAppTagRepo interface {
DeleteAll(ctx context.Context) error DeleteAll(ctx context.Context) error
GetByAppId(appId uint) ([]model.AppTag, error) GetByAppId(appId uint) ([]model.AppTag, error)
GetByTagIds(tagIds []uint) ([]model.AppTag, error) GetByTagIds(tagIds []uint) ([]model.AppTag, error)
DeleteBy(ctx context.Context, opts ...DBOption) error
WithByTagID(tagID uint) DBOption
} }
func NewIAppTagRepo() IAppTagRepo { func NewIAppTagRepo() IAppTagRepo {
return &AppTagRepo{} return &AppTagRepo{}
} }
func (a AppTagRepo) WithByTagID(tagID uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("tag_id = ?", tagID)
}
}
func (a AppTagRepo) BatchCreate(ctx context.Context, tags []*model.AppTag) error { func (a AppTagRepo) BatchCreate(ctx context.Context, tags []*model.AppTag) error {
return getTx(ctx).Create(&tags).Error return getTx(ctx).Create(&tags).Error
} }
@ -48,3 +58,7 @@ func (a AppTagRepo) GetByTagIds(tagIds []uint) ([]model.AppTag, error) {
} }
return appTags, nil return appTags, nil
} }
func (a AppTagRepo) DeleteBy(ctx context.Context, opts ...DBOption) error {
return getTx(ctx, opts...).Delete(&model.AppTag{}).Error
}

View File

@ -16,6 +16,9 @@ type ITagRepo interface {
GetByIds(ids []uint) ([]model.Tag, error) GetByIds(ids []uint) ([]model.Tag, error)
GetByKeys(keys []string) ([]model.Tag, error) GetByKeys(keys []string) ([]model.Tag, error)
GetByAppId(appId uint) ([]model.Tag, error) GetByAppId(appId uint) ([]model.Tag, error)
DeleteByID(ctx context.Context, id uint) error
Create(ctx context.Context, tag *model.Tag) error
Save(ctx context.Context, tag *model.Tag) error
} }
func NewITagRepo() ITagRepo { func NewITagRepo() ITagRepo {
@ -61,3 +64,15 @@ func (t TagRepo) GetByAppId(appId uint) ([]model.Tag, error) {
} }
return tags, nil return tags, nil
} }
func (t TagRepo) DeleteByID(ctx context.Context, id uint) error {
return getTx(ctx).Where("id = ?", id).Delete(&model.Tag{}).Error
}
func (t TagRepo) Create(ctx context.Context, tag *model.Tag) error {
return getTx(ctx).Create(tag).Error
}
func (t TagRepo) Save(ctx context.Context, tag *model.Tag) error {
return getTx(ctx).Save(tag).Error
}

View File

@ -120,6 +120,7 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
Website: ap.Website, Website: ap.Website,
Github: ap.Github, Github: ap.Github,
GpuSupport: ap.GpuSupport, GpuSupport: ap.GpuSupport,
Recommend: ap.Recommend,
} }
appDTOs = append(appDTOs, appDTO) appDTOs = append(appDTOs, appDTO)
appTags, err := appTagRepo.GetByAppId(ap.ID) appTags, err := appTagRepo.GetByAppId(ap.ID)

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"github.com/1Panel-dev/1Panel/agent/utils/nginx" "github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser" "github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"log" "log"
"math" "math"
"net/http" "net/http"
@ -403,27 +404,6 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
} }
switch install.App.Key { switch install.App.Key {
case constant.AppOpenresty:
//TODO 删除 Openresty 不再删除网站
//websites, _ := websiteRepo.List()
//for _, website := range websites {
// if website.AppInstallID > 0 {
// websiteAppInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
// if websiteAppInstall.AppId > 0 {
// websiteApp, _ := appRepo.GetFirst(commonRepo.WithByID(websiteAppInstall.AppId))
// if websiteApp.Type == constant.RuntimePHP {
// go func() {
// _, _ = compose.Down(websiteAppInstall.GetComposePath())
// _ = op.DeleteDir(websiteAppInstall.GetPath())
// }()
// _ = appInstallRepo.Delete(ctx, websiteAppInstall)
// }
// }
// }
//}
//_ = websiteRepo.DeleteAll(ctx)
//_ = websiteDomainRepo.DeleteAll(ctx)
//xpack.RemoveTamper("")
case constant.AppMysql, constant.AppMariaDB: case constant.AppMysql, constant.AppMariaDB:
_ = mysqlRepo.Delete(ctx, mysqlRepo.WithByMysqlName(install.Name)) _ = mysqlRepo.Delete(ctx, mysqlRepo.WithByMysqlName(install.Name))
case constant.AppPostgresql: case constant.AppPostgresql:
@ -1045,7 +1025,15 @@ func upApp(task *task.Task, appInstall *model.AppInstall, pullImages bool) {
if err != nil { if err != nil {
return err return err
} }
imagePrefix := xpack.GetImagePrefix()
for _, image := range images { for _, image := range images {
if imagePrefix != "" {
lastSlashIndex := strings.LastIndex(image, "/")
if lastSlashIndex != -1 {
image = image[lastSlashIndex+1:]
}
image = imagePrefix + "/" + image
}
task.Log(i18n.GetWithName("PullImageStart", image)) task.Log(i18n.GetWithName("PullImageStart", image))
if out, err = cmd.ExecWithTimeOut("docker pull "+image, 20*time.Minute); err != nil { if out, err = cmd.ExecWithTimeOut("docker pull "+image, 20*time.Minute); err != nil {
if out != "" { if out != "" {
@ -1555,6 +1543,22 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
if !serviceValid { if !serviceValid {
return buserr.New(constant.ErrFileParse) return buserr.New(constant.ErrFileParse)
} }
imagePreFix := xpack.GetImagePrefix()
if imagePreFix != "" {
for _, service := range services {
serviceValue := service.(map[string]interface{})
if image, ok := serviceValue["image"]; ok {
imageStr := image.(string)
lastSlashIndex := strings.LastIndex(imageStr, "/")
if lastSlashIndex != -1 {
imageStr = imageStr[lastSlashIndex+1:]
}
imageStr = imagePreFix + "/" + imageStr
serviceValue["image"] = imageStr
}
}
}
service, serviceExist := services[serviceName] service, serviceExist := services[serviceName]
if !serviceExist { if !serviceExist {
return buserr.New(constant.ErrFileParse) return buserr.New(constant.ErrFileParse)

View File

@ -70,7 +70,11 @@ MoveSiteDir: "The current upgrade requires migrating the OpenResty website direc
MoveSiteToDir: "Migrate the website directory to {{ .name }}" MoveSiteToDir: "Migrate the website directory to {{ .name }}"
ErrMoveSiteDir: "Failed to migrate the website directory" ErrMoveSiteDir: "Failed to migrate the website directory"
MoveSiteDirSuccess: "Successfully migrated the website directory" MoveSiteDirSuccess: "Successfully migrated the website directory"
DeleteRuntimePHP: "Delete PHP runtime environment" DeleteRuntimePHP: "Delete PHP runtime environment",
CustomAppStoreNotConfig: "Please configure the offline package address in the app store settings",
CustomAppStoreNotFound: "Failed to retrieve app store package, please check if it exists",
CustomAppStoreFileValid: "App store package must be in .tar.gz format"
#file #file
ErrFileCanNotRead: "File can not read" ErrFileCanNotRead: "File can not read"

View File

@ -71,7 +71,11 @@ MoveSiteDir: "當前升級需要遷移 OpenResty 網站目錄"
MoveSiteToDir: "遷移網站目錄到 {{ .name }}" MoveSiteToDir: "遷移網站目錄到 {{ .name }}"
ErrMoveSiteDir: "遷移網站目錄失敗" ErrMoveSiteDir: "遷移網站目錄失敗"
MoveSiteDirSuccess: "遷移網站目錄成功" MoveSiteDirSuccess: "遷移網站目錄成功"
DeleteRuntimePHP: "刪除運行環境 PHP 版本" DeleteRuntimePHP: "刪除運行環境 PHP 版本",
CustomAppStoreNotConfig: "請在應用商店設置離線包地址",
CustomAppStoreNotFound: "應用商店包獲取失敗,請檢查是否存在",
CustomAppStoreFileValid: "應用商店包需要 .tar.gz 格式"
#file #file
ErrFileCanNotRead: "此文件不支持預覽" ErrFileCanNotRead: "此文件不支持預覽"

View File

@ -71,6 +71,9 @@ MoveSiteToDir: "迁移网站目录到 {{ .name }}"
ErrMoveSiteDir: "迁移网站目录失败" ErrMoveSiteDir: "迁移网站目录失败"
MoveSiteDirSuccess: "迁移网站目录成功" MoveSiteDirSuccess: "迁移网站目录成功"
DeleteRuntimePHP: "删除 PHP 运行环境" DeleteRuntimePHP: "删除 PHP 运行环境"
CustomAppStoreNotConfig: "请在应用商店设置离线包地址"
CustomAppStoreNotFound: "应用商店包获取失败,请检查是否存在"
CustomAppStoreFileValid: "应用商店包需要 .tar.gz 格式"
#file #file
ErrFileCanNotRead: "此文件不支持预览" ErrFileCanNotRead: "此文件不支持预览"

View File

@ -43,3 +43,7 @@ func InitNodeData(tx *gorm.DB) (bool, string, error) { return true, "127.0.0.1",
func RequestToMaster(reqUrl, reqMethod string, reqBody io.Reader) (interface{}, error) { func RequestToMaster(reqUrl, reqMethod string, reqBody io.Reader) (interface{}, error) {
return nil, nil return nil, nil
} }
func GetImagePrefix() string {
return ""
}

View File

@ -118,3 +118,7 @@ export const GetAppStoreConfig = () => {
export const UpdateAppStoreConfig = (req: App.AppStoreConfig) => { export const UpdateAppStoreConfig = (req: App.AppStoreConfig) => {
return http.post(`apps/store/update`, req); return http.post(`apps/store/update`, req);
}; };
export const SyncCutomAppStore = (req: App.AppStoreSync) => {
return http.post(`/custom/app/sync`, req);
};

View File

@ -175,7 +175,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { App } from '@/api/interface/app'; import { App } from '@/api/interface/app';
import { onMounted, reactive, ref, computed } from 'vue'; import { onMounted, reactive, ref, computed } from 'vue';
import { GetAppTags, SearchApp, SyncApp, SyncLocalApp } from '@/api/modules/app'; import { GetAppTags, SearchApp, SyncApp, SyncCutomAppStore, SyncLocalApp } from '@/api/modules/app';
import Install from '../detail/install/index.vue'; import Install from '../detail/install/index.vue';
import router from '@/routers'; import router from '@/routers';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
@ -183,8 +183,11 @@ import { GlobalStore } from '@/store';
import { getLanguage, newUUID } from '@/utils/util'; import { getLanguage, newUUID } from '@/utils/util';
import Detail from '../detail/index.vue'; import Detail from '../detail/index.vue';
import TaskLog from '@/components/task-log/index.vue'; import TaskLog from '@/components/task-log/index.vue';
import { storeToRefs } from 'pinia';
import { GetCustomAppStoreConfig } from '@/xpack/api/modules/app';
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const { isProductPro } = storeToRefs(globalStore);
const mobile = computed(() => { const mobile = computed(() => {
return globalStore.isMobile(); return globalStore.isMobile();
@ -221,6 +224,7 @@ const moreTag = ref('');
const mainHeight = ref(0); const mainHeight = ref(0);
const detailRef = ref(); const detailRef = ref();
const taskLogRef = ref(); const taskLogRef = ref();
const syncCustomAppstore = ref(false);
const search = async (req: App.AppReq) => { const search = async (req: App.AppReq) => {
loading.value = true; loading.value = true;
@ -265,25 +269,29 @@ const openTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID); taskLogRef.value.openWithTaskID(taskID);
}; };
const sync = () => { const sync = async () => {
syncing.value = true; syncing.value = true;
const taskID = newUUID(); const taskID = newUUID();
const syncReq = { const syncReq = {
taskID: taskID, taskID: taskID,
}; };
SyncApp(syncReq) try {
.then((res) => { let res;
if (res.message != '') { if (isProductPro.value && syncCustomAppstore.value) {
MsgSuccess(res.message); res = await SyncCutomAppStore(syncReq);
} else { } else {
openTaskLog(taskID); res = await SyncApp(syncReq);
} }
canUpdate.value = false; if (res.message != '') {
search(req); MsgSuccess(res.message);
}) } else {
.finally(() => { openTaskLog(taskID);
syncing.value = false; }
}); canUpdate.value = false;
search(req);
} finally {
syncing.value = false;
}
}; };
const syncLocal = () => { const syncLocal = () => {
@ -329,7 +337,7 @@ const searchByName = () => {
search(req); search(req);
}; };
onMounted(() => { onMounted(async () => {
if (router.currentRoute.value.query.install) { if (router.currentRoute.value.query.install) {
installKey.value = String(router.currentRoute.value.query.install); installKey.value = String(router.currentRoute.value.query.install);
const params = { const params = {
@ -340,6 +348,12 @@ onMounted(() => {
installRef.value.acceptParams(params); installRef.value.acceptParams(params);
} }
search(req); search(req);
if (isProductPro.value) {
const res = await GetCustomAppStoreConfig();
if (res && res.data) {
syncCustomAppstore.value = res.data.status === 'enable';
}
}
mainHeight.value = window.innerHeight - 380; mainHeight.value = window.innerHeight - 380;
window.onresize = () => { window.onresize = () => {
return (() => { return (() => {

View File

@ -0,0 +1,87 @@
<template>
<DrawerPro v-model="drawerVisible" :header="$t('app.defaultWebDomain')" :back="handleClose" size="small">
<el-form ref="formRef" label-position="top" :model="form" :rules="rules" @submit.prevent v-loading="loading">
<el-form-item :label="$t('app.defaultWebDomain')" prop="defaultDomain">
<el-input v-model="form.defaultDomain">
<template #prepend>
<el-select v-model="protocol" placeholder="Select" class="p-w-100">
<el-option label="HTTP" value="http://" />
<el-option label="HTTPS" value="https://" />
</el-select>
</template>
</el-input>
<span class="input-help">{{ $t('app.defaultWebDomainHepler') }}</span>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose()">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="submit()">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</DrawerPro>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import i18n from '@/lang';
import { FormInstance } from 'element-plus';
import { Rules } from '@/global/form-rules';
import { UpdateAppStoreConfig } from '@/api/modules/app';
import { MsgSuccess } from '@/utils/message';
const emit = defineEmits<{ (e: 'close'): void }>();
const drawerVisible = ref();
const loading = ref();
const form = reactive({
defaultDomain: '',
});
const rules = reactive({
defaultDomain: [Rules.requiredInput],
});
const formRef = ref<FormInstance>();
const protocol = ref('http://');
interface DialogProps {
protocol: string;
domain: string;
}
const acceptParams = (config: DialogProps): void => {
form.defaultDomain = config.domain;
protocol.value;
drawerVisible.value = true;
};
const handleClose = () => {
drawerVisible.value = false;
emit('close');
};
const submit = async () => {
if (!formRef.value) return;
await formRef.value.validate(async (valid) => {
if (!valid) {
return;
}
loading.value = true;
try {
let defaultDomain = '';
if (form.defaultDomain) {
defaultDomain = protocol.value + form.defaultDomain;
}
const req = {
defaultDomain: defaultDomain,
};
await UpdateAppStoreConfig(req);
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
} catch (error) {
} finally {
loading.value = false;
handleClose();
}
});
};
defineExpose({
acceptParams,
});
</script>

View File

@ -4,7 +4,7 @@
<el-form <el-form
:model="config" :model="config"
label-position="left" label-position="left"
label-width="150px" label-width="180px"
class="ml-2.5" class="ml-2.5"
v-loading="loading" v-loading="loading"
:rules="rules" :rules="rules"
@ -15,32 +15,39 @@
<el-form-item :label="$t('app.defaultWebDomain')" prop="defaultDomain"> <el-form-item :label="$t('app.defaultWebDomain')" prop="defaultDomain">
<el-input v-model="config.defaultDomain"> <el-input v-model="config.defaultDomain">
<template #prepend> <template #prepend>
<el-select v-model="protocol" placeholder="Select" class="p-w-100"> <el-select v-model="protocol" placeholder="Select" class="p-w-100" disabled>
<el-option label="HTTP" value="http://" /> <el-option label="HTTP" value="http://" />
<el-option label="HTTPS" value="https://" /> <el-option label="HTTPS" value="https://" />
</el-select> </el-select>
</template> </template>
<template #append>
<el-button @click="setDefaultDomain()" icon="Setting">
{{ $t('commons.button.set') }}
</el-button>
</template>
</el-input> </el-input>
<span class="input-help">{{ $t('app.defaultWebDomainHepler') }}</span> <span class="input-help">{{ $t('app.defaultWebDomainHepler') }}</span>
</el-form-item> </el-form-item>
<el-form-item> <CustomSetting v-if="isProductPro" />
<el-button type="primary" :disabled="loading" @click="submit()">
{{ $t('commons.button.confirm') }}
</el-button>
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
</template> </template>
</LayoutContent> </LayoutContent>
<DefaultDomain ref="domainRef" @close="search" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { GetAppStoreConfig, UpdateAppStoreConfig } from '@/api/modules/app'; import { GetAppStoreConfig } from '@/api/modules/app';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { FormRules } from 'element-plus'; import { FormRules } from 'element-plus';
import CustomSetting from '@/xpack/views/appstore/index.vue';
import DefaultDomain from './default-domain/index.vue';
import { GlobalStore } from '@/store';
import { storeToRefs } from 'pinia';
const globalStore = GlobalStore();
const { isProductPro } = storeToRefs(globalStore);
const rules = ref<FormRules>({ const rules = ref<FormRules>({
defaultDomain: [Rules.domainOrIP], defaultDomain: [Rules.domainOrIP],
@ -51,12 +58,11 @@ const config = ref({
const loading = ref(false); const loading = ref(false);
const configForm = ref(); const configForm = ref();
const protocol = ref('http://'); const protocol = ref('http://');
const domainRef = ref();
function getUrl(url: string) { function getUrl(url: string) {
const regex = /^(https?:\/\/)(.*)/; const regex = /^(https?:\/\/)(.*)/;
const match = url.match(regex); const match = url.match(regex);
if (match) { if (match) {
const protocol = match[1]; const protocol = match[1];
const remainder = match[2]; const remainder = match[2];
@ -86,28 +92,10 @@ const search = async () => {
} }
}; };
const submit = async () => { const setDefaultDomain = () => {
if (!configForm.value) return; domainRef.value.acceptParams({
await configForm.value.validate(async (valid) => { domain: config.value.defaultDomain,
if (!valid) { protocol: protocol.value,
return;
}
loading.value = true;
try {
let defaultDomain = '';
if (config.value.defaultDomain) {
defaultDomain = protocol.value + config.value.defaultDomain;
}
const req = {
defaultDomain: defaultDomain,
};
await UpdateAppStoreConfig(req);
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
} catch (error) {
} finally {
loading.value = false;
search();
}
}); });
}; };