2026-05-23-family-member-channel-select.md 10.0 KB

家庭成员渠道选择 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 在小程序新增/编辑家庭成员页面中,新增渠道单选项,从会员渠道列表中选择,保存时同步设置成员渠道。

Architecture: 仅修改 pagesMy/familyMemberVindicate.vue 一个文件。页面加载时并行获取会员渠道列表和成员当前渠道(编辑时),使用原生 <picker> 组件实现单选,保存成员后调 POST /app/member/setChannels 同步渠道。

Tech Stack: uni-app Vue 3 Composition API、微信小程序原生 picker、uview-plus


文件变更清单

操作 文件
Modify SxsnWechat/pagesMy/familyMemberVindicate.vue

Task 1: 加载会员渠道列表 + 编辑时回显成员渠道

Files:

  • Modify: SxsnWechat/pagesMy/familyMemberVindicate.vue

背景:

  • GET /app/channel/list 返回 { code: 0, data: [{ id, channelName, type, code }] }
  • GET /app/member/channelList?memberId=xxx 返回 { code: 0, data: [{ id, channelName }] },取第一个作为已选渠道(单选)
  • proxy.$api.get(url, params) 是项目封装的 GET 请求,返回 { data: res }

  • [ ] Step 1: 在 script 中新增渠道相关响应式变量

familyMemberVindicate.vue<script setup> 中,在 const qicShow = ref(false) 之后插入:

// 渠道相关
const channelList = ref([])          // 会员渠道列表(可选项)
const selectedChannelId = ref('')    // 已选渠道 ID(字符串)
const selectedChannelIndex = ref(-1) // picker 当前选中下标,-1 表示未选
  • Step 2: 新增 loadChannelList 函数

const changeMember = ... 之前插入:

const loadChannelList = () => {
  proxy.$api.get('/app/channel/list', {}).then(({ data: res }) => {
    if (res.code !== 0) return
    channelList.value = res.data || []
  })
}
  • Step 3: 新增 loadMemberChannel 函数(编辑时回显)

loadChannelList 之后插入:

const loadMemberChannel = (memberId) => {
  proxy.$api.get('/app/member/channelList', { memberId }).then(({ data: res }) => {
    if (res.code !== 0) return
    const list = res.data || []
    if (list.length > 0) {
      selectedChannelId.value = String(list[0].id)
      // 等 channelList 加载完后同步 index
      const idx = channelList.value.findIndex(c => String(c.id) === selectedChannelId.value)
      if (idx >= 0) selectedChannelIndex.value = idx
    }
  })
}
  • Step 4: 在 onLoad 中调用

找到 onLoad((options) => { 块,修改为:

onLoad((options) => {
  turnType.value = options.type
  loadChannelList()
  const id = options?.id
  if (id) {
    title.value = '编辑家庭成员'
    getMemberInfo(id)
    loadMemberChannel(id)
  }
})
  • Step 5: Commit
cd /workspace/sxsn/SxsnWechat
git add pagesMy/familyMemberVindicate.vue
git commit -m "feat: 加载会员渠道列表,编辑时回显成员渠道"

Task 2: 新增渠道选择 UI 行

Files:

  • Modify: SxsnWechat/pagesMy/familyMemberVindicate.vue

背景:

  • 现有 pre 行结构:<view class="pre adfac"> 包含 pre-title(左,209rpx)和 pre-content(右,flex-end)
  • 使用微信小程序原生 <picker> 组件,mode="selector":range="channelList":range-key="'channelName'"
  • picker@change 事件返回 e.detail.value(选中下标)

  • [ ] Step 1: 在「就读学校」行之后插入渠道选择行

找到:

<view class="pre adfac" v-if="memberInfo.personnelType==2">
  <view class="pre-title"><span>*</span>就读学校</view>
  <view class="pre-content">
    <input v-model="memberInfo.currentSchool" ... />
  </view>
</view>

在其后插入:

<view class="pre adfac">
  <view class="pre-title"><span style="color: #FFFFFF;">*</span>渠道</view>
  <view class="pre-content">
    <picker
      v-if="channelList.length > 0"
      mode="selector"
      :range="channelList"
      range-key="channelName"
      :value="selectedChannelIndex"
      @change="onChannelChange"
    >
      <view style="font-size: 30rpx; color: #252525; text-align: right;">
        {{ selectedChannelIndex >= 0 ? channelList[selectedChannelIndex].channelName : '请选择渠道' }}
      </view>
    </picker>
    <view v-else style="font-size: 28rpx; color: #A1A4A9; text-align: right;">暂无可用渠道</view>
  </view>
</view>
  • Step 2: 新增 onChannelChange 方法

loadMemberChannel 之后插入:

const onChannelChange = (e) => {
  const idx = e.detail.value
  selectedChannelIndex.value = idx
  selectedChannelId.value = String(channelList.value[idx].id)
}
  • Step 3: 手动验证 UI

在微信开发者工具中打开「添加家庭成员」页面,确认:

  • 渠道行出现在「就读学校」之后
  • 点击渠道行弹出 picker,可选择渠道
  • 选中后右侧显示渠道名称

  • [ ] Step 4: Commit

cd /workspace/sxsn/SxsnWechat
git add pagesMy/familyMemberVindicate.vue
git commit -m "feat: 家庭成员表单新增渠道选择行"

Task 3: 保存时同步设置成员渠道

Files:

  • Modify: SxsnWechat/pagesMy/familyMemberVindicate.vue

背景:

  • POST /app/member/setChannels 参数:memberId(Long)、channelIds(String,逗号分隔,单选时只有一个 ID)
  • 新增成员时,POST /core/family/member 成功后响应 res.data 包含新成员的 id
  • 编辑成员时,memberInfo.value.id 已有值
  • selectedChannelId 为空字符串,channelIds''(清空成员渠道,继承家长)
  • setChannels 失败只 Toast 提示,不阻断跳转

  • [ ] Step 1: 新增 setMemberChannel 辅助函数

onChannelChange 之后插入:

const setMemberChannel = (memberId) => {
  proxy.$api.post('/app/member/setChannels', {
    memberId,
    channelIds: selectedChannelId.value
  }).then(({ data: res }) => {
    if (res.code !== 0) proxy.$showToast(res.msg)
  }).catch(() => {
    proxy.$showToast('渠道设置失败,请稍后重试')
  })
}
  • Step 2: 修改 handleSave 中的保存逻辑

找到 handleSave 中的接口调用部分:

proxy.$api[memberInfo.value.id?'put':'post']('/core/family/member',memberInfo.value).then(({data:res})=>{
  if(res.code!==0) return proxy.$showToast(res.msg)
  proxy.$showToast(memberInfo.value.id?'编辑成功':'添加成功')
  setTimeout(()=>{
    if(turnType.value==='my'){
      uni.reLaunch({ url:'/pages/my' })
      return
    }
    uni.redirectTo({ url:'/pagesMy/familyMember' })
  },1000)
})

替换为:

proxy.$api[memberInfo.value.id ? 'put' : 'post']('/core/family/member', memberInfo.value).then(({ data: res }) => {
  if (res.code !== 0) return proxy.$showToast(res.msg)
  // 设置成员渠道(新增时用返回的 id,编辑时用已有 id)
  const memberId = memberInfo.value.id || res.data?.id
  if (memberId) {
    setMemberChannel(memberId)
  }
  proxy.$showToast(memberInfo.value.id ? '编辑成功' : '添加成功')
  setTimeout(() => {
    if (turnType.value === 'my') {
      uni.reLaunch({ url: '/pages/my' })
      return
    }
    uni.redirectTo({ url: '/pagesMy/familyMember' })
  }, 1000)
})
  • Step 3: 手动验证保存流程

在微信开发者工具中:

  1. 新增家庭成员,选择渠道,保存 → 确认 Network 中有 setChannels 请求,参数正确
  2. 编辑已有成员,修改渠道,保存 → 确认 setChannels 请求发出
  3. 编辑成员,不选渠道,保存 → 确认 setChannels 请求中 channelIds 为空字符串
  • Step 4: Commit
cd /workspace/sxsn/SxsnWechat
git add pagesMy/familyMemberVindicate.vue
git commit -m "feat: 保存家庭成员时同步设置渠道"

Task 4: 编辑时 channelList 加载后同步 selectedChannelIndex

Files:

  • Modify: SxsnWechat/pagesMy/familyMemberVindicate.vue

背景:loadChannelListloadMemberChannel 是并行请求,loadMemberChannel 可能在 channelList 还未填充时就执行了 findIndex,导致 index 找不到(返回 -1)。需要在 loadChannelList 完成后,若 selectedChannelId 已有值,补充同步 index。

  • Step 1: 修改 loadChannelList,加载完成后同步 index

loadChannelList 修改为:

const loadChannelList = () => {
  proxy.$api.get('/app/channel/list', {}).then(({ data: res }) => {
    if (res.code !== 0) return
    channelList.value = res.data || []
    // 若 loadMemberChannel 已先完成并设置了 selectedChannelId,补充同步 index
    if (selectedChannelId.value) {
      const idx = channelList.value.findIndex(c => String(c.id) === selectedChannelId.value)
      if (idx >= 0) selectedChannelIndex.value = idx
    }
  })
}
  • Step 2: 手动验证编辑回显

在微信开发者工具中打开已有家庭成员的编辑页面,确认:

  • 渠道行正确显示该成员已设置的渠道名称(而非「请选择渠道」)

  • [ ] Step 3: Commit

cd /workspace/sxsn/SxsnWechat
git add pagesMy/familyMemberVindicate.vue
git commit -m "fix: 修复编辑时渠道回显竞态问题"

自检清单

  • 规格「新增/编辑时显示渠道选择行」→ Task 2
  • 规格「渠道单选,从会员渠道列表中选择」→ Task 1(loadChannelList)+ Task 2(picker)
  • 规格「编辑时回显已设置渠道」→ Task 1(loadMemberChannel)+ Task 4(竞态修复)
  • 规格「保存时调 setChannels」→ Task 3
  • 规格「渠道非必填」→ Task 2(无必填校验)+ Task 3(memberId 为空时跳过)
  • 规格「渠道列表为空时显示暂无可用渠道」→ Task 2(v-else)
  • 规格「setChannels 失败只 Toast,不阻断跳转」→ Task 3 Step 1(catch 只 Toast)
  • 无 placeholder,所有步骤含完整代码
  • selectedChannelId 类型统一为字符串(String(c.id)),避免雪花 ID 精度问题