# **MMessage.action 钩子扩展指南**

## **什么是钩子**

通过钩子机制，您可以在动作执行后拦截并自定义：

- 成功/失败/警告/确认等提示信息
- 页面跳转、关闭、刷新行为

---

## **快速开始**

### **第一步：引入依赖**

```
import { regHook } from '@weapp/utils';
```

### **第二步：注册钩子**

```
// 消息拦截示例
regHook('weappEbdfpage', 'Message.action.message', (data) => {
  console.log('动作消息:', data.message);
  return data; // 返回数据表示不拦截，继续默认行为
});

// 页面动作拦截示例
regHook('weappEbdfpage', 'Message.action.page', (data) => {
  console.log('页面动作:', data.pageAction);
  return data; // 返回数据表示不拦截，继续默认行为
});
```

---

## **钩子一览**

| **钩子名称** | **触发时机** | **用途** |
| --- | --- | --- |
| `Message.action.message` | 显示消息前 | 修改或拦截提示信息 |
| `Message.action.page` | 页面动作执行前 | 修改或拦截跳转/关闭/刷新 |

---

## **一、消息拦截钩子**

**钩子名**：`Message.action.message`

**触发条件**：`extraEvent.reminder` 不为空（Remind/Confirm/Warn/Error）

### **传入参数**

| **字段** | **类型** | **说明** |
| --- | --- | --- |
| `reminder` | string | 消息类型：'1'=成功提醒, '2'=确认框, '3'=警告, '4'=错误 |
| `status` | boolean | 执行结果：true=成功, false=失败 |
| `message` | string | 原始消息内容 |
| `originalData` | object | 完整的动作数据对象 |

### **返回值规则**

| **返回值** | **效果** |
| --- | --- |
| `null` | **拦截** - 不显示消息，不执行后续动作 |
| `{ message: "新内容" }` | **修改** - 使用新消息内容继续执行 |
| `data`（原样返回） | **不修改** - 使用原始消息继续执行 |

### **使用示例**

**示例1：修改成功消息**

```
regHook('weappEbdfpage', 'Message.action.message', (data) => {
  if (data.reminder === '1' && data.status) {
    return { ...data, message: '操作已成功完成！' };
  }
  return data;
});
```

**示例2：修改失败消息**

```
regHook('weappEbdfpage', 'Message.action.message', (data) => {
  if (!data.status) {
    return { ...data, message: '处理失败，请稍后重试。错误信息：' + data.message };
  }
  return data;
});
```

**示例3：拦截确认框（完全自定义）**

```
regHook('weappEbdfpage', 'Message.action.message', (data) => {
  if (data.reminder === '2') {
    // 自定义确认逻辑，返回 null 阻止默认弹框
    MyCustomDialog.show({ //需使用系统PC/移动端弹框替换
      title: '信息确认',
      message: data.message,
      onConfirm: () => console.log('用户确认了')
    });
    return null;
  }
  return data;
});
```

---

## **二、页面动作拦截钩子**

**钩子名**：`Message.action.page`

**触发条件**：`extraEvent.pageAction` 不为空（Refresh/ClosePage/JumpPage）

### **传入参数**

| **字段** | **类型** | **说明** |
| --- | --- | --- |
| `pageAction` | string | 动作类型：'1'=刷新, '2'=关闭, '3'=跳转 |
| `jumpUrl` | string | 跳转地址（仅 pageAction='3' 时有值） |
| `originalData` | object | 完整的动作数据对象 |

### **返回值规则**

| **返回值** | **效果** |
| --- | --- |
| `null` | **拦截** - 不执行跳转/关闭/刷新 |
| `{ pageAction, jumpUrl }` | **修改** - 使用新参数继续执行 |
| `data`（原样返回） | **不修改** - 使用原始参数继续执行 |

### **使用示例**

**示例1：阻止跳转到特定地址**

```
regHook('weappEbdfpage', 'Message.action.page', (data) => {
  if (data.pageAction === '3' && data.jumpUrl?.includes('forbidden.com')) {
    console.warn('跳转被拦截:', data.jumpUrl);
    return null;
  }
  return data;
});
```

**示例2：修改跳转地址**

```
regHook('weappEbdfpage', 'Message.action.page', (data) => {
  if (data.pageAction === '3' && data.jumpUrl) {
    // 将旧版地址替换为新版
    const newUrl = data.jumpUrl.replace('/old-page', '/new-page');
    return { ...data, jumpUrl: newUrl };
  }
  return data;
});
```

**示例3：将跳转改为刷新当前页**

```
regHook('weappEbdfpage', 'Message.action.page', (data) => {
  if (data.pageAction === '3') {
    // 根据条件判断是否改为刷新
    if (data.originalData?.refreshCard) {
      return { ...data, pageAction: '1' }; // '1' = Refresh
    }
  }
  return data;
});
```

**示例4：拦截关闭页面**

```
regHook('weappEbdfpage', 'Message.action.page', (data) => {
  if (data.pageAction === '2') {
    // 自定义关闭前处理
    if (!confirm('确定要关闭吗？')) {
      return null;
    }
  }
  return data;
});
```

---

## **三、综合示例**

以下是一个完整的扩展方案示例：

```
import { regHook, eventEmitter } from '@weapp/utils';

// ==================== 消息拦截 ====================
regHook('weappEbdfpage', 'Message.action.message', (data) => {
  // 统一添加前缀
  if (data.message) {
    const prefix = data.status ? '[成功]' : '[失败]';
    return { ...data, message: `${prefix} ${data.message}` };
  }
  return data;
});

// ==================== 页面动作拦截 ====================
regHook('weappEbdfpage', 'Message.action.page', (data) => {
  // 跳转安全检查
  if (data.pageAction === '3' && data.jumpUrl) {
    try {
      const url = new URL(data.jumpUrl, window.location.origin);
      // 只允许同域跳转
      if (url.origin !== window.location.origin) {
        console.warn('跨域跳转已被拦截');
        return null;
      }
    } catch (e) {
      // 非法URL，放行让系统处理
    }
  }
  return data;
});
```

---

## **四、移除钩子**

当不再需要钩子时，使用 `unRegHook` 移除：

```
import { regHook, unRegHook } from '@weapp/utils';

const myHook = (data) => {
  console.log('消息:', data.message);
  return data;
};

regHook('weappEbdfpage', 'Message.action.message', myHook);

// 当不再需要时移除
unRegHook('weappEbdfpage', 'Message.action.message', myHook);
```

> **注意**：移除时必须传入与注册时相同的函数引用。

---

## **五、常见问题**

**Q：钩子注册在哪里合适？** A：建议在页面组件的 `useEffect` 中注册，在组件销毁时移除。

**Q：多个钩子执行顺序是怎样的？** A：按注册顺序执行。可以通过 `regHook` 的第四个参数 `priority` 调整顺序。

**Q：如何调试钩子是否生效？** A：在钩子函数开头加 `console.log`，观察控制台输出。
