更新前端个人中心

This commit is contained in:
李志强 2025-06-05 17:06:39 +08:00
parent d4017014f5
commit e1e51c8c6f
9 changed files with 2640 additions and 564 deletions

View File

@ -1,5 +1,11 @@
<div class="basic-info"> <div class="basic-info">
<h2 class="section-title">个人资料</h2> <div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">个人资料</li>
<li>修改头像</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<form class="layui-form" lay-filter="basicForm"> <form class="layui-form" lay-filter="basicForm">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">用户名</label> <label class="layui-form-label">用户名</label>
@ -45,6 +51,37 @@
</div> </div>
</div> </div>
</form> </form>
</div>
<div class="layui-tab-item">
<div class="avatar-section">
<div class="avatar-upload-container">
<div class="current-avatar">
<img src="{$user.avatar|default='/static/images/avatar.png'}" alt="当前头像" id="currentAvatar">
<p class="avatar-tip">当前头像</p>
</div>
<div class="upload-area" id="uploadArea">
<i class="layui-icon layui-icon-upload"></i>
<p>点击或拖拽图片到此处上传</p>
<p class="upload-tip">支持 jpg、png、gif 格式,大小不超过 2MB</p>
<input type="file" id="avatarFile" accept="image/*" style="display: none;">
</div>
</div>
<div class="avatar-preview" style="display: none;">
<h3>预览</h3>
<div class="preview-container">
<img src="" alt="预览图" id="previewImage">
</div>
<div class="preview-actions">
<button class="layui-btn" id="confirmUpload">确认上传</button>
<button class="layui-btn layui-btn-primary" id="cancelUpload">取消</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<style> <style>
@ -78,6 +115,95 @@
min-height: 120px; min-height: 120px;
} }
.avatar-section {
max-width: 800px;
margin: 0 auto;
}
.avatar-upload-container {
display: flex;
gap: 40px;
margin-bottom: 32px;
}
.current-avatar {
text-align: center;
}
.current-avatar img {
width: 160px;
height: 160px;
border-radius: 50%;
object-fit: cover;
border: 3px solid #f5f5f5;
}
.avatar-tip {
margin-top: 12px;
color: #666;
}
.upload-area {
flex: 1;
border: 2px dashed #d9d9d9;
border-radius: 8px;
padding: 40px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
}
.upload-area:hover {
border-color: #1677ff;
}
.upload-area .layui-icon {
font-size: 48px;
color: #999;
margin-bottom: 16px;
}
.upload-area p {
margin: 8px 0;
color: #666;
}
.upload-tip {
font-size: 12px;
color: #999;
}
.avatar-preview {
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid #f0f0f0;
}
.avatar-preview h3 {
font-size: 16px;
color: #333;
margin-bottom: 16px;
}
.preview-container {
text-align: center;
margin-bottom: 24px;
}
.preview-container img {
max-width: 200px;
max-height: 200px;
border-radius: 8px;
}
.preview-actions {
text-align: center;
}
.preview-actions .layui-btn {
margin: 0 8px;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.layui-form-label { .layui-form-label {
width: 80px; width: 80px;
@ -86,15 +212,30 @@
.layui-input-block { .layui-input-block {
margin-left: 110px; margin-left: 110px;
} }
.avatar-upload-container {
flex-direction: column;
gap: 24px;
}
.current-avatar img {
width: 120px;
height: 120px;
}
.upload-area {
padding: 24px;
}
} }
</style> </style>
<script> <script>
layui.use(['form', 'layer'], function () { layui.use(['form', 'layer', 'upload'], function () {
var form = layui.form; var form = layui.form;
var layer = layui.layer; var layer = layui.layer;
var upload = layui.upload;
// 监听表单提交 // 监听个人资料表单提交
form.on('submit(saveBasic)', function (data) { form.on('submit(saveBasic)', function (data) {
// 发送AJAX请求保存数据 // 发送AJAX请求保存数据
fetch('/index/user/saveBasic', { fetch('/index/user/saveBasic', {
@ -123,5 +264,122 @@
return false; // 阻止表单默认提交 return false; // 阻止表单默认提交
}); });
// 点击上传区域触发文件选择
document.getElementById('uploadArea').addEventListener('click', function () {
document.getElementById('avatarFile').click();
});
// 处理文件选择
document.getElementById('avatarFile').addEventListener('change', function (e) {
var file = e.target.files[0];
if (!file) return;
// 检查文件类型
if (!['image/jpeg', 'image/png', 'image/gif', 'image/webp'].includes(file.type)) {
layer.msg('请上传 jpg、png、webp 或 gif 格式的图片');
return;
}
// 检查文件大小
if (file.size > 2 * 1024 * 1024) {
layer.msg('图片大小不能超过 2MB');
return;
}
// 预览图片
var reader = new FileReader();
reader.onload = function (e) {
document.getElementById('previewImage').src = e.target.result;
document.querySelector('.avatar-preview').style.display = 'block';
};
reader.readAsDataURL(file);
});
// 确认上传
document.getElementById('confirmUpload').addEventListener('click', function () {
var file = document.getElementById('avatarFile').files[0];
if (!file) return;
var formData = new FormData();
formData.append('avatar', file);
// 显示上传中
var loadIndex = layer.load(2);
// 发送上传请求
fetch('/index/user/update_avatar', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
layer.close(loadIndex);
if (data.code === 0) {
// 更新cookie中的头像
document.cookie = "user_avatar=" + data.data.url + "; path=/";
// 更新localStorage中的头像
localStorage.setItem('user_avatar', data.data.url);
layer.msg('头像上传成功', {
icon: 1,
time: 1000
}, function () {
// 更新当前头像显示
document.getElementById('currentAvatar').src = data.data.url;
// 隐藏预览区域
document.querySelector('.avatar-preview').style.display = 'none';
// 清空文件输入
document.getElementById('avatarFile').value = '';
// 刷新页面以更新所有显示的头像
window.location.reload();
});
} else {
layer.msg(data.msg || '上传失败', { icon: 2 });
}
})
.catch(error => {
layer.close(loadIndex);
layer.msg('上传失败,请重试', { icon: 2 });
});
});
// 取消上传
document.getElementById('cancelUpload').addEventListener('click', function () {
document.querySelector('.avatar-preview').style.display = 'none';
document.getElementById('avatarFile').value = '';
});
// 拖拽上传
var uploadArea = document.getElementById('uploadArea');
uploadArea.addEventListener('dragover', function (e) {
e.preventDefault();
this.style.borderColor = '#1677ff';
});
uploadArea.addEventListener('dragleave', function (e) {
e.preventDefault();
this.style.borderColor = '#d9d9d9';
});
uploadArea.addEventListener('drop', function (e) {
e.preventDefault();
this.style.borderColor = '#d9d9d9';
var file = e.dataTransfer.files[0];
if (!file) return;
// 触发文件选择事件
var dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
document.getElementById('avatarFile').files = dataTransfer.files;
// 手动触发change事件
var event = new Event('change');
document.getElementById('avatarFile').dispatchEvent(event);
});
}); });
</script> </script>

View File

@ -1,8 +1,5 @@
<div class="messages-section"> <div class="basic-info">
<h2 class="section-title">我的消息</h2> <div class="layui-tab">
<div class="message-tabs">
<div class="layui-tab layui-tab-brief" lay-filter="messageTabs">
<ul class="layui-tab-title"> <ul class="layui-tab-title">
<li class="layui-this">全部消息</li> <li class="layui-this">全部消息</li>
<li>未读消息</li> <li>未读消息</li>
@ -26,33 +23,44 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
<style> <style>
.messages-section { .basic-info {
max-width: 800px; max-width: 800px;
margin: 0 auto; margin: 0 auto;
} }
.section-title { .section-title {
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
margin-bottom: 24px; margin-bottom: 24px;
padding-bottom: 16px; padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
} }
.message-tabs { .layui-form-label {
width: 100px;
}
.layui-input-block {
margin-left: 130px;
}
.layui-form-item {
margin-bottom: 24px;
}
.layui-textarea {
min-height: 120px;
}
.message-list {
margin-top: 20px; margin-top: 20px;
} }
.message-list { .message-item {
margin-top: 20px;
}
.message-item {
padding: 16px; padding: 16px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
display: flex; display: flex;
@ -60,57 +68,57 @@
gap: 16px; gap: 16px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s; transition: background-color 0.3s;
} }
.message-item:hover { .message-item:hover {
background-color: #f9f9f9; background-color: #f9f9f9;
} }
.message-item.unread { .message-item.unread {
background-color: #f0f7ff; background-color: #f0f7ff;
} }
.message-avatar { .message-avatar {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 50%; border-radius: 50%;
object-fit: cover; object-fit: cover;
} }
.message-content { .message-content {
flex: 1; flex: 1;
} }
.message-title { .message-title {
font-weight: 500; font-weight: 500;
margin-bottom: 4px; margin-bottom: 4px;
color: #333; color: #333;
} }
.message-text { .message-text {
color: #666; color: #666;
font-size: 14px; font-size: 14px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.message-meta { .message-meta {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
font-size: 12px; font-size: 12px;
color: #999; color: #999;
} }
.message-time { .message-time {
color: #999; color: #999;
} }
.message-actions { .message-actions {
display: flex; display: flex;
gap: 8px; gap: 8px;
} }
.message-actions button { .message-actions button {
padding: 4px 8px; padding: 4px 8px;
font-size: 12px; font-size: 12px;
border-radius: 4px; border-radius: 4px;
@ -119,20 +127,28 @@
color: #666; color: #666;
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;
} }
.message-actions button:hover { .message-actions button:hover {
border-color: #1677ff; border-color: #1677ff;
color: #1677ff; color: #1677ff;
} }
.empty-message { .empty-message {
text-align: center; text-align: center;
padding: 40px 0; padding: 40px 0;
color: #999; color: #999;
} }
@media (max-width: 768px) {
.layui-form-label {
width: 80px;
}
.layui-input-block {
margin-left: 110px;
}
@media (max-width: 768px) {
.message-item { .message-item {
padding: 12px; padding: 12px;
} }
@ -141,11 +157,11 @@
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
} }
</style> </style>
<script> <script>
layui.use(['element', 'layer'], function(){ layui.use(['element', 'layer'], function () {
var element = layui.element; var element = layui.element;
var layer = layui.layer; var layer = layui.layer;
@ -158,27 +174,27 @@ layui.use(['element', 'layer'], function(){
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
layer.close(loadIndex); layer.close(loadIndex);
if(data.code === 0) { if (data.code === 0) {
renderMessages(container, data.data); renderMessages(container, data.data);
} else { } else {
layer.msg(data.msg || '加载失败', {icon: 2}); layer.msg(data.msg || '加载失败', { icon: 2 });
} }
}) })
.catch(error => { .catch(error => {
layer.close(loadIndex); layer.close(loadIndex);
layer.msg('加载失败,请重试', {icon: 2}); layer.msg('加载失败,请重试', { icon: 2 });
}); });
} }
// 渲染消息列表 // 渲染消息列表
function renderMessages(container, messages) { function renderMessages(container, messages) {
if(!messages || messages.length === 0) { if (!messages || messages.length === 0) {
container.innerHTML = '<div class="empty-message">暂无消息</div>'; container.innerHTML = '<div class="empty-message">暂无消息</div>';
return; return;
} }
var html = ''; var html = '';
messages.forEach(function(message) { messages.forEach(function (message) {
html += ` html += `
<div class="message-item ${message.is_read ? '' : 'unread'}" data-id="${message.id}"> <div class="message-item ${message.is_read ? '' : 'unread'}" data-id="${message.id}">
<img src="${message.avatar || '/static/images/avatar.png'}" class="message-avatar" alt="头像"> <img src="${message.avatar || '/static/images/avatar.png'}" class="message-avatar" alt="头像">
@ -207,7 +223,7 @@ layui.use(['element', 'layer'], function(){
function bindMessageEvents(container) { function bindMessageEvents(container) {
// 标记已读 // 标记已读
container.querySelectorAll('.mark-read').forEach(btn => { container.querySelectorAll('.mark-read').forEach(btn => {
btn.addEventListener('click', function(e) { btn.addEventListener('click', function (e) {
e.stopPropagation(); e.stopPropagation();
var messageId = this.closest('.message-item').dataset.id; var messageId = this.closest('.message-item').dataset.id;
markAsRead(messageId); markAsRead(messageId);
@ -216,7 +232,7 @@ layui.use(['element', 'layer'], function(){
// 删除消息 // 删除消息
container.querySelectorAll('.delete-message').forEach(btn => { container.querySelectorAll('.delete-message').forEach(btn => {
btn.addEventListener('click', function(e) { btn.addEventListener('click', function (e) {
e.stopPropagation(); e.stopPropagation();
var messageId = this.closest('.message-item').dataset.id; var messageId = this.closest('.message-item').dataset.id;
deleteMessage(messageId); deleteMessage(messageId);
@ -225,7 +241,7 @@ layui.use(['element', 'layer'], function(){
// 点击消息 // 点击消息
container.querySelectorAll('.message-item').forEach(item => { container.querySelectorAll('.message-item').forEach(item => {
item.addEventListener('click', function() { item.addEventListener('click', function () {
var messageId = this.dataset.id; var messageId = this.dataset.id;
viewMessage(messageId); viewMessage(messageId);
}); });
@ -239,51 +255,51 @@ layui.use(['element', 'layer'], function(){
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({id: messageId}) body: JSON.stringify({ id: messageId })
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if(data.code === 0) { if (data.code === 0) {
layer.msg('已标记为已读', {icon: 1}); layer.msg('已标记为已读', { icon: 1 });
// 重新加载消息列表 // 重新加载消息列表
loadMessages('all'); loadMessages('all');
loadMessages('unread'); loadMessages('unread');
loadMessages('read'); loadMessages('read');
} else { } else {
layer.msg(data.msg || '操作失败', {icon: 2}); layer.msg(data.msg || '操作失败', { icon: 2 });
} }
}) })
.catch(error => { .catch(error => {
layer.msg('操作失败,请重试', {icon: 2}); layer.msg('操作失败,请重试', { icon: 2 });
}); });
} }
// 删除消息 // 删除消息
function deleteMessage(messageId) { function deleteMessage(messageId) {
layer.confirm('确定要删除这条消息吗?', { layer.confirm('确定要删除这条消息吗?', {
btn: ['确定','取消'] btn: ['确定', '取消']
}, function(){ }, function () {
fetch('/index/user/deleteMessage', { fetch('/index/user/deleteMessage', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({id: messageId}) body: JSON.stringify({ id: messageId })
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if(data.code === 0) { if (data.code === 0) {
layer.msg('删除成功', {icon: 1}); layer.msg('删除成功', { icon: 1 });
// 重新加载消息列表 // 重新加载消息列表
loadMessages('all'); loadMessages('all');
loadMessages('unread'); loadMessages('unread');
loadMessages('read'); loadMessages('read');
} else { } else {
layer.msg(data.msg || '删除失败', {icon: 2}); layer.msg(data.msg || '删除失败', { icon: 2 });
} }
}) })
.catch(error => { .catch(error => {
layer.msg('删除失败,请重试', {icon: 2}); layer.msg('删除失败,请重试', { icon: 2 });
}); });
}); });
} }
@ -299,12 +315,12 @@ layui.use(['element', 'layer'], function(){
} }
// 监听标签切换 // 监听标签切换
element.on('tab(messageTabs)', function(data){ element.on('tab(messageTabs)', function (data) {
var type = ['all', 'unread', 'read'][data.index]; var type = ['all', 'unread', 'read'][data.index];
loadMessages(type); loadMessages(type);
}); });
// 初始加载全部消息 // 初始加载全部消息
loadMessages('all'); loadMessages('all');
}); });
</script> </script>

View File

@ -1,5 +1,4 @@
<div class="notifications-section"> <div class="notifications-section">
<h2 class="section-title">系统通知</h2>
<div class="layui-tab layui-tab-brief" lay-filter="notificationTabs"> <div class="layui-tab layui-tab-brief" lay-filter="notificationTabs">
<ul class="layui-tab-title"> <ul class="layui-tab-title">
@ -22,61 +21,61 @@
</div> </div>
<style> <style>
.notifications-section { .notifications-section {
max-width: 800px; max-width: 800px;
margin: 0 auto; margin: 0 auto;
} }
.section-title { .section-title {
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
margin-bottom: 24px; margin-bottom: 24px;
padding-bottom: 16px; padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
} }
.notification-list { .notification-list {
min-height: 200px; min-height: 200px;
} }
.notification-item { .notification-item {
padding: 16px; padding: 16px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
.notification-item:hover { .notification-item:hover {
background-color: #f9f9f9; background-color: #f9f9f9;
} }
.notification-content { .notification-content {
flex: 1; flex: 1;
} }
.notification-title { .notification-title {
font-size: 16px; font-size: 16px;
color: #333; color: #333;
margin-bottom: 8px; margin-bottom: 8px;
} }
.notification-time { .notification-time {
font-size: 12px; font-size: 12px;
color: #999; color: #999;
} }
.notification-actions { .notification-actions {
display: flex; display: flex;
gap: 8px; gap: 8px;
} }
.notification-item.unread .notification-title { .notification-item.unread .notification-title {
font-weight: 600; font-weight: 600;
} }
.notification-item.unread::before { .notification-item.unread::before {
content: ''; content: '';
display: inline-block; display: inline-block;
width: 8px; width: 8px;
@ -84,17 +83,17 @@
background-color: #1677ff; background-color: #1677ff;
border-radius: 50%; border-radius: 50%;
margin-right: 8px; margin-right: 8px;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.notification-actions { .notification-actions {
flex-direction: column; flex-direction: column;
} }
} }
</style> </style>
<script> <script>
layui.use(['element', 'layer'], function(){ layui.use(['element', 'layer'], function () {
var element = layui.element; var element = layui.element;
var layer = layui.layer; var layer = layui.layer;
@ -106,14 +105,14 @@ layui.use(['element', 'layer'], function(){
fetch('/index/user/getNotifications?type=' + type) fetch('/index/user/getNotifications?type=' + type)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if(data.code === 0) { if (data.code === 0) {
if(data.data.length === 0) { if (data.data.length === 0) {
container.innerHTML = '<div class="layui-none">暂无通知</div>'; container.innerHTML = '<div class="layui-none">暂无通知</div>';
return; return;
} }
var html = ''; var html = '';
data.data.forEach(function(notification) { data.data.forEach(function (notification) {
html += ` html += `
<div class="notification-item ${notification.is_read ? '' : 'unread'}" data-id="${notification.id}"> <div class="notification-item ${notification.is_read ? '' : 'unread'}" data-id="${notification.id}">
<div class="notification-content"> <div class="notification-content">
@ -129,26 +128,26 @@ layui.use(['element', 'layer'], function(){
}); });
container.innerHTML = html; container.innerHTML = html;
} else { } else {
layer.msg(data.msg || '加载失败', {icon: 2}); layer.msg(data.msg || '加载失败', { icon: 2 });
} }
}) })
.catch(error => { .catch(error => {
layer.msg('加载失败,请重试', {icon: 2}); layer.msg('加载失败,请重试', { icon: 2 });
}); });
} }
// 查看通知 // 查看通知
window.viewNotification = function(notificationId) { window.viewNotification = function (notificationId) {
fetch('/index/user/readNotification', { fetch('/index/user/readNotification', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({id: notificationId}) body: JSON.stringify({ id: notificationId })
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if(data.code === 0) { if (data.code === 0) {
layer.open({ layer.open({
type: 2, type: 2,
title: '通知详情', title: '通知详情',
@ -160,51 +159,51 @@ layui.use(['element', 'layer'], function(){
loadNotifications('unread'); loadNotifications('unread');
loadNotifications('read'); loadNotifications('read');
} else { } else {
layer.msg(data.msg || '操作失败', {icon: 2}); layer.msg(data.msg || '操作失败', { icon: 2 });
} }
}) })
.catch(error => { .catch(error => {
layer.msg('操作失败,请重试', {icon: 2}); layer.msg('操作失败,请重试', { icon: 2 });
}); });
} }
// 删除通知 // 删除通知
window.deleteNotification = function(notificationId) { window.deleteNotification = function (notificationId) {
layer.confirm('确定要删除这条通知吗?', { layer.confirm('确定要删除这条通知吗?', {
btn: ['确定','取消'] btn: ['确定', '取消']
}, function(){ }, function () {
fetch('/index/user/deleteNotification', { fetch('/index/user/deleteNotification', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({id: notificationId}) body: JSON.stringify({ id: notificationId })
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if(data.code === 0) { if (data.code === 0) {
layer.msg('删除成功', {icon: 1}); layer.msg('删除成功', { icon: 1 });
// 重新加载通知列表 // 重新加载通知列表
loadNotifications('all'); loadNotifications('all');
loadNotifications('unread'); loadNotifications('unread');
loadNotifications('read'); loadNotifications('read');
} else { } else {
layer.msg(data.msg || '删除失败', {icon: 2}); layer.msg(data.msg || '删除失败', { icon: 2 });
} }
}) })
.catch(error => { .catch(error => {
layer.msg('删除失败,请重试', {icon: 2}); layer.msg('删除失败,请重试', { icon: 2 });
}); });
}); });
} }
// 监听标签切换 // 监听标签切换
element.on('tab(notificationTabs)', function(data){ element.on('tab(notificationTabs)', function (data) {
var type = ['all', 'unread', 'read'][data.index]; var type = ['all', 'unread', 'read'][data.index];
loadNotifications(type); loadNotifications(type);
}); });
// 初始加载全部通知 // 初始加载全部通知
loadNotifications('all'); loadNotifications('all');
}); });
</script> </script>

View File

@ -12,9 +12,9 @@
<i class="icon">👤</i> <i class="icon">👤</i>
<span>个人资料</span> <span>个人资料</span>
</a> </a>
<a href="javascript:;" class="menu-item" data-target="profile-avatar"> <a href="javascript:;" class="menu-item" data-target="profile-wallet">
<i class="icon">🖼️</i> <i class="icon">💰</i>
<span>修改头像</span> <span>我的钱包</span>
</a> </a>
<a href="javascript:;" class="menu-item" data-target="profile-messages"> <a href="javascript:;" class="menu-item" data-target="profile-messages">
<i class="icon">✉️</i> <i class="icon">✉️</i>
@ -131,6 +131,10 @@
box-shadow: none; box-shadow: none;
} }
} }
i {
font-style: normal;
}
</style> </style>
<script> <script>

View File

@ -0,0 +1,86 @@
<div class="basic-info">
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">积分</li>
<li>云币</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<p>您当前的积分余额:<span id="points-balance">0</span></p>
</div>
<div class="layui-tab-item">
<p>您当前的云币余额:<span id="cloud-coins-balance">0</span></p>
<p>云币是真钱充值后获得的平台币。</p>
</div>
</div>
</div>
</div>
<script>
layui.use(['element'], function () {
var element = layui.element;
});
</script>
<script>
// JavaScript 部分,处理 tab 切换
const tabs = document.querySelectorAll('.tab');
const contents = document.querySelectorAll('.content-item');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
// 移除所有 tab 的 active 类
tabs.forEach(t => t.classList.remove('active'));
// 给当前点击的 tab 添加 active 类
tab.classList.add('active');
const target = tab.dataset.target;
// 隐藏所有内容项
contents.forEach(content => {
content.classList.remove('active');
if (content.id === target) {
content.classList.add('active');
}
});
});
});
</script>
<style>
/* 样式部分 */
.tab-container {
display: flex;
border-bottom: 1px solid #ccc;
}
.tab {
padding: 10px 20px;
cursor: pointer;
border: 1px solid transparent;
border-bottom: none;
}
.tab.active {
border-color: #ccc;
border-bottom: 1px solid white;
margin-bottom: -1px;
}
.tab-content {
padding: 20px;
border: 1px solid #ccc;
border-top: none;
}
.content-item {
display: none;
}
.content-item.active {
display: block;
}
.layui-unselect.layui-tab-bar {
display: none;
}
</style>

View File

@ -13,9 +13,9 @@
{include file="user/component/basic" /} {include file="user/component/basic" /}
</div> </div>
<!-- 修改头像 --> <!-- 我的钱包 -->
<div id="profile-avatar" class="content-section"> <div id="profile-wallet" class="content-section">
{include file="user/component/avatar" /} {include file="user/component/wallet" /}
</div> </div>
<!-- 我的消息 --> <!-- 我的消息 -->

View File

@ -28,7 +28,8 @@
"topthink/think-view": "^1.0", "topthink/think-view": "^1.0",
"topthink/think-captcha": "^3.0", "topthink/think-captcha": "^3.0",
"phpoffice/phpspreadsheet": "^1.25", "phpoffice/phpspreadsheet": "^1.25",
"phpmailer/phpmailer": "^6.9" "phpmailer/phpmailer": "^6.9",
"overtrue/wechat": "^5.36"
}, },
"require-dev": { "require-dev": {
"symfony/var-dumper": "^4.2", "symfony/var-dumper": "^4.2",
@ -43,7 +44,10 @@
} }
}, },
"config": { "config": {
"preferred-install": "dist" "preferred-install": "dist",
"allow-plugins": {
"easywechat-composer/easywechat-composer": true
}
}, },
"scripts": { "scripts": {
"post-autoload-dump": [ "post-autoload-dump": [

1882
composer.lock generated

File diff suppressed because it is too large Load Diff

5
config/wechat.php Normal file
View File

@ -0,0 +1,5 @@
return [
'app_id' => env('wechat.app_id'),
'secret' => env('wechat.secret'),
// 其他配置项...
];