diff --git a/backend/app/service/website.go b/backend/app/service/website.go index 3671dd975..feafefe01 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -19,7 +19,6 @@ import ( "path" "reflect" "regexp" - "strconv" "strings" "time" @@ -1164,7 +1163,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) switch req.Operate { case "create": _ = fileOp.DeleteFile(includePath) - case "update": + case "edit": _ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), 0755) } } @@ -1175,7 +1174,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) switch req.Operate { case "create": config = parser.NewStringParser(string(nginx_conf.Proxy)).Parse() - case "update": + case "edit": par, err = parser.NewParser(includePath) if err != nil { return @@ -1193,6 +1192,11 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) backPath := path.Join(includeDir, backName) _ = fileOp.Rename(includePath, backPath) return updateNginxConfig(constant.NginxScopeServer, nil, &website) + case "enable": + backName := fmt.Sprintf("%s.bak", req.Name) + backPath := path.Join(includeDir, backName) + _ = fileOp.Rename(backPath, includePath) + return updateNginxConfig(constant.NginxScopeServer, nil, &website) } config.FilePath = includePath directives := config.Directives @@ -1205,15 +1209,14 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost}) location.ChangePath(req.Modifier, req.Match) if req.Cache { - location.AddCache(strconv.Itoa(req.CacheTime) + req.CacheUnit) + location.AddCache(req.CacheTime, req.CacheUnit) } else { location.RemoveCache() } - if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { return buserr.WithErr(constant.ErrUpdateBuWebsite, err) } - nginxInclude := path.Join("www", "sites", website.Alias, "proxy", "*.conf") + nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias) if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil { return } @@ -1248,7 +1251,9 @@ func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, e config *components.Config ) for _, configFile := range fileList.Items { - proxyConfig := request.WebsiteProxyConfig{} + proxyConfig := request.WebsiteProxyConfig{ + ID: website.ID, + } parts := strings.Split(configFile.Name, ".") proxyConfig.Name = parts[0] if parts[1] == "conf" { @@ -1271,8 +1276,13 @@ func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, e } proxyConfig.ProxyPass = location.ProxyPass proxyConfig.Cache = location.Cache - //proxyConfig.CacheTime = location.CacheTime + if location.CacheTime > 0 { + proxyConfig.CacheTime = location.CacheTime + proxyConfig.CacheUnit = location.CacheUint + } proxyConfig.Match = location.Match + proxyConfig.Modifier = location.Modifier + proxyConfig.ProxyHost = location.Host res = append(res, proxyConfig) } return diff --git a/backend/utils/nginx/components/location.go b/backend/utils/nginx/components/location.go index 894ecaab3..79e66ae96 100644 --- a/backend/utils/nginx/components/location.go +++ b/backend/utils/nginx/components/location.go @@ -1,13 +1,18 @@ package components -type Location struct { - Modifier string - Match string - Cache bool - ProxyPass string - Host string - CacheTime string +import ( + "regexp" + "strconv" +) +type Location struct { + Modifier string + Match string + Cache bool + ProxyPass string + Host string + CacheTime int + CacheUint string Comment string Directives []IDirective Line int @@ -40,7 +45,18 @@ func NewLocation(directive IDirective) *Location { dirs := dir.GetBlock().GetDirectives() for _, di := range dirs { if di.GetName() == "expires" { - location.CacheTime = di.GetParameters()[0] + re := regexp.MustCompile(`^(\d+)(\w+)$`) + matches := re.FindStringSubmatch(di.GetParameters()[0]) + if matches == nil { + continue + } + cacheTime, err := strconv.Atoi(matches[1]) + if err != nil { + continue + } + unit := matches[2] + location.CacheUint = unit + location.CacheTime = cacheTime } } } @@ -158,7 +174,7 @@ func (l *Location) ChangePath(Modifier string, Match string) { l.Match = Match } -func (l *Location) AddCache(cacheTime string) { +func (l *Location) AddCache(cacheTime int, cacheUint string) { l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"}) directives := l.GetDirectives() newDir := &Directive{ @@ -169,7 +185,7 @@ func (l *Location) AddCache(cacheTime string) { block := &Block{} block.Directives = append(block.Directives, &Directive{ Name: "expires", - Parameters: []string{cacheTime}, + Parameters: []string{strconv.Itoa(cacheTime) + cacheUint}, }) newDir.Block = block directives = append(directives, newDir) @@ -180,6 +196,7 @@ func (l *Location) AddCache(cacheTime string) { l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", "10m"}) l.Cache = true l.CacheTime = cacheTime + l.CacheUint = cacheUint } func (l *Location) RemoveCache() { @@ -191,6 +208,7 @@ func (l *Location) RemoveCache() { l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"}) - l.CacheTime = "" + l.CacheTime = 0 + l.CacheUint = "" l.Cache = false } diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 3f1739352..d36056ba7 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -423,9 +423,6 @@ const message = { remoteConn: 'External connection address', remoteConnHelper2: 'Use this address for non-container or external connections', localIP: 'Local IP', - userGroup: 'User/Group', - user: 'User', - uGroup: 'Group', }, container: { createContainer: 'Create container', @@ -1181,6 +1178,21 @@ const message = { 'Some programs need to specify a secondary directory as the running directory, such as ThinkPHP5, Laravel', runUserHelper: 'For websites deployed through the PHP runtime environment, all files, folder owners, and user groups under the index and subdirectories need to be set to 1000, command: chown -R 1000:1000 index', + userGroup: 'User/Group', + user: 'User', + uGroup: 'Group', + proxyPath: 'Proxy Path', + proxyPass: 'Target URL', + cache: 'Cache', + status: 'Status', + createProxy: 'Create reverse proxy', + editProxy: 'Edit reverse proxy', + cacheTime: 'Cache time', + enableCache: 'Open cache', + proxyHost: 'Send domain name', + disabled: 'Stopped', + startProxy: 'Start Reverse proxy', + stopProxy: 'Stop the Reverse proxy', }, php: { short_open_tag: 'Short tag support', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 8b85d7fa6..ced583d62 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1183,7 +1183,6 @@ const message = { userGroup: '运行用户/组', user: '用户', uGroup: '用户组', - addProxy: '添加反向代理', proxyPath: '代理目录', proxyPass: '目标URL', cache: '缓存', @@ -1194,6 +1193,8 @@ const message = { enableCache: '开启缓存', proxyHost: '发送域名', disabled: '已停止', + startProxy: '开启反向代理', + stopProxy: '关闭反向代理', }, php: { short_open_tag: '短标签支持', diff --git a/frontend/src/views/website/website/config/basic/proxy/create/index.vue b/frontend/src/views/website/website/config/basic/proxy/create/index.vue index 2b1b4aef1..c6ab89442 100644 --- a/frontend/src/views/website/website/config/basic/proxy/create/index.vue +++ b/frontend/src/views/website/website/config/basic/proxy/create/index.vue @@ -1,24 +1,24 @@ <template> <el-drawer v-model="open" :close-on-click-modal="false" size="40%" :before-close="handleClose"> <template #header> - <DrawerHeader :header="$t('website.createProxy')" :back="handleClose" /> + <DrawerHeader :header="$t('website.' + proxy.operate + 'Proxy')" :back="handleClose" /> </template> <el-row v-loading="loading"> <el-col :span="22" :offset="1"> <el-form ref="proxyForm" label-position="top" :model="proxy" :rules="rules"> <el-form-item :label="$t('commons.table.name')" prop="name"> - <el-input v-model.trim="proxy.name"></el-input> + <el-input v-model.trim="proxy.name" :disabled="proxy.operate === 'edit'"></el-input> </el-form-item> <el-form-item :label="$t('website.proxyPath')" prop="match"> <el-input v-model.trim="proxy.match"></el-input> </el-form-item> <el-form-item :label="$t('website.enableCache')" prop="cache"> - <el-switch v-model="proxy.cache"></el-switch> + <el-switch v-model="proxy.cache" @change="changeCache(proxy.cache)"></el-switch> </el-form-item> <el-form-item :label="$t('website.cacheTime')" prop="cacheTime" v-if="proxy.cache"> <el-input v-model.number="proxy.cacheTime" maxlength="15"> <template #append> - <el-select v-model="proxy.cacheUnit" style="width: 80px"> + <el-select v-model="proxy.cacheUnit" style="width: 100px"> <el-option v-for="(unit, index) in Units" :key="index" @@ -65,7 +65,6 @@ import { ref } from 'vue'; import { MsgSuccess } from '@/utils/message'; import { Website } from '@/api/interface/website'; import { Units } from '@/global/mimetype'; -// import { Website } from '@/api/interface/website'; const proxyForm = ref<FormInstance>(); const rules = ref({ @@ -103,9 +102,20 @@ const handleClose = () => { const acceptParams = async (proxyParam: Website.ProxyConfig) => { proxy.value = proxyParam; + console.log(proxy.value); open.value = true; }; +const changeCache = (cache: boolean) => { + if (cache) { + proxy.value.cacheTime = 1; + proxy.value.cacheUnit = 'm'; + } else { + proxy.value.cacheTime = 0; + proxy.value.cacheUnit = ''; + } +}; + const submit = async (formEl: FormInstance | undefined) => { if (!formEl) return; await formEl.validate((valid) => { @@ -115,7 +125,11 @@ const submit = async (formEl: FormInstance | undefined) => { loading.value = true; CreateProxyConfig(proxy.value) .then(() => { - MsgSuccess(i18n.global.t('commons.msg.createSuccess')); + if (proxy.value.operate == 'create') { + MsgSuccess(i18n.global.t('commons.msg.createSuccess')); + } else { + MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); + } handleClose(); }) .finally(() => { diff --git a/frontend/src/views/website/website/config/basic/proxy/index.vue b/frontend/src/views/website/website/config/basic/proxy/index.vue index be3f3bce9..a282e9e0d 100644 --- a/frontend/src/views/website/website/config/basic/proxy/index.vue +++ b/frontend/src/views/website/website/config/basic/proxy/index.vue @@ -1,36 +1,46 @@ <template> <ComplexTable :data="data" @search="search" v-loading="loading"> <template #toolbar> - <el-button type="primary" plain @click="openCreate">{{ $t('website.addProxy') }}</el-button> + <el-button type="primary" plain @click="openCreate">{{ $t('website.createProxy') }}</el-button> </template> <el-table-column :label="$t('commons.table.name')" prop="name"></el-table-column> <el-table-column :label="$t('website.proxyPath')" prop="match"></el-table-column> <el-table-column :label="$t('website.proxyPass')" prop="proxyPass"></el-table-column> <el-table-column :label="$t('website.cache')" prop="cache"> <template #default="{ row }"> - <el-switch v-model="row.cache"></el-switch> + <el-switch v-model="row.cache" @change="changeCache(row)"></el-switch> </template> </el-table-column> <el-table-column :label="$t('commons.table.status')" prop="enable"> <template #default="{ row }"> - <el-button v-if="row.enable" link type="success" :icon="VideoPlay"> + <el-button v-if="row.enable" link type="success" :icon="VideoPlay" @click="opProxy(row)"> {{ $t('commons.status.running') }} </el-button> - <el-button v-else link type="danger" :icon="VideoPause"> + <el-button v-else link type="danger" :icon="VideoPause" @click="opProxy(row)"> {{ $t('commons.status.stopped') }} </el-button> </template> </el-table-column> + <fu-table-operations + :ellipsis="10" + width="260px" + :buttons="buttons" + :label="$t('commons.table.operate')" + fixed="right" + fix + /> </ComplexTable> <Create ref="createRef" @close="search()" /> </template> <script lang="ts" setup name="proxy"> import { Website } from '@/api/interface/website'; -import { GetProxyConfig } from '@/api/modules/website'; +import { CreateProxyConfig, GetProxyConfig } from '@/api/modules/website'; import { computed, onMounted, ref } from 'vue'; import Create from './create/index.vue'; import { VideoPlay, VideoPause } from '@element-plus/icons-vue'; +import i18n from '@/lang'; +import { MsgSuccess } from '@/utils/message'; const props = defineProps({ id: { @@ -45,6 +55,15 @@ const loading = ref(false); const data = ref(); const createRef = ref(); +const buttons = [ + { + label: i18n.global.t('commons.button.edit'), + click: function (row: Website.ProxyConfig) { + openEdit(row); + }, + }, +]; + const initData = (id: number): Website.ProxyConfig => ({ id: id, operate: 'create', @@ -62,6 +81,56 @@ const initData = (id: number): Website.ProxyConfig => ({ const openCreate = () => { createRef.value.acceptParams(initData(id.value)); }; + +const openEdit = (proxyConfig: Website.ProxyConfig) => { + let proxy = JSON.parse(JSON.stringify(proxyConfig)); + proxy.operate = 'edit'; + createRef.value.acceptParams(proxy); +}; + +const changeCache = (proxyConfig: Website.ProxyConfig) => { + proxyConfig.operate = 'edit'; + if (proxyConfig.cache) { + proxyConfig.cacheTime = 1; + proxyConfig.cacheUnit = 'm'; + } + submit(proxyConfig); +}; + +const submit = async (proxyConfig: Website.ProxyConfig) => { + loading.value = true; + CreateProxyConfig(proxyConfig) + .then(() => { + MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); + search(); + }) + .finally(() => { + loading.value = false; + }); +}; + +const opProxy = (proxyConfig: Website.ProxyConfig) => { + let proxy = JSON.parse(JSON.stringify(proxyConfig)); + proxy.enable = !proxyConfig.enable; + let message = ''; + if (proxy.enable) { + proxy.operate = 'enable'; + message = i18n.global.t('website.startProxy'); + } else { + proxy.operate = 'disable'; + message = i18n.global.t('website.stopProxy'); + } + ElMessageBox.confirm(message, i18n.global.t('cronjob.changeStatus'), { + confirmButtonText: i18n.global.t('commons.button.confirm'), + cancelButtonText: i18n.global.t('commons.button.cancel'), + }) + .then(async () => { + await submit(proxy); + search(); + }) + .catch(() => {}); +}; + const search = async () => { try { loading.value = true; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index edbce6450..a79fbf37c 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -39,7 +39,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { host: '0.0.0.0', proxy: { '/api/v1': { - target: 'http://localhost:9999/', + target: 'http://192.168.1.15:9999/', changeOrigin: true, ws: true, },