diff --git a/apps/nginx/versions/1.21.4/html/index.html b/apps/nginx/versions/1.21.4/html/index.html
deleted file mode 100644
index 3c0f411c2..000000000
--- a/apps/nginx/versions/1.21.4/html/index.html
+++ /dev/null
@@ -1 +0,0 @@
-站点创建成功
\ No newline at end of file
diff --git a/apps/nginx/versions/1.21.4/root/stop/index.html b/apps/nginx/versions/1.21.4/root/stop/index.html
new file mode 100644
index 000000000..a38fa64b6
--- /dev/null
+++ b/apps/nginx/versions/1.21.4/root/stop/index.html
@@ -0,0 +1,33 @@
+
+
+
+
+ 抱歉,站点已暂停
+
+
+
+
+
+
抱歉!该站点已经被管理员停止运行,请联系管理员了解详情!
+
+
+
\ No newline at end of file
diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go
index d92ab8586..d24d4d02f 100644
--- a/backend/app/api/v1/website.go
+++ b/backend/app/api/v1/website.go
@@ -49,6 +49,20 @@ func (b *BaseApi) CreateWebsite(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
+func (b *BaseApi) OpWebsite(c *gin.Context) {
+ var req request.WebsiteOp
+ if err := c.ShouldBindJSON(&req); err != nil {
+ helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
+ return
+ }
+ err := websiteService.OpWebsite(req)
+ if err != nil {
+ helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+ return
+ }
+ helper.SuccessWithData(c, nil)
+}
+
func (b *BaseApi) BackupWebsite(c *gin.Context) {
var req request.WebsiteResourceReq
if err := c.ShouldBindJSON(&req); err != nil {
diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go
index 74ec2e6cc..98a637369 100644
--- a/backend/app/dto/request/website.go
+++ b/backend/app/dto/request/website.go
@@ -45,6 +45,11 @@ type WebsiteDelete struct {
ForceDelete bool `json:"forceDelete"`
}
+type WebsiteOp struct {
+ ID uint `json:"id" validate:"required"`
+ Operate string `json:"operate"`
+}
+
type WebsiteWafReq struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
diff --git a/backend/app/service/website.go b/backend/app/service/website.go
index 7c7f56557..0c95bd6d2 100644
--- a/backend/app/service/website.go
+++ b/backend/app/service/website.go
@@ -29,6 +29,7 @@ type WebsiteService struct {
type IWebsiteService interface {
PageWebsite(req request.WebsiteSearch) (int64, []response.WebsiteDTO, error)
CreateWebsite(create request.WebsiteCreate) error
+ OpWebsite(req request.WebsiteOp) error
GetWebsiteOptions() ([]string, error)
Backup(id uint) error
Recover(req request.WebsiteRecover) error
@@ -113,6 +114,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) error {
return err
}
appInstall = &install
+ website.AppInstallID = 0
}
}
@@ -153,6 +155,17 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) error {
return nil
}
+func (w WebsiteService) OpWebsite(req request.WebsiteOp) error {
+ website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
+ if err != nil {
+ return err
+ }
+ if err := opWebsite(&website, req.Operate); err != nil {
+ return err
+ }
+ return websiteRepo.Save(context.Background(), &website)
+}
+
func (w WebsiteService) GetWebsiteOptions() ([]string, error) {
webs, err := websiteRepo.GetBy()
if err != nil {
diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go
index c4e77f129..63d1a31e5 100644
--- a/backend/app/service/website_utils.go
+++ b/backend/app/service/website_utils.go
@@ -162,7 +162,6 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
_ = deleteWebsiteFolder(nginxInstall, website)
return err
}
-
return nil
}
@@ -567,3 +566,47 @@ func deleteWebsiteFolder(nginxInstall model.AppInstall, website *model.Website)
}
return nil
}
+
+func opWebsite(website *model.Website, operate string) error {
+ nginxInstall, err := getNginxFull(website)
+ if err != nil {
+ return err
+ }
+ config := nginxInstall.SiteConfig.Config
+ servers := config.FindServers()
+ if len(servers) == 0 {
+ return errors.New("nginx config is not valid")
+ }
+ server := servers[0]
+ if operate == constant.StopWeb {
+ if website.Type != constant.Static {
+ server.RemoveDirective("location", []string{"/"})
+ }
+ server.UpdateRoot("/usr/share/nginx/html/stop")
+ website.Status = constant.WebStopped
+ }
+ if operate == constant.StartWeb {
+ switch website.Type {
+ case constant.Deployment:
+ server.RemoveDirective("root", nil)
+ appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
+ if err != nil {
+ return err
+ }
+ proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
+ server.UpdateRootProxy([]string{proxy})
+ case constant.Static:
+ server.UpdateRoot(path.Join("/www/sites", website.Alias, "index"))
+ server.UpdateRootLocation()
+ case constant.Proxy:
+ server.RemoveDirective("root", nil)
+ server.UpdateRootProxy([]string{website.Proxy})
+ }
+ website.Status = constant.WebRunning
+ }
+
+ if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
+ return err
+ }
+ return nginxCheckAndReload(nginxInstall.SiteConfig.OldContent, config.FilePath, nginxInstall.Install.ContainerName)
+}
diff --git a/backend/constant/website.go b/backend/constant/website.go
index fda453946..22e1de807 100644
--- a/backend/constant/website.go
+++ b/backend/constant/website.go
@@ -25,4 +25,7 @@ const (
DnsManual = "dnsManual"
Http = "http"
Manual = "manual"
+
+ StartWeb = "start"
+ StopWeb = "stop"
)
diff --git a/backend/router/ro_website.go b/backend/router/ro_website.go
index 60aa9adef..8e9933e2c 100644
--- a/backend/router/ro_website.go
+++ b/backend/router/ro_website.go
@@ -17,6 +17,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
{
groupRouter.POST("/search", baseApi.PageWebsite)
groupRouter.POST("", baseApi.CreateWebsite)
+ groupRouter.POST("/operate", baseApi.OpWebsite)
groupRouter.POST("/check", baseApi.CreateWebsiteCheck)
groupRouter.GET("/options", baseApi.GetWebsiteOptions)
groupRouter.POST("/update", baseApi.UpdateWebsite)
diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts
index 887624be4..656b1350d 100644
--- a/frontend/src/api/interface/website.ts
+++ b/frontend/src/api/interface/website.ts
@@ -68,6 +68,11 @@ export namespace Website {
webSiteGroupId: number;
}
+ export interface WebSiteOp {
+ id: number;
+ operate: string;
+ }
+
export interface Group extends CommonModel {
name: string;
default: boolean;
diff --git a/frontend/src/api/modules/website.ts b/frontend/src/api/modules/website.ts
index db0568004..8f3c28d3d 100644
--- a/frontend/src/api/modules/website.ts
+++ b/frontend/src/api/modules/website.ts
@@ -11,6 +11,10 @@ export const CreateWebsite = (req: Website.WebSiteCreateReq) => {
return http.post(`/websites`, req);
};
+export const OpWebsite = (req: Website.WebSiteOp) => {
+ return http.post(`/websites/operate`, req);
+};
+
export const BackupWebsite = (req: Website.BackupReq) => {
return http.post(`/websites/backup`, req);
};
diff --git a/frontend/src/components/app-layout/index.vue b/frontend/src/components/app-layout/index.vue
index bfeb6c1cd..c4f5d643d 100644
--- a/frontend/src/components/app-layout/index.vue
+++ b/frontend/src/components/app-layout/index.vue
@@ -26,6 +26,7 @@ const { switchDark } = useTheme();
const loadDataFromDB = async () => {
const res = await getSettingInfo();
i18n.locale.value = res.data.language;
+ i18n.warnHtmlMessage = false;
globalStore.updateLanguage(res.data.language);
globalStore.setThemeConfig({ ...themeConfig.value, theme: res.data.theme });
globalStore.setThemeConfig({ ...themeConfig.value, panelName: res.data.panelName });
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index df1058b7f..7eb37483c 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -906,6 +906,8 @@ export default {
videoSite: '视频',
errLog: '错误日志',
accessLog: '网站日志',
+ stopHelper: '停止站点后将无法正常访问,用户访问会显示当前站点停止页面,是否继续操作?',
+ startHelper: '启用站点后,用户可以正常访问网站内容,是否继续操作?',
},
nginx: {
serverNamesHashBucketSizeHelper: '服务器名字的hash表大小',
diff --git a/frontend/src/views/website/website/index.vue b/frontend/src/views/website/website/index.vue
index 940ea64e3..8588de59e 100644
--- a/frontend/src/views/website/website/index.vue
+++ b/frontend/src/views/website/website/index.vue
@@ -32,7 +32,17 @@
-
+
+ {{ $t('commons.status.running') }}
+
+
+ {{ $t('commons.status.stopped') }}
+
@@ -83,16 +93,16 @@ import { onMounted, reactive, ref } from '@vue/runtime-core';
import CreateWebSite from './create/index.vue';
import DeleteWebsite from './delete/index.vue';
import WebSiteGroup from './group/index.vue';
-import { SearchWebsites } from '@/api/modules/website';
+import { OpWebsite, SearchWebsites } from '@/api/modules/website';
import { Website } from '@/api/interface/website';
import AppStatus from '@/components/app-status/index.vue';
import NginxConfig from './nginx/index.vue';
import { dateFromat } from '@/utils/util';
-import Status from '@/components/status/index.vue';
import i18n from '@/lang';
import router from '@/routers';
import { App } from '@/api/interface/app';
+import { ElMessage, ElMessageBox } from 'element-plus';
const loading = ref(false);
@@ -190,6 +200,17 @@ const checkExist = (data: App.CheckInstalled) => {
installPath.value = data.installPath;
};
+const opWebsite = (op: string, id: number) => {
+ ElMessageBox.confirm(i18n.global.t('website.' + op + 'Helper'), i18n.global.t('cronjob.changeStatus'), {
+ confirmButtonText: i18n.global.t('commons.button.confirm'),
+ cancelButtonText: i18n.global.t('commons.button.cancel'),
+ }).then(async () => {
+ await OpWebsite({ id: id, operate: op });
+ ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
+ search();
+ });
+};
+
onMounted(() => {
search();
});