1121 lines
35 KiB
JavaScript
1121 lines
35 KiB
JavaScript
const config = require('../../../config/config.js');
|
||
const apiClient = require('../../../utils/api-client.js');
|
||
const imageCacheManager = require('../../../utils/image-cache-manager.js');
|
||
const { generateScanaSignature } = require('../../../utils/scana-signature.js');
|
||
const cosManager = require('../../../utils/cos-manager.js');
|
||
|
||
Page({
|
||
data: {
|
||
showQuitModal: false,
|
||
inputText: '',
|
||
textLength: 0,
|
||
// 用于接收相机页传递的图片
|
||
selectedImage: '',
|
||
currentLocation: '',
|
||
canPublish: false,
|
||
isQuitConfirmed: false,
|
||
showImageAction: false,
|
||
// 存储经纬度
|
||
latitude: '',
|
||
longitude: '',
|
||
// 位置信息字段
|
||
locationName: '',
|
||
distance: '',
|
||
fullAddress: '',
|
||
|
||
// 可见性相关
|
||
visibility: '', // 默认为空,表示未选择
|
||
auditReason: '', // 审核不通过的具体原因
|
||
|
||
// 系统信息
|
||
statusBarHeight: 0,
|
||
navBarHeight: 44,
|
||
totalNavBarHeight: 0,
|
||
|
||
// 审核弹窗状态
|
||
showAuditModal: false,
|
||
|
||
// 定位失败弹窗状态
|
||
showLocationErrorModal: false,
|
||
|
||
// Loading 状态
|
||
isLoading: false,
|
||
loadingText: '加载中...',
|
||
},
|
||
|
||
onLoad(options) {
|
||
// 获取系统信息
|
||
const systemInfo = wx.getSystemInfoSync();
|
||
const statusBarHeight = systemInfo.statusBarHeight;
|
||
|
||
// 计算导航栏总高度
|
||
const totalNavBarHeight = statusBarHeight + this.data.navBarHeight;
|
||
|
||
this.setData({
|
||
statusBarHeight: statusBarHeight,
|
||
totalNavBarHeight: totalNavBarHeight
|
||
});
|
||
|
||
this.onLoadAfterSystemInfo(options);
|
||
},
|
||
|
||
// 统一的 loading 显示方法
|
||
showLoadingWithBg(text = '加载中...') {
|
||
this.setData({
|
||
isLoading: true,
|
||
loadingText: text
|
||
});
|
||
wx.showLoading({
|
||
title: text,
|
||
mask: true
|
||
});
|
||
},
|
||
|
||
// 统一的 loading 隐藏方法
|
||
hideLoadingWithBg() {
|
||
this.setData({
|
||
isLoading: false
|
||
});
|
||
wx.hideLoading();
|
||
},
|
||
|
||
// 跳转到可见性选择页面
|
||
showVisibilityModal() {
|
||
wx.navigateTo({
|
||
url: `/subpackages/media/visibility-selector/visibility-selector?currentVisibility=${this.data.visibility}`
|
||
});
|
||
},
|
||
|
||
// 接收从可见性选择页面返回的结果
|
||
updateVisibility(visibility, extraData) {
|
||
console.log('updateVisibility 被调用,visibility:', visibility, '类型:', typeof visibility);
|
||
if (!visibility || visibility.trim() === '') {
|
||
console.warn('updateVisibility 接收到空值,忽略更新');
|
||
return;
|
||
}
|
||
// 确保 visibility 值被正确设置
|
||
const visibilityValue = String(visibility).trim();
|
||
|
||
// 同时保存到本地存储,防止 onShow 覆盖
|
||
wx.setStorageSync('visibilityFromSelector', visibilityValue);
|
||
|
||
this.setData({
|
||
visibility: visibilityValue
|
||
});
|
||
console.log('visibility 已更新为:', this.data.visibility);
|
||
console.log('setData 后的实际值:', this.data.visibility);
|
||
// 更新可见性后,检查是否可以发布
|
||
this.checkCanPublish();
|
||
|
||
// 延迟验证,确保值已保存
|
||
setTimeout(() => {
|
||
console.log('延迟验证 visibility:', this.data.visibility);
|
||
if (this.data.visibility !== visibilityValue) {
|
||
console.warn('visibility 值被覆盖,重新设置');
|
||
this.setData({ visibility: visibilityValue });
|
||
}
|
||
}, 100);
|
||
},
|
||
|
||
onLoadAfterSystemInfo(options) {
|
||
if (options.visibility) {
|
||
this.setData({
|
||
visibility: options.visibility
|
||
});
|
||
}
|
||
|
||
if (options.imagePath) {
|
||
try {
|
||
const imagePath = decodeURIComponent(options.imagePath);
|
||
this.setData({
|
||
selectedImage: imagePath
|
||
});
|
||
this.checkCanPublish();
|
||
|
||
// 检查是否为已上传的URL(http/https开头)
|
||
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
|
||
// 已经是上传后的URL,直接使用
|
||
// 确保 originalImageUrl 始终是有效的 OSS URL
|
||
this.setData({
|
||
originalImageUrl: imagePath,
|
||
selectedImage: imagePath // 初始显示使用 OSS URL
|
||
});
|
||
this.checkCanPublish();
|
||
|
||
// 后台缓存,不阻塞UI显示
|
||
imageCacheManager.cacheImage(imagePath).then(cachedPath => {
|
||
// 只更新 selectedImage 用于显示,保持 originalImageUrl 为 OSS URL
|
||
if (cachedPath && (cachedPath.startsWith('wxfile://') || cachedPath.startsWith('/'))) {
|
||
this.setData({ selectedImage: cachedPath });
|
||
}
|
||
}).catch(error => {
|
||
console.error('图片缓存失败:', error);
|
||
// 缓存失败不影响使用,继续使用 OSS URL 显示
|
||
});
|
||
}
|
||
// 检查是否为临时路径(需要上传)
|
||
else if (imagePath.startsWith('wxfile://') || imagePath.startsWith('tmp/') || imagePath.startsWith('http://tmp/')) {
|
||
// 先显示临时图片
|
||
this.setData({
|
||
selectedImage: imagePath
|
||
});
|
||
this.checkCanPublish();
|
||
|
||
// 上传图片
|
||
this.uploadImageToServer(imagePath)
|
||
.then(imageUrl => {
|
||
// 确保上传返回的是有效的 OSS URL
|
||
if (imageUrl && (imageUrl.startsWith('http://') || imageUrl.startsWith('https://'))) {
|
||
// 确保 originalImageUrl 是有效的 OSS URL
|
||
this.setData({ originalImageUrl: imageUrl });
|
||
// 后台缓存,不阻塞UI
|
||
imageCacheManager.cacheImage(imageUrl).then(cachedPath => {
|
||
// 只更新 selectedImage 用于显示,保持 originalImageUrl 为 OSS URL
|
||
if (cachedPath && (cachedPath.startsWith('wxfile://') || cachedPath.startsWith('/'))) {
|
||
this.setData({ selectedImage: cachedPath });
|
||
}
|
||
}).catch(error => {
|
||
console.error('图片缓存失败:', error);
|
||
// 缓存失败时,使用 OSS URL 显示
|
||
this.setData({ selectedImage: imageUrl });
|
||
});
|
||
} else {
|
||
console.error('上传返回的URL格式无效:', imageUrl);
|
||
wx.showToast({
|
||
title: '图片上传失败,URL格式无效',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('图片上传失败:', error);
|
||
wx.showToast({
|
||
title: '图片上传失败,请重试',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
});
|
||
} else {
|
||
// 其他情况,如果不是有效的 URL,可能需要上传
|
||
console.warn('图片路径格式未知:', imagePath);
|
||
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
|
||
this.setData({
|
||
originalImageUrl: imagePath,
|
||
selectedImage: imagePath
|
||
});
|
||
} else {
|
||
// 尝试上传
|
||
this.uploadImageToServer(imagePath)
|
||
.then(imageUrl => {
|
||
if (imageUrl && (imageUrl.startsWith('http://') || imageUrl.startsWith('https://'))) {
|
||
this.setData({
|
||
originalImageUrl: imageUrl,
|
||
selectedImage: imageUrl
|
||
});
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('图片上传失败:', error);
|
||
wx.showToast({
|
||
title: '图片处理失败,请重试',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
});
|
||
}
|
||
this.checkCanPublish();
|
||
}
|
||
} catch (error) {
|
||
console.error('处理图片路径失败:', error);
|
||
// 处理失败时静默处理,不影响页面显示
|
||
}
|
||
}
|
||
|
||
// 页面加载时检查发布状态
|
||
this.checkCanPublish();
|
||
|
||
// 页面初次加载时自动获取当前位置
|
||
this.getCurrentLocation();
|
||
},
|
||
|
||
|
||
receiveLocationData: function(locationData) {
|
||
try {
|
||
// 检查locationData是否为null或undefined
|
||
if (locationData === null || locationData === undefined) {
|
||
this.setData({
|
||
currentLocation: '',
|
||
locationName: '',
|
||
distance: '',
|
||
fullAddress: '',
|
||
latitude: '',
|
||
longitude: ''
|
||
});
|
||
} else {
|
||
const coordinateUpdate = {};
|
||
if (typeof locationData.location === 'string') {
|
||
const [lonStr = '', latStr = ''] = locationData.location.split(',');
|
||
const parsedLatitude = parseFloat((latStr || '').trim());
|
||
const parsedLongitude = parseFloat((lonStr || '').trim());
|
||
if (!Number.isNaN(parsedLatitude) && !Number.isNaN(parsedLongitude)) {
|
||
coordinateUpdate.latitude = parsedLatitude;
|
||
coordinateUpdate.longitude = parsedLongitude;
|
||
} else {
|
||
console.warn('无法解析location字段中的经纬度:', locationData.location);
|
||
}
|
||
} else if (
|
||
typeof locationData.latitude === 'number' &&
|
||
typeof locationData.longitude === 'number'
|
||
) {
|
||
coordinateUpdate.latitude = locationData.latitude;
|
||
coordinateUpdate.longitude = locationData.longitude;
|
||
}
|
||
|
||
// 检查是否是"地址未知"的情况
|
||
const isAddressUnknown = (locationData.address && locationData.address === '地址未知') ||
|
||
(locationData.name && locationData.name === '地址未知');
|
||
|
||
if (isAddressUnknown) {
|
||
|
||
this.setData(Object.assign({
|
||
currentLocation: locationData.name || locationData.address || '',
|
||
locationName: locationData.name || locationData.address || '',
|
||
distance: locationData.distance || '',
|
||
fullAddress: '地址未知'
|
||
}, coordinateUpdate));
|
||
} else {
|
||
// 处理正常的位置数据
|
||
this.setData(Object.assign({
|
||
currentLocation: locationData.name || locationData.address || locationData.toString(),
|
||
locationName: locationData.name || locationData.address || locationData.toString(),
|
||
distance: locationData.distance || '',
|
||
fullAddress: locationData.address && locationData.address !== locationData.name ? locationData.address : ''
|
||
}, coordinateUpdate));
|
||
}
|
||
|
||
}
|
||
} catch (error) {
|
||
this.setData({
|
||
currentLocation: '',
|
||
locationName: '',
|
||
distance: '',
|
||
fullAddress: '',
|
||
latitude: '',
|
||
longitude: ''
|
||
});
|
||
|
||
}
|
||
|
||
// 触发页面更新
|
||
try {
|
||
this.setData({
|
||
_forceUpdate: this.data._forceUpdate ? !this.data._forceUpdate : true
|
||
});
|
||
|
||
} catch (updateError) {
|
||
console.error('强制更新页面失败:', updateError);
|
||
}
|
||
},
|
||
|
||
onShow() {
|
||
// 延迟执行,确保 updateVisibility 已经执行完成
|
||
setTimeout(() => {
|
||
// 优先检查是否有从可见性选择页面返回的值
|
||
const visibilityFromSelector = wx.getStorageSync('visibilityFromSelector');
|
||
if (visibilityFromSelector) {
|
||
console.log('onShow - 从本地存储恢复 visibility:', visibilityFromSelector);
|
||
this.setData({ visibility: visibilityFromSelector });
|
||
wx.removeStorageSync('visibilityFromSelector');
|
||
}
|
||
|
||
const savedFormData = wx.getStorageSync('editPageFormData');
|
||
if (savedFormData) {
|
||
try {
|
||
const formData = JSON.parse(savedFormData);
|
||
// 只有在 visibility 不存在时才使用保存的数据,避免覆盖从可见性选择页面返回的值
|
||
const updateData = {
|
||
inputText: formData.inputText || '',
|
||
textLength: formData.textLength || 0,
|
||
originalImageUrl: formData.originalImageUrl || '',
|
||
};
|
||
// 只有在当前没有可见性设置时才恢复可见性
|
||
if (!this.data.visibility || this.data.visibility.trim() === '') {
|
||
updateData.visibility = formData.visibility || 'public';
|
||
}
|
||
this.setData(updateData);
|
||
// 清除保存的数据
|
||
wx.removeStorageSync('editPageFormData');
|
||
} catch (e) {
|
||
console.error('恢复表单数据失败:', e);
|
||
}
|
||
}
|
||
}, 150);
|
||
|
||
const selectedPoi = wx.getStorageSync('selectedPoi');
|
||
|
||
let shouldUseLocalData = true;
|
||
|
||
if (!this.data.locationName || this.data.locationName === '获取位置中...') {
|
||
|
||
} else {
|
||
|
||
shouldUseLocalData = false;
|
||
}
|
||
|
||
if (selectedPoi === null) {
|
||
this.setData({
|
||
currentLocation: '',
|
||
locationName: '',
|
||
distance: '',
|
||
fullAddress: ''
|
||
});
|
||
// 清除本地存储
|
||
wx.removeStorageSync('selectedPoi');
|
||
} else if (!shouldUseLocalData) {
|
||
|
||
} else if (selectedPoi) {
|
||
try {
|
||
if (typeof selectedPoi === 'string') {
|
||
this.setData({
|
||
currentLocation: selectedPoi,
|
||
locationName: selectedPoi,
|
||
distance: '',
|
||
fullAddress: selectedPoi
|
||
});
|
||
} else {
|
||
// 检查是否是"地址未知"的情况
|
||
const isAddressUnknown = (selectedPoi.address && selectedPoi.address === '地址未知') ||
|
||
(selectedPoi.name && selectedPoi.name === '地址未知');
|
||
|
||
if (isAddressUnknown) {
|
||
|
||
this.setData({
|
||
currentLocation: selectedPoi.name || selectedPoi.address || '',
|
||
locationName: selectedPoi.name || selectedPoi.address || '',
|
||
distance: selectedPoi.distance || '',
|
||
fullAddress: '地址未知'
|
||
});
|
||
} else {
|
||
this.setData({
|
||
currentLocation: selectedPoi.name || selectedPoi.address || selectedPoi.toString(),
|
||
locationName: selectedPoi.name || selectedPoi.address || selectedPoi.toString(),
|
||
distance: selectedPoi.distance || '',
|
||
fullAddress: selectedPoi.address && selectedPoi.address !== selectedPoi.name ? selectedPoi.address : ''
|
||
});
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('解析位置信息失败:', error);
|
||
this.setData({
|
||
currentLocation: selectedPoi,
|
||
locationName: selectedPoi,
|
||
distance: '',
|
||
fullAddress: selectedPoi
|
||
});
|
||
}
|
||
} else {
|
||
// 检查是否有"不显示地点"的标志
|
||
const isLocationHidden = wx.getStorageSync('isLocationHidden');
|
||
if (isLocationHidden) {
|
||
|
||
this.setData({
|
||
currentLocation: '',
|
||
locationName: '',
|
||
distance: '',
|
||
fullAddress: ''
|
||
});
|
||
} else {
|
||
|
||
this.getCurrentLocation();
|
||
}
|
||
}
|
||
|
||
// 页面显示时检查是否可以发布
|
||
this.checkCanPublish();
|
||
},
|
||
|
||
// 获取当前位置信息
|
||
getCurrentLocation() {
|
||
try {
|
||
this.setData({
|
||
currentLocation: '获取位置中...',
|
||
locationName: '获取位置中...',
|
||
distance: '',
|
||
fullAddress: ''
|
||
});
|
||
|
||
wx.getLocation({
|
||
type: 'gcj02',
|
||
success: (locationRes) => {
|
||
// 保存经纬度
|
||
this.setData({
|
||
latitude: locationRes.latitude,
|
||
longitude: locationRes.longitude
|
||
});
|
||
|
||
// 调用高德API
|
||
wx.request({
|
||
url: 'https://restapi.amap.com/v3/geocode/regeo',
|
||
data: {
|
||
location: `${locationRes.longitude},${locationRes.latitude}`,
|
||
key: config.amapKey,
|
||
extensions: 'all'
|
||
},
|
||
success: (res) => {
|
||
let locationText = '默认地址';
|
||
let locationName = '';
|
||
|
||
if (res.data.regeocode && res.data.regeocode.formatted_address) {
|
||
locationText = res.data.regeocode.formatted_address;
|
||
}
|
||
|
||
if (res.data.regeocode.pois && res.data.regeocode.pois[0]) {
|
||
locationName = res.data.regeocode.pois[0].name || '';
|
||
if (!locationText || locationText === '默认地址') {
|
||
locationText = res.data.regeocode.pois[0].address && res.data.regeocode.pois[0].address.trim() !== ''
|
||
? res.data.regeocode.pois[0].address
|
||
: res.data.regeocode.pois[0].name;
|
||
}
|
||
}
|
||
|
||
this.setData({
|
||
currentLocation: locationText,
|
||
locationName: locationName,
|
||
distance: '',
|
||
fullAddress: res.data.regeocode && res.data.regeocode.formatted_address ? res.data.regeocode.formatted_address : ''
|
||
});
|
||
|
||
this.checkCanPublish();
|
||
},
|
||
fail: (error) => {
|
||
console.error('获取地址信息失败:', error);
|
||
this.setData({
|
||
currentLocation: '获取位置信息失败',
|
||
locationName: '获取位置信息失败',
|
||
distance: '',
|
||
fullAddress: ''
|
||
});
|
||
}
|
||
});
|
||
},
|
||
fail: (error) => {
|
||
console.error('获取位置失败:', error);
|
||
this.setData({
|
||
currentLocation: '获取位置失败',
|
||
locationName: '获取位置失败',
|
||
distance: '',
|
||
fullAddress: ''
|
||
});
|
||
// 获取位置失败不影响页面使用,静默处理
|
||
}
|
||
});
|
||
} catch (error) {
|
||
console.error('获取当前位置异常:', error);
|
||
// 异常时不显示错误弹窗,静默处理
|
||
this.setData({
|
||
currentLocation: '获取位置失败',
|
||
locationName: '获取位置失败',
|
||
distance: '',
|
||
fullAddress: ''
|
||
});
|
||
}
|
||
},
|
||
|
||
// 计算文本长度
|
||
countTextLength(text) {
|
||
if (!text) return 0;
|
||
|
||
const emojiRegex = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{1F018}-\u{1F270}\u{FE0F}\u{200D}]/gu;
|
||
|
||
// 统计非emoji字符的数量
|
||
const nonEmojiText = text.replace(emojiRegex, '');
|
||
const nonEmojiCount = nonEmojiText.length;
|
||
|
||
// 统计emoji的数量
|
||
const emojiMatches = text.match(emojiRegex);
|
||
const emojiCount = emojiMatches ? emojiMatches.length : 0;
|
||
|
||
// 总和
|
||
return nonEmojiCount + emojiCount;
|
||
},
|
||
|
||
onTextInput(e) {
|
||
let inputText = e.detail.value || '';
|
||
const maxLength = 120;
|
||
|
||
// 计算实际字符数
|
||
const actualLength = this.countTextLength(inputText);
|
||
|
||
// 如果超过120字,截断文本
|
||
if (actualLength > maxLength) {
|
||
// 截断
|
||
let truncatedText = '';
|
||
let currentCount = 0;
|
||
|
||
for (let i = 0; i < inputText.length; i++) {
|
||
// 检查当前字符是否为emoji的一部分
|
||
const char = inputText.charAt(i);
|
||
const isEmojiPart = /[\uD800-\uDBFF]/.test(char) || /[\uDC00-\uDFFF]/.test(char) || char === '\uFE0F' || char === '\u200D';
|
||
|
||
// 计数逻辑
|
||
if (isEmojiPart) {
|
||
// 如果是emoji的一部分,不单独计数
|
||
truncatedText += char;
|
||
} else {
|
||
// 否则计数加1
|
||
if (currentCount < maxLength) {
|
||
truncatedText += char;
|
||
currentCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
inputText = truncatedText;
|
||
}
|
||
|
||
// 确保计数器最多显示120
|
||
const displayLength = Math.min(actualLength, maxLength);
|
||
|
||
this.setData({
|
||
inputText: inputText,
|
||
textLength: displayLength
|
||
});
|
||
|
||
this.checkCanPublish();
|
||
},
|
||
|
||
// 从相册选择图片
|
||
chooseImageFromAlbum() {
|
||
wx.chooseImage({
|
||
count: 1,
|
||
sizeType: ['original', 'compressed'],
|
||
sourceType: ['album'],
|
||
success: (res) => {
|
||
if (!res.tempFilePaths || res.tempFilePaths.length === 0) {
|
||
console.error('未获取到图片临时路径');
|
||
wx.showToast({
|
||
title: '选择图片失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
const tempFilePath = res.tempFilePaths[0];
|
||
|
||
// 显示加载提示
|
||
this.showLoadingWithBg('上传中...');
|
||
|
||
// 上传图片到后端
|
||
this.uploadImageToServer(tempFilePath)
|
||
.then (async (imageUrl) => {
|
||
this.hideLoadingWithBg();
|
||
// 上传成功
|
||
this.setData({ originalImageUrl: imageUrl });
|
||
this.setData({ selectedImage: tempFilePath });
|
||
this.checkCanPublish();
|
||
this.hideImageAction();
|
||
|
||
imageCacheManager.cacheImage(imageUrl).then(cachedPath => {
|
||
if (cachedPath && (cachedPath.startsWith('wxfile://') || cachedPath.startsWith('/'))) {
|
||
|
||
this.setData({ selectedImage: cachedPath });
|
||
} else {
|
||
|
||
}
|
||
}).catch(error => {
|
||
console.error('图片缓存失败:', error);
|
||
});
|
||
})
|
||
.catch(error => {
|
||
this.hideLoadingWithBg();
|
||
console.error('图片上传失败:', error);
|
||
wx.showToast({
|
||
title: '上传失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
},
|
||
fail: (error) => {
|
||
console.error('选择图片失败:', error);
|
||
wx.showToast({
|
||
title: '选择图片失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
// 上传图片
|
||
/**
|
||
* 上传图片到服务器
|
||
* @async
|
||
* @param {string} tempFilePath - 临时文件路径
|
||
* @returns {Promise<string>} 返回上传成功后的图片URL
|
||
* @description 使用COS管理器上传图片,支持压缩和进度监控
|
||
*/
|
||
async uploadImageToServer(tempFilePath) {
|
||
try {
|
||
if (!tempFilePath) {
|
||
throw new Error('文件路径为空');
|
||
}
|
||
|
||
const uploadResult = await cosManager.upload(tempFilePath, {
|
||
fileType: 'image',
|
||
enableDedup: false, // 启用去重,节省存储空间
|
||
onProgress: (percent) => {
|
||
console.log('上传进度:', percent + '%');
|
||
},
|
||
enableCompress: false,
|
||
compressOptions: {
|
||
maxWidth: 400,
|
||
maxHeight: 400,
|
||
targetSize: 500 * 1024
|
||
}
|
||
});
|
||
|
||
// 检查上传结果
|
||
if (!uploadResult || !uploadResult.success) {
|
||
throw new Error(uploadResult?.error || uploadResult?.message || '上传失败');
|
||
}
|
||
|
||
if (!uploadResult.fileUrl) {
|
||
throw new Error('上传失败:未获取到文件URL');
|
||
}
|
||
|
||
this.setData({ originalImageUrl: uploadResult.fileUrl });
|
||
return uploadResult.fileUrl;
|
||
} catch (error) {
|
||
console.error('上传图片到服务器失败:', error);
|
||
throw error; // 重新抛出错误,让调用者处理
|
||
}
|
||
},
|
||
|
||
removeImage() {
|
||
this.setData({
|
||
selectedImage: '',
|
||
originalImageUrl: ''
|
||
});
|
||
this.checkCanPublish();
|
||
},
|
||
|
||
// 图片预览功能
|
||
previewImage() {
|
||
// 优先使用原始图片URL进行预览,确保图片清晰完整
|
||
const previewUrl = this.data.originalImageUrl || this.data.selectedImage;
|
||
if (previewUrl) {
|
||
wx.previewImage({
|
||
current: previewUrl,
|
||
urls: [previewUrl]
|
||
});
|
||
}
|
||
},
|
||
|
||
chooseLocation() {
|
||
wx.getLocation({
|
||
type: 'gcj02',
|
||
success: (locationRes) => {
|
||
// 保存经纬度
|
||
this.setData({
|
||
latitude: locationRes.latitude,
|
||
longitude: locationRes.longitude
|
||
});
|
||
console.log('✅ 动态发布页微信原生定位成功: ',"lat: "+locationRes.latitude," lon: "+locationRes.longitude);
|
||
// 跳转到位置选择列表页面
|
||
wx.navigateTo({
|
||
url: `/subpackages/map-extras/locationList/locationList?latitude=${locationRes.latitude}&longitude=${locationRes.longitude}&locationName=${encodeURIComponent(this.data.locationName || '')}&address=${encodeURIComponent(this.data.fullAddress || '')}`
|
||
});
|
||
},
|
||
fail: (error) => {
|
||
console.error('获取位置失败:', error);
|
||
wx.showToast({
|
||
title: '获取位置失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
checkCanPublish() {
|
||
|
||
const hasValidText = this.data.textLength > 0 && this.data.inputText.trim()!== '';
|
||
const hasValidVisibility = !!this.data.visibility;
|
||
|
||
// 只有当有文本内容且选择了可见性时才能发布
|
||
const canPublish = hasValidText && hasValidVisibility;
|
||
this.setData({ canPublish });
|
||
return canPublish;
|
||
},
|
||
|
||
showImageAction() {
|
||
this.setData({ showImageAction: true });
|
||
},
|
||
|
||
hideImageAction() {
|
||
this.setData({ showImageAction: false });
|
||
},
|
||
|
||
takePhoto() {
|
||
const formData = {
|
||
inputText: this.data.inputText,
|
||
textLength: this.data.textLength,
|
||
visibility: this.data.visibility,
|
||
currentLocation: this.data.currentLocation,
|
||
locationName: this.data.locationName,
|
||
distance: this.data.distance,
|
||
fullAddress: this.data.fullAddress,
|
||
originalImageUrl: this.data.originalImageUrl
|
||
};
|
||
wx.setStorageSync('editPageFormData', JSON.stringify(formData));
|
||
|
||
this.hideImageAction();
|
||
wx.navigateTo({
|
||
url: '/subpackages/media/camera/camera'
|
||
});
|
||
},
|
||
|
||
onNavBack() {
|
||
if (this.data.inputText.trim() || this.data.selectedImage) {
|
||
this.setData({ showQuitModal: true });
|
||
} else {
|
||
wx.navigateBack({ delta: 2 });
|
||
}
|
||
},
|
||
|
||
quitEdit() {
|
||
this.setData({ isQuitConfirmed: true, showQuitModal: false });
|
||
wx.navigateBack({ delta: 2 });
|
||
},
|
||
|
||
cancelQuit() {
|
||
this.setData({ showQuitModal: false });
|
||
},
|
||
|
||
onBackPress() {
|
||
if (this.data.isQuitConfirmed) return false;
|
||
if (this.data.inputText.trim() || this.data.selectedImage) {
|
||
this.setData({ showQuitModal: true });
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
},
|
||
|
||
gotoLocationList() {
|
||
if (!this.data.latitude ||!this.data.longitude) {
|
||
wx.showToast({ title: '获取位置中,请稍后', icon: 'none' });
|
||
return;
|
||
}
|
||
wx.navigateTo({
|
||
url: `/subpackages/map-extras/locationList/locationList?latitude=${this.data.latitude}&longitude=${this.data.longitude}&locationName=${encodeURIComponent(this.data.locationName || '')}&address=${encodeURIComponent(this.data.fullAddress || '')}`
|
||
});
|
||
},
|
||
|
||
|
||
// 内容审核方法(已禁用,直接返回通过)
|
||
checkContentSafety(content) {
|
||
// 审核功能已禁用,直接返回审核通过
|
||
return Promise.resolve(true);
|
||
},
|
||
|
||
// 图片审核方法(已禁用,直接返回通过)
|
||
checkImageSafety(imageUrl) {
|
||
// 审核功能已禁用,直接返回审核通过
|
||
return Promise.resolve(true);
|
||
},
|
||
|
||
// 检查定位状态
|
||
checkLocationStatus() {
|
||
// 检查定位是否失败(如果用户尝试获取定位但失败了)
|
||
const locationFailed = this.data.currentLocation === '获取位置失败' ||
|
||
this.data.currentLocation === '获取位置信息失败';
|
||
|
||
// 如果定位失败,返回false;如果用户没有选择位置(空字符串)或正在获取,允许继续
|
||
// 注意:如果正在获取中,也应该提示用户等待或重试
|
||
if (this.data.currentLocation === '获取位置中...') {
|
||
return false; // 正在获取中,提示用户等待
|
||
}
|
||
|
||
// 如果定位失败,返回false
|
||
if (locationFailed) {
|
||
return false;
|
||
}
|
||
|
||
// 其他情况(包括没有选择位置)都允许继续
|
||
return true;
|
||
},
|
||
|
||
publishDynamic() {
|
||
// 清空历史原因
|
||
this.setData({ auditReason: '' });
|
||
const hasValidText = this.data.textLength > 0 && this.data.inputText.trim() !== '';
|
||
if (!hasValidText) {
|
||
wx.showToast({ title: '请填写动态内容', icon: 'none' });
|
||
return;
|
||
}
|
||
// 检查可见性:必须是非空字符串
|
||
let visibility = this.data.visibility;
|
||
console.log('publishDynamic - 当前 visibility 值:', visibility, '类型:', typeof visibility);
|
||
|
||
// 如果 visibility 为空,尝试从本地存储恢复
|
||
if (!visibility || visibility.trim() === '') {
|
||
const visibilityFromSelector = wx.getStorageSync('visibilityFromSelector');
|
||
if (visibilityFromSelector) {
|
||
visibility = visibilityFromSelector;
|
||
this.setData({ visibility: visibility });
|
||
console.log('从本地存储恢复 visibility:', visibility);
|
||
}
|
||
}
|
||
|
||
// 再次检查,如果仍然为空,使用默认值 'public'
|
||
if (!visibility || visibility.trim() === '') {
|
||
visibility = 'public';
|
||
this.setData({ visibility: visibility });
|
||
console.log('使用默认 visibility:', visibility);
|
||
}
|
||
|
||
console.log('publishDynamic - 最终使用的 visibility:', visibility);
|
||
|
||
// 检查定位状态
|
||
if (!this.checkLocationStatus()) {
|
||
this.setData({ showLocationErrorModal: true });
|
||
return;
|
||
}
|
||
|
||
// 审核功能已禁用,直接发布
|
||
// 文本和图片审核都已禁用,跳过审核步骤
|
||
// 使用最终确定的 visibility 值
|
||
this.setData({
|
||
auditReason: '',
|
||
showAuditModal: false,
|
||
visibility: visibility // 确保使用最新的 visibility 值
|
||
});
|
||
this.doPublish();
|
||
},
|
||
|
||
hideAuditModal() {
|
||
this.setData({ showAuditModal: false });
|
||
wx.createSelectorQuery().select('#contentInput').boundingClientRect(rect => {
|
||
if (rect) wx.pageScrollTo({ scrollTop: rect.top - 100 });
|
||
}).exec();
|
||
},
|
||
|
||
// 隐藏定位失败弹窗
|
||
hideLocationErrorModal() {
|
||
this.setData({ showLocationErrorModal: false });
|
||
},
|
||
|
||
// 重试获取定位
|
||
retryLocation() {
|
||
this.setData({ showLocationErrorModal: false });
|
||
// 重新获取定位
|
||
this.getCurrentLocation();
|
||
// 提示用户
|
||
wx.showToast({
|
||
title: '正在获取定位...',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
},
|
||
|
||
doPublish() {
|
||
this.showLoadingWithBg('发布中...');
|
||
const media = [];
|
||
let hasMedia = false;
|
||
|
||
if (this.data.selectedImage) {
|
||
// 确保使用有效的 OSS URL(http:// 或 https:// 开头)
|
||
let imageUrlForPublish = this.data.originalImageUrl;
|
||
|
||
// 如果 originalImageUrl 不存在或不是有效的 URL,需要先上传
|
||
if (!imageUrlForPublish ||
|
||
(!imageUrlForPublish.startsWith('http://') && !imageUrlForPublish.startsWith('https://'))) {
|
||
// 检查 selectedImage 是否是临时路径,需要上传
|
||
const selectedImage = this.data.selectedImage;
|
||
if (selectedImage &&
|
||
(selectedImage.startsWith('wxfile://') ||
|
||
selectedImage.startsWith('tmp/') ||
|
||
selectedImage.startsWith('http://tmp/') ||
|
||
selectedImage.startsWith('/'))) {
|
||
// 需要先上传图片
|
||
this.showLoadingWithBg('上传图片中...');
|
||
this.uploadImageToServer(selectedImage)
|
||
.then(imageUrl => {
|
||
if (imageUrl && (imageUrl.startsWith('http://') || imageUrl.startsWith('https://'))) {
|
||
this.setData({ originalImageUrl: imageUrl });
|
||
// 继续发布流程
|
||
this.processMediaForPublish(media, hasMedia);
|
||
} else {
|
||
this.hideLoadingWithBg();
|
||
wx.showToast({
|
||
title: '图片上传失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
})
|
||
.catch(error => {
|
||
this.hideLoadingWithBg();
|
||
console.error('图片上传失败:', error);
|
||
wx.showToast({
|
||
title: '图片上传失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
return;
|
||
} else {
|
||
// 如果 selectedImage 也不是有效的 URL,报错
|
||
this.hideLoadingWithBg();
|
||
wx.showToast({
|
||
title: '图片URL无效,请重新选择图片',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 使用有效的 OSS URL 继续发布流程
|
||
this.processMediaForPublish(media, hasMedia);
|
||
} else {
|
||
this.continuePublish(media, hasMedia);
|
||
}
|
||
},
|
||
|
||
// 处理媒体文件用于发布(提取公共逻辑)
|
||
processMediaForPublish(media, hasMedia) {
|
||
const imageUrlForPublish = this.data.originalImageUrl;
|
||
|
||
if (!imageUrlForPublish ||
|
||
(!imageUrlForPublish.startsWith('http://') && !imageUrlForPublish.startsWith('https://'))) {
|
||
this.hideLoadingWithBg();
|
||
wx.showToast({
|
||
title: '图片URL格式不正确,请重新选择图片',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 获取图片宽高
|
||
wx.getImageInfo({
|
||
src: imageUrlForPublish,
|
||
success: (imageInfo) => {
|
||
media.push({
|
||
type: "image",
|
||
url: imageUrlForPublish, // 确保使用有效的 OSS URL
|
||
width: imageInfo.width,
|
||
height: imageInfo.height,
|
||
size: 0,
|
||
quality: "high"
|
||
});
|
||
hasMedia = true;
|
||
this.continuePublish(media, hasMedia);
|
||
},
|
||
fail: (err) => {
|
||
this.hideLoadingWithBg();
|
||
console.error('获取图片信息失败:', err);
|
||
|
||
// 即使获取图片信息失败,也尝试发布(使用默认尺寸)
|
||
media.push({
|
||
type: "image",
|
||
url: imageUrlForPublish, // 确保使用有效的 OSS URL
|
||
width: 640,
|
||
height: 480,
|
||
size: 0,
|
||
quality: "high"
|
||
});
|
||
hasMedia = true;
|
||
this.continuePublish(media, hasMedia);
|
||
}
|
||
});
|
||
},
|
||
|
||
continuePublish(media, hasMedia) {
|
||
const token = apiClient.getToken();
|
||
|
||
|
||
if (!token) {
|
||
this.hideLoadingWithBg();
|
||
setTimeout(() => wx.navigateTo({ url: '/pages/login/login' }), 0);
|
||
return;
|
||
}
|
||
|
||
// 判断内容类型
|
||
let contentType = 'text';
|
||
if (hasMedia && this.data.inputText.trim()!== '') {
|
||
contentType ='mixed';
|
||
} else if (hasMedia) {
|
||
contentType = 'image';
|
||
}
|
||
|
||
// 构建位置信息
|
||
let location = null;
|
||
if (this.data.currentLocation) {
|
||
location = {
|
||
latitude: this.data.latitude || 0,
|
||
longitude: this.data.longitude || 0,
|
||
address: this.data.fullAddress || this.data.currentLocation || '未知地址',
|
||
name: this.data.locationName || this.data.currentLocation || '未知位置',
|
||
cityCode: ''
|
||
};
|
||
}
|
||
|
||
// 发起发布请求
|
||
wx.request({
|
||
url: `${config.api.baseUrl}/api/v1/feeds`,
|
||
method: 'POST',
|
||
data: {
|
||
content: this.data.inputText,
|
||
type: contentType,
|
||
media: media,
|
||
location: location,
|
||
visibility: this.data.visibility
|
||
},
|
||
header: {
|
||
'Authorization': `Bearer ${apiClient.getToken()}`,
|
||
'Content-Type': 'application/json',
|
||
},
|
||
success: (res) => {
|
||
this.hideLoadingWithBg();
|
||
// 🔥 统一处理401 - 使用apiClient的统一处理
|
||
if (apiClient.is401Error(res)) {
|
||
const app = getApp();
|
||
const isLoggedIn = app?.globalData?.isLoggedIn || false;
|
||
apiClient.handle401Error(isLoggedIn);
|
||
return;
|
||
}
|
||
if (res.data.code === 200) {
|
||
wx.showToast({ title: '发布成功', icon: 'success' });
|
||
wx.removeStorageSync('selectedPoi');
|
||
|
||
// 清空表单数据
|
||
this.setData({
|
||
inputText: '',
|
||
textLength: 0,
|
||
selectedImage: '',
|
||
originalImageUrl: '',
|
||
visibility: '',
|
||
currentLocation: '',
|
||
locationName: '',
|
||
distance: '',
|
||
fullAddress: '',
|
||
canPublish: false,
|
||
auditReason: '',
|
||
showAuditModal: false
|
||
});
|
||
|
||
// 清除本地存储
|
||
wx.removeStorageSync('editPageFormData');
|
||
wx.removeStorageSync('visibilityFromSelector');
|
||
|
||
setTimeout(() => wx.switchTab({ url: '/pages/map/map' }), 1500);
|
||
} else {
|
||
wx.showToast({ title: res.data.message || '发布失败', icon: 'none' });
|
||
}
|
||
},
|
||
fail: () => {
|
||
this.hideLoadingWithBg();
|
||
wx.showToast({ title: '发布失败,请重试', icon: 'none' });
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|