├── .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 | ![LICENSE](https://img.shields.io/badge/license-AGPL%20-blue.svg) 8 | ![](https://img.shields.io/badge/build-release-brightgreen.svg)   9 | ![](https://img.shields.io/badge/version-v2.0.0-brightgreen.svg) 10 | ![](https://img.shields.io/badge/webpack-v4.0.0-brightgreen.svg) 11 | 12 | ## Feature 13 | Mysql SQL语句审核平台 Yearning 前端页面代码 14 | 15 | ## Website 16 | [www.yearning.io](http://yearning.io) 17 | 18 | ## Snapshot 19 | 20 | ![](img/login.png) 21 | 22 | ![](img/dash.png) 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 | 5 | 8 | 9 | 3 10 | Created with Sketch. 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 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 | 7 | 8 | 19 | -------------------------------------------------------------------------------- /src/components/countUp.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | 15 | 108 | -------------------------------------------------------------------------------- /src/components/customForm/customForm.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 65 | 66 | -------------------------------------------------------------------------------- /src/components/editor.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 82 | -------------------------------------------------------------------------------- /src/components/expandTable.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /src/components/inforCard.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 | 35 | -------------------------------------------------------------------------------- /src/components/locking-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | -------------------------------------------------------------------------------- /src/components/modal/changePassword.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 138 | 139 | 142 | -------------------------------------------------------------------------------- /src/components/modal/editProfile.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 77 | 78 | 81 | -------------------------------------------------------------------------------- /src/components/modal/rulesLimits.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 94 | -------------------------------------------------------------------------------- /src/components/order/orderConfirm.vue: -------------------------------------------------------------------------------- 1 | 59 | 60 | 71 | 72 | 75 | -------------------------------------------------------------------------------- /src/components/order/orderForm.vue: -------------------------------------------------------------------------------- 1 | 70 | 71 | 108 | 109 | > 121 | -------------------------------------------------------------------------------- /src/components/order/orderFormContainer.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 42 | 43 | -------------------------------------------------------------------------------- /src/components/order/orderIsPost.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 50 | 51 | 57 | -------------------------------------------------------------------------------- /src/components/order/orderSteps.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /src/components/profile/basic.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 53 | 54 | -------------------------------------------------------------------------------- /src/components/profile/collapse.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 50 | 51 | -------------------------------------------------------------------------------- /src/components/profile/postForm.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 121 | 122 | -------------------------------------------------------------------------------- /src/components/profile/profile.vue: -------------------------------------------------------------------------------- 1 | 59 | 60 | 95 | 96 | 108 | -------------------------------------------------------------------------------- /src/components/profile/queryProfile.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | -------------------------------------------------------------------------------- /src/components/profile/stepDetail.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 49 | 50 | -------------------------------------------------------------------------------- /src/components/search/navSearch.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 100 | 101 | -------------------------------------------------------------------------------- /src/components/search/search.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 58 | 59 | -------------------------------------------------------------------------------- /src/components/sidebarMenu.vue: -------------------------------------------------------------------------------- 1 | 50 | 82 | 83 | 88 | -------------------------------------------------------------------------------- /src/components/unlock.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | 32 | 80 | -------------------------------------------------------------------------------- /src/framework.vue: -------------------------------------------------------------------------------- 1 | 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 | 29 | 30 | 91 | 92 | 95 | -------------------------------------------------------------------------------- /src/views/audit/order/reject.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 51 | 52 | 55 | -------------------------------------------------------------------------------- /src/views/audit/query/audit.vue: -------------------------------------------------------------------------------- 1 | 4 | 44 | 45 | 104 | 105 | 108 | -------------------------------------------------------------------------------- /src/views/board.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 45 | 46 | 49 | -------------------------------------------------------------------------------- /src/views/home/orderChart.vue: -------------------------------------------------------------------------------- 1 | 6 | 88 | 89 | -------------------------------------------------------------------------------- /src/views/home/sourcePie.vue: -------------------------------------------------------------------------------- 1 | 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 | 15 | 16 | 81 | 82 | -------------------------------------------------------------------------------- /src/views/manage/role/role.vue: -------------------------------------------------------------------------------- 1 | 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 | 31 | 32 | -------------------------------------------------------------------------------- /src/views/order/myOrder.vue: -------------------------------------------------------------------------------- 1 | 5 | 33 | 106 | 107 | -------------------------------------------------------------------------------- /src/views/order/order.vue: -------------------------------------------------------------------------------- 1 | 10 | 21 | -------------------------------------------------------------------------------- /src/views/personal/personal.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 113 | 114 | -------------------------------------------------------------------------------- /src/views/query/multiSource.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 112 | 113 | 116 | -------------------------------------------------------------------------------- /src/views/query/refer.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 69 | 70 | 99 | -------------------------------------------------------------------------------- /src/views/query/workFlow.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 134 | 135 | 162 | -------------------------------------------------------------------------------- /src/views/records/order.vue: -------------------------------------------------------------------------------- 1 | 41 | 113 | 114 | 118 | -------------------------------------------------------------------------------- /src/views/records/query.vue: -------------------------------------------------------------------------------- 1 | 5 | 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 | --------------------------------------------------------------------------------