Compare commits

..

3 Commits

Author SHA1 Message Date
编码猿
78336de068 22 2025-12-08 16:18:25 +08:00
编码猿
96ebc31637 去除pydio 2025-12-08 13:55:37 +08:00
编码猿
d1e37320d3 实现 this 指向 2025-12-08 13:54:20 +08:00
41 changed files with 303 additions and 120 deletions

1
.pydio
View File

@@ -1 +0,0 @@
599f9574-b305-4f7f-9987-46a7d0b47c5c

View File

@@ -1 +0,0 @@
a06d094b-d1c2-4adc-8c5c-0a9986f5aea8

View File

@@ -1 +0,0 @@
97f1b24f-9aff-44d4-b3af-c8a5ea6943c7

View File

@@ -1 +0,0 @@
1331c103-912a-4f75-9045-03aaa69824f8

View File

@@ -1 +0,0 @@
8bb6e31a-650f-4f25-9e76-72e5118f6438

View File

@@ -1 +0,0 @@
7fcbe2a8-4ef1-42fd-8123-b5ed331cbd41

View File

@@ -1 +0,0 @@
da7a2feb-9485-4fcf-855a-b6dbcedaad05

View File

@@ -1 +0,0 @@
282d544a-c6a9-4e6d-ab20-93a15ca73330

View File

@@ -1 +0,0 @@
609d9c08-74bf-4b6b-b612-c63a5bf29b24

View File

@@ -1 +0,0 @@
37bbcaf2-9403-4c45-a641-e6a09bbec803

View File

@@ -1 +0,0 @@
55e88823-96b5-4e92-a121-1743226e7284

View File

@@ -1 +0,0 @@
e9a6fea5-8124-47ee-8764-2a2b38559e29

View File

@@ -1 +0,0 @@
08d2ddbb-779b-48d9-a2f0-eff54b1a49ba

View File

@@ -1 +0,0 @@
984cb101-d8c8-46fc-bdf2-404c29895807

View File

@@ -1 +0,0 @@
29ff899f-7099-4b35-97d9-7eb12e8b1b67

View File

@@ -1 +0,0 @@
e36141e2-2743-4aa7-89cf-e34088c48df2

View File

@@ -1 +0,0 @@
88b35c97-9424-4ba5-a009-00ba813fb0fa

View File

@@ -1 +0,0 @@
50ce6829-d7b9-49e3-91b2-ead60352a710

View File

@@ -1 +0,0 @@
e99cbd4e-9620-464d-ad1f-a319540d4885

View File

@@ -2,16 +2,32 @@
* Copyright (c) 2020. bmy
*/
import { VueCustomize } from "@logic/base.type";
import VueRouter, { Route } from 'vue-router'
export interface Methods {
StartUp?(): void;
$route: Route;
$router: VueRouter;
// 可添加其他需要的Vue属性如$el/$data/$refs等
$el?: HTMLElement;
$data?: Record<string, any>;
$refs?: Record<string, any>;
}
/**
* logic 层的父类
* 主要实现 页面公共参数和ajax方法的地方
*/
export class BaseLogic {
export class BaseLogic<T> implements Methods {
// 泛型参数T表示Vue实例的类型
protected _?: T; // 保留this._以便向后兼容
$route!: Route;
$router!: VueRouter;
$el?: HTMLElement | undefined;
$data?: Record<string, any> | undefined;
// 保存Vue对象
public _!: any;
public page: number = 1;
public total_page: number = 1;
@@ -26,14 +42,19 @@ export class BaseLogic {
// 请求参数
public PageParams: { limit: number, page: number } = {
limit : 10, page : 1
limit: 10, page: 1
}
/**
* 【页面中公共的多次被用到的接口】可以在这个父类中定义,
* 子类logic中直接使用避免方法的冗余
* @constructor
*/
public async DepartmentListRequest(): Promise<void> {
constructor() {
}
// 组件初始化完成后调用
StartUp?(): void;
// 合并Vue实例到Logic实例
mergeVueInstance(vueInstance: T) {
// 保存Vue实例的引用以便在Logic实例中可以访问到Vue实例
this._ = vueInstance;
}
}

View File

@@ -1 +0,0 @@
d3709c65-896f-4fce-83c8-72248f572930

View File

@@ -6,13 +6,13 @@ import { Autowired } from "@ann/ioc.annotation";
import { BaseLogic } from "@logic/base.logic";
import { Methods, VueCustomize } from "@logic/base.type";
export class AboutLogic <T extends VueCustomize> extends BaseLogic implements Methods {
export class AboutLogic<T extends VueCustomize> extends BaseLogic<T> implements Methods {
constructor(_: T) {
super();
this._ = _
(this as any)._ = _; // 使用类型断言来解决TypeScript的类型检查问题
}
public async StartUp (): Promise<void> {
public async StartUp(): Promise<void> {
}
}

View File

@@ -8,39 +8,40 @@ import { UserService, ResponseType } from "@service/user.service";
import { BaseLogic } from "@logic/base.logic";
import { Methods, VueCustomize } from "@logic/base.type";
export class HomeLogic<T extends VueCustomize> extends BaseLogic implements Methods {
export class HomeLogic<T extends VueCustomize> extends BaseLogic<T> implements Methods {
@Autowired()
public readonly UserService!: UserService;
public title: string = "12222";
public List: ResponseType[] = [];
public List: ResponseType[] = [
{ user_id: 1, user_name: '测试1' },
{ user_id: 2, user_name: '测试2' },
];
// constructor() {
// super();
// }
constructor(_: T) {
constructor() {
super();
console.log("constructor params: ", _);
this._ = _
}
/**
* 在这里面调用需要打开页面就执行的ajax请求
* @constructor
* 页面初始化调用的方法
*/
public async StartUp (): Promise<void> {
public async StartUp(): Promise<void> {
// 在StartUp方法中访问$route和$router
console.log("StartUp - this: ", this);
console.log("StartUp - this.$route: ", this.$route);
console.log("StartUp - this.$router: ", this.$router);
await this.getData();
}
/**
* 请求首页数据
*/
public async getData (): Promise<void> {
this.List = await this.UserService.UserList({ type: 1, page: 1 });
console.log("this.List: ", this.List);
public async getData(): Promise<void> {
// this.List = await this.UserService.UserList({ type: 1, page: 1 });
// console.log("this.List: ", this.List);
// let res = await this.UserService.login({ type: 2, page: 2 });
// console.log("this.res: ", res);

View File

@@ -1 +0,0 @@
9b3b1288-db3f-4438-9341-a54217a9d678

View File

@@ -9,9 +9,9 @@ import { VueCustomize, RouterMeta } from "@logic/base.type";
import { Autowired } from "@ann/ioc.annotation";
@Component
export default class About extends VueCustomize {
export default class About extends VueCustomize {
@Autowired(About)
@Autowired()
private logic!: AboutLogic<About>
private RouterMeta: RouterMeta = {
@@ -20,16 +20,16 @@ export default class About extends VueCustomize {
isLogin: true
};
public async created () {
public async created() {
await this.logic.StartUp();
};
// 路由拦截器
beforeRouteEnter (to: Route, from: Route, next: (to?: RawLocation | false | ((vm: Vue) => void)) => void) {
beforeRouteEnter(to: Route, from: Route, next: (to?: RawLocation | false | ((vm: Vue) => void)) => void) {
next();
}
protected render () {
protected render() {
return (
<div class="About">
About

View File

@@ -18,13 +18,21 @@ import { VueCustomize, RouterMeta } from "@logic/base.type";
@Component
export default class Home extends VueCustomize {
// 可选手动声明data双重保障也可仅靠装饰器自动声明
public data() {
return {
logic: {}, // 确保Vue2初始化时劫持该属性
Utils: {}
};
}
public RouterMeta: RouterMeta = {
title: '首页',
showNav: true,
isLogin: true
}
@Autowired(Home)
@Autowired()
private logic!: HomeLogic<Home>
@Autowired()
@@ -49,6 +57,7 @@ export default class Home extends VueCustomize {
}
public back() {
this.logic.title = "44444";
console.log("qqqq");
}
@@ -61,6 +70,15 @@ export default class Home extends VueCustomize {
<HelloWorld msg="向HelloWorld props传参" />
<input type="text" v-model={this.logic.title} />
<h2>{this.logic.title}</h2>
{/* 显示$route和$router信息 */}
<div class="route-info">
<h3>:</h3>
<p>: {this.$route?.path}</p>
<p>: {this.$route?.name}</p>
<p>Logic实例路由路径: {(this.logic as any).$route?.path}</p>
</div>
{this.ClickButton()}
<ul>
{

View File

@@ -1 +0,0 @@
d7cca889-05d9-4311-b88d-a72968fc4581

View File

@@ -1 +0,0 @@
c2c6ec3b-b4b9-42f4-92b0-4e10d1e027a6

View File

@@ -1 +0,0 @@
cbff3cfc-8ebf-4480-a698-e4a7c6040408

View File

@@ -1,14 +1,184 @@
/*
* Copyright (c) 2020. bmy
*/
import Vue from 'vue';
export function Autowired(params?: any) {
return (target: any, propertyKey: string) => {
let typeClass = Reflect.getMetadata('design:type', target, propertyKey);
Object.defineProperty(target, propertyKey, {
value: params ? new typeClass(new params) : new typeClass(),
writable: true,
configurable: true
});
}
// 1. 定义最宽松的基础类型兼容所有场景避开symbol索引签名限制
type AutowiredTarget = {
[key: string]: any;
};
// 2. Vue组件实例专属类型仅声明string/number索引运行时兼容symbol
interface VueComponentInstance extends AutowiredTarget {
created?: (...args: any[]) => Promise<void> | void;
$router?: any;
$route?: any;
$el?: HTMLElement;
$data?: Record<string, any>;
}
// 3. Logic实例类型
interface LogicInstance extends AutowiredTarget {
mergeVueInstance?: <T extends VueComponentInstance>(vueInstance: T) => void;
}
// 4. 通用构造函数类型
type Constructor<T = any> = 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<LogicInstance>
): void {
// 保存原始created钩子
const originalCreated: (...args: any[]) => Promise<void> | void = target.created || (() => { });
// 重写created钩子显式指定this类型
target.created = async function (this: VueComponentInstance): Promise<void> {
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<string | symbol>(['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<string | symbol> {
const props = new Set<string | symbol>();
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
});
}

View File

@@ -1 +0,0 @@
f0ed9e16-3f2b-4d50-9858-120dc2e2ae2c

View File

@@ -21,28 +21,28 @@ export class ConfigureConfig {
ProdUrl: string,
ApiList: { [key: string]: string }
} = {
DevUrl: 'http://127.0.0.1:8080',
ProdUrl: 'http://127.0.0.1:9090/api',
ApiList: {
// start - 下面 注释内的各个对象key 将被Nodejs实时监听获取你key改动增删改将同步
// start - 自动生成接口请求中间层的文件和文件内部的代码。
// start - 注意 下面 被注释的key 将不会生成文件或代码
DevUrl: 'http://127.0.0.1:8080',
ProdUrl: 'http://127.0.0.1:9090/api',
ApiList: {
// start - 下面 注释内的各个对象key 将被Nodejs实时监听获取你key改动增删改将同步
// start - 自动生成接口请求中间层的文件和文件内部的代码。
// start - 注意 下面 被注释的key 将不会生成文件或代码
// UserList: '/UserList',
// User_IndexTest: '/test',
Car_carList: '/test',
// Car_addCar: '/test',
// UserList: '/UserList',
// User_IndexTest: '/test',
Car_carList: '/test',
Car_addCar: '/test',
Index_reg: '/reg',
Index_login: '/login',
Index_reg: '/reg',
Index_login: '/login',
Order_test: '/test',
Order_test: '/test',
// end - 上面 注释内的各个对象key 将被Nodejs实时监听获取你key改动增删改将同步
// end - 自动生成接口请求中间层的文件和文件内部的代码。
// end - 注意 上面 被注释的key 将不会生成文件或代码
}
};
// end - 上面 注释内的各个对象key 将被Nodejs实时监听获取你key改动增删改将同步
// end - 自动生成接口请求中间层的文件和文件内部的代码。
// end - 注意 上面 被注释的key 将不会生成文件或代码
}
};
/**
* Vue 插件

View File

@@ -1 +0,0 @@
852dea68-05ee-4958-8884-27c503363732

View File

@@ -1 +0,0 @@
45df40b6-06b8-4b49-9ece-3df4b113d74f

View File

@@ -14,4 +14,8 @@ export class CarService {
@Mapper(ResponseType)
public async carList (params: object): Promise<ResponseType[]> {}
@GET()
@Mapper(ResponseType)
public async addCar (params: object): Promise<ResponseType[]> {}
}

View File

@@ -1 +0,0 @@
6dd651dd-0493-4995-a44b-c15ccfdf75a4

View File

@@ -1 +0,0 @@
d3359e2f-bc25-4e14-b202-20080d06b04a

View File

@@ -1 +0,0 @@
e5b979e5-1ac3-429c-bf03-7d570eba9033

View File

@@ -1 +0,0 @@
23f23313-fd2c-4dfc-aeaa-6758f2f76ec2

View File

@@ -56,25 +56,25 @@ module.exports = {
errors: true
},
// before 这块代码都可以删除,仅仅为脚手架提供一个用于测试的接口
before: function (app, server) {
app.all('*', function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', '*');
res.header('Access-Control-Allow-Methods', '*');
res.header('Content-Type', 'application/json;charset=utf-8');
next();
});
app.get('/UserList', function (req, res) {
res.json({
status: 200,
message: '请求成功',
result: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' }
]
});
});
},
// before: function (app, server) {
// app.all('*', function (req, res, next) {
// res.header('Access-Control-Allow-Origin', '*');
// res.header('Access-Control-Allow-Headers', '*');
// res.header('Access-Control-Allow-Methods', '*');
// res.header('Content-Type', 'application/json;charset=utf-8');
// next();
// });
// app.get('/UserList', function (req, res) {
// res.json({
// status: 200,
// message: '请求成功',
// result: [
// { id: 1, name: '张三' },
// { id: 2, name: '李四' }
// ]
// });
// });
// },
// proxy: {
// '/api': {
// target: 'http://115.159.153.142:9010/h5',
@@ -111,7 +111,7 @@ module.exports = {
plugins: [
new ProgressPlugin({
handler: (percentage, message, ...args) => {
console.log(`${chalk.yellow("进度: ")}${chalk.green.bold(~~(percentage * 100) + "%")} ${args[0] ? chalk.black(args[0]) : " " } ${chalk.blue.bold(message)}`)
console.log(`${chalk.yellow("进度: ")}${chalk.green.bold(~~(percentage * 100) + "%")} ${args[0] ? chalk.black(args[0]) : " "} ${chalk.blue.bold(message)}`)
},
})
]