Explorar el Código

feat(pearl): 提醒列表页 + PearlController 5 接口补齐 + pages.json 路由修正

Sisyphus Agent hace 1 mes
padre
commit
2fb1fab6a1

+ 45 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/PearlController.java

@@ -43,4 +43,49 @@ public class PearlController {
                 ? Long.valueOf(params.get("itemId").toString()) : null;
         return resourceService.deleteResourceItem(userId, itemId);
     }
+
+    /** 获取 25 类连接类型列表 */
+    @PostMapping("/connection-types")
+    public Result<List<Map<String, Object>>> connectionTypes() {
+        return Result.success(resourceService.getConnectionTypes());
+    }
+
+    /** 记录互动 */
+    @PostMapping("/interaction/add")
+    public Result<Void> addInteraction(@RequestBody Map<String, Object> params,
+                                       @RequestAttribute("userId") Long userId) {
+        Long itemId = params.get("itemId") != null
+                ? Long.valueOf(params.get("itemId").toString()) : null;
+        String interactionType = (String) params.get("interactionType");
+        String content = (String) params.get("content");
+        return resourceService.addInteraction(userId, itemId, interactionType, content);
+    }
+
+    /** 互动历史 */
+    @PostMapping("/interaction/list")
+    public Result<List<Map<String, Object>>> interactionList(@RequestBody Map<String, Object> params,
+                                                             @RequestAttribute("userId") Long userId) {
+        Long itemId = params.get("itemId") != null
+                ? Long.valueOf(params.get("itemId").toString()) : null;
+        int page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
+        int size = params.get("size") != null ? Integer.parseInt(params.get("size").toString()) : 5;
+        return resourceService.getInteractionList(userId, itemId, page, size);
+    }
+
+    /** 待办提醒列表 */
+    @PostMapping("/reminder/list")
+    public Result<List<Map<String, Object>>> reminders(@RequestAttribute("userId") Long userId) {
+        return resourceService.getReminders(userId);
+    }
+
+    /** 手动覆盖优先级 */
+    @PostMapping("/item/update-priority")
+    public Result<Void> updatePriority(@RequestBody Map<String, Object> params,
+                                       @RequestAttribute("userId") Long userId) {
+        Long itemId = params.get("itemId") != null
+                ? Long.valueOf(params.get("itemId").toString()) : null;
+        Integer priority = params.get("priority") != null
+                ? Integer.valueOf(params.get("priority").toString()) : null;
+        return resourceService.updatePriority(userId, itemId, priority);
+    }
 }

+ 11 - 6
cfc-frontend/pages.json

@@ -1258,12 +1258,6 @@
           "style": {
             "navigationBarTitleText": "登记资源"
           }
-        },
-        {
-          "path": "pearl-reminders/index",
-          "style": {
-            "navigationBarTitleText": "互动提醒"
-          }
         }
       ]
     },
@@ -1735,6 +1729,17 @@
           }
         }
       ]
+    },
+    {
+      "root": "pages/pearl-reminders",
+      "pages": [
+        {
+          "path": "index",
+          "style": {
+            "navigationBarTitleText": "互动提醒"
+          }
+        }
+      ]
     }
   ],
   "globalStyle": {

+ 170 - 0
cfc-frontend/pages/pearl-reminders/index.vue

@@ -0,0 +1,170 @@
+<template>
+  <view class="container">
+    <view class="page-header">
+      <text class="page-title">互动提醒</text>
+      <text class="page-sub" v-if="reminders.length > 0">{{ reminders.length }} 个连接该联系了</text>
+    </view>
+
+    <view class="reminder-list" v-if="reminders.length > 0">
+      <view class="reminder-item" v-for="(r, idx) in reminders" :key="idx">
+        <view class="reminder-info">
+          <text class="reminder-name">{{ r.name }}</text>
+          <text class="reminder-tag">{{ r.connectionType }}</text>
+          <text class="reminder-days">已 {{ r.daysSinceLast }} 天未互动(建议每 {{ r.suggestIntervalMonth }} 个月)</text>
+        </view>
+        <view class="reminder-actions">
+          <text class="btn-contact" @tap="onContact(r)">去联系</text>
+          <text class="btn-later" @tap="onLater(r)">稍后</text>
+        </view>
+      </view>
+    </view>
+
+    <view class="empty" v-else>
+      <text class="empty-icon">🎉</text>
+      <text class="empty-text">所有连接都在维护中</text>
+    </view>
+  </view>
+</template>
+
+<script>
+import { getPearlReminders, addPearlInteraction } from '../../utils/api.js'
+
+export default {
+  data() {
+    return {
+      reminders: []
+    }
+  },
+  onShow() {
+    this.loadReminders()
+  },
+  methods: {
+    async loadReminders() {
+      try {
+        var res = await getPearlReminders()
+        if (res.code === 200 && res.data) {
+          this.reminders = res.data
+        }
+      } catch (e) {
+        uni.showToast({ title: '加载失败', icon: 'none' })
+      }
+    },
+    onContact(r) {
+      var self = this
+      uni.showActionSheet({
+        itemList: ['电话', '微信', '见面', '其他'],
+        success: function(res) {
+          var types = ['PHONE', 'WECHAT', 'MEETING', 'OTHER']
+          addPearlInteraction({
+            itemId: r.resourceItemId,
+            interactionType: types[res.tapIndex],
+            content: ''
+          }).then(function(resp) {
+            if (resp.code === 200) {
+              uni.showToast({ title: '已记录', icon: 'success' })
+              self.loadReminders()
+            } else {
+              uni.showToast({ title: resp.message || '记录失败', icon: 'none' })
+            }
+          })
+        }
+      })
+    },
+    onLater(r) {
+      // 暂不支持 DISMISS,直接刷新
+      this.loadReminders()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.container {
+  min-height: 100vh;
+  background: #f5f5f5;
+  padding: 24rpx;
+}
+.page-header {
+  padding: 20rpx 0 30rpx;
+}
+.page-title {
+  font-size: 36rpx;
+  font-weight: bold;
+  color: #333;
+}
+.page-sub {
+  font-size: 26rpx;
+  color: #999;
+  margin-top: 8rpx;
+  display: block;
+}
+.reminder-list {
+  display: flex;
+  flex-direction: column;
+  gap: 20rpx;
+}
+.reminder-item {
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 24rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.reminder-info {
+  flex: 1;
+}
+.reminder-name {
+  font-size: 30rpx;
+  font-weight: 600;
+  color: #333;
+  display: block;
+}
+.reminder-tag {
+  font-size: 22rpx;
+  color: #F97316;
+  background: #FFF7ED;
+  border-radius: 6rpx;
+  padding: 4rpx 12rpx;
+  margin-top: 8rpx;
+  display: inline-block;
+}
+.reminder-days {
+  font-size: 24rpx;
+  color: #999;
+  display: block;
+  margin-top: 8rpx;
+}
+.reminder-actions {
+  display: flex;
+  gap: 16rpx;
+}
+.btn-contact {
+  background: #F97316;
+  color: #fff;
+  border-radius: 999rpx;
+  padding: 12rpx 28rpx;
+  font-size: 26rpx;
+}
+.btn-later {
+  border: 2rpx solid #e0e0e0;
+  color: #666;
+  border-radius: 999rpx;
+  padding: 12rpx 28rpx;
+  font-size: 26rpx;
+}
+.empty {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding-top: 200rpx;
+}
+.empty-icon {
+  font-size: 80rpx;
+}
+.empty-text {
+  font-size: 28rpx;
+  color: #999;
+  margin-top: 20rpx;
+}
+</style>