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:
@@ -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>
|
||||
|
||||
@@ -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, '操作失败'));
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user