mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-10 18:05:48 +02:00
feat(china): set icp number and public security number #780
This commit is contained in:
parent
2950be6e82
commit
e326f5e930
13 changed files with 150 additions and 28 deletions
14
api/public/layout.go
Normal file
14
api/public/layout.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package public
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetICPSettings(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"icp_number": settings.NodeSettings.ICPNumber,
|
||||
"public_security_number": settings.NodeSettings.PublicSecurityNumber,
|
||||
})
|
||||
}
|
7
api/public/router.go
Normal file
7
api/public/router.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package public
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func InitRouter(r *gin.RouterGroup) {
|
||||
r.GET("/icp_settings", GetICPSettings)
|
||||
}
|
1
app/components.d.ts
vendored
1
app/components.d.ts
vendored
|
@ -76,6 +76,7 @@ declare module 'vue' {
|
|||
CodeEditorCodeEditor: typeof import('./src/components/CodeEditor/CodeEditor.vue')['default']
|
||||
EnvIndicatorEnvIndicator: typeof import('./src/components/EnvIndicator/EnvIndicator.vue')['default']
|
||||
FooterToolbarFooterToolBar: typeof import('./src/components/FooterToolbar/FooterToolBar.vue')['default']
|
||||
ICPICP: typeof import('./src/components/ICP/ICP.vue')['default']
|
||||
LogoLogo: typeof import('./src/components/Logo/Logo.vue')['default']
|
||||
NginxControlNginxControl: typeof import('./src/components/NginxControl/NginxControl.vue')['default']
|
||||
NodeSelectorNodeSelector: typeof import('./src/components/NodeSelector/NodeSelector.vue')['default']
|
||||
|
|
14
app/src/api/public.ts
Normal file
14
app/src/api/public.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import http from '@/lib/http'
|
||||
|
||||
export interface ICP {
|
||||
icp_number: string
|
||||
public_security_number: string
|
||||
}
|
||||
|
||||
const publicApi = {
|
||||
getICP<ICP>() {
|
||||
return http.get('/icp_settings')
|
||||
},
|
||||
}
|
||||
|
||||
export default publicApi
|
|
@ -63,6 +63,8 @@ export interface NginxSettings {
|
|||
export interface NodeSettings {
|
||||
name: string
|
||||
secret: string
|
||||
icp_number: string
|
||||
public_security_number: number
|
||||
}
|
||||
|
||||
export interface OpenaiSettings {
|
||||
|
|
50
app/src/components/ICP/ICP.vue
Normal file
50
app/src/components/ICP/ICP.vue
Normal file
|
@ -0,0 +1,50 @@
|
|||
<script setup lang="ts">
|
||||
import type { ICP } from '@/api/public'
|
||||
import publicApi from '@/api/public'
|
||||
|
||||
const icp = ref<ICP>({
|
||||
icp_number: '',
|
||||
public_security_number: '',
|
||||
})
|
||||
|
||||
publicApi.getICP().then(r => {
|
||||
icp.value = r
|
||||
})
|
||||
|
||||
const enabled = computed(() => {
|
||||
return icp.value.icp_number || icp.value.public_security_number
|
||||
})
|
||||
|
||||
const showDot = computed(() => icp.value.icp_number && icp.value.public_security_number)
|
||||
|
||||
const publicSecurityNumberLink = computed(() =>
|
||||
`https://www.beian.gov.cn/portal/registerSystemInfo?recordcode=${icp.value.public_security_number}`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="enabled">
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ icp.icp_number }}</a>
|
||||
<span v-if="showDot"> · </span>
|
||||
<a v-if="icp.public_security_number" class="public_security_number" :href="publicSecurityNumberLink">
|
||||
<img src="//www.beian.gov.cn/img/new/gongan.png" alt="公安备案">
|
||||
<span class="ml-5">{{ icp.public_security_number }}</span></a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
a {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.public_security_number {
|
||||
position: relative;
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -2,6 +2,7 @@
|
|||
import auth from '@/api/auth'
|
||||
import install from '@/api/install'
|
||||
import passkey from '@/api/passkey'
|
||||
import ICP from '@/components/ICP/ICP.vue'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
import Authorization from '@/components/TwoFA/Authorization.vue'
|
||||
|
@ -23,7 +24,7 @@ install.get_lock().then(async (r: { lock: boolean }) => {
|
|||
|
||||
const loading = ref(false)
|
||||
const enabled2FA = ref(false)
|
||||
const refOTP = ref()
|
||||
const refOTP = useTemplateRef('refOTP')
|
||||
const passcode = ref('')
|
||||
const recoveryCode = ref('')
|
||||
const passkeyConfigStatus = ref(false)
|
||||
|
@ -266,7 +267,10 @@ async function handlePasskeyLogin() {
|
|||
</AFormItem>
|
||||
</AForm>
|
||||
<div class="footer">
|
||||
<p>Copyright © 2021 - {{ thisYear }} Nginx UI</p>
|
||||
<p class="mb-4">
|
||||
Copyright © 2021 - {{ thisYear }} Nginx UI
|
||||
</p>
|
||||
<ICP class="mb-4" />
|
||||
Language
|
||||
<SetLanguage class="inline" />
|
||||
<div class="flex justify-center mt-4">
|
||||
|
@ -295,7 +299,7 @@ async function handlePasskeyLogin() {
|
|||
height: 100vh;
|
||||
|
||||
.login-form {
|
||||
max-width: 400px;
|
||||
max-width: 420px;
|
||||
width: 80%;
|
||||
|
||||
.project-title {
|
||||
|
@ -313,7 +317,7 @@ async function handlePasskeyLogin() {
|
|||
}
|
||||
|
||||
.footer {
|
||||
padding: 30px;
|
||||
padding: 30px 20px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,15 @@ const errors: Record<string, Record<string, string>> = inject('errors') as Recor
|
|||
<AFormItem :label="$gettext('Terminal Start Command')">
|
||||
<p>{{ data.terminal.start_cmd }}</p>
|
||||
</AFormItem>
|
||||
<AFormItem
|
||||
:label="$gettext('Node name')"
|
||||
:validate-status="errors?.node?.name ? 'error' : ''"
|
||||
:help="errors?.node?.name.includes('safety_text')
|
||||
? $gettext('The node name should only contain letters, unicode, numbers, hyphens, dashes, and dots.')
|
||||
: $gettext('Customize the name of local node to be displayed in the environment indicator.')"
|
||||
>
|
||||
<AInput v-model:value="data.node.name" />
|
||||
</AFormItem>
|
||||
<AFormItem
|
||||
:label="$gettext('Github Proxy')"
|
||||
:validate-status="errors?.http?.github_proxy ? 'error' : ''"
|
||||
|
@ -39,13 +48,28 @@ const errors: Record<string, Record<string, string>> = inject('errors') as Recor
|
|||
/>
|
||||
</AFormItem>
|
||||
<AFormItem
|
||||
:label="$gettext('Node name')"
|
||||
:validate-status="errors?.node?.name ? 'error' : ''"
|
||||
:help="errors?.node?.name.includes('safety_text')
|
||||
? $gettext('The node name should only contain letters, unicode, numbers, hyphens, dashes, and dots.')
|
||||
: $gettext('Customize the name of local node to be displayed in the environment indicator.')"
|
||||
:label="$gettext('ICP Number')"
|
||||
:validate-status="errors?.node?.icp_number ? 'error' : ''"
|
||||
:help="errors?.node?.icp_number.includes('safety_text')
|
||||
? $gettext('The ICP Number should only contain letters, unicode, numbers, hyphens, dashes, and dots.')
|
||||
: ''"
|
||||
>
|
||||
<AInput v-model:value="data.node.name" />
|
||||
<AInput
|
||||
v-model:value="data.node.icp_number"
|
||||
:placeholder="$gettext('For Chinese user')"
|
||||
/>
|
||||
</AFormItem>
|
||||
<AFormItem
|
||||
:label="$gettext('Public Security Number')"
|
||||
:validate-status="errors?.node?.public_security_number ? 'error' : ''"
|
||||
:help="errors?.node?.public_security_number.includes('safety_text')
|
||||
? $gettext('The Public Security Number should only contain letters, unicode, numbers, hyphens, dashes, and dots.')
|
||||
: ''"
|
||||
>
|
||||
<AInput
|
||||
v-model:value="data.node.public_security_number"
|
||||
:placeholder="$gettext('For Chinese user')"
|
||||
/>
|
||||
</AFormItem>
|
||||
</AForm>
|
||||
</template>
|
||||
|
|
|
@ -23,3 +23,16 @@
|
|||
|
||||
默认情况下,如果您启用了跳过安装模式,而没有在服务器部分设置 `App.JwtSecret` 和 `Node.Secret` 选项,
|
||||
Nginx UI 将为这两个选项生成一个随机的 UUID 值。
|
||||
|
||||
## ICPNumber
|
||||
- 类型: `string`
|
||||
- 版本: `>= v2.0.0-beta.42`
|
||||
|
||||
此选项用于设置 ICP 备案号。
|
||||
|
||||
## PublicSecurityNumber
|
||||
- 类型: `string`
|
||||
- 版本: `>= v2.0.0-beta.42`
|
||||
|
||||
此选项用于设置 ICP 备案号。
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/api/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/api/notification"
|
||||
"github.com/0xJacky/Nginx-UI/api/openai"
|
||||
"github.com/0xJacky/Nginx-UI/api/public"
|
||||
"github.com/0xJacky/Nginx-UI/api/settings"
|
||||
"github.com/0xJacky/Nginx-UI/api/sites"
|
||||
"github.com/0xJacky/Nginx-UI/api/streams"
|
||||
|
@ -39,6 +40,7 @@ func InitRouter() {
|
|||
|
||||
root := r.Group("/api")
|
||||
{
|
||||
public.InitRouter(root)
|
||||
system.InitPublicRouter(root)
|
||||
user.InitAuthRouter(root)
|
||||
|
||||
|
|
|
@ -5,7 +5,4 @@ type HTTP struct {
|
|||
InsecureSkipVerify bool `json:"insecure_skip_verify" protected:"true"`
|
||||
}
|
||||
|
||||
var HTTPSettings = &HTTP{
|
||||
GithubProxy: "",
|
||||
InsecureSkipVerify: false,
|
||||
}
|
||||
var HTTPSettings = &HTTP{}
|
||||
|
|
|
@ -11,7 +11,4 @@ type Nginx struct {
|
|||
RestartCmd string `json:"restart_cmd" protected:"true"`
|
||||
}
|
||||
|
||||
var NginxSettings = &Nginx{
|
||||
AccessLogPath: "",
|
||||
ErrorLogPath: "",
|
||||
}
|
||||
var NginxSettings = &Nginx{}
|
||||
|
|
|
@ -5,11 +5,8 @@ type Node struct {
|
|||
Secret string `json:"secret" protected:"true"`
|
||||
SkipInstallation bool `json:"skip_installation" protected:"true"`
|
||||
Demo bool `json:"demo" protected:"true"`
|
||||
ICPNumber string `json:"icp_number" binding:"omitempty,safety_text"`
|
||||
PublicSecurityNumber string `json:"public_security_number" binding:"omitempty,safety_text"`
|
||||
}
|
||||
|
||||
var NodeSettings = &Node{
|
||||
Name: "",
|
||||
Secret: "",
|
||||
SkipInstallation: false,
|
||||
Demo: false,
|
||||
}
|
||||
var NodeSettings = &Node{}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue