hookehuyr

feat(图片上传): 重构图片上传逻辑并添加审核结果处理

- 移除重复的审核不通过提示代码,统一处理上传失败情况
- 为上传成功的图片添加审核结果字段(qiniu_audit)
- 在多个页面添加头像上传须知对话框
- 使用主题颜色常量统一按钮样式
......@@ -5,7 +5,10 @@
<view class="w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center mb-2 overflow-hidden">
<image :src="formData.avatar_url || defaultAvatar" class="w-full h-full" mode="aspectFill" />
</view>
<text class="text-gray-500 text-sm">上传头像</text>
<view class="flex items-center justify-center">
<text class="text-gray-500 text-sm mr-1">上传头像</text>
<Ask size="15" color="#888" @tap.stop="showAvatarTipDialog = true" />
</view>
</view>
<!-- Form -->
......@@ -102,13 +105,38 @@
</nut-popup>
<nut-image-preview v-model:show="previewVisible" :images="previewImages" />
<!-- 头像上传须知对话框 -->
<nut-dialog
v-model:visible="showAvatarTipDialog"
title="头像上传须知"
>
<template #default>
<view class="text-gray-700 leading-loose text-sm text-left break-words">
<view class="mb-2">1. 头像大小不能超过5MB</view>
<view class="mb-2">2. 头像格式为jpg、jpeg、png</view>
<view>3. 头像未通过审核,可能原因:色情 / 暴恐内容、敏感人物、违规广告</view>
</view>
</template>
<template #footer>
<nut-button
@click="showAvatarTipDialog = false"
type="primary"
size="normal"
:color="THEME_COLORS.PRIMARY"
block
>
我知道了
</nut-button>
</template>
</nut-dialog>
</view>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
import Taro from '@tarojs/taro';
import { Date as DateIcon, Right } from '@nutui/icons-vue-taro';
import { Date as DateIcon, Right, Ask } from '@nutui/icons-vue-taro';
import BASE_URL from '@/utils/config';
// 默认头像
const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
......@@ -128,6 +156,7 @@ const formData = reactive({
wheelchair_text: '',
gender: null, // 0 for 女, 1 for 男
gender_text: '',
qiniu_audit: '', // 图片审核信息
});
/**
......@@ -137,6 +166,12 @@ const isFormValid = computed(() => {
return formData.nickname && formData.birth_date && formData.wheelchair_needed !== null && formData.gender !== null;
});
// --- Avatar Tip Dialog ---
/**
* @description 控制头像上传须知对话框显示
*/
const showAvatarTipDialog = ref(false);
// --- Date Picker ---
/**
* @description 控制日期选择器显示
......@@ -249,15 +284,29 @@ const changeAvatar = () => {
Taro.showLoading({ title: '上传中...' });
Taro.uploadFile({
url: BASE_URL + '/admin/?m=srv&a=upload',
url: BASE_URL + '/admin/?m=srv&a=upload&image_audit=1',
filePath: tempFile.path,
name: 'file',
success: (uploadRes) => {
Taro.hideLoading();
const data = JSON.parse(uploadRes.data);
if (data.code == 0) {
formData.avatar_url = data.data.src;
Taro.showToast({ title: '上传成功', icon: 'success' });
// 检查是否为审核不通过
if (data.data.audit_code == -1) {
Taro.showModal({
title: '温馨提示',
content: data.msg,
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
});
} else {
formData.avatar_url = data.data.src;
formData.qiniu_audit = data.data.audit_result;
Taro.showToast({ title: '上传成功', icon: 'success' });
}
} else {
Taro.showToast({ title: data.msg || '上传失败', icon: 'none' });
}
......
<!--
* @Date: 2025-08-27 17:44:53
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-09 11:38:58
* @LastEditTime: 2025-09-11 11:06:38
* @FilePath: /lls_program/src/pages/CreateFamily/index.vue
* @Description: 文件描述
-->
......@@ -191,6 +191,9 @@ const familyMottoPlaceholder = ref(['孝', '敬', '和', '睦']);
const familyNameError = ref('');
const familyIntroError = ref('');
// 图片审核信息
const familyAvatarAudit = ref('');
// 区域选择器相关
const showDistrictPicker = ref(false);
const districtValue = ref([]);
......@@ -337,22 +340,10 @@ const uploadImage = (filePath) => {
success: () => {
if (upload_data.code == 0 && upload_data.data) {
familyAvatar.value = upload_data.data.src;
familyAvatarAudit.value = upload_data.data.audit_result;
showToast('上传成功', 'success');
} else {
// 检查是否为审核不通过
if (upload_data.code == 0 && !upload_data.data && upload_data.msg && upload_data.msg.includes('审核不通过')) {
Taro.showModal({
title: '温馨提示',
content: '您上传的内容未通过审核',
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
});
} else {
showToast('服务器错误,稍后重试!', 'none');
}
showToast('服务器错误,稍后重试!', 'none');
}
},
});
......@@ -484,6 +475,7 @@ const handleCreateFamily = async () => {
county: selectedDistrict.value,
passphrase: familyMotto.value.join(''),
avatar_url: familyAvatar.value,
qiniu_audit: familyAvatarAudit.value,
});
Taro.hideLoading();
......
<!--
* @Date: 2025-08-27 17:44:53
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-09 11:39:20
* @LastEditTime: 2025-09-11 10:41:23
* @FilePath: /lls_program/src/pages/EditFamily/index.vue
* @Description: 文件描述
-->
......@@ -190,6 +190,9 @@ const familyMottoPlaceholder = ref(['孝', '敬', '和', '睦']);
const familyNameError = ref('');
const familyIntroError = ref('');
// 图片审核信息
const familyAvatarAudit = ref('');
// 区域选择器相关
const showDistrictPicker = ref(false);
const districtValue = ref([]);
......@@ -325,22 +328,10 @@ const uploadImage = (filePath) => {
success: () => {
if (upload_data.code === 0 && upload_data.data) {
familyAvatar.value = upload_data.data.src;
familyAvatarAudit.value = upload_data.data.audit_result;
showToast('上传成功', 'success');
} else {
// 检查是否为审核不通过
if (upload_data.code === 0 && !upload_data.data && upload_data.msg && upload_data.msg.includes('审核不通过')) {
Taro.showModal({
title: '温馨提示',
content: '您上传的内容未通过审核',
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
});
} else {
showToast('服务器错误,稍后重试!', 'none');
}
showToast('服务器错误,稍后重试!', 'none');
}
},
});
......@@ -467,6 +458,7 @@ const handleSaveFamily = async () => {
county: selectedDistrict.value,
passphrase: familyMotto.value.join(''),
avatar_url: familyAvatar.value,
qiniu_audit: familyAvatarAudit.value,
});
if (code) {
showToast('保存成功', 'success');
......
<template>
<view class="min-h-screen bg-gray-50 p-5 pb-24">
<!-- Avatar -->
<view class="flex flex-col items-center py-8" @click="changeAvatar">
<view class="flex flex-col items-center py-8" @tap="changeAvatar">
<view class="w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center mb-2 overflow-hidden">
<image :src="formData.avatar_url || defaultAvatar" class="w-full h-full" mode="aspectFill" />
</view>
<text class="text-gray-500 text-sm">上传头像</text>
<view class="flex items-center justify-center">
<text class="text-gray-500 text-sm mr-1">上传头像</text>
<Ask size="15" color="#888" @tap.stop="showAvatarTipDialog = true" />
</view>
</view>
<!-- Form -->
......@@ -102,13 +105,38 @@
</nut-popup>
<nut-image-preview v-model:show="previewVisible" :images="previewImages" />
<!-- 头像上传须知对话框 -->
<nut-dialog
v-model:visible="showAvatarTipDialog"
title="头像上传须知"
>
<template #default>
<view class="text-gray-700 leading-loose text-sm text-left break-words">
<view class="mb-2">1. 头像大小不能超过5MB</view>
<view class="mb-2">2. 头像格式为jpg、jpeg、png</view>
<view>3. 头像未通过审核,可能原因:色情 / 暴恐内容、敏感人物、违规广告</view>
</view>
</template>
<template #footer>
<nut-button
@click="showAvatarTipDialog = false"
type="primary"
size="normal"
:color="THEME_COLORS.PRIMARY"
block
>
我知道了
</nut-button>
</template>
</nut-dialog>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import Taro from '@tarojs/taro';
import { My, Date as DateIcon, Right } from '@nutui/icons-vue-taro';
import { My, Date as DateIcon, Right, Ask } from '@nutui/icons-vue-taro';
import BASE_URL from '@/utils/config';
// 默认头像
const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
......@@ -128,8 +156,15 @@ const formData = reactive({
wheelchair_text: '',
gender: null, // 0 for 女, 1 for 男
gender_text: '',
qiniu_audit: '', // 图片审核信息
});
// --- Avatar Tip Dialog ---
/**
* @description 控制头像上传须知对话框显示
*/
const showAvatarTipDialog = ref(false);
// --- Date Picker ---
/**
* @description 控制日期选择器显示
......@@ -242,15 +277,29 @@ const changeAvatar = () => {
Taro.showLoading({ title: '上传中...' });
Taro.uploadFile({
url: BASE_URL + '/admin/?m=srv&a=upload',
url: BASE_URL + '/admin/?m=srv&a=upload&image_audit=1',
filePath: tempFile.path,
name: 'file',
success: (uploadRes) => {
Taro.hideLoading();
const data = JSON.parse(uploadRes.data);
if (data.code === 0) {
formData.avatar_url = data.data.src;
Taro.showToast({ title: '上传成功', icon: 'success' });
// 检查是否为审核不通过
if (data.data.audit_code == -1) {
Taro.showModal({
title: '温馨提示',
content: data.msg,
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
});
} else {
formData.avatar_url = data.data.src;
formData.qiniu_audit = data.data.audit_result;
Taro.showToast({ title: '上传成功', icon: 'success' });
}
} else {
Taro.showToast({ title: data.msg || '上传失败', icon: 'none' });
}
......
......@@ -195,24 +195,12 @@ const uploadImage = (filePath) => {
if (upload_data.code === 0 && upload_data.data) {
screenshots.value.push({
url: upload_data.data.src,
localPath: filePath
localPath: filePath,
qiniu_audit: upload_data.data.audit_result,
});
showToast('上传成功', 'success');
} else {
// 检查是否为审核不通过
if (upload_data.code === 0 && !upload_data.data && upload_data.msg && upload_data.msg.includes('审核不通过')) {
Taro.showModal({
title: '温馨提示',
content: '您上传的内容未通过审核',
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
});
} else {
showToast('服务器错误,稍后重试!', 'error');
}
showToast('服务器错误,稍后重试!', 'error');
}
},
});
......
......@@ -590,7 +590,7 @@ const uploadBackgroundImage = (filePath) => {
Taro.showLoading({ title: '上传中...' })
Taro.uploadFile({
url: BASE_URL + '/admin/?m=srv&a=upload&image_audit=1',
url: BASE_URL + '/admin/?m=srv&a=upload',
filePath,
name: 'file',
success: (uploadRes) => {
......@@ -601,20 +601,7 @@ const uploadBackgroundImage = (filePath) => {
backgroundImages.value[currentPosterIndex.value] = data.data.src
Taro.showToast({ title: '上传成功', icon: 'success' })
} else {
// 检查是否为审核不通过
if (data.code === 0 && !data.data && data.msg && data.msg.includes('审核不通过')) {
Taro.showModal({
title: '温馨提示',
content: '您上传的内容未通过审核',
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
})
} else {
Taro.showToast({ title: data.msg || '上传失败', icon: 'none' })
}
Taro.showToast({ title: data.msg || '上传失败', icon: 'none' })
}
},
fail: () => {
......
......@@ -220,7 +220,8 @@ const chooseMedia = () => {
uploadedFile.value = {
type: 'image',
url: file.tempFilePath,
serverUrl: serverUrl,
serverUrl: serverUrl.src,
qiniu_audit: serverUrl.qiniu_audit,
size: file.size,
name: `image_${Date.now()}.jpg`
};
......@@ -228,7 +229,8 @@ const chooseMedia = () => {
uploadedFile.value = {
type: 'video',
url: file.tempFilePath,
serverUrl: serverUrl,
serverUrl: serverUrl.src,
qiniu_audit: serverUrl.qiniu_audit,
thumbnail: file.thumbTempFilePath,
duration: Math.floor(file.duration),
size: file.size,
......@@ -388,20 +390,8 @@ const uploadFileToServer = (filePath) => {
try {
const upload_data = JSON.parse(res.data);
if (upload_data.code === 0 && upload_data.data) {
resolve(upload_data.data.src);
resolve({ src: upload_data.data.src, qiniu_audit: upload_data.data.audit_result });
} else {
// 检查是否为审核不通过
if (upload_data.code === 0 && !upload_data.data && upload_data.msg && upload_data.msg.includes('审核不通过')) {
Taro.showModal({
title: '温馨提示',
content: '您上传的内容未通过审核',
showCancel: false
}).then(res => {
if (res.confirm) {
// 点击了确认按钮
}
});
}
reject(new Error(upload_data.msg || '服务器错误'));
}
} catch (error) {
......@@ -450,7 +440,8 @@ const saveMedia = async () => {
// url: uploadedFile.value.serverUrl,
// size: uploadedFile.value.size,
// name: uploadedFile.value.name,
// duration: uploadedFile.value.duration // 仅视频有此字段
// duration: uploadedFile.value.duration, // 仅视频有此字段
// qiniu_audit: uploadedFile.value.qiniu_audit,
// });
// 模拟接口调用
......
<!--
* @Date: 2025-08-27 17:43:45
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-06 21:59:10
* @LastEditTime: 2025-09-11 11:34:37
* @FilePath: /lls_program/src/pages/Welcome/index.vue
* @Description: 文件描述
-->
......@@ -96,7 +96,7 @@
@click="onPrivacyConfirm"
type="primary"
size="normal"
color="#007AFF"
:color="THEME_COLORS.PRIMARY"
block
>
同意搜集
......@@ -123,7 +123,7 @@
@click="onAgeConfirm"
type="primary"
size="normal"
color="#007AFF"
:color="THEME_COLORS.PRIMARY"
block
>
了解
......@@ -151,6 +151,8 @@ import BottomNav from '../../components/BottomNav.vue'; // 假设BottomNav组件
import AdOverlay from '@/components/AdOverlay.vue'
// 获取接口信息
import { getUserProfileAPI } from '@/api/user';
// 导入主题颜色
import { THEME_COLORS } from '@/utils/config';
const welcomeHomeImg = 'https://cdn.ipadbiz.cn/lls_prog/images/welcome_home.png';
......