2.1 版本文件
This commit is contained in:
+166
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
// 用户设置:修改用户名 / 邮箱 / 昵称
|
||||
require __DIR__ . '/includes/init.php';
|
||||
requireLogin('settings.php');
|
||||
$pageTitle = __('settings_page.title');
|
||||
|
||||
$stmt = db()->prepare('SELECT id, username, email, nickname, verified, is_admin, status, avatar FROM ' . tn('users') . ' WHERE id = ?');
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
$msg = '';
|
||||
$msgOk = false;
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
verifyCsrf();
|
||||
$u = trim($_POST['username'] ?? '');
|
||||
$em = trim($_POST['email'] ?? '');
|
||||
$nk = trim($_POST['nickname'] ?? '');
|
||||
|
||||
if (mb_strlen($u) < 3) $msg = __('settings_page.err_username_short');
|
||||
elseif (!filter_var($em, FILTER_VALIDATE_EMAIL)) $msg = __('settings_page.err_email_invalid');
|
||||
elseif ($nk !== '' && mb_strlen($nk) > 30) $msg = __('settings_page.err_nickname_long');
|
||||
|
||||
if ($msg === '') {
|
||||
$chk = db()->prepare('SELECT id FROM ' . tn('users') . ' WHERE username = ? AND id <> ?');
|
||||
$chk->execute([$u, $user['id']]);
|
||||
if ($chk->fetch()) {
|
||||
$msg = __('settings_page.err_username_taken');
|
||||
} else {
|
||||
$emailChanged = ($em !== $user['email']);
|
||||
db()->prepare('UPDATE ' . tn('users') . ' SET username = ?, email = ?, nickname = ? WHERE id = ?')
|
||||
->execute([$u, $em, $nk, $user['id']]);
|
||||
// 更换邮箱则取消验证状态,要求重新验证
|
||||
if ($emailChanged && !empty($user['verified'])) {
|
||||
db()->prepare('UPDATE ' . tn('users') . ' SET verified = 0 WHERE id = ?')
|
||||
->execute([$user['id']]);
|
||||
}
|
||||
// 重新读取最新资料
|
||||
$stmt->execute([$user['id']]);
|
||||
$user = $stmt->fetch();
|
||||
$msg = $emailChanged ? __('settings_page.saved_email_change') : __('settings_page.saved');
|
||||
$msgOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require 'includes/header.php';
|
||||
?>
|
||||
<section class="section">
|
||||
<h2 class="sec-title"><i class="fas fa-cog"></i> <?= __('settings_page.title') ?></h2>
|
||||
|
||||
<?php if ($msg): ?>
|
||||
<p class="<?= $msgOk ? 'banner-ok' : 'form-err' ?>"><?= h($msg) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="" class="grid-form settings-form">
|
||||
<?= csrfField() ?>
|
||||
|
||||
<!-- 头像上传 -->
|
||||
<div class="span2" style="margin-bottom:18px">
|
||||
<h3 style="color:var(--primary);font-size:1.05rem;margin-bottom:12px"><i class="fas fa-camera"></i> <?= __('settings_page.avatar_section') ?></h3>
|
||||
<div style="display:flex;align-items:center;gap:16px;flex-wrap:wrap">
|
||||
<div id="avatarPreviewWrap" style="width:80px;height:80px;border-radius:50%;overflow:hidden;background:var(--primary-container);display:flex;align-items:center;justify-content:center;border:3px solid var(--outline);flex-shrink:0">
|
||||
<?php if (!empty($user['avatar'])): ?>
|
||||
<img src="<?= h($user['avatar']) ?>" alt="" style="width:100%;height:100%;object-fit:cover">
|
||||
<?php else: ?>
|
||||
<span style="font-size:1.8rem;font-weight:700;color:var(--on-primary-container)"><?= h(avatarText($user['nickname'] ?: $user['username'])) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div>
|
||||
<label for="avatarInput" class="btn btn-sm btn-ghost" style="cursor:pointer;display:inline-flex;align-items:center;gap:6px">
|
||||
<i class="fas fa-upload"></i> <?= __('settings_page.select_image') ?>
|
||||
</label>
|
||||
<input type="file" id="avatarInput" accept="image/jpeg,image/png,image/webp,image/gif" style="display:none">
|
||||
<p style="font-size:.8rem;color:var(--muted);margin-top:4px"><?= __('settings_page.avatar_hint') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<p id="avatarMsg" style="font-size:.88rem;margin-top:6px"></p>
|
||||
</div>
|
||||
|
||||
<label><?= __('auth.username') ?><input type="text" name="username" value="<?= h($user['username']) ?>" required></label>
|
||||
<label><?= __('auth.email') ?><input type="email" name="email" value="<?= h($user['email']) ?>" required></label>
|
||||
<label class="span2"><?= __('user.nickname') ?><input type="text" name="nickname" value="<?= h($user['nickname']) ?>" placeholder="<?= __('settings_page.nickname_placeholder') ?>" maxlength="30"></label>
|
||||
<div class="form-actions span2">
|
||||
<button type="submit" class="btn btn-primary"><?= __('settings_page.save_btn') ?></button>
|
||||
<a href="myorders.php" class="btn btn-ghost"><?= __('settings_page.back_orders') ?></a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="panel verify-panel">
|
||||
<h3><i class="fas fa-envelope-circle-check"></i> <?= __('settings_page.verify_section') ?></h3>
|
||||
<?php if (!empty($user['verified'])): ?>
|
||||
<p class="ok-line"><i class="fas fa-circle-check"></i> <?= __('settings_page.verify_done') ?></p>
|
||||
<?php else: ?>
|
||||
<p class="warn-line"><i class="fas fa-triangle-exclamation"></i> <?= str_replace('{link}', '<a href="verify.php?resend=1">' . __('settings_page.verify_send_link') . '</a>', __('settings_page.verify_not_done')) ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
// 头像上传(AJAX)
|
||||
(function () {
|
||||
var input = document.getElementById('avatarInput');
|
||||
var msg = document.getElementById('avatarMsg');
|
||||
var wrap = document.getElementById('avatarPreviewWrap');
|
||||
if (!input) return;
|
||||
|
||||
input.addEventListener('change', function () {
|
||||
if (!input.files || !input.files[0]) return;
|
||||
var file = input.files[0];
|
||||
|
||||
// 前端预校验
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
msg.textContent = '<?= __('settings_page.img_too_big') ?>';
|
||||
msg.style.color = 'var(--danger)';
|
||||
return;
|
||||
}
|
||||
|
||||
// 即时预览
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
wrap.innerHTML = '<img src="' + e.target.result + '" alt="" style="width:100%;height:100%;object-fit:cover;border-radius:50%">';
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
// 上传
|
||||
msg.textContent = '<?= __('settings_page.uploading') ?>';
|
||||
msg.style.color = 'var(--muted)';
|
||||
var fd = new FormData();
|
||||
fd.append('avatar', file);
|
||||
fd.append('csrf_token', Fnw.csrf());
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'avatar_upload.php', true);
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
try { var res = JSON.parse(xhr.responseText); } catch (e) { res = { ok: false, msg: '<?= __('settings_page.response_err') ?>' }; }
|
||||
if (res.ok) {
|
||||
msg.textContent = res.msg || '<?= __('settings_page.upload_ok') ?>';
|
||||
msg.style.color = 'var(--ok)';
|
||||
updateAvatars(res.data.url);
|
||||
} else {
|
||||
msg.textContent = res.msg || '<?= __('settings_page.upload_fail') ?>';
|
||||
msg.style.color = 'var(--danger)';
|
||||
}
|
||||
} else {
|
||||
msg.textContent = '<?= str_replace('{code}', "' + xhr.status + '", __('settings_page.network_err')) ?>';
|
||||
msg.style.color = 'var(--danger)';
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
msg.textContent = '<?= __('settings_page.network_retry') ?>';
|
||||
msg.style.color = 'var(--danger)';
|
||||
};
|
||||
xhr.send(fd);
|
||||
});
|
||||
|
||||
function updateAvatars(url) {
|
||||
document.querySelectorAll('.avatar, .uc-avatar').forEach(function (el) {
|
||||
el.innerHTML = '<img src="' + url + '" alt="" style="width:100%;height:100%;object-fit:cover;border-radius:50%">';
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<?php require 'includes/footer.php'; ?>
|
||||
Reference in New Issue
Block a user