feat: 任务和社区页面

This commit is contained in:
Blizzard
2026-02-06 17:27:35 +08:00
parent d42471e1d5
commit b800ea03b5
30 changed files with 1777 additions and 551 deletions
+64 -109
View File
@@ -1,16 +1,15 @@
// pages/community/create/index.js
import { MOCK_POSTS } from '../../../utils/mockData';
import request from '../../../utils/request';
Page({
data: {
content: '',
images: [],
canPublish: false,
canPublish: false, // Only depends on content
autoFocus: true,
location: '',
selectedTopics: [],
suggestedTopics: ['植物养护', '多肉日记', '绿植分享', '花卉美照', '阳台花园', '新手入门'],
hasDraft: false,
showImageSheet: false,
imageSheetItems: [
{ label: '拍照', value: 'camera' },
@@ -19,60 +18,18 @@ Page({
},
onLoad() {
// Check for saved draft
this.loadDraft();
// No draft loading
},
onUnload() {
// Save draft if there's content
this.saveDraft();
},
loadDraft() {
try {
const draft = wx.getStorageSync('post_draft');
if (draft && (draft.content || draft.images.length > 0)) {
this.setData({
content: draft.content || '',
images: draft.images || [],
selectedTopics: draft.selectedTopics || [],
canPublish: draft.content && draft.content.trim().length > 0,
hasDraft: true
});
}
} catch (e) {
console.log('No draft found');
}
},
saveDraft() {
if (this.data.content || this.data.images.length > 0) {
try {
wx.setStorageSync('post_draft', {
content: this.data.content,
images: this.data.images,
selectedTopics: this.data.selectedTopics
});
} catch (e) {
console.log('Failed to save draft');
}
}
},
clearDraft() {
try {
wx.removeStorageSync('post_draft');
} catch (e) {
console.log('Failed to clear draft');
}
// No draft saving
},
onContentInput(e) {
const content = e.detail.value;
this.setData({
content,
canPublish: content.trim().length > 0,
hasDraft: false
canPublish: content.trim().length > 0
});
},
@@ -109,8 +66,7 @@ Page({
success: (res) => {
const newImages = res.tempFiles.map(f => f.tempFilePath);
this.setData({
images: [...this.data.images, ...newImages],
hasDraft: false
images: [...this.data.images, ...newImages]
});
}
});
@@ -130,8 +86,7 @@ Page({
success: (res) => {
const newImage = res.tempFiles[0].tempFilePath;
this.setData({
images: [...this.data.images, newImage],
hasDraft: false
images: [...this.data.images, newImage]
});
}
});
@@ -200,74 +155,74 @@ Page({
});
},
insertEmoji() {
// Simple emoji picker simulation
const emojis = ['🌱', '🌿', '🍀', '🌵', '🌻', '🌺', '🌸', '🌼', '🪴', '🌲'];
wx.showActionSheet({
itemList: emojis,
success: (res) => {
const emoji = emojis[res.tapIndex];
this.setData({
content: this.data.content + emoji,
canPublish: true
});
}
});
},
handleCancel() {
if (this.data.content || this.data.images.length > 0) {
wx.showModal({
title: '保存草稿',
content: '是否保存当前内容为草稿?',
cancelText: '不保存',
confirmText: '保存',
success: (res) => {
if (res.confirm) {
this.saveDraft();
wx.showToast({ title: '已保存草稿', icon: 'success' });
setTimeout(() => wx.navigateBack(), 500);
} else {
this.clearDraft();
wx.navigateBack();
}
}
});
} else {
wx.navigateBack();
}
wx.navigateBack();
},
handlePublish() {
if (!this.data.canPublish) {
async handlePublish() {
if (!this.data.content || !this.data.content.trim()) {
wx.showToast({ title: '请输入内容', icon: 'none' });
return;
}
// Content already includes topics as hashtags
const finalContent = this.data.content.trim();
wx.showLoading({ title: '发布中...', mask: true });
// Create new post
const newPost = {
id: Date.now().toString(),
user: '我的花园',
content: finalContent,
images: this.data.images,
time: '刚刚',
likes: [],
comments: []
};
try {
// 1. Upload Images
const ossIds = [];
const images = this.data.images;
// Add to global mock data (at the beginning)
MOCK_POSTS.unshift(newPost);
if (images.length > 0) {
const uploadPromises = images.map(filePath => {
return request.upload(filePath).then(res => {
// Res structure: { file: { id: "...", url: "..." } }
return res && res.file ? res.file.id : null;
});
});
// Clear draft
this.clearDraft();
const uploadedIds = await Promise.all(uploadPromises);
wx.showToast({ title: '发布成功', icon: 'success' });
uploadedIds.forEach(id => {
if (id) ossIds.push(id);
});
setTimeout(() => {
wx.navigateBack();
}, 1000);
if (images.length > 0 && ossIds.length === 0) {
throw new Error('图片上传失败');
}
}
// 2. Publish Post
// Title is removed from UI. Using content snippet or default title.
const content = this.data.content.trim();
const title = content.length > 20 ? content.substring(0, 20) + '...' : content;
const payload = {
title: title || '新动态', // Fallback title
content: content,
location: this.data.location || '',
ossIds: ossIds
};
await request.post('/post/publish', payload);
wx.hideLoading();
wx.showToast({ title: '发布成功', icon: 'success' });
// Refresh previous page
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2];
if (prevPage && prevPage.onRefresh) {
prevPage.onRefresh();
}
setTimeout(() => {
wx.navigateBack();
}, 1000);
} catch (err) {
wx.hideLoading();
console.error('Publish failed', err);
wx.showToast({ title: '发布失败', icon: 'none' });
}
}
})
+3 -1
View File
@@ -11,6 +11,8 @@
</view>
</view>
<!-- Text Input -->
<textarea
class="post-textarea"
@@ -33,7 +35,7 @@
<view wx:if="{{images.length > 0}}" class="image-section">
<view class="image-preview-grid">
<view wx:for="{{images}}" wx:key="*this" class="preview-item" bindlongpress="showImageMenu" data-index="{{index}}">
<t-image src="{{item}}" mode="aspectFill" width="100%" height="100%" />
<image src="{{item}}" mode="aspectFill" style="width: 100%; height: 100%; display: block;" />
<view class="remove-btn" catchtap="removeImage" data-index="{{index}}">
<t-icon name="close" size="24rpx" color="#fff" />
</view>
+20
View File
@@ -314,3 +314,23 @@ page {
font-size: 24rpx;
color: #999;
}
/* Title Input */
.title-section {
padding: 16rpx 0;
border-bottom: 2rpx solid #f5f5f5;
margin-bottom: 16rpx;
}
.post-title-input {
font-size: 36rpx;
font-weight: 700;
color: #333;
width: 100%;
height: 64rpx; /* Height for single line */
min-height: 64rpx;
}
.title-placeholder {
color: #bbb;
font-weight: 400;
}