@@ -0,0 +1,14 @@ | |||
# https://editorconfig.org | |||
root = true | |||
[*] | |||
charset = utf-8 | |||
indent_style = space | |||
indent_size = 2 | |||
end_of_line = lf | |||
insert_final_newline = true | |||
trim_trailing_whitespace = true | |||
[*.md] | |||
insert_final_newline = false | |||
trim_trailing_whitespace = false |
@@ -0,0 +1,9 @@ | |||
ENV = 'development' | |||
# 接口地址 | |||
VUE_APP_BASE_API = 'http://localhost:8008' | |||
#VUE_APP_BASE_API = 'http://192.168.10.107:8008' | |||
VUE_APP_WS_API = 'ws://localhost:8000' | |||
# 是否启用 babel-plugin-dynamic-import-node插件 | |||
VUE_CLI_BABEL_TRANSPILE_MODULES = true |
@@ -0,0 +1,7 @@ | |||
ENV = 'production' | |||
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置 | |||
# 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http | |||
VUE_APP_BASE_API = '' | |||
# 如果接口是 http 形式, wss 需要改为 ws | |||
VUE_APP_WS_API = '/' |
@@ -0,0 +1,4 @@ | |||
build/*.js | |||
src/assets | |||
public | |||
dist |
@@ -0,0 +1,198 @@ | |||
module.exports = { | |||
root: true, | |||
parserOptions: { | |||
parser: 'babel-eslint', | |||
sourceType: 'module' | |||
}, | |||
env: { | |||
browser: true, | |||
node: true, | |||
es6: true, | |||
}, | |||
extends: ['plugin:vue/recommended', 'eslint:recommended'], | |||
// add your custom rules here | |||
//it is base on https://github.com/vuejs/eslint-config-vue | |||
rules: { | |||
"vue/max-attributes-per-line": [2, { | |||
"singleline": 10, | |||
"multiline": { | |||
"max": 1, | |||
"allowFirstLine": false | |||
} | |||
}], | |||
"vue/singleline-html-element-content-newline": "off", | |||
"vue/multiline-html-element-content-newline":"off", | |||
"vue/name-property-casing": ["error", "PascalCase"], | |||
"vue/no-v-html": "off", | |||
'accessor-pairs': 2, | |||
'arrow-spacing': [2, { | |||
'before': true, | |||
'after': true | |||
}], | |||
'block-spacing': [2, 'always'], | |||
'brace-style': [2, '1tbs', { | |||
'allowSingleLine': true | |||
}], | |||
'camelcase': [0, { | |||
'properties': 'always' | |||
}], | |||
'comma-dangle': [2, 'never'], | |||
'comma-spacing': [2, { | |||
'before': false, | |||
'after': true | |||
}], | |||
'comma-style': [2, 'last'], | |||
'constructor-super': 2, | |||
'curly': [2, 'multi-line'], | |||
'dot-location': [2, 'property'], | |||
'eol-last': 2, | |||
'eqeqeq': ["error", "always", {"null": "ignore"}], | |||
'generator-star-spacing': [2, { | |||
'before': true, | |||
'after': true | |||
}], | |||
'handle-callback-err': [2, '^(err|error)$'], | |||
'indent': [2, 2, { | |||
'SwitchCase': 1 | |||
}], | |||
'jsx-quotes': [2, 'prefer-single'], | |||
'key-spacing': [2, { | |||
'beforeColon': false, | |||
'afterColon': true | |||
}], | |||
'keyword-spacing': [2, { | |||
'before': true, | |||
'after': true | |||
}], | |||
'new-cap': [2, { | |||
'newIsCap': true, | |||
'capIsNew': false | |||
}], | |||
'new-parens': 2, | |||
'no-array-constructor': 2, | |||
'no-caller': 2, | |||
'no-console': 'off', | |||
'no-class-assign': 2, | |||
'no-cond-assign': 2, | |||
'no-const-assign': 2, | |||
'no-control-regex': 0, | |||
'no-delete-var': 2, | |||
'no-dupe-args': 2, | |||
'no-dupe-class-members': 2, | |||
'no-dupe-keys': 2, | |||
'no-duplicate-case': 2, | |||
'no-empty-character-class': 2, | |||
'no-empty-pattern': 2, | |||
'no-eval': 2, | |||
'no-ex-assign': 2, | |||
'no-extend-native': 2, | |||
'no-extra-bind': 2, | |||
'no-extra-boolean-cast': 2, | |||
'no-extra-parens': [2, 'functions'], | |||
'no-fallthrough': 2, | |||
'no-floating-decimal': 2, | |||
'no-func-assign': 2, | |||
'no-implied-eval': 2, | |||
'no-inner-declarations': [2, 'functions'], | |||
'no-invalid-regexp': 2, | |||
'no-irregular-whitespace': 2, | |||
'no-iterator': 2, | |||
'no-label-var': 2, | |||
'no-labels': [2, { | |||
'allowLoop': false, | |||
'allowSwitch': false | |||
}], | |||
'no-lone-blocks': 2, | |||
'no-mixed-spaces-and-tabs': 2, | |||
'no-multi-spaces': 2, | |||
'no-multi-str': 2, | |||
'no-multiple-empty-lines': [2, { | |||
'max': 1 | |||
}], | |||
'no-native-reassign': 2, | |||
'no-negated-in-lhs': 2, | |||
'no-new-object': 2, | |||
'no-new-require': 2, | |||
'no-new-symbol': 2, | |||
'no-new-wrappers': 2, | |||
'no-obj-calls': 2, | |||
'no-octal': 2, | |||
'no-octal-escape': 2, | |||
'no-path-concat': 2, | |||
'no-proto': 2, | |||
'no-redeclare': 2, | |||
'no-regex-spaces': 2, | |||
'no-return-assign': [2, 'except-parens'], | |||
'no-self-assign': 2, | |||
'no-self-compare': 2, | |||
'no-sequences': 2, | |||
'no-shadow-restricted-names': 2, | |||
'no-spaced-func': 2, | |||
'no-sparse-arrays': 2, | |||
'no-this-before-super': 2, | |||
'no-throw-literal': 2, | |||
'no-trailing-spaces': 2, | |||
'no-undef': 2, | |||
'no-undef-init': 2, | |||
'no-unexpected-multiline': 2, | |||
'no-unmodified-loop-condition': 2, | |||
'no-unneeded-ternary': [2, { | |||
'defaultAssignment': false | |||
}], | |||
'no-unreachable': 2, | |||
'no-unsafe-finally': 2, | |||
'no-unused-vars': [2, { | |||
'vars': 'all', | |||
'args': 'none' | |||
}], | |||
'no-useless-call': 2, | |||
'no-useless-computed-key': 2, | |||
'no-useless-constructor': 2, | |||
'no-useless-escape': 0, | |||
'no-whitespace-before-property': 2, | |||
'no-with': 2, | |||
'one-var': [2, { | |||
'initialized': 'never' | |||
}], | |||
'operator-linebreak': [2, 'after', { | |||
'overrides': { | |||
'?': 'before', | |||
':': 'before' | |||
} | |||
}], | |||
'padded-blocks': [2, 'never'], | |||
'quotes': [2, 'single', { | |||
'avoidEscape': true, | |||
'allowTemplateLiterals': true | |||
}], | |||
'semi': [2, 'never'], | |||
'semi-spacing': [2, { | |||
'before': false, | |||
'after': true | |||
}], | |||
'space-before-blocks': [2, 'always'], | |||
'space-before-function-paren': [2, 'never'], | |||
'space-in-parens': [2, 'never'], | |||
'space-infix-ops': 2, | |||
'space-unary-ops': [2, { | |||
'words': true, | |||
'nonwords': false | |||
}], | |||
'spaced-comment': [2, 'always', { | |||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] | |||
}], | |||
'template-curly-spacing': [2, 'never'], | |||
'use-isnan': 2, | |||
'valid-typeof': 2, | |||
'wrap-iife': [2, 'any'], | |||
'yield-star-spacing': [2, 'both'], | |||
'yoda': [2, 'never'], | |||
'prefer-const': 2, | |||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, | |||
'object-curly-spacing': [2, 'always', { | |||
objectsInObjects: false | |||
}], | |||
'array-bracket-spacing': [2, 'never'] | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<projectDescription> | |||
<name>eladmin-web</name> | |||
<comment></comment> | |||
<projects> | |||
</projects> | |||
<buildSpec> | |||
<buildCommand> | |||
<name>com.aptana.ide.core.unifiedBuilder</name> | |||
<arguments> | |||
</arguments> | |||
</buildCommand> | |||
</buildSpec> | |||
<natures> | |||
<nature>com.aptana.projects.webnature</nature> | |||
</natures> | |||
<filteredResources> | |||
<filter> | |||
<id>1655869280269</id> | |||
<name></name> | |||
<type>26</type> | |||
<matcher> | |||
<id>org.eclipse.ui.ide.multiFilter</id> | |||
<arguments>1.0-name-matches-false-false-node_modules</arguments> | |||
</matcher> | |||
</filter> | |||
</filteredResources> | |||
</projectDescription> |
@@ -0,0 +1 @@ | |||
12 |
@@ -0,0 +1 @@ | |||
12 |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1574649300337" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4312" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M877.952 447.616v-0.256a272 272 0 0 0-479.68-175.68 166.144 166.144 0 0 0-226.016 155.296c0 4.768 0.32 9.6 0.704 14.144A196.896 196.896 0 0 0 206.592 832H448v-256H304l208-208 208 208H576v256h241.408a196.96 196.96 0 0 0 60.544-384.384z" fill="#cdcdcd" p-id="4313"></path></svg> |
@@ -0,0 +1,105 @@ | |||
<template> | |||
<div :class="className" :style="{height:height,width:width}" /> | |||
</template> | |||
<script> | |||
import echarts from 'echarts' | |||
require('echarts/theme/macarons') // echarts theme | |||
import { debounce } from '@/utils' | |||
export default { | |||
props: { | |||
className: { | |||
type: String, | |||
default: 'chart' | |||
}, | |||
width: { | |||
type: String, | |||
default: '100%' | |||
}, | |||
height: { | |||
type: String, | |||
default: '300px' | |||
} | |||
}, | |||
data() { | |||
return { | |||
chart: null | |||
} | |||
}, | |||
mounted() { | |||
this.initChart() | |||
this.__resizeHandler = debounce(() => { | |||
if (this.chart) { | |||
this.chart.resize() | |||
} | |||
}, 100) | |||
window.addEventListener('resize', this.__resizeHandler) | |||
}, | |||
beforeDestroy() { | |||
if (!this.chart) { | |||
return | |||
} | |||
window.removeEventListener('resize', this.__resizeHandler) | |||
this.chart.dispose() | |||
this.chart = null | |||
}, | |||
methods: { | |||
initChart() { | |||
this.chart = echarts.init(this.$el, 'macarons') | |||
this.chart.setOption({ | |||
tooltip: { | |||
position: 'top' | |||
}, | |||
animation: false, | |||
grid: { | |||
height: '50%', | |||
y: '10%' | |||
}, | |||
xAxis: { | |||
type: 'category', | |||
data: ['12a', '1a', '2a', '3a', '4a', '5a', '6a', '7a', '8a', '9a', '10a', '11a', '12p', '1p', '2p', '3p', '4p', '5p', '6p', '7p', '8p', '9p', '10p', '11p'], | |||
splitArea: { | |||
show: true | |||
} | |||
}, | |||
yAxis: { | |||
type: 'category', | |||
data: ['Saturday', 'Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday', 'Sunday'], | |||
splitArea: { | |||
show: true | |||
} | |||
}, | |||
visualMap: { | |||
min: 0, | |||
max: 10, | |||
calculable: true, | |||
orient: 'horizontal', | |||
left: 'center', | |||
bottom: '15%' | |||
}, | |||
series: [{ | |||
name: 'Punch Card', | |||
type: 'heatmap', | |||
data: [[0, 0, 5], [0, 1, 1], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 2], [0, 12, 4], [0, 13, 1], [0, 14, 1], [0, 15, 3], [0, 16, 4], [0, 17, 6], [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5], [1, 0, 7], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0], [1, 5, 0], [1, 6, 0], [1, 7, 0], [1, 8, 0], [1, 9, 0], [1, 10, 5], [1, 11, 2], [1, 12, 2], [1, 13, 6], [1, 14, 9], [1, 15, 11], [1, 16, 6], [1, 17, 7], [1, 18, 8], [1, 19, 12], [1, 20, 5], [1, 21, 5], [1, 22, 7], [1, 23, 2], [2, 0, 1], [2, 1, 1], [2, 2, 0], [2, 3, 0], [2, 4, 0], [2, 5, 0], [2, 6, 0], [2, 7, 0], [2, 8, 0], [2, 9, 0], [2, 10, 3], [2, 11, 2], [2, 12, 1], [2, 13, 9], [2, 14, 8], [2, 15, 10], [2, 16, 6], [2, 17, 5], [2, 18, 5], [2, 19, 5], [2, 20, 7], [2, 21, 4], [2, 22, 2], [2, 23, 4], [3, 0, 7], [3, 1, 3], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0], [3, 6, 0], [3, 7, 0], [3, 8, 1], [3, 9, 0], [3, 10, 5], [3, 11, 4], [3, 12, 7], [3, 13, 14], [3, 14, 13], [3, 15, 12], [3, 16, 9], [3, 17, 5], [3, 18, 5], [3, 19, 10], [3, 20, 6], [3, 21, 4], [3, 22, 4], [3, 23, 1], [4, 0, 1], [4, 1, 3], [4, 2, 0], [4, 3, 0], [4, 4, 0], [4, 5, 1], [4, 6, 0], [4, 7, 0], [4, 8, 0], [4, 9, 2], [4, 10, 4], [4, 11, 4], [4, 12, 2], [4, 13, 4], [4, 14, 4], [4, 15, 14], [4, 16, 12], [4, 17, 1], [4, 18, 8], [4, 19, 5], [4, 20, 3], [4, 21, 7], [4, 22, 3], [4, 23, 0], [5, 0, 2], [5, 1, 1], [5, 2, 0], [5, 3, 3], [5, 4, 0], [5, 5, 0], [5, 6, 0], [5, 7, 0], [5, 8, 2], [5, 9, 0], [5, 10, 4], [5, 11, 1], [5, 12, 5], [5, 13, 10], [5, 14, 5], [5, 15, 7], [5, 16, 11], [5, 17, 6], [5, 18, 0], [5, 19, 5], [5, 20, 3], [5, 21, 4], [5, 22, 2], [5, 23, 0], [6, 0, 1], [6, 1, 0], [6, 2, 0], [6, 3, 0], [6, 4, 0], [6, 5, 0], [6, 6, 0], [6, 7, 0], [6, 8, 0], [6, 9, 0], [6, 10, 1], [6, 11, 0], [6, 12, 2], [6, 13, 1], [6, 14, 3], [6, 15, 4], [6, 16, 0], [6, 17, 0], [6, 18, 0], [6, 19, 0], [6, 20, 1], [6, 21, 2], [6, 22, 2], [6, 23, 6]].map(function(item) { | |||
return [item[1], item[0], item[2] || '-'] | |||
}), | |||
label: { | |||
normal: { | |||
show: true | |||
} | |||
}, | |||
itemStyle: { | |||
emphasis: { | |||
shadowBlur: 10, | |||
shadowColor: 'rgba(0, 0, 0, 0.5)' | |||
} | |||
} | |||
}] | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,715 @@ | |||
<template> | |||
<div class="app-container"> | |||
<div style="margin-bottom:10px"> | |||
<el-button type="success" @click="addBtn">新增</el-button> | |||
<el-button type="success" @click="importBtn">导入</el-button> | |||
<el-button type="success" @click="exportTempBtn">模版下载</el-button> | |||
</div> | |||
<!--搜索--> | |||
<el-form class="mt_15" ref="form" inline size="small"> | |||
<el-form-item label="店铺"> | |||
<el-input v-model.trim="searchParm.shop" clearable placeholder='店铺'></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单ID"> | |||
<el-input v-model.trim="searchParm.orderId" clearable placeholder='订单ID'></el-input> | |||
</el-form-item> | |||
<el-form-item label="公司"> | |||
<el-select v-model.trim="searchParm.companyId" placeholder="请选择"> | |||
<el-option v-for="item in companys" :key="item.name" :label="item.name" :value="item.id"></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="类型"> | |||
<el-select v-model.trim="searchParm.status" placeholder="请选择"> | |||
<el-option | |||
v-for="item in typeList" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="状态"> | |||
<el-select v-model.trim="searchParm.status" placeholder="请选择"> | |||
<el-option | |||
v-for="item in statusList" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-date-picker | |||
v-model.trim="searchTime" | |||
type="daterange" | |||
range-separator=":" | |||
start-placeholder="开始日期" | |||
end-placeholder="结束日期" | |||
style="width:270px" | |||
></el-date-picker> | |||
<el-form-item> | |||
<el-button type="primary" @click="goSearch">搜索</el-button> | |||
<el-button type="warning" @click="resetForm">重置</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!--表格渲染--> | |||
<el-table ref="table" border size="small" :data="list" :header-cell-style="{textAlign:'center'}" :cell-style="{textAlign:'center'}"> | |||
<el-table-column label="序号" type="index" width="50" /> | |||
<el-table-column label="公司名称" prop="companyName" /> | |||
<el-table-column label="类型" prop="type" align="center"> | |||
<template slot-scope="scope"> | |||
{{ scope.row.type | getListType}} | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="总金额" prop="amount" /> | |||
<el-table-column label="店铺名称" prop="shop" /> | |||
<el-table-column label="订单ID" prop="orderId" /> | |||
<el-table-column label="评论" prop="comment" :formatter="commentSub"/> | |||
<!--<el-table-column label="状态" prop="status" align="center"> | |||
<template slot-scope="scope"> | |||
{{ scope.row.status | getStatus}} | |||
</template> | |||
</el-table-column>--> | |||
<el-table-column label="创建时间" prop="createdAt" /> | |||
<el-table-column label="修改时间" prop="updatedAt" /> | |||
<el-table-column label="操作" width="300"> | |||
<template slot-scope="scope"> | |||
<el-button type="info" @click="getBtnById(scope.row.id)">查看</el-button> | |||
<el-button type="warning" @click="editById(scope.row)">评论</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页--> | |||
<div class="mt_15"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="searchParm.page" | |||
:page-sizes="[10, 20, 30, 40, 50]" | |||
:page-size="searchParm.pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total"> | |||
</el-pagination> | |||
</div> | |||
<!--新增弹窗--> | |||
<el-dialog :visible.sync="dialogAddVisible" :title="dialogAddTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="addParm" size="small" :model="addParm" :rules="rules" label-width="130px"> | |||
<el-form-item label="公司" prop="companyId"> | |||
<el-select v-model.trim="addParm.companyId" placeholder="请选择"> | |||
<el-option | |||
v-for="item in companys" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="总金额" prop="amount"> | |||
<el-input v-model.trim="addParm.amount" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="状态描述" prop="paymentResults"> | |||
<el-input v-model.trim="addParm.paymentResults" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="购买数量" prop="pricesNumber"> | |||
<el-input v-model.trim="addParm.pricesNumber" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="商品名称" prop="shopName"> | |||
<el-input v-model.trim="addParm.shopName" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="时间" prop="orderDate"> | |||
<el-input v-model.trim="addParm.orderDate" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="店铺名称" prop="shop"> | |||
<el-input v-model.trim="addParm.shop" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单id" prop="orderId"> | |||
<el-input v-model.trim="addParm.orderId" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="评论" prop="comment"> | |||
<el-input v-model.trim="addParm.comment" clearable></el-input> | |||
</el-form-item> | |||
<el-input v-model.trim="addParm.paths" type="hidden" clearable></el-input> | |||
<el-upload | |||
class="upload-demo" | |||
:data = "updateFileType" | |||
:action="uploadFileImgUrl" | |||
:on-preview="handlePreview" | |||
:headers="uploadHeaders" | |||
:on-remove="handleRemove" | |||
:on-success="uploadImgSuccess" | |||
:before-upload="beforeImgUpload" | |||
:before-remove="beforeRemove" | |||
:file-list="fileList" | |||
list-type="picture"> | |||
<el-button size="small" type="primary">点击上传</el-button> | |||
<div slot="tip" class="el-upload__tip">只能上传img/jpg/png/jpeg文件,且不超过5M</div> | |||
</el-upload> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureAddCancle('addParm')">取消</el-button> | |||
<el-button type="primary" @click="sureAdd('addParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--评论弹窗--> | |||
<el-dialog :visible.sync="dialogEditVisible" :title="dialogEditTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="editParm" size="small" :model="editParm" :rules="rules" label-width="130px"> | |||
<el-form-item label="评论" prop="accountcommentName"> | |||
<el-input v-model.trim="editParm.comment" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
<el-input v-model.trim="editParm.paths" type="hidden" clearable></el-input> | |||
<el-upload | |||
class="upload-demo" | |||
:data = "updateFileType" | |||
:action="uploadFileImgUrl" | |||
:on-preview="handlePreview" | |||
:headers="uploadHeaders" | |||
:on-remove="handleRemove" | |||
:on-success="uploadImgSuccess" | |||
:before-upload="beforeImgUpload" | |||
:before-remove="beforeRemove" | |||
:file-list="fileList" | |||
list-type="picture"> | |||
<el-button size="small" type="primary">点击上传</el-button> | |||
<div slot="tip" class="el-upload__tip">只能上传img/jpg/png/jpeg文件,且不超过5M</div> | |||
</el-upload> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureEditCancle('editParm')">取消</el-button> | |||
<el-button type="primary" @click="sureEdit('editParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--详情弹窗--> | |||
<el-dialog :visible.sync="dialogDetailVisible" :title="dialogDetailTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="130px"> | |||
<el-form-item label="公司" prop="companyId"> | |||
<el-select v-model.trim="detailParm.companyId" disabled> | |||
<el-option | |||
v-for="item in companys" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="总金额" prop="amount"> | |||
<el-input v-model.trim="detailParm.amount" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="店铺名称" prop="shop"> | |||
<el-input v-model.trim="detailParm.shop" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="商品名称" prop="shopName"> | |||
<el-input v-model.trim="detailParm.shopName" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单id" prop="orderId"> | |||
<el-input v-model.trim="detailParm.orderId" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="评论" prop="comment"> | |||
<el-input v-model.trim="detailParm.comment" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="时间" prop="orderDate"> | |||
<el-input v-model.trim="detailParm.orderDate" disabled></el-input> | |||
</el-form-item> | |||
<el-upload | |||
class="upload-demo" | |||
:data = "updateFileType" | |||
:action="uploadFileImgUrl" | |||
:on-preview="handlePreview" | |||
:headers="uploadHeaders" | |||
:on-remove="handleRemove" | |||
:on-success="uploadImgSuccess" | |||
:file-list="fileList" | |||
list-type="picture"> | |||
</el-upload> | |||
</el-form> | |||
</div> | |||
</el-dialog> | |||
<!--订单信息导入 importBtn--> | |||
<el-dialog :visible.sync="dialogImportVisible" :title="dialogImportTitle" center width="23%"> | |||
<div class="dialog-content"> | |||
<el-upload | |||
class="upload-demo" | |||
drag | |||
ref="upload" | |||
:action="uploadFileUrl" | |||
:headers="uploadHeaders" | |||
:show-file-list = "false" | |||
:on-success="uploadSuccess" | |||
:before-remove="beforeRemove" | |||
:before-upload="beforeAvatarUpload" | |||
multiple> | |||
<i class="el-icon-upload"></i> | |||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> | |||
<div class="el-upload__tip" slot="tip">只能上传Excel文件,且不超过5M</div> | |||
</el-upload> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { add, getDetailById, commentFun, getList } from '@/api/group/clickOrder'; | |||
import { getAll } from "@/api/group/company"; | |||
import { doMainName } from "@/api/group/fileUpload"; | |||
export default { | |||
filters: { | |||
// getStatus: function (value) { | |||
// // 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 | |||
// if(value == 1) { | |||
// return '待执行'; | |||
// } else if (value == 2) { | |||
// return '执行中'; | |||
// } else if (value == 3) { | |||
// return '执行成功'; | |||
// } else if(value == 4) { | |||
// return '执行失败'; | |||
// } else { | |||
// return '执行失败'; | |||
// } | |||
// }, | |||
getListType: function (value) { | |||
// 类型:1.导入 2.刷单 | |||
if(value == 1) { | |||
return '导入'; | |||
} else if (value == 2) { | |||
return '刷单'; | |||
} | |||
} | |||
}, | |||
// 数据 | |||
data() { | |||
return { | |||
searchParm: { | |||
page: 1, | |||
pageSize: 10, | |||
sort:'created_at', | |||
order:'desc', | |||
accountName:null, | |||
robotClientUuid:null, | |||
sTime: null, | |||
eTime: null, | |||
shop: null, | |||
orderId: null, | |||
companyId: null, | |||
type: null, | |||
status: null | |||
}, | |||
total:0, | |||
list: [], | |||
fileList:[], | |||
doMainNameUrl: null, | |||
typeList: [ | |||
{ | |||
id: 1, | |||
name: "导入" | |||
}, | |||
{ | |||
id: 2, | |||
name: "刷单" | |||
} | |||
], | |||
statusList: [ | |||
{ | |||
id: 1, | |||
name: "待执行" | |||
}, | |||
{ | |||
id: 2, | |||
name: "执行中" | |||
}, | |||
{ | |||
id: 3, | |||
name: "执行成功" | |||
}, | |||
{ | |||
id: 4, | |||
name: "执行失败" | |||
} | |||
], | |||
uploadHeaders:{ Authorization: this.$store.getters.token }, | |||
dialogAddVisible: false, | |||
dialogAddTitle: '新增', | |||
dialogDetailVisible: false, | |||
dialogDetailTitle: '详情', | |||
dialogEditVisible: false, | |||
dialogEditTitle: '修改', | |||
dialogImportVisible: false, | |||
dialogImportTitle:'导入', | |||
searchTime: "", | |||
updateFileType: {type: 12}, | |||
uploadFileImgUrl: process.env.VUE_APP_BASE_API + '/api/file/uploadFile', | |||
uploadFileUrl: process.env.VUE_APP_BASE_API + '/api/clickOrder/import', | |||
tempUrl: process.env.VUE_APP_BASE_API + '/api/clickOrder/exportTemp', | |||
fileImages:{ | |||
name: null, | |||
url: null | |||
}, | |||
addParm: { | |||
id:null, | |||
companyId:null, | |||
paymentResults:null, | |||
pricesNumber:null, | |||
shopName:null, | |||
orderDate:null, | |||
amount:null, | |||
shop:null, | |||
orderId:null, | |||
comment:null, | |||
paths: [] | |||
}, | |||
detailParm: { | |||
id:null, | |||
companyId:null, | |||
amount:null, | |||
shop:null, | |||
shopName: null, | |||
orderDate: null, | |||
orderId:null, | |||
comment:null, | |||
paths:[] | |||
}, | |||
editParm: { | |||
id:null, | |||
comment:null, | |||
paths:[] | |||
}, | |||
companys: [], | |||
rules: { | |||
companyId: [ | |||
{ required: true, message: '请输入公司', trigger: 'blur' } | |||
], | |||
amount: [ | |||
{ required: true, message: '请输入总金额', trigger: 'blur' } | |||
], | |||
paymentResults: [ | |||
{ required: true, message: '请输入状态描述', trigger: 'blur' } | |||
], | |||
pricesNumber: [ | |||
{ required: true, message: '请输入购买数量', trigger: 'blur' } | |||
], | |||
shopName: [ | |||
{ required: true, message: '请输入商品名称', trigger: 'blur' } | |||
], | |||
shop: [ | |||
{ required: true, message: '请输入店铺名称', trigger: 'blur' } | |||
], | |||
orderDate: [ | |||
{ required: true, message: '请输入时间', trigger: 'blur' } | |||
], | |||
orderId: [ | |||
{ required: true, message: '请输入订单ID', trigger: 'blur' } | |||
] | |||
}, | |||
} | |||
}, | |||
// 调用 | |||
created() { | |||
this.getFileDoMainName(); | |||
this.getCompanyAll(); | |||
this.goSearch(); | |||
this.fileList = []; | |||
}, | |||
//方法 | |||
methods: { | |||
// 图片上传 | |||
handleRemove(file, fileList) { | |||
console.log(fileList) | |||
this.editParm.paths = []; | |||
for (let i = 0; i < fileList.length; i++) { | |||
const imgUrl = fileList[i].url; | |||
if (imgUrl.includes("/file/")) { | |||
imgUrl = imgUrl.substring(imgUrl.lastIndexOf("\/file\/") + 5, imgUrl.length); | |||
this.editParm.paths.push(imgUrl); | |||
} | |||
} | |||
}, | |||
handlePreview(file) { | |||
console.log("======handlePreview======="); | |||
console.log(file); | |||
}, | |||
uploadImgSuccess(res, file) { | |||
if(res.code==200) { | |||
const index = res.data.list[0].path.lastIndexOf("\/"); | |||
this.fileImages.name = res.data.list[0].path.substring(index + 1, res.data.list[0].path.length); | |||
this.fileImages.url = this.doMainNameUrl + res.data.list[0].path; | |||
this.editParm.paths.push(res.data.list[0].path); | |||
} | |||
}, | |||
//重置 | |||
resetForm() { | |||
this.searchParm.shop = null; | |||
this.searchParm.orderId = null; | |||
this.searchParm.companyId = null; | |||
this.searchParm.type = null; | |||
this.searchParm.status = null; | |||
this.searchTime = ""; | |||
this.goSearch(); | |||
}, | |||
// 获取所有公司信息 | |||
getCompanyAll() { | |||
getAll() | |||
.then(res => { | |||
if (res.code == 200) { | |||
this.companys = res.data; | |||
} | |||
}) | |||
.catch(() => {}); | |||
}, | |||
// 评论截取 | |||
commentSub(row, column) { | |||
if (row['comment'] != "undefined" && row['comment'] != null && row['comment'] != "" && row['comment'] != "null" && row['comment'] != "NULL") { | |||
return row['comment'].slice(0,3) + "..."; | |||
} | |||
}, | |||
// 查询 | |||
goSearch() { | |||
this.searchParm.sTime = this.searchTime[0]; | |||
this.searchParm.eTime = this.searchTime[1]; | |||
this.searchParm.page=1 | |||
this.getDataList() | |||
}, | |||
// 获取图片域名请求url fileDoMainName | |||
getFileDoMainName() { | |||
doMainName().then(res => { | |||
if(res.code==200) { | |||
this.doMainNameUrl = res.data; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
//导入成功 | |||
uploadSuccess(res, file) { | |||
this.dialogImportVisible = false; | |||
if(res.code==200) { | |||
if(res.data == true) { | |||
this.$message.success('导入成功!'); | |||
} | |||
else{ | |||
window.location.href = res.data; | |||
this.$message.error('导入失败!'); | |||
} | |||
} | |||
this.goSearch(); | |||
}, | |||
beforeAvatarUpload(file) { | |||
console.log(file); | |||
const isLt10M = file.size / 1024 / 1024 <10; | |||
if (!isLt10M) { | |||
this.$message.error('上传Excel文件大小不能超过 10MB!'); | |||
} | |||
return isLt10M; | |||
}, | |||
beforeRemove(file, fileList) { | |||
return this.$confirm(`确定移除 ${ file.name }?`); | |||
}, | |||
beforeImgUpload(file) { | |||
console.log(file); | |||
const isXlsImg = file.type === 'image/img'; | |||
const isXlsJpg = file.type === 'image/jpg'; | |||
const isXlsPng = file.type === 'image/png'; | |||
const isXlsJpeg = file.type === 'image/jpeg'; | |||
console.log("isXlsImg:" + isXlsImg); | |||
console.log("isXlsJpg:" + isXlsJpg); | |||
console.log("isXlsPng:" + isXlsPng); | |||
console.log("isXlsJpeg:" + isXlsJpeg); | |||
const isLt10M = file.size / 1024 / 1024 < 5; | |||
const isXls = true; | |||
if (!isXlsImg && !isXlsJpg && !isXlsPng && !isXlsJpeg) { | |||
this.$message.error('上传头像图片只能是img/jpg/png/jpeg 格式!'); | |||
isXls = false; | |||
} | |||
const isLt5M = file.size / 1024 / 1024 <5; | |||
if (!isLt5M) { | |||
this.$message.error('上传Excel文件大小不能超过 5MB!'); | |||
} | |||
return isXls && isLt5M; | |||
}, | |||
// 导入 | |||
importBtn() { | |||
this.dialogImportVisible = true | |||
}, | |||
//机器人模板 | |||
exportTempBtn() { | |||
console.log(this.tempUrl) | |||
window.location.href = this.tempUrl; | |||
}, | |||
// 新增 | |||
addBtn(){ | |||
this.addParm = { | |||
id:null, | |||
companyId:null, | |||
account:null, | |||
pwd:null, | |||
amount:null, | |||
shop:null, | |||
orderId:null, | |||
comment:null, | |||
paths: [] | |||
} | |||
this.fileList = [] | |||
this.dialogAddTitle='新增' | |||
this.dialogAddVisible = true; | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 修改 | |||
editById(data){ | |||
this.fileList = []; | |||
this.editParm.paths = []; | |||
this.editParm.comment = null; | |||
getDetailById({id: data.id}).then(res => { | |||
if(res.code==200) { | |||
this.editParm.id = res.data.id; | |||
this.editParm.comment = res.data.comment; | |||
if (res.data.paths != "undefined" && res.data.paths != null && res.data.paths != "" &&res.data.paths != "null" && res.data.paths != "NULL") { | |||
this.editParm.paths = res.data.paths.split(','); | |||
this.fileList = res.data.paths.split(',').map(val => { | |||
// return {url:"http://localhost:8008/file" + val} | |||
return {name: val.substring(val.lastIndexOf("\/") + 1, val.length), url: this.doMainNameUrl + val} | |||
console.log("url:" + val); | |||
}) | |||
console.log(this.fileList) | |||
} | |||
console.log("this.editParm.paths:" + this.editParm.paths); | |||
this.dialogEditVisible = true | |||
this.$refs.editParm.clearValidate(); | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 确认修改 | |||
sureEdit(editParm){ | |||
this.$refs[editParm].validate((valid) => { | |||
if (valid) { | |||
this.$refs.editParm.clearValidate(); | |||
this.editParm.paths = this.editParm.paths.toString() | |||
commentFun(this.editParm).then(res => { | |||
if(res.code==200) { | |||
console.log(res) | |||
this.dialogEditVisible = false | |||
this.$message.success('修改成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
} else { | |||
console.log('error submit!!'); | |||
return false; | |||
} | |||
}); | |||
}, | |||
sureAddCancle(editParm) { | |||
this.dialogEditVisible=flase | |||
this.$refs.editParm.clearValidate(); | |||
}, | |||
// 确认新增 | |||
sureAdd(addParm){ | |||
this.$refs[addParm].validate((valid) => { | |||
if (valid) { | |||
this.$refs.addParm.clearValidate(); | |||
this.addParm.paths = this.addParm.paths.toString() | |||
console.log(this.addParm) | |||
add(this.addParm).then(res => { | |||
if(res.code==200) { | |||
this.dialogAddVisible = false | |||
this.$message.success('新增成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
} else { | |||
console.log('error submit!!'); | |||
return false; | |||
} | |||
}); | |||
}, | |||
sureAddCancle(addParm) { | |||
this.dialogAddVisible=flase | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 查看根据id | |||
getBtnById(id){ | |||
getDetailById({id}).then(res => { | |||
if(res.code==200) { | |||
this.detailParm.id = res.data.id; | |||
this.detailParm.companyId = res.data.companyId; | |||
this.detailParm.amount = res.data.amount; | |||
this.detailParm.shop = res.data.shop; | |||
this.detailParm.orderId = res.data.orderId; | |||
this.detailParm.comment = res.data.comment; | |||
this.detailParm.shopName = res.data.shopName; | |||
this.detailParm.orderDate = res.data.orderDate; | |||
this.detailParm.paths = res.data.paths; | |||
this.fileList = []; | |||
if (res.data.paths != "undefined" && res.data.paths != null && res.data.paths != "" &&res.data.paths != "null" && res.data.paths != "NULL") { | |||
this.detailParm.paths = res.data.paths.split(','); | |||
} | |||
if (this.detailParm.paths != "undefined" && this.detailParm.paths != null && this.detailParm.paths != "" && this.detailParm.paths != "null" && this.detailParm.paths != "NULL") { | |||
this.detailParm.paths = res.data.paths.split(',') | |||
this.fileList = res.data.paths.split(',').map(val => { | |||
// return {url:"http://localhost:8008/file" + val} | |||
return {name: val.substring(val.lastIndexOf("\/") + 1, val.length), url: this.doMainNameUrl + val} | |||
}) | |||
console.log(this.fileList) | |||
} | |||
this.dialogDetailVisible = true; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页获取表格数据 | |||
getDataList(){ | |||
getList(this.searchParm).then(res => { | |||
console.log(res) | |||
if(res.code==200) { | |||
console.log(res) | |||
this.list = res.data.list; | |||
this.total = res.data.total; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页 | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.searchParm.pageSize = val; | |||
this.getDataList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.searchParm.page = val; | |||
this.getDataList(); | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
</style> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="2807" t="1547195013953" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#cdcdcd" d="M529.0496 527.616l-30.7712-30.7456 85.0688-85.0944 30.7712 30.7712z" p-id="2808"/><path fill="#cdcdcd" d="M0 340.48l427.52 256 248.32 427.52L1024 0l-1024 340.48zM665.6 921.6l-207.36-355.84-355.84-212.48L911.36 81.92l-243.2 243.2 30.72 30.72 243.2-243.2L665.6 921.6z" p-id="2809"/></svg> |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1574649142168" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1910" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M468.693333 16.725333a85.333333 85.333333 0 0 1 82.56 0l381.952 211.072a85.333333 85.333333 0 0 1 44.074667 74.666667v419.029333a85.333333 85.333333 0 0 1-44.074667 74.666667l-381.952 211.114667a85.333333 85.333333 0 0 1-82.56 0l-381.952-211.072A85.333333 85.333333 0 0 1 42.666667 721.493333V302.506667a85.333333 85.333333 0 0 1 44.074666-74.666667L468.693333 16.682667z m423.253334 285.781334l-381.994667-211.072L128 302.506667v418.986666l381.952 211.072 381.994667-211.072V302.506667z m-684.714667 42.197333a42.666667 42.666667 0 0 1 57.984-16.725333l244.736 135.253333 244.778667-135.253333a42.666667 42.666667 0 0 1 41.258666 74.666666l-243.370666 134.528v268.16a42.666667 42.666667 0 0 1-85.333334 0V537.173333L223.914667 402.688a42.666667 42.666667 0 0 1-16.682667-58.026667z" fill="#bfbfbf" p-id="1911"></path></svg> |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1546567861908" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2422" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M318.577778 819.2L17.066667 512l301.511111-307.2 45.511111 45.511111L96.711111 512l267.377778 261.688889zM705.422222 819.2l-45.511111-45.511111L927.288889 512l-267.377778-261.688889 45.511111-45.511111L1006.933333 512zM540.785778 221.866667l55.751111 11.150222L483.157333 802.133333l-55.751111-11.093333z" fill="#bfbfbf" p-id="2423"></path></svg> |
@@ -0,0 +1,34 @@ | |||
import request from '@/utils/request' | |||
export function getDicts() { | |||
return request({ | |||
url: 'api/dict/all', | |||
method: 'get' | |||
}) | |||
} | |||
export function add(data) { | |||
return request({ | |||
url: 'api/dict', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function del(ids) { | |||
return request({ | |||
url: 'api/dict/', | |||
method: 'delete', | |||
data: ids | |||
}) | |||
} | |||
export function edit(data) { | |||
return request({ | |||
url: 'api/dict', | |||
method: 'put', | |||
data | |||
}) | |||
} | |||
export default { add, edit, del } |
@@ -0,0 +1,149 @@ | |||
<template> | |||
<div :class="className" :style="{height:height,width:width}" /> | |||
</template> | |||
<script> | |||
import echarts from 'echarts' | |||
require('echarts/theme/macarons') // echarts theme | |||
import { debounce } from '@/utils' | |||
export default { | |||
props: { | |||
className: { | |||
type: String, | |||
default: 'chart' | |||
}, | |||
width: { | |||
type: String, | |||
default: '100%' | |||
}, | |||
height: { | |||
type: String, | |||
default: '500px' | |||
} | |||
}, | |||
data() { | |||
return { | |||
chart: null | |||
} | |||
}, | |||
mounted() { | |||
this.initChart() | |||
this.__resizeHandler = debounce(() => { | |||
if (this.chart) { | |||
this.chart.resize() | |||
} | |||
}, 100) | |||
window.addEventListener('resize', this.__resizeHandler) | |||
}, | |||
beforeDestroy() { | |||
if (!this.chart) { | |||
return | |||
} | |||
window.removeEventListener('resize', this.__resizeHandler) | |||
this.chart.dispose() | |||
this.chart = null | |||
}, | |||
methods: { | |||
initChart() { | |||
this.chart = echarts.init(this.$el, 'macarons') | |||
this.chart.setOption({ | |||
tooltip: { | |||
trigger: 'item', | |||
formatter: '{a} <br/>{b}: {c} ({d}%)' | |||
}, | |||
legend: { | |||
orient: 'vertical', | |||
x: 'left', | |||
data: ['直达', '营销广告', '搜索引擎', '邮件营销', '联盟广告', '视频广告', '百度', '谷歌', '必应', '其他'] | |||
}, | |||
series: [ | |||
{ | |||
name: '访问来源', | |||
type: 'pie', | |||
selectedMode: 'single', | |||
radius: [0, '30%'], | |||
label: { | |||
normal: { | |||
position: 'inner' | |||
} | |||
}, | |||
labelLine: { | |||
normal: { | |||
show: false | |||
} | |||
}, | |||
data: [ | |||
{ value: 335, name: '直达', selected: true }, | |||
{ value: 679, name: '营销广告' }, | |||
{ value: 1548, name: '搜索引擎' } | |||
] | |||
}, | |||
{ | |||
name: '访问来源', | |||
type: 'pie', | |||
radius: ['40%', '55%'], | |||
label: { | |||
normal: { | |||
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ', | |||
backgroundColor: '#eee', | |||
borderColor: '#aaa', | |||
borderWidth: 1, | |||
borderRadius: 4, | |||
shadowBlur: 3, | |||
shadowOffsetX: 2, | |||
shadowOffsetY: 2, | |||
shadowColor: '#999', | |||
padding: [0, 7], | |||
rich: { | |||
a: { | |||
color: '#999', | |||
lineHeight: 22, | |||
align: 'center' | |||
}, | |||
abg: { | |||
backgroundColor: '#333', | |||
width: '100%', | |||
align: 'right', | |||
height: 22, | |||
borderRadius: [4, 4, 0, 0] | |||
}, | |||
hr: { | |||
borderColor: '#aaa', | |||
width: '100%', | |||
borderWidth: 0.5, | |||
height: 0 | |||
}, | |||
b: { | |||
fontSize: 16, | |||
lineHeight: 33 | |||
}, | |||
per: { | |||
color: '#eee', | |||
backgroundColor: '#334455', | |||
padding: [2, 4], | |||
borderRadius: 2 | |||
} | |||
} | |||
} | |||
}, | |||
data: [ | |||
{ value: 335, name: '直达' }, | |||
{ value: 310, name: '邮件营销' }, | |||
{ value: 234, name: '联盟广告' }, | |||
{ value: 135, name: '视频广告' }, | |||
{ value: 1048, name: '百度' }, | |||
{ value: 251, name: '谷歌' }, | |||
{ value: 147, name: '必应' }, | |||
{ value: 102, name: '其他' } | |||
] | |||
} | |||
] | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,15 @@ | |||
import request from '@/utils/request' | |||
export function resetEmail(data) { | |||
return request({ | |||
url: 'api/code/resetEmail?email=' + data, | |||
method: 'post' | |||
}) | |||
} | |||
export function updatePass(pass) { | |||
return request({ | |||
url: 'api/users/updatePass/' + pass, | |||
method: 'get' | |||
}) | |||
} |
@@ -0,0 +1,36 @@ | |||
import variables from '@/assets/styles/element-variables.scss' | |||
import defaultSettings from '@/settings' | |||
const { tagsView, fixedHeader, sidebarLogo, showFooter, footerTxt, caseNumber } = defaultSettings | |||
const state = { | |||
theme: variables.theme, | |||
showSettings: false, | |||
tagsView: tagsView, | |||
fixedHeader: fixedHeader, | |||
sidebarLogo: sidebarLogo, | |||
showFooter: showFooter, | |||
footerTxt: footerTxt, | |||
caseNumber: caseNumber | |||
} | |||
const mutations = { | |||
CHANGE_SETTING: (state, { key, value }) => { | |||
if (state.hasOwnProperty(key)) { | |||
state[key] = value | |||
} | |||
} | |||
} | |||
const actions = { | |||
changeSetting({ commit }, data) { | |||
commit('CHANGE_SETTING', data) | |||
} | |||
} | |||
export default { | |||
namespaced: true, | |||
state, | |||
mutations, | |||
actions | |||
} | |||
@@ -0,0 +1 @@ | |||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg> |
@@ -0,0 +1,191 @@ | |||
Apache License | |||
Version 2.0, January 2004 | |||
http://www.apache.org/licenses/ | |||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||
1. Definitions. | |||
"License" shall mean the terms and conditions for use, reproduction, and | |||
distribution as defined by Sections 1 through 9 of this document. | |||
"Licensor" shall mean the copyright owner or entity authorized by the copyright | |||
owner that is granting the License. | |||
"Legal Entity" shall mean the union of the acting entity and all other entities | |||
that control, are controlled by, or are under common control with that entity. | |||
For the purposes of this definition, "control" means (i) the power, direct or | |||
indirect, to cause the direction or management of such entity, whether by | |||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||
outstanding shares, or (iii) beneficial ownership of such entity. | |||
"You" (or "Your") shall mean an individual or Legal Entity exercising | |||
permissions granted by this License. | |||
"Source" form shall mean the preferred form for making modifications, including | |||
but not limited to software source code, documentation source, and configuration | |||
files. | |||
"Object" form shall mean any form resulting from mechanical transformation or | |||
translation of a Source form, including but not limited to compiled object code, | |||
generated documentation, and conversions to other media types. | |||
"Work" shall mean the work of authorship, whether in Source or Object form, made | |||
available under the License, as indicated by a copyright notice that is included | |||
in or attached to the work (an example is provided in the Appendix below). | |||
"Derivative Works" shall mean any work, whether in Source or Object form, that | |||
is based on (or derived from) the Work and for which the editorial revisions, | |||
annotations, elaborations, or other modifications represent, as a whole, an | |||
original work of authorship. For the purposes of this License, Derivative Works | |||
shall not include works that remain separable from, or merely link (or bind by | |||
name) to the interfaces of, the Work and Derivative Works thereof. | |||
"Contribution" shall mean any work of authorship, including the original version | |||
of the Work and any modifications or additions to that Work or Derivative Works | |||
thereof, that is intentionally submitted to Licensor for inclusion in the Work | |||
by the copyright owner or by an individual or Legal Entity authorized to submit | |||
on behalf of the copyright owner. For the purposes of this definition, | |||
"submitted" means any form of electronic, verbal, or written communication sent | |||
to the Licensor or its representatives, including but not limited to | |||
communication on electronic mailing lists, source code control systems, and | |||
issue tracking systems that are managed by, or on behalf of, the Licensor for | |||
the purpose of discussing and improving the Work, but excluding communication | |||
that is conspicuously marked or otherwise designated in writing by the copyright | |||
owner as "Not a Contribution." | |||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf | |||
of whom a Contribution has been received by Licensor and subsequently | |||
incorporated within the Work. | |||
2. Grant of Copyright License. | |||
Subject to the terms and conditions of this License, each Contributor hereby | |||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | |||
irrevocable copyright license to reproduce, prepare Derivative Works of, | |||
publicly display, publicly perform, sublicense, and distribute the Work and such | |||
Derivative Works in Source or Object form. | |||
3. Grant of Patent License. | |||
Subject to the terms and conditions of this License, each Contributor hereby | |||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, | |||
irrevocable (except as stated in this section) patent license to make, have | |||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where | |||
such license applies only to those patent claims licensable by such Contributor | |||
that are necessarily infringed by their Contribution(s) alone or by combination | |||
of their Contribution(s) with the Work to which such Contribution(s) was | |||
submitted. If You institute patent litigation against any entity (including a | |||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a | |||
Contribution incorporated within the Work constitutes direct or contributory | |||
patent infringement, then any patent licenses granted to You under this License | |||
for that Work shall terminate as of the date such litigation is filed. | |||
4. Redistribution. | |||
You may reproduce and distribute copies of the Work or Derivative Works thereof | |||
in any medium, with or without modifications, and in Source or Object form, | |||
provided that You meet the following conditions: | |||
You must give any other recipients of the Work or Derivative Works a copy of | |||
this License; and | |||
You must cause any modified files to carry prominent notices stating that You | |||
changed the files; and | |||
You must retain, in the Source form of any Derivative Works that You distribute, | |||
all copyright, patent, trademark, and attribution notices from the Source form | |||
of the Work, excluding those notices that do not pertain to any part of the | |||
Derivative Works; and | |||
If the Work includes a "NOTICE" text file as part of its distribution, then any | |||
Derivative Works that You distribute must include a readable copy of the | |||
attribution notices contained within such NOTICE file, excluding those notices | |||
that do not pertain to any part of the Derivative Works, in at least one of the | |||
following places: within a NOTICE text file distributed as part of the | |||
Derivative Works; within the Source form or documentation, if provided along | |||
with the Derivative Works; or, within a display generated by the Derivative | |||
Works, if and wherever such third-party notices normally appear. The contents of | |||
the NOTICE file are for informational purposes only and do not modify the | |||
License. You may add Your own attribution notices within Derivative Works that | |||
You distribute, alongside or as an addendum to the NOTICE text from the Work, | |||
provided that such additional attribution notices cannot be construed as | |||
modifying the License. | |||
You may add Your own copyright statement to Your modifications and may provide | |||
additional or different license terms and conditions for use, reproduction, or | |||
distribution of Your modifications, or for any such Derivative Works as a whole, | |||
provided Your use, reproduction, and distribution of the Work otherwise complies | |||
with the conditions stated in this License. | |||
5. Submission of Contributions. | |||
Unless You explicitly state otherwise, any Contribution intentionally submitted | |||
for inclusion in the Work by You to the Licensor shall be under the terms and | |||
conditions of this License, without any additional terms or conditions. | |||
Notwithstanding the above, nothing herein shall supersede or modify the terms of | |||
any separate license agreement you may have executed with Licensor regarding | |||
such Contributions. | |||
6. Trademarks. | |||
This License does not grant permission to use the trade names, trademarks, | |||
service marks, or product names of the Licensor, except as required for | |||
reasonable and customary use in describing the origin of the Work and | |||
reproducing the content of the NOTICE file. | |||
7. Disclaimer of Warranty. | |||
Unless required by applicable law or agreed to in writing, Licensor provides the | |||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, | |||
including, without limitation, any warranties or conditions of TITLE, | |||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are | |||
solely responsible for determining the appropriateness of using or | |||
redistributing the Work and assume any risks associated with Your exercise of | |||
permissions under this License. | |||
8. Limitation of Liability. | |||
In no event and under no legal theory, whether in tort (including negligence), | |||
contract, or otherwise, unless required by applicable law (such as deliberate | |||
and grossly negligent acts) or agreed to in writing, shall any Contributor be | |||
liable to You for damages, including any direct, indirect, special, incidental, | |||
or consequential damages of any character arising as a result of this License or | |||
out of the use or inability to use the Work (including but not limited to | |||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or | |||
any and all other commercial damages or losses), even if such Contributor has | |||
been advised of the possibility of such damages. | |||
9. Accepting Warranty or Additional Liability. | |||
While redistributing the Work or Derivative Works thereof, You may choose to | |||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or | |||
other liability obligations and/or rights consistent with this License. However, | |||
in accepting such obligations, You may act only on Your own behalf and on Your | |||
sole responsibility, not on behalf of any other Contributor, and only if You | |||
agree to indemnify, defend, and hold each Contributor harmless for any liability | |||
incurred by, or claims asserted against, such Contributor by reason of your | |||
accepting any such warranty or additional liability. | |||
END OF TERMS AND CONDITIONS | |||
APPENDIX: How to apply the Apache License to your work | |||
To apply the Apache License to your work, attach the following boilerplate | |||
notice, with the fields enclosed by brackets "{}" replaced with your own | |||
identifying information. (Don't include the brackets!) The text should be | |||
enclosed in the appropriate comment syntax for the file format. We also | |||
recommend that a file or class name and description of purpose be included on | |||
the same "printed page" as the copyright notice for easier identification within | |||
third-party archives. | |||
Copyright 2019 Zheng Jie | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. |
@@ -0,0 +1,388 @@ | |||
/** | |||
* Created by PanJiaChen on 16/11/18. | |||
*/ | |||
/** | |||
* Parse the time to string | |||
* @param {(Object|string|number)} time | |||
* @param {string} cFormat | |||
* @returns {string} | |||
*/ | |||
export function parseTime(time, cFormat) { | |||
if (arguments.length === 0) { | |||
return null | |||
} | |||
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' | |||
let date | |||
if (typeof time === 'undefined' || time === null || time === 'null') { | |||
return '' | |||
} else if (typeof time === 'object') { | |||
date = time | |||
} else { | |||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { | |||
time = parseInt(time) | |||
} | |||
if ((typeof time === 'number') && (time.toString().length === 10)) { | |||
time = time * 1000 | |||
} | |||
date = new Date(time) | |||
} | |||
const formatObj = { | |||
y: date.getFullYear(), | |||
m: date.getMonth() + 1, | |||
d: date.getDate(), | |||
h: date.getHours(), | |||
i: date.getMinutes(), | |||
s: date.getSeconds(), | |||
a: date.getDay() | |||
} | |||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { | |||
let value = formatObj[key] | |||
// Note: getDay() returns 0 on Sunday | |||
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] } | |||
if (result.length > 0 && value < 10) { | |||
value = '0' + value | |||
} | |||
return value || 0 | |||
}) | |||
return time_str | |||
} | |||
/** | |||
* @param {number} time | |||
* @param {string} option | |||
* @returns {string} | |||
*/ | |||
export function formatTime(time, option) { | |||
if (('' + time).length === 10) { | |||
time = parseInt(time) * 1000 | |||
} else { | |||
time = +time | |||
} | |||
const d = new Date(time) | |||
const now = Date.now() | |||
const diff = (now - d) / 1000 | |||
if (diff < 30) { | |||
return '刚刚' | |||
} else if (diff < 3600) { | |||
// less 1 hour | |||
return Math.ceil(diff / 60) + '分钟前' | |||
} else if (diff < 3600 * 24) { | |||
return Math.ceil(diff / 3600) + '小时前' | |||
} else if (diff < 3600 * 24 * 2) { | |||
return '1天前' | |||
} | |||
if (option) { | |||
return parseTime(time, option) | |||
} else { | |||
return ( | |||
d.getMonth() + | |||
1 + | |||
'月' + | |||
d.getDate() + | |||
'日' + | |||
d.getHours() + | |||
'时' + | |||
d.getMinutes() + | |||
'分' | |||
) | |||
} | |||
} | |||
/** | |||
* @param {string} url | |||
* @returns {Object} | |||
*/ | |||
export function getQueryObject(url) { | |||
url = url == null ? window.location.href : url | |||
const search = url.substring(url.lastIndexOf('?') + 1) | |||
const obj = {} | |||
const reg = /([^?&=]+)=([^?&=]*)/g | |||
search.replace(reg, (rs, $1, $2) => { | |||
const name = decodeURIComponent($1) | |||
let val = decodeURIComponent($2) | |||
val = String(val) | |||
obj[name] = val | |||
return rs | |||
}) | |||
return obj | |||
} | |||
/** | |||
* @param {string} input value | |||
* @returns {number} output value | |||
*/ | |||
export function byteLength(str) { | |||
// returns the byte length of an utf8 string | |||
let s = str.length | |||
for (var i = str.length - 1; i >= 0; i--) { | |||
const code = str.charCodeAt(i) | |||
if (code > 0x7f && code <= 0x7ff) s++ | |||
else if (code > 0x7ff && code <= 0xffff) s += 2 | |||
if (code >= 0xDC00 && code <= 0xDFFF) i-- | |||
} | |||
return s | |||
} | |||
/** | |||
* @param {Array} actual | |||
* @returns {Array} | |||
*/ | |||
export function cleanArray(actual) { | |||
const newArray = [] | |||
for (let i = 0; i < actual.length; i++) { | |||
if (actual[i]) { | |||
newArray.push(actual[i]) | |||
} | |||
} | |||
return newArray | |||
} | |||
/** | |||
* @param {Object} json | |||
* @returns {Array} | |||
*/ | |||
export function param(json) { | |||
if (!json) return '' | |||
return cleanArray( | |||
Object.keys(json).map(key => { | |||
if (json[key] === undefined) return '' | |||
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) | |||
}) | |||
).join('&') | |||
} | |||
/** | |||
* @param {string} url | |||
* @returns {Object} | |||
*/ | |||
export function param2Obj(url) { | |||
const search = url.split('?')[1] | |||
if (!search) { | |||
return {} | |||
} | |||
return JSON.parse( | |||
'{"' + | |||
decodeURIComponent(search) | |||
.replace(/"/g, '\\"') | |||
.replace(/&/g, '","') | |||
.replace(/=/g, '":"') | |||
.replace(/\+/g, ' ') + | |||
'"}' | |||
) | |||
} | |||
/** | |||
* @param {string} val | |||
* @returns {string} | |||
*/ | |||
export function html2Text(val) { | |||
const div = document.createElement('div') | |||
div.innerHTML = val | |||
return div.textContent || div.innerText | |||
} | |||
/** | |||
* Merges two objects, giving the last one precedence | |||
* @param {Object} target | |||
* @param {(Object|Array)} source | |||
* @returns {Object} | |||
*/ | |||
export function objectMerge(target, source) { | |||
if (typeof target !== 'object') { | |||
target = {} | |||
} | |||
if (Array.isArray(source)) { | |||
return source.slice() | |||
} | |||
Object.keys(source).forEach(property => { | |||
const sourceProperty = source[property] | |||
if (typeof sourceProperty === 'object') { | |||
target[property] = objectMerge(target[property], sourceProperty) | |||
} else { | |||
target[property] = sourceProperty | |||
} | |||
}) | |||
return target | |||
} | |||
/** | |||
* @param {HTMLElement} element | |||
* @param {string} className | |||
*/ | |||
export function toggleClass(element, className) { | |||
if (!element || !className) { | |||
return | |||
} | |||
let classString = element.className | |||
const nameIndex = classString.indexOf(className) | |||
if (nameIndex === -1) { | |||
classString += '' + className | |||
} else { | |||
classString = | |||
classString.substr(0, nameIndex) + | |||
classString.substr(nameIndex + className.length) | |||
} | |||
element.className = classString | |||
} | |||
/** | |||
* @param {string} type | |||
* @returns {Date} | |||
*/ | |||
export function getTime(type) { | |||
if (type === 'start') { | |||
return new Date().getTime() - 3600 * 1000 * 24 * 90 | |||
} else { | |||
return new Date(new Date().toDateString()) | |||
} | |||
} | |||
/** | |||
* @param {Function} func | |||
* @param {number} wait | |||
* @param {boolean} immediate | |||
* @return {*} | |||
*/ | |||
export function debounce(func, wait, immediate) { | |||
let timeout, args, context, timestamp, result | |||
const later = function() { | |||
// 据上一次触发时间间隔 | |||
const last = +new Date() - timestamp | |||
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait | |||
if (last < wait && last > 0) { | |||
timeout = setTimeout(later, wait - last) | |||
} else { | |||
timeout = null | |||
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 | |||
if (!immediate) { | |||
result = func.apply(context, args) | |||
if (!timeout) context = args = null | |||
} | |||
} | |||
} | |||
return function(...args) { | |||
context = this | |||
timestamp = +new Date() | |||
const callNow = immediate && !timeout | |||
// 如果延时不存在,重新设定延时 | |||
if (!timeout) timeout = setTimeout(later, wait) | |||
if (callNow) { | |||
result = func.apply(context, args) | |||
context = args = null | |||
} | |||
return result | |||
} | |||
} | |||
/** | |||
* This is just a simple version of deep copy | |||
* Has a lot of edge cases bug | |||
* If you want to use a perfect deep copy, use lodash's _.cloneDeep | |||
* @param {Object} source | |||
* @returns {Object} | |||
*/ | |||
export function deepClone(source) { | |||
if (!source && typeof source !== 'object') { | |||
throw new Error('error arguments', 'deepClone') | |||
} | |||
const targetObj = source.constructor === Array ? [] : {} | |||
Object.keys(source).forEach(keys => { | |||
if (source[keys] && typeof source[keys] === 'object') { | |||
targetObj[keys] = deepClone(source[keys]) | |||
} else { | |||
targetObj[keys] = source[keys] | |||
} | |||
}) | |||
return targetObj | |||
} | |||
/** | |||
* @param {Array} arr | |||
* @returns {Array} | |||
*/ | |||
export function uniqueArr(arr) { | |||
return Array.from(new Set(arr)) | |||
} | |||
/** | |||
* @returns {string} | |||
*/ | |||
export function createUniqueString() { | |||
const timestamp = +new Date() + '' | |||
const randomNum = parseInt((1 + Math.random()) * 65536) + '' | |||
return (+(randomNum + timestamp)).toString(32) | |||
} | |||
/** | |||
* Check if an element has a class | |||
* @param {HTMLElement} elm | |||
* @param {string} cls | |||
* @returns {boolean} | |||
*/ | |||
export function hasClass(ele, cls) { | |||
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) | |||
} | |||
/** | |||
* Add class to element | |||
* @param {HTMLElement} elm | |||
* @param {string} cls | |||
*/ | |||
export function addClass(ele, cls) { | |||
if (!hasClass(ele, cls)) ele.className += ' ' + cls | |||
} | |||
/** | |||
* Remove class from element | |||
* @param {HTMLElement} elm | |||
* @param {string} cls | |||
*/ | |||
export function removeClass(ele, cls) { | |||
if (hasClass(ele, cls)) { | |||
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') | |||
ele.className = ele.className.replace(reg, ' ') | |||
} | |||
} | |||
// 替换邮箱字符 | |||
export function regEmail(email) { | |||
if (String(email).indexOf('@') > 0) { | |||
const str = email.split('@') | |||
let _s = '' | |||
if (str[0].length > 3) { | |||
for (var i = 0; i < str[0].length - 3; i++) { | |||
_s += '*' | |||
} | |||
} | |||
var new_email = str[0].substr(0, 3) + _s + '@' + str[1] | |||
} | |||
return new_email | |||
} | |||
// 替换手机字符 | |||
export function regMobile(mobile) { | |||
if (mobile.length > 7) { | |||
var new_mobile = mobile.substr(0, 3) + '****' + mobile.substr(7) | |||
} | |||
return new_mobile | |||
} | |||
// 下载文件 | |||
export function downloadFile(obj, name, suffix) { | |||
const url = window.URL.createObjectURL(new Blob([obj])) | |||
const link = document.createElement('a') | |||
link.style.display = 'none' | |||
link.href = url | |||
const fileName = parseTime(new Date()) + '-' + name + '.' + suffix | |||
link.setAttribute('download', fileName) | |||
document.body.appendChild(link) | |||
link.click() | |||
document.body.removeChild(link) | |||
} |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="1799" t="1553478255619" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#bfbfbf" d="M329.285097 317.714062l-8.422833 4.428869c-8.78099 4.584412-13.528108 14.84715-11.923564 24.415063 1.644453 4.909823 3.491521 9.864672 5.492084 14.747889 2.030239 4.854565 4.230348 9.652847 6.53688 14.293541 5.621021 7.891737 16.246009 11.824303 25.699312 8.858762l9.041934-2.868327c14.741749-3.860934 31.115672-0.056282 42.62582 11.512195 11.549034 11.526521 15.374152 27.863604 11.549034 42.570561l-2.882654 9.126868c-2.958378 9.438976 0.938372 20.042475 8.830109 25.706475 4.634554 2.328022 9.403161 4.52813 14.323217 6.529717 4.876054 2.043542 9.80839 3.846608 14.739702 5.478781 9.538237 1.603521 19.87363-3.123131 24.414039-11.910261l4.402263-8.388041c7.67889-13.144368 21.915126-22.002107 38.267559-22.002107 16.338107 0 30.547737 8.829086 38.255279 21.931498l4.41352 8.459672c4.584412 8.78713 14.84715 13.513782 24.414039 11.910261 4.91187-1.632173 9.851369-3.462868 14.734586-5.478781 4.882194-2.030239 9.66615-4.201695 14.322194-6.529717 7.891737-5.622044 11.809977-16.253172 8.843412-25.706475l-2.852978-9.041934c-3.859911-14.733563-0.069585-31.085996 11.484565-42.655496 11.55415-11.525498 27.878954-15.372106 42.599214-11.512195l9.097192 2.88163c9.426697 2.952238 20.044522-0.937348 25.693172-8.829086 2.313695-4.656043 4.527107-9.411347 6.54302-14.322194 2.029216-4.883217 3.847631-9.80839 5.495154-14.748912 1.616824-9.581216-3.108804-19.843954-11.911284-24.429389l-8.402367-4.400217c-13.132088-7.665587-21.98778-21.901823-21.98778-38.255279 0-16.32378 8.830109-30.589692 21.974477-38.268582l8.416693-4.443196c8.80248-4.571109 13.528108-14.832823 11.924587-24.400736-1.6465-4.910846-3.479241-9.850345-5.493108-14.733563-2.031263-4.868891-4.202719-9.680477-6.529717-14.308891-5.622044-7.890714-16.253172-11.82328-25.708522-8.842389l-9.05626 2.852978c-14.747889 3.861958-31.071669 0.057305-42.654472-11.512195-11.55415-11.55415-15.344476-27.877931-11.484565-42.612517l2.852978-9.05626c2.966565-9.44-0.951675-20.043499-8.856715-25.692149-4.641717-2.328022-9.397021-4.542456-14.307867-6.544043-4.883217-2.029216-9.82374-3.846608-14.734586-5.465478-9.567913-1.632173-19.872606 3.123131-24.414039 11.895935l-4.400217 8.389064c-7.67889 13.174044-21.931498 22.002107-38.268582 22.002107-16.309454 0-30.576389-8.828063-38.267559-22.002107l-4.387937-8.389064c-4.554736-8.771781-14.8318-13.528108-24.405853-11.895935-4.954849 1.604544-9.873882 3.435239-14.763239 5.4225-4.883217 2.044566-9.688663 4.217045-14.323217 6.545066-7.891737 5.649674-11.808954 16.266475-8.830109 25.735128l2.826372 9.05626c3.882424 14.762215 0.057305 31.085996-11.491729 42.612517-11.510148 11.5695-27.849278 15.373129-42.611493 11.526521l-9.070586-2.867304c-9.44-2.980891-20.063965 0.951675-25.686009 8.842389-2.342348 4.628414-4.52813 9.44-6.53688 14.308891-2.036379 4.882194-3.847631 9.822716-5.492084 14.733563-1.603521 9.581216 3.142573 19.85828 11.923564 24.443715l8.402367 4.400217c13.156648 7.67889 21.986757 21.944801 21.986757 38.268582C351.251388 295.79689 342.421278 310.019823 329.285097 317.714062zM511.977999 171.706687c59.532885 0 107.795075 48.275493 107.795075 107.779725 0 59.490929-48.26219 107.752096-107.795075 107.752096-59.533908 0-107.752096-48.26219-107.752096-107.752096C404.226926 219.98218 452.445114 171.706687 511.977999 171.706687z" p-id="1800"/><path fill="#bfbfbf" d="M924.647713 689.174212 798.570249 689.174212 798.570249 581.650313c0-26.387997-21.476127-47.850821-47.864124-47.850821L276.2543 533.799492c-26.386974 0-47.851844 21.462824-47.851844 47.850821l0 107.523899L99.345124 689.174212c-20.419052 0-36.95568 16.550954-36.95568 36.948517l0 184.771237c0 20.399609 16.536628 36.962843 36.95568 36.962843l273.965675 0c20.397562 0 36.947494-16.564257 36.947494-36.962843L410.258293 726.122729c0-20.398586-16.550954-36.948517-36.947494-36.948517l-123.103736 0L250.207064 581.650313c0-14.366196 11.68104-26.047236 26.047236-26.047236l474.451826 0c14.364149 0 26.062586 11.68104 26.062586 26.047236l0 107.523899L650.689201 689.174212c-20.412912 0-36.962843 16.550954-36.962843 36.948517l0 184.771237c0 20.399609 16.549931 36.962843 36.962843 36.962843l273.958512 0c20.397562 0 36.96182-16.564257 36.96182-36.962843L961.609533 726.122729C961.609533 705.725166 945.044252 689.174212 924.647713 689.174212z" p-id="1801"/></svg> |
@@ -0,0 +1,114 @@ | |||
{ | |||
"name": "eladmin-web", | |||
"version": "2.6.0", | |||
"description": "EL-ADMIN 前端源码", | |||
"author": "Zheng Jie", | |||
"license": "Apache-2.0", | |||
"scripts": { | |||
"dev": "vue-cli-service serve", | |||
"build:prod": "vue-cli-service build", | |||
"build:stage": "vue-cli-service build --mode staging", | |||
"preview": "node build/index.js --preview", | |||
"lint": "eslint --ext .js,.vue src", | |||
"test:unit": "jest --clearCache && vue-cli-service test:unit", | |||
"svgo": "svgo -f src/assets/icons/svg --config=src/assets/icons/svgo.yml", | |||
"new": "plop" | |||
}, | |||
"husky": { | |||
"hooks": { | |||
"pre-commit": "lint-staged" | |||
} | |||
}, | |||
"lint-staged": { | |||
"src/**/*.{js,vue}": [ | |||
"eslint --fix", | |||
"git add" | |||
] | |||
}, | |||
"repository": { | |||
"type": "git", | |||
"url": "https://github.com/elunez/eladmin-web.git" | |||
}, | |||
"bugs": { | |||
"url": "https://github.com/elunez/eladmin/issues" | |||
}, | |||
"dependencies": { | |||
"@riophae/vue-treeselect": "^0.4.0", | |||
"axios": "^0.21.1", | |||
"clipboard": "2.0.4", | |||
"codemirror": "^5.49.2", | |||
"core-js": "^2.6.12", | |||
"echarts": "^4.2.1", | |||
"echarts-wordcloud": "^1.1.3", | |||
"element-ui": "^2.15.8", | |||
"file-saver": "1.3.8", | |||
"fuse.js": "3.4.4", | |||
"js-beautify": "^1.10.2", | |||
"js-cookie": "2.2.0", | |||
"jsencrypt": "^3.0.0-rc.1", | |||
"jszip": "^3.7.1", | |||
"mavon-editor": "^2.9.1", | |||
"normalize.css": "7.0.0", | |||
"nprogress": "0.2.0", | |||
"path-to-regexp": "2.4.0", | |||
"qs": "^6.10.1", | |||
"screenfull": "4.2.0", | |||
"sortablejs": "1.8.4", | |||
"vue": "^2.6.14", | |||
"vue-count-to": "^1.0.13", | |||
"vue-cropper": "0.4.9", | |||
"vue-echarts": "^5.0.0-beta.0", | |||
"vue-image-crop-upload": "^2.5.0", | |||
"vue-json-viewer": "^2.2.22", | |||
"vue-router": "3.0.2", | |||
"vue-splitpane": "1.0.4", | |||
"vuedraggable": "2.20.0", | |||
"vuex": "3.1.0", | |||
"wangeditor": "^4.7.11", | |||
"xlsx": "^0.17.4" | |||
}, | |||
"devDependencies": { | |||
"@babel/parser": "^7.7.4", | |||
"@babel/register": "7.0.0", | |||
"@vue/babel-plugin-transform-vue-jsx": "^1.2.1", | |||
"@vue/cli-plugin-babel": "3.5.3", | |||
"@vue/cli-plugin-eslint": "^3.9.1", | |||
"@vue/cli-plugin-unit-jest": "3.5.3", | |||
"@vue/cli-service": "3.5.3", | |||
"@vue/test-utils": "1.0.0-beta.29", | |||
"autoprefixer": "^9.5.1", | |||
"babel-core": "7.0.0-bridge.0", | |||
"babel-eslint": "10.0.1", | |||
"babel-jest": "23.6.0", | |||
"babel-plugin-dynamic-import-node": "2.3.0", | |||
"babel-plugin-transform-remove-console": "^6.9.4", | |||
"chalk": "2.4.2", | |||
"chokidar": "2.1.5", | |||
"compression-webpack-plugin": "5.0.2", | |||
"connect": "3.6.6", | |||
"eslint": "5.15.3", | |||
"eslint-plugin-vue": "5.2.2", | |||
"html-webpack-plugin": "3.2.0", | |||
"http-proxy-middleware": "^0.19.1", | |||
"husky": "1.3.1", | |||
"lint-staged": "8.1.5", | |||
"plop": "2.3.0", | |||
"sass": "1.32.13", | |||
"sass-loader": "10.2.0", | |||
"script-ext-html-webpack-plugin": "2.1.3", | |||
"script-loader": "0.7.2", | |||
"serve-static": "^1.13.2", | |||
"svg-sprite-loader": "4.1.3", | |||
"svgo": "1.2.0", | |||
"tasksfile": "^5.1.1", | |||
"vue-template-compiler": "2.6.14" | |||
}, | |||
"engines": { | |||
"node": ">=8.9", | |||
"npm": ">= 3.0.0" | |||
}, | |||
"browserslist": [ | |||
"> 1%", | |||
"last 2 versions" | |||
] | |||
} |
@@ -0,0 +1,7 @@ | |||
const viewGenerator = require('./plop-templates/view/prompt') | |||
const componentGenerator = require('./plop-templates/component/prompt') | |||
module.exports = function(plop) { | |||
plop.setGenerator('view', viewGenerator) | |||
plop.setGenerator('component', componentGenerator) | |||
} |
@@ -0,0 +1,41 @@ | |||
import request from '@/utils/request' | |||
export function getList(data) { | |||
return request({ | |||
url: '/api/ctBrowse/list', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function add(data) { | |||
return request({ | |||
url: '/api/ctBrowse/add', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function editById(data) { | |||
return request({ | |||
url: '/api/ctBrowse/edit', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function getById(data) { | |||
return request({ | |||
url: '/api/ctBrowse/getById', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function deleteById(data) { | |||
return request({ | |||
url: '/api/ctBrowse/delete', | |||
method: 'post', | |||
data | |||
}) | |||
} |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="1989" t="1554009861477" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#8a8a8a" d="M756.081 1012.218 291.154 1012.218c-68.473 0-123.982-55.975-123.982-125.054L167.172 136.836c0-69.078 55.512-125.054 123.982-125.054l464.928 0c68.474 0 123.984 55.975 123.984 125.054l0 750.328C880.066 956.242 824.555 1012.218 756.081 1012.218L756.081 1012.218zM818.062 136.836c0-34.516-27.751-62.526-61.98-62.526L291.154 74.31c-34.228 0-61.991 28.01-61.991 62.526l0 31.268 588.899 0L818.062 136.836 818.062 136.836zM818.062 230.63 229.163 230.63l0 499.242 588.899 0L818.062 230.63 818.062 230.63zM818.062 792.398 229.163 792.398l0 94.766c0 34.54 27.765 62.526 61.991 62.526l464.928 0c34.229 0 61.98-27.986 61.98-62.526L818.062 792.398 818.062 792.398zM523.623 918.429c-25.668 0-46.482-20.993-46.482-46.896 0-25.903 20.816-46.895 46.482-46.895 25.664 0 46.477 20.993 46.477 46.895S549.287 918.429 523.623 918.429L523.623 918.429z" p-id="1990"/><path fill="#8a8a8a" d="M756.081 1017.218 291.154 1017.218c-71.121 0-128.982-58.342-128.982-130.054L162.172 136.836c0-71.712 57.861-130.054 128.982-130.054l464.928 0c71.122 0 128.984 58.342 128.984 130.054l0 750.328C885.066 958.876 827.204 1017.218 756.081 1017.218zM291.154 16.783c-65.607 0-118.982 53.856-118.982 120.054l0 750.328c0 66.198 53.375 120.054 118.982 120.054l464.927 0c65.608 0 118.985-53.855 118.985-120.054L875.066 136.836c0-66.198-53.376-120.054-118.984-120.054L291.154 16.782zM756.082 954.69 291.154 954.69c-36.939 0-66.991-30.292-66.991-67.526l0-99.766 598.899 0 0.001 99.766C823.063 924.398 793.016 954.69 756.082 954.69zM234.163 797.398l0 89.766c0 31.72 25.566 57.526 56.991 57.526l464.928 0c31.419 0 56.98-25.807 56.98-57.526l0-89.766L234.163 797.398zM523.623 923.429c-28.387 0-51.482-23.28-51.482-51.896s23.096-51.895 51.482-51.895c28.385 0 51.477 23.279 51.477 51.895S552.008 923.429 523.623 923.429zM523.623 829.639c-22.873 0-41.482 18.794-41.482 41.895 0 23.102 18.609 41.896 41.482 41.896 22.871 0 41.477-18.794 41.477-41.896C565.1 848.433 546.494 829.639 523.623 829.639zM823.062 734.872 224.163 734.872 224.163 225.63l598.899 0L823.062 734.872zM234.163 724.872l578.899 0L813.062 235.63 234.163 235.63 234.163 724.872zM823.062 173.104 224.163 173.104l0-36.268c0-37.234 30.052-67.526 66.991-67.526l464.927 0c36.934 0 66.98 30.292 66.98 67.526L823.061 173.104zM234.163 163.104l578.899 0 0-26.268c0-31.72-25.562-57.526-56.98-57.526L291.154 79.31c-31.425 0-56.991 25.806-56.991 57.526L234.163 163.104z" p-id="1991"/></svg> |
@@ -0,0 +1,198 @@ | |||
module.exports = { | |||
root: true, | |||
parserOptions: { | |||
parser: 'babel-eslint', | |||
sourceType: 'module' | |||
}, | |||
env: { | |||
browser: true, | |||
node: true, | |||
es6: true, | |||
}, | |||
extends: ['plugin:vue/recommended', 'eslint:recommended'], | |||
// add your custom rules here | |||
//it is base on https://github.com/vuejs/eslint-config-vue | |||
rules: { | |||
"vue/max-attributes-per-line": [2, { | |||
"singleline": 10, | |||
"multiline": { | |||
"max": 1, | |||
"allowFirstLine": false | |||
} | |||
}], | |||
"vue/singleline-html-element-content-newline": "off", | |||
"vue/multiline-html-element-content-newline":"off", | |||
"vue/name-property-casing": ["error", "PascalCase"], | |||
"vue/no-v-html": "off", | |||
'accessor-pairs': 2, | |||
'arrow-spacing': [2, { | |||
'before': true, | |||
'after': true | |||
}], | |||
'block-spacing': [2, 'always'], | |||
'brace-style': [2, '1tbs', { | |||
'allowSingleLine': true | |||
}], | |||
'camelcase': [0, { | |||
'properties': 'always' | |||
}], | |||
'comma-dangle': [2, 'never'], | |||
'comma-spacing': [2, { | |||
'before': false, | |||
'after': true | |||
}], | |||
'comma-style': [2, 'last'], | |||
'constructor-super': 2, | |||
'curly': [2, 'multi-line'], | |||
'dot-location': [2, 'property'], | |||
'eol-last': 2, | |||
'eqeqeq': ["error", "always", {"null": "ignore"}], | |||
'generator-star-spacing': [2, { | |||
'before': true, | |||
'after': true | |||
}], | |||
'handle-callback-err': [2, '^(err|error)$'], | |||
'indent': [2, 2, { | |||
'SwitchCase': 1 | |||
}], | |||
'jsx-quotes': [2, 'prefer-single'], | |||
'key-spacing': [2, { | |||
'beforeColon': false, | |||
'afterColon': true | |||
}], | |||
'keyword-spacing': [2, { | |||
'before': true, | |||
'after': true | |||
}], | |||
'new-cap': [2, { | |||
'newIsCap': true, | |||
'capIsNew': false | |||
}], | |||
'new-parens': 2, | |||
'no-array-constructor': 2, | |||
'no-caller': 2, | |||
'no-console': 'off', | |||
'no-class-assign': 2, | |||
'no-cond-assign': 2, | |||
'no-const-assign': 2, | |||
'no-control-regex': 0, | |||
'no-delete-var': 2, | |||
'no-dupe-args': 2, | |||
'no-dupe-class-members': 2, | |||
'no-dupe-keys': 2, | |||
'no-duplicate-case': 2, | |||
'no-empty-character-class': 2, | |||
'no-empty-pattern': 2, | |||
'no-eval': 2, | |||
'no-ex-assign': 2, | |||
'no-extend-native': 2, | |||
'no-extra-bind': 2, | |||
'no-extra-boolean-cast': 2, | |||
'no-extra-parens': [2, 'functions'], | |||
'no-fallthrough': 2, | |||
'no-floating-decimal': 2, | |||
'no-func-assign': 2, | |||
'no-implied-eval': 2, | |||
'no-inner-declarations': [2, 'functions'], | |||
'no-invalid-regexp': 2, | |||
'no-irregular-whitespace': 2, | |||
'no-iterator': 2, | |||
'no-label-var': 2, | |||
'no-labels': [2, { | |||
'allowLoop': false, | |||
'allowSwitch': false | |||
}], | |||
'no-lone-blocks': 2, | |||
'no-mixed-spaces-and-tabs': 2, | |||
'no-multi-spaces': 2, | |||
'no-multi-str': 2, | |||
'no-multiple-empty-lines': [2, { | |||
'max': 1 | |||
}], | |||
'no-native-reassign': 2, | |||
'no-negated-in-lhs': 2, | |||
'no-new-object': 2, | |||
'no-new-require': 2, | |||
'no-new-symbol': 2, | |||
'no-new-wrappers': 2, | |||
'no-obj-calls': 2, | |||
'no-octal': 2, | |||
'no-octal-escape': 2, | |||
'no-path-concat': 2, | |||
'no-proto': 2, | |||
'no-redeclare': 2, | |||
'no-regex-spaces': 2, | |||
'no-return-assign': [2, 'except-parens'], | |||
'no-self-assign': 2, | |||
'no-self-compare': 2, | |||
'no-sequences': 2, | |||
'no-shadow-restricted-names': 2, | |||
'no-spaced-func': 2, | |||
'no-sparse-arrays': 2, | |||
'no-this-before-super': 2, | |||
'no-throw-literal': 2, | |||
'no-trailing-spaces': 2, | |||
'no-undef': 2, | |||
'no-undef-init': 2, | |||
'no-unexpected-multiline': 2, | |||
'no-unmodified-loop-condition': 2, | |||
'no-unneeded-ternary': [2, { | |||
'defaultAssignment': false | |||
}], | |||
'no-unreachable': 2, | |||
'no-unsafe-finally': 2, | |||
'no-unused-vars': [2, { | |||
'vars': 'all', | |||
'args': 'none' | |||
}], | |||
'no-useless-call': 2, | |||
'no-useless-computed-key': 2, | |||
'no-useless-constructor': 2, | |||
'no-useless-escape': 0, | |||
'no-whitespace-before-property': 2, | |||
'no-with': 2, | |||
'one-var': [2, { | |||
'initialized': 'never' | |||
}], | |||
'operator-linebreak': [2, 'after', { | |||
'overrides': { | |||
'?': 'before', | |||
':': 'before' | |||
} | |||
}], | |||
'padded-blocks': [2, 'never'], | |||
'quotes': [2, 'single', { | |||
'avoidEscape': true, | |||
'allowTemplateLiterals': true | |||
}], | |||
'semi': [2, 'never'], | |||
'semi-spacing': [2, { | |||
'before': false, | |||
'after': true | |||
}], | |||
'space-before-blocks': [2, 'always'], | |||
'space-before-function-paren': [2, 'never'], | |||
'space-in-parens': [2, 'never'], | |||
'space-infix-ops': 2, | |||
'space-unary-ops': [2, { | |||
'words': true, | |||
'nonwords': false | |||
}], | |||
'spaced-comment': [2, 'always', { | |||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] | |||
}], | |||
'template-curly-spacing': [2, 'never'], | |||
'use-isnan': 2, | |||
'valid-typeof': 2, | |||
'wrap-iife': [2, 'any'], | |||
'yield-star-spacing': [2, 'both'], | |||
'yoda': [2, 'never'], | |||
'prefer-const': 2, | |||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, | |||
'object-curly-spacing': [2, 'always', { | |||
objectsInObjects: false | |||
}], | |||
'array-bracket-spacing': [2, 'never'] | |||
} | |||
} |
@@ -0,0 +1,5 @@ | |||
<template> | |||
<div style="padding:30px;"> | |||
<el-alert :closable="false" title="二级菜单" /> | |||
</div> | |||
</template> |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1572860137475" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1681" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M698.026667 597.333333C701.44 569.173333 704 541.013333 704 512 704 482.986667 701.44 454.826667 698.026667 426.666667L842.24 426.666667C849.066667 453.973333 853.333333 482.56 853.333333 512 853.333333 541.44 849.066667 570.026667 842.24 597.333333M622.506667 834.56C648.106667 787.2 667.733333 736 681.386667 682.666667L807.253333 682.666667C766.293333 753.066667 701.013333 807.68 622.506667 834.56M611.84 597.333333 412.16 597.333333C407.893333 569.173333 405.333333 541.013333 405.333333 512 405.333333 482.986667 407.893333 454.4 412.16 426.666667L611.84 426.666667C615.68 454.4 618.666667 482.986667 618.666667 512 618.666667 541.013333 615.68 569.173333 611.84 597.333333M512 851.626667C476.586667 800.426667 448 743.68 430.506667 682.666667L593.493333 682.666667C576 743.68 547.413333 800.426667 512 851.626667M341.333333 341.333333 216.746667 341.333333C257.28 270.506667 322.986667 215.893333 401.066667 189.44 375.466667 236.8 356.266667 288 341.333333 341.333333M216.746667 682.666667 341.333333 682.666667C356.266667 736 375.466667 787.2 401.066667 834.56 322.986667 807.68 257.28 753.066667 216.746667 682.666667M181.76 597.333333C174.933333 570.026667 170.666667 541.44 170.666667 512 170.666667 482.56 174.933333 453.973333 181.76 426.666667L325.973333 426.666667C322.56 454.826667 320 482.986667 320 512 320 541.013333 322.56 569.173333 325.973333 597.333333M512 171.946667C547.413333 223.146667 576 280.32 593.493333 341.333333L430.506667 341.333333C448 280.32 476.586667 223.146667 512 171.946667M807.253333 341.333333 681.386667 341.333333C667.733333 288 648.106667 236.8 622.506667 189.44 701.013333 216.32 766.293333 270.506667 807.253333 341.333333M512 85.333333C276.053333 85.333333 85.333333 277.333333 85.333333 512 85.333333 747.52 276.48 938.666667 512 938.666667 747.52 938.666667 938.666667 747.52 938.666667 512 938.666667 276.48 747.52 85.333333 512 85.333333Z" p-id="1682" fill="#515151"></path></svg> |
@@ -0,0 +1,81 @@ | |||
<template> | |||
<el-breadcrumb class="app-breadcrumb" separator="/"> | |||
<transition-group name="breadcrumb"> | |||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> | |||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span> | |||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> | |||
</el-breadcrumb-item> | |||
</transition-group> | |||
</el-breadcrumb> | |||
</template> | |||
<script> | |||
import pathToRegexp from 'path-to-regexp' | |||
export default { | |||
data() { | |||
return { | |||
levelList: null | |||
} | |||
}, | |||
watch: { | |||
$route(route) { | |||
// if you go to the redirect page, do not update the breadcrumbs | |||
if (route.path.startsWith('/redirect/')) { | |||
return | |||
} | |||
this.getBreadcrumb() | |||
} | |||
}, | |||
created() { | |||
this.getBreadcrumb() | |||
}, | |||
methods: { | |||
getBreadcrumb() { | |||
// only show routes with meta.title | |||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title) | |||
const first = matched[0] | |||
if (!this.isDashboard(first)) { | |||
matched = [{ path: '/dashboard', meta: { title: '首页' }}].concat(matched) | |||
} | |||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) | |||
}, | |||
isDashboard(route) { | |||
const name = route && route.name | |||
if (!name) { | |||
return false | |||
} | |||
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase() | |||
}, | |||
pathCompile(path) { | |||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561 | |||
const { params } = this.$route | |||
var toPath = pathToRegexp.compile(path) | |||
return toPath(params) | |||
}, | |||
handleLink(item) { | |||
const { redirect, path } = item | |||
if (redirect) { | |||
this.$router.push(redirect) | |||
return | |||
} | |||
this.$router.push(this.pathCompile(path)) | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.app-breadcrumb.el-breadcrumb { | |||
display: inline-block; | |||
font-size: 14px; | |||
line-height: 50px; | |||
margin-left: 8px; | |||
.no-redirect { | |||
color: #97a8be; | |||
cursor: text; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,336 @@ | |||
<template> | |||
<div class="app-container"> | |||
<div style="margin-bottom:10px"> | |||
<el-button type="success" @click="addBtn">新增</el-button> | |||
</div> | |||
<!--搜索--> | |||
<el-form class="mt_15" ref="form" inline size="small"> | |||
<el-form-item label="公司名称"> | |||
<el-input v-model.trim="searchParm.name" clearable placeholder='名称'></el-input> | |||
</el-form-item> | |||
<el-form-item label="地址"> | |||
<el-input v-model.trim="searchParm.address" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="联系方式"> | |||
<el-input v-model.trim="searchParm.phone" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button type="primary" @click="goSearch">搜索</el-button> | |||
<el-button type="warning" @click="resetForm">重置</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!--表格渲染--> | |||
<el-table ref="table" border size="small" :data="list" :header-cell-style="{textAlign:'center'}" :cell-style="{textAlign:'center'}"> | |||
<el-table-column label="序号" type="index" width="50" /> | |||
<el-table-column label="公司名称" prop="name" /> | |||
<el-table-column label="地址" prop="address" /> | |||
<el-table-column label="联系方式" prop="phone" /> | |||
<el-table-column label="创建时间" prop="createdAt" /> | |||
<el-table-column label="修改时间" prop="updatedAt" /> | |||
<el-table-column label="操作" width="220"> | |||
<template slot-scope="scope"> | |||
<el-button type="info" @click="getBtnById(scope.row.id)">查看</el-button> | |||
<el-button type="warning" @click="editById(scope.row)">修改</el-button> | |||
<el-button type="danger" @click="delById(scope.row.id)">删除</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页--> | |||
<div class="mt_15"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="searchParm.page" | |||
:page-sizes="[10, 20, 30, 40, 50]" | |||
:page-size="searchParm.pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total"> | |||
</el-pagination> | |||
</div> | |||
<!--新增弹窗--> | |||
<el-dialog :visible.sync="dialogAddVisible" :title="dialogAddTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="addParm" size="small" :model="addParm" :rules="rules" label-width="100px"> | |||
<el-form-item label="公司名称" prop="name"> | |||
<el-input v-model.trim="addParm.name" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="地址" prop="address"> | |||
<el-input v-model.trim="addParm.address" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="联系方式" prop="phone"> | |||
<el-input v-model.trim="addParm.phone" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureAddCancle('addParm')">取消</el-button> | |||
<el-button type="primary" @click="sureAdd('addParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--修改弹窗--> | |||
<el-dialog :visible.sync="dialogEditVisible" :title="dialogEditTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="editParm" size="small" :model="editParm" :rules="rules" label-width="100px"> | |||
<el-form-item label="公司名称" prop="name"> | |||
<el-input v-model.trim="editParm.name" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="地址" prop="address"> | |||
<el-input v-model.trim="editParm.address" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="联系方式" prop="phone"> | |||
<el-input v-model.trim="editParm.phone" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureEditCancle('editParm')">取消</el-button> | |||
<el-button type="primary" @click="sureEdit('editParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--详情弹窗--> | |||
<el-dialog :visible.sync="dialogDetailVisible" :title="dialogDetailTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="100px"> | |||
<el-form-item label="公司名称" prop="name" > | |||
<el-input v-model.trim="detailParm.name" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="地址" prop="address"> | |||
<el-input v-model.trim="detailParm.address" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="联系方式" prop="phone"> | |||
<el-input v-model.trim="detailParm.phone" :disabled="true"></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { add, editById, delById, getList, getById, getAll } from '@/api/group/company' | |||
export default { | |||
// 数据 | |||
data() { | |||
return { | |||
searchParm: { | |||
page: 1, | |||
pageSize: 10, | |||
name:null, | |||
sort:'created_at', | |||
order:'desc', | |||
address:null, | |||
phone:null, | |||
}, | |||
total:0, | |||
list: [], | |||
dialogAddVisible: false, | |||
dialogAddTitle: '新增', | |||
dialogDetailVisible: false, | |||
dialogDetailTitle: '详情', | |||
dialogEditVisible: false, | |||
dialogEditTitle: '修改', | |||
addParm: { | |||
id: null, | |||
name:'', | |||
address:'', | |||
phone: '', | |||
}, | |||
detailParm: { | |||
id: null, | |||
name:'', | |||
address:'', | |||
phone: '', | |||
}, | |||
editParm: { | |||
id: null, | |||
name:'', | |||
address:'', | |||
phone: '', | |||
}, | |||
rules: { | |||
platformId: [ | |||
{ required: true, message: '请输入平台ID', trigger: 'blur' } | |||
], | |||
platformName: [ | |||
{ required: true, message: '请输入平台名称', trigger: 'blur' } | |||
], | |||
name: [ | |||
{ required: true, message: '请输入公司名称', trigger: 'blur' } | |||
], | |||
address: [ | |||
{ required: true, message: '请输入地址', trigger: 'blur' } | |||
], | |||
phone: [ | |||
{ required: true, message: '请输入联系方式', trigger: 'blur' }, | |||
{ pattern : /^[+]?(0|([1-9]\d*))?$/, message : '请输入正确的手机号码', trigger: 'blur'} | |||
] | |||
} | |||
} | |||
}, | |||
// 调用 | |||
created() { | |||
this.goSearch() | |||
}, | |||
//方法 | |||
methods: { | |||
resetForm() { | |||
this.searchParm.name = null; | |||
this.searchParm.address = null; | |||
this.searchParm.phone = null; | |||
this.goSearch() | |||
}, | |||
// 查询 | |||
goSearch() { | |||
this.searchParm.page=1 | |||
this.getDataList() | |||
}, | |||
//重置 | |||
// 新增 | |||
addBtn(){ | |||
this.addParm = { | |||
id: null, | |||
platformName:'', | |||
name:'', | |||
address:'', | |||
phone: '', | |||
} | |||
this.dialogAddTitle='新增' | |||
this.dialogAddVisible = true; | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 根据id删除 | |||
delById(id){ | |||
this.$confirm('确认删除?','提示',{ | |||
confirmButtonText: '确定', | |||
cancelButtonText: '取消', | |||
type: 'warning' | |||
}).then(() => { | |||
delById({id}).then(res => { | |||
if(res.code==200) { | |||
this.$message.success('删除成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}).catch(() => { | |||
this.$message.info('取消删除') | |||
}) | |||
}, | |||
// 修改 | |||
editById(data){ | |||
this.$refs.editParm.clearValidate(); | |||
getById({id: data.id}).then(res => { | |||
if(res.code==200) { | |||
this.editParm.id = res.data.id; | |||
this.editParm.name = res.data.name; | |||
this.editParm.address = res.data.address; | |||
this.editParm.phone = res.data.phone; | |||
this.dialogEditVisible = true | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 确认修改 | |||
sureEdit(editParm){ | |||
this.$refs[editParm].validate((valid) => { | |||
if (valid) { | |||
this.$refs.editParm.clearValidate(); | |||
editById(this.editParm).then(res => { | |||
if(res.code==200) { | |||
console.log(res) | |||
this.dialogEditVisible = false | |||
this.$message.success('修改成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
} else { | |||
console.log('error submit!!'); | |||
return false; | |||
} | |||
}); | |||
}, | |||
sureEditCancle(editParm){ | |||
this.dialogEditVisible=flase | |||
this.$refs.editParm.clearValidate(); | |||
}, | |||
// 确认新增 | |||
sureAdd(addParm){ | |||
this.$refs[addParm].validate((valid) => { | |||
if (valid) { | |||
this.$refs.addParm.clearValidate(); | |||
add(this.addParm).then(res => { | |||
if(res.code==200) { | |||
this.dialogAddVisible = false | |||
this.$message.success('新增成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
} else { | |||
console.log('error submit!!'); | |||
return false; | |||
} | |||
}); | |||
}, | |||
sureAddCancle(addParm){ | |||
this.dialogAddVisible=flase | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 查看根据id | |||
getBtnById(id){ | |||
getById({id}).then(res => { | |||
if(res.code==200) { | |||
this.detailParm.id = res.data.id; | |||
this.detailParm.name = res.data.name; | |||
this.detailParm.address = res.data.address; | |||
this.detailParm.phone = res.data.phone; | |||
this.dialogDetailVisible = true | |||
this.$refs.ruleForm.clearValidate() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页获取表格数据 | |||
getDataList(){ | |||
getList(this.searchParm).then(res => { | |||
console.log(res) | |||
if(res.code==200) { | |||
console.log(res) | |||
this.list = res.data.list; | |||
this.total = res.data.total; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页 | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.searchParm.pageSize = val; | |||
this.getDataList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.searchParm.page = val; | |||
this.getDataList(); | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
</style> |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1649727419510" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18534" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M375.36 32v224c0 32-196.16 32-196.16 0V32a245.12 245.12 0 0 0 20.8 457.28L132.16 800a151.04 151.04 0 0 0 0 64 148.48 148.48 0 1 0 289.92-64l-67.84-311.36A245.12 245.12 0 0 0 375.36 32zM277.44 896a68.16 68.16 0 1 1 68.16-68.16A68.16 68.16 0 0 1 277.44 896zM864 544V288l48.96-73.28a51.84 51.84 0 0 0 5.12-48L877.12 64a51.84 51.84 0 0 0-48-32H771.2a51.84 51.84 0 0 0-48 32l-40.96 102.72a51.84 51.84 0 0 0 5.12 48L736 288v256a128 128 0 0 0-128 128v192a128 128 0 0 0 128 128h128a128 128 0 0 0 128-128v-192a128 128 0 0 0-128-128z" fill="#bfbfbf" p-id="18535"></path></svg> |
@@ -0,0 +1,55 @@ | |||
<template> | |||
<div class="app-container"> | |||
<p class="warn-content"> | |||
Markdown 基于 | |||
<el-link type="primary" href="https://github.com/hinesboy/mavonEditor" target="_blank">MavonEditor</el-link> | |||
</p> | |||
<mavon-editor ref="md" :style="'height:' + height" @imgAdd="imgAdd" /> | |||
</div> | |||
</template> | |||
<script> | |||
import { upload } from '@/utils/upload' | |||
import { mapGetters } from 'vuex' | |||
import { mavonEditor } from 'mavon-editor' | |||
import 'mavon-editor/dist/css/index.css' | |||
export default { | |||
name: 'Markdown', | |||
components: { | |||
mavonEditor | |||
}, | |||
data() { | |||
return { | |||
height: document.documentElement.clientHeight - 200 + 'px' | |||
} | |||
}, | |||
computed: { | |||
...mapGetters([ | |||
'imagesUploadApi', | |||
'baseApi' | |||
]) | |||
}, | |||
mounted() { | |||
const that = this | |||
window.onresize = function temp() { | |||
that.height = document.documentElement.clientHeight - 200 + 'px' | |||
} | |||
}, | |||
methods: { | |||
imgAdd(pos, $file) { | |||
upload(this.imagesUploadApi, $file).then(res => { | |||
const data = res.data | |||
const url = this.baseApi + '/file/' + data.type + '/' + data.realName | |||
this.$refs.md.$img2Url(pos, url) | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.v-note-wrapper.shadow { | |||
z-index: 5; | |||
} | |||
</style> |
@@ -0,0 +1,24 @@ | |||
<template> | |||
<div v-if="crud.props.searchToggle"> | |||
<el-input | |||
v-model="query.blurry" | |||
clearable | |||
size="small" | |||
placeholder="请输入你要搜索的内容" | |||
style="width: 200px;" | |||
class="filter-item" | |||
/> | |||
<date-range-picker v-model="query.createTime" class="date-item" /> | |||
<rrOperation /> | |||
</div> | |||
</template> | |||
<script> | |||
import { header } from '@crud/crud' | |||
import rrOperation from '@crud/RR.operation' | |||
import DateRangePicker from '@/components/DateRangePicker' | |||
export default { | |||
components: { rrOperation, DateRangePicker }, | |||
mixins: [header()] | |||
} | |||
</script> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="1468" t="1546239206365" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path d="M907 378.05l-12.4-14.33c-61-70.41-166.93-177.81-236.2-239.4l-14.12-12.58C609.07 80.37 562.07 63.09 512 63.09s-97.08 17.28-132.32 48.65l-14.12 12.57c-69.28 61.61-175.24 169-236.2 239.41l-12.41 14.33c-63.92 73.87-63.92 194 0 267.87l12.41 14.33C190.24 730.6 296.2 838 365.54 899.69l14.14 12.57c35.24 31.37 82.23 48.65 132.32 48.65s97.06-17.28 132.32-48.65l14.13-12.57 8.15-7.25c21.93-19.46 31.93-28.35 62.69-58.93l7.27-7.36-1.16-1.22a28.35 28.35 0 0 0-45.87-32.14c-2.92 2.78-43.63 41.53-68.73 63.91l-14.1 12.56c-24.89 22.1-58.53 34.28-94.7 34.28s-69.82-12.19-94.69-34.31l-14.14-12.58c-67.85-60.34-171.47-165.38-231-234.14l-12.4-14.32c-21.73-25.12-33.7-59.29-33.7-96.2s12-71.07 33.7-96.17l12.41-14.33c59.5-68.75 163.12-173.79 231-234.15l14.1-12.57c24.86-22.12 58.49-34.31 94.68-34.31s69.83 12.19 94.7 34.3l14.12 12.58c67.86 60.37 171.49 165.41 231 234.14l12.39 14.34c45.22 52.21 45.34 143.76 0.26 192.07l-7.15 7.69c-20.35 21.94-32.64 35.19-45.62 39.1-12.3 3.71-27.89-0.23-57.53-14.54-49.55-23.94-119.64-64-144-78 9.87-19.61 32.46-67.6 43.11-115.62l2.86-12.87H534.5v-15.06h154.78v-57.37H534.5v-72.41h-56.89v72.41H322.83v57.37h154.78v15.05H358.54V491H573c-4.63 14.52-13.16 32.57-19.19 44.37-22.13-8.73-80.75-29.33-141-29.33-37.94 0-69.92 10.28-92.49 29.71-22.37 19.27-34.19 46-34.19 77.42s11.32 58.29 32.75 77.74c21.9 19.89 53 30.41 90 30.41 42.76 0 87.09-19 128.18-54.78a326.76 326.76 0 0 0 43.61-46.35c22.9 12.75 90 50 152.61 83.47 40.83 21.85 69.5 26.18 95.87 14.47 25.09-11.14 47.07-36.53 77.49-71.68l0.47-0.54C971 572.07 971 451.9 907 378.05zM407.83 662c-60.15 0-64.83-37.38-64.83-48.82a48.21 48.21 0 0 1 12.15-31.36c11.06-12.2 28.45-18.39 51.69-18.39 50 0 95 17.21 115.39 26.35C503.71 611.69 456 662 407.83 662z" p-id="1469"/></svg> |
@@ -0,0 +1,210 @@ | |||
<template> | |||
<div class="app-container"> | |||
<!--工具栏--> | |||
<div class="head-container"> | |||
<div v-if="crud.props.searchToggle"> | |||
<!-- 搜索 --> | |||
<el-input v-model="query.jobName" clearable size="small" placeholder="输入任务名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery" /> | |||
<date-range-picker v-model="query.createTime" class="date-item" /> | |||
<rrOperation /> | |||
</div> | |||
<crudOperation :permission="permission"> | |||
<!-- 任务日志 --> | |||
<el-button | |||
slot="right" | |||
class="filter-item" | |||
size="mini" | |||
type="info" | |||
icon="el-icon-tickets" | |||
@click="doLog" | |||
>日志</el-button> | |||
</crudOperation> | |||
<Log ref="log" /> | |||
</div> | |||
<!--Form表单--> | |||
<el-dialog :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" append-to-body width="730px"> | |||
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="100px"> | |||
<el-form-item label="任务名称" prop="jobName"> | |||
<el-input v-model="form.jobName" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="任务描述" prop="description"> | |||
<el-input v-model="form.description" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="Bean名称" prop="beanName"> | |||
<el-input v-model="form.beanName" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="执行方法" prop="methodName"> | |||
<el-input v-model="form.methodName" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="Cron表达式" prop="cronExpression"> | |||
<el-input v-model="form.cronExpression" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="子任务ID"> | |||
<el-input v-model="form.subTask" placeholder="多个用逗号隔开,按顺序执行" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="任务负责人" prop="personInCharge"> | |||
<el-input v-model="form.personInCharge" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="告警邮箱" prop="email"> | |||
<el-input v-model="form.email" placeholder="多个邮箱用逗号隔开" style="width: 220px;" /> | |||
</el-form-item> | |||
<el-form-item label="失败后暂停"> | |||
<el-radio-group v-model="form.pauseAfterFailure" style="width: 220px"> | |||
<el-radio :label="true">是</el-radio> | |||
<el-radio :label="false">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item label="任务状态"> | |||
<el-radio-group v-model="form.isPause" style="width: 220px"> | |||
<el-radio :label="false">启用</el-radio> | |||
<el-radio :label="true">暂停</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item label="参数内容"> | |||
<el-input v-model="form.params" style="width: 556px;" rows="4" type="textarea" /> | |||
</el-form-item> | |||
</el-form> | |||
<div slot="footer" class="dialog-footer"> | |||
<el-button type="text" @click="crud.cancelCU">取消</el-button> | |||
<el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确认</el-button> | |||
</div> | |||
</el-dialog> | |||
<!--表格渲染--> | |||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler"> | |||
<el-table-column :selectable="checkboxT" type="selection" width="55" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="id" label="任务ID" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="jobName" label="任务名称" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="beanName" label="Bean名称" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="methodName" label="执行方法" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="params" label="参数" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="cronExpression" label="cron表达式" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="isPause" width="90px" label="状态"> | |||
<template slot-scope="scope"> | |||
<el-tag :type="scope.row.isPause ? 'warning' : 'success'">{{ scope.row.isPause ? '已暂停' : '运行中' }}</el-tag> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :show-overflow-tooltip="true" prop="description" width="150px" label="描述" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="createTime" width="136px" label="创建日期" /> | |||
<el-table-column v-if="checkPer(['admin','timing:edit','timing:del'])" label="操作" width="170px" align="center" fixed="right"> | |||
<template slot-scope="scope"> | |||
<el-button v-permission="['admin','timing:edit']" size="mini" style="margin-right: 3px;" type="text" @click="crud.toEdit(scope.row)">编辑</el-button> | |||
<el-button v-permission="['admin','timing:edit']" style="margin-left: -2px" type="text" size="mini" @click="execute(scope.row.id)">执行</el-button> | |||
<el-button v-permission="['admin','timing:edit']" style="margin-left: 3px" type="text" size="mini" @click="updateStatus(scope.row.id,scope.row.isPause ? '恢复' : '暂停')"> | |||
{{ scope.row.isPause ? '恢复' : '暂停' }} | |||
</el-button> | |||
<el-popover | |||
:ref="scope.row.id" | |||
v-permission="['admin','timing:del']" | |||
placement="top" | |||
width="200" | |||
> | |||
<p>确定停止并删除该任务吗?</p> | |||
<div style="text-align: right; margin: 0"> | |||
<el-button size="mini" type="text" @click="$refs[scope.row.id].doClose()">取消</el-button> | |||
<el-button :loading="delLoading" type="primary" size="mini" @click="delMethod(scope.row.id)">确定</el-button> | |||
</div> | |||
<el-button slot="reference" type="text" size="mini">删除</el-button> | |||
</el-popover> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页组件--> | |||
<pagination /> | |||
</div> | |||
</template> | |||
<script> | |||
import crudJob from '@/api/system/timing' | |||
import Log from './log' | |||
import CRUD, { presenter, header, form, crud } from '@crud/crud' | |||
import rrOperation from '@crud/RR.operation' | |||
import crudOperation from '@crud/CRUD.operation' | |||
import pagination from '@crud/Pagination' | |||
import DateRangePicker from '@/components/DateRangePicker' | |||
const defaultForm = { id: null, jobName: null, subTask: null, beanName: null, methodName: null, params: null, cronExpression: null, pauseAfterFailure: true, isPause: false, personInCharge: null, email: null, description: null } | |||
export default { | |||
name: 'Timing', | |||
components: { Log, pagination, crudOperation, rrOperation, DateRangePicker }, | |||
cruds() { | |||
return CRUD({ title: '定时任务', url: 'api/jobs', crudMethod: { ...crudJob }}) | |||
}, | |||
mixins: [presenter(), header(), form(defaultForm), crud()], | |||
data() { | |||
return { | |||
delLoading: false, | |||
permission: { | |||
add: ['admin', 'timing:add'], | |||
edit: ['admin', 'timing:edit'], | |||
del: ['admin', 'timing:del'] | |||
}, | |||
rules: { | |||
jobName: [ | |||
{ required: true, message: '请输入任务名称', trigger: 'blur' } | |||
], | |||
description: [ | |||
{ required: true, message: '请输入任务描述', trigger: 'blur' } | |||
], | |||
beanName: [ | |||
{ required: true, message: '请输入Bean名称', trigger: 'blur' } | |||
], | |||
methodName: [ | |||
{ required: true, message: '请输入方法名称', trigger: 'blur' } | |||
], | |||
cronExpression: [ | |||
{ required: true, message: '请输入Cron表达式', trigger: 'blur' } | |||
], | |||
personInCharge: [ | |||
{ required: true, message: '请输入负责人名称', trigger: 'blur' } | |||
] | |||
} | |||
} | |||
}, | |||
methods: { | |||
// 执行 | |||
execute(id) { | |||
crudJob.execution(id).then(res => { | |||
this.crud.notify('执行成功', CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}).catch(err => { | |||
console.log(err.response.data.message) | |||
}) | |||
}, | |||
// 改变状态 | |||
updateStatus(id, status) { | |||
if (status === '恢复') { | |||
this.updateParams(id) | |||
} | |||
crudJob.updateIsPause(id).then(res => { | |||
this.crud.toQuery() | |||
this.crud.notify(status + '成功', CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}).catch(err => { | |||
console.log(err.response.data.message) | |||
}) | |||
}, | |||
updateParams(id) { | |||
console.log(id) | |||
}, | |||
delMethod(id) { | |||
this.delLoading = true | |||
crudJob.del([id]).then(() => { | |||
this.delLoading = false | |||
this.$refs[id].doClose() | |||
this.crud.dleChangePage(1) | |||
this.crud.delSuccessNotify() | |||
this.crud.toQuery() | |||
}).catch(() => { | |||
this.delLoading = false | |||
this.$refs[id].doClose() | |||
}) | |||
}, | |||
// 显示日志 | |||
doLog() { | |||
this.$refs.log.dialog = true | |||
this.$refs.log.doInit() | |||
}, | |||
checkboxT(row, rowIndex) { | |||
return row.id !== 1 | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,72 @@ | |||
import router from './routers' | |||
import store from '@/store' | |||
import Config from '@/settings' | |||
import NProgress from 'nprogress' // progress bar | |||
import 'nprogress/nprogress.css'// progress bar style | |||
import { getToken } from '@/utils/auth' // getToken from cookie | |||
import { buildMenus } from '@/api/system/menu' | |||
import { filterAsyncRouter } from '@/store/modules/permission' | |||
NProgress.configure({ showSpinner: false })// NProgress Configuration | |||
const whiteList = ['/login']// no redirect whitelist | |||
router.beforeEach((to, from, next) => { | |||
if (to.meta.title) { | |||
document.title = to.meta.title + ' - ' + Config.title | |||
} | |||
NProgress.start() | |||
if (getToken()) { | |||
// 已登录且要跳转的页面是登录页 | |||
if (to.path === '/login') { | |||
next({ path: '/' }) | |||
NProgress.done() | |||
} else { | |||
if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息 | |||
store.dispatch('GetInfo').then(() => { // 拉取user_info | |||
// 动态路由,拉取菜单 | |||
loadMenus(next, to) | |||
}).catch(() => { | |||
store.dispatch('LogOut').then(() => { | |||
location.reload() // 为了重新实例化vue-router对象 避免bug | |||
}) | |||
}) | |||
// 登录时未拉取 菜单,在此处拉取 | |||
} else if (store.getters.loadMenus) { | |||
// 修改成false,防止死循环 | |||
store.dispatch('updateLoadMenus') | |||
loadMenus(next, to) | |||
} else { | |||
next() | |||
} | |||
} | |||
} else { | |||
/* has no token*/ | |||
if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入 | |||
next() | |||
} else { | |||
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 | |||
NProgress.done() | |||
} | |||
} | |||
}) | |||
export const loadMenus = (next, to) => { | |||
buildMenus().then(res => { | |||
const sdata = JSON.parse(JSON.stringify(res)) | |||
const rdata = JSON.parse(JSON.stringify(res)) | |||
const sidebarRoutes = filterAsyncRouter(sdata) | |||
const rewriteRoutes = filterAsyncRouter(rdata, false, true) | |||
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) | |||
store.dispatch('GenerateRoutes', rewriteRoutes).then(() => { // 存储路由 | |||
router.addRoutes(rewriteRoutes) // 动态添加可访问路由表 | |||
next({ ...to, replace: true }) | |||
}) | |||
store.dispatch('SetSidebarRouters', sidebarRoutes) | |||
}) | |||
} | |||
router.afterEach(() => { | |||
NProgress.done() // finish progress bar | |||
}) |
@@ -0,0 +1,14 @@ | |||
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' | |||
// 密钥对生成 http://web.chacuo.net/netrsakeypair | |||
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' + | |||
'2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ==' | |||
// 加密 | |||
export function encrypt(txt) { | |||
const encryptor = new JSEncrypt() | |||
encryptor.setPublicKey(publicKey) // 设置公钥 | |||
return encryptor.encrypt(txt) // 对需要加密的数据进行加密 | |||
} | |||
@@ -0,0 +1,31 @@ | |||
/** | |||
* I think element-ui's default theme color is too light for long-term use. | |||
* So I modified the default color and you can modify it to your liking. | |||
**/ | |||
/* theme color */ | |||
$--color-primary: #1890ff; | |||
$--color-success: #13ce66; | |||
$--color-warning: #FFBA00; | |||
$--color-danger: #ff4949; | |||
// $--color-info: #1E1E1E; | |||
$--button-font-weight: 400; | |||
// $--color-text-regular: #1f2d3d; | |||
$--border-color-light: #dfe4ed; | |||
$--border-color-lighter: #e6ebf5; | |||
$--table-border:1px solid#dfe6ec; | |||
/* icon font path, required */ | |||
$--font-path: '~element-ui/lib/theme-chalk/fonts'; | |||
@import "../../../node_modules/element-ui/packages/theme-chalk/src/index"; | |||
// the :export directive is the magic sauce for webpack | |||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass | |||
:export { | |||
theme: $--color-primary; | |||
} |
@@ -0,0 +1,56 @@ | |||
import Cookies from 'js-cookie' | |||
const state = { | |||
sidebar: { | |||
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, | |||
withoutAnimation: false | |||
}, | |||
device: 'desktop', | |||
size: Cookies.get('size') || 'small' | |||
} | |||
const mutations = { | |||
TOGGLE_SIDEBAR: state => { | |||
state.sidebar.opened = !state.sidebar.opened | |||
state.sidebar.withoutAnimation = false | |||
if (state.sidebar.opened) { | |||
Cookies.set('sidebarStatus', 1) | |||
} else { | |||
Cookies.set('sidebarStatus', 0) | |||
} | |||
}, | |||
CLOSE_SIDEBAR: (state, withoutAnimation) => { | |||
Cookies.set('sidebarStatus', 0) | |||
state.sidebar.opened = false | |||
state.sidebar.withoutAnimation = withoutAnimation | |||
}, | |||
TOGGLE_DEVICE: (state, device) => { | |||
state.device = device | |||
}, | |||
SET_SIZE: (state, size) => { | |||
state.size = size | |||
Cookies.set('size', size) | |||
} | |||
} | |||
const actions = { | |||
toggleSideBar({ commit }) { | |||
commit('TOGGLE_SIDEBAR') | |||
}, | |||
closeSideBar({ commit }, { withoutAnimation }) { | |||
commit('CLOSE_SIDEBAR', withoutAnimation) | |||
}, | |||
toggleDevice({ commit }, device) { | |||
commit('TOGGLE_DEVICE', device) | |||
}, | |||
setSize({ commit }, size) { | |||
commit('SET_SIZE', size) | |||
} | |||
} | |||
export default { | |||
namespaced: true, | |||
state, | |||
mutations, | |||
actions | |||
} |
@@ -0,0 +1,24 @@ | |||
import request from '@/utils/request' | |||
export function get() { | |||
return request({ | |||
url: 'api/email', | |||
method: 'get' | |||
}) | |||
} | |||
export function update(data) { | |||
return request({ | |||
url: 'api/email', | |||
data, | |||
method: 'put' | |||
}) | |||
} | |||
export function send(data) { | |||
return request({ | |||
url: 'api/email', | |||
data, | |||
method: 'post' | |||
}) | |||
} |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="1381" t="1545700997954" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path d="M880 512H320V288c0-106.032 85.968-192 192-192s192 85.968 192 192a48 48 0 1 0 96 0c0-159.056-128.944-288-288-288S224 128.944 224 288v224H144a48 48 0 0 0-48 48v416a48 48 0 0 0 48 48h736a48 48 0 0 0 48-48V560a48 48 0 0 0-48-48zM560 786.688V880a48 48 0 1 1-96 0v-93.312c-28.576-16.624-48-47.248-48-82.688a96 96 0 1 1 192 0c0 35.44-19.424 66.064-48 82.688z" p-id="1382"/></svg> |
@@ -0,0 +1,101 @@ | |||
<template> | |||
<div :class="className" :style="{height:height,width:width}" /> | |||
</template> | |||
<script> | |||
import echarts from 'echarts' | |||
require('echarts/theme/macarons') // echarts theme | |||
import { debounce } from '@/utils' | |||
export default { | |||
props: { | |||
className: { | |||
type: String, | |||
default: 'chart' | |||
}, | |||
width: { | |||
type: String, | |||
default: '100%' | |||
}, | |||
height: { | |||
type: String, | |||
default: '300px' | |||
} | |||
}, | |||
data() { | |||
return { | |||
chart: null | |||
} | |||
}, | |||
mounted() { | |||
this.initChart() | |||
this.__resizeHandler = debounce(() => { | |||
if (this.chart) { | |||
this.chart.resize() | |||
} | |||
}, 100) | |||
window.addEventListener('resize', this.__resizeHandler) | |||
}, | |||
beforeDestroy() { | |||
if (!this.chart) { | |||
return | |||
} | |||
window.removeEventListener('resize', this.__resizeHandler) | |||
this.chart.dispose() | |||
this.chart = null | |||
}, | |||
methods: { | |||
initChart() { | |||
this.chart = echarts.init(this.$el, 'macarons') | |||
const axisData = ['周一', '周二', '周三', '很长很长的周四', '周五', '周六', '周日'] | |||
const data = axisData.map(function(item, i) { | |||
return Math.round(Math.random() * 1000 * (i + 1)) | |||
}) | |||
const links = data.map(function(item, i) { | |||
return { | |||
source: i, | |||
target: i + 1 | |||
} | |||
}) | |||
links.pop() | |||
this.chart.setOption({ | |||
title: { | |||
text: '笛卡尔坐标系上的 Graph' | |||
}, | |||
tooltip: {}, | |||
xAxis: { | |||
type: 'category', | |||
boundaryGap: false, | |||
data: axisData | |||
}, | |||
yAxis: { | |||
type: 'value' | |||
}, | |||
series: [ | |||
{ | |||
type: 'graph', | |||
layout: 'none', | |||
coordinateSystem: 'cartesian2d', | |||
symbolSize: 40, | |||
label: { | |||
normal: { | |||
show: true | |||
} | |||
}, | |||
edgeSymbol: ['circle', 'arrow'], | |||
edgeSymbolSize: [4, 10], | |||
data: data, | |||
links: links, | |||
lineStyle: { | |||
normal: { | |||
color: '#2f4554' | |||
} | |||
} | |||
} | |||
] | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,68 @@ | |||
<!-- @author zhengjie --> | |||
<template> | |||
<div class="icon-body"> | |||
<el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons"> | |||
<i slot="suffix" class="el-icon-search el-input__icon" /> | |||
</el-input> | |||
<div class="icon-list"> | |||
<div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)"> | |||
<svg-icon :icon-class="item" style="height: 30px;width: 16px;" /> | |||
<span>{{ item }}</span> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import icons from './requireIcons' | |||
export default { | |||
name: 'IconSelect', | |||
data() { | |||
return { | |||
name: '', | |||
iconList: icons | |||
} | |||
}, | |||
methods: { | |||
filterIcons() { | |||
this.iconList = icons | |||
if (this.name) { | |||
this.iconList = this.iconList.filter(item => item.includes(this.name)) | |||
} | |||
}, | |||
selectedIcon(name) { | |||
this.$emit('selected', name) | |||
document.body.click() | |||
}, | |||
reset() { | |||
this.name = '' | |||
this.iconList = icons | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
.icon-body { | |||
width: 100%; | |||
padding: 10px; | |||
.icon-list { | |||
height: 200px; | |||
overflow-y: scroll; | |||
div { | |||
height: 30px; | |||
line-height: 30px; | |||
margin-bottom: -5px; | |||
cursor: pointer; | |||
width: 33%; | |||
float: left; | |||
} | |||
span { | |||
display: inline-block; | |||
vertical-align: -0.15em; | |||
fill: currentColor; | |||
overflow: hidden; | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,33 @@ | |||
import request from '@/utils/request' | |||
export function getAllTable() { | |||
return request({ | |||
url: 'api/generator/tables/all', | |||
method: 'get' | |||
}) | |||
} | |||
export function generator(tableName, type) { | |||
return request({ | |||
url: 'api/generator/' + tableName + '/' + type, | |||
method: 'post', | |||
responseType: type === 2 ? 'blob' : '' | |||
}) | |||
} | |||
export function save(data) { | |||
return request({ | |||
url: 'api/generator', | |||
data, | |||
method: 'put' | |||
}) | |||
} | |||
export function sync(tables) { | |||
return request({ | |||
url: 'api/generator/sync', | |||
method: 'post', | |||
data: tables | |||
}) | |||
} | |||
@@ -0,0 +1,753 @@ | |||
<template> | |||
<div class="app-container"> | |||
<div style="margin-bottom:10px"> | |||
<el-button type="success" @click="addBtn">新增</el-button> | |||
<el-button type="success" @click="importBtn">导入</el-button> | |||
<el-button type="success" @click="exportTempBtn">模版下载</el-button> | |||
</div> | |||
<!--搜索--> | |||
<el-form class="mt_15" ref="form" inline size="small"> | |||
<el-form-item label="店铺"> | |||
<el-input v-model="searchParm.shop" clearable placeholder='店铺'></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单ID"> | |||
<el-input v-model="searchParm.orderId" clearable placeholder='订单ID'></el-input> | |||
</el-form-item> | |||
<el-form-item label="公司"> | |||
<el-select v-model="searchParm.companyId" placeholder="请选择"> | |||
<el-option v-for="item in companys" :key="item.name" :label="item.name" :value="item.id"></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="平台"> | |||
<el-select v-model="searchParm.platformId" placeholder="请选择"> | |||
<el-option | |||
v-for="item in platformList" | |||
:key="item.id" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="类型"> | |||
<el-select v-model="searchParm.status" placeholder="请选择"> | |||
<el-option | |||
v-for="item in typeList" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="状态"> | |||
<el-select v-model="searchParm.status" placeholder="请选择"> | |||
<el-option | |||
v-for="item in statusList" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-date-picker | |||
v-model="searchTime" | |||
type="daterange" | |||
range-separator=":" | |||
start-placeholder="开始日期" | |||
end-placeholder="结束日期" | |||
style="width:270px" | |||
></el-date-picker> | |||
<el-form-item> | |||
<el-button type="primary" @click="goSearch">搜索</el-button> | |||
<el-button type="warning" @click="resetForm">重置</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!--表格渲染--> | |||
<el-table ref="table" border size="small" :data="list" :header-cell-style="{textAlign:'center'}" :cell-style="{textAlign:'center'}"> | |||
<el-table-column label="序号" type="index" width="50" /> | |||
<el-table-column label="平台名称" prop="platformName" /> | |||
<el-table-column label="公司名称" prop="companyName" /> | |||
<el-table-column label="总金额" prop="amount" /> | |||
<el-table-column label="店铺名称" prop="shop" /> | |||
<el-table-column label="订单ID" prop="orderId" /> | |||
<el-table-column label="评论" prop="comment" :formatter="commentSub"/> | |||
<el-table-column label="状态" prop="status" align="center"> | |||
<template slot-scope="scope"> | |||
{{ scope.row.status | getStatus}} | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="创建时间" prop="createdAt" /> | |||
<el-table-column label="修改时间" prop="updatedAt" /> | |||
<el-table-column label="操作" width="300"> | |||
<template slot-scope="scope"> | |||
<el-button type="info" @click="getBtnById(scope.row.id)">查看</el-button> | |||
<el-button type="warning" @click="editById(scope.row)">评论</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页--> | |||
<div class="mt_15"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="searchParm.page" | |||
:page-sizes="[10, 20, 30, 40, 50]" | |||
:page-size="searchParm.pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total"> | |||
</el-pagination> | |||
</div> | |||
<!--新增弹窗--> | |||
<el-dialog :visible.sync="dialogAddVisible" :title="dialogAddTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="addParm" size="small" :model="addParm" :rules="rules" label-width="130px"> | |||
<el-form-item label="公司" prop="companyId"> | |||
<el-select v-model="addParm.companyId" placeholder="请选择"> | |||
<el-option | |||
v-for="item in companys" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="平台" prop="platformId"> | |||
<el-select v-model="addParm.platformId" placeholder="请选择"> | |||
<el-option | |||
v-for="item in platformList" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="总金额" prop="amount"> | |||
<el-input v-model="addParm.amount" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="状态描述" prop="paymentResults"> | |||
<el-input v-model="addParm.paymentResults" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="购买数量" prop="pricesNumber"> | |||
<el-input v-model="addParm.pricesNumber" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="商品名称" prop="shopName"> | |||
<el-input v-model="addParm.shopName" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="时间" prop="orderDate"> | |||
<el-input v-model="addParm.orderDate" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="店铺名称" prop="shop"> | |||
<el-input v-model="addParm.shop" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单id" prop="orderId"> | |||
<el-input v-model="addParm.orderId" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="评论" prop="comment"> | |||
<el-input v-model="addParm.comment" clearable></el-input> | |||
</el-form-item> | |||
<el-input v-model="addParm.paths" type="hidden" clearable></el-input> | |||
<el-upload | |||
class="upload-demo" | |||
:data = "updateFileType" | |||
:action="uploadFileImgUrl" | |||
:on-preview="handlePreview" | |||
:headers="uploadHeaders" | |||
:on-remove="handleRemove" | |||
:on-success="uploadImgSuccess" | |||
:file-list="fileList" | |||
list-type="picture"> | |||
<el-button size="small" type="primary">点击上传</el-button> | |||
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> | |||
</el-upload> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="dialogAddVisible=flase">取消</el-button> | |||
<el-button type="primary" @click="sureAdd">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--评论弹窗--> | |||
<el-dialog :visible.sync="dialogEditVisible" :title="dialogEditTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="ruleForm" size="small" :model="editParm" :rules="rules" label-width="130px"> | |||
<el-form-item label="评论" prop="accountcommentName"> | |||
<el-input v-model="editParm.comment" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
<el-input v-model="editParm.paths" type="hidden" clearable></el-input> | |||
<el-upload | |||
class="upload-demo" | |||
:data = "updateFileType" | |||
:action="uploadFileImgUrl" | |||
:on-preview="handlePreview" | |||
:headers="uploadHeaders" | |||
:on-remove="handleRemove" | |||
:on-success="uploadImgSuccess" | |||
:file-list="fileList" | |||
list-type="picture"> | |||
<el-button size="small" type="primary">点击上传</el-button> | |||
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> | |||
</el-upload> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="dialogEditVisible=false">取消</el-button> | |||
<el-button type="primary" @click="sureEdit">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--详情弹窗--> | |||
<el-dialog :visible.sync="dialogDetailVisible" :title="dialogDetailTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="130px"> | |||
<el-form-item label="公司" prop="companyId"> | |||
<el-select v-model="detailParm.companyId" disabled> | |||
<el-option | |||
v-for="item in companys" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="平台" prop="platformId"> | |||
<el-select v-model="detailParm.platformId" disabled> | |||
<el-option | |||
v-for="item in platformList" | |||
:key="item.name" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
</el-form-item> | |||
<el-form-item label="总金额" prop="amount"> | |||
<el-input v-model="detailParm.amount" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="店铺名称" prop="shop"> | |||
<el-input v-model="detailParm.shop" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="商品名称" prop="shopName"> | |||
<el-input v-model="detailParm.shopName" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单id" prop="orderId"> | |||
<el-input v-model="detailParm.orderId" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="评论" prop="comment"> | |||
<el-input v-model="detailParm.comment" disabled></el-input> | |||
</el-form-item> | |||
<el-form-item label="时间" prop="orderDate"> | |||
<el-input v-model="detailParm.orderDate" disabled></el-input> | |||
</el-form-item> | |||
<el-upload | |||
class="upload-demo" | |||
:data = "updateFileType" | |||
:action="uploadFileImgUrl" | |||
:on-preview="handlePreview" | |||
:headers="uploadHeaders" | |||
:on-remove="handleRemove" | |||
:on-success="uploadImgSuccess" | |||
:file-list="fileList" | |||
list-type="picture"> | |||
</el-upload> | |||
</el-form> | |||
</div> | |||
</el-dialog> | |||
<!--订单信息导入 importBtn--> | |||
<el-dialog :visible.sync="dialogImportVisible" :title="dialogImportTitle" center width="23%"> | |||
<div class="dialog-content"> | |||
<el-upload | |||
class="upload-demo" | |||
drag | |||
ref="upload" | |||
:action="uploadFileUrl" | |||
:headers="uploadHeaders" | |||
:show-file-list = "false" | |||
:on-success="uploadSuccess" | |||
:before-upload="beforeAvatarUpload" | |||
multiple> | |||
<i class="el-icon-upload"></i> | |||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> | |||
<div class="el-upload__tip" slot="tip">只能上传xlsl文件,且不超过10M</div> | |||
</el-upload> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { add, getDetailById, commentFun, getList } from '@/api/group/clickOrder'; | |||
import { getAll } from "@/api/group/company"; | |||
export default { | |||
filters: { | |||
getStatus: function (value) { | |||
// 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 | |||
if(value == 1) { | |||
return '待执行'; | |||
} else if (value == 2) { | |||
return '执行中'; | |||
} else if (value == 3) { | |||
return '执行成功'; | |||
} else if(value == 4) { | |||
return '执行失败'; | |||
} else { | |||
return '执行失败'; | |||
} | |||
} | |||
}, | |||
// 数据 | |||
data() { | |||
return { | |||
searchParm: { | |||
page: 1, | |||
pageSize: 10, | |||
sort:'created_at', | |||
order:'desc', | |||
accountName:null, | |||
robotClientUuid:null, | |||
sTime: null, | |||
eTime: null, | |||
shop: null, | |||
orderId: null, | |||
platformId: null, | |||
companyId: null, | |||
type: null, | |||
status: null | |||
}, | |||
total:0, | |||
list: [], | |||
fileList:[], | |||
platformList: [ | |||
{ | |||
id: 1, | |||
name: "敦煌" | |||
}, | |||
{ | |||
id: 2, | |||
name: "速卖通" | |||
}, | |||
{ | |||
id: 3, | |||
name: "马帮" | |||
} | |||
], | |||
typeList: [ | |||
{ | |||
id: 1, | |||
name: "导入" | |||
}, | |||
{ | |||
id: 2, | |||
name: "刷单" | |||
} | |||
], | |||
statusList: [ | |||
{ | |||
id: 1, | |||
name: "待执行" | |||
}, | |||
{ | |||
id: 2, | |||
name: "执行中" | |||
}, | |||
{ | |||
id: 3, | |||
name: "执行成功" | |||
}, | |||
{ | |||
id: 4, | |||
name: "执行失败" | |||
} | |||
], | |||
uploadHeaders:{ Authorization: this.$store.getters.token }, | |||
dialogAddVisible: false, | |||
dialogAddTitle: '新增', | |||
dialogDetailVisible: false, | |||
dialogDetailTitle: '详情', | |||
dialogEditVisible: false, | |||
dialogEditTitle: '修改', | |||
dialogImportVisible: false, | |||
dialogImportTitle:'导入', | |||
searchTime: "", | |||
updateFileType: {type: 12}, | |||
uploadFileImgUrl: process.env.VUE_APP_BASE_API + '/api/file/uploadFile', | |||
uploadFileUrl: process.env.VUE_APP_BASE_API + '/api/clickOrder/import', | |||
tempUrl: process.env.VUE_APP_BASE_API + '/api/clickOrder/exportTemp', | |||
fileImages:{ | |||
name: null, | |||
url: null | |||
}, | |||
addParm: { | |||
id:null, | |||
platformId:null, | |||
companyId:null, | |||
paymentResults:null, | |||
pricesNumber:null, | |||
shopName:null, | |||
orderDate:null, | |||
amount:null, | |||
shop:null, | |||
orderId:null, | |||
comment:null, | |||
paths: [] | |||
}, | |||
detailParm: { | |||
id:null, | |||
platformId:null, | |||
companyId:null, | |||
amount:null, | |||
shop:null, | |||
shopName: null, | |||
orderDate: null, | |||
orderId:null, | |||
comment:null, | |||
paths:[] | |||
}, | |||
editParm: { | |||
id:null, | |||
comment:null, | |||
paths:[] | |||
}, | |||
ruleForm:{ | |||
platformId:null, | |||
companyId:null, | |||
account:null, | |||
pwd:null, | |||
amount:null, | |||
shop:null, | |||
orderId:null, | |||
comment:null, | |||
}, | |||
companys: [], | |||
rules: { | |||
platformId: [ | |||
{ required: true, message: '请输入平台', trigger: 'blur' } | |||
], | |||
companyId: [ | |||
{ required: true, message: '请输入公司', trigger: 'blur' } | |||
], | |||
account: [ | |||
{ required: true, message: '请输入账号', trigger: 'blur' } | |||
], | |||
pwd: [ | |||
{ required: true, message: '请输入密码', trigger: 'blur' } | |||
], | |||
amount: [ | |||
{ required: true, message: '请输入总金额', trigger: 'blur' } | |||
], | |||
shop: [ | |||
{ required: true, message: '请输入店铺名称', trigger: 'blur' } | |||
], | |||
orderId: [ | |||
{ required: true, message: '请输入订单ID', trigger: 'blur' } | |||
], | |||
comment: [ | |||
{ required: true, message: '请输入评论', trigger: 'blur' } | |||
] | |||
}, | |||
} | |||
}, | |||
// 调用 | |||
created() { | |||
this.goSearch(); | |||
this.fileList = []; | |||
}, | |||
//方法 | |||
methods: { | |||
// 图片上传 | |||
handleRemove(file, fileList) { | |||
console.log("======fileList======="); | |||
console.log(file); | |||
console.log(fileList); | |||
// 剔除 -这里先这样吧。硬编码 | |||
this.editParm.paths = []; | |||
for (let i = 0; i < fileList.length; i++) { | |||
console.log("for--- " + i); | |||
const imgUrl = fileList[i].url; | |||
console.log(imgUrl); | |||
if (imgUrl.includes("/file/")) { | |||
imgUrl = imgUrl.substring(imgUrl.lastIndexOf("\/file\/") + 5, imgUrl.length); | |||
console.log("包含file") | |||
} | |||
console.log(imgUrl); | |||
console.log("====1====") | |||
this.editParm.paths.push(imgUrl); | |||
console.log("====2====") | |||
} | |||
console.log("this.editParm.paths:" + this.editParm.paths); | |||
}, | |||
handlePreview(file) { | |||
console.log("======handlePreview======="); | |||
console.log(file); | |||
}, | |||
uploadImgSuccess(res, file) { | |||
if(res.code==200) { | |||
// this.addParm.path =res.data.list[0].path; | |||
const index = res.data.list[0].path.lastIndexOf("\/"); | |||
this.fileImages.name = res.data.list[0].path.substring(index + 1, res.data.list[0].path.length); | |||
this.fileImages.url = process.env.VUE_APP_BASE_API + "/file" + res.data.list[0].path; | |||
console.log("this.fileImages.url:" + this.fileImages.url); | |||
console.log("====uploadImgSuccess===="); | |||
console.log(this.fileList); | |||
console.log(this.editParm.paths); | |||
if (this.dialogEditVisible) { | |||
// if (this.editParm.paths != "undefined" && this.editParm.paths != null && this.editParm.paths != " " && this.editParm.paths != "null" && this.editParm.paths != "NULL") { | |||
// this.editParm.paths = this.editParm.paths + ";" + res.data.list[0].path; | |||
// } else { | |||
// this.editParm.paths = res.data.list[0].path; | |||
// } | |||
for (let i = 0; i < this.editParm.paths.length; i++) { | |||
console.log("for--- " + i); | |||
const imgUrl = this.editParm.paths[i].url; | |||
console.log(imgUrl); | |||
if (imgUrl.includes("/file/")) { | |||
imgUrl = imgUrl.substring(imgUrl.lastIndexOf("\/file\/") + 5, imgUrl.length); | |||
} | |||
console.log("包含file") | |||
} | |||
console.log("this.editParm.paths====1:" + this.editParm.paths); | |||
this.editParm.paths.push(res.data.list[0].path) | |||
console.log("res.data.list[0].path==:" + res.data.list[0].path); | |||
console.log("this.editParm.paths====2:" + this.editParm.paths); | |||
} | |||
if (this.dialogAddVisible) { | |||
// if (this.addParm.paths != "undefined" && this.addParm.paths != null && this.addParm.paths != " " && this.addParm.paths != "null" && this.addParm.paths != "NULL") { | |||
// this.addParm.paths = this.addParm.paths + ";" + res.data.list[0].path; | |||
// } else { | |||
// this.addParm.paths = res.data.list[0].path; | |||
// } | |||
this.addParm.paths.push(res.data.list[0].path) | |||
// console.log(this.addParm.paths); | |||
console.log("this.addParm.paths:" + this.addParm.paths); | |||
} | |||
} | |||
}, | |||
//重置 | |||
resetForm() { | |||
this.searchParm.shop = null; | |||
this.searchParm.orderId = null; | |||
this.searchParm.platformId = null; | |||
this.searchParm.companyId = null; | |||
this.searchParm.type = null; | |||
this.searchParm.status = null; | |||
this.searchTime = ""; | |||
this.goSearch(); | |||
}, | |||
// 获取所有公司信息 | |||
getCompanyAll() { | |||
getAll() | |||
.then(res => { | |||
this.companys = res.data; | |||
if (res.code == 200) { | |||
console.log(this.companys); | |||
} | |||
}) | |||
.catch(() => {}); | |||
}, | |||
// 评论截取 | |||
commentSub(row, column) { | |||
if (row['comment'] != "undefined" && row['comment'] != null && row['comment'] != "" && row['comment'] != "null" && row['comment'] != "NULL") { | |||
return row['comment'].slice(0,3) + "..."; | |||
} | |||
}, | |||
// 查询 | |||
goSearch() { | |||
this.searchParm.sTime = this.searchTime[0]; | |||
this.searchParm.eTime = this.searchTime[1]; | |||
this.searchParm.page=1 | |||
this.getCompanyAll(); | |||
this.getDataList() | |||
}, | |||
//导入成功 | |||
uploadSuccess(res, file) { | |||
this.dialogImportVisible = false; | |||
if(res.code==200) { | |||
console.log("********date:"+res.data) | |||
if(res.data == true) { | |||
this.$message.success('导入成功!'); | |||
} | |||
else{ | |||
window.location.href = res.data; | |||
this.$message.error('导入失败!'); | |||
} | |||
} | |||
this.goSearch(); | |||
}, | |||
beforeAvatarUpload(file) { | |||
console.log(file); | |||
const isLt10M = file.size / 1024 / 1024 <10; | |||
if (!isLt10M) { | |||
this.$message.error('上传Excel文件大小不能超过 10MB!'); | |||
} | |||
return isLt10M; | |||
}, | |||
// 导入 | |||
importBtn() { | |||
this.dialogImportVisible = true | |||
}, | |||
//机器人模板 | |||
exportTempBtn() { | |||
console.log(this.tempUrl) | |||
window.location.href = this.tempUrl; | |||
}, | |||
// 新增 | |||
addBtn(){ | |||
this.addParm = { | |||
id:null, | |||
platformId:null, | |||
companyId:null, | |||
account:null, | |||
pwd:null, | |||
amount:null, | |||
shop:null, | |||
orderId:null, | |||
comment:null, | |||
paths: [] | |||
} | |||
this.fileList = [] | |||
this.dialogAddTitle='新增' | |||
this.dialogAddVisible = true | |||
}, | |||
// 修改 | |||
editById(data){ | |||
this.fileList = []; | |||
this.editParm.paths = []; | |||
this.editParm.comment = null; | |||
getDetailById({id: data.id}).then(res => { | |||
if(res.code==200) { | |||
this.editParm.id = res.data.id; | |||
this.editParm.comment = res.data.comment; | |||
if (res.data.paths != "undefined" && res.data.paths != null && res.data.paths != "" &&res.data.paths != "null" && res.data.paths != "NULL") { | |||
this.editParm.paths = res.data.paths.split(','); | |||
} | |||
if (this.editParm.paths != "undefined" && this.editParm.paths != null && this.editParm.paths != "" && this.editParm.paths != "null" && this.editParm.paths != "NULL") { | |||
this.editParm.paths = res.data.paths.split(','); | |||
this.fileList = res.data.paths.split(',').map(val => { | |||
// return {url:"http://localhost:8008/file" + val} | |||
return {name: val.substring(val.lastIndexOf("\/") + 1, val.length), url: val} | |||
console.log("url:" + val); | |||
}) | |||
console.log(this.fileList) | |||
} | |||
this.dialogEditVisible = true | |||
this.$refs.ruleForm.clearValidate() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 确认修改 | |||
sureEdit(){ | |||
this.editParm.paths = this.editParm.paths.toString() | |||
commentFun(this.editParm).then(res => { | |||
if(res.code==200) { | |||
console.log(res) | |||
this.dialogEditVisible = false | |||
this.$message.success('修改成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 确认新增 | |||
sureAdd(){ | |||
this.addParm.paths = this.addParm.paths.toString() | |||
console.log(this.addParm) | |||
add(this.addParm).then(res => { | |||
if(res.code==200) { | |||
this.dialogAddVisible = false | |||
this.$message.success('新增成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 查看根据id | |||
getBtnById(id){ | |||
getDetailById({id}).then(res => { | |||
if(res.code==200) { | |||
this.detailParm.id = res.data.id; | |||
this.detailParm.platformId = res.data.platformId; | |||
this.detailParm.companyId = res.data.companyId; | |||
this.detailParm.amount = res.data.amount; | |||
this.detailParm.shop = res.data.shop; | |||
this.detailParm.orderId = res.data.orderId; | |||
this.detailParm.comment = res.data.comment; | |||
this.detailParm.shopName = res.data.shopName; | |||
this.detailParm.orderDate = res.data.orderDate; | |||
this.detailParm.paths = res.data.paths; | |||
this.fileList = []; | |||
if (res.data.paths != "undefined" && res.data.paths != null && res.data.paths != "" &&res.data.paths != "null" && res.data.paths != "NULL") { | |||
this.detailParm.paths = res.data.paths.split(','); | |||
} | |||
if (this.detailParm.paths != "undefined" && this.detailParm.paths != null && this.detailParm.paths != "" && this.detailParm.paths != "null" && this.detailParm.paths != "NULL") { | |||
this.detailParm.paths = res.data.paths.split(',') | |||
this.fileList = res.data.paths.split(',').map(val => { | |||
// return {url:"http://localhost:8008/file" + val} | |||
return {name: val.substring(val.lastIndexOf("\/") + 1, val.length), url: val} | |||
}) | |||
console.log(this.fileList) | |||
} | |||
this.dialogDetailVisible = true; | |||
this.$refs.ruleForm.clearValidate(); | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页获取表格数据 | |||
getDataList(){ | |||
getList(this.searchParm).then(res => { | |||
console.log(res) | |||
if(res.code==200) { | |||
console.log(res) | |||
this.list = res.data.list; | |||
this.total = res.data.total; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页 | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.searchParm.pageSize = val; | |||
this.getDataList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.searchParm.page = val; | |||
this.getDataList(); | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
</style> |
@@ -0,0 +1,5 @@ | |||
language: node_js | |||
node_js: 10 | |||
script: npm run test | |||
notifications: | |||
email: false |
@@ -0,0 +1,73 @@ | |||
import request from '@/utils/request' | |||
export function getList(data) { | |||
return request({ | |||
url: 'api/dhAddCar/list', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
//export function getClickFarmList(data) { | |||
//return request({ | |||
// url: 'api/clickFarming/list', | |||
// method: 'post', | |||
// data | |||
//}) | |||
//} | |||
export function add(data) { | |||
return request({ | |||
url: 'api/dhAddCar/add', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function sureEditById(data) { | |||
return request({ | |||
url: 'api/dhAddCar/edit', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function getEditDetailById(data) { | |||
return request({ | |||
url: 'api/dhAddCar/getEditDetailById', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function delById(data) { | |||
return request({ | |||
url: 'api/dhAddCar/delete', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function orderSuccess(data) { | |||
return request({ | |||
url: 'api/dhAddCar/orderSuccess', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function toBeCatch(data) { | |||
return request({ | |||
url: 'api/dhAddCar/toBeCatch', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function wellReceive(data) { | |||
return request({ | |||
url: 'api/dhAddCar/wellReceive', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
@@ -0,0 +1,214 @@ | |||
<template> | |||
<div class="login" :style="'background-image:url('+ Background +');'"> | |||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form"> | |||
<h3 class="title"> | |||
EL-ADMIN 后台管理系统 | |||
</h3> | |||
<el-form-item prop="username"> | |||
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号"> | |||
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> | |||
</el-input> | |||
</el-form-item> | |||
<el-form-item prop="password"> | |||
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin"> | |||
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> | |||
</el-input> | |||
</el-form-item> | |||
<el-form-item prop="code"> | |||
<el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin"> | |||
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> | |||
</el-input> | |||
<div class="login-code"> | |||
<img :src="codeUrl" @click="getCode"> | |||
</div> | |||
</el-form-item> | |||
<el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;"> | |||
记住我 | |||
</el-checkbox> | |||
<el-form-item style="width:100%;"> | |||
<el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin"> | |||
<span v-if="!loading">登 录</span> | |||
<span v-else>登 录 中...</span> | |||
</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!-- 底部 --> | |||
<div v-if="$store.state.settings.showFooter" id="el-login-footer"> | |||
<span v-html="$store.state.settings.footerTxt" /> | |||
<span> ⋅ </span> | |||
<a href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank">{{ $store.state.settings.caseNumber }}</a> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { encrypt } from '@/utils/rsaEncrypt' | |||
import Config from '@/settings' | |||
import { getCodeImg } from '@/api/login' | |||
import Cookies from 'js-cookie' | |||
import qs from 'qs' | |||
import Background from '@/assets/images/background.jpeg' | |||
export default { | |||
name: 'Login', | |||
data() { | |||
return { | |||
Background: Background, | |||
codeUrl: '', | |||
cookiePass: '', | |||
loginForm: { | |||
username: 'admin', | |||
password: '123456', | |||
rememberMe: false, | |||
code: '', | |||
uuid: '' | |||
}, | |||
loginRules: { | |||
username: [{ required: true, trigger: 'blur', message: '用户名不能为空' }], | |||
password: [{ required: true, trigger: 'blur', message: '密码不能为空' }], | |||
code: [{ required: true, trigger: 'change', message: '验证码不能为空' }] | |||
}, | |||
loading: false, | |||
redirect: undefined | |||
} | |||
}, | |||
watch: { | |||
$route: { | |||
handler: function(route) { | |||
const data = route.query | |||
if (data && data.redirect) { | |||
this.redirect = data.redirect | |||
delete data.redirect | |||
if (JSON.stringify(data) !== '{}') { | |||
this.redirect = this.redirect + '&' + qs.stringify(data, { indices: false }) | |||
} | |||
} | |||
}, | |||
immediate: true | |||
} | |||
}, | |||
created() { | |||
// 获取验证码 | |||
this.getCode() | |||
// 获取用户名密码等Cookie | |||
this.getCookie() | |||
// token 过期提示 | |||
this.point() | |||
}, | |||
methods: { | |||
getCode() { | |||
getCodeImg().then(res => { | |||
this.codeUrl = res.img | |||
this.loginForm.uuid = res.uuid | |||
}) | |||
}, | |||
getCookie() { | |||
const username = Cookies.get('username') | |||
let password = Cookies.get('password') | |||
const rememberMe = Cookies.get('rememberMe') | |||
// 保存cookie里面的加密后的密码 | |||
this.cookiePass = password === undefined ? '' : password | |||
password = password === undefined ? this.loginForm.password : password | |||
this.loginForm = { | |||
username: username === undefined ? this.loginForm.username : username, | |||
password: password, | |||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe), | |||
code: '' | |||
} | |||
}, | |||
handleLogin() { | |||
this.$refs.loginForm.validate(valid => { | |||
const user = { | |||
username: this.loginForm.username, | |||
password: this.loginForm.password, | |||
rememberMe: this.loginForm.rememberMe, | |||
code: this.loginForm.code, | |||
uuid: this.loginForm.uuid | |||
} | |||
if (user.password !== this.cookiePass) { | |||
user.password = encrypt(user.password) | |||
} | |||
if (valid) { | |||
this.loading = true | |||
if (user.rememberMe) { | |||
Cookies.set('username', user.username, { expires: Config.passCookieExpires }) | |||
Cookies.set('password', user.password, { expires: Config.passCookieExpires }) | |||
Cookies.set('rememberMe', user.rememberMe, { expires: Config.passCookieExpires }) | |||
} else { | |||
Cookies.remove('username') | |||
Cookies.remove('password') | |||
Cookies.remove('rememberMe') | |||
} | |||
this.$store.dispatch('Login', user).then(() => { | |||
this.loading = false | |||
this.$router.push({ path: this.redirect || '/' }) | |||
}).catch(() => { | |||
this.loading = false | |||
this.getCode() | |||
}) | |||
} else { | |||
console.log('error submit!!') | |||
return false | |||
} | |||
}) | |||
}, | |||
point() { | |||
const point = Cookies.get('point') !== undefined | |||
if (point) { | |||
this.$notify({ | |||
title: '提示', | |||
message: '当前登录状态已过期,请重新登录!', | |||
type: 'warning', | |||
duration: 5000 | |||
}) | |||
Cookies.remove('point') | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss"> | |||
.login { | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
height: 100%; | |||
background-size: cover; | |||
} | |||
.title { | |||
margin: 0 auto 30px auto; | |||
text-align: center; | |||
color: #707070; | |||
} | |||
.login-form { | |||
border-radius: 6px; | |||
background: #ffffff; | |||
width: 385px; | |||
padding: 25px 25px 5px 25px; | |||
.el-input { | |||
height: 38px; | |||
input { | |||
height: 38px; | |||
} | |||
} | |||
.input-icon{ | |||
height: 39px;width: 14px;margin-left: 2px; | |||
} | |||
} | |||
.login-tip { | |||
font-size: 13px; | |||
text-align: center; | |||
color: #bfbfbf; | |||
} | |||
.login-code { | |||
width: 33%; | |||
display: inline-block; | |||
height: 38px; | |||
float: right; | |||
img{ | |||
cursor: pointer; | |||
vertical-align:middle | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,30 @@ | |||
<template> | |||
<el-tabs v-model="activeName" type="card"> | |||
<el-tab-pane v-for="item in data" :key="item.name" :lazy="true" :label="item.name" :name="item.name"> | |||
<Java :value="item.content" :height="height" /> | |||
</el-tab-pane> | |||
</el-tabs> | |||
</template> | |||
<script> | |||
import Java from '@/components/JavaEdit/index' | |||
import { generator } from '@/api/generator/generator' | |||
export default { | |||
name: 'Preview', | |||
components: { Java }, | |||
data() { | |||
return { | |||
data: null, height: '', activeName: 'Entity' | |||
} | |||
}, | |||
created() { | |||
this.height = document.documentElement.clientHeight - 180 + 'px' | |||
const tableName = this.$route.params.tableName | |||
generator(tableName, 1).then(data => { | |||
this.data = data | |||
}).catch(() => { | |||
this.$router.go(-1) | |||
}) | |||
} | |||
} | |||
</script> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="2201" t="1545883026424" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path d="M925.597853 836.903811c0.367367-2.783393 0.847298-5.528923 0.847298-8.40953L926.44515 180.091658c19.034519-11.079336 31.976272-31.470759 31.976272-55.082526 0-35.32146-28.633131-63.956637-63.953567-63.956637-23.611767 0-44.007283 12.941753-55.082526 31.980365L182.108594 93.03286c-11.076266-19.038612-31.470759-31.980365-55.082526-31.980365-35.31839 0-63.953567 28.635177-63.953567 63.956637 0 23.611767 12.9438 44.00319 31.976272 55.082526l0 648.402623c0 2.880607 0.479931 5.627161 0.851391 8.40953-19.4991 10.954493-32.827663 31.586392-32.827663 55.543014 0 35.317367 28.635177 63.953567 63.953567 63.953567 35.32146 0 63.953567-28.635177 63.953567-63.953567l639.536698 0c0 35.317367 28.631084 63.953567 63.953567 63.953567 35.319413 0 63.953567-28.635177 63.953567-63.953567C958.421422 868.490204 945.093882 847.859327 925.597853 836.903811zM862.491583 828.494281 159.00234 828.494281 159.00234 180.091658c9.596566-5.586229 17.524119-13.513782 23.110347-23.110347l657.273664 0c5.582135 9.596566 13.509688 17.524119 23.106254 23.110347L862.492606 828.494281z" p-id="2202"/><path d="M670.62781 252.915243 350.86202 252.915243 318.885747 252.915243 286.908452 252.915243 286.908452 380.818285 350.86202 380.818285 350.86202 316.864718 478.768131 316.864718 478.768131 668.610874 414.815587 668.610874 414.815587 732.564441 606.675266 732.564441 606.675266 668.610874 542.721699 668.610874 542.721699 316.864718 670.62781 316.864718 670.62781 380.818285 734.585471 380.818285 734.585471 252.915243 702.609199 252.915243Z" p-id="2203"/></svg> |
@@ -0,0 +1,41 @@ | |||
import request from '@/utils/request' | |||
export function getList(data) { | |||
return request({ | |||
url: 'api/ctPlatform/list', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function add(data) { | |||
return request({ | |||
url: 'api/ctPlatform/add', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function delById(data) { | |||
return request({ | |||
url: 'api/ctPlatform/delete', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function editById(data) { | |||
return request({ | |||
url: 'api/ctPlatform/edit', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function getById(data) { | |||
return request({ | |||
url: 'api/ctPlatform/getById', | |||
method: 'post', | |||
data | |||
}) | |||
} |
@@ -0,0 +1,325 @@ | |||
<template> | |||
<div class="app-container"> | |||
<el-row :gutter="15"> | |||
<el-col style="margin-bottom: 10px"> | |||
<el-card class="box-card" shadow="never"> | |||
<div slot="header" class="clearfix"> | |||
<span class="role-span">字段配置:{{ tableName }}</span> | |||
<el-button | |||
:loading="genLoading" | |||
icon="el-icon-s-promotion" | |||
size="mini" | |||
style="float: right; padding: 6px 9px;" | |||
type="success" | |||
@click="toGen" | |||
>保存&生成</el-button> | |||
<el-button | |||
:loading="columnLoading" | |||
icon="el-icon-check" | |||
size="mini" | |||
style="float: right; padding: 6px 9px;margin-right: 9px" | |||
type="primary" | |||
@click="saveColumnConfig" | |||
>保存</el-button> | |||
<el-tooltip class="item" effect="dark" content="数据库中表字段变动时使用该功能" placement="top-start"> | |||
<el-button | |||
:loading="syncLoading" | |||
icon="el-icon-refresh" | |||
size="mini" | |||
style="float: right; padding: 6px 9px;" | |||
type="info" | |||
@click="sync" | |||
>同步</el-button> | |||
</el-tooltip> | |||
</div> | |||
<el-form size="small" label-width="90px"> | |||
<el-table v-loading="loading" :data="data" :max-height="tableHeight" size="small" style="width: 100%;margin-bottom: 15px"> | |||
<el-table-column prop="columnName" label="字段名称" /> | |||
<el-table-column prop="columnType" label="字段类型" /> | |||
<el-table-column prop="remark" label="字段描述"> | |||
<template slot-scope="scope"> | |||
<el-input v-model="data[scope.$index].remark" size="mini" class="edit-input" /> | |||
</template> | |||
</el-table-column> | |||
<el-table-column align="center" label="必填" width="70px"> | |||
<template slot-scope="scope"> | |||
<el-checkbox v-model="data[scope.$index].notNull" /> | |||
</template> | |||
</el-table-column> | |||
<el-table-column align="center" label="列表" width="70px"> | |||
<template slot-scope="scope"> | |||
<el-checkbox v-model="data[scope.$index].listShow" /> | |||
</template> | |||
</el-table-column> | |||
<el-table-column align="center" label="表单" width="70px"> | |||
<template slot-scope="scope"> | |||
<el-checkbox v-model="data[scope.$index].formShow" /> | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="表单类型"> | |||
<template slot-scope="scope"> | |||
<el-select v-model="data[scope.$index].formType" filterable class="edit-input" clearable size="mini" placeholder="请选择"> | |||
<el-option | |||
label="文本框" | |||
value="Input" | |||
/> | |||
<el-option | |||
label="文本域" | |||
value="Textarea" | |||
/> | |||
<el-option | |||
label="单选框" | |||
value="Radio" | |||
/> | |||
<el-option | |||
label="下拉框" | |||
value="Select" | |||
/> | |||
<el-option | |||
label="日期框" | |||
value="Date" | |||
/> | |||
</el-select> | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="查询方式"> | |||
<template slot-scope="scope"> | |||
<el-select v-model="data[scope.$index].queryType" filterable class="edit-input" clearable size="mini" placeholder="请选择"> | |||
<el-option | |||
label="=" | |||
value="=" | |||
/> | |||
<el-option | |||
label="!=" | |||
value="!=" | |||
/> | |||
<el-option | |||
label=">=" | |||
value=">=" | |||
/> | |||
<el-option | |||
label="<=" | |||
value="<=" | |||
/> | |||
<el-option | |||
label="Like" | |||
value="Like" | |||
/> | |||
<el-option | |||
label="NotNull" | |||
value="NotNull" | |||
/> | |||
<el-option | |||
label="BetWeen" | |||
value="BetWeen" | |||
/> | |||
</el-select> | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="日期注解"> | |||
<template slot-scope="scope"> | |||
<el-select v-model="data[scope.$index].dateAnnotation" filterable class="edit-input" clearable size="mini" placeholder="请选择"> | |||
<el-option | |||
label="自动创建时间" | |||
value="CreationTimestamp" | |||
/> | |||
<el-option | |||
label="自动更新时间" | |||
value="UpdateTimestamp" | |||
/> | |||
</el-select> | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="关联字典"> | |||
<template slot-scope="scope"> | |||
<el-select v-model="data[scope.$index].dictName" filterable class="edit-input" clearable size="mini" placeholder="请选择"> | |||
<el-option v-for="item in dicts" :key="item.id" :label="item.remark === '' ? item.name : item.remark" :value="item.name" /> | |||
</el-select> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
</el-form> | |||
</el-card> | |||
</el-col> | |||
<el-col> | |||
<el-card class="box-card" shadow="never"> | |||
<div slot="header" class="clearfix"> | |||
<span class="role-span">生成配置</span> | |||
<el-button | |||
:loading="configLoading" | |||
icon="el-icon-check" | |||
size="mini" | |||
style="float: right; padding: 6px 9px" | |||
type="primary" | |||
@click="doSubmit" | |||
>保存</el-button> | |||
</div> | |||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="78px"> | |||
<el-form-item label="作者名称" prop="author"> | |||
<el-input v-model="form.author" style="width: 40%" /> | |||
<span style="color: #C0C0C0;margin-left: 10px;">类上面的作者名称</span> | |||
</el-form-item> | |||
<el-form-item label="模块名称" prop="moduleName"> | |||
<el-input v-model="form.moduleName" style="width: 40%" /> | |||
<span style="color: #C0C0C0;margin-left: 10px;">模块的名称,请选择项目中已存在的模块</span> | |||
</el-form-item> | |||
<el-form-item label="至于包下" prop="pack"> | |||
<el-input v-model="form.pack" style="width: 40%" /> | |||
<span style="color: #C0C0C0;margin-left: 10px;">项目包的名称,生成的代码放到哪个包里面</span> | |||
</el-form-item> | |||
<el-form-item label="接口名称" prop="apiAlias"> | |||
<el-input v-model="form.apiAlias" style="width: 40%" /> | |||
<span style="color: #C0C0C0;margin-left: 10px;">接口的名称,用于控制器与接口文档中</span> | |||
</el-form-item> | |||
<el-form-item label="前端路径" prop="path"> | |||
<el-input v-model="form.path" style="width: 40%" /> | |||
<span style="color: #C0C0C0;margin-left: 10px;">输入views文件夹下的目录,不存在即创建</span> | |||
</el-form-item> | |||
<!-- <el-form-item label="接口目录">--> | |||
<!-- <el-input v-model="form.apiPath" style="width: 40%" />--> | |||
<!-- <span style="color: #C0C0C0;margin-left: 10px;">Api存放路径[src/api],为空则自动生成路径</span>--> | |||
<!-- </el-form-item>--> | |||
<el-form-item label="去表前缀" prop="prefix"> | |||
<el-input v-model="form.prefix" placeholder="默认不去除表前缀" style="width: 40%" /> | |||
<span style="color: #C0C0C0;margin-left: 10px;">默认不去除表前缀,可自定义</span> | |||
</el-form-item> | |||
<el-form-item label="是否覆盖" prop="cover"> | |||
<el-radio-group v-model="form.cover" size="mini" style="width: 40%"> | |||
<el-radio-button label="true">是</el-radio-button> | |||
<el-radio-button label="false">否</el-radio-button> | |||
</el-radio-group> | |||
<span style="color: #C0C0C0;margin-left: 10px;">谨防误操作,请慎重选择</span> | |||
</el-form-item> | |||
</el-form> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</template> | |||
<script> | |||
import crud from '@/mixins/crud' | |||
import { update, get } from '@/api/generator/genConfig' | |||
import { save, sync, generator } from '@/api/generator/generator' | |||
import { getDicts } from '@/api/system/dict' | |||
export default { | |||
name: 'GeneratorConfig', | |||
components: {}, | |||
mixins: [crud], | |||
data() { | |||
return { | |||
activeName: 'first', tableName: '', tableHeight: 550, columnLoading: false, configLoading: false, dicts: [], syncLoading: false, genLoading: false, | |||
form: { id: null, tableName: '', author: '', pack: '', path: '', moduleName: '', cover: 'false', apiPath: '', prefix: '', apiAlias: null }, | |||
rules: { | |||
author: [ | |||
{ required: true, message: '作者不能为空', trigger: 'blur' } | |||
], | |||
pack: [ | |||
{ required: true, message: '包路径不能为空', trigger: 'blur' } | |||
], | |||
moduleName: [ | |||
{ required: true, message: '包路径不能为空', trigger: 'blur' } | |||
], | |||
path: [ | |||
{ required: true, message: '前端路径不能为空', trigger: 'blur' } | |||
], | |||
apiAlias: [ | |||
{ required: true, message: '接口名称不能为空', trigger: 'blur' } | |||
], | |||
cover: [ | |||
{ required: true, message: '不能为空', trigger: 'blur' } | |||
] | |||
} | |||
} | |||
}, | |||
created() { | |||
this.tableHeight = document.documentElement.clientHeight - 385 | |||
this.tableName = this.$route.params.tableName | |||
this.$nextTick(() => { | |||
this.init() | |||
get(this.tableName).then(data => { | |||
this.form = data | |||
this.form.cover = this.form.cover.toString() | |||
}) | |||
getDicts().then(data => { | |||
this.dicts = data | |||
}) | |||
}) | |||
}, | |||
methods: { | |||
beforeInit() { | |||
this.url = 'api/generator/columns' | |||
const tableName = this.tableName | |||
this.params = { tableName } | |||
return true | |||
}, | |||
saveColumnConfig() { | |||
this.columnLoading = true | |||
save(this.data).then(res => { | |||
this.notify('保存成功', 'success') | |||
this.columnLoading = false | |||
}).catch(err => { | |||
this.columnLoading = false | |||
console.log(err.response.data.message) | |||
}) | |||
}, | |||
doSubmit() { | |||
this.$refs['form'].validate((valid) => { | |||
if (valid) { | |||
this.configLoading = true | |||
update(this.form).then(res => { | |||
this.notify('保存成功', 'success') | |||
this.form = res | |||
this.form.cover = this.form.cover.toString() | |||
this.configLoading = false | |||
}).catch(err => { | |||
this.configLoading = false | |||
console.log(err.response.data.message) | |||
}) | |||
} | |||
}) | |||
}, | |||
sync() { | |||
this.syncLoading = true | |||
sync([this.tableName]).then(() => { | |||
this.init() | |||
this.notify('同步成功', 'success') | |||
this.syncLoading = false | |||
}).then(() => { | |||
this.syncLoading = false | |||
}) | |||
}, | |||
toGen() { | |||
this.genLoading = true | |||
save(this.data).then(res => { | |||
this.notify('保存成功', 'success') | |||
// 生成代码 | |||
generator(this.tableName, 0).then(data => { | |||
this.genLoading = false | |||
this.notify('生成成功', 'success') | |||
}).catch(err => { | |||
this.genLoading = false | |||
console.log(err.response.data.message) | |||
}) | |||
}).catch(err => { | |||
this.genLoading = false | |||
console.log(err.response.data.message) | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss"> | |||
.edit-input { | |||
.el-input__inner { | |||
border: 1px solid #e5e6e7; | |||
} | |||
} | |||
</style> | |||
<style scoped> | |||
::v-deep .input-with-select .el-input-group__prepend { | |||
background-color: #fff; | |||
} | |||
</style> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="983" t="1552025141027" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#bfbfbf" d="M895.318 192H128.682C93.008 192 64 220.968 64 256.616v510.698C64 802.986 93.008 832 128.682 832h766.636C930.992 832 960 802.986 960 767.312V256.616C960 220.968 930.992 192 895.318 192zM568.046 704h-112.096v-192l-84.08 107.756L287.826 512v192H175.738V320h112.088l84.044 135.96 84.08-135.96h112.096v384z m167.314 0l-139.27-192h84v-192h112.086v192h84.054l-140.906 192h0.036z" p-id="984"/></svg> |
@@ -0,0 +1,54 @@ | |||
<template> | |||
<div :class="{'has-logo':showLogo}"> | |||
<logo v-if="showLogo" :collapse="isCollapse" /> | |||
<el-scrollbar wrap-class="scrollbar-wrapper"> | |||
<el-menu | |||
:default-active="activeMenu" | |||
:collapse="isCollapse" | |||
:background-color="variables.menuBg" | |||
:text-color="variables.menuText" | |||
:active-text-color="variables.menuActiveText" | |||
:collapse-transition="false" | |||
unique-opened | |||
mode="vertical" | |||
> | |||
<sidebar-item v-for="route in sidebarRouters" :key="route.path" :item="route" :base-path="route.path" /> | |||
</el-menu> | |||
</el-scrollbar> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapGetters } from 'vuex' | |||
import Logo from './Logo' | |||
import SidebarItem from './SidebarItem' | |||
import variables from '@/assets/styles/variables.scss' | |||
export default { | |||
components: { SidebarItem, Logo }, | |||
computed: { | |||
...mapGetters([ | |||
'sidebarRouters', | |||
'sidebar' | |||
]), | |||
activeMenu() { | |||
const route = this.$route | |||
const { meta, path } = route | |||
// if set path, the sidebar will highlight the path you set | |||
if (meta.activeMenu) { | |||
return meta.activeMenu | |||
} | |||
return path | |||
}, | |||
showLogo() { | |||
return this.$store.state.settings.sidebarLogo | |||
}, | |||
variables() { | |||
return variables | |||
}, | |||
isCollapse() { | |||
return !this.sidebar.opened | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,135 @@ | |||
<template> | |||
<div class="app-container"> | |||
<div class="head-container"> | |||
<Search /> | |||
<crudOperation> | |||
<el-button | |||
slot="left" | |||
class="filter-item" | |||
type="danger" | |||
icon="el-icon-delete" | |||
size="mini" | |||
:loading="crud.delAllLoading" | |||
@click="confirmDelAll()" | |||
> | |||
清空 | |||
</el-button> | |||
</crudOperation> | |||
</div> | |||
<!--表格渲染--> | |||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler"> | |||
<el-table-column type="expand"> | |||
<template slot-scope="props"> | |||
<el-form label-position="left" inline class="demo-table-expand"> | |||
<el-form-item label="请求方法"> | |||
<span>{{ props.row.method }}</span> | |||
</el-form-item> | |||
<el-form-item label="请求参数"> | |||
<span>{{ props.row.params }}</span> | |||
</el-form-item> | |||
</el-form> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="username" label="用户名" /> | |||
<el-table-column prop="requestIp" label="IP" /> | |||
<el-table-column :show-overflow-tooltip="true" prop="address" label="IP来源" /> | |||
<el-table-column prop="description" label="描述" /> | |||
<el-table-column prop="browser" label="浏览器" /> | |||
<el-table-column prop="createTime" label="创建日期" /> | |||
<el-table-column label="异常详情" width="100px"> | |||
<template slot-scope="scope"> | |||
<el-button size="mini" type="text" @click="info(scope.row.id)">查看详情</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<el-dialog :visible.sync="dialog" title="异常详情" append-to-body top="30px" width="85%"> | |||
<pre>{{ errorInfo }}</pre> | |||
</el-dialog> | |||
<!--分页组件--> | |||
<pagination /> | |||
</div> | |||
</template> | |||
<script> | |||
import { getErrDetail, delAllError } from '@/api/monitor/log' | |||
import Search from './search' | |||
import CRUD, { presenter } from '@crud/crud' | |||
import crudOperation from '@crud/CRUD.operation' | |||
import pagination from '@crud/Pagination' | |||
export default { | |||
name: 'ErrorLog', | |||
components: { Search, crudOperation, pagination }, | |||
cruds() { | |||
return CRUD({ title: '异常日志', url: 'api/logs/error' }) | |||
}, | |||
mixins: [presenter()], | |||
data() { | |||
return { | |||
errorInfo: '', dialog: false | |||
} | |||
}, | |||
created() { | |||
this.crud.optShow = { | |||
add: false, | |||
edit: false, | |||
del: false, | |||
download: true | |||
} | |||
}, | |||
methods: { | |||
// 获取异常详情 | |||
info(id) { | |||
this.dialog = true | |||
getErrDetail(id).then(res => { | |||
this.errorInfo = res.exception | |||
}) | |||
}, | |||
confirmDelAll() { | |||
this.$confirm(`确认清空所有异常日志吗?`, '提示', { | |||
confirmButtonText: '确定', | |||
cancelButtonText: '取消', | |||
type: 'warning' | |||
}).then(() => { | |||
this.crud.delAllLoading = true | |||
delAllError().then(res => { | |||
this.crud.delAllLoading = false | |||
this.crud.dleChangePage(1) | |||
this.crud.delSuccessNotify() | |||
this.crud.toQuery() | |||
}).catch(err => { | |||
this.crud.delAllLoading = false | |||
console.log(err.response.data.message) | |||
}) | |||
}).catch(() => { | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.demo-table-expand { | |||
font-size: 0; | |||
} | |||
.demo-table-expand label { | |||
width: 70px; | |||
color: #99a9bf; | |||
} | |||
.demo-table-expand .el-form-item { | |||
margin-right: 0; | |||
margin-bottom: 0; | |||
width: 100%; | |||
} | |||
.demo-table-expand .el-form-item__content { | |||
font-size: 12px; | |||
} | |||
/deep/ .el-dialog__body { | |||
padding: 0 20px 10px 20px !important; | |||
} | |||
.java.hljs { | |||
color: #444; | |||
background: #ffffff !important; | |||
height: 630px !important; | |||
} | |||
</style> |
@@ -0,0 +1,77 @@ | |||
import request from '@/utils/request' | |||
export function add(data) { | |||
return request({ | |||
url: 'api/deploy', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function del(ids) { | |||
return request({ | |||
url: 'api/deploy', | |||
method: 'delete', | |||
data: ids | |||
}) | |||
} | |||
export function edit(data) { | |||
return request({ | |||
url: 'api/deploy', | |||
method: 'put', | |||
data | |||
}) | |||
} | |||
export function getApps() { | |||
return request({ | |||
url: 'api/app', | |||
method: 'get' | |||
}) | |||
} | |||
export function getServers() { | |||
return request({ | |||
url: 'api/serverDeploy', | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* 启动服务 | |||
* @param data 选中行 | |||
*/ | |||
export function startServer(data) { | |||
return request({ | |||
url: 'api/deploy/startServer', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
* 停止服务 | |||
* @param data 选中行 | |||
*/ | |||
export function stopServer(data) { | |||
return request({ | |||
url: 'api/deploy/stopServer', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
* 停止服务 | |||
* @param data 选中行 | |||
*/ | |||
export function serverStatus(data) { | |||
return request({ | |||
url: 'api/deploy/serverStatus', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export default { add, edit, del, stopServer, serverStatus, startServer, getServers, getApps } |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="2986" t="1546864403462" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#bfbfbf" d="M814.502 270.913l30.18-30.18 30.58 30.58 37.825-37.825-86.377-86.378-37.825 37.825 30.58 30.58-30.18 30.18c-66.856-61.301-154.087-100.642-250.374-106.858V66.548h-53.499v72.289c-214.046 13.792-383.407 191.652-383.407 409.199 0 226.533 183.624 410.157 410.157 410.157s410.157-183.624 410.157-410.157c-0.001-106.858-40.892-204.139-107.817-277.123zM529.994 598.26v74.606h-35.666V598.26c-20.724-7.385-35.666-26.958-35.666-50.225 0-23.267 14.942-42.842 35.666-50.225v-235.1h35.666v235.102c20.724 7.383 35.666 26.958 35.666 50.225 0 23.265-14.942 42.839-35.666 50.223z" p-id="2987"/></svg> |
@@ -0,0 +1,422 @@ | |||
<template> | |||
<div class="app-container"> | |||
<div style="margin-bottom:10px"> | |||
<el-button type="success" @click="addBtn">新增</el-button> | |||
</div> | |||
<!--搜索--> | |||
<el-form class="mt_15" ref="form" inline size="small"> | |||
<el-form-item label="应用名称"> | |||
<el-input v-model.trim="searchParm.name" clearable placeholder="应用名称"></el-input> | |||
</el-form-item> | |||
<el-form-item label="应用id"> | |||
<el-input v-model.trim="searchParm.robotUuid" clearable placeholder="应用id"></el-input> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button type="primary" @click="goSearch">搜索</el-button> | |||
<el-button type="warning" @click="resetForm">重置</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!--表格渲染--> | |||
<el-table | |||
ref="table" | |||
border | |||
size="small" | |||
:data="list" | |||
:header-cell-style="{textAlign:'center'}" | |||
:cell-style="{textAlign:'center'}" | |||
> | |||
<el-table-column label="序号" type="index" width="50" /> | |||
<el-table-column label="应用名称" prop="name" /> | |||
<el-table-column label="应用id" prop="robotUuid" /> | |||
<el-table-column label="任务名称" prop="taskName" /> | |||
<el-table-column label="方法名称" prop="methodName" /> | |||
<el-table-column label="accessKeyId" prop="accessKeyId" /> | |||
<el-table-column label="accessKeySecret" prop="accessKeySecret" /> | |||
<el-table-column label="备注" prop="remark" /> | |||
<el-table-column label="创建时间" prop="createdAt" /> | |||
<el-table-column label="修改时间" prop="updatedAt" /> | |||
<el-table-column label="操作" width="220"> | |||
<template slot-scope="scope"> | |||
<el-button type="info" @click="getBtnById(scope.row.id)">查看</el-button> | |||
<el-button type="warning" @click="editById(scope.row)">修改</el-button> | |||
<el-button type="danger" @click="delById(scope.row.id)">删除</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页--> | |||
<div class="mt_15"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="searchParm.page" | |||
:page-sizes="[10, 20, 30, 40, 50]" | |||
:page-size="searchParm.pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total" | |||
></el-pagination> | |||
</div> | |||
<!--新增弹窗--> | |||
<el-dialog :visible.sync="dialogAddVisible" :title="dialogAddTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="addParm" size="small" :model="addParm" :rules="rules" label-width="150px"> | |||
<el-form-item label="应用名称" prop="name"> | |||
<el-input v-model.trim="addParm.name" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="应用ID" prop="robotUuid"> | |||
<el-input v-model.trim="addParm.robotUuid" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="任务名称" prop="taskName"> | |||
<el-select v-model.trim="addParm.taskName" placeholder="请选择"> | |||
<el-option | |||
v-for="item in taskList" | |||
:key="item.id" | |||
:label="item.name" | |||
:value="item.name" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="accessKeyId" prop="accessKeyId"> | |||
<el-input v-model.trim="addParm.accessKeyId" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="accessKeySecret" prop="accessKeySecret"> | |||
<el-input v-model.trim="addParm.accessKeySecret" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="备注" prop="remark"> | |||
<el-input v-model.trim="addParm.remark" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureAddCancle('addParm')">取消</el-button> | |||
<el-button type="primary" @click="sureAdd('addParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--修改弹窗--> | |||
<el-dialog :visible.sync="dialogEditVisible" :title="dialogEditTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="editParm" size="small" :model="editParm" :rules="rules" label-width="150px"> | |||
<el-form-item label="应用名称" prop="name"> | |||
<el-input v-model.trim="editParm.name" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="应用ID" prop="robotUuid"> | |||
<el-input v-model.trim="editParm.robotUuid" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="任务名称" prop="taskName"> | |||
<el-select v-model.trim="editParm.taskName" placeholder="请选择"> | |||
<el-option | |||
v-for="item in taskList" | |||
:key="item.id" | |||
:label="item.name" | |||
:value="item.name"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="accessKeyId" prop="accessKeyId"> | |||
<el-input v-model.trim="editParm.accessKeyId" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="accessKeySecret" prop="accessKeySecret"> | |||
<el-input v-model.trim="editParm.accessKeySecret" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item label="备注" prop="remark"> | |||
<el-input v-model.trim="editParm.remark" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureEditCancle('editParm')">取消</el-button> | |||
<el-button type="primary" @click="sureEdit('editParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--详情弹窗--> | |||
<el-dialog :visible.sync="dialogDetailVisible" :title="dialogDetailTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="130px"> | |||
<el-form-item label="应用名称" prop="name"> | |||
<el-input v-model.trim="detailParm.name" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="应用ID" prop="robotUuid"> | |||
<el-input v-model.trim="detailParm.robotUuid" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="任务名称" prop="taskName"> | |||
<el-input v-model.trim="detailParm.taskName" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="方法名称" prop="methodName"> | |||
<el-input v-model.trim="detailParm.methodName" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="accessKeyId" prop="accessKeyId"> | |||
<el-input v-model.trim="detailParm.accessKeyId" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="accessKeySecret" prop="accessKeySecret"> | |||
<el-input v-model.trim="detailParm.accessKeySecret" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="备注" prop="remark"> | |||
<el-input v-model.trim="detailParm.remark" :disabled="true"></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { getList, add, delById, getById, editById } from "@/api/group/apply"; | |||
export default { | |||
// 数据 | |||
data() { | |||
return { | |||
taskList: [ | |||
{ | |||
id: 1, | |||
name: "demoTask" | |||
}, | |||
{ | |||
id: 2, | |||
name: "clickFarmTask" | |||
}, { | |||
id: 3, | |||
name: "clickFarmSuppleMentTask" | |||
} | |||
], | |||
searchParm: { | |||
page: 1, | |||
pageSize: 10, | |||
sort: "created_at", | |||
order: "desc", | |||
name: null, | |||
robotUuid: null, | |||
remark: null | |||
}, | |||
total: 0, | |||
list: [], | |||
dialogAddVisible: false, | |||
dialogAddTitle: "新增", | |||
dialogDetailVisible: false, | |||
dialogDetailTitle: "详情", | |||
dialogEditVisible: false, | |||
dialogEditTitle: "修改", | |||
dialogImportVisible: false, | |||
dialogImportTitle: "导入", | |||
addParm: { | |||
id: null, | |||
name: null, | |||
robotUuid: null, | |||
taskName: null, | |||
methodName: null, | |||
accessKeyId: null, | |||
accessKeySecret: null, | |||
remark: null | |||
}, | |||
detailParm: { | |||
id: null, | |||
name: null, | |||
robotUuid: null, | |||
taskName: null, | |||
methodName: null, | |||
accessKeyId: null, | |||
accessKeySecret: null, | |||
remark: null | |||
}, | |||
editParm: { | |||
id: null, | |||
name: null, | |||
robotUuid: null, | |||
taskName: null, | |||
methodName: null, | |||
accessKeyId: null, | |||
accessKeySecret: null, | |||
remark: null | |||
}, | |||
rules: { | |||
name: [{ required: true, message: "请输入应用名称", trigger: "blur" }], | |||
robotUuid: [ | |||
{ required: true, message: "请输入应用id", trigger: "blur" } | |||
], | |||
taskName: [ | |||
{ required: true, message: "请输入任务名称", trigger: "blur" } | |||
], | |||
methodName: [ | |||
{ required: true, message: "请输入方法名称", trigger: "blur" } | |||
], | |||
accessKeyId: [ | |||
{ required: true, message: "请输入accessKeyId", trigger: "blur" } | |||
], | |||
accessKeySecret: [ | |||
{ required: true, message: "请输入accessKeySecret", trigger: "blur" } | |||
], | |||
remark: [{ required: true, message: "请输入备注", trigger: "blur" }] | |||
} | |||
}; | |||
}, | |||
// 调用 | |||
created() { | |||
this.goSearch(); | |||
}, | |||
//方法 | |||
methods: { | |||
//重置 | |||
resetForm() { | |||
this.searchParm.name = null; | |||
this.searchParm.robotUuid = null; | |||
this.searchParm.remark = null; | |||
this.goSearch(); | |||
}, | |||
// 查询 | |||
goSearch() { | |||
this.searchParm.page = 1; | |||
this.getDataList(); | |||
}, | |||
// 新增 | |||
addBtn() { | |||
this.addParm = { | |||
id: null, | |||
name: null, | |||
robotUuid: null, | |||
taskName: null, | |||
methodName: null, | |||
accessKeyId: null, | |||
accessKeySecret: null, | |||
remark: null | |||
}; | |||
this.dialogAddTitle = "新增"; | |||
this.dialogAddVisible = true; | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 根据id删除 | |||
delById(id) { | |||
this.$confirm("确认删除?", "提示", { | |||
confirmButtonText: "确定", | |||
cancelButtonText: "取消", | |||
type: "warning" | |||
}) | |||
.then(() => { | |||
delById({ id }) | |||
.then(res => { | |||
if (res.code == 200) { | |||
this.$message.success("删除成功!"); | |||
this.getDataList(); | |||
} | |||
}) | |||
.catch(err => { | |||
console.log(err); | |||
}); | |||
}) | |||
.catch(() => { | |||
this.$message.info("取消删除"); | |||
}); | |||
}, | |||
// 修改 | |||
editById(data) { | |||
this.$refs.editParm.clearValidate(); | |||
getById({ id: data.id }) | |||
.then(res => { | |||
if (res.code == 200) { | |||
this.editParm.id = res.data.id; | |||
this.editParm.name = res.data.name; | |||
this.editParm.robotUuid = res.data.robotUuid; | |||
this.editParm.taskName = res.data.taskName; | |||
this.editParm.accessKeyId = res.data.accessKeyId; | |||
this.editParm.accessKeySecret = res.data.accessKeySecret; | |||
this.editParm.remark = res.data.remark; | |||
this.dialogEditVisible = true; | |||
} | |||
}) | |||
.catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
// 确认修改 | |||
sureEdit(editParm) { | |||
editById(this.editParm) | |||
.then(res => { | |||
if (res.code == 200) { | |||
console.log(res); | |||
this.dialogEditVisible = false; | |||
this.$message.success("修改成功!"); | |||
this.getDataList(); | |||
} else if (res.code == -1) { | |||
this.$message.warning(res.message); | |||
} | |||
}) | |||
.catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
sureEdit(editParm) { | |||
this.dialogEditVisible=flase | |||
this.$refs.editParm.clearValidate(); | |||
}, | |||
// 确认新增 | |||
sureAdd(addParm) { | |||
add(this.addParm) | |||
.then(res => { | |||
if (res.code == 200) { | |||
this.dialogAddVisible = false; | |||
this.$message.success("新增成功!"); | |||
this.getDataList(); | |||
} else if (res.code == -1) { | |||
this.$message.warning(res.message); | |||
} | |||
}) | |||
.catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
sureAdd(addParm) { | |||
this.dialogAddVisible=flase | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 查看根据id | |||
getBtnById(id) { | |||
getById({ id }) | |||
.then(res => { | |||
if (res.code == 200) { | |||
this.detailParm.id = res.data.id; | |||
this.detailParm.name = res.data.name; | |||
this.detailParm.robotUuid = res.data.robotUuid; | |||
this.detailParm.taskName = res.data.taskName; | |||
this.detailParm.methodName = res.data.methodName; | |||
this.detailParm.accessKeyId = res.data.accessKeyId; | |||
this.detailParm.accessKeySecret = res.data.accessKeySecret; | |||
this.detailParm.remark = res.data.remark; | |||
this.dialogDetailVisible = true; | |||
} | |||
}) | |||
.catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
// 分页获取表格数据 | |||
getDataList() { | |||
getList(this.searchParm) | |||
.then(res => { | |||
console.log(res); | |||
if (res.code == 200) { | |||
console.log(res); | |||
this.list = res.data.list; | |||
this.total = res.data.total; | |||
} | |||
}) | |||
.catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
// 分页 | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.searchParm.pageSize = val; | |||
this.getDataList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.searchParm.page = val; | |||
this.getDataList(); | |||
} | |||
} | |||
}; | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
</style> |
@@ -0,0 +1,16 @@ | |||
<template> | |||
<elFrame :src="swaggerApi" /> | |||
</template> | |||
<script> | |||
import { mapGetters } from 'vuex' | |||
import elFrame from '@/components/Iframe/index' | |||
export default { | |||
name: 'Swagger', | |||
components: { elFrame }, | |||
computed: { | |||
...mapGetters([ | |||
'swaggerApi' | |||
]) | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,32 @@ | |||
<template> | |||
<div | |||
v-if="crud.props.searchToggle" | |||
> | |||
<el-input v-model="query.name" clearable size="small" placeholder="输入岗位名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" /> | |||
<date-range-picker v-model="query.createTime" class="date-item" /> | |||
<el-select v-model="query.enabled" clearable size="small" placeholder="状态" class="filter-item" style="width: 90px" @change="crud.toQuery"> | |||
<el-option v-for="item in dict.dict.job_status" :key="item.value" :label="item.label" :value="item.value" /> | |||
</el-select> | |||
<rrOperation /> | |||
</div> | |||
</template> | |||
<script> | |||
import { header } from '@crud/crud' | |||
import rrOperation from '@crud/RR.operation' | |||
import DateRangePicker from '@/components/DateRangePicker' | |||
export default { | |||
components: { rrOperation, DateRangePicker }, | |||
mixins: [header()], | |||
props: { | |||
dict: { | |||
type: Object, | |||
required: true | |||
}, | |||
permission: { | |||
type: Object, | |||
required: true | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,110 @@ | |||
<template> | |||
<div class="dashboard-container"> | |||
<div class="dashboard-editor-container"> | |||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> | |||
<heat-map /> | |||
</el-row> | |||
<el-row :gutter="32"> | |||
<el-col :xs="24" :sm="24" :lg="8"> | |||
<div class="chart-wrapper"> | |||
<radar-chart /> | |||
</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :lg="8"> | |||
<div class="chart-wrapper"> | |||
<sunburst /> | |||
</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :lg="8"> | |||
<div class="chart-wrapper"> | |||
<gauge /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="12"> | |||
<el-col :span="12"> | |||
<div class="chart-wrapper"> | |||
<rich /> | |||
</div> | |||
</el-col> | |||
<el-col :span="12"> | |||
<div class="chart-wrapper"> | |||
<theme-river /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="32"> | |||
<el-col :xs="24" :sm="24" :lg="12"> | |||
<div class="chart-wrapper"> | |||
<graph /> | |||
</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :lg="12"> | |||
<div class="chart-wrapper"> | |||
<sankey /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="12"> | |||
<el-col :span="12"> | |||
<div class="chart-wrapper"> | |||
<scatter /> | |||
</div> | |||
</el-col> | |||
<el-col :span="12"> | |||
<div class="chart-wrapper"> | |||
<point /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> | |||
<div class="chart-wrapper"> | |||
<category /> | |||
</div> | |||
</el-row> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import RadarChart from '@/components/Echarts/RadarChart' | |||
import HeatMap from '@/components/Echarts/HeatMap' | |||
import Gauge from '@/components/Echarts/Gauge' | |||
import Rich from '@/components/Echarts/Rich' | |||
import ThemeRiver from '@/components/Echarts/ThemeRiver' | |||
import Sunburst from '@/components/Echarts/Sunburst' | |||
import Graph from '@/components/Echarts/Graph' | |||
import Sankey from '@/components/Echarts/Sankey' | |||
import Scatter from '@/components/Echarts/Scatter' | |||
import Category from '@/components/Echarts/Category' | |||
import Point from '@/components/Echarts/Point' | |||
export default { | |||
name: 'Echarts', | |||
components: { | |||
Point, | |||
Category, | |||
Graph, | |||
HeatMap, | |||
RadarChart, | |||
Sunburst, | |||
Gauge, | |||
Rich, | |||
ThemeRiver, | |||
Sankey, | |||
Scatter | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
.dashboard-editor-container { | |||
padding: 18px 22px 22px 22px; | |||
background-color: rgb(240, 242, 245); | |||
.chart-wrapper { | |||
background: #fff; | |||
padding: 16px 16px 0; | |||
margin-bottom: 32px; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,41 @@ | |||
<template> | |||
<el-tabs v-model="activeName" style="padding-left: 8px;"> | |||
<el-tab-pane label="邮箱配置" name="first"> | |||
<Config /> | |||
</el-tab-pane> | |||
<el-tab-pane label="发送邮件" name="second"> | |||
<Send /> | |||
</el-tab-pane> | |||
<el-tab-pane label="使用说明" name="third"> | |||
<div> | |||
<blockquote class="my-blockquote"> 邮件服务器配置</blockquote> | |||
<pre class="my-code"> | |||
# 邮件服务器的SMTP地址,可选,默认为smtp | |||
# 邮件服务器的SMTP端口,可选,默认465或者25 | |||
# 发件人(必须正确,否则发送失败) | |||
# 用户名,默认为发件人邮箱前缀 | |||
# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,如QQ和163等等) | |||
# 是否开启ssl,默认开启</pre> | |||
<blockquote class="my-blockquote">更多帮助</blockquote> | |||
<pre class="my-code">更多帮助请查看文档:<a style="color:#009688" href="http://hutool.mydoc.io/#text_319499" target="_black">hutool工具包</a></pre> | |||
</div> | |||
</el-tab-pane> | |||
</el-tabs> | |||
</template> | |||
<script> | |||
import Config from './config' | |||
import Send from './send' | |||
export default { | |||
name: 'Email', | |||
components: { Config, Send }, | |||
data() { | |||
return { | |||
activeName: 'second' | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
</style> |
@@ -0,0 +1,16 @@ | |||
<template> | |||
<div> | |||
<svg-icon icon-class="doc" @click="click" /> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: 'Doc', | |||
methods: { | |||
click() { | |||
window.open('https://el-admin.vip/pages/010101/', '_blank') | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,68 @@ | |||
import Vue from 'vue' | |||
import Router from 'vue-router' | |||
import Layout from '../layout/index' | |||
Vue.use(Router) | |||
export const constantRouterMap = [ | |||
{ path: '/login', | |||
meta: { title: '登录', noCache: true }, | |||
component: (resolve) => require(['@/views/login'], resolve), | |||
hidden: true | |||
}, | |||
{ | |||
path: '/404', | |||
component: (resolve) => require(['@/views/features/404'], resolve), | |||
hidden: true | |||
}, | |||
{ | |||
path: '/401', | |||
component: (resolve) => require(['@/views/features/401'], resolve), | |||
hidden: true | |||
}, | |||
{ | |||
path: '/redirect', | |||
component: Layout, | |||
hidden: true, | |||
children: [ | |||
{ | |||
path: '/redirect/:path*', | |||
component: (resolve) => require(['@/views/features/redirect'], resolve) | |||
} | |||
] | |||
}, | |||
{ | |||
path: '/', | |||
component: Layout, | |||
redirect: '/dashboard', | |||
children: [ | |||
{ | |||
path: 'dashboard', | |||
component: (resolve) => require(['@/views/home'], resolve), | |||
name: 'Dashboard', | |||
meta: { title: '首页', icon: 'index', affix: true, noCache: true } | |||
} | |||
] | |||
}, | |||
{ | |||
path: '/user', | |||
component: Layout, | |||
hidden: true, | |||
redirect: 'noredirect', | |||
children: [ | |||
{ | |||
path: 'center', | |||
component: (resolve) => require(['@/views/system/user/center'], resolve), | |||
name: '个人中心', | |||
meta: { title: '个人中心' } | |||
} | |||
] | |||
} | |||
] | |||
export default new Router({ | |||
// mode: 'hash', | |||
mode: 'history', | |||
scrollBehavior: () => ({ y: 0 }), | |||
routes: constantRouterMap | |||
}) |
@@ -0,0 +1,41 @@ | |||
import request from '@/utils/request' | |||
export function getList(data) { | |||
return request({ | |||
url: 'api/ctExcel/list', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function add(data) { | |||
return request({ | |||
url: 'api/ctExcel/add', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function delById(data) { | |||
return request({ | |||
url: 'api/ctExcel/delete', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function editById(data) { | |||
return request({ | |||
url: 'api/ctExcel/edit', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function getById(data) { | |||
return request({ | |||
url: 'api/ctExcel/getById', | |||
method: 'post', | |||
data | |||
}) | |||
} |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="1258" t="1554279845314" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path d="M921.9 468.6H749.6c-9.4 0-18.4 3.8-25 10.5-6.6 6.7-10.3 15.7-10.3 25.1v11.1c0 19.6 15.9 35.5 35.4 35.5h172.2c19.5 0 35.3-15.9 35.3-35.5v-11.1c0-9.4-3.7-18.4-10.3-25.1-6.6-6.7-15.6-10.5-25-10.5zM522.4 163.9c-53.6 42.6-165.7 102.3-246.3 159.8h-0.1c-0.9 0.6-1.8 3.8-2.8 4.3-9.5 5.4-13.8 20.1-65.6 20.1h-101c-26 0-42 12.2-42 39.6V631c0 27.4 14.7 40.9 42 40.9H208c51.5 0.1 55.7 14.8 65.2 20.1 0.9 0.5 1.8 3.7 2.7 4.3h0.1c78.2 57.5 191 121.8 246.4 162.7 16.7 12.3 72.1 33.9 72.1-42.1v-614c0-76.1-55.9-51.8-72.1-39z m159 167.8c9.2 16.1 27.3 20.2 40.5 9l141.5-119.3c13.3-11.1 16.5-33.2 7.4-49.4l-5.2-9.1c-9.1-16.1-27.3-20.1-40.5-9L683.6 273.2c-13.2 11.2-16.5 33.2-7.4 49.4l5.2 9.1z m40.4 347.4c-13.2-11.1-31.3-7-40.4 9l-5.2 9.1c-9.1 16.1-5.8 38.2 7.4 49.4L825.1 866c13.2 11.1 31.3 7.1 40.4-9l5.2-9.1c9.1-16.1 5.8-38.2-7.4-49.4L721.8 679.1z m0 0" p-id="1259"/></svg> |
@@ -0,0 +1,254 @@ | |||
<template> | |||
<div class="app-container"> | |||
<!--工具栏--> | |||
<div class="head-container"> | |||
<div v-if="crud.props.searchToggle"> | |||
<!-- 搜索 --> | |||
<el-input v-model="query.name" clearable size="small" placeholder="输入部门名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" /> | |||
<date-range-picker v-model="query.createTime" class="date-item" /> | |||
<el-select v-model="query.enabled" clearable size="small" placeholder="状态" class="filter-item" style="width: 90px" @change="crud.toQuery"> | |||
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> | |||
</el-select> | |||
<rrOperation /> | |||
</div> | |||
<crudOperation :permission="permission" /> | |||
</div> | |||
<!--表单组件--> | |||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="500px"> | |||
<el-form ref="form" inline :model="form" :rules="rules" size="small" label-width="80px"> | |||
<el-form-item label="部门名称" prop="name"> | |||
<el-input v-model="form.name" style="width: 370px;" /> | |||
</el-form-item> | |||
<el-form-item label="部门排序" prop="deptSort"> | |||
<el-input-number | |||
v-model.number="form.deptSort" | |||
:min="0" | |||
:max="999" | |||
controls-position="right" | |||
style="width: 370px;" | |||
/> | |||
</el-form-item> | |||
<el-form-item label="顶级部门"> | |||
<el-radio-group v-model="form.isTop" style="width: 140px"> | |||
<el-radio label="1">是</el-radio> | |||
<el-radio label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item label="状态" prop="enabled"> | |||
<el-radio v-for="item in dict.dept_status" :key="item.id" v-model="form.enabled" :label="item.value">{{ item.label }}</el-radio> | |||
</el-form-item> | |||
<el-form-item v-if="form.isTop === '0'" style="margin-bottom: 0;" label="上级部门" prop="pid"> | |||
<treeselect | |||
v-model="form.pid" | |||
:load-options="loadDepts" | |||
:options="depts" | |||
style="width: 370px;" | |||
placeholder="选择上级类目" | |||
/> | |||
</el-form-item> | |||
</el-form> | |||
<div slot="footer" class="dialog-footer"> | |||
<el-button type="text" @click="crud.cancelCU">取消</el-button> | |||
<el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确认</el-button> | |||
</div> | |||
</el-dialog> | |||
<!--表格渲染--> | |||
<el-table | |||
ref="table" | |||
v-loading="crud.loading" | |||
lazy | |||
:load="getDeptDatas" | |||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}" | |||
:data="crud.data" | |||
row-key="id" | |||
@select="crud.selectChange" | |||
@select-all="crud.selectAllChange" | |||
@selection-change="crud.selectionChangeHandler" | |||
> | |||
<el-table-column :selectable="checkboxT" type="selection" width="55" /> | |||
<el-table-column label="名称" prop="name" /> | |||
<el-table-column label="排序" prop="deptSort" /> | |||
<el-table-column label="状态" align="center" prop="enabled"> | |||
<template slot-scope="scope"> | |||
<el-switch | |||
v-model="scope.row.enabled" | |||
:disabled="scope.row.id === 1" | |||
active-color="#409EFF" | |||
inactive-color="#F56C6C" | |||
@change="changeEnabled(scope.row, scope.row.enabled,)" | |||
/> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="createTime" label="创建日期" /> | |||
<el-table-column v-if="checkPer(['admin','dept:edit','dept:del'])" label="操作" width="130px" align="center" fixed="right"> | |||
<template slot-scope="scope"> | |||
<udOperation | |||
:data="scope.row" | |||
:permission="permission" | |||
:disabled-dle="scope.row.id === 1" | |||
msg="确定删除吗,如果存在下级节点则一并删除,此操作不能撤销!" | |||
/> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
</div> | |||
</template> | |||
<script> | |||
import crudDept from '@/api/system/dept' | |||
import Treeselect from '@riophae/vue-treeselect' | |||
import '@riophae/vue-treeselect/dist/vue-treeselect.css' | |||
import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect' | |||
import CRUD, { presenter, header, form, crud } from '@crud/crud' | |||
import rrOperation from '@crud/RR.operation' | |||
import crudOperation from '@crud/CRUD.operation' | |||
import udOperation from '@crud/UD.operation' | |||
import DateRangePicker from '@/components/DateRangePicker' | |||
const defaultForm = { id: null, name: null, isTop: '1', subCount: 0, pid: null, deptSort: 999, enabled: 'true' } | |||
export default { | |||
name: 'Dept', | |||
components: { Treeselect, crudOperation, rrOperation, udOperation, DateRangePicker }, | |||
cruds() { | |||
return CRUD({ title: '部门', url: 'api/dept', crudMethod: { ...crudDept }}) | |||
}, | |||
mixins: [presenter(), header(), form(defaultForm), crud()], | |||
// 设置数据字典 | |||
dicts: ['dept_status'], | |||
data() { | |||
return { | |||
depts: [], | |||
rules: { | |||
name: [ | |||
{ required: true, message: '请输入名称', trigger: 'blur' } | |||
], | |||
deptSort: [ | |||
{ required: true, message: '请输入序号', trigger: 'blur', type: 'number' } | |||
] | |||
}, | |||
permission: { | |||
add: ['admin', 'dept:add'], | |||
edit: ['admin', 'dept:edit'], | |||
del: ['admin', 'dept:del'] | |||
}, | |||
enabledTypeOptions: [ | |||
{ key: 'true', display_name: '正常' }, | |||
{ key: 'false', display_name: '禁用' } | |||
] | |||
} | |||
}, | |||
methods: { | |||
getDeptDatas(tree, treeNode, resolve) { | |||
const params = { pid: tree.id } | |||
setTimeout(() => { | |||
crudDept.getDepts(params).then(res => { | |||
resolve(res.content) | |||
}) | |||
}, 100) | |||
}, | |||
// 新增与编辑前做的操作 | |||
[CRUD.HOOK.afterToCU](crud, form) { | |||
if (form.pid !== null) { | |||
form.isTop = '0' | |||
} else if (form.id !== null) { | |||
form.isTop = '1' | |||
} | |||
form.enabled = `${form.enabled}` | |||
if (form.id != null) { | |||
this.getSupDepts(form.id) | |||
} else { | |||
this.getDepts() | |||
} | |||
}, | |||
getSupDepts(id) { | |||
crudDept.getDeptSuperior(id).then(res => { | |||
const date = res.content | |||
this.buildDepts(date) | |||
this.depts = date | |||
}) | |||
}, | |||
buildDepts(depts) { | |||
depts.forEach(data => { | |||
if (data.children) { | |||
this.buildDepts(data.children) | |||
} | |||
if (data.hasChildren && !data.children) { | |||
data.children = null | |||
} | |||
}) | |||
}, | |||
getDepts() { | |||
crudDept.getDepts({ enabled: true }).then(res => { | |||
this.depts = res.content.map(function(obj) { | |||
if (obj.hasChildren) { | |||
obj.children = null | |||
} | |||
return obj | |||
}) | |||
}) | |||
}, | |||
// 获取弹窗内部门数据 | |||
loadDepts({ action, parentNode, callback }) { | |||
if (action === LOAD_CHILDREN_OPTIONS) { | |||
crudDept.getDepts({ enabled: true, pid: parentNode.id }).then(res => { | |||
parentNode.children = res.content.map(function(obj) { | |||
if (obj.hasChildren) { | |||
obj.children = null | |||
} | |||
return obj | |||
}) | |||
setTimeout(() => { | |||
callback() | |||
}, 100) | |||
}) | |||
} | |||
}, | |||
// 提交前的验证 | |||
[CRUD.HOOK.afterValidateCU]() { | |||
if (this.form.pid !== null && this.form.pid === this.form.id) { | |||
this.$message({ | |||
message: '上级部门不能为空', | |||
type: 'warning' | |||
}) | |||
return false | |||
} | |||
if (this.form.isTop === '1') { | |||
this.form.pid = null | |||
} | |||
return true | |||
}, | |||
// 改变状态 | |||
changeEnabled(data, val) { | |||
this.$confirm('此操作将 "' + this.dict.label.dept_status[val] + '" ' + data.name + '部门, 是否继续?', '提示', { | |||
confirmButtonText: '确定', | |||
cancelButtonText: '取消', | |||
type: 'warning' | |||
}).then(() => { | |||
crudDept.edit(data).then(res => { | |||
this.crud.notify(this.dict.label.dept_status[val] + '成功', CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}).catch(err => { | |||
data.enabled = !data.enabled | |||
console.log(err.response.data.message) | |||
}) | |||
}).catch(() => { | |||
data.enabled = !data.enabled | |||
}) | |||
}, | |||
checkboxT(row, rowIndex) { | |||
return row.id !== 1 | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
::v-deep .vue-treeselect__control,::v-deep .vue-treeselect__placeholder,::v-deep .vue-treeselect__single-value { | |||
height: 30px; | |||
line-height: 30px; | |||
} | |||
</style> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
::v-deep .el-input-number .el-input__inner { | |||
text-align: left; | |||
} | |||
</style> |
@@ -0,0 +1,22 @@ | |||
import request from '@/utils/request' | |||
export function getErrDetail(id) { | |||
return request({ | |||
url: 'api/logs/error/' + id, | |||
method: 'get' | |||
}) | |||
} | |||
export function delAllError() { | |||
return request({ | |||
url: 'api/logs/del/error', | |||
method: 'delete' | |||
}) | |||
} | |||
export function delAllInfo() { | |||
return request({ | |||
url: 'api/logs/del/info', | |||
method: 'delete' | |||
}) | |||
} |
@@ -0,0 +1,76 @@ | |||
import Date from './datetime.js' | |||
export const calendarBaseShortcuts = [{ | |||
text: '今天', | |||
onClick(picker) { | |||
const startTime = new Date(new Date().setHours(0, 0, 0)) | |||
const endTime = new Date(new Date().setHours(23, 59, 59)) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}, { | |||
text: '昨天', | |||
onClick(picker) { | |||
const startTime = new Date(new Date().daysAgo(1).setHours(0, 0, 0)) | |||
const endTime = new Date(new Date().daysAgo(1).setHours(23, 59, 59)) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}, { | |||
text: '本周', | |||
onClick(picker) { | |||
const startTime = new Date(new Date().daysAgo(new Date().getDay() - 1).setHours(0, 0, 0)) | |||
const endTime = new Date(new Date().setHours(23, 59, 59)) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}, { | |||
text: '这个月', | |||
onClick(picker) { | |||
const startTime = new Date(new Date().monthBegin().setHours(0, 0, 0)) | |||
const endTime = new Date(new Date().setHours(23, 59, 59)) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}, { | |||
text: '当前季度', | |||
onClick(picker) { | |||
const startTime = new Date(new Date().quarterBegin().setHours(0, 0, 0)) | |||
const endTime = new Date(new Date().setHours(23, 59, 59)) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}, { | |||
text: '最近30天', | |||
onClick(picker) { | |||
const startTime = new Date(new Date().daysAgo(30).setHours(0, 0, 0)) | |||
const endTime = new Date(new Date().setHours(23, 59, 59)) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}] | |||
export const calendarMoveShortcuts = [{ | |||
text: '‹ 往前一天 ', | |||
onClick(picker) { | |||
let startTime = new Date(new Date().setHours(0, 0, 0)) | |||
let endTime = new Date(new Date().setHours(23, 59, 59)) | |||
if (!picker.value) { | |||
picker.value = [startTime, endTime] | |||
} | |||
startTime = picker.value[0].daysAgo(1) | |||
endTime = picker.value[1].daysAgo(1) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}, { | |||
text: ' 往后一天 ›', | |||
onClick(picker) { | |||
let startTime = new Date(new Date().setHours(0, 0, 0)) | |||
let endTime = new Date(new Date().setHours(23, 59, 59)) | |||
if (!picker.value) { | |||
picker.value = [startTime, endTime] | |||
} | |||
startTime = picker.value[0].daysAgo(-1) | |||
endTime = picker.value[1].daysAgo(-1) | |||
picker.$emit('pick', [startTime, endTime]) | |||
} | |||
}] | |||
export const calendarShortcuts = [ | |||
...calendarBaseShortcuts, | |||
...calendarMoveShortcuts | |||
] |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="3572" t="1545136555590" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#bfbfbf" d="M403.2 780.8V619.2h-160c-89.6 0-161.6 72-161.6 161.6s72 161.6 161.6 161.6 160-72 160-161.6z m81.6 0c0 134.4-108.8 243.2-243.2 243.2S0 915.2 0 780.8s108.8-243.2 243.2-243.2h243.2c-1.6 0-1.6 243.2-1.6 243.2z m134.4 0V619.2h161.6c89.6 0 161.6 72 161.6 161.6s-72 161.6-161.6 161.6-161.6-72-161.6-161.6z m-81.6 0c0 134.4 108.8 243.2 243.2 243.2S1024 915.2 1024 780.8s-108.8-243.2-243.2-243.2H537.6v243.2z m-134.4-537.6v161.6h-160c-89.6 0-161.6-72-161.6-161.6S153.6 81.6 243.2 81.6s160 72 160 161.6z m81.6 0C484.8 108.8 376 0 243.2 0 108.8 1.6 0 108.8 0 243.2s108.8 243.2 243.2 243.2h243.2c-1.6 0-1.6-243.2-1.6-243.2z m134.4 0v161.6h161.6c89.6 0 161.6-72 161.6-161.6S870.4 81.6 780.8 81.6 619.2 153.6 619.2 243.2z m-81.6 0C537.6 108.8 646.4 0 780.8 0c134.4 1.6 241.6 108.8 241.6 243.2s-108.8 243.2-243.2 243.2H537.6v-81.6-161.6z" p-id="3573"/></svg> |
@@ -0,0 +1,101 @@ | |||
<template> | |||
<div :class="{'hidden':hidden}" class="pagination-container"> | |||
<el-pagination | |||
:background="background" | |||
:current-page.sync="currentPage" | |||
:page-size.sync="pageSize" | |||
:layout="layout" | |||
:page-sizes="pageSizes" | |||
:total="total" | |||
v-bind="$attrs" | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
/> | |||
</div> | |||
</template> | |||
<script> | |||
import { scrollTo } from '@/utils/scroll-to' | |||
export default { | |||
name: 'Pagination', | |||
props: { | |||
total: { | |||
required: true, | |||
type: Number | |||
}, | |||
page: { | |||
type: Number, | |||
default: 1 | |||
}, | |||
limit: { | |||
type: Number, | |||
default: 20 | |||
}, | |||
pageSizes: { | |||
type: Array, | |||
default() { | |||
return [10, 20, 30, 50] | |||
} | |||
}, | |||
layout: { | |||
type: String, | |||
default: 'total, sizes, prev, pager, next, jumper' | |||
}, | |||
background: { | |||
type: Boolean, | |||
default: true | |||
}, | |||
autoScroll: { | |||
type: Boolean, | |||
default: true | |||
}, | |||
hidden: { | |||
type: Boolean, | |||
default: false | |||
} | |||
}, | |||
computed: { | |||
currentPage: { | |||
get() { | |||
return this.page | |||
}, | |||
set(val) { | |||
this.$emit('update:page', val) | |||
} | |||
}, | |||
pageSize: { | |||
get() { | |||
return this.limit | |||
}, | |||
set(val) { | |||
this.$emit('update:limit', val) | |||
} | |||
} | |||
}, | |||
methods: { | |||
handleSizeChange(val) { | |||
this.$emit('pagination', { page: this.currentPage, limit: val }) | |||
if (this.autoScroll) { | |||
scrollTo(0, 800) | |||
} | |||
}, | |||
handleCurrentChange(val) { | |||
this.$emit('pagination', { page: val, limit: this.pageSize }) | |||
if (this.autoScroll) { | |||
scrollTo(0, 800) | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.pagination-container { | |||
background: #fff; | |||
padding: 32px 16px; | |||
} | |||
.pagination-container.hidden { | |||
display: none; | |||
} | |||
</style> |
@@ -0,0 +1,24 @@ | |||
const getters = { | |||
deployUploadApi: state => state.api.deployUploadApi, | |||
databaseUploadApi: state => state.api.databaseUploadApi, | |||
size: state => state.app.size, | |||
sidebar: state => state.app.sidebar, | |||
device: state => state.app.device, | |||
token: state => state.user.token, | |||
visitedViews: state => state.tagsView.visitedViews, | |||
cachedViews: state => state.tagsView.cachedViews, | |||
roles: state => state.user.roles, | |||
user: state => state.user.user, | |||
loadMenus: state => state.user.loadMenus, | |||
permission_routers: state => state.permission.routers, | |||
addRouters: state => state.permission.addRouters, | |||
imagesUploadApi: state => state.api.imagesUploadApi, | |||
baseApi: state => state.api.baseApi, | |||
fileUploadApi: state => state.api.fileUploadApi, | |||
updateAvatarApi: state => state.api.updateAvatarApi, | |||
qiNiuUploadApi: state => state.api.qiNiuUploadApi, | |||
sqlApi: state => state.api.sqlApi, | |||
swaggerApi: state => state.api.swaggerApi, | |||
sidebarRouters: state => state.permission.sidebarRouters | |||
} | |||
export default getters |
@@ -0,0 +1,143 @@ | |||
<template> | |||
<div :class="className" :style="{height:height,width:width}" /> | |||
</template> | |||
<script> | |||
import echarts from 'echarts' | |||
require('echarts/theme/macarons') // echarts theme | |||
import { debounce } from '@/utils' | |||
export default { | |||
props: { | |||
className: { | |||
type: String, | |||
default: 'chart' | |||
}, | |||
width: { | |||
type: String, | |||
default: '100%' | |||
}, | |||
height: { | |||
type: String, | |||
default: '300px' | |||
} | |||
}, | |||
data() { | |||
return { | |||
chart: null | |||
} | |||
}, | |||
mounted() { | |||
this.initChart() | |||
this.__resizeHandler = debounce(() => { | |||
if (this.chart) { | |||
this.chart.resize() | |||
} | |||
}, 100) | |||
window.addEventListener('resize', this.__resizeHandler) | |||
}, | |||
beforeDestroy() { | |||
if (!this.chart) { | |||
return | |||
} | |||
window.removeEventListener('resize', this.__resizeHandler) | |||
this.chart.dispose() | |||
this.chart = null | |||
}, | |||
methods: { | |||
initChart() { | |||
this.chart = echarts.init(this.$el, 'macarons') | |||
const data = [ | |||
[[28604, 77, 17096869, 'Australia', 1990], [31163, 77.4, 27662440, 'Canada', 1990], [1516, 68, 1154605773, 'China', 1990], [13670, 74.7, 10582082, 'Cuba', 1990], [28599, 75, 4986705, 'Finland', 1990], [29476, 77.1, 56943299, 'France', 1990], [31476, 75.4, 78958237, 'Germany', 1990], [28666, 78.1, 254830, 'Iceland', 1990], [1777, 57.7, 870601776, 'India', 1990], [29550, 79.1, 122249285, 'Japan', 1990], [2076, 67.9, 20194354, 'North Korea', 1990], [12087, 72, 42972254, 'South Korea', 1990], [24021, 75.4, 3397534, 'New Zealand', 1990], [43296, 76.8, 4240375, 'Norway', 1990], [10088, 70.8, 38195258, 'Poland', 1990], [19349, 69.6, 147568552, 'Russia', 1990], [10670, 67.3, 53994605, 'Turkey', 1990], [26424, 75.7, 57110117, 'United Kingdom', 1990], [37062, 75.4, 252847810, 'United States', 1990]], | |||
[[44056, 81.8, 23968973, 'Australia', 2015], [43294, 81.7, 35939927, 'Canada', 2015], [13334, 76.9, 1376048943, 'China', 2015], [21291, 78.5, 11389562, 'Cuba', 2015], [38923, 80.8, 5503457, 'Finland', 2015], [37599, 81.9, 64395345, 'France', 2015], [44053, 81.1, 80688545, 'Germany', 2015], [42182, 82.8, 329425, 'Iceland', 2015], [5903, 66.8, 1311050527, 'India', 2015], [36162, 83.5, 126573481, 'Japan', 2015], [1390, 71.4, 25155317, 'North Korea', 2015], [34644, 80.7, 50293439, 'South Korea', 2015], [34186, 80.6, 4528526, 'New Zealand', 2015], [64304, 81.6, 5210967, 'Norway', 2015], [24787, 77.3, 38611794, 'Poland', 2015], [23038, 73.13, 143456918, 'Russia', 2015], [19360, 76.5, 78665830, 'Turkey', 2015], [38225, 81.4, 64715810, 'United Kingdom', 2015], [53354, 79.1, 321773631, 'United States', 2015]] | |||
] | |||
this.chart.setOption({ | |||
title: { | |||
text: '1990 与 2015 年各国家人均寿命与 GDP' | |||
}, | |||
legend: { | |||
right: 10, | |||
data: ['1990', '2015'] | |||
}, | |||
xAxis: { | |||
splitLine: { | |||
lineStyle: { | |||
type: 'dashed' | |||
} | |||
} | |||
}, | |||
yAxis: { | |||
splitLine: { | |||
lineStyle: { | |||
type: 'dashed' | |||
} | |||
}, | |||
scale: true | |||
}, | |||
series: [{ | |||
name: '1990', | |||
data: data[0], | |||
type: 'scatter', | |||
symbolSize: function(data) { | |||
return Math.sqrt(data[2]) / 5e2 | |||
}, | |||
label: { | |||
emphasis: { | |||
show: true, | |||
formatter: function(param) { | |||
return param.data[3] | |||
}, | |||
position: 'top' | |||
} | |||
}, | |||
itemStyle: { | |||
normal: { | |||
shadowBlur: 10, | |||
shadowColor: 'rgba(120, 36, 50, 0.5)', | |||
shadowOffsetY: 5, | |||
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{ | |||
offset: 0, | |||
color: 'rgb(251, 118, 123)' | |||
}, { | |||
offset: 1, | |||
color: 'rgb(204, 46, 72)' | |||
}]) | |||
} | |||
} | |||
}, { | |||
name: '2015', | |||
data: data[1], | |||
type: 'scatter', | |||
symbolSize: function(data) { | |||
return Math.sqrt(data[2]) / 5e2 | |||
}, | |||
label: { | |||
emphasis: { | |||
show: true, | |||
formatter: function(param) { | |||
return param.data[3] | |||
}, | |||
position: 'top' | |||
} | |||
}, | |||
itemStyle: { | |||
normal: { | |||
shadowBlur: 10, | |||
shadowColor: 'rgba(25, 100, 150, 0.5)', | |||
shadowOffsetY: 5, | |||
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{ | |||
offset: 0, | |||
color: 'rgb(129, 227, 238)' | |||
}, { | |||
offset: 1, | |||
color: 'rgb(25, 183, 207)' | |||
}]) | |||
} | |||
} | |||
}] | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,215 @@ | |||
<template> | |||
<div class="app-container"> | |||
<!--搜索--> | |||
<el-form class="mt_15" ref="form" inline size="small"> | |||
<el-form-item label="状态"> | |||
<el-select v-model.trim="searchParm.status" placeholder="请选择"> | |||
<el-option | |||
v-for="item in statusList" | |||
:key="item.value" | |||
:label="item.label" | |||
:value="item.value"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="公司ID"> | |||
<el-input v-model.trim="searchParm.companyId" clearable placeholder='公司ID'></el-input> | |||
</el-form-item> | |||
<el-form-item label="买家ID"> | |||
<el-input v-model.trim="searchParm.tokenEnum" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button type="primary" @click="goSearch">搜索</el-button> | |||
<el-button type="warning" @click="resetForm">重置</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!--表格渲染--> | |||
<el-table ref="table" border size="small" :data="list" :header-cell-style="{textAlign:'center'}" :cell-style="{textAlign:'center'}"> | |||
<el-table-column label="序号" type="index" width="50" /> | |||
<el-table-column label="公司ID" prop="companyId" /> | |||
<el-table-column label="买家ID" prop="tokenEnum" /> | |||
<el-table-column label="订单来源" prop="fromDetailInfo" /> | |||
<el-table-column label="状态" prop="status"> | |||
<template slot-scope="scope"> | |||
{{ scope.row.status | getStatus}} | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="创建时间" prop="createdAt" /> | |||
<el-table-column label="修改时间" prop="updatedAt" /> | |||
<el-table-column label="操作" width="220"> | |||
<template slot-scope="scope"> | |||
<el-button type="info" @click="getBtnById(scope.row.id)">查看</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页--> | |||
<div class="mt_15"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="searchParm.page" | |||
:page-sizes="[10, 20, 30, 40, 50]" | |||
:page-size="searchParm.pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total"> | |||
</el-pagination> | |||
</div> | |||
<!--详情弹窗--> | |||
<el-dialog :visible.sync="dialogDetailVisible" :title="dialogDetailTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="100px"> | |||
<el-form-item label="公司ID" prop="companyId"> | |||
<el-input v-model.trim="detailParm.companyId" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单来源" prop="fromDetailInfo"> | |||
<el-input v-model.trim="detailParm.fromDetailInfo" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="产品信息" prop="cartList" > | |||
<el-input v-model.trim="detailParm.cartList" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="订单收货地址" prop="contactInfo"> | |||
<el-input v-model.trim="detailParm.contactInfo" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="买家ID" prop="tokenEnum"> | |||
<el-input v-model.trim="detailParm.tokenEnum" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="状态" prop="status"> | |||
<!-- <el-input v-model.trim="detailParm.status" :disabled="true"></el-input> --> | |||
<el-select v-model.trim="detailParm.status" disabled placeholder="请选择"> | |||
<el-option | |||
v-for="item in statusList" | |||
:key="item.value" | |||
:label="item.label" | |||
:value="item.value"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { getList, getById } from '@/api/group/excelinfo' | |||
export default { | |||
filters: { | |||
getStatus: function (value) { | |||
if(value == 1) { | |||
return '待处理'; | |||
} else if (value == 2) { | |||
return '处理成功'; | |||
} else { | |||
return '处理失败'; | |||
} | |||
} | |||
}, | |||
// 数据 | |||
data() { | |||
return { | |||
searchParm: { | |||
page: 1, | |||
pageSize: 10, | |||
companyId:null, | |||
sort:'created_at', | |||
order:'desc', | |||
tokenEnum:null, | |||
status:null | |||
}, | |||
total:0, | |||
list: [], | |||
dialogDetailVisible: false, | |||
dialogDetailTitle: '详情', | |||
statusList:[{ | |||
value: null, | |||
label: '全部' | |||
}, | |||
{ | |||
value: 1, | |||
label: '待处理' | |||
}, { | |||
value: 2, | |||
label: '处理成功' | |||
}, { | |||
value: 3, | |||
label: '处理失败' | |||
}], | |||
detailParm: { | |||
id: null, | |||
companyId:'', | |||
fromDetailInfo:'', | |||
cartList: '', | |||
contactInfo:'', | |||
tokenEnum:null, | |||
status:null | |||
}, | |||
} | |||
}, | |||
// 调用 | |||
created() { | |||
this.goSearch() | |||
}, | |||
//方法 | |||
methods: { | |||
resetForm() { | |||
this.searchParm.status = null; | |||
this.searchParm.tokenEnum = null; | |||
this.searchParm.companyId = null; | |||
this.goSearch() | |||
}, | |||
// 查询 | |||
goSearch() { | |||
this.searchParm.page=1 | |||
this.getDataList() | |||
}, | |||
// 查看根据id | |||
getBtnById(id){ | |||
getById({id}).then(res => { | |||
if(res.code==200) { | |||
this.detailParm.id = res.data.id; | |||
this.detailParm.companyId = res.data.companyId; | |||
this.detailParm.fromDetailInfo = res.data.fromDetailInfo; | |||
this.detailParm.cartList = res.data.cartList; | |||
this.detailParm.contactInfo = res.data.contactInfo; | |||
this.detailParm.tokenEnum = res.data.tokenEnum; | |||
this.detailParm.status = res.data.status; | |||
this.dialogDetailVisible = true | |||
this.$refs.ruleForm.clearValidate() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页获取表格数据 | |||
getDataList(){ | |||
getList(this.searchParm).then(res => { | |||
console.log(res) | |||
if(res.code==200) { | |||
console.log(res) | |||
this.list = res.data.list; | |||
this.total = res.data.total; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页 | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.searchParm.pageSize = val; | |||
this.getDataList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.searchParm.page = val; | |||
this.getDataList(); | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
</style> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200.781" height="200" class="icon" p-id="1270" t="1545876582522" version="1.1" viewBox="0 0 1028 1024"><defs><style type="text/css"/></defs><path d="M20.746854 180.67456c-27.09504 27.136-21.31968 65.35168 0.26624 86.87616 0.86016 0.83968 87.49056 83.57888 209.3056 205.4144 3.13344 3.13344 7.22944 4.66944 11.32544 4.66944s8.192-1.57696 11.32544-4.66944c6.2464-6.2464 6.2464-16.384 0-22.6304-18.37056-18.37056-35.84-35.7376-52.40832-52.18304l50.85184-50.85184c6.2464-6.2464 6.2464-16.384 0-22.6304s-16.384-6.2464-22.6304 0l-50.97472 50.97472c-28.50816-28.16-53.63712-52.736-74.07616-72.66304l115.67104-115.67104c6.2464-6.2464 6.2464-16.384 0-22.6304s-16.384-6.2464-22.6304 0l-116.03968 116.03968c-23.552-22.81472-37.13024-35.77856-37.33504-36.00384-6.7584-6.7584-15.62624-25.76384 0-41.3696l160.01024-160.01024c6.18496-6.26688 22.6304-18.71872 40.67328-0.77824 0.79872 0.90112 81.59232 92.672 204.92288 216.00256 6.2464 6.2464 16.384 6.2464 22.6304 0s6.2464-16.384 0-22.6304c-122.55232-122.53184-202.752-213.6064-204.22656-215.26528-29.81888-29.75744-65.80224-20.82816-86.6304 0l-160.03072 160.01024zM699.392614 772.66944c-6.2464-6.2464-16.384-6.2464-22.6304 0l-50.91328 50.87232c-15.52384-15.70816-31.80544-32.1536-48.96768-49.31584-6.2464-6.2464-16.384-6.2464-22.6304 0s-6.2464 16.384 0 22.6304c118.53824 118.49728 201.3184 207.01184 202.50624 208.2816 10.97728 11.01824 26.0096 17.05984 42.33216 17.05984l0 0c16.7936 0 33.792-6.5536 44.31872-17.12128l159.92832-161.83296c20.13184-20.13184 21.27872-54.272 2.49856-73.1136l-214.58944-214.56896c-6.2464-6.2464-16.384-6.2464-22.6304 0s-6.2464 16.384 0 22.6304l214.58944 214.56896c6.41024 6.41024 5.18144 20.23424-2.51904 27.93472l-159.96928 161.83296c-3.6864 3.70688-12.04224 7.68-21.62688 7.68 0 0 0 0 0 0-5.50912 0-13.37344-1.35168-19.33312-7.33184-0.32768-0.34816-13.7216-14.66368-36.98688-39.0144l116.61312-116.61312c6.2464-6.2464 6.2464-16.384 0-22.6304s-16.384-6.2464-22.6304 0l-116.1216 116.1216c-19.968-20.76672-44.4416-46.01856-72.31488-74.42432l51.07712-51.07712c6.2464-6.20544 6.2464-16.32256 0-22.58944zM4.608614 1018.53184c3.072 3.13344 7.20896 4.79232 11.44832 4.79232 1.536 0 3.072-0.22528 4.56704-0.67584l320-95.3344c2.60096-0.77824 4.89472-2.1504 6.77888-4.05504l546.87744-550.56384c0.77824-0.77824 1.14688-1.76128 1.72032-2.62144l116.98176-117.00224c9.40032-9.44128 14.62272-21.95456 14.62272-35.28704 0-13.312-5.2224-25.82528-14.62272-35.20512l-167.5264-167.48544c-18.82112-18.82112-51.67104-18.82112-70.49216 0l-119.64416 119.64416c-0.77824 0.75776-1.18784 1.76128-1.76128 2.6624l-547.71712 547.7376c-1.80224 1.78176-3.13344 3.97312-3.91168 6.36928l-101.13024 310.8864c-1.86368 5.67296-0.4096 11.83744 3.74784 16.13824zM667.587174 168.67328l33.23904 33.23904-496.7424 498.0736-55.25504-12.53376 518.7584-518.77888zM224.072294 725.31968l499.42528-500.736 77.94688 77.94688-503.93088 497.47968-73.44128 0 0-74.69056zM860.365414 361.472l-519.80288 523.32544-18.47296-64.06144 501.98528-495.57504 36.29056 36.31104zM127.836774 715.48928l64.22528 14.58176 0 85.9136c0 8.82688 7.168 15.99488 15.99488 15.99488l83.968 0 20.29568 70.41024-271.60576 80.93696 87.1424-267.83744zM797.676134 37.72416c6.7584-6.7584 18.49344-6.7584 25.25184 0l167.5264 167.5264c3.35872 3.35872 5.2224 7.84384 5.2224 12.61568 0 4.73088-1.86368 9.25696-5.24288 12.63616l-107.86816 107.90912-192.73728-192.73728 107.86816-107.9296z" p-id="1271"/></svg> |
@@ -0,0 +1,116 @@ | |||
<template> | |||
<div :class="classObj" class="app-wrapper"> | |||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> | |||
<sidebar class="sidebar-container" /> | |||
<div :class="{hasTagsView:needTagsView}" class="main-container"> | |||
<div :class="{'fixed-header':fixedHeader}"> | |||
<navbar /> | |||
<tags-view v-if="needTagsView" /> | |||
</div> | |||
<app-main /> | |||
<right-panel v-if="showSettings"> | |||
<settings /> | |||
</right-panel> | |||
</div> | |||
<!-- 防止刷新后主题丢失 --> | |||
<Theme v-show="false" ref="theme" /> | |||
</div> | |||
</template> | |||
<script> | |||
import RightPanel from '@/components/RightPanel' | |||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components' | |||
import ResizeMixin from './mixin/ResizeHandler' | |||
import { mapState } from 'vuex' | |||
import Theme from '@/components/ThemePicker' | |||
import Cookies from 'js-cookie' | |||
export default { | |||
name: 'Layout', | |||
components: { | |||
AppMain, | |||
Navbar, | |||
RightPanel, | |||
Settings, | |||
Sidebar, | |||
TagsView, | |||
Theme | |||
}, | |||
mixins: [ResizeMixin], | |||
computed: { | |||
...mapState({ | |||
sidebar: state => state.app.sidebar, | |||
device: state => state.app.device, | |||
showSettings: state => state.settings.showSettings, | |||
needTagsView: state => state.settings.tagsView, | |||
fixedHeader: state => state.settings.fixedHeader | |||
}), | |||
classObj() { | |||
return { | |||
hideSidebar: !this.sidebar.opened, | |||
openSidebar: this.sidebar.opened, | |||
withoutAnimation: this.sidebar.withoutAnimation, | |||
mobile: this.device === 'mobile' | |||
} | |||
} | |||
}, | |||
mounted() { | |||
if (Cookies.get('theme')) { | |||
this.$refs.theme.theme = Cookies.get('theme') | |||
this.$store.dispatch('settings/changeSetting', { | |||
key: 'theme', | |||
value: Cookies.get('theme') | |||
}) | |||
} | |||
}, | |||
methods: { | |||
handleClickOutside() { | |||
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false }) | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
@import "~@/assets/styles/mixin.scss"; | |||
@import "~@/assets/styles/variables.scss"; | |||
.app-wrapper { | |||
@include clearfix; | |||
position: relative; | |||
height: 100%; | |||
width: 100%; | |||
&.mobile.openSidebar { | |||
position: fixed; | |||
top: 0; | |||
} | |||
} | |||
.drawer-bg { | |||
background: #000; | |||
opacity: 0.3; | |||
width: 100%; | |||
top: 0; | |||
height: 100%; | |||
position: absolute; | |||
z-index: 999; | |||
} | |||
.fixed-header { | |||
position: fixed; | |||
top: 0; | |||
right: 0; | |||
z-index: 9; | |||
width: calc(100% - #{$sideBarWidth}); | |||
transition: width 0.28s; | |||
padding: 0; | |||
} | |||
.hideSidebar .fixed-header { | |||
width: calc(100% - 54px) | |||
} | |||
.mobile .fixed-header { | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,10 @@ | |||
import request from '@/utils/request' | |||
export function getById(data) { | |||
return request({ | |||
url: 'api/dhAddCarCatch/getById', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
@@ -0,0 +1,863 @@ | |||
import { initData, download } from '@/api/data' | |||
import { parseTime, downloadFile } from '@/utils/index' | |||
import Vue from 'vue' | |||
/** | |||
* CRUD配置 | |||
* @author moxun | |||
* @param {*} options <br> | |||
* @return crud instance. | |||
* @example | |||
* 要使用多crud时,请在关联crud的组件处使用crud-tag进行标记,如:<jobForm :job-status="dict.job_status" crud-tag="job" /> | |||
*/ | |||
function CRUD(options) { | |||
const defaultOptions = { | |||
tag: 'default', | |||
// id字段名 | |||
idField: 'id', | |||
// 标题 | |||
title: '', | |||
// 请求数据的url | |||
url: '', | |||
// 表格数据 | |||
data: [], | |||
// 选择项 | |||
selections: [], | |||
// 待查询的对象 | |||
query: {}, | |||
// 查询数据的参数 | |||
params: {}, | |||
// Form 表单 | |||
form: {}, | |||
// 重置表单 | |||
defaultForm: () => {}, | |||
// 排序规则,默认 id 降序, 支持多字段排序 ['id,desc', 'createTime,asc'] | |||
sort: ['id,desc'], | |||
// 等待时间 | |||
time: 50, | |||
// CRUD Method | |||
crudMethod: { | |||
add: (form) => {}, | |||
del: (id) => {}, | |||
edit: (form) => {}, | |||
get: (id) => {} | |||
}, | |||
// 主页操作栏显示哪些按钮 | |||
optShow: { | |||
add: true, | |||
edit: true, | |||
del: true, | |||
download: true, | |||
reset: true | |||
}, | |||
// 自定义一些扩展属性 | |||
props: {}, | |||
// 在主页准备 | |||
queryOnPresenterCreated: true, | |||
// 调试开关 | |||
debug: false | |||
} | |||
options = mergeOptions(defaultOptions, options) | |||
const data = { | |||
...options, | |||
// 记录数据状态 | |||
dataStatus: {}, | |||
status: { | |||
add: CRUD.STATUS.NORMAL, | |||
edit: CRUD.STATUS.NORMAL, | |||
// 添加或编辑状态 | |||
get cu() { | |||
if (this.add === CRUD.STATUS.NORMAL && this.edit === CRUD.STATUS.NORMAL) { | |||
return CRUD.STATUS.NORMAL | |||
} else if (this.add === CRUD.STATUS.PREPARED || this.edit === CRUD.STATUS.PREPARED) { | |||
return CRUD.STATUS.PREPARED | |||
} else if (this.add === CRUD.STATUS.PROCESSING || this.edit === CRUD.STATUS.PROCESSING) { | |||
return CRUD.STATUS.PROCESSING | |||
} | |||
throw new Error('wrong crud\'s cu status') | |||
}, | |||
// 标题 | |||
get title() { | |||
return this.add > CRUD.STATUS.NORMAL ? `新增${crud.title}` : this.edit > CRUD.STATUS.NORMAL ? `编辑${crud.title}` : crud.title | |||
} | |||
}, | |||
msg: { | |||
submit: '提交成功', | |||
add: '新增成功', | |||
edit: '编辑成功', | |||
del: '删除成功' | |||
}, | |||
page: { | |||
// 页码 | |||
page: 0, | |||
// 每页数据条数 | |||
size: 10, | |||
// 总数据条数 | |||
total: 0 | |||
}, | |||
// 整体loading | |||
loading: false, | |||
// 导出的 Loading | |||
downloadLoading: false, | |||
// 删除的 Loading | |||
delAllLoading: false | |||
} | |||
const methods = { | |||
/** | |||
* 通用的提示 | |||
*/ | |||
submitSuccessNotify() { | |||
crud.notify(crud.msg.submit, CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}, | |||
addSuccessNotify() { | |||
crud.notify(crud.msg.add, CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}, | |||
editSuccessNotify() { | |||
crud.notify(crud.msg.edit, CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}, | |||
delSuccessNotify() { | |||
crud.notify(crud.msg.del, CRUD.NOTIFICATION_TYPE.SUCCESS) | |||
}, | |||
// 搜索 | |||
toQuery() { | |||
crud.page.page = 1 | |||
crud.refresh() | |||
}, | |||
// 刷新 | |||
refresh() { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeRefresh)) { | |||
return | |||
} | |||
return new Promise((resolve, reject) => { | |||
crud.loading = true | |||
// 请求数据 | |||
initData(crud.url, crud.getQueryParams()).then(data => { | |||
const table = crud.getTable() | |||
if (table && table.lazy) { // 懒加载子节点数据,清掉已加载的数据 | |||
table.store.states.treeData = {} | |||
table.store.states.lazyTreeNodeMap = {} | |||
} | |||
crud.page.total = data.totalElements | |||
crud.data = data.content | |||
crud.resetDataStatus() | |||
// time 毫秒后显示表格 | |||
setTimeout(() => { | |||
crud.loading = false | |||
callVmHook(crud, CRUD.HOOK.afterRefresh) | |||
}, crud.time) | |||
resolve(data) | |||
}).catch(err => { | |||
crud.loading = false | |||
reject(err) | |||
}) | |||
}) | |||
}, | |||
/** | |||
* 启动添加 | |||
*/ | |||
toAdd() { | |||
crud.resetForm() | |||
if (!(callVmHook(crud, CRUD.HOOK.beforeToAdd, crud.form) && callVmHook(crud, CRUD.HOOK.beforeToCU, crud.form))) { | |||
return | |||
} | |||
crud.status.add = CRUD.STATUS.PREPARED | |||
callVmHook(crud, CRUD.HOOK.afterToAdd, crud.form) | |||
callVmHook(crud, CRUD.HOOK.afterToCU, crud.form) | |||
}, | |||
/** | |||
* 启动编辑 | |||
* @param {*} data 数据项 | |||
*/ | |||
toEdit(data) { | |||
crud.resetForm(JSON.parse(JSON.stringify(data))) | |||
if (!(callVmHook(crud, CRUD.HOOK.beforeToEdit, crud.form) && callVmHook(crud, CRUD.HOOK.beforeToCU, crud.form))) { | |||
return | |||
} | |||
crud.status.edit = CRUD.STATUS.PREPARED | |||
crud.getDataStatus(crud.getDataId(data)).edit = CRUD.STATUS.PREPARED | |||
callVmHook(crud, CRUD.HOOK.afterToEdit, crud.form) | |||
callVmHook(crud, CRUD.HOOK.afterToCU, crud.form) | |||
}, | |||
/** | |||
* 启动删除 | |||
* @param {*} data 数据项 | |||
*/ | |||
toDelete(data) { | |||
crud.getDataStatus(crud.getDataId(data)).delete = CRUD.STATUS.PREPARED | |||
}, | |||
/** | |||
* 取消删除 | |||
* @param {*} data 数据项 | |||
*/ | |||
cancelDelete(data) { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeDeleteCancel, data)) { | |||
return | |||
} | |||
crud.getDataStatus(crud.getDataId(data)).delete = CRUD.STATUS.NORMAL | |||
callVmHook(crud, CRUD.HOOK.afterDeleteCancel, data) | |||
}, | |||
/** | |||
* 取消新增/编辑 | |||
*/ | |||
cancelCU() { | |||
const addStatus = crud.status.add | |||
const editStatus = crud.status.edit | |||
if (addStatus === CRUD.STATUS.PREPARED) { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeAddCancel, crud.form)) { | |||
return | |||
} | |||
crud.status.add = CRUD.STATUS.NORMAL | |||
} | |||
if (editStatus === CRUD.STATUS.PREPARED) { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeEditCancel, crud.form)) { | |||
return | |||
} | |||
crud.status.edit = CRUD.STATUS.NORMAL | |||
crud.getDataStatus(crud.getDataId(crud.form)).edit = CRUD.STATUS.NORMAL | |||
} | |||
crud.resetForm() | |||
if (addStatus === CRUD.STATUS.PREPARED) { | |||
callVmHook(crud, CRUD.HOOK.afterAddCancel, crud.form) | |||
} | |||
if (editStatus === CRUD.STATUS.PREPARED) { | |||
callVmHook(crud, CRUD.HOOK.afterEditCancel, crud.form) | |||
} | |||
// 清除表单验证 | |||
if (crud.findVM('form').$refs['form']) { | |||
crud.findVM('form').$refs['form'].clearValidate() | |||
} | |||
}, | |||
/** | |||
* 提交新增/编辑 | |||
*/ | |||
submitCU() { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeValidateCU)) { | |||
return | |||
} | |||
crud.findVM('form').$refs['form'].validate(valid => { | |||
if (!valid) { | |||
return | |||
} | |||
if (!callVmHook(crud, CRUD.HOOK.afterValidateCU)) { | |||
return | |||
} | |||
if (crud.status.add === CRUD.STATUS.PREPARED) { | |||
crud.doAdd() | |||
} else if (crud.status.edit === CRUD.STATUS.PREPARED) { | |||
crud.doEdit() | |||
} | |||
}) | |||
}, | |||
/** | |||
* 执行添加 | |||
*/ | |||
doAdd() { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeSubmit)) { | |||
return | |||
} | |||
crud.status.add = CRUD.STATUS.PROCESSING | |||
crud.crudMethod.add(crud.form).then(() => { | |||
crud.status.add = CRUD.STATUS.NORMAL | |||
crud.resetForm() | |||
crud.addSuccessNotify() | |||
callVmHook(crud, CRUD.HOOK.afterSubmit) | |||
crud.toQuery() | |||
}).catch(() => { | |||
crud.status.add = CRUD.STATUS.PREPARED | |||
callVmHook(crud, CRUD.HOOK.afterAddError) | |||
}) | |||
}, | |||
/** | |||
* 执行编辑 | |||
*/ | |||
doEdit() { | |||
if (!callVmHook(crud, CRUD.HOOK.beforeSubmit)) { | |||
return | |||
} | |||
crud.status.edit = CRUD.STATUS.PROCESSING | |||
crud.crudMethod.edit(crud.form).then(() => { | |||
crud.status.edit = CRUD.STATUS.NORMAL | |||
crud.getDataStatus(crud.getDataId(crud.form)).edit = CRUD.STATUS.NORMAL | |||
crud.editSuccessNotify() | |||
crud.resetForm() | |||
callVmHook(crud, CRUD.HOOK.afterSubmit) | |||
crud.refresh() | |||
}).catch(() => { | |||
crud.status.edit = CRUD.STATUS.PREPARED | |||
callVmHook(crud, CRUD.HOOK.afterEditError) | |||
}) | |||
}, | |||
/** | |||
* 执行删除 | |||
* @param {*} data 数据项 | |||
*/ | |||
doDelete(data) { | |||
let delAll = false | |||
let dataStatus | |||
const ids = [] | |||
if (data instanceof Array) { | |||
delAll = true | |||
data.forEach(val => { | |||
ids.push(this.getDataId(val)) | |||
}) | |||
} else { | |||
ids.push(this.getDataId(data)) | |||
dataStatus = crud.getDataStatus(this.getDataId(data)) | |||
} | |||
if (!callVmHook(crud, CRUD.HOOK.beforeDelete, data)) { | |||
return | |||
} | |||
if (!delAll) { | |||
dataStatus.delete = CRUD.STATUS.PROCESSING | |||
} | |||
return crud.crudMethod.del(ids).then(() => { | |||
if (delAll) { | |||
crud.delAllLoading = false | |||
} else dataStatus.delete = CRUD.STATUS.PREPARED | |||
crud.dleChangePage(1) | |||
crud.delSuccessNotify() | |||
callVmHook(crud, CRUD.HOOK.afterDelete, data) | |||
crud.refresh() | |||
}).catch(() => { | |||
if (delAll) { | |||
crud.delAllLoading = false | |||
} else dataStatus.delete = CRUD.STATUS.PREPARED | |||
}) | |||
}, | |||
/** | |||
* 通用导出 | |||
*/ | |||
doExport() { | |||
crud.downloadLoading = true | |||
download(crud.url + '/download', crud.getQueryParams()).then(result => { | |||
downloadFile(result, crud.title + '数据', 'xlsx') | |||
crud.downloadLoading = false | |||
}).catch(() => { | |||
crud.downloadLoading = false | |||
}) | |||
}, | |||
/** | |||
* 获取查询参数 | |||
*/ | |||
getQueryParams: function() { | |||
// 清除参数无值的情况 | |||
Object.keys(crud.query).length !== 0 && Object.keys(crud.query).forEach(item => { | |||
if (crud.query[item] === null || crud.query[item] === '') crud.query[item] = undefined | |||
}) | |||
Object.keys(crud.params).length !== 0 && Object.keys(crud.params).forEach(item => { | |||
if (crud.params[item] === null || crud.params[item] === '') crud.params[item] = undefined | |||
}) | |||
return { | |||
page: crud.page.page - 1, | |||
size: crud.page.size, | |||
sort: crud.sort, | |||
...crud.query, | |||
...crud.params | |||
} | |||
}, | |||
// 当前页改变 | |||
pageChangeHandler(e) { | |||
crud.page.page = e | |||
crud.refresh() | |||
}, | |||
// 每页条数改变 | |||
sizeChangeHandler(e) { | |||
crud.page.size = e | |||
crud.page.page = 1 | |||
crud.refresh() | |||
}, | |||
// 预防删除第二页最后一条数据时,或者多选删除第二页的数据时,页码错误导致请求无数据 | |||
dleChangePage(size) { | |||
if (crud.data.length === size && crud.page.page !== 1) { | |||
crud.page.page -= 1 | |||
} | |||
}, | |||
// 选择改变 | |||
selectionChangeHandler(val) { | |||
crud.selections = val | |||
}, | |||
/** | |||
* 重置查询参数 | |||
* @param {Boolean} toQuery 重置后进行查询操作 | |||
*/ | |||
resetQuery(toQuery = true) { | |||
const defaultQuery = JSON.parse(JSON.stringify(crud.defaultQuery)) | |||
const query = crud.query | |||
Object.keys(query).forEach(key => { | |||
query[key] = defaultQuery[key] | |||
}) | |||
// 重置参数 | |||
this.params = {} | |||
if (toQuery) { | |||
crud.toQuery() | |||
} | |||
}, | |||
/** | |||
* 重置表单 | |||
* @param {Array} data 数据 | |||
*/ | |||
resetForm(data) { | |||
const form = data || (typeof crud.defaultForm === 'object' ? JSON.parse(JSON.stringify(crud.defaultForm)) : crud.defaultForm.apply(crud.findVM('form'))) | |||
const crudFrom = crud.form | |||
for (const key in form) { | |||
if (crudFrom.hasOwnProperty(key)) { | |||
crudFrom[key] = form[key] | |||
} else { | |||
Vue.set(crudFrom, key, form[key]) | |||
} | |||
} | |||
// add by ghl 2020-10-04 页面重复添加信息时,下拉框的校验会存在,需要找工取消 | |||
if (crud.findVM('form').$refs['form']) { | |||
crud.findVM('form').$refs['form'].clearValidate() | |||
} | |||
}, | |||
/** | |||
* 重置数据状态 | |||
*/ | |||
resetDataStatus() { | |||
const dataStatus = {} | |||
function resetStatus(datas) { | |||
datas.forEach(e => { | |||
dataStatus[crud.getDataId(e)] = { | |||
delete: 0, | |||
edit: 0 | |||
} | |||
if (e.children) { | |||
resetStatus(e.children) | |||
} | |||
}) | |||
} | |||
resetStatus(crud.data) | |||
crud.dataStatus = dataStatus | |||
}, | |||
/** | |||
* 获取数据状态 | |||
* @param {Number | String} id 数据项id | |||
*/ | |||
getDataStatus(id) { | |||
return crud.dataStatus[id] | |||
}, | |||
/** | |||
* 用于树形表格多选, 选中所有 | |||
* @param selection | |||
*/ | |||
selectAllChange(selection) { | |||
// 如果选中的数目与请求到的数目相同就选中子节点,否则就清空选中 | |||
if (selection && selection.length === crud.data.length) { | |||
selection.forEach(val => { | |||
crud.selectChange(selection, val) | |||
}) | |||
} else { | |||
crud.getTable().clearSelection() | |||
} | |||
}, | |||
/** | |||
* 用于树形表格多选,单选的封装 | |||
* @param selection | |||
* @param row | |||
*/ | |||
selectChange(selection, row) { | |||
// 如果selection中存在row代表是选中,否则是取消选中 | |||
if (selection.find(val => { return crud.getDataId(val) === crud.getDataId(row) })) { | |||
if (row.children) { | |||
row.children.forEach(val => { | |||
crud.getTable().toggleRowSelection(val, true) | |||
selection.push(val) | |||
if (val.children) { | |||
crud.selectChange(selection, val) | |||
} | |||
}) | |||
} | |||
} else { | |||
crud.toggleRowSelection(selection, row) | |||
} | |||
}, | |||
/** | |||
* 切换选中状态 | |||
* @param selection | |||
* @param data | |||
*/ | |||
toggleRowSelection(selection, data) { | |||
if (data.children) { | |||
data.children.forEach(val => { | |||
crud.getTable().toggleRowSelection(val, false) | |||
if (val.children) { | |||
crud.toggleRowSelection(selection, val) | |||
} | |||
}) | |||
} | |||
}, | |||
findVM(type) { | |||
return crud.vms.find(vm => vm && vm.type === type).vm | |||
}, | |||
notify(title, type = CRUD.NOTIFICATION_TYPE.INFO) { | |||
crud.vms[0].vm.$notify({ | |||
title, | |||
type, | |||
duration: 2500 | |||
}) | |||
}, | |||
updateProp(name, value) { | |||
Vue.set(crud.props, name, value) | |||
}, | |||
getDataId(data) { | |||
return data[this.idField] | |||
}, | |||
getTable() { | |||
return this.findVM('presenter').$refs.table | |||
}, | |||
attchTable() { | |||
const table = this.getTable() | |||
this.updateProp('table', table) | |||
const that = this | |||
table.$on('expand-change', (row, expanded) => { | |||
if (!expanded) { | |||
return | |||
} | |||
const lazyTreeNodeMap = table.store.states.lazyTreeNodeMap | |||
row.children = lazyTreeNodeMap[crud.getDataId(row)] | |||
if (row.children) { | |||
row.children.forEach(ele => { | |||
const id = crud.getDataId(ele) | |||
if (that.dataStatus[id] === undefined) { | |||
that.dataStatus[id] = { | |||
delete: 0, | |||
edit: 0 | |||
} | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
} | |||
const crud = Object.assign({}, data) | |||
// 可观测化 | |||
Vue.observable(crud) | |||
// 附加方法 | |||
Object.assign(crud, methods) | |||
// 记录初始默认的查询参数,后续重置查询时使用 | |||
Object.assign(crud, { | |||
defaultQuery: JSON.parse(JSON.stringify(data.query)), | |||
// 预留4位存储:组件 主页、头部、分页、表单,调试查看也方便找 | |||
vms: Array(4), | |||
/** | |||
* 注册组件实例 | |||
* @param {String} type 类型 | |||
* @param {*} vm 组件实例 | |||
* @param {Number} index 该参数内部使用 | |||
*/ | |||
registerVM(type, vm, index = -1) { | |||
const vmObj = { | |||
type, | |||
vm: vm | |||
} | |||
if (index < 0) { | |||
this.vms.push(vmObj) | |||
return | |||
} | |||
if (index < 4) { // 内置预留vm数 | |||
this.vms[index] = vmObj | |||
return | |||
} | |||
this.vms.length = Math.max(this.vms.length, index) | |||
this.vms.splice(index, 1, vmObj) | |||
}, | |||
/** | |||
* 取消注册组件实例 | |||
* @param {*} vm 组件实例 | |||
*/ | |||
unregisterVM(type, vm) { | |||
for (let i = this.vms.length - 1; i >= 0; i--) { | |||
if (this.vms[i] === undefined) { | |||
continue | |||
} | |||
if (this.vms[i].type === type && this.vms[i].vm === vm) { | |||
if (i < 4) { // 内置预留vm数 | |||
this.vms[i] = undefined | |||
} else { | |||
this.vms.splice(i, 1) | |||
} | |||
break | |||
} | |||
} | |||
} | |||
}) | |||
// 冻结处理,需要扩展数据的话,使用crud.updateProp(name, value),以crud.props.name形式访问,这个是响应式的,可以做数据绑定 | |||
Object.freeze(crud) | |||
return crud | |||
} | |||
// hook VM | |||
function callVmHook(crud, hook) { | |||
if (crud.debug) { | |||
console.log('callVmHook: ' + hook) | |||
} | |||
const tagHook = crud.tag ? hook + '$' + crud.tag : null | |||
let ret = true | |||
const nargs = [crud] | |||
for (let i = 2; i < arguments.length; ++i) { | |||
nargs.push(arguments[i]) | |||
} | |||
// 有些组件扮演了多个角色,调用钩子时,需要去重 | |||
const vmSet = new Set() | |||
crud.vms.forEach(vm => vm && vmSet.add(vm.vm)) | |||
vmSet.forEach(vm => { | |||
if (vm[hook]) { | |||
ret = vm[hook].apply(vm, nargs) !== false && ret | |||
} | |||
if (tagHook && vm[tagHook]) { | |||
ret = vm[tagHook].apply(vm, nargs) !== false && ret | |||
} | |||
}) | |||
return ret | |||
} | |||
function mergeOptions(src, opts) { | |||
const optsRet = { | |||
...src | |||
} | |||
for (const key in src) { | |||
if (opts.hasOwnProperty(key)) { | |||
optsRet[key] = opts[key] | |||
} | |||
} | |||
return optsRet | |||
} | |||
/** | |||
* 查找crud | |||
* @param {*} vm | |||
* @param {string} tag | |||
*/ | |||
function lookupCrud(vm, tag) { | |||
tag = tag || vm.$attrs['crud-tag'] || 'default' | |||
// function lookupCrud(vm, tag) { | |||
if (vm.$crud) { | |||
const ret = vm.$crud[tag] | |||
if (ret) { | |||
return ret | |||
} | |||
} | |||
return vm.$parent ? lookupCrud(vm.$parent, tag) : undefined | |||
} | |||
/** | |||
* crud主页 | |||
*/ | |||
function presenter(crud) { | |||
if (crud) { | |||
console.warn('[CRUD warn]: ' + 'please use $options.cruds() { return CRUD(...) or [CRUD(...), ...] }') | |||
} | |||
return { | |||
data() { | |||
// 在data中返回crud,是为了将crud与当前实例关联,组件观测crud相关属性变化 | |||
return { | |||
crud: this.crud | |||
} | |||
}, | |||
beforeCreate() { | |||
this.$crud = this.$crud || {} | |||
let cruds = this.$options.cruds instanceof Function ? this.$options.cruds() : crud | |||
if (!(cruds instanceof Array)) { | |||
cruds = [cruds] | |||
} | |||
cruds.forEach(ele => { | |||
if (this.$crud[ele.tag]) { | |||
console.error('[CRUD error]: ' + 'crud with tag [' + ele.tag + ' is already exist') | |||
} | |||
this.$crud[ele.tag] = ele | |||
ele.registerVM('presenter', this, 0) | |||
}) | |||
this.crud = this.$crud['defalut'] || cruds[0] | |||
}, | |||
methods: { | |||
parseTime | |||
}, | |||
created() { | |||
for (const k in this.$crud) { | |||
if (this.$crud[k].queryOnPresenterCreated) { | |||
this.$crud[k].toQuery() | |||
} | |||
} | |||
}, | |||
destroyed() { | |||
for (const k in this.$crud) { | |||
this.$crud[k].unregisterVM('presenter', this) | |||
} | |||
}, | |||
mounted() { | |||
// 如果table未实例化(例如使用了v-if),请稍后在适当时机crud.attchTable刷新table信息 | |||
if (this.$refs.table !== undefined) { | |||
this.crud.attchTable() | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* 头部 | |||
*/ | |||
function header() { | |||
return { | |||
data() { | |||
return { | |||
crud: this.crud, | |||
query: this.crud.query | |||
} | |||
}, | |||
beforeCreate() { | |||
this.crud = lookupCrud(this) | |||
this.crud.registerVM('header', this, 1) | |||
}, | |||
destroyed() { | |||
this.crud.unregisterVM('header', this) | |||
} | |||
} | |||
} | |||
/** | |||
* 分页 | |||
*/ | |||
function pagination() { | |||
return { | |||
data() { | |||
return { | |||
crud: this.crud, | |||
page: this.crud.page | |||
} | |||
}, | |||
beforeCreate() { | |||
this.crud = lookupCrud(this) | |||
this.crud.registerVM('pagination', this, 2) | |||
}, | |||
destroyed() { | |||
this.crud.unregisterVM('pagination', this) | |||
} | |||
} | |||
} | |||
/** | |||
* 表单 | |||
*/ | |||
function form(defaultForm) { | |||
return { | |||
data() { | |||
return { | |||
crud: this.crud, | |||
form: this.crud.form | |||
} | |||
}, | |||
beforeCreate() { | |||
this.crud = lookupCrud(this) | |||
this.crud.registerVM('form', this, 3) | |||
}, | |||
created() { | |||
this.crud.defaultForm = defaultForm | |||
this.crud.resetForm() | |||
}, | |||
destroyed() { | |||
this.crud.unregisterVM('form', this) | |||
} | |||
} | |||
} | |||
/** | |||
* crud | |||
*/ | |||
function crud(options = {}) { | |||
const defaultOptions = { | |||
type: undefined | |||
} | |||
options = mergeOptions(defaultOptions, options) | |||
return { | |||
data() { | |||
return { | |||
crud: this.crud | |||
} | |||
}, | |||
beforeCreate() { | |||
this.crud = lookupCrud(this) | |||
this.crud.registerVM(options.type, this) | |||
}, | |||
destroyed() { | |||
this.crud.unregisterVM(options.type, this) | |||
} | |||
} | |||
} | |||
/** | |||
* CRUD钩子 | |||
*/ | |||
CRUD.HOOK = { | |||
/** 刷新 - 之前 */ | |||
beforeRefresh: 'beforeCrudRefresh', | |||
/** 刷新 - 之后 */ | |||
afterRefresh: 'afterCrudRefresh', | |||
/** 删除 - 之前 */ | |||
beforeDelete: 'beforeCrudDelete', | |||
/** 删除 - 之后 */ | |||
afterDelete: 'afterCrudDelete', | |||
/** 删除取消 - 之前 */ | |||
beforeDeleteCancel: 'beforeCrudDeleteCancel', | |||
/** 删除取消 - 之后 */ | |||
afterDeleteCancel: 'afterCrudDeleteCancel', | |||
/** 新建 - 之前 */ | |||
beforeToAdd: 'beforeCrudToAdd', | |||
/** 新建 - 之后 */ | |||
afterToAdd: 'afterCrudToAdd', | |||
/** 编辑 - 之前 */ | |||
beforeToEdit: 'beforeCrudToEdit', | |||
/** 编辑 - 之后 */ | |||
afterToEdit: 'afterCrudToEdit', | |||
/** 开始 "新建/编辑" - 之前 */ | |||
beforeToCU: 'beforeCrudToCU', | |||
/** 开始 "新建/编辑" - 之后 */ | |||
afterToCU: 'afterCrudToCU', | |||
/** "新建/编辑" 验证 - 之前 */ | |||
beforeValidateCU: 'beforeCrudValidateCU', | |||
/** "新建/编辑" 验证 - 之后 */ | |||
afterValidateCU: 'afterCrudValidateCU', | |||
/** 添加取消 - 之前 */ | |||
beforeAddCancel: 'beforeCrudAddCancel', | |||
/** 添加取消 - 之后 */ | |||
afterAddCancel: 'afterCrudAddCancel', | |||
/** 编辑取消 - 之前 */ | |||
beforeEditCancel: 'beforeCrudEditCancel', | |||
/** 编辑取消 - 之后 */ | |||
afterEditCancel: 'afterCrudEditCancel', | |||
/** 提交 - 之前 */ | |||
beforeSubmit: 'beforeCrudSubmitCU', | |||
/** 提交 - 之后 */ | |||
afterSubmit: 'afterCrudSubmitCU', | |||
afterAddError: 'afterCrudAddError', | |||
afterEditError: 'afterCrudEditError' | |||
} | |||
/** | |||
* CRUD状态 | |||
*/ | |||
CRUD.STATUS = { | |||
NORMAL: 0, | |||
PREPARED: 1, | |||
PROCESSING: 2 | |||
} | |||
/** | |||
* CRUD通知类型 | |||
*/ | |||
CRUD.NOTIFICATION_TYPE = { | |||
SUCCESS: 'success', | |||
WARNING: 'warning', | |||
INFO: 'info', | |||
ERROR: 'error' | |||
} | |||
export default CRUD | |||
export { | |||
presenter, | |||
header, | |||
form, | |||
pagination, | |||
crud | |||
} |
@@ -0,0 +1,98 @@ | |||
<template> | |||
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" title="七牛云配置" append-to-body width="580px"> | |||
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="110px"> | |||
<el-form-item label="Access Key" prop="accessKey"> | |||
<el-input v-model="form.accessKey" style="width: 95%" placeholder="accessKey,在安全中心,秘钥管理中查看" /> | |||
</el-form-item> | |||
<el-form-item label="Secret Key" prop="secretKey"> | |||
<el-input v-model="form.secretKey" type="password" style="width: 95%;" placeholder="secretKey,在安全中心,秘钥管理中查看" /> | |||
</el-form-item> | |||
<el-form-item label="空间名称" prop="bucket"> | |||
<el-input v-model="form.bucket" style="width: 95%;" placeholder="存储空间名称作为唯一的 Bucket 识别符" /> | |||
</el-form-item> | |||
<el-form-item label="外链域名" prop="host"> | |||
<el-input v-model="form.host" style="width: 95%;" placeholder="外链域名,可自定义,需在七牛云绑定" /> | |||
</el-form-item> | |||
<el-form-item label="存储区域"> | |||
<el-select v-model="form.zone" placeholder="请选择存储区域"> | |||
<el-option | |||
v-for="item in zones" | |||
:key="item" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="空间类型" prop="type"> | |||
<el-radio v-model="form.type" label="公开">公开</el-radio> | |||
<el-radio v-model="form.type" label="私有">私有</el-radio> | |||
</el-form-item> | |||
</el-form> | |||
<div slot="footer" class="dialog-footer"> | |||
<el-button type="text" @click="dialog = false">取消</el-button> | |||
<el-button :loading="loading" type="primary" @click="doSubmit">确认</el-button> | |||
</div> | |||
</el-dialog> | |||
</template> | |||
<script> | |||
import { get, update } from '@/api/tools/qiniu' | |||
export default { | |||
data() { | |||
return { | |||
zones: ['华东', '华北', '华南', '北美', '东南亚'], dialog: false, | |||
loading: false, form: { accessKey: '', secretKey: '', bucket: '', host: '', zone: '', type: '' }, | |||
rules: { | |||
accessKey: [ | |||
{ required: true, message: '请输入accessKey', trigger: 'blur' } | |||
], | |||
secretKey: [ | |||
{ required: true, message: '请输入secretKey', trigger: 'blur' } | |||
], | |||
bucket: [ | |||
{ required: true, message: '请输入空间名称', trigger: 'blur' } | |||
], | |||
host: [ | |||
{ required: true, message: '请输入外链域名', trigger: 'blur' } | |||
], | |||
type: [ | |||
{ required: true, message: '空间类型不能为空', trigger: 'blur' } | |||
] | |||
} | |||
} | |||
}, | |||
methods: { | |||
init() { | |||
get().then(res => { | |||
this.form = res | |||
}) | |||
}, | |||
doSubmit() { | |||
this.$refs['form'].validate((valid) => { | |||
if (valid) { | |||
this.loading = true | |||
update(this.form).then(res => { | |||
this.$notify({ | |||
title: '修改成功', | |||
type: 'success', | |||
duration: 2500 | |||
}) | |||
this.$parent.crud.toQuery() | |||
this.loading = false | |||
this.dialog = false | |||
}).catch(err => { | |||
this.loading = false | |||
console.log(err.response.data.message) | |||
}) | |||
} else { | |||
return false | |||
} | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
</style> |
@@ -0,0 +1,54 @@ | |||
<template> | |||
<a href="https://github.com/elunez/eladmin" target="_blank" class="github-corner" aria-label="View source on Github"> | |||
<svg | |||
width="80" | |||
height="80" | |||
viewBox="0 0 250 250" | |||
style="fill:#40c9c6; color:#fff;" | |||
aria-hidden="true" | |||
> | |||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" /> | |||
<path | |||
d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" | |||
fill="currentColor" | |||
style="transform-origin: 130px 106px;" | |||
class="octo-arm" | |||
/> | |||
<path | |||
d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" | |||
fill="currentColor" | |||
class="octo-body" | |||
/> | |||
</svg> | |||
</a> | |||
</template> | |||
<style scoped> | |||
.github-corner:hover .octo-arm { | |||
animation: octocat-wave 560ms ease-in-out | |||
} | |||
@keyframes octocat-wave { | |||
0%, | |||
100% { | |||
transform: rotate(0) | |||
} | |||
20%, | |||
60% { | |||
transform: rotate(-25deg) | |||
} | |||
40%, | |||
80% { | |||
transform: rotate(10deg) | |||
} | |||
} | |||
@media (max-width:500px) { | |||
.github-corner:hover .octo-arm { | |||
animation: none | |||
} | |||
.github-corner .octo-arm { | |||
animation: octocat-wave 560ms ease-in-out | |||
} | |||
} | |||
</style> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.719" height="200" class="icon" p-id="10233" t="1543827724451" version="1.1" viewBox="0 0 1084 1024"><defs><style type="text/css">@font-face{font-family:rbicon;src:url(chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2) format("woff2");font-weight:400;font-style:normal}</style></defs><path fill="#bfbfbf" d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"/></svg> |
@@ -0,0 +1,95 @@ | |||
<template> | |||
<div v-if="!item.hidden" class="menu-wrapper"> | |||
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> | |||
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"> | |||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"> | |||
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /> | |||
</el-menu-item> | |||
</app-link> | |||
</template> | |||
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body> | |||
<template slot="title"> | |||
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /> | |||
</template> | |||
<sidebar-item | |||
v-for="child in item.children" | |||
:key="child.path" | |||
:is-nest="true" | |||
:item="child" | |||
:base-path="resolvePath(child.path)" | |||
class="nest-menu" | |||
/> | |||
</el-submenu> | |||
</div> | |||
</template> | |||
<script> | |||
import path from 'path' | |||
import { isExternal } from '@/utils/validate' | |||
import Item from './Item' | |||
import AppLink from './Link' | |||
import FixiOSBug from './FixiOSBug' | |||
export default { | |||
name: 'SidebarItem', | |||
components: { Item, AppLink }, | |||
mixins: [FixiOSBug], | |||
props: { | |||
// route object | |||
item: { | |||
type: Object, | |||
required: true | |||
}, | |||
isNest: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
basePath: { | |||
type: String, | |||
default: '' | |||
} | |||
}, | |||
data() { | |||
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237 | |||
// TODO: refactor with render function | |||
this.onlyOneChild = null | |||
return {} | |||
}, | |||
methods: { | |||
hasOneShowingChild(children = [], parent) { | |||
const showingChildren = children.filter(item => { | |||
if (item.hidden) { | |||
return false | |||
} else { | |||
// Temp set(will be used if only has one showing child) | |||
this.onlyOneChild = item | |||
return true | |||
} | |||
}) | |||
// When there is only one child router, the child router is displayed by default | |||
if (showingChildren.length === 1) { | |||
return true | |||
} | |||
// Show parent if there are no child router to display | |||
if (showingChildren.length === 0) { | |||
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true } | |||
return true | |||
} | |||
return false | |||
}, | |||
resolvePath(routePath) { | |||
if (isExternal(routePath)) { | |||
return routePath | |||
} | |||
if (isExternal(this.basePath)) { | |||
return this.basePath | |||
} | |||
return path.resolve(this.basePath, routePath) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,115 @@ | |||
<template> | |||
<div> | |||
<div v-if="query.dictName === ''"> | |||
<div class="my-code">点击字典查看详情</div> | |||
</div> | |||
<div v-else> | |||
<!--工具栏--> | |||
<div class="head-container"> | |||
<div v-if="crud.props.searchToggle"> | |||
<!-- 搜索 --> | |||
<el-input v-model="query.label" clearable size="small" placeholder="输入字典标签查询" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery" /> | |||
<rrOperation /> | |||
</div> | |||
</div> | |||
<!--表单组件--> | |||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible="crud.status.cu > 0" :title="crud.status.title" width="500px"> | |||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px"> | |||
<el-form-item label="字典标签" prop="label"> | |||
<el-input v-model="form.label" style="width: 370px;" /> | |||
</el-form-item> | |||
<el-form-item label="字典值" prop="value"> | |||
<el-input v-model="form.value" style="width: 370px;" /> | |||
</el-form-item> | |||
<el-form-item label="排序" prop="dictSort"> | |||
<el-input-number v-model.number="form.dictSort" :min="0" :max="999" controls-position="right" style="width: 370px;" /> | |||
</el-form-item> | |||
</el-form> | |||
<div slot="footer" class="dialog-footer"> | |||
<el-button type="text" @click="crud.cancelCU">取消</el-button> | |||
<el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确认</el-button> | |||
</div> | |||
</el-dialog> | |||
<!--表格渲染--> | |||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" highlight-current-row style="width: 100%;" @selection-change="crud.selectionChangeHandler"> | |||
<el-table-column label="所属字典"> | |||
{{ query.dictName }} | |||
</el-table-column> | |||
<el-table-column prop="label" label="字典标签" /> | |||
<el-table-column prop="value" label="字典值" /> | |||
<el-table-column prop="dictSort" label="排序" /> | |||
<el-table-column v-if="checkPer(['admin','dict:edit','dict:del'])" label="操作" width="130px" align="center" fixed="right"> | |||
<template slot-scope="scope"> | |||
<udOperation | |||
:data="scope.row" | |||
:permission="permission" | |||
/> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页组件--> | |||
<pagination /> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import crudDictDetail from '@/api/system/dictDetail' | |||
import CRUD, { presenter, header, form } from '@crud/crud' | |||
import pagination from '@crud/Pagination' | |||
import rrOperation from '@crud/RR.operation' | |||
import udOperation from '@crud/UD.operation' | |||
const defaultForm = { id: null, label: null, value: null, dictSort: 999 } | |||
export default { | |||
components: { pagination, rrOperation, udOperation }, | |||
cruds() { | |||
return [ | |||
CRUD({ title: '字典详情', url: 'api/dictDetail', query: { dictName: '' }, sort: ['dictSort,asc', 'id,desc'], | |||
crudMethod: { ...crudDictDetail }, | |||
optShow: { | |||
add: true, | |||
edit: true, | |||
del: true, | |||
reset: false | |||
}, | |||
queryOnPresenterCreated: false | |||
}) | |||
] | |||
}, | |||
mixins: [ | |||
presenter(), | |||
header(), | |||
form(function() { | |||
return Object.assign({ dict: { id: this.dictId }}, defaultForm) | |||
})], | |||
data() { | |||
return { | |||
dictId: null, | |||
rules: { | |||
label: [ | |||
{ required: true, message: '请输入字典标签', trigger: 'blur' } | |||
], | |||
value: [ | |||
{ required: true, message: '请输入字典值', trigger: 'blur' } | |||
], | |||
dictSort: [ | |||
{ required: true, message: '请输入序号', trigger: 'blur', type: 'number' } | |||
] | |||
}, | |||
permission: { | |||
add: ['admin', 'dict:add'], | |||
edit: ['admin', 'dict:edit'], | |||
del: ['admin', 'dict:del'] | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
::v-deep .el-input-number .el-input__inner { | |||
text-align: left; | |||
} | |||
</style> |
@@ -0,0 +1,188 @@ | |||
<template> | |||
<div :class="{'show':show}" class="header-search"> | |||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> | |||
<el-select | |||
ref="headerSearchSelect" | |||
v-model="search" | |||
:remote-method="querySearch" | |||
filterable | |||
default-first-option | |||
remote | |||
placeholder="Search" | |||
class="header-search-select" | |||
@change="change" | |||
> | |||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" /> | |||
</el-select> | |||
</div> | |||
</template> | |||
<script> | |||
// fuse is a lightweight fuzzy-search module | |||
// make search results more in line with expectations | |||
import Fuse from 'fuse.js' | |||
import path from 'path' | |||
export default { | |||
name: 'HeaderSearch', | |||
data() { | |||
return { | |||
search: '', | |||
options: [], | |||
searchPool: [], | |||
show: false, | |||
fuse: undefined | |||
} | |||
}, | |||
computed: { | |||
routes() { | |||
return this.$store.state.permission.routers | |||
} | |||
}, | |||
watch: { | |||
routes() { | |||
this.searchPool = this.generateRoutes(this.routes) | |||
}, | |||
searchPool(list) { | |||
this.initFuse(list) | |||
}, | |||
show(value) { | |||
if (value) { | |||
document.body.addEventListener('click', this.close) | |||
} else { | |||
document.body.removeEventListener('click', this.close) | |||
} | |||
} | |||
}, | |||
mounted() { | |||
this.searchPool = this.generateRoutes(this.routes) | |||
}, | |||
methods: { | |||
click() { | |||
this.show = !this.show | |||
if (this.show) { | |||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus() | |||
} | |||
}, | |||
close() { | |||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur() | |||
this.options = [] | |||
this.show = false | |||
}, | |||
change(val) { | |||
if (this.ishttp(val.path)) { | |||
// http(s):// 路径新窗口打开 | |||
window.open(val.path, '_blank') | |||
} else { | |||
this.$router.push(val.path) | |||
} | |||
this.search = '' | |||
this.options = [] | |||
this.$nextTick(() => { | |||
this.show = false | |||
}) | |||
}, | |||
initFuse(list) { | |||
this.fuse = new Fuse(list, { | |||
shouldSort: true, | |||
threshold: 0.4, | |||
location: 0, | |||
distance: 100, | |||
maxPatternLength: 32, | |||
minMatchCharLength: 1, | |||
keys: [{ | |||
name: 'title', | |||
weight: 0.7 | |||
}, { | |||
name: 'path', | |||
weight: 0.3 | |||
}] | |||
}) | |||
}, | |||
// Filter out the routes that can be displayed in the sidebar | |||
// And generate the internationalized title | |||
generateRoutes(routes, basePath = '/', prefixTitle = []) { | |||
let res = [] | |||
for (const router of routes) { | |||
// skip hidden router | |||
if (router.hidden) { continue } | |||
const data = { | |||
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path, | |||
title: [...prefixTitle] | |||
} | |||
if (router.meta && router.meta.title) { | |||
data.title = [...data.title, router.meta.title] | |||
if (router.redirect !== 'noRedirect') { | |||
// only push the routes with title | |||
// special case: need to exclude parent router without redirect | |||
res.push(data) | |||
} | |||
} | |||
// recursive child routes | |||
if (router.children) { | |||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title) | |||
if (tempRoutes.length >= 1) { | |||
res = [...res, ...tempRoutes] | |||
} | |||
} | |||
} | |||
return res | |||
}, | |||
querySearch(query) { | |||
if (query !== '') { | |||
this.options = this.fuse.search(query) | |||
} else { | |||
this.options = [] | |||
} | |||
}, | |||
ishttp(url) { | |||
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.header-search { | |||
font-size: 0 !important; | |||
.search-icon { | |||
cursor: pointer; | |||
font-size: 18px; | |||
vertical-align: middle; | |||
} | |||
.header-search-select { | |||
font-size: 18px; | |||
transition: width 0.2s; | |||
width: 0; | |||
overflow: hidden; | |||
background: transparent; | |||
border-radius: 0; | |||
display: inline-block; | |||
vertical-align: middle; | |||
::v-deep .el-input__inner { | |||
border-radius: 0; | |||
border: 0; | |||
padding-left: 0; | |||
padding-right: 0; | |||
box-shadow: none !important; | |||
border-bottom: 1px solid #d9d9d9; | |||
vertical-align: middle; | |||
} | |||
} | |||
&.show { | |||
.header-search-select { | |||
width: 210px; | |||
margin-left: 10px; | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,106 @@ | |||
<template> | |||
<div :class="className" :style="{height:height,width:width}" /> | |||
</template> | |||
<script> | |||
import echarts from 'echarts' | |||
require('echarts/theme/macarons') // echarts theme | |||
import { debounce } from '@/utils' | |||
const animationDuration = 6000 | |||
export default { | |||
props: { | |||
className: { | |||
type: String, | |||
default: 'chart' | |||
}, | |||
width: { | |||
type: String, | |||
default: '100%' | |||
}, | |||
height: { | |||
type: String, | |||
default: '300px' | |||
} | |||
}, | |||
data() { | |||
return { | |||
chart: null | |||
} | |||
}, | |||
mounted() { | |||
this.initChart() | |||
this.__resizeHandler = debounce(() => { | |||
if (this.chart) { | |||
this.chart.resize() | |||
} | |||
}, 100) | |||
window.addEventListener('resize', this.__resizeHandler) | |||
}, | |||
beforeDestroy() { | |||
if (!this.chart) { | |||
return | |||
} | |||
window.removeEventListener('resize', this.__resizeHandler) | |||
this.chart.dispose() | |||
this.chart = null | |||
}, | |||
methods: { | |||
initChart() { | |||
this.chart = echarts.init(this.$el, 'macarons') | |||
this.chart.setOption({ | |||
tooltip: { | |||
trigger: 'axis', | |||
axisPointer: { // 坐标轴指示器,坐标轴触发有效 | |||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' | |||
} | |||
}, | |||
grid: { | |||
top: 10, | |||
left: '2%', | |||
right: '2%', | |||
bottom: '3%', | |||
containLabel: true | |||
}, | |||
xAxis: [{ | |||
type: 'category', | |||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |||
axisTick: { | |||
alignWithLabel: true | |||
} | |||
}], | |||
yAxis: [{ | |||
type: 'value', | |||
axisTick: { | |||
show: false | |||
} | |||
}], | |||
series: [{ | |||
name: 'pageA', | |||
type: 'bar', | |||
stack: 'vistors', | |||
barWidth: '60%', | |||
data: [79, 52, 200, 334, 390, 330, 220], | |||
animationDuration | |||
}, { | |||
name: 'pageB', | |||
type: 'bar', | |||
stack: 'vistors', | |||
barWidth: '60%', | |||
data: [80, 52, 200, 334, 390, 330, 220], | |||
animationDuration | |||
}, { | |||
name: 'pageC', | |||
type: 'bar', | |||
stack: 'vistors', | |||
barWidth: '60%', | |||
data: [30, 52, 200, 334, 390, 330, 220], | |||
animationDuration | |||
}] | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,382 @@ | |||
<template> | |||
<div class="app-container"> | |||
<div style="margin-bottom:10px"> | |||
<el-button type="success" @click="addBtn">新增</el-button> | |||
<el-button type="success" @click="exportTempBtn">模板下载</el-button> | |||
</div> | |||
<!--搜索--> | |||
<el-form class="mt_15" ref="searchForm" inline size="small"> | |||
<el-form-item label="状态"> | |||
<el-select v-model.trim="searchParm.status" placeholder="请选择"> | |||
<el-option | |||
v-for="item in searchStatusList" | |||
:key="item.value" | |||
:label="item.label" | |||
:value="item.value"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="备注"> | |||
<el-input v-model.trim="searchParm.remarks" clearable></el-input> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button type="primary" @click="goSearch">搜索</el-button> | |||
<el-button type="warning" @click="resetForm">重置</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<!--表格渲染--> | |||
<el-table ref="table" border size="small" :data="list" :header-cell-style="{textAlign:'center'}"> | |||
<el-table-column label="序号" type="index" width="50" align="center"/> | |||
<el-table-column label="路径" prop="path" align="center"/> | |||
<el-table-column label="状态" prop="status" align="center"> | |||
<template slot-scope="scope"> | |||
{{ scope.row.status | getStatus}} | |||
</template> | |||
</el-table-column> | |||
<el-table-column label="备注" prop="remarks" align="center"/> | |||
<el-table-column label="创建时间" prop="createdAt" align="center"/> | |||
<el-table-column label="修改时间" prop="updatedAt" align="center"/> | |||
<el-table-column label="操作" width="240"> | |||
<template slot-scope="scope"> | |||
<el-button type="info" @click="getBtnById(scope.row.id)">查看</el-button> | |||
<el-button type="warning" @click="editById(scope.row)">修改</el-button> | |||
<span v-if="scope.row.errorPath != null" slot="footer"> | |||
<el-button type="danger" @click="getError(scope.row.errorPath)" style="margin-left:10px">异常下载</el-button> | |||
</span> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<!--分页--> | |||
<div class="mt_15"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="searchParm.page" | |||
:page-sizes="[10, 20, 30, 40, 50]" | |||
:page-size="searchParm.pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total"> | |||
</el-pagination> | |||
</div> | |||
<!--新增弹窗--> | |||
<el-dialog :visible.sync="dialogAddVisible" :title="dialogAddTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="addParm" size="small" :model="addParm" :rules="rules" label-width="100px"> | |||
<el-input v-model.trim="addParm.path" type="hidden" clearable></el-input> | |||
<el-form-item label="路径" prop="path"> | |||
<el-upload | |||
class="upload-demo" | |||
ref="upload" | |||
:data = "updateFileType" | |||
:headers="uploadHeaders" | |||
:action="uploadFileUrl" | |||
:show-file-list = "false" | |||
:on-success="uploadSuccess" | |||
:before-upload="beforeAvatarUpload"> | |||
<el-button slot="trigger" size="small" type="primary">选取文件</el-button> | |||
<div slot="tip" class="el-upload__tip">只能上传xlsl文件,且不超过10M</div> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item label="备注" prop="remarks"> | |||
<el-input v-model.trim="addParm.remarks" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureAddCancle('addParm')">取消</el-button> | |||
<el-button type="primary" @click="sureAdd('addParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--修改弹窗--> | |||
<el-dialog :visible.sync="dialogEditVisible" :title="dialogEditTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="100px"> | |||
<el-form-item label="备注" prop="remarks"> | |||
<el-input v-model.trim="editParm.remarks" clearable></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<span slot="footer"> | |||
<el-button type="info" @click="sureEditCancle('editParm')">取消</el-button> | |||
<el-button type="primary" @click="sureEdit('editParm')">确认</el-button> | |||
</span> | |||
</el-dialog> | |||
<!--详情弹窗--> | |||
<el-dialog :visible.sync="dialogDetailVisible" :title="dialogDetailTitle" center width="45%"> | |||
<div class="dialog-content"> | |||
<el-form ref="form" size="small" label-width="100px"> | |||
<el-form-item label="路径" prop="path" > | |||
<el-input v-model.trim="detailParm.path" :disabled="true"></el-input> | |||
</el-form-item> | |||
<el-form-item label="状态" prop="status" > | |||
<!-- <el-input v-model.trim="detailParm.status" :disabled="true"></el-input> --> | |||
<el-select v-model.trim="detailParm.status" disabled placeholder="请选择"> | |||
<el-option | |||
v-for="item in statusList" | |||
:key="item.value" | |||
:label="item.label" | |||
:value="item.value"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label="备注" prop="remarks"> | |||
<el-input v-model.trim="detailParm.remarks" :disabled="true"></el-input> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { add, editById, delById, getList, getById } from '@/api/group/excel' | |||
export default { | |||
filters: { | |||
getStatus: function (value) { | |||
if(value == 1) { | |||
return '待导入'; | |||
} else if (value == 2) { | |||
return '导入成功'; | |||
} else { | |||
return '导入失败'; | |||
} | |||
} | |||
}, | |||
// 数据 | |||
data() { | |||
return { | |||
searchParm: { | |||
page: 1, | |||
pageSize: 10, | |||
sort:'created_at', | |||
order:'desc', | |||
status:null, | |||
remarks:null | |||
}, | |||
total:0, | |||
list: [], | |||
uploadHeaders:{ Authorization: this.$store.getters.token }, | |||
dialogAddVisible: false, | |||
dialogAddTitle: '新增', | |||
dialogDetailVisible: false, | |||
dialogDetailTitle: '详情', | |||
dialogEditVisible: false, | |||
dialogEditTitle: '修改', | |||
uploadFileUrl: process.env.VUE_APP_BASE_API + '/api/file/uploadFile', | |||
tempUrl:process.env.VUE_APP_BASE_API + '/api/ctExcel/exportTemp', | |||
updateFileType: {type: 10}, | |||
searchStatusList:[{ | |||
value: null, | |||
label: '全部' | |||
}, | |||
{ | |||
value: 1, | |||
label: '待导入' | |||
}, { | |||
value: 2, | |||
label: '导入成功' | |||
}, { | |||
value: 3, | |||
label: '导入失败' | |||
}], | |||
statusList:[{ | |||
value: 1, | |||
label: '待导入' | |||
}, | |||
{ | |||
value: 2, | |||
label: '导入成功' | |||
}, | |||
{ | |||
value: 3, | |||
label: '导入失败' | |||
}], | |||
addParm: { | |||
id: null, | |||
path:'', | |||
remarks:'' | |||
}, | |||
detailParm: { | |||
id: null, | |||
path:'', | |||
remarks:'', | |||
status: null | |||
}, | |||
editParm: { | |||
id: null, | |||
remarks: '' | |||
}, | |||
rules: { | |||
path: [ | |||
{ required: true, message: '请输入路径', trigger: 'blur' } | |||
], | |||
remarks: [ | |||
{ required: true, message: '请输入备注', trigger: 'blur' } | |||
] | |||
} | |||
} | |||
}, | |||
// 调用 | |||
created() { | |||
this.goSearch() | |||
}, | |||
//方法 | |||
methods: { | |||
resetForm() { | |||
this.searchParm.status = null; | |||
this.searchParm.remarks = ''; | |||
this.goSearch() | |||
}, | |||
// 查询 | |||
goSearch() { | |||
this.searchParm.page=1 | |||
this.getDataList() | |||
}, | |||
beforeAvatarUpload(file) { | |||
console.log(file); | |||
// const isXlsl = file.type === 'xlsl'; | |||
const isLt10M = file.size / 1024 / 1024 <10; | |||
// if (!isXlsl) { | |||
// this.$message.error('上传头像图片只能是 xlsl 格式!'); | |||
// } | |||
if (!isLt10M) {s | |||
this.$message.error('上传头像图片大小不能超过 10MB!'); | |||
} | |||
// return isXlsl && isLt10M; | |||
return isLt10M; | |||
}, | |||
uploadSuccess(res, file) { | |||
if(res.code==200) { | |||
this.addParm.path =res.data.list[0].path; | |||
} | |||
}, | |||
//excel模板下载 | |||
exportTempBtn(){ | |||
console.log(this.tempUrl); | |||
window.location.href = this.tempUrl; | |||
}, | |||
// 新增 | |||
addBtn(){ | |||
this.addParm = { | |||
id: null, | |||
path:'', | |||
remarks:'' | |||
} | |||
this.dialogAddTitle='新增' | |||
this.dialogAddVisible = true; | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 修改 | |||
editById(data){ | |||
getById({id: data.id}).then(res => { | |||
if(res.code==200) { | |||
this.editParm.id = res.data.id; | |||
this.editParm.remarks = res.data.remarks; | |||
this.dialogEditVisible = true | |||
this.$refs.addParm.clearValidate(); | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 确认修改 | |||
sureEdit(editParm){ | |||
editById(this.editParm).then(res => { | |||
if(res.code==200) { | |||
console.log(res) | |||
this.dialogEditVisible = false | |||
this.$message.success('修改成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
sureAddCancle(editParm) { | |||
this.dialogEditVisible=flase | |||
this.$refs.editParm.clearValidate(); | |||
}, | |||
// 确认新增 | |||
sureAdd(addParm){ | |||
this.$refs[addParm].validate((valid) => { | |||
if (valid) { | |||
this.$refs.addParm.clearValidate(); | |||
add(this.addParm).then(res => { | |||
if(res.code==200) { | |||
this.dialogAddVisible = false | |||
this.$message.success('新增成功!') | |||
this.getDataList() | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
} else { | |||
console.log('error submit!!'); | |||
return false; | |||
} | |||
}); | |||
}, | |||
sureAddCancle(addParm) { | |||
this.dialogAddVisible=flase | |||
this.$refs.addParm.clearValidate(); | |||
}, | |||
// 查看根据id | |||
getBtnById(id){ | |||
getById({id}).then(res => { | |||
if(res.code==200) { | |||
this.detailParm.id = res.data.id; | |||
this.detailParm.path = res.data.path; | |||
this.detailParm.remarks = res.data.remarks; | |||
this.detailParm.status = res.data.status; | |||
this.dialogDetailVisible = true | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
getError(errorPath){ | |||
console.log(errorPath); | |||
this.$message.success('下载成功!'); | |||
if(errorPath != null) { | |||
window.location.href = errorPath; | |||
} | |||
}, | |||
// 分页获取表格数据 | |||
getDataList(){ | |||
getList(this.searchParm).then(res => { | |||
console.log(res) | |||
if(res.code==200) { | |||
console.log(res) | |||
this.list = res.data.list; | |||
this.total = res.data.total; | |||
} | |||
}).catch(err => { | |||
console.log(err) | |||
}) | |||
}, | |||
// 分页 | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.searchParm.pageSize = val; | |||
this.getDataList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.searchParm.page = val; | |||
this.getDataList(); | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
</style> |
@@ -0,0 +1,43 @@ | |||
import request from '@/utils/request' | |||
export function getDetailById(data) { | |||
return request({ | |||
url: 'api/clickOrder/getById', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function supplement(data) { | |||
return request({ | |||
url: 'api/clickOrder/supplement', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function add(data) { | |||
return request({ | |||
url: 'api/clickOrder/add', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function commentFun(data) { | |||
return request({ | |||
url: 'api/clickOrder/comment', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function getList(data) { | |||
return request({ | |||
url: 'api/clickOrder/list', | |||
method: 'post', | |||
data | |||
}) | |||
} |
@@ -0,0 +1,15 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |||
<meta name="renderer" content="webkit"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | |||
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |||
<title><%= webpackConfig.name %></title> | |||
</head> | |||
<body> | |||
<div id="app"></div> | |||
<!-- built files will be auto injected --> | |||
</body> | |||
</html> |
@@ -0,0 +1,335 @@ | |||
import { | |||
initData, | |||
download | |||
} from '@/api/data' | |||
import { | |||
parseTime, | |||
downloadFile | |||
} from '@/utils/index' | |||
export default { | |||
data() { | |||
return { | |||
// 表格数据 | |||
data: [], | |||
// 排序规则,默认 id 降序, 支持多字段排序 ['id,desc', 'createTime,asc'] | |||
sort: ['id,desc'], | |||
// 页码 | |||
page: 0, | |||
// 每页数据条数 | |||
size: 10, | |||
// 总数据条数 | |||
total: 0, | |||
// 请求数据的url | |||
url: '', | |||
// 查询数据的参数 | |||
params: {}, | |||
// 待查询的对象 | |||
query: {}, | |||
// 等待时间 | |||
time: 50, | |||
// 是否为新增类型的表单 | |||
isAdd: false, | |||
// 导出的 Loading | |||
downloadLoading: false, | |||
// 表格 Loading 属性 | |||
loading: true, | |||
// 删除 Loading 属性 | |||
delLoading: false, | |||
delAllLoading: false, | |||
// 弹窗属性 | |||
dialog: false, | |||
// Form 表单 | |||
form: {}, | |||
// 重置表单 | |||
resetForm: {}, | |||
// 标题 | |||
title: '' | |||
} | |||
}, | |||
methods: { | |||
parseTime, | |||
downloadFile, | |||
async init() { | |||
if (!await this.beforeInit()) { | |||
return | |||
} | |||
return new Promise((resolve, reject) => { | |||
this.loading = true | |||
// 请求数据 | |||
initData(this.url, this.getQueryParame()).then(data => { | |||
this.total = data.totalElements | |||
this.data = data.content | |||
// time 毫秒后显示表格 | |||
setTimeout(() => { | |||
this.loading = false | |||
}, this.time) | |||
resolve(data) | |||
}).catch(err => { | |||
this.loading = false | |||
reject(err) | |||
}) | |||
}) | |||
}, | |||
beforeInit() { | |||
return true | |||
}, | |||
getQueryParame: function() { | |||
return { | |||
page: this.page, | |||
size: this.size, | |||
sort: this.sort, | |||
...this.query, | |||
...this.params | |||
} | |||
}, | |||
// 改变页码 | |||
pageChange(e) { | |||
this.page = e - 1 | |||
this.init() | |||
}, | |||
// 改变每页显示数 | |||
sizeChange(e) { | |||
this.page = 0 | |||
this.size = e | |||
this.init() | |||
}, | |||
// 预防删除第二页最后一条数据时,或者多选删除第二页的数据时,页码错误导致请求无数据 | |||
dleChangePage(size) { | |||
if (size === undefined) { | |||
size = 1 | |||
} | |||
if (this.data.length === size && this.page !== 0) { | |||
this.page = this.page - 1 | |||
} | |||
}, | |||
// 查询方法 | |||
toQuery() { | |||
this.page = 0 | |||
this.init() | |||
}, | |||
/** | |||
* 通用的提示封装 | |||
*/ | |||
submitSuccessNotify() { | |||
this.$notify({ | |||
title: '提交成功', | |||
type: 'success', | |||
duration: 2500 | |||
}) | |||
}, | |||
addSuccessNotify() { | |||
this.$notify({ | |||
title: '新增成功', | |||
type: 'success', | |||
duration: 2500 | |||
}) | |||
}, | |||
editSuccessNotify() { | |||
this.$notify({ | |||
title: '编辑成功', | |||
type: 'success', | |||
duration: 2500 | |||
}) | |||
}, | |||
delSuccessNotify() { | |||
this.$notify({ | |||
title: '删除成功', | |||
type: 'success', | |||
duration: 2500 | |||
}) | |||
}, | |||
notify(title, type) { | |||
this.$notify({ | |||
title: title, | |||
type: type, | |||
duration: 2500 | |||
}) | |||
}, | |||
/** | |||
* 删除前可以调用 beforeDelMethod 做一些操作 | |||
*/ | |||
beforeDelMethod() { | |||
return true | |||
}, | |||
/** | |||
* 通用的删除 | |||
*/ | |||
delMethod(id) { | |||
if (!this.beforeDelMethod()) { | |||
return | |||
} | |||
this.delLoading = true | |||
this.crudMethod.del(id).then(() => { | |||
this.delLoading = false | |||
this.$refs[id].doClose() | |||
this.dleChangePage() | |||
this.delSuccessNotify() | |||
this.afterDelMethod() | |||
this.init() | |||
}).catch(() => { | |||
this.delLoading = false | |||
this.$refs[id].doClose() | |||
}) | |||
}, | |||
afterDelMethod() {}, | |||
/** | |||
* 多选删除提示 | |||
*/ | |||
beforeDelAllMethod() { | |||
this.$confirm('你确定删除选中的数据吗?', '提示', { | |||
confirmButtonText: '确定', | |||
cancelButtonText: '取消', | |||
type: 'warning' | |||
}).then(() => { | |||
this.delAllMethod() | |||
}) | |||
}, | |||
/** | |||
* 多选删除 | |||
*/ | |||
delAllMethod() { | |||
this.delAllLoading = true | |||
const data = this.$refs.table.selection | |||
const ids = [] | |||
for (let i = 0; i < data.length; i++) { | |||
ids.push(data[i].id) | |||
} | |||
this.crudMethod.delAll(ids).then(() => { | |||
this.delAllLoading = false | |||
this.dleChangePage(ids.length) | |||
this.init() | |||
this.$notify({ | |||
title: '删除成功', | |||
type: 'success', | |||
duration: 2500 | |||
}) | |||
}).catch(() => { | |||
this.delAllLoading = false | |||
}) | |||
}, | |||
/** | |||
* 显示新增弹窗前可以调用该方法 | |||
*/ | |||
beforeShowAddForm() {}, | |||
/** | |||
* 显示新增弹窗 | |||
*/ | |||
showAddFormDialog() { | |||
this.isAdd = true | |||
this.resetForm = JSON.parse(JSON.stringify(this.form)) | |||
this.beforeShowAddForm() | |||
this.dialog = true | |||
}, | |||
/** | |||
* 显示编辑弹窗前可以调用该方法 | |||
*/ | |||
beforeShowEditForm(data) {}, | |||
/** | |||
* 显示编辑弹窗 | |||
*/ | |||
showEditFormDialog(data = '') { | |||
this.isAdd = false | |||
if (data) { | |||
this.resetForm = JSON.parse(JSON.stringify(this.form)) | |||
this.form = JSON.parse(JSON.stringify(data)) | |||
} | |||
this.beforeShowEditForm(data) | |||
this.dialog = true | |||
}, | |||
/** | |||
* 新增方法 | |||
*/ | |||
addMethod() { | |||
this.crudMethod.add(this.form).then(() => { | |||
this.addSuccessNotify() | |||
this.loading = false | |||
this.afterAddMethod() | |||
this.cancel() | |||
this.init() | |||
}).catch(() => { | |||
this.loading = false | |||
this.afterAddErrorMethod() | |||
}) | |||
}, | |||
/** | |||
* 新增后可以调用该方法 | |||
*/ | |||
afterAddMethod() {}, | |||
/** | |||
* 新增失败后调用该方法 | |||
*/ | |||
afterAddErrorMethod() {}, | |||
/** | |||
* 通用的编辑方法 | |||
*/ | |||
editMethod() { | |||
this.crudMethod.edit(this.form).then(() => { | |||
this.editSuccessNotify() | |||
this.loading = false | |||
this.afterEditMethod() | |||
this.cancel() | |||
this.init() | |||
}).catch(() => { | |||
this.loading = false | |||
}) | |||
}, | |||
/** | |||
* 编辑后可以调用该方法 | |||
*/ | |||
afterEditMethod() {}, | |||
/** | |||
* 提交前可以调用该方法 | |||
*/ | |||
beforeSubmitMethod() { | |||
return true | |||
}, | |||
/** | |||
* 提交 | |||
*/ | |||
submitMethod() { | |||
if (!this.beforeSubmitMethod()) { | |||
return | |||
} | |||
if (this.$refs['form']) { | |||
this.$refs['form'].validate((valid) => { | |||
if (valid) { | |||
this.loading = true | |||
if (this.isAdd) { | |||
this.addMethod() | |||
} else this.editMethod() | |||
} | |||
}) | |||
} | |||
}, | |||
/** | |||
* 隐藏弹窗 | |||
*/ | |||
cancel() { | |||
this.dialog = false | |||
if (this.$refs['form']) { | |||
this.$refs['form'].clearValidate() | |||
this.form = this.resetForm | |||
} | |||
}, | |||
/** | |||
* 获取弹窗的标题 | |||
*/ | |||
getFormTitle() { | |||
return this.isAdd ? `新增${this.title}` : `编辑${this.title}` | |||
}, | |||
/** | |||
* 通用导出 | |||
*/ | |||
downloadMethod() { | |||
this.beforeInit() | |||
this.downloadLoading = true | |||
download(this.url + '/download', this.params).then(result => { | |||
this.downloadFile(result, this.title + '数据', 'xlsx') | |||
this.downloadLoading = false | |||
}).catch(() => { | |||
this.downloadLoading = false | |||
}) | |||
} | |||
} | |||
} |
@@ -0,0 +1 @@ | |||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M49.217 41.329l-.136-35.24c-.06-2.715-2.302-4.345-5.022-4.405h-3.65c-2.712-.06-4.866 2.303-4.806 5.016l.152 19.164-24.151-23.79a6.698 6.698 0 0 0-9.499 0 6.76 6.76 0 0 0 0 9.526l23.93 23.713-18.345.074c-2.712-.069-5.228 1.813-5.64 5.02v3.462c.069 2.721 2.31 4.97 5.022 5.03l35.028-.207c.052.005.087.025.133.025l2.457.054a4.626 4.626 0 0 0 3.436-1.38c.88-.874 1.205-2.096 1.169-3.462l-.262-2.465c0-.048.182-.081.182-.136h.002zm52.523 51.212l18.32-.073c2.713.06 5.224-1.609 5.64-4.815v-3.462c-.068-2.722-2.317-4.97-5.021-5.04l-34.58.21c-.053 0-.086-.021-.138-.021l-2.451-.06a4.64 4.64 0 0 0-3.445 1.381c-.885.868-1.201 2.094-1.174 3.46l.27 2.46c.005.06-.177.095-.177.141l.141 34.697c.069 2.713 2.31 4.338 5.022 4.397l3.45.006c2.705.062 4.867-2.31 4.8-5.026l-.153-18.752 24.151 23.946a6.69 6.69 0 0 0 9.494 0 6.747 6.747 0 0 0 0-9.523L101.74 92.54v.001zM48.125 80.662a4.636 4.636 0 0 0-3.437-1.382l-2.457.06c-.05 0-.082.022-.137.022l-35.025-.21c-2.712.07-4.957 2.318-5.022 5.04v3.462c.409 3.206 2.925 4.874 5.633 4.814l18.554.06-24.132 23.928c-2.62 2.626-2.62 6.89 0 9.524a6.694 6.694 0 0 0 9.496 0l24.155-23.79-.155 18.866c-.06 2.722 2.094 5.093 4.801 5.025h3.65c2.72-.069 4.962-1.685 5.022-4.406l.141-34.956c0-.05-.182-.082-.182-.136l.262-2.46c.03-1.366-.286-2.592-1.166-3.46h-.001zM80.08 47.397a4.62 4.62 0 0 0 3.443 1.374l2.45-.054c.055 0 .088-.02.143-.028l35.08.21c2.712-.062 4.953-2.312 5.021-5.033l.009-3.463c-.417-3.211-2.937-5.084-5.64-5.025l-18.615-.073 23.917-23.715c2.63-2.623 2.63-6.879.008-9.513a6.691 6.691 0 0 0-9.494 0L92.251 26.016l.155-19.312c.065-2.713-2.097-5.085-4.802-5.025h-3.45c-2.713.069-4.954 1.693-5.022 4.406l-.139 35.247c0 .054.18.088.18.136l-.267 2.465c-.028 1.366.288 2.588 1.174 3.463v.001z"/></svg> |
@@ -0,0 +1 @@ | |||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.585 12.087c0 6.616 3.974 11.98 8.877 11.98 4.902 0 8.877-5.364 8.877-11.98 0-6.616-3.975-11.98-8.877-11.98-4.903 0-8.877 5.364-8.877 11.98zM125.86.107H35.613c-1.268 0-2.114 1.426-2.114 2.852v18.255c0 1.712 1.057 2.853 2.114 2.853h90.247c1.268 0 2.114-1.426 2.114-2.853V2.96c0-1.711-1.057-2.852-2.114-2.852zM.106 62.86c0 6.615 3.974 11.979 8.876 11.979 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zM124.17 50.88H33.921c-1.268 0-2.114 1.425-2.114 2.851v18.256c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852V53.73c0-1.426-.846-2.852-2.114-2.852zM.106 115.913c0 6.616 3.974 11.98 8.876 11.98 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zm124.064-11.98H33.921c-1.268 0-2.114 1.426-2.114 2.853v18.255c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852v-18.255c0-1.427-.846-2.853-2.114-2.853z"/></svg> |
@@ -0,0 +1,291 @@ | |||
<template> | |||
<div v-loading="!show" element-loading-text="数据加载中..." :style="!show ? 'height: 500px' : 'height: 100%'" class="app-container"> | |||
<div v-if="show"> | |||
<el-card class="box-card"> | |||
<div style="color: #666;font-size: 13px;"> | |||
<svg-icon icon-class="system" style="margin-right: 5px" /> | |||
<span> | |||
系统:{{ data.sys.os }} | |||
</span> | |||
<span> | |||
IP:{{ data.sys.ip }} | |||
</span> | |||
<span> | |||
项目已不间断运行:{{ data.sys.day }} | |||
</span> | |||
<i class="el-icon-refresh" style="margin-left: 40px" @click="init" /> | |||
</div> | |||
</el-card> | |||
<el-card class="box-card"> | |||
<div slot="header" class="clearfix"> | |||
<span style="font-weight: bold;color: #666;font-size: 15px">状态</span> | |||
</div> | |||
<div> | |||
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6" style="margin-bottom: 10px"> | |||
<div class="title">CPU使用率</div> | |||
<el-tooltip placement="top-end"> | |||
<div slot="content" style="font-size: 12px;"> | |||
<div style="padding: 3px;"> | |||
{{ data.cpu.name }} | |||
</div> | |||
<div style="padding: 3px"> | |||
{{ data.cpu.package }} | |||
</div> | |||
<div style="padding: 3px"> | |||
{{ data.cpu.core }} | |||
</div> | |||
<div style="padding: 3px"> | |||
{{ data.cpu.logic }} | |||
</div> | |||
</div> | |||
<div class="content"> | |||
<el-progress type="dashboard" :percentage="parseFloat(data.cpu.used)" /> | |||
</div> | |||
</el-tooltip> | |||
<div class="footer">{{ data.cpu.coreNumber }} 核心</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6" style="margin-bottom: 10px"> | |||
<div class="title">内存使用率</div> | |||
<el-tooltip placement="top-end"> | |||
<div slot="content" style="font-size: 12px;"> | |||
<div style="padding: 3px;"> | |||
总量:{{ data.memory.total }} | |||
</div> | |||
<div style="padding: 3px"> | |||
已使用:{{ data.memory.used }} | |||
</div> | |||
<div style="padding: 3px"> | |||
空闲:{{ data.memory.available }} | |||
</div> | |||
</div> | |||
<div class="content"> | |||
<el-progress type="dashboard" :percentage="parseFloat(data.memory.usageRate)" /> | |||
</div> | |||
</el-tooltip> | |||
<div class="footer">{{ data.memory.used }} / {{ data.memory.total }}</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6" style="margin-bottom: 10px"> | |||
<div class="title">交换区使用率</div> | |||
<el-tooltip placement="top-end"> | |||
<div slot="content" style="font-size: 12px;"> | |||
<div style="padding: 3px;"> | |||
总量:{{ data.swap.total }} | |||
</div> | |||
<div style="padding: 3px"> | |||
已使用:{{ data.swap.used }} | |||
</div> | |||
<div style="padding: 3px"> | |||
空闲:{{ data.swap.available }} | |||
</div> | |||
</div> | |||
<div class="content"> | |||
<el-progress type="dashboard" :percentage="parseFloat(data.swap.usageRate)" /> | |||
</div> | |||
</el-tooltip> | |||
<div class="footer">{{ data.swap.used }} / {{ data.swap.total }}</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6" style="margin-bottom: 10px"> | |||
<div class="title">磁盘使用率</div> | |||
<div class="content"> | |||
<el-tooltip placement="top-end"> | |||
<div slot="content" style="font-size: 12px;"> | |||
<div style="padding: 3px"> | |||
总量:{{ data.disk.total }} | |||
</div> | |||
<div style="padding: 3px"> | |||
空闲:{{ data.disk.available }} | |||
</div> | |||
</div> | |||
<div class="content"> | |||
<el-progress type="dashboard" :percentage="parseFloat(data.disk.usageRate)" /> | |||
</div> | |||
</el-tooltip> | |||
</div> | |||
<div class="footer">{{ data.disk.used }} / {{ data.disk.total }}</div> | |||
</el-col> | |||
</div> | |||
</el-card> | |||
<div> | |||
<el-row :gutter="6"> | |||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" style="margin-bottom: 10px"> | |||
<el-card class="box-card"> | |||
<div slot="header" class="clearfix"> | |||
<span style="font-weight: bold;color: #666;font-size: 15px">CPU使用率监控</span> | |||
</div> | |||
<div> | |||
<v-chart :options="cpuInfo" /> | |||
</div> | |||
</el-card> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" style="margin-bottom: 10px"> | |||
<el-card class="box-card"> | |||
<div slot="header" class="clearfix"> | |||
<span style="font-weight: bold;color: #666;font-size: 15px">内存使用率监控</span> | |||
</div> | |||
<div> | |||
<v-chart :options="memoryInfo" /> | |||
</div> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import ECharts from 'vue-echarts' | |||
import 'echarts/lib/chart/line' | |||
import 'echarts/lib/component/polar' | |||
import { initData } from '@/api/data' | |||
export default { | |||
name: 'ServerMonitor', | |||
components: { | |||
'v-chart': ECharts | |||
}, | |||
data() { | |||
return { | |||
show: false, | |||
monitor: null, | |||
url: 'api/monitor', | |||
data: {}, | |||
cpuInfo: { | |||
tooltip: { | |||
trigger: 'axis' | |||
}, | |||
xAxis: { | |||
type: 'category', | |||
boundaryGap: false, | |||
data: [] | |||
}, | |||
yAxis: { | |||
type: 'value', | |||
min: 0, | |||
max: 100, | |||
interval: 20 | |||
}, | |||
series: [{ | |||
data: [], | |||
type: 'line', | |||
areaStyle: { | |||
normal: { | |||
color: 'rgb(32, 160, 255)' // 改变区域颜色 | |||
} | |||
}, | |||
itemStyle: { | |||
normal: { | |||
color: '#6fbae1', | |||
lineStyle: { | |||
color: '#6fbae1' // 改变折线颜色 | |||
} | |||
} | |||
} | |||
}] | |||
}, | |||
memoryInfo: { | |||
tooltip: { | |||
trigger: 'axis' | |||
}, | |||
xAxis: { | |||
type: 'category', | |||
boundaryGap: false, | |||
data: [] | |||
}, | |||
yAxis: { | |||
type: 'value', | |||
min: 0, | |||
max: 100, | |||
interval: 20 | |||
}, | |||
series: [{ | |||
data: [], | |||
type: 'line', | |||
areaStyle: { | |||
normal: { | |||
color: 'rgb(32, 160, 255)' // 改变区域颜色 | |||
} | |||
}, | |||
itemStyle: { | |||
normal: { | |||
color: '#6fbae1', | |||
lineStyle: { | |||
color: '#6fbae1' // 改变折线颜色 | |||
} | |||
} | |||
} | |||
}] | |||
} | |||
} | |||
}, | |||
created() { | |||
this.init() | |||
this.monitor = window.setInterval(() => { | |||
setTimeout(() => { | |||
this.init() | |||
}, 2) | |||
}, 3500) | |||
}, | |||
destroyed() { | |||
clearInterval(this.monitor) | |||
}, | |||
methods: { | |||
init() { | |||
initData(this.url, {}).then(data => { | |||
this.data = data | |||
this.show = true | |||
if (this.cpuInfo.xAxis.data.length >= 8) { | |||
this.cpuInfo.xAxis.data.shift() | |||
this.memoryInfo.xAxis.data.shift() | |||
this.cpuInfo.series[0].data.shift() | |||
this.memoryInfo.series[0].data.shift() | |||
} | |||
this.cpuInfo.xAxis.data.push(data.time) | |||
this.memoryInfo.xAxis.data.push(data.time) | |||
this.cpuInfo.series[0].data.push(parseFloat(data.cpu.used)) | |||
this.memoryInfo.series[0].data.push(parseFloat(data.memory.usageRate)) | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
::v-deep .box-card { | |||
margin-bottom: 5px; | |||
span { | |||
margin-right: 28px; | |||
} | |||
.el-icon-refresh { | |||
margin-right: 10px; | |||
float: right; | |||
cursor:pointer; | |||
} | |||
} | |||
.cpu, .memory, .swap, .disk { | |||
width: 20%; | |||
float: left; | |||
padding-bottom: 20px; | |||
margin-right: 5%; | |||
} | |||
.title { | |||
text-align: center; | |||
font-size: 15px; | |||
font-weight: 500; | |||
color: #999; | |||
margin-bottom: 16px; | |||
} | |||
.footer { | |||
text-align: center; | |||
font-size: 15px; | |||
font-weight: 500; | |||
color: #999; | |||
margin-top: -5px; | |||
margin-bottom: 10px; | |||
} | |||
.content { | |||
text-align: center; | |||
margin-top: 5px; | |||
margin-bottom: 5px; | |||
} | |||
</style> |
@@ -0,0 +1,107 @@ | |||
<template> | |||
<div class="dashboard-container"> | |||
<div class="dashboard-editor-container"> | |||
<github-corner class="github-corner" /> | |||
<panel-group @handleSetLineChartData="handleSetLineChartData" /> | |||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> | |||
<line-chart :chart-data="lineChartData" /> | |||
</el-row> | |||
<el-row :gutter="32"> | |||
<el-col :xs="24" :sm="24" :lg="8"> | |||
<div class="chart-wrapper"> | |||
<radar-chart /> | |||
</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :lg="8"> | |||
<div class="chart-wrapper"> | |||
<pie-chart /> | |||
</div> | |||
</el-col> | |||
<el-col :xs="24" :sm="24" :lg="8"> | |||
<div class="chart-wrapper"> | |||
<bar-chart /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import GithubCorner from '@/components/GithubCorner' | |||
import PanelGroup from './dashboard/PanelGroup' | |||
import LineChart from './dashboard/LineChart' | |||
import RadarChart from '@/components/Echarts/RadarChart' | |||
import PieChart from '@/components/Echarts/PieChart' | |||
import BarChart from '@/components/Echarts/BarChart' | |||
const lineChartData = { | |||
newVisitis: { | |||
expectedData: [100, 120, 161, 134, 105, 160, 165], | |||
actualData: [120, 82, 91, 154, 162, 140, 145] | |||
}, | |||
messages: { | |||
expectedData: [200, 192, 120, 144, 160, 130, 140], | |||
actualData: [180, 160, 151, 106, 145, 150, 130] | |||
}, | |||
purchases: { | |||
expectedData: [80, 100, 121, 104, 105, 90, 100], | |||
actualData: [120, 90, 100, 138, 142, 130, 130] | |||
}, | |||
shoppings: { | |||
expectedData: [130, 140, 141, 142, 145, 150, 160], | |||
actualData: [120, 82, 91, 154, 162, 140, 130] | |||
} | |||
} | |||
export default { | |||
name: 'Dashboard', | |||
components: { | |||
GithubCorner, | |||
PanelGroup, | |||
LineChart, | |||
RadarChart, | |||
PieChart, | |||
BarChart | |||
}, | |||
data() { | |||
return { | |||
lineChartData: lineChartData.newVisitis | |||
} | |||
}, | |||
methods: { | |||
handleSetLineChartData(type) { | |||
this.lineChartData = lineChartData[type] | |||
} | |||
} | |||
} | |||
</script> | |||
<style rel="stylesheet/scss" lang="scss" scoped> | |||
.dashboard-editor-container { | |||
padding: 32px; | |||
background-color: rgb(240, 242, 245); | |||
position: relative; | |||
.github-corner { | |||
position: absolute; | |||
top: 0; | |||
border: 0; | |||
right: 0; | |||
} | |||
.chart-wrapper { | |||
background: #fff; | |||
padding: 16px 16px 0; | |||
margin-bottom: 32px; | |||
} | |||
} | |||
@media (max-width:1024px) { | |||
.chart-wrapper { | |||
padding: 8px; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="1497" t="1554868028575" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css"/></defs><path fill="#bfbfbf" d="M558.409143 658.285714h-92.818286l-28.379428 62.427429a18.285714 18.285714 0 1 1-33.28-15.140572l91.428571-201.142857a18.285714 18.285714 0 0 1 33.28 0l91.428571 201.142857a18.285714 18.285714 0 1 1-33.28 15.140572L558.409143 658.285714z m-16.64-36.571428L512 556.178286 482.230857 621.714286h59.538286zM329.142857 128h475.428572a18.285714 18.285714 0 1 1 0 36.571429H329.142857a91.428571 91.428571 0 0 0 0 182.857142h475.428572a18.285714 18.285714 0 0 1 18.285714 18.285715v512a18.285714 18.285714 0 0 1-18.285714 18.285714H329.142857A128 128 0 0 1 201.142857 768V256A128 128 0 0 1 329.142857 128zM237.714286 345.6V768A91.428571 91.428571 0 0 0 329.142857 859.428571h457.142857v-475.428571H329.142857a127.634286 127.634286 0 0 1-91.428571-38.4zM329.142857 274.285714a18.285714 18.285714 0 0 1 0-36.571428h438.857143a18.285714 18.285714 0 1 1 0 36.571428H329.142857z" p-id="1498"/></svg> |
@@ -0,0 +1,41 @@ | |||
import request from '@/utils/request' | |||
export function getList(data) { | |||
return request({ | |||
url: 'api/ctVpn/list', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function add(data){ | |||
return request({ | |||
url:'api/ctVpn/add', | |||
method:'post', | |||
data | |||
}) | |||
} | |||
export function delById(data) { | |||
return request({ | |||
url: 'api/ctVpn/delete', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function editById(data) { | |||
return request({ | |||
url: 'api/ctVpn/edit', | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
export function getById(data) { | |||
return request({ | |||
url: 'api/ctVpn/getById', | |||
method: 'post', | |||
data | |||
}) | |||
} |