├── .eslintrc.js
├── .gitignore
├── LICENSE
├── README.md
├── babel.config.js
├── img
├── dash.png
├── login.png
└── logo.jpg
├── package.json
├── public
├── icon.png
└── index.html
├── src
├── apis
│ ├── auditApis.ts
│ ├── autoTaskApis.ts
│ ├── changePasswordApis.ts
│ ├── commonApis.ts
│ ├── dashApis.ts
│ ├── dbApis.ts
│ ├── groupApis.ts
│ ├── loginApis.ts
│ ├── personalApis.ts
│ ├── queryApis.ts
│ ├── rolesApis.ts
│ ├── settingApis.ts
│ ├── tplApis.ts
│ └── userApis.ts
├── assets
│ ├── alipay.jpg
│ ├── circle.svg
│ ├── groud.mp4
│ ├── groud.png
│ ├── logo.png
│ ├── logo_s.png
│ ├── tpl.svg
│ └── wechat.jpg
├── components
│ ├── breadcrumbNav.vue
│ ├── countUp.vue
│ ├── customForm
│ │ └── customForm.vue
│ ├── editor.vue
│ ├── expandTable.vue
│ ├── identify.vue
│ ├── inforCard.vue
│ ├── locking-page.vue
│ ├── modal
│ │ ├── changePassword.vue
│ │ ├── editProfile.vue
│ │ └── rulesLimits.vue
│ ├── order
│ │ ├── orderConfirm.vue
│ │ ├── orderForm.vue
│ │ ├── orderFormContainer.vue
│ │ ├── orderIsPost.vue
│ │ ├── orderSQLs.vue
│ │ └── orderSteps.vue
│ ├── profile
│ │ ├── basic.vue
│ │ ├── collapse.vue
│ │ ├── postForm.vue
│ │ ├── profile.vue
│ │ ├── queryProfile.vue
│ │ ├── stepDetail.vue
│ │ └── testing.vue
│ ├── search
│ │ ├── navSearch.vue
│ │ └── search.vue
│ ├── sidebarMenu.vue
│ ├── tabQuery.vue
│ └── unlock.vue
├── framework.vue
├── interface
│ ├── index.ts
│ └── render.ts
├── language
│ ├── en-us.json
│ ├── index.ts
│ └── zh-cn.json
├── libs
│ ├── libs.ts
│ └── requests.ts
├── main.ts
├── main.vue
├── mixins
│ ├── basic.ts
│ ├── fetch.ts
│ ├── order.ts
│ ├── orderProfile.ts
│ └── query.ts
├── router.ts
├── shims-vue.d.ts
├── store
│ ├── index.ts
│ └── modules
│ │ ├── general.ts
│ │ ├── init_args.ts
│ │ ├── order.ts
│ │ ├── search.ts
│ │ ├── user.ts
│ │ └── verify.ts
├── styles
│ ├── common.css
│ ├── common.less
│ ├── infor-card.css
│ ├── infor-card.less
│ ├── main.less
│ ├── table.css
│ ├── table.less
│ ├── theme.less
│ ├── unlock.css
│ └── unlock.less
└── views
│ ├── audit
│ ├── order
│ │ ├── audit.vue
│ │ ├── osc.vue
│ │ └── reject.vue
│ └── query
│ │ └── audit.vue
│ ├── board.vue
│ ├── home
│ ├── home.vue
│ ├── orderChart.vue
│ └── sourcePie.vue
│ ├── login
│ ├── login.vue
│ └── render.ts
│ ├── manage
│ ├── autoTask
│ │ └── autoTask.vue
│ ├── db
│ │ └── db.vue
│ ├── flow
│ │ └── flow.vue
│ ├── group
│ │ ├── allCheck.vue
│ │ └── roleGroup.vue
│ ├── role
│ │ ├── role.vue
│ │ └── role_args.ts
│ ├── settings
│ │ └── setting.vue
│ └── user
│ │ ├── types.ts
│ │ └── user.vue
│ ├── order
│ ├── basicList.vue
│ ├── myOrder.vue
│ └── order.vue
│ ├── personal
│ └── personal.vue
│ ├── query
│ ├── multiSource.vue
│ ├── querySql.vue
│ ├── refer.vue
│ └── workFlow.vue
│ └── records
│ ├── order.vue
│ └── query.vue
├── tsconfig.json
└── vue.config.js
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended',
9 | '@vue/typescript'
10 | ],
11 | rules: {
12 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
13 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
14 | "vue/no-parsing-error": [2, { "x-invalid-end-tag": false }],
15 | "no-unused-vars": 'off',
16 | },
17 | parserOptions: {
18 | parser: '@typescript-eslint/parser'
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 | package-lock.json
23 |
24 | #Electron-builder output
25 | /dist_electron
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Gemini
6 | ### Yearning Web Pages Farmwork
7 | 
8 | 
9 | 
10 | 
11 |
12 | ## Feature
13 | Mysql SQL语句审核平台 Yearning 前端页面代码
14 |
15 | ## Website
16 | [www.yearning.io](http://yearning.io)
17 |
18 | ## Snapshot
19 |
20 | 
21 |
22 | 
23 |
24 | ## License
25 |
26 | - AGPL v3
27 |
28 | 任何二次开发及二次开源项目请严格遵守相应开源许可
29 |
30 | 2019 © Henry Yee
31 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/img/dash.png
--------------------------------------------------------------------------------
/img/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/img/login.png
--------------------------------------------------------------------------------
/img/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/img/logo.jpg
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yearning",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^2.6.5",
12 | "countup": "^1.8.2",
13 | "mavon-editor": "^2.7.7",
14 | "vue": "^2.6.13",
15 | "vue-monoplasty-slide-verify": "^1.1.3",
16 | "vuex-class": "^0.3.2"
17 | },
18 | "devDependencies": {
19 | "@antv/g2": "^4.1.17",
20 | "@types/sql-formatter": "^2.3.0",
21 | "@typescript-eslint/eslint-plugin": "^2.24.0",
22 | "@typescript-eslint/parser": "^2.24.0",
23 | "@vue/cli-plugin-babel": "^3.9.0",
24 | "@vue/cli-plugin-eslint": "^3.9.0",
25 | "@vue/cli-plugin-typescript": "^4.2.3",
26 | "@vue/cli-service": "^3.9.0",
27 | "@vue/eslint-config-typescript": "^5.0.2",
28 | "axios": "^0.21.1",
29 | "babel-eslint": "^10.0.1",
30 | "brace": "^0.11.0",
31 | "compression-webpack-plugin": "^3.1.0",
32 | "css-loader": "^3.0.0",
33 | "emmet": "git+https://github.com/cloud9ide/emmet-core.git",
34 | "eslint": "^5.16.0",
35 | "eslint-plugin-vue": "^5.0.0",
36 | "html2canvas": "^1.0.0-rc.5",
37 | "image-webpack-loader": "^6.0.0",
38 | "less": "^3.9.0",
39 | "less-loader": "^5.0.0",
40 | "particles.js": "^2.0.0",
41 | "sql-formatter": "^2.3.3",
42 | "terser-webpack-plugin": "^5.1.3",
43 | "typescript": "^3.8.3",
44 | "view-design": "^4.5.0",
45 | "vue-i18n": "^8.18.2",
46 | "vue-property-decorator": "^8.4.1",
47 | "vue-router": "^3.0.7",
48 | "vue-template-compiler": "^2.6.13",
49 | "vue-ts-locale": "^1.0.2",
50 | "vuex": "^3.1.1",
51 | "vuex-along": "^1.2.11",
52 | "vuex-module-decorators": "^0.17.0"
53 | },
54 | "eslintConfig": {
55 | "root": true,
56 | "env": {
57 | "node": true
58 | },
59 | "extends": [
60 | "plugin:vue/essential",
61 | "eslint:recommended"
62 | ],
63 | "rules": {
64 | "vue/no-parsing-error": [
65 | 2,
66 | {
67 | "x-invalid-end-tag": false
68 | }
69 | ]
70 | },
71 | "parserOptions": {
72 | "parser": "babel-eslint"
73 | }
74 | },
75 | "postcss": {
76 | "plugins": {
77 | "autoprefixer": {}
78 | }
79 | },
80 | "browserslist": [
81 | "> 1%",
82 | "last 2 versions"
83 | ]
84 | }
85 |
--------------------------------------------------------------------------------
/public/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/public/icon.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Yearning
6 |
7 |
8 |
9 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/apis/auditApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 |
4 | const AuditCommonPath = {
5 | admin: `${libs.url}/audit/order`,
6 | }
7 |
8 | interface SQLAuditOrder {
9 | work_id: string;
10 | perform?: string;
11 | flag?: number;
12 | tp?: string;
13 | text?: string;
14 | }
15 |
16 | export function AuditTestSQL(args: SQLAuditOrder) {
17 | return request({
18 | method: 'post',
19 | url: `${AuditCommonPath.admin}/test`,
20 | data: args
21 | })
22 | }
23 |
24 |
25 | export function AuditExecuteSQL(args: SQLAuditOrder) {
26 | return request({
27 | method: 'post',
28 | url: `${AuditCommonPath.admin}/execute`,
29 | data: args
30 | })
31 | }
32 |
33 | export function AuditStateSQL(args: SQLAuditOrder) {
34 | return request({
35 | method: 'post',
36 | url: `${AuditCommonPath.admin}/state`,
37 | data: args
38 | })
39 | }
40 |
41 | export function AuditKillOrder(args: SQLAuditOrder) {
42 | return request({
43 | method: 'post',
44 | url: `${AuditCommonPath.admin}/kill`,
45 | data: args
46 | })
47 | }
48 |
--------------------------------------------------------------------------------
/src/apis/autoTaskApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 |
4 | const AutoTaskCommonPath = {
5 | basic: `${libs.url}/manage/task`,
6 | }
7 |
8 |
9 | interface task {
10 | id?: number;
11 | name?: string;
12 | source?: string;
13 | data_base?: string;
14 | table?: string;
15 | tp?: number;
16 | affect_rows?: number
17 | status?: number
18 | }
19 |
20 | interface AutoTaskExplorer {
21 | tp: string // 类型flag
22 | task: task
23 | }
24 |
25 | interface AutoTaskFinder {
26 | page: number,
27 | find: any
28 | }
29 |
30 | export function AutoTaskCreateOrEditApi(args: AutoTaskExplorer) {
31 | return request({
32 | method: 'post',
33 | data: args,
34 | url: AutoTaskCommonPath.basic
35 | })
36 | }
37 |
38 | export function AutoTaskFetchApi(args: AutoTaskFinder) {
39 | return request({
40 | method: 'put',
41 | data: args,
42 | url: AutoTaskCommonPath.basic
43 | })
44 | }
45 |
46 | export function AutoTaskDeleteApi(args: number) {
47 | return request({
48 | method: 'delete',
49 | params: {
50 | id: args
51 | },
52 | url: AutoTaskCommonPath.basic
53 | })
54 | }
--------------------------------------------------------------------------------
/src/apis/changePasswordApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 |
4 | const PasswordCommonPath = {
5 | admin: `${libs.url}/manage/user`,
6 | common: `${libs.url}/common/edit`
7 | }
8 |
9 | interface Password {
10 | username: string;
11 | password: string;
12 | tp?: string
13 | }
14 |
15 | export function AdminChangePassword(args: Password) {
16 | return request({
17 | method: 'post',
18 | data: {
19 | tp: 'password',
20 | user: args
21 | },
22 | url: PasswordCommonPath.admin
23 | })
24 | }
25 |
26 | export function CommonChangePassword(args: Password) {
27 | return request({
28 | method: 'put',
29 | data: args,
30 | params: {tp: 'password'},
31 | url: PasswordCommonPath.common
32 | })
33 | }
--------------------------------------------------------------------------------
/src/apis/commonApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 |
4 | const CommonPath = {
5 | base: `${libs.url}/fetch`,
6 | post: `${libs.url}/common/post`
7 | }
8 |
9 |
10 | export interface CommonFetch {
11 | work_id?: string;
12 | idc?: string;
13 | tp?: string;
14 | source?: string;
15 | data_base?: string;
16 | table?: string;
17 | limit?: string;
18 | status?: number;
19 | page?: number;
20 | sql?: string;
21 | title?: string;
22 | is_dml?: boolean;
23 | }
24 |
25 | export function FetchCommonGetApis(tp: string, args: CommonFetch) {
26 | return request({
27 | method: 'get',
28 | url: `${CommonPath.base}/${tp}`,
29 | params: args
30 | })
31 | }
32 |
33 | export function PostOrder(args: any) {
34 | return request({
35 | method: 'post',
36 | url: CommonPath.post,
37 | data: args
38 | })
39 | }
40 |
41 | export function FetchCommonPutApis(tp: string, args: any) {
42 | return request({
43 | method: 'put',
44 | url: `${CommonPath.base}/${tp}`,
45 | data: args
46 | })
47 | }
48 |
49 | export function FetchCommonPostApis(tp: string, args: any) {
50 | return request({
51 | method: 'post',
52 | url: `${CommonPath.base}/${tp}`,
53 | data: args
54 | })
55 | }
56 |
57 | export function FetchCommonDeleteApis(tp: string) {
58 | return request({
59 | method: 'delete',
60 | url: `${CommonPath.base}/${tp}`,
61 | })
62 | }
--------------------------------------------------------------------------------
/src/apis/dashApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {order} from "@/interface";
4 |
5 | const DashCommonPath = {
6 | base: `${libs.url}/dash`
7 | }
8 |
9 | export function DashPutApi(tp: string) {
10 | return request({
11 | method: 'put',
12 | url: `${DashCommonPath.base}/${tp}`,
13 | })
14 | }
15 |
16 | export function DashGetApi(tp: string) {
17 | return request({
18 | method: 'get',
19 | url: `${DashCommonPath.base}/${tp}`,
20 | })
21 | }
--------------------------------------------------------------------------------
/src/apis/dbApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 |
4 | const DBCommonPath = {
5 | basic: `${libs.url}/manage/db`,
6 | }
7 |
8 | export interface DB {
9 | idc: string,
10 | source: string,
11 | ip: string,
12 | port: number,
13 | username: string,
14 | password: string,
15 | is_query: number
16 | }
17 |
18 | interface DBExplorer {
19 | tp: string // 类型flag
20 | db: DB
21 | }
22 |
23 | interface DBFinder {
24 | page: number,
25 | find: any
26 | }
27 |
28 | export function DBFetchApi(args: DBFinder) {
29 | return request({
30 | method: 'put',
31 | data: args,
32 | url: DBCommonPath.basic
33 | })
34 | }
35 |
36 | export function DBDeleteApi(args: string) {
37 | return request({
38 | method: 'delete',
39 | params: {
40 | source: args
41 | },
42 | url: DBCommonPath.basic
43 | })
44 | }
45 |
46 | export function DBCreateOrEditApi(args: DBExplorer) {
47 | return request({
48 | method: 'post',
49 | data: args,
50 | url: DBCommonPath.basic
51 | })
52 | }
--------------------------------------------------------------------------------
/src/apis/groupApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {Permission} from "@/interface";
4 |
5 | const GroupCommonPath = {
6 | basic: `${libs.url}/manage/group`,
7 | }
8 |
9 |
10 | interface group {
11 | permission?: Permission
12 | username?: string
13 | tp?: number
14 | group?: string | string[]
15 | }
16 |
17 | export function GroupCreateOrEditApi(args: group) {
18 | return request({
19 | method: 'post',
20 | data: args,
21 | url: GroupCommonPath.basic
22 | })
23 | }
24 |
25 | export function GroupFetchApi(args: group) {
26 | return request({
27 | method: 'get',
28 | params: args,
29 | url: GroupCommonPath.basic
30 | })
31 | }
32 |
33 | export function GroupDeleteApi(args: string) {
34 | return request({
35 | method: 'delete',
36 | params: {
37 | clear: args
38 | },
39 | url: GroupCommonPath.basic
40 | })
41 | }
--------------------------------------------------------------------------------
/src/apis/loginApis.ts:
--------------------------------------------------------------------------------
1 | import {request} from "@/libs/requests";
2 |
3 |
4 | const LoginCommonPath = {
5 | basic: '/login',
6 | ldap: '/ldap'
7 | }
8 |
9 |
10 | interface LoginForm {
11 | username: string;
12 | password: string;
13 | }
14 |
15 |
16 | export function LoginApi(isLdap: boolean, args: LoginForm) {
17 | return request({
18 | url: isLdap ? LoginCommonPath.ldap : LoginCommonPath.basic,
19 | method: "post",
20 | data: args
21 | })
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/apis/personalApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 |
4 | const PasswordCommonPath = {
5 | common: `${libs.url}/common/edit`
6 | }
7 |
8 | interface Mail {
9 | email: string;
10 | real_name: string
11 | }
12 |
13 | export function CommonChangeEmail(args: Mail) {
14 | return request({
15 | method: 'put',
16 | data: args,
17 | params: {tp: 'mail'},
18 | url: PasswordCommonPath.common
19 | })
20 | }
--------------------------------------------------------------------------------
/src/apis/queryApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {order} from "@/interface";
4 |
5 | const AuditCommonPath = {
6 | admin: `${libs.url}/audit/query`,
7 | base: `${libs.url}/query`
8 | }
9 |
10 | interface QueryOrderProfile {
11 | work_id?: string;
12 | page?: number;
13 | tp?: string;
14 | title?: string;
15 | source?: string;
16 | data_base?: string;
17 | table?: string;
18 | }
19 |
20 | export function FetchAuditQueryProfile(args: QueryOrderProfile) {
21 | return request({
22 | method: 'put',
23 | url: `${AuditCommonPath.admin}/profile`,
24 | data: args
25 | })
26 | }
27 |
28 | export function DeleteEmptyAuditQuery() {
29 | return request({
30 | method: 'delete',
31 | url: `${AuditCommonPath.admin}/clear`,
32 | })
33 | }
34 |
35 | export function ChangeAuditQueryState(args: QueryOrderProfile) {
36 | return request({
37 | method: 'post',
38 | url: `${AuditCommonPath.admin}/state`,
39 | data: args
40 | })
41 | }
42 |
43 | export function CommonGetApis(tp: string, args: QueryOrderProfile) {
44 | return request({
45 | method: 'get',
46 | url: `${AuditCommonPath.base}/${tp}`,
47 | params: args
48 | })
49 | }
50 |
51 | export function CommonDeleteApis(tp: string) {
52 | return request({
53 | method: 'delete',
54 | url: `${AuditCommonPath.base}/${tp}`,
55 | })
56 | }
57 |
58 | export function CommonPutApis(tp: string, args: any) {
59 | return request({
60 | method: 'put',
61 | url: `${AuditCommonPath.base}/${tp}`,
62 | data: args
63 | })
64 | }
65 |
66 | export function CommonPostApis(tp: string, args: order) {
67 | return request({
68 | method: 'post',
69 | url: `${AuditCommonPath.base}/${tp}`,
70 | data: args
71 | })
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/apis/rolesApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {Permission} from "@/interface";
4 |
5 | const RolesCommonPath = {
6 | basic: `${libs.url}/manage/roles`,
7 | }
8 |
9 | export function RolesCreateOrEditApi(args: any) {
10 | return request({
11 | method: 'post',
12 | data: args,
13 | url: RolesCommonPath.basic
14 | })
15 | }
16 |
17 | export function RolesFetchApi() {
18 | return request({
19 | method: 'put',
20 | url: RolesCommonPath.basic
21 | })
22 | }
--------------------------------------------------------------------------------
/src/apis/settingApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {message_modal, other_modal, Permission} from "@/interface";
4 |
5 | const SettingCommonPath = {
6 | basic: `${libs.url}/manage/setting`,
7 | }
8 |
9 | interface settings {
10 | ldap?: any;
11 | message?: message_modal;
12 | other?: other_modal;
13 | date?: string;
14 | tp?: boolean;
15 | }
16 |
17 | export function SettingCreateOrEditApi(args: settings) {
18 | return request({
19 | method: 'post',
20 | data: args,
21 | url: SettingCommonPath.basic
22 | })
23 | }
24 |
25 | export function SettingFetchApi() {
26 | return request({
27 | method: 'get',
28 | url: SettingCommonPath.basic
29 | })
30 | }
31 |
32 | export function SettingMessageTestApi(tp: string, args: message_modal) {
33 | return request({
34 | method: 'put',
35 | url: SettingCommonPath.basic,
36 | data: {
37 | mail:args
38 | },
39 | params: {
40 | test: tp
41 | }
42 | })
43 | }
44 |
45 | export function SettingLDAPTestApi(args: any) {
46 | return request({
47 | method: 'put',
48 | url: SettingCommonPath.basic,
49 | data: {
50 | ldap:args
51 | },
52 | params: {
53 | test: 'ldap'
54 | }
55 | })
56 | }
57 |
58 | export function SettingDeleteTestApi(args: settings) {
59 | return request({
60 | method: 'delete',
61 | url: SettingCommonPath.basic,
62 | params: args
63 | })
64 | }
--------------------------------------------------------------------------------
/src/apis/tplApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {TplOrder} from "@/interface";
4 |
5 | const TplCommonPath = {
6 | basic: `${libs.url}/manage/tpl`,
7 | }
8 |
9 | export interface Tpl {
10 | steps: TplOrder[];
11 | source: string;
12 | }
13 |
14 | export function TplAllSourceFetchApi() {
15 | return request({
16 | method: 'get',
17 | url: TplCommonPath.basic
18 | })
19 | }
20 |
21 | export function TplFetchProfile(args: string) {
22 | return request({
23 | method: 'put',
24 | params: {
25 | source: args
26 | },
27 | url: TplCommonPath.basic
28 | })
29 | }
30 |
31 | export function TplCreateOrEditApi(args:Tpl) {
32 | return request({
33 | method: 'post',
34 | data: args,
35 | url: TplCommonPath.basic
36 | })
37 | }
--------------------------------------------------------------------------------
/src/apis/userApis.ts:
--------------------------------------------------------------------------------
1 | import libs from "@/libs/libs";
2 | import {request} from "@/libs/requests";
3 | import {CommonFinder} from "@/interface";
4 |
5 | const UserCommonPath = {
6 | basic: `${libs.url}/manage/user`,
7 | }
8 |
9 | interface User {
10 | username: string
11 | password: string
12 | department: string
13 | real_name: string
14 | rule: string
15 | email: string
16 | }
17 |
18 | interface UserExplorer {
19 | tp?: string // 类型flag
20 | user?: User
21 | }
22 |
23 |
24 | export function UserFetchApi(args: CommonFinder) {
25 | return request({
26 | method: 'put',
27 | data: args,
28 | url: UserCommonPath.basic
29 | })
30 | }
31 |
32 | export function UserCreateOrEditApi(args: UserExplorer) {
33 | return request({
34 | method: 'post',
35 | data: args,
36 | url: UserCommonPath.basic
37 | })
38 | }
39 |
40 | export function UserDependGetApi(args: { user: string, tp: string }) {
41 | return request({
42 | method: 'get',
43 | params: args,
44 | url: UserCommonPath.basic
45 | })
46 | }
47 |
48 | export function UserDeleteApi(args: string) {
49 | return request({
50 | method: 'delete',
51 | params: {user: args},
52 | url: UserCommonPath.basic
53 | })
54 | }
--------------------------------------------------------------------------------
/src/assets/alipay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/src/assets/alipay.jpg
--------------------------------------------------------------------------------
/src/assets/circle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
24 |
--------------------------------------------------------------------------------
/src/assets/groud.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/src/assets/groud.mp4
--------------------------------------------------------------------------------
/src/assets/groud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/src/assets/groud.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/logo_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/src/assets/logo_s.png
--------------------------------------------------------------------------------
/src/assets/tpl.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/wechat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookieY/Yearning-gemini/cebb6590b562361489f35e7681898fa88bd3eb8f/src/assets/wechat.jpg
--------------------------------------------------------------------------------
/src/components/breadcrumbNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{item.title}}
4 |
5 |
6 |
7 |
8 |
19 |
--------------------------------------------------------------------------------
/src/components/countUp.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
{{ startVal }}{{ unit }}
11 |
12 |
13 |
14 |
15 |
108 |
--------------------------------------------------------------------------------
/src/components/customForm/customForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
18 |
19 |
20 |
65 |
66 |
--------------------------------------------------------------------------------
/src/components/editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
82 |
--------------------------------------------------------------------------------
/src/components/expandTable.vue:
--------------------------------------------------------------------------------
1 |
2 | {{row}}
3 |
4 |
5 |
18 |
19 |
22 |
--------------------------------------------------------------------------------
/src/components/inforCard.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
35 |
--------------------------------------------------------------------------------
/src/components/locking-page.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
39 |
--------------------------------------------------------------------------------
/src/components/modal/changePassword.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ $t('general.change_password') }}
4 |
16 |
17 |
18 |
19 |
138 |
139 |
142 |
--------------------------------------------------------------------------------
/src/components/modal/editProfile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 用户信息
4 |
32 |
33 |
34 |
35 |
77 |
78 |
81 |
--------------------------------------------------------------------------------
/src/components/modal/rulesLimits.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 用户权限
4 |
26 |
27 |
28 |
29 |
94 |
--------------------------------------------------------------------------------
/src/components/order/orderConfirm.vue:
--------------------------------------------------------------------------------
1 |
2 |
58 |
59 |
60 |
71 |
72 |
75 |
--------------------------------------------------------------------------------
/src/components/order/orderForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
108 |
109 | >
121 |
--------------------------------------------------------------------------------
/src/components/order/orderFormContainer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
42 |
43 |
--------------------------------------------------------------------------------
/src/components/order/orderIsPost.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 | 工单已提交
18 |
19 |
20 |
21 | 如有疑问请联系相关审核人/管理员
22 |
23 | 如填写错误请前往我的工单处撤销工单
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
50 |
51 |
57 |
--------------------------------------------------------------------------------
/src/components/order/orderSteps.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
18 |
21 |
--------------------------------------------------------------------------------
/src/components/profile/basic.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 环境: {{ order.idc }}
5 |
6 | 数据源: {{ order.source }}
7 |
8 | 数据库: {{ order.data_base }}
9 |
10 | 数据表: {{ order.table }}
11 |
12 | 是否备份: {{ order.backup===0?"否":"是" }}
13 |
14 |
15 | 提交人: {{ order.username }}
16 |
17 | 提交时间: {{ order.date }}
18 |
19 | 工单说明: {{ order.text }}
20 |
21 | 定时执行: {{ order.delay }}
22 |
23 |
24 |
25 |
当前状态
26 |
审核中
27 |
驳回
28 |
已执行
29 |
执行失败
30 |
待执行
31 |
执行中
32 |
33 |
34 |
35 |
36 |
SQL类型
37 |
DDL
38 |
DML
39 |
40 |
41 |
42 |
43 |
44 |
45 |
53 |
54 |
--------------------------------------------------------------------------------
/src/components/profile/collapse.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 提交的SQL语句
5 |
6 |
7 |
8 | 仅显示10条以内的SQL
9 |
10 |
11 | 显示全部SQL
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | 执行结果
21 |
22 |
23 |
24 |
27 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
50 |
51 |
--------------------------------------------------------------------------------
/src/components/profile/postForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本信息
5 |
6 |
7 | 用户名: {{ order.username }}
8 |
9 | 环境: {{ order.idc }}
10 |
11 | 定时执行: {{ order.delay }}
12 |
13 |
14 |
15 | 连接名: {{ order.source }}
16 |
17 | 数据库库名: {{ order.data_base }}
18 |
19 |
20 |
21 |
22 | 重新提交的语句
23 |
26 |
27 |
28 |
29 | 回滚语句
30 |
33 |
34 |
36 |
37 | 提交信息
38 |
49 |
50 |
51 |
52 |
53 |
121 |
122 |
--------------------------------------------------------------------------------
/src/components/profile/profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 工单编号:{{ this.order.work_id }}
6 |
7 |
8 |
9 |
12 |
16 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 流程步骤
34 |
35 |
37 |
38 |
39 |
40 |
41 | 流程记录
42 |
43 |
44 |
45 |
46 | SQL审核
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | 返回顶端
55 |
56 |
57 |
58 |
59 |
60 |
95 |
96 |
108 |
--------------------------------------------------------------------------------
/src/components/profile/queryProfile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 工单{{ this.$route.query.workid }}详细信息
7 |
8 |
9 |
10 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/profile/stepDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{row.action}}
6 | {{row.action}}
7 | {{row.action}}
8 | {{row.action}}
9 |
10 |
11 |
12 |
13 |
14 |
49 |
50 |
--------------------------------------------------------------------------------
/src/components/search/navSearch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ i.title }}
7 |
8 |
9 | {{ i.title }}
10 |
11 |
12 |
13 |
16 |
18 |
19 |
20 |
21 |
100 |
101 |
--------------------------------------------------------------------------------
/src/components/search/search.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
58 |
59 |
--------------------------------------------------------------------------------
/src/components/sidebarMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
48 |
49 |
50 |
82 |
83 |
88 |
--------------------------------------------------------------------------------
/src/components/unlock.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |

10 |
14 |
15 |
16 |
27 |
LDAP登录 已锁定
28 |
29 |
30 |
31 |
32 |
80 |
--------------------------------------------------------------------------------
/src/framework.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
--------------------------------------------------------------------------------
/src/interface/index.ts:
--------------------------------------------------------------------------------
1 | import {Finder} from "@/store/modules/search";
2 |
3 | interface order {
4 | tp?: number
5 | work_id?: string
6 | idc?: string
7 | source?: string,
8 | data_base?: string,
9 | table?: string,
10 | text?: string,
11 | delay?: string,
12 | type?: number,
13 | status?: number,
14 | username?: string,
15 | date?: string,
16 | execute_time?: string
17 | rejected?: string
18 | assigned?: string
19 | backup?: number,
20 | export?: number
21 | current_step?: number
22 | uuid?: string
23 | relevant?: string[]
24 | sql?: string;
25 | }
26 |
27 | interface other_modal {
28 | overdue: string,
29 | query_expire: string,
30 | limit: number,
31 | per_order: number,
32 | idc: string[],
33 | foce: string,
34 | insulate_word_list: string[],
35 | exclude_db_list: string[],
36 | exclued_db: string,
37 | sensitive: string,
38 | multi: boolean,
39 | register: boolean,
40 | export: boolean,
41 | query: boolean,
42 | }
43 |
44 | interface message_modal {
45 | ding: boolean,
46 | mail: boolean,
47 | port: number,
48 | push_type: boolean,
49 | }
50 |
51 | interface test_results {
52 | status: string,
53 | level: number,
54 | error: string,
55 | sql: string[],
56 | affect_rows: number
57 | }
58 |
59 | interface Permission {
60 | ddl_source: string[],
61 | dml_source: string[],
62 | query_source: string[],
63 | auditor: string[],
64 | }
65 |
66 | interface Fetch_data {
67 | idc: string[],
68 | source: string[],
69 | base: string[],
70 | table: string[],
71 | assigned: string[]
72 | }
73 |
74 | interface High_light {
75 | meta: string,
76 | vl: string
77 | }
78 |
79 | interface StepOrder {
80 | desc: string
81 | auditor: string[],
82 | type: number // 0 audit 1 executor
83 | }
84 |
85 | interface CommonFinder {
86 | page: number;
87 | find: Finder
88 | }
89 |
90 | interface Res {
91 | code: number;
92 | text: string;
93 | payload: any;
94 | }
95 |
96 | interface TplOrder {
97 | auditor: string[]
98 | type: number
99 | desc: string
100 | source?: string
101 | }
102 |
103 | export {
104 | order,
105 | other_modal,
106 | message_modal,
107 | test_results,
108 | Permission,
109 | Fetch_data,
110 | High_light,
111 | StepOrder,
112 | CommonFinder,
113 | Res,
114 | TplOrder
115 | }
116 |
--------------------------------------------------------------------------------
/src/interface/render.ts:
--------------------------------------------------------------------------------
1 | import expandRow from "@/components/expandTable.vue";
2 |
3 | let render = {
4 | tag: (h: any, params: { row: { status: number }; }) => {
5 | },
6 | backup: (h: any, params: { row: { backup: number }; }) => {
7 | },
8 | queryExport: (h: any, params: { row: { export: number }; }) => {
9 | },
10 | type: (h: any, params: { row: { type: number }; }) => {
11 | },
12 | expand: (h: any, params: { row: { sql: string }; }) => {
13 | },
14 | sub_sql: (h: any, params: { row: { sql: string }; }) => {
15 | },
16 | query_tag: (h: any, params: { row: { query_per: number } }) => {
17 | }
18 | }
19 |
20 | render.query_tag = (h: any, params: { row: { query_per: number } }) => {
21 | const row = params.row
22 | let color = ''
23 | let text = ''
24 | if (row.query_per === 2) {
25 | color = 'primary'
26 | text = '待审核'
27 | } else if (row.query_per === 0) {
28 | color = 'error'
29 | text = '驳回'
30 | } else if (row.query_per === 1) {
31 | color = 'success'
32 | text = '同意/查询'
33 | } else {
34 | color = 'warning'
35 | text = '查询结束'
36 | }
37 | return h('Tag', {
38 | props: {
39 | type: 'dot',
40 | color: color
41 | }
42 | }, text)
43 | }
44 |
45 | render.tag = (h: any, params: { row: { status: number }; }) => {
46 | const row = params.row;
47 | let color = '';
48 | let text = '';
49 | if (row.status === 2) {
50 | color = 'primary';
51 | text = '审核中';
52 | } else if (row.status === 0) {
53 | color = 'error';
54 | text = '驳回';
55 | } else if (row.status === 1) {
56 | color = 'success';
57 | text = '已执行';
58 | } else if (row.status === 4) {
59 | color = 'error';
60 | text = '执行失败';
61 | } else if (row.status === 5) {
62 | color = 'primary';
63 | text = '待执行';
64 | } else {
65 | color = 'warning';
66 | text = '执行中';
67 | }
68 | return h('Tag', {
69 | props: {
70 | type: 'dot',
71 | color: color
72 | }
73 | }, text)
74 | }
75 |
76 | render.backup = (h: any, params: { row: { backup: number }; }) => {
77 | const row = params.row;
78 | let text = "否"
79 | if (row.backup == 1) {
80 | text = "是"
81 | }
82 | return h('span', {}, text)
83 | }
84 |
85 | render.queryExport = (h: any, params: { row: { export: number }; }) => {
86 | const row = params.row;
87 | let text = "否"
88 | if (row.export == 1) {
89 | text = "是"
90 | }
91 | return h('span', {}, text)
92 | }
93 |
94 | render.type = (h: any, params: { row: { type: number }; }) => {
95 | const row = params.row;
96 | let text = "DDL"
97 | if (row.type == 1) {
98 | text = "DML"
99 | }
100 | return h('span', {}, text)
101 | }
102 |
103 | render.expand = (h: any, params: { row: { sql: string } }) => {
104 | return h(expandRow, {
105 | props: {
106 | row: params.row.sql
107 | }
108 | })
109 | }
110 |
111 | render.sub_sql = (h: any, params: { row: { sql: string } }) => {
112 | let text = params.row.sql.substring(0, 80)
113 | if (text.length > 80) {
114 | text += '...';
115 | }
116 | return h('span', text)
117 | }
118 | export default render
119 |
--------------------------------------------------------------------------------
/src/language/en-us.json:
--------------------------------------------------------------------------------
1 | {
2 | "sign" : "Sign up",
3 | "version" : "version",
4 | "about": "About Yearning",
5 | "community": "Community",
6 | "community_addr": "https://github.com/cookieY/Yearning/issues",
7 | "license": "License: AGPL3.0",
8 | "tips": "© 2021 HenryYee Please use Chrome for the best experience",
9 | "sponsor": "sponsor",
10 | "account": "username",
11 | "password": "password",
12 | "pin": "PIN",
13 | "login": "Sign in",
14 | "ldap": "LDAP mode",
15 | "sponsor_title": "Let Yearning continue to provide better features and services",
16 | "sponsor_1": "You can get it after sponsorship",
17 | "sponsor_2": "Contact the author to add their name to the sponsor list. For top sponsors, the company or individual logo can be added to the project's home page README and prioritized for the development of the business or individual needs.",
18 | "sponsor_3": "Customized",
19 | "sponsor_4": "Enterprises can seek customized functional services from Yearning authors",
20 | "sponsor_5": "Contact",
21 | "sponsor_6": "E-mail: henry@yearning.io",
22 | "sponsor_7": "PayPal: henry@yearning.io",
23 | "sign_up_validate": {
24 | "username":"please enter your username",
25 | "password": "please enter your password",
26 | "min": "Please enter at least 6 characters",
27 | "max": "Enter up to 32 characters",
28 | "regexp": "At least 1 uppercase letter, 1 lowercase letter, 1 number",
29 | "confirm": "please enter your new password",
30 | "twice": "password is inconsistent",
31 | "real": "please enter your real name",
32 | "department": "please enter your department",
33 | "mail": "please enter your E-mail",
34 | "mail_format": "Incorrect mail addr format",
35 | "sign_fail": "Please fill in the relevant registration information correctly",
36 | "pin": "Can not verify PIN"
37 | },
38 | "sign_userInfo": {
39 | "username": "Username",
40 | "password": "Password",
41 | "confirm": "Confirm",
42 | "real": "Real_name",
43 | "department": "Department",
44 | "mail": "E-mail"
45 | },
46 | "general": {
47 | "name": "Username",
48 | "real": "Real name",
49 | "role": "Role",
50 | "mail": "Mail",
51 | "department": "Department",
52 | "change_password": "Change password",
53 | "show_permissions": "Permissions",
54 | "db": "Database",
55 | "agreed": "agreed"
56 | },
57 | "dash": {
58 | "lock": "Lock",
59 | "unlock": "Unlock",
60 | "user": "User count",
61 | "source": "Source count",
62 | "order": "Order count",
63 | "query": "Query count",
64 | "edit_permissions": "Edit permissions/info",
65 | "profile": "Profile",
66 | "order_count": "Order total",
67 | "db_top": "DB/top 5",
68 | "axis": {
69 | "ddl": "DDL",
70 | "dml": "DML",
71 | "query": "Query",
72 | "trend": "Order trend"
73 | },
74 | "quick": "Quick nav",
75 | "board": "Board"
76 | },
77 | "banner": {
78 | "guide": "Guide",
79 | "login_out": "Login out",
80 | "statement": {
81 | "banner": "Welcome to use Yearning",
82 | "title": "Abount Yearning",
83 | "title_text": "An awesome SQL Audit platform for Mysql welcome to you use it!",
84 | "notes": "Develop notes:",
85 | "text": "As an open source platform. Yearning hopes that more developers will participate in the development together. At the same time, companies are encouraged to conduct secondary development and customization of the platform according to their own business.",
86 | "text_1": "Yearning adopts AGPL 3.0 license, the following are the related obligations and responsibilities in the license.",
87 | "text_2": "1. You may not use Yearning for any commercial purpose without authorization from the original author. This includes providing any business services based on Yearning through the Internet.",
88 | "text_3": "2. If you modify the code, you need to explain it in the modified file.",
89 | "text_4": "3. In the case of secondary development and publication (internal use is not within the terms), the software must be an open source project, not any commercial software of a commercial nature. If you want to commercialize, you must obtain the author's authorization.",
90 | "text_5": "4. All the terms of this platform comply with the corresponding open source license, please use and develop in strict accordance with the relevant license.",
91 | "text_6":"Disclaimer",
92 | "text_7":"All the consequences arising from the Yearning platform, the Yearning authors are not responsible for it! Please use it after conducting a security assessment and testing experience.",
93 | "text_8":"Of course, if you like it, just reward me ^_^ Login interface sponsorship button",
94 | "text_9":"This statement will not be pushed to non-super administrator users. After accepting the above terms and clicking agree, this notification will not appear again on the super administrator page."
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/language/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueI18n from 'vue-i18n';
3 | import iView from 'view-design'
4 |
5 | // import locale from 'view-design/dist/locale/en-US';
6 | import locale from 'view-design/dist/locale/zh-CN';
7 | // let ui_zh = require('view-design/dist/locale/zh-CN')
8 | // let ui_en = require('view-design/dist/locale/en-US')
9 | let app_zh = require('./zh-cn.json')
10 | let app_en = require('./en-us.json')
11 | Vue.use(VueI18n);
12 | Vue.use(iView,{
13 | locale
14 | })
15 | const messages = {
16 | en: Object.assign(app_en),
17 | zh: Object.assign(app_zh)
18 | };
19 |
20 | const i18n = new VueI18n({
21 | locale: 'zh', //if you need get the browser language use following "window.navigator.language"
22 | fallbackLocale: 'zh',
23 | messages: messages,
24 | silentTranslationWarn: true
25 | })
26 |
27 | export default i18n;
28 |
29 |
--------------------------------------------------------------------------------
/src/language/zh-cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "sign": "注册",
3 | "version": "版本",
4 | "about": "关于Yearning",
5 | "community": "使用交流群",
6 | "community_addr": "Q群:747364310",
7 | "license": "AGPL3.0",
8 | "tips": "© 2021 HenryYee 请使用最新版Chrome浏览器获得最佳体验",
9 | "sponsor": "赞助/技术协助",
10 | "account": "账号",
11 | "password": "密码",
12 | "pin": "验证码",
13 | "login": "登录",
14 | "ldap": "ldap登录",
15 | "sponsor_title": "让Yearning持续提供更好的功能与服务",
16 | "sponsor_1": "赞助后你可以得到的",
17 | "sponsor_2": "联系作者将自己的名字添加到赞助者名单中\n\n 对于顶级赞助商,可将公司或个人logo添加到项目首页README当中,并优先考虑对该企业或个人的需求进行开发。",
18 | "sponsor_3": "定制化需求",
19 | "sponsor_4": "企业可根据实际需要向Yearning作者寻求定制功能服务。",
20 | "sponsor_5": "联系方式",
21 | "sponsor_6": "电邮:henry@yearning.io",
22 | "sponsor_7": "QQ: 834958386",
23 | "sign_up_validate": {
24 | "username": "请输入用户名",
25 | "password": "请输入密码",
26 | "min": "请输入至少6个字符",
27 | "max": "最多输入32个字符",
28 | "regexp": "至少1个大写字母,1个小写字母,1个数字",
29 | "confirm": "请确认新密码",
30 | "twice": "输入的密码不一致",
31 | "real": "请输入真实姓名",
32 | "department": "请输入部门名",
33 | "mail": "请输入E-mail",
34 | "mail_format": "E-mail格式错误",
35 | "sign_fail": "请正确填写相关注册信息",
36 | "pin": "验证码错误,请重新输入!"
37 | },
38 | "sign_userInfo": {
39 | "username": "用户名",
40 | "password": "密码",
41 | "confirm": "确认密码",
42 | "real": "真实姓名",
43 | "department": "部门",
44 | "mail": "邮箱"
45 | },
46 | "general": {
47 | "name": "用户名",
48 | "real": "姓名",
49 | "role": "角色",
50 | "mail": "邮箱",
51 | "department": "部门",
52 | "change_password": "修改密码",
53 | "show_permissions": "查看权限",
54 | "db": "数据库",
55 | "agreed": "同意"
56 | },
57 | "dash": {
58 | "lock": "锁屏",
59 | "unlock": "解锁",
60 | "user": "用户数",
61 | "source": "数据源",
62 | "order": "工单数",
63 | "query": "查询总数",
64 | "edit_permissions": "修改邮箱/真实姓名",
65 | "profile": "个人信息",
66 | "order_count": "工单提交统计",
67 | "db_top": "高频库/top 10",
68 | "axis": {
69 | "ddl": "DDL工单提交数",
70 | "dml": "DML工单提交数",
71 | "query": "查询工单提交数",
72 | "trend": "工单趋势"
73 | },
74 | "quick": "快捷导航",
75 | "board": "公告"
76 | },
77 | "banner": {
78 | "guide": "使用说明",
79 | "login_out": "退出登录",
80 | "statement": {
81 | "banner": "欢迎使用Yearning SQL审核平台",
82 | "title": "关于Yearning:",
83 | "title_text": "Yearning MYSQL SQL语句审核平台。提供查询,SQL审核等多种功能。非常欢迎大家体验并使用Yearning!",
84 | "notes": "关于二次开发的声明:",
85 | "text": " 作为一款开源平台。Yearning很希望有更多的开发者一起参与到开发中。同时也鼓励各公司根据自身业务对平台进行二次开发及定制。",
86 | "text_1": " Yearning 采用AGPL 3.0许可证,以下为许可中相关的义务与责任。",
87 | "text_2": "1.未经原作者授权不得将Yearning 用于任何商业目的。包括通过网络提供任何基于Yearning的商业服务。",
88 | "text_3": "2.如果你修改了代码,需要在被修改的文件中说明。",
89 | "text_4": "3.如二次开发并公布的情况下(内部使用不在该条款之内),该软件必须为开源项目,不可为任何商业性质的商业软件。如需商业化必须获得原作者授权。",
90 | "text_5": "4.本平台所有条款符合相应开源许可,请严格按照相关许可使用及开发。",
91 | "text_6":"免责声明:",
92 | "text_7":"由Yearning平台所产生的一切后果,Yearning作者本人不负一切责任! 请在进行安全评估及测试体验后使用。",
93 | "text_8":"当然用的喜欢,就打赏下我吧 ^_^ 登录界面赞助按钮",
94 | "text_9":"此声明不会对非超级管理员用户推送。当接受上述条款并点击同意后,此通知将不会再次出现在超级管理员页面中。"
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/libs/libs.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import Notice from 'view-design/src/components/notice'
3 | import module_general from "@/store/modules/general";
4 | // @ts-ignore
5 | import Message from 'view-design/src/components/message'
6 |
7 | let libs: any = {};
8 | libs.title = function (title: string) {
9 | window.document.title = `Yearning || ${title}`
10 | };
11 |
12 | libs.random = function (lower: number, upper: number) {
13 | return Math.floor(Math.random() * (upper - lower)) + lower;
14 | };
15 |
16 | libs.notice = function (vl: string) {
17 | Notice.info({
18 | title: '通知',
19 | desc: vl
20 | })
21 | };
22 |
23 | libs.message = function (tp: string, vl: string) {
24 | Message[tp]({content: vl})
25 | };
26 |
27 | libs.highlight = 'alter|and|as|asc|between|count|create|delete|desc|distinct|drop|from|having|in|insert|into|is|join|like|not|on|or|order|select|set|table|union|update|values|where|accessible|action|add|after|algorithm|all|analyze|asensitive|at|authors|auto_increment|autocommit|avg|avg_row_length|before|binary|binlog|both|btree|cache|call|cascade|cascaded|case|catalog_name|chain|change|changed|character|check|checkpoint|checksum|class_origin|client_statistics|close|coalesce|code|collate|collation|collations|column|columns|comment|commit|committed|completion|concurrent|condition|connection|consistent|constraint|contains|continue|contributors|convert|cross|current_date|current_time|current_timestamp|current_user|cursor|data|database|databases|day_hour|day_microsecond|day_minute|day_second|deallocate|dec|declare|default|delay_key_write|delayed|delimiter|des_key_file|describe|deterministic|dev_pop|dev_samp|deviance|directory|disable|discard|distinctrow|div|dual|dumpfile|each|elseif|enable|enclosed|end|ends|engine|engines|enum|errors|escape|escaped|even|event|events|every|execute|exists|exit|explain|extended|fast|fetch|field|fields|first|flush|for|force|foreign|found_rows|full|fulltext|function|general|global|grant|grants|group|groupby_concat|handler|hash|help|high_priority|hosts|hour_microsecond|hour_minute|hour_second|if|ignore|ignore_server_ids|import|index|index_statistics|infile|inner|innodb|inout|insensitive|insert_method|install|interval|invoker|isolation|iterate|key|keys|kill|language|last|leading|leave|left|level|limit|linear|lines|list|load|local|localtime|localtimestamp|lock|logs|low_priority|master|master_heartbeat_period|master_ssl_verify_server_cert|masters|match|max|max_rows|maxvalue|message_text|middleint|migrate|min|min_rows|minute_microsecond|minute_second|mod|mode|modifies|modify|mutex|mysql_errno|natural|next|no|no_write_to_binlog|offline|offset|one|online|open|optimize|option|optionally|out|outer|outfile|pack_keys|parser|partition|partitions|password|phase|plugin|plugins|prepare|preserve|prev|primary|privileges|procedure|processlist|profile|profiles|purge|query|quick|range|read|read_write|reads|real|rebuild|recover|references|regexp|relaylog|release|remove|rename|reorganize|repair|repeatable|replace|acequire|resignal|restrict|resume|return|returns|revoke|right|rlike|rollback|rollup|row|row_format|rtree|savepoint|schedule|schema|schema_name|schemas|second_microsecond|security|sensitive|separator|serializable|server|session|share|show|signal|slave|slow|smallint|snapshot|soname|spatial|specific|sql|sql_big_result|sql_buffer_result|sql_cache|sql_calc_found_rows|sql_no_cache|sql_small_result|sqlexception|sqlstate|sqlwarning|ssl|start|starting|starts|status|std|stddev|stddev_pop|stddev_samp|storage|straight_join|subclass_origin|sum|suspend|table_name|table_statistics|tables|tablespace|temporary|terminated|to|trailing|transaction|trigger|triggers|truncate|uncommitted|undo|uninstall|unique|unlock|upgrade|usage|use|use_frm|user|user_resources|user_statistics|using|utc_date|utc_time|utc_timestamp|value|variables|varying|view|views|warnings|when|while|with|work|write|xa|xor|year_month|zerofill|begin|do|then|else|loop|repeat|by|bool|boolean|bit|blob|decimal|double|enum|float|long|longblob|longtext|medium|mediumblob|mediumint|mediumtext|time|timestamp|tinyblob|tinyint|tinytext|text|bigint|int|int1|int2|int3|int4|int8|integer|float|float4|float8|double|char|varbinary|varchar|varcharacter|precision|date|datetime|year|unsigned|signed|numeric|ucase|lcase|mid|len|round|rank|now|format|coalesce|ifnull|isnull|nvl'
28 |
29 | libs.url = '/api/v2';
30 |
31 | libs.openPage = function (vm: any, name: string) {
32 | vm.$router.push({name: name});
33 | module_general.breadcrumb_set(name);
34 | module_general.changed_currentPageName(name)
35 | };
36 |
37 | libs.clearOption = function (obj: any) {
38 | for (let i in obj) {
39 | if (obj.hasOwnProperty(i)) {
40 | if (typeof obj[i] === 'object') {
41 | obj[i] = []
42 | } else if (typeof obj[i] === 'string') {
43 | obj[i] = '0'
44 | } else if (typeof obj[i] === 'number') {
45 | obj[i] = 0
46 | } else {
47 | obj[i] = false
48 | }
49 | }
50 | }
51 | return obj
52 | };
53 |
54 | libs.concat = function (arr1: Array, arr2: Array) {
55 | let arr = arr1.concat();
56 | for (let i = 0; i < arr2.length; i++) {
57 | arr.indexOf(arr2[i]) === -1 ? arr.push(arr2[i]) : 0;
58 | }
59 | return arr;
60 | };
61 |
62 | libs.formVerify = (vm: any) => {
63 | const next: any = vm.$refs.ruleForm
64 | let isOk = false
65 | next.validate((valid: boolean) => {
66 | isOk = valid
67 | })
68 | return {isOk, next}
69 | }
70 |
71 |
72 | libs.patch = "Community"
73 | libs.version = "v 2.3.6 Neptune"
74 |
75 | export default libs
76 |
--------------------------------------------------------------------------------
/src/libs/requests.ts:
--------------------------------------------------------------------------------
1 | import axios, {AxiosInstance, AxiosResponse} from 'axios'
2 | import libs from "@/libs/libs";
3 | // @ts-ignore
4 | import Modal from "view-design/src/components/modal"
5 | // @ts-ignore
6 | import Message from "view-design/src/components/message"
7 | // @ts-ignore
8 | import Notice from "view-design/src/components/notice"
9 | import module_general from "@/store/modules/general";
10 | import {LoginApi} from "@/apis/loginApis";
11 | import {router} from "@/main";
12 | import {loginRender} from "@/views/login/render";
13 | import {Res} from "@/interface";
14 |
15 | const ACCESS_TOKEN = sessionStorage.getItem("jwt")
16 |
17 | const request: AxiosInstance = axios.create({})
18 |
19 | function ReLoginHandler() {
20 | Modal.warning({
21 | title: '重新登录',
22 | okText: '登录',
23 | closable: false,
24 | loading: true,
25 | render: loginRender,
26 | onOk: () => {
27 | LoginApi(module_general.openReLogin, {
28 | username: sessionStorage.getItem('user') as string,
29 | password: module_general.password
30 | })
31 | .then((res: AxiosResponse) => {
32 | sessionStorage.setItem('jwt', `Bearer ${res.data.payload.token}`);
33 | window.location.reload()
34 | })
35 | .catch(() => {
36 | router.push({name: 'login'}).then(() => {
37 | })
38 | })
39 | .finally(() => Modal.remove())
40 | }
41 | })
42 | }
43 |
44 | const errorHandler = (error: { response: { data: { message: string }; status: number } }) => {
45 | if (error.response) {
46 | if (error.response.status === 401) {
47 | if (document.getElementsByClassName('ivu-message-notice').length === 0) {
48 | let text = 'Token过期!请重新登录!';
49 | Message.warning({content: text, duration: 5});
50 | }
51 | ReLoginHandler()
52 | return Promise.reject(error)
53 | }
54 | const data = error.response.data
55 | Notice.error({
56 | title: `状态码:${error.response.status}`,
57 | desc: data.message
58 | })
59 | }
60 | return Promise.reject(error)
61 | }
62 |
63 | const responseInject = (res: Res) => {
64 | if (res.text !== '' && res.code === 1200) {
65 | Notice.info({
66 | title: '状态码:1200',
67 | desc: res.text
68 | })
69 | }
70 |
71 | if (res.code > 1200) {
72 | Notice.error({
73 | title: `状态码:${res.code}`,
74 | desc: res.text
75 | })
76 | }
77 |
78 | }
79 |
80 | request.interceptors.request.use(config => {
81 | if (ACCESS_TOKEN !== null) {
82 | config.headers['Authorization'] = ACCESS_TOKEN
83 | }
84 | return config
85 | }, errorHandler)
86 |
87 | request.interceptors.response.use((response) => {
88 | responseInject(response.data)
89 | return response
90 | }, errorHandler)
91 |
92 | export {
93 | request
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import Subnet from './framework.vue'
5 | import iView from 'view-design'
6 | import VueRouter from 'vue-router'
7 | import {MainRoute} from './router'
8 | import store from '@/store'
9 | import './styles/theme.less'
10 | import config from './libs/libs'
11 | import particles from 'particles.js/particles'
12 | import mavonEditor from 'mavon-editor'
13 | import 'mavon-editor/dist/css/index.css'
14 | import {LoadingBar} from 'view-design'
15 | import i18n from "@/language";
16 | import SlideVerify from 'vue-monoplasty-slide-verify';
17 | Vue.config.productionTip = false;
18 | Vue.prototype.$config = config;
19 | Vue.use(iView)
20 | Vue.use(SlideVerify)
21 | Vue.use(particles);
22 | Vue.use(VueRouter);
23 | Vue.use(mavonEditor);
24 | /* eslint-disable no-new */
25 | const RouterConfig = {
26 | routes: MainRoute
27 | };
28 |
29 | export const router = new VueRouter(RouterConfig);
30 |
31 | const originalPush = VueRouter.prototype.push
32 | VueRouter.prototype.push = function push(location: import("vue-router").RawLocation) {
33 | // @ts-ignore
34 | return originalPush.call(this as any, location).catch((err: any) => err)
35 | }
36 |
37 |
38 |
39 | router.beforeEach((to: any, from, next) => {
40 | LoadingBar.start();
41 | config.title(to.meta.title);
42 | if (sessionStorage.getItem('locking') === '1' && to.name !== 'locking') { // 判断当前是否是锁定状态
43 | next(false);
44 | router.replace({name: 'login'}).then(() => {
45 | }).catch(() => {
46 | LoadingBar.finish()
47 | })
48 | } else {
49 | if (!sessionStorage.getItem('user') && to.name !== 'login') { // 判断是否已经登录且前往的页面不是登录页
50 | next(false);
51 | router.replace({name: 'login'}).then(() => {
52 | }).catch(() => {
53 | LoadingBar.finish()
54 | })
55 | } else {
56 | next()
57 | }
58 | }
59 | });
60 |
61 | router.afterEach(() => {
62 | LoadingBar.finish();
63 | window.scrollTo(0, 0)
64 | });
65 |
66 | new Vue({
67 | el: '#Subnet',
68 | template: '',
69 | components: {Subnet},
70 | store: store,
71 | router: router,
72 | i18n
73 | });
74 |
--------------------------------------------------------------------------------
/src/mixins/fetch.ts:
--------------------------------------------------------------------------------
1 | import {Component, Mixins} from "vue-property-decorator";
2 | import Basic from "@/mixins/basic";
3 | import {Fetch_data, Res} from "@/interface";
4 | import {AxiosResponse} from "axios";
5 | import modules_order from "@/store/modules/order";
6 | import {CommonFetch, FetchCommonGetApis} from "@/apis/commonApis";
7 |
8 | @Component({components: {}})
9 | export default class FetchMixins extends Mixins(Basic) {
10 | fetchData: Fetch_data = {
11 | idc: [],
12 | source: [],
13 | base: [],
14 | table: [],
15 | assigned: []
16 | };
17 |
18 | fetchDiffSource(idc: string) {
19 | if (this.is_dml) {
20 | this.fetchSource(idc, "dml")
21 | } else {
22 | this.fetchSource(idc, "ddl")
23 | }
24 | }
25 |
26 | fetchSource(idc: string, tp: string) {
27 | if (idc) {
28 | FetchCommonGetApis('source', {idc: idc, tp: tp})
29 | .then((res: AxiosResponse) => {
30 | if (res.data.payload !== null) {
31 | this.fetchData.source = res.data.payload.source;
32 | this.fetchData.assigned = res.data.payload.assigned
33 | }
34 | })
35 | }
36 | }
37 |
38 | fetchBase(source: string) {
39 | if (source) {
40 | FetchCommonGetApis('base', {source: source})
41 | .then((res: AxiosResponse) => {
42 | this.fetchData.base = res.data.payload.results;
43 | modules_order.changed_wordList(this.$config.concat(this.wordList, res.data.payload.highlight))
44 | })
45 | }
46 | }
47 |
48 | fetchTable() {
49 | if (this.formItem.data_base) {
50 | FetchCommonGetApis('table', this.formItem as CommonFetch)
51 | .then((res: AxiosResponse) => {
52 | this.fetchData.table = res.data.payload.table;
53 | modules_order.changed_wordList(this.$config.concat(this.wordList, res.data.payload.highlight))
54 | })
55 | }
56 | }
57 |
58 | fetchIDC() {
59 | FetchCommonGetApis('idc', {})
60 | .then((res: AxiosResponse) => {
61 | this.fetchData.idc = res.data.payload;
62 | })
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/mixins/order.ts:
--------------------------------------------------------------------------------
1 | import {Component, Mixins} from "vue-property-decorator";
2 | import Basic from "@/mixins/basic";
3 | @Component({components: {}})
4 | export default class OrderMixins extends Mixins(Basic) {
5 |
6 | testColumns = [
7 | {
8 | title: '阶段',
9 | key: 'status',
10 | width: '150'
11 | },
12 | {
13 | title: '错误等级',
14 | key: 'level',
15 | width: '100'
16 | },
17 | {
18 | title: '错误信息',
19 | key: 'error',
20 | tooltip: true,
21 | width: 500
22 | },
23 | {
24 | title: '当前检查的sql',
25 | key: 'sql',
26 | tooltip: true
27 | },
28 | {
29 | title: '影响行数',
30 | key: 'affect_rows',
31 | width: '120'
32 | }
33 | ];
34 | }
35 |
--------------------------------------------------------------------------------
/src/mixins/orderProfile.ts:
--------------------------------------------------------------------------------
1 | import {Component, Mixins} from "vue-property-decorator";
2 | import Basic from "@/mixins/basic";
3 | import module_init_args from "@/store/modules/init_args";
4 | import {FetchCommonGetApis} from "@/apis/commonApis";
5 | import {AxiosResponse} from "axios";
6 | import {Res} from "@/interface";
7 |
8 | @Component({components: {}})
9 | export default class OrderProfileMixins extends Mixins(Basic) {
10 | columns = [
11 | {
12 | title: 'sql语句',
13 | key: 'sql',
14 |
15 | },
16 | {
17 | title: '状态',
18 | key: 'state',
19 | },
20 | {
21 | title: '错误信息',
22 | key: 'error',
23 | tooltip: true
24 | },
25 | {
26 | title: '影响行数',
27 | key: 'affect_row',
28 | width: 100
29 | },
30 | {
31 | title: '执行时间/秒',
32 | key: 'time',
33 | }
34 | ];
35 |
36 | results = [];
37 |
38 | switch_args = {
39 | reload_sql: false,
40 | is_more: '10'
41 | }
42 |
43 | get sqls() {
44 | return module_init_args.order_sql
45 | }
46 |
47 | set sqls(vl) {
48 | module_init_args.fetch_order_sql(vl)
49 | }
50 |
51 | get order() {
52 | return module_init_args.order_item
53 | }
54 |
55 | collapse = ['results', 'sql']
56 |
57 | fetch_post_sql(vl: string = '10') {
58 | this.$Spin.show()
59 | FetchCommonGetApis('sql', {work_id: this.order.work_id, limit: vl})
60 | .then((res: AxiosResponse ) => {
61 | module_init_args.fetch_order_sql(res.data.payload.sqls)
62 | })
63 | .finally(() => {
64 | this.$Spin.hide()
65 | })
66 | }
67 |
68 | open_form() {
69 | this.is_open = true
70 | }
71 |
72 | delOrder(work_id: string) {
73 | FetchCommonGetApis('undo', {work_id: work_id})
74 | .then(() => {
75 | this.$router.go(-1)
76 | })
77 | }
78 |
79 | current_page(vl = 1) {
80 | FetchCommonGetApis('detail', {work_id: this.order.work_id, status: this.order.status, page: vl})
81 | .then((res: AxiosResponse) => {
82 | this.results = res.data.payload.record;
83 | this.page_number = res.data.payload.count;
84 | })
85 | }
86 | }
87 |
88 |
--------------------------------------------------------------------------------
/src/mixins/query.ts:
--------------------------------------------------------------------------------
1 | import {Component, Mixins} from "vue-property-decorator";
2 | import {CommonDeleteApis, CommonPutApis} from "@/apis/queryApis";
3 | import {AxiosResponse} from "axios";
4 | import {Res} from "@/interface";
5 | import FetchMixins from "@/mixins/fetch";
6 |
7 | @Component({components: {}})
8 | export default class QueryMixin extends Mixins(FetchMixins) {
9 |
10 | export_list = false;
11 |
12 | deferReply() {
13 | CommonDeleteApis("undo")
14 | .finally(() => this.$router.push({name: 'query'}))
15 | }
16 |
17 | query_state() {
18 | CommonPutApis('status', null)
19 | .then((res: AxiosResponse) => {
20 | switch (res.data.payload.status) {
21 | case 1:
22 | this.$router.push({name: 'query_page'})
23 | return
24 | case 2:
25 | this.$router.push({name: 'query_apply'})
26 | return;
27 | default:
28 | this.fetchIDC();
29 | this.export_list = res.data.payload.export;
30 | }
31 | })
32 | }
33 | }
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | declare module '*.vue' {
4 | import Vue from 'vue'
5 |
6 | export default Vue
7 | }
8 | declare module 'particles.js/particles'
9 |
10 | declare module 'view-design/dist/locale/en-US'
11 |
12 | declare module 'view-design/dist/locale/zh-CN'
13 |
14 | declare module 'sql-formatter';
15 |
16 | declare module 'view-design/src/components/table/export-csv';
17 |
18 | declare module 'view-design/src/utils/csv';
19 | declare module 'vue-monoplasty-slide-verify';
20 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex);
5 |
6 | export default new Vuex.Store({
7 | mutations: {
8 | lock() {
9 | sessionStorage.setItem('locking', '1')
10 | },
11 | unlock() {
12 | sessionStorage.setItem('locking', '0')
13 | },
14 | }
15 | });
16 |
--------------------------------------------------------------------------------
/src/store/modules/general.ts:
--------------------------------------------------------------------------------
1 | import {Module, VuexModule, Mutation, getModule} from 'vuex-module-decorators'
2 | import store from "@/store";
3 | import {appRouter} from "@/router";
4 | // @ts-ignore
5 | import Message from "view-design/src/components/message";
6 |
7 | interface Path {
8 | title?: string | undefined
9 | path?: string
10 | name?: string
11 | text?: string
12 | }
13 |
14 | @Module({namespaced: true, name: 'modules_general', dynamic: true, store})
15 | class general extends VuexModule {
16 | stmt: boolean = false
17 | openReLogin: boolean = false
18 | password: string = ""
19 | menuList: object[] = []
20 | currentPageName?: string | undefined = 'home_index'
21 | currentPath: Path[] = [
22 | {
23 | title: '首页',
24 | path: '/',
25 | name: 'home_index'
26 | }
27 | ]
28 | snippet: Path[] = []
29 |
30 | @Mutation
31 | snippetTag(vm: Path) {
32 | if (this.snippet === null) {
33 | this.snippet = []
34 | }
35 | for (let i of this.snippet) {
36 | if (i.title === vm.title) {
37 | Message.error('snippet标签名不得重复!');
38 | return
39 | }
40 | }
41 | if (this.snippet.length > 14) {
42 | Message.error('snippet最多保存15个!');
43 | return
44 | }
45 | this.snippet.push({'title': vm.title, 'text': vm.text})
46 | Message.success('snippet已保存!');
47 | }
48 |
49 | @Mutation
50 | snippetTagToJson() {
51 | localStorage.setItem('snippet', JSON.stringify(this.snippet))
52 | }
53 |
54 | @Mutation
55 | snippetTagFromJson() {
56 | this.snippet = JSON.parse(localStorage.getItem('snippet'))
57 | }
58 |
59 | @Mutation
60 | snippetRemoveTag(vm: Path) {
61 | const index: number = this.snippet.indexOf(vm);
62 | this.snippet.splice(index, 1)
63 | }
64 |
65 | @Mutation
66 | changed_stmt_status(vm: boolean) {
67 | this.stmt = vm
68 | }
69 |
70 | @Mutation
71 | changed_ReLogin_password(vm: string) {
72 | this.password = vm
73 | }
74 |
75 | @Mutation
76 | changed_openReLogin_status(vm: boolean) {
77 | this.openReLogin = vm
78 | }
79 |
80 | @Mutation
81 | changed_menuList(vm: object[]) {
82 | this.menuList = vm
83 | }
84 |
85 | @Mutation
86 | changed_currentPageName(vm?: string | undefined) {
87 | this.currentPageName = vm
88 | }
89 |
90 | @Mutation
91 | breadcrumb_set(name?: string) {
92 | this.currentPath = []
93 | appRouter.forEach((val: any) => {
94 | for (let i of val.children) {
95 | if (i.name === name) {
96 | if (val.name !== 'main') {
97 | this.currentPath = [
98 | {
99 | title: val.meta.title,
100 | path: val.path,
101 | name: val.name
102 | }, {
103 | title: i.meta.title,
104 | path: `${val.path}/${i.path}`,
105 | name: i.name
106 | }
107 | ]
108 | } else {
109 | this.currentPath = [
110 | {
111 | title: i.meta.title,
112 | path: i.path,
113 | name: i.name
114 | }
115 | ]
116 | }
117 | }
118 | }
119 | })
120 | }
121 |
122 | @Mutation
123 | sidebar_filter() {
124 | let accessCode = parseInt(sessionStorage.getItem('access')); // 0
125 | let menuList: any = [];
126 | appRouter.forEach((item: any) => {
127 | if (item.access < accessCode) {
128 | let i = menuList.push(item);
129 | menuList[i - 1].children = item.children
130 | }
131 | });
132 | this.menuList = menuList
133 | }
134 | }
135 |
136 | const module_general = getModule(general)
137 | export default module_general
138 |
--------------------------------------------------------------------------------
/src/store/modules/init_args.ts:
--------------------------------------------------------------------------------
1 | import {Module, VuexModule, Mutation, getModule} from 'vuex-module-decorators'
2 | import store from "@/store";
3 | import {order, StepOrder} from "@/interface";
4 |
5 | @Module({namespaced: true, name: 'modules_init', dynamic: true, store})
6 | class init_args extends VuexModule {
7 | order_item: order = {
8 | work_id: '',
9 | idc: '',
10 | source: '',
11 | data_base: '',
12 | table: '',
13 | text: '',
14 | delay: '',
15 | type: 0,
16 | status: 0,
17 | username: '',
18 | date: '',
19 | rejected: '',
20 | execute_time: '',
21 | backup: 0,
22 | assigned: '',
23 | current_step: 0
24 | }
25 |
26 | order_sql = ''
27 |
28 | order_step: StepOrder[] = [{desc: '', auditor: [], type: 0}]
29 |
30 | @Mutation
31 | fetch_order_step(vl: StepOrder[]) {
32 | this.order_step = vl
33 | }
34 |
35 | @Mutation
36 | fetch_order_item(vm: order) {
37 | this.order_item = vm
38 | }
39 |
40 | @Mutation
41 | fetch_order_sql(vm: string) {
42 | this.order_sql = vm
43 | }
44 | }
45 |
46 |
47 | const module_init_args = getModule(init_args)
48 | export default module_init_args
49 |
--------------------------------------------------------------------------------
/src/store/modules/order.ts:
--------------------------------------------------------------------------------
1 | import {Module, VuexModule, Mutation, getModule} from 'vuex-module-decorators'
2 | import store from '@/store'
3 | import {order} from '@/interface'
4 | // @ts-ignore
5 | import Message from 'view-design/src/components/message'
6 | import sqlFormatter from "sql-formatter";
7 |
8 | interface SQLTest {
9 | status?: string
10 | level?: number
11 | sql?: string
12 | error?: string
13 | affect_rows?: number
14 | }
15 |
16 | @Module({dynamic: true, store, name: 'modules_order', namespaced: true})
17 | class order_local extends VuexModule {
18 | steps: number = 0
19 | is_dml: boolean = false
20 | sql: string = ''
21 | sql_order: order = {
22 | export: 0,
23 | }
24 | order: order = {
25 | tp: 0,
26 | idc: '',
27 | source: '',
28 | data_base: '',
29 | table: '',
30 | text: '',
31 | delay: '',
32 | assigned: '',
33 | backup: 1,
34 | export: 0,
35 | uuid: ''
36 | }
37 | always: object = {
38 | one: true,
39 | two: false,
40 | three: false
41 | }
42 | wordList: object[] = []
43 | osc_id: string = ''
44 | order_sql: SQLTest[] = []
45 |
46 | @Mutation
47 | clear_sql_order() {
48 | return this.sql_order = { export: 0} as order
49 | }
50 |
51 | @Mutation
52 | fetch_order_sql(vm: object[]) {
53 | return this.order_sql = vm
54 | }
55 |
56 | @Mutation
57 | fetch_order_osc_id(vm: string) {
58 | return this.osc_id = vm
59 | }
60 |
61 | @Mutation
62 | clear_order() {
63 | this.order = {
64 | idc: '',
65 | source: '',
66 | data_base: '',
67 | table: '',
68 | text: '',
69 | delay: '',
70 | assigned: '',
71 | backup: 1,
72 | export: 0,
73 | tp: 0
74 | }
75 | this.steps = 0
76 | this.sql = ''
77 | this.wordList = []
78 | }
79 |
80 | @Mutation
81 | beauty_sql() {
82 | this.sql = sqlFormatter.format(this.sql)
83 | }
84 |
85 | @Mutation
86 | clear_always() {
87 | this.always = {one: true, two: false, three: false}
88 | }
89 |
90 | @Mutation
91 | changed_wordList(vm: object[]) {
92 | this.wordList = vm
93 | }
94 |
95 | @Mutation
96 | changed_always(vm: object) {
97 | this.always = vm
98 | }
99 |
100 | @Mutation
101 | changed_step(vm: number) {
102 | this.steps = vm
103 | }
104 |
105 | @Mutation
106 | changed_is_dml(vm: boolean) {
107 | this.is_dml = vm
108 | }
109 |
110 | @Mutation
111 | save_sql(sql: string) {
112 | this.sql = sql
113 | }
114 | }
115 |
116 | const modules_order = getModule(order_local)
117 |
118 | export default modules_order
119 |
--------------------------------------------------------------------------------
/src/store/modules/search.ts:
--------------------------------------------------------------------------------
1 | import {Module, VuexModule, Mutation, getModule} from 'vuex-module-decorators'
2 | import store from "@/store";
3 |
4 | export interface Finder {
5 | picker: string[]
6 | valve: boolean
7 | text: string
8 | explain: string
9 | work_id: string
10 | type: number,
11 | status: number
12 | }
13 |
14 | @Module({namespaced: true, name: 'modules_search', dynamic: true, store})
15 | class search extends VuexModule {
16 |
17 | find: Finder = {
18 | picker: [],
19 | valve: false,
20 | text: '',
21 | explain: '',
22 | work_id: '',
23 | type: 2,
24 | status: 7
25 | }
26 |
27 | @Mutation
28 | post_search_args(vm: Finder) {
29 | this.find = vm
30 | }
31 | }
32 |
33 | const modules_search = getModule(search)
34 |
35 | export default modules_search
36 |
--------------------------------------------------------------------------------
/src/store/modules/user.ts:
--------------------------------------------------------------------------------
1 | import {Module, VuexModule, Mutation, getModule} from 'vuex-module-decorators'
2 | import store from "@/store";
3 |
4 |
5 | interface Edit {
6 | id?: number
7 | username?: string
8 | department?: string
9 | real_name?: string
10 | rule?: string
11 | email?: string
12 | password?: string
13 | }
14 |
15 | @Module({namespaced: true, name: 'modules_user', dynamic: true, store})
16 | class user extends VuexModule {
17 |
18 | edit: Edit = {
19 | id: 0,
20 | username: '',
21 | department: '',
22 | real_name: '',
23 | rule: '',
24 | email: '',
25 | password: ''
26 | }
27 |
28 | @Mutation
29 | fetch_user_info(vm: object) {
30 | this.edit = vm
31 | }
32 |
33 | @Mutation
34 | change_username(user:string) {
35 | this.edit.username = user
36 | }
37 | }
38 |
39 | const module_user = getModule(user)
40 |
41 | export default module_user
42 |
--------------------------------------------------------------------------------
/src/store/modules/verify.ts:
--------------------------------------------------------------------------------
1 | import {Module, VuexModule, Mutation, getModule} from 'vuex-module-decorators'
2 | import store from "@/store";
3 |
4 | interface group {
5 | username: string
6 | list: []
7 | group: string[]
8 | }
9 |
10 | @Module({namespaced: true, name: 'modules_verify', dynamic: true, store})
11 | class verify extends VuexModule {
12 | group: group = {
13 | username: '',
14 | list: [],
15 | group: []
16 | }
17 |
18 | @Mutation
19 | fetch_user_permissions(vm: group) {
20 | this.group = vm
21 | }
22 | }
23 |
24 | const module_verify = getModule(verify)
25 |
26 | export default module_verify
27 |
--------------------------------------------------------------------------------
/src/styles/common.css:
--------------------------------------------------------------------------------
1 | .demo-spin-icon-load {
2 | animation: ani-demo-spin 1s linear infinite;
3 | }
4 | .margin-top-8 {
5 | margin-top: 8px;
6 | }
7 | .margin-top-10 {
8 | margin-top: 10px;
9 | }
10 | .margin-top-20 {
11 | margin-top: 20px;
12 | }
13 | .margin-left-10 {
14 | margin-left: 10px;
15 | }
16 | .margin-bottom-10 {
17 | margin-bottom: 10px;
18 | }
19 | .margin-bottom-100 {
20 | margin-bottom: 100px;
21 | }
22 | .margin-right-10 {
23 | margin-right: 10px;
24 | }
25 | .padding-left-6 {
26 | padding-left: 6px;
27 | }
28 | .padding-left-8 {
29 | padding-left: 5px;
30 | }
31 | .padding-left-10 {
32 | padding-left: 10px;
33 | }
34 | .padding-left-20 {
35 | padding-left: 20px;
36 | }
37 | .height-100 {
38 | height: 100%;
39 | }
40 | .height-120px {
41 | height: 100px;
42 | }
43 | .height-200px {
44 | height: 200px;
45 | }
46 | .height-492px {
47 | height: 492px;
48 | }
49 | .height-460px {
50 | height: 460px;
51 | }
52 | .line-gray {
53 | height: 0;
54 | border-bottom: 2px solid #dcdcdc;
55 | }
56 | .notwrap {
57 | word-break: keep-all;
58 | white-space: nowrap;
59 | overflow: hidden;
60 | text-overflow: ellipsis;
61 | }
62 | .padding-left-5 {
63 | padding-left: 10px;
64 | }
65 | [v-cloak] {
66 | display: none;
67 | }
68 |
--------------------------------------------------------------------------------
/src/styles/common.less:
--------------------------------------------------------------------------------
1 | .demo-spin-icon-load{
2 | animation: ani-demo-spin 1s linear infinite;
3 | }
4 | .margin-left-percent-5 {
5 | margin-left: 5%;
6 | }
7 |
8 | .margin-top-8 {
9 | margin-top: 8px;
10 | }
11 |
12 | .margin-top-10 {
13 | margin-top: 10px;
14 | }
15 |
16 | .margin-top-20 {
17 | margin-top: 20px;
18 | }
19 |
20 | .margin-left-10 {
21 | margin-left: 10px;
22 | }
23 |
24 | .margin-bottom-10 {
25 | margin-bottom: 10px;
26 | }
27 |
28 | .margin-bottom-100 {
29 | margin-bottom: 100px;
30 | }
31 |
32 | .margin-right-10 {
33 | margin-right: 10px;
34 | }
35 |
36 | .padding-left-6 {
37 | padding-left: 6px;
38 | }
39 |
40 | .padding-left-8 {
41 | padding-left: 5px;
42 | }
43 |
44 | .padding-left-10 {
45 | padding-left: 10px;
46 | }
47 |
48 | .padding-left-20 {
49 | padding-left: 20px;
50 | }
51 |
52 | .height-100 {
53 | height: 100%;
54 | }
55 |
56 | .height-120px {
57 | height: 100px;
58 | }
59 |
60 | .height-200px {
61 | height: 200px;
62 | }
63 |
64 | .height-492px {
65 | height: 492px;
66 | }
67 |
68 | .height-460px {
69 | height: 460px;
70 | }
71 |
72 | .line-gray {
73 | height: 0;
74 | border-bottom: 2px solid #dcdcdc;
75 | }
76 |
77 | .notwrap {
78 | word-break: keep-all;
79 | white-space: nowrap;
80 | overflow: hidden;
81 | text-overflow: ellipsis;
82 | }
83 |
84 | .padding-left-5 {
85 | padding-left: 10px;
86 | }
87 |
88 | [v-cloak] {
89 | display: none;
90 | }
91 |
92 |
93 | .card {
94 | border: 0;
95 | }
96 |
97 | .card .card-body {
98 | padding: 1.5rem 2.5rem;
99 | height: 150px;
100 | }
101 |
102 | .card .card-body + .card-body {
103 | padding-top: 1rem;
104 | }
105 |
106 | .card .card-title {
107 | color: #000;
108 | margin-bottom: .75rem;
109 | text-transform: capitalize;
110 | font-family: "ubuntu-medium", sans-serif;
111 | font-size: 1.125rem;
112 | }
113 |
114 | .card .card-subtitle {
115 | font-family: "ubuntu-regular", sans-serif;
116 | margin-top: 0.625rem;
117 | margin-bottom: 0.625rem;
118 | }
119 |
120 | .card .card-description {
121 | margin-bottom: 1.5rem;
122 | font-family: "ubuntu-regular", sans-serif;
123 | color: #76838f;
124 | }
125 |
126 | .card.card-outline-success {
127 | border: 1px solid #1bcfb4;
128 | }
129 |
130 | .card.card-outline-primary {
131 | border: 1px solid #b66dff;
132 | }
133 |
134 | .card.card-outline-warning {
135 | border: 1px solid #fed713;
136 | }
137 |
138 | .card.card-outline-danger {
139 | border: 1px solid #fe7c96;
140 | }
141 |
142 | .card.card-rounded {
143 | border-radius: 5px;
144 | }
145 |
146 | .card.card-faded {
147 | background: #b5b0b2;
148 | border-color: #b5b0b2;
149 | }
150 |
151 | .card.card-circle-progress {
152 | color: #ffffff;
153 | text-align: center;
154 | }
155 |
156 | .card.card-img-holder {
157 | position: relative;
158 | }
159 |
160 | .card.card-img-holder .card-img-absolute {
161 | position: absolute;
162 | top: 0;
163 | right: 0;
164 | height: 100%;
165 | }
166 |
167 | .card-inverse-primary {
168 | background: rgba(182, 109, 255, 0.2);
169 | border: 1px solid #a764eb;
170 | color: #8a53c2;
171 | }
172 |
173 | .card-inverse-secondary {
174 | background: rgba(216, 216, 216, 0.2);
175 | border: 1px solid #c7c7c7;
176 | color: #a4a4a4;
177 | }
178 |
179 | .card-inverse-success {
180 | background: rgba(27, 207, 180, 0.2);
181 | border: 1px solid #19bea6;
182 | color: #159d89;
183 | }
184 |
185 | .card-inverse-info {
186 | background: rgba(25, 138, 227, 0.2);
187 | border: 1px solid #177fd1;
188 | color: #1369ad;
189 | }
190 |
191 | .card-inverse-warning {
192 | background: rgba(254, 215, 19, 0.2);
193 | border: 1px solid #eac611;
194 | color: #c1a30e;
195 | }
196 |
197 | .card-inverse-danger {
198 | background: rgba(254, 124, 150, 0.2);
199 | border: 1px solid #ea728a;
200 | color: #c15e72;
201 | }
202 |
203 | .card-inverse-light {
204 | background: rgba(248, 249, 250, 0.2);
205 | border: 1px solid #e4e5e6;
206 | color: #bcbdbe;
207 | }
208 |
209 | .card-inverse-dark {
210 | background: rgba(62, 75, 91, 0.2);
211 | border: 1px solid #394554;
212 | color: #2f3945;
213 | }
214 |
215 | .bg-gradient-danger {
216 | background: linear-gradient(to right, #ffbf96, #fe7096);
217 | }
218 |
219 | .bg-gradient-success {
220 | background: linear-gradient(to right, #84d9d2, #07cdae);
221 | }
222 | .bg-gradient-warning {
223 | background: linear-gradient(to right, #f6e384, #ffd500);
224 | }
225 |
226 | .bg-gradient-primary {
227 | background: linear-gradient(to right, #da8cff, #9a55ff);
228 | }
229 |
230 | .text-white {
231 | color: #ffffff !important;
232 | }
233 |
234 | .float-right {
235 | float: right !important;
236 | }
237 | .font-weight-normal {
238 | font-weight: 400 !important;
239 | }
240 | .bg-gradient-info {
241 | background: linear-gradient(to right, #90caf9, #047edf 99%);
242 | }
243 | .col-md-4 {
244 | flex: 0 0 33.33333%;
245 | max-width: 33.33333%;
246 | }
247 | .stretch-card {
248 | display: -webkit-flex;
249 | display: flex;
250 | -webkit-align-items: stretch;
251 | align-items: stretch;
252 | -webkit-justify-content: stretch;
253 | justify-content: stretch;
254 | }
255 | .grid-margin, .purchase-popup {
256 | margin-bottom: 2.5rem;
257 | }
258 |
259 | .edit-table-con-1 {
260 | box-sizing: content-box;
261 | padding: 15px 0 0;
262 | height: 550px;
263 | }
--------------------------------------------------------------------------------
/src/styles/infor-card.css:
--------------------------------------------------------------------------------
1 | .infor-card-icon-con {
2 | height: 100%;
3 | }
4 | .height-100 {
5 | height: 100%;
6 | }
7 | .infor-card-con {
8 | height: 100px;
9 | }
10 | .infor-intro-text {
11 | font-size: 12px;
12 | font-weight: 500;
13 | color: #C8C8C8;
14 | }
15 |
--------------------------------------------------------------------------------
/src/styles/infor-card.less:
--------------------------------------------------------------------------------
1 | .infor-card-icon-con {
2 | height: 100%;
3 | }
4 |
5 | .height-100 {
6 | height: 100%;
7 | }
8 |
9 | .infor-card-con {
10 | height: 190px;
11 | }
12 |
13 | .infor-intro-text {
14 | font-size: 30px;
15 | font-weight: bold;
16 | color: #ffffff;
17 | }
18 |
--------------------------------------------------------------------------------
/src/styles/main.less:
--------------------------------------------------------------------------------
1 | .fade-enter-active, .fade-leave-active {
2 | transition: opacity .1s;
3 | }
4 |
5 | .fade-enter, .fade-leave-to
6 | {
7 | opacity: 0;
8 | }
9 |
10 | .main {
11 | position: relative;
12 | width: 100%;
13 | height: 100%;
14 |
15 | .unlock-con {
16 | width: 0;
17 | height: 0;
18 | position: absolute;
19 | left: 50%;
20 | top: 50%;
21 | z-index: 11000;
22 | }
23 |
24 | .sidebar-menu-con {
25 | height: 100%;
26 | position: fixed;
27 | top: 0;
28 | left: 0;
29 | z-index: 1010;
30 | }
31 |
32 | .main-hide-text .layout-text {
33 | display: none;
34 | }
35 |
36 | &-content-container {
37 | position: relative;
38 | }
39 |
40 | &-header-con {
41 | box-sizing: border-box;
42 | position: fixed;
43 | display: block;
44 | padding-left: 200px;
45 | width: 100%;
46 | z-index: 1000;
47 | }
48 |
49 | &-breadcrumb {
50 | padding: 20px 30px 0;
51 | }
52 |
53 | &-menu-left {
54 | background: #464c5b;
55 | height: 100%;
56 | }
57 |
58 | .tags-con {
59 | height: 40px;
60 | padding: 2px 10px;
61 | z-index: -1;
62 | overflow: hidden;
63 | background: #f0edf3;
64 | .close-all-tag-con{
65 | position: absolute;
66 | right: 0;
67 | top: 62%;
68 | box-sizing: border-box;
69 | padding-top: 8px;
70 | text-align: center;
71 | width: 110px;
72 | height: 38%;
73 | background: white;
74 | box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1);
75 | z-index: 4;
76 | }
77 | }
78 |
79 | &-header {
80 | height: 60px;
81 | background: #fff;
82 | position: relative;
83 | z-index: 10;
84 |
85 | .navicon-con {
86 | margin: 6px;
87 | display: inline-block;
88 | }
89 |
90 | .header-middle-con {
91 | position: absolute;
92 | left: 60px;
93 | top: 0;
94 | right: 340px;
95 | bottom: 0;
96 | padding: 10px;
97 | overflow: hidden;
98 | }
99 |
100 | .header-avator-con {
101 | position: absolute;
102 | right: 0;
103 | top: 0;
104 | height: 100%;
105 | width:300px;
106 |
107 | .switch-theme-con {
108 | display: inline-block;
109 | width: 30px;
110 | height: 100%;
111 | }
112 |
113 | .message-con {
114 | display: inline-block;
115 | width: 30px;
116 | padding: 18px 0;
117 | text-align: center;
118 | cursor: pointer;
119 |
120 | i {
121 | vertical-align: middle;
122 | }
123 | }
124 |
125 | .change-skin {
126 | font-size: 14px;
127 | font-weight: 500;
128 | padding-right: 5px;
129 | }
130 |
131 | .switch-theme {
132 | height: 100%;
133 | }
134 |
135 | .user-dropdown {
136 | &-menu-con {
137 | position: absolute;
138 | right: 0;
139 | top: 0;
140 | width: 170px;
141 | height: 100%;
142 | z-index: 5;
143 | }
144 |
145 | &-innercon {
146 | height: 100%;
147 | padding-right: 6px;
148 | }
149 | }
150 |
151 | .full-screen-btn-con {
152 | display: inline-block;
153 | width: 30px;
154 | padding: 18px 0;
155 | text-align: center;
156 | cursor: pointer;
157 |
158 | i {
159 | vertical-align: middle;
160 | }
161 | }
162 |
163 | .lock-screen-btn-con {
164 | display: inline-block;
165 | width: 30px;
166 | padding: 18px 0;
167 | text-align: center;
168 | cursor: pointer;
169 |
170 | i {
171 | vertical-align: middle;
172 | }
173 | }
174 | }
175 | }
176 |
177 | .single-page-con {
178 | box-sizing: border-box;
179 | padding: 70px 0 10px;
180 | background-color: #f0edf3;
181 | z-index: -1;
182 |
183 | .single-page {
184 | margin: 10px;
185 | }
186 | }
187 |
188 | &-copy {
189 | text-align: center;
190 | padding: 10px 0 20px;
191 | color: #9ea7b4;
192 | }
193 | }
194 |
195 | .taglist-moving-animation-move {
196 | transition: transform 0.3s;
197 | }
198 |
199 | .logo-con {
200 | padding: 8px;
201 |
202 | img {
203 | width: 100%;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/src/styles/table.css:
--------------------------------------------------------------------------------
1 | .dragging-tip-enter-active {
2 | opacity: 1;
3 | transition: opacity 0.3s;
4 | }
5 | .dragging-tip-enter,
6 | .dragging-tip-leave-to {
7 | opacity: 0;
8 | transition: opacity 0.3s;
9 | }
10 | .dragging-tip-con {
11 | display: block;
12 | text-align: center;
13 | width: 100%;
14 | height: 50px;
15 | }
16 | .dragging-tip-con span {
17 | font-size: 18px;
18 | }
19 | .record-tip-con {
20 | display: block;
21 | width: 100%;
22 | height: 292px;
23 | overflow: auto;
24 | }
25 | .record-item {
26 | box-sizing: content-box;
27 | display: block;
28 | overflow: hidden;
29 | height: 24px;
30 | line-height: 24px;
31 | padding: 8px 10px;
32 | border-bottom: 1px dashed gainsboro;
33 | }
34 | .record-tip-con span {
35 | font-size: 14px;
36 | }
37 | .edittable-test-con {
38 | min-height: 600px;
39 | }
40 | .edittable-testauto-con {
41 | height: 100%;
42 | }
43 | .edittable-table-height-con {
44 | min-height: 600px;
45 | }
46 | .edittable-table-height1-con {
47 | height: 200px;
48 | }
49 | .edittable-con-1 {
50 | box-sizing: content-box;
51 | padding: 15px 0 0;
52 | height: 550px;
53 | }
54 | .exportable-table-download-con1 {
55 | padding: 16px 0 16px 20px;
56 | border-bottom: 1px dashed #c3c3c3;
57 | margin-bottom: 16px;
58 | }
59 | .exportable-table-download-con2 {
60 | padding-left: 20px;
61 | }
62 | .show-image {
63 | padding: 20px 0;
64 | }
65 | .show-image img {
66 | display: block;
67 | width: 100%;
68 | height: auto;
69 | }
70 |
--------------------------------------------------------------------------------
/src/styles/table.less:
--------------------------------------------------------------------------------
1 | .dragging-tip-enter-active {
2 | opacity: 1;
3 | transition: opacity 0.3s;
4 | }
5 |
6 | .dragging-tip-enter,
7 | .dragging-tip-leave-to {
8 | opacity: 0;
9 | transition: opacity 0.3s;
10 | }
11 |
12 | .dragging-tip-con {
13 | display: block;
14 | text-align: center;
15 | width: 100%;
16 | height: 50px;
17 | }
18 |
19 | .dragging-tip-con span {
20 | font-size: 18px;
21 | }
22 |
23 | .record-tip-con {
24 | display: block;
25 | width: 100%;
26 | height: 292px;
27 | overflow: auto;
28 | }
29 |
30 | .record-item {
31 | box-sizing: content-box;
32 | display: block;
33 | overflow: hidden;
34 | height: 24px;
35 | line-height: 24px;
36 | padding: 8px 10px;
37 | border-bottom: 1px dashed gainsboro;
38 | }
39 |
40 | .record-tip-con span {
41 | font-size: 14px;
42 | }
43 |
44 | .edittable-test-con {
45 | min-height: 600px;
46 | }
47 |
48 | .edittable-testauto-con {
49 | height: 100%;
50 | }
51 |
52 | .edittable-table-height-con {
53 | min-height: 600px;
54 | }
55 |
56 | .edittable-table-height1-con {
57 | height: 200px;
58 | }
59 |
60 | .edittable-con-1 {
61 | box-sizing: content-box;
62 | padding: 15px 0 0;
63 | height: 550px;
64 | }
65 |
66 | .exportable-table-download-con1 {
67 | padding: 16px 0 16px 20px;
68 | border-bottom: 1px dashed #c3c3c3;
69 | margin-bottom: 16px;
70 | }
71 |
72 | .exportable-table-download-con2 {
73 | padding-left: 20px;
74 | }
75 |
76 | .show-image {
77 | padding: 20px 0;
78 | }
79 |
80 | .show-image img {
81 | display: block;
82 | width: 100%;
83 | height: auto;
84 | }
85 |
--------------------------------------------------------------------------------
/src/styles/theme.less:
--------------------------------------------------------------------------------
1 | @import '~view-design/src/styles/index.less';
2 | @primary-color: #579fff;
3 | @success-color: #40d2bd;
4 | @warning-color: #fe8896;
5 | //@btn-primary-bg: #2c93e6;
6 | @error-color: #de4943;
7 | @font-size-base : 12px;
8 |
--------------------------------------------------------------------------------
/src/styles/unlock.css:
--------------------------------------------------------------------------------
1 | .unlock-body-con {
2 | position: absolute;
3 | width: 400px;
4 | height: 100px;
5 | left: 50%;
6 | top: 50%;
7 | margin-left: -200px;
8 | margin-top: -200px;
9 | transform-origin: center center;
10 | z-index: 10;
11 | }
12 | .unlock-body-con .unlock-avator-con {
13 | position: absolute;
14 | left: 50%;
15 | top: 50%;
16 | transform: translate(-50%, -50%);
17 | box-sizing: border-box;
18 | width: 100px;
19 | height: 100px;
20 | border-radius: 50%;
21 | overflow: hidden;
22 | border: 2px solid white;
23 | cursor: pointer;
24 | transition: all 0.5s;
25 | z-index: 12;
26 | box-shadow: 0 0 10px 2px rgba(255, 255, 255, 0.3);
27 | }
28 | .unlock-body-con .unlock-avator-con .unlock-avator-img {
29 | width: 100%;
30 | height: 100%;
31 | display: block;
32 | z-index: 7;
33 | }
34 | .unlock-body-con .unlock-avator-con .unlock-avator-cover {
35 | width: 100%;
36 | height: 100%;
37 | background: rgba(0, 0, 0, 0.6);
38 | z-index: 11600;
39 | position: absolute;
40 | left: 0;
41 | top: 0;
42 | opacity: 0;
43 | transition: opacity 0.2s;
44 | color: white;
45 | }
46 | .unlock-body-con .unlock-avator-con .unlock-avator-cover span {
47 | display: block;
48 | margin: 20px auto 5px;
49 | text-align: center;
50 | }
51 | .unlock-body-con .unlock-avator-con .unlock-avator-cover p {
52 | text-align: center;
53 | font-size: 16px;
54 | font-weight: 500;
55 | }
56 | .unlock-body-con .unlock-avator-con:hover .unlock-avator-cover {
57 | opacity: 1;
58 | transition: opacity 0.2s;
59 | }
60 | .unlock-body-con .unlock-avator-under-back {
61 | position: absolute;
62 | left: 50%;
63 | top: 50%;
64 | transform: translate(-45px, -50%);
65 | box-sizing: border-box;
66 | width: 100px;
67 | height: 100px;
68 | border-radius: 50%;
69 | background: #667aa6;
70 | transition: all 0.5s;
71 | z-index: 5;
72 | }
73 | .unlock-body-con .unlock-input-con {
74 | position: absolute;
75 | height: 70px;
76 | width: 350px;
77 | top: 15px;
78 | right: 0;
79 | }
80 | .unlock-body-con .unlock-input-con .unlock-input-overflow-con {
81 | position: absolute;
82 | width: 100%;
83 | height: 100%;
84 | left: 0;
85 | top: 0;
86 | overflow: hidden;
87 | }
88 | .unlock-body-con .unlock-input-con .unlock-input-overflow-con .unlock-overflow-body {
89 | position: absolute;
90 | top: 0;
91 | right: 0;
92 | width: 100%;
93 | height: 100%;
94 | transition: all 0.5s ease 0.5s;
95 | }
96 | .unlock-body-con .unlock-input-con .unlock-input-overflow-con .unlock-overflow-body .unlock-input {
97 | float: left;
98 | display: block;
99 | box-sizing: content-box;
100 | height: 22px;
101 | width: 230px;
102 | font-size: 18px;
103 | outline: none;
104 | padding: 11px 10px 11px 30px;
105 | border: 2px solid #e2ddde;
106 | margin-top: 10px;
107 | }
108 | .unlock-body-con .unlock-input-con .unlock-input-overflow-con .unlock-overflow-body .unlock-btn {
109 | float: left;
110 | display: block;
111 | font-size: 20px;
112 | padding: 7px 30px;
113 | cursor: pointer;
114 | border-radius: 0 25px 25px 0;
115 | border: 2px solid #e2ddde;
116 | border-left: none;
117 | background: #2d8cf0;
118 | outline: none;
119 | transition: all 0.2s;
120 | margin-top: 10px;
121 | }
122 | .unlock-body-con .unlock-input-con .unlock-input-overflow-con .unlock-overflow-body .unlock-btn:hover {
123 | background: #5cadff;
124 | box-shadow: 0 0 10px 3px rgba(255, 255, 255, 0.2);
125 | }
126 | .unlock-body-con .unlock-input-con .unlock-input-overflow-con .unlock-overflow-body .click-unlock-btn {
127 | background: #2b85e4 !important;
128 | }
129 | .unlock-body-con .unlock-locking-tip-con {
130 | width: 100px;
131 | height: 30px;
132 | text-align: center;
133 | position: absolute;
134 | left: 50%;
135 | margin-left: -50px;
136 | bottom: -80px;
137 | color: white;
138 | font-size: 18px;
139 | }
140 | @keyframes unlock-in {
141 | 0% {
142 | transform: scale(0);
143 | }
144 | 80% {
145 | transform: scale(0);
146 | }
147 | 88% {
148 | transform: scale(1.3);
149 | }
150 | 100% {
151 | transform: scale(1);
152 | }
153 | }
154 | @keyframes unlock-out {
155 | 0% {
156 | transform: scale(1);
157 | }
158 | 60% {
159 | transform: scale(1.2);
160 | }
161 | 100% {
162 | transform: scale(0);
163 | }
164 | }
165 | .show-unlock-enter-active {
166 | animation: unlock-in 1.4s ease;
167 | }
168 | .show-unlock-leave-to {
169 | opacity: 0;
170 | }
171 | .show-unlock-leave-active {
172 | transition: opacity 0.2s;
173 | }
174 |
--------------------------------------------------------------------------------
/src/styles/unlock.less:
--------------------------------------------------------------------------------
1 | .unlock-body-con {
2 | position: absolute;
3 | width: 400px;
4 | height: 100px;
5 | left: 50%;
6 | top: 50%;
7 | margin-left: -200px;
8 | margin-top: -200px;
9 | transform-origin: center center;
10 | z-index: 10;
11 |
12 | .unlock-avator-con {
13 | position: absolute;
14 | left: 50%;
15 | top: 50%;
16 | transform: translate(-50%,-50%);
17 | box-sizing: border-box;
18 | width: 100px;
19 | height: 100px;
20 | border-radius: 50%;
21 | overflow: hidden;
22 | border: 2px solid white;
23 | cursor: pointer;
24 | transition: all 0.5s;
25 | z-index: 12;
26 | box-shadow: 0 0 10px 2px rgba(255, 255, 255, .3);
27 |
28 | .unlock-avator-img {
29 | width: 100%;
30 | height: 100%;
31 | display: block;
32 | z-index: 7;
33 | }
34 |
35 | .unlock-avator-cover {
36 | width: 100%;
37 | height: 100%;
38 | background: rgba(0, 0, 0, .6);
39 | z-index: 11600;
40 | position: absolute;
41 | left: 0;
42 | top: 0;
43 | opacity: 0;
44 | transition: opacity 0.2s;
45 | color: white;
46 |
47 | span {
48 | display: block;
49 | margin: 20px auto 5px;
50 | text-align: center;
51 | }
52 |
53 | p {
54 | text-align: center;
55 | font-size: 16px;
56 | font-weight: 500;
57 | }
58 | }
59 |
60 | &:hover .unlock-avator-cover {
61 | opacity: 1;
62 | transition: opacity 0.2s;
63 | }
64 | }
65 |
66 | .unlock-avator-under-back {
67 | position: absolute;
68 | left: 50%;
69 | top: 50%;
70 | transform: translate(-45px,-50%);
71 | box-sizing: border-box;
72 | width: 100px;
73 | height: 100px;
74 | border-radius: 50%;
75 | background: #667aa6;
76 | transition: all 0.5s;
77 | z-index: 5;
78 | }
79 |
80 | .unlock-input-con {
81 | position: absolute;
82 | height: 70px;
83 | width: 350px;
84 | top: 15px;
85 | right: 0;
86 |
87 | .unlock-input-overflow-con {
88 | position: absolute;
89 | width: 100%;
90 | height: 100%;
91 | left: 0;
92 | top: 0;
93 | overflow: hidden;
94 |
95 | .unlock-overflow-body {
96 | position: absolute;
97 | top: 0;
98 | right: 0;
99 | width: 100%;
100 | height: 100%;
101 | transition: all 0.5s ease 0.5s;
102 |
103 | .unlock-input {
104 | float: left;
105 | display: block;
106 | box-sizing: content-box;
107 | height: 22px;
108 | width: 230px;
109 | font-size: 18px;
110 | outline: none;
111 | padding: 11px 10px 11px 30px;
112 | border: 2px solid #e2ddde;
113 | margin-top: 10px;
114 | }
115 |
116 | .unlock-btn {
117 | float: left;
118 | display: block;
119 | font-size: 20px;
120 | padding: 7px 30px;
121 | cursor: pointer;
122 | border-radius: 0 25px 25px 0;
123 | border: 2px solid #e2ddde;
124 | border-left: none;
125 | background: #2d8cf0;
126 | outline: none;
127 | transition: all 0.2s;
128 | margin-top: 10px;
129 |
130 | &:hover {
131 | background: #5cadff;
132 | box-shadow: 0 0 10px 3px rgba(255, 255, 255, .2);
133 | }
134 | }
135 |
136 | .click-unlock-btn {
137 | background: #2b85e4 !important;
138 | }
139 | }
140 | }
141 | }
142 |
143 | .unlock-locking-tip-con {
144 | width: 100px;
145 | height: 30px;
146 | text-align: center;
147 | position: absolute;
148 | left: 50%;
149 | margin-left: -50px;
150 | bottom: -80px;
151 | color: white;
152 | font-size: 18px;
153 | }
154 | }
155 | @keyframes unlock-in {
156 | 0% {
157 | transform: scale(0);
158 | }
159 |
160 | 80% {
161 | transform: scale(0);
162 | }
163 |
164 | 88% {
165 | transform: scale(1.3);
166 | }
167 |
168 | 100% {
169 | transform: scale(1);
170 | }
171 | }
172 | @keyframes unlock-out {
173 | 0% {
174 | transform: scale(1);
175 | }
176 |
177 | 60% {
178 | transform: scale(1.2);
179 | }
180 |
181 | 100% {
182 | transform: scale(0);
183 | }
184 | }
185 |
186 | .show-unlock-enter-active {
187 | animation: unlock-in 1.4s ease;
188 | }
189 |
190 | .show-unlock-leave-to {
191 | opacity: 0;
192 | }
193 |
194 | .show-unlock-leave-active {
195 | transition: opacity 0.2s;
196 | }
197 |
--------------------------------------------------------------------------------
/src/views/audit/order/osc.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
{{osc.percent}}%
19 |
20 | 当前正在执行第
21 | {{osc.current}}
22 | 条
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
91 |
92 |
95 |
--------------------------------------------------------------------------------
/src/views/audit/order/reject.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SQL工单驳回理由说明
6 |
7 |
9 |
10 |
11 |
12 |
51 |
52 |
55 |
--------------------------------------------------------------------------------
/src/views/audit/query/audit.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 | 查询审核
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
29 |
32 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
104 |
105 |
108 |
--------------------------------------------------------------------------------
/src/views/board.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 公告
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
45 |
46 |
49 |
--------------------------------------------------------------------------------
/src/views/home/orderChart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
88 |
89 |
--------------------------------------------------------------------------------
/src/views/home/sourcePie.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
74 |
75 |
--------------------------------------------------------------------------------
/src/views/login/render.ts:
--------------------------------------------------------------------------------
1 | import {CreateElement} from "vue";
2 | import module_general from "@/store/modules/general";
3 |
4 | export const loginRender = (t: CreateElement | undefined) => {
5 | let h = t as CreateElement
6 | return h('div', [
7 | h('br'),
8 | h('Input', {
9 | props: {
10 | value: module_general.password,
11 | type: 'password',
12 | autofocus: true,
13 | placeholder: '请输入密码'
14 | },
15 | on: {
16 | input: (val: string) => {
17 | module_general.changed_ReLogin_password(val);
18 | }
19 | }
20 | }),
21 | h('br'),
22 | h('br'),
23 | h('checkbox', {
24 | props: {
25 | value: module_general.openReLogin,
26 | },
27 | style: {
28 | marginLeft: '40%'
29 | },
30 | on: {
31 | 'on-change': (val: boolean) => {
32 | module_general.changed_openReLogin_status(val)
33 | }
34 | }
35 | }, 'ldap登录')
36 | ])
37 | }
--------------------------------------------------------------------------------
/src/views/manage/group/allCheck.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 全选
7 |
8 |
9 |
10 | {{ i }}
11 |
12 |
13 |
14 |
15 |
16 |
81 |
82 |
--------------------------------------------------------------------------------
/src/views/manage/role/role.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 返回顶端
5 |
6 |
7 |
8 | 审核规则
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
36 |
37 |
38 |
39 |
94 |
95 |
105 |
--------------------------------------------------------------------------------
/src/views/manage/user/types.ts:
--------------------------------------------------------------------------------
1 | interface DependUser {
2 | source: source[]
3 | grained: grained[]
4 | }
5 |
6 | interface source {
7 | source: string
8 | }
9 |
10 | interface grained {
11 | name: string
12 | }
13 |
14 | interface UserInfo {
15 | username: string;
16 | password: string;
17 | confirm_password: string;
18 | rule: string;
19 | department: string;
20 | email: string;
21 | real_name: string;
22 | }
23 |
24 | export {
25 | DependUser,
26 | UserInfo
27 | }
--------------------------------------------------------------------------------
/src/views/order/basicList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 我的工单
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/views/order/myOrder.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 我的工单
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
31 |
32 |
33 |
106 |
107 |
--------------------------------------------------------------------------------
/src/views/order/order.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
21 |
--------------------------------------------------------------------------------
/src/views/personal/personal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
30 |
31 |
32 | {{ $t('dash.edit_permissions') }}
33 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
113 |
114 |
--------------------------------------------------------------------------------
/src/views/query/multiSource.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
112 |
113 |
116 |
--------------------------------------------------------------------------------
/src/views/query/refer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 |
69 |
70 |
99 |
--------------------------------------------------------------------------------
/src/views/query/workFlow.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 | 注意事项:
12 |
13 | 1.必须填写查询说明
14 |
15 | 2.根据查询条件预估所需的查询时间
16 |
17 | 3.所有提交的查询语句均会进行审计记录
18 |
19 | 4.仅支持查询语句,不可使用非查询语句
20 |
21 | 5.已限制最大limit数,如自己输入的limit数大于平台配置的最大limit数则以平台配置的Limit数为准
22 |
23 |
24 |
25 |
26 |
54 |
55 |
56 |
57 |
59 |
60 |
61 |
62 |
63 |
134 |
135 |
162 |
--------------------------------------------------------------------------------
/src/views/records/order.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 历史工单执行记录
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
39 |
40 |
41 |
113 |
114 |
118 |
--------------------------------------------------------------------------------
/src/views/records/query.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 查询审计
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
100 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": true,
13 | "baseUrl": ".",
14 | "types": [
15 | "webpack-env"
16 | ],
17 | "paths": {
18 | "@/*": [
19 | "src/*"
20 | ]
21 | },
22 | "lib": [
23 | "esnext",
24 | "dom",
25 | "dom.iterable",
26 | "scripthost"
27 | ]
28 | },
29 | "include": [
30 | "src/**/*.ts",
31 | "src/**/*.tsx",
32 | "src/**/*.vue",
33 | "tests/**/*.ts",
34 | "tests/**/*.tsx"
35 | ],
36 | "exclude": [
37 | "node_modules"
38 | ],
39 | "noImplicitAny": false
40 | }
41 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const TerserPlugin = require('terser-webpack-plugin')
2 | module.exports = {
3 | publicPath: '/front',
4 | assetsDir: './assets',
5 | css: {
6 | loaderOptions: { // 向 CSS 相关的 loader 传递选项
7 | less: {
8 | javascriptEnabled: true
9 | }
10 | }
11 | },
12 | runtimeCompiler: true,
13 | productionSourceMap: false,
14 | devServer: {
15 | proxy: 'http://localhost:8000'
16 | },
17 | configureWebpack: (config)=>{
18 | if(process.env.NODE_ENV === 'production'){
19 | config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------