mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 20:49:03 +08:00
feat: 增加同步本地应用功能 (#537)
This commit is contained in:
parent
fb62ac17e5
commit
18029d8369
@ -38,8 +38,9 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
|
||||
// @Router /apps/sync [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"}
|
||||
func (b *BaseApi) SyncApp(c *gin.Context) {
|
||||
appService.SyncAppListFromLocal()
|
||||
global.LOG.Infof("sync app list start ...")
|
||||
if err := appService.SyncAppList(); err != nil {
|
||||
if err := appService.SyncAppListFromRemote(); err != nil {
|
||||
global.LOG.Errorf("sync app list error [%s]", err.Error())
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
@ -16,6 +16,7 @@ type App struct {
|
||||
Github string `json:"github" gorm:"type:varchar(64);not null"`
|
||||
Document string `json:"document" gorm:"type:varchar(64);not null"`
|
||||
Recommend int `json:"recommend" gorm:"type:Integer;not null"`
|
||||
Resource string `json:"resource" gorm:"type:varchar;not null;default:remote"`
|
||||
Details []AppDetail `json:"-" gorm:"-:migration"`
|
||||
TagsKey []string `json:"-" gorm:"-"`
|
||||
AppTags []AppTag `json:"-" gorm:"-:migration"`
|
||||
|
@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
)
|
||||
@ -26,13 +27,21 @@ type AppInstall struct {
|
||||
}
|
||||
|
||||
func (i *AppInstall) GetPath() string {
|
||||
return path.Join(constant.AppInstallDir, i.App.Key, i.Name)
|
||||
return path.Join(i.getAppPath(), i.Name)
|
||||
}
|
||||
|
||||
func (i *AppInstall) GetComposePath() string {
|
||||
return path.Join(constant.AppInstallDir, i.App.Key, i.Name, "docker-compose.yml")
|
||||
return path.Join(i.getAppPath(), i.Name, "docker-compose.yml")
|
||||
}
|
||||
|
||||
func (i *AppInstall) GetEnvPath() string {
|
||||
return path.Join(constant.AppInstallDir, i.App.Key, i.Name, ".env")
|
||||
return path.Join(i.getAppPath(), i.Name, ".env")
|
||||
}
|
||||
|
||||
func (i *AppInstall) getAppPath() string {
|
||||
if i.App.Resource == constant.AppResourceLocal {
|
||||
return path.Join(constant.LocalAppInstallDir, strings.TrimPrefix(i.App.Key, constant.AppResourceLocal))
|
||||
} else {
|
||||
return path.Join(constant.AppInstallDir, i.App.Key)
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ type IAppRepo interface {
|
||||
WithType(typeStr string) DBOption
|
||||
OrderByRecommend() DBOption
|
||||
GetRecommend() DBOption
|
||||
WithResource(resource string) DBOption
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.App, error)
|
||||
GetFirst(opts ...DBOption) (model.App, error)
|
||||
GetBy(opts ...DBOption) ([]model.App, error)
|
||||
@ -53,6 +54,12 @@ func (a AppRepo) GetRecommend() DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (a AppRepo) WithResource(resource string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("resource = ?", resource)
|
||||
}
|
||||
}
|
||||
|
||||
func (a AppRepo) Page(page, size int, opts ...DBOption) (int64, []model.App, error) {
|
||||
var apps []model.App
|
||||
db := getDb(opts...).Model(&model.App{})
|
||||
|
@ -35,9 +35,10 @@ type IAppService interface {
|
||||
GetApp(key string) (*response.AppDTO, error)
|
||||
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
|
||||
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
|
||||
SyncAppList() error
|
||||
SyncAppListFromRemote() error
|
||||
GetAppUpdate() (*response.AppUpdateRes, error)
|
||||
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
|
||||
SyncAppListFromLocal()
|
||||
}
|
||||
|
||||
func NewIAppService() IAppService {
|
||||
@ -294,7 +295,7 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
|
||||
}
|
||||
appInstall.DockerCompose = string(composeByte)
|
||||
|
||||
if err := copyAppData(app.Key, appDetail.Version, req.Name, req.Params); err != nil {
|
||||
if err := copyAppData(app.Key, appDetail.Version, req.Name, req.Params, app.Resource == constant.AppResourceLocal); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
@ -360,7 +361,156 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a AppService) SyncAppList() error {
|
||||
func (a AppService) SyncAppListFromLocal() {
|
||||
fileOp := files.NewFileOp()
|
||||
appDir := constant.LocalAppResourceDir
|
||||
listFile := path.Join(appDir, "list.json")
|
||||
if !fileOp.Stat(listFile) {
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("start sync local apps...")
|
||||
content, err := fileOp.GetContent(listFile)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get list.json content failed %s", err.Error())
|
||||
return
|
||||
}
|
||||
list := &dto.AppList{}
|
||||
if err := json.Unmarshal(content, list); err != nil {
|
||||
global.LOG.Errorf("unmarshal list.json failed %s", err.Error())
|
||||
return
|
||||
}
|
||||
oldApps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceLocal))
|
||||
appsMap := getApps(oldApps, list.Items, true)
|
||||
for _, l := range list.Items {
|
||||
localKey := "local" + l.Key
|
||||
app := appsMap[localKey]
|
||||
icon, err := os.ReadFile(path.Join(appDir, l.Key, "metadata", "logo.png"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get [%s] icon error: %s", l.Name, err.Error())
|
||||
continue
|
||||
}
|
||||
iconStr := base64.StdEncoding.EncodeToString(icon)
|
||||
app.Icon = iconStr
|
||||
app.TagsKey = append(l.Tags, "Local")
|
||||
app.Recommend = 9999
|
||||
versions := l.Versions
|
||||
detailsMap := getAppDetails(app.Details, versions)
|
||||
|
||||
for _, v := range versions {
|
||||
detail := detailsMap[v]
|
||||
detailPath := path.Join(appDir, l.Key, "versions", v)
|
||||
if _, err := os.Stat(detailPath); err != nil {
|
||||
global.LOG.Errorf("get [%s] folder error: %s", detailPath, err.Error())
|
||||
continue
|
||||
}
|
||||
readmeStr, err := os.ReadFile(path.Join(detailPath, "README.md"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get [%s] README error: %s", detailPath, err.Error())
|
||||
}
|
||||
detail.Readme = string(readmeStr)
|
||||
dockerComposeStr, err := os.ReadFile(path.Join(detailPath, "docker-compose.yml"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get [%s] docker-compose.yml error: %s", detailPath, err.Error())
|
||||
continue
|
||||
}
|
||||
detail.DockerCompose = string(dockerComposeStr)
|
||||
paramStr, err := os.ReadFile(path.Join(detailPath, "config.json"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get [%s] form.json error: %s", detailPath, err.Error())
|
||||
}
|
||||
detail.Params = string(paramStr)
|
||||
detailsMap[v] = detail
|
||||
}
|
||||
var newDetails []model.AppDetail
|
||||
for _, v := range detailsMap {
|
||||
newDetails = append(newDetails, v)
|
||||
}
|
||||
app.Details = newDetails
|
||||
appsMap[localKey] = app
|
||||
}
|
||||
var (
|
||||
addAppArray []model.App
|
||||
updateArray []model.App
|
||||
appIds []uint
|
||||
)
|
||||
for _, v := range appsMap {
|
||||
if v.ID == 0 {
|
||||
addAppArray = append(addAppArray, v)
|
||||
} else {
|
||||
updateArray = append(updateArray, v)
|
||||
appIds = append(appIds, v.ID)
|
||||
}
|
||||
}
|
||||
tx, ctx := getTxAndContext()
|
||||
if len(addAppArray) > 0 {
|
||||
if err := appRepo.BatchCreate(ctx, addAppArray); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, update := range updateArray {
|
||||
if err := appRepo.Save(ctx, &update); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := appTagRepo.DeleteByAppIds(ctx, appIds); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
apps := append(addAppArray, updateArray...)
|
||||
var (
|
||||
addDetails []model.AppDetail
|
||||
updateDetails []model.AppDetail
|
||||
appTags []*model.AppTag
|
||||
)
|
||||
tags, _ := tagRepo.All()
|
||||
tagMap := make(map[string]uint, len(tags))
|
||||
for _, app := range tags {
|
||||
tagMap[app.Key] = app.ID
|
||||
}
|
||||
for _, a := range apps {
|
||||
for _, t := range a.TagsKey {
|
||||
tagId, ok := tagMap[t]
|
||||
if ok {
|
||||
appTags = append(appTags, &model.AppTag{
|
||||
AppId: a.ID,
|
||||
TagId: tagId,
|
||||
})
|
||||
}
|
||||
}
|
||||
for _, d := range a.Details {
|
||||
d.AppId = a.ID
|
||||
if d.ID == 0 {
|
||||
addDetails = append(addDetails, d)
|
||||
} else {
|
||||
updateDetails = append(updateDetails, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(addDetails) > 0 {
|
||||
if err := appDetailRepo.BatchCreate(ctx, addDetails); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, u := range updateDetails {
|
||||
if err := appDetailRepo.Update(ctx, u); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(appTags) > 0 {
|
||||
if err := appTagRepo.BatchCreate(ctx, appTags); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
global.LOG.Infof("sync local apps success")
|
||||
return
|
||||
}
|
||||
func (a AppService) SyncAppListFromRemote() error {
|
||||
updateRes, err := a.GetAppUpdate()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -393,11 +543,11 @@ func (a AppService) SyncAppList() error {
|
||||
Name: t.Name,
|
||||
})
|
||||
}
|
||||
oldApps, err := appRepo.GetBy()
|
||||
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appsMap := getApps(oldApps, list.Items)
|
||||
appsMap := getApps(oldApps, list.Items, false)
|
||||
for _, l := range list.Items {
|
||||
app := appsMap[l.Key]
|
||||
icon, err := os.ReadFile(path.Join(appDir, l.Key, "metadata", "logo.png"))
|
||||
@ -453,8 +603,9 @@ func (a AppService) SyncAppList() error {
|
||||
var (
|
||||
addAppArray []model.App
|
||||
updateArray []model.App
|
||||
tagMap = make(map[string]uint, len(tags))
|
||||
)
|
||||
tagMap := make(map[string]uint, len(tags))
|
||||
|
||||
for _, v := range appsMap {
|
||||
if v.ID == 0 {
|
||||
addAppArray = append(addAppArray, v)
|
||||
|
@ -293,11 +293,9 @@ func checkLimit(app model.App) error {
|
||||
}
|
||||
|
||||
func checkRequiredAndLimit(app model.App) error {
|
||||
|
||||
if err := checkLimit(app); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if app.Required != "" {
|
||||
var requiredArray []string
|
||||
if err := json.Unmarshal([]byte(app.Required), &requiredArray); err != nil {
|
||||
@ -326,7 +324,6 @@ func checkRequiredAndLimit(app model.App) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -343,10 +340,17 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
|
||||
}
|
||||
}
|
||||
|
||||
func copyAppData(key, version, installName string, params map[string]interface{}) (err error) {
|
||||
func copyAppData(key, version, installName string, params map[string]interface{}, isLocal bool) (err error) {
|
||||
fileOp := files.NewFileOp()
|
||||
resourceDir := path.Join(constant.AppResourceDir, key, "versions", version)
|
||||
appResourceDir := constant.AppResourceDir
|
||||
installAppDir := path.Join(constant.AppInstallDir, key)
|
||||
appKey := key
|
||||
if isLocal {
|
||||
appResourceDir = constant.LocalAppResourceDir
|
||||
appKey = strings.TrimPrefix(key, "local")
|
||||
installAppDir = path.Join(constant.LocalAppInstallDir, appKey)
|
||||
}
|
||||
resourceDir := path.Join(appResourceDir, appKey, "versions", version)
|
||||
|
||||
if !fileOp.Stat(installAppDir) {
|
||||
if err = fileOp.CreateDir(installAppDir, 0755); err != nil {
|
||||
@ -471,20 +475,29 @@ func getAppDetails(details []model.AppDetail, versions []string) map[string]mode
|
||||
return appDetails
|
||||
}
|
||||
|
||||
func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
|
||||
func getApps(oldApps []model.App, items []dto.AppDefine, isLocal bool) map[string]model.App {
|
||||
apps := make(map[string]model.App, len(oldApps))
|
||||
for _, old := range oldApps {
|
||||
old.Status = constant.AppTakeDown
|
||||
apps[old.Key] = old
|
||||
}
|
||||
for _, item := range items {
|
||||
app, ok := apps[item.Key]
|
||||
key := item.Key
|
||||
if isLocal {
|
||||
key = "local" + key
|
||||
}
|
||||
app, ok := apps[key]
|
||||
if !ok {
|
||||
app = model.App{}
|
||||
}
|
||||
if isLocal {
|
||||
app.Resource = constant.AppResourceLocal
|
||||
} else {
|
||||
app.Resource = constant.AppResourceRemote
|
||||
}
|
||||
app.Name = item.Name
|
||||
app.Limit = item.Limit
|
||||
app.Key = item.Key
|
||||
app.Key = key
|
||||
app.ShortDescZh = item.ShortDescZh
|
||||
app.ShortDescEn = item.ShortDescEn
|
||||
app.Website = item.Website
|
||||
@ -494,7 +507,7 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
|
||||
app.CrossVersionUpdate = item.CrossVersionUpdate
|
||||
app.Required = item.GetRequired()
|
||||
app.Status = constant.AppNormal
|
||||
apps[item.Key] = app
|
||||
apps[key] = app
|
||||
}
|
||||
return apps
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) error {
|
||||
return err
|
||||
}
|
||||
timeNow := time.Now().Format("20060102150405")
|
||||
|
||||
backupDir := fmt.Sprintf("%s/app/%s/%s", localDir, req.Name, req.DetailName)
|
||||
|
||||
fileName := fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow)
|
||||
@ -98,7 +99,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro
|
||||
return err
|
||||
}
|
||||
|
||||
appPath := fmt.Sprintf("%s/%s/%s", constant.AppInstallDir, install.App.Key, install.Name)
|
||||
appPath := fmt.Sprintf("%s/%s", install.GetPath(), install.Name)
|
||||
if err := handleTar(appPath, tmpDir, "app.tar.gz", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -16,6 +16,9 @@ const (
|
||||
AppOpenresty = "openresty"
|
||||
AppMysql = "mysql"
|
||||
AppRedis = "redis"
|
||||
|
||||
AppResourceLocal = "local"
|
||||
AppResourceRemote = "remote"
|
||||
)
|
||||
|
||||
type AppOperate string
|
||||
|
@ -7,9 +7,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
DataDir = global.CONF.System.DataDir
|
||||
ResourceDir = path.Join(DataDir, "resource")
|
||||
AppResourceDir = path.Join(ResourceDir, "apps")
|
||||
AppInstallDir = path.Join(DataDir, "apps")
|
||||
RuntimeDir = path.Join(DataDir, "runtime")
|
||||
DataDir = global.CONF.System.DataDir
|
||||
ResourceDir = path.Join(DataDir, "resource")
|
||||
AppResourceDir = path.Join(ResourceDir, "apps")
|
||||
AppInstallDir = path.Join(DataDir, "apps")
|
||||
LocalAppResourceDir = path.Join(ResourceDir, "localApps")
|
||||
LocalAppInstallDir = path.Join(DataDir, "localApps")
|
||||
RuntimeDir = path.Join(DataDir, "runtime")
|
||||
)
|
||||
|
@ -15,8 +15,10 @@ func Init() {
|
||||
constant.AppResourceDir = path.Join(constant.ResourceDir, "apps")
|
||||
constant.AppInstallDir = path.Join(constant.DataDir, "apps")
|
||||
constant.RuntimeDir = path.Join(constant.DataDir, "runtime")
|
||||
constant.LocalAppResourceDir = path.Join(constant.ResourceDir, "localApps")
|
||||
constant.LocalAppInstallDir = path.Join(constant.DataDir, "localApps")
|
||||
|
||||
dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup, constant.RuntimeDir}
|
||||
dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup, constant.RuntimeDir, constant.LocalAppResourceDir}
|
||||
|
||||
fileOp := files.NewFileOp()
|
||||
for _, dir := range dirs {
|
||||
|
@ -21,7 +21,7 @@ func syncApp() {
|
||||
return
|
||||
}
|
||||
global.LOG.Info("sync app start...")
|
||||
if err := service.NewIAppService().SyncAppList(); err != nil {
|
||||
if err := service.NewIAppService().SyncAppListFromRemote(); err != nil {
|
||||
global.LOG.Errorf("sync app error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ func Init() {
|
||||
migrations.AddTableSnap,
|
||||
migrations.AddDefaultGroup,
|
||||
migrations.AddTableRuntime,
|
||||
migrations.UpdateTableApp,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -254,3 +254,13 @@ var AddTableRuntime = &gormigrate.Migration{
|
||||
return tx.AutoMigrate(&model.Runtime{}, &model.Website{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateTableApp = &gormigrate.Migration{
|
||||
ID: "20230408-update-table-app",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.App{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -87,6 +87,7 @@ declare module 'vue' {
|
||||
SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default']
|
||||
SystemUpgrade: typeof import('./src/components/system-upgrade/index.vue')['default']
|
||||
TableSetting: typeof import('./src/components/table-setting/index.vue')['default']
|
||||
Terminal: typeof import('./src/components/terminal/index.vue')['default']
|
||||
Tooltip: typeof import('./src/components/tooltip/index.vue')['default']
|
||||
Upload: typeof import('./src/components/upload/index.vue')['default']
|
||||
VCharts: typeof import('./src/components/v-charts/index.vue')['default']
|
||||
|
@ -75,8 +75,10 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="app-tag">
|
||||
<el-tag v-for="(tag, ind) in app.tags" :key="ind" :colr="getColor(ind)">
|
||||
{{ language == 'zh' ? tag.name : tag.key }}
|
||||
<el-tag v-for="(tag, ind) in app.tags" :key="ind" style="margin-right: 5px">
|
||||
<span :style="{ color: getColor(ind) }">
|
||||
{{ language == 'zh' ? tag.name : tag.key }}
|
||||
</span>
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
@ -113,7 +115,7 @@ let req = reactive({
|
||||
|
||||
let apps = ref<App.App[]>([]);
|
||||
let tags = ref<App.Tag[]>([]);
|
||||
const colorArr = ['#6495ED', '#54FF9F', '#BEBEBE', '#FFF68F', '#FFFF00', '#8B0000'];
|
||||
const colorArr = ['#005eeb', '#008B45', '#BEBEBE', '#FFF68F', '#FFFF00', '#8B0000'];
|
||||
let loading = ref(false);
|
||||
let activeTag = ref('all');
|
||||
let showDetail = ref(false);
|
||||
|
@ -105,7 +105,7 @@
|
||||
round
|
||||
size="small"
|
||||
:disabled="installed.status !== 'Running'"
|
||||
@click="openUploads(installed.app.key, installed.name)"
|
||||
@click="openUploads(installed.app.name, installed.name)"
|
||||
v-if="mode === 'installed'"
|
||||
>
|
||||
{{ $t('database.loadBackup') }}
|
||||
@ -117,7 +117,7 @@
|
||||
round
|
||||
size="small"
|
||||
:disabled="installed.status !== 'Running'"
|
||||
@click="openBackups(installed.app.key, installed.name)"
|
||||
@click="openBackups(installed.app.name, installed.name)"
|
||||
v-if="mode === 'installed'"
|
||||
>
|
||||
{{ $t('app.backup') }}
|
||||
@ -201,17 +201,17 @@ import { getAge } from '@/utils/util';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
|
||||
let data = ref<any>();
|
||||
let loading = ref(false);
|
||||
let syncLoading = ref(false);
|
||||
const data = ref<any>();
|
||||
const loading = ref(false);
|
||||
const syncLoading = ref(false);
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
const paginationConfig = reactive({
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
let open = ref(false);
|
||||
let operateReq = reactive({
|
||||
const open = ref(false);
|
||||
const operateReq = reactive({
|
||||
installId: 0,
|
||||
operate: '',
|
||||
detailId: 0,
|
||||
@ -222,9 +222,9 @@ const checkRef = ref();
|
||||
const deleteRef = ref();
|
||||
const appParamRef = ref();
|
||||
const upgradeRef = ref();
|
||||
let tags = ref<App.Tag[]>([]);
|
||||
let activeTag = ref('all');
|
||||
let searchReq = reactive({
|
||||
const tags = ref<App.Tag[]>([]);
|
||||
const activeTag = ref('all');
|
||||
const searchReq = reactive({
|
||||
page: 1,
|
||||
pageSize: 15,
|
||||
name: '',
|
||||
@ -232,8 +232,8 @@ let searchReq = reactive({
|
||||
update: false,
|
||||
});
|
||||
const router = useRouter();
|
||||
let activeName = ref(i18n.global.t('app.installed'));
|
||||
let mode = ref('installed');
|
||||
const activeName = ref(i18n.global.t('app.installed'));
|
||||
const mode = ref('installed');
|
||||
|
||||
const sync = () => {
|
||||
syncLoading.value = true;
|
||||
|
@ -174,6 +174,7 @@ import Process from './process/index.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Back, Refresh } from '@element-plus/icons-vue';
|
||||
import { MsgSuccess, MsgWarning } from '@/utils/message';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
|
||||
interface FilePaths {
|
||||
url: string;
|
||||
|
Loading…
Reference in New Issue
Block a user