添加部分功能
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB |
@@ -24,19 +24,16 @@
|
||||
|
||||
<!-- 头部导航 -->
|
||||
<div class="header">
|
||||
<router-link
|
||||
<div
|
||||
v-for="(item, index) in headerItems"
|
||||
:key="index"
|
||||
:to="item.path"
|
||||
class="header-item"
|
||||
custom
|
||||
v-slot="{ navigate }"
|
||||
>
|
||||
<div @click="navigate" class="header-item-content">
|
||||
<div @click="item.text === '系统公告' ? handleSystemAnnouncementClick() : $router.push(item.path)" class="header-item-content">
|
||||
<img :src="item.image" :alt="item.text" class="header-image" />
|
||||
<div class="header-text">{{ item.text }}</div>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 修改后的操作区域 - 三个图片并排 -->
|
||||
@@ -75,7 +72,7 @@
|
||||
<el-dialog
|
||||
v-model="showWelcomeDialog"
|
||||
width="90%"
|
||||
:style="{ height: '425px' }"
|
||||
:style="{ height: isSystemAnnouncementClick ? '525px' : '425px' }"
|
||||
:show-close="true"
|
||||
:close-on-click-modal="true"
|
||||
:close-on-press-escape="true"
|
||||
@@ -87,10 +84,10 @@
|
||||
<div class="welcome-icon">🎉</div>
|
||||
<h3>融汇通更新</h3>
|
||||
<div class="welcome-features">
|
||||
<div class="announcements-container" v-if="unreadAnnouncements.length > 0">
|
||||
<div class="announcements-container" v-if="displayAnnouncements.length > 0">
|
||||
<div
|
||||
class="announcement-item"
|
||||
v-for="announcement in unreadAnnouncements"
|
||||
v-for="announcement in displayAnnouncements"
|
||||
:key="announcement.id"
|
||||
>
|
||||
<div class="announcement-header">
|
||||
@@ -105,7 +102,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-announcements">
|
||||
<span>暂无未读更新信息</span>
|
||||
<span>{{ isSystemAnnouncementClick ? '暂无公告信息' : '暂无未读更新信息' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,6 +200,20 @@ export default {
|
||||
return announcements.value.filter(announcement => !announcement.is_read);
|
||||
});
|
||||
|
||||
// 标记是否通过系统公告按钮打开对话框
|
||||
const isSystemAnnouncementClick = ref(false);
|
||||
|
||||
// 计算要显示的公告列表
|
||||
const displayAnnouncements = computed(() => {
|
||||
if (isSystemAnnouncementClick.value) {
|
||||
// 如果是通过系统公告按钮打开,显示所有公告并按创建时间倒序排列(最新的在前)
|
||||
return [...announcements.value].sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
||||
} else {
|
||||
// 否则只显示未读公告
|
||||
return unreadAnnouncements.value;
|
||||
}
|
||||
});
|
||||
|
||||
// 计算是否应该显示弹窗
|
||||
const shouldShowDialog = computed(() => {
|
||||
return unreadAnnouncements.value.length > 0;
|
||||
@@ -290,8 +301,12 @@ export default {
|
||||
|
||||
// 关闭欢迎弹窗并标记所有未读公告为已读
|
||||
const closeWelcomeDialog = async () => {
|
||||
await markAllAnnouncementsAsRead();
|
||||
// 只有在非系统公告点击时才标记为已读
|
||||
if (!isSystemAnnouncementClick.value) {
|
||||
await markAllAnnouncementsAsRead();
|
||||
}
|
||||
showWelcomeDialog.value = false;
|
||||
isSystemAnnouncementClick.value = false; // 重置标志
|
||||
};
|
||||
|
||||
// 点击已读按钮
|
||||
@@ -299,6 +314,13 @@ export default {
|
||||
showWelcomeDialog.value = false;
|
||||
};
|
||||
|
||||
// 处理系统公告点击事件
|
||||
const handleSystemAnnouncementClick = () => {
|
||||
console.log('触发')
|
||||
isSystemAnnouncementClick.value = true;
|
||||
showWelcomeDialog.value = true; // 无条件显示对话框
|
||||
};
|
||||
|
||||
return {
|
||||
modules: [Autoplay, Pagination],
|
||||
userPoints,
|
||||
@@ -315,6 +337,9 @@ export default {
|
||||
getUserPoints, // 如果需要外部调用可以暴露
|
||||
closeWelcomeDialog,
|
||||
handleReadClick,
|
||||
handleSystemAnnouncementClick,
|
||||
displayAnnouncements,
|
||||
isSystemAnnouncementClick,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
<h2>用户登录</h2>
|
||||
<p>欢迎来到炬融圈</p>
|
||||
</div>
|
||||
|
||||
<div class="image">
|
||||
<img src="/imgs/login.png" alt="炬融圈">
|
||||
</div>
|
||||
|
||||
<el-form
|
||||
ref="loginFormRef"
|
||||
@@ -346,33 +342,6 @@ const handleRememberMe = () => {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 图片容器样式 */
|
||||
.image {
|
||||
width: 375px; /* 固定宽度 */
|
||||
height: 287px; /* 固定高度 */
|
||||
margin: 0 auto 20px; /* 水平居中,底部留出间距 */
|
||||
overflow: hidden; /* 隐藏超出容器的部分 */
|
||||
border-radius: 8px; /* 可选:添加圆角增强视觉效果 */
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); /* 可选:添加轻微阴影 */
|
||||
}
|
||||
|
||||
/* 图片填充样式 */
|
||||
.image img {
|
||||
width: 100%; /* 宽度充满容器 */
|
||||
height: 100%; /* 高度充满容器 */
|
||||
object-fit: contain;
|
||||
display: block; /* 去除图片底部默认空白 */
|
||||
}
|
||||
|
||||
/* 响应式适配(小屏设备自动缩放) */
|
||||
@media (max-width: 375px) {
|
||||
.image {
|
||||
width: 100%; /* 在小于375px的屏幕上宽度自适应 */
|
||||
height: auto; /* 高度按比例自动计算 */
|
||||
aspect-ratio: 375 / 287; /* 保持原比例 */
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@@ -114,28 +114,16 @@
|
||||
<el-form-item prop="agreement">
|
||||
<el-checkbox
|
||||
v-model="registerForm.agreement"
|
||||
@change="handleAgreementChange"
|
||||
@click.prevent="showAgreementDialog"
|
||||
:disabled="true"
|
||||
>
|
||||
我已阅读并同意
|
||||
<el-link
|
||||
type="primary"
|
||||
@click="showAgreement"
|
||||
:class="{ viewed: agreementViewed }"
|
||||
>
|
||||
《用户协议》
|
||||
</el-link>
|
||||
和
|
||||
<el-link
|
||||
type="primary"
|
||||
@click="showPrivacy"
|
||||
:class="{ viewed: privacyViewed }"
|
||||
>
|
||||
《隐私政策》
|
||||
</el-link>
|
||||
<span @click="showAgreementDialog" class="agreement-text">
|
||||
我已阅读并同意《用户协议》和《隐私政策》
|
||||
</span>
|
||||
</el-checkbox>
|
||||
<div v-if="!canCheckAgreement" class="agreement-hint">
|
||||
<div class="agreement-hint">
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
<span>请先点击查看用户协议和隐私政策</span>
|
||||
<span>请点击查看用户协议和隐私政策</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -170,6 +158,64 @@
|
||||
<div class="decoration-shape shape-3"></div>
|
||||
<div class="decoration-shape shape-4"></div>
|
||||
</div>
|
||||
|
||||
<!-- 协议弹窗 -->
|
||||
<el-dialog
|
||||
v-model="showAgreementDialogVisible"
|
||||
title="用户协议和隐私政策"
|
||||
width="90%"
|
||||
:style="{ maxWidth: '600px' }"
|
||||
:show-close="true"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
center
|
||||
class="agreement-dialog"
|
||||
position="bottom"
|
||||
>
|
||||
<div class="agreement-content">
|
||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||
<el-tab-pane name="agreement">
|
||||
<template #label>
|
||||
<span>用户协议</span>
|
||||
<el-icon v-if="agreementViewed" class="check-icon"><Check /></el-icon>
|
||||
</template>
|
||||
<div class="agreement-text-content" ref="agreementContent">
|
||||
<h3>用户协议</h3>
|
||||
<p>1. 用户应当遵守法律法规,不得发布违法违规内容。</p>
|
||||
<p>2. 用户对自己发布的内容承担全部责任。</p>
|
||||
<p>3. 平台有权对违规内容进行删除或限制。</p>
|
||||
<p>4. 用户应当保护好自己的账号安全。</p>
|
||||
<p>5. 平台保留修改本协议的权利。</p>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="privacy">
|
||||
<template #label>
|
||||
<span>隐私政策</span>
|
||||
<el-icon v-if="privacyViewed" class="check-icon"><Check /></el-icon>
|
||||
</template>
|
||||
<div class="privacy-text-content" ref="privacyContent">
|
||||
<h3>隐私政策</h3>
|
||||
<p>1. 我们重视用户隐私保护。</p>
|
||||
<p>2. 我们只收集必要的用户信息。</p>
|
||||
<p>3. 用户信息仅用于提供服务。</p>
|
||||
<p>4. 我们不会向第三方泄露用户信息。</p>
|
||||
<p>5. 用户有权查看、修改或删除个人信息。</p>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<div class="read-status">
|
||||
|
||||
</div>
|
||||
<div class="dialog-buttons">
|
||||
<el-button @click="closeAgreementDialog">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAgreement" :disabled="!(agreementViewed && privacyViewed)">确认已阅读</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -187,6 +233,7 @@ import {
|
||||
CreditCard,
|
||||
Location,
|
||||
InfoFilled,
|
||||
Check,
|
||||
} from '@element-plus/icons-vue';
|
||||
import Captcha from '@/components/Captcha.vue';
|
||||
import api from '@/utils/api'
|
||||
@@ -218,9 +265,12 @@ const registerForm = reactive({
|
||||
// 协议查看状态
|
||||
const agreementViewed = ref(false);
|
||||
const privacyViewed = ref(false);
|
||||
const canCheckAgreement = computed(
|
||||
() => agreementViewed.value && privacyViewed.value
|
||||
);
|
||||
|
||||
// 协议弹窗相关状态
|
||||
const showAgreementDialogVisible = ref(false);
|
||||
const activeTab = ref('agreement');
|
||||
const agreementContent = ref();
|
||||
const privacyContent = ref();
|
||||
|
||||
// 短信验证码相关状态
|
||||
const sendingSMS = ref(false);
|
||||
@@ -477,62 +527,45 @@ const handleRegister = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 显示用户协议
|
||||
const showAgreement = () => {
|
||||
ElMessageBox.alert(
|
||||
`<div style="text-align: left; line-height: 1.6;">
|
||||
<h3>用户协议</h3>
|
||||
<p>1. 用户应当遵守法律法规,不得发布违法违规内容。</p>
|
||||
<p>2. 用户对自己发布的内容承担全部责任。</p>
|
||||
<p>3. 平台有权对违规内容进行删除或限制。</p>
|
||||
<p>4. 用户应当保护好自己的账号安全。</p>
|
||||
<p>5. 平台保留修改本协议的权利。</p>
|
||||
</div>`,
|
||||
'用户协议',
|
||||
{
|
||||
confirmButtonText: '我已了解',
|
||||
dangerouslyUseHTMLString: true,
|
||||
customClass: 'agreement-dialog',
|
||||
}
|
||||
).then(() => {
|
||||
agreementViewed.value = true;
|
||||
ElMessage.success('已查看用户协议');
|
||||
});
|
||||
// 显示协议弹窗
|
||||
const showAgreementDialog = () => {
|
||||
showAgreementDialogVisible.value = true;
|
||||
activeTab.value = 'agreement';
|
||||
// 弹窗打开时默认用户协议已读
|
||||
agreementViewed.value = true;
|
||||
};
|
||||
|
||||
// 显示隐私政策
|
||||
const showPrivacy = () => {
|
||||
ElMessageBox.alert(
|
||||
`<div style="text-align: left; line-height: 1.6;">
|
||||
<h3>隐私政策</h3>
|
||||
<p>1. 我们重视用户隐私保护。</p>
|
||||
<p>2. 我们只收集必要的用户信息。</p>
|
||||
<p>3. 用户信息仅用于提供服务。</p>
|
||||
<p>4. 我们不会向第三方泄露用户信息。</p>
|
||||
<p>5. 用户有权查看、修改或删除个人信息。</p>
|
||||
</div>`,
|
||||
'隐私政策',
|
||||
{
|
||||
confirmButtonText: '我已了解',
|
||||
dangerouslyUseHTMLString: true,
|
||||
customClass: 'privacy-dialog',
|
||||
}
|
||||
).then(() => {
|
||||
privacyViewed.value = true;
|
||||
ElMessage.success('已查看隐私政策');
|
||||
});
|
||||
// 关闭协议弹窗
|
||||
const closeAgreementDialog = () => {
|
||||
showAgreementDialogVisible.value = false;
|
||||
};
|
||||
|
||||
// 处理协议勾选
|
||||
const handleAgreementChange = (value) => {
|
||||
if (value && !canCheckAgreement.value) {
|
||||
registerForm.agreement = false;
|
||||
ElMessage.warning('请先查看用户协议和隐私政策后再勾选');
|
||||
return false;
|
||||
// 确认已阅读协议
|
||||
const confirmAgreement = () => {
|
||||
if (agreementViewed.value && privacyViewed.value) {
|
||||
registerForm.agreement = true;
|
||||
showAgreementDialogVisible.value = false;
|
||||
ElMessage.success('已确认阅读用户协议和隐私政策');
|
||||
} else {
|
||||
ElMessage.warning('请先查看用户协议和隐私政策');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 处理选项卡切换
|
||||
const handleTabChange = (tabName) => {
|
||||
if (tabName === 'agreement') {
|
||||
// 切换到用户协议时,标记为已读
|
||||
agreementViewed.value = true;
|
||||
} else if (tabName === 'privacy') {
|
||||
// 切换到隐私政策时,标记为已读
|
||||
privacyViewed.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 图片上传成功处理
|
||||
const handleUploadSuccess = (response, field) => {
|
||||
ElMessage.success('图片上传成功');
|
||||
@@ -888,9 +921,94 @@ onMounted(() => {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-link.viewed) {
|
||||
color: #67c23a !important;
|
||||
font-weight: 500;
|
||||
.agreement-text {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.agreement-text:hover {
|
||||
color: #66b1ff;
|
||||
}
|
||||
|
||||
/* 协议弹窗样式 */
|
||||
:deep(.agreement-dialog) {
|
||||
.el-dialog__body {
|
||||
padding: 20px;
|
||||
max-height: 60vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.agreement-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.agreement-text-content,
|
||||
.privacy-text-content {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
line-height: 1.6;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.agreement-text-content h3,
|
||||
.privacy-text-content h3 {
|
||||
color: #303133;
|
||||
margin-bottom: 16px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.agreement-text-content p,
|
||||
.privacy-text-content p {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.agreement-text-content strong,
|
||||
.privacy-text-content strong {
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
color: #67c23a;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
.agreement-text-content::-webkit-scrollbar,
|
||||
.privacy-text-content::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.agreement-text-content::-webkit-scrollbar-track,
|
||||
.privacy-text-content::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.agreement-text-content::-webkit-scrollbar-thumb,
|
||||
.privacy-text-content::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.agreement-text-content::-webkit-scrollbar-thumb:hover,
|
||||
.privacy-text-content::-webkit-scrollbar-thumb:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
|
||||
:deep(.el-link.viewed:hover) {
|
||||
|
||||
Reference in New Issue
Block a user