mirror of
https://github.com/HuLaSpark/HuLa.git
synced 2026-09-21 04:35:36 +08:00
perf(component): ⚡ 优化注册流程和样式
This commit is contained in:
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="BunSettings">
|
||||
<option name="bunPath" value="$USER_HOME$/.bun/bin/bun" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -5,4 +5,9 @@
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
/public/*
|
||||
.idea/**
|
||||
.vscode/**
|
||||
src-tauri/capabilities/**
|
||||
src-tauri/gen/**
|
||||
CHANGELOG.md
|
||||
auto-imports.d.ts
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"plugins": {
|
||||
"@release-it/bumper": {
|
||||
"in": ["src-tauri/tauri.*.json"],
|
||||
"out": ["src-tauri/tauri.*.json"]
|
||||
"in": ["src-tauri/tauri.*.json", "src-tauri/Cargo.toml"],
|
||||
"out": ["src-tauri/tauri.*.json", "src-tauri/Cargo.toml"]
|
||||
},
|
||||
"@release-it/conventional-changelog": {
|
||||
"preset": {
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,72 +1 @@
|
||||
{
|
||||
"default": {
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"local": true,
|
||||
"windows": ["*"],
|
||||
"permissions": [
|
||||
"core:window:default",
|
||||
"core:window:allow-create",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-is-focused",
|
||||
"core:window:allow-is-fullscreen",
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-scale-factor",
|
||||
"core:window:allow-unminimize",
|
||||
"core:window:allow-set-always-on-top",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-min-size",
|
||||
"core:window:allow-unmaximize",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:webview:allow-create-webview",
|
||||
"core:webview:allow-create-webview-window",
|
||||
"core:webview:allow-internal-toggle-devtools",
|
||||
"core:webview:allow-set-webview-size",
|
||||
"core:webview:allow-webview-size",
|
||||
"core:event:default",
|
||||
"core:event:allow-listen",
|
||||
"os:default",
|
||||
"os:allow-os-type",
|
||||
"os:allow-arch",
|
||||
"os:allow-version",
|
||||
"os:allow-hostname",
|
||||
"process:default",
|
||||
"process:allow-exit",
|
||||
"clipboard-manager:allow-clear",
|
||||
"clipboard-manager:allow-write-image",
|
||||
"http:allow-fetch",
|
||||
"http:allow-fetch-cancel",
|
||||
"http:allow-fetch-read-body",
|
||||
"http:allow-fetch-send",
|
||||
"core:tray:default",
|
||||
"core:tray:allow-get-by-id",
|
||||
"shell:default",
|
||||
"shell:allow-open",
|
||||
"autostart:allow-enable",
|
||||
"autostart:allow-disable",
|
||||
"autostart:allow-is-enabled",
|
||||
"dialog:allow-confirm",
|
||||
"core:resources:allow-close",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [{ "url": "http://**" }, { "url": "https://**" }, { "url": "http://*:*" }, { "url": "https://*:*" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"desktop-capability": {
|
||||
"identifier": "desktop-capability",
|
||||
"description": "",
|
||||
"local": true,
|
||||
"windows": ["home"],
|
||||
"permissions": ["updater:default", "updater:allow-check", "updater:allow-download", "updater:allow-install"],
|
||||
"platforms": ["macOS", "windows", "linux"]
|
||||
}
|
||||
}
|
||||
{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["*"],"permissions":["core:window:default","core:window:allow-create","core:window:allow-start-dragging","core:window:allow-close","core:window:allow-hide","core:window:allow-center","core:window:allow-show","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-destroy","core:window:allow-is-focused","core:window:allow-is-fullscreen","core:window:allow-set-focus","core:window:allow-set-position","core:window:allow-scale-factor","core:window:allow-unminimize","core:window:allow-set-always-on-top","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-unmaximize","core:window:allow-set-fullscreen","core:webview:allow-create-webview","core:webview:allow-create-webview-window","core:webview:allow-internal-toggle-devtools","core:webview:allow-set-webview-size","core:webview:allow-webview-size","core:event:default","core:event:allow-listen","os:default","os:allow-os-type","os:allow-arch","os:allow-version","os:allow-hostname","process:default","process:allow-exit","clipboard-manager:allow-clear","clipboard-manager:allow-write-image","http:allow-fetch","http:allow-fetch-cancel","http:allow-fetch-read-body","http:allow-fetch-send","core:tray:default","core:tray:allow-get-by-id","shell:default","shell:allow-open","autostart:allow-enable","autostart:allow-disable","autostart:allow-is-enabled","dialog:allow-confirm","core:resources:allow-close",{"identifier":"http:default","allow":[{"url":"http://**"},{"url":"https://**"},{"url":"http://*:*"},{"url":"https://*:*"}]}]},"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["home"],"permissions":["updater:default","updater:allow-check","updater:allow-download","updater:allow-install"],"platforms":["macOS","windows","linux"]}}
|
||||
@@ -21,7 +21,9 @@
|
||||
{
|
||||
"description": "A list of capabilities.",
|
||||
"type": "object",
|
||||
"required": ["capabilities"],
|
||||
"required": [
|
||||
"capabilities"
|
||||
],
|
||||
"properties": {
|
||||
"capabilities": {
|
||||
"description": "The list of capabilities.",
|
||||
@@ -37,7 +39,10 @@
|
||||
"Capability": {
|
||||
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```",
|
||||
"type": "object",
|
||||
"required": ["identifier", "permissions"],
|
||||
"required": [
|
||||
"identifier",
|
||||
"permissions"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`",
|
||||
@@ -88,7 +93,10 @@
|
||||
},
|
||||
"platforms": {
|
||||
"description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`",
|
||||
"type": ["array", "null"],
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Target"
|
||||
}
|
||||
@@ -98,7 +106,9 @@
|
||||
"CapabilityRemote": {
|
||||
"description": "Configuration for remote URLs that are associated with the capability.",
|
||||
"type": "object",
|
||||
"required": ["urls"],
|
||||
"required": [
|
||||
"urls"
|
||||
],
|
||||
"properties": {
|
||||
"urls": {
|
||||
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api",
|
||||
@@ -1576,7 +1586,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["path"],
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
@@ -1598,7 +1610,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["path"],
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
@@ -1689,7 +1703,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["url"],
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"description": "A URL that can be accessed by the webview when using the HTTP APIs. Wildcards can be used following the URL pattern standard.\n\nSee [the URL Pattern spec](https://urlpattern.spec.whatwg.org/) for more information.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin on port 443\n\n- \"https://*:*\" : allows all HTTPS origin on any port\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
@@ -1711,7 +1727,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["url"],
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"description": "A URL that can be accessed by the webview when using the HTTP APIs. Wildcards can be used following the URL pattern standard.\n\nSee [the URL Pattern spec](https://urlpattern.spec.whatwg.org/) for more information.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin on port 443\n\n- \"https://*:*\" : allows all HTTPS origin on any port\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
@@ -1808,7 +1826,10 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["cmd", "name"],
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1831,7 +1852,10 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["name", "sidecar"],
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1862,7 +1886,10 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["cmd", "name"],
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1885,7 +1912,10 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["name", "sidecar"],
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1934,14 +1964,20 @@
|
||||
},
|
||||
"allow": {
|
||||
"description": "Data that defines what is allowed by the scope.",
|
||||
"type": ["array", "null"],
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
|
||||
"type": ["array", "null"],
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
@@ -1949,7 +1985,9 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": ["identifier"]
|
||||
"required": [
|
||||
"identifier"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5443,27 +5481,37 @@
|
||||
{
|
||||
"description": "MacOS.",
|
||||
"type": "string",
|
||||
"enum": ["macOS"]
|
||||
"enum": [
|
||||
"macOS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Windows.",
|
||||
"type": "string",
|
||||
"enum": ["windows"]
|
||||
"enum": [
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Linux.",
|
||||
"type": "string",
|
||||
"enum": ["linux"]
|
||||
"enum": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Android.",
|
||||
"type": "string",
|
||||
"enum": ["android"]
|
||||
"enum": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "iOS.",
|
||||
"type": "string",
|
||||
"enum": ["iOS"]
|
||||
"enum": [
|
||||
"iOS"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5477,7 +5525,9 @@
|
||||
{
|
||||
"description": "A variable that is set while calling the command from the webview API.",
|
||||
"type": "object",
|
||||
"required": ["validator"],
|
||||
"required": [
|
||||
"validator"
|
||||
],
|
||||
"properties": {
|
||||
"raw": {
|
||||
"description": "Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.",
|
||||
@@ -5510,4 +5560,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,9 @@
|
||||
{
|
||||
"description": "A list of capabilities.",
|
||||
"type": "object",
|
||||
"required": ["capabilities"],
|
||||
"required": [
|
||||
"capabilities"
|
||||
],
|
||||
"properties": {
|
||||
"capabilities": {
|
||||
"description": "The list of capabilities.",
|
||||
@@ -37,7 +39,10 @@
|
||||
"Capability": {
|
||||
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```",
|
||||
"type": "object",
|
||||
"required": ["identifier", "permissions"],
|
||||
"required": [
|
||||
"identifier",
|
||||
"permissions"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`",
|
||||
@@ -88,7 +93,10 @@
|
||||
},
|
||||
"platforms": {
|
||||
"description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`",
|
||||
"type": ["array", "null"],
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Target"
|
||||
}
|
||||
@@ -98,7 +106,9 @@
|
||||
"CapabilityRemote": {
|
||||
"description": "Configuration for remote URLs that are associated with the capability.",
|
||||
"type": "object",
|
||||
"required": ["urls"],
|
||||
"required": [
|
||||
"urls"
|
||||
],
|
||||
"properties": {
|
||||
"urls": {
|
||||
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api",
|
||||
@@ -1576,7 +1586,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["path"],
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
@@ -1598,7 +1610,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["path"],
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
@@ -1689,7 +1703,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["url"],
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"description": "A URL that can be accessed by the webview when using the HTTP APIs. Wildcards can be used following the URL pattern standard.\n\nSee [the URL Pattern spec](https://urlpattern.spec.whatwg.org/) for more information.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin on port 443\n\n- \"https://*:*\" : allows all HTTPS origin on any port\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
@@ -1711,7 +1727,9 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["url"],
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"description": "A URL that can be accessed by the webview when using the HTTP APIs. Wildcards can be used following the URL pattern standard.\n\nSee [the URL Pattern spec](https://urlpattern.spec.whatwg.org/) for more information.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin on port 443\n\n- \"https://*:*\" : allows all HTTPS origin on any port\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
@@ -1808,7 +1826,10 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["cmd", "name"],
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1831,7 +1852,10 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["name", "sidecar"],
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1862,7 +1886,10 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["cmd", "name"],
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1885,7 +1912,10 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["name", "sidecar"],
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
@@ -1934,14 +1964,20 @@
|
||||
},
|
||||
"allow": {
|
||||
"description": "Data that defines what is allowed by the scope.",
|
||||
"type": ["array", "null"],
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
|
||||
"type": ["array", "null"],
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
@@ -1949,7 +1985,9 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": ["identifier"]
|
||||
"required": [
|
||||
"identifier"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5443,27 +5481,37 @@
|
||||
{
|
||||
"description": "MacOS.",
|
||||
"type": "string",
|
||||
"enum": ["macOS"]
|
||||
"enum": [
|
||||
"macOS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Windows.",
|
||||
"type": "string",
|
||||
"enum": ["windows"]
|
||||
"enum": [
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Linux.",
|
||||
"type": "string",
|
||||
"enum": ["linux"]
|
||||
"enum": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Android.",
|
||||
"type": "string",
|
||||
"enum": ["android"]
|
||||
"enum": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "iOS.",
|
||||
"type": "string",
|
||||
"enum": ["iOS"]
|
||||
"enum": [
|
||||
"iOS"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5477,7 +5525,9 @@
|
||||
{
|
||||
"description": "A variable that is set while calling the command from the webview API.",
|
||||
"type": "object",
|
||||
"required": ["validator"],
|
||||
"required": [
|
||||
"validator"
|
||||
],
|
||||
"properties": {
|
||||
"raw": {
|
||||
"description": "Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.",
|
||||
@@ -5510,4 +5560,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,11 @@
|
||||
"icons/windows/Square310x310Logo.png",
|
||||
"icons/windows/StoreLogo.png"
|
||||
],
|
||||
"windows": {}
|
||||
"windows": {
|
||||
"wix": {
|
||||
"language": "zh-CN"
|
||||
}
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
|
||||
@@ -84,6 +84,10 @@ watch(globalStore.addFriendModalInfo, (val) => {
|
||||
userInfo.value = useUserInfo(val.uid).value
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
requestMsg.value = `我是 ${userInfo.value.name}`
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<n-flex align="center" :size="6">
|
||||
<svg class="size-14px" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48">
|
||||
<path
|
||||
:data-follow-stroke="isValid ? '#13987f' : '#909090'"
|
||||
:data-follow-fill="isValid ? '#AFDBD2' : '#fefefe'"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="4"
|
||||
:stroke="isValid ? '#13987f' : '#909090'"
|
||||
:fill="isValid ? '#AFDBD2' : '#fefefe'"
|
||||
d="M24 44a19.937 19.937 0 0 0 14.142-5.858A19.937 19.937 0 0 0 44 24a19.938 19.938 0 0 0-5.858-14.142A19.937 19.937 0 0 0 24 4 19.938 19.938 0 0 0 9.858 9.858 19.938 19.938 0 0 0 4 24a19.937 19.937 0 0 0 5.858 14.142A19.938 19.938 0 0 0 24 44Z" />
|
||||
<path
|
||||
:data-follow-stroke="isValid ? '#13987f' : '#909090'"
|
||||
stroke-linejoin="round"
|
||||
stroke-linecap="round"
|
||||
stroke-width="4"
|
||||
:stroke="isValid ? '#13987f' : '#909090'"
|
||||
d="m16 24 6 6 12-12" />
|
||||
</svg>
|
||||
<p :class="['text-12px', { 'color-#131313': isValid, 'color-#909090': !isValid }]">{{ message }}</p>
|
||||
</n-flex>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
value: string
|
||||
message?: string
|
||||
validator?: (value: string) => boolean
|
||||
}>()
|
||||
|
||||
const isValid = computed(() => (props.validator ? props.validator(props.value) : true))
|
||||
</script>
|
||||
@@ -6,7 +6,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import type { ImageBody } from '@/services/types'
|
||||
import { formatImage } from '@/utils/Formatting.ts'
|
||||
|
||||
|
||||
@@ -15,12 +15,14 @@ import { delay } from 'lodash-es'
|
||||
import router from '@/router'
|
||||
import { listen } from '@tauri-apps/api/event'
|
||||
import { useMenuTopStore } from '@/stores/menuTop.ts'
|
||||
import { useLoginHistoriesStore } from '@/stores/loginHistory.ts'
|
||||
|
||||
export const leftHook = () => {
|
||||
const prefers = matchMedia('(prefers-color-scheme: dark)')
|
||||
const { createWebviewWindow } = useWindow()
|
||||
const settingStore = useSettingStore()
|
||||
const { menuTop } = useMenuTopStore()
|
||||
const loginHistoriesStore = useLoginHistoriesStore()
|
||||
const userStore = useUserStore()
|
||||
const cachedStore = useCachedStore()
|
||||
const { themes, login } = settingStore
|
||||
@@ -121,6 +123,7 @@ export const leftHook = () => {
|
||||
apis.modifyUserName(editInfo.value.content.name).then(() => {
|
||||
// 更新本地缓存的用户信息
|
||||
login.accountInfo.name = editInfo.value.content.name!
|
||||
loginHistoriesStore.updateLoginHistory(login.accountInfo) // 更新登录历史记录
|
||||
updateCurrentUserCache('name', editInfo.value.content.name) // 更新缓存里面的用户信息
|
||||
if (!editInfo.value.content.modifyNameChance) return
|
||||
editInfo.value.content.modifyNameChance -= 1
|
||||
|
||||
@@ -3,8 +3,13 @@ import { useUserStore } from '@/stores/user'
|
||||
import { useChatStore } from '@/stores/chat'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { useGlobalStore } from '@/stores/global'
|
||||
import { WsResponseMessageType } from '@/utils/wsType'
|
||||
import type { LoginSuccessResType, LoginInitResType, WsReqMsgContentType, OnStatusChangeType } from '@/utils/wsType'
|
||||
import { WsResponseMessageType } from '@/services/wsType.ts'
|
||||
import type {
|
||||
LoginSuccessResType,
|
||||
LoginInitResType,
|
||||
WsReqMsgContentType,
|
||||
OnStatusChangeType
|
||||
} from '@/services/wsType.ts'
|
||||
import type { MessageType, MarkItemType, RevokedMsgType } from '@/services/types'
|
||||
import { OnlineEnum, ChangeTypeEnum, RoomTypeEnum, WsResEnum, MittEnum } from '@/enums'
|
||||
import { computedToken } from '@/services/request'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UserInfoType, UserItem } from '@/services/types'
|
||||
import type { UserInfoType, UserItem } from '@/services/types.ts'
|
||||
|
||||
// 1.登录返回二维码 2.用户扫描成功等待授权 3.用户登录成功返回用户信息 4.收到消息 5.上下线推送 6.前端token失效
|
||||
export enum WsResponseMessageType {
|
||||
@@ -39,17 +39,26 @@ export const useLoginHistoriesStore = defineStore(
|
||||
}
|
||||
])
|
||||
|
||||
const getLoginHistoryIndex = (loginHistory: STO.Setting['login']['accountInfo']) => {
|
||||
return loginHistories.value.findIndex((i) => i.account === loginHistory.account)
|
||||
}
|
||||
|
||||
const addLoginHistory = (loginHistory: STO.Setting['login']['accountInfo']) => {
|
||||
const index = loginHistories.value.findIndex((i) => i.account === loginHistory.account)
|
||||
const index = getLoginHistoryIndex(loginHistory)
|
||||
index === -1 && loginHistories.value.push(loginHistory)
|
||||
}
|
||||
|
||||
const updateLoginHistory = (loginHistory: STO.Setting['login']['accountInfo']) => {
|
||||
const index = getLoginHistoryIndex(loginHistory)
|
||||
index !== -1 && (loginHistories.value[index] = loginHistory)
|
||||
}
|
||||
|
||||
const removeLoginHistory = (loginHistory: STO.Setting['login']['accountInfo']) => {
|
||||
const index = loginHistories.value.findIndex((i) => i.account === loginHistory.account)
|
||||
const index = getLoginHistoryIndex(loginHistory)
|
||||
index !== -1 && loginHistories.value.splice(index, 1)
|
||||
}
|
||||
|
||||
return { loginHistories, addLoginHistory, removeLoginHistory }
|
||||
return { loginHistories, addLoginHistory, updateLoginHistory, removeLoginHistory }
|
||||
},
|
||||
{
|
||||
share: {
|
||||
|
||||
Vendored
+4
@@ -36,6 +36,8 @@ declare module 'vue' {
|
||||
NDropdown: typeof import('naive-ui')['NDropdown']
|
||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||
NFlex: typeof import('naive-ui')['NFlex']
|
||||
NForm: typeof import('naive-ui')['NForm']
|
||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
NIconWrapper: typeof import('naive-ui')['NIconWrapper']
|
||||
NImage: typeof import('naive-ui')['NImage']
|
||||
@@ -66,5 +68,7 @@ declare module 'vue' {
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Screenshot: typeof import('./../components/common/Screenshot.vue')['default']
|
||||
Text: typeof import('./../components/rightBox/renderMessage/Text.vue')['default']
|
||||
Validation: typeof import('./../components/common/Validation.vue')['default']
|
||||
ValidationIcon: typeof import('./../components/common/ValidationIcon.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +68,11 @@
|
||||
</div>
|
||||
|
||||
<n-input
|
||||
class="pl-16px"
|
||||
maxlength="16"
|
||||
minlength="6"
|
||||
size="large"
|
||||
show-password-on="click"
|
||||
v-model:value="info.password"
|
||||
type="password"
|
||||
:placeholder="passwordPH"
|
||||
|
||||
@@ -53,7 +53,7 @@ import { useLogin } from '@/hooks/useLogin.ts'
|
||||
import { useWindow } from '@/hooks/useWindow.ts'
|
||||
import { LoginStatus, useWsLoginStore } from '@/stores/ws.ts'
|
||||
import wsIns from '@/services/webSocket.ts'
|
||||
import { WsRequestMsgType } from '@/utils/wsType.ts'
|
||||
import { WsRequestMsgType } from '@/services/wsType.ts'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const loginStore = useWsLoginStore()
|
||||
|
||||
@@ -12,42 +12,62 @@
|
||||
|
||||
<!-- 注册菜单 -->
|
||||
<n-flex class="ma text-center h-full w-260px" vertical :size="16">
|
||||
<n-input
|
||||
maxlength="8"
|
||||
minlength="1"
|
||||
size="large"
|
||||
v-model:value="info.name"
|
||||
type="text"
|
||||
:allow-input="noSideSpace"
|
||||
:placeholder="namePH"
|
||||
@focus="namePH = ''"
|
||||
@blur="namePH = '输入HuLa昵称'"
|
||||
clearable />
|
||||
<n-form :model="info" :rules="rules" ref="registerForm">
|
||||
<n-form-item path="name">
|
||||
<n-input
|
||||
maxlength="8"
|
||||
minlength="1"
|
||||
size="large"
|
||||
v-model:value="info.name"
|
||||
type="text"
|
||||
:allow-input="noSideSpace"
|
||||
:placeholder="namePH"
|
||||
@focus="namePH = ''"
|
||||
@blur="namePH = '输入HuLa昵称'"
|
||||
clearable />
|
||||
</n-form-item>
|
||||
|
||||
<n-input
|
||||
size="large"
|
||||
maxlength="12"
|
||||
minlength="6"
|
||||
v-model:value="info.account"
|
||||
type="text"
|
||||
:allow-input="noSideSpace"
|
||||
:placeholder="accountPH"
|
||||
@focus="accountPH = ''"
|
||||
@blur="accountPH = '输入HuLa账号'"
|
||||
clearable>
|
||||
</n-input>
|
||||
<n-form-item path="account">
|
||||
<n-input
|
||||
size="large"
|
||||
maxlength="12"
|
||||
minlength="6"
|
||||
v-model:value="info.account"
|
||||
type="text"
|
||||
:allow-input="onlyAlphaNumeric"
|
||||
:placeholder="accountPH"
|
||||
@focus="accountPH = ''"
|
||||
@blur="accountPH = '输入HuLa账号'"
|
||||
clearable />
|
||||
</n-form-item>
|
||||
|
||||
<n-input
|
||||
maxlength="16"
|
||||
minlength="6"
|
||||
size="large"
|
||||
v-model:value="info.password"
|
||||
type="password"
|
||||
:allow-input="noSideSpace"
|
||||
:placeholder="passwordPH"
|
||||
@focus="passwordPH = ''"
|
||||
@blur="passwordPH = '输入HuLa密码'"
|
||||
clearable />
|
||||
<n-form-item path="password">
|
||||
<n-input
|
||||
class="pl-16px"
|
||||
maxlength="16"
|
||||
minlength="6"
|
||||
size="large"
|
||||
show-password-on="click"
|
||||
v-model:value="info.password"
|
||||
type="password"
|
||||
:allow-input="noSideSpace"
|
||||
:placeholder="passwordPH"
|
||||
@focus="passwordPH = ''"
|
||||
@blur="passwordPH = '输入HuLa密码'"
|
||||
clearable />
|
||||
</n-form-item>
|
||||
<!-- 密码提示信息 -->
|
||||
<n-flex vertical v-if="info.password">
|
||||
<n-flex vertical :size="4">
|
||||
<Validation :value="info.password" message="最少6位" :validator="validateMinLength" />
|
||||
<Validation :value="info.password" message="由英文和数字构成" :validator="validateAlphaNumeric" />
|
||||
<Validation
|
||||
:value="info.password"
|
||||
message="必须有一个特殊字符!@#¥%.&*"
|
||||
:validator="validateSpecialChar" />
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
|
||||
<!-- 协议 -->
|
||||
<n-flex justify="center" :size="6">
|
||||
@@ -73,7 +93,7 @@
|
||||
|
||||
<!-- 底部栏 -->
|
||||
<n-flex class="text-(12px #909090)" :size="8" justify="center">
|
||||
<span>Copyright © {{ currentYear - 1 }}-{{ currentYear }} HuLaSpark All Rights Reserved.</span>
|
||||
<span>Copyright {{ currentYear - 1 }}-{{ currentYear }} HuLaSpark All Rights Reserved.</span>
|
||||
</n-flex>
|
||||
</n-config-provider>
|
||||
</template>
|
||||
@@ -83,6 +103,7 @@ import apis from '@/services/apis.ts'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import dayjs from 'dayjs'
|
||||
import { RegisterUserReq } from '@/services/types.ts'
|
||||
import Validation from '@/components/common/Validation.vue'
|
||||
|
||||
/** 账号信息 */
|
||||
const info = ref({
|
||||
@@ -101,30 +122,76 @@ const passwordPH = ref('输入HuLa密码')
|
||||
const btnText = ref('注册')
|
||||
// 使用day.js获取当前年份
|
||||
const currentYear = dayjs().year()
|
||||
const registerForm = ref(null)
|
||||
// 校验规则
|
||||
const rules = {
|
||||
name: {
|
||||
required: true,
|
||||
message: '请输入昵称',
|
||||
trigger: 'blur'
|
||||
},
|
||||
account: {
|
||||
required: true,
|
||||
message: '请输入账号',
|
||||
trigger: 'blur'
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
trigger: ['blur', 'input']
|
||||
}
|
||||
}
|
||||
|
||||
/** 不允许输入空格 */
|
||||
const noSideSpace = (value: string) => !value.startsWith(' ') && !value.endsWith(' ')
|
||||
|
||||
/** 只允许输入英文和数字 */
|
||||
const onlyAlphaNumeric = (value: string) => /^[a-zA-Z0-9]*$/.test(value)
|
||||
|
||||
/** 密码验证函数 */
|
||||
const validateMinLength = (value: string) => value.length >= 6
|
||||
|
||||
/** 检查密码是否包含英文和数字 */
|
||||
const validateAlphaNumeric = (value: string) => {
|
||||
const hasLetter = /[a-zA-Z]/.test(value)
|
||||
const hasNumber = /[0-9]/.test(value)
|
||||
return hasLetter && hasNumber
|
||||
}
|
||||
|
||||
/** 检查密码是否包含特殊字符 */
|
||||
const validateSpecialChar = (value: string) => /[!@#¥$%.&*]/.test(value)
|
||||
|
||||
/** 检查密码是否满足所有条件 */
|
||||
const isPasswordValid = computed(() => {
|
||||
const password = info.value.password
|
||||
return validateMinLength(password) && validateAlphaNumeric(password) && validateSpecialChar(password)
|
||||
})
|
||||
|
||||
/** 注册 */
|
||||
const register = async () => {
|
||||
btnEnable.value = true
|
||||
loading.value = true
|
||||
btnText.value = '注册中...'
|
||||
// 注册
|
||||
await apis
|
||||
.register({ ...info.value } as RegisterUserReq)
|
||||
.then(() => {
|
||||
window.$message.success('注册成功')
|
||||
btnText.value = '注册'
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
btnEnable.value = false
|
||||
btnText.value = '注册'
|
||||
})
|
||||
await registerForm.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
btnEnable.value = true
|
||||
loading.value = true
|
||||
btnText.value = '注册中...'
|
||||
// 注册
|
||||
apis
|
||||
.register({ ...info.value } as RegisterUserReq)
|
||||
.then(() => {
|
||||
window.$message.success('注册成功')
|
||||
btnText.value = '注册'
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
btnEnable.value = false
|
||||
btnText.value = '注册'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
btnEnable.value = !(info.value.account && info.value.password && protocol.value)
|
||||
btnEnable.value = !(info.value.account && isPasswordValid.value && protocol.value)
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -141,4 +208,8 @@ onUnmounted(() => {})
|
||||
.textFont {
|
||||
font-family: AliFangYuan, sans-serif !important;
|
||||
}
|
||||
|
||||
:deep(.n-form-item.n-form-item--top-labelled) {
|
||||
grid-template-rows: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import Components from 'unplugin-vue-components/vite' //组件注册
|
||||
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
|
||||
import { getRootPath, getSrcPath } from './build/config/getPath'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import unocss from '@unocss/vite'
|
||||
import UnoCSS from '@unocss/vite'
|
||||
import terser from '@rollup/plugin-terser'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
@@ -36,7 +36,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
|
||||
* */
|
||||
vue(),
|
||||
vueJsx(), // 开启jsx功能
|
||||
unocss(), // 开启unocss
|
||||
UnoCSS(), // 开启UnoCSS
|
||||
AutoImport({
|
||||
imports: [
|
||||
'vue',
|
||||
|
||||
Reference in New Issue
Block a user