Explorar o código

Enhanced domain add

0xJacky %!s(int64=3) %!d(string=hai) anos
pai
achega
60919aea4c

+ 1 - 1
frontend/package.json

@@ -1,6 +1,6 @@
 {
 {
     "name": "nginx-ui-frontend",
     "name": "nginx-ui-frontend",
-    "version": "1.2.2",
+    "version": "1.3.0",
     "private": true,
     "private": true,
     "scripts": {
     "scripts": {
         "serve": "vue-cli-service serve",
         "serve": "vue-cli-service serve",

+ 1 - 1
frontend/src/components/StdDataEntry/StdDataEntry.vue

@@ -115,7 +115,7 @@
 
 
             <p v-if="!dataSource[d.dataIndex] && d.empty_description" v-html="d.empty_description"/>
             <p v-if="!dataSource[d.dataIndex] && d.empty_description" v-html="d.empty_description"/>
         </a-form-item>
         </a-form-item>
-        <a-form-item>
+        <a-form-item v-if="$slots.supplement||$slots.action">
             <slot name="supplement"/>
             <slot name="supplement"/>
             <slot name="action"/>
             <slot name="action"/>
         </a-form-item>
         </a-form-item>

+ 52 - 24
frontend/src/locale/en/LC_MESSAGES/app.po

@@ -23,28 +23,27 @@ msgstr ""
 msgid "Action"
 msgid "Action"
 msgstr ""
 msgstr ""
 
 
-#: src/router/index.js:47 src/views/domain/DomainAdd.vue:18
+#: src/router/index.js:47 src/views/domain/DomainAdd.vue:27
 msgid "Add Site"
 msgid "Add Site"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainAdd.vue:2
-msgid ""
-"Add site here first, then you can configure TLS on the domain edit page."
-msgstr ""
-
-#: src/views/domain/DomainEdit.vue:194
+#: src/views/domain/DomainAdd.vue:86 src/views/domain/DomainEdit.vue:172
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:188
+#: src/views/domain/DomainAdd.vue:80 src/views/domain/DomainEdit.vue:166
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:37
+msgid "Base information"
+msgstr ""
+
 #: src/views/other/About.vue:11
 #: src/views/other/About.vue:11
 msgid "Build with"
 msgid "Build with"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:23
+#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:24
 msgid "Cancel"
 msgid "Cancel"
 msgstr ""
 msgstr ""
 
 
@@ -76,6 +75,10 @@ msgstr ""
 msgid "Configurations"
 msgid "Configurations"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:40
+msgid "Configure SSL"
+msgstr ""
+
 #: src/views/dashboard/DashBoard.vue:207
 #: src/views/dashboard/DashBoard.vue:207
 msgid "CPU Status"
 msgid "CPU Status"
 msgstr ""
 msgstr ""
@@ -84,6 +87,10 @@ msgstr ""
 msgid "CPU:"
 msgid "CPU:"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:31 src/views/domain/DomainAdd.vue:5
+msgid "Create Another"
+msgstr ""
+
 #: src/views/user/User.vue:23
 #: src/views/user/User.vue:23
 msgid "Created at"
 msgid "Created at"
 msgstr ""
 msgstr ""
@@ -104,7 +111,7 @@ msgstr ""
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:196
+#: src/views/domain/DomainAdd.vue:88 src/views/domain/DomainEdit.vue:174
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr ""
 msgstr ""
 
 
@@ -121,10 +128,14 @@ msgstr ""
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:133
+#: src/views/domain/DomainEdit.vue:134
 msgid "Do you want to change the template to support the TLS?"
 msgid "Do you want to change the template to support the TLS?"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:111
+msgid "Domain Config Created Successfully"
+msgstr ""
+
 #: src/views/domain/DomainEdit.vue:42
 #: src/views/domain/DomainEdit.vue:42
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr ""
 msgstr ""
@@ -145,11 +156,11 @@ msgstr ""
 msgid "Email (*)"
 msgid "Email (*)"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:190
+#: src/views/domain/DomainAdd.vue:82 src/views/domain/DomainEdit.vue:168
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainAdd.vue:33
+#: src/views/domain/DomainAdd.vue:39
 msgid "Enable failed"
 msgid "Enable failed"
 msgstr ""
 msgstr ""
 
 
@@ -162,7 +173,7 @@ msgstr ""
 msgid "Enabled"
 msgid "Enabled"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainAdd.vue:27 src/views/domain/DomainList.vue:46
+#: src/views/domain/DomainAdd.vue:36 src/views/domain/DomainList.vue:46
 msgid "Enabled successfully"
 msgid "Enabled successfully"
 msgstr ""
 msgstr ""
 
 
@@ -182,11 +193,16 @@ msgstr ""
 msgid "File Not Found"
 msgid "File Not Found"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:43
+msgid "Finished"
+msgstr ""
+
+#: src/views/domain/DomainAdd.vue:13 src/views/domain/DomainAdd.vue:2
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
 msgid "Getting Certificate from Let's Encrypt"
 msgid "Getting Certificate from Let's Encrypt"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:156
+#: src/views/domain/methods.js:34
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr ""
 msgstr ""
 
 
@@ -265,6 +281,10 @@ msgstr ""
 msgid "Memory"
 msgid "Memory"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:28 src/views/domain/DomainAdd.vue:2
+msgid "Modify Config"
+msgstr ""
+
 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
 msgid "Name"
 msgid "Name"
 msgstr ""
 msgstr ""
@@ -281,6 +301,10 @@ msgstr ""
 msgid "Network Total Send"
 msgid "Network Total Send"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:38
+msgid "Next"
+msgstr ""
+
 #: src/router/index.js:105
 #: src/router/index.js:105
 msgid "Not Found"
 msgid "Not Found"
 msgstr ""
 msgstr ""
@@ -289,7 +313,7 @@ msgstr ""
 msgid "Not Valid Before: %{date}"
 msgid "Not Valid Before: %{date}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:155
+#: src/views/domain/methods.js:33
 msgid ""
 msgid ""
 "Note: The server_name in the current configuration must be the domain name "
 "Note: The server_name in the current configuration must be the domain name "
 "you need to get the certificate."
 "you need to get the certificate."
@@ -343,18 +367,17 @@ msgstr ""
 msgid "Root Directory (root)"
 msgid "Root Directory (root)"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainAdd.vue:6
-#: src/views/domain/DomainEdit.vue:24
+#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainEdit.vue:27
 msgid "Save"
 msgid "Save"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:38
-#: src/views/domain/DomainEdit.vue:151
+#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:43
+#: src/views/domain/DomainAdd.vue:54 src/views/domain/DomainEdit.vue:152
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:24
-#: src/views/domain/DomainEdit.vue:145
+#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:33
+#: src/views/domain/DomainAdd.vue:51 src/views/domain/DomainEdit.vue:146
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr ""
 msgstr ""
 
 
@@ -362,7 +385,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:71
+#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:72
 #: src/views/other/Login.vue:35
 #: src/views/other/Login.vue:35
 msgid "Server error"
 msgid "Server error"
 msgstr ""
 msgstr ""
@@ -379,6 +402,10 @@ msgstr ""
 msgid "Sites List"
 msgid "Sites List"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:20 src/views/domain/DomainAdd.vue:9
+msgid "Skip"
+msgstr ""
+
 #: src/views/domain/DomainList.vue:11
 #: src/views/domain/DomainList.vue:11
 msgid "Status"
 msgid "Status"
 msgstr ""
 msgstr ""
@@ -418,11 +445,12 @@ msgid ""
 "changed after it has been created."
 "changed after it has been created."
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:15 src/views/domain/DomainAdd.vue:4
 #: src/views/domain/DomainEdit.vue:11 src/views/domain/DomainEdit.vue:5
 #: src/views/domain/DomainEdit.vue:11 src/views/domain/DomainEdit.vue:5
 msgid "This feature is not available in demo."
 msgid "This feature is not available in demo."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainEdit.vue:135
 msgid "This operation will lose the custom configuration."
 msgid "This operation will lose the custom configuration."
 msgstr ""
 msgstr ""
 
 

BIN=BIN
frontend/src/locale/zh_CN/LC_MESSAGES/app.mo


+ 58 - 26
frontend/src/locale/zh_CN/LC_MESSAGES/app.po

@@ -25,28 +25,27 @@ msgstr "关于"
 msgid "Action"
 msgid "Action"
 msgstr "操作"
 msgstr "操作"
 
 
-#: src/router/index.js:47 src/views/domain/DomainAdd.vue:18
+#: src/router/index.js:47 src/views/domain/DomainAdd.vue:27
 msgid "Add Site"
 msgid "Add Site"
 msgstr "添加站点"
 msgstr "添加站点"
 
 
-#: src/views/domain/DomainAdd.vue:2
-msgid ""
-"Add site here first, then you can configure TLS on the domain edit page."
-msgstr "在这里添加站点,完成后可进入编辑页面配置 TLS。"
-
-#: src/views/domain/DomainEdit.vue:194
+#: src/views/domain/DomainAdd.vue:86 src/views/domain/DomainEdit.vue:172
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "成功关闭 %{name} 自动续签"
 msgstr "成功关闭 %{name} 自动续签"
 
 
-#: src/views/domain/DomainEdit.vue:188
+#: src/views/domain/DomainAdd.vue:80 src/views/domain/DomainEdit.vue:166
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "成功启用 %{name} 自动续签"
 msgstr "成功启用 %{name} 自动续签"
 
 
+#: src/views/domain/DomainAdd.vue:37
+msgid "Base information"
+msgstr "基本信息"
+
 #: src/views/other/About.vue:11
 #: src/views/other/About.vue:11
 msgid "Build with"
 msgid "Build with"
 msgstr "构建基于"
 msgstr "构建基于"
 
 
-#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:23
+#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:24
 msgid "Cancel"
 msgid "Cancel"
 msgstr "取消"
 msgstr "取消"
 
 
@@ -78,6 +77,10 @@ msgstr "配置名称"
 msgid "Configurations"
 msgid "Configurations"
 msgstr "配置"
 msgstr "配置"
 
 
+#: src/views/domain/DomainAdd.vue:40
+msgid "Configure SSL"
+msgstr "配置 SSL"
+
 #: src/views/dashboard/DashBoard.vue:207
 #: src/views/dashboard/DashBoard.vue:207
 msgid "CPU Status"
 msgid "CPU Status"
 msgstr "CPU 状态"
 msgstr "CPU 状态"
@@ -86,6 +89,10 @@ msgstr "CPU 状态"
 msgid "CPU:"
 msgid "CPU:"
 msgstr ""
 msgstr ""
 
 
+#: src/views/domain/DomainAdd.vue:31 src/views/domain/DomainAdd.vue:5
+msgid "Create Another"
+msgstr "再创建一个"
+
 #: src/views/user/User.vue:23
 #: src/views/user/User.vue:23
 msgid "Created at"
 msgid "Created at"
 msgstr "创建时间"
 msgstr "创建时间"
@@ -106,7 +113,7 @@ msgstr "检测到版本更新,页面将会刷新。"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "开发模式"
 msgstr "开发模式"
 
 
-#: src/views/domain/DomainEdit.vue:196
+#: src/views/domain/DomainAdd.vue:88 src/views/domain/DomainEdit.vue:174
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "关闭 %{name} 自动续签失败"
 msgstr "关闭 %{name} 自动续签失败"
 
 
@@ -123,10 +130,14 @@ msgstr "禁用成功"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "磁盘 IO"
 msgstr "磁盘 IO"
 
 
-#: src/views/domain/DomainEdit.vue:133
+#: src/views/domain/DomainEdit.vue:134
 msgid "Do you want to change the template to support the TLS?"
 msgid "Do you want to change the template to support the TLS?"
 msgstr "你想要改变模板以支持 TLS 吗?"
 msgstr "你想要改变模板以支持 TLS 吗?"
 
 
+#: src/views/domain/DomainAdd.vue:111
+msgid "Domain Config Created Successfully"
+msgstr "域名配置文件创建成功"
+
 #: src/views/domain/DomainEdit.vue:42
 #: src/views/domain/DomainEdit.vue:42
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "编辑 %{n}"
 msgstr "编辑 %{n}"
@@ -147,11 +158,11 @@ msgstr "编辑站点"
 msgid "Email (*)"
 msgid "Email (*)"
 msgstr "邮箱 (*)"
 msgstr "邮箱 (*)"
 
 
-#: src/views/domain/DomainEdit.vue:190
+#: src/views/domain/DomainAdd.vue:82 src/views/domain/DomainEdit.vue:168
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "启用 %{name} 自动续签失败"
 msgstr "启用 %{name} 自动续签失败"
 
 
-#: src/views/domain/DomainAdd.vue:33
+#: src/views/domain/DomainAdd.vue:39
 msgid "Enable failed"
 msgid "Enable failed"
 msgstr "启用失败"
 msgstr "启用失败"
 
 
@@ -164,7 +175,7 @@ msgstr "启用 TLS"
 msgid "Enabled"
 msgid "Enabled"
 msgstr "启用"
 msgstr "启用"
 
 
-#: src/views/domain/DomainAdd.vue:27 src/views/domain/DomainList.vue:46
+#: src/views/domain/DomainAdd.vue:36 src/views/domain/DomainList.vue:46
 msgid "Enabled successfully"
 msgid "Enabled successfully"
 msgstr "启用成功"
 msgstr "启用成功"
 
 
@@ -184,11 +195,16 @@ msgstr "启用失败 %{msg}"
 msgid "File Not Found"
 msgid "File Not Found"
 msgstr "未找到文件"
 msgstr "未找到文件"
 
 
+#: src/views/domain/DomainAdd.vue:43
+msgid "Finished"
+msgstr "完成"
+
+#: src/views/domain/DomainAdd.vue:13 src/views/domain/DomainAdd.vue:2
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
 msgid "Getting Certificate from Let's Encrypt"
 msgid "Getting Certificate from Let's Encrypt"
 msgstr "从 Let's Encrypt 获取证书"
 msgstr "从 Let's Encrypt 获取证书"
 
 
-#: src/views/domain/DomainEdit.vue:156
+#: src/views/domain/methods.js:34
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "正在获取证书,请稍等..."
 msgstr "正在获取证书,请稍等..."
 
 
@@ -269,6 +285,10 @@ msgstr "用户管理"
 msgid "Memory"
 msgid "Memory"
 msgstr "内存"
 msgstr "内存"
 
 
+#: src/views/domain/DomainAdd.vue:28 src/views/domain/DomainAdd.vue:2
+msgid "Modify Config"
+msgstr "修改配置文件"
+
 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
 msgid "Name"
 msgid "Name"
 msgstr "名称"
 msgstr "名称"
@@ -285,6 +305,10 @@ msgstr "下载流量"
 msgid "Network Total Send"
 msgid "Network Total Send"
 msgstr "上传流量"
 msgstr "上传流量"
 
 
+#: src/views/domain/DomainAdd.vue:38
+msgid "Next"
+msgstr "下一步"
+
 #: src/router/index.js:105
 #: src/router/index.js:105
 msgid "Not Found"
 msgid "Not Found"
 msgstr "找不到页面"
 msgstr "找不到页面"
@@ -293,7 +317,7 @@ msgstr "找不到页面"
 msgid "Not Valid Before: %{date}"
 msgid "Not Valid Before: %{date}"
 msgstr "此前无效: %{date}"
 msgstr "此前无效: %{date}"
 
 
-#: src/views/domain/DomainEdit.vue:155
+#: src/views/domain/methods.js:33
 msgid ""
 msgid ""
 "Note: The server_name in the current configuration must be the domain name "
 "Note: The server_name in the current configuration must be the domain name "
 "you need to get the certificate."
 "you need to get the certificate."
@@ -347,18 +371,17 @@ msgstr "下载"
 msgid "Root Directory (root)"
 msgid "Root Directory (root)"
 msgstr "网站根目录 (root)"
 msgstr "网站根目录 (root)"
 
 
-#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainAdd.vue:6
-#: src/views/domain/DomainEdit.vue:24
+#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainEdit.vue:27
 msgid "Save"
 msgid "Save"
 msgstr "保存"
 msgstr "保存"
 
 
-#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:38
-#: src/views/domain/DomainEdit.vue:151
+#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:43
+#: src/views/domain/DomainAdd.vue:54 src/views/domain/DomainEdit.vue:152
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "保存错误 %{msg}"
 msgstr "保存错误 %{msg}"
 
 
-#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:24
-#: src/views/domain/DomainEdit.vue:145
+#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:33
+#: src/views/domain/DomainAdd.vue:51 src/views/domain/DomainEdit.vue:146
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr "保存成功"
 msgstr "保存成功"
 
 
@@ -366,7 +389,7 @@ msgstr "保存成功"
 msgid "Send"
 msgid "Send"
 msgstr "上传"
 msgstr "上传"
 
 
-#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:71
+#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:72
 #: src/views/other/Login.vue:35
 #: src/views/other/Login.vue:35
 msgid "Server error"
 msgid "Server error"
 msgstr "服务器错误"
 msgstr "服务器错误"
@@ -383,6 +406,10 @@ msgstr "网站域名 (server_name)"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "站点列表"
 msgstr "站点列表"
 
 
+#: src/views/domain/DomainAdd.vue:20 src/views/domain/DomainAdd.vue:9
+msgid "Skip"
+msgstr "跳过"
+
 #: src/views/domain/DomainList.vue:11
 #: src/views/domain/DomainList.vue:11
 msgid "Status"
 msgid "Status"
 msgstr "状态"
 msgstr "状态"
@@ -423,14 +450,15 @@ msgid ""
 "fields in your configuration file. The configuration filename cannot be "
 "fields in your configuration file. The configuration filename cannot be "
 "changed after it has been created."
 "changed after it has been created."
 msgstr ""
 msgstr ""
-"只有在您的配置文件中有相应字段时,下列的配置才能生效。配置文件名称创建后不"
-"修改。"
+"只有在您的配置文件中有相应字段时,下列的配置才能生效。配置文件名称创建后不"
+"修改。"
 
 
+#: src/views/domain/DomainAdd.vue:15 src/views/domain/DomainAdd.vue:4
 #: src/views/domain/DomainEdit.vue:11 src/views/domain/DomainEdit.vue:5
 #: src/views/domain/DomainEdit.vue:11 src/views/domain/DomainEdit.vue:5
 msgid "This feature is not available in demo."
 msgid "This feature is not available in demo."
 msgstr "该功能在 Demo 中不可用。"
 msgstr "该功能在 Demo 中不可用。"
 
 
-#: src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainEdit.vue:135
 msgid "This operation will lose the custom configuration."
 msgid "This operation will lose the custom configuration."
 msgstr "该操作将会丢失自定义配置。"
 msgstr "该操作将会丢失自定义配置。"
 
 
@@ -455,6 +483,10 @@ msgstr "用户名 (*)"
 msgid "Writes"
 msgid "Writes"
 msgstr "写"
 msgstr "写"
 
 
+#~ msgid ""
+#~ "Add site here first, then you can configure TLS on the domain edit page."
+#~ msgstr "在这里添加站点,完成后可进入编辑页面配置 TLS。"
+
 #~ msgid "Server Status"
 #~ msgid "Server Status"
 #~ msgstr "服务器状态"
 #~ msgstr "服务器状态"
 
 

BIN=BIN
frontend/src/locale/zh_TW/LC_MESSAGES/app.mo


+ 59 - 25
frontend/src/locale/zh_TW/LC_MESSAGES/app.po

@@ -11,7 +11,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: easygettext\n"
 "Generated-By: easygettext\n"
-"X-Generator: Poedit 2.2\n"
+"X-Generator: Poedit 3.0.1\n"
 
 
 #: src/router/index.js:99
 #: src/router/index.js:99
 msgid "404 Not Found"
 msgid "404 Not Found"
@@ -26,28 +26,27 @@ msgstr "關於"
 msgid "Action"
 msgid "Action"
 msgstr "操作"
 msgstr "操作"
 
 
-#: src/router/index.js:47 src/views/domain/DomainAdd.vue:18
+#: src/router/index.js:47 src/views/domain/DomainAdd.vue:27
 msgid "Add Site"
 msgid "Add Site"
 msgstr "新增站點"
 msgstr "新增站點"
 
 
-#: src/views/domain/DomainAdd.vue:2
-msgid ""
-"Add site here first, then you can configure TLS on the domain edit page."
-msgstr "在這裡新增站點,完成後可進入編輯頁面配置 TLS。"
-
-#: src/views/domain/DomainEdit.vue:194
+#: src/views/domain/DomainAdd.vue:86 src/views/domain/DomainEdit.vue:172
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "成功關閉 %{name} 自動續簽"
 msgstr "成功關閉 %{name} 自動續簽"
 
 
-#: src/views/domain/DomainEdit.vue:188
+#: src/views/domain/DomainAdd.vue:80 src/views/domain/DomainEdit.vue:166
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "成功啟用 %{name} 自動續簽"
 msgstr "成功啟用 %{name} 自動續簽"
 
 
+#: src/views/domain/DomainAdd.vue:37
+msgid "Base information"
+msgstr "基本訊息"
+
 #: src/views/other/About.vue:11
 #: src/views/other/About.vue:11
 msgid "Build with"
 msgid "Build with"
 msgstr "構建基於"
 msgstr "構建基於"
 
 
-#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:23
+#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:24
 msgid "Cancel"
 msgid "Cancel"
 msgstr "取消"
 msgstr "取消"
 
 
@@ -79,6 +78,10 @@ msgstr "配置名稱"
 msgid "Configurations"
 msgid "Configurations"
 msgstr "配置"
 msgstr "配置"
 
 
+#: src/views/domain/DomainAdd.vue:40
+msgid "Configure SSL"
+msgstr "配置 SSL"
+
 #: src/views/dashboard/DashBoard.vue:207
 #: src/views/dashboard/DashBoard.vue:207
 msgid "CPU Status"
 msgid "CPU Status"
 msgstr "中央處理器狀態"
 msgstr "中央處理器狀態"
@@ -87,6 +90,10 @@ msgstr "中央處理器狀態"
 msgid "CPU:"
 msgid "CPU:"
 msgstr "中央處理器:"
 msgstr "中央處理器:"
 
 
+#: src/views/domain/DomainAdd.vue:31 src/views/domain/DomainAdd.vue:5
+msgid "Create Another"
+msgstr "再創建一個"
+
 #: src/views/user/User.vue:23
 #: src/views/user/User.vue:23
 msgid "Created at"
 msgid "Created at"
 msgstr "建立時間"
 msgstr "建立時間"
@@ -107,7 +114,7 @@ msgstr "檢測到版本更新,頁面將會重新整理。"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "開發模式"
 msgstr "開發模式"
 
 
-#: src/views/domain/DomainEdit.vue:196
+#: src/views/domain/DomainAdd.vue:88 src/views/domain/DomainEdit.vue:174
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "關閉 %{name} 自動續簽失敗"
 msgstr "關閉 %{name} 自動續簽失敗"
 
 
@@ -124,10 +131,14 @@ msgstr "禁用成功"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "磁碟 IO"
 msgstr "磁碟 IO"
 
 
-#: src/views/domain/DomainEdit.vue:133
+#: src/views/domain/DomainEdit.vue:134
 msgid "Do you want to change the template to support the TLS?"
 msgid "Do you want to change the template to support the TLS?"
 msgstr "你想要改變模板以支援 TLS 嗎?"
 msgstr "你想要改變模板以支援 TLS 嗎?"
 
 
+#: src/views/domain/DomainAdd.vue:111
+msgid "Domain Config Created Successfully"
+msgstr "域名配置文件創建成功"
+
 #: src/views/domain/DomainEdit.vue:42
 #: src/views/domain/DomainEdit.vue:42
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "編輯 %{n}"
 msgstr "編輯 %{n}"
@@ -148,11 +159,11 @@ msgstr "編輯站點"
 msgid "Email (*)"
 msgid "Email (*)"
 msgstr "郵箱 (*)"
 msgstr "郵箱 (*)"
 
 
-#: src/views/domain/DomainEdit.vue:190
+#: src/views/domain/DomainAdd.vue:82 src/views/domain/DomainEdit.vue:168
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "啟用 %{name} 自動續簽失敗"
 msgstr "啟用 %{name} 自動續簽失敗"
 
 
-#: src/views/domain/DomainAdd.vue:33
+#: src/views/domain/DomainAdd.vue:39
 msgid "Enable failed"
 msgid "Enable failed"
 msgstr "啟用失敗"
 msgstr "啟用失敗"
 
 
@@ -165,7 +176,7 @@ msgstr "啟用 TLS"
 msgid "Enabled"
 msgid "Enabled"
 msgstr "啟用"
 msgstr "啟用"
 
 
-#: src/views/domain/DomainAdd.vue:27 src/views/domain/DomainList.vue:46
+#: src/views/domain/DomainAdd.vue:36 src/views/domain/DomainList.vue:46
 msgid "Enabled successfully"
 msgid "Enabled successfully"
 msgstr "啟用成功"
 msgstr "啟用成功"
 
 
@@ -185,11 +196,16 @@ msgstr "啟用失敗 %{msg}"
 msgid "File Not Found"
 msgid "File Not Found"
 msgstr "未找到檔案"
 msgstr "未找到檔案"
 
 
+#: src/views/domain/DomainAdd.vue:43
+msgid "Finished"
+msgstr "完成"
+
+#: src/views/domain/DomainAdd.vue:13 src/views/domain/DomainAdd.vue:2
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
 msgid "Getting Certificate from Let's Encrypt"
 msgid "Getting Certificate from Let's Encrypt"
 msgstr "從 Let's Encrypt 獲取證書"
 msgstr "從 Let's Encrypt 獲取證書"
 
 
-#: src/views/domain/DomainEdit.vue:156
+#: src/views/domain/methods.js:34
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "正在獲取證書,請稍等..."
 msgstr "正在獲取證書,請稍等..."
 
 
@@ -247,6 +263,7 @@ msgid "Logout successful"
 msgstr "登出成功"
 msgstr "登出成功"
 
 
 #: src/views/domain/DomainEdit.vue:12 src/views/domain/DomainEdit.vue:6
 #: src/views/domain/DomainEdit.vue:12 src/views/domain/DomainEdit.vue:6
+#, fuzzy
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "HTTPChallengePort (default: 9180) before getting the certificate."
 "HTTPChallengePort (default: 9180) before getting the certificate."
@@ -270,6 +287,10 @@ msgstr "使用者管理"
 msgid "Memory"
 msgid "Memory"
 msgstr "記憶體"
 msgstr "記憶體"
 
 
+#: src/views/domain/DomainAdd.vue:28 src/views/domain/DomainAdd.vue:2
+msgid "Modify Config"
+msgstr "修改配置"
+
 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
 msgid "Name"
 msgid "Name"
 msgstr "名稱"
 msgstr "名稱"
@@ -286,6 +307,10 @@ msgstr "下載流量"
 msgid "Network Total Send"
 msgid "Network Total Send"
 msgstr "上傳流量"
 msgstr "上傳流量"
 
 
+#: src/views/domain/DomainAdd.vue:38
+msgid "Next"
+msgstr "下一步"
+
 #: src/router/index.js:105
 #: src/router/index.js:105
 msgid "Not Found"
 msgid "Not Found"
 msgstr "找不到頁面"
 msgstr "找不到頁面"
@@ -294,7 +319,7 @@ msgstr "找不到頁面"
 msgid "Not Valid Before: %{date}"
 msgid "Not Valid Before: %{date}"
 msgstr "此前無效: %{date}"
 msgstr "此前無效: %{date}"
 
 
-#: src/views/domain/DomainEdit.vue:155
+#: src/views/domain/methods.js:33
 msgid ""
 msgid ""
 "Note: The server_name in the current configuration must be the domain name "
 "Note: The server_name in the current configuration must be the domain name "
 "you need to get the certificate."
 "you need to get the certificate."
@@ -348,18 +373,17 @@ msgstr "下載"
 msgid "Root Directory (root)"
 msgid "Root Directory (root)"
 msgstr "網站根目錄 (root)"
 msgstr "網站根目錄 (root)"
 
 
-#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainAdd.vue:6
-#: src/views/domain/DomainEdit.vue:24
+#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainEdit.vue:27
 msgid "Save"
 msgid "Save"
 msgstr "儲存"
 msgstr "儲存"
 
 
-#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:38
-#: src/views/domain/DomainEdit.vue:151
+#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:43
+#: src/views/domain/DomainAdd.vue:54 src/views/domain/DomainEdit.vue:152
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "儲存錯誤 %{msg}"
 msgstr "儲存錯誤 %{msg}"
 
 
-#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:24
-#: src/views/domain/DomainEdit.vue:145
+#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:33
+#: src/views/domain/DomainAdd.vue:51 src/views/domain/DomainEdit.vue:146
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr "儲存成功"
 msgstr "儲存成功"
 
 
@@ -367,7 +391,7 @@ msgstr "儲存成功"
 msgid "Send"
 msgid "Send"
 msgstr "上傳"
 msgstr "上傳"
 
 
-#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:71
+#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:72
 #: src/views/other/Login.vue:35
 #: src/views/other/Login.vue:35
 msgid "Server error"
 msgid "Server error"
 msgstr "伺服器錯誤"
 msgstr "伺服器錯誤"
@@ -384,6 +408,10 @@ msgstr "網站域名 (server_name)"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "站點列表"
 msgstr "站點列表"
 
 
+#: src/views/domain/DomainAdd.vue:20 src/views/domain/DomainAdd.vue:9
+msgid "Skip"
+msgstr "跳過"
+
 #: src/views/domain/DomainList.vue:11
 #: src/views/domain/DomainList.vue:11
 msgid "Status"
 msgid "Status"
 msgstr "狀態"
 msgstr "狀態"
@@ -419,6 +447,7 @@ msgid "The filename cannot contain the following characters: %{c}"
 msgstr "檔名不能包含以下字元: %{c}"
 msgstr "檔名不能包含以下字元: %{c}"
 
 
 #: src/views/domain/DomainEdit.vue:4
 #: src/views/domain/DomainEdit.vue:4
+#, fuzzy
 msgid ""
 msgid ""
 "The following values will only take effect if you have the corresponding "
 "The following values will only take effect if you have the corresponding "
 "fields in your configuration file. The configuration filename cannot be "
 "fields in your configuration file. The configuration filename cannot be "
@@ -427,11 +456,12 @@ msgstr ""
 "只有在您的配置檔案中有相應欄位時,下列的配置才能生效。配置檔名稱建立後不可修"
 "只有在您的配置檔案中有相應欄位時,下列的配置才能生效。配置檔名稱建立後不可修"
 "改。"
 "改。"
 
 
+#: src/views/domain/DomainAdd.vue:15 src/views/domain/DomainAdd.vue:4
 #: src/views/domain/DomainEdit.vue:11 src/views/domain/DomainEdit.vue:5
 #: src/views/domain/DomainEdit.vue:11 src/views/domain/DomainEdit.vue:5
 msgid "This feature is not available in demo."
 msgid "This feature is not available in demo."
 msgstr "此功能在演示中不可用。"
 msgstr "此功能在演示中不可用。"
 
 
-#: src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainEdit.vue:135
 msgid "This operation will lose the custom configuration."
 msgid "This operation will lose the custom configuration."
 msgstr "該操作將會丟失自定義配置。"
 msgstr "該操作將會丟失自定義配置。"
 
 
@@ -456,6 +486,10 @@ msgstr "使用者名稱 (*)"
 msgid "Writes"
 msgid "Writes"
 msgstr "寫"
 msgstr "寫"
 
 
+#~ msgid ""
+#~ "Add site here first, then you can configure TLS on the domain edit page."
+#~ msgstr "在這裡新增站點,完成後可進入編輯頁面配置 TLS。"
+
 #~ msgid "Server Status"
 #~ msgid "Server Status"
 #~ msgstr "伺服器狀態"
 #~ msgstr "伺服器狀態"
 
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
frontend/src/translations.json


+ 1 - 1
frontend/src/views/config/ConfigEdit.vue

@@ -13,7 +13,7 @@
 <script>
 <script>
 import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
 import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
 import VueItextarea from '@/components/VueItextarea/VueItextarea'
 import VueItextarea from '@/components/VueItextarea/VueItextarea'
-import {$gettext, $interpolate} from "@/lib/translate/gettext"
+import $gettext, {$interpolate} from "@/lib/translate/gettext";
 
 
 export default {
 export default {
     name: 'DomainEdit',
     name: 'DomainEdit',

+ 140 - 31
frontend/src/views/domain/DomainAdd.vue

@@ -1,59 +1,163 @@
 <template>
 <template>
     <a-card :title="$gettext('Add Site')">
     <a-card :title="$gettext('Add Site')">
-        <p v-translate>Add site here first, then you can configure TLS on the domain edit page.</p>
-        <std-data-entry :data-list="columns" :data-source="config"/>
-        <footer-tool-bar>
-            <a-button
-                type="primary"
-                @click="save"
+        <div class="container">
+            <a-steps :current="current_step" size="small">
+                <a-step :title="$gettext('Base information')" />
+                <a-step :title="$gettext('Configure SSL')" />
+                <a-step :title="$gettext('Finished')" />
+            </a-steps>
+
+            <std-data-entry :data-list="columns" :data-source="config" :error="error" v-show="current_step===0"/>
+
+            <template v-if="current_step===1">
+                <a-button
+                    @click="issue_cert"
+                    type="primary" ghost
+                    style="margin: 10px 0"
+                    :disabled="is_demo"
+                >
+                    <translate>Getting Certificate from Let's Encrypt</translate>
+                </a-button>
+                <p v-if="is_demo" v-translate>This feature is not available in demo.</p>
+
+                <std-data-entry :data-list="columnsSSL" :data-source="config" :error="error" />
+                <a-space style="margin-right: 10px">
+                    <a-button
+                        v-if="current_step===1"
+                        @click="current_step++"
+                    >
+                        <translate>Skip</translate>
+                    </a-button>
+                </a-space>
+            </template>
+
+            <a-result
+                v-if="current_step===2"
+                status="success"
+                :title="$gettext('Domain Config Created Successfully')"
             >
             >
-                <translate>Save</translate>
-            </a-button>
-        </footer-tool-bar>
+                <template #extra>
+                    <a-button type="primary" @click="goto_modify">
+                        <translate>Modify Config</translate>
+                    </a-button>
+                    <a-button @click="create_another">
+                        <translate>Create Another</translate>
+                    </a-button>
+                </template>
+            </a-result>
+
+            <a-space v-if="current_step<2">
+                <a-button
+                    type="primary"
+                    @click="save"
+                    :disabled="!config.name"
+                >
+                    <translate>Next</translate>
+                </a-button>
+            </a-space>
+
+        </div>
+
+
     </a-card>
     </a-card>
 </template>
 </template>
 
 
 <script>
 <script>
-import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
 import StdDataEntry from '@/components/StdDataEntry/StdDataEntry'
 import StdDataEntry from '@/components/StdDataEntry/StdDataEntry'
-import {columns} from '@/views/domain/columns'
-import {unparse} from '@/views/domain/methods'
-import $gettext, {$interpolate} from "@/lib/translate/gettext";
+import {columns, columnsSSL} from '@/views/domain/columns'
+import {unparse, issue_cert} from '@/views/domain/methods'
+import $gettext, {$interpolate} from "@/lib/translate/gettext"
 
 
 export default {
 export default {
     name: 'DomainAdd',
     name: 'DomainAdd',
-    components: {StdDataEntry, FooterToolBar},
+    components: {StdDataEntry},
     data() {
     data() {
         return {
         return {
-            config: {},
-            columns: columns.slice(0, -1) // 隐藏SSL支持开关
+            config: {
+                http_listen_port: 80,
+                https_listen_port: 443
+            },
+            columns: columns.slice(0, -1), // 隐藏SSL支持开关
+            error: {},
+            current_step: 0,
+            columnsSSL
         }
         }
     },
     },
-    beforeCreate() {
-
+    watch: {
+        'config.auto_cert'() {
+            this.change_auto_cert()
+        }
     },
     },
     methods: {
     methods: {
         save() {
         save() {
-            this.$api.domain.get_template('http-conf').then(r => {
-                let text = unparse(r.template, this.config)
-                this.$api.domain.save(this.config.name, {content: text, enabled: true}).then(() => {
-                    this.$message.success($gettext('Saved successfully'))
+            if (this.current_step===0) {
+                this.$api.domain.get_template('http-conf').then(r => {
+                    let text = unparse(r.template, this.config)
 
 
-                    this.$api.domain.enable(this.config.name).then(() => {
-                        this.$message.success($gettext('Enabled successfully'))
+                    this.$api.domain.save(this.config.name, {content: text, enabled: true}).then(() => {
+                        this.$message.success($gettext('Saved successfully'))
 
 
-                        this.$router.push('/domain/' + this.config.name)
+                        this.$api.domain.enable(this.config.name).then(() => {
+                            this.$message.success($gettext('Enabled successfully'))
+                            this.current_step++
+                        }).catch(r => {
+                            this.$message.error(r.message ?? $gettext('Enable failed'), 10)
+                        })
 
 
                     }).catch(r => {
                     }).catch(r => {
-                        console.log(r)
-                        this.$message.error(r.message ?? $gettext('Enable failed'), 10)
+                        this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}), 10)
                     })
                     })
+                })
+            } else if (this.current_step === 1) {
+                this.$api.domain.get_template('https-conf').then(r => {
+                    let text = unparse(r.template, this.config)
+
+                    this.$api.domain.save(this.config.name, {content: text, enabled: true}).then(() => {
+                        this.$message.success($gettext('Saved successfully'))
+                        this.current_step++
+                    }).catch(r => {
+                        this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}), 10)
+                    })
+                })
+            }
 
 
-                }).catch(r => {
-                    console.log(r)
-                    this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}), 10)
+        },
+        issue_cert() {
+            issue_cert(this.config.server_name, this.callback)
+        },
+        callback(ssl_certificate, ssl_certificate_key) {
+            this.$set(this.config, 'ssl_certificate', ssl_certificate)
+            this.$set(this.config, 'ssl_certificate_key', ssl_certificate_key)
+        },
+        goto_modify() {
+            this.$router.push('/domain/'+this.config.name)
+        },
+        create_another() {
+            this.current_step = 0
+            this.config = {
+                http_listen_port: 80,
+                https_listen_port: 443
+            }
+        },
+        change_auto_cert() {
+            if (this.config.auto_cert) {
+                this.$api.domain.add_auto_cert(this.config.name).then(() => {
+                    this.$message.success($interpolate($gettext('Auto-renewal enabled for %{name}'), {name: this.config.name}))
+                }).catch(e => {
+                    this.$message.error(e.message ?? $interpolate($gettext('Enable auto-renewal failed for %{name}'), {name: this.config.name}))
                 })
                 })
-            })
+            } else {
+                this.$api.domain.remove_auto_cert(this.config.name).then(() => {
+                    this.$message.success($interpolate($gettext('Auto-renewal disabled for %{name}'), {name: this.config.name}))
+                }).catch(e => {
+                    this.$message.error(e.message ?? $interpolate($gettext('Disable auto-renewal failed for %{name}'), {name: this.config.name}))
+                })
+            }
+        }
+    },
+    computed: {
+        is_demo() {
+            return this.$store.getters.env.demo === true
         }
         }
     }
     }
 }
 }
@@ -63,4 +167,9 @@ export default {
 .ant-steps {
 .ant-steps {
     padding: 10px 0 20px 0;
     padding: 10px 0 20px 0;
 }
 }
+
+.container {
+    max-width: 800px;
+    margin: 0 auto
+}
 </style>
 </style>

+ 21 - 39
frontend/src/views/domain/DomainEdit.vue

@@ -26,8 +26,12 @@
 
 
         <footer-tool-bar>
         <footer-tool-bar>
             <a-space>
             <a-space>
-                <a-button @click="$router.go(-1)"><translate>Cancel</translate></a-button>
-                <a-button type="primary" @click="save"><translate>Save</translate></a-button>
+                <a-button @click="$router.go(-1)">
+                    <translate>Cancel</translate>
+                </a-button>
+                <a-button type="primary" @click="save">
+                    <translate>Save</translate>
+                </a-button>
             </a-space>
             </a-space>
         </footer-tool-bar>
         </footer-tool-bar>
     </div>
     </div>
@@ -39,9 +43,10 @@ import StdDataEntry from '@/components/StdDataEntry/StdDataEntry'
 import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
 import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
 import VueItextarea from '@/components/VueItextarea/VueItextarea'
 import VueItextarea from '@/components/VueItextarea/VueItextarea'
 import {columns, columnsSSL} from '@/views/domain/columns'
 import {columns, columnsSSL} from '@/views/domain/columns'
-import {unparse} from '@/views/domain/methods'
+import {unparse, issue_cert} from '@/views/domain/methods'
 import CertInfo from '@/views/domain/CertInfo'
 import CertInfo from '@/views/domain/CertInfo'
-import {$gettext, $interpolate} from "@/lib/translate/gettext"
+import {$gettext, $interpolate} from '@/lib/translate/gettext'
+
 
 
 export default {
 export default {
     name: 'DomainEdit',
     name: 'DomainEdit',
@@ -185,52 +190,29 @@ export default {
                 }
                 }
             }).catch(r => {
             }).catch(r => {
                 console.log(r)
                 console.log(r)
-                this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}), 10)
+                this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ''}), 10)
             })
             })
         },
         },
         issue_cert() {
         issue_cert() {
-            this.$message.info($gettext('Note: The server_name in the current configuration must be the domain name you need to get the certificate.'), 15)
-            this.$message.info($gettext('Getting the certificate, please wait...'), 15)
-            this.ws = new WebSocket(this.getWebSocketRoot() + '/cert/issue/' + this.config.server_name
-                + '?token=' + btoa(this.$store.state.user.token))
-
-            this.ws.onopen = () => {
-                this.ws.send('go')
-            }
-
-            this.ws.onmessage = m => {
-                const r = JSON.parse(m.data)
-                switch (r.status) {
-                    case 'success':
-                        this.$message.success(r.message, 10)
-                        break
-                    case 'info':
-                        this.$message.info(r.message, 10)
-                        break
-                    case 'error':
-                        this.$message.error(r.message, 10)
-                        break
-                }
-
-                if (r.status === 'success' && r.ssl_certificate !== undefined && r.ssl_certificate_key !== undefined) {
-                    this.config.ssl_certificate = r.ssl_certificate
-                    this.config.ssl_certificate_key = r.ssl_certificate_key
-                    if (this.$refs['cert-info']) this.$refs['cert-info'].get()
-                }
-            }
+            issue_cert(this.config.server_name, this.callback)
+        },
+        callback(ssl_certificate, ssl_certificate_key) {
+            this.$set(this.config, 'ssl_certificate', ssl_certificate)
+            this.$set(this.config, 'ssl_certificate_key', ssl_certificate_key)
+            if (this.$refs['cert-info']) this.$refs['cert-info'].get()
         },
         },
         change_auto_cert() {
         change_auto_cert() {
             if (this.config.auto_cert) {
             if (this.config.auto_cert) {
                 this.$api.domain.add_auto_cert(this.name).then(() => {
                 this.$api.domain.add_auto_cert(this.name).then(() => {
-                    this.$message.success($interpolate($gettext('Auto-renewal enabled for %{name}'), {name: this.name}))
+                    this.$message.success($interpolate($gettext('Auto-renewal enabled for %{name}', {name: this.name})))
                 }).catch(e => {
                 }).catch(e => {
-                    this.$message.error(e.message ?? $interpolate($gettext('Enable auto-renewal failed for %{name}'), {name: this.name}))
+                    this.$message.error(e.message ?? $interpolate($gettext('Enable auto-renewal failed for %{name}', {name: this.name})))
                 })
                 })
             } else {
             } else {
                 this.$api.domain.remove_auto_cert(this.name).then(() => {
                 this.$api.domain.remove_auto_cert(this.name).then(() => {
-                    this.$message.success($interpolate($gettext('Auto-renewal disabled for %{name}'), {name: this.name}))
+                    this.$message.success($interpolate($gettext('Auto-renewal disabled for %{name}', {name: this.name})))
                 }).catch(e => {
                 }).catch(e => {
-                    this.$message.error(e.message ?? $interpolate($gettext('Disable auto-renewal failed for %{name}'), {name: this.name}))
+                    this.$message.error(e.message ?? $interpolate($gettext('Disable auto-renewal failed for %{name}', {name: this.name})))
                 })
                 })
             }
             }
         }
         }
@@ -246,7 +228,7 @@ export default {
             }
             }
         },
         },
         is_demo() {
         is_demo() {
-            return this.$store.getters.env.demo===true
+            return this.$store.getters.env.demo === true
         }
         }
     }
     }
 }
 }

+ 34 - 1
frontend/src/views/domain/methods.js

@@ -1,3 +1,6 @@
+import $gettext from '@/lib/translate/gettext'
+import store from '@/lib/store'
+import Vue from 'vue'
 const unparse = (text, config) => {
 const unparse = (text, config) => {
     // http_listen_port: /listen (.*);/i,
     // http_listen_port: /listen (.*);/i,
     // https_listen_port: /listen (.*) ssl/i,
     // https_listen_port: /listen (.*) ssl/i,
@@ -26,4 +29,34 @@ const unparse = (text, config) => {
     return text
     return text
 }
 }
 
 
-export {unparse}
+const issue_cert = (server_name, callback) => {
+    Vue.prototype.$message.info($gettext('Note: The server_name in the current configuration must be the domain name you need to get the certificate.'), 15)
+    Vue.prototype.$message.info($gettext('Getting the certificate, please wait...'), 15)
+    const ws = new WebSocket(Vue.prototype.getWebSocketRoot() + '/cert/issue/' + server_name
+        + '?token=' + btoa(store.state.user.token))
+
+    ws.onopen = () => {
+        ws.send('go')
+    }
+
+    ws.onmessage = m => {
+        const r = JSON.parse(m.data)
+        switch (r.status) {
+            case 'success':
+                Vue.prototype.$message.success(r.message, 10)
+                break
+            case 'info':
+                Vue.prototype.$message.info(r.message, 10)
+                break
+            case 'error':
+                Vue.prototype.$message.error(r.message, 10)
+                break
+        }
+
+        if (r.status === 'success' && r.ssl_certificate !== undefined && r.ssl_certificate_key !== undefined) {
+            callback(r.ssl_certificate, r.ssl_certificate_key)
+        }
+    }
+}
+
+export {unparse, issue_cert}

+ 2 - 1
frontend/version.json

@@ -1 +1,2 @@
-{"version":"1.2.2","build_id":1,"total_build":49}
+{"version":"1.3.0","build_id":1,"total_build":51}
+

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 557 - 348
frontend/yarn.lock


+ 3 - 2
server/api/cert.go

@@ -4,6 +4,7 @@ import (
     "encoding/json"
     "encoding/json"
     "github.com/0xJacky/Nginx-UI/server/settings"
     "github.com/0xJacky/Nginx-UI/server/settings"
     "github.com/0xJacky/Nginx-UI/server/tool"
     "github.com/0xJacky/Nginx-UI/server/tool"
+    "github.com/0xJacky/Nginx-UI/server/tool/nginx"
     "github.com/gin-gonic/gin"
     "github.com/gin-gonic/gin"
     "github.com/gorilla/websocket"
     "github.com/gorilla/websocket"
     "log"
     "log"
@@ -96,7 +97,7 @@ func IssueCert(c *gin.Context) {
                 return
                 return
             }
             }
 
 
-            sslCertificatePath := tool.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
+            sslCertificatePath := nginx.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
             _, err = os.Stat(sslCertificatePath)
             _, err = os.Stat(sslCertificatePath)
 
 
             if err != nil {
             if err != nil {
@@ -122,7 +123,7 @@ func IssueCert(c *gin.Context) {
                 return
                 return
             }
             }
 
 
-            sslCertificateKeyPath := tool.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key")
+            sslCertificateKeyPath := nginx.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key")
             _, err = os.Stat(sslCertificateKeyPath)
             _, err = os.Stat(sslCertificateKeyPath)
 
 
             if err != nil {
             if err != nil {

+ 7 - 6
server/api/config.go

@@ -2,6 +2,7 @@ package api
 
 
 import (
 import (
 	"github.com/0xJacky/Nginx-UI/server/tool"
 	"github.com/0xJacky/Nginx-UI/server/tool"
+	"github.com/0xJacky/Nginx-UI/server/tool/nginx"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"io/ioutil"
 	"io/ioutil"
 	"log"
 	"log"
@@ -19,7 +20,7 @@ func GetConfigs(c *gin.Context) {
 		"modify": "time",
 		"modify": "time",
 	}
 	}
 
 
-	configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("/"))
+	configFiles, err := ioutil.ReadDir(nginx.GetNginxConfPath("/"))
 
 
 	if err != nil {
 	if err != nil {
 		ErrHandler(c, err)
 		ErrHandler(c, err)
@@ -49,7 +50,7 @@ func GetConfigs(c *gin.Context) {
 
 
 func GetConfig(c *gin.Context) {
 func GetConfig(c *gin.Context) {
 	name := c.Param("name")
 	name := c.Param("name")
-	path := filepath.Join(tool.GetNginxConfPath("/"), name)
+	path := filepath.Join(nginx.GetNginxConfPath("/"), name)
 
 
 	content, err := ioutil.ReadFile(path)
 	content, err := ioutil.ReadFile(path)
 
 
@@ -80,7 +81,7 @@ func AddConfig(c *gin.Context) {
 	name := request.Name
 	name := request.Name
 	content := request.Content
 	content := request.Content
 
 
-	path := filepath.Join(tool.GetNginxConfPath("/"), name)
+	path := filepath.Join(nginx.GetNginxConfPath("/"), name)
 
 
 	log.Println(path)
 	log.Println(path)
 	if _, err = os.Stat(path); err == nil {
 	if _, err = os.Stat(path); err == nil {
@@ -98,7 +99,7 @@ func AddConfig(c *gin.Context) {
 		}
 		}
 	}
 	}
 
 
-	output := tool.ReloadNginx()
+	output := nginx.ReloadNginx()
 
 
 	if output != "" {
 	if output != "" {
 		c.JSON(http.StatusInternalServerError, gin.H{
 		c.JSON(http.StatusInternalServerError, gin.H{
@@ -126,7 +127,7 @@ func EditConfig(c *gin.Context) {
 		ErrHandler(c, err)
 		ErrHandler(c, err)
 		return
 		return
 	}
 	}
-	path := filepath.Join(tool.GetNginxConfPath("/"), name)
+	path := filepath.Join(nginx.GetNginxConfPath("/"), name)
 	content := request.Content
 	content := request.Content
 
 
 	origContent, err := ioutil.ReadFile(path)
 	origContent, err := ioutil.ReadFile(path)
@@ -144,7 +145,7 @@ func EditConfig(c *gin.Context) {
 		}
 		}
 	}
 	}
 
 
-	output := tool.ReloadNginx()
+	output := nginx.ReloadNginx()
 
 
 	if output != "" {
 	if output != "" {
 		c.JSON(http.StatusInternalServerError, gin.H{
 		c.JSON(http.StatusInternalServerError, gin.H{

+ 30 - 21
server/api/domain.go

@@ -3,6 +3,7 @@ package api
 import (
 import (
 	"github.com/0xJacky/Nginx-UI/server/model"
 	"github.com/0xJacky/Nginx-UI/server/model"
 	"github.com/0xJacky/Nginx-UI/server/tool"
 	"github.com/0xJacky/Nginx-UI/server/tool"
+	"github.com/0xJacky/Nginx-UI/server/tool/nginx"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"io/ioutil"
 	"io/ioutil"
 	"net/http"
 	"net/http"
@@ -20,25 +21,25 @@ func GetDomains(c *gin.Context) {
 		"modify":  "time",
 		"modify":  "time",
 	}
 	}
 
 
-	configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("sites-available"))
+	configFiles, err := ioutil.ReadDir(nginx.GetNginxConfPath("sites-available"))
 
 
 	if err != nil {
 	if err != nil {
 		ErrHandler(c, err)
 		ErrHandler(c, err)
 		return
 		return
 	}
 	}
 
 
-	enabledConfig, err := ioutil.ReadDir(filepath.Join(tool.GetNginxConfPath("sites-enabled")))
-
-	enabledConfigMap := make(map[string]bool)
-	for i := range enabledConfig {
-		enabledConfigMap[enabledConfig[i].Name()] = true
-	}
+	enabledConfig, err := ioutil.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
 
 
 	if err != nil {
 	if err != nil {
 		ErrHandler(c, err)
 		ErrHandler(c, err)
 		return
 		return
 	}
 	}
 
 
+	enabledConfigMap := make(map[string]bool)
+	for i := range enabledConfig {
+		enabledConfigMap[enabledConfig[i].Name()] = true
+	}
+
 	var configs []gin.H
 	var configs []gin.H
 
 
 	for i := range configFiles {
 	for i := range configFiles {
@@ -62,10 +63,10 @@ func GetDomains(c *gin.Context) {
 
 
 func GetDomain(c *gin.Context) {
 func GetDomain(c *gin.Context) {
 	name := c.Param("name")
 	name := c.Param("name")
-	path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
+	path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
 
 
 	enabled := true
 	enabled := true
-	if _, err := os.Stat(filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
+	if _, err := os.Stat(filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
 		enabled = false
 		enabled = false
 	}
 	}
 
 
@@ -98,7 +99,7 @@ func EditDomain(c *gin.Context) {
 	name := c.Param("name")
 	name := c.Param("name")
 	request := make(gin.H)
 	request := make(gin.H)
 	err = c.BindJSON(&request)
 	err = c.BindJSON(&request)
-	path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
+	path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
 
 
 	err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
 	err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
 	if err != nil {
 	if err != nil {
@@ -106,10 +107,10 @@ func EditDomain(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)
+	enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
 	if _, err = os.Stat(enabledConfigFilePath); err == nil {
 	if _, err = os.Stat(enabledConfigFilePath); err == nil {
 		// 测试配置文件
 		// 测试配置文件
-		err = tool.TestNginxConf(enabledConfigFilePath)
+		err = nginx.TestNginxConf()
 		if err != nil {
 		if err != nil {
 			c.JSON(http.StatusInternalServerError, gin.H{
 			c.JSON(http.StatusInternalServerError, gin.H{
 				"message": err.Error(),
 				"message": err.Error(),
@@ -117,7 +118,7 @@ func EditDomain(c *gin.Context) {
 			return
 			return
 		}
 		}
 
 
-		output := tool.ReloadNginx()
+		output := nginx.ReloadNginx()
 
 
 		if output != "" {
 		if output != "" {
 			c.JSON(http.StatusInternalServerError, gin.H{
 			c.JSON(http.StatusInternalServerError, gin.H{
@@ -131,8 +132,8 @@ func EditDomain(c *gin.Context) {
 }
 }
 
 
 func EnableDomain(c *gin.Context) {
 func EnableDomain(c *gin.Context) {
-	configFilePath := filepath.Join(tool.GetNginxConfPath("sites-available"), c.Param("name"))
-	enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), c.Param("name"))
+	configFilePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), c.Param("name"))
+	enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
 
 
 	_, err := os.Stat(configFilePath)
 	_, err := os.Stat(configFilePath)
 
 
@@ -149,7 +150,7 @@ func EnableDomain(c *gin.Context) {
 	}
 	}
 
 
 	// 测试配置文件,不通过则撤回启用
 	// 测试配置文件,不通过则撤回启用
-	err = tool.TestNginxConf(enabledConfigFilePath)
+	err = nginx.TestNginxConf()
 	if err != nil {
 	if err != nil {
 		_ = os.Remove(enabledConfigFilePath)
 		_ = os.Remove(enabledConfigFilePath)
 		c.JSON(http.StatusInternalServerError, gin.H{
 		c.JSON(http.StatusInternalServerError, gin.H{
@@ -158,7 +159,7 @@ func EnableDomain(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	output := tool.ReloadNginx()
+	output := nginx.ReloadNginx()
 
 
 	if output != "" {
 	if output != "" {
 		c.JSON(http.StatusInternalServerError, gin.H{
 		c.JSON(http.StatusInternalServerError, gin.H{
@@ -173,7 +174,7 @@ func EnableDomain(c *gin.Context) {
 }
 }
 
 
 func DisableDomain(c *gin.Context) {
 func DisableDomain(c *gin.Context) {
-	enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), c.Param("name"))
+	enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
 
 
 	_, err := os.Stat(enabledConfigFilePath)
 	_, err := os.Stat(enabledConfigFilePath)
 
 
@@ -189,7 +190,15 @@ func DisableDomain(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	output := tool.ReloadNginx()
+	// delete auto cert record
+	cert := model.Cert{Domain: c.Param("name")}
+	err = cert.Remove()
+	if err != nil {
+		ErrHandler(c, err)
+		return
+	}
+
+	output := nginx.ReloadNginx()
 
 
 	if output != "" {
 	if output != "" {
 		c.JSON(http.StatusInternalServerError, gin.H{
 		c.JSON(http.StatusInternalServerError, gin.H{
@@ -206,8 +215,8 @@ func DisableDomain(c *gin.Context) {
 func DeleteDomain(c *gin.Context) {
 func DeleteDomain(c *gin.Context) {
 	var err error
 	var err error
 	name := c.Param("name")
 	name := c.Param("name")
-	availablePath := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
-	enabledPath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)
+	availablePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
+	enabledPath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
 
 
 	if _, err = os.Stat(availablePath); os.IsNotExist(err) {
 	if _, err = os.Stat(availablePath); os.IsNotExist(err) {
 		c.JSON(http.StatusNotFound, gin.H{
 		c.JSON(http.StatusNotFound, gin.H{

+ 27 - 1
server/model/cert.go

@@ -1,5 +1,11 @@
 package model
 package model
 
 
+import (
+	"github.com/0xJacky/Nginx-UI/server/tool/nginx"
+	"io/ioutil"
+	"path/filepath"
+)
+
 type Cert struct {
 type Cert struct {
 	Model
 	Model
 	Domain string `json:"domain"`
 	Domain string `json:"domain"`
@@ -19,7 +25,27 @@ func FirstOrCreateCert(domain string) (c Cert, err error) {
 }
 }
 
 
 func GetAutoCertList() (c []Cert) {
 func GetAutoCertList() (c []Cert) {
-	db.Find(&c)
+	var t []Cert
+	db.Find(&t)
+	// check if this domain is enabled
+
+	enabledConfig, err := ioutil.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
+
+	if err != nil {
+		return
+	}
+
+	enabledConfigMap := make(map[string]bool)
+	for i := range enabledConfig {
+		enabledConfigMap[enabledConfig[i].Name()] = true
+	}
+
+	for _, v := range t {
+		if enabledConfigMap[v.Domain] == true {
+			c = append(c, v)
+		}
+	}
+
 	return
 	return
 }
 }
 
 

+ 2 - 2
server/test/acme_test.go

@@ -2,7 +2,7 @@ package test
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/0xJacky/Nginx-UI/server/tool"
+	"github.com/0xJacky/Nginx-UI/server/tool/nginx"
 	"io/ioutil"
 	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
@@ -46,7 +46,7 @@ func TestAcme(t *testing.T) {
 				"install",
 				"install",
 				"--log",
 				"--log",
 				"--home", "/usr/local/acme.sh",
 				"--home", "/usr/local/acme.sh",
-				"--cert-home", tool.GetNginxConfPath("ssl")).
+				"--cert-home", nginx.GetNginxConfPath("ssl")).
 				CombinedOutput()
 				CombinedOutput()
 			if err != nil {
 			if err != nil {
 				log.Println(err)
 				log.Println(err)

+ 3 - 3
server/test/cert_test.go

@@ -2,7 +2,7 @@ package test
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/0xJacky/Nginx-UI/server/tool"
+	"github.com/0xJacky/Nginx-UI/server/tool/nginx"
 	"log"
 	"log"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
@@ -20,14 +20,14 @@ func TestCert(t *testing.T) {
 	}
 	}
 	fmt.Printf("%s\n", out)
 	fmt.Printf("%s\n", out)
 
 
-	_, err = os.Stat(tool.GetNginxConfPath("ssl/test.ojbk.me/fullchain.cer"))
+	_, err = os.Stat(nginx.GetNginxConfPath("ssl/test.ojbk.me/fullchain.cer"))
 
 
 	if err != nil {
 	if err != nil {
 		log.Println(err)
 		log.Println(err)
 		return
 		return
 	}
 	}
 	log.Println("[found]", "fullchain.cer")
 	log.Println("[found]", "fullchain.cer")
-	_, err = os.Stat(tool.GetNginxConfPath("ssl/test.ojbk.me/test.ojbk.me.key"))
+	_, err = os.Stat(nginx.GetNginxConfPath("ssl/test.ojbk.me/test.ojbk.me.key"))
 
 
 	if err != nil {
 	if err != nil {
 		log.Println(err)
 		log.Println(err)

+ 147 - 146
server/tool/cert.go

@@ -1,178 +1,179 @@
 package tool
 package tool
 
 
 import (
 import (
-    "crypto"
-    "crypto/ecdsa"
-    "crypto/elliptic"
-    "crypto/rand"
-    "crypto/tls"
-    "crypto/x509"
-    "github.com/0xJacky/Nginx-UI/server/model"
-    "github.com/0xJacky/Nginx-UI/server/settings"
-    "github.com/go-acme/lego/v4/certcrypto"
-    "github.com/go-acme/lego/v4/certificate"
-    "github.com/go-acme/lego/v4/challenge/http01"
-    "github.com/go-acme/lego/v4/lego"
-    "github.com/go-acme/lego/v4/registration"
-    "io"
-    "io/ioutil"
-    "log"
-    "net/http"
-    "os"
-    "path/filepath"
-    "time"
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/tls"
+	"crypto/x509"
+	"github.com/0xJacky/Nginx-UI/server/model"
+	"github.com/0xJacky/Nginx-UI/server/settings"
+	"github.com/0xJacky/Nginx-UI/server/tool/nginx"
+	"github.com/go-acme/lego/v4/certcrypto"
+	"github.com/go-acme/lego/v4/certificate"
+	"github.com/go-acme/lego/v4/challenge/http01"
+	"github.com/go-acme/lego/v4/lego"
+	"github.com/go-acme/lego/v4/registration"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"time"
 )
 )
 
 
 // MyUser You'll need a user or account type that implements acme.User
 // MyUser You'll need a user or account type that implements acme.User
 type MyUser struct {
 type MyUser struct {
-    Email        string
-    Registration *registration.Resource
-    key          crypto.PrivateKey
+	Email        string
+	Registration *registration.Resource
+	key          crypto.PrivateKey
 }
 }
 
 
 func (u *MyUser) GetEmail() string {
 func (u *MyUser) GetEmail() string {
-    return u.Email
+	return u.Email
 }
 }
 func (u MyUser) GetRegistration() *registration.Resource {
 func (u MyUser) GetRegistration() *registration.Resource {
-    return u.Registration
+	return u.Registration
 }
 }
 func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
 func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
-    return u.key
+	return u.key
 }
 }
 
 
 func AutoCert() {
 func AutoCert() {
-    for {
-        log.Println("[AutoCert] Start")
-        autoCertList := model.GetAutoCertList()
-        for i := range autoCertList {
-            domain := autoCertList[i].Domain
-            key, err := GetCertInfo(domain)
-            if err != nil {
-                // 获取证书信息失败,本次跳过
-                continue
-            }
-            // 未到一个月
-            if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
-                continue
-            }
-            // 过一个月了,重新申请证书
-            err = IssueCert(domain)
-            if err != nil {
-                log.Println(err)
-            }
-        }
-        time.Sleep(1 * time.Hour)
-    }
+	for {
+		log.Println("[AutoCert] Start")
+		autoCertList := model.GetAutoCertList()
+		for i := range autoCertList {
+			domain := autoCertList[i].Domain
+			key, err := GetCertInfo(domain)
+			if err != nil {
+				// 获取证书信息失败,本次跳过
+				continue
+			}
+			// 未到一个月
+			if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
+				continue
+			}
+			// 过一个月了,重新申请证书
+			err = IssueCert(domain)
+			if err != nil {
+				log.Println(err)
+			}
+		}
+		time.Sleep(1 * time.Hour)
+	}
 }
 }
 
 
 func GetCertInfo(domain string) (key *x509.Certificate, err error) {
 func GetCertInfo(domain string) (key *x509.Certificate, err error) {
 
 
-    var response *http.Response
+	var response *http.Response
 
 
-    ts := &http.Transport{
-        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
-    }
+	ts := &http.Transport{
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
 
 
-    client := &http.Client{Transport: ts}
+	client := &http.Client{Transport: ts}
 
 
-    response, err = client.Get("https://" + domain)
+	response, err = client.Get("https://" + domain)
 
 
-    if err != nil {
-        return
-    }
+	if err != nil {
+		return
+	}
 
 
-    defer func(Body io.ReadCloser) {
-        err = Body.Close()
-        if err != nil {
-            log.Println(err)
-            return
-        }
-    }(response.Body)
+	defer func(Body io.ReadCloser) {
+		err = Body.Close()
+		if err != nil {
+			log.Println(err)
+			return
+		}
+	}(response.Body)
 
 
-    key = response.TLS.PeerCertificates[0]
+	key = response.TLS.PeerCertificates[0]
 
 
-    return
+	return
 }
 }
 
 
 func IssueCert(domain string) error {
 func IssueCert(domain string) error {
-    // Create a user. New accounts need an email and private key to start.
-    privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-
-    myUser := MyUser{
-        Email: settings.ServerSettings.Email,
-        key:   privateKey,
-    }
-
-    config := lego.NewConfig(&myUser)
-
-    if settings.ServerSettings.Demo {
-        config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
-    }
-    config.Certificate.KeyType = certcrypto.RSA2048
-
-    // A client facilitates communication with the CA server.
-    client, err := lego.NewClient(config)
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-
-    err = client.Challenge.SetHTTP01Provider(
-        http01.NewProviderServer("",
-            settings.ServerSettings.HTTPChallengePort,
-        ),
-    )
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-
-    // New users will need to register
-    reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-    myUser.Registration = reg
-
-    request := certificate.ObtainRequest{
-        Domains: []string{domain},
-        Bundle:  true,
-    }
-    certificates, err := client.Certificate.Obtain(request)
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-    saveDir := GetNginxConfPath("ssl/" + domain)
-    if _, err := os.Stat(saveDir); os.IsNotExist(err) {
-        err = os.Mkdir(saveDir, 0755)
-        if err != nil {
-            log.Println("fail to create", saveDir)
-            return err
-        }
-    }
-
-    // Each certificate comes back with the cert bytes, the bytes of the client's
-    // private key, and a certificate URL. SAVE THESE TO DISK.
-    err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
-        certificates.Certificate, 0644)
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-    err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
-        certificates.PrivateKey, 0644)
-    if err != nil {
-        log.Println(err)
-        return err
-    }
-
-    ReloadNginx()
-
-    return nil
+	// Create a user. New accounts need an email and private key to start.
+	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+
+	myUser := MyUser{
+		Email: settings.ServerSettings.Email,
+		key:   privateKey,
+	}
+
+	config := lego.NewConfig(&myUser)
+
+	if settings.ServerSettings.Demo {
+		config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
+	}
+	config.Certificate.KeyType = certcrypto.RSA2048
+
+	// A client facilitates communication with the CA server.
+	client, err := lego.NewClient(config)
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+
+	err = client.Challenge.SetHTTP01Provider(
+		http01.NewProviderServer("",
+			settings.ServerSettings.HTTPChallengePort,
+		),
+	)
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+
+	// New users will need to register
+	reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+	myUser.Registration = reg
+
+	request := certificate.ObtainRequest{
+		Domains: []string{domain},
+		Bundle:  true,
+	}
+	certificates, err := client.Certificate.Obtain(request)
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+	saveDir := nginx.GetNginxConfPath("ssl/" + domain)
+	if _, err := os.Stat(saveDir); os.IsNotExist(err) {
+		err = os.Mkdir(saveDir, 0755)
+		if err != nil {
+			log.Println("fail to create", saveDir)
+			return err
+		}
+	}
+
+	// Each certificate comes back with the cert bytes, the bytes of the client's
+	// private key, and a certificate URL. SAVE THESE TO DISK.
+	err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
+		certificates.Certificate, 0644)
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+	err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
+		certificates.PrivateKey, 0644)
+	if err != nil {
+		log.Println(err)
+		return err
+	}
+
+	nginx.ReloadNginx()
+
+	return nil
 }
 }

+ 2 - 2
server/tool/nginx.go → server/tool/nginx/nginx.go

@@ -1,4 +1,4 @@
-package tool
+package nginx
 
 
 import (
 import (
 	"errors"
 	"errors"
@@ -9,7 +9,7 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-func TestNginxConf(filePath string) error {
+func TestNginxConf() error {
 	out, err := exec.Command("nginx", "-t").CombinedOutput()
 	out, err := exec.Command("nginx", "-t").CombinedOutput()
 	if err != nil {
 	if err != nil {
 		log.Println(err)
 		log.Println(err)

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio