├── app
├── .htaccess
├── admin
│ ├── lang
│ │ ├── zh-cn
│ │ │ ├── security
│ │ │ │ ├── datarecyclelog.php
│ │ │ │ ├── sensitivedatalog.php
│ │ │ │ ├── datarecycle.php
│ │ │ │ └── sensitivedata.php
│ │ │ ├── auth
│ │ │ │ ├── rule.php
│ │ │ │ ├── admin.php
│ │ │ │ └── group.php
│ │ │ ├── dashboard.php
│ │ │ ├── routine
│ │ │ │ ├── admininfo.php
│ │ │ │ └── attachment.php
│ │ │ ├── user
│ │ │ │ ├── moneylog.php
│ │ │ │ └── scorelog.php
│ │ │ ├── index.php
│ │ │ ├── crud
│ │ │ │ └── crud.php
│ │ │ └── ajax.php
│ │ └── en
│ │ │ ├── security
│ │ │ ├── datarecyclelog.php
│ │ │ ├── sensitivedatalog.php
│ │ │ ├── datarecycle.php
│ │ │ └── sensitivedata.php
│ │ │ ├── auth
│ │ │ ├── menu.php
│ │ │ ├── group.php
│ │ │ └── admin.php
│ │ │ ├── routine
│ │ │ ├── admininfo.php
│ │ │ └── attachment.php
│ │ │ ├── user
│ │ │ ├── moneylog.php
│ │ │ └── scorelog.php
│ │ │ ├── dashboard.php
│ │ │ ├── crud
│ │ │ └── crud.php
│ │ │ ├── index.php
│ │ │ └── ajax.php
│ ├── library
│ │ ├── crud
│ │ │ └── stubs
│ │ │ │ └── mixins
│ │ │ │ ├── model
│ │ │ │ ├── beforeInsert.stub
│ │ │ │ ├── getters
│ │ │ │ │ ├── string.stub
│ │ │ │ │ ├── float.stub
│ │ │ │ │ ├── jsonDecode.stub
│ │ │ │ │ ├── htmlDecode.stub
│ │ │ │ │ ├── remoteSelectLabels.stub
│ │ │ │ │ ├── stringToArray.stub
│ │ │ │ │ └── cityNames.stub
│ │ │ │ ├── mixins
│ │ │ │ │ └── beforeInsertWithSnowflake.stub
│ │ │ │ ├── setters
│ │ │ │ │ ├── time.stub
│ │ │ │ │ └── arrayToString.stub
│ │ │ │ ├── belongsTo.stub
│ │ │ │ ├── model.stub
│ │ │ │ └── afterInsert.stub
│ │ │ │ ├── controller
│ │ │ │ ├── initialize.stub
│ │ │ │ ├── controller.stub
│ │ │ │ └── index.stub
│ │ │ │ └── validate
│ │ │ │ └── validate.stub
│ │ └── stubs
│ │ │ └── backendEntrance.stub
│ ├── middleware.php
│ ├── model
│ │ ├── UserGroup.php
│ │ ├── AdminGroup.php
│ │ ├── DataRecycle.php
│ │ ├── SensitiveData.php
│ │ ├── AdminRule.php
│ │ ├── CrudLog.php
│ │ ├── UserRule.php
│ │ ├── DataRecycleLog.php
│ │ ├── SensitiveDataLog.php
│ │ ├── UserScoreLog.php
│ │ └── User.php
│ ├── event.php
│ ├── controller
│ │ ├── Dashboard.php
│ │ ├── crud
│ │ │ └── Log.php
│ │ ├── user
│ │ │ ├── MoneyLog.php
│ │ │ └── ScoreLog.php
│ │ └── auth
│ │ │ └── AdminLog.php
│ ├── validate
│ │ ├── Config.php
│ │ ├── AdminGroup.php
│ │ ├── AdminRule.php
│ │ ├── UserMoneyLog.php
│ │ ├── UserScoreLog.php
│ │ ├── DataRecycle.php
│ │ └── SensitiveData.php
│ └── common.php
├── api
│ ├── middleware.php
│ ├── common.php
│ ├── lang
│ │ ├── zh-cn
│ │ │ ├── user.php
│ │ │ └── ems.php
│ │ ├── en.php
│ │ └── en
│ │ │ ├── user.php
│ │ │ ├── account.php
│ │ │ └── ems.php
│ └── validate
│ │ └── Account.php
├── service.php
├── provider.php
├── common
│ ├── model
│ │ ├── UserScoreLog.php
│ │ ├── UserMoneyLog.php
│ │ └── User.php
│ ├── library
│ │ ├── token
│ │ │ └── TokenExpirationException.php
│ │ └── upload
│ │ │ └── Driver.php
│ ├── middleware
│ │ └── AdminLog.php
│ ├── facade
│ │ └── Token.php
│ └── service
│ │ └── moduleService.php
├── middleware.php
├── event.php
├── AppService.php
└── Request.php
├── runtime
└── .gitignore
├── public
├── robots.txt
├── favicon.ico
├── install
│ ├── favicon.ico
│ ├── assets
│ │ └── loading.gif
│ └── index.html
├── static
│ ├── fonts
│ │ ├── ttfs
│ │ │ ├── 1.ttf
│ │ │ ├── 2.ttf
│ │ │ ├── 3.ttf
│ │ │ ├── 4.ttf
│ │ │ ├── 5.ttf
│ │ │ └── 6.ttf
│ │ └── zhttfs
│ │ │ ├── 1.ttf
│ │ │ └── SourceHanSansCN-Normal.ttf
│ └── images
│ │ ├── avatar.png
│ │ ├── captcha
│ │ ├── image
│ │ │ ├── 1.jpg
│ │ │ ├── 2.jpg
│ │ │ ├── 3.jpg
│ │ │ ├── 4.jpg
│ │ │ ├── 5.jpg
│ │ │ ├── 6.jpg
│ │ │ ├── 7.jpg
│ │ │ └── 8.jpg
│ │ └── click
│ │ │ ├── bgs
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ └── 3.png
│ │ │ └── icons
│ │ │ ├── apple.png
│ │ │ ├── bell.png
│ │ │ ├── bird.png
│ │ │ ├── bomb.png
│ │ │ ├── candy.png
│ │ │ ├── crab.png
│ │ │ ├── cup.png
│ │ │ ├── fire.png
│ │ │ ├── pear.png
│ │ │ ├── banana.png
│ │ │ ├── bicycle.png
│ │ │ ├── dolphin.png
│ │ │ ├── guitar.png
│ │ │ ├── hexagon.png
│ │ │ ├── rocket.png
│ │ │ ├── aeroplane.png
│ │ │ ├── butterfly.png
│ │ │ ├── sailboat.png
│ │ │ ├── snowflake.png
│ │ │ └── wolf head.png
│ │ └── local-module-logo.png
├── npm-install-test
│ └── package.json
└── router.php
├── .gitattributes
├── web
├── public
│ └── favicon.ico
├── src
│ ├── assets
│ │ ├── bg.jpg
│ │ ├── qr.png
│ │ ├── logo.png
│ │ ├── bg-dark.jpg
│ │ ├── login-header.png
│ │ └── icons
│ │ │ ├── dark.svg
│ │ │ ├── lang.svg
│ │ │ ├── full-screen-cancel.svg
│ │ │ ├── light.svg
│ │ │ └── terminal.svg
│ ├── lang
│ │ ├── frontend
│ │ │ ├── zh-cn
│ │ │ │ ├── index.ts
│ │ │ │ └── user
│ │ │ │ │ ├── account
│ │ │ │ │ ├── balance.ts
│ │ │ │ │ ├── integral.ts
│ │ │ │ │ ├── changePassword.ts
│ │ │ │ │ ├── overview.ts
│ │ │ │ │ └── profile.ts
│ │ │ │ │ └── login.ts
│ │ │ ├── en
│ │ │ │ ├── index.ts
│ │ │ │ └── user
│ │ │ │ │ ├── account
│ │ │ │ │ ├── integral.ts
│ │ │ │ │ ├── balance.ts
│ │ │ │ │ ├── overview.ts
│ │ │ │ │ ├── changePassword.ts
│ │ │ │ │ └── profile.ts
│ │ │ │ │ └── login.ts
│ │ │ ├── zh-cn.ts
│ │ │ └── en.ts
│ │ ├── backend
│ │ │ ├── zh-cn
│ │ │ │ ├── user
│ │ │ │ │ ├── group.ts
│ │ │ │ │ ├── scoreLog.ts
│ │ │ │ │ ├── moneyLog.ts
│ │ │ │ │ ├── user.ts
│ │ │ │ │ └── rule.ts
│ │ │ │ ├── login.ts
│ │ │ │ ├── auth
│ │ │ │ │ ├── group.ts
│ │ │ │ │ ├── adminLog.ts
│ │ │ │ │ └── admin.ts
│ │ │ │ ├── security
│ │ │ │ │ ├── dataRecycle.ts
│ │ │ │ │ ├── sensitiveData.ts
│ │ │ │ │ ├── dataRecycleLog.ts
│ │ │ │ │ └── sensitiveDataLog.ts
│ │ │ │ ├── routine
│ │ │ │ │ ├── adminInfo.ts
│ │ │ │ │ ├── config.ts
│ │ │ │ │ └── attachment.ts
│ │ │ │ ├── crud
│ │ │ │ │ └── state.ts
│ │ │ │ └── dashboard.ts
│ │ │ └── en
│ │ │ │ ├── user
│ │ │ │ ├── group.ts
│ │ │ │ ├── scoreLog.ts
│ │ │ │ ├── moneyLog.ts
│ │ │ │ └── user.ts
│ │ │ │ ├── login.ts
│ │ │ │ ├── auth
│ │ │ │ ├── adminLog.ts
│ │ │ │ ├── admin.ts
│ │ │ │ └── group.ts
│ │ │ │ ├── security
│ │ │ │ ├── dataRecycle.ts
│ │ │ │ ├── sensitiveData.ts
│ │ │ │ ├── dataRecycleLog.ts
│ │ │ │ └── sensitiveDataLog.ts
│ │ │ │ ├── routine
│ │ │ │ ├── adminInfo.ts
│ │ │ │ ├── config.ts
│ │ │ │ └── attachment.ts
│ │ │ │ ├── crud
│ │ │ │ └── state.ts
│ │ │ │ └── dashboard.ts
│ │ ├── common
│ │ │ ├── zh-cn
│ │ │ │ ├── 401.ts
│ │ │ │ ├── pagesTitle.ts
│ │ │ │ ├── 404.ts
│ │ │ │ ├── validate.ts
│ │ │ │ └── axios.ts
│ │ │ └── en
│ │ │ │ ├── pagesTitle.ts
│ │ │ │ ├── 401.ts
│ │ │ │ ├── 404.ts
│ │ │ │ ├── validate.ts
│ │ │ │ └── axios.ts
│ │ ├── autoload.ts
│ │ └── globs-zh-cn.ts
│ ├── styles
│ │ ├── index.scss
│ │ ├── dark.scss
│ │ ├── mixins.scss
│ │ └── var.scss
│ ├── components
│ │ ├── mixins
│ │ │ ├── userProfile.vue
│ │ │ ├── loginFooter.vue
│ │ │ ├── loginMounted.ts
│ │ │ ├── editor
│ │ │ │ └── default.vue
│ │ │ ├── userMounted.ts
│ │ │ └── baUpload.ts
│ │ ├── table
│ │ │ └── fieldRender
│ │ │ │ ├── default.vue
│ │ │ │ ├── customTemplate.vue
│ │ │ │ ├── datetime.vue
│ │ │ │ ├── color.vue
│ │ │ │ ├── icon.vue
│ │ │ │ ├── customRender.vue
│ │ │ │ ├── image.vue
│ │ │ │ ├── url.vue
│ │ │ │ ├── tag.vue
│ │ │ │ └── images.vue
│ │ ├── formItem
│ │ │ └── index.ts
│ │ ├── contextmenu
│ │ │ └── interface.ts
│ │ ├── baInput
│ │ │ └── components
│ │ │ │ └── editor.vue
│ │ ├── icon
│ │ │ ├── svg
│ │ │ │ └── index.vue
│ │ │ └── index.vue
│ │ └── clickCaptcha
│ │ │ └── index.ts
│ ├── stores
│ │ ├── constant
│ │ │ ├── common.ts
│ │ │ ├── terminalTaskStatus.ts
│ │ │ └── cacheKey.ts
│ │ ├── index.ts
│ │ ├── refs.ts
│ │ └── siteConfig.ts
│ ├── api
│ │ └── backend
│ │ │ ├── auth
│ │ │ └── group.ts
│ │ │ ├── user
│ │ │ ├── group.ts
│ │ │ ├── moneyLog.ts
│ │ │ └── scoreLog.ts
│ │ │ ├── dashboard.ts
│ │ │ ├── security
│ │ │ ├── dataRecycle.ts
│ │ │ ├── sensitiveData.ts
│ │ │ ├── dataRecycleLog.ts
│ │ │ └── sensitiveDataLog.ts
│ │ │ └── routine
│ │ │ ├── AdminInfo.ts
│ │ │ └── config.ts
│ ├── views
│ │ └── backend
│ │ │ ├── routine
│ │ │ └── attachment
│ │ │ │ └── index.ts
│ │ │ ├── crud
│ │ │ └── index.vue
│ │ │ └── module
│ │ │ └── index.vue
│ ├── utils
│ │ ├── useCurrentInstance.ts
│ │ ├── pageShade.ts
│ │ ├── horizontalScroll.ts
│ │ ├── storage.ts
│ │ ├── build.ts
│ │ ├── useDark.ts
│ │ ├── loading.ts
│ │ └── random.ts
│ ├── layouts
│ │ ├── frontend
│ │ │ ├── components
│ │ │ │ ├── main.vue
│ │ │ │ └── footer.vue
│ │ │ └── container
│ │ │ │ ├── disable.vue
│ │ │ │ └── default.vue
│ │ ├── common
│ │ │ └── router-view
│ │ │ │ └── iframe.vue
│ │ └── backend
│ │ │ ├── container
│ │ │ ├── streamline.vue
│ │ │ ├── double.vue
│ │ │ ├── classic.vue
│ │ │ └── default.vue
│ │ │ └── components
│ │ │ └── header.vue
│ ├── router
│ │ └── static
│ │ │ ├── memberCenterBase.ts
│ │ │ └── adminBase.ts
│ ├── main.ts
│ └── App.vue
├── .env
├── .npmrc
├── .vscode
│ ├── extensions.json
│ └── settings.json
├── .env.development
├── .env.production
├── types
│ ├── module.d.ts
│ ├── tableRenderer.d.ts
│ └── global.d.ts
├── .editorconfig
├── index.html
├── tsconfig.json
└── .prettierrc.js
├── .env-example
├── config
├── middleware.php
├── console.php
├── trace.php
├── session.php
├── cookie.php
├── filesystem.php
├── view.php
├── upload.php
├── cache.php
├── lang.php
├── app.php
├── log.php
└── route.php
├── think
├── extend
└── ba
│ └── Exception.php
├── database
└── migrations
│ ├── 20230719211338_version201.php
│ └── 20231112093414_version205.php
└── .gitignore
/app/.htaccess:
--------------------------------------------------------------------------------
1 | deny from all
--------------------------------------------------------------------------------
/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
3 | # Windows
4 | *.bat text eol=crlf
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/web/public/favicon.ico
--------------------------------------------------------------------------------
/web/src/assets/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/web/src/assets/bg.jpg
--------------------------------------------------------------------------------
/web/src/assets/qr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/web/src/assets/qr.png
--------------------------------------------------------------------------------
/web/.env:
--------------------------------------------------------------------------------
1 | # port 端口号
2 | VITE_PORT = 1818
3 |
4 | # open 运行 npm run dev 时自动打开浏览器
5 | VITE_OPEN = false
6 |
--------------------------------------------------------------------------------
/web/.npmrc:
--------------------------------------------------------------------------------
1 | # 若不开启且使用 pnpm 安装依赖后,element-plus 和 vue-i18n(useI18n) 共存时组件的类型定义将丢失
2 | shamefully-hoist=true
3 |
--------------------------------------------------------------------------------
/web/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/web/src/assets/logo.png
--------------------------------------------------------------------------------
/public/install/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/install/favicon.ico
--------------------------------------------------------------------------------
/web/src/assets/bg-dark.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/web/src/assets/bg-dark.jpg
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/security/datarecyclelog.php:
--------------------------------------------------------------------------------
1 | '没有记录被还原',
4 | ];
--------------------------------------------------------------------------------
/public/static/fonts/ttfs/1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/ttfs/1.ttf
--------------------------------------------------------------------------------
/public/static/fonts/ttfs/2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/ttfs/2.ttf
--------------------------------------------------------------------------------
/public/static/fonts/ttfs/3.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/ttfs/3.ttf
--------------------------------------------------------------------------------
/public/static/fonts/ttfs/4.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/ttfs/4.ttf
--------------------------------------------------------------------------------
/public/static/fonts/ttfs/5.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/ttfs/5.ttf
--------------------------------------------------------------------------------
/public/static/fonts/ttfs/6.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/ttfs/6.ttf
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/security/sensitivedatalog.php:
--------------------------------------------------------------------------------
1 | '没有记录被回滚',
4 | ];
--------------------------------------------------------------------------------
/public/static/fonts/zhttfs/1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/zhttfs/1.ttf
--------------------------------------------------------------------------------
/public/static/images/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/avatar.png
--------------------------------------------------------------------------------
/web/src/assets/login-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/web/src/assets/login-header.png
--------------------------------------------------------------------------------
/web/src/lang/frontend/zh-cn/index.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Steve Jobs': '伟大的艺术品不必追随潮流,他本身就能引领潮流。 -- 乔布斯',
3 | }
4 |
--------------------------------------------------------------------------------
/.env-example:
--------------------------------------------------------------------------------
1 | APP_DEBUG = true
2 |
3 | [APP]
4 | DEFAULT_TIMEZONE = Asia/Shanghai
5 |
6 | [LANG]
7 | default_lang = zh-cn
8 |
--------------------------------------------------------------------------------
/public/install/assets/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/install/assets/loading.gif
--------------------------------------------------------------------------------
/web/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["vue.volar", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
3 | }
4 |
--------------------------------------------------------------------------------
/app/admin/lang/en/security/datarecyclelog.php:
--------------------------------------------------------------------------------
1 | 'No records have been restored',
4 | ];
--------------------------------------------------------------------------------
/public/static/images/captcha/image/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/1.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/2.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/3.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/4.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/5.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/6.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/7.jpg
--------------------------------------------------------------------------------
/public/static/images/captcha/image/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/image/8.jpg
--------------------------------------------------------------------------------
/app/admin/lang/en/security/sensitivedatalog.php:
--------------------------------------------------------------------------------
1 | 'No records have been roll-back',
4 | ];
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/auth/rule.php:
--------------------------------------------------------------------------------
1 | '规则类型',
4 | 'title' => '规则标题',
5 | 'name' => '规则名称',
6 | ];
--------------------------------------------------------------------------------
/public/static/images/local-module-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/local-module-logo.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/bgs/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/bgs/1.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/bgs/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/bgs/2.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/bgs/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/bgs/3.png
--------------------------------------------------------------------------------
/app/admin/lang/en/auth/menu.php:
--------------------------------------------------------------------------------
1 | 'Rule type',
4 | 'title' => 'Rule title',
5 | 'name' => 'Rule name',
6 | ];
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/user/group.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | GroupName: '组名',
3 | 'Group name': '组别名称',
4 | jurisdiction: '权限',
5 | }
6 |
--------------------------------------------------------------------------------
/app/api/middleware.php:
--------------------------------------------------------------------------------
1 | '开源等于互助;开源需要大家一起来支持,支持的方式有很多种,比如使用、推荐、写教程、保护生态、贡献代码、回答问题、分享经验、打赏赞助等;欢迎您加入我们!',
4 | ];
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/banana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/banana.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/bicycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/bicycle.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/dolphin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/dolphin.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/guitar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/guitar.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/hexagon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/hexagon.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/rocket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/rocket.png
--------------------------------------------------------------------------------
/web/src/lang/frontend/en/index.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Steve Jobs': "Great art don't have to follow the trend, it alone can lead.-- Steve Jobs",
3 | }
4 |
--------------------------------------------------------------------------------
/public/static/fonts/zhttfs/SourceHanSansCN-Normal.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/fonts/zhttfs/SourceHanSansCN-Normal.ttf
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/aeroplane.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/aeroplane.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/butterfly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/butterfly.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/sailboat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/sailboat.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/snowflake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/snowflake.png
--------------------------------------------------------------------------------
/public/static/images/captcha/click/icons/wolf head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-admin/buildadmin/HEAD/public/static/images/captcha/click/icons/wolf head.png
--------------------------------------------------------------------------------
/web/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @use '/@/styles/app';
2 | @use '/@/styles/element';
3 | @use '/@/styles/var';
4 | @use '/@/styles/dark';
5 | @use '/@/styles/markdown';
6 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/beforeInsert.stub:
--------------------------------------------------------------------------------
1 |
2 | protected static function onBeforeInsert($model): void
3 | {
4 | {%setSnowFlakeIdCode%}
5 | }
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/getters/string.stub:
--------------------------------------------------------------------------------
1 |
2 | public function get{%field%}Attr($value): string
3 | {
4 | return (string)$value;
5 | }
--------------------------------------------------------------------------------
/config/middleware.php:
--------------------------------------------------------------------------------
1 | [],
6 | // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
7 | 'priority' => [],
8 | ];
9 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/user/group.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | GroupName: 'Group name',
3 | 'Group name': 'Group name',
4 | jurisdiction: 'Permissions',
5 | }
6 |
--------------------------------------------------------------------------------
/web/src/lang/common/zh-cn/401.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | noPowerTip:
3 | '这不是你想要的,但我们是认真的。我只是想用一种特殊的方式告诉你,你无权访问此页面,或者该文件无效。您可以联系网站管理员以更快地解决问题,或返回网站首页浏览其他页面。',
4 | }
5 |
--------------------------------------------------------------------------------
/web/.env.development:
--------------------------------------------------------------------------------
1 | # 本地环境
2 | ENV = 'development'
3 |
4 | # base路径
5 | VITE_BASE_PATH = './'
6 |
7 | # 本地环境接口地址 - 尾部无需带'/'
8 | VITE_AXIOS_BASE_URL = 'http://localhost:8000'
9 |
--------------------------------------------------------------------------------
/web/src/components/mixins/userProfile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Field renderer not found
4 |
5 |
6 |
--------------------------------------------------------------------------------
/web/src/stores/constant/common.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 公共常量定义
3 | */
4 |
5 | /**
6 | * 系统级 z-index 配置,比如全局通知消息的 z-index(浏览器支持的最大值通常为 2147483647)
7 | */
8 | export const SYSTEM_ZINDEX = 2147483600
9 |
--------------------------------------------------------------------------------
/web/src/stores/constant/terminalTaskStatus.ts:
--------------------------------------------------------------------------------
1 | export const enum taskStatus {
2 | Waiting,
3 | Connecting,
4 | Executing,
5 | Success,
6 | Failed,
7 | Unknown,
8 | }
9 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/getters/float.stub:
--------------------------------------------------------------------------------
1 |
2 | public function get{%field%}Attr($value): ?float
3 | {
4 | return is_null($value) ? null : (float)$value;
5 | }
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/mixins/beforeInsertWithSnowflake.stub:
--------------------------------------------------------------------------------
1 | $pk = $model->getPk();
2 | $model->$pk = \app\common\library\SnowFlake::generateParticle();
--------------------------------------------------------------------------------
/think:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | console->run();
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/getters/jsonDecode.stub:
--------------------------------------------------------------------------------
1 |
2 | public function get{%field%}Attr($value): array
3 | {
4 | return !$value ? [] : json_decode($value, true);
5 | }
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/setters/time.stub:
--------------------------------------------------------------------------------
1 |
2 | public function set{%field%}Attr($value): ?string
3 | {
4 | return $value ? date('H:i:s', strtotime($value)) : $value;
5 | }
--------------------------------------------------------------------------------
/app/admin/middleware.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/setters/arrayToString.stub:
--------------------------------------------------------------------------------
1 |
2 | public function set{%field%}Attr($value): string
3 | {
4 | return is_array($value) ? implode(',', $value) : $value;
5 | }
--------------------------------------------------------------------------------
/web/src/components/mixins/loginMounted.ts:
--------------------------------------------------------------------------------
1 | export default function loginMounted(): Promise {
2 | // 通常用于会员登录页初始化时接受各种回调或收参跳转,返回 true 将终止会员登录页初始化
3 | return new Promise((resolve) => resolve(false))
4 | }
5 |
--------------------------------------------------------------------------------
/app/service.php:
--------------------------------------------------------------------------------
1 | '请输入正确的用户名',
4 | 'Please input correct password' => '请输入正确的密码',
5 | 'Avatar modified successfully!' => '头像修改成功!',
6 | ];
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/routine/attachment.php:
--------------------------------------------------------------------------------
1 | '同一文件被多次上传时,只会保存一份至磁盘和增加一条附件记录;删除附件记录,将自动删除对应文件!',
4 | '%d records and files have been deleted' => '删除了%d条记录和文件',
5 | ];
--------------------------------------------------------------------------------
/web/src/api/backend/auth/group.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export function getAdminRules() {
4 | return createAxios({
5 | url: '/admin/auth.Rule/index',
6 | method: 'get',
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/web/src/api/backend/user/group.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export function getUserRules() {
4 | return createAxios({
5 | url: '/admin/user.Rule/index',
6 | method: 'get',
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/controller/initialize.stub:
--------------------------------------------------------------------------------
1 |
2 | public function initialize(): void
3 | {
4 | parent::initialize();
5 | $this->model = new \{%modelNamespace%}\{%modelName%}();{%filterRule%}
6 | }
--------------------------------------------------------------------------------
/app/admin/model/UserGroup.php:
--------------------------------------------------------------------------------
1 | 'Rule Name',
4 | 'Controller' => 'Controller',
5 | 'Data Table' => 'Corresponding data table',
6 | 'Primary Key' => 'Data table primary key',
7 | ];
--------------------------------------------------------------------------------
/app/admin/model/AdminGroup.php:
--------------------------------------------------------------------------------
1 | Request::class,
9 | 'think\exception\Handle' => ExceptionHandle::class,
10 | ];
11 |
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/security/datarecycle.php:
--------------------------------------------------------------------------------
1 | '规则名称',
4 | 'Controller' => '控制器',
5 | 'Data Table' => '对应数据表',
6 | 'Primary Key' => '数据表主键',
7 | 'Remark lang' => '在此定义需要回收的数据,实现数据自动统一回收',
8 | ];
--------------------------------------------------------------------------------
/app/common/model/UserScoreLog.php:
--------------------------------------------------------------------------------
1 | [],
8 | ];
9 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/login.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Please enter an account': 'Please enter your account',
3 | 'Please input a password': 'Please enter your password',
4 | 'Hold session': 'Keep the session',
5 | 'Sign in': 'Sign in',
6 | }
7 |
--------------------------------------------------------------------------------
/web/src/lang/frontend/en/user/account/integral.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Change time': 'Change time',
3 | 'Current points': 'Current points',
4 | 'Points after change': 'Points after change',
5 | 'Score change record': 'Score change record',
6 | }
7 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/belongsTo.stub:
--------------------------------------------------------------------------------
1 |
2 | public function {%relationMethod%}(): \think\model\relation\BelongsTo
3 | {
4 | return $this->{%relationMode%}({%relationClassName%}, '{%relationForeignKey%}', '{%relationPrimaryKey%}');
5 | }
--------------------------------------------------------------------------------
/web/src/lang/frontend/en/user/account/balance.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Change time': 'Change time',
3 | 'Current balance': 'Current balance',
4 | 'Balance after change': 'Balance after change',
5 | 'Balance change record': 'Balance change record',
6 | }
7 |
--------------------------------------------------------------------------------
/web/src/api/backend/dashboard.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/Dashboard/'
4 |
5 | export function index() {
6 | return createAxios({
7 | url: url + 'index',
8 | method: 'get',
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/web/src/api/backend/security/dataRecycle.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/security.DataRecycle/'
4 |
5 | export function add() {
6 | return createAxios({
7 | url: url + 'add',
8 | method: 'get',
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/web/src/api/backend/security/sensitiveData.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/security.SensitiveData/'
4 |
5 | export function add() {
6 | return createAxios({
7 | url: url + 'add',
8 | method: 'get',
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/app/admin/lang/en/security/sensitivedata.php:
--------------------------------------------------------------------------------
1 | 'Rule name',
4 | 'Controller' => 'Controller',
5 | 'Data Table' => 'Corresponding data table',
6 | 'Primary Key' => 'Data table primary key',
7 | 'Data Fields' => 'Sensitive data fields',
8 | ];
--------------------------------------------------------------------------------
/web/src/lang/common/zh-cn/pagesTitle.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | home: '首页',
3 | admin: '后台',
4 | adminLogin: '登录',
5 | notFound: '页面找不到了',
6 | noPower: '无访问权限',
7 | noTitle: '无标题',
8 | loading: 'Loading...',
9 | user: '会员中心',
10 | userLogin: '会员登录',
11 | }
12 |
--------------------------------------------------------------------------------
/app/admin/model/DataRecycle.php:
--------------------------------------------------------------------------------
1 | 'Please enter the correct username',
4 | 'Please input correct password' => 'Please enter the correct password',
5 | 'Avatar modified successfully!' => 'Profile picture modified successfully!',
6 | ];
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/user/moneylog.php:
--------------------------------------------------------------------------------
1 | '用户',
4 | 'money' => '变更金额',
5 | 'memo' => '变更备注',
6 | "The user can't find it" => '用户找不到啦',
7 | 'Change note cannot be blank' => '变更备注不能为空',
8 | ];
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/user/scorelog.php:
--------------------------------------------------------------------------------
1 | '用户',
4 | 'score' => '变更积分',
5 | 'memo' => '变更备注',
6 | "The user can't find it" => '用户找不到啦',
7 | 'Change note cannot be blank' => '变更备注不能为空',
8 | ];
--------------------------------------------------------------------------------
/web/types/module.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import { DefineComponent } from 'vue'
5 | // eslint-disable-next-line @typescript-eslint/no-empty-object-type
6 | const component: DefineComponent<{}, {}, any>
7 | export default component
8 | }
9 |
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/security/sensitivedata.php:
--------------------------------------------------------------------------------
1 | '规则名称',
4 | 'Controller' => '控制器',
5 | 'Data Table' => '对应数据表',
6 | 'Primary Key' => '数据表主键',
7 | 'Data Fields' => '敏感数据字段',
8 | 'Remark lang' => '在此定义需要保护的敏感字段,随后系统将自动监听该字段的修改操作,并提供了敏感字段的修改回滚功能',
9 | ];
--------------------------------------------------------------------------------
/web/src/components/mixins/editor/default.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ $t('utils.Please install editor') }}
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/web/src/lang/common/zh-cn/404.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'problems tip': '你的网页遇到了一些问题,系统正在优化和上报故障信息,我们在未来将改善和减少这种情况的发生.',
3 | 'We will automatically return to the previous page when we are finished': '我们将在完成后自动返回到上一页。',
4 | 'Return to home page': '返回首页',
5 | 'Back to previous page': '返回上一页',
6 | }
7 |
--------------------------------------------------------------------------------
/app/admin/lang/en/auth/group.php:
--------------------------------------------------------------------------------
1 | 'Super administrator',
4 | 'No permission' => 'No permission',
5 | 'You cannot modify your own management group!' => 'You cannot modify your own management group!',
6 | ];
7 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/getters/remoteSelectLabels.stub:
--------------------------------------------------------------------------------
1 |
2 | public function get{%field%}Attr($value, $row): array
3 | {
4 | return [
5 | '{%labelFieldName%}' => {%className%}::whereIn('{%primaryKey%}', $row['{%foreignKey%}'])->column('{%labelFieldName%}'),
6 | ];
7 | }
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/getters/stringToArray.stub:
--------------------------------------------------------------------------------
1 |
2 | public function get{%field%}Attr($value): array
3 | {
4 | if ($value === '' || $value === null) return [];
5 | if (!is_array($value)) {
6 | return explode(',', $value);
7 | }
8 | return $value;
9 | }
--------------------------------------------------------------------------------
/app/admin/lang/en/auth/admin.php:
--------------------------------------------------------------------------------
1 | 'Administrator Grouping ',
4 | 'Please use another administrator account to disable the current account!' => 'Disable the current account, please use another administrator account!',
5 | ];
--------------------------------------------------------------------------------
/app/middleware.php:
--------------------------------------------------------------------------------
1 | [
5 | ],
6 |
7 | 'listen' => [
8 | 'AppInit' => [],
9 | 'HttpRun' => [],
10 | 'HttpEnd' => [],
11 | 'LogLevel' => [],
12 | 'LogWrite' => [],
13 | ],
14 |
15 | 'subscribe' => [
16 | ],
17 | ];
18 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/auth/group.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | GroupName: '组名',
3 | 'Group name': '组别名称',
4 | jurisdiction: '权限',
5 | 'Parent group': '上级分组',
6 | 'The parent group cannot be the group itself': '上级分组不能是分组本身',
7 | 'Manage subordinate role groups here': '在此管理下级角色组(您拥有下级角色组的所有权限并且拥有额外的权限,不含同级)',
8 | }
9 |
--------------------------------------------------------------------------------
/config/trace.php:
--------------------------------------------------------------------------------
1 | 'Html',
8 | // 读取的日志通道名
9 | 'channel' => '',
10 | ];
11 |
--------------------------------------------------------------------------------
/web/src/lang/common/en/pagesTitle.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | home: 'Home',
3 | admin: 'Admin',
4 | adminLogin: 'Login',
5 | notFound: 'Page not found',
6 | noPower: 'No access permission',
7 | noTitle: 'No title',
8 | loading: 'Loading...',
9 | user: 'Member Center',
10 | userLogin: 'Menber Login',
11 | }
12 |
--------------------------------------------------------------------------------
/web/.editorconfig:
--------------------------------------------------------------------------------
1 | # https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 4
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | indent_style = tab
14 | insert_final_newline = false
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/auth/adminLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | admin_id: '管理ID',
3 | username: '管理用户名',
4 | title: '标题',
5 | data: '请求数据',
6 | url: 'URL',
7 | ip: 'IP',
8 | useragent: 'UserAgent',
9 | 'Operation administrator': '操作管理员',
10 | 'Operator IP': '操作人IP',
11 | 'Request data': '请求数据',
12 | }
13 |
--------------------------------------------------------------------------------
/web/src/lang/common/en/401.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | noPowerTip:
3 | "It's not what you want, but we're serious. I want to tell you in a special way that you don't have permission to access this page or the file is invalid. You can contact the website administrator to solve the problem faster or go back home page to view another page.",
4 | }
5 |
--------------------------------------------------------------------------------
/app/admin/lang/en/user/moneylog.php:
--------------------------------------------------------------------------------
1 | 'User',
4 | 'money' => 'Change amount',
5 | 'memo' => 'Change Notes',
6 | "The user can't find it" => "User does not exist",
7 | 'Change note cannot be blank' => 'Change Notes cannot be empty',
8 | ];
--------------------------------------------------------------------------------
/app/admin/lang/en/user/scorelog.php:
--------------------------------------------------------------------------------
1 | 'User',
4 | 'score' => 'Change points',
5 | 'memo' => 'Change Notes',
6 | "The user can't find it" => 'User does not exist',
7 | 'Change note cannot be blank' => 'Change notes cannot be empty',
8 | ];
--------------------------------------------------------------------------------
/web/src/lang/frontend/zh-cn.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 前台公共语言包
3 | * 覆盖风险:请避免使用页面语言包的目录名、文件名作为翻译 key
4 | */
5 | export default {
6 | Integral: '积分',
7 | Balance: '余额',
8 | Language: '语言',
9 | Copyright: '版权所有',
10 | 'Member Center': '会员中心',
11 | 'Logout login': '注销登录',
12 | 'Member center disabled': '会员中心已禁用,请联系网站管理员开启。',
13 | }
14 |
--------------------------------------------------------------------------------
/web/src/lang/frontend/zh-cn/user/account/changePassword.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Change Password': '修改密码',
3 | 'Old password': '旧密码',
4 | 'New password': '新密码',
5 | 'Confirm new password': '确认新密码',
6 | 'Please enter your current password': '请输入现在的密码',
7 | 'The duplicate password does not match the new password': '重复密码与新密码不相符',
8 | }
9 |
--------------------------------------------------------------------------------
/web/src/lang/frontend/zh-cn/user/account/overview.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Account information': '账户信息',
3 | profile: '个人资料',
4 | 'Filled in': '已填写',
5 | 'Not filled in': '未填写',
6 | mobile: '手机号',
7 | email: '电子邮箱',
8 | 'Last login IP': '最后登录IP',
9 | 'Last login': '最后登录',
10 | 'Growth statistics': '增长统计',
11 | }
12 |
--------------------------------------------------------------------------------
/app/AppService.php:
--------------------------------------------------------------------------------
1 | '管理员分组',
4 | 'Please use another administrator account to disable the current account!' => '请使用另外的管理员账户禁用当前账户!',
5 | 'You have no permission to add an administrator to this group!' => '您没有权限向此分组添加管理员!',
6 | ];
--------------------------------------------------------------------------------
/web/src/api/backend/user/moneyLog.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/user.MoneyLog/'
4 |
5 | export function add(userId: string) {
6 | return createAxios({
7 | url: url + 'add',
8 | method: 'get',
9 | params: {
10 | userId: userId,
11 | },
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/web/src/api/backend/user/scoreLog.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/user.ScoreLog/'
4 |
5 | export function add(userId: string) {
6 | return createAxios({
7 | url: url + 'add',
8 | method: 'get',
9 | params: {
10 | userId: userId,
11 | },
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/app/admin/lang/en/dashboard.php:
--------------------------------------------------------------------------------
1 | "Open source equals mutual assistance, and needs everyone's support. There are many ways to support it, such as using, recommending, writing tutorials, protecting the ecology, contributing code, answering questions, sharing experiences, donation, sponsorship and so on. Welcome to join us!",
4 | ];
--------------------------------------------------------------------------------
/web/types/tableRenderer.d.ts:
--------------------------------------------------------------------------------
1 | /** 可用的表格单元格渲染器,以 ./src/components/table/fieldRender/ 目录中的文件名自动生成 */
2 | type TableRenderer =
3 | | 'buttons'
4 | | 'color'
5 | | 'customRender'
6 | | 'customTemplate'
7 | | 'datetime'
8 | | 'icon'
9 | | 'image'
10 | | 'images'
11 | | 'switch'
12 | | 'tag'
13 | | 'tags'
14 | | 'url'
15 | | 'slot'
16 |
--------------------------------------------------------------------------------
/app/admin/model/SensitiveData.php:
--------------------------------------------------------------------------------
1 | 'array',
18 | ];
19 | }
--------------------------------------------------------------------------------
/web/src/components/mixins/userMounted.ts:
--------------------------------------------------------------------------------
1 | interface UserMountedRet {
2 | type: 'jump' | 'break' | 'continue' | 'reload'
3 | [key: string]: any
4 | }
5 |
6 | export default function userMounted(): Promise {
7 | // 通常用于会员中心初始化时接受各种回调或收参跳转,返回 true 将终止会员中心初始化
8 | return new Promise((resolve) => {
9 | resolve({ type: 'continue' })
10 | })
11 | }
12 |
--------------------------------------------------------------------------------
/app/admin/event.php:
--------------------------------------------------------------------------------
1 | [
5 | ],
6 | 'listen' => [
7 | 'AppInit' => [],
8 | 'HttpRun' => [],
9 | 'HttpEnd' => [],
10 | 'LogLevel' => [],
11 | 'LogWrite' => [],
12 | 'backendInit' => [app\common\event\Security::class],
13 | ],
14 | 'subscribe' => [
15 | ],
16 | ];
--------------------------------------------------------------------------------
/web/src/lang/backend/en/auth/adminLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | admin_id: 'Manage ID',
3 | username: 'Manage Username',
4 | title: 'Title',
5 | data: 'Request Data',
6 | url: 'URL',
7 | ip: 'IP',
8 | useragent: 'UserAgent',
9 | 'Operation administrator': 'Operation administrator',
10 | 'Operator IP': 'Operator IP',
11 | 'Request data': 'Request Data',
12 | }
13 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/auth/admin.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | username: '用户名',
3 | nickname: '昵称',
4 | group: '角色组',
5 | avatar: '头像',
6 | email: '电子邮箱',
7 | mobile: '手机号',
8 | 'Last login': '最后登录',
9 | Password: '密码',
10 | 'Please leave blank if not modified': '不修改请留空',
11 | 'Personal signature': '个性签名',
12 | 'Administrator login': '管理员登录名',
13 | }
14 |
--------------------------------------------------------------------------------
/app/admin/lang/en/routine/attachment.php:
--------------------------------------------------------------------------------
1 | '%d records and files have been deleted',
4 | 'remark_text' => 'When the same file is uploaded multiple times, only one copy will be saved to the disk and an attachment record will be added; Deleting an attachment record will automatically delete the corresponding file!',
5 | ];
--------------------------------------------------------------------------------
/app/common/library/token/TokenExpirationException.php:
--------------------------------------------------------------------------------
1 | whereIn('id', $row['{%originalFieldName%}'])->column('name');
6 | return $cityNames ? implode(',', $cityNames) : '';
7 | }
--------------------------------------------------------------------------------
/web/src/lang/frontend/en.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * frontend common language package
3 | */
4 | export default {
5 | Integral: 'Integral',
6 | Balance: 'Balance',
7 | Language: 'Language',
8 | Copyright: 'Copyright',
9 | 'Member Center': 'Member Center',
10 | 'Logout login': 'Logout',
11 | 'Member center disabled': 'The member center has been disabled. Please contact the webmaster to turn it on.',
12 | }
13 |
--------------------------------------------------------------------------------
/extend/ba/Exception.php:
--------------------------------------------------------------------------------
1 | error(__($e->getMessage()), $e->getData(), $e->getCode());
10 | */
11 | class Exception extends E
12 | {
13 | public function __construct(protected $message, protected $code = 0, protected $data = [])
14 | {
15 | parent::__construct($message, $code);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/admin/controller/Dashboard.php:
--------------------------------------------------------------------------------
1 | success('', [
17 | 'remark' => get_route_remark()
18 | ]);
19 | }
20 | }
--------------------------------------------------------------------------------
/database/migrations/20230719211338_version201.php:
--------------------------------------------------------------------------------
1 | table('user');
10 | if ($user->hasIndex('email')) {
11 | $user->removeIndexByName('email')
12 | ->removeIndexByName('mobile')
13 | ->update();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/admin/model/AdminRule.php:
--------------------------------------------------------------------------------
1 | {
7 | const imgSuffix = ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp']
8 | if (imgSuffix.includes(cellValue)) {
9 | return row.full_url
10 | }
11 | return buildSuffixSvgUrl(cellValue)
12 | }
13 |
--------------------------------------------------------------------------------
/app/admin/model/CrudLog.php:
--------------------------------------------------------------------------------
1 | 'array',
21 | 'fields' => 'array',
22 | ];
23 |
24 | }
--------------------------------------------------------------------------------
/web/src/components/formItem/index.ts:
--------------------------------------------------------------------------------
1 | import type { CSSProperties } from 'vue'
2 | import type { FormItemProps, ElTooltipProps } from 'element-plus'
3 |
4 | export interface FormItemAttr extends Partial> {
5 | // 通用属性名称的键入提示
6 | id?: string
7 | class?: string
8 | style?: CSSProperties
9 | // 块级输入帮助信息
10 | blockHelp?: string
11 | // 输入提示信息(使用 el-tooltip 渲染)
12 | tip?: string | Partial
13 | }
14 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/model.stub:
--------------------------------------------------------------------------------
1 | extends ContextMenuItem {
14 | sourceData?: T
15 | }
16 |
17 | export interface Props {
18 | width?: number
19 | items: ContextMenuItem[]
20 | }
21 |
--------------------------------------------------------------------------------
/web/src/components/mixins/baUpload.ts:
--------------------------------------------------------------------------------
1 | import type { AxiosRequestConfig } from 'axios'
2 |
3 | export const state: () => 'disable' | 'enable' = () => 'disable'
4 |
5 | export function fileUpload(fd: FormData, params: anyObj = {}, config: AxiosRequestConfig = {}): ApiPromise {
6 | // 上传扩展,定义此函数,并将上方的 state 设定为 enable,系统可自动使用此函数进行上传
7 | return new Promise((resolve, reject) => {
8 | console.log(fd, params, config)
9 | reject('未定义')
10 | })
11 | }
12 |
--------------------------------------------------------------------------------
/web/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "[json]": {
3 | "editor.defaultFormatter": "esbenp.prettier-vscode"
4 | },
5 | "[jsonc]": {
6 | "editor.defaultFormatter": "esbenp.prettier-vscode"
7 | },
8 | "[typescript]": {
9 | "editor.defaultFormatter": "esbenp.prettier-vscode"
10 | },
11 | "[vue]": {
12 | "editor.defaultFormatter": "esbenp.prettier-vscode"
13 | },
14 | "eslint.validate": ["javascript", "vue", "typescript"]
15 | }
16 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/security/dataRecycle.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Rule name': '规则名称',
3 | controller: '控制器',
4 | 'data sheet': '数据表',
5 | 'Data table primary key': '数据表主键',
6 | 'Deleting monitoring': '删除监控中',
7 | 'The rule name helps to identify deleted data later': '规则名称有助于后续识别被删数据',
8 | 'The data collection mechanism will monitor delete operations under this controller': '数据回收机制将监控此控制器下的删除操作',
9 | 'Corresponding data sheet': '对应数据表',
10 | }
11 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/auth/admin.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | username: 'Username',
3 | nickname: 'Nickname',
4 | group: 'Group',
5 | avatar: 'Avatar',
6 | email: 'Email',
7 | mobile: 'Mobile Number',
8 | 'Last login': 'Last login',
9 | Password: 'Password',
10 | 'Please leave blank if not modified': 'Please leave blank if you do not modify.',
11 | 'Personal signature': 'Personal Signature',
12 | 'Administrator login': 'Administrator Login Name',
13 | }
14 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/auth/group.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | GroupName: 'Group Name',
3 | 'Group name': 'Group Name',
4 | jurisdiction: 'Permissions',
5 | 'Parent group': 'Superior group',
6 | 'The parent group cannot be the group itself': 'The parent group cannot be the group itself',
7 | 'Manage subordinate role groups here':
8 | 'In managing a subordinate role group (excluding a peer role group), you have all the rights of a subordinate role group and additional rights',
9 | }
10 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/model/afterInsert.stub:
--------------------------------------------------------------------------------
1 |
2 | protected static function onAfterInsert($model): void
3 | {
4 | if (is_null($model->{%field%})) {
5 | $pk = $model->getPk();
6 | if (strlen($model[$pk]) >= 19) {
7 | $model->where($pk, $model[$pk])->update(['{%field%}' => $model->count()]);
8 | } else {
9 | $model->where($pk, $model[$pk])->update(['{%field%}' => $model[$pk]]);
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/routine/adminInfo.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Last logged in on': '上次登录于',
3 | 'user name': '用户名',
4 | 'User nickname': '用户昵称',
5 | 'Please enter a nickname': '请输入昵称',
6 | 'e-mail address': '邮箱地址',
7 | 'phone number': '手机号码',
8 | autograph: '签名',
9 | 'This guy is lazy and doesn write anything': '这家伙很懒,什么也没写',
10 | 'New password': '新密码',
11 | 'Please leave blank if not modified': '不修改请留空',
12 | 'Save changes': '保存修改',
13 | 'Operation log': '操作日志',
14 | }
15 |
--------------------------------------------------------------------------------
/web/src/utils/useCurrentInstance.ts:
--------------------------------------------------------------------------------
1 | import { getCurrentInstance } from 'vue'
2 | import type { ComponentInternalInstance } from 'vue'
3 |
4 | export default function useCurrentInstance() {
5 | if (!getCurrentInstance()) {
6 | throw new Error('useCurrentInstance() can only be used inside setup() or functional components!')
7 | }
8 | const { appContext } = getCurrentInstance() as ComponentInternalInstance
9 | const proxy = appContext.config.globalProperties
10 | return {
11 | proxy,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Loading...
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/web/src/assets/icons/dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/validate/validate.stub:
--------------------------------------------------------------------------------
1 | [],
28 | 'edit' => [],
29 | ];
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/user/moneyLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'User name': '用户名',
3 | 'User nickname': '用户昵称',
4 | balance: '余额',
5 | 'User ID': '用户ID',
6 | 'Change balance': '变更余额',
7 | 'Before change': '变更前',
8 | 'After change': '变更后',
9 | remarks: '备注',
10 | 'Current balance': '当前余额',
11 | 'Change amount': '变动数额',
12 | 'Please enter the balance change amount': '请输入余额变更数额',
13 | 'Balance after change': '变更后余额',
14 | 'Please enter change remarks / description': '请输入变更备注/说明',
15 | User: '用户',
16 | }
17 |
--------------------------------------------------------------------------------
/public/install/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | BuildAdmin-安装
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/admin/lang/en/crud/crud.php:
--------------------------------------------------------------------------------
1 | 'Field %s failed to be renamed because the field does not exist in the data table',
4 | 'del-field fail not exist' => 'Failed to delete field %s because the field does not exist in the data table',
5 | 'change-field-attr fail not exist' => 'Description Failed to modify the properties of field %s because the field does not exist in the data table',
6 | 'add-field fail exist' => 'Failed to add field %s because the field already exists in the data table',
7 | ];
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/index.php:
--------------------------------------------------------------------------------
1 | '无后台菜单,请联系超级管理员!',
4 | 'You have already logged in. There is no need to log in again~' => '您已经登录过了,无需重复登录~',
5 | 'Login succeeded!' => '登录成功!',
6 | 'Incorrect user name or password!' => '用户名或密码不正确!',
7 | 'Login' => '登录',
8 | 'Logout' => '注销登录',
9 | ];
10 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/controller/controller.stub:
--------------------------------------------------------------------------------
1 | 'PHPSESSID',
9 | // SESSION_ID的提交变量,解决flash上传跨域
10 | 'var_session_id' => '',
11 | // 驱动方式 支持file cache
12 | 'type' => 'file',
13 | // 存储连接标识 当type使用cache的时候有效
14 | 'store' => null,
15 | // 过期时间
16 | 'expire' => 1440,
17 | // 前缀
18 | 'prefix' => '',
19 | ];
20 |
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/crud/crud.php:
--------------------------------------------------------------------------------
1 | 'CRUD代码生成-解析字段数据',
4 | 'Log start' => 'CRUD代码生成-从历史记录开始',
5 | 'Generate check' => 'CRUD代码生成-生成前预检',
6 | 'change-field-name fail not exist' => '字段 %s 改名失败,数据表内不存在该字段',
7 | 'del-field fail not exist' => '字段 %s 删除失败,数据表内不存在该字段',
8 | 'change-field-attr fail not exist' => '修改字段 %s 的属性失败,数据表内不存在该字段',
9 | 'add-field fail exist' => '添加字段 %s 失败,数据表内已经存在该字段',
10 | 'Failed to load cloud data' => '加载云端数据失败,请稍后重试!',
11 | ];
--------------------------------------------------------------------------------
/config/cookie.php:
--------------------------------------------------------------------------------
1 | 0,
8 | // cookie 保存路径
9 | 'path' => '/',
10 | // cookie 有效域名
11 | 'domain' => '',
12 | // cookie 启用安全传输
13 | 'secure' => false,
14 | // httponly设置
15 | 'httponly' => false,
16 | // 是否使用 setcookie
17 | 'setcookie' => true,
18 | // samesite 设置,支持 'strict' 'lax'
19 | 'samesite' => '',
20 | ];
21 |
--------------------------------------------------------------------------------
/web/src/stores/constant/cacheKey.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 本地缓存Key
3 | */
4 |
5 | // 管理员资料
6 | export const ADMIN_INFO = 'adminInfo'
7 |
8 | // WEB端布局配置
9 | export const STORE_CONFIG = 'storeConfig_v2'
10 | // 后台标签页
11 | export const STORE_TAB_VIEW_CONFIG = 'storeTabViewConfig'
12 | // 终端
13 | export const STORE_TERMINAL = 'storeTerminal'
14 |
15 | // 工作时间
16 | export const WORKING_TIME = 'workingTime'
17 |
18 | // 切换到手机端前的上次布局方式
19 | export const BEFORE_RESIZE_LAYOUT = 'beforeResizeLayout'
20 |
21 | // 会员资料
22 | export const USER_INFO = 'userInfo'
23 |
24 | // ba官网用户信息
25 | export const BA_ACCOUNT = 'ba_account'
26 |
--------------------------------------------------------------------------------
/app/Request.php:
--------------------------------------------------------------------------------
1 | proxyServerIp = $proxyServerIp;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/security/sensitiveData.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Rule name': '规则名称',
3 | controller: '控制器',
4 | 'data sheet': '数据表',
5 | 'Data table primary key': '数据表主键',
6 | 'Sensitive fields': '敏感字段',
7 | 'Modifying monitoring': '修改监控中',
8 | 'The rule name helps to identify the modified data later': '规则名称有助于后续识别被修改数据',
9 | 'The data listening mechanism will monitor the modification operations under this controller': '数据监听机制将监控此控制器下的修改操作',
10 | 'Corresponding data sheet': '对应数据表',
11 | 'Filling in field notes helps you quickly identify fields later': '填写字段注释有助于后续快速识别字段',
12 | }
13 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/user/user.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'User name': '用户名',
3 | nickname: '昵称',
4 | group: '分组',
5 | avatar: '头像',
6 | Gender: '性别',
7 | male: '男',
8 | female: '女',
9 | mobile: '手机号',
10 | 'Last login IP': '最后登录IP',
11 | 'Last login': '最后登录',
12 | email: '电子邮箱',
13 | birthday: '生日',
14 | balance: '余额',
15 | 'Adjustment balance': '调整余额',
16 | integral: '积分',
17 | 'Adjust integral': '调整积分',
18 | password: '密码',
19 | 'Please leave blank if not modified': '不修改请留空',
20 | 'Personal signature': '个性签名',
21 | 'Login account': '登录账户名',
22 | }
23 |
--------------------------------------------------------------------------------
/web/src/layouts/frontend/components/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/app/admin/model/UserRule.php:
--------------------------------------------------------------------------------
1 | getPk();
18 | $model->where($pk, $model[$pk])->update(['weigh' => $model[$pk]]);
19 | }
20 |
21 | public function setComponentAttr($value)
22 | {
23 | if ($value) $value = str_replace('\\', '/', $value);
24 | return $value;
25 | }
26 | }
--------------------------------------------------------------------------------
/app/common/middleware/AdminLog.php:
--------------------------------------------------------------------------------
1 | isPost() || $request->isDelete()) && Config::get('buildadmin.auto_write_admin_log')) {
20 | AdminLogModel::instance()->record();
21 | }
22 | return $response;
23 | }
24 | }
--------------------------------------------------------------------------------
/web/src/styles/dark.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:map';
2 | @use 'mixins.scss' as *;
3 | @use 'element-plus/theme-chalk/src/dark/css-vars.scss';
4 |
5 | // Background
6 | $bg-color: () !default;
7 | $bg-color: map.merge(
8 | (
9 | '': #141414,
10 | 'overlay': #1d1e1f,
11 | ),
12 | $bg-color
13 | );
14 |
15 | // Border
16 | $border-color: () !default;
17 | $border-color: map.merge(
18 | (
19 | '': #4c4d4f,
20 | ),
21 | $border-color
22 | );
23 |
24 | html.dark {
25 | @include set-component-css-var('bg-color', $bg-color);
26 | @include set-component-css-var('border-color', $border-color);
27 | }
28 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/security/dataRecycle.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Rule name': 'Rule name',
3 | controller: 'Controller',
4 | 'data sheet': 'Data table',
5 | 'Data table primary key': 'Data table primary key',
6 | 'Deleting monitoring': 'Delete monitoring',
7 | 'The rule name helps to identify deleted data later': 'Rule names help to identify deleted data subsequently later.',
8 | 'The data collection mechanism will monitor delete operations under this controller':
9 | 'The data recycle mechanism will monitor the delete operations under this controller.',
10 | 'Corresponding data sheet': 'Corresponding data sheet',
11 | }
12 |
--------------------------------------------------------------------------------
/app/admin/model/DataRecycleLog.php:
--------------------------------------------------------------------------------
1 | belongsTo(DataRecycle::class, 'recycle_id');
21 | }
22 |
23 | public function admin(): BelongsTo
24 | {
25 | return $this->belongsTo(Admin::class, 'admin_id');
26 | }
27 | }
--------------------------------------------------------------------------------
/web/src/lang/autoload.ts:
--------------------------------------------------------------------------------
1 | import { adminBaseRoutePath } from '/@/router/static/adminBase'
2 |
3 | /*
4 | * 语言包按需加载映射表
5 | * 使用固定字符串 ${lang} 指代当前语言
6 | * key 为页面 path,value 为语言包文件相对路径,访问时,按需自动加载映射表的语言包,同时加载 path 对应的语言包(若存在)
7 | */
8 | export default {
9 | '/': ['./frontend/${lang}/index.ts'],
10 | [adminBaseRoutePath + '/moduleStore']: ['./backend/${lang}/module.ts'],
11 | [adminBaseRoutePath + '/user/rule']: ['./backend/${lang}/auth/rule.ts'],
12 | [adminBaseRoutePath + '/user/scoreLog']: ['./backend/${lang}/user/moneyLog.ts'],
13 | [adminBaseRoutePath + '/crud/crud']: ['./backend/${lang}/crud/log.ts', './backend/${lang}/crud/state.ts'],
14 | }
15 |
--------------------------------------------------------------------------------
/app/admin/lang/en/index.php:
--------------------------------------------------------------------------------
1 | 'No background menu, please contact the super administrator!',
4 | 'You have already logged in. There is no need to log in again~' => 'You have already logged in, no need to log in again.',
5 | 'Login succeeded!' => 'Login successful!',
6 | 'Incorrect user name or password!' => 'Incorrect username or password!',
7 | 'Login' => 'Login',
8 | 'Logout' => 'Logout',
9 | ];
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/customTemplate.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
22 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/routine/adminInfo.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Last logged in on': 'Last logged on',
3 | 'user name': 'Username',
4 | 'User nickname': 'User nickname',
5 | 'Please enter a nickname': 'Please enter a nickname',
6 | 'e-mail address': 'E-mail address',
7 | 'phone number': 'Mobile number',
8 | autograph: 'Signature',
9 | 'This guy is lazy and doesn write anything': "This guy is lazy and didn't write anything.",
10 | 'New password': 'New password',
11 | 'Please leave blank if not modified': 'Please leave blank if you do not modify',
12 | 'Save changes': 'Save changes',
13 | 'Operation log': 'Operation log',
14 | }
15 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/routine/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Are you sure to delete the configuration item?': '确定删除配置项吗?',
3 | 'Add configuration item': '添加配置项',
4 | 'Quick configuration entry': '快捷配置入口',
5 | 'Variable name': '变量名',
6 | 'Variable group': '变量分组',
7 | 'Variable title': '变量标题',
8 | 'Variable type': '变量类型',
9 | number: '数字',
10 | 'Please enter the recipient email address': '请输入接收者邮箱地址',
11 | 'Test mail sending': '测试邮件发送',
12 | 'send out': '发送',
13 | 'Please enter the correct email address': '请输入正确的电子邮箱地址',
14 | Sending: '发送中...',
15 | 'Please enter the correct mail configuration': '请输入正确的邮件配置',
16 | }
17 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/security/dataRecycleLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | restore: '还原',
3 | 'Are you sure to restore the selected records?': '确定还原选中记录?',
4 | 'Restore the selected record to the original data table': '还原选中记录到原数据表',
5 | 'Operation administrator': '操作管理员',
6 | 'Recycling rule name': '回收规则名称',
7 | 'Rule name': '规则名称',
8 | controller: '控制器',
9 | 'data sheet': '数据表',
10 | DeletedData: '被删数据',
11 | 'Arbitrary fragment fuzzy query': '任意片段模糊查询',
12 | 'Click to expand': '点击展开',
13 | 'Data table primary key': '数据表主键',
14 | 'Operator IP': '操作者IP',
15 | 'Deleted data': '被删除的数据',
16 | 'Delete time': '删除时间',
17 | }
18 |
--------------------------------------------------------------------------------
/app/admin/model/SensitiveDataLog.php:
--------------------------------------------------------------------------------
1 | belongsTo(SensitiveData::class, 'sensitive_id');
21 | }
22 |
23 | public function admin(): BelongsTo
24 | {
25 | return $this->belongsTo(Admin::class, 'admin_id');
26 | }
27 | }
--------------------------------------------------------------------------------
/config/filesystem.php:
--------------------------------------------------------------------------------
1 | env('filesystem.driver', 'local'),
6 | // 磁盘列表
7 | 'disks' => [
8 | 'local' => [
9 | 'type' => 'local',
10 | 'root' => app()->getRuntimePath() . 'storage',
11 | ],
12 | 'public' => [
13 | // 磁盘类型
14 | 'type' => 'local',
15 | // 磁盘路径
16 | 'root' => app()->getRootPath() . 'public/storage',
17 | // 磁盘路径对应的外部URL路径
18 | 'url' => '/storage',
19 | // 可见性
20 | 'visibility' => 'public',
21 | ],
22 | // 更多的磁盘配置信息
23 | ],
24 | ];
25 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/datetime.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ !cellValue ? '-' : timeFormat(cellValue, field.timeFormat ?? 'yyyy-mm-dd hh:MM:ss') }}
4 |
5 |
6 |
7 |
23 |
--------------------------------------------------------------------------------
/web/types/global.d.ts:
--------------------------------------------------------------------------------
1 | interface Window {
2 | existLoading: boolean
3 | lazy: number
4 | unique: number
5 | tokenRefreshing: boolean
6 | requests: Function[]
7 | eventSource: EventSource
8 | loadLangHandle: Record
9 | }
10 |
11 | interface anyObj {
12 | [key: string]: any
13 | }
14 |
15 | interface TableDefaultData {
16 | list: T
17 | remark: string
18 | total: number
19 | }
20 |
21 | interface ApiResponse {
22 | code: number
23 | data: T
24 | msg: string
25 | time: number
26 | }
27 |
28 | type ApiPromise = Promise>
29 |
30 | type Writeable = { -readonly [P in keyof T]: T[P] }
31 |
--------------------------------------------------------------------------------
/web/src/api/backend/security/dataRecycleLog.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/security.DataRecycleLog/'
4 |
5 | export function restore(ids: string[]) {
6 | return createAxios(
7 | {
8 | url: url + 'restore',
9 | method: 'POST',
10 | data: {
11 | ids: ids,
12 | },
13 | },
14 | {
15 | showSuccessMessage: true,
16 | }
17 | )
18 | }
19 |
20 | export function info(id: string) {
21 | return createAxios({
22 | url: url + 'info',
23 | method: 'get',
24 | params: {
25 | id: id,
26 | },
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/web/src/assets/icons/lang.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/security/sensitiveDataLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Operation administrator': '操作管理员',
3 | 'Rule name': '规则名称',
4 | controller: '控制器',
5 | 'data sheet': '数据表',
6 | 'Modify line': '修改行',
7 | Modification: '修改项',
8 | 'Before modification': '修改前',
9 | 'After modification': '修改后',
10 | 'Modification time': '修改时间',
11 | 'Are you sure you want to rollback the record?': '确认要回滚记录吗?',
12 | 'Rollback the selected record to the original data table': '回滚选中记录到原数据表',
13 | 'Operator IP': '操作者IP',
14 | 'Data table primary key': '数据表主键',
15 | 'Modified item': '被修改项',
16 | 'Modification comparison': '修改对比',
17 | RollBACK: '回滚',
18 | }
19 |
--------------------------------------------------------------------------------
/web/src/api/backend/security/sensitiveDataLog.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/security.SensitiveDataLog/'
4 |
5 | export function rollback(ids: string[]) {
6 | return createAxios(
7 | {
8 | url: url + 'rollback',
9 | method: 'POST',
10 | data: {
11 | ids: ids,
12 | },
13 | },
14 | {
15 | showSuccessMessage: true,
16 | }
17 | )
18 | }
19 |
20 | export function info(id: string) {
21 | return createAxios({
22 | url: url + 'info',
23 | method: 'get',
24 | params: {
25 | id: id,
26 | },
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/user/moneyLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'User name': 'Username',
3 | 'User nickname': 'User nickname',
4 | balance: 'Balance',
5 | 'User ID': 'User ID',
6 | 'Change balance': 'Change balance',
7 | 'Before change': 'Before the change',
8 | 'After change': 'After the change',
9 | remarks: 'Remark',
10 | 'Current balance': 'Current balance',
11 | 'Change amount': 'Change amount',
12 | 'Please enter the balance change amount': 'Please enter the balance change amount.',
13 | 'Balance after change': 'Balance after change',
14 | 'Please enter change remarks / description': 'Please enter change remarks/description',
15 | User: 'User',
16 | }
17 |
--------------------------------------------------------------------------------
/web/src/lang/frontend/zh-cn/user/login.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | reach: '到',
3 | login: '登录',
4 | register: '注册',
5 | 'Via email': '通过邮箱',
6 | 'Via mobile number': '通过手机号',
7 | 'User name': '用户名',
8 | account: '用户名/邮箱/手机号',
9 | password: '密码',
10 | 'Verification Code': '验证码',
11 | mobile: '手机号',
12 | email: '电子邮箱',
13 | send: '发送',
14 | seconds: '秒',
15 | 'Remember me': '记住我',
16 | 'Forgot your password?': '忘记密码?',
17 | 'Back to login': '回到登录',
18 | 'No account yet? Click Register': '还没有账户?点击注册',
19 | 'Retrieve password': '找回密码',
20 | 'Retrieval method': '找回方式',
21 | 'New password': '新密码',
22 | second: '确定',
23 | 'Account name': '账户',
24 | }
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # 通过 Git 部署项目至线上时建议删除的忽略规则
2 | /vendor
3 | /modules
4 | /public/*.lock
5 | /public/index.html
6 | /public/assets
7 |
8 | # 通过 Git 部署项目至线上时可以考虑删除的忽略规则
9 | /public/storage/*
10 | composer.lock
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
15 | # common
16 | /nbproject
17 | /runtime/*
18 | /install
19 | node_modules
20 | dist
21 | dist-ssr
22 | .DS_Store
23 | /.env
24 | Desktop.ini
25 |
26 | # Log files
27 | *.log
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 | pnpm-debug.log*
32 |
33 | # Editor directories and files
34 | .idea
35 | .vscode
36 | *.suo
37 | *.ntvs*
38 | *.njsproj
39 | *.sln
40 | *.sw?
41 | !/web/.vscode
42 |
43 | # Other
44 | *.css.map
45 | *.local
46 | !.gitkeep
47 | .svn
--------------------------------------------------------------------------------
/config/view.php:
--------------------------------------------------------------------------------
1 | 'Think',
9 | // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
10 | 'auto_rule' => 1,
11 | // 模板目录名
12 | 'view_dir_name' => 'view',
13 | // 模板后缀
14 | 'view_suffix' => 'html',
15 | // 模板文件名分隔符
16 | 'view_depr' => DIRECTORY_SEPARATOR,
17 | // 模板引擎普通标签开始标记
18 | 'tpl_begin' => '{',
19 | // 模板引擎普通标签结束标记
20 | 'tpl_end' => '}',
21 | // 标签库标签开始标记
22 | 'taglib_begin' => '{',
23 | // 标签库标签结束标记
24 | 'taglib_end' => '}',
25 | ];
26 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/color.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
22 |
23 |
29 |
--------------------------------------------------------------------------------
/web/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "lib": ["ESNext", "DOM"],
6 | "useDefineForClassFields": true,
7 | "moduleResolution": "Bundler",
8 | "strict": true,
9 | "jsx": "preserve",
10 | "sourceMap": false,
11 | "resolveJsonModule": true,
12 | "esModuleInterop": true,
13 | "isolatedModules": true,
14 | "baseUrl": "./",
15 | "allowJs": true,
16 | "skipLibCheck": true,
17 | "paths": {
18 | "/@/*": ["src/*"]
19 | },
20 | "types": ["vite/client", "element-plus/global"]
21 | },
22 | "include": ["src/**/*.ts", "src/**/*.vue", "types/**/*.d.ts", "vite.config.ts"]
23 | }
24 |
--------------------------------------------------------------------------------
/config/upload.php:
--------------------------------------------------------------------------------
1 | '10mb',
9 | // 文件保存格式化方法:topic=存储子目录,fileName=文件名前15个字符
10 | 'save_name' => '/storage/{topic}/{year}{mon}{day}/{fileName}{fileSha1}{.suffix}',
11 |
12 | /**
13 | * 上传文件的后缀和 MIME类型 白名单
14 | * 0. 永远使用最少配置
15 | * 1. 此处不支持通配符
16 | * 2. 千万不要允许 php,php5,.htaccess,.user.ini 等可执行或配置文件
17 | * 3. 允许 pdf,ppt,docx 等可能含有脚本的文件时,请先从服务器配置此类文件直接下载而不是预览
18 | */
19 | 'allowed_suffixes' => 'jpg,png,bmp,jpeg,gif,webp,zip,rar,wav,mp4,mp3',
20 | 'allowed_mime_types' => [],
21 | ];
--------------------------------------------------------------------------------
/web/src/lang/backend/en/user/user.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'User name': 'Username',
3 | nickname: 'Nickname',
4 | group: 'Group',
5 | avatar: 'Avatar',
6 | Gender: 'Gender',
7 | male: 'Male',
8 | female: 'Female',
9 | mobile: 'Mobile Number',
10 | 'Last login IP': 'Last login IP',
11 | 'Last login': 'Last login',
12 | email: 'Email',
13 | birthday: 'Birthday',
14 | balance: 'Balance',
15 | 'Adjustment balance': 'Adjust balance',
16 | integral: 'Integral',
17 | 'Adjust integral': 'Adjust integral',
18 | password: 'Password',
19 | 'Please leave blank if not modified': 'Please leave blank if you do not modify',
20 | 'Personal signature': 'Personal signature',
21 | 'Login account': 'Login account name',
22 | }
23 |
--------------------------------------------------------------------------------
/app/admin/validate/Config.php:
--------------------------------------------------------------------------------
1 | 'require|unique:config',
13 | ];
14 |
15 | /**
16 | * 验证提示信息
17 | * @var array
18 | */
19 | protected $message = [];
20 |
21 | /**
22 | * 字段描述
23 | */
24 | protected $field = [
25 | ];
26 |
27 | /**
28 | * 验证场景
29 | */
30 | protected $scene = [
31 | 'add' => ['name'],
32 | ];
33 |
34 | public function __construct()
35 | {
36 | $this->field = [
37 | 'name' => __('Variable name'),
38 | ];
39 | parent::__construct();
40 | }
41 | }
--------------------------------------------------------------------------------
/web/src/styles/mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin set-css-var-value($name, $value) {
2 | #{joinVarName($name)}: #{$value};
3 | }
4 |
5 | @function joinVarName($list) {
6 | $name: '--ba';
7 | @each $item in $list {
8 | @if $item != '' {
9 | $name: $name + '-' + $item;
10 | }
11 | }
12 | @return $name;
13 | }
14 |
15 | @function getCssVarName($args...) {
16 | @return joinVarName($args);
17 | }
18 |
19 | /*
20 | * 通过映射设置所有的CSS变量
21 | */
22 | @mixin set-component-css-var($name, $variables) {
23 | @each $attribute, $value in $variables {
24 | @if $attribute == 'default' {
25 | #{getCssVarName($name)}: #{$value};
26 | } @else {
27 | #{getCssVarName($name, $attribute)}: #{$value};
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/web/src/styles/var.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:map';
2 | @use 'mixins' as *;
3 |
4 | // 后台主体窗口左右间距
5 | $main-space: 16px;
6 | $primary-light: #3f6ad8;
7 |
8 | // --ba-background
9 | $bg-color: () !default;
10 | $bg-color: map.merge(
11 | (
12 | '': #f5f5f5,
13 | 'overlay': #ffffff,
14 | ),
15 | $bg-color
16 | );
17 |
18 | // --ba-border-color
19 | $border-color: () !default;
20 | $border-color: map.merge(
21 | (
22 | '': #f6f6f6,
23 | ),
24 | $border-color
25 | );
26 |
27 | :root {
28 | @include set-css-var-value('main-space', $main-space);
29 | @include set-css-var-value('color-primary-light', $primary-light);
30 | @include set-component-css-var('bg-color', $bg-color);
31 | @include set-component-css-var('border-color', $border-color);
32 | }
33 |
--------------------------------------------------------------------------------
/web/src/utils/pageShade.ts:
--------------------------------------------------------------------------------
1 | import { useEventListener } from '@vueuse/core'
2 |
3 | /*
4 | * 显示页面遮罩
5 | */
6 | export const showShade = function (className = 'shade', closeCallBack: Function): void {
7 | const containerEl = document.querySelector('.layout-container') as HTMLElement
8 | const shadeDiv = document.createElement('div')
9 | shadeDiv.setAttribute('class', 'ba-layout-shade ' + className)
10 | containerEl.appendChild(shadeDiv)
11 | useEventListener(shadeDiv, 'click', () => closeShade(closeCallBack))
12 | }
13 |
14 | /*
15 | * 隐藏页面遮罩
16 | */
17 | export const closeShade = function (closeCallBack: Function = () => {}): void {
18 | const shadeEl = document.querySelector('.ba-layout-shade') as HTMLElement
19 | shadeEl && shadeEl.remove()
20 |
21 | closeCallBack()
22 | }
23 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
26 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/customRender.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
29 |
--------------------------------------------------------------------------------
/app/common/facade/Token.php:
--------------------------------------------------------------------------------
1 | env('cache.driver', 'file'),
10 |
11 | // 缓存连接方式配置
12 | 'stores' => [
13 | 'file' => [
14 | // 驱动方式
15 | 'type' => 'File',
16 | // 缓存保存目录
17 | 'path' => '',
18 | // 缓存前缀
19 | 'prefix' => '',
20 | // 缓存有效期 0表示永久缓存
21 | 'expire' => 0,
22 | // 缓存标签前缀
23 | 'tag_prefix' => 'tag:',
24 | // 序列化机制 例如 ['serialize', 'unserialize']
25 | 'serialize' => [],
26 | ],
27 | // 更多的缓存连接
28 | ],
29 | ];
30 |
--------------------------------------------------------------------------------
/web/src/lang/common/zh-cn/validate.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Captcha loading failed, please click refresh button': '验证码加载失败,请点击刷新按钮',
3 | 'The correct area is not clicked, please try again!': '未点中正确区域,请重试!',
4 | 'Verification is successful!': '验证成功!',
5 | 'Please click': '请依次点击',
6 | 'Please enter the correct mobile number': '请输入正确的手机号',
7 | 'Please enter the correct account': '要求3到15位,字母开头且只含字母、数字、下划线',
8 | 'Please enter the correct password': '密码要求6到32位,不能包含 & < > " \'',
9 | 'Please enter the correct name': '请输入正确的名称',
10 | 'Content cannot be empty': '内容不能为空',
11 | 'Floating point number': '浮点数',
12 | required: '必填',
13 | 'editor required': '富文本必填',
14 | 'Please enter the correct ID number': '请输入正确的身份证号码',
15 | number: '数字(包括浮点数和整数)',
16 | integer: '整数(不包括浮点数)',
17 | float: '浮点数(不包括整数)',
18 | }
19 |
--------------------------------------------------------------------------------
/config/lang.php:
--------------------------------------------------------------------------------
1 | env('lang.default_lang', 'zh-cn'),
9 | // 允许的语言列表
10 | 'allow_lang_list' => ['zh-cn', 'en'],
11 | // 多语言自动侦测变量名
12 | 'detect_var' => 'lang',
13 | // 是否使用Cookie记录-开启后 ob_flush() 等操作会报错
14 | 'use_cookie' => false,
15 | // 多语言cookie变量
16 | 'cookie_var' => 'think_lang',
17 | // 多语言header变量
18 | 'header_var' => 'think-lang',
19 | // 扩展语言包
20 | 'extend_list' => [],
21 | // Accept-Language转义为对应语言包名称
22 | 'accept_language' => [
23 | 'zh-hans-cn' => 'zh-cn',
24 | ],
25 | // 是否支持语言分组
26 | 'allow_group' => false,
27 | ];
28 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/security/sensitiveData.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Rule name': 'Rule name',
3 | controller: 'Controller',
4 | 'data sheet': 'Data table',
5 | 'Data table primary key': 'Data table primary key',
6 | 'Sensitive fields': 'Sensitive fields',
7 | 'Modifying monitoring': 'Modify monitoring',
8 | 'The rule name helps to identify the modified data later': 'Rule names help to identify modified data subsequently later.',
9 | 'The data listening mechanism will monitor the modification operations under this controller':
10 | 'The data monitor mechanism will monitor the modified operation under this controller.',
11 | 'Corresponding data sheet': 'Corresponding data table',
12 | 'Filling in field notes helps you quickly identify fields later': 'Fill in field comments help to identify fields quickly later.',
13 | }
14 |
--------------------------------------------------------------------------------
/database/migrations/20231112093414_version205.php:
--------------------------------------------------------------------------------
1 | find();
12 | $value = $configQuickEntrance->value;
13 | foreach ($value as &$item) {
14 | if (str_starts_with($item['value'], '/admin/')) {
15 | $pathData = Db::name('admin_rule')->where('path', substr($item['value'], 7))->find();
16 | if ($pathData) {
17 | $item['value'] = $pathData['name'];
18 | }
19 | }
20 | }
21 | $configQuickEntrance->value = $value;
22 | $configQuickEntrance->save();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/routine/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Are you sure to delete the configuration item?': 'Are you sure to delete the configuration item?',
3 | 'Add configuration item': 'Add configuration item',
4 | 'Quick configuration entry': 'Quick configuration entry',
5 | 'Variable name': 'Variable name',
6 | 'Variable group': 'Variable group',
7 | 'Variable title': 'Variable title',
8 | 'Variable type': 'Variable type',
9 | number: 'Number',
10 | 'Please enter the recipient email address': 'Please enter the recipient email address',
11 | 'Test mail sending': 'Test mail sending',
12 | 'send out': 'send',
13 | 'Please enter the correct email address': 'Please enter the correct email address',
14 | Sending: 'Sending',
15 | 'Please enter the correct mail configuration': 'Please enter the correct mail configuration',
16 | }
17 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/security/dataRecycleLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | restore: 'Restore',
3 | 'Are you sure to restore the selected records?': 'Are you sure to restore the selected records?',
4 | 'Restore the selected record to the original data table': 'Restore the selected record to the original data table.',
5 | 'Operation administrator': 'Operation administrator',
6 | 'Recycling rule name': 'Recycling rule name',
7 | 'Rule name': 'Rule name',
8 | controller: 'Controller',
9 | 'data sheet': 'Data table',
10 | DeletedData: 'Deleted data',
11 | 'Arbitrary fragment fuzzy query': 'Arbitrary fragment fuzzy query',
12 | 'Click to expand': 'Click to expand',
13 | 'Data table primary key': 'Data table primary key',
14 | 'Operator IP': 'Operator IP',
15 | 'Deleted data': 'Deleted data',
16 | 'Delete time': 'Delete time',
17 | }
18 |
--------------------------------------------------------------------------------
/web/src/layouts/common/router-view/iframe.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
23 |
24 |
32 |
--------------------------------------------------------------------------------
/web/src/lang/frontend/en/user/login.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | reach: ' Reach ',
3 | login: 'Login',
4 | register: 'Register',
5 | 'Via email': 'By email',
6 | 'Via mobile number': 'By mobile number',
7 | 'User name': 'User name',
8 | account: 'Username/Email/Mobile',
9 | password: 'Password',
10 | 'Verification Code': 'Captcha',
11 | mobile: 'mobile',
12 | email: 'email',
13 | send: 'send',
14 | seconds: 'seconds',
15 | 'Remember me': 'Remember me',
16 | 'Forgot your password?': 'Forgot your password?',
17 | 'Back to login': 'Back to login',
18 | 'No account yet? Click Register': 'No account yet? Click Register',
19 | 'Retrieve password': 'Retrieve password',
20 | 'Retrieval method': 'Retrieval method',
21 | 'New password': 'New password',
22 | second: 'second',
23 | 'Account name': 'Account name',
24 | }
25 |
--------------------------------------------------------------------------------
/app/admin/controller/crud/Log.php:
--------------------------------------------------------------------------------
1 | model = new CrudLog();
31 |
32 | if (!$this->auth->check('crud/crud/index')) {
33 | $this->error(__('You have no permission'), [], 401);
34 | }
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/web/src/layouts/backend/container/streamline.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
30 |
--------------------------------------------------------------------------------
/app/admin/library/stubs/backendEntrance.stub:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // [ 应用入口文件 ]
13 | namespace think;
14 |
15 | require __DIR__ . '/../vendor/autoload.php';
16 |
17 | // 执行HTTP应用并响应
18 | $http = (new App())->http;
19 |
20 | $response = $http->name('admin')->run();
21 |
22 | $response->send();
23 |
24 | $http->end($response);
25 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/security/sensitiveDataLog.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Operation administrator': 'Operation administrator',
3 | 'Rule name': 'Rule name',
4 | controller: 'Controller',
5 | 'data sheet': 'Data table',
6 | 'Modify line': 'Modify row',
7 | Modification: 'Modify item',
8 | 'Before modification': 'Before modification',
9 | 'After modification': 'After modification',
10 | 'Modification time': 'Modify time',
11 | 'Are you sure you want to rollback the record?': 'Are you sure to rollback the record?',
12 | 'Rollback the selected record to the original data table': 'Rollback the selected record to the original data table.',
13 | 'Operator IP': 'Operator IP',
14 | 'Data table primary key': 'Data table primary key',
15 | 'Modified item': 'Modified item',
16 | 'Modification comparison': 'Modify the comparison',
17 | RollBACK: 'Rollback',
18 | }
19 |
--------------------------------------------------------------------------------
/web/src/router/static/memberCenterBase.ts:
--------------------------------------------------------------------------------
1 | import type { RouteRecordRaw } from 'vue-router'
2 |
3 | /**
4 | * 会员中心基础路由路径
5 | */
6 | export const memberCenterBaseRoutePath = '/user'
7 |
8 | /*
9 | * 会员中心基础静态路由
10 | */
11 | const memberCenterBaseRoute: RouteRecordRaw = {
12 | path: memberCenterBaseRoutePath,
13 | name: 'user',
14 | component: () => import('/@/layouts/frontend/user.vue'),
15 | // 重定向到 loading 路由
16 | redirect: memberCenterBaseRoutePath + '/loading',
17 | meta: {
18 | title: `pagesTitle.user`,
19 | },
20 | children: [
21 | {
22 | path: 'loading/:to?',
23 | name: 'userMainLoading',
24 | component: () => import('/@/layouts/common/components/loading.vue'),
25 | meta: {
26 | title: `pagesTitle.loading`,
27 | },
28 | },
29 | ],
30 | }
31 |
32 | export default memberCenterBaseRoute
33 |
--------------------------------------------------------------------------------
/web/src/views/backend/crud/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/public/router.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 | // $Id$
12 |
13 | @ini_set('zlib.output_compression', 'Off');
14 |
15 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
16 | return false;
17 | } else {
18 | $_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php';
19 |
20 | require __DIR__ . "/index.php";
21 | }
22 |
--------------------------------------------------------------------------------
/web/src/lang/frontend/zh-cn/user/account/profile.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | profile: '个人资料',
3 | 'Change Password': '修改密码',
4 | avatar: '头像',
5 | 'User name': '用户名',
6 | 'User nickname': '用户昵称',
7 | mail: '邮箱',
8 | email: '电子邮箱',
9 | 'Operation via right button': '通过右侧按钮操作',
10 | 'Click Modify': '点击修改',
11 | bind: '绑定',
12 | mobile: '手机号',
13 | Gender: '性别',
14 | secrecy: '保密',
15 | male: '男',
16 | female: '女',
17 | birthday: '生日',
18 | 'Personal signature': '个性签名',
19 | 'Account verification': '账户验证',
20 | 'Account password verification': '账户密码验证',
21 | 'Mail verification': '邮件验证',
22 | 'SMS verification': '短信验证',
23 | password: '密码',
24 | accept: '接受',
25 | 'next step': '下一步',
26 | 'New email': '新邮箱',
27 | 'New mobile': '新手机号',
28 | 'Verification Code': '验证码',
29 | send: '发送',
30 | seconds: '秒',
31 | nickname: '昵称',
32 | }
33 |
--------------------------------------------------------------------------------
/app/admin/lang/en/ajax.php:
--------------------------------------------------------------------------------
1 | 'Failed to switch package manager, please modify the configuration file manually:%s',
4 | 'Failed to modify the terminal configuration. Please modify the configuration file manually:%s' => 'Failed to modify the terminal configuration, please modify the configuration file manually:%s',
5 | 'upload' => 'Upload files',
6 | 'Change terminal config' => 'Modify terminal configuration',
7 | 'Clear cache' => 'Clear cache',
8 | 'Data table does not exist' => 'Data table does not exist',
9 | ];
--------------------------------------------------------------------------------
/web/src/stores/refs.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * references
3 | * 全局提供:引用(指向)一些对象(组件)的句柄
4 | */
5 | import type { ScrollbarInstance } from 'element-plus'
6 | import type { CSSProperties } from 'vue'
7 | import { computed, ref } from 'vue'
8 | import NavTabs from '/@/layouts/backend/components/navBar/tabs.vue'
9 | import { mainHeight } from '/@/utils/layout'
10 |
11 | /**
12 | * 后台顶栏(tabs)组件ref(仅默认和经典布局)
13 | */
14 | export const layoutNavTabsRef = ref>()
15 |
16 | /**
17 | * 前后台布局的主体的滚动条组件ref
18 | */
19 | export const layoutMainScrollbarRef = ref()
20 |
21 | /**
22 | * 前后台布局的主体滚动条的额外样式,包括高度
23 | */
24 | export const layoutMainScrollbarStyle = computed(() => mainHeight())
25 |
26 | /**
27 | * 前后台布局的菜单组件ref
28 | */
29 | export const layoutMenuRef = ref()
30 |
31 | /**
32 | * 前后台布局的菜单栏滚动条组件ref
33 | */
34 | export const layoutMenuScrollbarRef = ref()
35 |
--------------------------------------------------------------------------------
/web/src/router/static/adminBase.ts:
--------------------------------------------------------------------------------
1 | import type { RouteRecordRaw } from 'vue-router'
2 |
3 | /**
4 | * 后台基础路由路径
5 | * 您可以随时于后台->系统配置中修改此值,程序可自动完成代码修改,同时建立对应的API入口和禁止admin应用访问
6 | */
7 | export const adminBaseRoutePath = '/admin'
8 |
9 | /*
10 | * 后台基础静态路由
11 | */
12 | const adminBaseRoute: RouteRecordRaw = {
13 | path: adminBaseRoutePath,
14 | name: 'admin',
15 | component: () => import('/@/layouts/backend/index.vue'),
16 | // 直接重定向到 loading 路由
17 | redirect: adminBaseRoutePath + '/loading',
18 | meta: {
19 | title: `pagesTitle.admin`,
20 | },
21 | children: [
22 | {
23 | path: 'loading/:to?',
24 | name: 'adminMainLoading',
25 | component: () => import('/@/layouts/common/components/loading.vue'),
26 | meta: {
27 | title: `pagesTitle.loading`,
28 | },
29 | },
30 | ],
31 | }
32 |
33 | export default adminBaseRoute
34 |
--------------------------------------------------------------------------------
/config/app.php:
--------------------------------------------------------------------------------
1 | env('app.host', ''),
9 | // 应用的命名空间
10 | 'app_namespace' => '',
11 | // 是否启用路由
12 | 'with_route' => true,
13 | // 默认应用
14 | 'default_app' => 'api',
15 | // 默认时区
16 | 'default_timezone' => 'Asia/Shanghai',
17 |
18 | // 应用映射(自动多应用模式有效)
19 | 'app_map' => [],
20 | // 域名绑定(自动多应用模式有效)
21 | 'domain_bind' => [],
22 | // 禁止URL访问的应用列表(自动多应用模式有效)
23 | 'deny_app_list' => ['common'],
24 |
25 | // 异常页面的模板文件
26 | 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
27 |
28 | // 错误显示信息,非调试模式有效
29 | 'error_message' => '页面错误!请稍后再试~',
30 | // 显示错误信息
31 | 'show_error_msg' => false,
32 | ];
33 |
--------------------------------------------------------------------------------
/app/admin/validate/AdminGroup.php:
--------------------------------------------------------------------------------
1 | 'require',
13 | 'rules' => 'require',
14 | ];
15 |
16 | /**
17 | * 验证提示信息
18 | * @var array
19 | */
20 | protected $message = [];
21 |
22 | /**
23 | * 字段描述
24 | */
25 | protected $field = [
26 | ];
27 |
28 | /**
29 | * 验证场景
30 | */
31 | protected $scene = [
32 | 'add' => ['name', 'rules'],
33 | 'edit' => ['name', 'rules'],
34 | ];
35 |
36 | public function __construct()
37 | {
38 | $this->field = [
39 | 'name' => __('name'),
40 | ];
41 | $this->message = [
42 | 'rules' => __('Please select rules'),
43 | ];
44 | parent::__construct();
45 | }
46 | }
--------------------------------------------------------------------------------
/web/src/api/backend/routine/AdminInfo.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/routine.AdminInfo/'
4 |
5 | export const actionUrl = new Map([
6 | ['index', url + 'index'],
7 | ['edit', url + 'edit'],
8 | ['log', '/admin/auth.AdminLog/index'],
9 | ])
10 |
11 | export function index() {
12 | return createAxios({
13 | url: actionUrl.get('index'),
14 | method: 'get',
15 | })
16 | }
17 |
18 | export function log(filter: anyObj = {}) {
19 | return createAxios({
20 | url: actionUrl.get('log'),
21 | method: 'get',
22 | params: filter,
23 | })
24 | }
25 |
26 | export function postData(data: anyObj) {
27 | return createAxios(
28 | {
29 | url: actionUrl.get('edit'),
30 | method: 'post',
31 | data: data,
32 | },
33 | {
34 | showSuccessMessage: true,
35 | }
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/app/common/model/UserMoneyLog.php:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
15 |
16 |
34 |
--------------------------------------------------------------------------------
/web/src/layouts/backend/container/double.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
32 |
--------------------------------------------------------------------------------
/web/src/layouts/backend/container/classic.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
32 |
--------------------------------------------------------------------------------
/web/src/layouts/backend/container/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
32 |
--------------------------------------------------------------------------------
/web/src/lang/common/zh-cn/axios.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Operation successful': '操作成功',
3 | 'Automatic cancellation due to duplicate request:': '因为请求重复被自动取消:',
4 | 'Interface redirected!': '接口重定向了!',
5 | 'Incorrect parameter!': '参数不正确!',
6 | 'You do not have permission to operate!': '您没有权限操作!',
7 | 'Error requesting address:': '请求地址出错:',
8 | 'Request timed out!': '请求超时!',
9 | 'The same data already exists in the system!': '系统已存在相同数据!',
10 | 'Server internal error!': '服务器内部错误!',
11 | 'Service not implemented!': '服务未实现!',
12 | 'Gateway error!': '网关错误!',
13 | 'Service unavailable!': '服务不可用!',
14 | 'The service is temporarily unavailable Please try again later!': '服务暂时无法访问,请稍后再试!',
15 | 'HTTP version is not supported!': 'HTTP版本不受支持!',
16 | 'Abnormal problem, please contact the website administrator!': '异常问题,请联系网站管理员!',
17 | 'Network request timeout!': '网络请求超时!',
18 | 'Server exception!': '服务端异常!',
19 | 'You are disconnected!': '您断网了!',
20 | }
21 |
--------------------------------------------------------------------------------
/app/admin/validate/AdminRule.php:
--------------------------------------------------------------------------------
1 | 'require',
13 | 'title' => 'require',
14 | 'name' => 'require|unique:admin_rule',
15 | ];
16 |
17 | /**
18 | * 验证提示信息
19 | * @var array
20 | */
21 | protected $message = [];
22 |
23 | /**
24 | * 字段描述
25 | */
26 | protected $field = [
27 | ];
28 |
29 | /**
30 | * 验证场景
31 | */
32 | protected $scene = [
33 | 'add' => ['type', 'title', 'name'],
34 | 'edit' => ['type', 'title', 'name'],
35 | ];
36 |
37 | public function __construct()
38 | {
39 | $this->field = [
40 | 'type' => __('type'),
41 | 'title' => __('title'),
42 | 'name' => __('name'),
43 | ];
44 | parent::__construct();
45 | }
46 | }
--------------------------------------------------------------------------------
/app/admin/validate/UserMoneyLog.php:
--------------------------------------------------------------------------------
1 | 'require',
13 | 'money' => 'require',
14 | 'memo' => 'require',
15 | ];
16 |
17 | /**
18 | * 验证提示信息
19 | * @var array
20 | */
21 | protected $message = [];
22 |
23 | /**
24 | * 字段描述
25 | */
26 | protected $field = [
27 | ];
28 |
29 | /**
30 | * 验证场景
31 | */
32 | protected $scene = [
33 | 'add' => ['user_id', 'money', 'memo'],
34 | 'edit' => ['user_id', 'money', 'memo'],
35 | ];
36 |
37 | public function __construct()
38 | {
39 | $this->field = [
40 | 'user_id' => __('user_id'),
41 | 'money' => __('money'),
42 | 'memo' => __('memo'),
43 | ];
44 | parent::__construct();
45 | }
46 | }
--------------------------------------------------------------------------------
/app/admin/validate/UserScoreLog.php:
--------------------------------------------------------------------------------
1 | 'require',
13 | 'score' => 'require',
14 | 'memo' => 'require',
15 | ];
16 |
17 | /**
18 | * 验证提示信息
19 | * @var array
20 | */
21 | protected $message = [];
22 |
23 | /**
24 | * 字段描述
25 | */
26 | protected $field = [
27 | ];
28 |
29 | /**
30 | * 验证场景
31 | */
32 | protected $scene = [
33 | 'add' => ['user_id', 'score', 'memo'],
34 | 'edit' => ['user_id', 'score', 'memo'],
35 | ];
36 |
37 | public function __construct()
38 | {
39 | $this->field = [
40 | 'user_id' => __('user_id'),
41 | 'score' => __('score'),
42 | 'memo' => __('memo'),
43 | ];
44 | parent::__construct();
45 | }
46 | }
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/crud/state.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | remarks: '备注',
3 | 'Primary key': '主键',
4 | 'Primary key (Snowflake ID)': '主键(雪花ID)',
5 | 'Disable Search': '禁用搜索',
6 | 'Weight (drag and drop sorting)': '权重(拖拽排序)',
7 | 'Status:0=Disabled,1=Enabled': '状态:0=禁用,1=启用',
8 | 'Remote Select (association table)': '远程下拉(关联表)',
9 | 'Remote Select (Multi)': '远程下拉(关联多选)',
10 | 'Radio:opt0=Option1,opt1=Option2': '单选框:opt0=选项一,opt1=选项二',
11 | 'Checkbox:opt0=Option1,opt1=Option2': '复选框:opt0=选项一,opt1=选项二',
12 | Multi: '(多选)',
13 | 'Select:opt0=Option1,opt1=Option2': '下拉框:opt0=选项一,opt1=选项二',
14 | 'Switch:0=off,1=on': '开关:0=关,1=开',
15 | 'Time date (timestamp storage)': '时间日期(时间戳存储)',
16 | 'If left blank, the verifier title attribute will be filled in automatically': '留空则自动填写验证器title属性(看不懂请直接填写完整错误消息)',
17 | 'Weight (automatically generate drag sort button)': '权重(自动生成拖拽排序按钮)',
18 | 'If it is not input, it will be automatically analyzed by the controller': '不输入则以控制器自动解析',
19 | }
20 |
--------------------------------------------------------------------------------
/app/api/common.php:
--------------------------------------------------------------------------------
1 | {
28 | if (this.el.clientWidth >= this.el.scrollWidth) {
29 | return
30 | }
31 | this.el.scrollLeft += event.deltaY ? event.deltaY : event.detail && event.detail !== 0 ? event.detail : -event.wheelDelta
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/web/src/layouts/backend/components/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
22 |
23 |
29 |
--------------------------------------------------------------------------------
/web/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import { loadLang } from '/@/lang/index'
5 | import { registerIcons } from '/@/utils/common'
6 | import ElementPlus from 'element-plus'
7 | import mitt from 'mitt'
8 | import pinia from '/@/stores/index'
9 | import { directives } from '/@/utils/directives'
10 | import 'element-plus/dist/index.css'
11 | import 'element-plus/theme-chalk/display.css'
12 | import 'font-awesome/css/font-awesome.min.css'
13 | import '/@/styles/index.scss'
14 | // modules import mark, Please do not remove.
15 |
16 | async function start() {
17 | const app = createApp(App)
18 | app.use(pinia)
19 |
20 | // 全局语言包加载
21 | await loadLang(app)
22 |
23 | app.use(router)
24 | app.use(ElementPlus)
25 |
26 | // 全局注册
27 | directives(app) // 指令
28 | registerIcons(app) // icons
29 |
30 | app.mount('#app')
31 |
32 | // modules start mark, Please do not remove.
33 |
34 | app.config.globalProperties.eventBus = mitt()
35 | }
36 | start()
37 |
--------------------------------------------------------------------------------
/app/common/service/moduleService.php:
--------------------------------------------------------------------------------
1 | moduleAppInit();
14 | }
15 |
16 | public function moduleAppInit(): void
17 | {
18 | $installed = Server::installedList(root_path() . 'modules' . DIRECTORY_SEPARATOR);
19 | foreach ($installed as $item) {
20 | if ($item['state'] != 1) {
21 | continue;
22 | }
23 | $moduleClass = Server::getClass($item['uid']);
24 | if (class_exists($moduleClass)) {
25 | if (method_exists($moduleClass, 'AppInit')) {
26 | Event::listen('AppInit', function () use ($moduleClass) {
27 | $handle = new $moduleClass();
28 | $handle->AppInit();
29 | });
30 | }
31 | }
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/web/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
37 |
--------------------------------------------------------------------------------
/app/admin/library/crud/stubs/mixins/controller/index.stub:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * 查看
4 | * @throws Throwable
5 | */
6 | public function index(): void
7 | {
8 | // 如果是 select 则转发到 select 方法,若未重写该方法,其实还是继续执行 index
9 | if ($this->request->param('select')) {
10 | $this->select();
11 | }
12 |
13 | /**
14 | * 1. withJoin 不可使用 alias 方法设置表别名,别名将自动使用关联模型名称(小写下划线命名规则)
15 | * 2. 以下的别名设置了主表别名,同时便于拼接查询参数等
16 | * 3. paginate 数据集可使用链式操作 each(function($item, $key) {}) 遍历处理
17 | */
18 | list($where, $alias, $limit, $order) = $this->queryBuilder();
19 | $res = $this->model
20 | ->withJoin($this->withJoinTable, $this->withJoinType)
21 | {%relationVisibleFields%}
22 | ->alias($alias)
23 | ->where($where)
24 | ->order($order)
25 | ->paginate($limit);
26 |
27 | $this->success('', [
28 | 'list' => $res->items(),
29 | 'total' => $res->total(),
30 | 'remark' => get_route_remark(),
31 | ]);
32 | }
--------------------------------------------------------------------------------
/app/api/lang/zh-cn/user.php:
--------------------------------------------------------------------------------
1 | '验证码',
4 | 'captchaId' => '验证码标识',
5 | 'Register type' => '注册类型',
6 | 'Please input correct username' => '请输入正确的用户名',
7 | 'Please input correct password' => '请输入正确的密码',
8 | 'Registration parameter error' => '注册参数错误',
9 | 'Login succeeded!' => '登录成功',
10 | 'Please enter the correct verification code' => '请输入正确的验证码',
11 | 'You have already logged in. There is no need to log in again~' => '您已经登录过了,无需重复登录~',
12 | 'Check in failed, please try again or contact the website administrator~' => '签入失败,请重试或联系网站管理员~',
13 | 'Member center disabled' => '会员中心已禁用,请联系网站管理员开启。',
14 | ];
--------------------------------------------------------------------------------
/web/src/lang/frontend/en/user/account/profile.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | profile: 'Profile',
3 | 'Change Password': 'Change Password',
4 | avatar: 'Avatar',
5 | 'User name': 'User name',
6 | 'User nickname': 'User nickname',
7 | mail: 'mail',
8 | email: 'email',
9 | 'Operation via right button': 'Operation via right button',
10 | 'Click Modify': 'Click Modify',
11 | bind: 'bind',
12 | mobile: 'mobile',
13 | Gender: 'Gender',
14 | secrecy: 'secrecy',
15 | male: 'male',
16 | female: 'female',
17 | birthday: 'birthday',
18 | 'Personal signature': 'Personal signature',
19 | 'Account verification': 'Account verification',
20 | 'Account password verification': 'Account password verification',
21 | 'Mail verification': 'Mail verification',
22 | 'SMS verification': 'SMS verification',
23 | password: 'password',
24 | accept: 'accept',
25 | 'next step': 'next step',
26 | 'New email': 'New email',
27 | 'New mobile': 'New mobile',
28 | 'Verification Code': 'Captcha',
29 | send: 'send',
30 | seconds: 'seconds',
31 | nickname: 'nickname',
32 | }
33 |
--------------------------------------------------------------------------------
/web/src/layouts/frontend/container/disable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
33 |
--------------------------------------------------------------------------------
/app/admin/common.php:
--------------------------------------------------------------------------------
1 | config('buildadmin.api_url'),
23 | 'timeout' => 30,
24 | 'connect_timeout' => 30,
25 | 'verify' => false,
26 | 'http_errors' => false,
27 | 'headers' => [
28 | 'X-REQUESTED-WITH' => 'XMLHttpRequest',
29 | 'Referer' => dirname(request()->root(true)),
30 | 'User-Agent' => 'BuildAdminClient',
31 | ]
32 | ]);
33 | }
34 | }
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/ajax.php:
--------------------------------------------------------------------------------
1 | '开始进行数据库迁移',
4 | 'Start formatting the web project code' => '开始格式化前端代码(失败无影响,代码编辑器内按需的手动格式化即可)',
5 | 'Start installing the composer dependencies' => '开始安装服务端依赖',
6 | 'Start executing the build command of the web project' => '开始执行 web 工程的 build 命令,成功后会自动将构建产物移动至 根目录/public 目录下',
7 | 'Failed to modify the terminal configuration. Please modify the configuration file manually:%s' => '修改终端配置失败,请手动修改配置文件:%s',
8 | 'upload' => '上传文件',
9 | 'Change terminal config' => '修改终端配置',
10 | 'Clear cache' => '清理缓存',
11 | 'Data table does not exist' => '数据表不存在~',
12 | ];
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/image.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
31 |
32 |
38 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/dashboard.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'You have worked today': '您今天已工作了',
3 | 'Continue to work': '继续工作',
4 | 'have a bit of rest': '休息片刻',
5 | 'Member registration': '会员注册量',
6 | 'Total number of members': '会员总数',
7 | 'Number of installed plug-ins': '已装插件数',
8 | 'Membership growth': '会员增长情况',
9 | 'Annex growth': '附件增长情况',
10 | 'New member': '刚刚加入的会员',
11 | 'Joined us': '加入了我们',
12 | 'Member source': '会员来源',
13 | 'Member last name': '会员姓氏',
14 | Loading: '加载中...',
15 | Monday: '周一',
16 | Tuesday: '周二',
17 | Wednesday: '周三',
18 | Thursday: '周四',
19 | Friday: '周五',
20 | Saturday: '周六',
21 | Sunday: '周日',
22 | Visits: '访问量',
23 | 'Registration volume': '注册量',
24 | picture: '图片',
25 | file: '文档',
26 | table: '表格',
27 | other: '其它',
28 | 'Compressed package': '压缩包',
29 | Baidu: '百度',
30 | 'Direct access': '直接访问',
31 | 'take a plane': '坐飞机',
32 | 'Take the high-speed railway': '坐高铁',
33 | 'full name': '姓名',
34 | hour: '小时',
35 | minute: '分',
36 | second: '秒',
37 | day: '天',
38 | 'Number of attachments Uploaded': '附件上传量',
39 | }
40 |
--------------------------------------------------------------------------------
/web/.prettierrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | printWidth: 150,
3 | // 指定每个缩进级别的空格数
4 | tabWidth: 4,
5 | // 使用制表符而不是空格缩进行
6 | useTabs: false,
7 | // 在语句末尾打印分号
8 | semi: false,
9 | // 使用单引号而不是双引号
10 | singleQuote: true,
11 | // 更改引用对象属性的时间 可选值""
12 | quoteProps: 'as-needed',
13 | // 在JSX中使用单引号而不是双引号
14 | jsxSingleQuote: false,
15 | // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"",默认none
16 | trailingComma: 'es5',
17 | // 在对象文字中的括号之间打印空格
18 | bracketSpacing: true,
19 | // 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
20 | arrowParens: 'always',
21 | // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
22 | rangeStart: 0,
23 | rangeEnd: Infinity,
24 | // 指定要使用的解析器,不需要写文件开头的 @prettier
25 | requirePragma: false,
26 | // 不需要自动在文件开头插入 @prettier
27 | insertPragma: false,
28 | // 使用默认的折行标准 always\never\preserve
29 | proseWrap: 'preserve',
30 | // 指定HTML文件的全局空格敏感度 css\strict\ignore
31 | htmlWhitespaceSensitivity: 'css',
32 | // Vue文件脚本和样式标签缩进
33 | vueIndentScriptAndStyle: false,
34 | // 换行符使用 lf 结尾是 可选值""
35 | endOfLine: 'lf',
36 | }
37 |
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/routine/attachment.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Upload administrator': '上传管理员',
3 | 'Upload user': '上传会员',
4 | 'Storage mode': '存储方式',
5 | 'Physical path': '物理路径',
6 | 'image width': '图片宽度',
7 | 'Picture height': '图片高度',
8 | 'file size': '文件大小',
9 | 'mime type': 'mime类型',
10 | 'SHA1 code': 'sha1',
11 | 'The file is saved in the directory, and the file will not be automatically transferred if the record is modified':
12 | '文件保存目录,修改记录不会自动转移文件',
13 | 'File saving path Modifying records will not automatically transfer files': '文件保存路径,修改记录不会自动转移文件',
14 | 'Width of picture file': '图片文件的宽度',
15 | 'Height of picture file': '图片文件的高度',
16 | 'Original file name': '文件原始名称',
17 | 'File size (bytes)': '文件大小(bytes)',
18 | 'File MIME type': '文件mime类型',
19 | 'Upload (Reference) times of this file': '此文件的上传(引用)次数',
20 | 'When the same file is uploaded multiple times, only one attachment record will be saved and added':
21 | '同一文件被多次上传时,只会保存一份和增加一条附件记录',
22 | 'SHA1 encoding of file': '文件的sha1编码',
23 | 'Files and records will be deleted at the same time Are you sure?': '将同时删除文件和记录,确认吗?',
24 | }
25 |
--------------------------------------------------------------------------------
/app/admin/validate/DataRecycle.php:
--------------------------------------------------------------------------------
1 | 'require',
13 | 'controller' => 'require|unique:security_data_recycle',
14 | 'data_table' => 'require',
15 | 'primary_key' => 'require',
16 | ];
17 |
18 | /**
19 | * 验证提示信息
20 | * @var array
21 | */
22 | protected $message = [];
23 |
24 | /**
25 | * 字段描述
26 | */
27 | protected $field = [
28 | ];
29 |
30 | /**
31 | * 验证场景
32 | */
33 | protected $scene = [
34 | 'add' => ['name', 'controller', 'data_table', 'primary_key'],
35 | 'edit' => ['name', 'controller', 'data_table', 'primary_key'],
36 | ];
37 |
38 | public function __construct()
39 | {
40 | $this->field = [
41 | 'name' => __('Name'),
42 | 'controller' => __('Controller'),
43 | 'data_table' => __('Data Table'),
44 | 'primary_key' => __('Primary Key'),
45 | ];
46 | parent::__construct();
47 | }
48 | }
--------------------------------------------------------------------------------
/app/common/library/upload/Driver.php:
--------------------------------------------------------------------------------
1 | " \'',
9 | 'Please enter the correct name': 'Please enter the correct name',
10 | 'Content cannot be empty': 'The content cannot be blank',
11 | 'Floating point number': ' Floating number',
12 | required: 'Required',
13 | 'editor required': 'editor Required',
14 | 'Please enter the correct ID number': 'Please enter the correct ID number',
15 | number: 'Number (including float and integer)',
16 | integer: 'Integer (excluding float)',
17 | float: 'Float (excluding integer)',
18 | }
19 |
--------------------------------------------------------------------------------
/web/src/stores/siteConfig.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import type { RouteRecordRaw } from 'vue-router'
3 | import type { SiteConfig } from '/@/stores/interface'
4 |
5 | export const useSiteConfig = defineStore('siteConfig', {
6 | state: (): SiteConfig => {
7 | return {
8 | siteName: '',
9 | version: '',
10 | cdnUrl: '',
11 | apiUrl: '',
12 | upload: {
13 | mode: 'local',
14 | },
15 | headNav: [],
16 | recordNumber: '',
17 | cdnUrlParams: '',
18 | initialize: false,
19 | userInitialize: false,
20 | }
21 | },
22 | actions: {
23 | dataFill(state: SiteConfig) {
24 | // 使用 this.$patch(state) 时 headNav 的类型异常,直接赋值
25 | this.$state = state
26 | },
27 | setHeadNav(headNav: RouteRecordRaw[]) {
28 | this.headNav = headNav
29 | },
30 | setInitialize(initialize: boolean) {
31 | this.initialize = initialize
32 | },
33 | setUserInitialize(userInitialize: boolean) {
34 | this.userInitialize = userInitialize
35 | },
36 | },
37 | })
38 |
--------------------------------------------------------------------------------
/web/src/utils/storage.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * window.localStorage
3 | * @method set 设置
4 | * @method get 获取
5 | * @method remove 移除
6 | * @method clear 移除全部
7 | */
8 | export const Local = {
9 | set(key: string, val: any) {
10 | window.localStorage.setItem(key, JSON.stringify(val))
11 | },
12 | get(key: string) {
13 | const json: any = window.localStorage.getItem(key)
14 | return JSON.parse(json)
15 | },
16 | remove(key: string) {
17 | window.localStorage.removeItem(key)
18 | },
19 | clear() {
20 | window.localStorage.clear()
21 | },
22 | }
23 |
24 | /**
25 | * window.sessionStorage
26 | * @method set 设置会话缓存
27 | * @method get 获取会话缓存
28 | * @method remove 移除会话缓存
29 | * @method clear 移除全部会话缓存
30 | */
31 | export const Session = {
32 | set(key: string, val: any) {
33 | window.sessionStorage.setItem(key, JSON.stringify(val))
34 | },
35 | get(key: string) {
36 | const json: any = window.sessionStorage.getItem(key)
37 | return JSON.parse(json)
38 | },
39 | remove(key: string) {
40 | window.sessionStorage.removeItem(key)
41 | },
42 | clear() {
43 | window.sessionStorage.clear()
44 | },
45 | }
46 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/url.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
40 |
--------------------------------------------------------------------------------
/app/api/lang/en.php:
--------------------------------------------------------------------------------
1 | 'Login expired, please login again.',
4 | 'Account not exist' => 'Account does not exist',
5 | 'Account disabled' => 'Account is disabled',
6 | 'Token login failed' => 'Token login failed',
7 | 'Please try again after 1 day' => 'The number of failed login attempts has exceeded the limit, please try again after 24 hours.',
8 | 'Password is incorrect' => 'Incorrect password',
9 | 'You are not logged in' => 'You are not logged in.',
10 | 'Unknown operation' => 'Unknown operation',
11 | 'No action available, please contact the administrator~' => 'There is no action available, please contact the administrator~',
12 | 'Please login first' => 'Please login first!',
13 | 'You have no permission' => 'No permission to operate!',
14 | 'Captcha error' => 'Captcha error!',
15 | ];
--------------------------------------------------------------------------------
/app/api/lang/en/user.php:
--------------------------------------------------------------------------------
1 | 'Captcha',
4 | 'captchaId' => 'Captcha ID',
5 | 'Please input correct username' => 'Please enter the correct username.',
6 | 'Please input correct password' => 'Please enter the correct password.',
7 | 'Registration parameter error' => 'Wrong registration parameter',
8 | 'Login succeeded!' => 'Login succeeded!',
9 | 'Please enter the correct verification code' => 'Please enter the correct Captcha.',
10 | 'You have already logged in. There is no need to log in again~' => 'You have already logged in, no need to log in again.',
11 | 'Check in failed, please try again or contact the website administrator~' => 'Check in failed,please try again or contact the webmaster.',
12 | 'Member center disabled' => 'The member centre has been disabled, please contact the webmaster to turn it on.',
13 | ];
--------------------------------------------------------------------------------
/web/src/layouts/frontend/container/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
36 |
--------------------------------------------------------------------------------
/app/admin/model/UserScoreLog.php:
--------------------------------------------------------------------------------
1 | user_id)->lock(true)->find();
27 | if (!$user) {
28 | throw new Exception("The user can't find it");
29 | }
30 | if (!$model->memo) {
31 | throw new Exception("Change note cannot be blank");
32 | }
33 | $model->before = $user->score;
34 |
35 | $user->score += $model->score;
36 | $user->save();
37 |
38 | $model->after = $user->score;
39 | }
40 |
41 | public static function onBeforeDelete(): bool
42 | {
43 | return false;
44 | }
45 |
46 | public function user(): BelongsTo
47 | {
48 | return $this->belongsTo(User::class, 'user_id');
49 | }
50 | }
--------------------------------------------------------------------------------
/web/src/components/baInput/components/editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/admin/controller/user/MoneyLog.php:
--------------------------------------------------------------------------------
1 | model = new UserMoneyLog();
29 | }
30 |
31 | /**
32 | * 添加
33 | * @param int $userId
34 | * @throws Throwable
35 | */
36 | public function add(int $userId = 0): void
37 | {
38 | if ($this->request->isPost()) {
39 | parent::add();
40 | }
41 |
42 | $user = User::where('id', $userId)->find();
43 | if (!$user) {
44 | $this->error(__("The user can't find it"));
45 | }
46 | $this->success('', [
47 | 'user' => $user
48 | ]);
49 | }
50 | }
--------------------------------------------------------------------------------
/app/admin/controller/user/ScoreLog.php:
--------------------------------------------------------------------------------
1 | model = new UserScoreLog();
29 | }
30 |
31 | /**
32 | * 添加
33 | * @param int $userId
34 | * @throws Throwable
35 | */
36 | public function add(int $userId = 0): void
37 | {
38 | if ($this->request->isPost()) {
39 | parent::add();
40 | }
41 |
42 | $user = User::where('id', $userId)->find();
43 | if (!$user) {
44 | $this->error(__("The user can't find it"));
45 | }
46 | $this->success('', [
47 | 'user' => $user
48 | ]);
49 | }
50 | }
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/tag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | {{ !isEmpty(field.replaceValue) ? (field.replaceValue[cellValue] ?? cellValue) : cellValue }}
11 |
12 |
13 |
14 |
15 |
35 |
--------------------------------------------------------------------------------
/web/src/utils/build.ts:
--------------------------------------------------------------------------------
1 | import { readdirSync, writeFile } from 'fs'
2 | import { trimEnd } from 'lodash-es'
3 |
4 | function getFileNames(dir: string) {
5 | const dirents = readdirSync(dir, {
6 | withFileTypes: true,
7 | })
8 | const fileNames: string[] = []
9 | for (const dirent of dirents) {
10 | if (!dirent.isDirectory()) fileNames.push(dirent.name.replace('.vue', ''))
11 | }
12 | return fileNames
13 | }
14 |
15 | /**
16 | * 生成 ./types/tableRenderer.d.ts 文件
17 | */
18 | const buildTableRendererType = () => {
19 | let tableRenderer = getFileNames('./src/components/table/fieldRender/')
20 |
21 | // 增加 slot,去除 default
22 | tableRenderer.push('slot')
23 | tableRenderer = tableRenderer.filter((item) => item !== 'default')
24 |
25 | let tableRendererContent =
26 | '/** 可用的表格单元格渲染器,以 ./src/components/table/fieldRender/ 目录中的文件名自动生成 */\ntype TableRenderer =\n | '
27 | for (const key in tableRenderer) {
28 | tableRendererContent += `'${tableRenderer[key]}'\n | `
29 | }
30 | tableRendererContent = trimEnd(tableRendererContent, ' | ')
31 |
32 | writeFile('./types/tableRenderer.d.ts', tableRendererContent, 'utf-8', (err) => {
33 | if (err) throw err
34 | })
35 | }
36 |
37 | buildTableRendererType()
38 |
--------------------------------------------------------------------------------
/app/api/lang/en/account.php:
--------------------------------------------------------------------------------
1 | 'Nickname',
4 | 'birthday' => 'Birthday',
5 | 'captcha' => 'Captcha',
6 | 'Old password error' => 'Old password error',
7 | 'Data updated successfully~' => 'Data updated successfully',
8 | 'Please input correct password' => 'Please enter the correct password',
9 | 'nicknameChsDash' => 'Usernames can only be Chinese characters, letters, numbers, underscores_ and dashes-.',
10 | 'Password has been changed~' => 'Password has been changed~',
11 | 'Password has been changed, please login again~' => 'Password has been changed, please login again~',
12 | 'Account does not exist~' => 'Account does not exist',
13 | 'Failed to modify password, please try again later~' => 'Failed to modify password, please try again later~',
14 | 'Please enter the correct verification code' => 'Please enter the correct Captcha',
15 | '%s has been registered' => '%s has been registered, please login directly.',
16 | ];
--------------------------------------------------------------------------------
/app/api/lang/en/ems.php:
--------------------------------------------------------------------------------
1 | 'email format error',
4 | 'user_register' => 'Member registration verification',
5 | 'user_retrieve_pwd' => 'Retrieve password verification',
6 | 'user_change_email' => 'Modify mailbox validation',
7 | 'user_email_verify' => 'Member Email Verification',
8 | 'Your verification code is: %s' => 'Your Captcha is: %s,valid for 10 minutes~',
9 | 'Mail sent successfully~' => 'Mail sent successfully',
10 | 'Account does not exist~' => 'Account does not exist',
11 | 'Mail sending service unavailable' => 'The mail sending service is not working, please contact the webmaster to configure it.',
12 | 'Frequent email sending' => 'Frequent email sending',
13 | 'Email has been registered, please log in directly' => 'Email has been registered, please log in directly~',
14 | 'The email has been occupied' => 'The email has been occupied',
15 | 'Email not registered' => 'Email not registered',
16 | ];
--------------------------------------------------------------------------------
/web/src/lang/backend/zh-cn/user/rule.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Normal routing': '普通路由',
3 | 'Member center menu contents': '会员中心菜单目录',
4 | 'Member center menu items': '会员中心菜单项',
5 | 'Top bar menu items': '顶栏菜单项',
6 | 'Page button': '页面按钮',
7 | 'Top bar user dropdown': '顶栏会员菜单下拉项',
8 | 'Type route tips': '自动注册为前端路由',
9 | 'Type menu_dir tips': '自动注册路由,并作为会员中心的菜单目录,此项本身不可跳转',
10 | 'Type menu tips': '自动注册路由,并作为会员中心的菜单项目',
11 | 'Type nav tips': '自动注册路由,并作为站点顶栏的菜单项目',
12 | 'Type button tips': '自动注册为权限节点,可通过 v-auth 快速验权',
13 | 'Type nav_user_menu tips': '自动注册路由,并作为顶栏会员菜单下拉项',
14 | 'English name': '英文名称',
15 | 'Web side routing path': 'WEB 端路由路径(vue-router 的 path)',
16 | no_login_valid: '未登录有效',
17 | 'no_login_valid 0': '游客无效',
18 | 'no_login_valid 1': '游客有效',
19 | 'no_login_valid tips': '游客没有会员分组,通过本选项设置当前规则是否对游客有效(可见)',
20 | 'For example, if you add account/overview as a route only': 'WEB 端组件路径,请以 /src 开头,如:/src/views/frontend/index.vue',
21 | 'Web side component path, please start with /src, such as: /src/views/frontend/index':
22 | '比如将 `account/overview` 只添加为路由,那么可以另外将 `account/overview`、`account/overview/:a`、`account/overview/:b/:c` 只添加为菜单',
23 | 'Component path tips': '组件路径在 WEB 工程内是必填的,否则无法访问,但作为 Nuxt 工程内的菜单时,无需填写此项,请根据菜单使用场景填写',
24 | }
25 |
--------------------------------------------------------------------------------
/web/src/assets/icons/full-screen-cancel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/admin/validate/SensitiveData.php:
--------------------------------------------------------------------------------
1 | 'require',
13 | 'controller' => 'require|unique:security_sensitive_data',
14 | 'data_table' => 'require',
15 | 'primary_key' => 'require',
16 | 'data_fields' => 'require',
17 | ];
18 |
19 | /**
20 | * 验证提示信息
21 | * @var array
22 | */
23 | protected $message = [];
24 |
25 | /**
26 | * 字段描述
27 | */
28 | protected $field = [
29 | ];
30 |
31 | /**
32 | * 验证场景
33 | */
34 | protected $scene = [
35 | 'add' => ['name', 'data_fields', 'controller', 'data_table', 'primary_key'],
36 | 'edit' => ['name', 'data_fields', 'controller', 'data_table', 'primary_key'],
37 | ];
38 |
39 | public function __construct()
40 | {
41 | $this->field = [
42 | 'name' => __('Name'),
43 | 'data_fields' => __('Data Fields'),
44 | 'controller' => __('Controller'),
45 | 'data_table' => __('Data Table'),
46 | 'primary_key' => __('Primary Key'),
47 | ];
48 | parent::__construct();
49 | }
50 | }
--------------------------------------------------------------------------------
/config/log.php:
--------------------------------------------------------------------------------
1 | env('log.channel', 'file'),
9 | // 日志记录级别
10 | 'level' => [],
11 | // 日志类型记录的通道 ['error'=>'email',...]
12 | 'type_channel' => [],
13 | // 关闭全局日志写入
14 | 'close' => false,
15 | // 全局日志处理 支持闭包
16 | 'processor' => null,
17 |
18 | // 日志通道列表
19 | 'channels' => [
20 | 'file' => [
21 | // 日志记录方式
22 | 'type' => 'File',
23 | // 日志保存目录
24 | 'path' => '',
25 | // 单文件日志写入
26 | 'single' => false,
27 | // 独立日志级别
28 | 'apart_level' => [],
29 | // 最大日志文件数量
30 | 'max_files' => 0,
31 | // 使用JSON格式记录
32 | 'json' => false,
33 | // 日志处理
34 | 'processor' => null,
35 | // 关闭通道日志写入
36 | 'close' => false,
37 | // 日志输出格式化
38 | 'format' => '[%s][%s] %s',
39 | // 是否实时写入
40 | 'realtime_write' => false,
41 | ],
42 | // 其它日志通道配置
43 | ],
44 |
45 | ];
46 |
--------------------------------------------------------------------------------
/web/src/assets/icons/light.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/web/src/components/icon/svg/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
41 |
42 |
50 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/crud/state.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | remarks: 'remarks',
3 | 'Primary key': 'Primary key',
4 | 'Primary key (Snowflake ID)': 'Primary key (Snowflake ID)',
5 | 'Disable Search': 'Disable Search',
6 | 'Weight (drag and drop sorting)': 'Weight (drag and drop sorting)',
7 | 'Status:0=Disabled,1=Enabled': 'Status:0=Disabled,1=Enabled',
8 | 'Remote Select (association table)': 'Remote Select (association table)',
9 | 'Remote Select (Multi)': 'Remote Select (Multi)',
10 | 'Radio:opt0=Option1,opt1=Option2': 'Radio:opt0=Option1,opt1=Option2',
11 | 'Checkbox:opt0=Option1,opt1=Option2': 'Checkbox:opt0=Option1,opt1=Option2',
12 | Multi: '(Multi)',
13 | 'Select:opt0=Option1,opt1=Option2': 'Select:opt0=Option1,opt1=Option2',
14 | 'Switch:0=off,1=on': 'Switch:0=off,1=on',
15 | 'Time date (timestamp storage)': 'Time date (timestamp storage)',
16 | 'If left blank, the verifier title attribute will be filled in automatically':
17 | 'If left blank, the verifier title attribute will be filled in automatically',
18 | 'Weight (automatically generate drag sort button)': 'Weight (automatically generate drag sort button)',
19 | 'If it is not input, it will be automatically analyzed by the controller':
20 | 'If it is not input, it will be automatically analyzed by the controller',
21 | }
22 |
--------------------------------------------------------------------------------
/web/src/lang/common/en/axios.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Operation successful': 'Operate successful',
3 | 'Automatic cancellation due to duplicate request:': 'Automatic cancellation due to duplicate requests:',
4 | 'Interface redirected!': 'Interface redirected!',
5 | 'Incorrect parameter!': 'Incorrect parameter!',
6 | 'You do not have permission to operate!': 'You have no permission to operate!',
7 | 'Error requesting address:': 'Error requesting address:',
8 | 'Request timed out!': 'Request timeout!',
9 | 'The same data already exists in the system!': 'The same data already exists on the system!',
10 | 'Server internal error!': 'Internal server error!',
11 | 'Service not implemented!': 'Service unrealized!',
12 | 'Gateway error!': 'Gateway error!',
13 | 'Service unavailable!': 'Service unavailable!',
14 | 'The service is temporarily unavailable Please try again later!': 'The service is temporarily unavailable, please try again later!',
15 | 'HTTP version is not supported!': 'HTTP version is not Unsupported!',
16 | 'Abnormal problem, please contact the website administrator!': 'Abnormal problems, please contact the website administrator!',
17 | 'Network request timeout!': 'Network request timeout!',
18 | 'Server exception!': 'Server-side exceptions!',
19 | 'You are disconnected!': 'You are disconnected!',
20 | }
21 |
--------------------------------------------------------------------------------
/web/src/assets/icons/terminal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/src/utils/useDark.ts:
--------------------------------------------------------------------------------
1 | import { useDark, useToggle } from '@vueuse/core'
2 | import { useConfig } from '/@/stores/config'
3 | import { onMounted, onUnmounted, ref, watch } from 'vue'
4 |
5 | const isDark = useDark({
6 | onChanged(dark: boolean) {
7 | const config = useConfig()
8 | updateHtmlDarkClass(dark)
9 | config.setLayout('isDark', dark)
10 | config.onSetLayoutColor()
11 | },
12 | })
13 |
14 | /**
15 | * 切换暗黑模式
16 | */
17 | const toggleDark = useToggle(isDark)
18 |
19 | /**
20 | * 切换当前页面的暗黑模式
21 | */
22 | export function togglePageDark(val: boolean) {
23 | const config = useConfig()
24 | const isDark = ref(config.layout.isDark)
25 | onMounted(() => {
26 | if (isDark.value !== val) updateHtmlDarkClass(val)
27 | })
28 | onUnmounted(() => {
29 | updateHtmlDarkClass(isDark.value)
30 | })
31 | watch(
32 | () => config.layout.isDark,
33 | (newVal) => {
34 | isDark.value = newVal
35 | if (isDark.value !== val) updateHtmlDarkClass(val)
36 | }
37 | )
38 | }
39 |
40 | export function updateHtmlDarkClass(val: boolean) {
41 | const htmlEl = document.getElementsByTagName('html')[0]
42 | if (val) {
43 | htmlEl.setAttribute('class', 'dark')
44 | } else {
45 | htmlEl.setAttribute('class', '')
46 | }
47 | }
48 |
49 | export default toggleDark
50 |
--------------------------------------------------------------------------------
/web/src/views/backend/module/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
40 |
41 |
46 |
--------------------------------------------------------------------------------
/web/src/utils/loading.ts:
--------------------------------------------------------------------------------
1 | import { nextTick } from 'vue'
2 | import '/@/styles/loading.scss'
3 |
4 | export const loading = {
5 | show: () => {
6 | const bodys: Element = document.body
7 | const div = document.createElement('div')
8 | div.className = 'block-loading'
9 | div.innerHTML = `
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | `
24 | bodys.insertBefore(div, bodys.childNodes[0])
25 | },
26 | hide: () => {
27 | nextTick(() => {
28 | setTimeout(() => {
29 | const el = document.querySelector('.block-loading')
30 | el && el.parentNode?.removeChild(el)
31 | }, 1000)
32 | })
33 | },
34 | }
35 |
--------------------------------------------------------------------------------
/web/src/components/clickCaptcha/index.ts:
--------------------------------------------------------------------------------
1 | import { createVNode, render } from 'vue'
2 | import ClickCaptchaConstructor from './index.vue'
3 | import { shortUuid } from '/@/utils/random'
4 |
5 | interface ClickCaptchaOptions {
6 | // 验证码弹窗的自定义class
7 | class?: string
8 | // 前端验证成功时立即清理验证码数据,不可再进行二次验证,不开启则 600s 后自动清理数据
9 | unset?: boolean
10 | // 验证失败的提示信息
11 | error?: string
12 | // 验证成功的提示信息
13 | success?: string
14 | // 验证码 API 的基础 URL,默认为当前服务端 URL(VITE_AXIOS_BASE_URL)
15 | apiBaseURL?: string
16 | }
17 |
18 | /**
19 | * 弹出点击验证码
20 | * @param uuid 开发者自定义的唯一标识
21 | * @param callback 验证成功的回调,业务接口可通过 captchaInfo 进行二次验证
22 | * @param options
23 | */
24 | const clickCaptcha = (uuid: string, callback?: (captchaInfo: string) => void, options: ClickCaptchaOptions = {}) => {
25 | const container = document.createElement('div')
26 | const vnode = createVNode(ClickCaptchaConstructor, {
27 | uuid,
28 | callback,
29 | ...options,
30 | key: shortUuid(),
31 | onDestroy: () => {
32 | render(null, container)
33 | },
34 | })
35 | render(vnode, container)
36 | document.body.appendChild(container.firstElementChild!)
37 | }
38 |
39 | /**
40 | * 组件的 props 类型定义
41 | */
42 | export interface Props extends ClickCaptchaOptions {
43 | uuid: string
44 | callback?: (captchaInfo: string) => void
45 | }
46 |
47 | export default clickCaptcha
48 |
--------------------------------------------------------------------------------
/app/admin/model/User.php:
--------------------------------------------------------------------------------
1 | belongsTo(UserGroup::class, 'group_id');
40 | }
41 |
42 | /**
43 | * 重置用户密码
44 | * @param int|string $uid 用户ID
45 | * @param string $newPassword 新密码
46 | * @return int|User
47 | */
48 | public function resetPassword(int|string $uid, string $newPassword): int|User
49 | {
50 | return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
51 | }
52 | }
--------------------------------------------------------------------------------
/config/route.php:
--------------------------------------------------------------------------------
1 | '/',
9 | // URL伪静态后缀
10 | 'url_html_suffix' => 'html',
11 | // URL普通方式参数 用于自动生成
12 | 'url_common_param' => true,
13 | // 是否开启路由延迟解析
14 | 'url_lazy_route' => false,
15 | // 是否强制使用路由
16 | 'url_route_must' => false,
17 | // 合并路由规则
18 | 'route_rule_merge' => false,
19 | // 路由是否完全匹配
20 | 'route_complete_match' => false,
21 | // 访问控制器层名称
22 | 'controller_layer' => 'controller',
23 | // 空控制器名
24 | 'empty_controller' => 'Error',
25 | // 是否使用控制器后缀
26 | 'controller_suffix' => false,
27 | // 默认的路由变量规则
28 | 'default_route_pattern' => '[\w\.]+',
29 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
30 | 'request_cache_key' => false,
31 | // 请求缓存有效期
32 | 'request_cache_expire' => null,
33 | // 全局请求缓存排除规则
34 | 'request_cache_except' => [],
35 | // 默认控制器名
36 | 'default_controller' => 'Index',
37 | // 默认操作名
38 | 'default_action' => 'index',
39 | // 操作方法后缀
40 | 'action_suffix' => '',
41 | // 默认JSONP格式返回的处理方法
42 | 'default_jsonp_handler' => 'jsonpReturn',
43 | // 默认JSONP处理方法
44 | 'var_jsonp_handler' => 'callback',
45 | ];
46 |
--------------------------------------------------------------------------------
/web/src/lang/globs-zh-cn.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 全局公共语言包
3 | * 覆盖风险:请避免使用页面语言包的目录名、文件名作为翻译 key、请使用大写开头避免覆盖
4 | */
5 | export default {
6 | Id: 'ID',
7 | State: '状态',
8 | Home: '首页',
9 | Complete: '完成',
10 | Edit: '编辑',
11 | Add: '添加',
12 | Info: '查看详情',
13 | Delete: '删除',
14 | Refresh: '刷新',
15 | Operate: '操作',
16 | Confirm: '确认',
17 | Cancel: '取消',
18 | Save: '保存',
19 | Upload: '上传',
20 | Retry: '重试',
21 | Reminder: '温馨提示',
22 | Disable: '禁用',
23 | Enable: '启用',
24 | Shrink: '收缩',
25 | Open: '展开',
26 | Search: '搜索',
27 | Reset: '重置',
28 | To: '至',
29 | None: '无',
30 | Unknown: '未知',
31 | Weigh: '权重',
32 | 'Drag sort': '拖动以排序',
33 | 'Save and edit next item': '保存并编辑下一项',
34 | 'Quick search placeholder': '通过{fields}模糊搜索',
35 | 'Please select field': '请选择{field}',
36 | 'Please input field': '请输入{field}',
37 | 'Please enter the correct field': '请输入正确的{field}',
38 | 'Update time': '修改时间',
39 | 'Create time': '创建时间',
40 | 'Fuzzy query': '模糊查询',
41 | 'Click select': '点击选择',
42 | 'Edit selected row': '编辑选中行',
43 | 'Delete selected row': '删除选中行',
44 | 'Are you sure to delete the selected record?': '确定删除选中记录?',
45 | 'All submenus': '所有子菜单',
46 | 'Shrink all': '收缩所有',
47 | 'Expand all': '展开所有',
48 | 'Expand generic search': '展开公共搜索',
49 | 'Link address': '链接地址',
50 | 'No route found to jump~': '没有找到可以跳转的路由~',
51 | }
52 |
--------------------------------------------------------------------------------
/web/src/components/table/fieldRender/images.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
17 |
18 |
19 |
36 |
37 |
44 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/dashboard.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'You have worked today': 'You have worked today: ',
3 | 'Continue to work': 'Keep working',
4 | 'have a bit of rest': 'Take a break',
5 | 'Member registration': 'Member registration',
6 | 'Total number of members': 'Total number of members',
7 | 'Number of installed plug-ins': 'Number of installed plug-ins',
8 | 'Membership growth': 'Membership growth',
9 | 'Annex growth': 'Annex Growth',
10 | 'New member': 'New Member',
11 | 'Joined us': 'Joined us',
12 | 'Member source': 'Member source',
13 | 'Member last name': 'Member last name',
14 | Loading: 'Loading',
15 | Monday: 'Monday',
16 | Tuesday: 'Tuesday',
17 | Wednesday: 'Wednesday',
18 | Thursday: 'Thursday',
19 | Friday: 'Friday',
20 | Saturday: 'Saturday',
21 | Sunday: 'Sunday',
22 | Visits: 'Visits',
23 | 'Registration volume': 'The number of registered users',
24 | picture: 'picture',
25 | file: 'file',
26 | table: 'table',
27 | other: 'other',
28 | 'Compressed package': 'Compressed package',
29 | Baidu: 'Baidu',
30 | 'Direct access': 'Direct access',
31 | 'take a plane': 'Take a plane',
32 | 'Take the high-speed railway': 'Take the high-speed rail',
33 | 'full name': 'Full name',
34 | hour: 'Hour',
35 | minute: 'Minute',
36 | second: 'Second',
37 | day: 'Day',
38 | 'Number of attachments Uploaded': 'Number of attachments upload',
39 | }
40 |
--------------------------------------------------------------------------------
/app/api/lang/zh-cn/ems.php:
--------------------------------------------------------------------------------
1 | '电子邮箱格式错误',
4 | 'user_register' => '会员注册验证',
5 | 'user_change_email' => '修改邮箱验证',
6 | 'user_retrieve_pwd' => '找回密码验证',
7 | 'user_email_verify' => '会员身份验证',
8 | 'Your verification code is: %s' => '您的验证码是:%s,十分钟内有效~',
9 | 'Mail sent successfully~' => '邮件发送成功~',
10 | 'Account does not exist~' => '账户不存在~',
11 | 'Mail sending service unavailable' => '邮件发送服务不可用,请联系网站管理员进行配置~',
12 | 'Frequent email sending' => '频繁发送电子邮件',
13 | 'Email has been registered, please log in directly' => '电子邮箱已注册,请直接登录~',
14 | 'The email has been occupied' => '电子邮箱已被占用!',
15 | 'Email not registered' => '电子邮箱未注册',
16 | 'Please use the account registration email to send the verification code' => '请使用账户注册邮箱发送验证码!',
17 | 'Password error' => '密码错误!',
18 | ];
--------------------------------------------------------------------------------
/web/src/components/icon/index.vue:
--------------------------------------------------------------------------------
1 |
42 |
--------------------------------------------------------------------------------
/web/src/api/backend/routine/config.ts:
--------------------------------------------------------------------------------
1 | import createAxios from '/@/utils/axios'
2 |
3 | export const url = '/admin/routine.Config/'
4 |
5 | export const actionUrl = new Map([
6 | ['index', url + 'index'],
7 | ['add', url + 'add'],
8 | ['edit', url + 'edit'],
9 | ['del', url + 'del'],
10 | ['sendTestMail', url + 'sendTestMail'],
11 | ])
12 |
13 | export function index() {
14 | return createAxios({
15 | url: actionUrl.get('index'),
16 | method: 'get',
17 | })
18 | }
19 |
20 | export function postData(action: string, data: anyObj) {
21 | return createAxios(
22 | {
23 | url: actionUrl.get(action),
24 | method: 'post',
25 | data: data,
26 | },
27 | {
28 | showSuccessMessage: true,
29 | }
30 | )
31 | }
32 |
33 | export function del(ids: string[]) {
34 | return createAxios(
35 | {
36 | url: actionUrl.get('del'),
37 | method: 'DELETE',
38 | params: {
39 | ids: ids,
40 | },
41 | },
42 | {
43 | showSuccessMessage: true,
44 | }
45 | )
46 | }
47 |
48 | export function postSendTestMail(data: anyObj, mail: string) {
49 | return createAxios(
50 | {
51 | url: actionUrl.get('sendTestMail'),
52 | method: 'POST',
53 | data: Object.assign({}, data, { testMail: mail }),
54 | },
55 | {
56 | showSuccessMessage: true,
57 | }
58 | )
59 | }
60 |
--------------------------------------------------------------------------------
/app/admin/controller/auth/AdminLog.php:
--------------------------------------------------------------------------------
1 | model = new AdminLogModel();
25 | }
26 |
27 | /**
28 | * 查看
29 | * @throws Throwable
30 | */
31 | public function index(): void
32 | {
33 | if ($this->request->param('select')) {
34 | $this->select();
35 | }
36 |
37 | list($where, $alias, $limit, $order) = $this->queryBuilder();
38 | if (!$this->auth->isSuperAdmin()) {
39 | $where[] = ['admin_id', '=', $this->auth->id];
40 | }
41 | $res = $this->model
42 | ->withJoin($this->withJoinTable, $this->withJoinType)
43 | ->alias($alias)
44 | ->where($where)
45 | ->order($order)
46 | ->paginate($limit);
47 |
48 | $this->success('', [
49 | 'list' => $res->items(),
50 | 'total' => $res->total(),
51 | 'remark' => get_route_remark(),
52 | ]);
53 | }
54 | }
--------------------------------------------------------------------------------
/app/api/validate/Account.php:
--------------------------------------------------------------------------------
1 | 'require|regex:^[a-zA-Z][a-zA-Z0-9_]{2,15}$|unique:user',
13 | 'nickname' => 'require|chsDash',
14 | 'birthday' => 'date',
15 | 'email' => 'require|email|unique:user',
16 | 'mobile' => 'require|mobile|unique:user',
17 | 'password' => 'require|regex:^(?!.*[&<>"\'\n\r]).{6,32}$',
18 | 'account' => 'require',
19 | 'captcha' => 'require',
20 | ];
21 |
22 | /**
23 | * 验证场景
24 | */
25 | protected $scene = [
26 | 'edit' => ['username', 'nickname', 'birthday'],
27 | 'changePassword' => ['password'],
28 | 'retrievePassword' => ['account', 'captcha', 'password'],
29 | ];
30 |
31 | public function __construct()
32 | {
33 | $this->field = [
34 | 'username' => __('Username'),
35 | 'email' => __('Email'),
36 | 'mobile' => __('Mobile'),
37 | 'password' => __('Password'),
38 | 'nickname' => __('nickname'),
39 | 'birthday' => __('birthday'),
40 | ];
41 | $this->message = array_merge($this->message, [
42 | 'nickname.chsDash' => __('nicknameChsDash'),
43 | 'password.regex' => __('Please input correct password')
44 | ]);
45 | parent::__construct();
46 | }
47 | }
--------------------------------------------------------------------------------
/web/src/utils/random.ts:
--------------------------------------------------------------------------------
1 | const hexList: string[] = []
2 | for (let i = 0; i <= 15; i++) {
3 | hexList[i] = i.toString(16)
4 | }
5 |
6 | /**
7 | * 生成随机数
8 | * @param min 最小值
9 | * @param max 最大值
10 | * @returns 生成的随机数
11 | */
12 | export function randomNum(min: number, max: number) {
13 | switch (arguments.length) {
14 | case 1:
15 | return parseInt((Math.random() * min + 1).toString(), 10)
16 | break
17 | case 2:
18 | return parseInt((Math.random() * (max - min + 1) + min).toString(), 10)
19 | break
20 | default:
21 | return 0
22 | break
23 | }
24 | }
25 |
26 | /**
27 | * 生成全球唯一标识
28 | * @returns uuid
29 | */
30 | export function uuid(): string {
31 | let uuid = ''
32 | for (let i = 1; i <= 36; i++) {
33 | if (i === 9 || i === 14 || i === 19 || i === 24) {
34 | uuid += '-'
35 | } else if (i === 15) {
36 | uuid += 4
37 | } else if (i === 20) {
38 | uuid += hexList[(Math.random() * 4) | 8]
39 | } else {
40 | uuid += hexList[(Math.random() * 16) | 0]
41 | }
42 | }
43 | return uuid
44 | }
45 |
46 | /**
47 | * 生成唯一标识
48 | * @param prefix 前缀
49 | * @returns 唯一标识
50 | */
51 | export function shortUuid(prefix = ''): string {
52 | const time = Date.now()
53 | const random = Math.floor(Math.random() * 1000000000)
54 | if (!window.unique) window.unique = 0
55 | window.unique++
56 | return prefix + '_' + random + window.unique + String(time)
57 | }
58 |
--------------------------------------------------------------------------------
/app/common/model/User.php:
--------------------------------------------------------------------------------
1 | where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
36 | }
37 |
38 | public function getMoneyAttr($value): string
39 | {
40 | return bcdiv($value, 100, 2);
41 | }
42 |
43 | /**
44 | * 用户的余额是不可以直接进行修改的,请通过 UserMoneyLog 模型插入记录来实现自动修改余额
45 | * 此处定义上 money 的修改器仅为防止直接对余额的修改造成数据错乱
46 | */
47 | public function setMoneyAttr($value): string
48 | {
49 | return bcmul($value, 100, 2);
50 | }
51 | }
--------------------------------------------------------------------------------
/app/admin/lang/zh-cn/auth/group.php:
--------------------------------------------------------------------------------
1 | '组别名称',
4 | 'Please select rules' => '请选择权限',
5 | 'Super administrator' => '超级管理员',
6 | 'No permission' => '无权限',
7 | 'You cannot modify your own management group!' => '不能修改自己所在的管理组!',
8 | 'You need to have all permissions of this group to operate this group~' => '您需要拥有该分组的所有权限才可以操作该分组~',
9 | 'You need to have all the permissions of the group and have additional permissions before you can operate the group~' => '您需要拥有该分组的所有权限且还有额外权限时,才可以操作该分组~',
10 | 'Role group has all your rights, please contact the upper administrator to add or do not need to add!' => '角色组拥有您的全部权限,请联系上级管理员添加或无需添加!',
11 | 'The group permission node exceeds the range that can be allocated' => '分组权限节点超出可分配范围,请刷新重试~',
12 | 'Remark lang' => '为保障系统安全,角色组本身的上下级关系仅供参考,系统的实际上下级划分是根据`权限多寡`来确定的,两位管理员的权限节点:相同被认为是`同级`、包含且有额外权限才被认为是`上级`,同级不可管理同级,上级可为下级分配自己拥有的权限节点;若有特殊情况管理员需转`上级`,可建立一个虚拟权限节点',
13 | ];
14 |
--------------------------------------------------------------------------------
/web/src/lang/backend/en/routine/attachment.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | 'Upload administrator': 'Upload administrator',
3 | 'Upload user': 'Upload member',
4 | 'Storage mode': 'Storage mode',
5 | 'Physical path': 'Physical path',
6 | 'image width': 'Picture width',
7 | 'Picture height': 'Picture height',
8 | 'file size': 'file size',
9 | 'mime type': 'mime type ',
10 | 'SHA1 code': 'SHA1',
11 | 'The file is saved in the directory, and the file will not be automatically transferred if the record is modified':
12 | 'The file had saved in the directory, and the modification record will not automatically tansfer the file.',
13 | 'File saving path Modifying records will not automatically transfer files':
14 | 'The file had saved in the path, and the modification record will not automatically tansfer the file.',
15 | 'Width of picture file': 'The width of the image file.',
16 | 'Height of picture file': 'The height of the image file.',
17 | 'Original file name': 'Original name of the file',
18 | 'File size (bytes)': 'File size (Bytes)',
19 | 'File MIME type': 'File MIME type',
20 | 'Upload (Reference) times of this file': 'Upload (Reference) times of this file',
21 | 'When the same file is uploaded multiple times, only one attachment record will be saved and added':
22 | 'When the same file is uploaded many times, only one attachment record will be saved and added.',
23 | 'SHA1 encoding of file': 'The SHA1 encoding of file',
24 | 'Files and records will be deleted at the same time Are you sure?': 'Files and records will be deleted at the same time Are you sure?',
25 | }
26 |
--------------------------------------------------------------------------------