├── .gitignore ├── .npmignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── LICENSE ├── package.json ├── packages ├── commitLint │ ├── .release-it.json │ ├── index.js │ ├── package.json │ └── readme.md ├── dlnpm │ ├── .gitignore │ ├── .npmignore │ ├── .npmrc │ ├── LICENSE │ ├── dlnpm.js │ ├── package.json │ └── readme.md ├── gitlook │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── package.json │ └── scripts │ │ └── statistics.js ├── tnbc │ ├── LICENSE │ ├── README.md │ ├── index.js │ └── package.json ├── yiadmin │ ├── .gitignore │ ├── .npmignore │ ├── .prettierrc │ ├── LICENSE │ ├── README.md │ ├── index.html │ ├── jsconfig.json │ ├── package.json │ ├── public │ │ └── logo.png │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── login-back.png │ │ │ ├── login-left-image.png │ │ │ └── logo.png │ │ ├── components │ │ │ └── .gitkeep │ │ ├── config │ │ │ ├── app.js │ │ │ └── internal.js │ │ ├── env │ │ │ ├── .env.development │ │ │ └── .env.production │ │ ├── i18n │ │ │ ├── en.json │ │ │ └── zh.json │ │ ├── layouts │ │ │ └── default │ │ │ │ ├── components │ │ │ │ └── sideMenu.vue │ │ │ │ └── index.vue │ │ ├── main.js │ │ ├── pages │ │ │ ├── index │ │ │ │ ├── index.vue │ │ │ │ └── route.js │ │ │ ├── internal │ │ │ │ ├── admin │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── api │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── appConfig │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── banner │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── dict │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── dictCategory │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── feedback │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── login │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── loginLog │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── mailLog │ │ │ │ │ ├── components │ │ │ │ │ │ └── sendMailDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── menu │ │ │ │ │ ├── components │ │ │ │ │ │ ├── editDataDrawer.vue │ │ │ │ │ │ └── editMenuDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── news │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── notice │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ ├── readme.md │ │ │ │ ├── role │ │ │ │ │ ├── components │ │ │ │ │ │ └── editDataDrawer.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ │ └── user │ │ │ │ │ ├── index.vue │ │ │ │ │ └── route.js │ │ │ └── t2 │ │ │ │ ├── index.vue │ │ │ │ └── route.js │ │ ├── plugins │ │ │ ├── http.js │ │ │ ├── i18n.js │ │ │ ├── router.js │ │ │ └── storage.js │ │ ├── stores │ │ │ └── useGlobal.js │ │ ├── styles │ │ │ ├── global.scss │ │ │ ├── internal.scss │ │ │ └── variable.scss │ │ └── utils │ │ │ ├── index.js │ │ │ └── internal.js │ ├── uno.config.js │ └── yite.config.js ├── yiapi │ ├── LICENSE │ ├── apis │ │ ├── admin │ │ │ ├── _meta.js │ │ │ ├── api.js │ │ │ ├── delete.js │ │ │ ├── insert.js │ │ │ ├── login.js │ │ │ ├── menu.js │ │ │ ├── select.js │ │ │ └── update.js │ │ ├── api │ │ │ ├── _meta.js │ │ │ ├── select.js │ │ │ └── selectAll.js │ │ ├── dict │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ ├── detail.js │ │ │ ├── insert.js │ │ │ ├── select.js │ │ │ ├── selectAll.js │ │ │ └── update.js │ │ ├── dictCategory │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ ├── insert.js │ │ │ ├── select.js │ │ │ ├── selectAll.js │ │ │ └── update.js │ │ ├── loginLog │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ └── select.js │ │ ├── mailLog │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ └── select.js │ │ ├── menu │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ ├── insert.js │ │ │ ├── select.js │ │ │ ├── selectAll.js │ │ │ └── update.js │ │ ├── role │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ ├── insert.js │ │ │ ├── select.js │ │ │ ├── selectAll.js │ │ │ └── update.js │ │ ├── tool │ │ │ ├── _meta.js │ │ │ ├── getOnline.js │ │ │ ├── sendMail.js │ │ │ ├── setOnline.js │ │ │ └── tokenCheck.js │ │ ├── tree │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ ├── insert.js │ │ │ ├── select.js │ │ │ ├── selectAll.js │ │ │ └── update.js │ │ ├── upload │ │ │ ├── _meta.js │ │ │ └── local.js │ │ ├── user │ │ │ ├── _meta.js │ │ │ ├── detail.js │ │ │ ├── emailModifyPassword.js │ │ │ ├── emailPassLogin.js │ │ │ ├── emailRegister.js │ │ │ ├── emailVerifyBind.js │ │ │ ├── emailVerifyLogin.js │ │ │ ├── select.js │ │ │ └── update.js │ │ └── weixin │ │ │ ├── _meta.js │ │ │ ├── code2Session.js │ │ │ ├── getConfig.js │ │ │ ├── getJsapiTicket.js │ │ │ ├── loginCheck.js │ │ │ ├── loginQrcode.js │ │ │ ├── message.js │ │ │ ├── payCheck.js │ │ │ ├── payNotify.js │ │ │ ├── payQrcode.js │ │ │ └── phoneInfo.js │ ├── bootstrap │ │ ├── auth.js │ │ ├── cors.js │ │ ├── cron.js │ │ ├── mail.js │ │ ├── mysql.js │ │ ├── rate.js │ │ ├── redis.js │ │ ├── syncApi.js │ │ ├── syncDev.js │ │ ├── syncMenu.js │ │ ├── tool.js │ │ ├── upload.js │ │ └── xmlParse.js │ ├── check.js │ ├── config │ │ ├── app.js │ │ ├── blackApis.js │ │ ├── blackMenus.js │ │ ├── cache.js │ │ ├── callback.js │ │ ├── cron.js │ │ ├── freeApis.js │ │ ├── http.js │ │ ├── jwt.js │ │ ├── logFilter.js │ │ ├── mail.js │ │ ├── menu.js │ │ ├── mysql.js │ │ ├── payment.js │ │ ├── product.js │ │ ├── rate.js │ │ ├── redis.js │ │ ├── role.js │ │ ├── schemaHelper.js │ │ ├── secondTime.js │ │ ├── tableExt.js │ │ ├── upload.js │ │ ├── weixin.js │ │ └── whiteApis.js │ ├── fn.js │ ├── note.md │ ├── package.json │ ├── plugins │ │ ├── jwt.js │ │ ├── logger.js │ │ └── swagger.js │ ├── readme.md │ ├── schema │ │ ├── app.js │ │ ├── blackApis.js │ │ ├── blackMenus.js │ │ ├── cache.js │ │ ├── callback.js │ │ ├── cron.js │ │ ├── freeApis.js │ │ ├── http.js │ │ ├── jwt.js │ │ ├── logFilter.js │ │ ├── mail.js │ │ ├── menu.js │ │ ├── mysql.js │ │ ├── payment.js │ │ ├── product.js │ │ ├── rate.js │ │ ├── redis.js │ │ ├── role.js │ │ ├── schemaHelper.js │ │ ├── secondTime.js │ │ ├── table.js │ │ ├── tableExt.js │ │ ├── upload.js │ │ ├── weixin.js │ │ └── whiteApis.js │ ├── scripts │ │ └── syncMysql.js │ ├── system.js │ ├── tables │ │ ├── admin.js │ │ ├── api.js │ │ ├── appConfig.js │ │ ├── dict.js │ │ ├── dictCategory.js │ │ ├── loginLog.js │ │ ├── mailLog.js │ │ ├── menu.js │ │ ├── payOrder.js │ │ ├── role.js │ │ ├── tree.js │ │ └── user.js │ ├── todo.md │ ├── utils │ │ ├── fnApiCheck.js │ │ ├── fnApiInfo.js │ │ ├── fnApiPath.js │ │ ├── fnApiRaw.js │ │ ├── fnApiSign.js │ │ ├── fnClearEmpty.js │ │ ├── fnDbInsert.js │ │ ├── fnDbUpdate.js │ │ ├── fnHashSign.js │ │ ├── fnImportAbsolutePath.js │ │ ├── fnImportAppConfig.js │ │ ├── fnImportCoreConfig.js │ │ ├── fnImportCoreSchema.js │ │ ├── fnIncrUID.js │ │ ├── fnLuhn.js │ │ ├── fnPureMD5.js │ │ ├── fnRandom6Number.js │ │ ├── fnRelativePath.js │ │ ├── fnRepairEmpty.js │ │ ├── fnRoute.js │ │ ├── fnRouterPath.js │ │ ├── fnRsaSha256.js │ │ ├── fnSaltMD5.js │ │ ├── fnSchema.js │ │ ├── fnUUID.js │ │ ├── getCacheName.js │ │ ├── getDbFields.js │ │ ├── isPortOpen.js │ │ └── wxPay.js │ └── yiapi.js ├── yibase │ ├── .gitignore │ ├── .npmignore │ ├── .prettierrc │ ├── LICENSE │ ├── index.html │ ├── jsconfig.json │ ├── package.json │ ├── public │ │ └── logo.png │ ├── readme.md │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ └── logo.png │ │ ├── components │ │ │ └── .gitkeep │ │ ├── config │ │ │ └── .gitkeep │ │ ├── env │ │ │ ├── .env │ │ │ ├── .env.development │ │ │ └── .env.production │ │ ├── i18n │ │ │ ├── en.json │ │ │ └── zh.json │ │ ├── layouts │ │ │ ├── default │ │ │ │ └── index.vue │ │ │ └── other │ │ │ │ └── index.vue │ │ ├── main.js │ │ ├── pages │ │ │ ├── index │ │ │ │ ├── components │ │ │ │ │ └── t1.vue │ │ │ │ ├── index.vue │ │ │ │ └── route.js │ │ │ └── news │ │ │ │ ├── index.vue │ │ │ │ └── route.js │ │ ├── plugins │ │ │ ├── http.js │ │ │ ├── i18n.js │ │ │ ├── router.js │ │ │ └── storage.js │ │ ├── stores │ │ │ └── useGlobal.js │ │ ├── styles │ │ │ ├── global.scss │ │ │ └── variable.scss │ │ └── utils │ │ │ └── index.js │ ├── uno.config.js │ └── yite.config.js ├── yidocs │ ├── .vitepress │ │ ├── config.js │ │ └── theme │ │ │ ├── components │ │ │ └── homeMore.vue │ │ │ ├── index.js │ │ │ └── style │ │ │ └── custom.css │ ├── index.js │ ├── markdown │ │ ├── 9-关于我们 │ │ │ └── 1-关于我们 │ │ │ │ ├── 1-个人介绍.md │ │ │ │ └── 2-微信群守则.md │ │ ├── index.md │ │ └── public │ │ │ ├── favicon.ico │ │ │ ├── index.js │ │ │ ├── logo.jpg │ │ │ ├── logo.png │ │ │ ├── logo │ │ │ ├── bimostyle.png │ │ │ ├── fnMap.png │ │ │ ├── hello-iam.png │ │ │ ├── markdown-style.png │ │ │ ├── my-service.png │ │ │ ├── npm-nice.png │ │ │ ├── open-source.png │ │ │ └── yitodo.png │ │ │ ├── logo2.png │ │ │ ├── logo3.png │ │ │ ├── logo4.png │ │ │ └── logo5.png │ ├── package.json │ └── readme.md ├── yidocsAuto │ ├── .gitignore │ ├── .npmignore │ ├── LICENSE │ ├── assets │ │ ├── 1.png │ │ └── 2.png │ ├── index.js │ ├── package.json │ └── readme.md ├── yiserver │ ├── .gitignore │ ├── .npmignore │ ├── .prettierrc │ ├── LICENSE │ ├── README.md │ ├── apis │ │ ├── admin │ │ │ ├── _meta.js │ │ │ └── delete2.js │ │ └── example │ │ │ ├── _meta.js │ │ │ ├── delete.js │ │ │ ├── detail.js │ │ │ ├── insert.js │ │ │ ├── select.js │ │ │ └── update.js │ ├── config │ │ ├── app.js │ │ ├── blackApis.js │ │ ├── blackMenus.js │ │ ├── callback.js │ │ ├── cron.js │ │ ├── custom.js │ │ ├── dbField.js │ │ ├── freeApis.js │ │ ├── http.js │ │ ├── jwt.js │ │ ├── key.js │ │ ├── logFilter.js │ │ ├── mail.js │ │ ├── menu.js │ │ ├── mysql.js │ │ ├── payment.js │ │ ├── product.js │ │ ├── rate.js │ │ ├── redis.js │ │ ├── role.js │ │ ├── schemaField.js │ │ ├── secondTime.js │ │ ├── tableExt.js │ │ ├── upload.js │ │ ├── weixin.js │ │ └── whiteApis.js │ ├── env │ │ ├── .development.env │ │ └── .production.env │ ├── nodemon.json │ ├── package.json │ ├── plugins │ │ └── .gitkeep │ ├── pm2.config.cjs │ ├── public │ │ └── .gitkeep │ ├── scripts │ │ └── syncMysql.js │ ├── tables │ │ └── example.js │ └── yiapi.js └── yite-cli │ ├── LICENSE │ ├── bin.js │ ├── index.js │ ├── jsconfig.json │ ├── libs │ └── minimist.js │ ├── package.json │ ├── plugins │ ├── i18n.js │ └── router.js │ ├── readme.md │ ├── scripts │ ├── build.js │ ├── dev.js │ └── update.js │ ├── todo.md │ ├── utils.js │ └── vite.config.js ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | esdata 6 | data 7 | .cache 8 | lab 9 | labs 10 | cache 11 | .VSCodeCounter 12 | oclif.manifest.json 13 | dist 14 | report.html 15 | dist-ssr 16 | *.local 17 | .vscode-test/ 18 | *.vsix 19 | out 20 | CHANGELOG.md 21 | .changeset 22 | others/softs 23 | other.md 24 | 25 | # Editor directories and files 26 | .vscode/* 27 | .cache 28 | .yicode/auto-imports.d.ts 29 | !.vscode/extensions.json 30 | .idea 31 | .DS_Store 32 | *.suo 33 | *.ntvs* 34 | *.njsproj 35 | *.sln 36 | *.sw? 37 | 38 | # Runtime data 39 | pids 40 | *.pid 41 | *.seed 42 | 43 | # Directory for instrumented libs generated by jscoverage/JSCover 44 | lib-cov 45 | 46 | # Coverage directory used by tools like istanbul 47 | coverage 48 | 49 | # nyc test coverage 50 | .nyc_output 51 | 52 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 53 | .grunt 54 | 55 | # node-waf configuration 56 | .lock-wscript 57 | 58 | # Compiled binary addons (http://nodejs.org/api/addons.html) 59 | build/Release 60 | 61 | # Dependency directories 62 | node_modules 63 | jspm_packages 64 | 65 | # Optional npm cache directory 66 | .npm 67 | 68 | # Optional REPL history 69 | .node_repl_history 70 | 71 | # 0x 72 | profile-* 73 | 74 | # mac files 75 | .DS_Store 76 | 77 | # vim swap files 78 | *.swp 79 | 80 | # webstorm 81 | .idea 82 | 83 | # vscode 84 | .vscode 85 | *code-workspace 86 | 87 | # clinic 88 | profile* 89 | *clinic* 90 | *flamegraph* 91 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | labs 4 | .vscode -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmmirror.com 2 | # registry=https://registry.npmjs.org 3 | SHARP_BINARY_HOST=https://npmmirror.com/mirrors/sharp 4 | SHARP_LIBVIPS_BINARY_HOST=https://npmmirror.com/mirrors/sharp-libvips 5 | 6 | # pnpm publish --access public --no-git-checks -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | libs 2 | pnpm-lock.yaml -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 1024, 7 | "bracketSpacing": true, 8 | "useTabs": false, 9 | "arrowParens": "always" 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "version": "0.0.2", 4 | "private": true, 5 | "type": "module", 6 | "publishConfig": { 7 | "access": "restricted" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/chenbimo/yicode.git" 12 | }, 13 | "description": "随易科技(yicode.tech) - 软件开发生态", 14 | "homepage": "https://chensuiyi.me", 15 | "main": "index.js", 16 | "scripts": { 17 | "r": "pnpm -r --no-git-checks publish" 18 | }, 19 | "keywords": [ 20 | "yicode", 21 | "cli", 22 | "webpack", 23 | "vite", 24 | "vue", 25 | "vue2", 26 | "vue3", 27 | "nodejs" 28 | ], 29 | "author": "chensuiyi ", 30 | "devDependencies": { 31 | "@commitlint/cli": "^19.3.0", 32 | "@yicode/commit-lint": "^1.1.7", 33 | "lint-staged": "^15.2.7", 34 | "prettier": "^3.3.3", 35 | "rollup": "^4.19.1", 36 | "simple-git-hooks": "^2.11.1" 37 | }, 38 | "simple-git-hooks": { 39 | "commit-msg": "pnpm commitlint --edit ${1}", 40 | "pre-commit": "pnpm lint-staged" 41 | }, 42 | "lint-staged": { 43 | "*.{js,css,scss,less,ts,jsx,vue,html,json,md,yaml}": "prettier --write" 44 | }, 45 | "commitlint": { 46 | "extends": [ 47 | "@yicode/commit-lint" 48 | ] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/commitLint/.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "release-it-pnpm": { 4 | "disableRelease": true 5 | } 6 | }, 7 | "npm": { 8 | "publish": true, 9 | "publishPath": ".", 10 | "publishArgs": [], 11 | "tag": null, 12 | "otp": null, 13 | "ignoreVersion": false, 14 | "allowSameVersion": false, 15 | "versionArgs": [], 16 | "skipChecks": true, 17 | "timeout": 30 18 | }, 19 | "git": { 20 | "changelog": false, 21 | "commit": true, 22 | "commitMessage": "发布版本:${version}", 23 | "tag": false, 24 | "push": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/commitLint/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserPreset: { 3 | parserOpts: { 4 | headerPattern: /^(.*?)(?:\((.*)\))?: (.*)$/, 5 | headerCorrespondence: ['type', 'scope', 'subject'] 6 | } 7 | }, 8 | rules: { 9 | // 头部 10 | 'header-case': [0], 11 | 'header-full-stop': [2, 'never', '.'], 12 | // 身体 13 | 'body-full-stop': [2, 'never', '.'], 14 | 'body-leading-blank': [2, 'always'], 15 | 'body-case': [0], 16 | // 尾部 17 | 'footer-leading-blank': [2, 'always'], 18 | 'footer-min-length': [2, 'always', 0], 19 | // 作用域 20 | 'scope-case': [0], 21 | // 主题 22 | 'subject-case': [0, 'never'], 23 | 'subject-empty': [2, 'never'], 24 | 'subject-full-stop': [2, 'never', '.'], 25 | 'subject-exclamation-mark': [0], 26 | // 类型 27 | 'type-case': [0], 28 | 'type-empty': [2, 'never'], 29 | 'type-enum': [ 30 | 2, 31 | 'always', 32 | [ 33 | // 新增 34 | '新增项目', 35 | '新增文件', 36 | '新增功能', 37 | // 更新 38 | '升级依赖', 39 | '更新文档', 40 | // 风格 41 | '调整风格', 42 | '美化界面', 43 | // 优化 44 | '优化体验', 45 | '完善功能', 46 | '优化性能', 47 | '重构代码', 48 | // 修复 49 | '修复问题', 50 | // 奇想 51 | '埋下彩蛋', 52 | '思考计划', 53 | // 发布 54 | '打包构建', 55 | '发布版本', 56 | // 流程 57 | '回退复原', 58 | '持续集成', 59 | '检测测试', 60 | // 配置 61 | '调整配置', 62 | // 临时 63 | '暂存代码' 64 | ] 65 | ] 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /packages/commitLint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/commit-lint", 3 | "version": "1.1.7", 4 | "description": "git 提交信息校验", 5 | "type": "commonjs", 6 | "main": "index.js", 7 | "private": false, 8 | "publishConfig": { 9 | "access": "public", 10 | "registry": "https://registry.npmjs.org" 11 | }, 12 | "scripts": {}, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/chenbimo/commit-lint" 16 | }, 17 | "homepage": "https://chensuiyi.me", 18 | "keywords": [ 19 | "vite", 20 | "vue.js", 21 | "vue-cli", 22 | "webpack", 23 | "cli", 24 | "vue", 25 | "web", 26 | "qrcode" 27 | ], 28 | "author": "chensuiyi ", 29 | "devDependencies": {} 30 | } 31 | -------------------------------------------------------------------------------- /packages/commitLint/readme.md: -------------------------------------------------------------------------------- 1 | # @yicode/commit-lint 2 | 3 | yicode 生态专用 git 提交信息格式验证工具 4 | -------------------------------------------------------------------------------- /packages/dlnpm/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | esdata 6 | data 7 | .cache 8 | lab 9 | labs 10 | cache 11 | .VSCodeCounter 12 | oclif.manifest.json 13 | dist 14 | report.html 15 | dist-ssr 16 | *.local 17 | .vscode-test/ 18 | *.vsix 19 | out 20 | CHANGELOG.md 21 | .changeset 22 | others/softs 23 | other.md 24 | 25 | # Editor directories and files 26 | .vscode/* 27 | .cache 28 | .yicode/auto-imports.d.ts 29 | !.vscode/extensions.json 30 | .idea 31 | .DS_Store 32 | *.suo 33 | *.ntvs* 34 | *.njsproj 35 | *.sln 36 | *.sw? 37 | 38 | # Runtime data 39 | pids 40 | *.pid 41 | *.seed 42 | 43 | # Directory for instrumented libs generated by jscoverage/JSCover 44 | lib-cov 45 | 46 | # Coverage directory used by tools like istanbul 47 | coverage 48 | 49 | # nyc test coverage 50 | .nyc_output 51 | 52 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 53 | .grunt 54 | 55 | # node-waf configuration 56 | .lock-wscript 57 | 58 | # Compiled binary addons (http://nodejs.org/api/addons.html) 59 | build/Release 60 | 61 | # Dependency directories 62 | node_modules 63 | jspm_packages 64 | 65 | # Optional npm cache directory 66 | .npm 67 | 68 | # Optional REPL history 69 | .node_repl_history 70 | 71 | # 0x 72 | profile-* 73 | 74 | # mac files 75 | .DS_Store 76 | 77 | # vim swap files 78 | *.swp 79 | 80 | # webstorm 81 | .idea 82 | 83 | # vscode 84 | .vscode 85 | *code-workspace 86 | 87 | # clinic 88 | profile* 89 | *clinic* 90 | *flamegraph* 91 | -------------------------------------------------------------------------------- /packages/dlnpm/.npmignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | labs 4 | .vscode -------------------------------------------------------------------------------- /packages/dlnpm/.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmmirror.com 2 | # registry=https://registry.npmjs.org 3 | SHARP_BINARY_HOST=https://npmmirror.com/mirrors/sharp 4 | SHARP_LIBVIPS_BINARY_HOST=https://npmmirror.com/mirrors/sharp-libvips -------------------------------------------------------------------------------- /packages/dlnpm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/dlnpm", 3 | "version": "1.4.1", 4 | "description": "dlnpm - npm包下载工具", 5 | "author": "chensuiyi ", 6 | "bin": { 7 | "dlnpm": "dlnpm.js" 8 | }, 9 | "type": "module", 10 | "homepage": "https://chensuiyi.me", 11 | "scripts": {}, 12 | "engines": {}, 13 | "keywords": [ 14 | "npm", 15 | "download", 16 | "package", 17 | "npmjs" 18 | ], 19 | "private": false, 20 | "publishConfig": { 21 | "access": "public", 22 | "registry": "https://registry.npmjs.org" 23 | }, 24 | "main": "dlnpm.js", 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/chenbimo/yicode.git" 28 | }, 29 | "files": [ 30 | "readme.md", 31 | "package.json", 32 | "LICENSE", 33 | "dlnpm.js", 34 | ".npmrc", 35 | ".gitignore", 36 | ".npmignore" 37 | ], 38 | "dependencies": { 39 | "@inquirer/prompts": "^5.3.4", 40 | "got": "^14.4.2", 41 | "log-symbols": "^6.0.0", 42 | "pacote": "^18.0.6" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/dlnpm/readme.md: -------------------------------------------------------------------------------- 1 | # dlnpm - (download npm)- 下载 npm 包 2 | 3 | 作者:[陈随易 https://chensuiyi.me](https://chensuiyi.me) 4 | 5 | ## 用途 6 | 7 | 下载对应的 `npm` 资源到当前目录的 `npm-package` 目录下,而不是通过 `npm install` 安装的方式下载到 `node_modules` 目录下。 8 | 9 | 将代码、模板、项目托管到 `npm` 仓库中,使用本工具下载对应资源,解决需要自行搭建下载服务器、购买带宽、购买存储等问题。 10 | 11 | ## 使用 12 | 13 | 全局安装 `dlnpm` 包。 14 | 15 | 注: 16 | 17 | - 随易科技 `编程开发` 包均已 `@yicode` 为前缀 18 | - 随易科技 `完整项目` 包均已 `@yicode-project` 为前缀 19 | - 随易科技 `模板案例` 包均已 `@yicode-template` 为前缀 20 | 21 | ```bash 22 | pnpm add -g @yicode/dlnpm 23 | ``` 24 | 25 | 安装完毕后,直接在命令行输入 `dlnpm` 并回车,按提示操作即可。 26 | 27 | ```bash 28 | > dlnpm 29 | 30 | ℹ 开发者:随易科技(https://yicode.tech) 31 | ----------------------------------------- 32 | ? 选择下载类型 官方资源 33 | ? 选择从哪里下载 淘宝仓库 - npmmirror.com 34 | ? 选择要下载的包 yite + vue3 基础项目开发模板 35 | ? 输入要下载的版本(默认下载最新版本) latest 36 | ✔ 资源已下载到默认的 npm-package 目录,请移动到正确的目录! 37 | ``` 38 | 39 | ## 其他 40 | 41 | 本包提供 `2` 种 `npm` 资源包下载体验形式 42 | 43 | 1. 随易科技官方 `npm` 资源包(使用选择包名方式,简单方便) 44 | 2. 其他任意 `npm` 资源包(使用输入包名的方式,下载任意资源) 45 | 46 | ## 赞赏作者 47 | 48 | ![赞赏](https://static.yicode.tech/images/zan-shang.jpg) 49 | -------------------------------------------------------------------------------- /packages/gitlook/README.md: -------------------------------------------------------------------------------- 1 | # gitlook 2 | 3 | git 命令行项目提交统计查看工具 4 | 5 | # 安装工具 6 | 7 | 安装 gitlook 8 | 9 | ```bash 10 | npm install -g @yicode/gitlook 11 | ``` 12 | 13 | # 查看 git 统计 14 | 15 | ![picture 3](https://s2.loli.net/2022/09/16/BG2xSwbeVLaYJ1u.png) 16 | 17 | 开源仓库地址 18 | 19 | [gitee - https://gitee.com/chenbimo/yicode](https://gitee.com/chenbimo/yicode) 20 | 21 | [github - https://github.com/chenbimo/yicode](https://github.com/chenbimo/yicode) 22 | 23 | ## 概述说明 24 | 25 | `gitlook` 是一个用于增强开发体验和效率的工具库集合,旨在给开发者,带来方便。 26 | 27 | ## 使用声明 28 | 29 | > 本项目使用 Apache 2.0 协议开源,可免费无偿使用及商用,需保留原作者版权信息。 30 | 31 | ## 社区交流 32 | 33 | 项目相关讨论交流,请添加作者微信 `chensuiyime` 入群。 34 | -------------------------------------------------------------------------------- /packages/gitlook/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import path from 'path'; 3 | import { select } from '@inquirer/prompts'; 4 | 5 | import { statistics } from './scripts/statistics.js'; 6 | 7 | // 提示参数收集 8 | const promptParams = { 9 | // 执行命令 10 | executeCommand: 'statistics' 11 | }; 12 | 13 | async function gitlookPrompt() { 14 | promptParams.executeCommand = await select({ 15 | message: '请选择一个命令', 16 | loop: false, 17 | default: promptParams.executeCommand, 18 | choices: [ 19 | { 20 | name: '数据统计', 21 | value: 'statistics', 22 | describe: '数据提交统计' 23 | } 24 | ] 25 | }); 26 | 27 | if (promptParams.executeCommand === 'statistics') { 28 | await statistics(promptParams); 29 | } 30 | } 31 | 32 | gitlookPrompt(); 33 | -------------------------------------------------------------------------------- /packages/gitlook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/gitlook", 3 | "version": "1.3.0", 4 | "description": "gitlook - 命令行 git 提交数据统计查看工具", 5 | "main": "index.js", 6 | "bin": { 7 | "gitlook": "index.js" 8 | }, 9 | "type": "module", 10 | "private": false, 11 | "publishConfig": { 12 | "access": "public", 13 | "registry": "https://registry.npmjs.org" 14 | }, 15 | "scripts": {}, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/chenbimo/yicode.git" 19 | }, 20 | "keywords": [ 21 | "yicode", 22 | "cli", 23 | "git", 24 | "nodejs", 25 | "javascript", 26 | "脚手架" 27 | ], 28 | "files": [ 29 | "scripts/", 30 | "index.js", 31 | "LICENSE", 32 | "package.json", 33 | "README.md" 34 | ], 35 | "homepage": "https://chensuiyi.me", 36 | "author": "chensuiyi ", 37 | "dependencies": { 38 | "@inquirer/prompts": "^5.3.4", 39 | "cli-table3": "^0.6.5", 40 | "dayjs": "^1.11.12", 41 | "lodash-es": "^4.17.21", 42 | "ora": "^8.0.1", 43 | "simple-git": "^3.25.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/tnbc/README.md: -------------------------------------------------------------------------------- 1 | # tnb(taobao npmrc binary)淘宝NPM配置二进制下载地址 2 | 3 | 全局安装后,执行 `tnb` 回车即可。 4 | 5 | ## 参考 6 | 7 | - https://github.com/cnpm/binary-mirror-config 8 | -------------------------------------------------------------------------------- /packages/tnbc/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import url from 'node:url'; 3 | import { join } from 'node:path'; 4 | import { env, platform } from 'node:process'; 5 | import { readFileSync, writeFileSync } from 'node:fs'; 6 | 7 | // 配置处理包 8 | import { parse as ini_parse, stringify as ini_stringify } from 'ini'; 9 | import { ensureFileSync } from 'fs-extra/esm'; 10 | import logSymbols from 'log-symbols'; 11 | 12 | // NPM 配置地址 13 | const npmrc = join(env[platform === 'win32' ? 'USERPROFILE' : 'HOME'], '.npmrc'); 14 | 15 | // 镜像地址 16 | const taobaoMirror = 'https://npmmirror.com/mirrors/'; 17 | 18 | // 包映射 19 | const packageMap = { 20 | SHARP_BINARY_HOST: `${taobaoMirror}sharp/`, 21 | SHARP_LIBVIPS_BINARY_HOST: `${taobaoMirror}sharp-libvips/`, 22 | CHROMEDRIVER_CDNURL: `${taobaoMirror}chromedriver/`, 23 | ELECTRON_MIRROR: `${taobaoMirror}electron/`, 24 | ELECTRON_CUSTOM_DIR: `{{ version }}`, 25 | ELECTRON_SKIP_BINARY_DOWNLOAD: 1, 26 | SASS_BINARY_SITE: `${taobaoMirror}node-sass` 27 | }; 28 | 29 | // 获取当前npmrc配置 30 | const mainFun = () => { 31 | ensureFileSync(npmrc); 32 | const fileData = readFileSync(npmrc, 'utf-8'); 33 | const fileConfig = ini_parse(fileData); 34 | const fileKeys = Object.keys(fileConfig).map((name) => name.toUpperCase()); 35 | let newFileConfig = {}; 36 | for (let key in fileConfig) { 37 | let keyUpper = key.toUpperCase(); 38 | if (packageMap[keyUpper]) { 39 | newFileConfig[keyUpper] = packageMap[keyUpper]; 40 | } else { 41 | newFileConfig[key] = fileConfig[key]; 42 | } 43 | } 44 | writeFileSync(npmrc, ini_stringify(newFileConfig)); 45 | console.log(`${logSymbols.success} NPM二进制下载链接设置成功`); 46 | }; 47 | 48 | mainFun(); 49 | -------------------------------------------------------------------------------- /packages/tnbc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/tnbc", 3 | "version": "1.3.0", 4 | "description": "淘宝NPM配置二进制下载地址", 5 | "type": "module", 6 | "bin": { 7 | "tbn": "index.js" 8 | }, 9 | "private": false, 10 | "publishConfig": { 11 | "access": "public", 12 | "registry": "https://registry.npmjs.org" 13 | }, 14 | "exports": { 15 | ".": "./index.js" 16 | }, 17 | "scripts": {}, 18 | "files": [ 19 | "index.js", 20 | "LICENSE", 21 | "package.json", 22 | "README.md" 23 | ], 24 | "keywords": [ 25 | "fastify", 26 | "nodejs", 27 | "api", 28 | "yiapi" 29 | ], 30 | "author": "chensuiyi ", 31 | "repository": { 32 | "type": "git", 33 | "url": "https://github.com/chenbimo/yicode.git" 34 | }, 35 | "homepage": "https://chensuiyi.me", 36 | "dependencies": { 37 | "colorette": "^2.0.20", 38 | "fs-extra": "^11.2.0", 39 | "ini": "^4.1.3", 40 | "log-symbols": "^6.0.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/yiadmin/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | esdata 6 | data 7 | .npmrc 8 | .cache 9 | lab 10 | labs 11 | cache 12 | .npmrc 13 | .VSCodeCounter 14 | oclif.manifest.json 15 | dist 16 | report.html 17 | dist-ssr 18 | *.local 19 | .vscode-test/ 20 | *.vsix 21 | out 22 | CHANGELOG.md 23 | note.md 24 | .changeset 25 | 26 | # Editor directories and files 27 | .vscode/* 28 | .cache 29 | .yicode/auto-imports.d.ts 30 | !.vscode/extensions.json 31 | .idea 32 | .DS_Store 33 | *.suo 34 | *.ntvs* 35 | *.njsproj 36 | *.sln 37 | *.sw? 38 | 39 | # Runtime data 40 | pids 41 | *.pid 42 | *.seed 43 | 44 | # Directory for instrumented libs generated by jscoverage/JSCover 45 | lib-cov 46 | 47 | # Coverage directory used by tools like istanbul 48 | coverage 49 | 50 | # nyc test coverage 51 | .nyc_output 52 | 53 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 54 | .grunt 55 | 56 | # node-waf configuration 57 | .lock-wscript 58 | 59 | # Compiled binary addons (http://nodejs.org/api/addons.html) 60 | build/Release 61 | 62 | # Dependency directories 63 | node_modules 64 | jspm_packages 65 | 66 | # Optional npm cache directory 67 | .npm 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # 0x 73 | profile-* 74 | 75 | # mac files 76 | .DS_Store 77 | 78 | # vim swap files 79 | *.swp 80 | 81 | # webstorm 82 | .idea 83 | 84 | # vscode 85 | .vscode 86 | *code-workspace 87 | 88 | # clinic 89 | profile* 90 | *clinic* 91 | *flamegraph* 92 | -------------------------------------------------------------------------------- /packages/yiadmin/.npmignore: -------------------------------------------------------------------------------- 1 | dist 2 | .cache 3 | CHANGELOG.md -------------------------------------------------------------------------------- /packages/yiadmin/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 1024, 7 | "bracketSpacing": true, 8 | "useTabs": false, 9 | "arrowParens": "always" 10 | } 11 | -------------------------------------------------------------------------------- /packages/yiadmin/README.md: -------------------------------------------------------------------------------- 1 | ## yiadmin(易管理) 2 | 3 | 跟 `yiapi(易接口)` 配套的后台管理模板。 4 | -------------------------------------------------------------------------------- /packages/yiadmin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 易管理 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/yiadmin/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "baseUrl": "./", 6 | "paths": { 7 | "@/*": ["src/*"] 8 | } 9 | }, 10 | "exclude": ["node_modules", "dist"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/yiadmin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/yiadmin", 3 | "version": "1.4.3", 4 | "description": "前后分离的 vue3 + vite + yite-cli 后台管理模板", 5 | "sideEffects": true, 6 | "type": "module", 7 | "private": false, 8 | "publishConfig": { 9 | "access": "public", 10 | "registry": "https://registry.npmjs.org" 11 | }, 12 | "scripts": { 13 | "dev": "yite --command=dev --envfile=development --workdir=./", 14 | "build": "yite --command=build --envfile=production --workdir=./", 15 | "update:template": "yite --command=update --project-type=yiadmin" 16 | }, 17 | "keywords": [ 18 | "lodash", 19 | "utils", 20 | "helper", 21 | "help" 22 | ], 23 | "author": "chensuiyi ", 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/chenbimo/yicode.git" 27 | }, 28 | "homepage": "https://chensuiyi.me", 29 | "dependencies": { 30 | "@arco-design/web-vue": "^2.56.0", 31 | "@arco-plugins/vite-vue": "^1.4.5", 32 | "@iconify/json": "^2.2.232", 33 | "@yicode/yidash": "^3.9.0", 34 | "axios": "^1.7.2", 35 | "date-fns": "^3.6.0", 36 | "js-md5": "^0.8.3", 37 | "lodash-es": "^4.17.21", 38 | "pinia": "^2.2.0", 39 | "sass": "^1.77.8", 40 | "store2": "^2.14.3", 41 | "vue": "^3.4.34", 42 | "vue-i18n": "^9.13.1", 43 | "vue-router": "^4.4.0" 44 | }, 45 | "devDependencies": { 46 | "@yicode/yite-cli": "^2.8.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/yiadmin/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiadmin/public/logo.png -------------------------------------------------------------------------------- /packages/yiadmin/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /packages/yiadmin/src/assets/login-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiadmin/src/assets/login-back.png -------------------------------------------------------------------------------- /packages/yiadmin/src/assets/login-left-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiadmin/src/assets/login-left-image.png -------------------------------------------------------------------------------- /packages/yiadmin/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiadmin/src/assets/logo.png -------------------------------------------------------------------------------- /packages/yiadmin/src/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiadmin/src/components/.gitkeep -------------------------------------------------------------------------------- /packages/yiadmin/src/config/app.js: -------------------------------------------------------------------------------- 1 | export const $AppConfig = { 2 | name: '随易科技' 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yiadmin/src/config/internal.js: -------------------------------------------------------------------------------- 1 | export const $InternalConfig = { 2 | // 用户令牌 3 | token: $Storage.local.get('token') || '', 4 | // 用户数据 5 | userData: $Storage.local.get('userData') || {}, 6 | // 表格边框 7 | tableBordered: { 8 | cell: true 9 | }, 10 | // 表格滚动 11 | tableScroll: { 12 | x: '100%', 13 | y: '100%', 14 | maxHeight: '100%' 15 | }, 16 | // 抽屉默认宽度 17 | drawerWidth: 400, 18 | // 每页显示数量 19 | pageLimit: 30 20 | }; 21 | -------------------------------------------------------------------------------- /packages/yiadmin/src/env/.env.development: -------------------------------------------------------------------------------- 1 | VITE_HOST="http://127.0.0.1:3000/api" 2 | VITE_NAMESPACE="dev.yiadmin" -------------------------------------------------------------------------------- /packages/yiadmin/src/env/.env.production: -------------------------------------------------------------------------------- 1 | VITE_HOST="https://127.0.0.1:3000/api" 2 | VITE_NAMESPACE="pro.yiadmin" -------------------------------------------------------------------------------- /packages/yiadmin/src/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test" 3 | } 4 | -------------------------------------------------------------------------------- /packages/yiadmin/src/i18n/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "测试" 3 | } 4 | -------------------------------------------------------------------------------- /packages/yiadmin/src/layouts/default/components/sideMenu.vue: -------------------------------------------------------------------------------- 1 | 12 | 45 | -------------------------------------------------------------------------------- /packages/yiadmin/src/main.js: -------------------------------------------------------------------------------- 1 | import App from '@/App.vue'; 2 | 3 | const app = createApp(App); 4 | 5 | const $Pinia = Pinia.createPinia(); 6 | 7 | app.use($Router); 8 | app.use($Pinia); 9 | app.use($I18n); 10 | 11 | app.mount('#app'); 12 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/index/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 30 | 31 | 35 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/index/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/admin/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/api/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/appConfig/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/banner/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/dict/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/dictCategory/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/feedback/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/login/route.js: -------------------------------------------------------------------------------- 1 | export default { 2 | layout: false 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/loginLog/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/mailLog/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/menu/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/news/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/notice/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/readme.md: -------------------------------------------------------------------------------- 1 | 此目录下的文件不要改动!!! 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/role/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/internal/user/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/t2/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 30 | 31 | 35 | -------------------------------------------------------------------------------- /packages/yiadmin/src/pages/t2/route.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/plugins/http.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const $Http = axios.create({ 4 | method: 'POST', 5 | baseURL: import.meta.env.VITE_HOST, 6 | timeout: 1000 * 60, 7 | withCredentials: false, 8 | responseType: 'json', 9 | responseEncoding: 'utf8', 10 | headers: {} 11 | }); 12 | // 添加请求拦截器 13 | $Http.interceptors.request.use( 14 | function (config) { 15 | const token = $Storage.local.get('token'); 16 | if (token) { 17 | config.headers.authorization = 'Bearer ' + token; 18 | } 19 | return config; 20 | }, 21 | function (err) { 22 | return Promise.reject(err); 23 | } 24 | ); 25 | 26 | // 添加响应拦截器 27 | $Http.interceptors.response.use( 28 | function (res) { 29 | if (res.data.code === 0) { 30 | return Promise.resolve(res.data); 31 | } 32 | if (res.data.symbol === 'NOT_LOGIN') { 33 | location.href = location.origin + '/#/internal/login'; 34 | } 35 | return Promise.reject(res.data); 36 | }, 37 | function (err) { 38 | return Promise.reject(err); 39 | } 40 | ); 41 | export { $Http }; 42 | -------------------------------------------------------------------------------- /packages/yiadmin/src/plugins/i18n.js: -------------------------------------------------------------------------------- 1 | import { yiteMessages } from 'virtual:yite-messages'; 2 | 3 | const $I18n = createI18n({ 4 | locale: 'zh', 5 | messages: await yiteMessages() 6 | }); 7 | 8 | export { $I18n }; 9 | -------------------------------------------------------------------------------- /packages/yiadmin/src/plugins/router.js: -------------------------------------------------------------------------------- 1 | import { yiteRoutes } from 'virtual:yite-router'; 2 | 3 | // 创建路由 4 | const $Router = createRouter({ 5 | routes: yiteRoutes(), 6 | history: createWebHashHistory() 7 | }); 8 | 9 | export { $Router }; 10 | -------------------------------------------------------------------------------- /packages/yiadmin/src/plugins/storage.js: -------------------------------------------------------------------------------- 1 | import store2 from 'store2'; 2 | const $Storage = store2.namespace(import.meta.env.VITE_NAMESPACE); 3 | 4 | // 提供给手动导入使用 5 | export { $Storage }; 6 | -------------------------------------------------------------------------------- /packages/yiadmin/src/stores/useGlobal.js: -------------------------------------------------------------------------------- 1 | export const useGlobal = Pinia.defineStore('global', () => { 2 | // 全局数据 3 | const $GlobalData = $ref({ 4 | // 内置配置,不要修改 5 | ...$InternalConfig, 6 | appConfig: $AppConfig 7 | }); 8 | 9 | // 全局计算数据 10 | const $GlobalComputed = {}; 11 | 12 | // 全局方法 13 | const $GlobalMethod = {}; 14 | 15 | return { 16 | $GlobalData, 17 | $GlobalComputed, 18 | $GlobalMethod 19 | }; 20 | }); 21 | -------------------------------------------------------------------------------- /packages/yiadmin/src/styles/global.scss: -------------------------------------------------------------------------------- 1 | @import './internal.scss'; 2 | -------------------------------------------------------------------------------- /packages/yiadmin/src/styles/variable.scss: -------------------------------------------------------------------------------- 1 | $layout-wrapper-width: 1200px; 2 | $layout-header-height: 54px; 3 | -------------------------------------------------------------------------------- /packages/yiadmin/src/utils/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiadmin/src/utils/index.js -------------------------------------------------------------------------------- /packages/yiadmin/src/utils/internal.js: -------------------------------------------------------------------------------- 1 | // 获取资源 2 | export function utilInternalAssets(name) { 3 | return new URL(`../assets/${name}`, import.meta.url).href; 4 | } 5 | -------------------------------------------------------------------------------- /packages/yiadmin/uno.config.js: -------------------------------------------------------------------------------- 1 | import { unocssConfig } from '@yicode/yite-cli/unocss.js'; 2 | import { defineConfig } from 'unocss'; 3 | export default defineConfig(unocssConfig); 4 | -------------------------------------------------------------------------------- /packages/yiadmin/yite.config.js: -------------------------------------------------------------------------------- 1 | import { vitePluginForArco } from '@arco-plugins/vite-vue'; 2 | export const yiteConfig = { 3 | devtool: false, 4 | // 自动导入解析 5 | autoImport: { 6 | resolvers: [ 7 | { 8 | name: 'ArcoResolver', 9 | options: {} 10 | } 11 | ], 12 | imports: [ 13 | { 14 | '@arco-design/web-vue': [ 15 | // 16 | 'Message', 17 | 'Modal', 18 | 'Notification', 19 | 'Drawer' 20 | ] 21 | } 22 | ] 23 | }, 24 | // 自动组件解析 25 | autoComponent: { 26 | resolvers: [ 27 | { 28 | name: 'ArcoResolver', 29 | options: { 30 | sideEffect: true 31 | } 32 | } 33 | ] 34 | }, 35 | // webpack 配置 36 | viteConfig: { 37 | plugins: [ 38 | vitePluginForArco({ 39 | style: 'css' 40 | }) 41 | ], 42 | optimizeDeps: { 43 | include: [ 44 | // 45 | 'lodash-es', 46 | 'vue-i18n', 47 | 'js-md5', 48 | 'axios', 49 | '@yicode/yidash', 50 | 'date-fns', 51 | 'date-fns/locale', 52 | 'tiny-cookie', 53 | '@arco-design/web-vue/es/icon', 54 | 'store2', 55 | '@arco-design/web-vue' 56 | ] 57 | } 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /packages/yiapi/apis/admin/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | // 目录名称 3 | dirName: '管理员', 4 | // 接口名称 5 | apiNames: { 6 | api: '查询管理员接口权限', 7 | menu: '查询管理员菜单权限', 8 | login: '管理员登录', 9 | insert: '添加管理员', 10 | delete: '删除管理员', 11 | select: '分页查询管理员', 12 | update: '更新管理员信息' 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /packages/yiapi/apis/admin/api.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | // 配置文件 4 | import { httpConfig } from '../../config/http.js'; 5 | // 接口元数据 6 | import { metaConfig } from './_meta.js'; 7 | 8 | // 处理函数 9 | export default async (fastify) => { 10 | fnRoute(import.meta.url, fastify, metaConfig, { 11 | // 请求参数约束 12 | schemaRequest: { 13 | type: 'object', 14 | properties: {} 15 | }, 16 | // 执行函数 17 | apiHandler: async (req, res) => { 18 | try { 19 | const result = await fastify.getUserApis(req.session); 20 | return { 21 | ...httpConfig.SELECT_SUCCESS, 22 | data: { 23 | rows: result 24 | } 25 | }; 26 | } catch (err) { 27 | fastify.log.error(err); 28 | return httpConfig.SELECT_FAIL; 29 | } 30 | } 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /packages/yiapi/apis/admin/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 接口元数据 8 | import { metaConfig } from './_meta.js'; 9 | 10 | // 处理函数 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | id: fnSchema(schemaHelperConfig.id) 19 | }, 20 | required: ['id'] 21 | }, 22 | // 执行函数 23 | apiHandler: async (req, res) => { 24 | try { 25 | const adminModel = fastify.mysql // 26 | .table('sys_admin') 27 | .where({ id: req.body.id }) 28 | .modify(function (db) {}); 29 | 30 | const adminData = await adminModel.clone().selectOne(['id']); 31 | if (!adminData?.id) { 32 | return httpConfig.NO_DATA; 33 | } 34 | 35 | const result = await adminModel.deleteData(); 36 | 37 | return { 38 | ...httpConfig.DELETE_SUCCESS, 39 | data: result 40 | }; 41 | } catch (err) { 42 | fastify.log.error(err); 43 | return httpConfig.DELETE_FAIL; 44 | } 45 | } 46 | }); 47 | }; 48 | -------------------------------------------------------------------------------- /packages/yiapi/apis/admin/menu.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | // 配置文件 4 | import { httpConfig } from '../../config/http.js'; 5 | // 接口元数据 6 | import { metaConfig } from './_meta.js'; 7 | 8 | // 处理函数 9 | export default async (fastify) => { 10 | // 当前文件的路径,fastify 实例 11 | fnRoute(import.meta.url, fastify, metaConfig, { 12 | // 请求参数约束 13 | schemaRequest: { 14 | type: 'object', 15 | properties: {} 16 | }, 17 | // 执行函数 18 | apiHandler: async (req, res) => { 19 | try { 20 | const result = await fastify.getUserMenus(req.session); 21 | return { 22 | ...httpConfig.SELECT_SUCCESS, 23 | data: { 24 | rows: result 25 | } 26 | }; 27 | } catch (err) { 28 | fastify.log.error(err); 29 | return httpConfig.SELECT_FAIL; 30 | } 31 | } 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/yiapi/apis/admin/update.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | import { fnSaltMD5 } from '../../utils/fnSaltMD5.js'; 5 | // 配置文件 6 | import { httpConfig } from '../../config/http.js'; 7 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 8 | // 数据表格 9 | import { tableData } from '../../tables/admin.js'; 10 | // 接口元数据 11 | import { metaConfig } from './_meta.js'; 12 | 13 | // 处理函数 14 | export default async (fastify) => { 15 | // 当前文件的路径,fastify 实例 16 | fnRoute(import.meta.url, fastify, metaConfig, { 17 | // 请求参数约束 18 | schemaRequest: { 19 | type: 'object', 20 | properties: { 21 | id: fnSchema(schemaHelperConfig.id), 22 | password: fnSchema(tableData.password), 23 | nickname: fnSchema(tableData.nickname), 24 | role: fnSchema(tableData.role) 25 | }, 26 | required: ['id'] 27 | }, 28 | // 执行函数 29 | apiHandler: async (req, res) => { 30 | try { 31 | if (req.body.role === 'dev') { 32 | return { 33 | ...httpConfig.FAIL, 34 | msg: '不能增加开发管理员角色' 35 | }; 36 | } 37 | const adminModel = fastify.mysql // 38 | .table('sys_admin') 39 | .where({ id: req.body.id }) 40 | .modify(function (db) {}); 41 | 42 | await adminModel.clone().updateData({ 43 | password: fnSaltMD5(req.body.password), 44 | nickname: req.body.nickname, 45 | role: req.body.role 46 | }); 47 | 48 | return httpConfig.UPDATE_SUCCESS; 49 | } catch (err) { 50 | fastify.log.error(err); 51 | return httpConfig.UPDATE_FAIL; 52 | } 53 | } 54 | }); 55 | }; 56 | -------------------------------------------------------------------------------- /packages/yiapi/apis/api/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '接口', 3 | apiNames: { 4 | select: '分页查询接口', 5 | selectAll: '查询所有接口' 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /packages/yiapi/apis/api/select.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/api.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | page: fnSchema(schemaHelperConfig.page), 21 | limit: fnSchema(schemaHelperConfig.limit) 22 | } 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const apiModel = fastify.mysql // 28 | .table('sys_api') 29 | .modify(function (db) {}); 30 | 31 | const { totalCount } = await apiModel.clone().selectCount(); 32 | 33 | const rows = await apiModel 34 | // 35 | .clone() 36 | .orderBy('created_at', 'desc') 37 | .selectData(req.body.page, req.body.limit); 38 | 39 | return { 40 | ...httpConfig.SELECT_SUCCESS, 41 | data: { 42 | total: totalCount, 43 | rows: rows, 44 | page: req.body.page, 45 | limit: req.body.limit 46 | } 47 | }; 48 | } catch (err) { 49 | fastify.log.error(err); 50 | return httpConfig.SELECT_FAIL; 51 | } 52 | } 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /packages/yiapi/apis/api/selectAll.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | // 配置文件 4 | import { httpConfig } from '../../config/http.js'; 5 | import { cacheConfig } from '../../config/cache.js'; 6 | // 接口元数据 7 | import { metaConfig } from './_meta.js'; 8 | 9 | // 处理函数 10 | export default async (fastify) => { 11 | // 当前文件的路径,fastify 实例 12 | fnRoute(import.meta.url, fastify, metaConfig, { 13 | // 请求参数约束 14 | schemaRequest: { 15 | type: 'object', 16 | properties: {} 17 | }, 18 | // 执行函数 19 | apiHandler: async (req, res) => { 20 | try { 21 | const result = await fastify.redisGet(cacheConfig.api); 22 | 23 | return { 24 | ...httpConfig.SELECT_SUCCESS, 25 | data: { 26 | rows: result 27 | } 28 | }; 29 | } catch (err) { 30 | fastify.log.error(err); 31 | return httpConfig.SELECT_FAIL; 32 | } 33 | } 34 | }); 35 | }; 36 | -------------------------------------------------------------------------------- /packages/yiapi/apis/dict/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '字典', 3 | apiNames: { 4 | insert: '添加字典', 5 | delete: '删除字典', 6 | update: '修改字典', 7 | select: '分页查询字典', 8 | selectAll: '查询所有字典', 9 | detail: '查询字典详情' 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /packages/yiapi/apis/dict/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/dict.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | id: fnSchema(schemaHelperConfig.id) 21 | }, 22 | required: ['id'] 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const dictModel = fastify.mysql // 28 | .table('sys_dict') 29 | .where({ id: req.body.id }); 30 | 31 | const dictData = await dictModel.clone().selectOne(['id', 'is_system']); 32 | if (!dictData?.id) { 33 | return httpConfig.NO_DATA; 34 | } 35 | 36 | if (dictData?.is_system === 1) { 37 | return { 38 | ...httpConfig.DELETE_FAIL, 39 | msg: '默认字典,无法删除' 40 | }; 41 | } 42 | 43 | const result = await dictModel.clone().deleteData(); 44 | return { 45 | ...httpConfig.DELETE_SUCCESS, 46 | data: result 47 | }; 48 | } catch (err) { 49 | fastify.log.error(err); 50 | return httpConfig.DELETE_FAIL; 51 | } 52 | } 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /packages/yiapi/apis/dict/detail.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | // 数据表格 7 | import { tableData } from '../../tables/dict.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | // 处理函数 12 | export default async (fastify) => { 13 | // 当前文件的路径,fastify 实例 14 | fnRoute(import.meta.url, fastify, metaConfig, { 15 | // 请求参数约束 16 | schemaRequest: { 17 | type: 'object', 18 | properties: { 19 | code: fnSchema(tableData.code) 20 | }, 21 | required: ['code'] 22 | }, 23 | // 执行函数 24 | apiHandler: async (req, res) => { 25 | try { 26 | const dictModel = fastify.mysql.table('sys_dict'); 27 | 28 | const result = await dictModel // 29 | .clone() 30 | .where('code', req.body.code) 31 | .selectOne(); 32 | 33 | return { 34 | ...httpConfig.SELECT_SUCCESS, 35 | data: result 36 | }; 37 | } catch (err) { 38 | fastify.log.error(err); 39 | return httpConfig.SELECT_FAIL; 40 | } 41 | } 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /packages/yiapi/apis/dict/selectAll.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | // 数据表格 7 | import { tableData } from '../../tables/dict.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | // 处理函数 12 | export default async (fastify) => { 13 | // 当前文件的路径,fastify 实例 14 | fnRoute(import.meta.url, fastify, metaConfig, { 15 | // 请求参数约束 16 | schemaRequest: { 17 | type: 'object', 18 | properties: { 19 | category_code: fnSchema(tableData.category_code) 20 | } 21 | }, 22 | // 执行函数 23 | apiHandler: async (req, res) => { 24 | try { 25 | const dictModel = fastify.mysql 26 | .table('sys_dict') 27 | .where('category_code', req.body.category_code) 28 | .modify(function (db) {}); 29 | const rowsTemp = await dictModel.clone().selectAll(); 30 | 31 | const rows = rowsTemp?.map((item) => { 32 | if (item.symbol === 'number') { 33 | item.value = Number(item.value); 34 | } 35 | return item; 36 | }); 37 | return { 38 | ...httpConfig.SELECT_SUCCESS, 39 | data: { 40 | rows: rows 41 | } 42 | }; 43 | } catch (err) { 44 | fastify.log.error(err); 45 | return httpConfig.SELECT_FAIL; 46 | } 47 | } 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /packages/yiapi/apis/dictCategory/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '字典分类', 3 | apiNames: { 4 | insert: '添加字典分类', 5 | delete: '删除字典分类', 6 | update: '修改字典分类', 7 | select: '分页查询字典分类', 8 | selectAll: '查询所有字典分类' 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/yiapi/apis/dictCategory/selectAll.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | // 数据表格 7 | import { tableData } from '../../tables/dictCategory.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | // 处理函数 12 | export default async (fastify) => { 13 | // 当前文件的路径,fastify 实例 14 | fnRoute(import.meta.url, fastify, metaConfig, { 15 | // 请求参数约束 16 | schemaRequest: { 17 | type: 'object', 18 | properties: {} 19 | }, 20 | // 执行函数 21 | apiHandler: async (req, res) => { 22 | try { 23 | const dictCategoryModel = fastify.mysql // 24 | .table('sys_dict_category') 25 | .modify(function (db) {}); 26 | 27 | const rows = await dictCategoryModel.clone().selectAll(); 28 | 29 | return { 30 | ...httpConfig.SELECT_SUCCESS, 31 | data: { 32 | rows: rows 33 | } 34 | }; 35 | } catch (err) { 36 | fastify.log.error(err); 37 | return httpConfig.SELECT_FAIL; 38 | } 39 | } 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /packages/yiapi/apis/loginLog/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '登录日志', 3 | apiNames: { 4 | delete: '删除登录日志', 5 | select: '查询登录日志' 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /packages/yiapi/apis/loginLog/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/loginLog.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | id: fnSchema(schemaHelperConfig.id) 21 | }, 22 | required: ['id'] 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const loginLogModel = fastify.mysql.table('sys_login_log'); 28 | 29 | const result = await loginLogModel.clone().where({ id: req.body.id }).deleteData(); 30 | 31 | return { 32 | ...httpConfig.DELETE_SUCCESS, 33 | data: result 34 | }; 35 | } catch (err) { 36 | fastify.log.error(err); 37 | return httpConfig.DELETE_FAIL; 38 | } 39 | } 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /packages/yiapi/apis/mailLog/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '邮件日志', 3 | apiNames: { 4 | delete: '删除邮件日志', 5 | select: '查询邮件日志' 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /packages/yiapi/apis/mailLog/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/mailLog.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | id: fnSchema(schemaHelperConfig.id) 21 | }, 22 | required: ['id'] 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const mailLogModel = fastify.mysql.table('sys_mail_log'); 28 | 29 | const result = await mailLogModel.clone().where({ id: req.body.id }).deleteData(); 30 | 31 | return { 32 | ...httpConfig.DELETE_SUCCESS, 33 | data: result 34 | }; 35 | } catch (err) { 36 | fastify.log.error(err); 37 | return httpConfig.DELETE_FAIL; 38 | } 39 | } 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /packages/yiapi/apis/menu/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '菜单', 3 | apiNames: { 4 | insert: '添加菜单', 5 | delete: '删除菜单', 6 | update: '修改菜单', 7 | select: '分页查询菜单', 8 | selectAll: '查询所有菜单' 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/yiapi/apis/menu/select.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/menu.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | page: fnSchema(schemaHelperConfig.page), 21 | limit: fnSchema(schemaHelperConfig.limit) 22 | }, 23 | required: [] 24 | }, 25 | // 执行函数 26 | apiHandler: async (req, res) => { 27 | try { 28 | const menuModel = fastify.mysql // 29 | .table('sys_menu') 30 | .modify(function (db) {}); 31 | 32 | const { totalCount } = await menuModel.clone().selectCount(); 33 | 34 | const rows = await menuModel 35 | // 36 | .clone() 37 | .orderBy('created_at', 'desc') 38 | .selectData(req.body.page, req.body.limit); 39 | 40 | return { 41 | ...httpConfig.SELECT_SUCCESS, 42 | data: { 43 | total: totalCount, 44 | rows: rows, 45 | page: req.body.page, 46 | limit: req.body.limit 47 | } 48 | }; 49 | } catch (err) { 50 | fastify.log.error(err); 51 | return httpConfig.SELECT_FAIL; 52 | } 53 | } 54 | }); 55 | }; 56 | -------------------------------------------------------------------------------- /packages/yiapi/apis/menu/selectAll.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { cacheConfig } from '../../config/cache.js'; 7 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 8 | // 数据表格 9 | import { tableData } from '../../tables/menu.js'; 10 | // 接口元数据 11 | import { metaConfig } from './_meta.js'; 12 | 13 | // 处理函数 14 | export default async (fastify) => { 15 | // 当前文件的路径,fastify 实例 16 | fnRoute(import.meta.url, fastify, metaConfig, { 17 | // 请求参数约束 18 | schemaRequest: { 19 | type: 'object', 20 | properties: {} 21 | }, 22 | // 执行函数 23 | apiHandler: async (req, res) => { 24 | try { 25 | const result = await fastify.redisGet(cacheConfig.menu); 26 | 27 | return { 28 | ...httpConfig.SELECT_SUCCESS, 29 | data: { 30 | rows: result 31 | } 32 | }; 33 | } catch (err) { 34 | fastify.log.error(err); 35 | return httpConfig.SELECT_FAIL; 36 | } 37 | } 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /packages/yiapi/apis/role/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '角色', 3 | apiNames: { 4 | insert: '添加角色', 5 | delete: '删除角色', 6 | update: '修改角色', 7 | select: '分页查询角色', 8 | selectAll: '查询所有角色' 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/yiapi/apis/role/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/role.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | id: fnSchema(schemaHelperConfig.id) 21 | }, 22 | required: ['id'] 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const roleModel = fastify.mysql // 28 | .table('sys_role') 29 | .where('id', req.body.id) 30 | .modify(function (db) {}); 31 | 32 | const roleData = await roleModel.clone().selectOne(['id', 'is_system']); 33 | if (!roleData?.id) { 34 | return httpConfig.NO_DATA; 35 | } 36 | 37 | if (roleData.is_system === 1) { 38 | return { 39 | ...httpConfig.DELETE_FAIL, 40 | msg: '默认角色,无法删除' 41 | }; 42 | } 43 | 44 | const result = await roleModel.clone().deleteData(); 45 | 46 | // 生成新的权限 47 | await fastify.cacheRoleData(); 48 | 49 | return { 50 | ...httpConfig.DELETE_SUCCESS, 51 | data: result 52 | }; 53 | } catch (err) { 54 | return httpConfig.DELETE_FAIL; 55 | } 56 | } 57 | }); 58 | }; 59 | -------------------------------------------------------------------------------- /packages/yiapi/apis/role/selectAll.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/role.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: {} 20 | }, 21 | // 执行函数 22 | apiHandler: async (req, res) => { 23 | try { 24 | const roleModel = fastify.mysql // 25 | .table('sys_role') 26 | .modify(function (db) { 27 | // 如果不是开发管理员查询,则排除掉开发角色 28 | if (req.session.role !== 'dev') { 29 | db.where('code', '<>', 'dev'); 30 | } 31 | }); 32 | 33 | const rows = await roleModel.clone().selectAll(); 34 | 35 | return { 36 | ...httpConfig.SELECT_SUCCESS, 37 | data: { 38 | rows: rows 39 | } 40 | }; 41 | } catch (err) { 42 | fastify.log.error(err); 43 | return httpConfig.SELECT_FAIL; 44 | } 45 | } 46 | }); 47 | }; 48 | -------------------------------------------------------------------------------- /packages/yiapi/apis/tool/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '工具', 3 | apiNames: { 4 | sendMail: '发送邮件', 5 | tokenCheck: '令牌检测', 6 | getOnline: '获取在线统计', 7 | setOnline: '设置在线统计' 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yiapi/apis/tool/tokenCheck.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 接口元数据 8 | import { metaConfig } from './_meta.js'; 9 | 10 | // 处理函数 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: {}, 18 | required: [] 19 | }, 20 | // 执行函数 21 | apiHandler: async (req, res) => { 22 | try { 23 | try { 24 | const jwtData = await req.jwtVerify(); 25 | return { 26 | ...httpConfig.SUCCESS, 27 | data: { 28 | state: 'yes' 29 | } 30 | }; 31 | } catch (err) { 32 | return { 33 | ...httpConfig.SUCCESS, 34 | data: { 35 | state: 'no' 36 | } 37 | }; 38 | } 39 | } catch (err) { 40 | fastify.log.error(err); 41 | return httpConfig.FAIL; 42 | } 43 | } 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /packages/yiapi/apis/tree/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '树结构', 3 | apiNames: { 4 | insert: '添加树结构', 5 | delete: '删除树结构', 6 | update: '修改树结构', 7 | select: '分页查询树结构', 8 | selectAll: '查询所有树结构' 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/yiapi/apis/tree/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/tree.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | id: fnSchema(schemaHelperConfig.id) 21 | }, 22 | required: ['id'] 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const treeModel = fastify.mysql.table('sys_tree'); 28 | 29 | const treeData = await treeModel // 30 | .clone() 31 | .where({ pid: req.body.id }) 32 | .selectOne(['id']); 33 | 34 | if (treeData?.id) { 35 | return { 36 | ...httpConfig.FAIL, 37 | msg: '该树存在下级树,无法删除' 38 | }; 39 | } 40 | 41 | const result = await treeModel // 42 | .clone() 43 | .where({ id: req.body.id }) 44 | .deleteData(); 45 | 46 | return { 47 | ...httpConfig.DELETE_SUCCESS, 48 | data: result 49 | }; 50 | } catch (err) { 51 | fastify.log.error(err); 52 | return httpConfig.DELETE_FAIL; 53 | } 54 | } 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /packages/yiapi/apis/tree/selectAll.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/tree.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | // 处理函数 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: { 20 | category: fnSchema(tableData.category) 21 | }, 22 | required: ['category'] 23 | }, 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const roleModel = fastify.mysql // 28 | .table('sys_tree') 29 | .where('category', req.body.category) 30 | .modify(function (db) {}); 31 | 32 | const rows = await roleModel.clone().selectAll(); 33 | 34 | return { 35 | ...httpConfig.SELECT_SUCCESS, 36 | data: { 37 | rows: rows 38 | } 39 | }; 40 | } catch (err) { 41 | fastify.log.error(err); 42 | return httpConfig.SELECT_FAIL; 43 | } 44 | } 45 | }); 46 | }; 47 | -------------------------------------------------------------------------------- /packages/yiapi/apis/upload/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '文件上传', 3 | apiNames: { 4 | local: '上传到本地' 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /packages/yiapi/apis/user/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | dirName: '用户', 3 | apiNames: { 4 | detail: '查询用户详情', 5 | select: '分页查询用户', 6 | update: '更新用户', 7 | emailModifyPassword: '修改邮箱登陆密码', 8 | emailPassLogin: '邮箱密码登录', 9 | emailRegister: '邮箱注册', 10 | emailVerifyBind: '绑定邮箱', 11 | emailVerifyLogin: '邮箱验证码登录' 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /packages/yiapi/apis/user/detail.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | import { getDbFields } from '../../utils/getDbFields.js'; 5 | // 配置文件 6 | import { httpConfig } from '../../config/http.js'; 7 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 8 | // 数据表格 9 | import { tableData } from '../../tables/user.js'; 10 | // 接口元数据 11 | import { metaConfig } from './_meta.js'; 12 | 13 | export default async (fastify) => { 14 | // 当前文件的路径,fastify 实例 15 | fnRoute(import.meta.url, fastify, metaConfig, { 16 | // 请求参数约束 17 | schemaRequest: { 18 | type: 'object', 19 | properties: {} 20 | }, 21 | // 执行函数 22 | apiHandler: async (req, res) => { 23 | try { 24 | // 查询用户是否存在 25 | const sysUserModel = fastify.mysql.table('sys_user'); 26 | 27 | const result = await sysUserModel 28 | .clone() // 29 | .where('id', req.session.id) 30 | .selectOne(getDbFields(tableData, ['password'])); 31 | 32 | if (!result?.id) { 33 | return { 34 | ...httpConfig.SELECT_FAIL, 35 | msg: '没有查到用户信息' 36 | }; 37 | } 38 | 39 | return { 40 | ...httpConfig.SELECT_SUCCESS, 41 | data: result 42 | }; 43 | } catch (err) { 44 | fastify.log.error(err); 45 | return httpConfig.SELECT_FAIL; 46 | } 47 | } 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /packages/yiapi/apis/user/update.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | // 配置文件 5 | import { httpConfig } from '../../config/http.js'; 6 | import { schemaHelperConfig } from '../../config/schemaHelper.js'; 7 | // 数据表格 8 | import { tableData } from '../../tables/user.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | export default async (fastify) => { 13 | // 当前文件的路径,fastify 实例 14 | fnRoute(import.meta.url, fastify, metaConfig, { 15 | // 请求参数约束 16 | schemaRequest: { 17 | type: 'object', 18 | properties: { 19 | avatar: fnSchema(tableData.avatar), 20 | nickname: fnSchema(tableData.nickname), 21 | bio: fnSchema(tableData.bio), 22 | describe: fnSchema(tableData.describe) 23 | }, 24 | required: [] 25 | }, 26 | // 执行函数 27 | apiHandler: async (req, res) => { 28 | try { 29 | const userModel = fastify.mysql // 30 | .table('sys_user') 31 | .where({ id: req.session.id }); 32 | 33 | const result = await userModel 34 | // 35 | .clone() 36 | .where({ id: req.session.id }) 37 | .updateData({ 38 | avatar: req.body.avatar, 39 | nickname: req.body.nickname, 40 | bio: req.body.bio, 41 | describe: req.body.describe 42 | }); 43 | 44 | return { 45 | ...httpConfig.UPDATE_SUCCESS, 46 | data: result 47 | }; 48 | } catch (err) { 49 | fastify.log.error(err); 50 | return httpConfig.UPDATE_FAIL; 51 | } 52 | } 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /packages/yiapi/apis/weixin/_meta.js: -------------------------------------------------------------------------------- 1 | import { fnSchema } from '@yicode/yiapi/fn.js'; 2 | export const metaConfig = { 3 | dirName: '微信', 4 | apiNames: { 5 | code2Session: '通过code换取session', 6 | getConfig: '获取页面配置', 7 | getJsapiTicket: '获取js票据', 8 | loginCheck: '登录检测', 9 | loginQrcode: '登录二维码', 10 | message: '回调消息', 11 | payCheck: '支付成功检测', 12 | payNotify: '支付成功同志', 13 | payQrcode: '支付二维码', 14 | phoneInfo: '手机信息' 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiapi/apis/weixin/code2Session.js: -------------------------------------------------------------------------------- 1 | import got from 'got'; 2 | // 工具函数 3 | import { fnRoute } from '../../utils/fnRoute.js'; 4 | import { fnSchema } from '../../utils/fnSchema.js'; 5 | // 配置文件 6 | import { appConfig } from '../../config/app.js'; 7 | import { httpConfig } from '../../config/http.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | code: fnSchema({ name: 'code串', schema: { type: 'string', min: 1 } }) 19 | }, 20 | required: ['code'] 21 | }, 22 | // 执行函数 23 | apiHandler: async (req, res) => { 24 | try { 25 | const result = await got({ 26 | method: 'GET', 27 | url: 'https://api.weixin.qq.com/sns/jscode2session', 28 | searchParams: { 29 | appid: appConfig.custom.weixin.appId, 30 | secret: appConfig.custom.weixin.appSecret, 31 | grant_type: 'authorization_code', 32 | js_code: req.body.code 33 | } 34 | }); 35 | return { 36 | ...httpConfig.SUCCESS, 37 | data: result.data 38 | }; 39 | } catch (err) { 40 | fastify.log.error(err); 41 | return httpConfig.FAIL; 42 | } 43 | } 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /packages/yiapi/apis/weixin/getJsapiTicket.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | import { fnApiRaw } from '../../utils/fnApiRaw.js'; 5 | import { fnHashSign } from '../../utils/fnHashSign.js'; 6 | // 配置文件 7 | import { httpConfig } from '../../config/http.js'; 8 | import { cacheConfig } from '../../config/cache.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | export default async (fastify) => { 13 | // 当前文件的路径,fastify 实例 14 | fnRoute(import.meta.url, fastify, metaConfig, { 15 | // 请求参数约束 16 | schemaRequest: { 17 | type: 'object', 18 | properties: { 19 | url: fnSchema({ name: '页面路径', schema: { type: 'string' } }) 20 | }, 21 | required: ['url'] 22 | }, 23 | // 执行函数 24 | apiHandler: async (req, res) => { 25 | try { 26 | const cacheWeixinJsapiTicket = await fastify.redisGet(cacheConfig.weixinJsapiTicket); 27 | if (cacheWeixinJsapiTicket) { 28 | return { 29 | ...httpConfig.SUCCESS, 30 | data: { 31 | jsapiTicket: cacheWeixinJsapiTicket, 32 | from: 'cache' 33 | } 34 | }; 35 | } 36 | 37 | const jsapi_ticket = await fastify.getWeixinJsapiTicket(); 38 | 39 | // 如果报错 40 | if (jsapi_ticket) { 41 | return { 42 | ...httpConfig.SUCCESS, 43 | data: jsapi_ticket 44 | }; 45 | } 46 | 47 | return httpConfig.FAIL; 48 | } catch (err) { 49 | fastify.log.error(err); 50 | return httpConfig.FAIL; 51 | } 52 | } 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /packages/yiapi/apis/weixin/payCheck.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute } from '../../utils/fnRoute.js'; 3 | import { fnSchema } from '../../utils/fnSchema.js'; 4 | import { getCacheName } from '../../utils/getCacheName.js'; 5 | // 配置文件 6 | import { httpConfig } from '../../config/http.js'; 7 | // 数据库表 8 | import { tableData } from '../../tables/payOrder.js'; 9 | // 接口元数据 10 | import { metaConfig } from './_meta.js'; 11 | 12 | export default async (fastify) => { 13 | // 当前文件的路径,fastify 实例 14 | fnRoute(import.meta.url, fastify, metaConfig, { 15 | // 请求参数约束 16 | schemaRequest: { 17 | type: 'object', 18 | properties: { 19 | order_no: fnSchema(tableData.order_no) 20 | }, 21 | required: ['order_no'] 22 | }, 23 | // 执行函数 24 | apiHandler: async (req, res) => { 25 | try { 26 | const redisKey = getCacheName(`payOrder_${req.session.id}_${req.body.order_no}`); 27 | const payOrderNo = await fastify.redisGet(redisKey); 28 | if (payOrderNo) { 29 | await fastify.redis.del(redisKey); 30 | return { 31 | ...httpConfig.SUCCESS, 32 | msg: '付款成功!', 33 | data: { 34 | result: 'yes' 35 | } 36 | }; 37 | } else { 38 | return { 39 | ...httpConfig.SUCCESS, 40 | msg: '付款中...', 41 | data: { 42 | result: 'no' 43 | } 44 | }; 45 | } 46 | } catch (err) { 47 | fastify.log.error(err); 48 | return httpConfig.FAIL; 49 | } 50 | } 51 | }); 52 | }; 53 | -------------------------------------------------------------------------------- /packages/yiapi/apis/weixin/phoneInfo.js: -------------------------------------------------------------------------------- 1 | import got from 'got'; 2 | // 工具函数 3 | import { fnRoute } from '../../utils/fnRoute.js'; 4 | import { fnSchema } from '../../utils/fnSchema.js'; 5 | // 配置文件 6 | import { httpConfig } from '../../config/http.js'; 7 | // 接口元数据 8 | import { metaConfig } from './_meta.js'; 9 | 10 | export default async (fastify) => { 11 | // 当前文件的路径,fastify 实例 12 | fnRoute(import.meta.url, fastify, metaConfig, { 13 | // 请求参数约束 14 | schemaRequest: { 15 | type: 'object', 16 | properties: { 17 | accessToken: { 18 | type: 'string', 19 | minLength: 100, 20 | maxLength: 1000, 21 | title: 'accessToken' 22 | }, 23 | code: { 24 | type: 'string', 25 | minLength: 10, 26 | maxLength: 100, 27 | title: 'code' 28 | } 29 | }, 30 | required: ['code', 'accessToken'] 31 | }, 32 | // 执行函数 33 | apiHandler: async (req, res) => { 34 | try { 35 | const result = await got({ 36 | url: 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' + req.body.accessToken, 37 | json: { 38 | code: req.body.code 39 | } 40 | }); 41 | if (result.data.errmsg === 'ok') { 42 | return { 43 | ...httpConfig.SUCCESS, 44 | data: result.data.phone_info 45 | }; 46 | } else { 47 | fastify.log.error(result.data); 48 | return httpConfig.FAIL; 49 | } 50 | } catch (err) { 51 | fastify.log.error(err); 52 | return httpConfig.FAIL; 53 | } 54 | } 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /packages/yiapi/bootstrap/cors.js: -------------------------------------------------------------------------------- 1 | import fp from 'fastify-plugin'; 2 | import fastifyCors from '@fastify/cors'; 3 | 4 | async function plugin(fastify, opts) { 5 | await fastify.register(fastifyCors, function (instance) { 6 | return (req, callback) => { 7 | // 默认跨域,如果需要指定请求前缀,可以被传入的参数覆盖 8 | const newCorsConfig = { 9 | origin: req.headers.origin || req.headers.host || '*', 10 | methods: ['GET', 'OPTIONS', 'POST'], 11 | allowedHeaders: ['Content-Type', 'Authorization', 'authorization', 'token'], 12 | exposedHeaders: ['Content-Range', 'X-Content-Range', 'Authorization', 'authorization', 'token'], 13 | preflightContinue: false, 14 | strictPreflight: false, 15 | preflight: true, 16 | optionsSuccessStatus: 204, 17 | credentials: false 18 | }; 19 | 20 | callback(null, newCorsConfig); 21 | }; 22 | }); 23 | } 24 | export default fp(plugin, { name: 'cors' }); 25 | -------------------------------------------------------------------------------- /packages/yiapi/bootstrap/cron.js: -------------------------------------------------------------------------------- 1 | import { Cron } from 'croner'; 2 | import fp from 'fastify-plugin'; 3 | import logSymbols from 'log-symbols'; 4 | import { yd_is_function } from '@yicode/yidash'; 5 | 6 | // 工具函数 7 | 8 | // 配置信息 9 | import { cronConfig } from '../config/cron.js'; 10 | 11 | function plugin(fastify, opts, next) { 12 | cronConfig.forEach((item) => { 13 | if (yd_is_function(item.handler) === false) { 14 | console.log(logSymbols.error, `${item.name} 定时器 handler 必须为一个函数`); 15 | process.exit(); 16 | } 17 | const options = { 18 | name: item.name, 19 | maxRuns: item.maxRuns, 20 | timezone: item.timezone 21 | }; 22 | const job = Cron(item.timer, options, () => { 23 | item.handler(appConfig); 24 | }); 25 | fastify.decorate(item.code, job); 26 | }); 27 | next(); 28 | } 29 | export default fp(plugin, { name: 'cron', dependencies: ['tool'] }); 30 | -------------------------------------------------------------------------------- /packages/yiapi/bootstrap/mail.js: -------------------------------------------------------------------------------- 1 | import fp from 'fastify-plugin'; 2 | import nodemailer from 'nodemailer'; 3 | import { mailConfig } from '../config/mail.js'; 4 | 5 | async function plugin(fastify, opts) { 6 | const mailTransport = await nodemailer.createTransport({ 7 | host: mailConfig.host, 8 | port: mailConfig.post, 9 | pool: mailConfig.pool, 10 | secure: mailConfig.secure, 11 | auth: { 12 | user: mailConfig.user, 13 | pass: mailConfig.pass 14 | } 15 | }); 16 | 17 | // 发送邮件 18 | function sendMail(params) { 19 | return new Promise(async (resolve, reject) => { 20 | try { 21 | const result = await mailTransport.sendMail({ 22 | from: { 23 | name: mailConfig.from_name, 24 | address: mailConfig.from_email 25 | }, 26 | ...params 27 | }); 28 | resolve(result); 29 | } catch (err) { 30 | reject(err); 31 | } 32 | }); 33 | } 34 | 35 | fastify.decorate('sendEmail', sendMail); 36 | } 37 | export default fp(plugin, { name: 'email' }); 38 | -------------------------------------------------------------------------------- /packages/yiapi/bootstrap/rate.js: -------------------------------------------------------------------------------- 1 | import fp from 'fastify-plugin'; 2 | import rateLimit from '@fastify/rate-limit'; 3 | 4 | import { rateConfig } from '../config/rate.js'; 5 | 6 | async function plugin(fastify, options) { 7 | try { 8 | await fastify.register(rateLimit, { 9 | global: rateConfig.global || true, 10 | max: rateConfig.max || 100, 11 | ban: null, 12 | timeWindow: rateConfig.timeWindow || 1000 * 10, 13 | hook: rateConfig.hook || 'onRequest', 14 | cache: rateConfig.cache || 10000, 15 | allowList: rateConfig.allowList || ['127.0.0.1', 'localhost'], 16 | redis: null, 17 | nameSpace: rateConfig.namespace || 'test_rate:', 18 | continueExceeding: true, 19 | skipOnError: true, 20 | keyGenerator: function (req) { 21 | return req.headers['x-real-ip'] || req.headers['x-client-ip'] || req.ip || req.headers['x-forwarded-for']; 22 | }, 23 | onExceeded(req, key) { 24 | fastify.log.warn({ 25 | key: key, 26 | message: '请求过快', 27 | apiPath: req?.url, 28 | session: req?.session, 29 | reqId: req?.id 30 | }); 31 | } 32 | }); 33 | } catch (err) { 34 | fastify.log.error(err); 35 | } 36 | } 37 | 38 | export default fp(plugin, { name: 'rate', dependencies: ['redis'] }); 39 | -------------------------------------------------------------------------------- /packages/yiapi/bootstrap/upload.js: -------------------------------------------------------------------------------- 1 | import fp from 'fastify-plugin'; 2 | import fastifyMultipart from '@fastify/multipart'; 3 | 4 | async function plugin(fastify) { 5 | await fastify.register(fastifyMultipart, { 6 | attachFieldsToBody: true, 7 | limits: { 8 | fieldNameSize: 100, 9 | fieldSize: 100, 10 | fields: 10, 11 | fileSize: 100000000, // 文件最大为100M 12 | files: 1, 13 | headerPairs: 2000, 14 | parts: 1000 15 | } 16 | }); 17 | } 18 | 19 | export default fp(plugin, { 20 | name: 'upload' 21 | }); 22 | -------------------------------------------------------------------------------- /packages/yiapi/bootstrap/xmlParse.js: -------------------------------------------------------------------------------- 1 | import fp from 'fastify-plugin'; 2 | import fxp from 'fast-xml-parser'; 3 | import { appConfig } from '../config/app.js'; 4 | 5 | async function plugin(fastify) { 6 | const opts = { 7 | contentType: ['text/xml', 'application/xml', 'application/rss+xml'], 8 | validate: false 9 | }; 10 | 11 | function contentParser(req, payload, done) { 12 | const xmlParser = new fxp.XMLParser(opts); 13 | const parsingOpts = opts; 14 | 15 | let body = ''; 16 | payload.on('error', errorListener); 17 | payload.on('data', dataListener); 18 | payload.on('end', endListener); 19 | 20 | function errorListener(err) { 21 | done(err); 22 | } 23 | function endListener() { 24 | if (parsingOpts.validate) { 25 | const result = fxp.XMLValidator.validate(body, parsingOpts); 26 | if (result.err) { 27 | const invalidFormat = new Error('Invalid Format: ' + result.err.msg); 28 | invalidFormat.statusCode = 400; 29 | payload.removeListener('error', errorListener); 30 | payload.removeListener('data', dataListener); 31 | payload.removeListener('end', endListener); 32 | done(invalidFormat); 33 | } else { 34 | handleParseXml(body); 35 | } 36 | } else { 37 | handleParseXml(body); 38 | } 39 | } 40 | function dataListener(data) { 41 | body = body + data; 42 | } 43 | function handleParseXml(body) { 44 | try { 45 | done(null, xmlParser.parse(body)); 46 | } catch (err) { 47 | done(err); 48 | } 49 | } 50 | } 51 | 52 | fastify.addContentTypeParser(opts.contentType, contentParser); 53 | } 54 | 55 | export default fp(plugin, { 56 | name: 'xmlParse' 57 | }); 58 | -------------------------------------------------------------------------------- /packages/yiapi/config/app.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { appConfig: importConfig } = await fnImportAppConfig('app', {}); 4 | 5 | export const appConfig = Object.assign( 6 | { 7 | // 应用名称 8 | appName: '易接口', 9 | // 加密盐 10 | md5Salt: 'yiapi-123456.', 11 | // 监听端口 12 | port: 3000, 13 | // 监听主机 14 | host: '127.0.0.1', 15 | // 超级管理员密码 16 | devPassword: 'dev123456', 17 | // 是否进行参数验证 18 | paramsCheck: false, 19 | // 是否显示接口文档 20 | isSwagger: false, 21 | // 是否开启微信支付 22 | isWxPay: false, 23 | // 是否使用 session 模式 24 | isSession: false, 25 | // TODO: 考虑增加 uuid 类型以及不同的 uuid 格式 26 | // 数据库表主键方案 default(mysql 自带)time(时序 ID) 27 | tablePrimaryKey: 'default' 28 | }, 29 | importConfig 30 | ); 31 | -------------------------------------------------------------------------------- /packages/yiapi/config/blackApis.js: -------------------------------------------------------------------------------- 1 | import { yd_data_unique } from '@yicode/yidash'; 2 | import { system } from '../system.js'; 3 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 4 | 5 | const { blackApisConfig: importConfig } = await fnImportAppConfig('blackApis', []); 6 | 7 | export const blackApisConfig = yd_data_unique(importConfig); 8 | -------------------------------------------------------------------------------- /packages/yiapi/config/blackMenus.js: -------------------------------------------------------------------------------- 1 | import { yd_data_unique } from '@yicode/yidash'; 2 | import { system } from '../system.js'; 3 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 4 | 5 | const { blackMenusConfig: importConfig } = await fnImportAppConfig('blackMenus', []); 6 | 7 | export const blackMenusConfig = yd_data_unique(importConfig); 8 | -------------------------------------------------------------------------------- /packages/yiapi/config/cache.js: -------------------------------------------------------------------------------- 1 | export const cacheConfig = { 2 | // 角色缓存 3 | role: 'cacheData:role', 4 | // 菜单缓存 5 | menu: 'cacheData:menu', 6 | // 接口缓存 7 | api: 'cacheData:api', 8 | // 接口名称缓存 9 | apiNames: 'cacheData:apiNames', 10 | // 接口白名单列表 11 | apiWhiteLists: 'cacheData:apiWhiteLists', 12 | // 微信票据缓存 13 | weixinJsapiTicket: 'cacheData:weixinJsapiTicket', 14 | // 微信令牌缓存 15 | weixinAccessToken: 'cacheData:weixinAccessToken' 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiapi/config/callback.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { callbackConfig: importConfig } = await fnImportAppConfig('callback', {}); 4 | 5 | export const callbackConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/cron.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { cronConfig: importConfig } = await fnImportAppConfig('cron', []); 4 | 5 | export const cronConfig = importConfig; 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/freeApis.js: -------------------------------------------------------------------------------- 1 | import { yd_data_unique } from '@yicode/yidash'; 2 | import { system } from '../system.js'; 3 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 4 | 5 | const { freeApisConfig: importConfig } = await fnImportAppConfig('freeApis', []); 6 | 7 | export const freeApisConfig = yd_data_unique([ 8 | // 9 | '/', 10 | '/favicon.*', 11 | '/public/**', 12 | ...importConfig 13 | ]); 14 | -------------------------------------------------------------------------------- /packages/yiapi/config/http.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { httpConfig: importConfig } = await fnImportAppConfig('http', {}); 4 | 5 | // http状态码 6 | export const httpConfig = Object.assign(importConfig, { 7 | SUCCESS: { symbol: 'SUCCESS', code: 0, msg: '操作成功' }, 8 | INSERT_SUCCESS: { symbol: 'INSERT_SUCCESS', code: 0, msg: '添加成功' }, 9 | SELECT_SUCCESS: { symbol: 'SELECT_SUCCESS', code: 0, msg: '查询成功' }, 10 | UPDATE_SUCCESS: { symbol: 'UPDATE_SUCCESS', code: 0, msg: '更新成功' }, 11 | DELETE_SUCCESS: { symbol: 'DELETE_SUCCESS', code: 0, msg: '删除成功' }, 12 | FAIL: { symbol: 'FAIL', code: 1, msg: '操作失败' }, 13 | INSERT_FAIL: { symbol: 'INSERT_FAIL', code: 1, msg: '添加失败' }, 14 | SELECT_FAIL: { symbol: 'SELECT_FAIL', code: 1, msg: '查询失败' }, 15 | UPDATE_FAIL: { symbol: 'UPDATE_FAIL', code: 1, msg: '更新失败' }, 16 | DELETE_FAIL: { symbol: 'DELETE_FAIL', code: 1, msg: '删除失败' }, 17 | INFO: { symbol: 'INFO', code: 11, msg: '提示' }, 18 | WARN: { symbol: 'WARN', code: 12, msg: '警告' }, 19 | ERROR: { symbol: 'ERROR', code: 13, msg: '错误' }, 20 | NOT_LOGIN: { symbol: 'NOT_LOGIN', code: 14, msg: '未登录' }, 21 | API_DISABLED: { symbol: 'API_DISABLED', code: 15, msg: '接口已禁用' }, 22 | NO_FILE: { symbol: 'NO_FILE', code: 17, msg: '文件不存在' }, 23 | NO_API: { symbol: 'NO_API', code: 18, msg: '接口不存在' }, 24 | NO_USER: { symbol: 'NO_USER', code: 19, msg: '用户不存在' }, 25 | NO_DATA: { symbol: 'NO_DATA', code: 20, msg: '数据不存在' } 26 | }); 27 | -------------------------------------------------------------------------------- /packages/yiapi/config/jwt.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { jwtConfig: importConfig } = await fnImportAppConfig('jwt', {}); 4 | 5 | export const jwtConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/logFilter.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { logFilterConfig: importConfig } = await fnImportAppConfig('logFilter', []); 4 | 5 | export const logFilterConfig = [...importConfig]; 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/mail.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { mailConfig: importConfig } = await fnImportAppConfig('mail', {}); 4 | 5 | export const mailConfig = Object.assign( 6 | { 7 | host: 'demo.com', 8 | port: 465, 9 | pool: true, 10 | secure: true, 11 | // qq 邮箱 12 | user: 'demo@qq.com', 13 | pass: '', 14 | from_name: '易接口', 15 | from_email: 'demo@qq.com' 16 | }, 17 | importConfig 18 | ); 19 | -------------------------------------------------------------------------------- /packages/yiapi/config/mysql.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { mysqlConfig: importConfig } = await fnImportAppConfig('mysql', {}); 4 | 5 | export const mysqlConfig = Object.assign( 6 | { 7 | host: '127.0.0.1', 8 | port: 3306, 9 | db: 'test3', 10 | username: 'root', 11 | password: 'root' 12 | }, 13 | importConfig 14 | ); 15 | -------------------------------------------------------------------------------- /packages/yiapi/config/payment.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { paymentConfig: importConfig } = await fnImportAppConfig('payment', []); 4 | 5 | export const paymentConfig = importConfig; 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/product.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { productConfig: importConfig } = await fnImportAppConfig('product', {}); 4 | 5 | export const productConfig = importConfig; 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/rate.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { rateConfig: importConfig } = await fnImportAppConfig('rate', {}); 4 | 5 | export const rateConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/redis.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { redisConfig: importConfig } = await fnImportAppConfig('redis', {}); 4 | 5 | export const redisConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/role.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { roleConfig: importConfig } = await fnImportAppConfig('role', {}); 4 | 5 | export const roleConfig = Object.assign(importConfig, { 6 | visitor: { 7 | name: '游客', 8 | describe: '具备有限的权限和有限的查看内容', 9 | is_system: 1 10 | }, 11 | user: { 12 | name: '用户', 13 | describe: '用户权限和对于的内容查看', 14 | is_system: 1 15 | }, 16 | admin: { 17 | name: '管理', 18 | describe: '管理权限、除开发相关权限之外的权限等', 19 | is_system: 1 20 | }, 21 | super: { 22 | name: '超级管理', 23 | describe: '超级管理权限、除开发相关权限之外的权限等', 24 | is_system: 1 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /packages/yiapi/config/schemaHelper.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { schemaFieldConfig: importConfig } = await fnImportAppConfig('schemaField', {}); 4 | 5 | export const schemaHelperConfig = Object.assign(importConfig, { 6 | // 主键 ID 7 | id: { 8 | name: '主键ID', 9 | type: 'bigInt', 10 | min: 1 11 | }, 12 | // 第几页 13 | page: { 14 | name: '第几页', 15 | type: 'bigInt', 16 | default: 1, 17 | min: 1 18 | }, 19 | // 每页数量 20 | limit: { 21 | name: '每页数量', 22 | type: 'bigInt', 23 | default: 20, 24 | min: 1, 25 | max: 100 26 | }, 27 | // 搜索关键字 28 | keyword: { 29 | name: '搜索关键字', 30 | type: 'string', 31 | default: '', 32 | min: 0, 33 | max: 100 34 | }, 35 | // 布尔值 36 | bool_enum: { 37 | name: '布尔值', 38 | type: 'tinyInt', 39 | enum: [0, 1] 40 | }, 41 | // 状态 (0 正常,1 禁用,2 删除) 42 | state_enum: { 43 | name: '状态值', 44 | type: 'tinyInt', 45 | enum: [0, 1, 2] 46 | }, 47 | // 最小数字为 1 48 | min1: { 49 | name: '最小数字为1', 50 | type: 'bigInt', 51 | min: 1 52 | }, 53 | // 最小数字为 0 54 | min0: { 55 | name: '最小数字为0', 56 | type: 'bigInt', 57 | min: 0 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /packages/yiapi/config/secondTime.js: -------------------------------------------------------------------------------- 1 | export const secondTimeConfig = { 2 | // 永久 3 | forever: 0, 4 | // 年 5 | year: 31536000, 6 | // 季 7 | quarter: 7776000, 8 | // 月 9 | month: 2592000, 10 | // 周 11 | week: 604800, 12 | // 天 13 | day: 86400, 14 | // 时 15 | hour: 3600, 16 | // 分 17 | minute: 60 18 | }; 19 | -------------------------------------------------------------------------------- /packages/yiapi/config/tableExt.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { tableExtConfig: importConfig } = await fnImportAppConfig('tableExt', {}); 4 | 5 | export const tableExtConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/upload.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { uploadConfig: importConfig } = await fnImportAppConfig('upload', {}); 4 | 5 | export const uploadConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/weixin.js: -------------------------------------------------------------------------------- 1 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 2 | 3 | const { weixinConfig: importConfig } = await fnImportAppConfig('weixin', {}); 4 | 5 | export const weixinConfig = Object.assign({}, importConfig); 6 | -------------------------------------------------------------------------------- /packages/yiapi/config/whiteApis.js: -------------------------------------------------------------------------------- 1 | import { yd_data_unique } from '@yicode/yidash'; 2 | import { system } from '../system.js'; 3 | import { fnImportAppConfig } from '../utils/fnImportAppConfig.js'; 4 | 5 | const { whiteApisConfig: importConfig } = await fnImportAppConfig('whiteApis', []); 6 | 7 | export const whiteApisConfig = yd_data_unique(importConfig); 8 | -------------------------------------------------------------------------------- /packages/yiapi/fn.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | export { fnSchema } from './utils/fnSchema.js'; 3 | export { fnUUID } from './utils/fnUUID.js'; 4 | export { fnSaltMD5 } from './utils/fnSaltMD5.js'; 5 | export { fnPureMD5 } from './utils/fnPureMD5.js'; 6 | export { fnRoute } from './utils/fnRoute.js'; 7 | export { fnRsaSha256 } from './utils/fnRsaSha256.js'; 8 | -------------------------------------------------------------------------------- /packages/yiapi/note.md: -------------------------------------------------------------------------------- 1 | ## 数据库字段设计和请求验证 2 | 3 | ```json 4 | // 公共参数 5 | { 6 | "name": "角色代号", 7 | // 字段配置 8 | "fieldType": "string", // 9 | "fieldDefault": "", 10 | "intLength": 2000, 11 | "index": false, 12 | "unique": false, 13 | "unsigned": false, 14 | "precision": 1, 15 | "scale": 5, 16 | // 请求限制 17 | "schemaType": "string", // integer number string array 18 | "schemaDefault": "", 19 | "min": 1, 20 | "max": 100, 21 | // -- string 22 | "pattern": "", 23 | // -- integer number 24 | "multipleOf": 1, 25 | // -- array 26 | "items": "", // 如果只有类型,则是列表,否则就是元组, 27 | "uniqueItems": false, 28 | "additionalItems": false, 29 | // -- common 30 | "enum": [] 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/yiapi/plugins/jwt.js: -------------------------------------------------------------------------------- 1 | // 内部模块 2 | // 外部模块 3 | import fp from 'fastify-plugin'; 4 | import fastifyJwt from '@fastify/jwt'; 5 | // 配置文件 6 | import { jwtConfig } from '../config/jwt.js'; 7 | 8 | async function plugin(fastify) { 9 | await fastify.register(fastifyJwt, { 10 | secret: jwtConfig.secret, 11 | decoratorName: 'session', 12 | decode: { 13 | complete: true 14 | }, 15 | sign: { 16 | algorithm: 'HS256', 17 | expiresIn: jwtConfig.expiresIn 18 | }, 19 | verify: { 20 | algorithms: ['HS256'] 21 | } 22 | }); 23 | } 24 | export default fp(plugin, { name: 'jwt' }); 25 | -------------------------------------------------------------------------------- /packages/yiapi/plugins/logger.js: -------------------------------------------------------------------------------- 1 | // 核心模块 2 | import { resolve } from 'node:path'; 3 | // 外部模块 4 | import winston from 'winston'; 5 | import 'winston-daily-rotate-file'; 6 | 7 | import { system } from '../system.js'; 8 | 9 | const fileConfig = { 10 | dirname: resolve(system.appDir, 'logs'), 11 | filename: '%DATE%.log', 12 | datePattern: 'YYYY-MM-DD', 13 | zippedArchive: false, 14 | maxSize: '50m' 15 | }; 16 | 17 | const fileTransport = new winston.transports.DailyRotateFile(fileConfig); 18 | 19 | const configParams = { 20 | levels: { 21 | fatal: 0, 22 | error: 1, 23 | warn: 2, 24 | info: 3, 25 | trace: 4, 26 | debug: 5 27 | }, 28 | level: 'warn', 29 | format: winston.format.combine(winston.format.timestamp(), winston.format.json()), 30 | transports: [] 31 | }; 32 | 33 | // 如果是产品环境,则将日志写到文件中 34 | // 如果是开发环境,则直接打印日志 35 | if (process.env.NODE_ENV === 'production') { 36 | configParams.transports = [fileTransport]; 37 | } else { 38 | configParams.transports = [new winston.transports.Console()]; 39 | } 40 | 41 | const logger = winston.createLogger(configParams); 42 | 43 | export { logger }; 44 | -------------------------------------------------------------------------------- /packages/yiapi/plugins/swagger.js: -------------------------------------------------------------------------------- 1 | import fp from 'fastify-plugin'; 2 | import fastifySwagger from '@fastify/swagger'; 3 | import fastifySwaggerUi from '@fastify/swagger-ui'; 4 | 5 | import { appConfig } from '../config/app.js'; 6 | 7 | async function plugin(fastify, opts) { 8 | await fastify.register(fastifySwagger, { 9 | mode: 'dynamic', 10 | swagger: { 11 | info: { 12 | title: `${appConfig.appName}接口文档`, 13 | description: `${appConfig.appName}接口文档`, 14 | version: '1.0.0' 15 | }, 16 | host: '127.0.0.1', 17 | schemes: ['http'], 18 | consumes: ['application/json'], 19 | produces: ['application/json'] 20 | } 21 | }); 22 | 23 | await fastify.register(fastifySwaggerUi, { 24 | routePrefix: '/swagger', 25 | initOAuth: {}, 26 | uiConfig: { 27 | docExpansion: 'none', 28 | deepLinking: false 29 | }, 30 | staticCSP: true 31 | }); 32 | } 33 | export default fp(plugin, { 34 | name: 'swagger' 35 | }); 36 | -------------------------------------------------------------------------------- /packages/yiapi/schema/app.js: -------------------------------------------------------------------------------- 1 | export const appSchema = { 2 | title: '应用基本配置', 3 | type: 'object', 4 | properties: { 5 | appName: { 6 | title: '应用名称', 7 | type: 'string', 8 | minLength: 1, 9 | maxLength: 50 10 | }, 11 | md5Salt: { 12 | title: 'MD5加密盐值', 13 | type: 'string', 14 | minLength: 1, 15 | maxLength: 300 16 | }, 17 | port: { 18 | title: '监听端口', 19 | type: 'integer', 20 | minimum: 0 21 | }, 22 | host: { 23 | title: '监听主机', 24 | type: 'string', 25 | minLength: 1, 26 | maxLength: 30 27 | }, 28 | devPassword: { 29 | title: '开发者密码', 30 | type: 'string', 31 | minLength: 6, 32 | maxLength: 20 33 | }, 34 | paramsCheck: { 35 | title: '接口参数验证', 36 | type: 'boolean', 37 | default: false 38 | }, 39 | isSwagger: { 40 | title: '是否开启接口文档', 41 | type: 'boolean', 42 | default: false 43 | }, 44 | isWxPay: { 45 | title: '是否开启支付功能', 46 | type: 'boolean', 47 | default: false 48 | }, 49 | isSession: { 50 | title: '是否开启会话模式', 51 | type: 'boolean', 52 | default: false 53 | }, 54 | // 数据库表主键方案 55 | tablePrimaryKey: { 56 | title: '数据库表主键方案', 57 | type: 'string', 58 | enum: ['default', 'time'] 59 | } 60 | }, 61 | additionalProperties: false, 62 | required: [ 63 | // 64 | 'appName', 65 | 'md5Salt', 66 | 'port', 67 | 'host', 68 | 'devPassword', 69 | 'paramsCheck', 70 | 'isSwagger', 71 | 'isWxPay', 72 | 'tablePrimaryKey' 73 | ] 74 | }; 75 | -------------------------------------------------------------------------------- /packages/yiapi/schema/blackApis.js: -------------------------------------------------------------------------------- 1 | export const blackApisSchema = { 2 | // 黑名单接口,不可访问的接口 3 | title: '黑名单接口', 4 | type: 'array', 5 | items: { 6 | type: 'string' 7 | }, 8 | uniqueItems: true 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yiapi/schema/blackMenus.js: -------------------------------------------------------------------------------- 1 | export const blackMenusSchema = { 2 | // 黑名单菜单 3 | title: '黑名单菜单', 4 | type: 'array', 5 | items: { 6 | type: 'string' 7 | }, 8 | uniqueItems: true 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yiapi/schema/cache.js: -------------------------------------------------------------------------------- 1 | export const cacheSchema = { 2 | // 定时器配置 3 | title: '缓存名称配置', 4 | type: 'object', 5 | patternProperties: { 6 | '^[a-z][a-zA-Z0-9_]*$': { 7 | title: '缓存名称', 8 | type: 'string' 9 | } 10 | }, 11 | additionalProperties: false 12 | }; 13 | -------------------------------------------------------------------------------- /packages/yiapi/schema/callback.js: -------------------------------------------------------------------------------- 1 | export const callbackSchema = { 2 | title: '回调函数', 3 | type: 'object', 4 | patternProperties: { 5 | '^[a-z][a-z0-9_-]*$': { 6 | title: '任意字段', 7 | type: 'object' 8 | }, 9 | additionalProperties: false 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /packages/yiapi/schema/cron.js: -------------------------------------------------------------------------------- 1 | export const cronSchema = { 2 | // 定时器配置 3 | title: '定时器', 4 | type: 'array', 5 | items: { 6 | type: 'object', 7 | properties: { 8 | timer: { 9 | title: '定时器', 10 | type: 'string' 11 | }, 12 | name: { 13 | title: '定时器名称', 14 | type: 'string' 15 | }, 16 | code: { 17 | title: '定时器代号', 18 | type: 'string' 19 | }, 20 | maxRuns: { 21 | title: '最大运行次数', 22 | type: 'number' 23 | }, 24 | timezone: { 25 | title: '时区', 26 | type: 'string' 27 | }, 28 | handler: { 29 | title: '处理函数' 30 | } 31 | }, 32 | additionalProperties: false, 33 | required: ['timer', 'handler', 'name', 'code'] 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /packages/yiapi/schema/freeApis.js: -------------------------------------------------------------------------------- 1 | export const freeApisSchema = { 2 | // 任何情况下可以访问的路由 3 | title: '自由接口', 4 | type: 'array', 5 | items: { 6 | type: 'string' 7 | }, 8 | uniqueItems: true 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yiapi/schema/http.js: -------------------------------------------------------------------------------- 1 | export const httpSchema = { 2 | title: 'HTTP返回码', 3 | type: 'object', 4 | properties: { 5 | '*': { 6 | title: '任意字段', 7 | type: 'object', 8 | properties: { 9 | symbol: { 10 | title: '唯一符号', 11 | type: 'string' 12 | }, 13 | code: { 14 | title: '状态码', 15 | type: 'integer', 16 | minimum: 0 17 | }, 18 | msg: { 19 | title: '消息内容', 20 | type: 'string' 21 | } 22 | }, 23 | additionalProperties: false, 24 | required: ['symbol', 'code', 'msg'] 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /packages/yiapi/schema/jwt.js: -------------------------------------------------------------------------------- 1 | export const jwtSchema = { 2 | // jwt 配置 3 | title: 'jwt 配置', 4 | type: 'object', 5 | properties: { 6 | secret: { 7 | title: '加密字符', 8 | type: 'string' 9 | }, 10 | expiresIn: { 11 | title: '过期时间', 12 | type: 'string' 13 | } 14 | }, 15 | additionalProperties: false, 16 | required: [ 17 | // 18 | 'secret', 19 | 'expiresIn' 20 | ] 21 | }; 22 | -------------------------------------------------------------------------------- /packages/yiapi/schema/logFilter.js: -------------------------------------------------------------------------------- 1 | export const logFilterSchema = { 2 | title: '日志字段过滤', 3 | type: 'array', 4 | items: { 5 | type: 'string' 6 | }, 7 | uniqueItems: true 8 | }; 9 | -------------------------------------------------------------------------------- /packages/yiapi/schema/mail.js: -------------------------------------------------------------------------------- 1 | export const mailSchema = { 2 | // 邮件配置 3 | title: '邮件配置', 4 | type: 'object', 5 | properties: { 6 | host: { 7 | title: '主机地址', 8 | type: 'string' 9 | }, 10 | port: { 11 | title: '端口', 12 | type: 'number' 13 | }, 14 | pool: { 15 | title: '是否开启连接池', 16 | type: 'boolean' 17 | }, 18 | secure: { 19 | title: '是否开启 https', 20 | type: 'boolean' 21 | }, 22 | user: { 23 | title: '账号', 24 | type: 'string' 25 | }, 26 | pass: { 27 | title: '密码', 28 | type: 'string' 29 | }, 30 | from_name: { 31 | title: '发送者昵称', 32 | type: 'string' 33 | }, 34 | from_email: { 35 | title: '发送者邮箱', 36 | type: 'string' 37 | } 38 | }, 39 | additionalProperties: false, 40 | required: [ 41 | // 42 | 'host', 43 | 'port', 44 | 'pool', 45 | 'secure', 46 | 'user', 47 | 'pass', 48 | 'from_name', 49 | 'from_email' 50 | ] 51 | }; 52 | -------------------------------------------------------------------------------- /packages/yiapi/schema/mysql.js: -------------------------------------------------------------------------------- 1 | export const mysqlSchema = { 2 | // 数据库配置 3 | title: '数据库配合', 4 | type: 'object', 5 | properties: { 6 | db: { 7 | title: '数据库名称', 8 | type: 'string' 9 | }, 10 | username: { 11 | title: '用户名', 12 | type: 'string' 13 | }, 14 | password: { 15 | title: '密码', 16 | type: 'string' 17 | }, 18 | host: { 19 | title: '主机地址', 20 | type: 'string' 21 | }, 22 | port: { 23 | title: '监听端口', 24 | type: 'number' 25 | } 26 | }, 27 | additionalProperties: false, 28 | required: [ 29 | // 30 | 'db', 31 | 'username', 32 | 'password', 33 | 'host', 34 | 'port' 35 | ] 36 | }; 37 | -------------------------------------------------------------------------------- /packages/yiapi/schema/payment.js: -------------------------------------------------------------------------------- 1 | export const paymentSchema = { 2 | // 支付配置 3 | title: '支付配置', 4 | type: 'array', 5 | items: { 6 | type: 'object', 7 | properties: { 8 | // 产品名称 9 | name: { 10 | title: '产品名称', 11 | type: 'string', 12 | minLength: 1, 13 | maxLength: 20 14 | }, 15 | // 产品代号 16 | product: { 17 | title: '产品代号', 18 | type: 'integer', 19 | minimum: 1 20 | }, 21 | // 支付代号 22 | code: { 23 | title: '支付代号', 24 | type: 'integer', 25 | minimum: 1 26 | }, 27 | // 时长 0=永久 非0=秒 28 | duration: { 29 | title: '购买时间(秒)', 30 | type: 'integer', 31 | minimum: 0 32 | }, 33 | // 价格 分 34 | money: { 35 | title: '购买价格(分)', 36 | type: 'integer', 37 | minimum: 1 38 | } 39 | }, 40 | additionalProperties: false, 41 | required: [ 42 | // 43 | 'name', 44 | 'product', 45 | 'code', 46 | 'duration', 47 | 'money' 48 | ] 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /packages/yiapi/schema/product.js: -------------------------------------------------------------------------------- 1 | export const productSchema = { 2 | // 产品配置 3 | title: '产品配置', 4 | type: 'object', 5 | properties: { 6 | '*': { 7 | type: 'integer', 8 | minimum: 1 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /packages/yiapi/schema/rate.js: -------------------------------------------------------------------------------- 1 | export const rateSchema = { 2 | // 请求限速 3 | title: '请求频率', 4 | type: 'object', 5 | properties: { 6 | global: { 7 | type: 'boolean', 8 | title: '是否影响全部的路由' 9 | }, 10 | max: { 11 | type: 'number', 12 | title: '限制时间内的最大请求数' 13 | }, 14 | timeWindow: { 15 | type: 'number', 16 | title: '限制时间' 17 | }, 18 | hook: { 19 | type: 'string', 20 | title: '触发的钩子' 21 | }, 22 | cache: { 23 | type: 'number', 24 | title: '内存缓存大小' 25 | }, 26 | allowList: { 27 | type: 'array', 28 | title: '白名单' 29 | } 30 | }, 31 | additionalProperties: false 32 | }; 33 | -------------------------------------------------------------------------------- /packages/yiapi/schema/redis.js: -------------------------------------------------------------------------------- 1 | export const redisSchema = { 2 | // redis 配置 3 | title: '缓存配置', 4 | type: 'object', 5 | properties: { 6 | keyPrefix: { 7 | title: '缓存前缀', 8 | type: 'string' 9 | }, 10 | username: { 11 | title: '用户名', 12 | type: 'string' 13 | }, 14 | password: { 15 | title: '连接密码', 16 | type: 'string' 17 | }, 18 | host: { 19 | title: '主机地址', 20 | type: 'string' 21 | }, 22 | db: { 23 | title: '库序号', 24 | type: 'number' 25 | }, 26 | port: { 27 | title: '监听端口', 28 | type: 'number' 29 | } 30 | }, 31 | additionalProperties: false, 32 | required: [ 33 | // 34 | 'keyPrefix', 35 | 'username', 36 | 'password', 37 | 'db', 38 | 'host', 39 | 'port' 40 | ] 41 | }; 42 | -------------------------------------------------------------------------------- /packages/yiapi/schema/role.js: -------------------------------------------------------------------------------- 1 | export const roleSchema = { 2 | title: '角色配置', 3 | type: 'object', 4 | patternProperties: { 5 | '^[a-z][a-z0-9_]*$': { 6 | title: '角色代号', 7 | type: 'object', 8 | properties: { 9 | name: { 10 | title: '角色名称', 11 | type: 'string', 12 | minLength: 1, 13 | maxLength: 20 14 | }, 15 | describe: { 16 | title: '角色描述', 17 | type: 'string', 18 | minLength: 0, 19 | maxLength: 200 20 | }, 21 | is_system: { 22 | title: '是否系统角色', 23 | type: 'integer', 24 | default: 0, 25 | enum: [0, 1] 26 | } 27 | }, 28 | additionalProperties: false, 29 | required: ['name', 'describe'] 30 | } 31 | }, 32 | additionalProperties: false 33 | }; 34 | -------------------------------------------------------------------------------- /packages/yiapi/schema/schemaHelper.js: -------------------------------------------------------------------------------- 1 | import { tableSchema as schemaHelperSchema } from './table.js'; 2 | export { schemaHelperSchema }; 3 | -------------------------------------------------------------------------------- /packages/yiapi/schema/secondTime.js: -------------------------------------------------------------------------------- 1 | export const secondTimeSchema = { 2 | title: '秒级时间映射', 3 | type: 'object', 4 | properties: { 5 | '*': { 6 | type: 'integer' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yiapi/schema/tableExt.js: -------------------------------------------------------------------------------- 1 | // 核心模块 2 | import { readdirSync } from 'node:fs'; 3 | import { resolve } from 'node:path'; 4 | // 外部模块 5 | import { yd_string_snakeCase } from '@yicode/yidash'; 6 | // 内部模块 7 | import { system } from '../system.js'; 8 | import { tableSchema } from './table.js'; 9 | 10 | const sysDbFiles = readdirSync(resolve(system.yiapiDir, 'tables')); 11 | const propertieFields = {}; 12 | 13 | sysDbFiles.forEach((file) => { 14 | propertieFields[yd_string_snakeCase('sys_' + file.replace('.js', ''))] = tableSchema; 15 | }); 16 | 17 | export const tableExtSchema = { 18 | // 扩展系统表字段 19 | title: '系统表扩展字段', 20 | type: 'object', 21 | properties: propertieFields, 22 | additionalProperties: false 23 | }; 24 | -------------------------------------------------------------------------------- /packages/yiapi/schema/upload.js: -------------------------------------------------------------------------------- 1 | export const uploadSchema = { 2 | // 文件上传 3 | title: '上传配置', 4 | type: 'object', 5 | properties: { 6 | dir: { 7 | type: 'string' 8 | } 9 | }, 10 | additionalProperties: false, 11 | required: ['dir'] 12 | }; 13 | -------------------------------------------------------------------------------- /packages/yiapi/schema/weixin.js: -------------------------------------------------------------------------------- 1 | export const weixinSchema = { 2 | title: '微信配置', 3 | type: 'object', 4 | properties: { 5 | // 商户配置 6 | mchId: { 7 | title: '商户号', 8 | type: 'string' 9 | }, 10 | serialNo: { 11 | title: '支付序列号', 12 | type: 'string' 13 | }, 14 | apiv3PrivateKey: { 15 | title: '支付秘钥', 16 | type: 'string' 17 | }, 18 | privateKey: { 19 | title: '商户私钥', 20 | type: 'string' 21 | }, 22 | // 公众号配置 23 | // appId 24 | appId: { 25 | title: '公众号appId', 26 | type: 'string' 27 | }, 28 | // appSecret 29 | appSecret: { 30 | title: '公众号密钥', 31 | type: 'string' 32 | }, 33 | // 支付回调地址 34 | notifyUrl: { 35 | title: '支付通知地址', 36 | type: 'string' 37 | } 38 | }, 39 | additionalProperties: false, 40 | required: [ 41 | // 42 | 'mchId', 43 | 'serialNo', 44 | 'apiv3PrivateKey', 45 | 'privateKey', 46 | 'appId', 47 | 'appSecret', 48 | 'notifyUrl' 49 | ] 50 | }; 51 | -------------------------------------------------------------------------------- /packages/yiapi/schema/whiteApis.js: -------------------------------------------------------------------------------- 1 | export const whiteApisSchema = { 2 | // 白名单接口,登录后访问无限制 3 | title: '白名单接口', 4 | type: 'array', 5 | items: { 6 | type: 'string' 7 | }, 8 | uniqueItems: true 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yiapi/system.js: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { cwd } from 'node:process'; 3 | 4 | export const system = { 5 | appDir: cwd(), 6 | yiapiDir: dirname(import.meta.filename) 7 | }; 8 | -------------------------------------------------------------------------------- /packages/yiapi/tables/api.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '系统接口表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_api || {}, { 4 | pid: { 5 | name: '父级ID', 6 | type: 'bigInt', 7 | default: 0, 8 | isIndex: true, 9 | min: 1 10 | }, 11 | pids: { 12 | name: '父级ID链', 13 | type: 'string', 14 | default: '0', 15 | max: 1000 16 | }, 17 | name: { 18 | name: '名称', 19 | type: 'string', 20 | default: '', 21 | max: 100 22 | }, 23 | value: { 24 | name: '值', 25 | type: 'string', 26 | default: '', 27 | max: 500 28 | }, 29 | sort: { 30 | name: '字典排序', 31 | type: 'bigInt', 32 | default: 0, 33 | min: 0 34 | }, 35 | describe: { 36 | name: '描述', 37 | type: 'string', 38 | default: '', 39 | max: 500 40 | }, 41 | is_bool: { 42 | name: '真假树', 43 | type: 'tinyInt', 44 | default: 0, 45 | enum: [0, 1] 46 | }, 47 | is_open: { 48 | name: '是否公开', 49 | type: 'tinyInt', 50 | default: 0, 51 | enum: [0, 1] 52 | }, 53 | is_system: { 54 | name: '是否系统账号(不可删除)', 55 | type: 'tinyInt', 56 | default: 0, 57 | enum: [0, 1] 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /packages/yiapi/tables/appConfig.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '项目配置表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_app_config || {}, { 4 | site_name: { 5 | name: '站点名称', 6 | type: 'string', 7 | default: '', 8 | max: 100 9 | }, 10 | site_logo: { 11 | name: '站点logo', 12 | type: 'string', 13 | default: '', 14 | max: 300 15 | }, 16 | site_bei: { 17 | name: '备案号', 18 | type: 'string', 19 | default: '', 20 | max: 100 21 | }, 22 | smtp_host: { 23 | name: 'SMTP 服务器', 24 | type: 'string', 25 | default: '', 26 | max: 200 27 | }, 28 | smtp_port: { 29 | name: 'SMTP 端口', 30 | type: 'mediumInt', 31 | default: 0, 32 | min: 0 33 | }, 34 | smtp_username: { 35 | name: 'SMTP 用户名', 36 | type: 'string', 37 | default: '', 38 | max: 100 39 | }, 40 | smtp_password: { 41 | name: 'SMTP 密码', 42 | type: 'string', 43 | default: '', 44 | max: 100 45 | }, 46 | smtp_from_name: { 47 | name: '发送者昵称', 48 | type: 'string', 49 | default: '', 50 | max: 100 51 | }, 52 | smtp_from_email: { 53 | name: '发送者邮箱', 54 | type: 'string', 55 | default: '', 56 | max: 100 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /packages/yiapi/tables/dict.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '系统字典表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_dict || {}, { 4 | category_id: { 5 | name: '分类ID', 6 | type: 'bigInt', 7 | default: 0, 8 | isIndex: true, 9 | min: 0 10 | }, 11 | category_code: { 12 | name: '分类编码', 13 | type: 'string', 14 | default: '', 15 | isIndex: true, 16 | max: 50, 17 | pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$' 18 | }, 19 | code: { 20 | name: '字典编码', 21 | type: 'string', 22 | default: '', 23 | max: 50, 24 | pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$' 25 | }, 26 | name: { 27 | name: '字典名称', 28 | type: 'string', 29 | default: '', 30 | max: 100 31 | }, 32 | value: { 33 | name: '字典值', 34 | type: 'string', 35 | default: '', 36 | max: 1000 37 | }, 38 | symbol: { 39 | name: '数字类型或字符串类型', 40 | type: 'string', 41 | default: '', 42 | enum: ['string', 'number'] 43 | }, 44 | sort: { 45 | name: '字典排序', 46 | type: 'bigInt', 47 | default: 0, 48 | min: 0 49 | }, 50 | describe: { 51 | name: '描述', 52 | type: 'string', 53 | default: '', 54 | max: 500 55 | }, 56 | thumbnail: { 57 | name: '缩略图', 58 | type: 'string', 59 | default: '', 60 | max: 500 61 | }, 62 | is_system: { 63 | name: '是否系统数据(不可删除)', 64 | type: 'tinyInt', 65 | default: 0, 66 | enum: [0, 1] 67 | } 68 | }); 69 | -------------------------------------------------------------------------------- /packages/yiapi/tables/dictCategory.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '系统字典分类表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_dict_category || {}, { 4 | code: { 5 | name: '字典分类编码', 6 | type: 'string', 7 | default: '', 8 | min: 1, 9 | max: 50, 10 | pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$' 11 | }, 12 | name: { 13 | name: '字典分类名称', 14 | type: 'string', 15 | default: '', 16 | min: 1, 17 | max: 100 18 | }, 19 | sort: { 20 | name: '字典分类排序', 21 | type: 'bigInt', 22 | default: 0, 23 | min: 0 24 | }, 25 | describe: { 26 | name: '描述', 27 | type: 'string', 28 | default: '', 29 | min: 0, 30 | max: 500 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /packages/yiapi/tables/loginLog.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '登录日志表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_login_log || {}, { 4 | username: { 5 | name: '用户名', 6 | type: 'string', 7 | default: '', 8 | max: 30 9 | }, 10 | nickname: { 11 | name: '昵称', 12 | type: 'string', 13 | default: '', 14 | max: 50 15 | }, 16 | role: { 17 | name: '角色', 18 | type: 'string', 19 | default: '', 20 | max: 50 21 | }, 22 | ip: { 23 | name: 'ip', 24 | type: 'string', 25 | default: '', 26 | max: 30 27 | }, 28 | ua: { 29 | name: 'ua', 30 | type: 'string', 31 | default: '', 32 | max: 500 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /packages/yiapi/tables/mailLog.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '邮件日志表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_mail_log || {}, { 4 | login_email: { 5 | name: '登录邮箱', 6 | type: 'string', 7 | default: '', 8 | max: 100 9 | }, 10 | from_name: { 11 | name: '发送者昵称', 12 | type: 'string', 13 | default: '', 14 | max: 100 15 | }, 16 | from_email: { 17 | name: '发送者邮箱', 18 | type: 'string', 19 | default: '', 20 | max: 100 21 | }, 22 | to_email: { 23 | name: '接收者邮箱', 24 | type: 'string', 25 | default: '', 26 | max: 5000 27 | }, 28 | email_type: { 29 | name: '邮件类型', 30 | type: 'string', 31 | default: 'common', 32 | enum: ['common', 'verify'] 33 | }, 34 | email_code: { 35 | name: '邮件识别码', 36 | type: 'string', 37 | default: '', 38 | enum: ['loginVerifyCode', 'bindMailVerifyCode', 'setupPasswordVerifyCode'] 39 | }, 40 | text_content: { 41 | name: '发送内容', 42 | type: 'string', 43 | default: '', 44 | max: 10000 45 | } 46 | }); 47 | -------------------------------------------------------------------------------- /packages/yiapi/tables/menu.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '系统菜单表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_menu || {}, { 4 | pid: { 5 | name: '父级ID', 6 | type: 'bigInt', 7 | default: 0, 8 | isIndex: true, 9 | min: 0 10 | }, 11 | image: { 12 | name: '菜单图标', 13 | type: 'string', 14 | default: '', 15 | max: 500 16 | }, 17 | name: { 18 | name: '名称', 19 | type: 'string', 20 | default: '', 21 | max: 100 22 | }, 23 | value: { 24 | name: '路由', 25 | type: 'string', 26 | default: '', 27 | isUnique: true, 28 | max: 500 29 | }, 30 | sort: { 31 | name: '字典排序', 32 | type: 'bigInt', 33 | default: 0, 34 | min: 0 35 | }, 36 | describe: { 37 | name: '描述', 38 | type: 'string', 39 | default: '', 40 | max: 500 41 | }, 42 | is_open: { 43 | name: '是否公开', 44 | type: 'tinyInt', 45 | default: 0, 46 | enum: [0, 1] 47 | }, 48 | is_system: { 49 | name: '是否系统账号(不可删除)', 50 | type: 'tinyInt', 51 | default: 0, 52 | enum: [0, 1] 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /packages/yiapi/tables/role.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '系统角色表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_role || {}, { 4 | code: { 5 | name: '角色编码', 6 | type: 'string', 7 | default: '', 8 | max: 50, 9 | pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$' 10 | }, 11 | name: { 12 | name: '角色名称', 13 | type: 'string', 14 | default: '', 15 | max: 100 16 | }, 17 | describe: { 18 | name: '角色描述', 19 | type: 'string', 20 | default: '', 21 | max: 500 22 | }, 23 | menu_ids: { 24 | name: '角色菜单', 25 | type: 'mediumText', 26 | default: '', 27 | max: 50000 28 | }, 29 | api_ids: { 30 | name: '角色接口', 31 | type: 'mediumText', 32 | default: '', 33 | max: 50000 34 | }, 35 | sort: { 36 | name: '角色排序', 37 | type: 'bigInt', 38 | default: 0, 39 | min: 0 40 | }, 41 | is_system: { 42 | name: '是否系统角色(不可删除)', 43 | type: 'tinyInt', 44 | default: 0, 45 | enum: [0, 1] 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /packages/yiapi/tables/tree.js: -------------------------------------------------------------------------------- 1 | import { tableExtConfig } from '../config/tableExt.js'; 2 | export const tableName = '系统目录表'; 3 | export const tableData = Object.assign(tableExtConfig.sys_tree || {}, { 4 | pid: { 5 | name: '父级ID', 6 | type: 'bigInt', 7 | default: 0, 8 | isIndex: true, 9 | min: 0 10 | }, 11 | pids: { 12 | name: '父级ID链', 13 | type: 'string', 14 | default: '0', 15 | max: 10000 16 | }, 17 | level: { 18 | name: '目录层级', 19 | type: 'tinyInt', 20 | default: 1, 21 | min: 1 22 | }, 23 | category: { 24 | name: '分类编码', 25 | type: 'string', 26 | default: '', 27 | max: 100, 28 | pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$' 29 | }, 30 | image: { 31 | name: '图标', 32 | type: 'string', 33 | default: '', 34 | max: 500 35 | }, 36 | name: { 37 | name: '名称', 38 | type: 'string', 39 | default: '', 40 | max: 100 41 | }, 42 | value: { 43 | name: '值', 44 | type: 'string', 45 | default: '', 46 | max: 500 47 | }, 48 | sort: { 49 | name: '字典排序', 50 | type: 'bigInt', 51 | default: 0, 52 | min: 0 53 | }, 54 | describe: { 55 | name: '描述', 56 | type: 'string', 57 | default: '', 58 | max: 500 59 | }, 60 | thumbnail: { 61 | name: '缩略图', 62 | type: 'string', 63 | default: '', 64 | max: 500 65 | }, 66 | is_bool: { 67 | name: '真假树', 68 | type: 'tinyInt', 69 | default: 0, 70 | enum: [0, 1] 71 | }, 72 | is_open: { 73 | name: '是否公开', 74 | type: 'tinyInt', 75 | default: 0, 76 | enum: [0, 1] 77 | }, 78 | is_system: { 79 | name: '是否系统账号(不可删除)', 80 | type: 'tinyInt', 81 | default: 0, 82 | enum: [0, 1] 83 | } 84 | }); 85 | -------------------------------------------------------------------------------- /packages/yiapi/todo.md: -------------------------------------------------------------------------------- 1 | ## 待办 2 | 3 | - [ ] 限制图片上传大小 4 | - [ ] 管理上传的图片 5 | - [ ] 同步数据库结构的时候,判断为必须停服维护才可以 6 | - [ ] 处理异步通知问题,可能需要用到消息队列 7 | - [ ] 添加和更新菜单后,管理员可以可以立马看到效果 8 | - [ ] 图片作为日志打印了 9 | - [ ] 图片上传buffer警告问题,写法更新 10 | - [x] 没有改动的系统表不要更新 11 | - [ ] fnInreUUID函数优化为更稳定的版本 12 | - [x] 把syncDatabase函数从内核移出 13 | - [x] 局域网访问 14 | - [ ] 定时还原数据库功能 15 | - [ ] 单点登录 16 | - [ ] jwt 放到redis中,可以被主动踢出功能 17 | - [ ] 拉黑功能 18 | - [ ] 初始化数据库自增模式后,禁止再次改变 19 | - [ ] 支付订单支持优惠码(直接减免),折扣码(百分比)减免 20 | - [x] 系统接口和用户接口重复的判断 21 | - [ ] 增加对控制公众号相关的功能 22 | - [ ] 增加对跨域的配置支持 23 | - [ ] 增加一个配置可视化面板 24 | - [ ] 给接口做隐藏验证,如果不是官方域名的请求,则不予返回数据。 25 | - [ ] 增加监控报错接口和功能 26 | - [ ] 限速要排除微信回调接口 27 | - [ ] 实现在线人数等功能 28 | - [ ] 数据库同步字段名称改变不要删除,把该字段改成其他名称。 29 | - [ ] 提供数据库创建和对比,不提供同步功能。 30 | - [ ] 限制Node.js版本只能为v20 31 | - [ ] 判断process.env.NODE_ENV是否为production或development 32 | - [x] 判断系统接口和用户接口名称冲突问题 33 | - [ ] 缓存使用配置文件统一管理 34 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnApiCheck.js: -------------------------------------------------------------------------------- 1 | // 检查传参有效性 2 | export function fnApiCheck(req) { 3 | return new Promise((resolve, reject) => { 4 | const fields = req.body; 5 | 6 | const fieldsParams = _omit(fields, ['sign']); 7 | 8 | if (_isEmpty(fieldsParams)) { 9 | return resolve({ code: 0, msg: '接口未带参数' }); 10 | } 11 | 12 | if (!fieldsParams.t) { 13 | return reject({ code: 1, msg: '接口请求时间无效' }); 14 | } 15 | 16 | const diffTime = Date.now() - Number(fieldsParams.t); 17 | if (diffTime > 3 * 60 * 1000) { 18 | return reject({ code: 1, msg: '接口请求时间已过期' }); 19 | } 20 | 21 | const paramsValid = fnApiParamsSign(fieldsParams); 22 | 23 | if (paramsValid.sign !== fields.sign) { 24 | return reject({ code: 1, msg: '接口请求参数校验失败', other: paramsValid }); 25 | } 26 | 27 | return resolve({ code: 0, msg: '接口参数正常' }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnApiInfo.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url'; 2 | import { dirname, basename } from 'node:path'; 3 | 4 | export function fnFilename(metaUrl) { 5 | return fileURLToPath(metaUrl); 6 | } 7 | 8 | export function fnDirname(metaUrl) { 9 | const filename = fileURLToPath(metaUrl); 10 | return dirname(filename); 11 | } 12 | 13 | // 获取文件名(不包括扩展名) 14 | export function fnApiInfo(metaUrl) { 15 | const _filename = fnFilename(metaUrl); 16 | const _dirname = fnDirname(metaUrl); 17 | 18 | const pureFileName = basename(_filename, '.js'); 19 | 20 | const parentDirName = _dirname.replace(/\\+/gi, '/').replace(/.+\/apis/, ''); 21 | 22 | const metaFile = dirname(metaUrl) + '/_meta.js'; 23 | 24 | const apiData = { 25 | pureFileName: pureFileName, 26 | parentDirName: parentDirName, 27 | apiPath: [parentDirName, pureFileName].join('/') 28 | }; 29 | 30 | return apiData; 31 | } 32 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnApiPath.js: -------------------------------------------------------------------------------- 1 | // 获取请求的接口路径 2 | export function fnApiPath(metaUrl) { 3 | const apiPath = '/' + path.relative(path.resolve('./apis'), fileURLToPath(metaUrl)).replace('.js', '').replace(/\\+/, '/'); 4 | return apiPath; 5 | } 6 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnApiRaw.js: -------------------------------------------------------------------------------- 1 | // 获取参数按小写排序拼接 2 | export const fnApiRaw = (args) => { 3 | const keys = Object.keys(args).sort(); 4 | const newArgs = keys 5 | .map((key) => { 6 | return `${key.toLowerCase()}=${args[key]}`; 7 | }) 8 | .join('&'); 9 | 10 | return newArgs; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnApiSign.js: -------------------------------------------------------------------------------- 1 | import md5 from 'blueimp-md5'; 2 | // 请求参数签名 3 | export function fnApiParamsSign(params) { 4 | let fieldsArray = []; 5 | _forOwn(params, (value, key) => { 6 | if (value !== undefined && value !== null) { 7 | fieldsArray.push(`${key}=${value}`); 8 | } 9 | }); 10 | 11 | const fieldsSort = fieldsArray.sort().join('&'); 12 | 13 | const fieldsMd5 = md5(fieldsSort); 14 | return { sign: fieldsMd5, sort: fieldsSort }; 15 | } 16 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnClearEmpty.js: -------------------------------------------------------------------------------- 1 | // 清理对象的空数据 2 | export function fnClearEmpty(obj, expludeFields = ['id']) { 3 | let newObj = {}; 4 | _forOwn(obj, (value, key) => { 5 | if (value !== null && value !== undefined) { 6 | newObj[key] = value; 7 | } 8 | }); 9 | return _omit(newObj, expludeFields); 10 | } 11 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnDbInsert.js: -------------------------------------------------------------------------------- 1 | import { appConfig } from '../config/app.js'; 2 | import { fnIncrUID } from '../utils/fnIncrUID.js'; 3 | 4 | export function fnDbInsert(obj) { 5 | const newObj = {}; 6 | for (const key in obj) { 7 | if (obj.hasOwnProperty(key)) { 8 | if (obj[key] !== null && obj[key] !== undefined) { 9 | newObj[key] = obj[key]; 10 | } 11 | } 12 | } 13 | newObj.created_at = Date.now(); 14 | newObj.updated_at = Date.now(); 15 | if (appConfig.tablePrimaryKey !== 'default') { 16 | // 当主键为 time 模式时,更改 id 字段的值 17 | if (appConfig.tablePrimaryKey === 'time') { 18 | newObj.id = fnIncrUID(); 19 | } 20 | } 21 | return newObj; 22 | } 23 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnDbUpdate.js: -------------------------------------------------------------------------------- 1 | export function fnDbUpdate(obj) { 2 | const excludeFields = ['id', 'created_at']; 3 | let newObj = {}; 4 | for (const key in obj) { 5 | if (obj.hasOwnProperty(key)) { 6 | if (obj[key] !== null && obj[key] !== undefined && !excludeFields.includes(key)) { 7 | newObj[key] = obj[key]; 8 | } 9 | } 10 | } 11 | newObj.updated_at = Date.now(); 12 | return newObj; 13 | } 14 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnHashSign.js: -------------------------------------------------------------------------------- 1 | // 创建哈希算法 2 | export const fnHashSign = (algorithm, content) => { 3 | const hash = crypto.createHash(algorithm); 4 | hash.update(content); 5 | return hash.digest('hex'); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnImportAbsolutePath.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, pathToFileURL } from 'node:url'; 2 | 3 | export const fnImportAbsolutePath = async (absolutePath, name, defaultValue) => { 4 | try { 5 | const data = await import(pathToFileURL(absolutePath)); 6 | return data; 7 | } catch (err) { 8 | console.trace('🚀 ~ fnImportAbsolutePath ~ err:', err); 9 | return { 10 | [name]: defaultValue 11 | }; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnImportAppConfig.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, pathToFileURL } from 'node:url'; 2 | import { resolve } from 'node:path'; 3 | import { system } from '../system.js'; 4 | 5 | export const fnImportAppConfig = async (name, defaultValue = {}) => { 6 | try { 7 | const absolutePath = resolve(system.appDir, 'config', name + '.js'); 8 | const data = await import(pathToFileURL(absolutePath)); 9 | return data; 10 | } catch (err) { 11 | console.log('🚀 ~ fnImportAppConfig ~ err:', err); 12 | return { 13 | [name + 'Config']: defaultValue 14 | }; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnImportCoreConfig.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, pathToFileURL } from 'node:url'; 2 | import { resolve } from 'node:path'; 3 | import { system } from '../system.js'; 4 | 5 | export const fnImportCoreConfig = async (name, defaultValue = {}) => { 6 | try { 7 | const absolutePath = resolve(system.yiapiDir, 'config', name + '.js'); 8 | const data = await import(pathToFileURL(absolutePath)); 9 | return data; 10 | } catch (err) { 11 | console.log('🚀 ~ fnImport ~ err:', err); 12 | return { 13 | [name + 'Config']: defaultValue 14 | }; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnImportCoreSchema.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, pathToFileURL } from 'node:url'; 2 | import { resolve } from 'node:path'; 3 | import { system } from '../system.js'; 4 | 5 | export const fnImportCoreSchema = async (name, defaultValue = {}) => { 6 | try { 7 | const absolutePath = resolve(system.yiapiDir, 'schema', name + '.js'); 8 | const data = await import(pathToFileURL(absolutePath)); 9 | return data; 10 | } catch (err) { 11 | console.log('🚀 ~ fnImport ~ err:', err); 12 | return { 13 | [name + 'Schema']: defaultValue 14 | }; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnIncrUID.js: -------------------------------------------------------------------------------- 1 | import { randomInt } from 'node:crypto'; 2 | // 创建顺序自增唯一 ID 3 | export function fnIncrUID() { 4 | const timestamp = Math.floor(Date.now() / 1000); 5 | const random = randomInt(100000, 999999); 6 | return `${timestamp}${random}`; 7 | } 8 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnLuhn.js: -------------------------------------------------------------------------------- 1 | // 信用卡验证算法 2 | export const fnLuhn = (str) => { 3 | const ord = 48; 4 | const textEncoder = new TextEncoder(); 5 | const bytes = textEncoder.encode(String(str)); 6 | let ptr = bytes.length - 1; 7 | let sum = 0; 8 | let mul = 2; 9 | while (ptr >= 0) { 10 | let val = bytes[ptr--] - ord; 11 | val *= mul; 12 | sum += ((val % 10) + val / 10) | 0; 13 | mul = 1 + (mul % 2); 14 | } 15 | return (10 - (sum % 10)) % 10; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnPureMD5.js: -------------------------------------------------------------------------------- 1 | import md5 from 'blueimp-md5'; 2 | // 单纯的 md5 值 3 | export function fnPureMD5(value) { 4 | return md5(value); 5 | } 6 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnRandom6Number.js: -------------------------------------------------------------------------------- 1 | // 随机 6 位数 2 | export function fnRandom6Number() { 3 | return _random(100000, 999999); 4 | } 5 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnRelativePath.js: -------------------------------------------------------------------------------- 1 | export function fnRelativePath(from, to) { 2 | const _relative = path.relative(from, to); 3 | let _covertPath = _relative.replace(/\\+/g, '/'); 4 | 5 | // 如果第一个不是(.),则自动拼接点 6 | if (_covertPath.indexOf('.') !== 0) { 7 | _covertPath = './' + _covertPath; 8 | } 9 | return _covertPath; 10 | } 11 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnRepairEmpty.js: -------------------------------------------------------------------------------- 1 | // 补全空对象 2 | 3 | export function fnRepairEmptyData(obj, expludeFields = ['id']) { 4 | let newObj = {}; 5 | _forOwn(obj, (value, key) => { 6 | if (value !== null && value !== undefined) { 7 | newObj[key] = value; 8 | } else { 9 | newObj[key] = ''; 10 | } 11 | }); 12 | return _omit(newObj, expludeFields); 13 | } 14 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnRouterPath.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 返回路由地址的路径段 3 | * @param {String} url 请求路径(不带 host) 4 | * @returns {String} 返回路径字段 5 | */ 6 | export function fnRouterPath(url) { 7 | const urls = new URL(url, 'http://127.0.0.1'); 8 | const apiPath = urls.pathname; 9 | return apiPath; 10 | } 11 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnRsaSha256.js: -------------------------------------------------------------------------------- 1 | import { createSign } from 'node:crypto'; 2 | // rsa-sha256 加密 3 | export function fnRsaSha256(data, privateKey) { 4 | const sign = createSign('RSA-SHA256'); 5 | sign.update(data); 6 | const signature = sign.sign(privateKey, 'base64'); 7 | return signature; 8 | } 9 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnSaltMD5.js: -------------------------------------------------------------------------------- 1 | import md5 from 'blueimp-md5'; 2 | import { appConfig } from '../config/app.js'; 3 | // 加盐的 md5 值 4 | export function fnSaltMD5(value) { 5 | return md5(value, appConfig.md5Salt); 6 | } 7 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnSchema.js: -------------------------------------------------------------------------------- 1 | export const tableFieldSchemaMap = { 2 | // 字符串型 3 | string: 'string', 4 | // 文本型 5 | mediumText: 'string', 6 | text: 'string', 7 | bigText: 'string', 8 | // 整型 9 | tinyInt: 'integer', 10 | smallInt: 'integer', 11 | mediumInt: 'integer', 12 | int: 'integer', 13 | bigInt: 'integer', 14 | // 浮点型 15 | float: 'number', 16 | // 双精度型 17 | double: 'number' 18 | }; 19 | 20 | export const fnSchema = (field) => { 21 | if (!field) { 22 | throw new Error('字段格式错误'); 23 | } 24 | const params = { 25 | title: field.name, 26 | type: tableFieldSchemaMap[field.type] 27 | }; 28 | if (field.type === 'string') { 29 | if (field.default2 !== undefined) { 30 | params.default = field.default2; 31 | } 32 | if (field.min !== undefined) { 33 | params.minLength = field.min; 34 | } 35 | if (field.max !== undefined) { 36 | params.maxLength = field.max; 37 | } 38 | if (field.enum !== undefined) { 39 | params.enum = field.enum; 40 | } 41 | if (field.pattern !== undefined) { 42 | params.pattern = field.pattern; 43 | } 44 | } 45 | if (field.type === 'integer' || field.type === 'number') { 46 | if (field.default2 !== undefined) { 47 | params.default = field.default2; 48 | } 49 | if (field.min !== undefined) { 50 | params.minimum = field.min; 51 | } 52 | if (field.max !== undefined) { 53 | params.maximum = field.max; 54 | } 55 | if (field.enum !== undefined) { 56 | params.enum = field.enum; 57 | } 58 | if (field.multipleOf !== undefined) { 59 | params.multipleOf = field.multipleOf; 60 | } 61 | } 62 | 63 | return params; 64 | }; 65 | -------------------------------------------------------------------------------- /packages/yiapi/utils/fnUUID.js: -------------------------------------------------------------------------------- 1 | import { customAlphabet } from 'nanoid'; 2 | // 自定义初始化字符 3 | const nanoid = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 26); 4 | // 随机 hash 值 5 | export function fnUUID(size = 26) { 6 | return nanoid(size); 7 | } 8 | -------------------------------------------------------------------------------- /packages/yiapi/utils/getCacheName.js: -------------------------------------------------------------------------------- 1 | export const getCacheName = (str) => { 2 | return `cacheData:${str}`; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yiapi/utils/getDbFields.js: -------------------------------------------------------------------------------- 1 | export const getDbFields = (tableData, exclude = []) => { 2 | const defaultFields = ['id', 'created_at', 'updated_at', 'deleted_at']; 3 | const selectFields = Object.keys(tableData).filter((field) => !exclude[field]); 4 | return [...defaultFields, ...selectFields]; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/yiapi/utils/isPortOpen.js: -------------------------------------------------------------------------------- 1 | import { createServer as net_createServer, Server as net_Server } from 'node:net'; 2 | // 端口是否打开 3 | export const fnIsPortOpen = (port) => { 4 | return new Promise((resolve, reject) => { 5 | const server = net_createServer(); 6 | 7 | server.on('error', (err) => { 8 | if (err.code === 'EADDRINUSE') { 9 | resolve(false); 10 | } else { 11 | reject(err); 12 | } 13 | }); 14 | server.on('listening', (data) => { 15 | server.close(() => { 16 | resolve(true); 17 | }); 18 | }); 19 | 20 | server.listen(port); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/yibase/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | esdata 6 | data 7 | .cache 8 | lab 9 | labs 10 | cache 11 | .VSCodeCounter 12 | oclif.manifest.json 13 | dist 14 | report.html 15 | dist-ssr 16 | *.local 17 | .vscode-test/ 18 | *.vsix 19 | out 20 | CHANGELOG.md 21 | note.md 22 | .changeset 23 | 24 | # Editor directories and files 25 | .vscode/* 26 | .cache 27 | .yicode/auto-imports.d.ts 28 | !.vscode/extensions.json 29 | .idea 30 | .DS_Store 31 | *.suo 32 | *.ntvs* 33 | *.njsproj 34 | *.sln 35 | *.sw? 36 | 37 | # Runtime data 38 | pids 39 | *.pid 40 | *.seed 41 | 42 | # Directory for instrumented libs generated by jscoverage/JSCover 43 | lib-cov 44 | 45 | # Coverage directory used by tools like istanbul 46 | coverage 47 | 48 | # nyc test coverage 49 | .nyc_output 50 | 51 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 52 | .grunt 53 | 54 | # node-waf configuration 55 | .lock-wscript 56 | 57 | # Compiled binary addons (http://nodejs.org/api/addons.html) 58 | build/Release 59 | 60 | # Dependency directories 61 | node_modules 62 | jspm_packages 63 | 64 | # Optional npm cache directory 65 | .npm 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # 0x 71 | profile-* 72 | 73 | # mac files 74 | .DS_Store 75 | 76 | # vim swap files 77 | *.swp 78 | 79 | # webstorm 80 | .idea 81 | 82 | # vscode 83 | .vscode 84 | *code-workspace 85 | 86 | # clinic 87 | profile* 88 | *clinic* 89 | *flamegraph* 90 | -------------------------------------------------------------------------------- /packages/yibase/.npmignore: -------------------------------------------------------------------------------- 1 | dist 2 | .cache 3 | CHANGELOG.md -------------------------------------------------------------------------------- /packages/yibase/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 1024, 7 | "bracketSpacing": true, 8 | "useTabs": false, 9 | "arrowParens": "always" 10 | } 11 | -------------------------------------------------------------------------------- /packages/yibase/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | yibase-template 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/yibase/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "baseUrl": "./", 6 | "paths": { 7 | "@/*": ["src/*"] 8 | } 9 | }, 10 | "exclude": ["node_modules", "dist"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/yibase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/yibase", 3 | "version": "1.5.2", 4 | "description": "vue3 + vite + yite-cli 基础开发模板", 5 | "sideEffects": true, 6 | "type": "module", 7 | "private": false, 8 | "publishConfig": { 9 | "access": "public", 10 | "registry": "https://registry.npmjs.org" 11 | }, 12 | "scripts": { 13 | "dev": "yite --command=dev --envfile=development --workdir=./", 14 | "build": "yite --command=build --envfile=production --workdir=./" 15 | }, 16 | "keywords": [ 17 | "lodash", 18 | "utils", 19 | "helper", 20 | "help" 21 | ], 22 | "author": "chensuiyi ", 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/chenbimo/yicode.git" 26 | }, 27 | "homepage": "https://chensuiyi.me", 28 | "dependencies": { 29 | "@iconify/json": "^2.2.232", 30 | "@yicode/yite-cli": "^2.8.0", 31 | "axios": "^1.7.2", 32 | "pinia": "^2.2.0", 33 | "sass": "^1.77.8", 34 | "store2": "^2.14.3", 35 | "vue": "^3.4.34", 36 | "vue-i18n": "^9.13.1", 37 | "vue-router": "^4.4.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/yibase/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yibase/public/logo.png -------------------------------------------------------------------------------- /packages/yibase/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /packages/yibase/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yibase/src/assets/logo.png -------------------------------------------------------------------------------- /packages/yibase/src/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yibase/src/components/.gitkeep -------------------------------------------------------------------------------- /packages/yibase/src/config/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yibase/src/config/.gitkeep -------------------------------------------------------------------------------- /packages/yibase/src/env/.env: -------------------------------------------------------------------------------- 1 | # 项目名 2 | VITE_PROJECT_NAME="base-vue3222" -------------------------------------------------------------------------------- /packages/yibase/src/env/.env.development: -------------------------------------------------------------------------------- 1 | VITE_HOST="http://127.0.0.1:3000/api" 2 | # VITE_HOST=https://api-nav.yicode.tech 3 | VITE_NAMESPACE="dev.yibase-vue3" -------------------------------------------------------------------------------- /packages/yibase/src/env/.env.production: -------------------------------------------------------------------------------- 1 | VITE_HOST="http://127.0.0.1:3000/api" 2 | VITE_NAMESPACE="pro.yibase-vue3" -------------------------------------------------------------------------------- /packages/yibase/src/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test" 3 | } 4 | -------------------------------------------------------------------------------- /packages/yibase/src/i18n/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "测试" 3 | } 4 | -------------------------------------------------------------------------------- /packages/yibase/src/layouts/default/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 30 | 31 | 35 | -------------------------------------------------------------------------------- /packages/yibase/src/layouts/other/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 30 | 31 | 35 | -------------------------------------------------------------------------------- /packages/yibase/src/main.js: -------------------------------------------------------------------------------- 1 | import App from '@/App.vue'; 2 | 3 | const app = createApp(App); 4 | 5 | const $Pinia = Pinia.createPinia(); 6 | 7 | app.use($Router); 8 | app.use($Pinia); 9 | app.use($I18n); 10 | 11 | app.mount('#app'); 12 | -------------------------------------------------------------------------------- /packages/yibase/src/pages/index/components/t1.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /packages/yibase/src/pages/index/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | -------------------------------------------------------------------------------- /packages/yibase/src/pages/index/route.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'dafdf' 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yibase/src/pages/news/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /packages/yibase/src/pages/news/route.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '111', 3 | layout: 'other' 4 | }; 5 | -------------------------------------------------------------------------------- /packages/yibase/src/plugins/http.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const $Http = axios.create({ 4 | method: 'POST', 5 | baseURL: import.meta.env.VITE_HOST, 6 | timeout: 1000 * 60, 7 | withCredentials: false, 8 | responseType: 'json', 9 | responseEncoding: 'utf8', 10 | headers: {} 11 | }); 12 | // 添加请求拦截器 13 | $Http.interceptors.request.use( 14 | function (config) { 15 | const token = $Storage.local.get('token'); 16 | if (token) { 17 | config.headers.authorization = 'Bearer ' + token; 18 | } 19 | return config; 20 | }, 21 | function (error) { 22 | return Promise.reject(error); 23 | } 24 | ); 25 | 26 | // 添加响应拦截器 27 | $Http.interceptors.response.use( 28 | function (res) { 29 | if (res.data.code === 0) { 30 | return Promise.resolve(res.data); 31 | } 32 | 33 | return Promise.reject(res.data); 34 | }, 35 | function (error) { 36 | console.log('🚀 ~ error:', error); 37 | } 38 | ); 39 | export { $Http }; 40 | -------------------------------------------------------------------------------- /packages/yibase/src/plugins/i18n.js: -------------------------------------------------------------------------------- 1 | import { yiteMessages } from 'virtual:yite-messages'; 2 | 3 | const $I18n = createI18n({ 4 | locale: 'zh', 5 | messages: await yiteMessages() 6 | }); 7 | 8 | export { $I18n }; 9 | -------------------------------------------------------------------------------- /packages/yibase/src/plugins/router.js: -------------------------------------------------------------------------------- 1 | import { yiteRoutes } from 'virtual:yite-router'; 2 | 3 | // 创建路由 4 | const $Router = createRouter({ 5 | routes: yiteRoutes(), 6 | history: createWebHashHistory() 7 | }); 8 | 9 | export { $Router }; 10 | -------------------------------------------------------------------------------- /packages/yibase/src/plugins/storage.js: -------------------------------------------------------------------------------- 1 | import store2 from 'store2'; 2 | const $Storage = store2.namespace(import.meta.env.VITE_NAMESPACE); 3 | 4 | // 提供给手动导入使用 5 | export { $Storage }; 6 | -------------------------------------------------------------------------------- /packages/yibase/src/stores/useGlobal.js: -------------------------------------------------------------------------------- 1 | export const useGlobal = Pinia.defineStore('global', () => { 2 | // 全局数据 3 | const $GlobalData = $ref({ 4 | // 用户令牌 5 | token: $Storage.local.get('token') || '', 6 | // 用户数据 7 | userData: $Storage.local.get('userData') || {} 8 | }); 9 | 10 | // 全局计算数据 11 | const $GlobalComputed = {}; 12 | 13 | // 全局方法 14 | const $GlobalMethod = {}; 15 | 16 | return { 17 | $GlobalData, 18 | $GlobalComputed, 19 | $GlobalMethod 20 | }; 21 | }); 22 | -------------------------------------------------------------------------------- /packages/yibase/src/styles/global.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yibase/src/styles/global.scss -------------------------------------------------------------------------------- /packages/yibase/src/styles/variable.scss: -------------------------------------------------------------------------------- 1 | $layout-wrapper-width: 1200px; 2 | $layout-header-height: 54px; 3 | -------------------------------------------------------------------------------- /packages/yibase/src/utils/index.js: -------------------------------------------------------------------------------- 1 | export const utilGetAssets = (name) => { 2 | return new URL(`../assets/${name}`, import.meta.url).href; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yibase/uno.config.js: -------------------------------------------------------------------------------- 1 | import { unocssConfig } from '@yicode/yite-cli/unocss.js'; 2 | import { defineConfig } from 'unocss'; 3 | export default defineConfig(unocssConfig); 4 | -------------------------------------------------------------------------------- /packages/yibase/yite.config.js: -------------------------------------------------------------------------------- 1 | export const yiteConfig = { 2 | devtool: false, 3 | // 自动导入解析 4 | autoImport: { 5 | resolvers: [] 6 | }, 7 | // 自动组件解析 8 | autoComponent: { 9 | resolvers: [] 10 | }, 11 | // webpack 配置 12 | viteConfig: { 13 | optimizeDeps: { 14 | include: [ 15 | // 16 | 'vue-i18n', 17 | 'axios', 18 | 'store2' 19 | ] 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /packages/yidocs/.vitepress/theme/index.js: -------------------------------------------------------------------------------- 1 | import DefaultTheme from 'vitepress/theme'; 2 | import './style/custom.css'; 3 | import homeMore from './components/homeMore.vue'; 4 | export default { 5 | extends: DefaultTheme, 6 | enhanceApp({ app, router, siteData }) { 7 | app.component('homeMore', homeMore); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/yidocs/index.js: -------------------------------------------------------------------------------- 1 | import fg from 'fast-glob'; 2 | import { dirname, basename } from 'node:path'; 3 | import { renameSync } from 'node:fs'; 4 | const files = fg.sync(['markdown/**/[[:digit:]]#*'], { dot: true, onlyDirectories: true }); 5 | files.reverse().forEach((file) => { 6 | const basename2 = basename(file).replace('#', '-'); 7 | const dirname2 = dirname(file); 8 | const file2 = `${dirname2}/${basename2}`; 9 | renameSync(file, file2); 10 | // console.log('🚀 ~ files.forEach ~ file2:', file2); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/yidocs/markdown/9-关于我们/1-关于我们/1-个人介绍.md: -------------------------------------------------------------------------------- 1 | ## 关于作者 2 | 3 | > 微信号:`chensuiyime` 4 | > 5 | > 个人网站:`https://chensuiyi.me` 6 | 7 | 一个在折腾路上狂奔的程序员。 8 | 9 | 何以解忧,唯有代码,不忘初心,方得始终。 10 | 11 | ## 时间线 12 | 13 | - `1993年` 诞生,男,身高数尺,日食三餐。 14 | - `2011年` 高二,重点高中转职高从高一读起,学计算机专业。 15 | - `2015年` 大二读完挂 8 科,退学,找了一个月工作后,进行 PHP 实习。 16 | - `2016年` 经网友介绍,做前端,半年后独立负责整个项目前后端,步入全栈。 17 | - `2017年` 做前端线下讲师,教学方式无人懂,或者说一般人不适合我自己的学习模式 18 | - `2018年` 喜欢上了游戏开发,于是找了个游戏公司做游戏前端,加班多,凌晨 1,2 点下班。 19 | - `2019年` 依旧心怀天下,想把自己的学习模式分享出去,于是做前端线上讲师,下半年离职后,做远程技术顾问。 20 | - `2020年` 跟朋友合伙创业、加班、熬夜,利用下班时间做开源项目。 21 | - `2021年` 因为家里发生了一些事情,离职回到老家全职接单,月入 2000,抽空写开源。 22 | - `2022年` 继续接单,收入赶上工资,业余写开源项目。 23 | - `2023年` 注册公司,产品 + 文章,收入甚微,饥肠辘辘,做更有价值的长期主义者。 24 | - `2024年` 继续在 `开源商业化`、`独立产品`、`知识付费` 的方向上狂奔。 25 | 26 | ## 我的现状 27 | 28 | 在职业生涯的第 `5` 年,也就是 `2020` 年回到农村,从此再也没有出去工作过。 29 | 30 | 现在是自由职业,独立开发者,创业者。 31 | 32 | 我想,我这辈子都不会再去上班了。 33 | 34 | 写开源,写文章,写产品,写小说,这就是我想做的事情,我的人生意义所在。 35 | 36 | 如果想跟我交流探索自由职业,独立开发,副业搞钱,请加我微信:`chensuiyime` 37 | 38 | ## 人生忠告 39 | 40 | 年轻人,一定要多读书! 41 | 42 | 社会很残酷! 43 | 44 | 至少拿个本科文凭再出来混!不然会损失很多机会! 45 | 46 | 1. 不要躺平,命由天定,人定胜天! 47 | 2. 提高自身能力,才能吸引到更多机会。 48 | 3. 多结交有实力的朋友,他们可能会产生机会。 49 | 4. 业余探索副业收入,从现在开始,不要等待! 50 | 5. 减少无效的抱怨,多思考如何脱离困境。 51 | 52 | ## 赞赏支持我 53 | 54 | 如果你是在微信公众号看到这篇作者介绍的,可以直接赞赏我 55 | 56 | 如果你是在其他地方看到这篇作者介绍的,可以赞助支持我 57 | 58 | ![赞赏](https://static.yicode.tech/images/zan-shang.jpg) 59 | 60 | ## 更多故事 61 | 62 | 可以前往这篇文章[农村程序员&独立开发者,在村里各处写代码的日常与一路走来的历程](https://juejin.cn/post/7294509366556262463)查看 63 | -------------------------------------------------------------------------------- /packages/yidocs/markdown/9-关于我们/1-关于我们/2-微信群守则.md: -------------------------------------------------------------------------------- 1 | 易编程 - 微信群守则 2 | 3 | 关于群主:https://chensuiyi.me 4 | 5 | ## 可以进行 6 | 7 | - 副业搞钱、点子思路、合作合伙、软件创意。 8 | - 技术交流,问题咨询、编程分享、求职招聘。 9 | - 日常生活、个人爱好、技术资讯、个人介绍。 10 | - 打广告可以私聊群主确认,合法合规合理的广告是支持的。 11 | 12 | ## 不要进行 13 | 14 | - 政治军事、娱乐明星、国际舆论等。 15 | - 黄、赌、毒等相关。 16 | - 负能量、黑产、暴力等。 17 | - 不要讨论各种敏感话题。 18 | - 不要进行人身攻击等。 19 | 20 | ## 交流提问 21 | 22 | - 问题背景、截图、描述、期望结果、目前的问题。 23 | - 不要打击任何人的积极性。 24 | - 不要质疑任何人的生活、习惯。 25 | - 多分享自己的作品,经验、软件。 26 | 27 | ## 关于私聊 28 | 29 | - 贸然加好友,有可能会打扰到私人时间。 30 | - 不过本群不对加好友做任何干涉。 31 | - 有广告乱加人的,可以艾特群主举报。 32 | - 请谨慎鉴别,跟钱和个人信息相关的谨慎分享。 33 | -------------------------------------------------------------------------------- /packages/yidocs/markdown/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | hero: 5 | name: 陈随易 6 | text: 生命不息,折腾不止。 7 | tagline: 何以解忧,唯有代码,不忘初心,方得始终。 8 | image: 9 | src: /logo5.png 10 | alt: VitePress 11 | actions: 12 | - theme: brand 13 | text: 微信:chensuiyime 14 | - theme: brand 15 | text: 扣扣:24323626 16 | 17 | features: 18 | - icon: 🍓 19 | title: 随易周刊 20 | details: 平均每周一期的随易观世界 21 | link: /5-随易周刊/1-随易周刊/1-第0001期 22 | - icon: 🍄 23 | title: 自律记录 24 | details: 陈随易的2024年自律记录 25 | link: /9-关于我们/2-自律记录/1-2024年/1-年度计划 26 | - icon: 🍒 27 | title: 关于我 28 | details: 一个在折腾之路上狂奔的疯子 29 | link: /9-关于我们/1-关于我们/1-个人介绍 30 | - icon: 🚀 31 | title: 开源项目 32 | details: 自2019年持续维护、更新、完善至今 33 | link: https://github.com/chenbimo/yicode 34 | --- 35 | 36 | 37 | -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/favicon.ico -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/index.js: -------------------------------------------------------------------------------- 1 | const swiper = new Swiper('.swiper', { 2 | slidesPerView: 3, 3 | spaceBetween: 30, 4 | pagination: { 5 | el: '.swiper-pagination', 6 | clickable: true 7 | }, 8 | 9 | navigation: { 10 | nextEl: '.swiper-button-next', 11 | prevEl: '.swiper-button-prev' 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo.jpg -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/bimostyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/bimostyle.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/fnMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/fnMap.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/hello-iam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/hello-iam.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/markdown-style.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/markdown-style.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/my-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/my-service.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/npm-nice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/npm-nice.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/open-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/open-source.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo/yitodo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo/yitodo.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo2.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo3.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo4.png -------------------------------------------------------------------------------- /packages/yidocs/markdown/public/logo5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocs/markdown/public/logo5.png -------------------------------------------------------------------------------- /packages/yidocs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/yidocs", 3 | "version": "3.3.13", 4 | "description": "陈随易的网站", 5 | "type": "module", 6 | "main": "index.js", 7 | "private": false, 8 | "publishConfig": { 9 | "access": "public", 10 | "registry": "https://registry.npmjs.org" 11 | }, 12 | "scripts": { 13 | "dev": "vitepress dev", 14 | "build": "vitepress build" 15 | }, 16 | "keywords": [], 17 | "author": "陈随易 ", 18 | "license": "ISC", 19 | "dependencies": { 20 | "@yicode/yidocs-auto": "^1.6.3" 21 | }, 22 | "devDependencies": { 23 | "vitepress": "^1.3.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/yidocsAuto/.gitignore: -------------------------------------------------------------------------------- 1 | examples -------------------------------------------------------------------------------- /packages/yidocsAuto/.npmignore: -------------------------------------------------------------------------------- 1 | examples -------------------------------------------------------------------------------- /packages/yidocsAuto/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocsAuto/assets/1.png -------------------------------------------------------------------------------- /packages/yidocsAuto/assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yidocsAuto/assets/2.png -------------------------------------------------------------------------------- /packages/yidocsAuto/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/yidocs-auto", 3 | "version": "1.6.3", 4 | "description": "vitepress 导航和侧边栏自动生成工具", 5 | "type": "module", 6 | "private": false, 7 | "publishConfig": { 8 | "access": "public", 9 | "registry": "https://registry.npmjs.org" 10 | }, 11 | "exports": { 12 | ".": "./index.js" 13 | }, 14 | "sideEffects": true, 15 | "scripts": {}, 16 | "keywords": [ 17 | "lodash", 18 | "utils", 19 | "helper", 20 | "help" 21 | ], 22 | "author": "chensuiyi ", 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/chenbimo/yidocs-auto" 26 | }, 27 | "homepage": "https://chensuiyi.me", 28 | "dependencies": { 29 | "colorette": "^2.0.20", 30 | "fast-glob": "^3.3.2", 31 | "lodash-es": "^4.17.21" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/yiserver/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | esdata 6 | data 7 | .npmrc 8 | .cache 9 | lab 10 | labs 11 | cache 12 | .npmrc 13 | .VSCodeCounter 14 | oclif.manifest.json 15 | dist 16 | report.html 17 | dist-ssr 18 | *.local 19 | .vscode-test/ 20 | *.vsix 21 | out 22 | CHANGELOG.md 23 | note.md 24 | .changeset 25 | 26 | # Editor directories and files 27 | .vscode/* 28 | .cache 29 | .yicode/auto-imports.d.ts 30 | !.vscode/extensions.json 31 | .idea 32 | .DS_Store 33 | *.suo 34 | *.ntvs* 35 | *.njsproj 36 | *.sln 37 | *.sw? 38 | 39 | # Runtime data 40 | pids 41 | *.pid 42 | *.seed 43 | 44 | # Directory for instrumented libs generated by jscoverage/JSCover 45 | lib-cov 46 | 47 | # Coverage directory used by tools like istanbul 48 | coverage 49 | 50 | # nyc test coverage 51 | .nyc_output 52 | 53 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 54 | .grunt 55 | 56 | # node-waf configuration 57 | .lock-wscript 58 | 59 | # Compiled binary addons (http://nodejs.org/api/addons.html) 60 | build/Release 61 | 62 | # Dependency directories 63 | node_modules 64 | jspm_packages 65 | 66 | # Optional npm cache directory 67 | .npm 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # 0x 73 | profile-* 74 | 75 | # mac files 76 | .DS_Store 77 | 78 | # vim swap files 79 | *.swp 80 | 81 | # webstorm 82 | .idea 83 | 84 | # vscode 85 | .vscode 86 | *code-workspace 87 | 88 | # clinic 89 | profile* 90 | *clinic* 91 | *flamegraph* 92 | -------------------------------------------------------------------------------- /packages/yiserver/.npmignore: -------------------------------------------------------------------------------- 1 | dist 2 | .cache 3 | CHANGELOG.md -------------------------------------------------------------------------------- /packages/yiserver/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 1024, 7 | "bracketSpacing": true, 8 | "useTabs": false, 9 | "arrowParens": "always" 10 | } 11 | -------------------------------------------------------------------------------- /packages/yiserver/apis/admin/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | // 目录名称 3 | dirName: '管理表', 4 | // 接口名称 5 | apiNames: { 6 | insert: '添加功能演示', 7 | delete2: '删除功能演示', 8 | select: '分页功能演示', 9 | update: '更新功能演示', 10 | detail: '详情功能演示' 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /packages/yiserver/apis/admin/delete2.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute, fnSchema } from '@yicode/yiapi/fn.js'; 3 | // 配置文件 4 | import { httpConfig } from '@yicode/yiapi/config/http.js'; 5 | import { schemaHelperConfig } from '@yicode/yiapi/config/schemaHelper.js'; 6 | // 接口元数据 7 | import { metaConfig } from './_meta.js'; 8 | 9 | export default async (fastify) => { 10 | // 当前文件的路径,fastify 实例 11 | fnRoute(import.meta.url, fastify, metaConfig, { 12 | // 请求参数约束 13 | schemaRequest: { 14 | type: 'object', 15 | properties: { 16 | id: fnSchema(schemaHelperConfig.id) 17 | }, 18 | required: ['id'] 19 | }, 20 | // 执行函数 21 | apiHandler: async (req, res) => { 22 | try { 23 | const newsModel = fastify.mysql // 24 | .table('news') 25 | .modify(function (qb) {}); 26 | 27 | const result = await newsModel.clone().where('id', req.body.id).deleteData(); 28 | 29 | return { 30 | ...httpConfig.INSERT_SUCCESS, 31 | data: result 32 | }; 33 | } catch (err) { 34 | fastify.log.error(err); 35 | return httpConfig.SELECT_FAIL; 36 | } 37 | } 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /packages/yiserver/apis/example/_meta.js: -------------------------------------------------------------------------------- 1 | export const metaConfig = { 2 | // 目录名称 3 | dirName: '演示表', 4 | // 接口名称 5 | apiNames: { 6 | insert: '添加功能演示', 7 | delete: '删除功能演示', 8 | select: '分页功能演示', 9 | update: '更新功能演示', 10 | detail: '详情功能演示' 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /packages/yiserver/apis/example/delete.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute, fnSchema } from '@yicode/yiapi/fn.js'; 3 | // 配置文件 4 | import { httpConfig } from '@yicode/yiapi/config/http.js'; 5 | import { schemaHelperConfig } from '@yicode/yiapi/config/schemaHelper.js'; 6 | // 数据库表 7 | import { tableData } from '../../tables/example.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | id: fnSchema(schemaHelperConfig.id) 19 | }, 20 | required: ['id'] 21 | }, 22 | // 执行函数 23 | apiHandler: async (req, res) => { 24 | try { 25 | const newsModel = fastify.mysql // 26 | .table('news') 27 | .modify(function (qb) {}); 28 | 29 | const result = await newsModel.clone().where('id', req.body.id).deleteData(); 30 | 31 | return { 32 | ...httpConfig.INSERT_SUCCESS, 33 | data: result 34 | }; 35 | } catch (err) { 36 | fastify.log.error(err); 37 | return httpConfig.SELECT_FAIL; 38 | } 39 | } 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /packages/yiserver/apis/example/detail.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute, fnSchema } from '@yicode/yiapi/fn.js'; 3 | // 配置文件 4 | import { httpConfig } from '@yicode/yiapi/config/http.js'; 5 | import { schemaHelperConfig } from '@yicode/yiapi/config/schemaHelper.js'; 6 | // 数据库表 7 | import { tableData } from '../../tables/example.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | id: fnSchema(schemaHelperConfig.id) 19 | }, 20 | required: ['id'] 21 | }, 22 | 23 | // 执行函数 24 | apiHandler: async (req, res) => { 25 | try { 26 | const newsModel = fastify.mysql.table('news'); 27 | 28 | const result = await newsModel // 29 | .clone() 30 | .where({ id: req.body.id }) 31 | .selectOne(); 32 | 33 | return { 34 | ...httpConfig.SELECT_SUCCESS, 35 | data: result 36 | }; 37 | } catch (err) { 38 | fastify.log.error(err); 39 | return httpConfig.SELECT_FAIL; 40 | } 41 | } 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /packages/yiserver/apis/example/insert.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute, fnSchema } from '@yicode/yiapi/fn.js'; 3 | // 配置文件 4 | import { httpConfig } from '@yicode/yiapi/config/http.js'; 5 | import { schemaHelperConfig } from '@yicode/yiapi/config/schemaHelper.js'; 6 | // 数据库表 7 | import { tableData } from '../../tables/example.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | nickname: fnSchema(tableData.nickname), 19 | age: fnSchema(tableData.age) 20 | }, 21 | required: ['title'] 22 | }, 23 | 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | const trx = await fastify.mysql.transaction(); 27 | try { 28 | const newsModel = trx('news'); 29 | 30 | const result = await newsModel // 31 | .clone() 32 | .insertData({ 33 | title: req.body.title, 34 | thumbnail: req.body.thumbnail, 35 | content: req.body.content 36 | }); 37 | 38 | throw new Error('123'); 39 | await trx.commit(); 40 | return { 41 | ...httpConfig.INSERT_SUCCESS, 42 | data: result 43 | }; 44 | } catch (err) { 45 | await trx.rollback(); 46 | fastify.log.error(err); 47 | return httpConfig.INSERT_FAIL; 48 | } 49 | } 50 | }); 51 | }; 52 | -------------------------------------------------------------------------------- /packages/yiserver/apis/example/select.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute, fnSchema } from '@yicode/yiapi/fn.js'; 3 | // 配置文件 4 | import { httpConfig } from '@yicode/yiapi/config/http.js'; 5 | import { schemaHelperConfig } from '@yicode/yiapi/config/schemaHelper.js'; 6 | // 数据库表 7 | import { tableData } from '../../tables/example.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | page: fnSchema(schemaHelperConfig.page), 19 | limit: fnSchema(schemaHelperConfig.limit) 20 | }, 21 | required: [] 22 | }, 23 | 24 | // 执行函数 25 | apiHandler: async (req, res) => { 26 | try { 27 | const newsModel = fastify.mysql // 28 | .table('news') 29 | .modify(function (qb) {}); 30 | 31 | // 记录总数 32 | const { totalCount } = await newsModel 33 | .clone() // 34 | .selectCount(); 35 | 36 | // 记录列表 37 | const rows = await newsModel 38 | .clone() // 39 | .orderBy('created_at', 'desc') 40 | .selectData(req.body.page, req.body.limit); 41 | 42 | return { 43 | ...httpConfig.SELECT_SUCCESS, 44 | data: { 45 | total: totalCount, 46 | rows: rows, 47 | page: req.body.page, 48 | limit: req.body.limit 49 | } 50 | }; 51 | } catch (err) { 52 | fastify.log.error(err); 53 | return httpConfig.SELECT_FAIL; 54 | } 55 | } 56 | }); 57 | }; 58 | -------------------------------------------------------------------------------- /packages/yiserver/apis/example/update.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | import { fnRoute, fnSchema } from '@yicode/yiapi/fn.js'; 3 | // 配置文件 4 | import { httpConfig } from '@yicode/yiapi/config/http.js'; 5 | import { schemaHelperConfig } from '@yicode/yiapi/config/schemaHelper.js'; 6 | // 数据库表 7 | import { tableData } from '../../tables/example.js'; 8 | // 接口元数据 9 | import { metaConfig } from './_meta.js'; 10 | 11 | export default async (fastify) => { 12 | // 当前文件的路径,fastify 实例 13 | fnRoute(import.meta.url, fastify, metaConfig, { 14 | // 请求参数约束 15 | schemaRequest: { 16 | type: 'object', 17 | properties: { 18 | id: fnSchema(schemaHelperConfig.id), 19 | nickname: fnSchema(tableData.nickname), 20 | age: fnSchema(tableData.age) 21 | }, 22 | required: ['id'] 23 | }, 24 | 25 | // 执行函数 26 | apiHandler: async (req, res) => { 27 | try { 28 | const newsModel = fastify.mysql.table('news'); 29 | 30 | const result = await newsModel // 31 | .clone() 32 | .where('id', req.body.id) 33 | .updateData({ 34 | title: req.body.title, 35 | thumbnail: req.body.thumbnail, 36 | content: req.body.content 37 | }); 38 | 39 | return { 40 | ...httpConfig.INSERT_SUCCESS, 41 | data: result 42 | }; 43 | } catch (err) { 44 | fastify.log.error(err); 45 | return httpConfig.INSERT_FAIL; 46 | } 47 | } 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /packages/yiserver/config/app.js: -------------------------------------------------------------------------------- 1 | export const appConfig = { 2 | devPassword: 'dev123456', 3 | md5Salt: 'yiapi-123456.', 4 | isSwagger: true 5 | }; 6 | -------------------------------------------------------------------------------- /packages/yiserver/config/blackApis.js: -------------------------------------------------------------------------------- 1 | export const blackApisConfig = []; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/blackMenus.js: -------------------------------------------------------------------------------- 1 | export const blackMenusConfig = []; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/callback.js: -------------------------------------------------------------------------------- 1 | export const callbackConfig = { 2 | // 微信消息回调 3 | weixinMessage(fastify, options) { 4 | console.log('🚀 ~ file: callback.js:2 ~ messageCallback ~ options:', options); 5 | }, 6 | // 微信支付回调 7 | weixinPayNotify(fastify, options) { 8 | console.log('🚀 ~ file: callback.js:7 ~ weixinPayNotify ~ options:', options); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/yiserver/config/cron.js: -------------------------------------------------------------------------------- 1 | // 定时器设置 2 | export const cronConfig = [ 3 | // { 4 | // timer: '*/5 * * * * *', 5 | // name: '测试定时器', 6 | // code: 'test', 7 | // handler: (yiapi) => { 8 | // if (cluster.isPrimary) { 9 | // console.log(`主进程 ${process.pid}`); 10 | // } else { 11 | // console.log(`客进程 ${process.pid}`); 12 | // } 13 | // } 14 | // } 15 | ]; 16 | -------------------------------------------------------------------------------- /packages/yiserver/config/custom.js: -------------------------------------------------------------------------------- 1 | // 自定义配置 2 | const customConfig = { 3 | tencentCloud: { 4 | secretId: '', 5 | secretKey: '', 6 | bucket: '', 7 | region: '' 8 | } 9 | }; 10 | 11 | export { customConfig }; 12 | -------------------------------------------------------------------------------- /packages/yiserver/config/dbField.js: -------------------------------------------------------------------------------- 1 | export const dbFieldConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/freeApis.js: -------------------------------------------------------------------------------- 1 | export const freeApisConfig = [ 2 | // 3 | '/api/tool/tokenCheck', 4 | '/api/admin/login', 5 | '/api/weixin/loginCheck', 6 | '/api/weixin/getConfg', 7 | '/api/weixin/loginQrcode', 8 | '/api/weixin/message', 9 | '/api/weixin/payNotify' 10 | ]; 11 | -------------------------------------------------------------------------------- /packages/yiserver/config/http.js: -------------------------------------------------------------------------------- 1 | export const httpConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/jwt.js: -------------------------------------------------------------------------------- 1 | export const jwtConfig = { 2 | secret: 'yiapi', 3 | expiresIn: '7d' 4 | }; 5 | -------------------------------------------------------------------------------- /packages/yiserver/config/key.js: -------------------------------------------------------------------------------- 1 | // 微信私有key 2 | export const weixinPrivateKey = ` 3 | -----BEGIN PRIVATE KEY----- 4 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqsJG8J92865oZ 5 | b6mQQ5Y1w8Pa0FOf2yiyWyKJjsBx6XorTBX/O0kndDkb1rPJ7b5tStJMHRYqunOc 6 | wnY3w/CoAxxH08yrMUvEVLs= 7 | -----END PRIVATE KEY----- 8 | `; 9 | -------------------------------------------------------------------------------- /packages/yiserver/config/logFilter.js: -------------------------------------------------------------------------------- 1 | export const logFilterConfig = []; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/mail.js: -------------------------------------------------------------------------------- 1 | export const mailConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/menu.js: -------------------------------------------------------------------------------- 1 | // 自定义菜单 2 | export const menuConfig = { 3 | // 自定义菜单演示 4 | // '/keyword': { 5 | // name: '关键字', 6 | // sort: 2, 7 | // children: { 8 | // '/keyword/list': { 9 | // name: '关键字列表', 10 | // sort: 1 11 | // } 12 | // } 13 | // } 14 | }; 15 | -------------------------------------------------------------------------------- /packages/yiserver/config/mysql.js: -------------------------------------------------------------------------------- 1 | export const mysqlConfig = { 2 | // 开发环境配置 3 | development: { 4 | host: '127.0.0.1', 5 | port: 3306, 6 | db: 'test3', 7 | username: 'root', 8 | password: 'root' 9 | }, 10 | // 生产环境配置 11 | production: { 12 | host: '127.0.0.1', 13 | port: 3306, 14 | db: 'test', 15 | username: 'root', 16 | password: 'root' 17 | } 18 | }[process.env.NODE_ENV || 'development']; 19 | -------------------------------------------------------------------------------- /packages/yiserver/config/payment.js: -------------------------------------------------------------------------------- 1 | import { secondTimeConfig } from '@yicode/yiapi/config/secondTime.js'; 2 | import { productConfig } from './product.js'; 3 | export const paymentConfig = [ 4 | { 5 | // 产品名称 6 | name: '测试产品 - 月会员', 7 | // 产品代号 8 | product: productConfig.test, 9 | // 支付代号 10 | code: 1, 11 | // 时长 0=永久 非0=秒 12 | duration: secondTimeConfig.month, 13 | // 价格 分 14 | money: 1500 15 | }, 16 | { 17 | // 产品名称 18 | name: '测试产品 - 永久会员', 19 | // 产品代号 20 | product: productConfig.test, 21 | // 支付代号 22 | code: 2, 23 | // 时长 0=永久 非0=秒 24 | duration: secondTimeConfig.forever, 25 | // 价格 分 26 | money: 4500 27 | } 28 | ]; 29 | -------------------------------------------------------------------------------- /packages/yiserver/config/product.js: -------------------------------------------------------------------------------- 1 | export const productConfig = { 2 | test: 1 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yiserver/config/rate.js: -------------------------------------------------------------------------------- 1 | export const rateConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/redis.js: -------------------------------------------------------------------------------- 1 | export const redisConfig = { 2 | // 开发环境配置 3 | development: { 4 | host: '127.0.0.1', 5 | port: 6379, 6 | username: '', 7 | password: '', 8 | db: 0, 9 | keyPrefix: 'test:' 10 | }, 11 | // 开发环境配置 12 | production: { 13 | host: '127.0.0.1', 14 | port: 6379, 15 | username: '', 16 | password: '123456789123456789', 17 | db: 0, 18 | keyPrefix: 'test:' 19 | } 20 | }[process.env.NODE_ENV || 'development']; 21 | -------------------------------------------------------------------------------- /packages/yiserver/config/role.js: -------------------------------------------------------------------------------- 1 | export const roleConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/schemaField.js: -------------------------------------------------------------------------------- 1 | export const schemaFieldConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/secondTime.js: -------------------------------------------------------------------------------- 1 | export const secondTimeConfig = {}; 2 | -------------------------------------------------------------------------------- /packages/yiserver/config/tableExt.js: -------------------------------------------------------------------------------- 1 | // 系统表字段扩展 2 | export const tableExtConfig = { 3 | sys_user: { 4 | test_field: { 5 | name: '测试字段,此字段不能删除', 6 | type: 'string', 7 | default: '', 8 | min: 1, 9 | max: 50 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /packages/yiserver/config/upload.js: -------------------------------------------------------------------------------- 1 | export const uploadConfig = { 2 | dir: process.env.NODE_ENV === 'development' ? './public/static' : './public/static' 3 | }; 4 | -------------------------------------------------------------------------------- /packages/yiserver/config/weixin.js: -------------------------------------------------------------------------------- 1 | // 微信商户配置 2 | import { weixinPrivateKey } from './key.js'; 3 | export const weixinConfig = { 4 | // 商户配置 5 | mchId: '123456', 6 | serialNo: '123456789123456789123456', 7 | apiv3PrivateKey: '123456789123456789123456', 8 | privateKey: weixinPrivateKey, 9 | // 公众号配置 10 | appId: 'wx123456123456', 11 | appSecret: '123456789123456789123456', 12 | // 支付回调地址 13 | notifyUrl: '' 14 | }; 15 | -------------------------------------------------------------------------------- /packages/yiserver/config/whiteApis.js: -------------------------------------------------------------------------------- 1 | export const whiteApisConfig = []; 2 | -------------------------------------------------------------------------------- /packages/yiserver/env/.development.env: -------------------------------------------------------------------------------- 1 | NODE_ENV="development" -------------------------------------------------------------------------------- /packages/yiserver/env/.production.env: -------------------------------------------------------------------------------- 1 | NODE_ENV="production" -------------------------------------------------------------------------------- /packages/yiserver/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true, 3 | "ignore": ["*.test.js", "**/fixtures/*", "**/node_modules/**/*", "**/logs/*", "**/tables/*"], 4 | "execMap": { 5 | "js": "node yiapi.js" 6 | }, 7 | "env": { 8 | "NODE_ENV": "development" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/yiserver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/yiserver", 3 | "version": "5.3.17", 4 | "description": "易接口模板", 5 | "main": "yiapi.js", 6 | "type": "module", 7 | "private": false, 8 | "publishConfig": { 9 | "access": "public", 10 | "registry": "https://registry.npmjs.org" 11 | }, 12 | "scripts": { 13 | "dev": "nodemon --config=nodemon.json", 14 | "server": "pm2 start pm2.config.cjs", 15 | "syncMysql:dev": "node --env-file=env/.development.env ./scripts/syncMysql.js", 16 | "syncMysql:prod": "node --env-file=env/.production.env ./scripts/syncMysql.js", 17 | "flamegraph": "pnpm dlx rimraf .cache/0x & pnpm dlx 0x --output-dir=.cache/0x --output-html={outputDir}/index.html -- node --env-file=env/.development.env yiapi.js" 18 | }, 19 | "keywords": [ 20 | "api", 21 | "nodejs", 22 | "fastify" 23 | ], 24 | "author": "chensuiyi ", 25 | "homepage": "https://chensuiyi.me", 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/chenbimo/yicode.git" 29 | }, 30 | "dependencies": { 31 | "@yicode/yiapi": "^5.3.18" 32 | }, 33 | "devDependencies": { 34 | "nodemon": "^3.1.4" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/yiserver/plugins/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiserver/plugins/.gitkeep -------------------------------------------------------------------------------- /packages/yiserver/pm2.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apps: [ 3 | { 4 | name: 'yicode_demo', 5 | instances: 'max', 6 | script: './yiapi.js', 7 | exec_mode: 'cluster', 8 | watch: false, 9 | autorestart: true, 10 | ignore_watch: ['node_modules', 'logs', 'data'], 11 | env: { 12 | NODE_ENV: 'production' 13 | } 14 | } 15 | ] 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yiserver/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yiserver/public/.gitkeep -------------------------------------------------------------------------------- /packages/yiserver/scripts/syncMysql.js: -------------------------------------------------------------------------------- 1 | import { syncMysql } from '@yicode/yiapi/scripts/syncMysql.js'; 2 | syncMysql(); 3 | -------------------------------------------------------------------------------- /packages/yiserver/tables/example.js: -------------------------------------------------------------------------------- 1 | export const tableName = '演示表'; 2 | export const tableData = { 3 | nickname: { 4 | name: '用户名', 5 | type: 'string', 6 | default: '', 7 | min: 1, 8 | max: 50 9 | }, 10 | age: { 11 | name: '年龄', 12 | type: 'tinyInt', 13 | default: 18, 14 | min: 0, 15 | max: 150 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /packages/yiserver/yiapi.js: -------------------------------------------------------------------------------- 1 | import { initServer } from '@yicode/yiapi/yiapi.js'; 2 | initServer(); 3 | -------------------------------------------------------------------------------- /packages/yite-cli/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenbimo/yicode/4b9a4ba70f6eef23f3f9251499ac3579f6b28f5f/packages/yite-cli/index.js -------------------------------------------------------------------------------- /packages/yite-cli/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "es6", 5 | "baseUrl": "./", 6 | "paths": { 7 | "*": ["*"] 8 | } 9 | }, 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/yite-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@yicode/yite-cli", 3 | "version": "2.8.0", 4 | "description": "专注于vite + vue3 的项目开发脚手架", 5 | "main": "./index.js", 6 | "module": "./index.js", 7 | "exports": { 8 | "./*": "./*" 9 | }, 10 | "bin": { 11 | "yite": "bin.js" 12 | }, 13 | "type": "module", 14 | "private": false, 15 | "publishConfig": { 16 | "access": "public", 17 | "registry": "https://registry.npmjs.org" 18 | }, 19 | "scripts": {}, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/chenbimo/yite-cli" 23 | }, 24 | "homepage": "https://chensuiyi.me", 25 | "keywords": [ 26 | "vite", 27 | "vue.js", 28 | "vue-cli", 29 | "webpack", 30 | "cli", 31 | "vue", 32 | "web", 33 | "脚手架" 34 | ], 35 | "author": "chensuiyi ", 36 | "dependencies": { 37 | "@vitejs/plugin-vue": "^5.1.1", 38 | "@vue-macros/reactivity-transform": "^1.0.0", 39 | "colorette": "^2.0.20", 40 | "copy-anything": "^4.0.2", 41 | "fast-glob": "^3.3.2", 42 | "fs-extra": "^11.2.0", 43 | "got": "^14.4.2", 44 | "log-symbols": "^6.0.0", 45 | "merge-anything": "^6.0.2", 46 | "pacote": "^18.0.6", 47 | "portfinder": "^1.0.32", 48 | "rollup-plugin-visualizer": "^5.12.0", 49 | "unplugin-auto-import": "^0.18.2", 50 | "unplugin-icons": "^0.19.0", 51 | "unplugin-vue-components": "^0.27.3", 52 | "vite": "^5.3.5", 53 | "vite-plugin-vue-devtools": "^7.3.7", 54 | "vue-i18n": "^9.13.1" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/yite-cli/plugins/i18n.js: -------------------------------------------------------------------------------- 1 | // 查找模块 2 | const importGlob = async (pattern) => { 3 | return `import.meta.glob("${pattern}", {as: 'raw'})`; 4 | }; 5 | 6 | // 生成虚拟模块 7 | const createVirtualModuleCode = async (options) => { 8 | return ` 9 | export const yiteMessages = async () => { 10 | let files = ${await importGlob('@/i18n/*.json')}; 11 | let messages = {}; 12 | for (let key in files) { 13 | let data = await files[key](); 14 | messages[key.replace('/src/i18n/', '').replace('.json', '')] = JSON.parse(data); 15 | } 16 | return messages; 17 | }; 18 | `; 19 | }; 20 | 21 | export const yiteI18n = (options) => { 22 | let config = {}; 23 | // 虚拟模块定义 24 | const virtualModuleId = `virtual:yite-messages`; 25 | const resolvedVirtualModuleId = '\0' + virtualModuleId; 26 | 27 | return { 28 | name: 'yite-i18n', 29 | enforce: 'pre', 30 | options(options) {}, 31 | buildStart(options) {}, 32 | configResolved(resolvedConfig) { 33 | config = resolvedConfig; 34 | }, 35 | resolveId(id) { 36 | if (id === virtualModuleId) { 37 | return resolvedVirtualModuleId; 38 | } 39 | }, 40 | load(id) { 41 | if (id === resolvedVirtualModuleId) { 42 | return createVirtualModuleCode(); 43 | } 44 | } 45 | }; 46 | }; 47 | -------------------------------------------------------------------------------- /packages/yite-cli/readme.md: -------------------------------------------------------------------------------- 1 | ## yite-cli 2 | 3 | > 专注于 vite + vue3 的项目开发脚手架 4 | 5 | ### 文档地址 6 | -------------------------------------------------------------------------------- /packages/yite-cli/scripts/build.js: -------------------------------------------------------------------------------- 1 | import { build } from 'vite'; 2 | import path from 'path'; 3 | import { fnCliDir } from '../utils.js'; 4 | 5 | async function mainBuild(options) { 6 | await build({ 7 | configFile: path.resolve(fnCliDir(), 'vite.config.js') 8 | }); 9 | } 10 | 11 | export { mainBuild }; 12 | -------------------------------------------------------------------------------- /packages/yite-cli/scripts/dev.js: -------------------------------------------------------------------------------- 1 | import { createServer } from 'vite'; 2 | 3 | import path from 'path'; 4 | import { fnCliDir } from '../utils.js'; 5 | 6 | async function mainDev(options) { 7 | const server = await createServer({ 8 | // 任何合法的用户配置选项,加上 `mode` 和 `configFile` 9 | configFile: path.resolve(fnCliDir(), 'vite.config.js') 10 | }); 11 | await server.listen(); 12 | 13 | server.printUrls(); 14 | } 15 | 16 | export { mainDev }; 17 | -------------------------------------------------------------------------------- /packages/yite-cli/scripts/update.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs-extra'; 3 | import got from 'got'; 4 | import pacote from 'pacote'; 5 | import logSymbols from 'log-symbols'; 6 | 7 | import { fnAppDir } from '../utils.js'; 8 | 9 | async function mainUpdate(options) { 10 | try { 11 | const appDir = fnAppDir(options.workdir); 12 | const updateDir = path.resolve(appDir, '.cache', 'npm-package'); 13 | const metaData = await got.get(`https://registry.npmmirror.com/@yicode/yiadmin/latest`).json(); 14 | const downMeta = await pacote.extract(metaData.dist.tarball, updateDir, {}); 15 | fs.copySync(path.resolve(updateDir, 'src', 'pages', 'internal'), path.resolve(appDir, 'src', 'pages', 'internal')); 16 | fs.copySync(path.resolve(updateDir, 'src', 'config', 'internal.js'), path.resolve(appDir, 'src', 'config', 'internal.js')); 17 | fs.copySync(path.resolve(updateDir, 'src', 'utils', 'internal.js'), path.resolve(appDir, 'src', 'utils', 'internal.js')); 18 | fs.copySync(path.resolve(updateDir, 'src', 'styles', 'internal.scss'), path.resolve(appDir, 'src', 'styles', 'internal.scss')); 19 | console.log(logSymbols.success, '项目更新成功!'); 20 | } catch (error) { 21 | console.log('🚀 ~ file: update.js:20 ~ mainUpdate ~ error:', error); 22 | console.log(logSymbols.error, '资源错误或不存在!'); 23 | } 24 | } 25 | 26 | export { mainUpdate }; 27 | -------------------------------------------------------------------------------- /packages/yite-cli/todo.md: -------------------------------------------------------------------------------- 1 | - 引入vite-plugin-node-polyfills 2 | - 处理开启压缩图片后,public的图片会消失的问题。 3 | - 2 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | --------------------------------------------------------------------------------