@ray-js/robot-data-stream 0.0.15-beta.8 → 0.0.16-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/lib/constant.d.ts +1 -0
  2. package/lib/constant.js +11 -0
  3. package/lib/mqtt/hooks/useStructuredMessage.d.ts +0 -3
  4. package/lib/mqtt/hooks/useStructuredMessage.js +150 -75
  5. package/lib/mqtt/mqttProvider.d.ts +10 -1
  6. package/lib/mqtt/mqttProvider.js +5 -3
  7. package/lib/mqtt/type/fun.d.ts +24 -9
  8. package/lib/mqtt/type/fun.js +2 -1
  9. package/lib/mqtt/type/index.d.ts +4 -1
  10. package/lib/mqtt/type/protocols/base.d.ts +4 -1
  11. package/lib/mqtt/type/protocols/base.js +9 -3
  12. package/lib/mqtt/type/protocols/carpetCleanProtocol.d.ts +2 -2
  13. package/lib/mqtt/type/protocols/carpetCleanProtocol.js +2 -2
  14. package/lib/mqtt/type/protocols/carpetProtocol.d.ts +5 -5
  15. package/lib/mqtt/type/protocols/carpetProtocol.js +7 -7
  16. package/lib/mqtt/type/protocols/roomPropertyProtocol.d.ts +8 -2
  17. package/lib/mqtt/type/protocols/roomPropertyProtocol.js +26 -5
  18. package/lib/mqtt/type/protocols/scheduleProtocol.d.ts +12 -3
  19. package/lib/mqtt/type/protocols/scheduleProtocol.js +17 -0
  20. package/lib/mqtt/type/protocols/selectRoomCleanProtocol.d.ts +6 -2
  21. package/lib/mqtt/type/protocols/selectRoomCleanProtocol.js +12 -4
  22. package/lib/mqtt/type/protocols/spotCleanProtocol.d.ts +8 -2
  23. package/lib/mqtt/type/protocols/spotCleanProtocol.js +24 -2
  24. package/lib/mqtt/type/protocols/wifiMapProtocol.d.ts +1 -0
  25. package/lib/mqtt/type/protocols/wifiMapProtocol.js +2 -1
  26. package/lib/mqtt/type/protocols/zoneCleanProtocol.d.ts +7 -2
  27. package/lib/mqtt/type/protocols/zoneCleanProtocol.js +31 -4
  28. package/lib/mqtt/useRoomProperty.js +8 -5
  29. package/lib/mqtt/useSchedule.js +20 -7
  30. package/lib/mqtt/useSelectRoomClean.js +37 -14
  31. package/lib/mqtt/useSpotClean.js +22 -12
  32. package/lib/mqtt/useWifiMap.js +4 -2
  33. package/lib/mqtt/useZoneClean.js +38 -46
  34. package/lib/mqtt/waterPreference.d.ts +20 -0
  35. package/lib/mqtt/waterPreference.js +70 -0
  36. package/package.json +7 -4
package/lib/constant.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export declare const SUCTION_MAP: Record<string, number>;
2
2
  export declare const CISTERN_MAP: Record<string, number>;
3
3
  export declare const CLEAN_MODE_MAP: Record<string, number>;
4
+ export declare const ROUTE_PREFERENCE_MAP: Record<string, number>;
4
5
  export declare enum FileNameEnum {
5
6
  map = "map.bin",
6
7
  mapStructured = "map_structured.bin",
package/lib/constant.js CHANGED
@@ -28,6 +28,17 @@ export const CLEAN_MODE_MAP = {
28
28
  clean_before_mop: 3,
29
29
  sweep_after_mop: 3
30
30
  };
31
+
32
+ // 路线偏好(四种清洁偏好)
33
+ export const ROUTE_PREFERENCE_MAP = {
34
+ standard: 0,
35
+ // 标准
36
+ fast: 1,
37
+ // 快速
38
+ deep: 2,
39
+ // 深度
40
+ custom: 3 // 自定义
41
+ };
31
42
  export let FileNameEnum = /*#__PURE__*/function (FileNameEnum) {
32
43
  FileNameEnum["map"] = "map.bin";
33
44
  FileNameEnum["mapStructured"] = "map_structured.bin";
@@ -13,8 +13,5 @@ export declare const useStructuredMessage: () => {
13
13
  };
14
14
  /**
15
15
  * 错误处理工具函数
16
- * @param error 错误对象
17
- * @param defaultMessage 默认错误消息
18
- * @returns Error 对象
19
16
  */
20
17
  export declare const handleMqttError: (error: unknown, defaultMessage: string) => Error;
@@ -1,11 +1,29 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
- import { getDeviceOnlineType, onDeviceOnlineStatusUpdate } from '@ray-js/ray';
2
+ import { getDeviceOnlineType, offDeviceOnlineStatusUpdate, onDeviceOnlineStatusUpdate } from '@ray-js/ray';
3
3
  import { isFunction } from 'lodash-es';
4
4
  import { useCallback, useEffect, useRef } from 'react';
5
5
  import { getBitValue, logger } from '../../utils';
6
6
  import { createSetCommonParams } from '../createCommonOptions';
7
7
  import { useMqtt } from '../mqttProvider';
8
8
  import { normalResolve } from '../promise';
9
+ // 常量定义
10
+ const COMMUNICATION_CHANNELS = {
11
+ MQTT: 'mqtt',
12
+ LAN: 'lan'
13
+ };
14
+ const DEVICE_ONLINE_BITS = {
15
+ WIFI: 0,
16
+ LOCAL: 1
17
+ };
18
+ const LOG_LEVEL = {
19
+ INFO: 'info',
20
+ ERROR: 'error'
21
+ };
22
+
23
+ // 类型定义
24
+
25
+ // 通信方法接口
26
+
9
27
  /**
10
28
  * 统一的 MQTT 消息发送 Hook
11
29
  * 提供统一的 sendMqttMessage 方法,自动从 Context 获取 devId 和配置
@@ -15,103 +33,160 @@ export const useStructuredMessage = () => {
15
33
  const {
16
34
  devId
17
35
  } = context.devices.common.getDevInfo();
18
- const isLocalOnLineRef = useRef(false);
19
- const isWifiOnLineRef = useRef(true);
20
- const _onDeviceOnlineStatusChange = useCallback(_ref => {
36
+ const isLocalOnlineRef = useRef(false);
37
+ const isWifiOnlineRef = useRef(true);
38
+
39
+ // 设备在线状态处理器
40
+ const handleDeviceOnlineStatusChange = useCallback(_ref => {
21
41
  let {
22
42
  onlineType
23
43
  } = _ref;
24
- // bit 0: WiFi在线
25
- const wifiOnline = !!getBitValue(onlineType, 0);
26
- // bit 1: 局域网在线
27
- const localOnline = !!getBitValue(onlineType, 1);
28
- logger('info', {
29
- msg: `onDeviceOnlineStatusChange00000: onlineType ==>${onlineType}===>wifiOnline:${wifiOnline}===>localOnline:${localOnline}`
30
- });
31
- isLocalOnLineRef.current = localOnline;
32
- isWifiOnLineRef.current = wifiOnline;
44
+ const wifiOnline = Boolean(getBitValue(onlineType, DEVICE_ONLINE_BITS.WIFI));
45
+ const localOnline = Boolean(getBitValue(onlineType, DEVICE_ONLINE_BITS.LOCAL));
46
+ isLocalOnlineRef.current = localOnline;
47
+ isWifiOnlineRef.current = wifiOnline;
33
48
  }, []);
49
+
50
+ // 订阅设备在线状态更新
34
51
  useEffect(() => {
35
52
  if (!devId) return;
36
- getDeviceOnlineType({
53
+ (() => {
54
+ getDeviceOnlineType({
55
+ deviceId: devId,
56
+ success: handleDeviceOnlineStatusChange
57
+ });
58
+ })();
59
+ onDeviceOnlineStatusUpdate(handleDeviceOnlineStatusChange);
60
+ return offDeviceOnlineStatusUpdate(handleDeviceOnlineStatusChange);
61
+ }, [devId, handleDeviceOnlineStatusChange]);
62
+
63
+ // MQTT 通信方法
64
+ const mqttCommunication = {
65
+ isAvailable: () => {
66
+ var _ty;
67
+ return isWifiOnlineRef.current && ((_ty = ty) === null || _ty === void 0 ? void 0 : _ty.device) && isFunction(ty.device.sendMqttMessage);
68
+ },
69
+ send: (params, successCallback, failCallback) => {
70
+ const messageParams = _objectSpread(_objectSpread({}, params), {}, {
71
+ success: successCallback,
72
+ fail: failCallback
73
+ });
74
+ ty.device.sendMqttMessage(messageParams);
75
+ }
76
+ };
77
+
78
+ // LAN 通信方法
79
+ const lanCommunication = {
80
+ isAvailable: () => {
81
+ var _ty2;
82
+ return isLocalOnlineRef.current && ((_ty2 = ty) === null || _ty2 === void 0 ? void 0 : _ty2.device) && isFunction(ty.device.publishLanMessage);
83
+ },
84
+ send: (params, successCallback, failCallback) => {
85
+ const messageParams = _objectSpread(_objectSpread({}, params), {}, {
86
+ success: successCallback,
87
+ fail: failCallback
88
+ });
89
+ ty.device.publishLanMessage(messageParams);
90
+ }
91
+ };
92
+
93
+ // 创建消息参数
94
+ const createMessageParams = (reqType, message, useLocal) => {
95
+ return createSetCommonParams({
37
96
  deviceId: devId,
38
- success: _onDeviceOnlineStatusChange
97
+ reqType,
98
+ message,
99
+ isLocalOnLine: useLocal
100
+ });
101
+ };
102
+
103
+ // 记录通信日志
104
+ const logCommunication = (level, reqType, message, params) => {
105
+ const baseMessage = `${reqType} ${message}`;
106
+ const fullMessage = params ? `${baseMessage}: ${JSON.stringify(params)}` : baseMessage;
107
+ logger(level, {
108
+ msg: fullMessage
39
109
  });
40
- onDeviceOnlineStatusUpdate(_onDeviceOnlineStatusChange);
41
- }, [_onDeviceOnlineStatusChange, devId]);
110
+ };
111
+
112
+ // 通信策略选择器
113
+ const selectCommunicationMethod = preferredChannel => {
114
+ const isPreferredMqtt = preferredChannel === COMMUNICATION_CHANNELS.MQTT;
115
+ const primaryMethod = isPreferredMqtt ? mqttCommunication : lanCommunication;
116
+ const fallbackMethod = isPreferredMqtt ? lanCommunication : mqttCommunication;
117
+ const useLocal = isPreferredMqtt ? false : true;
118
+ if (primaryMethod.isAvailable()) {
119
+ return {
120
+ method: primaryMethod,
121
+ useLocal
122
+ };
123
+ }
124
+ if (fallbackMethod.isAvailable()) {
125
+ return {
126
+ method: fallbackMethod,
127
+ useLocal: !useLocal
128
+ };
129
+ }
130
+ return null;
131
+ };
132
+
133
+ // 处理通信失败
134
+ const handleCommunicationError = (preferredChannel, reject) => {
135
+ const errorMessage = preferredChannel === COMMUNICATION_CHANNELS.MQTT ? `操作需要 MQTT 模式,请在 MqttProvider 中启用 useMqtt` : `没有可用的通信方式。局域网在线: ${isLocalOnlineRef.current}, WiFi在线: ${isWifiOnlineRef.current}`;
136
+ reject(new Error(errorMessage));
137
+ };
42
138
 
43
139
  /**
44
- * 发送 MQTT 消息
45
- * @param reqType 请求类型
46
- * @param message 消息体(可选)
47
- * @param responseType 响应类型(可选,如果不提供则使用 reqType)
48
- * @param resolve Promise 的 resolve 回调
49
- * @param reject Promise 的 reject 回调
140
+ * 发送结构化消息
50
141
  */
51
142
  const sendStructuredMessage = useCallback((reqType, message, resolve, reject, responseType) => {
143
+ // 参数验证
52
144
  if (!devId) {
53
- reject(new Error('devId is required'));
145
+ reject(new Error('设备ID (devId) 为必填项'));
54
146
  return;
55
147
  }
56
- // 检查是否使用 MQTT 模式
57
148
  if (!context.useMqtt) {
58
- reject(new Error(`Operation ${reqType} requires MQTT mode. Please enable useMqtt in MqttProvider.`));
149
+ reject(new Error(`操作 ${reqType} 需要 MQTT 模式。请在 MqttProvider 中启用 useMqtt。`));
59
150
  return;
60
151
  }
61
152
  try {
62
- var _ty, _ty2;
63
- const params = createSetCommonParams({
64
- deviceId: devId,
65
- reqType,
66
- message,
67
- isLocalOnLine: isLocalOnLineRef.current
68
- });
69
-
70
- // 优先使用局域网通信(LAN)
71
- if (isLocalOnLineRef.current && (_ty = ty) !== null && _ty !== void 0 && _ty.device && isFunction(ty.device.publishLanMessage)) {
72
- // @ts-ignore - publishLanMessage 可能不存在于类型定义中
73
- ty.device.publishLanMessage(_objectSpread(_objectSpread({}, params), {}, {
74
- success: () => {
75
- logger('info', {
76
- msg: `${reqType} LAN message publish success: ${JSON.stringify(params)}`
77
- });
78
- // 局域网通信成功回调
79
- },
80
- fail: e => {
81
- logger('error', {
82
- msg: `${reqType} LAN message publish failed: ${JSON.stringify(e)}`
83
- });
84
- }
85
- }));
86
- }
87
- // 如果局域网不可用,使用 WiFi MQTT 通信
88
- else if (isWifiOnLineRef.current && (_ty2 = ty) !== null && _ty2 !== void 0 && _ty2.device && isFunction(ty.device.sendMqttMessage)) {
89
- ty.device.sendMqttMessage(_objectSpread(_objectSpread({}, params), {}, {
90
- success: () => {
91
- // WiFi MQTT 通信成功回调
92
- logger('info', {
93
- msg: `${reqType} WiFi MQTT message send success: ${JSON.stringify(params)}`
94
- });
95
- },
96
- fail: e => {
97
- logger('error', {
98
- msg: `${reqType} MQTT message send failed: ${JSON.stringify(e)}`
99
- });
100
- }
101
- }));
102
- }
103
- // 如果两种通信方式都不可用,抛出错误
104
- else {
105
- reject(new Error(`No available communication method. LAN online: ${isLocalOnLineRef.current}, WiFi online: ${isWifiOnLineRef.current}`));
153
+ const {
154
+ preferredChannel
155
+ } = context;
156
+ const selectedMethod = selectCommunicationMethod(preferredChannel);
157
+ if (!selectedMethod) {
158
+ handleCommunicationError(preferredChannel, reject);
106
159
  return;
107
160
  }
108
- // 如果指定了响应类型,使用响应类型;否则使用请求类型
161
+ const {
162
+ method,
163
+ useLocal
164
+ } = selectedMethod;
165
+ const messageParams = createMessageParams(reqType, message, useLocal);
166
+
167
+ // 成功回调
168
+
169
+ // 失败回调
170
+
171
+ // 发送消息
172
+ method.send(messageParams, () => {
173
+ const channelName = useLocal ? '局域网' : 'WiFi MQTT';
174
+ const fallbackSuffix = method === mqttCommunication && preferredChannel === COMMUNICATION_CHANNELS.LAN ? ' (备用)' : '';
175
+ logCommunication(LOG_LEVEL.INFO, reqType, `${channelName} 消息发送成功${fallbackSuffix}`, messageParams);
176
+ }, error => {
177
+ logCommunication(LOG_LEVEL.ERROR, reqType, '消息发送失败', _objectSpread(_objectSpread({}, messageParams), {}, {
178
+ error: JSON.stringify(error)
179
+ }));
180
+ });
181
+
182
+ // 处理响应
109
183
 
110
184
  normalResolve(responseType || reqType, resolve, reject);
111
185
  } catch (error) {
186
+ logCommunication(LOG_LEVEL.ERROR, reqType, `发送消息时发生异常: ${error}`);
112
187
  reject(error);
113
188
  }
114
- }, [devId, context.useMqtt]);
189
+ }, [devId, context.useMqtt, context.preferredChannel]);
115
190
  return {
116
191
  sendStructuredMessage
117
192
  };
@@ -119,13 +194,13 @@ export const useStructuredMessage = () => {
119
194
 
120
195
  /**
121
196
  * 错误处理工具函数
122
- * @param error 错误对象
123
- * @param defaultMessage 默认错误消息
124
- * @returns Error 对象
125
197
  */
126
198
  export const handleMqttError = (error, defaultMessage) => {
127
199
  if (error instanceof Error) {
128
200
  return error;
129
201
  }
202
+ if (typeof error === 'string') {
203
+ return new Error(error);
204
+ }
130
205
  return new Error(defaultMessage);
131
206
  };
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import { MqttError } from './promise';
3
+ export type CommunicationChannel = 'mqtt' | 'lan';
3
4
  export interface MqttContextValue {
4
5
  useMqtt: boolean;
5
6
  commandVersion: '0' | '1';
7
+ preferredChannel: CommunicationChannel;
6
8
  devices: {
7
9
  common: {
8
10
  getDevInfo: () => {
@@ -26,6 +28,13 @@ export interface MqttProviderProps {
26
28
  useMqtt: boolean;
27
29
  commandVersion: '0' | '1';
28
30
  devices: MqttContextValue['devices'];
31
+ /**
32
+ * 优先选择的通信通道
33
+ * - 'mqtt': 优先使用 MQTT 通道(WiFi MQTT)
34
+ * - 'lan': 优先使用局域网通道(LAN)
35
+ * @default 'mqtt'
36
+ */
37
+ preferredChannel?: CommunicationChannel;
29
38
  onMqttReady?: () => void;
30
39
  /**
31
40
  * 可选的错误处理回调
@@ -45,7 +54,7 @@ export interface MqttProviderProps {
45
54
  onError?: MqttErrorHandler;
46
55
  }
47
56
  export declare function useMqtt(): MqttContextValue;
48
- export declare function MqttProvider({ children, useMqtt, commandVersion, devices, onError, onMqttReady, }: MqttProviderProps): React.JSX.Element;
57
+ export declare function MqttProvider({ children, useMqtt, commandVersion, devices, preferredChannel, onError, onMqttReady, }: MqttProviderProps): React.JSX.Element;
49
58
  export declare namespace MqttProvider {
50
59
  var defaultProps: {
51
60
  onMqttReady: undefined;
@@ -7,6 +7,8 @@ import { setUnhandledRejectionHandler } from './promise';
7
7
  import { ProtocolEnum } from './type';
8
8
  import log4js from '@ray-js/log4js';
9
9
 
10
+ // 通信通道类型
11
+
10
12
  // Context 类型定义
11
13
 
12
14
  // 创建一个Context
@@ -32,6 +34,7 @@ export function MqttProvider(_ref) {
32
34
  useMqtt,
33
35
  commandVersion,
34
36
  devices,
37
+ preferredChannel = 'mqtt',
35
38
  onError,
36
39
  onMqttReady
37
40
  } = _ref;
@@ -42,10 +45,9 @@ export function MqttProvider(_ref) {
42
45
  const instance = useMemo(() => ({
43
46
  useMqtt,
44
47
  commandVersion,
48
+ preferredChannel,
45
49
  devices
46
- // isLocalOnLine,
47
- // isWifiOnLine,
48
- }), [useMqtt, commandVersion, devices]);
50
+ }), [useMqtt, commandVersion, preferredChannel, devices]);
49
51
 
50
52
  // 使用 ref 存储设备 ID 和初始化状态,避免重复初始化
51
53
  const devIdRef = useRef(null);
@@ -16,7 +16,7 @@ export declare const ProtocolSchemas: {
16
16
  sideBrushRotating: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>>;
17
17
  }, z.core.$strip>;
18
18
  update_carpet: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
19
- ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>;
19
+ ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
20
20
  shape: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
21
21
  type: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>>;
22
22
  cleanMode: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>>;
@@ -29,7 +29,7 @@ export declare const ProtocolSchemas: {
29
29
  }, z.core.$strip>>>>;
30
30
  }, z.core.$strip>;
31
31
  delete_carpet: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
32
- ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>;
32
+ ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
33
33
  }, z.core.$strip>;
34
34
  set_carpet: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
35
35
  num: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat;
@@ -39,7 +39,7 @@ export declare const ProtocolSchemas: {
39
39
  }, z.core.$strip>>>;
40
40
  cleanMode: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
41
41
  shape: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
42
- ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
42
+ ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
43
43
  type: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
44
44
  autoBoost: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
45
45
  fineCleaning: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
@@ -48,11 +48,14 @@ export declare const ProtocolSchemas: {
48
48
  set_schedule: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
49
49
  list: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
50
50
  suctions: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
51
- cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
51
+ cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
52
+ waterValues: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
52
53
  cleanCounts: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
53
54
  yMops: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
54
55
  sweepMopModes: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
55
56
  ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
57
+ routePreferences: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
58
+ nameLabels: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
56
59
  active: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat;
57
60
  cycle: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
58
61
  time: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
@@ -85,13 +88,16 @@ export declare const ProtocolSchemas: {
85
88
  y: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>;
86
89
  }, z.core.$strip>;
87
90
  suctions: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
88
- cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
91
+ cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
92
+ waterValues: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
89
93
  cleanCounts: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
90
94
  yMops: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
91
95
  sweepMopModes: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
96
+ routePreferences: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
92
97
  }, z.core.$strip>;
93
98
  set_wifi_map: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
94
99
  taskId: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>;
100
+ switch: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniBoolean<boolean>>;
95
101
  }, z.core.$strip>;
96
102
  set_voice: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
97
103
  id: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat;
@@ -124,11 +130,14 @@ export declare const ProtocolSchemas: {
124
130
  }, z.core.$strip>;
125
131
  set_spot_clean: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
126
132
  suctions: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
127
- cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
133
+ cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
134
+ waterValues: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
128
135
  cleanCounts: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
129
136
  yMops: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
130
137
  sweepMopModes: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
131
138
  ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
139
+ routePreferences: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
140
+ nameLabels: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
132
141
  spots: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
133
142
  x: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>;
134
143
  y: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>;
@@ -137,14 +146,17 @@ export declare const ProtocolSchemas: {
137
146
  x: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>;
138
147
  y: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>;
139
148
  }, z.core.$strip>>;
149
+ names: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
140
150
  }, z.core.$strip>;
141
151
  set_select_room_clean: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
142
152
  roomId: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat;
143
153
  suction: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>;
144
- cistern: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>;
154
+ cistern: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<any>;
155
+ waterValue: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<any>;
145
156
  cleanTimes: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
146
157
  yMop: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
147
158
  sweepMopMode: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>;
159
+ routePreference: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>;
148
160
  }, z.core.$strip>>;
149
161
  set_quiet_hours: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
150
162
  startTime: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
@@ -198,18 +210,21 @@ export declare const ProtocolSchemas: {
198
210
  position: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>;
199
211
  subDevId: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>;
200
212
  }, z.core.$strip>>;
201
- set_carpet_clean: any;
213
+ set_carpet_clean: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
202
214
  set_room_property: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
203
215
  num: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
204
216
  ids: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>;
205
217
  suctions: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
206
- cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
218
+ cisterns: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
207
219
  cleanCounts: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
208
220
  yMops: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
209
221
  sweepMopModes: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
210
222
  floorTypes: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
211
223
  names: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
224
+ nameLabels: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
212
225
  orders: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
226
+ routePreferences: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
227
+ waterValues: import("../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
213
228
  }, z.core.$strip>;
214
229
  };
215
230
  export type ProtocolTypes = {
@@ -21,7 +21,7 @@ import { setVirtualAreaSchema } from './protocols/virtualAreaProtocol';
21
21
  import { setVirtualWallSchema } from './protocols/virtualWallProtocol';
22
22
  import { setVoiceSchema } from './protocols/voiceProtocol';
23
23
  import { setWifiMapSchema } from './protocols/wifiMapProtocol';
24
- import { setZoneCleanSchema } from './protocols/zoneCleanProtocol';
24
+ import { setZoneCleanSchema, validateSetZoneClean } from './protocols/zoneCleanProtocol';
25
25
 
26
26
  /**
27
27
  * 验证失败错误代码
@@ -68,6 +68,7 @@ const protocolValidators = {
68
68
  set_carpet: validateSetCarpet,
69
69
  set_schedule: validateSetSchedule,
70
70
  set_spot_clean: validateSetSpotClean,
71
+ set_zone_clean: validateSetZoneClean,
71
72
  set_room_property: validateSetRoomProperty
72
73
  // query_carpet 没有自定义验证逻辑,不需要注册
73
74
  // delete_carpet 没有自定义验证逻辑,不需要注册
@@ -22,12 +22,15 @@ export declare enum WifiMapEnum {
22
22
  }
23
23
  export type RoomPreference = {
24
24
  suctions?: string[];
25
- cisterns?: string[];
25
+ cisterns?: Array<string | number>;
26
+ waterValues?: Array<string | number>;
26
27
  cleanCounts?: number[];
27
28
  yMops?: number[];
28
29
  sweepMopModes?: string[];
30
+ routePreferences?: string[];
29
31
  floorTypes?: number[];
30
32
  names?: string[];
33
+ nameLabels?: number[];
31
34
  ids?: number[];
32
35
  orders?: number[];
33
36
  };
@@ -5,11 +5,14 @@ export declare const Point: import("../../../myLib/zod/src/v4/mini/schemas").Zod
5
5
  }, z.core.$strip>;
6
6
  export declare const RoomPreferenceFieldsSchema: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
7
7
  suctions: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
8
- cisterns: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
8
+ cisterns: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
9
+ waterValues: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>>;
9
10
  cleanCounts: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
10
11
  yMops: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
11
12
  sweepMopModes: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
12
13
  ids: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
14
+ routePreferences: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>>>;
15
+ nameLabels: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniOptional<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumberFormat>>;
13
16
  }, z.core.$strip>;
14
17
  export declare const BaseResponseSchema: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
15
18
  success: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniBoolean<boolean>;
@@ -10,8 +10,10 @@ export const Point = z.object({
10
10
  export const RoomPreferenceFieldsSchema = z.object({
11
11
  // 吸力, closed - 关闭 gentle - 安静 normal - 正常 strong - 强劲 max - 超强 ,默认值为''
12
12
  suctions: z.optional(z.array(z.string())),
13
- // 拖地水量 "closed"- 关闭,"low"-低,"middle"-中,"high"-高,默认值为''
14
- cisterns: z.optional(z.array(z.string())),
13
+ // 拖地水量 "closed"- 关闭,"low"-低,"middle"-中,"high"-高,默认值为'',兼容number类型
14
+ cisterns: z.optional(z.array(z.union([z.string(), z.number()]))),
15
+ // 自定义水量的值
16
+ waterValues: z.optional(z.array(z.union([z.string(), z.number()]))),
15
17
  // 清扫次数 默认值1
16
18
  cleanCounts: z.optional(z.array(z.int())),
17
19
  // 拖地模式 1:开启Y型拖地 0:关闭Y型拖地 -1 未设置 默认值-1
@@ -19,7 +21,11 @@ export const RoomPreferenceFieldsSchema = z.object({
19
21
  // 扫拖模式 "only_sweep":仅扫,"only_mop":仅拖,"both_work":扫拖同时,"clean_before_mop":先扫后拖,默认值为'only_sweep'
20
22
  sweepMopModes: z.optional(z.array(z.string())),
21
23
  // 房间id集合
22
- ids: z.optional(z.array(z.int()))
24
+ ids: z.optional(z.array(z.int())),
25
+ // 路线偏好(四种清洁偏好): "standard"-标准, "fast"-快速, "deep"-深度, "custom"-自定义,默认值为'standard'
26
+ routePreferences: z.optional(z.array(z.string())),
27
+ // 房间名称标签
28
+ nameLabels: z.optional(z.array(z.int()))
23
29
  });
24
30
 
25
31
  // BaseResponse Schema(用于响应类型)
@@ -1,12 +1,12 @@
1
1
  import * as z from '../../../myLib/zod/mini';
2
- declare const setCarpetCleanSchema: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>;
2
+ export declare const setCarpetCleanSchema: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
3
3
  declare const carpetCleanResponseSchema: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniObject<{
4
4
  success: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniBoolean<boolean>;
5
5
  errCode: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>;
6
6
  reqType: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>;
7
7
  version: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>;
8
8
  taskId: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniString<string>;
9
- ids: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniNumber<number>>;
9
+ ids: import("../../../myLib/zod/src/v4/mini/schemas").ZodMiniArray<any>;
10
10
  }, z.core.$strip>;
11
11
  export type CarpetCleanResponse = z.infer<typeof carpetCleanResponseSchema>;
12
12
  export type TRequestCarpetClean = () => Promise<CarpetCleanResponse>;
@@ -2,11 +2,11 @@ import * as z from '../../../myLib/zod/mini';
2
2
  import { BaseResponseSchema } from './base';
3
3
 
4
4
  // 设置地毯清扫参数 Schema
5
- const setCarpetCleanSchema = z.array(z.number()); // 地毯ID数组,注意: .min()放在数组元素上
5
+ export const setCarpetCleanSchema = z.array(z.union([z.number(), z.string()]));
6
6
 
7
7
  // 地毯清扫响应 Schema
8
8
  const carpetCleanResponseSchema = z.extend(BaseResponseSchema, {
9
- ids: z.array(z.number())
9
+ ids: z.array(z.union([z.number(), z.string()]))
10
10
  });
11
11
 
12
12
  // 类型导出