feat: 重建 Bell GoAdmin 产品骨架 (#62)
@@ -0,0 +1,14 @@
|
||||
# https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1,8 @@
|
||||
# just a flag
|
||||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = 'http://localhost:18090'
|
||||
|
||||
# Suppress Sass deprecation warnings
|
||||
SASS_SILENCE_DEPRECATIONS = 'legacy-js-api'
|
||||
@@ -0,0 +1,8 @@
|
||||
# just a flag
|
||||
ENV = 'production'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = ''
|
||||
|
||||
# Suppress Sass deprecation warnings
|
||||
SASS_SILENCE_DEPRECATIONS = 'legacy-js-api'
|
||||
@@ -0,0 +1,8 @@
|
||||
NODE_ENV = production
|
||||
|
||||
# just a flag
|
||||
ENV = 'staging'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = ''
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
build/*.js
|
||||
src/assets
|
||||
public
|
||||
dist
|
||||
@@ -0,0 +1,203 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: '@babel/eslint-parser',
|
||||
sourceType: 'module',
|
||||
requireConfigFile: false
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
extends: ['plugin:vue/vue3-recommended', 'eslint:recommended'],
|
||||
|
||||
// add your custom rules here
|
||||
// it is base on https://github.com/vuejs/eslint-config-vue
|
||||
rules: {
|
||||
'vue/max-attributes-per-line': [2, {
|
||||
'singleline': {
|
||||
'max': 10
|
||||
},
|
||||
'multiline': {
|
||||
'max': 1
|
||||
}
|
||||
}],
|
||||
'vue/no-template-shadow': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
// Vue 3 规则调整
|
||||
'vue/no-deprecated-slot-attribute': 'warn',
|
||||
'vue/multi-word-component-names': 'warn',
|
||||
'accessor-pairs': 2,
|
||||
'arrow-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'block-spacing': [2, 'always'],
|
||||
'brace-style': [2, '1tbs', {
|
||||
'allowSingleLine': true
|
||||
}],
|
||||
'camelcase': [0, {
|
||||
'properties': 'always'
|
||||
}],
|
||||
'comma-dangle': [2, 'never'],
|
||||
'comma-spacing': [2, {
|
||||
'before': false,
|
||||
'after': true
|
||||
}],
|
||||
'comma-style': [2, 'last'],
|
||||
'constructor-super': 2,
|
||||
'curly': [2, 'multi-line'],
|
||||
'dot-location': [2, 'property'],
|
||||
'eol-last': 2,
|
||||
'eqeqeq': ['error', 'always', { 'null': 'ignore' }],
|
||||
'generator-star-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'handle-callback-err': [2, '^(err|error)$'],
|
||||
'indent': [2, 2, {
|
||||
'SwitchCase': 1
|
||||
}],
|
||||
'jsx-quotes': [2, 'prefer-single'],
|
||||
'key-spacing': [2, {
|
||||
'beforeColon': false,
|
||||
'afterColon': true
|
||||
}],
|
||||
'keyword-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'new-cap': [2, {
|
||||
'newIsCap': true,
|
||||
'capIsNew': false
|
||||
}],
|
||||
'new-parens': 2,
|
||||
'no-array-constructor': 2,
|
||||
'no-caller': 2,
|
||||
'no-console': 'off',
|
||||
'no-class-assign': 2,
|
||||
'no-cond-assign': 2,
|
||||
'no-const-assign': 2,
|
||||
'no-control-regex': 0,
|
||||
'no-delete-var': 2,
|
||||
'no-dupe-args': 2,
|
||||
'no-dupe-class-members': 2,
|
||||
'no-dupe-keys': 2,
|
||||
'no-duplicate-case': 2,
|
||||
'no-empty-character-class': 2,
|
||||
'no-empty-pattern': 2,
|
||||
'no-eval': 2,
|
||||
'no-ex-assign': 2,
|
||||
'no-extend-native': 2,
|
||||
'no-extra-bind': 2,
|
||||
'no-extra-boolean-cast': 2,
|
||||
'no-extra-parens': [2, 'functions'],
|
||||
'no-fallthrough': 2,
|
||||
'no-floating-decimal': 2,
|
||||
'no-func-assign': 2,
|
||||
'no-implied-eval': 2,
|
||||
'no-inner-declarations': [2, 'functions'],
|
||||
'no-invalid-regexp': 2,
|
||||
'no-irregular-whitespace': 2,
|
||||
'no-iterator': 2,
|
||||
'no-label-var': 2,
|
||||
'no-labels': [2, {
|
||||
'allowLoop': false,
|
||||
'allowSwitch': false
|
||||
}],
|
||||
'no-lone-blocks': 2,
|
||||
'no-mixed-spaces-and-tabs': 2,
|
||||
'no-multi-spaces': 2,
|
||||
'no-multi-str': 2,
|
||||
'no-multiple-empty-lines': [2, {
|
||||
'max': 1
|
||||
}],
|
||||
'no-native-reassign': 2,
|
||||
'no-negated-in-lhs': 2,
|
||||
'no-new-object': 2,
|
||||
'no-new-require': 2,
|
||||
'no-new-symbol': 2,
|
||||
'no-new-wrappers': 2,
|
||||
'no-obj-calls': 2,
|
||||
'no-octal': 2,
|
||||
'no-octal-escape': 2,
|
||||
'no-path-concat': 2,
|
||||
'no-proto': 2,
|
||||
'no-redeclare': 2,
|
||||
'no-regex-spaces': 2,
|
||||
'no-return-assign': [2, 'except-parens'],
|
||||
'no-self-assign': 2,
|
||||
'no-self-compare': 2,
|
||||
'no-sequences': 2,
|
||||
'no-shadow-restricted-names': 2,
|
||||
'no-spaced-func': 2,
|
||||
'no-sparse-arrays': 2,
|
||||
'no-this-before-super': 2,
|
||||
'no-throw-literal': 2,
|
||||
'no-trailing-spaces': 2,
|
||||
'no-undef': 2,
|
||||
'no-undef-init': 2,
|
||||
'no-unexpected-multiline': 2,
|
||||
'no-unmodified-loop-condition': 2,
|
||||
'no-unneeded-ternary': [2, {
|
||||
'defaultAssignment': false
|
||||
}],
|
||||
'no-unreachable': 2,
|
||||
'no-unsafe-finally': 2,
|
||||
'no-unused-vars': [2, {
|
||||
'vars': 'all',
|
||||
'args': 'none'
|
||||
}],
|
||||
'no-useless-call': 2,
|
||||
'no-useless-computed-key': 2,
|
||||
'no-useless-constructor': 2,
|
||||
'no-useless-escape': 0,
|
||||
'no-whitespace-before-property': 2,
|
||||
'no-with': 2,
|
||||
'one-var': [2, {
|
||||
'initialized': 'never'
|
||||
}],
|
||||
'operator-linebreak': [2, 'after', {
|
||||
'overrides': {
|
||||
'?': 'before',
|
||||
':': 'before'
|
||||
}
|
||||
}],
|
||||
'padded-blocks': [2, 'never'],
|
||||
'quotes': [2, 'single', {
|
||||
'avoidEscape': true,
|
||||
'allowTemplateLiterals': true
|
||||
}],
|
||||
'semi': [2, 'never'],
|
||||
'semi-spacing': [2, {
|
||||
'before': false,
|
||||
'after': true
|
||||
}],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'space-before-function-paren': [2, 'never'],
|
||||
'space-in-parens': [2, 'never'],
|
||||
'space-infix-ops': 2,
|
||||
'space-unary-ops': [2, {
|
||||
'words': true,
|
||||
'nonwords': false
|
||||
}],
|
||||
'spaced-comment': [2, 'always', {
|
||||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
||||
}],
|
||||
'template-curly-spacing': [2, 'never'],
|
||||
'use-isnan': 2,
|
||||
'valid-typeof': 2,
|
||||
'wrap-iife': [2, 'any'],
|
||||
'yield-star-spacing': [2, 'both'],
|
||||
'yoda': [2, 'never'],
|
||||
'prefer-const': 2,
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||
'object-curly-spacing': [2, 'always', {
|
||||
objectsInObjects: false
|
||||
}],
|
||||
'array-bracket-spacing': [2, 'never']
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Build CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: 24.x
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: install
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm build:prod
|
||||
|
||||
- name: ClearFile
|
||||
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
|
||||
with:
|
||||
host: ${{ secrets.SSH_HOST }} # 下面三个配置与上一步类似
|
||||
username: ${{ secrets.SSH_USERNAME }}
|
||||
key: ${{ secrets.DEPLOY_KEY }}
|
||||
# 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器
|
||||
script: |
|
||||
sudo rm -rf /www/vue2/*
|
||||
|
||||
- name: Deploy to Server # 第四步,rsync推送文件
|
||||
uses: AEnterprise/rsync-deploy@72ddc262307c9dd0213aa3fbd9816c8932260326 # v1.0.2 # 使用别人包装好的步骤镜像
|
||||
env:
|
||||
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # 引用配置,SSH私钥
|
||||
ARGS: -avz --delete --exclude='*.pyc' # rsync参数,排除.pyc文件
|
||||
SERVER_PORT: '22' # SSH端口
|
||||
FOLDER: ./dist/* # 要推送的文件夹,路径相对于代码仓库的根目录
|
||||
SERVER_IP: ${{ secrets.SSH_HOST }} # 引用配置,服务器的host名(IP或者域名domain.com)
|
||||
USERNAME: ${{ secrets.SSH_USERNAME }} # 引用配置,服务器登录名
|
||||
SERVER_DESTINATION: /www/vue2/ # 部署到目标文件夹
|
||||
@@ -0,0 +1,33 @@
|
||||
name: 'GitHub Actions Mirror'
|
||||
|
||||
on: [push, delete]
|
||||
|
||||
jobs:
|
||||
mirror_to_gitee:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: 'Mirror to gitee'
|
||||
uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1
|
||||
with:
|
||||
target_repo_url:
|
||||
git@gitee.com:go-admin-team/go-admin-ui.git
|
||||
ssh_private_key:
|
||||
${{ secrets.GITEE_KEY }}
|
||||
mirror_to_gitlab:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: 'Mirror to gitlab'
|
||||
uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1
|
||||
with:
|
||||
target_repo_url:
|
||||
git@gitlab.com:go-admin-team/go-admin-ui.git
|
||||
ssh_private_key:
|
||||
${{ secrets.GITLAB_KEY }}
|
||||
@@ -0,0 +1,33 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.x, 24.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm build:prod
|
||||
env:
|
||||
CI: true
|
||||
@@ -0,0 +1,33 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
**/*.log
|
||||
|
||||
tests/**/coverage/
|
||||
tests/e2e/reports
|
||||
selenium-debug.log
|
||||
|
||||
# Playwright
|
||||
test-results/
|
||||
playwright-report/
|
||||
blob-report/
|
||||
.playwright/
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.local
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Claude Code
|
||||
CLAUDE.md
|
||||
.claude/
|
||||
@@ -0,0 +1 @@
|
||||
pnpm exec lint-staged
|
||||
@@ -0,0 +1,3 @@
|
||||
registry=https://registry.npmmirror.com
|
||||
sass_binary_site=https://registry.npmmirror.com/-/binary/node-sass/
|
||||
electron_mirror=https://registry.npmmirror.com/-/binary/electron/
|
||||
@@ -0,0 +1,14 @@
|
||||
FROM node:24-alpine as build-stage
|
||||
WORKDIR /app
|
||||
COPY package.json pnpm-lock.yaml .npmrc ./
|
||||
RUN npm install -g pnpm@9.15.1
|
||||
RUN pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
RUN pnpm build:prod
|
||||
|
||||
# production stage
|
||||
FROM nginx:stable-alpine
|
||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 wenjianzhang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,301 @@
|
||||
# go-admin
|
||||
|
||||
<img align="right" width="320" src="https://gitee.com/mydearzwj/image/raw/master/img/go-admin.svg">
|
||||
|
||||
|
||||
[](https://github.com/go-admin-team/go-admin)
|
||||
[](https://github.com/go-admin-team/go-admin/releases)
|
||||
[](https://github.com/go-admin-team/go-admin)
|
||||
|
||||
[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | 简体中文
|
||||
|
||||
|
||||
基于Gin + Vue + Element UI的前后端分离权限管理系统,系统初始化极度简单,只需要配置文件中,修改数据库连接,系统支持多指令操作,迁移指令可以让初始化数据库信息变得更简单,服务指令可以很简单的启动api服务
|
||||
|
||||
[在线文档](https://doc.go-admin.dev)
|
||||
|
||||
[github在线文档](https://wenjianzhang.github.io)
|
||||
|
||||
[gitee在线文档](http://mydearzwj.gitee.io/go-admin-doc/)
|
||||
|
||||
[后端项目](https://github.com/go-admin-team/go-admin)
|
||||
|
||||
[视频教程](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
||||
|
||||
## ✨ 特性
|
||||
|
||||
- 遵循 RESTful API 设计规范
|
||||
|
||||
- 基于 GIN WEB API 框架,提供了丰富的中间件支持(用户认证、跨域、访问日志、追踪ID等)
|
||||
|
||||
- 基于Casbin的 RBAC 访问控制模型
|
||||
|
||||
- JWT 认证
|
||||
|
||||
- 支持 Swagger 文档(基于swaggo)
|
||||
|
||||
- 基于 GORM 的数据库存储,可扩展多种类型数据库
|
||||
|
||||
- 配置文件简单的模型映射,快速能够得到想要的配置
|
||||
|
||||
- 代码生成工具
|
||||
|
||||
- 表单构建工具
|
||||
|
||||
- 多指令模式
|
||||
|
||||
- TODO: 单元测试
|
||||
|
||||
|
||||
## 🎁 内置
|
||||
|
||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
||||
3. 岗位管理:配置系统用户所属担任职务。
|
||||
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识,接口权限等。
|
||||
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
|
||||
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
||||
7. 参数管理:对系统动态配置常用参数。
|
||||
8. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||
9. 登录日志:系统登录日志记录查询包含登录异常。
|
||||
1. 接口文档:根据业务代码自动生成相关的api接口文档。
|
||||
1. 代码生成:根据数据表结构生成对应的增删改查相对应业务,全程可视化操作,让基本业务可以零代码实现。
|
||||
1. 表单构建:自定义页面样式,拖拉拽实现页面布局。
|
||||
1. 服务监控:查看一些服务器的基本信息。
|
||||
1. 内容管理:demo功能,下设分类管理、内容管理。可以参考使用方便快速入门。
|
||||
|
||||
## 准备工作
|
||||
|
||||
你需要在本地安装 [go] [gin] [node](http://nodejs.org/) 和 [git](https://git-scm.com/)
|
||||
|
||||
同时配套了系列教程包含视频和文档,如何从下载完成到熟练使用,强烈建议大家先看完这些教程再来实践本项目!!!
|
||||
|
||||
### 轻松实现go-admin写出第一个应用 - 文档教程
|
||||
|
||||
[步骤一 - 基础内容介绍](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial01.html)
|
||||
|
||||
[步骤二 - 实际应用 - 编写增删改查](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial02.html)
|
||||
|
||||
### 手把手教你从入门到放弃 - 视频教程
|
||||
|
||||
[如何启动go-admin](https://www.bilibili.com/video/BV1z5411x7JG)
|
||||
|
||||
[使用生成工具轻松实现业务](https://www.bilibili.com/video/BV1Dg4y1i79D)
|
||||
|
||||
[v1.1.0版本代码生成工具-释放双手](https://www.bilibili.com/video/BV1N54y1i71P) [进阶]
|
||||
|
||||
[多命令启动方式讲解以及IDE配置](https://www.bilibili.com/video/BV1Fg4y1q7ph)
|
||||
|
||||
[go-admin菜单的配置说明](https://www.bilibili.com/video/BV1Wp4y1D715) [必看]
|
||||
|
||||
[如何配置菜单信息以及接口信息](https://www.bilibili.com/video/BV1zv411B7nG) [必看]
|
||||
|
||||
[go-admin权限配置使用说明](https://www.bilibili.com/video/BV1rt4y197d3) [必看]
|
||||
|
||||
[go-admin数据权限使用说明](https://www.bilibili.com/video/BV1LK4y1s71e) [必看]
|
||||
|
||||
|
||||
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr ,视频教程和文档持续更新中**
|
||||
|
||||
## 📦 本地开发
|
||||
|
||||
### 环境要求
|
||||
|
||||
go 1.26.5
|
||||
|
||||
node版本: v22+(推荐 v24 LTS)
|
||||
|
||||
包管理器: pnpm v9+(项目使用 pnpm,锁文件为 pnpm-lock.yaml)
|
||||
|
||||
### 开发目录创建
|
||||
|
||||
```bash
|
||||
|
||||
# 创建开发目录
|
||||
mkdir goadmin
|
||||
cd goadmin
|
||||
```
|
||||
|
||||
### 获取代码
|
||||
|
||||
> 重点注意:两个项目必须放在同一文件夹下;
|
||||
|
||||
```bash
|
||||
# 获取后端代码
|
||||
git clone https://github.com/go-admin-team/go-admin.git
|
||||
|
||||
# 获取前端代码
|
||||
git clone https://github.com/go-admin-team/go-admin-ui.git
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 启动说明
|
||||
|
||||
#### 服务端启动说明
|
||||
|
||||
```bash
|
||||
# 进入 go-admin 后端项目
|
||||
cd ./go-admin
|
||||
|
||||
# 编译项目
|
||||
go build
|
||||
|
||||
# 修改配置
|
||||
# 文件路径 go-admin/config/settings.yml
|
||||
vi ./config/setting.yml
|
||||
|
||||
# 1. 配置文件中修改数据库信息
|
||||
# 注意: settings.database 下对应的配置数据
|
||||
# 2. 确认log路径
|
||||
```
|
||||
|
||||
:::tip ⚠️注意 在windows环境如果没有安装中CGO,会出现这个问题;
|
||||
|
||||
```bash
|
||||
E:\go-admin>go build
|
||||
# github.com/mattn/go-sqlite3
|
||||
cgo: exec /missing-cc: exec: "/missing-cc": file does not exist
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
D:\Code\go-admin>go build
|
||||
# github.com/mattn/go-sqlite3
|
||||
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
||||
```
|
||||
|
||||
[解决cgo问题进入](https://doc.go-admin.dev/guide/other/faq.html#_5-cgo-exec-missing-cc-exec-missing-cc-file-does-not-exist)
|
||||
|
||||
:::
|
||||
|
||||
#### 初始化数据库,以及服务启动
|
||||
|
||||
``` bash
|
||||
# 首次配置需要初始化数据库资源信息
|
||||
# macOS or linux 下使用
|
||||
$ ./go-admin migrate -c=config/settings.dev.yml
|
||||
|
||||
# ⚠️注意:windows 下使用
|
||||
$ go-admin.exe migrate -c=config/settings.dev.yml
|
||||
|
||||
|
||||
# 启动项目,也可以用IDE进行调试
|
||||
# macOS or linux 下使用
|
||||
$ ./go-admin server -c config/settings.yml
|
||||
|
||||
|
||||
# ⚠️注意:windows 下使用
|
||||
$ go-admin.exe server -c config/settings.yml
|
||||
```
|
||||
|
||||
#### 使用docker 编译启动
|
||||
|
||||
```shell
|
||||
# 编译镜像
|
||||
docker build -t go-admin .
|
||||
|
||||
# 启动容器,第一个go-admin是容器名字,第二个go-admin是镜像名称
|
||||
# -v 映射配置文件 本地路径:容器路径
|
||||
docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 文档生成
|
||||
|
||||
```bash
|
||||
go generate
|
||||
```
|
||||
|
||||
#### 交叉编译
|
||||
```bash
|
||||
# windows
|
||||
env GOOS=windows GOARCH=amd64 go build main.go
|
||||
|
||||
# or
|
||||
# linux
|
||||
env GOOS=linux GOARCH=amd64 go build main.go
|
||||
```
|
||||
|
||||
### UI交互端启动说明
|
||||
|
||||
```bash
|
||||
|
||||
# 安装 pnpm(若未安装)
|
||||
npm install -g pnpm
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 国内网络可指定镜像源加速
|
||||
pnpm install --registry=https://registry.npmmirror.com
|
||||
|
||||
# 启动服务
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## 🎬 在线体验
|
||||
> 上游在线演示凭据不属于 Bell,已移除。
|
||||
|
||||
演示地址:[http://www.go-admin.dev](http://www.go-admin.dev/#/login)
|
||||
|
||||
|
||||
## 📨 互动
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq.png" width="200px"></td>
|
||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>微信</td>
|
||||
<td>此群已满</td>
|
||||
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## 💎 主要成员
|
||||
|
||||
<a href="https://github.com/wenjianzhang"> <img src="https://avatars.githubusercontent.com/u/3890175?s=460&u=20eac63daef81588fbac611da676b99859319251&v=4" width="80px"></a>
|
||||
<a href="https://github.com/lwnmengjing"> <img src="https://avatars.githubusercontent.com/u/12806223?s=400&u=a89272dce50100b77b4c0d5c81c718bf78ebb580&v=4" width="80px"></a>
|
||||
<a href="https://github.com/chengxiao"> <img src="https://avatars.githubusercontent.com/u/1379545?s=460&u=557da5503d0ac4a8628df6b4075b17853d5edcd9&v=4" width="80px"></a>
|
||||
<a href="https://github.com/bing127"> <img src="https://avatars.githubusercontent.com/u/31166183?s=460&u=c085bff88df10bb7676c8c0351ba9dcd031d1fb3&v=4" width="80px"></a>
|
||||
|
||||
|
||||
|
||||
## JetBrains 开源证书支持
|
||||
|
||||
`go-admin` 项目一直以来都是在 JetBrains 公司旗下的 GoLand 集成开发环境中进行开发,基于 **free JetBrains Open Source license(s)** 正版免费授权,在此表达我的谢意。
|
||||
|
||||
<a href="https://www.jetbrains.com/?from=kubeadm-ha" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||
|
||||
|
||||
## 🤝 特别感谢
|
||||
1. [chengxiao](https://github.com/chengxiao)
|
||||
2. [gin](https://github.com/gin-gonic/gin)
|
||||
2. [casbin](https://github.com/casbin/casbin)
|
||||
2. [spf13/viper](https://github.com/spf13/viper)
|
||||
2. [gorm](https://github.com/jinzhu/gorm)
|
||||
2. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
||||
2. [jwt-go](https://github.com/dgrijalva/jwt-go)
|
||||
2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||
2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||
2. [form-generator](https://github.com/JakHuang/form-generator)
|
||||
|
||||
## 🤟 打赏
|
||||
|
||||
> 如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink:
|
||||
|
||||
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
||||
|
||||
## 🤝 链接
|
||||
[Go开发者成长线路图](http://www.golangroadmap.com/)
|
||||
|
||||
## 🔑 License
|
||||
|
||||
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
||||
|
||||
Copyright (c) 2020 wenjianzhang
|
||||
@@ -0,0 +1,287 @@
|
||||
# go-admin
|
||||
|
||||
<img align="right" width="320" src="https://gitee.com/mydearzwj/image/raw/master/img/go-admin.svg">
|
||||
|
||||
|
||||
[](https://github.com/go-admin-team/go-admin)
|
||||
[](https://github.com/go-admin-team/go-admin/releases)
|
||||
[](https://github.com/go-admin-team/go-admin)
|
||||
|
||||
English | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md)
|
||||
|
||||
The front-end and back-end separation authority management system based on Gin + Vue + Element UI is extremely simple to initialize the system. You only need to modify the database connection in the configuration file. The system supports multi-instruction operations. Migration instructions can make it easier to initialize database information. Service instructions It's easy to start the api service.
|
||||
|
||||
[documentation](https://doc.go-admin.dev)
|
||||
|
||||
[Backend project](https://github.com/go-admin-team/go-admin)
|
||||
|
||||
[Video tutorial](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
||||
|
||||
## ✨ Feature
|
||||
|
||||
- Follow RESTful API design specifications
|
||||
|
||||
- Based on the GIN WEB API framework, it provides rich middleware support (user authentication, cross-domain, access log, tracking ID, etc.)
|
||||
|
||||
- RBAC access control model based on Casbin
|
||||
|
||||
- JWT authentication
|
||||
|
||||
- Support Swagger documents (based on swaggo)
|
||||
|
||||
- Database storage based on GORM, which can expand multiple types of databases
|
||||
|
||||
- Simple model mapping of configuration files to quickly get the desired configuration
|
||||
|
||||
- Code generation tool
|
||||
|
||||
- Form builder
|
||||
|
||||
- Multi-command mode
|
||||
|
||||
- TODO: unit test
|
||||
|
||||
|
||||
## 🎁 Internal
|
||||
|
||||
1. User management: The user is the system operator, this function mainly completes the system user configuration.
|
||||
2. Department management: configure the system organization (company, department, group), and display the tree structure to support data permissions.
|
||||
3. Position management: configure the positions of system users.
|
||||
4. Menu management: configure the system menu, operation authority, button authority identification, interface authority, etc.
|
||||
5. Role management: Role menu permission assignment and role setting are divided into data scope permissions by organization.
|
||||
6. Dictionary management: Maintain some relatively fixed data frequently used in the system.
|
||||
7. Parameter management: dynamically configure common parameters for the system.
|
||||
8. Operation log: system normal operation log record and query; system abnormal information log record and query.
|
||||
9. Login log: The system login log record query contains login exceptions.
|
||||
1. Interface documentation: Automatically generate related api interface documents according to the business code.
|
||||
1. Code generation: According to the data table structure, generate the corresponding addition, deletion, modification, and check corresponding business, and the whole process of visual operation, so that the basic business can be implemented with zero code.
|
||||
1. Form construction: Customize the page style, drag and drop to realize the page layout.
|
||||
1. Service monitoring: View the basic information of some servers.
|
||||
1. Content management: demo function, including classification management and content management. You can refer to the easy to use quick start.
|
||||
|
||||
## Ready to work
|
||||
|
||||
You need to install locally [go] [gin] [node](http://nodejs.org/) 和 [git](https://git-scm.com/)
|
||||
|
||||
At the same time, a series of tutorials including videos and documents are provided. How to complete the downloading to the proficient use, it is strongly recommended that you read these tutorials before you practice this project! ! !
|
||||
|
||||
### Easily implement go-admin to write the first application-documentation tutorial
|
||||
|
||||
[Step 1 - basic content introduction](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial01.html)
|
||||
|
||||
[Step 2 - Practical application - writing database operations](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial02.html)
|
||||
|
||||
### Teach you from getting started to giving up-video tutorial
|
||||
|
||||
[How to start go-admin](https://www.bilibili.com/video/BV1z5411x7JG)
|
||||
|
||||
[Easily implement business using build tools](https://www.bilibili.com/video/BV1Dg4y1i79D)
|
||||
|
||||
[v1.1.0 version code generation tool-free your hands](https://www.bilibili.com/video/BV1N54y1i71P) [Advanced]
|
||||
|
||||
[Explanation of multi-command startup mode and IDE configuration](https://www.bilibili.com/video/BV1Fg4y1q7ph)
|
||||
|
||||
[Configuration instructions for go-admin menu](https://www.bilibili.com/video/BV1Wp4y1D715) [Must see]
|
||||
|
||||
[How to configure menu information and interface information](https://www.bilibili.com/video/BV1zv411B7nG) [Must see]
|
||||
|
||||
[go-admin permission configuration instructions](https://www.bilibili.com/video/BV1rt4y197d3) [Must see]
|
||||
|
||||
[Instructions for use of go-admin data permissions](https://www.bilibili.com/video/BV1LK4y1s71e) [Must see]
|
||||
|
||||
**If you have any questions, please read the above-mentioned usage documents and articles first. If you are not satisfied, welcome to issue and pr. Video tutorials and documents are being updated continuously.**
|
||||
|
||||
## 📦 Local development
|
||||
|
||||
### Environmental requirements
|
||||
|
||||
go 1.26.5
|
||||
|
||||
nodejs: v22+ (v24 LTS recommended)
|
||||
|
||||
package manager: pnpm v9+ (this project uses pnpm, lockfile is pnpm-lock.yaml)
|
||||
|
||||
### Development directory creation
|
||||
|
||||
```bash
|
||||
|
||||
# Create a development directory
|
||||
mkdir goadmin
|
||||
cd goadmin
|
||||
```
|
||||
|
||||
### Get the code
|
||||
|
||||
> Important note: the two projects must be placed in the same folder;
|
||||
|
||||
```bash
|
||||
# Get backend code
|
||||
git clone https://github.com/go-admin-team/go-admin.git
|
||||
|
||||
# Get the front-end code
|
||||
git clone https://github.com/go-admin-team/go-admin-ui.git
|
||||
|
||||
```
|
||||
|
||||
### Startup instructions
|
||||
|
||||
#### Server startup instructions
|
||||
|
||||
```bash
|
||||
# Enter the go-admin backend project
|
||||
cd ./go-admin
|
||||
|
||||
# Compile the project
|
||||
go build
|
||||
|
||||
# Change setting
|
||||
# File path go-admin/config/settings.yml
|
||||
vi ./config/setting.yml
|
||||
|
||||
# 1. Modify the database information in the configuration file
|
||||
# Note: The corresponding configuration data under settings.database
|
||||
# 2. Confirm the log path
|
||||
```
|
||||
|
||||
:::tip ⚠️Note that this problem will occur if CGO is not installed in the windows environment;
|
||||
|
||||
```bash
|
||||
E:\go-admin>go build
|
||||
# github.com/mattn/go-sqlite3
|
||||
cgo: exec /missing-cc: exec: "/missing-cc": file does not exist
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
D:\Code\go-admin>go build
|
||||
# github.com/mattn/go-sqlite3
|
||||
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
||||
```
|
||||
|
||||
[Solve the cgo problem and enter](https://doc.go-admin.dev/guide/other/faq.html#_5-cgo-exec-missing-cc-exec-missing-cc-file-does-not-exist)
|
||||
|
||||
:::
|
||||
|
||||
#### Initialize the database, and start the service
|
||||
|
||||
``` bash
|
||||
# The first configuration needs to initialize the database resource information
|
||||
# Use under macOS or linux
|
||||
$ ./go-admin migrate -c=config/settings.dev.yml
|
||||
|
||||
# ⚠️Note: Use under windows
|
||||
$ go-admin.exe migrate -c=config/settings.dev.yml
|
||||
|
||||
# Start the project, you can also use the IDE for debugging
|
||||
# Use under macOS or linux
|
||||
$ ./go-admin server -c config/settings.yml
|
||||
|
||||
# ⚠️Note: Use under windows
|
||||
$ go-admin.exe server -c config/settings.yml
|
||||
```
|
||||
|
||||
#### Use docker to compile and start
|
||||
|
||||
```shell
|
||||
# Compile the image
|
||||
docker build -t go-admin .
|
||||
|
||||
|
||||
# Start the container, the first go-admin is the container name, and the second go-admin is the image name
|
||||
# -v Mapping configuration file Local path: container path
|
||||
docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Generation Document
|
||||
|
||||
```bash
|
||||
go generate
|
||||
```
|
||||
|
||||
#### Cross compile
|
||||
```bash
|
||||
# windows
|
||||
env GOOS=windows GOARCH=amd64 go build main.go
|
||||
|
||||
# or
|
||||
# linux
|
||||
env GOOS=linux GOARCH=amd64 go build main.go
|
||||
```
|
||||
|
||||
### UI interactive terminal startup instructions
|
||||
|
||||
```bash
|
||||
# Install pnpm if you don't have it
|
||||
npm install -g pnpm
|
||||
|
||||
# Installation dependencies
|
||||
pnpm install
|
||||
|
||||
# Start service
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## 🎬 Online Demo
|
||||
> Upstream demo credentials are not Bell credentials and have been removed.
|
||||
|
||||
演示地址:[http://www.go-admin.dev](http://www.go-admin.dev/#/login)
|
||||
|
||||
|
||||
## 📨 Interactive
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Wechat</td>
|
||||
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## 💎 Members
|
||||
|
||||
<a href="https://github.com/wenjianzhang"> <img src="https://avatars.githubusercontent.com/u/3890175?s=460&u=20eac63daef81588fbac611da676b99859319251&v=4" width="80px"></a>
|
||||
<a href="https://github.com/lwnmengjing"> <img src="https://avatars.githubusercontent.com/u/12806223?s=400&u=a89272dce50100b77b4c0d5c81c718bf78ebb580&v=4" width="80px"></a>
|
||||
<a href="https://github.com/chengxiao"> <img src="https://avatars.githubusercontent.com/u/1379545?s=460&u=557da5503d0ac4a8628df6b4075b17853d5edcd9&v=4" width="80px"></a>
|
||||
<a href="https://github.com/bing127"> <img src="https://avatars.githubusercontent.com/u/31166183?s=460&u=c085bff88df10bb7676c8c0351ba9dcd031d1fb3&v=4" width="80px"></a>
|
||||
|
||||
|
||||
|
||||
## JetBrains open source certificate support
|
||||
|
||||
The `go-admin` project has always been developed in the GoLand integrated development environment under JetBrains, based on the **free JetBrains Open Source license(s)** genuine free license. I would like to express my gratitude.
|
||||
|
||||
<a href="https://www.jetbrains.com/?from=kubeadm-ha" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||
|
||||
|
||||
## 🤝 Thanks
|
||||
1. [chengxiao](https://github.com/chengxiao)
|
||||
2. [gin](https://github.com/gin-gonic/gin)
|
||||
2. [casbin](https://github.com/casbin/casbin)
|
||||
2. [spf13/viper](https://github.com/spf13/viper)
|
||||
2. [gorm](https://github.com/jinzhu/gorm)
|
||||
2. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
||||
2. [jwt-go](https://github.com/dgrijalva/jwt-go)
|
||||
2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||
2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||
2. [form-generator](https://github.com/JakHuang/form-generator)
|
||||
|
||||
## 🤟 Sponsor Us
|
||||
|
||||
> If you think this project helped you, you can buy a glass of juice for the author to show encouragement :tropical_drink:
|
||||
|
||||
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
||||
|
||||
## 🤝 Link
|
||||
[Go developer growth roadmap](http://www.golangroadmap.com/)
|
||||
|
||||
## 🔑 License
|
||||
|
||||
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
||||
|
||||
Copyright (c) 2020 wenjianzhang
|
||||
@@ -0,0 +1,90 @@
|
||||
# Sass Legacy API 废弃警告处理说明
|
||||
|
||||
## 问题描述
|
||||
编译时出现警告:
|
||||
```
|
||||
Deprecation Warning [legacy-js-api]: The legacy JS API is deprecated
|
||||
and will be removed in Dart Sass 2.0.0.
|
||||
```
|
||||
|
||||
## 原因
|
||||
- 项目当前使用 `sass-loader: ^13.3.3` + `sass: ^1.91.0`
|
||||
- sass-loader 13.x 默认仍走 Dart Sass 的 legacy JS API(从 14.x 起才默认使用 modern API)
|
||||
- Dart Sass 2.0 将移除此 API
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 🎯 方案1:环境变量静默(已实施)✅
|
||||
|
||||
在 `.env.development` 和 `.env.production` 中添加:
|
||||
|
||||
```bash
|
||||
SASS_SILENCE_DEPRECATIONS = 'legacy-js-api'
|
||||
```
|
||||
|
||||
Dart Sass 会自动读取此环境变量并静默对应警告。
|
||||
|
||||
**优点**:
|
||||
- ✅ 不需要重装依赖
|
||||
- ✅ 不修改 webpack 配置
|
||||
- ✅ 立即生效
|
||||
- ✅ 官方推荐方式
|
||||
|
||||
**缺点**:
|
||||
- ⚠️ 只是隐藏警告,未来 Dart Sass 2.0 可能不兼容
|
||||
|
||||
---
|
||||
|
||||
### 🚀 方案2:切换到 modern API(推荐长期方案)
|
||||
|
||||
升级 sass-loader 到 14+,默认使用 Dart Sass 的 modern API:
|
||||
|
||||
```bash
|
||||
pnpm add -D sass-loader@^14.2.1
|
||||
```
|
||||
|
||||
或在当前 13.x 下于 `vue.config.js` 中显式指定:
|
||||
|
||||
```js
|
||||
css: {
|
||||
loaderOptions: {
|
||||
sass: { api: 'modern' }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
两种方式生效后即可移除环境变量配置。
|
||||
|
||||
**优点**:
|
||||
- ✅ 彻底解决问题
|
||||
- ✅ 面向未来兼容
|
||||
|
||||
**缺点**:
|
||||
- ⚠️ 可能需要调整配置
|
||||
- ⚠️ 需要重新安装依赖
|
||||
|
||||
---
|
||||
|
||||
## 当前状态
|
||||
|
||||
✅ **已采用方案1**,通过环境变量静默警告。
|
||||
|
||||
sass-loader 虽已是 13.3.3,但仍走 legacy API,因此静默配置目前仍然必要。
|
||||
建议在未来 Vue 3 稳定后,按方案2 切换到 modern API 并移除该环境变量。
|
||||
|
||||
---
|
||||
|
||||
## 验证
|
||||
|
||||
重启开发服务器后,编译过程中不再显示该警告:
|
||||
|
||||
```bash
|
||||
# 需要完全重启,而不是热重载
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 参考
|
||||
- [Sass Legacy JS API](https://sass-lang.com/d/legacy-js-api)
|
||||
- [Sass Silencing Deprecations](https://sass-lang.com/documentation/cli/dart-sass/#silencedeprecations)
|
||||
- [sass-loader v13 文档](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# go-admin-ui Vue3 升级实施文档
|
||||
|
||||
## 1. 项目分支说明
|
||||
当前升级分支:`dev-to-vue3`
|
||||
|
||||
## 2. 升级目标
|
||||
- Vue 2.x → Vue 3.x
|
||||
- Element UI → Element Plus
|
||||
- Babel、Webpack、ESLint、Jest 等工具包升级
|
||||
- 其他安全性相关依赖(如 axios、lodash)升级
|
||||
- **Node.js 版本升级**:从 >=8.9 升级到 >=18.0(推荐 LTS 版本)
|
||||
|
||||
## 3. 升级实施阶段
|
||||
|
||||
### 阶段零:环境准备(0.5 天) ✅ 已完成
|
||||
- 检查当前 Node.js 版本(当前 v18.20.1 ✅)
|
||||
- 升级 Node.js 到最新 LTS 版本(已满足要求)
|
||||
- 升级 npm 到最新版本(已满足要求)
|
||||
- 验证新环境下的项目能否正常运行基础命令(如 `npm install` ✅)
|
||||
|
||||
### 阶段一:准备与调研 ✅ 已完成
|
||||
- 备份当前代码,确保可回滚。
|
||||
- 盘点所有依赖,确认升级目标版本。
|
||||
- 使用 npm-check-updates 生成升级清单 ✅
|
||||
- 执行次要版本依赖升级 ✅
|
||||
- 解决依赖冲突并安装新版本 ✅
|
||||
- 验证项目基础功能(lint、test)✅
|
||||
|
||||
### 阶段二:依赖升级
|
||||
- 使用 npm-check-updates 或手动修改 `package.json`,升级核心依赖。
|
||||
- 执行 `npm install`,解决依赖冲突。
|
||||
- 升级 Babel、Webpack、ESLint、Jest、axios、lodash 等工具包。
|
||||
|
||||
### 阶段三:代码适配与重构
|
||||
- 全面适配 Vue 3 语法(如 Composition API、生命周期钩子变更)。
|
||||
- 替换 Element UI 为 Element Plus,调整组件用法。
|
||||
- 升级 vue-router、vuex,并适配新 API。
|
||||
- 检查第三方库兼容性,必要时替换或移除。
|
||||
|
||||
### 阶段四:配置文件调整
|
||||
- 更新 babel.config.js、webpack、eslint、jest 等配置文件。
|
||||
- 检查并调整 polyfill、postcss、plop 等相关配置。
|
||||
|
||||
### 阶段五:测试与回归
|
||||
- 运行单元测试,修复因升级导致的测试失败。
|
||||
- 手动回归主要功能页面,确保无异常。
|
||||
- 检查打包、部署流程是否正常。
|
||||
|
||||
### 阶段六:文档与说明
|
||||
- 更新 README.md,说明升级内容及注意事项。
|
||||
- 补充迁移指南,便于团队成员理解变更。
|
||||
|
||||
### 阶段七:评审与合并
|
||||
- 团队代码评审,确认无重大问题后合并至主分支。
|
||||
|
||||
## 4. 当前进度总结
|
||||
- ✅ Node.js 环境检查完成(v18.20.1)
|
||||
- ✅ 依赖盘点完成,生成了 68 个可升级项
|
||||
- ✅ 次要版本依赖升级完成(patch/minor 版本)
|
||||
- ✅ 依赖安装成功,项目可正常运行
|
||||
- ✅ ESLint 验证通过(发现 35 个问题,多数为代码风格问题)
|
||||
- ⚠️ 单元测试部分失败(9 个失败,14 个通过),主要问题:
|
||||
- `time_str` 变量初始化问题(src/utils/index.js)
|
||||
- @vue/test-utils `contains` 方法弃用(测试代码需更新)
|
||||
|
||||
## 5. 参考迁移资源
|
||||
- [Vue 2 → Vue 3 官方迁移指南](https://v3-migration.vuejs.org/)
|
||||
- [Element UI → Element Plus 迁移文档](https://element-plus.org/zh-CN/guide/migration.html)
|
||||
- [vue-router 4.x 文档](https://router.vuejs.org/)
|
||||
- [vuex 4.x 文档](https://vuex.vuejs.org/)
|
||||
- [Node.js LTS 版本说明](https://nodejs.org/en/about/releases/)
|
||||
|
||||
---
|
||||
|
||||
> 后续所有升级、重构、测试等工作请严格按照本实施文档分阶段推进。
|
||||
@@ -0,0 +1,206 @@
|
||||
# Vue 3 最佳实践完整检查清单
|
||||
|
||||
## ✅ 已完成的优化 (按优先级)
|
||||
|
||||
### 🔴 P0 - 关键错误修复
|
||||
- [x] 移除所有 `this.$set` 使用 → 直接赋值 (Vue 3 原生响应式)
|
||||
- [x] 移除所有 `$listeners` (Vue 3 自动合并到 $attrs)
|
||||
- [x] 更新生命周期钩子: `beforeDestroy` → `beforeUnmount`
|
||||
- [x] 修复 `v-else` 与 `v-if` 相邻性问题
|
||||
- [x] 移除所有 `.native` 修饰符
|
||||
|
||||
### 🟠 P1 - 语法更新
|
||||
- [x] 更新 `::v-deep` → `:deep()`
|
||||
- [x] 修复 `router-link` tag 属性 → 使用 `custom + v-slot`
|
||||
- [x] 更新 filters → methods
|
||||
- [x] 修复 prop mutation (创建本地副本)
|
||||
- [x] 添加所有 emits 声明 (13个组件)
|
||||
|
||||
### 🟡 P2 - 代码质量
|
||||
- [x] 组件命名符合 multi-word 规则
|
||||
- [x] v-slot 属性顺序优化
|
||||
- [x] 移除 trailing spaces
|
||||
- [x] 修复格式问题
|
||||
|
||||
## 📊 组件命名优化记录
|
||||
|
||||
### 已修复的组件 (15个)
|
||||
|
||||
| 原名称 | 新名称 | 文件路径 |
|
||||
|-------|-------|---------|
|
||||
| `Pagination` | `PaginationComponent` | components/Pagination |
|
||||
| `Todo` | `TodoItem` | dashboard/TodoList |
|
||||
| `Trend` | `TrendIndicator` | components/Trend |
|
||||
| `Monitor` | `MonitorPage` | views/sys-tools |
|
||||
| `Profile` | `ProfilePage` | views/profile |
|
||||
| `Dashboard` | `DashboardPage` | views/dashboard |
|
||||
| `Role` | `RoleManagement` | views/admin/sys-role |
|
||||
| `Layout` | `MainLayout` | layout |
|
||||
| `index` | `TagsViewContainer` | layout/components/TagsView |
|
||||
| `Gen` | `CodeGen` | views/dev-tools/gen |
|
||||
| `Swagger` | `SwaggerDoc` | views/dev-tools/swagger |
|
||||
| `Page401` | `ErrorPage401` | views/error-page |
|
||||
| `Page404` | `Page404` | 保持(已符合)|
|
||||
| `BasicInfoForm` | `BasicInfoFormComponent` | dev-tools/gen |
|
||||
| `GenInfoForm` | `GenInfoFormComponent` | dev-tools/gen |
|
||||
|
||||
### 全局组件注册优化
|
||||
|
||||
```javascript
|
||||
// main.js 中的优化
|
||||
app.component('AppPagination', Pagination) // was: Pagination
|
||||
app.component('CodeEditor', Codemirror) // was: Codemirror
|
||||
app.component('SvgIcon', SvgIcon) // 保持
|
||||
app.component('BasicLayout', BasicLayout) // 保持
|
||||
```
|
||||
|
||||
## 🔍 Vue 3 兼容性最终检查
|
||||
|
||||
### ✅ 完全兼容
|
||||
|
||||
| 检查项 | 状态 | 说明 |
|
||||
|-------|------|-----|
|
||||
| `$listeners` | ✅ 已清理 | 0处使用 |
|
||||
| `$set` / `$delete` | ✅ 已清理 | 改为直接赋值 |
|
||||
| `.sync` 修饰符 | ✅ 已清理 | 0处使用 |
|
||||
| `.native` 修饰符 | ✅ 已清理 | 批量移除 |
|
||||
| `beforeDestroy` | ✅ 已更新 | → `beforeUnmount` |
|
||||
| `destroyed` | ✅ 已更新 | → `unmounted` |
|
||||
| `::v-deep` | ✅ 已更新 | → `:deep()` |
|
||||
| `filters` | ✅ 已迁移 | → methods |
|
||||
| `functional` 组件 | ✅ 已迁移 | 普通组件 |
|
||||
| `router-link tag` | ✅ 已更新 | → custom + v-slot |
|
||||
|
||||
### ⚠️ 非阻塞警告 (可接受)
|
||||
|
||||
剩余 ~5-10 个 ESLint 警告:
|
||||
- 部分业务组件命名(可选优化)
|
||||
- 代码风格建议(不影响功能)
|
||||
|
||||
## 📚 Vue 3 最佳实践应用
|
||||
|
||||
### 1. 响应式系统
|
||||
```javascript
|
||||
// ❌ Vue 2
|
||||
this.$set(obj, 'key', value)
|
||||
this.$delete(obj, 'key')
|
||||
|
||||
// ✅ Vue 3
|
||||
obj.key = value
|
||||
delete obj.key
|
||||
```
|
||||
|
||||
### 2. 事件监听
|
||||
```vue
|
||||
<!-- ❌ Vue 2 -->
|
||||
<component v-on="$listeners" />
|
||||
<input @input.native="handler" />
|
||||
|
||||
<!-- ✅ Vue 3 -->
|
||||
<component /> <!-- 自动透传 -->
|
||||
<input @input="handler" />
|
||||
```
|
||||
|
||||
### 3. 组件命名
|
||||
```javascript
|
||||
// ❌ 单个单词
|
||||
name: 'Dashboard'
|
||||
name: 'index'
|
||||
|
||||
// ✅ Multi-word
|
||||
name: 'DashboardPage'
|
||||
name: 'TagsViewContainer'
|
||||
```
|
||||
|
||||
### 4. Prop 修改
|
||||
```javascript
|
||||
// ❌ 直接修改 prop
|
||||
props: ['value']
|
||||
this.value = newValue
|
||||
|
||||
// ✅ 创建本地副本
|
||||
props: ['value']
|
||||
data() {
|
||||
return { localValue: this.value }
|
||||
}
|
||||
watch: {
|
||||
value(val) { this.localValue = val },
|
||||
localValue(val) { this.$emit('update:value', val) }
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Emits 声明
|
||||
```javascript
|
||||
// ❌ 未声明
|
||||
this.$emit('change', value)
|
||||
|
||||
// ✅ 显式声明
|
||||
export default {
|
||||
emits: ['change', 'update:modelValue'],
|
||||
methods: {
|
||||
handleChange() {
|
||||
this.$emit('change', value)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 样式穿透
|
||||
```scss
|
||||
// ❌ Vue 2
|
||||
::v-deep .class { }
|
||||
|
||||
// ✅ Vue 3
|
||||
:deep(.class) { }
|
||||
```
|
||||
|
||||
## 🎯 质量指标
|
||||
|
||||
### ESLint 改善
|
||||
```
|
||||
初始: 414 problems (242 errors, 172 warnings)
|
||||
最终: ~5-10 warnings (0 errors)
|
||||
──────────────────────────────────────────
|
||||
改善: -98% 问题 🎉
|
||||
错误: -100% (242 → 0) ⭐⭐⭐
|
||||
```
|
||||
|
||||
### 编译状态
|
||||
- ✅ 0 编译错误
|
||||
- ✅ 0 运行时错误
|
||||
- ✅ Sass 警告已静默
|
||||
- ✅ 热重载正常
|
||||
|
||||
### 代码质量
|
||||
- ✅ 100% Vue 3 兼容
|
||||
- ✅ 符合 Vue 3 最佳实践
|
||||
- ✅ 组件命名规范
|
||||
- ✅ TypeScript 友好
|
||||
|
||||
## 🚀 下一步建议
|
||||
|
||||
### 可选优化 (P3)
|
||||
- [ ] 考虑使用 Composition API 重构复杂组件
|
||||
- [ ] 使用 `<script setup>` 语法糖(更简洁)
|
||||
- [ ] 迁移到 Pinia(替代 Vuex)
|
||||
- [ ] 升级 Codemirror 到 v6
|
||||
- [ ] 添加 TypeScript 支持
|
||||
|
||||
### 性能优化
|
||||
- [ ] 使用 `defineAsyncComponent` 懒加载大组件
|
||||
- [ ] 使用 `v-memo` 优化长列表
|
||||
- [ ] 使用 Suspense 处理异步组件
|
||||
|
||||
## ✅ 验收标准
|
||||
|
||||
所有以下标准均已达成:
|
||||
|
||||
1. ✅ 编译无错误
|
||||
2. ✅ ESLint 0 errors
|
||||
3. ✅ 无 Vue 2 废弃语法
|
||||
4. ✅ 符合 Vue 3 最佳实践
|
||||
5. ✅ 组件命名规范
|
||||
6. ✅ 运行时无警告
|
||||
7. ✅ 功能完整保留
|
||||
|
||||
**项目已完全升级到 Vue 3,达到生产就绪状态!** 🎊
|
||||
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
plugins: [
|
||||
'@vue/babel-plugin-jsx'
|
||||
],
|
||||
env: {
|
||||
development: {
|
||||
plugins: ['dynamic-import-node']
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<title>Bell 预警管理</title>
|
||||
<meta name="keywords" content="Bell,预警管理,go-admin">
|
||||
<meta name="description"
|
||||
content="基于Gin + Vue + Element UI的前后端分离权限管理系统,初始化极度简单,只需要配置文件中,修改数据库连接,系统启动后会自动初始化数据库信息以及必须的基础数据">
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
background: #f0f1f5;
|
||||
}
|
||||
|
||||
.chromeframe {
|
||||
margin: 0.2em 0;
|
||||
background: #ccc;
|
||||
color: #000;
|
||||
padding: 0.2em 0;
|
||||
}
|
||||
|
||||
#loader-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
#loader {
|
||||
display: block;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: -75px 0 0 -75px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #FFF;
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
-ms-animation: spin 2s linear infinite;
|
||||
-moz-animation: spin 2s linear infinite;
|
||||
-o-animation: spin 2s linear infinite;
|
||||
animation: spin 2s linear infinite;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
#loader:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #FFF;
|
||||
-webkit-animation: spin 3s linear infinite;
|
||||
-moz-animation: spin 3s linear infinite;
|
||||
-o-animation: spin 3s linear infinite;
|
||||
-ms-animation: spin 3s linear infinite;
|
||||
animation: spin 3s linear infinite;
|
||||
}
|
||||
|
||||
#loader:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #FFF;
|
||||
-moz-animation: spin 1.5s linear infinite;
|
||||
-o-animation: spin 1.5s linear infinite;
|
||||
-ms-animation: spin 1.5s linear infinite;
|
||||
-webkit-animation: spin 1.5s linear infinite;
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#loader-wrapper .loader-section {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 51%;
|
||||
height: 100%;
|
||||
background: #7171C6;
|
||||
z-index: 1000;
|
||||
-webkit-transform: translateX(0);
|
||||
-ms-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#loader-wrapper .loader-section.section-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#loader-wrapper .loader-section.section-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
||||
.loaded #loader-wrapper .loader-section.section-left {
|
||||
-webkit-transform: translateX(-100%);
|
||||
-ms-transform: translateX(-100%);
|
||||
transform: translateX(-100%);
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
}
|
||||
|
||||
.loaded #loader-wrapper .loader-section.section-right {
|
||||
-webkit-transform: translateX(100%);
|
||||
-ms-transform: translateX(100%);
|
||||
transform: translateX(100%);
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
}
|
||||
|
||||
.loaded #loader {
|
||||
opacity: 0;
|
||||
-webkit-transition: all 0.3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.loaded #loader-wrapper {
|
||||
visibility: hidden;
|
||||
-webkit-transform: translateY(-100%);
|
||||
-ms-transform: translateY(-100%);
|
||||
transform: translateY(-100%);
|
||||
-webkit-transition: all 0.3s 1s ease-out;
|
||||
transition: all 0.3s 1s ease-out;
|
||||
}
|
||||
|
||||
.no-js #loader-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.no-js h1 {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
#loader-wrapper .load_title {
|
||||
font-family: 'Open Sans';
|
||||
color: #FFF;
|
||||
font-size: 14.3px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
z-index: 9999999999999;
|
||||
position: absolute;
|
||||
top: 60%;
|
||||
opacity: 1;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#loader-wrapper .load_title span {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
color: #FFF;
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div id="loader-wrapper">
|
||||
<div id="loader"></div>
|
||||
<div class="loader-section section-left"></div>
|
||||
<div class="loader-section section-right"></div>
|
||||
<div class="load_title">正在加载系统资源,请耐心等待</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
module.exports = {
|
||||
// jest 27 起默认环境由 jsdom 改为 node,组件测试需显式指定
|
||||
testEnvironment: 'jsdom',
|
||||
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
||||
transform: {
|
||||
'^.+\\.vue$': '@vue/vue3-jest',
|
||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
|
||||
'jest-transform-stub',
|
||||
'^.+\\.jsx?$': 'babel-jest'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1'
|
||||
},
|
||||
snapshotSerializers: ['jest-serializer-vue'],
|
||||
testMatch: [
|
||||
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
||||
],
|
||||
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
|
||||
coverageDirectory: '<rootDir>/tests/unit/coverage',
|
||||
// 'collectCoverage': true,
|
||||
'coverageReporters': [
|
||||
'lcov',
|
||||
'text-summary'
|
||||
],
|
||||
testURL: 'http://localhost/'
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"name": "go-admin",
|
||||
"version": "2.0.9",
|
||||
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
||||
"author": "https://github.com/wenjianzhang",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve",
|
||||
"build:prod": "vue-cli-service build",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"preview": "node build/index.js --preview",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
||||
"test:ci": "pnpm lint && pnpm test:unit",
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||
"new": "plop",
|
||||
"prepare": "husky || true"
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,vue}": [
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"admin",
|
||||
"go-admin",
|
||||
"go-admin-ui",
|
||||
"dashboard",
|
||||
"element-ui",
|
||||
"boilerplate",
|
||||
"admin-template",
|
||||
"management-system"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/go-admin-team/go-admin.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/go-admin-team/go-admin/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@tsparticles/slim": "^3.9.1",
|
||||
"@tsparticles/vue3": "^3.0.1",
|
||||
"@vueuse/core": "^14.4.0",
|
||||
"axios": "^1.19.0",
|
||||
"clipboard": "2.0.11",
|
||||
"codemirror": "^6.0.2",
|
||||
"core-js": "^3.50.0",
|
||||
"driver.js": "0.9.8",
|
||||
"dropzone": "5.9.3",
|
||||
"echarts": "^6.1.0",
|
||||
"element-plus": "^2.14.4",
|
||||
"file-saver": "2.0.5",
|
||||
"fuse.js": "6.6.2",
|
||||
"js-cookie": "3.0.8",
|
||||
"jszip": "3.10.1",
|
||||
"moment": "^2.30.1",
|
||||
"normalize.css": "8.0.1",
|
||||
"nprogress": "0.2.0",
|
||||
"path-to-regexp": "6.3.0",
|
||||
"remixicon": "^2.5.0",
|
||||
"sass-resources-loader": "^2.2.5",
|
||||
"screenfull": "5.2.0",
|
||||
"vue": "^3.5.41",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-count-to": "1.0.13",
|
||||
"vue-cropper": "^1.1.4",
|
||||
"vue-router": "^4.6.4",
|
||||
"vue3-dnd": "^2.1.0",
|
||||
"vue3-treeselect": "^0.1.10",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuex": "^4.1.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.28.3",
|
||||
"@babel/eslint-parser": "^7.29.7",
|
||||
"@babel/register": "^7.29.7",
|
||||
"@babel/runtime": "^7.29.7",
|
||||
"@playwright/test": "^1.62.1",
|
||||
"@vue/babel-plugin-jsx": "^1.5.0",
|
||||
"@vue/babel-preset-app": "^5.0.9",
|
||||
"@vue/cli-plugin-babel": "^5.0.9",
|
||||
"@vue/cli-plugin-eslint": "^5.0.9",
|
||||
"@vue/cli-plugin-unit-jest": "^5.0.9",
|
||||
"@vue/cli-service": "^5.0.9",
|
||||
"@vue/compiler-sfc": "^3.5.41",
|
||||
"@vue/test-utils": "^2.4.11",
|
||||
"@vue/vue3-jest": "^27.0.0",
|
||||
"autoprefixer": "^9.8.8",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "27.5.1",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"beautifier": "^0.1.7",
|
||||
"chalk": "4.1.2",
|
||||
"chokidar": "3.6.0",
|
||||
"compression-webpack-plugin": "^4.0.1",
|
||||
"connect": "3.7.0",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-plugin-vue": "^9.33.0",
|
||||
"html-webpack-plugin": "4.5.2",
|
||||
"husky": "9.1.7",
|
||||
"jest": "27.5.1",
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"jest-transform-stub": "^2.0.0",
|
||||
"lint-staged": "17.3.0",
|
||||
"mockjs": "1.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"plop": "2.7.6",
|
||||
"runjs": "^4.4.2",
|
||||
"sass": "^1.102.0",
|
||||
"sass-loader": "^13.3.3",
|
||||
"script-ext-html-webpack-plugin": "2.1.5",
|
||||
"script-loader": "0.7.2",
|
||||
"serve-static": "^1.16.3",
|
||||
"svg-sprite-loader": "^5.2.1",
|
||||
"svgo": "1.3.2"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.1",
|
||||
"engines": {
|
||||
"node": ">=22",
|
||||
"pnpm": ">=9"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e',
|
||||
timeout: 30_000,
|
||||
retries: 0,
|
||||
reporter: [['list']],
|
||||
use: {
|
||||
baseURL: 'http://localhost:9527',
|
||||
headless: true,
|
||||
screenshot: 'on',
|
||||
video: 'retain-on-failure',
|
||||
trace: 'retain-on-failure',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
{{#if template}}
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
{{/if}}
|
||||
|
||||
{{#if script}}
|
||||
<script>
|
||||
export default {
|
||||
name: '{{ properCase name }}',
|
||||
props: {},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
{{/if}}
|
||||
|
||||
{{#if style}}
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,55 @@
|
||||
const { notEmpty } = require('../utils.js')
|
||||
|
||||
module.exports = {
|
||||
description: 'generate vue component',
|
||||
prompts: [{
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: 'component name please',
|
||||
validate: notEmpty('name')
|
||||
},
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'blocks',
|
||||
message: 'Blocks:',
|
||||
choices: [{
|
||||
name: '<template>',
|
||||
value: 'template',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: '<script>',
|
||||
value: 'script',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'style',
|
||||
value: 'style',
|
||||
checked: true
|
||||
}
|
||||
],
|
||||
validate(value) {
|
||||
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
|
||||
return 'Components require at least a <script> or <template> tag.'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
],
|
||||
actions: data => {
|
||||
const name = '{{properCase name}}'
|
||||
const actions = [{
|
||||
type: 'add',
|
||||
path: `src/components/${name}/index.vue`,
|
||||
templateFile: 'plop-templates/component/index.hbs',
|
||||
data: {
|
||||
name: name,
|
||||
template: data.blocks.includes('template'),
|
||||
script: data.blocks.includes('script'),
|
||||
style: data.blocks.includes('style')
|
||||
}
|
||||
}]
|
||||
|
||||
return actions
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{#if state}}
|
||||
const state = {}
|
||||
{{/if}}
|
||||
|
||||
{{#if mutations}}
|
||||
const mutations = {}
|
||||
{{/if}}
|
||||
|
||||
{{#if actions}}
|
||||
const actions = {}
|
||||
{{/if}}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
{{options}}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
const { notEmpty } = require('../utils.js')
|
||||
|
||||
module.exports = {
|
||||
description: 'generate store',
|
||||
prompts: [{
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: 'store name please',
|
||||
validate: notEmpty('name')
|
||||
},
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'blocks',
|
||||
message: 'Blocks:',
|
||||
choices: [{
|
||||
name: 'state',
|
||||
value: 'state',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'mutations',
|
||||
value: 'mutations',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'actions',
|
||||
value: 'actions',
|
||||
checked: true
|
||||
}
|
||||
],
|
||||
validate(value) {
|
||||
if (!value.includes('state') || !value.includes('mutations')) {
|
||||
return 'store require at least state and mutations'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
],
|
||||
actions(data) {
|
||||
const name = '{{name}}'
|
||||
const { blocks } = data
|
||||
const options = ['state', 'mutations']
|
||||
const joinFlag = `,
|
||||
`
|
||||
if (blocks.length === 3) {
|
||||
options.push('actions')
|
||||
}
|
||||
|
||||
const actions = [{
|
||||
type: 'add',
|
||||
path: `src/store/modules/${name}.js`,
|
||||
templateFile: 'plop-templates/store/index.hbs',
|
||||
data: {
|
||||
options: options.join(joinFlag),
|
||||
state: blocks.includes('state'),
|
||||
mutations: blocks.includes('mutations'),
|
||||
actions: blocks.includes('actions')
|
||||
}
|
||||
}]
|
||||
return actions
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
exports.notEmpty = name => {
|
||||
return v => {
|
||||
if (!v || v.trim === '') {
|
||||
return `${name} is required`
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{{#if template}}
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
{{/if}}
|
||||
|
||||
{{#if script}}
|
||||
<script>
|
||||
export default {
|
||||
name: '{{ properCase name }}',
|
||||
props: {},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
{{/if}}
|
||||
|
||||
{{#if style}}
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,55 @@
|
||||
const { notEmpty } = require('../utils.js')
|
||||
|
||||
module.exports = {
|
||||
description: 'generate a view',
|
||||
prompts: [{
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: 'view name please',
|
||||
validate: notEmpty('name')
|
||||
},
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'blocks',
|
||||
message: 'Blocks:',
|
||||
choices: [{
|
||||
name: '<template>',
|
||||
value: 'template',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: '<script>',
|
||||
value: 'script',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'style',
|
||||
value: 'style',
|
||||
checked: true
|
||||
}
|
||||
],
|
||||
validate(value) {
|
||||
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
|
||||
return 'View require at least a <script> or <template> tag.'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
],
|
||||
actions: data => {
|
||||
const name = '{{name}}'
|
||||
const actions = [{
|
||||
type: 'add',
|
||||
path: `src/views/${name}/index.vue`,
|
||||
templateFile: 'plop-templates/view/index.hbs',
|
||||
data: {
|
||||
name: name,
|
||||
template: data.blocks.includes('template'),
|
||||
script: data.blocks.includes('script'),
|
||||
style: data.blocks.includes('style')
|
||||
}
|
||||
}]
|
||||
|
||||
return actions
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
const viewGenerator = require('./plop-templates/view/prompt')
|
||||
const componentGenerator = require('./plop-templates/component/prompt')
|
||||
const storeGenerator = require('./plop-templates/store/prompt.js')
|
||||
|
||||
module.exports = function(plop) {
|
||||
plop.setGenerator('view', viewGenerator)
|
||||
plop.setGenerator('component', componentGenerator)
|
||||
plop.setGenerator('store', storeGenerator)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,56 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://go-admin:8000/api;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection “”;
|
||||
proxy_connect_timeout 300s;
|
||||
proxy_send_timeout 900;
|
||||
proxy_read_timeout 900;
|
||||
proxy_buffer_size 32k;
|
||||
proxy_buffers 4 64k;
|
||||
proxy_busy_buffers_size 128k;
|
||||
proxy_redirect off;
|
||||
proxy_hide_header Vary;
|
||||
proxy_set_header Accept-Encoding '';
|
||||
proxy_set_header Referer $http_referer;
|
||||
proxy_set_header Cookie $http_cookie;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /login {
|
||||
proxy_pass http://go-admin:8000/login;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection “”;
|
||||
proxy_connect_timeout 300s;
|
||||
proxy_send_timeout 900;
|
||||
proxy_read_timeout 900;
|
||||
proxy_buffer_size 32k;
|
||||
proxy_buffers 4 64k;
|
||||
proxy_busy_buffers_size 128k;
|
||||
proxy_redirect off;
|
||||
proxy_hide_header Vary;
|
||||
proxy_set_header Accept-Encoding '';
|
||||
proxy_set_header Referer $http_referer;
|
||||
proxy_set_header Cookie $http_cookie;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: go-admin-ui
|
||||
labels:
|
||||
app: go-admin-ui
|
||||
service: go-admim-ui
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
name: http
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: go-admin-ui
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: go-admin-ui-v1
|
||||
labels:
|
||||
app: go-admin-ui
|
||||
version: v1
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: go-admin-ui
|
||||
version: v1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: go-admin-ui
|
||||
version: v1
|
||||
spec:
|
||||
containers:
|
||||
- name: go-admin-ui
|
||||
image: ${IMAGE}
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: frontendconf
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: frontendconf
|
||||
configMap:
|
||||
name: nginx-frontend
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
kubectl create ns go-admin
|
||||
kubectl create configmap nginx-frontend --from-file=./default.conf -n go-admin
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典数据列表
|
||||
export function listData(query) {
|
||||
return request({
|
||||
url: '/api/v1/dict/data?dictType=' + query.dictType,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典数据详细
|
||||
export function getData(dictCode) {
|
||||
return request({
|
||||
url: '/api/v1/dict/data/' + dictCode,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据字典类型查询字典数据信息
|
||||
export function getDicts(dictType) {
|
||||
return request({
|
||||
url: '/api/v1/dict-data/option-select?dictType=' + dictType,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典数据
|
||||
export function addData(data) {
|
||||
return request({
|
||||
url: '/api/v1/dict/data',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典数据
|
||||
export function updateData(data) {
|
||||
return request({
|
||||
url: '/api/v1/dict/data/' + data.dictCode,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典数据
|
||||
export function delData(dictCode) {
|
||||
return request({
|
||||
url: '/api/v1/dict/data',
|
||||
method: 'delete',
|
||||
data: dictCode
|
||||
})
|
||||
}
|
||||
|
||||
// 导出字典数据
|
||||
export function exportData(query) {
|
||||
return request({
|
||||
url: '/api/v1/dict/data/export',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典类型列表
|
||||
export function listType(query) {
|
||||
return request({
|
||||
url: '/api/v1/dict/type',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典类型详细
|
||||
export function getType(dictId) {
|
||||
return request({
|
||||
url: '/api/v1/dict/type/' + dictId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典类型
|
||||
export function addType(data) {
|
||||
return request({
|
||||
url: '/api/v1/dict/type',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典类型
|
||||
export function updateType(data) {
|
||||
return request({
|
||||
url: '/api/v1/dict/type/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典类型
|
||||
export function delType(dictId) {
|
||||
return request({
|
||||
url: '/api/v1/dict/type',
|
||||
method: 'delete',
|
||||
data: dictId
|
||||
})
|
||||
}
|
||||
|
||||
// 导出字典类型
|
||||
export function exportType(query) {
|
||||
return request({
|
||||
url: '/api/v1/dict/type/export',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 获取字典选择框列表
|
||||
export function optionselect() {
|
||||
return request({
|
||||
url: '/api/v1/dict/type-option-select',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询SysApi列表
|
||||
export function listSysApi(query) {
|
||||
return request({
|
||||
url: '/api/v1/sys-api',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询SysApi详细
|
||||
export function getSysApi(id) {
|
||||
return request({
|
||||
url: '/api/v1/sys-api/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增SysApi
|
||||
export function addSysApi(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-api',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改SysApi
|
||||
export function updateSysApi(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-api/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除SysApi
|
||||
export function delSysApi(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-api',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询参数列表
|
||||
export function listConfig(query) {
|
||||
return request({
|
||||
url: '/api/v1/config',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询参数详细
|
||||
export function getConfig(configId) {
|
||||
return request({
|
||||
url: '/api/v1/config/' + configId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据参数键名查询参数值
|
||||
export function getConfigKey(configKey) {
|
||||
return request({
|
||||
url: '/api/v1/configKey/' + configKey,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增参数配置
|
||||
export function addConfig(data) {
|
||||
return request({
|
||||
url: '/api/v1/config',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改参数配置
|
||||
export function updateConfig(data) {
|
||||
return request({
|
||||
url: '/api/v1/config/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除参数配置
|
||||
export function delConfig(data) {
|
||||
return request({
|
||||
url: '/api/v1/config',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function getSetConfig(query) {
|
||||
return request({
|
||||
url: '/api/v1/set-config',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function updateSetConfig(data) {
|
||||
return request({
|
||||
url: '/api/v1/set-config',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getDeptList(query) {
|
||||
return request({
|
||||
url: '/api/v1/dept',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询部门详细
|
||||
export function getDept(deptId) {
|
||||
return request({
|
||||
url: '/api/v1/dept/' + deptId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询部门下拉树结构
|
||||
export function treeselect() {
|
||||
return request({
|
||||
url: '/api/v1/deptTree',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据角色ID查询部门树结构
|
||||
export function roleDeptTreeselect(roleId) {
|
||||
return request({
|
||||
url: '/api/v1/roleDeptTreeselect/' + roleId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增部门
|
||||
export function addDept(data) {
|
||||
return request({
|
||||
url: '/api/v1/dept',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改部门
|
||||
export function updateDept(data, id) {
|
||||
return request({
|
||||
url: '/api/v1/dept/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除部门
|
||||
export function delDept(data) {
|
||||
return request({
|
||||
url: '/api/v1/dept',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询SysLoginlog列表
|
||||
export function listSysLoginlog(query) {
|
||||
return request({
|
||||
url: '/api/v1/sys-login-log',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询SysLoginlog详细
|
||||
export function getSysLoginlog(ID) {
|
||||
return request({
|
||||
url: '/api/v1/sys-login-log/' + ID,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 删除SysLoginlog
|
||||
export function delSysLoginlog(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-login-log',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询菜单列表
|
||||
export function listMenu(query) {
|
||||
return request({
|
||||
url: '/api/v1/menu',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询菜单详细
|
||||
export function getMenu(menuId) {
|
||||
return request({
|
||||
url: '/api/v1/menu/' + menuId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询菜单下拉树结构
|
||||
// export function treeselect() {
|
||||
// return request({
|
||||
// url: '/api/v1/menuTreeselect',
|
||||
// method: 'get'
|
||||
// })
|
||||
// }
|
||||
|
||||
// 根据角色ID查询菜单下拉树结构
|
||||
export function roleMenuTreeselect(roleId) {
|
||||
return request({
|
||||
url: '/api/v1/roleMenuTreeselect/' + roleId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增菜单
|
||||
export function addMenu(data) {
|
||||
return request({
|
||||
url: '/api/v1/menu',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改菜单
|
||||
export function updateMenu(data, id) {
|
||||
return request({
|
||||
url: '/api/v1/menu/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除菜单
|
||||
export function delMenu(data) {
|
||||
return request({
|
||||
url: '/api/v1/menu',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 清空操作日志
|
||||
export function cleanOperlog() {
|
||||
return request({
|
||||
url: '/api/v1/operlog/clean',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询SysOperlog列表
|
||||
export function listSysOperlog(query) {
|
||||
return request({
|
||||
url: '/api/v1/sys-opera-log',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 删除SysOperlog
|
||||
export function delSysOperlog(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-opera-log',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询岗位列表
|
||||
export function listPost(query) {
|
||||
return request({
|
||||
url: '/api/v1/post',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询岗位详细
|
||||
export function getPost(postId) {
|
||||
return request({
|
||||
url: '/api/v1/post/' + postId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增岗位
|
||||
export function addPost(data) {
|
||||
return request({
|
||||
url: '/api/v1/post',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改岗位
|
||||
export function updatePost(data, id) {
|
||||
return request({
|
||||
url: '/api/v1/post/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除岗位
|
||||
export function delPost(postId) {
|
||||
return request({
|
||||
url: '/api/v1/post',
|
||||
method: 'delete',
|
||||
data: postId
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询角色列表
|
||||
export function listRole(query) {
|
||||
return request({
|
||||
url: '/api/v1/role',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询角色详细
|
||||
export function getRole(roleId) {
|
||||
return request({
|
||||
url: '/api/v1/role/' + roleId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增角色
|
||||
export function addRole(data) {
|
||||
return request({
|
||||
url: '/api/v1/role',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改角色
|
||||
export function updateRole(data, roleId) {
|
||||
return request({
|
||||
url: '/api/v1/role/' + roleId,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 角色数据权限
|
||||
export function dataScope(data) {
|
||||
return request({
|
||||
url: '/api/v1/roledatascope',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 角色状态修改
|
||||
export function changeRoleStatus(roleId, status) {
|
||||
const data = {
|
||||
roleId,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: '/api/v1/role-status',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除角色
|
||||
export function delRole(roleId) {
|
||||
return request({
|
||||
url: '/api/v1/role',
|
||||
method: 'delete',
|
||||
data: roleId
|
||||
})
|
||||
}
|
||||
|
||||
export function getListrole(id) {
|
||||
return request({
|
||||
url: '/api/v1/menu/role/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getRoutes() {
|
||||
return request({
|
||||
url: '/api/v1/menurole',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// export function getMenuNames() {
|
||||
// return request({
|
||||
// url: '/api/v1/menuids',
|
||||
// method: 'get'
|
||||
// })
|
||||
// }
|
||||
@@ -0,0 +1,135 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询用户列表
|
||||
export function listUser(query) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询用户详细
|
||||
export function getUser(userId) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user/' + userId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getUserInit() {
|
||||
return request({
|
||||
url: '/api/v1/sys-user/',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增用户
|
||||
export function addUser(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改用户
|
||||
export function updateUser(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
export function delUser(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 导出用户
|
||||
export function exportUser(query) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user/export',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 用户密码重置
|
||||
export function resetUserPwd(userId, password) {
|
||||
const data = {
|
||||
userId,
|
||||
password
|
||||
}
|
||||
return request({
|
||||
url: '/api/v1/user/pwd/reset',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 用户状态修改
|
||||
export function changeUserStatus(e) {
|
||||
const data = {
|
||||
userId: e.userId,
|
||||
status: e.status
|
||||
}
|
||||
return request({
|
||||
url: '/api/v1/user/status',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改用户个人信息
|
||||
export function updateUserProfile(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys-user/profile',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 下载用户导入模板
|
||||
export function importTemplate() {
|
||||
return request({
|
||||
url: '/api/v1/sys-user/importTemplate',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 用户密码重置
|
||||
export function updateUserPwd(oldPassword, newPassword) {
|
||||
const data = {
|
||||
oldPassword,
|
||||
newPassword
|
||||
}
|
||||
return request({
|
||||
url: '/api/v1/user/pwd/set',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 用户头像上传
|
||||
export function uploadAvatar(data) {
|
||||
return request({
|
||||
url: '/api/v1/user/avatar',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询用户个人信息
|
||||
export function getUserProfile() {
|
||||
return request({
|
||||
url: '/api/v1/user/profile',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询SysJob列表
|
||||
export function listSysJob(query) {
|
||||
return request({
|
||||
url: '/api/v1/sysjob',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询SysJob详细
|
||||
export function getSysJob(jobId) {
|
||||
return request({
|
||||
url: '/api/v1/sysjob/' + jobId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增SysJob
|
||||
export function addSysJob(data) {
|
||||
return request({
|
||||
url: '/api/v1/sysjob',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改SysJob
|
||||
export function updateSysJob(data) {
|
||||
return request({
|
||||
url: '/api/v1/sysjob',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除SysJob
|
||||
export function delSysJob(data) {
|
||||
return request({
|
||||
url: '/api/v1/sysjob',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 移除SysJob
|
||||
export function removeJob(jobId) {
|
||||
return request({
|
||||
url: '/api/v1/job/remove/' + jobId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 启动SysJob
|
||||
export function startJob(jobId) {
|
||||
return request({
|
||||
url: '/api/v1/job/start/' + jobId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取验证码
|
||||
export function getCodeImg() {
|
||||
return request({
|
||||
url: '/api/v1/captcha',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询 此接口不在验证数据权限
|
||||
export function getSetting() {
|
||||
return request({
|
||||
url: '/api/v1/app-config',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询服务器详细
|
||||
export function getServer() {
|
||||
return request({
|
||||
url: '/api/v1/server-monitor',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function searchUser(name) {
|
||||
return request({
|
||||
url: '/search/user',
|
||||
method: 'get',
|
||||
params: { name }
|
||||
})
|
||||
}
|
||||
|
||||
export function transactionList(query) {
|
||||
return request({
|
||||
url: '/transaction/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function list(data) {
|
||||
return request({
|
||||
url: 'api/v1/schedule/list',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export function add(data) {
|
||||
return request({
|
||||
url: 'api/v1/schedule/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function edit(data) {
|
||||
return request({
|
||||
url: 'api/v1/schedule/update',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function getSchedule(id) {
|
||||
return request({
|
||||
url: 'api/v1/schedule/query',
|
||||
method: 'get',
|
||||
params: {
|
||||
id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteSchedule(data) {
|
||||
return request({
|
||||
url: 'api/v1/schedule/delete',
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// 查询列表
|
||||
export function getItems(f, query) {
|
||||
query = query || { pageSize: 10000 }
|
||||
return f(query)
|
||||
}
|
||||
|
||||
export function setItems(response, k, v) {
|
||||
const data = []
|
||||
k = k || 'id'
|
||||
v = v || 'name'
|
||||
if (response.data && response.data.list && response.data.list.length > 0) {
|
||||
response.data.list.forEach(e => {
|
||||
data.push({
|
||||
key: e[k].toString(),
|
||||
value: e[v].toString()
|
||||
})
|
||||
})
|
||||
return data
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询生成表数据
|
||||
export function listTable(query) {
|
||||
return request({
|
||||
url: '/api/v1/sys/tables/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询db数据库列表
|
||||
export function listDbTable(query) {
|
||||
return request({
|
||||
url: '/api/v1/db/tables/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询表详细信息
|
||||
export function getGenTable(tableId) {
|
||||
return request({
|
||||
url: '/api/v1/sys/tables/info/' + tableId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getGenTableInfo(tablename) {
|
||||
return request({
|
||||
url: '/api/v1/sys/tables?tableName=' + tablename,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 修改代码生成信息
|
||||
export function updateGenTable(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys/tables/info',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 导入表
|
||||
export function importTable(data) {
|
||||
return request({
|
||||
url: '/api/v1/sys/tables/info',
|
||||
method: 'post',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 预览生成代码
|
||||
export function previewTable(tableId) {
|
||||
return request({
|
||||
url: '/api/v1/gen/preview/' + tableId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// 删除表数据
|
||||
export function delTable(tableId) {
|
||||
return request({
|
||||
url: '/api/v1/sys/tables/info/' + tableId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 生成代码到项目
|
||||
export function toProjectTable(tableId) {
|
||||
return request({
|
||||
url: '/api/v1/gen/toproject/' + tableId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 生成接口数据到迁移脚本
|
||||
export function apiToFile(tableId) {
|
||||
return request({
|
||||
url: '/api/v1/gen/apitofile/' + tableId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function toProjectTableCheckRole(tableId, ischeckrole) {
|
||||
return request({
|
||||
url: '/api/v1/gen/toproject/' + tableId + '?ischeckrole=' + ischeckrole,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 生成菜单到数据库
|
||||
export function toDBTable(tableId) {
|
||||
return request({
|
||||
url: '/api/v1/gen/todb/' + tableId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getTableTree() {
|
||||
return request({
|
||||
url: '/api/v1/gen/tabletree',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// login 登陆
|
||||
export function login(data) {
|
||||
return request({
|
||||
url: '/api/v1/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// logout 退出
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/api/v1/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// refreshtoken 刷新token
|
||||
export function refreshtoken(data) {
|
||||
return request({
|
||||
url: '/refreshtoken',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// getInfo 获取用户基本信息
|
||||
export function getInfo() {
|
||||
return request({
|
||||
url: '/api/v1/getinfo',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询SysJob列表
|
||||
export function unWsLogout(id, group) {
|
||||
return request({
|
||||
url: '/wslogout/' + id + '/' + group,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||
<feMerge>
|
||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
|
||||
<g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
|
||||
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
|
||||
<mask id="mask-3" fill="white">
|
||||
<use xlink:href="#path-2"></use>
|
||||
</mask>
|
||||
<g id="Rectangle-18">
|
||||
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||
</g>
|
||||
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
||||
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 16 KiB |