Files
----/前端源码/uni-app/components/screens/ProfileUserInfo.vue

249 lines
5.2 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="userinfo-screen">
<view class="userinfo-bg"></view>
<view class="status-bar-placeholder"></view>
<view class="userinfo-header">
<view class="userinfo-back-btn" @click="handleBack">
<text class="userinfo-back-icon"></text>
</view>
<text class="userinfo-title">我的信息</text>
<view class="userinfo-header-placeholder"></view>
</view>
<scroll-view scroll-y class="userinfo-content">
<view class="userinfo-inner">
<view class="userinfo-section">
<text class="userinfo-label">用户名</text>
<input
v-model="username"
class="userinfo-input"
type="text"
maxlength="32"
placeholder="请输入用户名"
/>
</view>
<view class="userinfo-section userinfo-section-mt">
<text class="userinfo-label">手机号</text>
<input
v-model="mobile"
class="userinfo-input"
type="tel"
maxlength="11"
placeholder="请输入手机号"
/>
</view>
<view class="userinfo-save" @click="handleSave">
<text class="userinfo-save-text">{{ saving ? "保存中…" : "保存" }}</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getUserInfo, setUserInfo } from "@/utils/auth";
import { userApi } from "@/api";
declare const uni: any;
const emit = defineEmits<{
back: [];
}>();
const username = ref("");
const mobile = ref("");
const saving = ref(false);
const isValidPhone = (phone: string) => /^1[3-9]\d{9}$/.test(phone);
const loadFromStorage = () => {
const info = getUserInfo();
if (!info || typeof info !== "object") return;
const u = info as Record<string, unknown>;
username.value = String(
u.username ?? u.name ?? ""
).trim();
mobile.value = String(u.mobile ?? u.phone ?? "").trim();
};
onMounted(() => {
loadFromStorage();
});
const handleBack = () => {
emit("back");
};
const handleSave = async () => {
const name = username.value.trim();
const tel = mobile.value.trim();
if (!name) {
uni.showToast({ title: "请输入用户名", icon: "none" });
return;
}
if (!tel) {
uni.showToast({ title: "请输入手机号", icon: "none" });
return;
}
if (!isValidPhone(tel)) {
uni.showToast({ title: "请输入正确的手机号", icon: "none" });
return;
}
if (saving.value) return;
saving.value = true;
try {
await userApi.updateCurrentUserUsernameMobile({
username: name,
mobile: tel,
});
// 仅把表单结果合并进已有 userInfo不把接口 data 整包写入,避免覆盖/清空头像、id 等字段
const prev = getUserInfo();
if (!prev || typeof prev !== "object") {
uni.showToast({ title: "登录状态异常,请重新登录", icon: "none" });
return;
}
setUserInfo({
...prev,
nickname: name,
name: name,
username: name,
mobile: tel,
phone: tel,
});
uni.showToast({ title: "已保存", icon: "success" });
} catch (e: any) {
uni.showToast({
title: e?.msg || e?.message || "保存失败,请稍后重试",
icon: "none",
});
} finally {
saving.value = false;
}
};
</script>
<style scoped>
.userinfo-screen {
height: 100%;
display: flex;
flex-direction: column;
background-color: #f0efe9;
position: relative;
}
.status-bar-placeholder {
height: var(--status-bar-height, 0);
width: 100%;
flex-shrink: 0;
}
.userinfo-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
opacity: 0.3;
background-image: url("https://www.transparenttextures.com/patterns/rice-paper.png");
}
.userinfo-header {
position: relative;
z-index: 10;
height: 88rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
border-bottom: 1rpx solid #dcd3c9;
background-color: rgba(253, 251, 247, 0.8);
backdrop-filter: blur(10rpx);
}
.userinfo-back-btn {
width: 64rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: -16rpx;
}
.userinfo-back-icon {
font-size: 48rpx;
color: #5a5a5a;
font-weight: 300;
}
.userinfo-title {
font-size: 32rpx;
font-weight: 700;
color: #2c2c2c;
letter-spacing: 0.2em;
}
.userinfo-header-placeholder {
width: 64rpx;
}
.userinfo-content {
flex: 1;
height: 0;
position: relative;
z-index: 10;
}
.userinfo-inner {
padding: 32rpx;
}
.userinfo-section {
background-color: #fffdf9;
border-radius: 24rpx;
border: 1rpx solid #e5e5e5;
padding: 24rpx 32rpx;
}
.userinfo-section-mt {
margin-top: 24rpx;
}
.userinfo-label {
display: block;
font-size: 24rpx;
color: #888;
margin-bottom: 16rpx;
}
.userinfo-input {
width: 100%;
font-size: 30rpx;
color: #2c2c2c;
border: none;
background: transparent;
padding: 0;
}
.userinfo-save {
margin-top: 48rpx;
height: 88rpx;
border-radius: 44rpx;
background: linear-gradient(135deg, #8b7355, #6b5344);
display: flex;
align-items: center;
justify-content: center;
}
.userinfo-save-text {
font-size: 30rpx;
color: #fffdf9;
font-weight: 600;
letter-spacing: 0.15em;
}
</style>