Compare commits
No commits in common. "2d39c81ef7560c00bb1762462fb9fc44b9baed51" and "3cbab55eb8e9abfa2e78a831cc910e3d31c7f8bb" have entirely different histories.
2d39c81ef7
...
3cbab55eb8
@ -5,7 +5,7 @@
|
|||||||
"author": "Zheng Jie",
|
"author": "Zheng Jie",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
|
"dev": "vue-cli-service serve",
|
||||||
"build:prod": "vue-cli-service build",
|
"build:prod": "vue-cli-service build",
|
||||||
"build:stage": "vue-cli-service build --mode staging",
|
"build:stage": "vue-cli-service build --mode staging",
|
||||||
"preview": "node build/index.js --preview",
|
"preview": "node build/index.js --preview",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 805 KiB After Width: | Height: | Size: 236 KiB |
Binary file not shown.
Before Width: | Height: | Size: 889 KiB After Width: | Height: | Size: 8.6 KiB |
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="display: inline-block">
|
<div>
|
||||||
<el-button v-permission="permission.edit" :loading="crud.status.cu === 2" :disabled="disabledEdit" size="mini" type="primary" icon="el-icon-edit" @click.stop="crud.toEdit(data)" />
|
<el-button v-permission="permission.edit" :loading="crud.status.cu === 2" :disabled="disabledEdit" size="mini" type="primary" icon="el-icon-edit" @click.stop="crud.toEdit(data)" />
|
||||||
<el-popover v-model="pop" v-permission="permission.del" placement="top" width="180" trigger="manual" @show="onPopoverShow" @hide="onPopoverHide">
|
<el-popover v-model="pop" v-permission="permission.del" placement="top" width="180" trigger="manual" @show="onPopoverShow" @hide="onPopoverHide">
|
||||||
<p>{{ msg }}</p>
|
<p>{{ msg }}</p>
|
||||||
|
@ -346,7 +346,7 @@ function CRUD(options) {
|
|||||||
if (crud.params[item] === null || crud.params[item] === '') crud.params[item] = undefined
|
if (crud.params[item] === null || crud.params[item] === '') crud.params[item] = undefined
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
page: crud.page.page,
|
current: crud.page.page,
|
||||||
size: crud.page.size,
|
size: crud.page.size,
|
||||||
...crud.query,
|
...crud.query,
|
||||||
...crud.params
|
...crud.params
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import echarts from 'echarts'
|
import echarts from 'echarts'
|
||||||
require('echarts/theme/macarons') // echarts theme
|
require('echarts/theme/macarons') // echarts theme
|
||||||
import { debounce } from '@/utils'
|
import { debounce } from '@/utils'
|
||||||
import { getPieChatData } from '@/api/dashboard/dashboard'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@ -25,9 +24,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chart: null,
|
chart: null
|
||||||
dataList: [],
|
|
||||||
dataTitle: [],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -48,22 +45,9 @@ export default {
|
|||||||
this.chart = null
|
this.chart = null
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async initChart() {
|
initChart() {
|
||||||
let iDataList = [];
|
|
||||||
let iDataTitle = [];
|
|
||||||
await getPieChatData().then(res => {
|
|
||||||
res.forEach(function (rItem) {
|
|
||||||
let name = rItem.text;
|
|
||||||
let value = rItem.value;
|
|
||||||
let item = { name: name, value: value }
|
|
||||||
iDataTitle.push(name)
|
|
||||||
iDataList.push(item)
|
|
||||||
});
|
|
||||||
})
|
|
||||||
this.dataList = iDataList;
|
|
||||||
this.dataTitle = iDataTitle;
|
|
||||||
|
|
||||||
this.chart = echarts.init(this.$el, 'macarons')
|
this.chart = echarts.init(this.$el, 'macarons')
|
||||||
|
|
||||||
this.chart.setOption({
|
this.chart.setOption({
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
@ -72,23 +56,29 @@ export default {
|
|||||||
legend: {
|
legend: {
|
||||||
left: 'center',
|
left: 'center',
|
||||||
bottom: '10',
|
bottom: '10',
|
||||||
data: this.dataTitle
|
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
|
||||||
},
|
},
|
||||||
calculable: true,
|
calculable: true,
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '主治医生文档数',
|
name: 'WEEKLY WRITE ARTICLES',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
roseType: 'radius',
|
roseType: 'radius',
|
||||||
radius: [15, 95],
|
radius: [15, 95],
|
||||||
center: ['50%', '38%'],
|
center: ['50%', '38%'],
|
||||||
data: this.dataList,
|
data: [
|
||||||
|
{ value: 320, name: 'Industries' },
|
||||||
|
{ value: 240, name: 'Technology' },
|
||||||
|
{ value: 149, name: 'Forex' },
|
||||||
|
{ value: 100, name: 'Gold' },
|
||||||
|
{ value: 59, name: 'Forecasts' }
|
||||||
|
],
|
||||||
animationEasing: 'cubicInOut',
|
animationEasing: 'cubicInOut',
|
||||||
animationDuration: 2600
|
animationDuration: 2600
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,17 +8,17 @@
|
|||||||
<template v-if="device!=='mobile'">
|
<template v-if="device!=='mobile'">
|
||||||
<search id="header-search" class="right-menu-item" />
|
<search id="header-search" class="right-menu-item" />
|
||||||
|
|
||||||
<!-- <el-tooltip content="项目文档" effect="dark" placement="bottom">-->
|
<el-tooltip content="项目文档" effect="dark" placement="bottom">
|
||||||
<!-- <Doc class="right-menu-item hover-effect" />-->
|
<Doc class="right-menu-item hover-effect" />
|
||||||
<!-- </el-tooltip>-->
|
</el-tooltip>
|
||||||
|
|
||||||
<el-tooltip content="全屏缩放" effect="dark" placement="bottom">
|
<el-tooltip content="全屏缩放" effect="dark" placement="bottom">
|
||||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
<!-- <el-tooltip content="布局设置" effect="dark" placement="bottom">-->
|
<el-tooltip content="布局设置" effect="dark" placement="bottom">
|
||||||
<!-- <size-select id="size-select" class="right-menu-item hover-effect" />-->
|
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||||
<!-- </el-tooltip>-->
|
</el-tooltip>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '健康档案中心',
|
title: 'ELADMIN-后台管理',
|
||||||
logo: Logo
|
logo: Logo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ export default {
|
|||||||
if (this.params[item] === null || this.params[item] === '') this.params[item] = undefined
|
if (this.params[item] === null || this.params[item] === '') this.params[item] = undefined
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
page: this.page,
|
current: this.page,
|
||||||
size: this.size,
|
size: this.size,
|
||||||
...this.query,
|
...this.query,
|
||||||
...this.params
|
...this.params
|
||||||
|
@ -2,7 +2,7 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* @description 网站标题
|
* @description 网站标题
|
||||||
*/
|
*/
|
||||||
title: '健康档案中心',
|
title: 'ELADMIN',
|
||||||
/**
|
/**
|
||||||
* @description 是否显示 tagsView
|
* @description 是否显示 tagsView
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,7 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* 是否显示设置的底部信息
|
* 是否显示设置的底部信息
|
||||||
*/
|
*/
|
||||||
showFooter: false,
|
showFooter: true,
|
||||||
/**
|
/**
|
||||||
* 底部文字,支持html语法
|
* 底部文字,支持html语法
|
||||||
*/
|
*/
|
||||||
|
@ -61,10 +61,10 @@ export default {
|
|||||||
this.chart = echarts.init(this.$el, 'macarons')
|
this.chart = echarts.init(this.$el, 'macarons')
|
||||||
this.setOptions(this.chartData)
|
this.setOptions(this.chartData)
|
||||||
},
|
},
|
||||||
setOptions({ data } = {}) { // , actualData
|
setOptions({ expectedData, actualData } = {}) {
|
||||||
this.chart.setOption({
|
this.chart.setOption({
|
||||||
xAxis: {
|
xAxis: {
|
||||||
data: ['今天', '昨天', '前天', '大前天'],
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: false
|
show: false
|
||||||
@ -90,10 +90,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
data: ['数量'] // ,'actual'
|
data: ['expected', 'actual']
|
||||||
},
|
},
|
||||||
series: [{
|
series: [{
|
||||||
name: '数量', itemStyle: {
|
name: 'expected', itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: '#FF005A',
|
color: '#FF005A',
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
@ -104,31 +104,30 @@ export default {
|
|||||||
},
|
},
|
||||||
smooth: true,
|
smooth: true,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: data,
|
data: expectedData,
|
||||||
animationDuration: 2800,
|
animationDuration: 2800,
|
||||||
animationEasing: 'cubicInOut'
|
animationEasing: 'cubicInOut'
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// name: 'actual',
|
name: 'actual',
|
||||||
// smooth: true,
|
smooth: true,
|
||||||
// type: 'line',
|
type: 'line',
|
||||||
// itemStyle: {
|
itemStyle: {
|
||||||
// normal: {
|
normal: {
|
||||||
// color: '#3888fa',
|
color: '#3888fa',
|
||||||
// lineStyle: {
|
lineStyle: {
|
||||||
// color: '#3888fa',
|
color: '#3888fa',
|
||||||
// width: 2
|
width: 2
|
||||||
// },
|
},
|
||||||
// areaStyle: {
|
areaStyle: {
|
||||||
// color: '#f3f8ff'
|
color: '#f3f8ff'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// },
|
},
|
||||||
// data: actualData,
|
data: actualData,
|
||||||
// animationDuration: 2800,
|
animationDuration: 2800,
|
||||||
// animationEasing: 'quadraticOut'
|
animationEasing: 'quadraticOut'
|
||||||
// }
|
}]
|
||||||
]
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,54 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row :gutter="40" class="panel-group">
|
<el-row :gutter="40" class="panel-group">
|
||||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||||
<div class="card-panel" @click="handleSetLineChartData('user')">
|
<div class="card-panel" @click="handleSetLineChartData('newVisitis')">
|
||||||
<div class="card-panel-icon-wrapper icon-people">
|
<div class="card-panel-icon-wrapper icon-people">
|
||||||
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
|
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div class="card-panel-description">
|
<div class="card-panel-description">
|
||||||
<div class="card-panel-text">
|
<div class="card-panel-text">
|
||||||
用户统计
|
New Visits
|
||||||
</div>
|
</div>
|
||||||
<count-to :start-val="0" :end-val="groupData.user" :duration="2600" class="card-panel-num" />
|
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||||
<div class="card-panel" @click="handleSetLineChartData('dept')">
|
<div class="card-panel" @click="handleSetLineChartData('messages')">
|
||||||
<div class="card-panel-icon-wrapper icon-message">
|
<div class="card-panel-icon-wrapper icon-message">
|
||||||
<svg-icon icon-class="dept" class-name="card-panel-icon" />
|
<svg-icon icon-class="message" class-name="card-panel-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div class="card-panel-description">
|
<div class="card-panel-description">
|
||||||
<div class="card-panel-text">
|
<div class="card-panel-text">
|
||||||
部门统计
|
Messages
|
||||||
</div>
|
</div>
|
||||||
<count-to :start-val="0" :end-val="groupData.dept" :duration="3000" class="card-panel-num" />
|
<count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||||
<div class="card-panel" @click="handleSetLineChartData('role')">
|
<div class="card-panel" @click="handleSetLineChartData('purchases')">
|
||||||
<div class="card-panel-icon-wrapper icon-money">
|
<div class="card-panel-icon-wrapper icon-money">
|
||||||
<svg-icon icon-class="role" class-name="card-panel-icon" />
|
<svg-icon icon-class="money" class-name="card-panel-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div class="card-panel-description">
|
<div class="card-panel-description">
|
||||||
<div class="card-panel-text">
|
<div class="card-panel-text">
|
||||||
角色统计
|
Purchases
|
||||||
</div>
|
</div>
|
||||||
<count-to :start-val="0" :end-val="groupData.role" :duration="3200" class="card-panel-num" />
|
<count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||||
<div class="card-panel" @click="handleSetLineChartData('law')">
|
<div class="card-panel" @click="handleSetLineChartData('shoppings')">
|
||||||
<div class="card-panel-icon-wrapper icon-shopping">
|
<div class="card-panel-icon-wrapper icon-shopping">
|
||||||
<svg-icon icon-class="server" class-name="card-panel-icon" />
|
<svg-icon icon-class="shopping" class-name="card-panel-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div class="card-panel-description">
|
<div class="card-panel-description">
|
||||||
<div class="card-panel-text">
|
<div class="card-panel-text">
|
||||||
执法数据
|
Shoppings
|
||||||
</div>
|
</div>
|
||||||
<count-to :start-val="0" :end-val="groupData.law" :duration="3600" class="card-panel-num" />
|
<count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -57,34 +57,15 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CountTo from 'vue-count-to'
|
import CountTo from 'vue-count-to'
|
||||||
import {getCardData} from '@/api/dashboard/dashboard'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CountTo
|
CountTo
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
groupData: {
|
|
||||||
"user": 0,
|
|
||||||
"dept": 0,
|
|
||||||
"role": 0,
|
|
||||||
"law": 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getGroup();
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
getGroup() {
|
|
||||||
getCardData().then(res => {
|
|
||||||
this.groupData = res
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleSetLineChartData(type) {
|
handleSetLineChartData(type) {
|
||||||
this.$emit('handleSetLineChartData', type)
|
this.$emit('handleSetLineChartData', type)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,82 +1,79 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dashboard-container">
|
<div class="dashboard-container">
|
||||||
<div class="dashboard-editor-container">
|
<div class="dashboard-editor-container">
|
||||||
|
<github-corner class="github-corner" />
|
||||||
|
|
||||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
||||||
|
|
||||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
||||||
<line-chart :chart-data="lineChartData" :chartData="lineChartData" />
|
<line-chart :chart-data="lineChartData" />
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="32">
|
<el-row :gutter="32">
|
||||||
<!-- <el-col :xs="24" :sm="24" :lg="8">-->
|
<el-col :xs="24" :sm="24" :lg="8">
|
||||||
<!-- <div class="chart-wrapper">-->
|
<div class="chart-wrapper">
|
||||||
<!-- <radar-chart />-->
|
<radar-chart />
|
||||||
<!-- </div>-->
|
</div>
|
||||||
<!-- </el-col>-->
|
</el-col>
|
||||||
<el-col :xs="24" :sm="24" :lg="24">
|
<el-col :xs="24" :sm="24" :lg="8">
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<pie-chart />
|
<pie-chart />
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- <el-col :xs="24" :sm="24" :lg="12">-->
|
<el-col :xs="24" :sm="24" :lg="8">
|
||||||
<!-- <div class="chart-wrapper">-->
|
<div class="chart-wrapper">
|
||||||
<!-- <bar-chart />-->
|
<bar-chart />
|
||||||
<!-- </div>-->
|
</div>
|
||||||
<!-- </el-col>-->
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import GithubCorner from '@/components/GithubCorner'
|
||||||
import PanelGroup from './dashboard/PanelGroup'
|
import PanelGroup from './dashboard/PanelGroup'
|
||||||
import LineChart from './dashboard/LineChart'
|
import LineChart from './dashboard/LineChart'
|
||||||
// import RadarChart from '@/components/Echarts/RadarChart'
|
import RadarChart from '@/components/Echarts/RadarChart'
|
||||||
import PieChart from '@/components/Echarts/PieChart'
|
import PieChart from '@/components/Echarts/PieChart'
|
||||||
// import BarChart from '@/components/Echarts/BarChart'
|
import BarChart from '@/components/Echarts/BarChart'
|
||||||
import { getLineChart} from '@/api/dashboard/dashboard'
|
|
||||||
|
|
||||||
const lineChartData = {
|
const lineChartData = {
|
||||||
user: {
|
newVisitis: {
|
||||||
data: [100, 120, 161, 134, 105, 160, 165],
|
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||||
// actualData: [120, 82, 91, 154, 162, 140, 145]
|
actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||||
},
|
},
|
||||||
dept: {
|
messages: {
|
||||||
data: [200, 192, 120, 144, 160, 130, 140],
|
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||||
// actualData: [180, 160, 151, 106, 145, 150, 130]
|
actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||||
},
|
},
|
||||||
role: {
|
purchases: {
|
||||||
data: [80, 100, 121, 104, 105, 90, 100],
|
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||||
// actualData: [120, 90, 100, 138, 142, 130, 130]
|
actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||||
},
|
},
|
||||||
law: {
|
shoppings: {
|
||||||
data: [130, 140, 141, 142, 145, 150, 160],
|
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||||
// actualData: [120, 82, 91, 154, 162, 140, 130]
|
actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
components: {
|
components: {
|
||||||
|
GithubCorner,
|
||||||
PanelGroup,
|
PanelGroup,
|
||||||
LineChart,
|
LineChart,
|
||||||
// RadarChart,
|
RadarChart,
|
||||||
PieChart,
|
PieChart,
|
||||||
// BarChart
|
BarChart
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
lineChartData: lineChartData.user
|
lineChartData: lineChartData.newVisitis
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
this.handleSetLineChartData("user");
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
handleSetLineChartData(type) {
|
handleSetLineChartData(type) {
|
||||||
getLineChart(type).then(res => {
|
this.lineChartData = lineChartData[type]
|
||||||
this.lineChartData.data = res
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="login" :style="'background-image:url('+ Background +');'">
|
<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">
|
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form">
|
||||||
<h3 class="title">
|
<h3 class="title">
|
||||||
健康档案管理中心
|
ELADMIN 后台管理系统
|
||||||
</h3>
|
</h3>
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
|
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
|
||||||
@ -186,7 +186,6 @@ export default {
|
|||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
width: 385px;
|
width: 385px;
|
||||||
padding: 25px 25px 5px 25px;
|
padding: 25px 25px 5px 25px;
|
||||||
opacity: 0.9;
|
|
||||||
.el-input {
|
.el-input {
|
||||||
height: 38px;
|
height: 38px;
|
||||||
input {
|
input {
|
||||||
|
144
eladmin-web/src/views/maint/app/index.vue
Normal file
144
eladmin-web/src/views/maint/app/index.vue
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!--工具栏-->
|
||||||
|
<div class="head-container">
|
||||||
|
<div v-if="crud.props.searchToggle">
|
||||||
|
<!-- 搜索 -->
|
||||||
|
<el-input v-model="query.name" clearable placeholder="输入名称搜索" style="width: 200px" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||||
|
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||||
|
<rrOperation />
|
||||||
|
</div>
|
||||||
|
<crudOperation :permission="permission">
|
||||||
|
<el-button
|
||||||
|
slot="left"
|
||||||
|
v-permission="['admin','app:add']"
|
||||||
|
:disabled="!currentRow"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="copy"
|
||||||
|
>复制</el-button>
|
||||||
|
</crudOperation>
|
||||||
|
</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="800px">
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="100px">
|
||||||
|
<el-form-item label="应用名称" prop="name">
|
||||||
|
<el-input v-model="form.name" style="width: 670px" placeholder="部署后的文件或者目录名称,用于备份" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应用端口" prop="port">
|
||||||
|
<el-input-number v-model.number="form.port" placeholder="例如:8080" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上传目录" prop="uploadPath">
|
||||||
|
<el-input v-model="form.uploadPath" style="width: 670px" placeholder="例如: /opt/upload" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部署目录" prop="deployPath">
|
||||||
|
<el-input v-model="form.deployPath" style="width: 670px" placeholder="例如: /opt/app" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备份目录" prop="backupPath">
|
||||||
|
<el-input v-model="form.backupPath" style="width: 670px" placeholder="例如: /opt/backup" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部署脚本" prop="deployScript">
|
||||||
|
<el-input v-model="form.deployScript" :rows="3" type="textarea" autosize style="width: 670px" placeholder="" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="启动脚本" prop="startScript">
|
||||||
|
<el-input v-model="form.startScript" :rows="3" type="textarea" autosize style="width: 670px" 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" :data="crud.data" highlight-current-row style="width: 100%" @selection-change="crud.selectionChangeHandler" @current-change="handleCurrentChange">
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<el-table-column prop="name" label="应用名称" />
|
||||||
|
<el-table-column prop="port" label="端口号" />
|
||||||
|
<el-table-column prop="uploadPath" label="上传目录" />
|
||||||
|
<el-table-column prop="deployPath" label="部署目录" />
|
||||||
|
<el-table-column prop="backupPath" label="备份目录" />
|
||||||
|
<el-table-column prop="createTime" label="创建日期" />
|
||||||
|
<el-table-column v-if="checkPer(['admin','app:edit','app:del'])" label="操作" width="150px" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<udOperation
|
||||||
|
:data="scope.row"
|
||||||
|
:permission="permission"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--分页组件-->
|
||||||
|
<pagination />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import crudApp from '@/api/maint/app'
|
||||||
|
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 pagination from '@crud/Pagination'
|
||||||
|
import DateRangePicker from '@/components/DateRangePicker'
|
||||||
|
|
||||||
|
const defaultForm = { id: null, name: null, port: 8080, uploadPath: '/opt/upload', deployPath: '/opt/app', backupPath: '/opt/backup', startScript: null, deployScript: null }
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
components: { pagination, crudOperation, rrOperation, udOperation, DateRangePicker },
|
||||||
|
cruds() {
|
||||||
|
return CRUD({ title: '应用', url: 'api/app', crudMethod: { ...crudApp }})
|
||||||
|
},
|
||||||
|
mixins: [presenter(), header(), form(defaultForm), crud()],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentRow: null,
|
||||||
|
permission: {
|
||||||
|
add: ['admin', 'app:add'],
|
||||||
|
edit: ['admin', 'app:edit'],
|
||||||
|
del: ['admin', 'app:del']
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入应用名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
port: [
|
||||||
|
{ required: true, message: '请输入应用端口', trigger: 'blur', type: 'number' }
|
||||||
|
],
|
||||||
|
uploadPath: [
|
||||||
|
{ required: true, message: '请输入上传目录', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
deployPath: [
|
||||||
|
{ required: true, message: '请输入部署目录', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
backupPath: [
|
||||||
|
{ required: true, message: '请输入备份目录', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
startScript: [
|
||||||
|
{ required: true, message: '请输入启动脚本', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
deployScript: [
|
||||||
|
{ required: true, message: '请输入部署脚本', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
copy() {
|
||||||
|
for (const key in this.currentRow) {
|
||||||
|
this.form[key] = this.currentRow[key]
|
||||||
|
}
|
||||||
|
this.form.id = null
|
||||||
|
this.form.createTime = null
|
||||||
|
this.crud.toAdd()
|
||||||
|
},
|
||||||
|
handleCurrentChange(row) {
|
||||||
|
this.currentRow = JSON.parse(JSON.stringify(row))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
86
eladmin-web/src/views/maint/database/execute.vue
Normal file
86
eladmin-web/src/views/maint/database/execute.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog append-to-body :close-on-click-modal="false" :visible.sync="dialog" title="执行脚本" width="400px">
|
||||||
|
<el-form ref="form" :rules="rules" size="small">
|
||||||
|
<el-upload
|
||||||
|
:action="databaseUploadApi"
|
||||||
|
:data="databaseInfo"
|
||||||
|
:headers="headers"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
class="upload-demo"
|
||||||
|
drag
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload" />
|
||||||
|
<div class="el-upload__text">
|
||||||
|
将文件拖到此处,或
|
||||||
|
<em>点击上传</em>
|
||||||
|
</div>
|
||||||
|
<div slot="tip" class="el-upload__tip">上传后,系统会自动执行SQL脚本</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="cancel">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
databaseInfo: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
dialog: false,
|
||||||
|
headers: {
|
||||||
|
Authorization: getToken()
|
||||||
|
},
|
||||||
|
rules: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['databaseUploadApi'])
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cancel() {
|
||||||
|
this.dialog = false
|
||||||
|
},
|
||||||
|
handleSuccess(response, file, fileList) {
|
||||||
|
if (response === 'success') {
|
||||||
|
this.$notify({
|
||||||
|
title: '执行成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2500
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$notify({
|
||||||
|
title: response,
|
||||||
|
type: 'error',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleError(e, file, fileList) {
|
||||||
|
const msg = JSON.parse(e.message)
|
||||||
|
this.$notify({
|
||||||
|
title: msg.message,
|
||||||
|
type: 'error',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
148
eladmin-web/src/views/maint/database/index.vue
Normal file
148
eladmin-web/src/views/maint/database/index.vue
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!--工具栏-->
|
||||||
|
<div class="head-container">
|
||||||
|
<div v-if="crud.props.searchToggle">
|
||||||
|
<!-- 搜索 -->
|
||||||
|
<el-input v-model="query.blurry" clearable placeholder="模糊搜索" style="width: 200px" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||||
|
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||||
|
<rrOperation />
|
||||||
|
</div>
|
||||||
|
<crudOperation :permission="permission">
|
||||||
|
<el-button
|
||||||
|
slot="right"
|
||||||
|
v-permission="['admin','database:add']"
|
||||||
|
:disabled="!selectIndex"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="warning"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
@click="execute"
|
||||||
|
>执行脚本
|
||||||
|
</el-button>
|
||||||
|
</crudOperation>
|
||||||
|
</div>
|
||||||
|
<!--表单组件-->
|
||||||
|
<eForm ref="execute" :database-info="currentRow" />
|
||||||
|
<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="530px">
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="100px">
|
||||||
|
<el-form-item label="连接名称" prop="name">
|
||||||
|
<el-input v-model="form.name" style="width: 370px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="JDBC地址" prop="jdbcUrl">
|
||||||
|
<el-input v-model="form.jdbcUrl" style="width: 300px" />
|
||||||
|
<el-button :loading="loading" type="success" @click="testConnectDatabase">测试</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户" prop="userName">
|
||||||
|
<el-input v-model="form.userName" style="width: 370px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" prop="pwd">
|
||||||
|
<el-input v-model="form.pwd" type="password" 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 stripe style="width: 100%" @selection-change="handleCurrentChange">
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<el-table-column prop="name" width="130px" label="数据库名称" />
|
||||||
|
<el-table-column prop="jdbcUrl" label="连接地址" />
|
||||||
|
<el-table-column prop="userName" width="200px" label="用户名" />
|
||||||
|
<el-table-column prop="createTime" width="200px" label="创建日期" />
|
||||||
|
<el-table-column v-if="checkPer(['admin','database:edit','database:del'])" label="操作" width="150px" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<udOperation
|
||||||
|
:data="scope.row"
|
||||||
|
:permission="permission"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--分页组件-->
|
||||||
|
<pagination />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import crudDatabase from '@/api/maint/database'
|
||||||
|
import { testDbConnect } from '@/api/maint/connect'
|
||||||
|
import eForm from './execute'
|
||||||
|
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 pagination from '@crud/Pagination'
|
||||||
|
import DateRangePicker from '@/components/DateRangePicker'
|
||||||
|
|
||||||
|
const defaultForm = { id: null, name: null, jdbcUrl: 'jdbc:mysql://', userName: null, pwd: null }
|
||||||
|
export default {
|
||||||
|
name: 'DataBase',
|
||||||
|
components: { eForm, pagination, crudOperation, rrOperation, udOperation, DateRangePicker },
|
||||||
|
cruds() {
|
||||||
|
return CRUD({ title: '数据库', url: 'api/database', crudMethod: { ...crudDatabase }})
|
||||||
|
},
|
||||||
|
mixins: [presenter(), header(), form(defaultForm), crud()],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentRow: {},
|
||||||
|
selectIndex: '',
|
||||||
|
databaseInfo: '',
|
||||||
|
loading: false,
|
||||||
|
permission: {
|
||||||
|
add: ['admin', 'database:add'],
|
||||||
|
edit: ['admin', 'database:edit'],
|
||||||
|
del: ['admin', 'database:del']
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入数据库名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
jdbcUrl: [
|
||||||
|
{ required: true, message: '请输入数据库连接地址', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
userName: [
|
||||||
|
{ required: true, message: '请输入用户名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
pwd: [
|
||||||
|
{ required: true, message: '请输入数据库密码', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
testConnectDatabase() {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.loading = true
|
||||||
|
testDbConnect(this.form).then((res) => {
|
||||||
|
this.loading = false
|
||||||
|
this.crud.notify(res ? '连接成功' : '连接失败', res ? 'success' : 'error')
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
execute() {
|
||||||
|
this.$refs.execute.dialog = true
|
||||||
|
},
|
||||||
|
handleCurrentChange(selection) {
|
||||||
|
this.crud.selections = selection
|
||||||
|
if (selection.length === 1) {
|
||||||
|
const row = selection[0]
|
||||||
|
this.selectIndex = row.id
|
||||||
|
this.currentRow = row
|
||||||
|
} else {
|
||||||
|
this.currentRow = {}
|
||||||
|
this.selectIndex = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
190
eladmin-web/src/views/maint/deploy/deploy.vue
Normal file
190
eladmin-web/src/views/maint/deploy/deploy.vue
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog append-to-body :close-on-click-modal="false" :visible.sync="dialog" title="应用部署" width="400px">
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" size="small">
|
||||||
|
<el-upload
|
||||||
|
:action="deployUploadApi"
|
||||||
|
:data="deployInfo"
|
||||||
|
:headers="headers"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
class="upload-demo"
|
||||||
|
drag
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload" />
|
||||||
|
<div class="el-upload__text">
|
||||||
|
将文件拖到此处,或
|
||||||
|
<em>点击上传</em>
|
||||||
|
</div>
|
||||||
|
<div slot="tip" class="el-upload__tip">多个应用上传文件名称为all.zip,数据库更新脚本扩展名为.sql,上传成功后系统自动部署系统。</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="cancel">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { add, edit, getApps, getServers } from '@/api/maint/deploy'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
dialog: false,
|
||||||
|
apps: [],
|
||||||
|
servers: [],
|
||||||
|
headers: {
|
||||||
|
Authorization: getToken()
|
||||||
|
},
|
||||||
|
deployInfo: {},
|
||||||
|
form: {
|
||||||
|
id: '',
|
||||||
|
appId: '',
|
||||||
|
ip: '',
|
||||||
|
selectIp: []
|
||||||
|
},
|
||||||
|
rules: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['deployUploadApi'])
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.initWebSocket()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initSelect()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cancel() {
|
||||||
|
this.resetForm()
|
||||||
|
},
|
||||||
|
doSubmit() {
|
||||||
|
this.loading = true
|
||||||
|
if (this.isAdd) {
|
||||||
|
this.doAdd()
|
||||||
|
} else {
|
||||||
|
this.doEdit()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
joinIp() {
|
||||||
|
this.form.ip = ''
|
||||||
|
this.form.selectIp.forEach(ip => {
|
||||||
|
if (this.form.ip !== '') {
|
||||||
|
this.form.ip += ','
|
||||||
|
}
|
||||||
|
this.form.ip += ip
|
||||||
|
})
|
||||||
|
},
|
||||||
|
doAdd() {
|
||||||
|
this.joinIp()
|
||||||
|
add(this.form)
|
||||||
|
.then(res => {
|
||||||
|
this.resetForm()
|
||||||
|
this.$notify({
|
||||||
|
title: '添加成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2500
|
||||||
|
})
|
||||||
|
this.loading = false
|
||||||
|
this.$parent.init()
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.loading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
doEdit() {
|
||||||
|
this.joinIp()
|
||||||
|
edit(this.form)
|
||||||
|
.then(res => {
|
||||||
|
this.resetForm()
|
||||||
|
this.$notify({
|
||||||
|
title: '修改成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2500
|
||||||
|
})
|
||||||
|
this.loading = false
|
||||||
|
this.$parent.init()
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.loading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resetForm() {
|
||||||
|
this.dialog = false
|
||||||
|
this.$refs['form'].resetFields()
|
||||||
|
this.form = {
|
||||||
|
id: '',
|
||||||
|
appId: '',
|
||||||
|
ip: '',
|
||||||
|
selectIp: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initSelect() {
|
||||||
|
getApps().then(res => {
|
||||||
|
this.apps = res.content
|
||||||
|
})
|
||||||
|
getServers().then(res => {
|
||||||
|
this.servers = res.content
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSuccess(response, file, fileList) {
|
||||||
|
this.cancel()
|
||||||
|
},
|
||||||
|
// 监听上传失败
|
||||||
|
handleError(e, file, fileList) {
|
||||||
|
const msg = JSON.parse(e.message)
|
||||||
|
this.$notify({
|
||||||
|
title: msg.message,
|
||||||
|
type: 'error',
|
||||||
|
duration: 2500
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initWebSocket() {
|
||||||
|
const wsUri = (process.env.VUE_APP_WS_API === '/' ? '/' : (process.env.VUE_APP_WS_API + '/')) + 'webSocket/deploy'
|
||||||
|
this.websock = new WebSocket(wsUri)
|
||||||
|
this.websock.onerror = this.webSocketOnError
|
||||||
|
this.websock.onmessage = this.webSocketOnMessage
|
||||||
|
},
|
||||||
|
webSocketOnError(e) {
|
||||||
|
this.$notify({
|
||||||
|
title: 'WebSocket连接发生错误',
|
||||||
|
type: 'error',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
webSocketOnMessage(e) {
|
||||||
|
const data = JSON.parse(e.data)
|
||||||
|
if (data.msgType === 'INFO') {
|
||||||
|
this.$notify({
|
||||||
|
title: '',
|
||||||
|
message: data.msg,
|
||||||
|
type: 'success',
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
duration: 5500
|
||||||
|
})
|
||||||
|
} else if (data.msgType === 'ERROR') {
|
||||||
|
this.$notify({
|
||||||
|
title: '',
|
||||||
|
message: data.msg,
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
type: 'error',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
webSocketSend(agentData) {
|
||||||
|
this.websock.send(agentData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
229
eladmin-web/src/views/maint/deploy/index.vue
Normal file
229
eladmin-web/src/views/maint/deploy/index.vue
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!--工具栏-->
|
||||||
|
<div class="head-container">
|
||||||
|
<div v-if="crud.props.searchToggle">
|
||||||
|
<!-- 搜索 -->
|
||||||
|
<el-input v-model="query.appName" clearable placeholder="输入应用名称查询" style="width: 200px" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||||
|
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||||
|
<rrOperation />
|
||||||
|
</div>
|
||||||
|
<crudOperation :permission="permission">
|
||||||
|
<template slot="right">
|
||||||
|
<el-button
|
||||||
|
v-permission="['admin','deploy:add']"
|
||||||
|
:disabled="!selectIndex"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
@click="sysRestore"
|
||||||
|
>系统还原
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-permission="['admin','deploy:add']"
|
||||||
|
:disabled="!selectIndex"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
@click="serverStatus"
|
||||||
|
>状态查询
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-permission="['admin','deploy:add']"
|
||||||
|
:disabled="!selectIndex"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="success"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
@click="startServer"
|
||||||
|
>启动
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-permission="['admin','deploy:add']"
|
||||||
|
:disabled="!selectIndex"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="danger"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
@click="stopServer"
|
||||||
|
>停止
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-permission="['admin','deploy:add']"
|
||||||
|
:disabled="!selectIndex"
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="warning"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
@click="deploy"
|
||||||
|
>一键部署
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</crudOperation>
|
||||||
|
</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" :model="form" :rules="rules" size="small" label-width="80px">
|
||||||
|
<el-form-item label="应用" prop="app.id">
|
||||||
|
<el-select v-model.number="form.app.id" placeholder="请选择" style="width: 370px">
|
||||||
|
<el-option v-for="item in apps" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="服务器" prop="deploys">
|
||||||
|
<el-select v-model="form.deploys" multiple placeholder="请选择" style="width: 370px">
|
||||||
|
<el-option v-for="item in servers" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</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>
|
||||||
|
<!--统还原组件-->
|
||||||
|
<fForm ref="sysRestore" :key="times" :app-name="appName" />
|
||||||
|
<dForm ref="deploy" />
|
||||||
|
<!--表格渲染-->
|
||||||
|
<el-table ref="table" v-loading="crud.loading" :data="crud.data" highlight-current-row stripe style="width: 100%" @selection-change="handleCurrentChange">
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<el-table-column prop="app.name" label="应用名称" />
|
||||||
|
<el-table-column prop="servers" label="服务器列表" />
|
||||||
|
<el-table-column prop="createTime" label="部署日期" />
|
||||||
|
<el-table-column v-if="checkPer(['admin','deploy:edit','deploy:del'])" label="操作" width="150px" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<udOperation
|
||||||
|
:data="scope.row"
|
||||||
|
:permission="permission"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--分页组件-->
|
||||||
|
<pagination />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import crudDeploy from '@/api/maint/deploy'
|
||||||
|
import dForm from './deploy'
|
||||||
|
import fForm from './sysRestore'
|
||||||
|
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 pagination from '@crud/Pagination'
|
||||||
|
import DateRangePicker from '@/components/DateRangePicker'
|
||||||
|
|
||||||
|
const defaultForm = { id: null, app: { id: null }, deploys: [] }
|
||||||
|
export default {
|
||||||
|
name: 'Deploy',
|
||||||
|
components: { dForm, fForm, pagination, crudOperation, rrOperation, udOperation, DateRangePicker },
|
||||||
|
cruds() {
|
||||||
|
return CRUD({ title: '部署', url: 'api/deploy', crudMethod: { ...crudDeploy }})
|
||||||
|
},
|
||||||
|
mixins: [presenter(), header(), form(defaultForm), crud()],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentRow: {}, selectIndex: '', appName: '', urlHistory: '',
|
||||||
|
times: 0, appId: '', deployId: '', apps: [], servers: [],
|
||||||
|
permission: {
|
||||||
|
add: ['admin', 'deploy:add'],
|
||||||
|
edit: ['admin', 'deploy:edit'],
|
||||||
|
del: ['admin', 'deploy:del']
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'app.id': [
|
||||||
|
{ required: true, message: '应用不能为空', trigger: 'blur', type: 'number' }
|
||||||
|
],
|
||||||
|
deploys: [
|
||||||
|
{ required: true, message: '服务器不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
[CRUD.HOOK.beforeRefresh]() {
|
||||||
|
this.selectIndex = ''
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 新增编辑前做的操作
|
||||||
|
[CRUD.HOOK.beforeToCU](crud, form) {
|
||||||
|
this.initSelect()
|
||||||
|
const deploys = []
|
||||||
|
form.deploys.forEach(function(deploy, index) {
|
||||||
|
deploys.push(deploy.id)
|
||||||
|
})
|
||||||
|
this.form.deploys = deploys
|
||||||
|
},
|
||||||
|
// 提交前
|
||||||
|
[CRUD.HOOK.beforeSubmit]() {
|
||||||
|
const deploys = []
|
||||||
|
this.form.deploys.forEach(function(data, index) {
|
||||||
|
const deploy = { id: data }
|
||||||
|
deploys.push(deploy)
|
||||||
|
})
|
||||||
|
this.form.deploys = deploys
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
deploy() {
|
||||||
|
this.$refs.deploy.dialog = true
|
||||||
|
this.$refs.deploy.deployInfo = this.currentRow
|
||||||
|
},
|
||||||
|
sysRestore() {
|
||||||
|
this.$refs.sysRestore.dialog = true
|
||||||
|
},
|
||||||
|
handleCurrentChange(selection) {
|
||||||
|
this.crud.selections = selection
|
||||||
|
if (selection.length === 1) {
|
||||||
|
const row = selection[0]
|
||||||
|
this.selectIndex = row.id
|
||||||
|
this.currentRow = row
|
||||||
|
this.appName = row.app.name
|
||||||
|
this.times = this.times + 1
|
||||||
|
this.appId = row.appId
|
||||||
|
this.deployId = row.id
|
||||||
|
} else {
|
||||||
|
this.currentRow = {}
|
||||||
|
this.selectIndex = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
startServer() {
|
||||||
|
crudDeploy.startServer(JSON.stringify(this.currentRow))
|
||||||
|
.then(res => {
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('error:' + err.response.data.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
stopServer() {
|
||||||
|
crudDeploy.stopServer(JSON.stringify(this.currentRow))
|
||||||
|
.then(res => {
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('error:' + err.response.data.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
serverStatus() {
|
||||||
|
crudDeploy.serverStatus(JSON.stringify(this.currentRow))
|
||||||
|
.then(res => {
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('error:' + err.response.data.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initSelect() {
|
||||||
|
crudDeploy.getApps().then(res => {
|
||||||
|
this.apps = res.content
|
||||||
|
})
|
||||||
|
crudDeploy.getServers().then(res => {
|
||||||
|
this.servers = res.content
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
107
eladmin-web/src/views/maint/deploy/sysRestore.vue
Normal file
107
eladmin-web/src/views/maint/deploy/sysRestore.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog append-to-body :close-on-click-modal="false" :visible.sync="dialog" title="系统还原" width="800px">
|
||||||
|
<!--工具栏-->
|
||||||
|
<div class="head-container">
|
||||||
|
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||||
|
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
|
||||||
|
</div>
|
||||||
|
<el-form size="small" label-width="80px">
|
||||||
|
<!--表格渲染-->
|
||||||
|
<el-table v-loading="loading" :data="data" style="width: 100%" @row-click="showRow">
|
||||||
|
<el-table-column width="30px">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-radio v-model="radio" :label="scope.$index" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="appName" label="应用名称" />
|
||||||
|
<el-table-column prop="ip" label="部署IP" />
|
||||||
|
<el-table-column prop="deployDate" label="部署时间" />
|
||||||
|
<el-table-column prop="deployUser" label="部署人员" />
|
||||||
|
</el-table>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="text" @click="cancel">取消</el-button>
|
||||||
|
<el-button v-permission="['admin','deploy:add']" :loading="submitLoading" type="primary" @click="doSubmit">确认</el-button>
|
||||||
|
</div>
|
||||||
|
<!--分页组件-->
|
||||||
|
<el-pagination
|
||||||
|
:total="total"
|
||||||
|
:current-page="page"
|
||||||
|
style="margin-top: 8px"
|
||||||
|
layout="total, prev, pager, next, sizes"
|
||||||
|
@size-change="sizeChange"
|
||||||
|
@current-change="pageChange"
|
||||||
|
/>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import crud from '@/mixins/crud'
|
||||||
|
import { reducte } from '@/api/maint/deployHistory'
|
||||||
|
import DateRangePicker from '@/components/DateRangePicker'
|
||||||
|
export default {
|
||||||
|
components: { DateRangePicker },
|
||||||
|
mixins: [crud],
|
||||||
|
props: {
|
||||||
|
appName: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
submitLoading: false,
|
||||||
|
dialog: false,
|
||||||
|
history: [],
|
||||||
|
radio: '',
|
||||||
|
appNames: '',
|
||||||
|
selectIndex: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.init()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
beforeInit() {
|
||||||
|
this.url = 'api/deployHistory'
|
||||||
|
this.deployId = this.$parent.deployId
|
||||||
|
if (this.deployId === '') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.params['deployId'] = this.deployId
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
showRow(row) {
|
||||||
|
this.radio = this.data.indexOf(row)
|
||||||
|
this.selectIndex = row.id
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
this.dialog = false
|
||||||
|
this.submitLoading = false
|
||||||
|
},
|
||||||
|
doSubmit() {
|
||||||
|
if (this.selectIndex === '') {
|
||||||
|
this.$message.error('请选择要还原的备份')
|
||||||
|
} else {
|
||||||
|
this.submitLoading = true
|
||||||
|
reducte(JSON.stringify(this.data[this.radio]))
|
||||||
|
.then(res => {
|
||||||
|
this.dialog = false
|
||||||
|
this.submitLoading = false
|
||||||
|
this.appNames = ''
|
||||||
|
this.$parent.crud.toQuery()
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.submitLoading = false
|
||||||
|
console.log('error:' + err.response.data.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
93
eladmin-web/src/views/maint/deployHistory/index.vue
Normal file
93
eladmin-web/src/views/maint/deployHistory/index.vue
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!--工具栏-->
|
||||||
|
<div class="head-container">
|
||||||
|
<div v-if="crud.props.searchToggle">
|
||||||
|
<!-- 搜索 -->
|
||||||
|
<el-input v-model="query.blurry" clearable placeholder="输入搜索内容" style="width: 200px" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||||
|
<date-range-picker v-model="query.deployDate" class="date-item" />
|
||||||
|
<rrOperation />
|
||||||
|
</div>
|
||||||
|
<crudOperation :permission="permission" />
|
||||||
|
</div>
|
||||||
|
<!--表格渲染-->
|
||||||
|
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%" @selection-change="crud.selectionChangeHandler">
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<el-table-column prop="appName" label="应用名称" />
|
||||||
|
<el-table-column prop="ip" label="部署IP" />
|
||||||
|
<el-table-column prop="deployUser" label="部署人员" />
|
||||||
|
<el-table-column prop="deployDate" label="部署时间" />
|
||||||
|
<el-table-column v-if="checkPer(['admin','deployHistory:del'])" label="操作" width="100px" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-popover
|
||||||
|
:ref="scope.row.id"
|
||||||
|
v-permission="['admin','deployHistory:del']"
|
||||||
|
placement="top"
|
||||||
|
width="180"
|
||||||
|
>
|
||||||
|
<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="danger" icon="el-icon-delete" size="mini" />
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--分页组件-->
|
||||||
|
<pagination />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { del } from '@/api/maint/deployHistory'
|
||||||
|
import CRUD, { presenter, header } 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'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DeployHistory',
|
||||||
|
components: { pagination, crudOperation, rrOperation, DateRangePicker },
|
||||||
|
cruds() {
|
||||||
|
return CRUD({ title: '部署历史', url: 'api/deployHistory', crudMethod: { del }})
|
||||||
|
},
|
||||||
|
mixins: [presenter(), header()],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
delLoading: false,
|
||||||
|
permission: {
|
||||||
|
del: ['admin', 'deployHistory:del']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.crud.optShow = {
|
||||||
|
add: false,
|
||||||
|
edit: false,
|
||||||
|
del: true,
|
||||||
|
download: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
delMethod(id) {
|
||||||
|
this.delLoading = true
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
136
eladmin-web/src/views/maint/server/index.vue
Normal file
136
eladmin-web/src/views/maint/server/index.vue
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!--工具栏-->
|
||||||
|
<div class="head-container">
|
||||||
|
<div v-if="crud.props.searchToggle">
|
||||||
|
<!-- 搜索 -->
|
||||||
|
<el-input v-model="query.blurry" clearable placeholder="输入名称或IP搜索" style="width: 200px" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||||
|
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||||
|
<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="470px">
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="55px">
|
||||||
|
<el-form-item label="名称" prop="name">
|
||||||
|
<el-input v-model="form.name" style="width: 370px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="IP" prop="ip">
|
||||||
|
<el-input v-model="form.ip" style="width: 370px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="端口" prop="port">
|
||||||
|
<el-input-number v-model.number="form.port" controls-position="right" style="width: 370px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账号" prop="account">
|
||||||
|
<el-input v-model="form.account" style="width: 370px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" prop="password">
|
||||||
|
<el-input v-model="form.password" type="password" style="width: 200px" />
|
||||||
|
<el-button :loading="loading" type="success" style="align: right;" @click="testConnectServer">测试连接</el-button>
|
||||||
|
</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 type="selection" width="55" />
|
||||||
|
<el-table-column prop="name" label="名称" />
|
||||||
|
<el-table-column prop="ip" label="IP" />
|
||||||
|
<el-table-column prop="port" label="端口" />
|
||||||
|
<el-table-column prop="account" label="账号" />
|
||||||
|
<el-table-column prop="createTime" label="创建日期" />
|
||||||
|
<el-table-column v-if="checkPer(['admin','serverDeploy:edit','serverDeploy:del'])" label="操作" width="150px" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<udOperation
|
||||||
|
:data="scope.row"
|
||||||
|
:permission="permission"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--分页组件-->
|
||||||
|
<pagination />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import crudServer from '@/api/maint/serverDeploy'
|
||||||
|
import { testServerConnect } from '@/api/maint/connect'
|
||||||
|
import { validateIP } from '@/utils/validate'
|
||||||
|
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 pagination from '@crud/Pagination'
|
||||||
|
import DateRangePicker from '@/components/DateRangePicker'
|
||||||
|
|
||||||
|
const defaultForm = { id: null, name: null, ip: null, port: 22, account: 'root', password: null }
|
||||||
|
export default {
|
||||||
|
name: 'Server',
|
||||||
|
components: { pagination, crudOperation, rrOperation, udOperation, DateRangePicker },
|
||||||
|
cruds() {
|
||||||
|
return CRUD({ title: '服务器', url: 'api/serverDeploy', crudMethod: { ...crudServer }})
|
||||||
|
},
|
||||||
|
mixins: [presenter(), header(), form(defaultForm), crud()],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
accountList: [],
|
||||||
|
accountMap: {},
|
||||||
|
loading: false,
|
||||||
|
permission: {
|
||||||
|
add: ['admin', 'serverDeploy:add'],
|
||||||
|
edit: ['admin', 'serverDeploy:edit'],
|
||||||
|
del: ['admin', 'serverDeploy:del']
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
ip: [
|
||||||
|
{ required: true, message: '请输入IP', trigger: 'blur' },
|
||||||
|
{ validator: validateIP, trigger: 'change' }
|
||||||
|
],
|
||||||
|
port: [
|
||||||
|
{ required: true, message: '请输入端口', trigger: 'blur', type: 'number' }
|
||||||
|
],
|
||||||
|
account: [
|
||||||
|
{ required: true, message: '请输入账号', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: '请输入密码', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
testConnectServer() {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.loading = true
|
||||||
|
testServerConnect(this.form).then((res) => {
|
||||||
|
this.loading = false
|
||||||
|
this.$notify({
|
||||||
|
title: res ? '连接成功' : '连接失败',
|
||||||
|
type: res ? 'success' : 'error',
|
||||||
|
duration: 2500
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
|
::v-deep .el-input-number .el-input__inner {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
</style>
|
36
eladmin-web/src/views/nested/menu1/menu1-1/index.vue
Normal file
36
eladmin-web/src/views/nested/menu1/menu1-1/index.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-alert :closable="false" title="三级菜单1" type="success" />
|
||||||
|
<el-form label-width="170px" style="margin-top: 20px">
|
||||||
|
<el-form-item label="三级菜单缓存功能测试区">
|
||||||
|
<el-input v-model="input" placeholder="请输入内容" style="width: 360px;" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div>
|
||||||
|
<blockquote class="my-blockquote"> 三级菜单缓存配置教程</blockquote>
|
||||||
|
<pre class="my-code">
|
||||||
|
1、将前后端代码更新为最新版版本,或对照提交记录修改,点击查看-> <a href="https://gitee.com/elunez/eladmin/commit/43d1a63577f9d5347924355708429a2d210e29f7" target="_blank">提交(1)</a>、<a href="https://gitee.com/elunez/eladmin/commit/46393875148fcca5eaa327d4073f72edb3752f5c" target="_blank">提交(2)</a>、<a href="https://gitee.com/elunez/eladmin-web/commit/c93c99d8921abbb2c52afc806635f5ca08d6bda8" target="_blank">提交(3)</a>
|
||||||
|
2、将 二级菜单 的 菜单类型 设置为 目录 级别,并且原有的 组件路径 需要清空
|
||||||
|
3、将 三级菜单 的 菜单缓存 设置为 是,最后将 组件名称 填写正确
|
||||||
|
4、具体设置可参考 菜单管理 的 多级菜单 配置进行进行相应的修改
|
||||||
|
</pre>
|
||||||
|
<blockquote class="my-blockquote">更多帮助</blockquote>
|
||||||
|
<pre class="my-code">QQ交流群:一群:891137268、二群:947578238、三群:659622532</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Test',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
input: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.my-code a{
|
||||||
|
color:#009688;
|
||||||
|
}
|
||||||
|
</style>
|
5
eladmin-web/src/views/nested/menu1/menu1-2/index.vue
Normal file
5
eladmin-web/src/views/nested/menu1/menu1-2/index.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div style="padding:30px;">
|
||||||
|
<el-alert :closable="false" title="三级菜单2" type="success" />
|
||||||
|
</div>
|
||||||
|
</template>
|
5
eladmin-web/src/views/nested/menu2/index.vue
Normal file
5
eladmin-web/src/views/nested/menu2/index.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div style="padding:30px;">
|
||||||
|
<el-alert :closable="false" title="二级菜单" />
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -21,7 +21,7 @@
|
|||||||
<ul class="user-info">
|
<ul class="user-info">
|
||||||
<li><div style="height: 100%"><svg-icon icon-class="login" /> 登录账号<div class="user-right">{{ user.username }}</div></div></li>
|
<li><div style="height: 100%"><svg-icon icon-class="login" /> 登录账号<div class="user-right">{{ user.username }}</div></div></li>
|
||||||
<li><svg-icon icon-class="user1" /> 用户昵称 <div class="user-right">{{ user.nickName }}</div></li>
|
<li><svg-icon icon-class="user1" /> 用户昵称 <div class="user-right">{{ user.nickName }}</div></li>
|
||||||
<li><svg-icon icon-class="dept" /> 所属医院 <div class="user-right"> {{ user.dept.name }}</div></li>
|
<li><svg-icon icon-class="dept" /> 所属部门 <div class="user-right"> {{ user.dept.name }}</div></li>
|
||||||
<li><svg-icon icon-class="phone" /> 手机号码 <div class="user-right">{{ user.phone }}</div></li>
|
<li><svg-icon icon-class="phone" /> 手机号码 <div class="user-right">{{ user.phone }}</div></li>
|
||||||
<li><svg-icon icon-class="email" /> 用户邮箱 <div class="user-right">{{ user.email }}</div></li>
|
<li><svg-icon icon-class="email" /> 用户邮箱 <div class="user-right">{{ user.email }}</div></li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -86,32 +86,32 @@
|
|||||||
<el-form-item label="邮箱" prop="email">
|
<el-form-item label="邮箱" prop="email">
|
||||||
<el-input v-model="form.email" />
|
<el-input v-model="form.email" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="归属" prop="dept.id">
|
<el-form-item label="部门" prop="dept.id">
|
||||||
<treeselect
|
<treeselect
|
||||||
v-model="form.dept.id"
|
v-model="form.dept.id"
|
||||||
:options="depts"
|
:options="depts"
|
||||||
:load-options="loadDepts"
|
:load-options="loadDepts"
|
||||||
style="width: 173px"
|
style="width: 173px"
|
||||||
placeholder="选择医院"
|
placeholder="选择部门"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="岗位" prop="jobDatas" class="is-required">-->
|
<el-form-item label="岗位" prop="jobDatas" class="is-required">
|
||||||
<!-- <el-select-->
|
<el-select
|
||||||
<!-- v-model="jobDatas"-->
|
v-model="jobDatas"
|
||||||
<!-- style="width: 172px"-->
|
style="width: 172px"
|
||||||
<!-- multiple-->
|
multiple
|
||||||
<!-- placeholder="请选择"-->
|
placeholder="请选择"
|
||||||
<!-- @remove-tag="deleteTag"-->
|
@remove-tag="deleteTag"
|
||||||
<!-- @change="changeJob"-->
|
@change="changeJob"
|
||||||
<!-- >-->
|
>
|
||||||
<!-- <el-option-->
|
<el-option
|
||||||
<!-- v-for="item in jobs"-->
|
v-for="item in jobs"
|
||||||
<!-- :key="item.name"-->
|
:key="item.name"
|
||||||
<!-- :label="item.name"-->
|
:label="item.name"
|
||||||
<!-- :value="item.id"-->
|
:value="item.id"
|
||||||
<!-- />-->
|
/>
|
||||||
<!-- </el-select>-->
|
</el-select>
|
||||||
<!-- </el-form-item>-->
|
</el-form-item>
|
||||||
<el-form-item label="性别">
|
<el-form-item label="性别">
|
||||||
<el-radio-group v-model="form.gender" style="width: 178px">
|
<el-radio-group v-model="form.gender" style="width: 178px">
|
||||||
<el-radio label="男">男</el-radio>
|
<el-radio label="男">男</el-radio>
|
||||||
@ -291,8 +291,6 @@ export default {
|
|||||||
value = this.roleDatas
|
value = this.roleDatas
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
callback(new Error('请选择至少一个角色'))
|
callback(new Error('请选择至少一个角色'))
|
||||||
} else if (value.length > 1) {
|
|
||||||
callback(new Error('只能选择一个角色'))
|
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
|
98
eladmin-web/src/views/tools/aliPay/config.vue
Normal file
98
eladmin-web/src/views/tools/aliPay/config.vue
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="100px">
|
||||||
|
<el-form-item label="appID" prop="appId">
|
||||||
|
<el-input v-model="form.appId" style="width: 40%" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">应用APPID,收款账号既是APPID对应支付宝账号</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商家账号" prop="sysServiceProviderId">
|
||||||
|
<el-input v-model="form.sysServiceProviderId" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">商家账号</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商户私钥" prop="privateKey">
|
||||||
|
<el-input v-model="form.privateKey" type="password" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">商户私钥,你的PKCS8格式RSA2私钥</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付宝公钥" prop="publicKey">
|
||||||
|
<el-input v-model="form.publicKey" type="password" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">支付宝公钥</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="回调地址" prop="returnUrl">
|
||||||
|
<el-input v-model="form.returnUrl" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">订单完成后返回的地址</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="异步通知" prop="notifyUrl">
|
||||||
|
<el-input v-model="form.notifyUrl" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">支付结果异步通知地址</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="">
|
||||||
|
<el-button :loading="loading" size="medium" type="primary" @click="doSubmit">保存配置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { get, update } from '@/api/tools/alipay'
|
||||||
|
export default {
|
||||||
|
name: 'Config',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
form: { appId: '', sysServiceProviderId: '', privateKey: '', publicKey: '', returnUrl: '', notifyUrl: '' },
|
||||||
|
rules: {
|
||||||
|
appId: [
|
||||||
|
{ required: true, message: '请输入appID', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
sysServiceProviderId: [
|
||||||
|
{ required: true, message: '请输入商家账号', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
privateKey: [
|
||||||
|
{ required: true, message: '商户私钥不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
publicKey: [
|
||||||
|
{ required: true, message: '支付宝公钥不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
returnUrl: [
|
||||||
|
{ required: true, message: '回调地址不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
notifyUrl: [
|
||||||
|
{ required: true, message: '回调地址不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
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.loading = false
|
||||||
|
}).catch(err => {
|
||||||
|
this.loading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
48
eladmin-web/src/views/tools/aliPay/index.vue
Normal file
48
eladmin-web/src/views/tools/aliPay/index.vue
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<el-tabs v-model="activeName" style="padding-left: 5px;">
|
||||||
|
<el-tab-pane label="参数配置" name="first">
|
||||||
|
<Config />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="支付测试" name="second">
|
||||||
|
<ToPay />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="使用说明" name="third">
|
||||||
|
<div>
|
||||||
|
<blockquote class="my-blockquote">注意</blockquote>
|
||||||
|
<pre class="my-code">
|
||||||
|
测试所用参数都是沙箱环境,仅供测试使用,申请地址:<a style="color: #00a0e9" href="https://openhome.alipay.com/platform/appDaily.htm?tab=info" target="_blank">支付宝开发平台</a>
|
||||||
|
如需付款测试,请使用
|
||||||
|
账号:uuxesw9745@sandbox.com
|
||||||
|
密码与支付密码:111111</pre>
|
||||||
|
<blockquote class="my-blockquote"> 支付设置</blockquote>
|
||||||
|
<pre class="my-code">
|
||||||
|
// 支付提供两个接口,
|
||||||
|
// PC端与手机端,并且在前端使用代码识别
|
||||||
|
if (/(Android)/i.test(navigator.userAgent)){ // 判断是否为Android手机
|
||||||
|
url = "/aliPay/toPayAsWeb"
|
||||||
|
}else if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){ // 判断是否为苹果手机
|
||||||
|
url = "/aliPay/toPayAsWeb"
|
||||||
|
} else {
|
||||||
|
url = "/aliPay/toPayAsPC"
|
||||||
|
}</pre>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Config from './config'
|
||||||
|
import ToPay from './toPay'
|
||||||
|
export default {
|
||||||
|
name: 'AliPay',
|
||||||
|
components: { Config, ToPay },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeName: 'second'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
86
eladmin-web/src/views/tools/aliPay/toPay.vue
Normal file
86
eladmin-web/src/views/tools/aliPay/toPay.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="90px">
|
||||||
|
<el-form-item label="商品名称" prop="subject">
|
||||||
|
<el-input v-model="form.subject" style="width: 35%" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品价格" prop="totalAmount">
|
||||||
|
<el-input v-model="form.totalAmount" style="width: 35%" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">测试允许区间(0,5000]</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品描述" prop="body">
|
||||||
|
<el-input v-model="form.body" style="width: 35%" rows="8" type="textarea" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="">
|
||||||
|
<el-button :loading="loading" size="medium" type="primary" @click="doSubmit">去支付</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { toAliPay } from '@/api/tools/alipay'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
url: '',
|
||||||
|
// 新窗口的引用
|
||||||
|
newWin: null,
|
||||||
|
loading: false, form: { subject: '', totalAmount: '', body: '' },
|
||||||
|
rules: {
|
||||||
|
subject: [
|
||||||
|
{ required: true, message: '商品名称不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
totalAmount: [
|
||||||
|
{ required: true, message: '商品价格不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
body: [
|
||||||
|
{ required: true, message: '商品描述不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
url(newVal, oldVal) {
|
||||||
|
if (newVal && this.newWin) {
|
||||||
|
this.newWin.sessionStorage.clear()
|
||||||
|
this.newWin.location.href = newVal
|
||||||
|
// 重定向后把url和newWin重置
|
||||||
|
this.url = ''
|
||||||
|
this.newWin = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doSubmit() {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.loading = true
|
||||||
|
// 先打开一个空的新窗口,再请求
|
||||||
|
this.newWin = window.open()
|
||||||
|
let url = ''
|
||||||
|
if (/(Android)/i.test(navigator.userAgent)) { // 判断是否为Android手机
|
||||||
|
url = 'aliPay/toPayAsWeb'
|
||||||
|
} else if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { // 判断是否为苹果手机
|
||||||
|
url = 'aliPay/toPayAsWeb'
|
||||||
|
} else {
|
||||||
|
url = 'aliPay/toPayAsPC'
|
||||||
|
}
|
||||||
|
toAliPay(url, this.form).then(res => {
|
||||||
|
this.loading = false
|
||||||
|
this.url = res
|
||||||
|
}).catch(err => {
|
||||||
|
this.loading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
91
eladmin-web/src/views/tools/email/config.vue
Normal file
91
eladmin-web/src/views/tools/email/config.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="100px">
|
||||||
|
<el-form-item label="发件人邮箱" prop="fromUser">
|
||||||
|
<el-input v-model="form.fromUser" style="width: 40%" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">Sender mailbox</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="发件用户名" prop="user">
|
||||||
|
<el-input v-model="form.user" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">Sender usernamex</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="邮箱密码" prop="pass">
|
||||||
|
<el-input v-model="form.pass" type="password" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">email Password</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="SMTP地址" prop="host">
|
||||||
|
<el-input v-model="form.host" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">SMTP address</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="SMTP端口" prop="port">
|
||||||
|
<el-input v-model="form.port" style="width: 40%;" />
|
||||||
|
<span style="color: #C0C0C0;margin-left: 10px;">SMTP port</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="">
|
||||||
|
<el-button :loading="loading" size="medium" type="primary" @click="doSubmit">保存配置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { get, update } from '@/api/tools/email'
|
||||||
|
export default {
|
||||||
|
name: 'Config',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false, form: { id: 1, fromUser: '', user: '', pass: '', host: '', port: '', sslEnable: '' },
|
||||||
|
rules: {
|
||||||
|
fromUser: [
|
||||||
|
{ required: true, message: '请输入发件人邮箱', trigger: 'blur' },
|
||||||
|
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
user: [
|
||||||
|
{ required: true, message: '请输入发件用户名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
pass: [
|
||||||
|
{ required: true, message: '密码不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
host: [
|
||||||
|
{ required: true, message: 'SMTP地址不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
port: [
|
||||||
|
{ required: true, message: 'SMTP端口不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
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.loading = false
|
||||||
|
}).catch(err => {
|
||||||
|
this.loading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
41
eladmin-web/src/views/tools/email/index.vue
Normal file
41
eladmin-web/src/views/tools/email/index.vue
Normal file
@ -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>
|
98
eladmin-web/src/views/tools/email/send.vue
Normal file
98
eladmin-web/src/views/tools/email/send.vue
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="100px">
|
||||||
|
<el-form-item label="邮件标题" prop="subject">
|
||||||
|
<el-input v-model="form.subject" style="width: 646px" placeholder="请输入邮件标题,标题不能为空" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="收件地址" prop="tos">
|
||||||
|
<el-input v-model="form.tos" style="width: 646px" placeholder="请输入收件地址,多个地址英文逗号,隔开" />
|
||||||
|
</el-form-item>
|
||||||
|
<div ref="editor" class="editor" />
|
||||||
|
<el-button :loading="loading" style="margin-left:1.6%;margin-bottom: 30px" size="medium" type="primary" @click="doSubmit">发送邮件</el-button>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { send } from '@/api/tools/email'
|
||||||
|
import { upload } from '@/utils/upload'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import E from 'wangeditor'
|
||||||
|
export default {
|
||||||
|
name: 'Index',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false, form: { subject: '', tos: '', content: '' },
|
||||||
|
rules: {
|
||||||
|
subject: [
|
||||||
|
{ required: true, message: '标题不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
tos: [
|
||||||
|
{ required: true, message: '收件人不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'imagesUploadApi',
|
||||||
|
'baseApi'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const _this = this
|
||||||
|
var editor = new E(this.$refs.editor)
|
||||||
|
// 自定义菜单配置
|
||||||
|
editor.config.zIndex = 10
|
||||||
|
// 文件上传
|
||||||
|
editor.config.customUploadImg = function(files, insert) {
|
||||||
|
// files 是 input 中选中的文件列表
|
||||||
|
// insert 是获取图片 url 后,插入到编辑器的方法
|
||||||
|
files.forEach(image => {
|
||||||
|
upload(_this.imagesUploadApi, image).then(res => {
|
||||||
|
const data = res.data
|
||||||
|
const url = _this.baseApi + '/file/' + data.type + '/' + data.realName
|
||||||
|
insert(url)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
editor.config.onchange = (html) => {
|
||||||
|
this.form.content = html
|
||||||
|
}
|
||||||
|
editor.create()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doSubmit() {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.loading = true
|
||||||
|
send(this.form).then(res => {
|
||||||
|
this.$notify({
|
||||||
|
title: '发送成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2500
|
||||||
|
})
|
||||||
|
this.loading = false
|
||||||
|
}).catch(err => {
|
||||||
|
this.loading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.editor{
|
||||||
|
text-align:left;
|
||||||
|
margin: 20px;
|
||||||
|
width: 730px;
|
||||||
|
}
|
||||||
|
::v-deep .w-e-text-container {
|
||||||
|
height: 360px !important;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,19 +3,18 @@
|
|||||||
<el-tab-pane label="本地存储" name="first">
|
<el-tab-pane label="本地存储" name="first">
|
||||||
<Local ref="local" />
|
<Local ref="local" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!-- <el-tab-pane label="七牛云存储" name="second">-->
|
<el-tab-pane label="七牛云存储" name="second">
|
||||||
<!-- <QiNiu ref="qiNiu" />-->
|
<QiNiu ref="qiNiu" />
|
||||||
<!-- </el-tab-pane>-->
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// import QiNiu from './qiniu/index'
|
import QiNiu from './qiniu/index'
|
||||||
import Local from './local/index'
|
import Local from './local/index'
|
||||||
export default {
|
export default {
|
||||||
name: 'Storage',
|
name: 'Storage',
|
||||||
components: { Local },
|
components: { QiNiu, Local },
|
||||||
// components: { QiNiu, Local },
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeName: 'first'
|
activeName: 'first'
|
||||||
|
98
eladmin-web/src/views/tools/storage/qiniu/form.vue
Normal file
98
eladmin-web/src/views/tools/storage/qiniu/form.vue
Normal file
@ -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>
|
189
eladmin-web/src/views/tools/storage/qiniu/index.vue
Normal file
189
eladmin-web/src/views/tools/storage/qiniu/index.vue
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container" style="padding: 8px;">
|
||||||
|
<!--表单组件-->
|
||||||
|
<eForm ref="form" />
|
||||||
|
<!-- 工具栏 -->
|
||||||
|
<div class="head-container">
|
||||||
|
<div v-if="crud.props.searchToggle">
|
||||||
|
<!-- 搜索 -->
|
||||||
|
<el-input v-model="query.key" 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">
|
||||||
|
<template slot="left">
|
||||||
|
<!-- 上传 -->
|
||||||
|
<el-button class="filter-item" size="mini" type="primary" icon="el-icon-upload" @click="dialog = true">上传</el-button>
|
||||||
|
<!-- 同步 -->
|
||||||
|
<el-button :icon="icon" class="filter-item" size="mini" type="warning" @click="synchronize">同步</el-button>
|
||||||
|
<!-- 配置 -->
|
||||||
|
<el-button
|
||||||
|
class="filter-item"
|
||||||
|
size="mini"
|
||||||
|
type="success"
|
||||||
|
icon="el-icon-s-tools"
|
||||||
|
@click="doConfig"
|
||||||
|
>配置</el-button>
|
||||||
|
</template>
|
||||||
|
</crudOperation>
|
||||||
|
<!-- 文件上传 -->
|
||||||
|
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" append-to-body width="500px" @close="doSubmit">
|
||||||
|
<el-upload
|
||||||
|
:before-remove="handleBeforeRemove"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:file-list="fileList"
|
||||||
|
:headers="headers"
|
||||||
|
:action="qiNiuUploadApi"
|
||||||
|
class="upload-demo"
|
||||||
|
multiple
|
||||||
|
>
|
||||||
|
<el-button size="small" type="primary">点击上传</el-button>
|
||||||
|
<div slot="tip" style="display: block;" class="el-upload__tip">请勿上传违法文件,且文件不超过15M</div>
|
||||||
|
</el-upload>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="doSubmit">确认</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 type="selection" width="55" />
|
||||||
|
<el-table-column prop="name" :show-overflow-tooltip="true" label="文件名">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<a href="JavaScript:" class="el-link el-link--primary" target="_blank" type="primary" @click="download(scope.row.id)">{{ scope.row.key }}</a>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :show-overflow-tooltip="true" prop="suffix" label="文件类型" @selection-change="crud.selectionChangeHandler" />
|
||||||
|
<el-table-column prop="bucket" label="空间名称" />
|
||||||
|
<el-table-column prop="size" label="文件大小" />
|
||||||
|
<el-table-column prop="type" label="空间类型" />
|
||||||
|
<el-table-column prop="updateTime" label="创建日期" />
|
||||||
|
</el-table>
|
||||||
|
<!--分页组件-->
|
||||||
|
<pagination />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import crudQiNiu from '@/api/tools/qiniu'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
import eForm from './form'
|
||||||
|
import CRUD, { presenter, header, 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'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { eForm, pagination, crudOperation, rrOperation, DateRangePicker },
|
||||||
|
cruds() {
|
||||||
|
return CRUD({ title: '七牛云文件', url: 'api/qiNiuContent', crudMethod: { ...crudQiNiu }})
|
||||||
|
},
|
||||||
|
mixins: [presenter(), header(), crud()],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
permission: {
|
||||||
|
del: ['admin', 'storage:del']
|
||||||
|
},
|
||||||
|
title: '文件', dialog: false,
|
||||||
|
icon: 'el-icon-refresh',
|
||||||
|
url: '', headers: { 'Authorization': getToken() },
|
||||||
|
dialogImageUrl: '', dialogVisible: false, fileList: [], files: [], newWin: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'qiNiuUploadApi'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
url(newVal, oldVal) {
|
||||||
|
if (newVal && this.newWin) {
|
||||||
|
this.newWin.sessionStorage.clear()
|
||||||
|
this.newWin.location.href = newVal
|
||||||
|
// 重定向后把url和newWin重置
|
||||||
|
this.url = ''
|
||||||
|
this.newWin = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.crud.optShow.add = false
|
||||||
|
this.crud.optShow.edit = false
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 七牛云配置
|
||||||
|
doConfig() {
|
||||||
|
const _this = this.$refs.form
|
||||||
|
_this.init()
|
||||||
|
_this.dialog = true
|
||||||
|
},
|
||||||
|
handleSuccess(response, file, fileList) {
|
||||||
|
const uid = file.uid
|
||||||
|
const id = response.id
|
||||||
|
this.files.push({ uid, id })
|
||||||
|
},
|
||||||
|
handleBeforeRemove(file, fileList) {
|
||||||
|
for (let i = 0; i < this.files.length; i++) {
|
||||||
|
if (this.files[i].uid === file.uid) {
|
||||||
|
crudQiNiu.del([this.files[i].id]).then(res => {})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handlePictureCardPreview(file) {
|
||||||
|
this.dialogImageUrl = file.url
|
||||||
|
this.dialogVisible = true
|
||||||
|
},
|
||||||
|
// 刷新列表数据
|
||||||
|
doSubmit() {
|
||||||
|
this.fileList = []
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.dialogImageUrl = ''
|
||||||
|
this.dialog = false
|
||||||
|
this.crud.toQuery()
|
||||||
|
},
|
||||||
|
// 监听上传失败
|
||||||
|
handleError(e, file, fileList) {
|
||||||
|
const msg = JSON.parse(e.message)
|
||||||
|
this.crud.notify(msg.message, CRUD.NOTIFICATION_TYPE.ERROR)
|
||||||
|
},
|
||||||
|
// 下载文件
|
||||||
|
download(id) {
|
||||||
|
this.downloadLoading = true
|
||||||
|
// 先打开一个空的新窗口,再请求
|
||||||
|
this.newWin = window.open()
|
||||||
|
crudQiNiu.download(id).then(res => {
|
||||||
|
this.downloadLoading = false
|
||||||
|
this.url = res.url
|
||||||
|
}).catch(err => {
|
||||||
|
this.downloadLoading = false
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 同步数据
|
||||||
|
synchronize() {
|
||||||
|
this.icon = 'el-icon-loading'
|
||||||
|
crudQiNiu.sync().then(res => {
|
||||||
|
this.icon = 'el-icon-refresh'
|
||||||
|
this.$message({
|
||||||
|
showClose: true,
|
||||||
|
message: '数据同步成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
this.crud.toQuery()
|
||||||
|
}).catch(err => {
|
||||||
|
this.icon = 'el-icon-refresh'
|
||||||
|
console.log(err.response.data.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -176,7 +176,7 @@ 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
|
the same "printed page" as the copyright notice for easier identification within
|
||||||
third-party archives.
|
third-party archives.
|
||||||
|
|
||||||
Copyright 2019-2025 Tz
|
Copyright 2019-2025 Zheng Jie
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -1,17 +1,26 @@
|
|||||||
<h1 style="text-align: center">区块链医疗数据共享平台管理</h1>
|
<h1 style="text-align: center">ELADMIN 后台管理系统</h1>
|
||||||
|
|
||||||
#### 项目简介
|
#### 项目简介
|
||||||
一个基于 Spring Boot 2.7.18 、 Mybatis-Plus、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统
|
一个基于 Spring Boot 2.7.18 、 Mybatis-Plus、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统
|
||||||
|
|
||||||
|
**开发文档:** [https://eladmin.vip](https://eladmin.vip)
|
||||||
|
|
||||||
|
**体验地址:** [https://eladmin.vip/demo](https://eladmin.vip/demo)
|
||||||
|
|
||||||
**账号密码:** `admin / 123456`
|
**账号密码:** `admin / 123456`
|
||||||
|
|
||||||
#### 项目结构
|
#### 项目源码
|
||||||
项目采用按功能分模块的开发方式,结构如下
|
|
||||||
|
|
||||||
- `eladmin-common` 为系统的公共模块,各种工具类,公共配置存在该模块
|
| github | gitee |
|
||||||
|
|--------------------------------------| --- |
|
||||||
|
| https://github.com/elunez/eladmin-mp | https://gitee.com/elunez/eladmin-mp |
|
||||||
|
|
||||||
- `eladmin-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
|
#### VPS推荐
|
||||||
|
<a href="https://bwh81.net/aff.php?aff=70876" target="_blank">
|
||||||
|
<img src="https://eladmin.vip/images/banner/side.jpeg" style="width: 435px;border-radius: 2px;" alt="帮瓦工">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
使用优惠码: `BWHNCXNVXV`,可获得 6.81% 的折扣, [查看介绍](https://eladmin.vip/pages/040101/)
|
||||||
#### 主要特性
|
#### 主要特性
|
||||||
- 使用最新技术栈,社区资源丰富。
|
- 使用最新技术栈,社区资源丰富。
|
||||||
- 高效率开发,代码生成器可一键生成前后端代码
|
- 高效率开发,代码生成器可一键生成前后端代码
|
||||||
@ -32,7 +41,14 @@
|
|||||||
- 岗位管理:配置各个部门的职位
|
- 岗位管理:配置各个部门的职位
|
||||||
- 字典管理:可维护常用一些固定的数据,如:状态,性别等
|
- 字典管理:可维护常用一些固定的数据,如:状态,性别等
|
||||||
- 系统日志:记录用户操作日志与异常日志,方便开发人员定位排错
|
- 系统日志:记录用户操作日志与异常日志,方便开发人员定位排错
|
||||||
- 档案管理:医院对用户档案的隐私保护和档案上链追溯管理,授权查看等权限限制
|
- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456
|
||||||
|
- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然
|
||||||
|
- 代码生成:高灵活度生成前后端代码,减少大量重复的工作任务
|
||||||
|
- 邮件工具:配合富文本,发送html格式的邮件
|
||||||
|
- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据
|
||||||
|
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
|
||||||
|
- 服务监控:监控服务器的负载情况
|
||||||
|
- 运维管理:一键部署你的应用
|
||||||
|
|
||||||
#### 项目结构
|
#### 项目结构
|
||||||
项目采用按功能分模块的开发方式,结构如下
|
项目采用按功能分模块的开发方式,结构如下
|
||||||
@ -41,6 +57,12 @@
|
|||||||
|
|
||||||
- `eladmin-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
|
- `eladmin-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
|
||||||
|
|
||||||
|
- `eladmin-logging` 为系统的日志模块,其他模块如果需要记录日志需要引入该模块
|
||||||
|
|
||||||
|
- `eladmin-tools` 为第三方工具模块,包含:邮件、七牛云存储、本地存储、支付宝
|
||||||
|
|
||||||
|
- `eladmin-generator` 为系统的代码生成模块,支持生成前后端CRUD代码
|
||||||
|
|
||||||
#### 详细结构
|
#### 详细结构
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -67,4 +89,26 @@
|
|||||||
- sysrunner 程序启动后处理数据
|
- sysrunner 程序启动后处理数据
|
||||||
- modules 系统相关模块(登录授权、系统监控、定时任务、系统模块、运维模块)
|
- modules 系统相关模块(登录授权、系统监控、定时任务、系统模块、运维模块)
|
||||||
- eladmin-logging 系统日志模块
|
- eladmin-logging 系统日志模块
|
||||||
```
|
- eladmin-tools 系统第三方工具模块
|
||||||
|
- email 邮件工具
|
||||||
|
- qiniu 七牛云存储工具
|
||||||
|
- alipay 支付宝支付工具
|
||||||
|
- local-storage 本地存储工具
|
||||||
|
- eladmin-generator 系统代码生成模块
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 特别鸣谢
|
||||||
|
|
||||||
|
- 感谢 [PanJiaChen](https://github.com/PanJiaChen/vue-element-admin) 大佬提供的前端模板
|
||||||
|
|
||||||
|
- 感谢 [Moxun](https://github.com/moxun1639) 大佬提供的前端 Curd 通用组件
|
||||||
|
|
||||||
|
- 感谢 [zhy6599](https://gitee.com/zhy6599) 大佬提供的后端运维管理相关功能
|
||||||
|
|
||||||
|
- 感谢 [j.yao.SUSE](https://github.com/everhopingandwaiting) 大佬提供的匿名接口与Redis限流等功能
|
||||||
|
|
||||||
|
#### 项目捐赠
|
||||||
|
项目的发展离不开你的支持,请作者喝杯咖啡吧☕ [Donate](https://eladmin.vip/pages/030101/)
|
||||||
|
|
||||||
|
#### 反馈交流
|
||||||
|
- QQ交流群:891137268 、947578238、659622532
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -30,7 +30,7 @@ import java.sql.Timestamp;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用字段, is_del 根据需求自行添加
|
* 通用字段, is_del 根据需求自行添加
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2019年10月24日20:46:32
|
* @date 2019年10月24日20:46:32
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -26,7 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建自定义的线程池
|
* 创建自定义的线程池
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description
|
* @description
|
||||||
* @date 2023-06-08
|
* @date 2023-06-08
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,7 +23,7 @@ import java.util.List;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
*/
|
*/
|
||||||
@Service(value = "el")
|
@Service(value = "el")
|
||||||
public class AuthorityConfig {
|
public class AuthorityConfig {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,8 +20,6 @@ import com.alibaba.fastjson2.JSONFactory;
|
|||||||
import com.alibaba.fastjson2.JSONWriter;
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.codec.digest.MurmurHash3;
|
import org.apache.commons.codec.digest.MurmurHash3;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
|
||||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
@ -44,13 +42,12 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2025-01-13
|
* @date 2025-01-13
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
@AutoConfigureBefore(RedisAutoConfiguration.class)
|
|
||||||
public class RedisConfiguration extends CachingConfigurerSupport {
|
public class RedisConfiguration extends CachingConfigurerSupport {
|
||||||
|
|
||||||
// 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
// 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||||
|
@ -6,14 +6,11 @@ import org.redisson.Redisson;
|
|||||||
import org.redisson.api.RedissonClient;
|
import org.redisson.api.RedissonClient;
|
||||||
import org.redisson.config.Config;
|
import org.redisson.config.Config;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
|
||||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@AutoConfigureBefore(RedisAutoConfiguration.class)
|
|
||||||
public class RedissonConfiguration {
|
public class RedissonConfiguration {
|
||||||
|
|
||||||
@Value("${spring.redis.host}")
|
@Value("${spring.redis.host}")
|
||||||
|
@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description
|
* @description
|
||||||
* @date 2025-01-11
|
* @date 2025-01-11
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,7 +20,7 @@ import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description 自定义 p6spy sql输出格式
|
* @description 自定义 p6spy sql输出格式
|
||||||
* @date 2024-12-26
|
* @date 2024-12-26
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,7 +23,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description
|
* @description
|
||||||
* @date 2023-06-13
|
* @date 2023-06-13
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,7 +22,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description
|
* @description
|
||||||
* @date 2023-06-12
|
* @date 2023-06-12
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,7 +21,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,7 +20,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @website <a href="https://eladmin.vip">...</a>
|
* @website <a href="https://eladmin.vip">...</a>
|
||||||
* @description
|
* @description
|
||||||
* @date 2020-05-18
|
* @date 2020-05-18
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -37,7 +37,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* WebMvcConfigurer
|
* WebMvcConfigurer
|
||||||
*
|
*
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-30
|
* @date 2018-11-30
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2023 Tz
|
* Copyright 2019-2023 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -47,7 +47,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* api页面 /doc.html
|
* api页面 /doc.html
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,7 +20,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author ZhangHouYing
|
||||||
* @date 2019-08-24 15:44
|
* @date 2019-08-24 15:44
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,7 +20,7 @@ import org.springframework.http.HttpStatus;
|
|||||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
* 统一异常处理
|
* 统一异常处理
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,7 +18,7 @@ package me.zhengjie.exception;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
public class EntityExistException extends RuntimeException {
|
public class EntityExistException extends RuntimeException {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,7 +18,7 @@ package me.zhengjie.exception;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
public class EntityNotFoundException extends RuntimeException {
|
public class EntityNotFoundException extends RuntimeException {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,7 +18,7 @@ package me.zhengjie.exception.handler;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -31,7 +31,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|||||||
import static org.springframework.http.HttpStatus.*;
|
import static org.springframework.http.HttpStatus.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -25,7 +25,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description 匿名标记工具
|
* @description 匿名标记工具
|
||||||
* @date 2025-01-13
|
* @date 2025-01-13
|
||||||
**/
|
**/
|
||||||
|
@ -19,7 +19,7 @@ import java.math.BigDecimal;
|
|||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description 计算类
|
* @description 计算类
|
||||||
* @date 2024-12-27
|
* @date 2024-12-27
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,7 +18,7 @@ package me.zhengjie.utils;
|
|||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @description 用于关闭各种连接,缺啥补啥
|
* @description 用于关闭各种连接,缺啥补啥
|
||||||
* @date 2021-03-05
|
* @date 2021-03-05
|
||||||
**/
|
**/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,7 +18,7 @@ package me.zhengjie.utils;
|
|||||||
/**
|
/**
|
||||||
* 常用静态常量
|
* 常用静态常量
|
||||||
*
|
*
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-12-26
|
* @date 2018-12-26
|
||||||
*/
|
*/
|
||||||
public class ElConstant {
|
public class ElConstant {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -24,7 +24,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密
|
* 加密
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
public class EncryptUtils {
|
public class EncryptUtils {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -38,7 +38,7 @@ import java.util.stream.Collectors;
|
|||||||
/**
|
/**
|
||||||
* File工具类,扩展 hutool 工具包
|
* File工具类,扩展 hutool 工具包
|
||||||
*
|
*
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-12-27
|
* @date 2018-12-27
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -213,7 +213,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
|||||||
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
|
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
|
||||||
// 处理数据以防止CSV注入
|
// 处理数据以防止CSV注入
|
||||||
List<Map<String, Object>> sanitizedList = list.parallelStream().map(map -> {
|
List<Map<String, Object>> sanitizedList = list.parallelStream().map(map -> {
|
||||||
Map<String, Object> sanitizedMap = new LinkedHashMap<>();
|
Map<String, Object> sanitizedMap = new HashMap<>();
|
||||||
map.forEach((key, value) -> {
|
map.forEach((key, value) -> {
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
String strValue = (String) value;
|
String strValue = (String) value;
|
||||||
|
@ -6,7 +6,7 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页结果封装类
|
* 分页结果封装类
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
* @param <T>
|
* @param <T>
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,7 +20,7 @@ import java.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页工具
|
* 分页工具
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-12-10
|
* @date 2018-12-10
|
||||||
*/
|
*/
|
||||||
public class PageUtil extends cn.hutool.core.util.PageUtil {
|
public class PageUtil extends cn.hutool.core.util.PageUtil {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,7 +22,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 HttpServletRequest
|
* 获取 HttpServletRequest
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2018-11-24
|
* @date 2018-11-24
|
||||||
*/
|
*/
|
||||||
public class RequestHolder {
|
public class RequestHolder {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -35,7 +35,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前登录的用户
|
* 获取当前登录的用户
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2019-01-17
|
* @date 2019-01-17
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -28,7 +28,7 @@ import java.net.UnknownHostException;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
|
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,7 +20,7 @@ import java.io.StringWriter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 异常工具 2019-01-06
|
* 异常工具 2019-01-06
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
*/
|
*/
|
||||||
public class ThrowableUtil {
|
public class ThrowableUtil {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,7 +22,7 @@ import lombok.Getter;
|
|||||||
* <p>
|
* <p>
|
||||||
* 验证码业务场景
|
* 验证码业务场景
|
||||||
* </p>
|
* </p>
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2020-05-02
|
* @date 2020-05-02
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,7 +22,7 @@ import lombok.Getter;
|
|||||||
* <p>
|
* <p>
|
||||||
* 验证码业务场景对应的 Redis 中的 key
|
* 验证码业务场景对应的 Redis 中的 key
|
||||||
* </p>
|
* </p>
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2020-05-02
|
* @date 2020-05-02
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,7 +22,7 @@ import lombok.Getter;
|
|||||||
* <p>
|
* <p>
|
||||||
* 数据权限枚举
|
* 数据权限枚举
|
||||||
* </p>
|
* </p>
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2020-05-07
|
* @date 2020-05-07
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -19,7 +19,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @website https://eladmin.vip
|
* @website https://eladmin.vip
|
||||||
* @description
|
* @description
|
||||||
* @date 2020-06-10
|
* @date 2020-06-10
|
||||||
|
37
eladmin/eladmin-generator/pom.xml
Normal file
37
eladmin/eladmin-generator/pom.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>eladmin</artifactId>
|
||||||
|
<groupId>me.zhengjie</groupId>
|
||||||
|
<version>1.1</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>eladmin-generator</artifactId>
|
||||||
|
<name>代码生成模块</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<configuration.version>1.10</configuration.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.zhengjie</groupId>
|
||||||
|
<artifactId>eladmin-common</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--模板引擎-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/commons-configuration/commons-configuration -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-configuration</groupId>
|
||||||
|
<artifactId>commons-configuration</artifactId>
|
||||||
|
<version>${configuration.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列的数据信息
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-02
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("code_column")
|
||||||
|
public class ColumnInfo implements Serializable {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "ID", hidden = true)
|
||||||
|
@TableId(value = "column_id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "表名")
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "数据库字段名称")
|
||||||
|
private String columnName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "数据库字段类型")
|
||||||
|
private String columnType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "数据库字段键类型")
|
||||||
|
private String keyType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "字段额外的参数")
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "数据库字段描述")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否必填")
|
||||||
|
private Boolean notNull;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否在列表显示")
|
||||||
|
private Boolean listShow = true;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否表单显示")
|
||||||
|
private Boolean formShow = true;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "表单类型")
|
||||||
|
private String formType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "查询 1:模糊 2:精确")
|
||||||
|
private String queryType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "字典名称")
|
||||||
|
private String dictName;
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码生成配置
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-03
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("code_config")
|
||||||
|
public class GenConfig implements Serializable {
|
||||||
|
|
||||||
|
public GenConfig(String tableName) {
|
||||||
|
this.tableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "ID", hidden = true)
|
||||||
|
@TableId(value = "config_id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@ApiModelProperty(value = "表名")
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "接口名称")
|
||||||
|
private String apiAlias;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@ApiModelProperty(value = "包路径")
|
||||||
|
private String pack;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@ApiModelProperty(value = "模块名")
|
||||||
|
private String moduleName;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@ApiModelProperty(value = "前端文件路径")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "前端文件路径")
|
||||||
|
private String apiPath;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "作者")
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "表前缀")
|
||||||
|
private String prefix;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否覆盖")
|
||||||
|
private Boolean cover = false;
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.domain.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表的数据信息
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TableInfo {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "表名称")
|
||||||
|
private Object tableName;
|
||||||
|
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@ApiModelProperty(value = "创建日期:yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Object createTime;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "数据库引擎")
|
||||||
|
private Object engine;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "编码集")
|
||||||
|
private Object coding;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private Object remark;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import me.zhengjie.domain.ColumnInfo;
|
||||||
|
import me.zhengjie.domain.dto.TableInfo;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2023-06-26
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ColumnInfoMapper extends BaseMapper<ColumnInfo> {
|
||||||
|
|
||||||
|
IPage<TableInfo> getTables(@Param("tableName") String tableName, Page<Object> page);
|
||||||
|
|
||||||
|
List<ColumnInfo> findByTableNameOrderByIdAsc(@Param("tableName") String tableName);
|
||||||
|
|
||||||
|
List<ColumnInfo> getColumns(@Param("tableName") String tableName);
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 Tz
|
* Copyright 2019-2025 Zheng Jie
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -13,25 +13,19 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package me.zhengjie.modules.system.mapper;
|
package me.zhengjie.mapper;
|
||||||
|
|
||||||
import me.zhengjie.modules.system.domain.dto.DashboardDataVo;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tz
|
* @author Zheng Jie
|
||||||
* @date 2023-06-19
|
* @date 2023-06-26
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface DashboardMapper {
|
public interface GenConfigMapper extends BaseMapper<GenConfig> {
|
||||||
|
|
||||||
List<DashboardDataVo> getCardData();
|
GenConfig findByTableName(@Param("tableName") String tableName);
|
||||||
|
}
|
||||||
List<DashboardDataVo> getLineChartData(@Param("type") String type);
|
|
||||||
|
|
||||||
List<DashboardDataVo> getPieChatData();
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.rest;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
|
import me.zhengjie.service.GenConfigService;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-14
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/api/genConfig")
|
||||||
|
@Api(tags = "系统:代码生成器配置管理")
|
||||||
|
public class GenConfigController {
|
||||||
|
|
||||||
|
private final GenConfigService genConfigService;
|
||||||
|
|
||||||
|
@ApiOperation("查询")
|
||||||
|
@GetMapping(value = "/{tableName}")
|
||||||
|
public ResponseEntity<GenConfig> queryGenConfig(@PathVariable String tableName){
|
||||||
|
return new ResponseEntity<>(genConfigService.find(tableName), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
@ApiOperation("修改")
|
||||||
|
public ResponseEntity<GenConfig> updateGenConfig(@Validated @RequestBody GenConfig genConfig){
|
||||||
|
return new ResponseEntity<>(genConfigService.update(genConfig.getTableName(), genConfig),HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.rest;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import me.zhengjie.domain.ColumnInfo;
|
||||||
|
import me.zhengjie.domain.dto.TableInfo;
|
||||||
|
import me.zhengjie.exception.BadRequestException;
|
||||||
|
import me.zhengjie.service.GenConfigService;
|
||||||
|
import me.zhengjie.service.GeneratorService;
|
||||||
|
import me.zhengjie.utils.PageResult;
|
||||||
|
import me.zhengjie.utils.PageUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-02
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/api/generator")
|
||||||
|
@Api(tags = "系统:代码生成管理")
|
||||||
|
public class GeneratorController {
|
||||||
|
|
||||||
|
private final GeneratorService generatorService;
|
||||||
|
private final GenConfigService genConfigService;
|
||||||
|
|
||||||
|
@Value("${generator.enabled}")
|
||||||
|
private Boolean generatorEnabled;
|
||||||
|
|
||||||
|
@ApiOperation("查询数据库数据")
|
||||||
|
@GetMapping(value = "/tables")
|
||||||
|
public ResponseEntity<PageResult<TableInfo>> queryTables(@RequestParam(defaultValue = "") String name, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size){
|
||||||
|
return new ResponseEntity<>(generatorService.getTables(name, new Page<>(page, size)), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("查询字段数据")
|
||||||
|
@GetMapping(value = "/columns")
|
||||||
|
public ResponseEntity<PageResult<ColumnInfo>> queryColumns(@RequestParam String tableName){
|
||||||
|
List<ColumnInfo> columnInfos = generatorService.getColumns(tableName);
|
||||||
|
return new ResponseEntity<>(PageUtil.toPage(columnInfos), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("保存字段数据")
|
||||||
|
@PutMapping
|
||||||
|
public ResponseEntity<HttpStatus> saveColumn(@RequestBody List<ColumnInfo> columnInfos){
|
||||||
|
generatorService.save(columnInfos);
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("同步字段数据")
|
||||||
|
@PostMapping(value = "sync")
|
||||||
|
public ResponseEntity<HttpStatus> syncColumn(@RequestBody List<String> tables){
|
||||||
|
for (String table : tables) {
|
||||||
|
generatorService.sync(generatorService.getColumns(table), generatorService.query(table));
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("生成代码")
|
||||||
|
@PostMapping(value = "/{tableName}/{type}")
|
||||||
|
public ResponseEntity<Object> generatorCode(@PathVariable String tableName, @PathVariable Integer type, HttpServletRequest request, HttpServletResponse response){
|
||||||
|
if(!generatorEnabled && type == 0){
|
||||||
|
throw new BadRequestException("此环境不允许生成代码,请选择预览或者下载查看!");
|
||||||
|
}
|
||||||
|
switch (type){
|
||||||
|
// 生成代码
|
||||||
|
case 0: generatorService.generator(genConfigService.find(tableName), generatorService.getColumns(tableName));
|
||||||
|
break;
|
||||||
|
// 预览
|
||||||
|
case 1: return generatorService.preview(genConfigService.find(tableName), generatorService.getColumns(tableName));
|
||||||
|
// 打包
|
||||||
|
case 2: generatorService.download(genConfigService.find(tableName), generatorService.getColumns(tableName), request, response);
|
||||||
|
break;
|
||||||
|
default: throw new BadRequestException("没有这个选项");
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-14
|
||||||
|
*/
|
||||||
|
public interface GenConfigService extends IService<GenConfig> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询表配置
|
||||||
|
* @param tableName 表名
|
||||||
|
* @return 表配置
|
||||||
|
*/
|
||||||
|
GenConfig find(String tableName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新表配置
|
||||||
|
* @param tableName 表名
|
||||||
|
* @param genConfig 表配置
|
||||||
|
* @return 表配置
|
||||||
|
*/
|
||||||
|
GenConfig update(String tableName, GenConfig genConfig);
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
|
import me.zhengjie.domain.ColumnInfo;
|
||||||
|
import me.zhengjie.domain.dto.TableInfo;
|
||||||
|
import me.zhengjie.utils.PageResult;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-02
|
||||||
|
*/
|
||||||
|
public interface GeneratorService extends IService<ColumnInfo> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据库元数据
|
||||||
|
*
|
||||||
|
* @param name 表名
|
||||||
|
* @param page 分页参数
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
PageResult<TableInfo> getTables(String name, Page<Object> page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到数据表的元数据
|
||||||
|
* @param name 表名
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
List<ColumnInfo> getColumns(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步表数据
|
||||||
|
* @param columnInfos /
|
||||||
|
* @param columnInfoList /
|
||||||
|
*/
|
||||||
|
void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保持数据
|
||||||
|
* @param columnInfos /
|
||||||
|
*/
|
||||||
|
void save(List<ColumnInfo> columnInfos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码生成
|
||||||
|
* @param genConfig 配置信息
|
||||||
|
* @param columns 字段信息
|
||||||
|
*/
|
||||||
|
void generator(GenConfig genConfig, List<ColumnInfo> columns);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预览
|
||||||
|
* @param genConfig 配置信息
|
||||||
|
* @param columns 字段信息
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打包下载
|
||||||
|
* @param genConfig 配置信息
|
||||||
|
* @param columns 字段信息
|
||||||
|
* @param request /
|
||||||
|
* @param response /
|
||||||
|
*/
|
||||||
|
void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据库的表字段数据数据
|
||||||
|
* @param table /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
List<ColumnInfo> query(String table);
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
|
import me.zhengjie.mapper.GenConfigMapper;
|
||||||
|
import me.zhengjie.service.GenConfigService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-14
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@SuppressWarnings({"unchecked","all"})
|
||||||
|
public class GenConfigServiceImpl extends ServiceImpl<GenConfigMapper, GenConfig> implements GenConfigService {
|
||||||
|
|
||||||
|
private final GenConfigMapper genConfigMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GenConfig find(String tableName) {
|
||||||
|
GenConfig genConfig = genConfigMapper.findByTableName(tableName);
|
||||||
|
if(genConfig == null){
|
||||||
|
return new GenConfig(tableName);
|
||||||
|
}
|
||||||
|
return genConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GenConfig update(String tableName, GenConfig genConfig) {
|
||||||
|
String separator = File.separator;
|
||||||
|
String[] paths;
|
||||||
|
String symbol = "\\";
|
||||||
|
if (symbol.equals(separator)) {
|
||||||
|
paths = genConfig.getPath().split("\\\\");
|
||||||
|
} else {
|
||||||
|
paths = genConfig.getPath().split(File.separator);
|
||||||
|
}
|
||||||
|
StringBuilder api = new StringBuilder();
|
||||||
|
for (String path : paths) {
|
||||||
|
api.append(path);
|
||||||
|
api.append(separator);
|
||||||
|
if ("src".equals(path)) {
|
||||||
|
api.append("api");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genConfig.setApiPath(api.toString());
|
||||||
|
saveOrUpdate(genConfig);
|
||||||
|
return genConfig;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.util.ZipUtil;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
|
import me.zhengjie.domain.ColumnInfo;
|
||||||
|
import me.zhengjie.domain.dto.TableInfo;
|
||||||
|
import me.zhengjie.exception.BadRequestException;
|
||||||
|
import me.zhengjie.mapper.ColumnInfoMapper;
|
||||||
|
import me.zhengjie.service.GeneratorService;
|
||||||
|
import me.zhengjie.utils.*;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-02
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GeneratorServiceImpl extends ServiceImpl<ColumnInfoMapper, ColumnInfo> implements GeneratorService {
|
||||||
|
|
||||||
|
private final ColumnInfoMapper columnInfoMapper;
|
||||||
|
private final String CONFIG_MESSAGE = "请先配置生成器";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<TableInfo> getTables(String name, Page<Object> page) {
|
||||||
|
return PageUtil.toPage(columnInfoMapper.getTables(name, page));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public List<ColumnInfo> getColumns(String tableName) {
|
||||||
|
List<ColumnInfo> columnInfos = columnInfoMapper.findByTableNameOrderByIdAsc(tableName);
|
||||||
|
if (CollectionUtil.isNotEmpty(columnInfos)) {
|
||||||
|
return columnInfos;
|
||||||
|
} else {
|
||||||
|
columnInfos = query(tableName);
|
||||||
|
saveBatch(columnInfos);
|
||||||
|
return columnInfos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ColumnInfo> query(String tableName) {
|
||||||
|
List<ColumnInfo> columnInfos = columnInfoMapper.getColumns(tableName);
|
||||||
|
for (ColumnInfo columnInfo : columnInfos) {
|
||||||
|
columnInfo.setTableName(tableName);
|
||||||
|
if(GenUtil.PK.equalsIgnoreCase(columnInfo.getKeyType())
|
||||||
|
&& GenUtil.EXTRA.equalsIgnoreCase(columnInfo.getExtra())){
|
||||||
|
columnInfo.setNotNull(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return columnInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList) {
|
||||||
|
// 第一种情况,数据库类字段改变或者新增字段
|
||||||
|
for (ColumnInfo columnInfo : columnInfoList) {
|
||||||
|
// 根据字段名称查找
|
||||||
|
List<ColumnInfo> columns = columnInfos.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList());
|
||||||
|
// 如果能找到,就修改部分可能被字段
|
||||||
|
if (CollectionUtil.isNotEmpty(columns)) {
|
||||||
|
ColumnInfo column = columns.get(0);
|
||||||
|
column.setColumnType(columnInfo.getColumnType());
|
||||||
|
column.setExtra(columnInfo.getExtra());
|
||||||
|
column.setKeyType(columnInfo.getKeyType());
|
||||||
|
if (StringUtils.isBlank(column.getRemark())) {
|
||||||
|
column.setRemark(columnInfo.getRemark());
|
||||||
|
}
|
||||||
|
saveOrUpdate(column);
|
||||||
|
} else {
|
||||||
|
// 如果找不到,则保存新字段信息
|
||||||
|
save(columnInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 第二种情况,数据库字段删除了
|
||||||
|
for (ColumnInfo columnInfo : columnInfos) {
|
||||||
|
// 根据字段名称查找
|
||||||
|
List<ColumnInfo> columns = columnInfoList.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList());
|
||||||
|
// 如果找不到,就代表字段被删除了,则需要删除该字段
|
||||||
|
if (CollectionUtil.isEmpty(columns)) {
|
||||||
|
removeById(columnInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void save(List<ColumnInfo> columnInfos) {
|
||||||
|
saveOrUpdateBatch(columnInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generator(GenConfig genConfig, List<ColumnInfo> columns) {
|
||||||
|
if (genConfig.getId() == null) {
|
||||||
|
throw new BadRequestException(CONFIG_MESSAGE);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
GenUtil.generatorCode(columns, genConfig);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw new BadRequestException("生成失败,请手动处理已生成的文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns) {
|
||||||
|
if (genConfig.getId() == null) {
|
||||||
|
throw new BadRequestException(CONFIG_MESSAGE);
|
||||||
|
}
|
||||||
|
List<Map<String, Object>> genList = GenUtil.preview(columns, genConfig);
|
||||||
|
return new ResponseEntity<>(genList, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
if (genConfig.getId() == null) {
|
||||||
|
throw new BadRequestException(CONFIG_MESSAGE);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
File file = new File(GenUtil.download(columns, genConfig));
|
||||||
|
String zipPath = file.getPath() + ".zip";
|
||||||
|
ZipUtil.zip(file.getPath(), zipPath);
|
||||||
|
FileUtil.downloadFile(request, response, new File(zipPath), true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new BadRequestException("打包失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.configuration.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql字段转java
|
||||||
|
*
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-03
|
||||||
|
*/
|
||||||
|
public class ColUtil {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ColUtil.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换mysql数据类型为java数据类型
|
||||||
|
*
|
||||||
|
* @param type 数据库字段类型
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
static String cloToJava(String type) {
|
||||||
|
Configuration config = getConfig();
|
||||||
|
assert config != null;
|
||||||
|
return config.getString(type, "unknowType");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置信息
|
||||||
|
*/
|
||||||
|
public static PropertiesConfiguration getConfig() {
|
||||||
|
try {
|
||||||
|
return new PropertiesConfiguration("gen.properties");
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package me.zhengjie.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.extra.template.*;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.zhengjie.domain.GenConfig;
|
||||||
|
import me.zhengjie.domain.ColumnInfo;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
import static me.zhengjie.utils.FileUtil.SYS_TEM_DIR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码生成
|
||||||
|
*
|
||||||
|
* @author Zheng Jie
|
||||||
|
* @date 2019-01-02
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({"unchecked", "all"})
|
||||||
|
public class GenUtil {
|
||||||
|
|
||||||
|
private static final String TIMESTAMP = "Timestamp";
|
||||||
|
|
||||||
|
private static final String BIGDECIMAL = "BigDecimal";
|
||||||
|
|
||||||
|
public static final String PK = "PRI";
|
||||||
|
|
||||||
|
public static final String EXTRA = "auto_increment";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后端代码模板名称
|
||||||
|
*
|
||||||
|
* @return List
|
||||||
|
*/
|
||||||
|
private static List<String> getAdminTemplateNames() {
|
||||||
|
List<String> templateNames = new ArrayList<>();
|
||||||
|
templateNames.add("Entity");
|
||||||
|
templateNames.add("Controller");
|
||||||
|
templateNames.add("QueryCriteria");
|
||||||
|
templateNames.add("Service");
|
||||||
|
templateNames.add("ServiceImpl");
|
||||||
|
templateNames.add("Mapper");
|
||||||
|
templateNames.add("Mapper-xml");
|
||||||
|
return templateNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取前端代码模板名称
|
||||||
|
*
|
||||||
|
* @return List
|
||||||
|
*/
|
||||||
|
private static List<String> getFrontTemplateNames() {
|
||||||
|
List<String> templateNames = new ArrayList<>();
|
||||||
|
templateNames.add("index");
|
||||||
|
templateNames.add("api");
|
||||||
|
return templateNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Map<String, Object>> preview(List<ColumnInfo> columns, GenConfig genConfig) {
|
||||||
|
Map<String, Object> genMap = getGenMap(columns, genConfig);
|
||||||
|
List<Map<String, Object>> genList = new ArrayList<>();
|
||||||
|
// 获取后端模版
|
||||||
|
List<String> templates = getAdminTemplateNames();
|
||||||
|
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
|
||||||
|
for (String templateName : templates) {
|
||||||
|
Map<String, Object> map = new HashMap<>(1);
|
||||||
|
Template template = engine.getTemplate("admin/" + templateName + ".ftl");
|
||||||
|
map.put("content", template.render(genMap));
|
||||||
|
map.put("name", templateName.replace("-xml", ".xml"));
|
||||||
|
genList.add(map);
|
||||||
|
}
|
||||||
|
// 获取前端模版
|
||||||
|
templates = getFrontTemplateNames();
|
||||||
|
for (String templateName : templates) {
|
||||||
|
Map<String, Object> map = new HashMap<>(1);
|
||||||
|
Template template = engine.getTemplate("front/" + templateName + ".ftl");
|
||||||
|
map.put(templateName, template.render(genMap));
|
||||||
|
map.put("content", template.render(genMap));
|
||||||
|
map.put("name", templateName);
|
||||||
|
genList.add(map);
|
||||||
|
}
|
||||||
|
return genList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String download(List<ColumnInfo> columns, GenConfig genConfig) throws IOException {
|
||||||
|
// 拼接的路径:/tmpeladmin-gen-temp/,这个路径在Linux下需要root用户才有权限创建,非root用户会权限错误而失败,更改为: /tmp/eladmin-gen-temp/
|
||||||
|
// String tempPath =SYS_TEM_DIR + "eladmin-gen-temp" + File.separator + genConfig.getTableName() + File.separator;
|
||||||
|
String tempPath = SYS_TEM_DIR + "eladmin-gen-temp" + File.separator + genConfig.getTableName() + File.separator;
|
||||||
|
Map<String, Object> genMap = getGenMap(columns, genConfig);
|
||||||
|
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
|
||||||
|
// 生成后端代码
|
||||||
|
List<String> templates = getAdminTemplateNames();
|
||||||
|
for (String templateName : templates) {
|
||||||
|
Template template = engine.getTemplate("admin/" + templateName + ".ftl");
|
||||||
|
String filePath = getAdminFilePath(templateName, genConfig, genMap.get("className").toString(), tempPath + "eladmin" + File.separator);
|
||||||
|
assert filePath != null;
|
||||||
|
File file = new File(filePath);
|
||||||
|
// 如果非覆盖生成
|
||||||
|
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 生成代码
|
||||||
|
genFile(file, template, genMap);
|
||||||
|
}
|
||||||
|
// 生成前端代码
|
||||||
|
templates = getFrontTemplateNames();
|
||||||
|
for (String templateName : templates) {
|
||||||
|
Template template = engine.getTemplate("front/" + templateName + ".ftl");
|
||||||
|
String path = tempPath + "eladmin-web" + File.separator;
|
||||||
|
String apiPath = path + "src" + File.separator + "api" + File.separator;
|
||||||
|
String srcPath = path + "src" + File.separator + "views" + File.separator + genMap.get("changeClassName").toString() + File.separator;
|
||||||
|
String filePath = getFrontFilePath(templateName, apiPath, srcPath, genMap.get("changeClassName").toString());
|
||||||
|
assert filePath != null;
|
||||||
|
File file = new File(filePath);
|
||||||
|
// 如果非覆盖生成
|
||||||
|
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 生成代码
|
||||||
|
genFile(file, template, genMap);
|
||||||
|
}
|
||||||
|
return tempPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig) throws IOException {
|
||||||
|
Map<String, Object> genMap = getGenMap(columnInfos, genConfig);
|
||||||
|
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
|
||||||
|
// 生成后端代码
|
||||||
|
List<String> templates = getAdminTemplateNames();
|
||||||
|
for (String templateName : templates) {
|
||||||
|
Template template = engine.getTemplate("admin/" + templateName + ".ftl");
|
||||||
|
String rootPath = System.getProperty("user.dir");
|
||||||
|
String filePath = getAdminFilePath(templateName, genConfig, genMap.get("className").toString(), rootPath);
|
||||||
|
|
||||||
|
assert filePath != null;
|
||||||
|
File file = new File(filePath);
|
||||||
|
|
||||||
|
// 如果非覆盖生成
|
||||||
|
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 生成代码
|
||||||
|
genFile(file, template, genMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成前端代码
|
||||||
|
templates = getFrontTemplateNames();
|
||||||
|
for (String templateName : templates) {
|
||||||
|
Template template = engine.getTemplate("front/" + templateName + ".ftl");
|
||||||
|
String filePath = getFrontFilePath(templateName, genConfig.getApiPath(), genConfig.getPath(), genMap.get("changeClassName").toString());
|
||||||
|
|
||||||
|
assert filePath != null;
|
||||||
|
File file = new File(filePath);
|
||||||
|
|
||||||
|
// 如果非覆盖生成
|
||||||
|
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 生成代码
|
||||||
|
genFile(file, template, genMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取模版数据
|
||||||
|
private static Map<String, Object> getGenMap(List<ColumnInfo> columnInfos, GenConfig genConfig) {
|
||||||
|
// 存储模版字段数据
|
||||||
|
Map<String, Object> genMap = new HashMap<>(16);
|
||||||
|
// 接口别名
|
||||||
|
genMap.put("apiAlias", genConfig.getApiAlias());
|
||||||
|
// 包名称
|
||||||
|
genMap.put("package", genConfig.getPack());
|
||||||
|
// 模块名称
|
||||||
|
genMap.put("moduleName", genConfig.getModuleName());
|
||||||
|
// 作者
|
||||||
|
genMap.put("author", genConfig.getAuthor());
|
||||||
|
// 创建日期
|
||||||
|
genMap.put("date", LocalDate.now().toString());
|
||||||
|
// 表名
|
||||||
|
genMap.put("tableName", genConfig.getTableName());
|
||||||
|
// 大写开头的类名
|
||||||
|
String className = StringUtils.toCapitalizeCamelCase(genConfig.getTableName());
|
||||||
|
// 小写开头的类名
|
||||||
|
String changeClassName = StringUtils.toCamelCase(genConfig.getTableName());
|
||||||
|
// 判断是否去除表前缀
|
||||||
|
if (StringUtils.isNotEmpty(genConfig.getPrefix())) {
|
||||||
|
className = StringUtils.toCapitalizeCamelCase(StrUtil.removePrefix(genConfig.getTableName(), genConfig.getPrefix()));
|
||||||
|
changeClassName = StringUtils.toCamelCase(StrUtil.removePrefix(genConfig.getTableName(), genConfig.getPrefix()));
|
||||||
|
changeClassName = StringUtils.uncapitalize(changeClassName);
|
||||||
|
}
|
||||||
|
// 保存类名
|
||||||
|
genMap.put("className", className);
|
||||||
|
// 保存小写开头的类名
|
||||||
|
genMap.put("changeClassName", changeClassName);
|
||||||
|
// 存在 Timestamp 字段
|
||||||
|
genMap.put("hasTimestamp", false);
|
||||||
|
// 查询类中存在 Timestamp 字段
|
||||||
|
genMap.put("queryHasTimestamp", false);
|
||||||
|
// 存在 BigDecimal 字段
|
||||||
|
genMap.put("hasBigDecimal", false);
|
||||||
|
// 查询类中存在 BigDecimal 字段
|
||||||
|
genMap.put("queryHasBigDecimal", false);
|
||||||
|
// 是否需要创建查询
|
||||||
|
genMap.put("hasQuery", false);
|
||||||
|
// 自增主键
|
||||||
|
genMap.put("auto", false);
|
||||||
|
// 存在字典
|
||||||
|
genMap.put("hasDict", false);
|
||||||
|
// 存在日期注解
|
||||||
|
genMap.put("hasDateAnnotation", false);
|
||||||
|
// 存储主键字段名
|
||||||
|
genMap.put("pkIdName", "none");
|
||||||
|
// 存储符号
|
||||||
|
genMap.put("symbol", "#");
|
||||||
|
// 保存字段信息
|
||||||
|
List<Map<String, Object>> columns = new ArrayList<>();
|
||||||
|
// 保存查询字段的信息
|
||||||
|
List<Map<String, Object>> queryColumns = new ArrayList<>();
|
||||||
|
// 存储字典信息
|
||||||
|
List<String> dicts = new ArrayList<>();
|
||||||
|
// 存储 between 信息
|
||||||
|
List<Map<String, Object>> betweens = new ArrayList<>();
|
||||||
|
// 存储不为空的字段信息
|
||||||
|
List<Map<String, Object>> isNotNullColumns = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ColumnInfo column : columnInfos) {
|
||||||
|
Map<String, Object> listMap = new HashMap<>(16);
|
||||||
|
// 字段描述
|
||||||
|
listMap.put("remark", column.getRemark());
|
||||||
|
// 字段类型
|
||||||
|
listMap.put("columnKey", column.getKeyType());
|
||||||
|
// 主键类型
|
||||||
|
String colType = ColUtil.cloToJava(column.getColumnType());
|
||||||
|
// 小写开头的字段名
|
||||||
|
String changeColumnName = StringUtils.toCamelCase(column.getColumnName());
|
||||||
|
// 大写开头的字段名
|
||||||
|
String capitalColumnName = StringUtils.toCapitalizeCamelCase(column.getColumnName());
|
||||||
|
if (PK.equals(column.getKeyType())) {
|
||||||
|
// 存储主键类型
|
||||||
|
genMap.put("pkColumnType", colType);
|
||||||
|
// 存储小写开头的字段名
|
||||||
|
genMap.put("pkChangeColName", changeColumnName);
|
||||||
|
// 存储大写开头的字段名
|
||||||
|
genMap.put("pkCapitalColName", capitalColumnName);
|
||||||
|
// 存储主键字段名
|
||||||
|
genMap.put("pkIdName", column.getColumnName());
|
||||||
|
}
|
||||||
|
// 是否存在 Timestamp 类型的字段
|
||||||
|
if (TIMESTAMP.equals(colType)) {
|
||||||
|
genMap.put("hasTimestamp", true);
|
||||||
|
}
|
||||||
|
// 是否存在 BigDecimal 类型的字段
|
||||||
|
if (BIGDECIMAL.equals(colType)) {
|
||||||
|
genMap.put("hasBigDecimal", true);
|
||||||
|
}
|
||||||
|
// 主键是否自增
|
||||||
|
if (EXTRA.equals(column.getExtra())) {
|
||||||
|
genMap.put("auto", true);
|
||||||
|
}
|
||||||
|
// 主键存在字典
|
||||||
|
if (StringUtils.isNotBlank(column.getDictName())) {
|
||||||
|
genMap.put("hasDict", true);
|
||||||
|
if(!dicts.contains(column.getDictName()))
|
||||||
|
dicts.add(column.getDictName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储字段类型
|
||||||
|
listMap.put("columnType", colType);
|
||||||
|
// 存储字原始段名称
|
||||||
|
listMap.put("columnName", column.getColumnName());
|
||||||
|
// 不为空
|
||||||
|
listMap.put("istNotNull", column.getNotNull());
|
||||||
|
// 字段列表显示
|
||||||
|
listMap.put("columnShow", column.getListShow());
|
||||||
|
// 表单显示
|
||||||
|
listMap.put("formShow", column.getFormShow());
|
||||||
|
// 表单组件类型
|
||||||
|
listMap.put("formType", StringUtils.isNotBlank(column.getFormType()) ? column.getFormType() : "Input");
|
||||||
|
// 小写开头的字段名称
|
||||||
|
listMap.put("changeColumnName", changeColumnName);
|
||||||
|
//大写开头的字段名称
|
||||||
|
listMap.put("capitalColumnName", capitalColumnName);
|
||||||
|
// 字典名称
|
||||||
|
listMap.put("dictName", column.getDictName());
|
||||||
|
// 添加非空字段信息
|
||||||
|
if (column.getNotNull()) {
|
||||||
|
isNotNullColumns.add(listMap);
|
||||||
|
}
|
||||||
|
// 判断是否有查询,如有则把查询的字段set进columnQuery
|
||||||
|
if (!StringUtils.isBlank(column.getQueryType())) {
|
||||||
|
// 查询类型
|
||||||
|
listMap.put("queryType", column.getQueryType());
|
||||||
|
// 是否存在查询
|
||||||
|
genMap.put("hasQuery", true);
|
||||||
|
if (TIMESTAMP.equals(colType)) {
|
||||||
|
// 查询中存储 Timestamp 类型
|
||||||
|
genMap.put("queryHasTimestamp", true);
|
||||||
|
}
|
||||||
|
if (BIGDECIMAL.equals(colType)) {
|
||||||
|
// 查询中存储 BigDecimal 类型
|
||||||
|
genMap.put("queryHasBigDecimal", true);
|
||||||
|
}
|
||||||
|
if ("between".equalsIgnoreCase(column.getQueryType())) {
|
||||||
|
betweens.add(listMap);
|
||||||
|
} else {
|
||||||
|
// 添加到查询列表中
|
||||||
|
queryColumns.add(listMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 添加到字段列表中
|
||||||
|
columns.add(listMap);
|
||||||
|
}
|
||||||
|
// 保存字段列表
|
||||||
|
genMap.put("columns", columns);
|
||||||
|
// 保存查询列表
|
||||||
|
genMap.put("queryColumns", queryColumns);
|
||||||
|
// 保存字段列表
|
||||||
|
genMap.put("dicts", dicts);
|
||||||
|
// 保存查询列表
|
||||||
|
genMap.put("betweens", betweens);
|
||||||
|
// 保存非空字段信息
|
||||||
|
genMap.put("isNotNullColumns", isNotNullColumns);
|
||||||
|
return genMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义后端文件路径以及名称
|
||||||
|
*/
|
||||||
|
private static String getAdminFilePath(String templateName, GenConfig genConfig, String className, String rootPath) {
|
||||||
|
String projectPath = rootPath + File.separator + genConfig.getModuleName();
|
||||||
|
String packagePath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator;
|
||||||
|
String mpXmlPath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator;
|
||||||
|
if (!ObjectUtils.isEmpty(genConfig.getPack())) {
|
||||||
|
packagePath += genConfig.getPack().replace(".", File.separator) + File.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Entity".equals(templateName)) {
|
||||||
|
return packagePath + "domain" + File.separator + className + ".java";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Controller".equals(templateName)) {
|
||||||
|
return packagePath + "rest" + File.separator + className + "Controller.java";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Service".equals(templateName)) {
|
||||||
|
return packagePath + "service" + File.separator + className + "Service.java";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("ServiceImpl".equals(templateName)) {
|
||||||
|
return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("QueryCriteria".equals(templateName)) {
|
||||||
|
return packagePath + "domain" + File.separator + "dto" + File.separator + className + "QueryCriteria.java";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Mapper".equals(templateName)) {
|
||||||
|
return packagePath + "mapper" + File.separator + className + "Mapper.java";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Mapper-xml".equals(templateName)) {
|
||||||
|
return mpXmlPath + "mapper" + File.separator + className + "Mapper.xml";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义前端文件路径以及名称
|
||||||
|
*/
|
||||||
|
private static String getFrontFilePath(String templateName, String apiPath, String path, String apiName) {
|
||||||
|
|
||||||
|
if ("api".equals(templateName)) {
|
||||||
|
return apiPath + File.separator + apiName + ".js";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("index".equals(templateName)) {
|
||||||
|
return path + File.separator + "index.vue";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void genFile(File file, Template template, Map<String, Object> map) throws IOException {
|
||||||
|
// 生成目标文件
|
||||||
|
Writer writer = null;
|
||||||
|
try {
|
||||||
|
FileUtil.touch(file);
|
||||||
|
writer = new FileWriter(file);
|
||||||
|
template.render(map, writer);
|
||||||
|
} catch (TemplateException | IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
assert writer != null;
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
eladmin/eladmin-generator/src/main/resources/gen.properties
Normal file
27
eladmin/eladmin-generator/src/main/resources/gen.properties
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#数据库类型转Java类型
|
||||||
|
tinyint=Integer
|
||||||
|
smallint=Integer
|
||||||
|
mediumint=Integer
|
||||||
|
int=Integer
|
||||||
|
integer=Integer
|
||||||
|
|
||||||
|
bigint=Long
|
||||||
|
|
||||||
|
float=Float
|
||||||
|
|
||||||
|
double=Double
|
||||||
|
|
||||||
|
decimal=BigDecimal
|
||||||
|
|
||||||
|
bit=Boolean
|
||||||
|
|
||||||
|
char=String
|
||||||
|
varchar=String
|
||||||
|
tinytext=String
|
||||||
|
text=String
|
||||||
|
mediumtext=String
|
||||||
|
longtext=String
|
||||||
|
|
||||||
|
date=Timestamp
|
||||||
|
datetime=Timestamp
|
||||||
|
timestamp=Timestamp
|
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="me.zhengjie.mapper.ColumnInfoMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="me.zhengjie.domain.ColumnInfo">
|
||||||
|
<id column="column_id" property="id"/>
|
||||||
|
<result column="table_name" property="tableName"/>
|
||||||
|
<result column="column_name" property="columnName"/>
|
||||||
|
<result column="column_type" property="columnType"/>
|
||||||
|
<result column="key_type" property="keyType"/>
|
||||||
|
<result column="extra" property="extra"/>
|
||||||
|
<result column="remark" property="remark"/>
|
||||||
|
<result column="not_null" property="notNull"/>
|
||||||
|
<result column="list_show" property="listShow"/>
|
||||||
|
<result column="form_show" property="formShow"/>
|
||||||
|
<result column="form_type" property="formType"/>
|
||||||
|
<result column="query_type" property="queryType"/>
|
||||||
|
<result column="dict_name" property="dictName"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
column_id, table_name, column_name, column_type, key_type, extra, remark, not_null, list_show, form_show, form_type, query_type, dict_name
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="getTables" resultType="me.zhengjie.domain.dto.TableInfo">
|
||||||
|
select table_name, create_time, engine, table_collation as coding, table_comment as remark
|
||||||
|
from information_schema.tables
|
||||||
|
where table_schema = (select database())
|
||||||
|
and table_name like concat('%',#{tableName},'%')
|
||||||
|
order by create_time desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="findByTableNameOrderByIdAsc" resultMap="BaseResultMap">
|
||||||
|
select
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
from code_column
|
||||||
|
where table_name = #{tableName}
|
||||||
|
order by column_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getColumns" resultMap="BaseResultMap">
|
||||||
|
select column_name, if(is_nullable = 'NO', 1, 0) not_null,
|
||||||
|
data_type as column_type, column_comment as remark,
|
||||||
|
column_key key_type, extra
|
||||||
|
from information_schema.columns
|
||||||
|
where table_name = #{tableName}
|
||||||
|
and table_schema = (select database())
|
||||||
|
order by ordinal_position
|
||||||
|
</select>
|
||||||
|
</mapper>
|
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="me.zhengjie.mapper.GenConfigMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="me.zhengjie.domain.GenConfig">
|
||||||
|
<id column="config_id" property="id"/>
|
||||||
|
<result column="table_name" property="tableName"/>
|
||||||
|
<result column="api_alias" property="apiAlias"/>
|
||||||
|
<result column="pack" property="pack"/>
|
||||||
|
<result column="module_name" property="moduleName"/>
|
||||||
|
<result column="path" property="path"/>
|
||||||
|
<result column="api_path" property="apiPath"/>
|
||||||
|
<result column="author" property="author"/>
|
||||||
|
<result column="prefix" property="prefix"/>
|
||||||
|
<result column="cover" property="cover"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
config_id, table_name, api_alias, pack, module_name, path, api_path, author, prefix, cover
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="findByTableName" resultMap="BaseResultMap">
|
||||||
|
SELECT
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
FROM code_config
|
||||||
|
WHERE table_name = #{tableName}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package ${package}.rest;
|
||||||
|
|
||||||
|
import me.zhengjie.annotation.Log;
|
||||||
|
import ${package}.domain.${className};
|
||||||
|
import ${package}.service.${className}Service;
|
||||||
|
import ${package}.domain.dto.${className}QueryCriteria;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import me.zhengjie.utils.PageResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ${author}
|
||||||
|
* @date ${date}
|
||||||
|
**/
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Api(tags = "${apiAlias}")
|
||||||
|
@RequestMapping("/api/${changeClassName}")
|
||||||
|
public class ${className}Controller {
|
||||||
|
|
||||||
|
private final ${className}Service ${changeClassName}Service;
|
||||||
|
|
||||||
|
@ApiOperation("导出数据")
|
||||||
|
@GetMapping(value = "/download")
|
||||||
|
@PreAuthorize("@el.check('${changeClassName}:list')")
|
||||||
|
public void export${className}(HttpServletResponse response, ${className}QueryCriteria criteria) throws IOException {
|
||||||
|
${changeClassName}Service.download(${changeClassName}Service.queryAll(criteria), response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@ApiOperation("查询${apiAlias}")
|
||||||
|
@PreAuthorize("@el.check('${changeClassName}:list')")
|
||||||
|
public ResponseEntity<PageResult<${className}>> query${className}(${className}QueryCriteria criteria){
|
||||||
|
Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize());
|
||||||
|
return new ResponseEntity<>(${changeClassName}Service.queryAll(criteria,page),HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Log("新增${apiAlias}")
|
||||||
|
@ApiOperation("新增${apiAlias}")
|
||||||
|
@PreAuthorize("@el.check('${changeClassName}:add')")
|
||||||
|
public ResponseEntity<Object> create${className}(@Validated @RequestBody ${className} resources){
|
||||||
|
${changeClassName}Service.create(resources);
|
||||||
|
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
@Log("修改${apiAlias}")
|
||||||
|
@ApiOperation("修改${apiAlias}")
|
||||||
|
@PreAuthorize("@el.check('${changeClassName}:edit')")
|
||||||
|
public ResponseEntity<Object> update${className}(@Validated @RequestBody ${className} resources){
|
||||||
|
${changeClassName}Service.update(resources);
|
||||||
|
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
@Log("删除${apiAlias}")
|
||||||
|
@ApiOperation("删除${apiAlias}")
|
||||||
|
@PreAuthorize("@el.check('${changeClassName}:del')")
|
||||||
|
public ResponseEntity<Object> delete${className}(@ApiParam(value = "传ID数组[]") @RequestBody List<${pkColumnType}> ids) {
|
||||||
|
${changeClassName}Service.deleteAll(ids);
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2025 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.
|
||||||
|
*/
|
||||||
|
package ${package}.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import cn.hutool.core.bean.copier.CopyOptions;
|
||||||
|
<#if hasTimestamp>
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
</#if>
|
||||||
|
<#if hasBigDecimal>
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
</#if>
|
||||||
|
<#assign notBlankUsed = false>
|
||||||
|
<#assign notNullUsed = false>
|
||||||
|
<#if columns??>
|
||||||
|
<#list columns as column>
|
||||||
|
<#if column.istNotNull && column.columnKey != 'PRI'>
|
||||||
|
<#if column.columnType = 'String'>
|
||||||
|
<#assign notBlankUsed = true>
|
||||||
|
<#else>
|
||||||
|
<#assign notNullUsed = true>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<#if notBlankUsed>
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
</#if>
|
||||||
|
<#if notNullUsed>
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
</#if>
|
||||||
|
import java.io.Serializable;
|
||||||
|
<#if auto>
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
</#if>
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description /
|
||||||
|
* @author ${author}
|
||||||
|
* @date ${date}
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@TableName("${tableName}")
|
||||||
|
public class ${className} implements Serializable {
|
||||||
|
<#if columns??>
|
||||||
|
<#list columns as column>
|
||||||
|
|
||||||
|
<#if column.columnKey = 'PRI'>
|
||||||
|
@TableId(value = "${column.columnName}"<#if auto>, type = IdType.AUTO</#if>)
|
||||||
|
</#if>
|
||||||
|
<#if column.istNotNull && column.columnKey != 'PRI'>
|
||||||
|
<#if column.columnType = 'String'>
|
||||||
|
@NotBlank
|
||||||
|
<#else>
|
||||||
|
@NotNull
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
<#if column.remark != ''>
|
||||||
|
@ApiModelProperty(value = "${column.remark}")
|
||||||
|
<#else>
|
||||||
|
@ApiModelProperty(value = "${column.changeColumnName}")
|
||||||
|
</#if>
|
||||||
|
private ${column.columnType} ${column.changeColumnName};
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
public void copy(${className} source){
|
||||||
|
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user