diff --git a/internal/route/http.go b/internal/route/http.go
index c02252a9..e2d3432f 100644
--- a/internal/route/http.go
+++ b/internal/route/http.go
@@ -492,6 +492,7 @@ func (route *Http) Register(r *chi.Mux) {
r.Get("/", route.setting.Get)
r.Post("/", route.setting.Update)
r.Post("/cert", route.setting.UpdateCert)
+ r.Post("/obtain_cert", route.setting.ObtainCert)
})
r.Route("/systemctl", func(r chi.Router) {
diff --git a/web/src/api/panel/setting/index.ts b/web/src/api/panel/setting/index.ts
index d491458a..0d9999ef 100644
--- a/web/src/api/panel/setting/index.ts
+++ b/web/src/api/panel/setting/index.ts
@@ -4,5 +4,7 @@ export default {
// 获取设置
list: (): any => http.Get('/setting'),
// 保存设置
- update: (settings: any): any => http.Post('/setting', settings)
+ update: (settings: any): any => http.Post('/setting', settings),
+ // 刷新证书
+ obtainCert: (): any => http.Post('/setting/obtain_cert')
}
diff --git a/web/src/views/setting/IndexView.vue b/web/src/views/setting/IndexView.vue
index 2ff216c7..9ee934a8 100644
--- a/web/src/views/setting/IndexView.vue
+++ b/web/src/views/setting/IndexView.vue
@@ -19,6 +19,23 @@ const permissionStore = usePermissionStore()
const currentTab = ref('base')
const createModal = ref(false)
+// 记录已保存的 HTTPS 相关设置,用于判断是否有未保存的修改
+const savedHttpsState = ref({ https: false, acme: false, public_ip: '[]' })
+const httpsSettingsDirty = computed(() => {
+ return (
+ model.value.https !== savedHttpsState.value.https ||
+ model.value.acme !== savedHttpsState.value.acme ||
+ JSON.stringify(model.value.public_ip) !== savedHttpsState.value.public_ip
+ )
+})
+const snapshotHttpsState = () => {
+ savedHttpsState.value = {
+ https: model.value.https,
+ acme: model.value.acme,
+ public_ip: JSON.stringify(model.value.public_ip)
+ }
+}
+
const { data: model } = useRequest(setting.list, {
initialData: {
name: '',
@@ -48,6 +65,9 @@ const { data: model } = useRequest(setting.list, {
}
})
+// 数据加载完成后快照 HTTPS 状态
+watch(model, () => snapshotHttpsState(), { once: true, deep: true })
+
const handleSave = () => {
if (model.value.entrance.trim() === '') {
model.value.entrance = '/'
@@ -55,6 +75,9 @@ const handleSave = () => {
useRequest(setting.update(model.value)).onSuccess(({ data }) => {
window.$message.success($gettext('Saved successfully'))
+ // 更新 HTTPS 快照
+ snapshotHttpsState()
+
// 更新语言设置
if (model.value.locale !== themeStore.locale) {
themeStore.setLocale(model.value.locale)
@@ -79,6 +102,19 @@ const handleSave = () => {
})
}
+const handleObtainCert = () => {
+ useRequest(setting.obtainCert()).onSuccess(() => {
+ window.$message.success($gettext('Certificate refreshed successfully'))
+ window.$message.info($gettext('Panel is restarting, page will refresh in 5 seconds'))
+ setTimeout(() => {
+ const hostname = window.location.hostname
+ const port = model.value.port
+ const entrance = model.value.entrance || '/'
+ window.location.href = `https://${hostname}:${port}${entrance}`
+ }, 5000)
+ })
+}
+
const handleCreate = () => {
createModal.value = true
}
@@ -106,6 +142,14 @@ const handleCreate = () => {
{{ $gettext('Save') }}
+
+ {{ $gettext('Refresh Certificate') }}
+