add(components): 添加MyInput组件
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
|
||||
<div id="Test">
|
||||
<MyInput icon-name="user"></MyInput>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MyInput from '@/components/MyInput.vue';
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,454 +1,292 @@
|
||||
<template>
|
||||
<div class="login-wrap" @keyup.enter="handleLogin">
|
||||
<div class="login-card" role="form" aria-label="登录表单">
|
||||
<!-- 左侧品牌/装饰 -->
|
||||
<div class="login-side">
|
||||
<div class="brand">
|
||||
<div class="brand-logo" aria-hidden="true">
|
||||
<!-- 圆形头像徽标 -->
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect x="2" y="2" width="20" height="20" rx="5" fill="currentColor" />
|
||||
<path
|
||||
d="M8 14c0-1.657 1.343-3 3-3s3 1.343 3 3"
|
||||
stroke="white"
|
||||
stroke-width="1.2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<circle cx="11" cy="9" r="1.3" fill="white" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="brand-name">即时通讯</div>
|
||||
</div>
|
||||
|
||||
<p class="side-desc">与朋友、同事保持联络 — 轻量、快速、私密。</p>
|
||||
|
||||
<div class="side-illu" aria-hidden="true">
|
||||
<!-- 简单装饰圆块,避免加载外部图片 -->
|
||||
<div class="bubble b1"></div>
|
||||
<div class="bubble b2"></div>
|
||||
<div class="bubble b3"></div>
|
||||
</div>
|
||||
<div class="login-layout">
|
||||
|
||||
<div class="side-visual">
|
||||
<div class="visual-mask"></div>
|
||||
<div class="brand-container">
|
||||
<h1 class="hero-title">Work<br>Together.</h1>
|
||||
<p class="hero-subtitle">下一代企业级即时通讯平台,让沟通无距离。</p>
|
||||
</div>
|
||||
|
||||
<!-- 右侧表单 -->
|
||||
<div class="login-body">
|
||||
<header class="login-header">
|
||||
<h2 class="login-title">欢迎回来</h2>
|
||||
<p class="login-subtitle">使用账号登录以继续</p>
|
||||
</header>
|
||||
|
||||
<form class="login-form" @submit.prevent="handleLogin" autocomplete="on" novalidate>
|
||||
<div class="input-container" :class="{ focused: usernameFocused || username }">
|
||||
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path
|
||||
d="M20 21V19C20 16.7909 18.2091 15 16 15H8C5.79086 15 4 16.7909 4 19V21"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.6"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
<circle cx="12" cy="7" r="4" fill="none" stroke="currentColor" stroke-width="1.6" />
|
||||
</svg>
|
||||
<input
|
||||
id="username"
|
||||
type="text"
|
||||
v-model="username"
|
||||
@focus="usernameFocused = true"
|
||||
@blur="usernameFocused = false"
|
||||
placeholder="用户名 / 邮箱"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="input-container" :class="{ focused: passwordFocused || password }">
|
||||
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<rect
|
||||
x="3"
|
||||
y="11"
|
||||
width="18"
|
||||
height="11"
|
||||
rx="2"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.6"
|
||||
/>
|
||||
<path
|
||||
d="M7 11V7C7 4.23858 9.23858 2 12 2C14.7614 2 17 4.23858 17 7V11"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.6"
|
||||
/>
|
||||
</svg>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
v-model="password"
|
||||
@focus="passwordFocused = true"
|
||||
@blur="passwordFocused = false"
|
||||
placeholder="密码"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="row-between">
|
||||
<label class="remember">
|
||||
<input type="checkbox" v-model="remember" />
|
||||
<span class="box" aria-hidden="true"></span>
|
||||
记住我
|
||||
</label>
|
||||
<a class="link" href="#" @click.prevent>忘记密码?</a>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-primary" :disabled="loading" aria-disabled="loading">
|
||||
<span v-if="!loading">登录</span>
|
||||
<span v-else>登录中...</span>
|
||||
</button>
|
||||
|
||||
<p v-if="errorMsg" class="error">{{ errorMsg }}</p>
|
||||
</form>
|
||||
|
||||
<footer class="login-footer">
|
||||
<span>还没有账号?</span>
|
||||
<a class="link" href="#" @click.prevent>注册</a>
|
||||
</footer>
|
||||
<div class="visual-footer">
|
||||
<span>© 2024 IM System</span>
|
||||
<div class="dots">
|
||||
<span></span><span></span><span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="side-form">
|
||||
<div class="form-wrapper">
|
||||
<div class="welcome-header">
|
||||
<h2>账号登录</h2>
|
||||
<p>请输入您的工作账号以继续</p>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="handleLogin">
|
||||
<div class="input-group">
|
||||
<label>用户名 / 邮箱</label>
|
||||
<div class="field-wrap">
|
||||
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
<input type="text" v-model="form.username" placeholder="name@company.com" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<div class="label-row">
|
||||
<label>密码</label>
|
||||
<a href="#" class="forgot-link">忘记密码?</a>
|
||||
</div>
|
||||
<div class="field-wrap">
|
||||
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||||
</svg>
|
||||
<input type="password" v-model="form.password" placeholder="••••••••" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="submit-btn" :disabled="loading">
|
||||
{{ loading ? '登录中...' : '登 录' }}
|
||||
<svg v-if="!loading" viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="arrow"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="register-hint">
|
||||
还没有账号? <a href="#">联系管理员注册</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const remember = ref(false)
|
||||
const errorMsg = ref('')
|
||||
const loading = ref(false)
|
||||
|
||||
const usernameFocused = ref(false)
|
||||
const passwordFocused = ref(false)
|
||||
const form = reactive({
|
||||
username: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
const handleLogin = () => {
|
||||
errorMsg.value = ''
|
||||
if (!username.value.trim() || !password.value) {
|
||||
errorMsg.value = '用户名或密码不能为空'
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
// 模拟登录延迟(客户端示例),生产中替换为 API 调用
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
if (username.value === 'admin' && password.value === '123456') {
|
||||
errorMsg.value = ''
|
||||
alert('登录成功!')
|
||||
// TODO: 跳转到 IM 主界面
|
||||
} else {
|
||||
errorMsg.value = '用户名或密码错误'
|
||||
}
|
||||
}, 700)
|
||||
setTimeout(() => loading.value = false, 1500)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 容器与居中 */
|
||||
.login-wrap {
|
||||
/* 撑满 Window 组件的内容区 */
|
||||
.login-layout {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 登录卡片:左右两栏 */
|
||||
.login-card {
|
||||
width: 740px;
|
||||
max-width: calc(100% - 48px);
|
||||
height: 460px;
|
||||
display: flex;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.98));
|
||||
box-shadow: 0 18px 40px rgba(16, 24, 40, 0.08);
|
||||
border: 1px solid rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
/* 左侧品牌区域 */
|
||||
.login-side {
|
||||
width: 44%;
|
||||
min-width: 280px;
|
||||
padding: 28px 22px;
|
||||
background: linear-gradient(160deg, rgba(59, 130, 246, 0.06), rgba(99, 102, 241, 0.04));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
/* --- 左侧视觉 --- */
|
||||
.side-visual {
|
||||
width: 42%;
|
||||
background: linear-gradient(135deg, #4f46e5 0%, #3b82f6 100%);
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
/* 增加一点背景纹理 */
|
||||
.side-visual::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background-image: radial-gradient(rgba(255,255,255,0.15) 1px, transparent 1px);
|
||||
background-size: 20px 20px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.brand-logo {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
|
||||
.brand-container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.hero-title {
|
||||
font-size: 48px;
|
||||
font-weight: 800;
|
||||
line-height: 1.1;
|
||||
margin-bottom: 16px;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
.hero-subtitle {
|
||||
font-size: 15px;
|
||||
opacity: 0.9;
|
||||
line-height: 1.6;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.visual-footer {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
left: 40px;
|
||||
right: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.dots span {
|
||||
display: inline-block;
|
||||
width: 4px; height: 4px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* --- 右侧表单 --- */
|
||||
.side-form {
|
||||
flex: 1;
|
||||
background: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #3b82f6;
|
||||
background: rgba(59, 130, 246, 0.08);
|
||||
border-radius: 12px;
|
||||
padding: 40px;
|
||||
}
|
||||
.brand-name {
|
||||
font-size: 18px;
|
||||
|
||||
.form-wrapper {
|
||||
width: 100%;
|
||||
max-width: 360px;
|
||||
}
|
||||
|
||||
.welcome-header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.welcome-header h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
color: #1e293b;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.welcome-header p {
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.side-desc {
|
||||
color: #475569;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
max-width: 210px;
|
||||
margin-bottom: 18px;
|
||||
.input-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 简单的装饰圆块 */
|
||||
.side-illu {
|
||||
position: absolute;
|
||||
right: -30px;
|
||||
bottom: -20px;
|
||||
}
|
||||
.bubble {
|
||||
border-radius: 50%;
|
||||
opacity: 0.12;
|
||||
}
|
||||
.b1 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background: linear-gradient(135deg, #60a5fa, #7c3aed);
|
||||
transform: rotate(10deg);
|
||||
margin: 8px;
|
||||
}
|
||||
.b2 {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
background: linear-gradient(135deg, #a78bfa, #60a5fa);
|
||||
margin: 8px;
|
||||
}
|
||||
.b3 {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: linear-gradient(135deg, #93c5fd, #a78bfa);
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
/* 右侧表单 */
|
||||
.login-body {
|
||||
width: 56%;
|
||||
padding: 30px 34px;
|
||||
.label-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.login-header {
|
||||
text-align: left;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.login-title {
|
||||
font-size: 20px;
|
||||
margin: 0 0 6px;
|
||||
color: #0f172a;
|
||||
font-weight: 700;
|
||||
}
|
||||
.login-subtitle {
|
||||
margin: 0;
|
||||
label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.forgot-link {
|
||||
font-size: 12px;
|
||||
color: #4f46e5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 表单 */
|
||||
.login-form {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
/* 输入容器 */
|
||||
.input-container {
|
||||
/* 输入框样式:现代填充风格 */
|
||||
.field-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #ffffff;
|
||||
border-radius: 10px;
|
||||
padding: 12px 12px 12px 44px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.06);
|
||||
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.02);
|
||||
transition: all 0.22s ease;
|
||||
}
|
||||
.input-container .icon {
|
||||
.field-wrap .icon {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: #94a3b8;
|
||||
opacity: 0.95;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
.input-container input {
|
||||
.field-wrap input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 12px 12px 12px 40px;
|
||||
background: #f1f5f9; /* 浅灰底色 */
|
||||
border: 2px solid transparent;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: #0f172a;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
color: #1e293b;
|
||||
outline: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* 聚焦态 */
|
||||
.input-container.focused {
|
||||
border-color: rgba(99, 102, 241, 0.9);
|
||||
box-shadow: 0 8px 20px rgba(99, 102, 241, 0.08);
|
||||
transform: translateY(-2px);
|
||||
/* 聚焦交互 */
|
||||
.field-wrap input:focus {
|
||||
background: #fff;
|
||||
border-color: #4f46e5; /* 品牌色 */
|
||||
box-shadow: 0 4px 12px rgba(79, 70, 229, 0.1);
|
||||
}
|
||||
.input-container.focused .icon {
|
||||
color: rgba(99, 102, 241, 0.95);
|
||||
.field-wrap input:focus + .icon,
|
||||
.field-wrap input:focus ~ .icon {
|
||||
color: #4f46e5;
|
||||
}
|
||||
|
||||
/* 行内布局 */
|
||||
.row-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* 记住我 checkbox */
|
||||
.remember {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #475569;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.remember input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.remember .box {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: inline-block;
|
||||
border-radius: 6px;
|
||||
border: 1.5px solid rgba(15, 23, 42, 0.08);
|
||||
background: white;
|
||||
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.03);
|
||||
transition: all 0.14s ease;
|
||||
}
|
||||
.remember input:checked + .box {
|
||||
background: linear-gradient(90deg, #6366f1, #3b82f6);
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.remember input:checked + .box::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
border: 2px solid white;
|
||||
border-left: 0;
|
||||
border-top: 0;
|
||||
transform: translate(5px, 2px) rotate(45deg);
|
||||
}
|
||||
|
||||
/* 链接样式 */
|
||||
.link {
|
||||
color: #3b82f6;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
.link:hover {
|
||||
text-decoration: underline;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
/* 主操作按钮 */
|
||||
.btn-primary {
|
||||
/* 按钮 */
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
padding: 12px 14px;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
background: linear-gradient(90deg, #6366f1, #3b82f6);
|
||||
margin-top: 10px;
|
||||
padding: 12px;
|
||||
background: #4f46e5;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.18);
|
||||
transition:
|
||||
transform 0.12s ease,
|
||||
box-shadow 0.12s ease,
|
||||
opacity 0.12s;
|
||||
}
|
||||
.btn-primary:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: default;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* 错误提示 */
|
||||
.error {
|
||||
color: #b91c1c;
|
||||
background: #fff5f5;
|
||||
border-left: 4px solid #f87171;
|
||||
padding: 10px 12px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
/* 页脚注册 */
|
||||
.login-footer {
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: background 0.2s, transform 0.1s;
|
||||
}
|
||||
.submit-btn:hover {
|
||||
background: #4338ca;
|
||||
}
|
||||
.submit-btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.submit-btn:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
/* 响应式 */
|
||||
@media (max-width: 820px) {
|
||||
.login-card {
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
}
|
||||
.login-side {
|
||||
width: 100%;
|
||||
min-height: 140px;
|
||||
order: 1;
|
||||
}
|
||||
.login-body {
|
||||
width: 100%;
|
||||
order: 2;
|
||||
padding: 22px;
|
||||
}
|
||||
.register-hint {
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
color: #64748b;
|
||||
}
|
||||
</style>
|
||||
.register-hint a {
|
||||
color: #4f46e5;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.login-layout {
|
||||
flex-direction: column;
|
||||
}
|
||||
.side-visual {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
padding: 24px;
|
||||
}
|
||||
.hero-title { font-size: 28px; }
|
||||
.visual-footer { display: none; }
|
||||
.side-form { flex: 1; padding: 24px; }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user