From 527b0e8a8d5d4f2e32dcc6c71ae8ad87ed7b4d03 Mon Sep 17 00:00:00 2001
From: cheng <545895878@qq.com>
Date: Wed, 5 Aug 2026 22:58:26 +0800
Subject: [PATCH] =?UTF-8?q?feat(event):=20=E6=B7=BB=E5=8A=A0=E9=85=92?=
=?UTF-8?q?=E5=B1=80=E7=BC=96=E8=BE=91=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除 UniAppWebSocket 类实现,使用独立的 websocket 模块
- 添加 UpdateEvent 和 DeleteEvent API 接口
- 在 EventCard 组件中添加发起人管理操作按钮
- 实现酒局状态数字枚举到字符串的映射转换
- 在 circle 页面集成编辑删除事件处理
- 重构 event-create 页面支持编辑模式
- 在 event-detail 页面添加发起人操作区域
- 实现删除确认对话框和页面返回刷新逻辑
---
common/api.js | 150 +++-------------------------
components/EventCard.vue | 53 ++++++++--
pages/circle/circle.vue | 28 +++++-
pages/event-create/event-create.vue | 81 +++++++++++----
pages/event-detail/event-detail.vue | 83 ++++++++++++---
5 files changed, 223 insertions(+), 172 deletions(-)
diff --git a/common/api.js b/common/api.js
index f2c1f58..9b4a3c7 100644
--- a/common/api.js
+++ b/common/api.js
@@ -107,144 +107,9 @@ function uploadRequest(url, params) {
})
}
-/**
- * 使用 uni-app WebSocket API 实现的 WebSocket 类
- * 符合之前定义的 WebsocketInterface(无类型约束)
- */
-class UniAppWebSocket {
- /**
- * 构造函数:传入 WebSocket 服务器地址
- * @param {string} host - 完整的 WebSocket URL,例如 'wss://example.com/ws'
- */
- constructor(host) {
- this.host = host;
- // 事件回调属性(外部可赋值)
- this.close = null; // 可赋值为函数,同时也可用主动关闭连接
- this.onopen = null;
- this.onmessage = null;
- // 内部 SocketTask 实例
- this.socketTask = null;
- // 初始化连接
- this._initSocket();
- }
-
- /**
- * 初始化 WebSocket 连接(私有方法,约定以 _ 开头)
- */
- _initSocket() {
- const self = this;
-
- // 创建 SocketTask
- this.socketTask = uni.connectSocket({
- url: this.host,
- success() {
- // 连接创建成功(但尚未打开)
- },
- fail(err) {
- // 连接创建失败,触发错误事件
- const errorEvent = { type: 'error', error: err, target: self };
- self.onerror(errorEvent);
- }
- });
-
- // 监听打开事件
- this.socketTask.onOpen((res) => {
- if (self.onopen) {
- // 构造一个简单的事件对象
- const event = { type: 'open', target: self, ...res };
- self.onopen(event);
- }
- });
-
- // 监听消息事件
- this.socketTask.onMessage((res) => {
- if (self.onmessage) {
- // res.data 是消息数据
- const event = {
- type: 'message',
- data: res.data,
- target: self
- };
- self.onmessage(event);
- }
- });
-
- // 监听关闭事件
- this.socketTask.onClose((res) => {
- // 构造关闭事件
- const event = {
- type: 'close',
- code: res.code,
- reason: res.reason,
- wasClean: res.wasClean,
- target: self
- };
- // 调用 onclose 方法(可被重写)
- self.onclose(event);
- });
-
- // 监听错误事件
- this.socketTask.onError((err) => {
- const errorEvent = { type: 'error', error: err, target: self };
- self.onerror(errorEvent);
- });
-
- // 将 close 属性设置为一个可调用函数,用于主动断开连接
- // 同时也满足接口的 “回调类型” 定义
- this.close = function(ev) {
- if (self.socketTask) {
- const code = ev && ev.code ? ev.code : 1000;
- const reason = ev && ev.reason ? ev.reason : '';
- self.socketTask.close({ code, reason });
- }
- // 如果作为回调函数,返回 null 即可(无实际意义)
- return null;
- };
- }
-
- /**
- * 关闭事件处理方法(可被外部重写)
- * @param {Object} event - 关闭事件对象
- */
- onclose(event) {
- // 默认空实现,你可以在外部覆盖此方法
- // console.log('连接已关闭', event);
- }
-
- /**
- * 错误事件处理方法(可被外部重写)
- * @param {Object} event - 错误事件对象
- */
- onerror(event) {
- // 默认空实现
- // console.error('连接错误', event);
- }
-
- /**
- * 发送数据
- * @param {string|ArrayBuffer|Blob} data - 要发送的数据
- * @throws {Error} 如果 WebSocket 未初始化
- */
- send(data) {
- if (!this.socketTask) {
- throw new Error('WebSocket 未初始化,无法发送数据');
- }
- this.socketTask.send({
- data: data,
- success() {
- // 发送成功,可添加日志
- },
- fail(err) {
- // 发送失败,触发错误事件
- const errorEvent = { type: 'error', error: err, target: this };
- this.onerror(errorEvent);
- }
- });
- }
-}
-
// ==========================================
// 初始化 SDK 实例
+// (WebSocket 适配器使用 common/uni-websocket.js,已修复 wx.connectSocket 降级问题)
// ==========================================
const client = new HaveADrink({
host: API_HOST,
@@ -397,6 +262,19 @@ export async function CreateEvent({ title, time, location, maxPeople, note, lati
return { data: res }
}
+/** 修改酒局(仅发起人可改,后端会校验归属) */
+export async function UpdateEvent({ eventId, title, time, location, maxPeople, note, latitude, longitude }) {
+ const geo = (latitude != null && longitude != null) ? { latitude, longitude } : undefined
+ const res = await client.UpdateEvent({ id: eventId, title, time, location, maxPeople, geo, note })
+ return { data: res }
+}
+
+/** 删除酒局(仅发起人可删,后端会校验归属) */
+export async function DeleteEvent({ eventId }) {
+ const res = await client.DeleteEvent({ id: eventId })
+ return { data: res }
+}
+
/** 报名酒局 */
export async function JoinEvent({ eventId }) {
const res = await client.JoinEvent({ id: eventId })
diff --git a/components/EventCard.vue b/components/EventCard.vue
index 093353e..b85d49f 100644
--- a/components/EventCard.vue
+++ b/components/EventCard.vue
@@ -1,7 +1,7 @@
-
+
{{ statusLabel }}
@@ -32,7 +32,16 @@
{{ event.organizer ? event.organizer.nickname : '' }}
-
+
+
+
+ ✏️ 编辑
+
+
+ 🗑️ 删除
+
+
+
✓ 已报名
报名
@@ -44,14 +53,21 @@
export default {
name: 'EventCard',
props: {
- event: { type: Object, default: () => ({}) }
+ event: { type: Object, default: () => ({}) },
+ /** 是否为发起人(可编辑/删除) */
+ canManage: { type: Boolean, default: false }
},
- emits: ['item-click'],
+ emits: ['item-click', 'edit', 'delete'],
computed: {
+ /** 后端状态为数字枚举:1=报名中 2=待开始 3=进行中 4=已结束(兼容字符串返回) */
+ statusKey() {
+ const map = { 1: 'open', 2: 'upcoming', 3: 'ongoing', 4: 'ended' }
+ const raw = this.event.status
+ return map[Number(raw)] || String(raw).toLowerCase()
+ },
statusLabel() {
- const val = String(this.event.status).toLowerCase()
const map = { open: '报名中', upcoming: '待开始', ongoing: '进行中', ended: '已结束' }
- return map[val] || '报名中'
+ return map[this.statusKey] || '报名中'
}
}
}
@@ -182,4 +198,29 @@ export default {
background: linear-gradient(135deg, $amber, $amber-deep);
font-weight: $fw-bold;
}
+
+.event-manage {
+ display: flex;
+ align-items: center;
+ gap: $sp-md;
+}
+
+.event-manage-btn {
+ padding: 8rpx 20rpx;
+ border-radius: $radius-full;
+ background: $bg-elevated;
+
+ &:active {
+ opacity: 0.7;
+ }
+}
+
+.event-manage-text {
+ font-size: $fs-sm;
+ color: $text-secondary;
+}
+
+.event-manage-del {
+ color: $coral;
+}
diff --git a/pages/circle/circle.vue b/pages/circle/circle.vue
index 6a2ed0f..7e917bf 100644
--- a/pages/circle/circle.vue
+++ b/pages/circle/circle.vue
@@ -109,6 +109,9 @@
v-for="evt in events"
:key="evt.id"
:event="evt"
+ :can-manage="evt.isOrganizer === true"
+ @edit="goEditEvent"
+ @delete="confirmDeleteEvent"
@item-click="goEventDetail"
/>
{
+ if (!res.confirm) return
+ try {
+ await DeleteEvent({ eventId: evt.id })
+ this.events = this.events.filter(e => String(e.id) !== String(evt.id))
+ uni.showToast({ title: '已删除', icon: 'none' })
+ } catch (e) {
+ // httpRequest 已全局弹错误提示(如非本人酒局后端会拒绝)
+ }
+ }
+ })
+ },
goCreateEvent() {
uni.navigateTo({ url: '/pages/event-create/event-create' })
},
diff --git a/pages/event-create/event-create.vue b/pages/event-create/event-create.vue
index 98fbc9c..30d96ff 100644
--- a/pages/event-create/event-create.vue
+++ b/pages/event-create/event-create.vue
@@ -6,7 +6,7 @@
‹
- 发起酒局
+ {{ isEdit ? '编辑酒局' : '发起酒局' }}
@@ -98,9 +98,9 @@
/>
-
+
@@ -108,7 +108,7 @@