first commit

This commit is contained in:
编码猿
2024-09-27 01:28:38 +08:00
commit a9bde91e8e
2653 changed files with 701970 additions and 0 deletions

1
王凯私活/.pydio Normal file
View File

@@ -0,0 +1 @@
ab1f76db-5a8f-4f4d-bf69-b9ce52cc4be0

View File

@@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 10

23
王凯私活/TsxVueClassApi/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
.DS_Store
node_modules
dist/
package-lock.json
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1 @@
82e9c414-c32a-4cf7-b4ee-f40c1ebff499

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,448 @@
## 前言:
前端发展真的是一个轮回,越发展越偏向**原生**`Vue3`开发阶段就参与并使用了,但是`Vue3`真的垃圾,十分的不喜欢这种垃圾的语法,钟爱`class``ts装饰器`,所以有了本项目!!
本项目作为`Vue`脚手架而存在已在很多公司项目中落地并经过不断打磨同时为了更优雅的代码开发本人写了很多周边的辅助插件装饰器shell为你提供类似`java`开发中`SpringBoot`那般优雅的爽快感!
**围绕项目开发的插件有:**
1: [vue-cli-plugin-tsx-autorouter](https://www.npmjs.com/package/vue-cli-plugin-tsx-autorouter) tsx自动路由插件
`Nuxt.js`的思想启发,针对本项目`tsx`开发,根据页面结构自动生成路由配置文件,借助`babel``ast`实现提取`tsx`
中类的属性进而实现路由`meta`
2./bin/tinit 封装shell命令行工具实现通过命令行直接创建众多代码文件
3解耦前端 页面 & JSON数据实现JSON映射存储到类属性
- 1: [json-mapper-class](https://www.npmjs.com/package/json-mapper-class) 核心插件
- 2: [json-class-interface](https://www.npmjs.com/package/json-class-interface) `TypeScript`
项目中通用的JSON数据自动生成类型工具支持生成 [json-mapper-class](https://www.npmjs.com/package/json-mapper-class)
标准代码。
- 3: [json-class-desktop](https://gitee.com/bmycode/json-class-desktop) 基于`tauri` `Svelte`
写的[json-class-interface](https://www.npmjs.com/package/json-class-interface) 桌面端工具,支持`Mac``linux``windows`
4装饰器将封装成通用TS项目插件
- 1: 让代码更加优雅简洁高效的请求中间层装饰器 @GET@POST@DELETE@PUT
```typescript
@GET()
@Mapper(ResponseType)
public async IndexTest (params: object): Promise<ResponseType[]> {
// 留空,不要写请求代码 即可发送请求,除非 useHandle: true这时 方法入参 params 为 ajax 接口数据,直接处理 params
// 即可,同时也不需要写请求代码!!
}
```
- 2: 依赖注入装饰器:@Autowired
- 3: 其他装饰器:@GlobalMethod@Mapper@RegVuePlugs@RegServiceAndMethods@Start 等等..
5AutoServiceCodeGeneration实时监听`configure.config.ts`配置文件,然后根据`ApiList`中的对象`key`
名称自动生成请求中间层的代码,降低手动复制的低效率!
介绍:
1: 文件监听已通过Nodejs流操作实现文件监听读取提取核心代码并实现同一文件中不同编辑下的新旧数据`Diff`。
2请求中间层代码自动生成**思路已有,挑战性不足,所以还未进行代码实现**
## TsxVueClassApi
基于`Vue Class Api``TypeScript``JSX`,搭建的一套项目脚手架,实现了很多常用的注解,同时基于`babel`插件通过`Ast`语法树进行路由配置文件的自动生成等。
如果你喜欢`JSX`,那么这套脚手架你应该会十分喜欢,代码语法如下:
```tsx
import "@pageLess/homeInterface.less";
import { Component } from 'vue-property-decorator';
import HelloWorld from '@components/HelloWorld';
import { HomeLogic } from "@logic/page/Home.logic";
import { Getter } from "vuex-class";
import { IndexUtils } from "@utils/index.utils";
import { Autowired } from "@ann/Ioc.annotation";
import { VueCustomize, RouterMeta } from "@logic/Base.type";
@Component
export default class Home extends VueCustomize {
// RouterMeta 是 vue-router 路由meta配置信息会被 我们的插件
// vue-cli-plugin-tsx-autorouter 进行 ast 提取注入到 自动生成的 路由配置文件中
public RouterMeta: RouterMeta = {
title: '首页',
showNav: true,
isLogin: true
}
// 抽离组件所有逻辑到独立类,解耦 页面层 和 逻辑层
// 通过 Autowired 依赖注入装饰器 实现 注入 逻辑 -> 页面
// 同时 传入 vue 的 this实现逻辑层可以调用vue方法
@Autowired(Home)
private logic!: HomeLogic<Home>
@Autowired()
public readonly Utils!: IndexUtils;
@Getter('GettersTabsContentArr')
public readonly getterFoo!: Array<any>;
public async created() {
await this.logic.StartUp();
}
public ClickButton(): JSX.Element {
return (
<a-button type="primary" onClick={ async () => {
console.log("按钮被点击22222");
} }>
Primary
</a-button>
)
}
public back() {
console.log("qqqq");
}
protected render() {
return (
<div class="homeInterface">
<img src="/img/baidu.png" alt=""/>
<h1 on-click={ this.back }>111</h1>
<HelloWorld msg="向HelloWorld props传参"/>
<input type="text" v-model={ this.logic.title }/>
<h2>{ this.logic.title }</h2>
{ this.ClickButton() }
<ul>
{
this.logic.List.map(v => {
return <li>
{ v.user_id }
{ v.user_name }
</li>
})
}
</ul>
</div>
)
}
}
```
**这个脚手架我们正在项目中使用,同时也在不断的开发和完善!!!!**
## 1安装
需要额外全局安装的插件有:
```bash
npm i -g concurrently cross-env gulp
```
然后下载项目,初始化并启动:
```bash
git clone https://gitee.com/bmycode/vue-class-api-tsx.git
npm i
npm run start
# 注意网站运行后使用电脑本机的局域网ip地址来访问例如http://192.168.1.101:8080/#/Home
```
**注意**
`Vue`官方原生底层就支持`JSX`语法,但是官方没有关于`Vue`中使用`JSX`的文档,而且很多`Vue`ui框架和第三方插件都没有相关语法但是这不影响我们在`Vue`中正常使用`JSX`。很多语法需要特殊注意和改造一下!!
## 2使用
下面说下这个脚手架的使用和注意事项。
### 2.1:项目结构
请仔细看文件后面的中文说明!!!
```txt
├── README.md
├── babel.config.js babel配置文件
├── bin 终端NewFile工具
│   ├── config
│   │   └── index.js
│   └── tinit
├── dist 打包后的文件夹
├── gulpfile.js gulp配置文件实现监听page自动生成路由文件
├── package.json 核心依赖配置文件
├── public 公共的资源文件
├── src 存放核心源码
│   ├── application 页面相关
│   │   ├── app.tsx 最外层顶级父组件
│   │   ├── assets 静态资源回合webpack打包进源码
│   │   ├── components 公共组件
│   │   ├── logic 【重要】TSX组件中的js逻辑抽象层
│   │   │   ├── base.logic.ts 【重要】所有TSX组件的js逻辑父类
│   │   │   ├── base.type.ts 组件中 通用类型的编写
│   │   │   └── page 【重要】对应页面的TSX组件逻辑抽象
│   │   └── page 【重要】存放TSX页面组件
│   └── core 核心JS层
│   ├── annotation 存放自己开发的装饰器
   │   ├── JsonToClass json-mapper-class 的源代码
│   │   ├── http.annotation.ts 请求装饰器
│   │   ├── ioc.annotation.ts IOC依赖装饰器
│   │   └── register.annotation.ts 启动装饰器
│   ├── config 站点配置文件
│   │   ├── configure.config.ts 核心配置文件
│   │   └── route.config.ts 自动生成的路由配置文件
│   ├── dao axios的封装
│   ├── model TS存取器
│   ├── run 项目的启动类
│   │   ├── init.run.ts 初始化Vue各种配置
│   ├── service 请求的service层封装
│   │   └── impl 请求service的具体类
│   ├── store Vuex的配置
│   ├── types 自定义的声明文件
│   └── utils 工具函数
├── tsconfig.json TS的配置文件
└── vue.config.js Vue-cli3 的配合文件
```
### 2.2:编码注意事项和规范,严格遵守!!!
1`page/`文件夹中的所有`tsx`组件必须继承自`VueCustomize``VueCustomize`是所有页面的父类,可以在这里定义一些公共的类型!
2`logic/`文件夹中的所有`logic.ts`必须继承`BaseLogic`并实现接口`Methods``BaseLogic`是所有页面逻辑层的公共封装,可以把使用率高的接口或者变量放在`BaseLogic`
中去定义和实现,这样页面的逻辑层子类可以实现直接使用!
3`logic/`中页面的逻辑层可以使用装饰器`@Autowired()`去注入多个`service`的依赖,实现对`ajax`中间层方法的调用,以发送`ajax`请求!具体的看下面代码
```typescript
import { Autowired } from "@/core/annotation/Ioc.annotation";
import { UserServiceImpl, ResponseType} from "@/core/service/impl/User.service.impl";
import { BaseLogic } from "@logic/Base.logic";
import { Methods, VueCustomize } from "@logic/Base.type";
export class HomeLogic<T extends VueCustomize> extends BaseLogic implements Methods {
@Autowired()
public readonly UserServiceImpl!: UserServiceImpl;
public title: string = "12222";
public List: ResponseType[] = [];
constructor(_: T) {
super();
this._ = _
}
/**
* 在这里面调用需要打开页面就执行的ajax请求
* @constructor
*/
public async StartUp (): Promise<void> {
await this.getData();
}
/**
* 请求首页数据
*/
public async getData (): Promise<void> {
this.List = await this.UserServiceImpl.IndexTest({ type: 1, page: 1 });
console.log("this.List: ", this.List);
// let res = await this.UserServiceImpl.login({ type: 2, page: 2 });
// console.log("this.res: ", res);
// this._.$setToken("")
// await this._.$router.push('/About')
}
}
```
4`logic/`中必须实现构造函数`constructor`,在构造函数中保存`tsx`页面传入指向`vue`实例的`this`,这样才能在`logic`中正确使用`vue`的一些方法,具体看代码:
```typescript
constructor(_: T) {
super();
this._ = _
}
/**
* 请求首页数据
*/
public async getData (): Promise<void> {
this.List = await this.UserServiceImpl.IndexTest({ type: 1, page: 1 });
console.log("this.List: ", this.List);
}
```
5如何将自定义的方法通过 `Vue.prototype.xxx` 挂载到`Vue`上以方便全局使用?
答:在`utils/index.utils.ts`中定义方法的时候请使用装饰器`@GlobalMethod()`装饰方法,然后如果你在`tsx`
页面组件中需要使用此方法,那么请在`base.type.ts`中定义变量并编写变量类型!
同时如果你需要在`logic`逻辑层使用此方法,那么需要在`base.logic.ts`的`VueType`接口中编写类型。具体请看代码:
```typescript
// src/core/utils/index.utils.ts
import { ConfigureConfig } from "@config/configure.config";
import { GlobalMethod } from "@ann/Register.annotation";
export class IndexUtils {
/**
* 方法上打上 @GlobalMethod() 注解这个方法会自动成为vue的全局方法
* 组件中直接this.$setToken() 即可
*/
@GlobalMethod()
public setToken (args: string): void {
localStorage.setItem("token", args)
}
}
// src/application/logic/base.logic.ts
// 定义 $setToken 方法和入参类型,返回值等!
export class VueCustomize extends Vue {
$setToken!: (token: string) => void
}
```
如果你觉得上面方式使用全局方法太过于麻烦,那么你可以在你需要使用的`logic`类或`tsx`组件中使用装饰器`@Autowired()`来注入`index.utils.ts`到类属性中,代码示例:
```typescript
import "@pageLess/homeInterface.less";
import { Component } from 'vue-property-decorator';
import HelloWorld from '@components/HelloWorld';
import { HomeLogic } from "@logic/page/Home.logic";
import { Getter } from "vuex-class";
// 1导入需要被注入的类
import { IndexUtils } from "@utils/index.utils";
// 2导入装饰器
import { Autowired } from "@ann/Ioc.annotation";
import { VueCustomize, RouterMeta } from "@logic/Base.type";
import { toClass, toInterface, configFilePath } from "json-class-interface";
@Component
export default class Home extends VueCustomize {
// 抽离组件所有逻辑到独立类,解耦页面和数据
@Autowired(Home)
private logic!: HomeLogic<Home>
// RouterMeta 是 vue-router 路由meta配置信息会被ast提取注入到自动生成的路由配置文件中
public RouterMeta: RouterMeta = {
title: '首页',
showNav: true,
isLogin: true
}
// 3将 IndexUtils 注入到属性 Utils 中
@Autowired()
public readonly Utils!: IndexUtils;
@Getter('GettersTabsContentArr')
public readonly getterFoo!: Array<any>;
public async created () {
// 4使用 setToken 方法
this.Utils.setToken("1111")
}
public ClickButton(): JSX.Element {
return (
<a-button
type = "primary"
onClick = { async()
=>
{
console.log("按钮被点击22222");
}
}>
Primary
< /a-button>
)
}
public back() {
console.log("qqqq");
}
protected render() {
return (
<div class = "homeInterface" >
<img src = "/img/baidu.png"
alt = "" / >
<h1 on - click = { this.back } > 111 < /h1>
< HelloWorld
msg = "向HelloWorld props传参" / >
<input type = "text"
v - model = { this.logic.title }
/>
< h2 > { this.logic.title } < /h2>
{
this.ClickButton()
}
<ul>
{
this.logic.List.map(v => {
return <li>
{ v.user_id }
{v.user_name}
</li>
})
}
< /ul>
< /div>
)
}
}
```
### 2.3:使用注意事项
**1** 项目中的路由使用的是`vue-router`,同时我借鉴了`Nuxt.js`的思想,自己开发了路由配置文件自动生成的插件,这个插件是`Vue-cli 3`的插件,所以不能在`Vue cli 2`的项目中使用!!
插件源码已经提交`npm`包市场!请完整阅读下面的插件文档,路由的配置文件让插件帮我们自动生成就好了!!!
[vue-cli-plugin-tsx-autorouter](https://www.npmjs.com/package/vue-cli-plugin-tsx-autorouter)
**2** 同时借鉴`PHP`开发框架`Laravel`开发终端命令行工具,通过命令帮我们创建带有模板代码能直接运行的文件!代码放在 `bin/` 文件夹中!
使用手册:
```bash
╭─bmy@MacBook-Pro /Applications/Source/TsxVueClassApi master*
╰─$ ./bin/tinit -h
Usage: tinit [options]
Options:
-t, --file-type <type> 文件类型: [pagelogicserviceimplless]
-n, --file-name <name> 被创建的文件名称
-i, --is-create <is> 是否为 -t 参数自动创建相关文件类型 (default: false)
-v, --version 显示当前的版本
-h, --help display help for command
```
参数说明:
- -t需要被创建的文件类型取值 pageTSX页面logicTSX页面的js抽象层service请求中间层的接口impl实现接口的类lesscss样式文件。可以多传
- -n需要被创建的文件名
- -i如果数值为true那么会自动创建 -t 参数所有的文件类型
使用案例:
```bash
╭─bmy@MacBook-Pro /Applications/Source/TsxVueClassApi master*
╰─$ ./bin/tinit -t page logic -n Test
成功创建文件...
```
上面命令执行后会分别在`src/application/page`中创建创建文件`Text.tsx`页面组件,同时在`src/application/logic/page`中创建`Test.logic.ts`的逻辑层文件。
多试几次,请自行熟练掌握!!
## 3开发中功能
- [x] 【重要】1实现`ajax`请求到的数据和`model`层的映射绑定,这种数据绑定关系,可以完全解决后端改接口字段从而导致前端代码也需要同步大量修改的问题!!
- 插件文档:[https://gitee.com/bmycode/json-to-class-or-interface](https://gitee.com/bmycode/json-to-class-or-interface)
- [x] 【不太重要】1实时监听`configure.config.ts`配置文件,然后根据`ApiList`中的对象`key`名称自动在`service`层的类中生成对应的方法,降低手动复制的低效率!
- 已实现功能,但未整合进项目!

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2024. bmy
* Email2271608011@qq.com
* Githubhttps://github.com/helpcode
*/
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
// plugins: [
// [
// "import",
// {libraryName: "ant-design-vue", libraryDirectory: "es", style: true}
// ]
// ]
}

View File

@@ -0,0 +1 @@
4ac2522b-c3cb-4af1-87fb-ee6e6242e0fc

View File

@@ -0,0 +1 @@
9d76d575-a956-4eba-b474-4daf9b6b8054

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2024. bmy
* Email2271608011@qq.com
* Githubhttps://github.com/helpcode
*/
module.exports = {
pageConfig: (name) => {
return `
import "@pageLess/${ name }.less";
import { Component, Vue } from 'vue-property-decorator';
import { ${ name }Logic } from "@logic/page/${ name }.logic";
import { Route, RawLocation } from 'vue-router';
import { VueCustomize, RouterMeta } from "@logic/base.type";
import { Autowired } from "@ann/ioc.annotation";
@Component
export default class ${ name } extends VueCustomize {
private logic: ${name}Logic<${name}> = new ${name}Logic(this);
private RouterMeta: RouterMeta = {
title: '${ name }',
showNav: true,
isLogin: true
};
public async created() {
await this.logic.StartUp();
};
// 路由拦截器
beforeRouteEnter(to: Route, from: Route, next: (to?: RawLocation | false | ((vm: Vue) => void)) => void) {
next();
}
protected render() {
return (
<div class="${ name }">
${ name }
</div>
)
}
}
`
},
logicConfig: (name) => {
return `
import { Autowired } from "@ann/ioc.annotation";
import { UserServiceImpl, ResponseType } from "@impl/user.service.impl";
import { BaseLogic } from "@logic/base.logic";
import { Methods, VueCustomize } from "@logic/base.type";
export class ${name}Logic<T extends ${name}> extends BaseLogic<T> implements Methods {
@Autowired()
public readonly UserServiceImpl!: UserServiceImpl;
constructor(_: T) {
super();
this._ = _;
}
public async StartUp(): Promise<void> {
}
}
`
},
serviceConfig: (name) => {
return `
export interface ${ name }Service {
IndexClass(params: object): Promise<any>;
}
`
},
implPathConfig: (name) => {
return `
import { ${ name }Service } from "@service/${ name }.service";
import { Autowired } from "@ann/Ioc.annotation";
import { GET } from "@ann/Http.annotation";
export class ${ name }ServiceImpl implements ${ name }Service {
@GET({ useHandle: false })
public async IndexClass(params: object): Promise<any> { }
}
`
},
lessConfig: (name) => {
return `
@import "../mixin/_";
.${ name } {
}
`
}
}

View File

@@ -0,0 +1,101 @@
<!--
~ Copyright (c) 2024. bmy
~ Email2271608011@qq.com
~ Githubhttps://github.com/helpcode
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>启动页面</title>
<meta id="viewport" content="width=device-width,initial-scale=1,minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"
name="viewport">
<script src="https://at.alicdn.com/t/c/font_4318577_uqa853deiz.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.main {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: -150px;
}
.main .icon {
width: 150px;
height: 150px;
}
.main p {
font-size: 20px;
font-weight: bolder;
letter-spacing: 2px;
margin-bottom: 15px;
}
.main .pg {
height: 15px;
border: none;
}
progress::-webkit-progress-bar {
border-radius: 10px;
background: #34495e;
}
progress::-webkit-progress-value {
border-radius: 10px;
background: #41b883;
}
</style>
</head>
<body>
<div class="main">
<svg aria-hidden="true" class="icon">
<use xlink:href="#json-Vue"></use>
</svg>
<p class="title">..</p>
<progress class="pg" max="100" value="0"></progress>
</div>
<script>
const pro = $('.pg');
const title = $('.title');
async function getProgress() {
return await fetch('/__progress').then(res => res.json());
}
async function freshProgress() {
let {progress} = await getProgress()
let intProgress = ~~(progress * 100)
pro.value = intProgress;
title.innerText = `${intProgress}%`;
if (progress < 1) {
setTimeout(freshProgress, 500);
}
}
function $(className) {
return document.querySelector(className);
}
freshProgress();
</script>
</body>
</html>

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2024. bmy
* Email2271608011@qq.com
* Githubhttps://github.com/helpcode
*/
#!/usr/bin/env node
const {program} = require('commander');
const packageConfig = require("../package.json");
const fs = require("fs");
const path = require('path');
const Config = require("./config");
var isWin = /^win/.test(process.platform);
const RootPath = process.cwd();
program
.requiredOption('-t, --file-type <type>', '文件类型: [pagelogicserviceimplless]')
.option('-n, --file-name <name>', '被创建的文件名称')
.option('-i, --is-create <is>', '是否为 -t 参数自动创建相关文件类型', false);
program.version(packageConfig.version, '-v, --version', '显示当前的版本');
program.parse(process.argv);
// 存储终端的参数
let programOptions = program.opts();
let OtherFileType = program.parse(process.argv).args
// tsx 页面路径
let PagePath = isWin ? `${ RootPath }\\src\\application\\page\\${ UpperCase(programOptions.fileName) }.tsx` : `${ RootPath }/src/application/page/${ UpperCase(programOptions.fileName) }.tsx`;
// logic 页面路径
let LogicPath = isWin ? `${ RootPath }\\src\\application\\logic\\page\\${ UpperCase(programOptions.fileName) }.logic.ts` : `${ RootPath }/src/application/logic/page/${ UpperCase(programOptions.fileName) }.logic.ts`;
// service 页面路径
let ServicePath = isWin ? `${ RootPath }\\src\\core\\service\\${ UpperCase(programOptions.fileName) }.service.ts` : `${ RootPath }/src/core/service/${ UpperCase(programOptions.fileName) }.service.ts`;
// Impl 页面路径
let ImplPath = isWin ? `${ RootPath }\\src\\core\\service\\impl\\${ UpperCase(programOptions.fileName) }.service.impl.ts` : `${ RootPath }/src/core/service/impl/${ UpperCase(programOptions.fileName) }.service.impl.ts`;
// Less 页面路径
let LessPath = isWin ? `${ RootPath }\\src\\application\\assets\\less\\page\\${ UpperCase(programOptions.fileName) }.less` : `${ RootPath }/src/application/assets/less/page/${ UpperCase(programOptions.fileName) }.less`;
// 需要创建的文件类型
let FileList = ['page', 'logic', 'service', 'impl', 'less'];
// 是否需要为 controller 联合创建所有文件
if (programOptions.isCreate) {
FileList.forEach(val => replaceTplText(val));
console.log("成功创建文件...");
} else {
// 循环创建多个文件
if (OtherFileType.length != 0) {
[...OtherFileType, programOptions.fileType].forEach(v => replaceTplText(v))
} else {
replaceTplText(programOptions.fileType)
}
console.log("成功创建文件...");
}
/**
* 替换模板的内容,并将内容写入文件。
*/
let FileText = ""
function replaceTplText(action) {
switch (action) {
case 'page':
fs.writeFileSync(PagePath, Config.pageConfig(UpperCase(programOptions.fileName)));
break;
case 'logic':
fs.writeFileSync(LogicPath, Config.logicConfig(UpperCase(programOptions.fileName)));
break;
case 'service':
fs.writeFileSync(ServicePath, Config.serviceConfig(UpperCase(programOptions.fileName)));
break;
case 'impl':
fs.writeFileSync(ImplPath, Config.implPathConfig(UpperCase(programOptions.fileName)));
break;
case 'less':
fs.writeFileSync(LessPath, Config.lessConfig(UpperCase(programOptions.fileName)));
break;
default:
break
}
}
/**
* 单词首字母大写
* @param str
* @returns {void | string | *}
* @constructor
*/
function UpperCase(str) {
return str.replace(str[0], str[0].toUpperCase())
}
/**
* 读取文件内容
* @param path
* @returns {*}
* @constructor
*/
function GetFileText(path) {
return (fs.readFileSync(pathJoin(path), 'utf-8')).toString();
}
/**
* 拼接路径
* @param paths
* @returns {string}
*/
function pathJoin(paths) {
return path.join(__dirname, paths)
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024. bmy
* Email2271608011@qq.com
* Githubhttps://github.com/helpcode
*/
const gulp = require('gulp');
const {exec} = require('child_process');
/**
* 执行 vue-cli-service route 命令进行路由编译
*/
gulp.task('AutoCompileRouter', function (cb) {
return exec('npm run route', (err, stdout, stderr) => {
if (err) {
console.log("编译失败: ", err);
cb(err)
} else {
console.log("编译成功");
}
});
});
/**
* 监听 page 所有文件的修改,自动触发 AutoCompileRouter 任务
*/
gulp.task('auto', async () => {
gulp.watch('src/application/page/**/*', gulp.parallel('AutoCompileRouter'));
});
gulp.task('default', gulp.parallel('auto'));

View File

@@ -0,0 +1,52 @@
<!--
~ Copyright (c) 2024. bmy
~ Email2271608011@qq.com
~ Githubhttps://github.com/helpcode
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
name="viewport">
<meta content="ie=edge" http-equiv="X-UA-Compatible">
<title>Document</title>
</head>
<body>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script>
$.ajax({
url: "http://8.140.20.241:8080/menu/getMenus",
type: "POST",
contentType: 'application/json; charset=utf-8',
headers: {
adminId: 7,
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6IjE5YmY4OWNjOTU1ZTc1NjE2MjQ0ZTE5OTVlNjQ5OTgyIiwiZXhwIjoxNzA1MDQ0OTExLCJ1c2VybmFtZSI6ImFkbWluIn0.7Mhqx8dkgYOqCQEPJZVoUBeg9nuXo_7qyn4qxraUiKQ"
},
data: JSON.stringify({}),
success: function (res) {
console.log(res)
}
})
</script>
<!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
<!--<script>-->
<!-- axios.post('http://8.140.20.241:8080/menu/getMenus',-->
<!-- {},-->
<!-- {-->
<!-- headers: {-->
<!-- adminId: 7,-->
<!-- token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6IjE5YmY4OWNjOTU1ZTc1NjE2MjQ0ZTE5OTVlNjQ5OTgyIiwiZXhwIjoxNzA1MDQ0OTExLCJ1c2VybmFtZSI6ImFkbWluIn0.7Mhqx8dkgYOqCQEPJZVoUBeg9nuXo_7qyn4qxraUiKQ"-->
<!-- }-->
<!-- })-->
<!-- .then(function (response) {-->
<!-- console.log(response);-->
<!-- })-->
<!-- .catch(function (error) {-->
<!-- console.log(error);-->
<!-- });-->
<!--</script>-->
</html>

View File

@@ -0,0 +1,59 @@
{
"name": "tsx-vue-class-api",
"version": "1.1.0",
"private": true,
"scripts": {
"start": "concurrently \"npm run serve\" ",
"serve": "cross-env NODE_ENV=dev vue-cli-service serve",
"build": "cross-env NODE_ENV=production vue-cli-service build",
"route": "vue-cli-service route"
},
"bin": {
"tinit": "bin/tinit"
},
"dependencies": {
"@antv/g6": "^4.8.21",
"axios": "^0.20.0",
"core-js": "^3.8.3",
"echarts": "^5.4.3",
"element-ui": "^2.15.14",
"isarray": "^2.0.5",
"moment": "^2.30.1",
"qrcodejs2": "0.0.2",
"vue": "^2.6.14",
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^9.1.2",
"vue-router": "^3.2.0",
"vuex": "^3.4.0",
"vuex-class": "^0.3.2"
},
"devDependencies": {
"vue-template-compiler": "^2.6.14",
"@babel/generator": "^7.11.4",
"@babel/parser": "^7.11.4",
"@babel/types": "^7.11.0",
"@types/isarray": "^2.0.0",
"@types/vue-select": "^3.16.8",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-polyfill": "^6.26.0",
"commander": "^6.1.0",
"compression-webpack-plugin": "^5.0.1",
"es6-promise": "^4.2.8",
"glob": "^7.1.3",
"gulp": "^4.0.2",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"pify": "^4.0.1",
"reflect-metadata": "^0.1.13",
"single-line-log": "^1.1.2",
"typescript": "~3.9.3",
"uglifyjs-webpack-plugin": "^2.2.0",
"vue-cli-plugin-tsx-autorouter": "^1.3.6",
"webpack-bundle-analyzer": "^3.8.0",
"yamljs": "^0.3.0"
}
}

View File

@@ -0,0 +1 @@
54e03d48-6f43-4c06-bf43-ca00c9f9ba29

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1 @@
3497e353-e33f-4aee-812c-0d60f4f6e425

View File

@@ -0,0 +1 @@
09864b04-3417-420e-bfc9-007a981d39e8

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View File

@@ -0,0 +1 @@
c9d78330-abe7-4ed2-8ee5-142ed48cc4de

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Some files were not shown because too many files have changed in this diff Show More