feat: migrate to PostgreSQL GORM and MinIO file storage

Use UUID models and soft deletion, persist file relationships with deduplicated monthly MinIO objects, and add admin file management. Update mini-program media handling and add local dev configuration.
This commit is contained in:
2026-11-01 11:48:45 +08:00
parent 0530523750
commit 4934a69581
94 changed files with 4686 additions and 2147 deletions
+13 -38
View File
@@ -1,3 +1,4 @@
const { uploadReference } = require('../../utils/file-media');
const { getLayout } = require('../../utils/layout');
const { api, API_BASE, getImageUrl, uploadFileCompat } = require('../../utils/request');
const { guardStorageSpace } = require('../../utils/storage-guard');
@@ -24,7 +25,7 @@ Page({
wx.showToast({ title: '参数错误', icon: 'none' });
return;
}
this.setData({ diaryId: parseInt(id) });
this.setData({ diaryId: String(id) });
this.loadDiary();
},
@@ -50,7 +51,7 @@ Page({
'form.lng': data.lng || 0,
'form.location': data.location || '',
tempImages: tempImages,
existingImages: imgs,
existingImages: Array.isArray(data.image_file_ids) && data.image_file_ids.length === imgs.length ? data.image_file_ids : imgs,
contentLength: content.length
});
} catch (e) {
@@ -110,10 +111,10 @@ Page({
var existing = this.data.existingImages || [];
var temps = this.data.tempImages || [];
// 判断哪些是新上传的图片(tempFilePaths 以 http 开头的是已有图片,否则是新选的)
// 已有图片通过原始引用识别;开发工具的本地图片也可能以 http 开头。
for (var i = 0; i < temps.length; i++) {
var p = temps[i];
if (p.indexOf('http') === 0) {
if (existing[i] && getImageUrl(existing[i]) === p) {
// 已有图片,用原始路径
uploadPaths.push(existing[i] || '');
} else {
@@ -149,42 +150,16 @@ Page({
},
_uploadImage: async function(filePath) {
try {
var data = await uploadFileCompat({
url: API_BASE + '/upload',
filePath: filePath,
name: 'file',
formData: { sub_dir: 'diaries' }
});
var path = data && (data.path || data.url || '');
if (!path) {
// 内容安全检测失败:抛出错误提示用户
if (data && data.error) {
throw data;
}
try {
var retryData = await uploadFileCompat({
url: API_BASE + '/upload',
filePath: filePath,
name: 'file',
formData: { sub_dir: 'diaries' }
});
path = retryData && (retryData.path || retryData.url || '');
} catch(retryErr) {
console.error('图片上传重试失败', retryErr);
}
}
return path;
} catch(e) {
// 内容安全违规错误:直接抛出,中断发布并提示用户
if (e && e.error) {
throw e;
}
console.error('图片上传失败', e);
return '';
}
var data = await uploadFileCompat({
url: API_BASE + '/upload',
filePath: filePath,
name: 'file',
formData: { sub_dir: 'diaries' }
});
return uploadReference(data);
},
goBack: function() {
wx.navigateBack();
}