fix: 新增 tree 组件的监听事件,优化 meta 全选的回调事件监听
This commit is contained in:
parent
35b99a3270
commit
762f480f81
10
.vscode/launch.json
vendored
Normal file
10
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "http://localhost:8000/metas/big-image-preview",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:8000/metas/big-image-preview"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,5 +1,39 @@
|
||||
# @zhst/biz
|
||||
|
||||
## 0.9.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增 tree 组件的监听事件,优化 meta 全选的回调事件监听
|
||||
- Updated dependencies
|
||||
- @zhst/hooks@0.8.3
|
||||
- @zhst/func@0.7.4
|
||||
- @zhst/meta@0.8.4
|
||||
|
||||
## 0.9.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 删除预览图组件,新增摄像头状态判断,修复 ts 生成失败问题
|
||||
|
||||
## 0.9.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 添加 biz 模块修改树形盒子组件监听事件
|
||||
|
||||
## 0.9.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增监听点击事件自定义
|
||||
|
||||
## 0.9.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增 BoxSelectTree 监听时钟点击事件,导入盒子事件
|
||||
|
||||
## 0.9.1
|
||||
|
||||
### Patch Changes
|
||||
|
8
packages/biz/es/index.d.ts
vendored
8
packages/biz/es/index.d.ts
vendored
@ -1,8 +1,12 @@
|
||||
export { default as BigImageModal } from './BigImageModal';
|
||||
export type { BigImageModalProps } from './BigImageModal';
|
||||
export { default as BoxSelectTree } from './boxSelectTree';
|
||||
export type { BoxSelectTreeProps } from './boxSelectTree';
|
||||
export { default as Tree } from './tree';
|
||||
export type { TreeData } from './tree';
|
||||
export type { BoxTreeProps, TreeData } from './tree';
|
||||
export { default as TreeTransfer } from './treeTransfer';
|
||||
export type { TreeTransferProps } from './treeTransfer';
|
||||
export { default as TreeTransferModal } from './treeTransferModal';
|
||||
export type { TreeTransferModalProps } from './treeTransferModal';
|
||||
export { default as WarningRecordCard } from './WarningRecordCard';
|
||||
export type { IRecord, WarningRecordCardProps } from './WarningRecordCard';
|
||||
export type { WarningRecordCardProps, IRecord } from './WarningRecordCard';
|
||||
|
@ -1,95 +0,0 @@
|
||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
||||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
||||
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
||||
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
||||
import { useMemo } from 'react';
|
||||
import { throttle as loadshThrottle, noop } from '@zhst/func';
|
||||
import { useDeepEffect, useLatest } from '@zhst/hooks';
|
||||
import ws from "./ws";
|
||||
var getSelf = function getSelf(v) {
|
||||
return v;
|
||||
};
|
||||
export var SocketApi = {
|
||||
CameraTaskStatue: 'singer.DeviceService/SubScribeCameraTaskStatus',
|
||||
DeviceStatus: 'singer.TaskManagerService/SubscribeTaskStatus',
|
||||
SubscribeSolutionDeploy: 'singer.SolutionManagerService/SubscribeSolutionDeploy',
|
||||
SubscribeTasksSummary: 'singer.TaskManagerService/SubscribeTasksSummary',
|
||||
MonitorSubscribeResult: 'singer.MonitorService/MonitorSubscribeResult',
|
||||
MonitorSubscribeStatus: 'singer.MonitorService/MonitorSubscribeStatus',
|
||||
SubscribeArchiveGroupUpload: 'singer.ArchiveGroupService/CreateArchiveByImport',
|
||||
SubscribeJointTask: 'singer.JointTaskService/SubscribeJointTask',
|
||||
SubscribeGroupFragment: 'singer.VideoService/SubscribeVideoFragmentStatus',
|
||||
// 监听视频分片状态变化,包括新建、删除、变化
|
||||
SubscribeGroup: 'singer.VideoService/SubscribeGroup',
|
||||
// 监听视频分组状态变化,列表变化也通知
|
||||
SubscribeStreamEvent: 'singer.MediaManagerService/SubscribeStreamEvent' // 监听视频分组状态变化,列表变化也通知
|
||||
};
|
||||
export default (function (topic) {
|
||||
var iterator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
|
||||
var opt = arguments.length > 2 ? arguments[2] : undefined;
|
||||
var _ref = opt || {},
|
||||
_ref$req = _ref.req,
|
||||
req = _ref$req === void 0 ? {} : _ref$req,
|
||||
_ref$throttle = _ref.throttle,
|
||||
throttle = _ref$throttle === void 0 ? 0 : _ref$throttle,
|
||||
_ref$beforeLoopTmp = _ref.beforeLoopTmp,
|
||||
beforeLoopTmp = _ref$beforeLoopTmp === void 0 ? getSelf : _ref$beforeLoopTmp,
|
||||
_ref$shouldBreak = _ref.shouldBreak,
|
||||
shouldBreak = _ref$shouldBreak === void 0 ? false : _ref$shouldBreak,
|
||||
forceRefresh = _ref.forceRefresh,
|
||||
close = _ref.close;
|
||||
|
||||
// 带上token
|
||||
var reqstring = useMemo(function () {
|
||||
var newReq = _objectSpread(_objectSpread({}, req), {}, {
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem('USER-TOKEN')
|
||||
}
|
||||
});
|
||||
return JSON.stringify(newReq);
|
||||
}, [req]);
|
||||
var latestIterator = useLatest(iterator);
|
||||
useDeepEffect(function () {
|
||||
if (close) {
|
||||
return;
|
||||
}
|
||||
//控制socket 请求发送
|
||||
if (shouldBreak) {
|
||||
return;
|
||||
}
|
||||
//去抖动
|
||||
|
||||
var tmpData = [];
|
||||
var throttleUpdate = loadshThrottle(function () {
|
||||
if (tmpData.length == 0) {
|
||||
return;
|
||||
}
|
||||
var _tmpData = beforeLoopTmp(tmpData);
|
||||
latestIterator.current(_tmpData); //加了throttle 数据就变成数组
|
||||
tmpData = [];
|
||||
}, throttle);
|
||||
var unSubscribe = ws.subscribe(SocketApi[topic], reqstring, function (socketData) {
|
||||
try {
|
||||
if (!throttle) {
|
||||
latestIterator.current(socketData);
|
||||
} else {
|
||||
tmpData.push(socketData);
|
||||
throttleUpdate();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('useSocke:', error);
|
||||
}
|
||||
});
|
||||
return function () {
|
||||
try {
|
||||
unSubscribe();
|
||||
throttleUpdate.cancel();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}, [topic, reqstring, shouldBreak, forceRefresh, close]);
|
||||
});
|
2
packages/biz/es/useSocket/onceChannel.d.ts
vendored
2
packages/biz/es/useSocket/onceChannel.d.ts
vendored
@ -1,2 +0,0 @@
|
||||
declare const startChannel: (topic: any, req: any, callback: any) => () => void;
|
||||
export default startChannel;
|
@ -1,24 +0,0 @@
|
||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
||||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
||||
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
||||
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
||||
//@ts-nocheck
|
||||
import channel from "./ws";
|
||||
var startChannel = function startChannel(topic, req, callback) {
|
||||
// 带上token
|
||||
var reqstring = JSON.stringify(_objectSpread(_objectSpread({}, req), {}, {
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem('USER-TOKEN')
|
||||
}
|
||||
}));
|
||||
var unSubscribe = channel.subscribe(topic, reqstring, function (socketData) {
|
||||
var shouldStop = callback(socketData);
|
||||
if (shouldStop) {
|
||||
unSubscribe === null || unSubscribe === void 0 || unSubscribe();
|
||||
}
|
||||
});
|
||||
return unSubscribe;
|
||||
};
|
||||
export default startChannel;
|
@ -1,244 +0,0 @@
|
||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
||||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
||||
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
||||
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
||||
// @ts-nocheck
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { has } from '@zhst/func';
|
||||
import io from 'socket.io-client';
|
||||
import { SOCKET_HOST } from '@common/constants';
|
||||
var EMITSTATE = {
|
||||
NOT_CONNECT: 0,
|
||||
WAITING: 1,
|
||||
CONNECT: 2
|
||||
};
|
||||
var initRetryTime = 0;
|
||||
var intervalTime = 5 * 1000; //下次重试增加时间
|
||||
var maxIntervalTime = 1 * 60 * 60 * 1000; //最大重试时间1小时
|
||||
var Channel = /*#__PURE__*/function () {
|
||||
function Channel() {
|
||||
var _this = this;
|
||||
_classCallCheck(this, Channel);
|
||||
/**
|
||||
* io 实例化对象
|
||||
*/
|
||||
_defineProperty(this, "ioIns", void 0);
|
||||
/**
|
||||
* 已存在的订阅列表
|
||||
*/
|
||||
_defineProperty(this, "listeners", [
|
||||
// {
|
||||
// topic: "",
|
||||
// req: "",
|
||||
// suInfo: {},
|
||||
// hasEmit: false,//是否已经订阅
|
||||
// lastRetryInterval: 0,
|
||||
// handles: {
|
||||
// }
|
||||
// }
|
||||
]);
|
||||
/**
|
||||
* 调试信息 记录订阅/反订阅次数
|
||||
*/
|
||||
_defineProperty(this, "subscribeListenerId", []);
|
||||
_defineProperty(this, "unSubscribeListenerId", []);
|
||||
_defineProperty(this, "init", function () {
|
||||
var ioIns = _this.ioIns = io(SOCKET_HOST, {
|
||||
reconnection: true,
|
||||
transports: ['websocket'],
|
||||
forceNew: true
|
||||
});
|
||||
ioIns.on('connect', function () {
|
||||
for (var _len = arguments.length, arg = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||
arg[_key] = arguments[_key];
|
||||
}
|
||||
console.debug('connect', arg);
|
||||
_this.ioIns = ioIns;
|
||||
_this.listeners.forEach(function (v) {
|
||||
_this.doEmit(v['topic'], v['req'], v['id']);
|
||||
});
|
||||
});
|
||||
ioIns.on('event', function () {
|
||||
for (var _len2 = arguments.length, arg = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
||||
arg[_key2] = arguments[_key2];
|
||||
}
|
||||
console.debug('event', arg);
|
||||
});
|
||||
ioIns.on('disconnect', function () {
|
||||
for (var _len3 = arguments.length, arg = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
|
||||
arg[_key3] = arguments[_key3];
|
||||
}
|
||||
console.debug('disconnect', arg);
|
||||
_this.subscribeListenerId = [];
|
||||
_this.unSubscribeListenerId = [];
|
||||
});
|
||||
ioIns.on('reconnect', function () {
|
||||
for (var _len4 = arguments.length, arg = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
|
||||
arg[_key4] = arguments[_key4];
|
||||
}
|
||||
console.debug('reconnect', arg);
|
||||
_this.listeners.forEach(function (v) {
|
||||
v['hasEmit'] = EMITSTATE.NOT_CONNECT;
|
||||
_this.doEmit(v['topic'], v['req'], v['id']);
|
||||
});
|
||||
});
|
||||
});
|
||||
_defineProperty(this, "retry", function (listener) {
|
||||
//重试逻辑
|
||||
var intervalId = setTimeout(function () {
|
||||
var hasExit = _this.listeners.find(function (v) {
|
||||
return v['topic'] === (listener === null || listener === void 0 ? void 0 : listener['topic']) && v['req'] === listener['req'];
|
||||
});
|
||||
if (!hasExit) return;
|
||||
listener['hasEmit'] = EMITSTATE.NOT_CONNECT;
|
||||
_this.doEmit(listener['topic'], listener['req'], listener['id']);
|
||||
}, listener.lastRetryInterval);
|
||||
listener.intervalId = intervalId;
|
||||
listener.lastRetryInterval = intervalTime + listener.lastRetryInterval > maxIntervalTime ? maxIntervalTime : intervalTime + listener.lastRetryInterval;
|
||||
});
|
||||
_defineProperty(this, "doEmit", function (topic, req, listenerId) {
|
||||
var _this$ioIns, _this$ioIns$emit;
|
||||
if (!_this.ioIns) {
|
||||
_this.init();
|
||||
}
|
||||
//订阅过就不订阅了
|
||||
var hasEmit = _this.listeners.find(function (v) {
|
||||
return v['topic'] === topic && v['req'] === req && v['hasEmit'] !== EMITSTATE.NOT_CONNECT;
|
||||
});
|
||||
if (hasEmit) {
|
||||
return;
|
||||
}
|
||||
var listener = _this.listeners.find(function (v) {
|
||||
return v['topic'] === topic && v['req'] === req;
|
||||
});
|
||||
listener['hasEmit'] = EMITSTATE.WAITING;
|
||||
(_this$ioIns = _this.ioIns) === null || _this$ioIns === void 0 || (_this$ioIns$emit = _this$ioIns.emit) === null || _this$ioIns$emit === void 0 || _this$ioIns$emit.call(_this$ioIns, topic, req, function (data) {
|
||||
var _this$ioIns2, _this$ioIns2$on;
|
||||
console.info('emit', topic, req, data);
|
||||
var suInfo = JSON.parse(data);
|
||||
if (has(suInfo, 'Error.code')) {
|
||||
if (suInfo.Error.code === 500) {
|
||||
//后端出错
|
||||
_this.retry(listener);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// console.debug('SUBSCRIBE', listenerId, topic, req, suInfo);
|
||||
_this.subscribeListenerId.push(listenerId);
|
||||
// debugger
|
||||
//重新找一遍topic
|
||||
var currentTopicIndex = _this.listeners.findIndex(function (v) {
|
||||
return v['topic'] === topic && v['req'] === req && v['id'] === listenerId;
|
||||
});
|
||||
if (currentTopicIndex == -1) {
|
||||
// 不存在说明listener取消了 直接反订阅
|
||||
_this.ioIns.emit('UnSubscribe', JSON.stringify(suInfo), function (data) {
|
||||
_this.unSubscribeListenerId.push(listenerId);
|
||||
console.debug('UNSUBSCRIBE', listenerId, topic, req, data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!suInfo['SubscribeID']) {
|
||||
_this.listeners.splice(currentTopicIndex, 0);
|
||||
} else {
|
||||
_this.listeners[currentTopicIndex]['suInfo'] = suInfo;
|
||||
_this.listeners[currentTopicIndex]['hasEmit'] = EMITSTATE.CONNECT;
|
||||
}
|
||||
(_this$ioIns2 = _this.ioIns) === null || _this$ioIns2 === void 0 || (_this$ioIns2$on = _this$ioIns2.on) === null || _this$ioIns2$on === void 0 || _this$ioIns2$on.call(_this$ioIns2, suInfo['SubscribeID'], function (data) {
|
||||
console.info('on', suInfo['SubscribeID'], data);
|
||||
try {
|
||||
var socketData = JSON.parse(data);
|
||||
if (has(socketData, 'Error.code')) {
|
||||
if (socketData.Error.code === 500) {
|
||||
//后端出错
|
||||
_this.retry(listener);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var _ref = _this.listeners.find(function (v) {
|
||||
return v['topic'] === topic && v['req'] === req;
|
||||
}) || {},
|
||||
_ref$handles = _ref.handles,
|
||||
handles = _ref$handles === void 0 ? {} : _ref$handles;
|
||||
Object.keys(handles).forEach(function (key) {
|
||||
try {
|
||||
//后面观察 为什么delete后在foreach
|
||||
var func = handles[key];
|
||||
if (!func) return;
|
||||
func(socketData);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.debug('error', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
_createClass(Channel, [{
|
||||
key: "subscribe",
|
||||
value: function subscribe(topic, req, handle) {
|
||||
var handleId = uuidv4();
|
||||
var listenerId = uuidv4();
|
||||
var listener = this.listeners.find(function (v) {
|
||||
return v['topic'] === topic && v['req'] === req;
|
||||
});
|
||||
if (listener) {
|
||||
listener['handles'][handleId] = handle;
|
||||
} else {
|
||||
this.listeners.push({
|
||||
topic: topic,
|
||||
req: req,
|
||||
suInfo: {},
|
||||
id: listenerId,
|
||||
hasEmit: EMITSTATE.NOT_CONNECT,
|
||||
lastRetryInterval: initRetryTime,
|
||||
handles: _defineProperty({}, "".concat(handleId), handle)
|
||||
});
|
||||
//未注册过 则去订阅
|
||||
this.doEmit(topic, req, listenerId);
|
||||
}
|
||||
return this.unSubscribe.bind(this, topic, req, handleId, listenerId);
|
||||
}
|
||||
}, {
|
||||
key: "unSubscribe",
|
||||
value: function unSubscribe(topic, req, handleId, listenerId) {
|
||||
var _this2 = this;
|
||||
var listener = this.listeners.find(function (v) {
|
||||
return v['topic'] === topic && v['req'] === req && v['id'] === listenerId;
|
||||
});
|
||||
var _ref2 = listener || {},
|
||||
_ref2$handles = _ref2.handles,
|
||||
handles = _ref2$handles === void 0 ? {} : _ref2$handles,
|
||||
suInfo = _ref2.suInfo;
|
||||
if (handles[handleId]) {
|
||||
delete handles[handleId];
|
||||
//如果没有其他订阅就删除
|
||||
if (Object.keys(handles).length === 0) {
|
||||
if (this.intervalId) {
|
||||
clearTimeout(this.intervalId);
|
||||
}
|
||||
if (listener['hasEmit'] === EMITSTATE['CONNECT']) {
|
||||
this.ioIns.emit('UnSubscribe', JSON.stringify(suInfo), function (data) {
|
||||
_this2.unSubscribeListenerId.push(listenerId);
|
||||
console.debug('UNSUBSCRIBE', listener['id'], topic, req, data);
|
||||
});
|
||||
}
|
||||
this.listeners = this.listeners.filter(function (v) {
|
||||
return !(v['topic'] === topic && v['req'] === req);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
return Channel;
|
||||
}(); //单例
|
||||
var channelIns = new Channel();
|
||||
//暴露实例 调试用
|
||||
window.__channel__ = channelIns;
|
||||
export default channelIns;
|
31
packages/biz/es/utils/constants.d.ts
vendored
31
packages/biz/es/utils/constants.d.ts
vendored
@ -1,31 +0,0 @@
|
||||
export declare const OBJECT_GRNER_THRESHOLD = 0.8;
|
||||
export declare const OBJECT_AGE_TYPE_THRESHOLD = 0.5;
|
||||
export declare const MODE_KEY = "test_mode";
|
||||
export declare const SEARCH_IMG_COUNT = 10;
|
||||
export declare const GLOBAL_IS_ITEM_NUMBER_SHOW = false;
|
||||
export declare const publicPath = "hummingbird";
|
||||
export declare const ENTER_CIRCLE = "MONITORTYPE_ENTER_CIRCLE";
|
||||
export declare const OUT_CIRCLE = "MONITORTYPE_OUT_CIRCLE";
|
||||
export declare const TEMP = "MONITORTYPE_TEMP";
|
||||
export declare const GLOBAL_IS_BOX_VMS_SHOW = true;
|
||||
export declare const BODY_SEARCH_THRESHOID = 0.45;
|
||||
export declare const RECORD_VERSION = "3.0.0";
|
||||
export declare const DeviceTab: {
|
||||
EMPTY: number;
|
||||
REAL_CAMERA: number;
|
||||
PREPROCESS_CAMERA: number;
|
||||
TAG_CAMERA: number;
|
||||
HISTORY_VIDEO_GROUP: number;
|
||||
VIRTUAL_CAMERA: number;
|
||||
REAL_CAMERA_NOFACE: number;
|
||||
REAL_CAMERA_ONLYFACE: number;
|
||||
REAL_CAMERA_NOFACE_NOBOX_NODIRECONNECT: number;
|
||||
};
|
||||
export declare const BOX_TYPE_LIST: {
|
||||
value: string;
|
||||
label: string;
|
||||
}[];
|
||||
export declare const ALL_LIST: {
|
||||
value: string;
|
||||
label: string;
|
||||
}[];
|
8
packages/biz/lib/index.d.ts
vendored
8
packages/biz/lib/index.d.ts
vendored
@ -1,8 +1,12 @@
|
||||
export { default as BigImageModal } from './BigImageModal';
|
||||
export type { BigImageModalProps } from './BigImageModal';
|
||||
export { default as BoxSelectTree } from './boxSelectTree';
|
||||
export type { BoxSelectTreeProps } from './boxSelectTree';
|
||||
export { default as Tree } from './tree';
|
||||
export type { TreeData } from './tree';
|
||||
export type { BoxTreeProps, TreeData } from './tree';
|
||||
export { default as TreeTransfer } from './treeTransfer';
|
||||
export type { TreeTransferProps } from './treeTransfer';
|
||||
export { default as TreeTransferModal } from './treeTransferModal';
|
||||
export type { TreeTransferModalProps } from './treeTransferModal';
|
||||
export { default as WarningRecordCard } from './WarningRecordCard';
|
||||
export type { IRecord, WarningRecordCardProps } from './WarningRecordCard';
|
||||
export type { WarningRecordCardProps, IRecord } from './WarningRecordCard';
|
||||
|
@ -1,118 +0,0 @@
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/useSocket/index.ts
|
||||
var useSocket_exports = {};
|
||||
__export(useSocket_exports, {
|
||||
SocketApi: () => SocketApi,
|
||||
default: () => useSocket_default
|
||||
});
|
||||
module.exports = __toCommonJS(useSocket_exports);
|
||||
var import_react = require("react");
|
||||
var import_func = require("@zhst/func");
|
||||
var import_hooks = require("@zhst/hooks");
|
||||
var import_ws = __toESM(require("./ws"));
|
||||
var getSelf = (v) => v;
|
||||
var SocketApi = {
|
||||
CameraTaskStatue: "singer.DeviceService/SubScribeCameraTaskStatus",
|
||||
DeviceStatus: "singer.TaskManagerService/SubscribeTaskStatus",
|
||||
SubscribeSolutionDeploy: "singer.SolutionManagerService/SubscribeSolutionDeploy",
|
||||
SubscribeTasksSummary: "singer.TaskManagerService/SubscribeTasksSummary",
|
||||
MonitorSubscribeResult: "singer.MonitorService/MonitorSubscribeResult",
|
||||
MonitorSubscribeStatus: "singer.MonitorService/MonitorSubscribeStatus",
|
||||
SubscribeArchiveGroupUpload: "singer.ArchiveGroupService/CreateArchiveByImport",
|
||||
SubscribeJointTask: "singer.JointTaskService/SubscribeJointTask",
|
||||
SubscribeGroupFragment: "singer.VideoService/SubscribeVideoFragmentStatus",
|
||||
// 监听视频分片状态变化,包括新建、删除、变化
|
||||
SubscribeGroup: "singer.VideoService/SubscribeGroup",
|
||||
// 监听视频分组状态变化,列表变化也通知
|
||||
SubscribeStreamEvent: "singer.MediaManagerService/SubscribeStreamEvent"
|
||||
// 监听视频分组状态变化,列表变化也通知
|
||||
};
|
||||
var useSocket_default = (topic, iterator = import_func.noop, opt) => {
|
||||
const {
|
||||
req = {},
|
||||
throttle = 0,
|
||||
beforeLoopTmp = getSelf,
|
||||
shouldBreak = false,
|
||||
forceRefresh,
|
||||
close
|
||||
} = opt || {};
|
||||
const reqstring = (0, import_react.useMemo)(() => {
|
||||
const newReq = {
|
||||
...req,
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem("USER-TOKEN")
|
||||
}
|
||||
};
|
||||
return JSON.stringify(newReq);
|
||||
}, [req]);
|
||||
const latestIterator = (0, import_hooks.useLatest)(iterator);
|
||||
(0, import_hooks.useDeepEffect)(() => {
|
||||
if (close) {
|
||||
return;
|
||||
}
|
||||
if (shouldBreak) {
|
||||
return;
|
||||
}
|
||||
let tmpData = [];
|
||||
const throttleUpdate = (0, import_func.throttle)(() => {
|
||||
if (tmpData.length == 0) {
|
||||
return;
|
||||
}
|
||||
const _tmpData = beforeLoopTmp(tmpData);
|
||||
latestIterator.current(_tmpData);
|
||||
tmpData = [];
|
||||
}, throttle);
|
||||
const unSubscribe = import_ws.default.subscribe(SocketApi[topic], reqstring, (socketData) => {
|
||||
try {
|
||||
if (!throttle) {
|
||||
latestIterator.current(socketData);
|
||||
} else {
|
||||
tmpData.push(socketData);
|
||||
throttleUpdate();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("useSocke:", error);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
try {
|
||||
unSubscribe();
|
||||
throttleUpdate.cancel();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}, [topic, reqstring, shouldBreak, forceRefresh, close]);
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
SocketApi
|
||||
});
|
2
packages/biz/lib/useSocket/onceChannel.d.ts
vendored
2
packages/biz/lib/useSocket/onceChannel.d.ts
vendored
@ -1,2 +0,0 @@
|
||||
declare const startChannel: (topic: any, req: any, callback: any) => () => void;
|
||||
export default startChannel;
|
@ -1,51 +0,0 @@
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/useSocket/onceChannel.tsx
|
||||
var onceChannel_exports = {};
|
||||
__export(onceChannel_exports, {
|
||||
default: () => onceChannel_default
|
||||
});
|
||||
module.exports = __toCommonJS(onceChannel_exports);
|
||||
var import_ws = __toESM(require("./ws"));
|
||||
var startChannel = (topic, req, callback) => {
|
||||
let reqstring = JSON.stringify({
|
||||
...req,
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem("USER-TOKEN")
|
||||
}
|
||||
});
|
||||
let unSubscribe = import_ws.default.subscribe(topic, reqstring, (socketData) => {
|
||||
let shouldStop = callback(socketData);
|
||||
if (shouldStop) {
|
||||
unSubscribe == null ? void 0 : unSubscribe();
|
||||
}
|
||||
});
|
||||
return unSubscribe;
|
||||
};
|
||||
var onceChannel_default = startChannel;
|
@ -1,224 +0,0 @@
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/useSocket/ws.ts
|
||||
var ws_exports = {};
|
||||
__export(ws_exports, {
|
||||
default: () => ws_default
|
||||
});
|
||||
module.exports = __toCommonJS(ws_exports);
|
||||
var import_uuid = require("uuid");
|
||||
var import_func = require("@zhst/func");
|
||||
var import_socket = __toESM(require("socket.io-client"));
|
||||
var import_constants = require("@common/constants");
|
||||
var EMITSTATE = {
|
||||
NOT_CONNECT: 0,
|
||||
WAITING: 1,
|
||||
CONNECT: 2
|
||||
};
|
||||
var initRetryTime = 0;
|
||||
var intervalTime = 5 * 1e3;
|
||||
var maxIntervalTime = 1 * 60 * 60 * 1e3;
|
||||
var Channel = class {
|
||||
constructor() {
|
||||
/**
|
||||
* 已存在的订阅列表
|
||||
*/
|
||||
this.listeners = [
|
||||
// {
|
||||
// topic: "",
|
||||
// req: "",
|
||||
// suInfo: {},
|
||||
// hasEmit: false,//是否已经订阅
|
||||
// lastRetryInterval: 0,
|
||||
// handles: {
|
||||
// }
|
||||
// }
|
||||
];
|
||||
/**
|
||||
* 调试信息 记录订阅/反订阅次数
|
||||
*/
|
||||
this.subscribeListenerId = [];
|
||||
this.unSubscribeListenerId = [];
|
||||
this.init = () => {
|
||||
const ioIns = this.ioIns = (0, import_socket.default)(import_constants.SOCKET_HOST, {
|
||||
reconnection: true,
|
||||
transports: ["websocket"],
|
||||
forceNew: true
|
||||
});
|
||||
ioIns.on("connect", (...arg) => {
|
||||
console.debug("connect", arg);
|
||||
this.ioIns = ioIns;
|
||||
this.listeners.forEach((v) => {
|
||||
this.doEmit(v["topic"], v["req"], v["id"]);
|
||||
});
|
||||
});
|
||||
ioIns.on("event", (...arg) => {
|
||||
console.debug("event", arg);
|
||||
});
|
||||
ioIns.on("disconnect", (...arg) => {
|
||||
console.debug("disconnect", arg);
|
||||
this.subscribeListenerId = [];
|
||||
this.unSubscribeListenerId = [];
|
||||
});
|
||||
ioIns.on("reconnect", (...arg) => {
|
||||
console.debug("reconnect", arg);
|
||||
this.listeners.forEach((v) => {
|
||||
v["hasEmit"] = EMITSTATE.NOT_CONNECT;
|
||||
this.doEmit(v["topic"], v["req"], v["id"]);
|
||||
});
|
||||
});
|
||||
};
|
||||
this.retry = (listener) => {
|
||||
const intervalId = setTimeout(() => {
|
||||
const hasExit = this.listeners.find(
|
||||
(v) => v["topic"] === (listener == null ? void 0 : listener["topic"]) && v["req"] === listener["req"]
|
||||
);
|
||||
if (!hasExit)
|
||||
return;
|
||||
listener["hasEmit"] = EMITSTATE.NOT_CONNECT;
|
||||
this.doEmit(listener["topic"], listener["req"], listener["id"]);
|
||||
}, listener.lastRetryInterval);
|
||||
listener.intervalId = intervalId;
|
||||
listener.lastRetryInterval = intervalTime + listener.lastRetryInterval > maxIntervalTime ? maxIntervalTime : intervalTime + listener.lastRetryInterval;
|
||||
};
|
||||
this.doEmit = (topic, req, listenerId) => {
|
||||
var _a, _b;
|
||||
if (!this.ioIns) {
|
||||
this.init();
|
||||
}
|
||||
const hasEmit = this.listeners.find(
|
||||
(v) => v["topic"] === topic && v["req"] === req && v["hasEmit"] !== EMITSTATE.NOT_CONNECT
|
||||
);
|
||||
if (hasEmit) {
|
||||
return;
|
||||
}
|
||||
const listener = this.listeners.find((v) => v["topic"] === topic && v["req"] === req);
|
||||
listener["hasEmit"] = EMITSTATE.WAITING;
|
||||
(_b = (_a = this.ioIns) == null ? void 0 : _a.emit) == null ? void 0 : _b.call(_a, topic, req, (data) => {
|
||||
var _a2, _b2;
|
||||
console.info("emit", topic, req, data);
|
||||
const suInfo = JSON.parse(data);
|
||||
if ((0, import_func.has)(suInfo, "Error.code")) {
|
||||
if (suInfo.Error.code === 500) {
|
||||
this.retry(listener);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.subscribeListenerId.push(listenerId);
|
||||
const currentTopicIndex = this.listeners.findIndex(
|
||||
(v) => v["topic"] === topic && v["req"] === req && v["id"] === listenerId
|
||||
);
|
||||
if (currentTopicIndex == -1) {
|
||||
this.ioIns.emit("UnSubscribe", JSON.stringify(suInfo), (data2) => {
|
||||
this.unSubscribeListenerId.push(listenerId);
|
||||
console.debug("UNSUBSCRIBE", listenerId, topic, req, data2);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!suInfo["SubscribeID"]) {
|
||||
this.listeners.splice(currentTopicIndex, 0);
|
||||
} else {
|
||||
this.listeners[currentTopicIndex]["suInfo"] = suInfo;
|
||||
this.listeners[currentTopicIndex]["hasEmit"] = EMITSTATE.CONNECT;
|
||||
}
|
||||
(_b2 = (_a2 = this.ioIns) == null ? void 0 : _a2.on) == null ? void 0 : _b2.call(_a2, suInfo["SubscribeID"], (data2) => {
|
||||
console.info("on", suInfo["SubscribeID"], data2);
|
||||
try {
|
||||
const socketData = JSON.parse(data2);
|
||||
if ((0, import_func.has)(socketData, "Error.code")) {
|
||||
if (socketData.Error.code === 500) {
|
||||
this.retry(listener);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const { handles = {} } = this.listeners.find((v) => v["topic"] === topic && v["req"] === req) || {};
|
||||
Object.keys(handles).forEach((key) => {
|
||||
try {
|
||||
const func = handles[key];
|
||||
if (!func)
|
||||
return;
|
||||
func(socketData);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.debug("error", error);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
subscribe(topic, req, handle) {
|
||||
const handleId = (0, import_uuid.v4)();
|
||||
const listenerId = (0, import_uuid.v4)();
|
||||
const listener = this.listeners.find((v) => v["topic"] === topic && v["req"] === req);
|
||||
if (listener) {
|
||||
listener["handles"][handleId] = handle;
|
||||
} else {
|
||||
this.listeners.push({
|
||||
topic,
|
||||
req,
|
||||
suInfo: {},
|
||||
id: listenerId,
|
||||
hasEmit: EMITSTATE.NOT_CONNECT,
|
||||
lastRetryInterval: initRetryTime,
|
||||
handles: {
|
||||
[`${handleId}`]: handle
|
||||
}
|
||||
});
|
||||
this.doEmit(topic, req, listenerId);
|
||||
}
|
||||
return this.unSubscribe.bind(this, topic, req, handleId, listenerId);
|
||||
}
|
||||
unSubscribe(topic, req, handleId, listenerId) {
|
||||
const listener = this.listeners.find(
|
||||
(v) => v["topic"] === topic && v["req"] === req && v["id"] === listenerId
|
||||
);
|
||||
const { handles = {}, suInfo } = listener || {};
|
||||
if (handles[handleId]) {
|
||||
delete handles[handleId];
|
||||
if (Object.keys(handles).length === 0) {
|
||||
if (this.intervalId) {
|
||||
clearTimeout(this.intervalId);
|
||||
}
|
||||
if (listener["hasEmit"] === EMITSTATE["CONNECT"]) {
|
||||
this.ioIns.emit("UnSubscribe", JSON.stringify(suInfo), (data) => {
|
||||
this.unSubscribeListenerId.push(listenerId);
|
||||
console.debug("UNSUBSCRIBE", listener["id"], topic, req, data);
|
||||
});
|
||||
}
|
||||
this.listeners = this.listeners.filter((v) => !(v["topic"] === topic && v["req"] === req));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var channelIns = new Channel();
|
||||
window.__channel__ = channelIns;
|
||||
var ws_default = channelIns;
|
31
packages/biz/lib/utils/constants.d.ts
vendored
31
packages/biz/lib/utils/constants.d.ts
vendored
@ -1,31 +0,0 @@
|
||||
export declare const OBJECT_GRNER_THRESHOLD = 0.8;
|
||||
export declare const OBJECT_AGE_TYPE_THRESHOLD = 0.5;
|
||||
export declare const MODE_KEY = "test_mode";
|
||||
export declare const SEARCH_IMG_COUNT = 10;
|
||||
export declare const GLOBAL_IS_ITEM_NUMBER_SHOW = false;
|
||||
export declare const publicPath = "hummingbird";
|
||||
export declare const ENTER_CIRCLE = "MONITORTYPE_ENTER_CIRCLE";
|
||||
export declare const OUT_CIRCLE = "MONITORTYPE_OUT_CIRCLE";
|
||||
export declare const TEMP = "MONITORTYPE_TEMP";
|
||||
export declare const GLOBAL_IS_BOX_VMS_SHOW = true;
|
||||
export declare const BODY_SEARCH_THRESHOID = 0.45;
|
||||
export declare const RECORD_VERSION = "3.0.0";
|
||||
export declare const DeviceTab: {
|
||||
EMPTY: number;
|
||||
REAL_CAMERA: number;
|
||||
PREPROCESS_CAMERA: number;
|
||||
TAG_CAMERA: number;
|
||||
HISTORY_VIDEO_GROUP: number;
|
||||
VIRTUAL_CAMERA: number;
|
||||
REAL_CAMERA_NOFACE: number;
|
||||
REAL_CAMERA_ONLYFACE: number;
|
||||
REAL_CAMERA_NOFACE_NOBOX_NODIRECONNECT: number;
|
||||
};
|
||||
export declare const BOX_TYPE_LIST: {
|
||||
value: string;
|
||||
label: string;
|
||||
}[];
|
||||
export declare const ALL_LIST: {
|
||||
value: string;
|
||||
label: string;
|
||||
}[];
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zhst/biz",
|
||||
"version": "0.9.1",
|
||||
"version": "0.9.6",
|
||||
"description": "业务库",
|
||||
"keywords": [
|
||||
"business",
|
||||
|
@ -1,24 +1,11 @@
|
||||
import React, { FC } from 'react';
|
||||
import { InputProps, Tabs, TabsProps, TreeDataNode, TreeProps } from 'antd'
|
||||
import { Tabs, TabsProps } from 'antd'
|
||||
import BoxPanel from './components/boxPanel';
|
||||
import { ModalFormProps } from '@ant-design/pro-components';
|
||||
import type { BoxPanelProps } from './components/boxPanel';
|
||||
|
||||
export interface BoxSelectTreeProps {
|
||||
boxDataSource: TreeDataNode[]
|
||||
data: TreeDataNode[]
|
||||
onSearch?: (e: any) => void // 搜索
|
||||
onItemSelect?: TreeProps['onSelect']
|
||||
onItemCheck?: TreeProps['onCheck']
|
||||
export interface BoxSelectTreeProps extends BoxPanelProps {
|
||||
onTabChange?: (e: any) => void
|
||||
onBoxBatchDelete?: (data?: any) => void
|
||||
onBoxDelete?: (data?: any) => void
|
||||
onCreateSubmit?: ModalFormProps['onFinish']
|
||||
tabsProps?: TabsProps
|
||||
searchInputProps?: InputProps
|
||||
treeProps?: TreeProps
|
||||
showOptions?: boolean
|
||||
customImport?: any
|
||||
extraBtns?: any
|
||||
}
|
||||
|
||||
const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
@ -32,18 +19,17 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
onBoxBatchDelete,
|
||||
onBoxDelete,
|
||||
onCreateSubmit,
|
||||
onClockClick,
|
||||
onImport,
|
||||
onCreate,
|
||||
tabsProps,
|
||||
searchInputProps,
|
||||
treeProps,
|
||||
customImport,
|
||||
showOptions,
|
||||
extraBtns,
|
||||
showOptions = true
|
||||
} = props
|
||||
|
||||
const onChange = (key: string) => {
|
||||
onTabChange?.(key)
|
||||
};
|
||||
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
@ -54,6 +40,7 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
boxDataSource={boxDataSource}
|
||||
treeProps={treeProps}
|
||||
data={data}
|
||||
onCreate={onCreate}
|
||||
onCreateSubmit={onCreateSubmit}
|
||||
onBoxBatchDelete={onBoxBatchDelete}
|
||||
onBoxDelete={onBoxDelete}
|
||||
@ -63,6 +50,8 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
showOptions={showOptions}
|
||||
customImport={customImport}
|
||||
extraBtns={extraBtns}
|
||||
onClockClick={onClockClick}
|
||||
onImport={onImport}
|
||||
/>
|
||||
)
|
||||
},
|
||||
@ -75,6 +64,7 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
searchInputProps={searchInputProps}
|
||||
treeProps={treeProps}
|
||||
data={data}
|
||||
onCreate={onCreate}
|
||||
onBoxBatchDelete={onBoxBatchDelete}
|
||||
onCreateSubmit={onCreateSubmit}
|
||||
onBoxDelete={onBoxDelete}
|
||||
@ -84,6 +74,8 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
showOptions={showOptions}
|
||||
customImport={customImport}
|
||||
extraBtns={extraBtns}
|
||||
onClockClick={onClockClick}
|
||||
onImport={onImport}
|
||||
/>
|
||||
)
|
||||
},
|
||||
@ -94,7 +86,7 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||
defaultActiveKey="1"
|
||||
centered
|
||||
items={items}
|
||||
onChange={onChange}
|
||||
onChange={onTabChange}
|
||||
tabBarGutter={0}
|
||||
indicator={{ size: (origin) => origin, align: 'center' }}
|
||||
{...tabsProps}
|
||||
|
@ -3,13 +3,14 @@ import{ Button, Divider, Input, Space, TreeDataNode } from 'antd'
|
||||
import { ModalForm, ModalFormProps, ProFormInstance, ProFormText } from '@ant-design/pro-components'
|
||||
import { ClockCircleOutlined, CloseCircleOutlined, DiffOutlined, FolderAddOutlined, ImportOutlined, SwitcherOutlined } from '@ant-design/icons'
|
||||
import type { TreeProps, InputProps } from 'antd';
|
||||
import type { BoxTreeProps } from '../../../tree';
|
||||
import TreeTransferModal from '../../../treeTransferModal'
|
||||
import BoxTree from '../../../tree';
|
||||
|
||||
export interface BoxGroupPanelProps {
|
||||
export interface BoxPanelProps {
|
||||
searchInputProps?: InputProps
|
||||
showOptions?: boolean
|
||||
treeProps?: TreeProps
|
||||
treeProps?: Partial<BoxTreeProps>
|
||||
data: TreeDataNode[]
|
||||
boxDataSource: TreeDataNode[]
|
||||
handleImport?: () => void
|
||||
@ -20,11 +21,14 @@ export interface BoxGroupPanelProps {
|
||||
onBoxDelete?: (data?: any) => void
|
||||
onCreateSubmit?: ModalFormProps['onFinish']
|
||||
onClockClick?: () => void
|
||||
onImport?: () => void
|
||||
onBatch?: () => void
|
||||
onCreate?: () => void
|
||||
customImport?: any
|
||||
extraBtns?: any
|
||||
}
|
||||
|
||||
const BoxGroupPanel: FC<BoxGroupPanelProps> = (props) => {
|
||||
const BoxPanel: FC<BoxPanelProps> = (props) => {
|
||||
const {
|
||||
searchInputProps,
|
||||
showOptions = true,
|
||||
@ -38,6 +42,9 @@ const BoxGroupPanel: FC<BoxGroupPanelProps> = (props) => {
|
||||
onBoxBatchDelete,
|
||||
onBoxDelete,
|
||||
onClockClick,
|
||||
onImport,
|
||||
onBatch,
|
||||
onCreate,
|
||||
boxDataSource,
|
||||
customImport
|
||||
} = props
|
||||
@ -116,7 +123,7 @@ const BoxGroupPanel: FC<BoxGroupPanelProps> = (props) => {
|
||||
<Input size='middle' onChange={(e) => onSearch?.(e)} placeholder='请输入盒子名称' {...searchInputProps} />
|
||||
{customImport || (
|
||||
<>
|
||||
<Button type="text" onClick={() => handleCheckable()} icon={!isTreeCheckable ? <DiffOutlined /> : <SwitcherOutlined />} />
|
||||
<Button type="text" onClick={() => onBatch?.() || handleCheckable()} icon={isTreeCheckable ? <SwitcherOutlined /> : <DiffOutlined />} />
|
||||
<Button type="text" onClick={() => onClockClick?.()} icon={<ClockCircleOutlined />} />
|
||||
</>
|
||||
)}
|
||||
@ -125,58 +132,65 @@ const BoxGroupPanel: FC<BoxGroupPanelProps> = (props) => {
|
||||
{showOptions && (
|
||||
<>
|
||||
<Space align='center'>
|
||||
<Button type='text' style={{ padding: '4px 8px' }} icon={<ImportOutlined />} >导入盒子</Button>
|
||||
<Button type='text' style={{ padding: '4px 8px' }} onClick={() => onImport?.()} icon={<ImportOutlined />} >导入盒子</Button>
|
||||
<Divider type="vertical" style={{ margin: '8px 0' }} />
|
||||
<ModalForm<{
|
||||
name: string
|
||||
boxList?: any[]
|
||||
}>
|
||||
width={'600px'}
|
||||
formRef={createFormRef}
|
||||
title="新建组"
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
layout='horizontal'
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 18 }}
|
||||
trigger={<Button type='text' style={{ padding: '4px 8px' }} icon={<FolderAddOutlined />} >新建组</Button>}
|
||||
submitter={{
|
||||
searchConfig: {
|
||||
submitText: '确定',
|
||||
resetText: '取消',
|
||||
},
|
||||
}}
|
||||
onFinish={onCreateSubmit}
|
||||
>
|
||||
<ProFormText
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
width="md"
|
||||
name="name"
|
||||
label="盒子组名称"
|
||||
placeholder="请输入盒子名称"
|
||||
/>
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="boxList"
|
||||
label="盒子选择"
|
||||
fieldProps={{
|
||||
readOnly: true,
|
||||
value: `已选择${createFormRef.current?.getFieldValue('boxList')?.length || 0}个盒子`,
|
||||
suffix: (
|
||||
<Space>
|
||||
<a onClick={() => {
|
||||
createFormRef.current?.setFieldValue('boxList', null)
|
||||
onBoxChoiceReset()
|
||||
}} >恢复默认</a>
|
||||
<a onClick={() => setBoxChoiceOpen(true)}>范围选择</a>
|
||||
</Space>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</ModalForm>
|
||||
{onCreate ?
|
||||
(
|
||||
<Button onClick={onCreate} type='text' style={{ padding: '4px 8px' }} icon={<FolderAddOutlined />} >新建组</Button>
|
||||
) : (
|
||||
<ModalForm<{
|
||||
name: string
|
||||
boxList?: any[]
|
||||
}>
|
||||
width={'600px'}
|
||||
open={onCreate ? false : undefined}
|
||||
formRef={createFormRef}
|
||||
title="新建组"
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
layout='horizontal'
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 18 }}
|
||||
trigger={<Button type='text' style={{ padding: '4px 8px' }} icon={<FolderAddOutlined />} >新建组</Button>}
|
||||
submitter={{
|
||||
searchConfig: {
|
||||
submitText: '确定',
|
||||
resetText: '取消',
|
||||
},
|
||||
}}
|
||||
onFinish={onCreateSubmit}
|
||||
>
|
||||
<ProFormText
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
width="md"
|
||||
name="name"
|
||||
label="盒子组名称"
|
||||
placeholder="请输入盒子名称"
|
||||
/>
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="boxList"
|
||||
label="盒子选择"
|
||||
fieldProps={{
|
||||
readOnly: true,
|
||||
value: `已选择${createFormRef.current?.getFieldValue('boxList')?.length || 0}个盒子`,
|
||||
suffix: (
|
||||
<Space>
|
||||
<a onClick={() => {
|
||||
createFormRef.current?.setFieldValue('boxList', null)
|
||||
onBoxChoiceReset()
|
||||
}} >恢复默认</a>
|
||||
<a onClick={() => setBoxChoiceOpen(true)}>范围选择</a>
|
||||
</Space>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</ModalForm>
|
||||
)
|
||||
}
|
||||
<Divider type="vertical" style={{ margin: '8px 0' }} />
|
||||
{/* @ts-ignore */}
|
||||
<Button danger type='text' style={{ padding: '4px 8px' }} icon={<CloseCircleOutlined />} disabled={treeProps?.checkedKeys?.length <= 0} onClick={onBoxBatchDelete} >删除</Button>
|
||||
@ -198,4 +212,4 @@ const BoxGroupPanel: FC<BoxGroupPanelProps> = (props) => {
|
||||
)
|
||||
}
|
||||
|
||||
export default BoxGroupPanel
|
||||
export default BoxPanel
|
||||
|
82
packages/biz/src/boxSelectTree/demo/async.tsx
Normal file
82
packages/biz/src/boxSelectTree/demo/async.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import React, { useState } from 'react';
|
||||
import { BoxSelectTree } from '@zhst/biz';
|
||||
import { boxDataSource } from './mock'
|
||||
|
||||
interface DataNode {
|
||||
title: string;
|
||||
key: string;
|
||||
isLeaf?: boolean;
|
||||
children?: DataNode[];
|
||||
}
|
||||
|
||||
const initTreeData: DataNode[] = [
|
||||
{ title: '盒子组1', key: '0' },
|
||||
{ title: '盒子组2', key: '1' },
|
||||
{ title: '盒子组3', key: '2', isLeaf: true },
|
||||
];
|
||||
|
||||
/**
|
||||
* 递归更新树结构
|
||||
* @param list 原数组列表
|
||||
* @param key 当前选中的项
|
||||
* @param children 需要插入更新的数据
|
||||
* @returns newList
|
||||
*/
|
||||
const updateTreeData = (list: DataNode[], key: React.Key, children: DataNode[]): DataNode[] =>
|
||||
list.map((node) => {
|
||||
if (node.key === key) {
|
||||
return {
|
||||
...node,
|
||||
children,
|
||||
};
|
||||
}
|
||||
if (node.children) {
|
||||
return {
|
||||
...node,
|
||||
children: updateTreeData(node.children, key, children),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
});
|
||||
|
||||
const demo = () => {
|
||||
const [treeData, setTreeData] = useState(initTreeData);
|
||||
const [activeKey, setActiveKey] = useState('1')
|
||||
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
|
||||
|
||||
const onLoadData = ({ key, children }: any) =>
|
||||
new Promise<void>((resolve) => {
|
||||
if (children) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
setTreeData((origin) =>
|
||||
updateTreeData(origin, key, [
|
||||
{ title: '盒子', key: `${key}-0` },
|
||||
{ title: '盒子', key: `${key}-1` },
|
||||
]),
|
||||
);
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
||||
<BoxSelectTree
|
||||
data={treeData}
|
||||
boxDataSource={boxDataSource}
|
||||
showOptions={false}
|
||||
tabsProps={{
|
||||
activeKey,
|
||||
}}
|
||||
treeProps={{
|
||||
loadData: (_params) => onLoadData(_params),
|
||||
checkedKeys
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default demo;
|
@ -47,8 +47,9 @@ const demo = () => {
|
||||
onItemCheck={onTreeCheck}
|
||||
onItemSelect={e => console.log('onItemSelect', e)}
|
||||
onTabChange={val => setActiveKey(val)}
|
||||
onBoxDelete={data => console.log('盒子删除', data)}
|
||||
onBoxBatchDelete={onBoxBatchDelete}
|
||||
onClockClick={() => console.log('时钟点击事件')}
|
||||
onImport={() => console.log('导入盒子')}
|
||||
tabsProps={{
|
||||
activeKey,
|
||||
}}
|
||||
@ -71,7 +72,11 @@ const demo = () => {
|
||||
value: searchVal
|
||||
}}
|
||||
treeProps={{
|
||||
checkedKeys
|
||||
onItemDelete: data => console.log('删除', data),
|
||||
onItemSetting: data => console.log('配置事件', data),
|
||||
onItemRename: (data) =>console.log('重命名', data),
|
||||
onItemRenameFinish: async (val, data) => console.log('盒子重命名提交(返回boolean,控制弹框显示\隐藏)', val, data),
|
||||
checkedKeys,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
category: Components
|
||||
title: BoxSelectTree 盒子树
|
||||
demo:
|
||||
cols: 4
|
||||
cols: 2
|
||||
group:
|
||||
title: 进阶组件
|
||||
order: 2
|
||||
@ -15,6 +15,7 @@ group:
|
||||
<code src="./demo/basic.tsx">基本用法</code>
|
||||
<code src="./demo/extraBtns.tsx">自定义其它按钮</code>
|
||||
<code src="./demo/noOptions.tsx">不显示其它按钮</code>
|
||||
<code src="./demo/async.tsx">异步加载数据</code>
|
||||
|
||||
## API
|
||||
|
||||
@ -30,5 +31,8 @@ group:
|
||||
| onBoxDelete | 盒子删除事件 | function: (e) => void | - | - |
|
||||
| onBoxBatchDelete | 盒子批量删除事件 | function: (e) => void | - | - |
|
||||
| onCreateSubmit | 新建提交事件 | function: (e) => void | - | - |
|
||||
| onImport | 监听导入盒子点击事件 | function: () => void | - | - |
|
||||
| onClockClick | 监听时钟点击事件 | function: () => void | - | - |
|
||||
| onCreate | 监听创建点击事件 | function: () => void | 如果不传默认用自带的创建事件 | - |
|
||||
| showOptions | 展示其它功能按钮 | boolean | true | - |
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import BoxSelectTree from './boxSelectTree';
|
||||
|
||||
export type { BoxSelectTreeProps } from './boxSelectTree'
|
||||
|
||||
export default BoxSelectTree;
|
||||
|
@ -1,8 +1,12 @@
|
||||
export { default as BigImageModal } from './BigImageModal'
|
||||
export type { BigImageModalProps } from './BigImageModal'
|
||||
export { default as BoxSelectTree } from './boxSelectTree'
|
||||
export type { BoxSelectTreeProps } from './boxSelectTree'
|
||||
export { default as Tree } from './tree'
|
||||
export type { TreeData } from './tree'
|
||||
export type { BoxTreeProps, TreeData } from './tree'
|
||||
export { default as TreeTransfer } from './treeTransfer'
|
||||
export type { TreeTransferProps } from './treeTransfer'
|
||||
export { default as TreeTransferModal } from './treeTransferModal'
|
||||
export type { TreeTransferModalProps } from './treeTransferModal'
|
||||
export { default as WarningRecordCard } from './WarningRecordCard'
|
||||
export type {IRecord, WarningRecordCardProps} from './WarningRecordCard'
|
||||
export type { WarningRecordCardProps, IRecord } from './WarningRecordCard'
|
||||
|
@ -17,7 +17,8 @@ export interface BoxTreeProps extends TreeProps {
|
||||
onItemSelect?: TreeProps['onSelect']
|
||||
onItemSetting?: (_data: any) => void
|
||||
onItemDelete?: (_data: any) => void
|
||||
onRenameFinish?: (_data: any, _nodeData: any) => Promise<any>
|
||||
onItemRename?: (_nodeData: any) => void
|
||||
onItemRenameFinish?: (_data: any, _nodeData: any) => Promise<any>
|
||||
}
|
||||
|
||||
const boxTree: FC<BoxTreeProps> = (props) => {
|
||||
@ -29,15 +30,18 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
||||
data = [],
|
||||
showItemOption = true,
|
||||
treeCheckable = false,
|
||||
onRenameFinish,
|
||||
onItemRename,
|
||||
onItemRenameFinish,
|
||||
customOptions
|
||||
} = props
|
||||
const { token } = useToken()
|
||||
const [checkedItem, setCheckedItem] = useState<React.Key>('')
|
||||
|
||||
const cameraStatus = new Map([
|
||||
['0', 'success'],
|
||||
['1', 'error']
|
||||
['0', 'error'],
|
||||
['1', 'success'],
|
||||
['3', 'processing'],
|
||||
['4', 'default'],
|
||||
])
|
||||
|
||||
return (
|
||||
@ -54,7 +58,7 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
||||
return (
|
||||
<div className={`${componentName}-item-render`}>
|
||||
{/* @ts-ignore */}
|
||||
{!_nodeData.children && _nodeData.isCamera && <Badge style={{ marginRight: '6px' }} status={cameraStatus.get('0')} />}
|
||||
{!_nodeData.children && _nodeData.isCamera && <Badge style={{ marginRight: '6px' }} status={cameraStatus.get(_nodeData.status || '4')} />}
|
||||
<span
|
||||
// @ts-ignore
|
||||
style={(checkedItem === _nodeData.key) && _nodeData.isCamera ? {
|
||||
@ -74,14 +78,18 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
||||
layout='horizontal'
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 18 }}
|
||||
trigger={<EditOutlined />}
|
||||
trigger={<EditOutlined onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onItemRename?.(_nodeData)
|
||||
}} />}
|
||||
submitter={{
|
||||
searchConfig: {
|
||||
submitText: '确定',
|
||||
resetText: '取消',
|
||||
},
|
||||
}}
|
||||
onFinish={async (value) => onRenameFinish?.(value, _nodeData)}
|
||||
onFinish={async (value) => onItemRenameFinish?.(value, _nodeData)}
|
||||
>
|
||||
<ProFormText
|
||||
rules={[
|
||||
@ -95,8 +103,16 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
||||
placeholder="请输入盒子名称"
|
||||
/>
|
||||
</ModalForm>
|
||||
<SettingOutlined onClick={() => onItemSetting?.(_nodeData)} />
|
||||
<CloseOutlined onClick={() => onItemDelete?.(_nodeData)} />
|
||||
<SettingOutlined onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onItemSetting?.(_nodeData)}
|
||||
} />
|
||||
<CloseOutlined onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onItemDelete?.(_nodeData)
|
||||
}} />
|
||||
</>
|
||||
)}
|
||||
</Space>
|
||||
|
@ -4,7 +4,13 @@ import BoxTree from './boxTree';
|
||||
export interface TreeData extends TreeDataNode {
|
||||
children?: TreeDataNode['children'] & {
|
||||
isCamera?: boolean
|
||||
/**
|
||||
* 0-失败 1-成功 2-进行中 3-未知
|
||||
*/
|
||||
status?: '0' | '1' | '2' | '3'
|
||||
}[]
|
||||
}
|
||||
|
||||
export type { BoxTreeProps } from './boxTree'
|
||||
|
||||
export default BoxTree;
|
||||
|
@ -1,3 +1,7 @@
|
||||
import TreeTransfer from "./TreeTransfer";
|
||||
|
||||
export type { TreeTransferProps } from './TreeTransfer'
|
||||
|
||||
export * from './treeTransferHelper'
|
||||
|
||||
export default TreeTransfer
|
||||
|
@ -1,3 +1,5 @@
|
||||
import TreeTransferModal from './TreeTransferModal'
|
||||
|
||||
export type { TreeTransferModalProps } from './TreeTransferModal'
|
||||
|
||||
export default TreeTransferModal
|
||||
|
@ -1,99 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import { throttle as loadshThrottle, noop } from '@zhst/func';
|
||||
import { useDeepEffect, useLatest } from '@zhst/hooks';
|
||||
import ws from './ws';
|
||||
|
||||
const getSelf = (v: any) => v;
|
||||
export const SocketApi = {
|
||||
CameraTaskStatue: 'singer.DeviceService/SubScribeCameraTaskStatus',
|
||||
DeviceStatus: 'singer.TaskManagerService/SubscribeTaskStatus',
|
||||
SubscribeSolutionDeploy: 'singer.SolutionManagerService/SubscribeSolutionDeploy',
|
||||
SubscribeTasksSummary: 'singer.TaskManagerService/SubscribeTasksSummary',
|
||||
MonitorSubscribeResult: 'singer.MonitorService/MonitorSubscribeResult',
|
||||
MonitorSubscribeStatus: 'singer.MonitorService/MonitorSubscribeStatus',
|
||||
SubscribeArchiveGroupUpload: 'singer.ArchiveGroupService/CreateArchiveByImport',
|
||||
SubscribeJointTask: 'singer.JointTaskService/SubscribeJointTask',
|
||||
SubscribeGroupFragment: 'singer.VideoService/SubscribeVideoFragmentStatus', // 监听视频分片状态变化,包括新建、删除、变化
|
||||
SubscribeGroup: 'singer.VideoService/SubscribeGroup', // 监听视频分组状态变化,列表变化也通知
|
||||
SubscribeStreamEvent: 'singer.MediaManagerService/SubscribeStreamEvent', // 监听视频分组状态变化,列表变化也通知
|
||||
};
|
||||
type ApiKeys = keyof typeof SocketApi;
|
||||
|
||||
export default (
|
||||
topic: ApiKeys,
|
||||
iterator: any = noop,
|
||||
opt?: {
|
||||
req?: { [key: string]: any };
|
||||
throttle?: number;
|
||||
parseData?: boolean;
|
||||
beforeLoopTmp?: Function;
|
||||
shouldBreak: boolean;
|
||||
forceRefresh: any;
|
||||
close?: boolean;
|
||||
}
|
||||
) => {
|
||||
const {
|
||||
req = {},
|
||||
throttle = 0,
|
||||
beforeLoopTmp = getSelf,
|
||||
shouldBreak = false,
|
||||
forceRefresh,
|
||||
close,
|
||||
} = opt || {};
|
||||
|
||||
// 带上token
|
||||
const reqstring = useMemo(() => {
|
||||
const newReq = {
|
||||
...req,
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem('USER-TOKEN'),
|
||||
},
|
||||
};
|
||||
return JSON.stringify(newReq);
|
||||
}, [req]);
|
||||
|
||||
const latestIterator = useLatest(iterator);
|
||||
useDeepEffect(() => {
|
||||
if (close) {
|
||||
return;
|
||||
}
|
||||
//控制socket 请求发送
|
||||
if (shouldBreak) {
|
||||
return;
|
||||
}
|
||||
//去抖动
|
||||
|
||||
let tmpData: any = [];
|
||||
const throttleUpdate = loadshThrottle(() => {
|
||||
if (tmpData.length == 0) {
|
||||
return;
|
||||
}
|
||||
const _tmpData = beforeLoopTmp(tmpData);
|
||||
latestIterator.current(_tmpData); //加了throttle 数据就变成数组
|
||||
tmpData = [];
|
||||
}, throttle);
|
||||
|
||||
const unSubscribe = ws.subscribe(SocketApi[topic], reqstring, (socketData: any) => {
|
||||
try {
|
||||
if (!throttle) {
|
||||
latestIterator.current(socketData);
|
||||
} else {
|
||||
tmpData.push(socketData);
|
||||
throttleUpdate();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('useSocke:', error);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
try {
|
||||
unSubscribe();
|
||||
throttleUpdate.cancel();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}, [topic, reqstring, shouldBreak, forceRefresh, close]);
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
//@ts-nocheck
|
||||
import channel from './ws';
|
||||
|
||||
const startChannel = (topic, req, callback) => {
|
||||
// 带上token
|
||||
let reqstring = JSON.stringify({
|
||||
...req,
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem('USER-TOKEN'),
|
||||
},
|
||||
});
|
||||
|
||||
let unSubscribe = channel.subscribe(topic, reqstring, (socketData) => {
|
||||
let shouldStop = callback(socketData);
|
||||
if (shouldStop) {
|
||||
unSubscribe?.();
|
||||
}
|
||||
});
|
||||
|
||||
return unSubscribe;
|
||||
};
|
||||
|
||||
export default startChannel;
|
@ -1,222 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { has } from '@zhst/func';
|
||||
import io from 'socket.io-client';
|
||||
import { SOCKET_HOST } from '@common/constants';
|
||||
|
||||
const EMITSTATE = {
|
||||
NOT_CONNECT: 0,
|
||||
WAITING: 1,
|
||||
CONNECT: 2,
|
||||
};
|
||||
|
||||
const initRetryTime = 0;
|
||||
const intervalTime = 5 * 1000; //下次重试增加时间
|
||||
const maxIntervalTime = 1 * 60 * 60 * 1000; //最大重试时间1小时
|
||||
|
||||
class Channel {
|
||||
/**
|
||||
* io 实例化对象
|
||||
*/
|
||||
ioIns;
|
||||
/**
|
||||
* 已存在的订阅列表
|
||||
*/
|
||||
listeners = [
|
||||
// {
|
||||
// topic: "",
|
||||
// req: "",
|
||||
// suInfo: {},
|
||||
// hasEmit: false,//是否已经订阅
|
||||
// lastRetryInterval: 0,
|
||||
// handles: {
|
||||
// }
|
||||
// }
|
||||
];
|
||||
|
||||
/**
|
||||
* 调试信息 记录订阅/反订阅次数
|
||||
*/
|
||||
subscribeListenerId = [];
|
||||
unSubscribeListenerId = [];
|
||||
|
||||
init = () => {
|
||||
const ioIns = (this.ioIns = io(SOCKET_HOST, {
|
||||
reconnection: true,
|
||||
transports: ['websocket'],
|
||||
forceNew: true,
|
||||
}));
|
||||
ioIns.on('connect', (...arg: any) => {
|
||||
console.debug('connect', arg);
|
||||
this.ioIns = ioIns;
|
||||
this.listeners.forEach((v) => {
|
||||
this.doEmit(v['topic'], v['req'], v['id']);
|
||||
});
|
||||
});
|
||||
|
||||
ioIns.on('event', (...arg: any) => {
|
||||
console.debug('event', arg);
|
||||
});
|
||||
|
||||
ioIns.on('disconnect', (...arg: any) => {
|
||||
console.debug('disconnect', arg);
|
||||
this.subscribeListenerId = [];
|
||||
this.unSubscribeListenerId = [];
|
||||
});
|
||||
|
||||
ioIns.on('reconnect', (...arg: any) => {
|
||||
console.debug('reconnect', arg);
|
||||
this.listeners.forEach((v) => {
|
||||
v['hasEmit'] = EMITSTATE.NOT_CONNECT;
|
||||
this.doEmit(v['topic'], v['req'], v['id']);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
retry = (listener: { [x: string]: any; lastRetryInterval: number | undefined; intervalId: NodeJS.Timeout; } | undefined) => {
|
||||
//重试逻辑
|
||||
const intervalId = setTimeout(() => {
|
||||
const hasExit = this.listeners.find(
|
||||
(v) => v['topic'] === listener?.['topic'] && v['req'] === listener['req']
|
||||
);
|
||||
if (!hasExit) return;
|
||||
listener['hasEmit'] = EMITSTATE.NOT_CONNECT;
|
||||
this.doEmit(listener['topic'], listener['req'], listener['id']);
|
||||
}, listener.lastRetryInterval);
|
||||
|
||||
listener.intervalId = intervalId;
|
||||
listener.lastRetryInterval =
|
||||
intervalTime + listener.lastRetryInterval > maxIntervalTime
|
||||
? maxIntervalTime
|
||||
: intervalTime + listener.lastRetryInterval;
|
||||
};
|
||||
|
||||
doEmit = (topic, req, listenerId) => {
|
||||
if (!this.ioIns) {
|
||||
this.init();
|
||||
}
|
||||
//订阅过就不订阅了
|
||||
const hasEmit = this.listeners.find(
|
||||
(v) => v['topic'] === topic && v['req'] === req && v['hasEmit'] !== EMITSTATE.NOT_CONNECT
|
||||
);
|
||||
if (hasEmit) {
|
||||
return;
|
||||
}
|
||||
const listener = this.listeners.find((v) => v['topic'] === topic && v['req'] === req);
|
||||
listener['hasEmit'] = EMITSTATE.WAITING;
|
||||
|
||||
this.ioIns?.emit?.(topic, req, (data) => {
|
||||
console.info('emit', topic, req, data);
|
||||
const suInfo = JSON.parse(data);
|
||||
if (has(suInfo, 'Error.code')) {
|
||||
if (suInfo.Error.code === 500) {
|
||||
//后端出错
|
||||
this.retry(listener);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// console.debug('SUBSCRIBE', listenerId, topic, req, suInfo);
|
||||
this.subscribeListenerId.push(listenerId);
|
||||
// debugger
|
||||
//重新找一遍topic
|
||||
const currentTopicIndex = this.listeners.findIndex(
|
||||
(v) => v['topic'] === topic && v['req'] === req && v['id'] === listenerId
|
||||
);
|
||||
if (currentTopicIndex == -1) {
|
||||
// 不存在说明listener取消了 直接反订阅
|
||||
this.ioIns.emit('UnSubscribe', JSON.stringify(suInfo), (data) => {
|
||||
this.unSubscribeListenerId.push(listenerId);
|
||||
console.debug('UNSUBSCRIBE', listenerId, topic, req, data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!suInfo['SubscribeID']) {
|
||||
this.listeners.splice(currentTopicIndex, 0);
|
||||
} else {
|
||||
this.listeners[currentTopicIndex]['suInfo'] = suInfo;
|
||||
this.listeners[currentTopicIndex]['hasEmit'] = EMITSTATE.CONNECT;
|
||||
}
|
||||
|
||||
this.ioIns?.on?.(suInfo['SubscribeID'], (data) => {
|
||||
console.info('on', suInfo['SubscribeID'], data);
|
||||
try {
|
||||
const socketData = JSON.parse(data);
|
||||
if (has(socketData, 'Error.code')) {
|
||||
if (socketData.Error.code === 500) {
|
||||
//后端出错
|
||||
this.retry(listener);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const { handles = {} } =
|
||||
this.listeners.find((v) => v['topic'] === topic && v['req'] === req) || {};
|
||||
Object.keys(handles).forEach((key) => {
|
||||
try {
|
||||
//后面观察 为什么delete后在foreach
|
||||
const func = handles[key];
|
||||
if (!func) return;
|
||||
func(socketData);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.debug('error', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
subscribe(topic, req, handle) {
|
||||
const handleId = uuidv4();
|
||||
const listenerId = uuidv4();
|
||||
const listener = this.listeners.find((v) => v['topic'] === topic && v['req'] === req);
|
||||
if (listener) {
|
||||
listener['handles'][handleId] = handle;
|
||||
} else {
|
||||
this.listeners.push({
|
||||
topic: topic,
|
||||
req: req,
|
||||
suInfo: {},
|
||||
id: listenerId,
|
||||
hasEmit: EMITSTATE.NOT_CONNECT,
|
||||
lastRetryInterval: initRetryTime,
|
||||
handles: {
|
||||
[`${handleId}`]: handle,
|
||||
},
|
||||
});
|
||||
//未注册过 则去订阅
|
||||
this.doEmit(topic, req, listenerId);
|
||||
}
|
||||
return this.unSubscribe.bind(this, topic, req, handleId, listenerId);
|
||||
}
|
||||
|
||||
unSubscribe(topic, req, handleId, listenerId) {
|
||||
const listener = this.listeners.find(
|
||||
(v) => v['topic'] === topic && v['req'] === req && v['id'] === listenerId
|
||||
);
|
||||
const { handles = {}, suInfo } = listener || {};
|
||||
if (handles[handleId]) {
|
||||
delete handles[handleId];
|
||||
//如果没有其他订阅就删除
|
||||
if (Object.keys(handles).length === 0) {
|
||||
if (this.intervalId) {
|
||||
clearTimeout(this.intervalId);
|
||||
}
|
||||
if (listener['hasEmit'] === EMITSTATE['CONNECT']) {
|
||||
this.ioIns.emit('UnSubscribe', JSON.stringify(suInfo), (data) => {
|
||||
this.unSubscribeListenerId.push(listenerId);
|
||||
console.debug('UNSUBSCRIBE', listener['id'], topic, req, data);
|
||||
});
|
||||
}
|
||||
this.listeners = this.listeners.filter((v) => !(v['topic'] === topic && v['req'] === req));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//单例
|
||||
const channelIns = new Channel();
|
||||
//暴露实例 调试用
|
||||
window.__channel__ = channelIns;
|
||||
|
||||
export default channelIns;
|
@ -1,5 +1,13 @@
|
||||
# @zhst/utils
|
||||
|
||||
## 0.7.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增 tree 组件的监听事件,优化 meta 全选的回调事件监听
|
||||
- Updated dependencies
|
||||
- @zhst/request@0.8.3
|
||||
|
||||
## 0.7.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zhst/func",
|
||||
"version": "0.7.3",
|
||||
"version": "0.7.4",
|
||||
"description": "函数合集",
|
||||
"keywords": [
|
||||
"hooks"
|
||||
|
@ -240,128 +240,3 @@ export const getRotateImg = (image: HTMLImageElement, rotate: number) => {
|
||||
commonCanvas.parentNode?.removeChild(commonCanvas);
|
||||
return file;
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化工具
|
||||
* @param originData
|
||||
* @returns
|
||||
*/
|
||||
export const getOdRect = (originData: IOdRectOrigin) => {
|
||||
let data = get(originData, 'objects', [])
|
||||
.filter((v: any) => !isNull(get(v, 'infoOnSource.bboxInFrame.bboxRatio')))
|
||||
.map((v: any, index: any) => {
|
||||
// objectId==0 特征没有提取到过滤1掉
|
||||
const rect = get(v, 'infoOnSource.bboxInFrame.bboxRatio');
|
||||
const extendBox = get(v, 'infoOnSource.bboxInFrame.extendBoxRatio');
|
||||
const frameTimestamp = get(v, 'timestamp'); //时间戳创建档案的时候需要
|
||||
const qualityScore = get(v, 'qualityScore');
|
||||
const algorithmVersion =
|
||||
get(v, 'objectType') === 'OBJECT_TYPE_PEDESTRAIN'
|
||||
? 'VERSION_REID_HEAD_ATTR'
|
||||
: get(v, 'objectType') === 'OBJECT_TYPE_FACE'
|
||||
? 'VERSION_FACE'
|
||||
: 'VERSION_REID_HEAD_ATTR';
|
||||
const featureData = get(v, 'feature', []).filter(
|
||||
(v: any) => v.type === 'FEATURE_TYPE_BYTE'
|
||||
);
|
||||
const objectRectIndex = algorithmVersion === 'VERSION_FACE' ? 0 : 1;
|
||||
const objectType = get(v, 'objectType');
|
||||
const objectId = get(v, 'objectIndex.objectId');
|
||||
const sourceObjectId = get(v, 'sourceObjectId');
|
||||
return {
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
w: rect.w,
|
||||
h: rect.h,
|
||||
// faceCorrectImage: faceCorrectImage,
|
||||
id: index,
|
||||
qualityScore: qualityScore,
|
||||
algorithmVersion: algorithmVersion,
|
||||
featureData: get(featureData, '0.featureByte'),
|
||||
objectRectIndex: objectRectIndex,
|
||||
objectType: objectType,
|
||||
objectId: objectId,
|
||||
frameTimestamp: frameTimestamp,
|
||||
sourceObjectId: sourceObjectId,
|
||||
extendBox: extendBox,
|
||||
};
|
||||
});
|
||||
if (data.length > 0) {
|
||||
data = data.filter((v: { objectId: string; }) => v.objectId !== '0');
|
||||
} else {
|
||||
throw new Error('empty');
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
//档案库od
|
||||
export const getOdRectV2 = (originData: { odv2Result: any[]; }) => {
|
||||
const resp = originData.odv2Result[0];
|
||||
const subObjects: { x: any; y: any; w: any; h: any; id: any; qualityScore: any; algorithmVersion: any; featrueData: any; objectRectIndex: number; objectType: any; objectId: any; }[] = []; //形体
|
||||
const data = get(resp, 'objects', [])
|
||||
.filter((v: any) => !isNull(get(v, 'subObjects[0].infoOnSource.bboxInFrame.bboxRatio')))
|
||||
.map((v: any, index: any) => {
|
||||
const rect = get(v, 'infoOnSource.bboxInFrame.bboxRatio');
|
||||
const qualityScore = get(v, 'qualityScore');
|
||||
const algorithmVersion = get(v, 'objectType');
|
||||
const featrueData = get(v, 'feature', []).filter(
|
||||
(v: { name: string; }) => v.name === 'feature-body' || v.name === 'feature-face'
|
||||
);
|
||||
const objectRectIndex = algorithmVersion === 'OBJECT_TYPE_FACE' ? 0 : 1;
|
||||
const objectType = get(v, 'objectType');
|
||||
const objectId = get(v, 'objectIndex.objectId');
|
||||
//如果存在subObjects的数组不为null表示形体里面带人脸,人脸的od框也要显示出来
|
||||
if (get(v, 'subObjects', []).length) {
|
||||
get(v, 'subObjects', []).forEach((e: any) => {
|
||||
const rect = get(e, 'infoOnSource.bboxInFrame.bboxRatio');
|
||||
const qualityScore = get(e, 'qualityScore');
|
||||
const algorithmVersion = get(e, 'objectType');
|
||||
const featrueData = get(e, 'feature', []).filter(
|
||||
(v: { name: string; }) => v.name === 'feature-body' || v.name === 'feature-face'
|
||||
);
|
||||
const objectRectIndex = algorithmVersion === 'OBJECT_TYPE_FACE' ? 0 : 1;
|
||||
const objectType = get(e, 'objectType');
|
||||
const objectId = get(e, 'objectIndex.objectId');
|
||||
subObjects.push({
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
w: rect.w,
|
||||
h: rect.h,
|
||||
id: index,
|
||||
qualityScore: qualityScore,
|
||||
algorithmVersion: algorithmVersion,
|
||||
featrueData: featrueData.length ? featrueData[0].featureByte : '',
|
||||
objectRectIndex: objectRectIndex,
|
||||
objectType: objectType,
|
||||
objectId,
|
||||
});
|
||||
});
|
||||
}
|
||||
return {
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
w: rect.w,
|
||||
h: rect.h,
|
||||
id: index,
|
||||
qualityScore: qualityScore,
|
||||
algorithmVersion: algorithmVersion,
|
||||
featrueData: featrueData[0].featureByte,
|
||||
objectRectIndex: objectRectIndex,
|
||||
objectType: objectType,
|
||||
objectId: objectId,
|
||||
};
|
||||
});
|
||||
const brr = data.concat(subObjects).map((v: { id: any; }, vs: any) => {
|
||||
if (String(v.id)) {
|
||||
v.id = vs;
|
||||
}
|
||||
return v;
|
||||
});
|
||||
if (brr.length > 0) {
|
||||
console.log(brr, 'data111');
|
||||
} else {
|
||||
throw new Error('empty');
|
||||
}
|
||||
console.log(brr);
|
||||
return brr;
|
||||
};
|
||||
|
@ -1,5 +1,13 @@
|
||||
# @zhst/hooks
|
||||
|
||||
## 0.8.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增 tree 组件的监听事件,优化 meta 全选的回调事件监听
|
||||
- Updated dependencies
|
||||
- @zhst/func@0.7.4
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zhst/hooks",
|
||||
"version": "0.8.2",
|
||||
"version": "0.8.3",
|
||||
"description": "hooks合集",
|
||||
"keywords": [
|
||||
"hooks"
|
||||
|
@ -1,5 +1,15 @@
|
||||
# @zhst/utils
|
||||
|
||||
## 0.8.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增 tree 组件的监听事件,优化 meta 全选的回调事件监听
|
||||
- Updated dependencies
|
||||
- @zhst/hooks@0.8.3
|
||||
- @zhst/func@0.7.4
|
||||
- @zhst/meta@0.8.4
|
||||
|
||||
## 0.8.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zhst/meta",
|
||||
"version": "0.8.3",
|
||||
"version": "0.8.4",
|
||||
"description": "原子组件",
|
||||
"keywords": [
|
||||
"meta",
|
||||
|
@ -7,7 +7,6 @@ import {
|
||||
isNull,
|
||||
generateImg,
|
||||
dataURLToBlob,
|
||||
getOdRect,
|
||||
getExtendRect,
|
||||
getTransformRect,
|
||||
getRotateImg,
|
||||
@ -17,7 +16,7 @@ import {
|
||||
} from '@zhst/func';
|
||||
import Align from 'rc-align';
|
||||
import { Button, Empty } from '..';
|
||||
import { type Rect, type IScreenshotButtonProp, type AlignType, type IOdRectOrigin } from '@zhst/types'
|
||||
import { type Rect, type IScreenshotButtonProp, type AlignType } from '@zhst/types'
|
||||
import Icon from '../iconfont';
|
||||
import {
|
||||
Cropper,
|
||||
@ -30,10 +29,10 @@ import {
|
||||
import BtnGroup from './components/BtnGroup';
|
||||
import './index.less'
|
||||
import { defaultAlignOption, CROP_TYPE } from '../utils/constants'
|
||||
import { getOdRect, IOdObject } from './bigImagePreviewHelper'
|
||||
|
||||
const componentName = `zhst-image__img-view`;
|
||||
|
||||
|
||||
export interface ViewOption {
|
||||
/* 图片url */
|
||||
image?: string | HTMLImageElement;
|
||||
@ -67,7 +66,7 @@ export interface ImgViewProps extends React.HTMLAttributes<HTMLElement> {
|
||||
attachImg?: Array<{ label: string; url: string }>; // 缩略图列表
|
||||
odRect?: Rect
|
||||
score?: number
|
||||
objects?: IOdRectOrigin[] // 图片人物框选
|
||||
objects?: IOdObject
|
||||
}
|
||||
showAttachImgLabel?: boolean; // 是否显示缩略图
|
||||
showOpt?: boolean; // 是否显示操作面板
|
||||
@ -77,6 +76,7 @@ export interface ImgViewProps extends React.HTMLAttributes<HTMLElement> {
|
||||
screenshotButtonAlign?: AlignType;
|
||||
screenshotButtonRender?: (screenshotButtonProp: IScreenshotButtonProp) => ReactElement;
|
||||
hideLeftTopBtn?: boolean;
|
||||
onRectSelect?: (obj: IOdObject) => void
|
||||
showScore?: boolean // 是否显示相似度
|
||||
viewOption?: ViewOption;
|
||||
}
|
||||
@ -127,12 +127,12 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
showScore = true,
|
||||
showScore = false,
|
||||
data,
|
||||
showOpt = false,
|
||||
showAttachImgLabel = true,
|
||||
screenshotButtonAlign = defaultAlignOption,
|
||||
screenshotButtonRender = () => <div style={{ color: '#fff' }}>回调DOM</div>,
|
||||
screenshotButtonRender = () => <div style={{ color: '#fff', width: '80px', top: 0 }}>回调DOM</div>,
|
||||
hideLeftTopBtn = true,
|
||||
viewOption = {}
|
||||
} = props;
|
||||
@ -144,18 +144,13 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
objects = [],
|
||||
} = data
|
||||
const imgContainerRef = React.useRef(null);
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
|
||||
const init = useCallback(($container: null) => {
|
||||
imgContainerRef.current = $container;
|
||||
setIsReady(true);
|
||||
}, []);
|
||||
// ============================= viewer =========================
|
||||
const imgInsRef = useRef<any>(null);
|
||||
const [isImgReady, setIsImgReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isReady || !imgContainerRef?.current) return;
|
||||
if (!imgContainerRef?.current) return;
|
||||
const handleReady = addEventListenerWrapper(imgContainerRef.current, EVENT_VIEWER_READY, () => {
|
||||
setIsImgReady(true);
|
||||
});
|
||||
@ -176,7 +171,7 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
imgInsRef?.current?.destroy?.();
|
||||
imgInsRef.current = null;
|
||||
};
|
||||
}, [isReady, imageKey]);
|
||||
}, [imageKey]);
|
||||
|
||||
// ============================= viewer操作按钮 =========================
|
||||
const handleOptClick = (v: string) => {
|
||||
@ -227,7 +222,8 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
};
|
||||
}, [isImgReady, showCrop, cropType, imageKey]);
|
||||
|
||||
const initData = (_objects: IOdRectOrigin[]) => {
|
||||
// 初始化页面的绘制矩形
|
||||
const initData = (_objects: IOdObject | never[]) => {
|
||||
const imgIns = imgInsRef.current;
|
||||
const _odRect = odRect
|
||||
//清理crop
|
||||
@ -301,12 +297,15 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
handlerCropEndRef.current = addEventListenerWrapper(imgContainerRef.current, EVENT_CROP_END, (event: { detail: any; }) => {
|
||||
const data = event.detail;
|
||||
setSelectAlgorithmVersion(null);
|
||||
setCropRect({
|
||||
const _rect = {
|
||||
x: data.left,
|
||||
y: data.top,
|
||||
w: data.width,
|
||||
h: data.height,
|
||||
});
|
||||
}
|
||||
setCropRect(_rect);
|
||||
const p = getCropInfo({ type: cropType, rect: _rect })
|
||||
console.log('p', p)
|
||||
alignRef?.current?.forceAlign?.();
|
||||
});
|
||||
cropInsRef.current = new Cropper(imgContainerRef.current, {
|
||||
@ -317,11 +316,10 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
}
|
||||
|
||||
// 获取框选的截图框信息
|
||||
const latestCropType = useLatest(cropType);
|
||||
const latestCropRect = useLatest(cropRect);
|
||||
const getCropInfo = async (cb: (data: any) => void) => {
|
||||
const cropType = latestCropType.current;
|
||||
const cropRect = latestCropRect.current;
|
||||
const getCropInfo = async (opt: { type: string; rect: Rect }) => {
|
||||
const { type, rect } = opt
|
||||
const cropType = type;
|
||||
const cropRect = rect;
|
||||
const imgIns = imgInsRef.current;
|
||||
const transform = imgIns.targetTransform;
|
||||
let newImgKey = imageKey;
|
||||
@ -398,8 +396,15 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
rectList[index] = newRect;
|
||||
})
|
||||
);
|
||||
cb?.({ rectList, extendRectList, selectIndex, imgKey: newImgKey })
|
||||
return { rectList, extendRectList, selectIndex, imgKey: newImgKey };
|
||||
|
||||
let data = {
|
||||
rectList,
|
||||
extendRectList,
|
||||
selectIndex,
|
||||
imgKey: newImgKey
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
// 操作界面判断
|
||||
@ -421,22 +426,12 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
const [selectAttachImgIndex, setSelectAttachImgIndex] = useState(0);
|
||||
const [isZoomin, setIsZoomin] = useState(false);
|
||||
|
||||
/**
|
||||
* 修改当前图片预览下标
|
||||
* @param diff 跳转强度 正向后翻、负值向前翻
|
||||
*/
|
||||
const handleChangeIndex = (cb?: () => void) => {
|
||||
if (!imageKey) return
|
||||
cb?.()
|
||||
}
|
||||
|
||||
// ============================== Ref ===============================
|
||||
useImperativeHandle(ref, () => ({
|
||||
imgInsRef,
|
||||
setShowCrop,
|
||||
initData,
|
||||
getCropInfo,
|
||||
handleChangeIndex
|
||||
}));
|
||||
|
||||
return (
|
||||
@ -449,7 +444,7 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
`${componentName}-main`,
|
||||
cropType === CROP_TYPE['AUTO'] && `${componentName}-main--cursor`
|
||||
)}
|
||||
ref={init}
|
||||
ref={imgContainerRef}
|
||||
/>
|
||||
{/* 图片操作 */}
|
||||
{!hideLeftTopBtn && (
|
||||
@ -562,7 +557,7 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{showScore && <div
|
||||
{(showScore || score) && <div
|
||||
style={{ bottom: 20 }}
|
||||
className={classNames(`${componentName}__face-score`)}
|
||||
>
|
||||
|
@ -0,0 +1,58 @@
|
||||
import { get, isNull } from "@zhst/func";
|
||||
import { ObjectType, Rect } from "@zhst/types";
|
||||
|
||||
export interface IOdObject {
|
||||
objects: {
|
||||
bboxRatio: Rect
|
||||
timestamp?: string
|
||||
qualityScore?: string
|
||||
extendBoxRatio?: any
|
||||
objectType?: ObjectType
|
||||
objectIndex?: {
|
||||
objectId: string
|
||||
}
|
||||
sourceObjectId?: string
|
||||
}[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化工具
|
||||
* @param originData
|
||||
* @returns
|
||||
*/
|
||||
export const getOdRect = (originData: IOdObject) => {
|
||||
let data = get(originData, 'objects', [])
|
||||
.filter((v: any) => !isNull(get(v, 'bboxRatio')) || get(v, 'objectIndex.objectId') !== '0' )
|
||||
.map((v: any, index: any) => {
|
||||
const rect = get(v, 'bboxRatio');
|
||||
const extendBox = get(v, 'extendBoxRatio');
|
||||
const frameTimestamp = get(v, 'timestamp'); //时间戳创建档案的时候需要
|
||||
const qualityScore = get(v, 'qualityScore');
|
||||
const algorithmVersion =
|
||||
get(v, 'objectType') === 'OBJECT_TYPE_PEDESTRAIN'
|
||||
? 'VERSION_REID_HEAD_ATTR'
|
||||
: get(v, 'objectType') === 'OBJECT_TYPE_FACE'
|
||||
? 'VERSION_FACE'
|
||||
: 'VERSION_REID_HEAD_ATTR';
|
||||
const objectRectIndex = algorithmVersion === 'VERSION_FACE' ? 0 : 1;
|
||||
const objectType = get(v, 'objectType');
|
||||
const objectId = get(v, 'objectIndex.objectId');
|
||||
const sourceObjectId = get(v, 'sourceObjectId');
|
||||
return {
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
w: rect.w,
|
||||
h: rect.h,
|
||||
id: index,
|
||||
qualityScore,
|
||||
algorithmVersion,
|
||||
objectRectIndex,
|
||||
objectType,
|
||||
objectId,
|
||||
frameTimestamp,
|
||||
sourceObjectId,
|
||||
extendBox,
|
||||
};
|
||||
});
|
||||
return data;
|
||||
};
|
@ -25,28 +25,20 @@ const props = {
|
||||
time: '2022-01-01', // 摄像头拍摄时间
|
||||
objects: [
|
||||
{
|
||||
"infoOnSource": {
|
||||
"bboxInFrame": {
|
||||
"bboxRatio": {
|
||||
"x": 0.5519352,
|
||||
"y": 0.2965385,
|
||||
"w": 0.05185461,
|
||||
"h": 0.24698898
|
||||
},
|
||||
},
|
||||
},
|
||||
"bboxRatio": {
|
||||
"x": 0.5519352,
|
||||
"y": 0.2965385,
|
||||
"w": 0.05185461,
|
||||
"h": 0.24698898
|
||||
},
|
||||
},
|
||||
{
|
||||
"infoOnSource": {
|
||||
"bboxInFrame": {
|
||||
"bboxRatio": {
|
||||
"x": 0.58543766,
|
||||
"y": 0.3203356,
|
||||
"w": 0.052037954,
|
||||
"h": 0.2664015
|
||||
},
|
||||
},
|
||||
},
|
||||
"bboxRatio": {
|
||||
"x": 0.58543766,
|
||||
"y": 0.3203356,
|
||||
"w": 0.052037954,
|
||||
"h": 0.2664015
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
43
packages/meta/src/BigImagePreview/demo/noAttach.tsx
Normal file
43
packages/meta/src/BigImagePreview/demo/noAttach.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
import React, { useRef } from 'react';
|
||||
import { Button, Space } from '@zhst/meta'
|
||||
import { BigImagePreview } from '@zhst/meta'
|
||||
|
||||
|
||||
const props = {
|
||||
heigth: '500px',
|
||||
data: {
|
||||
imageKey: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
odRect:{
|
||||
"x":0.553125,"y":0.29722223,"w":0.048958335,"h":0.2462963
|
||||
},
|
||||
cameraPosition: 'string', // 摄像头位置
|
||||
time: '2022-01-01', // 摄像头拍摄时间
|
||||
objects: [
|
||||
{
|
||||
"bboxRatio": {
|
||||
"x": 0.5519352,
|
||||
"y": 0.2965385,
|
||||
"w": 0.05185461,
|
||||
"h": 0.24698898
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
onRectSelect: data => console.log('data', data)
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const imgRef = useRef(null)
|
||||
|
||||
return (
|
||||
<Space size={[8, 16]} direction="vertical">
|
||||
<BigImagePreview {...props} ref={imgRef} />
|
||||
<Space>
|
||||
<Button type="primary" onClick={() => imgRef.current?.setShowCrop(true)}>编辑</Button>
|
||||
<Button onClick={() => imgRef.current?.handleChangeIndex(1)}>下一张</Button>
|
||||
<Button onClick={() => imgRef.current?.setShowCrop(false)}>取消</Button>
|
||||
</Space>
|
||||
</Space>
|
||||
)
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
position: relative;
|
||||
width: calc(100%);
|
||||
height: 100%;
|
||||
font-size: 0;
|
||||
|
||||
&__face-score {
|
||||
position: absolute;
|
||||
@ -62,14 +63,9 @@
|
||||
height: 202px;
|
||||
transition: all 200ms;
|
||||
|
||||
&--fixed {
|
||||
}
|
||||
|
||||
&--zoomin {
|
||||
height: 100%;
|
||||
|
||||
&--fixed {
|
||||
}
|
||||
}
|
||||
|
||||
&__tab {
|
||||
|
@ -8,6 +8,7 @@ title: BigImagePreview 大图预览组件
|
||||
# BigImagePreview 大图预览组件
|
||||
|
||||
<code src="./demo/base.tsx">基本</code>
|
||||
<code src="./demo/noAttach.tsx">不展示小图</code>
|
||||
|
||||
## API
|
||||
|
||||
|
@ -63,7 +63,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
||||
adjustY: true,
|
||||
},
|
||||
},
|
||||
screenshotButtonRender = () => <div style={{ color: '#fff' }}>回调DOM</div>,
|
||||
screenshotButtonRender = () => <div style={{ color: '#fff', width: '80px', top: 0 }}>回调DOM</div>,
|
||||
onCropChange,
|
||||
defautlNormalizationRect: defaultNormalizationRect,
|
||||
} = props;
|
||||
|
@ -1,5 +1,11 @@
|
||||
# @zhst/request
|
||||
|
||||
## 0.8.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 新增 tree 组件的监听事件,优化 meta 全选的回调事件监听
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zhst/request",
|
||||
"version": "0.8.2",
|
||||
"version": "0.8.3",
|
||||
"description": "请求库",
|
||||
"keywords": [
|
||||
"request",
|
||||
|
Loading…
Reference in New Issue
Block a user