feat: 发帖去身份用昵称、标签对齐筛选、图片限2、无类型任务也留痕

- 发帖去掉「发布身份」选择,统一用发布者昵称(后端按 user 取昵称)
- 发帖标签改成 晒宠/新手求助/经验,和社区顶部筛选完全一致;
  tabTag 新手求助→新手求助(原来映射成「求助」对不上)
- 内容输入框:点整块 field 都聚焦(原生 textarea 在 scroll-view 里
  命中区域会偏,只有 placeholder 处能点)
- 发帖图片上限 3→2,文案标注「最多 2 张」
- 无记录类型的自定义任务完成后,补一条 note 记录,最近记录里留痕

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-31 14:12:52 +08:00
parent b52729dec8
commit a91f5e39ca
4 changed files with 34 additions and 37 deletions
+8 -17
View File
@@ -48,7 +48,7 @@ func (s *Service) attachPostImages(posts []model.Post) {
func tabTag(tab string) string {
switch tab {
case "新手求助":
return "求助"
return "新手求助"
case "晒宠":
return "晒宠"
case "经验":
@@ -111,23 +111,14 @@ type PostInput struct {
// CreatePost 发帖
func (s *Service) CreatePost(userID string, in PostInput) (*model.Post, error) {
authorName := "匿名宠友"
authorEmoji := "🐾"
switch in.Identity {
case "official":
authorName = "肉垫计划官方"
case "petName":
if in.PetID != nil {
var pet model.Pet
if err := s.db.First(&pet, *in.PetID).Error; err == nil {
authorName = pet.Name + "的铲屎官"
authorEmoji = pet.Emoji
}
}
}
// 取作者 openid(内容安全接口 v2 要求带上),并把图片 file id 解析成可访问 URL
// 取作者信息:统一用发布者昵称(去掉了发布身份选择),openid 给内容安全接口用
var user model.User
s.db.Select("id, open_id").First(&user, userID)
s.db.Select("id, open_id, nickname").First(&user, userID)
authorName := user.Nickname
if authorName == "" {
authorName = "宠友"
}
authorEmoji := "🐾"
imgURLs := s.resolveImageURLs(in.ImageFileIDs)
// 发布前过内容安全:文本同步判、图片提交异步查。检测不了或有图 → 待人工/待回调
@@ -43,8 +43,8 @@ const REMINDER_TYPES = [
const REMINDER_LABELS = REMINDER_TYPES.map((t) => t.label);
const IDENTITY = ['petName', 'anonymous', 'official'];
const PTAG = ['晒宠', '求助', '经验', '避坑'];
// 标签和社区顶部筛选保持一致(晒宠 / 新手求助 / 经验)
const PTAG = ['晒宠', '新手求助', '经验'];
Component({
options: { addGlobalClass: true },
@@ -61,6 +61,7 @@ Component({
optSel: {},
// 通用简易记录(洗护/清洁那 15 种共用)
postContent: '',
pfFocus: false, // 发帖内容框聚焦标记(点整块 field 聚焦用)
postImages: [],
remForm: { id: '', typeIdx: 0, title: '', date: '', freq: '' },
remTypeLabels: REMINDER_LABELS,
@@ -345,6 +346,9 @@ Component({
this.setData({ optSel });
},
onPostInput(e) { this.setData({ postContent: e.detail.value }); },
// 点内容 field 任意处都聚焦(原生 textarea 在 scroll-view 里命中区域会偏)
onPostFieldTap() { this.setData({ pfFocus: true }); },
onPostBlur() { this.setData({ pfFocus: false }); },
loadComments() {
if (!this.data.postId) return;
api.listComments(this.data.postId)
@@ -539,8 +543,8 @@ Component({
api.getTasks(id).then((tasks) => this.setData({ manageTasks: tasks || [] })).catch(() => {});
},
onPickPostImages() {
const left = 3 - this.data.postImages.length;
if (left <= 0) return wx.showToast({ title: '最多 3 张', icon: 'none' });
const left = 2 - this.data.postImages.length;
if (left <= 0) return wx.showToast({ title: '最多 2 张', icon: 'none' });
upload
.chooseAndUploadImages(left)
.then((list) => this.setData({ postImages: this.data.postImages.concat(list) }))
@@ -604,14 +608,13 @@ Component({
async onCreatePost() {
const content = (this.data.postContent || '').trim();
if (!content) return wx.showToast({ title: '写点什么吧', icon: 'none' });
const identity = IDENTITY[this.segIdx('ident')];
const tag = PTAG[this.data.optSel.ptag === undefined ? 0 : this.data.optSel.ptag];
if (this.data.saving) return;
this.setData({ saving: true });
try {
// 去掉发布身份,统一用发布者昵称(后端按 user 取昵称)
const post = await api.createPost({
pet_id: identity === 'petName' ? store.currentPetId() : null,
identity,
identity: 'user',
content,
tags: [tag],
image_file_ids: this.data.postImages.map((i) => i.id),
@@ -201,27 +201,22 @@ module.exports.sel = function (map, key, index, def) {
→ 其他资料),品种从后端 breeds 表来、按首字母索引。弹层塞不下这些 -->
<block wx:elif="{{innerType === 'createPost'}}">
<view class="sheet-h3">发布图文</view>
<view class="sheet-p">选择发布身份,分享你的养宠日常。</view>
<view class="field"><label>发布身份</label><view class="seg">
<view class="seg-btn {{u.sel(segSel,'ident',0,0)?'selected':''}}" data-group="ident" data-index="0" bindtap="onSeg">{{pet.name}}</view>
<view class="seg-btn {{u.sel(segSel,'ident',1,0)?'selected':''}}" data-group="ident" data-index="1" bindtap="onSeg">匿名宠友</view>
<view class="seg-btn {{u.sel(segSel,'ident',2,0)?'selected':''}}" data-group="ident" data-index="2" bindtap="onSeg">官方笔记</view>
</view></view>
<view class="field"><label>内容</label>
<textarea class="textarea" placeholder="分享养宠日常、求助问题、经验笔记..." placeholder-class="placeholder" value="{{postContent}}" bindinput="onPostInput"></textarea></view>
<view class="sheet-p">用你的昵称分享养宠日常。</view>
<!-- 点整块 field 都能聚焦:原生 textarea 在 scroll-view 里命中区域会偏 -->
<view class="field" bindtap="onPostFieldTap"><label>内容</label>
<textarea class="textarea" focus="{{pfFocus}}" placeholder="分享养宠日常、求助问题、经验笔记..." placeholder-class="placeholder" value="{{postContent}}" bindinput="onPostInput" bindblur="onPostBlur"></textarea></view>
<view class="mini-options">
<view class="option {{u.sel(optSel,'ptag',0,0)?'selected':''}}" data-group="ptag" data-index="0" bindtap="onOpt">晒宠</view>
<view class="option {{u.sel(optSel,'ptag',1,0)?'selected':''}}" data-group="ptag" data-index="1" bindtap="onOpt">求助</view>
<view class="option {{u.sel(optSel,'ptag',1,0)?'selected':''}}" data-group="ptag" data-index="1" bindtap="onOpt">新手求助</view>
<view class="option {{u.sel(optSel,'ptag',2,0)?'selected':''}}" data-group="ptag" data-index="2" bindtap="onOpt">经验</view>
<view class="option {{u.sel(optSel,'ptag',3,0)?'selected':''}}" data-group="ptag" data-index="3" bindtap="onOpt">避坑</view>
</view>
<view class="field"><label>图片(可选,仅图片</label>
<view class="field"><label>图片(可选,最多 2 张</label>
<view class="img-picker">
<view wx:for="{{postImages}}" wx:key="id" class="img-thumb">
<image src="{{item.url}}" mode="aspectFill"></image>
<view class="img-del" catchtap="onRemovePostImage" data-index="{{index}}"><pt-icon name="close" size="{{24}}"></pt-icon></view>
</view>
<view wx:if="{{postImages.length < 9}}" class="img-add" bindtap="onPickPostImages"><pt-icon name="plus" size="{{48}}"></pt-icon></view>
<view wx:if="{{postImages.length < 2}}" class="img-add" bindtap="onPickPostImages"><pt-icon name="plus" size="{{48}}"></pt-icon></view>
</view>
</view>
<button class="btn btn-primary btn-block" bindtap="onCreatePost">发布到宠友圈</button>
+9 -1
View File
@@ -180,13 +180,21 @@ Page({
wx.navigateTo({ url });
return;
}
// 没有关联记录类型的任务(如遛狗),直接切换完成
// 没有关联记录类型的任务(自定义/无 sheet_type):直接切换完成
// 并且切到「完成」时补一条 note 记录,这样最近记录里也留痕
api
.toggleTask(t.id)
.then((res) => {
const tasks = this.data.tasks.slice();
tasks[i] = Object.assign({}, tasks[i], { done: res.done });
this.setData({ tasks });
if (!res.done) return; // 取消完成就不建记录
const pid = store.currentPetId();
if (!pid) return;
return api
.createRecord(pid, { type: 'note', title: '完成:' + t.title })
.then(() => this.loadTimeline(1))
.catch(() => {}); // 建记录失败不影响任务已完成
})
.catch((err) => toastErr(err, '操作失败'));
},