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 @@ @@ -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(); });