import Vue from 'vue'; // 1. 定义最宽松的基础类型(兼容所有场景,避开symbol索引签名限制) type AutowiredTarget = { [key: string]: any; }; // 2. Vue组件实例专属类型(仅声明string/number索引,运行时兼容symbol) interface VueComponentInstance extends AutowiredTarget { created?: (...args: any[]) => Promise | void; $router?: any; $route?: any; $el?: HTMLElement; $data?: Record; } // 3. Logic实例类型 interface LogicInstance extends AutowiredTarget { mergeVueInstance?: (vueInstance: T) => void; } // 4. 通用构造函数类型 type Constructor = new (...args: any[]) => T; /** * 自动注入实例装饰器 * 适配所有场景: * - Vue组件的logic属性:自动创建Logic实例并合并Vue所有属性 * - Logic类/普通类的属性:直接创建实例并挂载 */ export function Autowired(params?: any) { return function (target: AutowiredTarget, propertyKey: string | symbol): void { // 获取属性对应的类构造函数 const typeClass = Reflect.getMetadata('design:type', target, propertyKey) as Constructor; // 仅对Vue组件的logic属性做特殊处理(运行时判断) if (propertyKey === 'logic') { enhanceVueLogicProperty(target as VueComponentInstance, propertyKey, typeClass); } else { // 所有其他场景(包括Logic类的属性):直接挂载实例 mountNormalInstance(target, propertyKey, typeClass, params); } }; } /** * 挂载普通实例(适配所有非Vue组件场景) */ function mountNormalInstance( target: AutowiredTarget, propertyKey: string | symbol, typeClass: Constructor, params?: any ): void { if (!typeClass) { console.warn(`类构造函数不存在,属性${String(propertyKey)}注入失败`); return; } // 创建实例并挂载(统一用defineProperty兼容symbol) const instance = params ? new typeClass(params) : new typeClass(); Object.defineProperty(target, propertyKey, { value: instance, writable: true, configurable: true, enumerable: true }); } /** * 增强Vue组件的logic属性:创建实例并合并Vue所有属性 */ function enhanceVueLogicProperty( target: VueComponentInstance, propertyKey: string | symbol, typeClass: Constructor ): void { // 保存原始created钩子 const originalCreated: (...args: any[]) => Promise | void = target.created || (() => { }); // 重写created钩子(显式指定this类型) target.created = async function (this: VueComponentInstance): Promise { const vueInstance = this; // 防御性判断 if (!typeClass) { console.warn(`Logic类构造函数不存在,属性${String(propertyKey)}注入失败`); await originalCreated.call(this); return; } // 创建Logic实例 const logicInstance = Vue.observable(new typeClass()); // 核心修复:用Object.defineProperty兼容symbol,避开TS索引检查 Object.defineProperty(this, propertyKey, { value: logicInstance, writable: true, configurable: true, enumerable: true }); // 合并Vue属性(仅当存在mergeVueInstance方法时) if (typeof logicInstance.mergeVueInstance === 'function') { logicInstance.mergeVueInstance(vueInstance); mergeVueProperties(logicInstance, vueInstance); resetLogicConstructor(logicInstance); } // 执行原始created钩子 await originalCreated.call(this); }; } /** * 合并Vue实例的所有属性到Logic实例 */ function mergeVueProperties(logicInstance: LogicInstance, vueInstance: VueComponentInstance): void { const allProps = getAllVueProperties(vueInstance); const excludeProps = new Set(['constructor', 'prototype', '__proto__', 'mergeVueInstance']); allProps.forEach(prop => { if (excludeProps.has(prop)) return; const logicPropDesc = Object.getOwnPropertyDescriptor(logicInstance, prop); if (logicPropDesc && !logicPropDesc.configurable) return; try { const vuePropDesc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(vueInstance), prop) || Object.getOwnPropertyDescriptor(vueInstance, prop); if (vuePropDesc) { Object.defineProperty(logicInstance, prop, { ...vuePropDesc, enumerable: true, configurable: true }); } else { // 兜底:用defineProperty赋值,兼容symbol Object.defineProperty(logicInstance, prop, { value: vueInstance[prop as keyof typeof vueInstance], enumerable: true, configurable: true, writable: true }); } } catch (e) { if (typeof prop === 'string' && !['__proto__', 'constructor'].includes(prop)) { console.warn(`合并属性 ${String(prop)} 失败:`, e); } } }); } /** * 收集Vue实例的所有属性(包括原型链、Symbol) */ function getAllVueProperties(obj: any): Set { const props = new Set(); let currentObj: any = obj; while (currentObj && currentObj !== Object.prototype) { Object.getOwnPropertyNames(currentObj).forEach(prop => props.add(prop)); Object.getOwnPropertySymbols(currentObj).forEach(prop => props.add(prop)); currentObj = Object.getPrototypeOf(currentObj); } return props; } /** * 重置Logic实例的constructor指向 */ function resetLogicConstructor(logicInstance: LogicInstance): void { Object.defineProperty(logicInstance, 'constructor', { value: logicInstance.constructor, configurable: true, enumerable: false, writable: true }); }