>();
+ logger.LogError(ex, "Failed to initialize services on startup");
+ }
+ }
+
+ ///
+ /// SQLiteݿַ
+ ///
+ private static string CreateSqliteDBConn()
+ {
+ var dbFolder = Path.Combine(Environment.CurrentDirectory, "db");
+ Directory.CreateDirectory(dbFolder); // ж
+
+ var dbPath = Path.Combine(dbFolder, "dy.sqlite");
+ if (!File.Exists(dbPath))
+ {
+ using (File.Create(dbPath)) { } // ʹusingȷļر
+ }
+
+ return $"DataSource={dbPath}";
+ }
+
+ ///
+ /// ʼݿ
+ ///
+ private static ISqlSugarClient InitDataBase(DbType dbType, string connString)
+ {
+ // SQLiteַ
+ if (dbType == DbType.Sqlite)
+ {
+ connString = CreateSqliteDBConn();
+ }
+
+ if (string.IsNullOrEmpty(connString))
+ {
+ return null;
+ }
+
+ return new SqlSugarClient(new ConnectionConfig
+ {
+ ConnectionString = connString,
+ InitKeyType = InitKeyType.Attribute,
+ DbType = dbType,
+ IsAutoCloseConnection = true
+ }, db =>
+ {
+ // ־
+ db.Aop.OnLogExecuting = (sql, pars) => Serilog.Log.Debug(sql);
+ db.Aop.OnError = e =>
+ {
+ Serilog.Log.Error(e.Message);
+ Serilog.Log.Error(e.Sql);
+ };
+
+ // ݿͱ
+ db.DbMaintenance.CreateDatabase();
+ var modelTypes = Assembly.GetExecutingAssembly()
+ .GetTypes()
+ .Where(t => t.Namespace?.StartsWith("dy.net.model") ?? false)
+ .ToArray();
+ db.CodeFirst.InitTables(modelTypes);
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Properties/PublishProfiles/FolderProfile.pubxml b/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..3ed83c2
--- /dev/null
+++ b/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,21 @@
+
+
+
+
+ true
+ false
+ true
+ Release
+ Any CPU
+ FileSystem
+ bin\Release\net6.0\publish\
+ FileSystem
+ <_TargetId>Folder
+
+ net6.0
+ 680660ef-acae-43a9-ab6c-b75532e758ad
+ false
+
+
\ No newline at end of file
diff --git a/Properties/PublishProfiles/FolderProfile.pubxml.user b/Properties/PublishProfiles/FolderProfile.pubxml.user
new file mode 100644
index 0000000..e997050
--- /dev/null
+++ b/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -0,0 +1,11 @@
+
+
+
+
+ <_PublishTargetUrl>F:\work\code\me\dy-sync\bin\Release\net6.0\publish\
+ True|2025-09-30T05:29:42.2354235Z||;True|2025-09-25T11:44:52.6858389+08:00||;True|2025-09-25T11:08:27.8810109+08:00||;True|2025-09-25T09:28:50.2563374+08:00||;True|2025-09-24T16:14:02.3072184+08:00||;True|2025-09-23T22:38:52.4414757+08:00||;True|2025-09-23T22:19:07.1006356+08:00||;True|2025-09-23T22:18:01.5945225+08:00||;True|2025-09-23T22:06:15.6293613+08:00||;True|2025-09-23T21:53:14.2977444+08:00||;True|2025-09-23T21:46:55.2322411+08:00||;False|2025-09-23T21:45:23.7858854+08:00||;False|2025-09-23T21:03:51.8325689+08:00||;True|2025-09-23T10:03:32.2251920+08:00||;False|2025-09-23T09:38:08.2372201+08:00||;False|2025-09-23T09:37:49.9390545+08:00||;True|2024-03-11T21:31:45.8102398+08:00||;True|2024-03-11T07:26:24.7660541+08:00||;True|2024-03-08T22:08:40.0154831+08:00||;True|2024-03-03T10:14:36.8109114+08:00||;True|2024-03-02T18:44:57.3288537+08:00||;True|2024-01-24T17:51:37.9164415+08:00||;True|2024-01-24T16:36:50.5612157+08:00||;True|2024-01-24T15:51:35.7556653+08:00||;True|2024-01-17T23:40:40.7526618+08:00||;True|2024-01-17T23:36:10.3692844+08:00||;True|2024-01-17T23:22:03.2378834+08:00||;True|2024-01-03T11:35:44.7118292+08:00||;True|2024-01-03T11:11:23.4270453+08:00||;True|2024-01-03T11:04:35.2081526+08:00||;True|2024-01-03T10:57:03.7053107+08:00||;True|2024-01-03T10:51:50.7463989+08:00||;False|2024-01-03T10:50:24.9775312+08:00||;True|2024-01-03T10:47:30.1128183+08:00||;True|2024-01-03T10:42:55.8640657+08:00||;True|2024-01-03T09:24:24.3436056+08:00||;True|2024-01-02T23:40:38.2001198+08:00||;True|2024-01-02T23:08:36.7230444+08:00||;True|2024-01-02T22:53:43.9658255+08:00||;True|2024-01-02T22:25:38.5545279+08:00||;False|2024-01-02T22:24:42.6577609+08:00||;True|2024-01-02T22:04:33.4708889+08:00||;True|2024-01-02T21:49:57.9249898+08:00||;True|2023-12-28T22:42:58.5976180+08:00||;True|2023-12-28T22:24:09.2051205+08:00||;True|2023-12-28T22:05:48.4865497+08:00||;True|2023-12-28T21:50:57.4549336+08:00||;True|2023-12-28T21:45:30.4557939+08:00||;True|2023-12-28T21:19:59.3614594+08:00||;False|2023-12-28T21:17:04.3069097+08:00||;False|2023-12-28T21:15:56.7788810+08:00||;False|2023-12-28T21:14:57.3617402+08:00||;False|2023-12-28T21:10:45.4382469+08:00||;True|2023-12-28T19:45:33.1431914+08:00||;True|2023-12-26T11:30:36.6418716+08:00||;True|2023-12-26T11:17:40.6433651+08:00||;True|2023-12-26T09:13:56.0741559+08:00||;True|2023-12-26T09:10:55.5358737+08:00||;True|2023-12-25T23:15:34.6534359+08:00||;True|2023-12-25T23:09:47.1566176+08:00||;False|2023-12-25T23:07:32.1118803+08:00||;True|2023-12-25T22:59:50.4643459+08:00||;True|2023-12-25T22:50:14.3584798+08:00||;False|2023-12-25T22:49:20.0279513+08:00||;True|2023-12-25T22:44:07.4183973+08:00||;True|2023-12-25T22:35:27.3847085+08:00||;True|2023-12-25T22:23:21.3542658+08:00||;True|2023-12-25T22:12:00.5219522+08:00||;True|2023-12-25T16:52:12.5089621+08:00||;True|2023-12-25T16:43:30.8348193+08:00||;True|2023-12-25T16:35:08.2421925+08:00||;True|2023-12-25T16:25:21.3233455+08:00||;False|2023-12-25T16:24:39.1703901+08:00||;True|2023-12-25T16:24:01.4340091+08:00||;True|2023-12-25T16:10:06.5213850+08:00||;True|2023-12-25T15:42:17.1376331+08:00||;True|2023-12-25T15:29:47.8537015+08:00||;True|2023-12-25T14:04:54.3750643+08:00||;False|2023-12-25T14:04:07.9330700+08:00||;True|2023-12-25T13:51:58.1949269+08:00||;True|2023-12-25T13:41:42.4832670+08:00||;True|2023-12-25T13:00:25.3861450+08:00||;True|2023-12-25T12:48:45.3851245+08:00||;True|2023-12-25T12:46:54.1266013+08:00||;True|2023-12-25T12:37:03.2615780+08:00||;False|2023-12-25T12:36:06.2657224+08:00||;True|2023-12-25T12:31:59.6032354+08:00||;True|2023-12-25T12:26:50.2316015+08:00||;True|2023-12-25T12:18:27.4149004+08:00||;True|2023-12-25T11:59:46.1381276+08:00||;True|2023-12-25T00:36:00.0643971+08:00||;True|2023-12-25T00:28:55.0051504+08:00||;False|2023-12-25T00:21:35.4266163+08:00||;True|2023-12-25T00:18:47.0638530+08:00||;True|2023-12-25T00:12:09.6195055+08:00||;True|2023-12-25T00:01:34.9698196+08:00||;False|2023-12-24T23:50:48.6479274+08:00||;True|2023-12-22T09:54:04.1399592+08:00||;True|2023-12-22T08:59:53.2795721+08:00||;False|2023-12-18T23:40:16.8523325+08:00||;
+
+
+
\ No newline at end of file
diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json
new file mode 100644
index 0000000..a492985
--- /dev/null
+++ b/Properties/launchSettings.json
@@ -0,0 +1,37 @@
+{
+ "profiles": {
+ "dy.net": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "http://localhost:5193"
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "weatherforecast",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Docker": {
+ "commandName": "Docker",
+ "launchBrowser": true,
+ "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/weatherforecast",
+ "publishAllPorts": true
+ }
+ },
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:35772",
+ "sslPort": 0
+ }
+ }
+}
\ No newline at end of file
diff --git a/SecUserId.png b/SecUserId.png
deleted file mode 100644
index 27d86b1..0000000
Binary files a/SecUserId.png and /dev/null differ
diff --git a/app/.babelrc b/app/.babelrc
new file mode 100644
index 0000000..c13c5f6
--- /dev/null
+++ b/app/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["es2015"]
+}
diff --git a/app/.env b/app/.env
new file mode 100644
index 0000000..adce5e5
--- /dev/null
+++ b/app/.env
@@ -0,0 +1,2 @@
+VITE_BASE_URL=/
+VITE_API_URL=http://localhost
diff --git a/app/.env.development b/app/.env.development
new file mode 100644
index 0000000..c4d5c01
--- /dev/null
+++ b/app/.env.development
@@ -0,0 +1,2 @@
+VITE_BASE_URL=/
+VITE_API_URL=http://localhost:10101
\ No newline at end of file
diff --git a/app/.env.github b/app/.env.github
new file mode 100644
index 0000000..b44d27e
--- /dev/null
+++ b/app/.env.github
@@ -0,0 +1 @@
+VITE_BASE_URL=/
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..a85a70d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1,16 @@
+node_modules
+.DS_Store
+dist
+dist-ssr
+*.local
+.vscode
+.history
+.idea
+*.log
+*session.sql
+package-lock.json
+yarn.lock
+stepin-template.session.sql
+docs/.vitepress/cache
+target
+components.d.ts
\ No newline at end of file
diff --git a/app/.prettierrc.json b/app/.prettierrc.json
new file mode 100644
index 0000000..8b1abb1
--- /dev/null
+++ b/app/.prettierrc.json
@@ -0,0 +1,22 @@
+{
+ "arrowParens": "always",
+ "bracketSpacing": true,
+ "endOfLine": "lf",
+ "htmlWhitespaceSensitivity": "css",
+ "insertPragma": false,
+ "singleAttributePerLine": false,
+ "bracketSameLine": false,
+ "jsxBracketSameLine": false,
+ "bracketLine": false,
+ "jsxSingleQuote": true,
+ "printWidth": 120,
+ "proseWrap": "preserve",
+ "quoteProps": "as-needed",
+ "requirePragma": false,
+ "semi": true,
+ "singleQuote": true,
+ "tabWidth": 2,
+ "trailingComma": "es5",
+ "useTabs": false,
+ "vueIndentScriptAndStyle": true
+}
diff --git a/app/LICENSE b/app/LICENSE
new file mode 100644
index 0000000..1c9026b
--- /dev/null
+++ b/app/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 stepui
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/app/README-en_US.md b/app/README-en_US.md
new file mode 100644
index 0000000..f01d0b6
--- /dev/null
+++ b/app/README-en_US.md
@@ -0,0 +1,83 @@
+Stepin Template
+
+
+
+开箱即用的中后台前端/设计解决方案
+
+(原[ Vue Antd Admin](https://github.com/iczer/vue-antd-admin/) Vue3 版本)
+
+
+
+
+
+
+
+
+
+
+
+English | [简体中文](./README.md)
+
+- 预览地址: https://stepui.gitee.io/stepin-template
+- 使用文档: http://stepui.gitee.io/stepin-template-docs/
+- 常见问题: http://stepui.gitee.io/stepin-template-docs/issue
+- 国内镜像: https://gitee.com/stepui/stepin-template
+
+## 特性
+
+- 强大的主题定制功能,实时动态切换
+- 多页签功能,助力后台管理高效开发
+- 内置权限控制,兼容 ABAC 和 RBAC 模型
+- 丰富的内置业务组件和常用页面模板
+
+## 浏览器支持
+| [
](http://godban.github.io/browsers-support-badges/)Edge | [
](http://godban.github.io/browsers-support-badges/)Firefox | [
](http://godban.github.io/browsers-support-badges/)Chrome | [
](http://godban.github.io/browsers-support-badges/)Safari | [
](http://godban.github.io/browsers-support-badges/)Opera |
+| --- | --- | --- | --- | --- |
+| last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
+## 环境要求
+
+|git|node|yarn|
+|---|----|----|
+|`^2.15.0`|`^16.14.0`|`^1.21.1`|
+
+## 使用
+
+### 拉取代码
+
+```bash
+git clone https://github.com/stepui/stepin-template.git
+```
+
+### 安装依赖
+
+```bash
+yarn install
+```
+
+### 启动
+
+```
+yarn dev
+```
+
+### 预览
+
+启动成功后,控制台会显示本地访问地址:http://127.0.0.1:5173,浏览器打开即可预览。
+
+更新多信息请参考 [使用文档](http://stepui.gitee.io/stepin-template-docs/)
+
+## 参与贡献
+
+我们非常欢迎你的贡献,你可以通过以下方式和我们一起共建 :star2::
+
+- 在你的公司或个人项目中使用 Stepin Template。
+- 通过 [Issue](https://github.com/stepui/stepin-template/issues/new) 报告:bug:或进行咨询。
+- 提交 [Pull Request](https://github.com/stepui/stepin-template/pulls) 改进 Stepin Template 的代码。
+- 加入社群,与小伙伴们一同交流心得。QQ 群:441231578
+
+## 打赏作者
+如果该项目对您有所帮助,可以请作者喝一杯咖啡。
+
+
+
+
diff --git a/app/README.md b/app/README.md
new file mode 100644
index 0000000..8ee0382
--- /dev/null
+++ b/app/README.md
@@ -0,0 +1,84 @@
+Stepin Template
+
+
+
+开箱即用的中后台前端/设计解决方案
+
+(原[ Vue Antd Admin](https://github.com/iczer/vue-antd-admin/) Vue3 版本)
+
+
+
+
+
+
+
+
+
+
+
+简体中文 | [English](./README-en_US.md)
+
+- 预览地址: https://stepui.gitee.io/stepin-template
+- 使用文档: http://stepui.gitee.io/stepin-template-docs/
+- 常见问题: http://stepui.gitee.io/stepin-template-docs/issue
+- 国内镜像: https://gitee.com/stepui/stepin-template
+
+## 特性
+
+- 强大的主题定制功能,实时动态切换
+- 多页签功能,助力后台管理高效开发
+- 内置权限控制,兼容 ABAC 和 RBAC 模型
+- 丰富的内置业务组件和常用页面模板
+
+## 浏览器支持
+| [
](http://godban.github.io/browsers-support-badges/)Edge | [
](http://godban.github.io/browsers-support-badges/)Firefox | [
](http://godban.github.io/browsers-support-badges/)Chrome | [
](http://godban.github.io/browsers-support-badges/)Safari | [
](http://godban.github.io/browsers-support-badges/)Opera |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
+## 环境要求
+
+| git | node | yarn |
+| --------- | ---------- | --------- |
+| `^2.15.0` | `^16.14.0` | `^1.21.1` |
+
+## 使用
+
+### 拉取代码
+
+```sh
+git clone https://github.com/stepui/stepin-template.git
+```
+
+### 安装依赖
+
+```sh
+yarn install
+```
+
+### 启动
+
+```sh
+yarn dev
+```
+
+### 预览
+
+启动成功后,控制台会显示本地访问地址:http://127.0.0.1:5173,浏览器打开即可预览。
+
+更新多信息请参考 [使用文档](http://stepui.gitee.io/stepin-template-docs/)
+
+## 参与贡献
+
+我们非常欢迎你的贡献,你可以通过以下方式和我们一起共建 :star2::
+
+- 在你的公司或个人项目中使用 Stepin Template。
+- 通过 [Issue](https://github.com/stepui/stepin-template/issues/new) 报告:bug:或进行咨询。
+- 提交 [Pull Request](https://github.com/stepui/stepin-template/pulls) 改进 Stepin Template 的代码。
+- 加入社群,与小伙伴们一同交流心得。QQ 群:441231578
+- less报错
+ yarn remove less && yarn add less@4.1.3 -D
+## 打赏作者
+如果该项目对您有所帮助,可以请作者喝一杯咖啡。
+
+
+
+
diff --git a/app/gulpfile.babel.js/index.js b/app/gulpfile.babel.js/index.js
new file mode 100644
index 0000000..4a06b30
--- /dev/null
+++ b/app/gulpfile.babel.js/index.js
@@ -0,0 +1,86 @@
+import { series, src, dest } from 'gulp';
+import clean from 'gulp-clean';
+import replace from 'gulp-replace';
+import vueTsc from './vueTemplateTsc';
+
+export { default as tsc } from './vueTemplateTsc';
+
+function cleanAll() {
+ return src(['./target/*', '!./target/node_modules'], { allowEmpty: true }).pipe(clean({ force: true }));
+}
+
+function copyIndex() {
+ return src(['./index.html']).pipe(replace('.ts', '.js')).pipe(replace(' + TS', '')).pipe(dest('./target'));
+}
+
+function copyPublic() {
+ return src(['./public/**/*']).pipe(dest('./target/public'));
+}
+
+function copyStyleAndJs() {
+ return src(['./src/**/*.{less,css,js}']).pipe(dest('./target/src'));
+}
+
+function copyAssets() {
+ return src(['./src/assets/**/*']).pipe(dest('./target/src/assets'));
+}
+
+function copyConfig() {
+ return src([
+ './.env*',
+ './.gitignore',
+ '.babelrc',
+ './*.{json,cjs}',
+ './LICENSE',
+ '!./tsconfig.*',
+ '!./package*.json',
+ ]).pipe(dest('./target'));
+}
+
+function copyReadme() {
+ return src(['./*.md']).pipe(replace('stepin-template.git', 'stepin-template-js.git')).pipe(dest('./target'));
+}
+
+function copyPackageJson() {
+ return src(['./package.json'])
+ .pipe(replace(/,?[\r\n]+.*"(gulp[\-\w]*|vue-tsc|typescript)"[^,\r\n]*/g, ''))
+ .pipe(replace(/vue-tsc --noEmit && /g, ''))
+ .pipe(dest('./target'));
+}
+function cleanJsRepository() {
+ return src([
+ '../stepin-template-js/*',
+ '!../stepin-template-js/node_modules',
+ '!../stepin-template-js/.git',
+ '!../stepin-template-js/.history',
+ '!../stepin-template-js/.vscode',
+ ]).pipe(clean({ force: true }));
+}
+export function copyToJsRepository() {
+ return src([
+ './target/**/*',
+ './.env*',
+ './.gitignore',
+ '.babelrc',
+ '!./target/node_modules/**/*',
+ '!./target/node_modules',
+ ]).pipe(dest('../stepin-template-js'));
+}
+
+export function copyDocs() {
+ return src(['./docs/**/*', '!./docs/.vitepress/**/*', '!./docs/.vitepress']).pipe(dest('../stepin-template-js/docs'));
+}
+
+export const makeJs = series(cleanJsRepository, copyToJsRepository, copyDocs);
+
+export default series(
+ cleanAll,
+ vueTsc,
+ copyIndex,
+ copyPublic,
+ copyStyleAndJs,
+ copyConfig,
+ copyReadme,
+ copyAssets,
+ copyPackageJson
+);
diff --git a/app/gulpfile.babel.js/transform.js b/app/gulpfile.babel.js/transform.js
new file mode 100644
index 0000000..4165e3f
--- /dev/null
+++ b/app/gulpfile.babel.js/transform.js
@@ -0,0 +1,19 @@
+import { Transform } from 'stream';
+
+export class BufferTransform extends Transform {
+ constructor(transform) {
+ super({
+ objectMode: true,
+ transform(file, enc, callback) {
+ if (file.isBuffer()) {
+ file.contents = Buffer.from(transform(new String(file.contents)));
+ }
+ if (file.isStream()) {
+ console.log('stream file', file.path);
+ }
+ return callback(null, file);
+ },
+ });
+ return this;
+ }
+}
diff --git a/app/gulpfile.babel.js/vueTemplateTsc.js b/app/gulpfile.babel.js/vueTemplateTsc.js
new file mode 100644
index 0000000..040d354
--- /dev/null
+++ b/app/gulpfile.babel.js/vueTemplateTsc.js
@@ -0,0 +1,152 @@
+import { src, dest, series } from 'gulp';
+import rename from 'gulp-rename';
+import replace from 'gulp-replace';
+import { BufferTransform } from './transform';
+
+import ts from 'typescript';
+import prettier from 'prettier';
+import tsConfig from '../tsconfig.json';
+
+tsConfig.compilerOptions.sourceMap = false;
+tsConfig.compilerOptions.importsNotUsedAsValues = 'preserve';
+
+/**
+ * vue 文件代码格式化
+ * @param {*} code
+ * @returns
+ */
+const vueFormatter = () =>
+ new BufferTransform((code) =>
+ prettier.format(code, {
+ trailingComma: 'es5',
+ parser: 'vue',
+ vueIndentScriptAndStyle: true,
+ singleQuote: true,
+ })
+ );
+/**
+ * ts 文件代码格式化
+ * @param {*} code
+ * @returns
+ */
+const tsFormatter = () =>
+ new BufferTransform((code) =>
+ prettier.format(code, {
+ trailingComma: 'es5',
+ parser: 'typescript',
+ singleQuote: true,
+ })
+ );
+
+/** ts编译器 */
+const tsToJs = (tsStrCode) => {
+ const code = tsStrCode
+ .replace(/defineEmits<[\s\S]*>\(\);/g, (match) =>
+ match.replace(/'?([\w:]*)'?:\s*\[.*\];/g, "'$1',").replace(/\(e:\s*(\'[^',]*\')[^;]*;/g, '$1,')
+ )
+ .replace(/<{([^\{\}<>]*)}>\(\)/g, '([$1])');
+ const result = ts.transpileModule(code, tsConfig);
+ const jsStrCode = result.outputText;
+ return jsStrCode;
+};
+
+/**
+ * SFC 文件 ts 代码编译
+ * @param {*} tmpContent
+ * @returns
+ */
+const handleTmpContent = (tmpContent) => {
+ if (!tmpContent) {
+ return tmpContent;
+ }
+ return tmpContent
+ .replace(/(?<=((@|:|v-)[\w\-]*="))([^"]*)(?=")/g, function (match) {
+ if (/\s*{[\s\S]*}\s*/.test(match)) {
+ return tsToJs(`const patch = ${match}`).replace(/;\s*/g, '').replace('const patch = ', '');
+ }
+ return `${tsToJs(match).replace(/;\s*/g, '')}`;
+ })
+ .replace(/(?<=({{))([^{}]*)(?=}})/g, function (match) {
+ if (/\s*{[\s\S]*}\s*/.test(match)) {
+ return tsToJs(`const patch = ${match}`).replace(/;\s*/g, '').replace('const patch = ', '');
+ }
+ return `${tsToJs(match).replace(/;\s*$/, '')}`;
+ });
+};
+
+function transformVue(options) {
+ return new BufferTransform((content) =>
+ content
+ .replace(/(?<=(\))([\s\S]*)(?=(\<\/template>))/, function (match) {
+ return handleTmpContent(match);
+ })
+ .replace(/(?<=(\
+
+