Files
sundynix-pets/pets-fe/pages/plan/plan.wxml
T
Blizzard 9b30bfaaff feat: 计划按自然月管理,加「应用到每天」和下月未排提醒
## 为什么不是「从计划开始日起 30 天」
上一版是那样做的,截图一看就不对:计划是月中建的,日历显示
「7月26日 — 8月25日」,既不像本月也不像下月,用户想问「这个月还剩什么」
根本对不上。改成自然月,日历就是一眼能认的月历。

能翻到下月 —— 否则「做下月计划」这件事本身做不了。

## 校验从「Day 上限」改成「日期」
PlanTask.Day 是相对计划开始日的,月份边界是相对今天的,两者会错开。
原来卡 Day<=30,计划建了几天之后下月末就换算成 Day=40 多,
用户在日历上明明看得到那格、点进去却存不了。

现在的规则:不早于计划开始日(下界放到开始日而不是本月 1 号——模板生成的
历史节点可能在上个月,那些要允许原地改),不晚于下月月底。

## 应用到每天
一天建一条,不做「一条 + repeat 字段读时展开」:勾选状态是按天的,
展开方案还得再开一张表记「哪天打过勾」,而直接建 N 条天然就有这个能力。

范围止于**这一天所在那个月**的月底,不跨月——「应用到每天」说的是这个月每天,
跨过去就变成用户没要求的事了。只有新增能选,已有的那条改成每天等于凭空
复制 N 份(用户想要的是「以后每天」,不是「把这条撒开」)。

## 首页那个提醒
GET /pets/:id/plan/month-status 返回本月件数/剩余、下月件数、need_next。

need_next 只在**月末最后 7 天**且下月为空时为真:月初就催「排下个月」太早,
用户会当成噪音。角标做在图标上而不是弹 toast——每次进首页弹一下很烦,
而这件事不紧急、看见就行。

副标题有优先级:「8 月计划还没排」压过「本月都做完了」,因为前者有时效。
四种状态实跑验过,包括让位关系。

## 顺手
pet-switch 加 show-add 属性。计划页只需要在既有宠物之间切,建档入口在首页
和「我的」就够了,到处摆一个「添加」会让这条 chip 变得很长。

本月/下月的切换用新的 .link-tabs 而不是挂在 .head-links 上:首页的
「管理 / 全部完成」也用 head-links,那是两个并列动作,不该有一个是灰的。

## 验证(预生产库实跑)
  月边界     本月末通过、下月末通过、下下月拒(报出具体日期)
  应用到每天  今天→本月末 2 条,没跨月
  month-status  下月清空 → need_next 翻 true;补一条 → 翻回 false
  四种副标题  下月未排 / 本月还有 N 件 / 本月都做完了 / 还没有安排,含优先级
  测试数据全部还原

上一条 cd 打错目录,导致「日期窗口」那次改动没写进文件、只有批量那半截进去了,
所以中间出现过一次 planWindow undefined。这次一并改对。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 11:09:06 +08:00

121 lines
6.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<nav-bar title="养宠计划" show-back="{{true}}"></nav-bar>
<view class="top-bar"><pet-switch show-add="{{false}}"></pet-switch></view>
<scroll-view class="page-scroll" scroll-y="{{true}}" enhanced="{{true}}" show-scrollbar="{{false}}">
<view class="page-body">
<view wx:if="{{!pet.id}}" class="no-pet">
<view class="no-pet-ic"><pt-icon name="community" size="{{52}}"></pt-icon></view>
<view class="no-pet-b">还没有毛孩子的档案</view>
<view class="no-pet-p">建好档会按它的年龄阶段自动排好 30 天计划和疫苗驱虫提醒。</view>
<view class="btn btn-dark" bindtap="onAddPet"><pt-icon name="plus" size="{{30}}"></pt-icon>建一份档案</view>
</view>
<block wx:else>
<view class="card">
<view class="section-head">
<view class="sh-title">{{pet.name}}的 30 天计划</view>
<view class="tag warn">{{plan.completion_pct || 0}}%</view>
</view>
<view class="progress-row"><text>完成度</text><text>{{plan.completion_pct || 0}}%</text></view>
<view class="bar"><view class="bar-fill" style="width:{{plan.completion_pct || 0}}%"></view></view>
</view>
<!-- 月历。按自然月切而不是「从计划开始日起 30 天」:那样窗口会跨两个月,
用户看着 7月26日—8月25日 既不像本月也不像下月,「这个月还剩什么」对不上。
能翻到下月,否则「做下月计划」这件事本身做不了 -->
<view class="card">
<view class="section-head">
<view class="sh-title">{{monthLabel}}</view>
<view class="link-tabs">
<view class="link {{monthOff === 0 ? 'on' : ''}}" data-off="0" bindtap="switchMonth">本月</view>
<view class="link {{monthOff === 1 ? 'on' : ''}}" data-off="1" bindtap="switchMonth">下月</view>
</view>
</view>
<view wx:if="{{monthOff === 1 && !nextCount}}" class="plan-tip">
<pt-icon name="warn" size="{{28}}"></pt-icon>{{monthLabel}}还没有安排,点某天加几件
</view>
<view class="cal-grid">
<text class="cal-w">一</text><text class="cal-w">二</text><text class="cal-w">三</text><text class="cal-w">四</text><text class="cal-w">五</text><text class="cal-w">六</text><text class="cal-w">日</text>
<view wx:for="{{cells}}" wx:key="index"
class="cal-cell {{item.blank ? 'blank' : ''}} {{item.today ? 'today' : ''}} {{item.count ? 'tasked' : ''}} {{item.date === selDate ? 'sel' : ''}}"
data-date="{{item.date}}" bindtap="onTapDay">{{item.day || ''}}</view>
</view>
</view>
<!-- 选中那天的安排 -->
<view class="card">
<view class="section-head">
<view class="sh-title">{{selLabel}}</view>
<view class="link" bindtap="openAdd"> 加一件</view>
</view>
<view wx:for="{{dayTasks}}" wx:key="id" class="plan-task {{item.done ? 'done' : ''}}">
<view class="pk-check" catchtap="toggleTask" data-id="{{item.id}}">
<pt-icon wx:if="{{item.done}}" name="check" size="{{22}}"></pt-icon>
</view>
<view class="pk-body" data-id="{{item.id}}" bindtap="openEdit">
<text class="pk-b">{{item.title}}</text>
<view wx:if="{{item.description}}" class="pk-p">{{item.description}}</view>
</view>
<view class="pk-del" catchtap="onDelete" data-id="{{item.id}}" data-title="{{item.title}}">
<pt-icon name="trash" size="{{28}}"></pt-icon>
</view>
</view>
<view wx:if="{{!dayTasks.length}}" class="empty">这天还没有安排,点右上角加一件</view>
</view>
<!-- 全部 30 天的路线图,折叠着 -->
<view class="card">
<view class="section-head">
<view class="sh-title">完整路线图</view>
<view class="link" bindtap="toggleAll">{{allOpen ? '收起' : '展开全部'}}</view>
</view>
<block wx:if="{{allOpen}}">
<view wx:for="{{plan.tasks}}" wx:key="id" class="time-block">
<view class="time-label">{{item.day_label}}<text wx:if="{{item.dateLabel}}" class="time-date">{{item.dateLabel}}</text></view>
<view class="plan-task {{item.done ? 'done' : ''}}">
<view class="pk-check" catchtap="toggleTask" data-id="{{item.id}}">
<pt-icon wx:if="{{item.done}}" name="check" size="{{22}}"></pt-icon>
</view>
<view class="pk-body"><text class="pk-b">{{item.title}}</text><view class="pk-p">{{item.description}}</view></view>
</view>
</view>
<view wx:if="{{!plan.tasks.length}}" class="empty">暂无计划</view>
</block>
<view wx:else class="tiny">共 {{plan.tasks.length || 0}} 件事,已完成 {{doneCount}} 件</view>
</view>
</block>
</view>
</scroll-view>
<!-- 加/改一条计划。字段少,用弹层比再开一页合适 -->
<view wx:if="{{editShow}}" class="pe-mask" bindtap="closeEdit">
<view class="pe-sheet" catchtap="noop">
<view class="pe-h">{{editId ? '改这件事' : '加一件事'}}</view>
<view class="field"><label>做什么</label>
<input class="input" placeholder="比如 带去打第二针" placeholder-class="placeholder"
value="{{form.title}}" bindinput="onFormTitle"/></view>
<view class="field"><label>哪天</label>
<picker mode="date" value="{{form.date}}" start="{{pickStart}}" end="{{pickEnd}}" bindchange="onFormDate">
<view class="picker-box">{{form.date}}</view>
</picker>
<view class="tiny">只能安排 {{pickStart}} 到 {{pickEnd}} 之间</view>
</view>
<view class="field"><label>备注</label>
<textarea class="textarea" placeholder="可不填" placeholder-class="placeholder"
value="{{form.description}}" bindinput="onFormDesc"></textarea></view>
<!-- 只有新增能选「每天」:已有的那条改成每天等于凭空复制 29 份,
用户想要的是「以后每天」,不是「把这条撒开」 -->
<view wx:if="{{!editId}}" class="field pe-daily">
<view class="pe-daily-main">
<view class="tt-b">应用到每天</view>
<view class="tt-p">从这天排到 {{monthEndLabel}},每天一条,可以分别打勾</view>
</view>
<switch checked="{{form.daily}}" color="#F5A947" bindchange="onFormDaily"></switch>
</view>
<view class="btn btn-primary btn-block" bindtap="onSubmit">{{saving ? '保存中…' : '保存'}}</view>
</view>
</view>
<bottom-sheet show="{{sheetShow}}" type="{{sheetType}}" bind:close="closeSheet"></bottom-sheet>