hookehuyr

feat(家庭功能): 优化家庭创建和编辑页面的封面图处理

- 添加默认家庭封面图资源
- 统一家庭名称输入限制为10个字符
- 优化封面图上传和预览逻辑,支持默认封面显示
- 调整上传图片大小限制为5MB
- 为输入框添加cursorSpacing属性改善用户体验
<svg width="400" height="200" viewBox="0 0 400 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- 背景渐变 -->
<defs>
<linearGradient id="bg-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#E3F2FD;stop-opacity:1" />
<stop offset="100%" style="stop-color:#BBDEFB;stop-opacity:1" />
</linearGradient>
</defs>
<!-- 背景 -->
<rect width="400" height="200" fill="url(#bg-gradient)"/>
<!-- 房子图标 -->
<g transform="translate(150, 60)">
<!-- 房子主体 -->
<rect x="20" y="40" width="60" height="50" fill="#FFF3E0" stroke="#FF9800" stroke-width="2" rx="4"/>
<!-- 屋顶 -->
<polygon points="10,45 50,15 90,45" fill="#FF5722" stroke="#D84315" stroke-width="2"/>
<!-- 门 -->
<rect x="35" y="65" width="15" height="25" fill="#8D6E63" rx="2"/>
<circle cx="46" cy="77" r="1.5" fill="#FFF"/>
<!-- 窗户 -->
<rect x="25" y="50" width="12" height="10" fill="#81D4FA" stroke="#0277BD" stroke-width="1" rx="1"/>
<rect x="63" y="50" width="12" height="10" fill="#81D4FA" stroke="#0277BD" stroke-width="1" rx="1"/>
<!-- 窗户十字 -->
<line x1="31" y1="50" x2="31" y2="60" stroke="#0277BD" stroke-width="0.5"/>
<line x1="25" y1="55" x2="37" y2="55" stroke="#0277BD" stroke-width="0.5"/>
<line x1="69" y1="50" x2="69" y2="60" stroke="#0277BD" stroke-width="0.5"/>
<line x1="63" y1="55" x2="75" y2="55" stroke="#0277BD" stroke-width="0.5"/>
</g>
<!-- 文字 -->
<text x="200" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#666" font-weight="500">温馨家庭</text>
<text x="200" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#999">点击上传家庭封面图</text>
</svg>
\ No newline at end of file
<!--
* @Date: 2025-08-27 17:44:53
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-01 11:37:51
* @LastEditTime: 2025-09-02 11:27:00
* @FilePath: /lls_program/src/pages/CreateFamily/index.vue
* @Description: 文件描述
-->
......@@ -21,9 +21,9 @@
type="text"
v-model="familyName"
class="w-full text-gray-600 focus:outline-none"
placeholder="请输入家庭名称(最多20个字)"
placeholder="请输入家庭名称(最多10个字)"
@blur="validateFamilyName"
maxlength="20"
maxlength="10"
/>
<view v-if="familyNameError" class="text-red-500 text-sm mt-2">{{ familyNameError }}</view>
</view>
......@@ -82,6 +82,7 @@
@blur="handleBlur(index)"
class="w-full h-full bg-transparent text-center"
style="font-size: 38rpx;"
:cursorSpacing="100"
/>
</view>
</view>
......@@ -103,36 +104,34 @@
<view class="block text-lg font-medium mb-2">
家庭封面图(选填)
</view>
<!-- 已上传封面显示 -->
<view v-if="familyAvatar" class="mb-4">
<!-- 封面显示区域 -->
<view class="mb-4">
<view class="relative">
<image
:src="familyAvatar"
:src="familyAvatar || defaultFamilyCover"
class="w-full h-48 rounded-lg object-cover"
mode="aspectFill"
@tap="previewAvatar"
/>
<view
v-if="familyAvatar"
@click="deleteAvatar"
class="absolute -top-2 -right-2 w-6 h-6 bg-red-500 rounded-full flex items-center justify-center"
>
<view class="text-white text-sm">×</view>
</view>
<view
@click="chooseImage"
class="absolute bottom-2 right-2 px-3 py-1 bg-black bg-opacity-50 text-white text-sm rounded-full flex items-center"
>
<Photograph size="14" class="mr-1" />
{{ familyAvatar ? '更换' : '上传' }}
</view>
</view>
</view>
<!-- 上传区域 -->
<view
v-if="!familyAvatar"
class="border border-dashed border-gray-200 rounded-lg p-12 flex flex-col items-center justify-center h-48"
@click="chooseImage"
>
<view class="text-gray-400 mb-4">
<Photograph size="32" />
</view>
<view class="text-center text-gray-400 text-lg">点击上传封面图</view>
<view class="text-center text-gray-400 text-sm mt-2">
支持图片格式(jpg、png)最大10MB
</view>
<!-- 上传提示 -->
<view class="text-center text-gray-400 text-sm">
支持图片格式(jpg、png)最大5MB
</view>
</view>
</view>
......@@ -178,6 +177,7 @@ import Taro from '@tarojs/taro';
import { Edit, Tips, Photograph, Right } from '@nutui/icons-vue-taro';
// import AppHeader from '../../components/AppHeader.vue';
import BASE_URL from '@/utils/config';
import defaultFamilyCoverSvg from '@/assets/images/default-family-cover.png';
const familyName = ref('');
const familyIntro = ref('');
......@@ -214,6 +214,7 @@ const districtColumns = ref([
const familyAvatar = ref('');
const focusedIndex = ref(-1);
const inputRefs = ref([]);
const defaultFamilyCover = ref(defaultFamilyCoverSvg);
const isFormValid = computed(() => {
return (
......@@ -298,14 +299,14 @@ const chooseImage = () => {
success: function (res) {
const tempFilePath = res.tempFilePaths[0];
// 检查文件大小(10MB = 10 * 1024 * 1024 bytes)
Taro.getFileInfo({
filePath: tempFilePath,
success: function (fileInfo) {
if (fileInfo.size > 10 * 1024 * 1024) {
showToast('图片大小不能超过10MB', 'none');
return;
}
// 检查文件大小(5MB = 5 * 1024 * 1024 bytes)
Taro.getFileInfo({
filePath: tempFilePath,
success: function (fileInfo) {
if (fileInfo.size > 5 * 1024 * 1024) {
showToast('图片大小不能超过5MB', 'none');
return;
}
uploadImage(tempFilePath);
},
fail: function () {
......@@ -364,11 +365,8 @@ const uploadImage = (filePath) => {
* 预览头像
*/
const previewAvatar = () => {
if (!familyAvatar.value) {
showToast('暂无图片可预览', 'error');
return;
}
previewImages.value = [{ src: familyAvatar.value }];
const imageToPreview = familyAvatar.value || defaultFamilyCover.value;
previewImages.value = [{ src: imageToPreview }];
previewIndex.value = 0;
previewVisible.value = true;
};
......@@ -393,8 +391,8 @@ const closePreview = () => {
*/
const validateFamilyName = () => {
familyNameError.value = '';
if (familyName.value.length > 20) {
familyNameError.value = '家庭名称不能超过20个字';
if (familyName.value.length > 10) {
familyNameError.value = '家庭名称不能超过10个字';
}
};
......@@ -421,10 +419,10 @@ const validateForm = () => {
return false;
}
if (familyName.value.length > 20) {
if (familyName.value.length > 10) {
Taro.showModal({
title: '提示',
content: '家庭名称不能超过20个字,请重新输入',
content: '家庭名称不能超过10个字,请重新输入',
showCancel: false
});
return false;
......
<!--
* @Date: 2025-08-27 17:44:53
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-01 11:39:03
* @LastEditTime: 2025-09-02 11:23:27
* @FilePath: /lls_program/src/pages/EditFamily/index.vue
* @Description: 文件描述
-->
......@@ -21,9 +21,9 @@
type="text"
v-model="familyName"
class="w-full text-gray-600 focus:outline-none"
placeholder="请输入家庭名称(最多20个字)"
placeholder="请输入家庭名称(最多10个字)"
@blur="validateFamilyName"
maxlength="20"
maxlength="10"
/>
<view v-if="familyNameError" class="text-red-500 text-sm mt-2">{{ familyNameError }}</view>
</view>
......@@ -103,36 +103,34 @@
<view class="block text-lg font-medium mb-2">
家庭封面图(选填)
</view>
<!-- 已上传封面显示 -->
<view v-if="familyAvatar" class="mb-4">
<!-- 封面显示区域 -->
<view class="mb-4">
<view class="relative">
<image
:src="familyAvatar"
:src="familyAvatar || defaultFamilyCover"
class="w-full h-48 rounded-lg object-cover"
mode="aspectFill"
@tap="previewAvatar"
/>
<view
v-if="familyAvatar"
@click="deleteAvatar"
class="absolute -top-2 -right-2 w-6 h-6 bg-red-500 rounded-full flex items-center justify-center"
>
<view class="text-white text-sm">×</view>
</view>
<view
@click="chooseImage"
class="absolute bottom-2 right-2 px-3 py-1 bg-black bg-opacity-50 text-white text-sm rounded-full flex items-center"
>
<Photograph size="14" class="mr-1" />
{{ familyAvatar ? '更换' : '上传' }}
</view>
</view>
</view>
<!-- 上传区域 -->
<view
v-if="!familyAvatar"
class="border border-dashed border-gray-200 rounded-lg p-12 flex flex-col items-center justify-center h-48"
@click="chooseImage"
>
<view class="text-gray-400 mb-4">
<Photograph size="32" />
</view>
<view class="text-center text-gray-400 text-lg">点击上传封面图</view>
<view class="text-center text-gray-400 text-sm mt-2">
支持图片格式(jpg、png)最大10MB
</view>
<!-- 上传提示 -->
<view class="text-center text-gray-400 text-sm">
支持图片格式(jpg、png)最大5MB
</view>
</view>
</view>
......@@ -175,6 +173,7 @@ import Taro from '@tarojs/taro';
import { Edit, Tips, Photograph, Right } from '@nutui/icons-vue-taro';
// import AppHeader from '../../components/AppHeader.vue';
import BASE_URL from '@/utils/config';
import defaultFamilyCoverSvg from '@/assets/images/default-family-cover.png';
const familyName = ref('');
const familyIntro = ref('');
......@@ -210,6 +209,7 @@ const districtColumns = ref([
]);
const familyAvatar = ref('');
const focusedIndex = ref(-1);
const defaultFamilyCover = ref(defaultFamilyCoverSvg);
// 图片预览相关
const previewVisible = ref(false);
......@@ -281,12 +281,12 @@ const chooseImage = () => {
success: function (res) {
const tempFilePath = res.tempFilePaths[0];
// 检查文件大小(10MB = 10 * 1024 * 1024 bytes)
// 检查文件大小(5MB = 5 * 1024 * 1024 bytes)
Taro.getFileInfo({
filePath: tempFilePath,
success: function (fileInfo) {
if (fileInfo.size > 10 * 1024 * 1024) {
showToast('图片大小不能超过10MB', 'none');
if (fileInfo.size > 5 * 1024 * 1024) {
showToast('图片大小不能超过5MB', 'none');
return;
}
uploadImage(tempFilePath);
......@@ -347,11 +347,8 @@ const uploadImage = (filePath) => {
* 预览头像
*/
const previewAvatar = () => {
if (!familyAvatar.value) {
showToast('暂无图片可预览', 'none');
return;
}
previewImages.value = [{ src: familyAvatar.value }];
const imageToPreview = familyAvatar.value || defaultFamilyCover.value;
previewImages.value = [{ src: imageToPreview }];
previewIndex.value = 0;
previewVisible.value = true;
};
......@@ -376,8 +373,8 @@ const closePreview = () => {
*/
const validateFamilyName = () => {
familyNameError.value = '';
if (familyName.value.length > 20) {
familyNameError.value = '家庭名称不能超过20个字';
if (familyName.value.length > 10) {
familyNameError.value = '家庭名称不能超过10个字';
}
};
......@@ -404,10 +401,10 @@ const validateForm = () => {
return false;
}
if (familyName.value.length > 20) {
if (familyName.value.length > 10) {
Taro.showModal({
title: '提示',
content: '家庭名称不能超过20个字,请重新输入',
content: '家庭名称不能超过10个字,请重新输入',
showCancel: false
});
return false;
......
......@@ -28,6 +28,7 @@
@focus="focusedIndex = index"
@blur="handleBlur(index)"
class="motto-input"
:cursorSpacing="100"
/>
</view>
</view>
......