加入了隐私协议(注册时),加入了用户协议(登录时)

This commit is contained in:
Gaofeng 2025-11-24 21:49:44 +08:00
parent a5172668a8
commit 88b7ee97aa
4 changed files with 638 additions and 14 deletions

View file

@ -110,7 +110,7 @@
<div class="self-start flex flex-none items-center text-gray-600 dark:text-gray-400">
<!-- <div class="md:hidden flex self-center w-[1px] h-5 mx-2 bg-gray-300 dark:bg-stone-700" /> -->
{#if $user?.role === 'user' ? ($user?.permissions?.chat?.temporary ?? true) && !($user?.permissions?.chat?.temporary_enforced ?? false) : true}
<!-- {#if $user?.role === 'user' ? ($user?.permissions?.chat?.temporary ?? true) && !($user?.permissions?.chat?.temporary_enforced ?? false) : true}
{#if !chat?.id}
<Tooltip content={$i18n.t(`Temporary Chat`)}>
<button
@ -158,9 +158,9 @@
</button>
</Tooltip>
{/if}
{/if}
{/if} -->
{#if $mobile && !$temporaryChatEnabled && chat && chat.id}
<!-- {#if $mobile && !$temporaryChatEnabled && chat && chat.id}
<Tooltip content={$i18n.t('New Chat')}>
<button
class=" flex {$showSidebar
@ -176,9 +176,9 @@
</div>
</button>
</Tooltip>
{/if}
{/if} -->
{#if shareEnabled && chat && (chat.id || $temporaryChatEnabled)}
<!-- {#if shareEnabled && chat && (chat.id || $temporaryChatEnabled)}
<Menu
{chat}
{shareEnabled}
@ -199,9 +199,9 @@
</div>
</button>
</Menu>
{/if}
{/if} -->
{#if $user?.role === 'admin' || ($user?.permissions.chat?.controls ?? true)}
<!-- {#if $user?.role === 'admin' || ($user?.permissions.chat?.controls ?? true)}
<Tooltip content={$i18n.t('Controls')}>
<button
class=" flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-850 transition"
@ -215,9 +215,9 @@
</div>
</button>
</Tooltip>
{/if}
{/if} -->
{#if $user !== undefined && $user !== null}
<!-- {#if $user !== undefined && $user !== null}
<UserMenu
className="max-w-[240px]"
role={$user?.role}
@ -242,7 +242,7 @@
</div>
</div>
</UserMenu>
{/if}
{/if} -->
</div>
</div>
</div>

513
src/lib/constants/legal.ts Normal file
View file

@ -0,0 +1,513 @@
export const agreementContent = `
使XXX()XXX()XXX有限公司及其关联公司使使XXX()使
使18使使使
使使
XXX@163.com与我们联系
1
1.1
XXX.cn网站使用XXX()
1.2
使
1.3
2
2.1 XXX()XXX()XXX()
2.2
2.3 使使
2.4
XXX()XXX()XXX()XXX() XXX()使使XXX()
3
3.1 使XXX()XXX()
3.2 18使使
3.3 使使XXX()线
3.4 使XXX()
3.6 使使XXX()XXX()XXX()XXX()
3.8 使XXX()退
3.9 使
3.10 XXX()使使使
3.11 使XXX()
4 使
4.1 使XXX()使XXX()使XXX()XXX()使
1
2
3使
4.2 使XXX()
4.3 XXX()使XXX()
4.4 XXX()使使
4.4.1 XXX()
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)
(11)
(12)
4.4.2
(1)
(2)
(3)
(4)
(5)使
(6)
(7)
(8)
(9)
(10)
(11)
(12)
4.4.3
(1)
(2)使4.4.14.4.2
4.4.4 XXX()
(1)
(2)
(3)
(4)
(5)XXX()XXX()
(6)
(7)(8)XXX()XXX()
(9)XXX()XXX()
(10)XXX()XXX()使XXX()
4.4.5使
4.4.6XXX() 使XXX() XXX()使
5
5.1 XXX()
5.2XXX()XXX()
5.3使XXX()
5.4使/使XXX()使
5.5使XXX()/AI对话机器人XXX()//
广 使使
/XXX()/ XXX()XXX()AI对话机器人AI对话内容使使使
6
6.1 XXX()XXX()使
7
7.1 XXX()XXX()使XXX()
7.2 XXX()
7.3 XXX()使
8
8.1 XXX()使XXX()XXX()使XXX()XXX()XXX()XXX()XXX()XXX()
8.2 使XXX()
8.3 4 使XXX()XXX()9.2
9
9.1 使XXX@163.com我们会在收到您的投诉材料后进行处理
9.2 使XXX@163.com申诉所需的材料至少包括您的账号信息使使
9.3 15
10
10.1 XXX()使XXX()XXX()
10.2 XXX()使
10.3 XXX()XXX()使XXX()XXX()使XXX()
10.4 XXX()使
11
11.1
11.2 XXX有限公司住所地有管辖权的法院起诉
12
12.1 使使
`;
export const privacyContent = `
XXX科技有限公司运营的产品XXXXXX.cn"我们"
使使/使使/
使
使
使
1/ TODO()
1 便
/
使/使XXX()
2使使使/
3
2
////
///使/
//使
3
user ID (user IDopen ID信息)/使/使
4
使
5
XXX()便///
6SDK统计服务
1SDK统计服务SDK数据将不含与我们提供产品或服务无关的数据SDK服务请具体查阅本协议附件二所示XXX()使SDK类服务前先行查看其隐私条款
SDK统计服务SDK或其他类似的应用程序侵权您的个人信息
XXX@163.com
2SDK/API/JS代码版本/WiFi等CPU和电池使用情况等
7
使使XXX()
8
使
使 Cookie
Cookie
1 Cookie Cookie Cookie
2 Cookie Cookie Cookie Cookie 访
Cookie 使 URL退
Do Not Track
Do Not Track Do Not Track Do Not Track
1
2
3
4访
5
1
2
1
2
1
1使使
2使使
3
2
1使访使"服务" SSL https 使使访访
2
3使
4访便
5
1
2
3
使
访
1访使访访
访访 XXX()--
访XXX@163.com30访
2使使访XXX@163.com
"(一)访问您的个人信息"
XXX@163.com30
1
2使
3
4使
5
XXX()-XXX()XXX@163.com发送邮件申请删除您的个人信息XXX()/
"第一部分"使
访 XXX()
1XXX()-
2XXX@163.com
3
4
XXX@163.com
1
2
3
4
5
/
使
14
使XXX()
XXX@163.com
XXX@163.com
XXX有限公司住所地享有管辖权的人民法院提起诉讼
XXX()
"您"使访使/
使
使使/
便使/访XXX()使/使
14使/
使
1使/使
2/使使使使
3使使
1
2
3
4
5
/
使
访
WEB端查询和访问儿童的相关个人信息
/
WEB端更正//
使
1WEB端联系我们删除儿童的相关个人信息使/
2
1使
2使
3
4使
5
/
/
访
使/
·XXX有限公司
·XXX@163.com
XXX()SDK服务商
SDK服务
IMEI/IMSISIM卡序列号/MAC地址 https://weixin.qq.com/cgi-bin/readtemplate?lang=3Dzh_CN&t=3Dweixin_agreement&s=3Dprivacy
QQ主体 QQ第三方登录功能 App开发者和/QQ直接收集的个人信息App终端用户在使用QQ互联SDK产品和/App开发者或者其他第三方获取的App开发者和/ https://wiki.connect.qq.com/qq
IMEI/IMSISIM卡序列号/MAC地址 https://opendocs.alipay.com/open/01g6qm
`;

View file

@ -171,7 +171,7 @@
{$i18n.t('Add Memory')}
</div>
</button>
<button
<!-- <button
class="px-4 py-2 text-sm font-medium text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-xl transition"
on:click={() => {
if ($memories.length > 0) {
@ -198,7 +198,7 @@
</svg>
{$i18n.t('Clear memory')}
</div>
</button>
</button> -->
</div>
</div>

View file

@ -12,11 +12,13 @@
import { ldapUserSignIn, getSessionUser, userSignIn, userSignUp } from '$lib/apis/auths';
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import { agreementContent as defaultAgreementContent, privacyContent as defaultPrivacyContent } from '$lib/constants/legal';
import { WEBUI_NAME, config, user, socket } from '$lib/stores';
import { generateInitialsImage, canvasPixelTest } from '$lib/utils';
import Spinner from '$lib/components/common/Spinner.svelte';
import Modal from '$lib/components/common/Modal.svelte';
import OnBoarding from '$lib/components/OnBoarding.svelte';
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
import { redirect } from '@sveltejs/kit';
@ -35,6 +37,12 @@
let confirmPassword = '';
let ldapUsername = '';
let agreeToTerms = false;
let showAgreementModal = false;
let agreementContent = defaultAgreementContent;
let agreeToPrivacy = false;
let showPrivacyModal = false;
let privacyContent = defaultPrivacyContent;
const setSessionUser = async (sessionUser, redirectPath: string | null = null) => {
if (sessionUser) {
@ -95,8 +103,16 @@
if (mode === 'ldap') {
await ldapSignInHandler();
} else if (mode === 'signin') {
if (!agreeToTerms) {
toast.error('如果要登陆,请先同意用户协议');
return;
}
await signInHandler();
} else {
if (!agreeToPrivacy) {
toast.error('如果要注册,请先同意隐私协议');
return;
}
await signUpHandler();
}
};
@ -229,7 +245,7 @@
<img
id="logo"
crossorigin="anonymous"
src="{WEBUI_BASE_URL}/static/favicon.png"
src="static/favicon.png"
class="size-24 rounded-full"
alt=""
/>
@ -334,6 +350,29 @@
/>
</div>
{#if mode === 'signin'}
<div class="mt-3 flex items-start text-sm text-left text-gray-700 dark:text-gray-300 gap-2">
<input
id="agree-terms"
type="checkbox"
class="mt-0.5 rounded border-gray-300 bg-transparent text-gray-800 dark:text-gray-100 focus:ring-0"
bind:checked={agreeToTerms}
/>
<label for="agree-terms" class="leading-tight">
<span>我已阅读并同意</span>
<button
type="button"
class="ml-1 underline font-medium"
on:click={() => {
showAgreementModal = true;
}}
>
用户协议
</button>
</label>
</div>
{/if}
{#if mode === 'signup' && $config?.features?.enable_signup_password_confirmation}
<div class="mt-2">
<label
@ -353,6 +392,29 @@
/>
</div>
{/if}
{#if mode === 'signup'}
<div class="mt-3 flex items-start text-sm text-left text-gray-700 dark:text-gray-300 gap-2">
<input
id="agree-privacy"
type="checkbox"
class="mt-0.5 rounded border-gray-300 bg-transparent text-gray-800 dark:text-gray-100 focus:ring-0"
bind:checked={agreeToPrivacy}
/>
<label for="agree-privacy" class="leading-tight">
<span>我已阅读并同意</span>
<button
type="button"
class="ml-1 underline font-medium"
on:click={() => {
showPrivacyModal = true;
}}
>
隐私协议
</button>
</label>
</div>
{/if}
</div>
{/if}
<div class="mt-5">
@ -575,7 +637,7 @@
<img
id="logo"
crossorigin="anonymous"
src="{WEBUI_BASE_URL}/static/favicon.png"
src="static/favicon.png"
class=" w-6 rounded-full"
alt=""
/>
@ -585,3 +647,52 @@
{/if}
{/if}
</div>
<Modal bind:show={showAgreementModal} size="lg">
<div class="p-8 space-y-5 max-w-4xl">
<!-- <div class="space-y-1">
<div class="text-xl font-semibold text-gray-900 dark:text-white">用户协议</div>
<div class="text-sm text-gray-500 dark:text-gray-400">
以下为占位说明,请替换为正式的服务条款与隐私政策。
</div>
</div> -->
<div class="text-sm text-gray-800 dark:text-gray-100 leading-relaxed space-y-3 max-h-[60vh] overflow-y-auto pr-1 marked">
{@html DOMPurify.sanitize(marked.parse(agreementContent || '这里是用户协议占位内容。请根据实际需求替换为正式的使用条款文本。'))}
</div>
<div class="flex justify-end gap-2">
<button
type="button"
class="px-4 py-2 text-sm rounded-full border border-gray-200 dark:border-gray-700 text-gray-800 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition"
on:click={() => {
showAgreementModal = false;
}}
>
关闭
</button>
</div>
</div>
</Modal>
<Modal bind:show={showPrivacyModal} size="lg">
<div class="p-8 space-y-5 max-w-4xl">
<div class="text-sm text-gray-800 dark:text-gray-100 leading-relaxed space-y-3 max-h-[60vh] overflow-y-auto pr-1 marked">
{@html DOMPurify.sanitize(marked.parse(privacyContent || '这里是隐私协议占位内容。请根据实际需求替换为正式的隐私政策文本。'))}
</div>
<div class="flex justify-end gap-2">
<button
type="button"
class="px-4 py-2 text-sm rounded-full border border-gray-200 dark:border-gray-700 text-gray-800 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition"
on:click={() => {
showPrivacyModal = false;
}}
>
关闭
</button>
</div>
</div>
</Modal>