推送
This commit is contained in:
parent
1154eaab0b
commit
2d39c81ef7
@ -5,7 +5,7 @@
|
||||
"author": "Zheng Jie",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve",
|
||||
"dev": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
|
||||
"build:prod": "vue-cli-service build",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"preview": "node build/index.js --preview",
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 805 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 889 KiB |
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="display: inline-block">
|
||||
<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">
|
||||
<p>{{ msg }}</p>
|
||||
|
@ -6,6 +6,7 @@
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
import { getPieChatData } from '@/api/dashboard/dashboard'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@ -24,7 +25,9 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
chart: null,
|
||||
dataList: [],
|
||||
dataTitle: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -45,9 +48,22 @@ export default {
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
async 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.setOption({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
@ -56,29 +72,23 @@ export default {
|
||||
legend: {
|
||||
left: 'center',
|
||||
bottom: '10',
|
||||
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
|
||||
data: this.dataTitle
|
||||
},
|
||||
calculable: true,
|
||||
series: [
|
||||
{
|
||||
name: 'WEEKLY WRITE ARTICLES',
|
||||
name: '主治医生文档数',
|
||||
type: 'pie',
|
||||
roseType: 'radius',
|
||||
radius: [15, 95],
|
||||
center: ['50%', '38%'],
|
||||
data: [
|
||||
{ value: 320, name: 'Industries' },
|
||||
{ value: 240, name: 'Technology' },
|
||||
{ value: 149, name: 'Forex' },
|
||||
{ value: 100, name: 'Gold' },
|
||||
{ value: 59, name: 'Forecasts' }
|
||||
],
|
||||
data: this.dataList,
|
||||
animationEasing: 'cubicInOut',
|
||||
animationDuration: 2600
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -8,17 +8,17 @@
|
||||
<template v-if="device!=='mobile'">
|
||||
<search id="header-search" class="right-menu-item" />
|
||||
|
||||
<el-tooltip content="项目文档" effect="dark" placement="bottom">
|
||||
<Doc class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
<!-- <el-tooltip content="项目文档" effect="dark" placement="bottom">-->
|
||||
<!-- <Doc class="right-menu-item hover-effect" />-->
|
||||
<!-- </el-tooltip>-->
|
||||
|
||||
<el-tooltip content="全屏缩放" effect="dark" placement="bottom">
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="布局设置" effect="dark" placement="bottom">
|
||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
<!-- <el-tooltip content="布局设置" effect="dark" placement="bottom">-->
|
||||
<!-- <size-select id="size-select" class="right-menu-item hover-effect" />-->
|
||||
<!-- </el-tooltip>-->
|
||||
|
||||
</template>
|
||||
|
||||
|
@ -25,7 +25,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: 'ELADMIN-后台管理',
|
||||
title: '健康档案中心',
|
||||
logo: Logo
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ module.exports = {
|
||||
/**
|
||||
* @description 网站标题
|
||||
*/
|
||||
title: 'ELADMIN',
|
||||
title: '健康档案中心',
|
||||
/**
|
||||
* @description 是否显示 tagsView
|
||||
*/
|
||||
@ -34,7 +34,7 @@ module.exports = {
|
||||
/**
|
||||
* 是否显示设置的底部信息
|
||||
*/
|
||||
showFooter: true,
|
||||
showFooter: false,
|
||||
/**
|
||||
* 底部文字,支持html语法
|
||||
*/
|
||||
|
@ -61,10 +61,10 @@ export default {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
this.setOptions(this.chartData)
|
||||
},
|
||||
setOptions({ expectedData, actualData } = {}) {
|
||||
setOptions({ data } = {}) { // , actualData
|
||||
this.chart.setOption({
|
||||
xAxis: {
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
data: ['今天', '昨天', '前天', '大前天'],
|
||||
boundaryGap: false,
|
||||
axisTick: {
|
||||
show: false
|
||||
@ -90,10 +90,10 @@ export default {
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['expected', 'actual']
|
||||
data: ['数量'] // ,'actual'
|
||||
},
|
||||
series: [{
|
||||
name: 'expected', itemStyle: {
|
||||
name: '数量', itemStyle: {
|
||||
normal: {
|
||||
color: '#FF005A',
|
||||
lineStyle: {
|
||||
@ -104,30 +104,31 @@ export default {
|
||||
},
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
data: expectedData,
|
||||
data: data,
|
||||
animationDuration: 2800,
|
||||
animationEasing: 'cubicInOut'
|
||||
},
|
||||
{
|
||||
name: 'actual',
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#3888fa',
|
||||
lineStyle: {
|
||||
color: '#3888fa',
|
||||
width: 2
|
||||
},
|
||||
areaStyle: {
|
||||
color: '#f3f8ff'
|
||||
}
|
||||
}
|
||||
},
|
||||
data: actualData,
|
||||
animationDuration: 2800,
|
||||
animationEasing: 'quadraticOut'
|
||||
}]
|
||||
// {
|
||||
// name: 'actual',
|
||||
// smooth: true,
|
||||
// type: 'line',
|
||||
// itemStyle: {
|
||||
// normal: {
|
||||
// color: '#3888fa',
|
||||
// lineStyle: {
|
||||
// color: '#3888fa',
|
||||
// width: 2
|
||||
// },
|
||||
// areaStyle: {
|
||||
// color: '#f3f8ff'
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// data: actualData,
|
||||
// animationDuration: 2800,
|
||||
// animationEasing: 'quadraticOut'
|
||||
// }
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +1,54 @@
|
||||
<template>
|
||||
<el-row :gutter="40" class="panel-group">
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('newVisitis')">
|
||||
<div class="card-panel" @click="handleSetLineChartData('user')">
|
||||
<div class="card-panel-icon-wrapper icon-people">
|
||||
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
New Visits
|
||||
用户统计
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
|
||||
<count-to :start-val="0" :end-val="groupData.user" :duration="2600" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('messages')">
|
||||
<div class="card-panel" @click="handleSetLineChartData('dept')">
|
||||
<div class="card-panel-icon-wrapper icon-message">
|
||||
<svg-icon icon-class="message" class-name="card-panel-icon" />
|
||||
<svg-icon icon-class="dept" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Messages
|
||||
部门统计
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
|
||||
<count-to :start-val="0" :end-val="groupData.dept" :duration="3000" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('purchases')">
|
||||
<div class="card-panel" @click="handleSetLineChartData('role')">
|
||||
<div class="card-panel-icon-wrapper icon-money">
|
||||
<svg-icon icon-class="money" class-name="card-panel-icon" />
|
||||
<svg-icon icon-class="role" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Purchases
|
||||
角色统计
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
|
||||
<count-to :start-val="0" :end-val="groupData.role" :duration="3200" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('shoppings')">
|
||||
<div class="card-panel" @click="handleSetLineChartData('law')">
|
||||
<div class="card-panel-icon-wrapper icon-shopping">
|
||||
<svg-icon icon-class="shopping" class-name="card-panel-icon" />
|
||||
<svg-icon icon-class="server" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Shoppings
|
||||
执法数据
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
|
||||
<count-to :start-val="0" :end-val="groupData.law" :duration="3600" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
@ -57,15 +57,34 @@
|
||||
|
||||
<script>
|
||||
import CountTo from 'vue-count-to'
|
||||
import {getCardData} from '@/api/dashboard/dashboard'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CountTo
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
groupData: {
|
||||
"user": 0,
|
||||
"dept": 0,
|
||||
"role": 0,
|
||||
"law": 0,
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getGroup();
|
||||
},
|
||||
methods: {
|
||||
getGroup() {
|
||||
getCardData().then(res => {
|
||||
this.groupData = res
|
||||
})
|
||||
},
|
||||
handleSetLineChartData(type) {
|
||||
this.$emit('handleSetLineChartData', type)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,79 +1,82 @@
|
||||
<template>
|
||||
<div class="dashboard-container">
|
||||
<div class="dashboard-editor-container">
|
||||
<github-corner class="github-corner" />
|
||||
|
||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
||||
|
||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
||||
<line-chart :chart-data="lineChartData" />
|
||||
<line-chart :chart-data="lineChartData" :chartData="lineChartData" />
|
||||
</el-row>
|
||||
<el-row :gutter="32">
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<radar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<!-- <el-col :xs="24" :sm="24" :lg="8">-->
|
||||
<!-- <div class="chart-wrapper">-->
|
||||
<!-- <radar-chart />-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<el-col :xs="24" :sm="24" :lg="24">
|
||||
<div class="chart-wrapper">
|
||||
<pie-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<bar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<!-- <el-col :xs="24" :sm="24" :lg="12">-->
|
||||
<!-- <div class="chart-wrapper">-->
|
||||
<!-- <bar-chart />-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GithubCorner from '@/components/GithubCorner'
|
||||
import PanelGroup from './dashboard/PanelGroup'
|
||||
import LineChart from './dashboard/LineChart'
|
||||
import RadarChart from '@/components/Echarts/RadarChart'
|
||||
// import RadarChart from '@/components/Echarts/RadarChart'
|
||||
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 = {
|
||||
newVisitis: {
|
||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||
user: {
|
||||
data: [100, 120, 161, 134, 105, 160, 165],
|
||||
// actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||
},
|
||||
messages: {
|
||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||
dept: {
|
||||
data: [200, 192, 120, 144, 160, 130, 140],
|
||||
// actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||
},
|
||||
purchases: {
|
||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||
role: {
|
||||
data: [80, 100, 121, 104, 105, 90, 100],
|
||||
// actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||
},
|
||||
shoppings: {
|
||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||
law: {
|
||||
data: [130, 140, 141, 142, 145, 150, 160],
|
||||
// actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: {
|
||||
GithubCorner,
|
||||
PanelGroup,
|
||||
LineChart,
|
||||
RadarChart,
|
||||
// RadarChart,
|
||||
PieChart,
|
||||
BarChart
|
||||
// BarChart
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lineChartData: lineChartData.newVisitis
|
||||
lineChartData: lineChartData.user
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.handleSetLineChartData("user");
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.lineChartData = lineChartData[type]
|
||||
getLineChart(type).then(res => {
|
||||
this.lineChartData.data = res
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="login" :style="'background-image:url('+ Background +');'">
|
||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form">
|
||||
<h3 class="title">
|
||||
ELADMIN 后台管理系统
|
||||
健康档案管理中心
|
||||
</h3>
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
|
||||
@ -186,6 +186,7 @@ export default {
|
||||
background: #ffffff;
|
||||
width: 385px;
|
||||
padding: 25px 25px 5px 25px;
|
||||
opacity: 0.9;
|
||||
.el-input {
|
||||
height: 38px;
|
||||
input {
|
||||
|
@ -1,144 +0,0 @@
|
||||
<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>
|
@ -1,86 +0,0 @@
|
||||
<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>
|
@ -1,148 +0,0 @@
|
||||
<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>
|
@ -1,190 +0,0 @@
|
||||
<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>
|
@ -1,229 +0,0 @@
|
||||
<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>
|
@ -1,107 +0,0 @@
|
||||
<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>
|
@ -1,93 +0,0 @@
|
||||
<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>
|
@ -1,136 +0,0 @@
|
||||
<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>
|
@ -1,36 +0,0 @@
|
||||
<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>
|
@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="三级菜单2" type="success" />
|
||||
</div>
|
||||
</template>
|
@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="二级菜单" />
|
||||
</div>
|
||||
</template>
|
@ -21,7 +21,7 @@
|
||||
<ul class="user-info">
|
||||
<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="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="email" /> 用户邮箱 <div class="user-right">{{ user.email }}</div></li>
|
||||
<li>
|
||||
|
@ -86,32 +86,32 @@
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" />
|
||||
</el-form-item>
|
||||
<el-form-item label="部门" prop="dept.id">
|
||||
<el-form-item label="归属" prop="dept.id">
|
||||
<treeselect
|
||||
v-model="form.dept.id"
|
||||
:options="depts"
|
||||
:load-options="loadDepts"
|
||||
style="width: 173px"
|
||||
placeholder="选择部门"
|
||||
placeholder="选择医院"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位" prop="jobDatas" class="is-required">
|
||||
<el-select
|
||||
v-model="jobDatas"
|
||||
style="width: 172px"
|
||||
multiple
|
||||
placeholder="请选择"
|
||||
@remove-tag="deleteTag"
|
||||
@change="changeJob"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in jobs"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="岗位" prop="jobDatas" class="is-required">-->
|
||||
<!-- <el-select-->
|
||||
<!-- v-model="jobDatas"-->
|
||||
<!-- style="width: 172px"-->
|
||||
<!-- multiple-->
|
||||
<!-- placeholder="请选择"-->
|
||||
<!-- @remove-tag="deleteTag"-->
|
||||
<!-- @change="changeJob"-->
|
||||
<!-- >-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item in jobs"-->
|
||||
<!-- :key="item.name"-->
|
||||
<!-- :label="item.name"-->
|
||||
<!-- :value="item.id"-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="form.gender" style="width: 178px">
|
||||
<el-radio label="男">男</el-radio>
|
||||
@ -291,6 +291,8 @@ export default {
|
||||
value = this.roleDatas
|
||||
if (!value || value.length === 0) {
|
||||
callback(new Error('请选择至少一个角色'))
|
||||
} else if (value.length > 1) {
|
||||
callback(new Error('只能选择一个角色'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
|
@ -1,98 +0,0 @@
|
||||
<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>
|
@ -1,48 +0,0 @@
|
||||
<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>
|
@ -1,86 +0,0 @@
|
||||
<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>
|
@ -1,91 +0,0 @@
|
||||
<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>
|
@ -1,41 +0,0 @@
|
||||
<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>
|
@ -1,98 +0,0 @@
|
||||
<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,18 +3,19 @@
|
||||
<el-tab-pane label="本地存储" name="first">
|
||||
<Local ref="local" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="七牛云存储" name="second">
|
||||
<QiNiu ref="qiNiu" />
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="七牛云存储" name="second">-->
|
||||
<!-- <QiNiu ref="qiNiu" />-->
|
||||
<!-- </el-tab-pane>-->
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QiNiu from './qiniu/index'
|
||||
// import QiNiu from './qiniu/index'
|
||||
import Local from './local/index'
|
||||
export default {
|
||||
name: 'Storage',
|
||||
components: { QiNiu, Local },
|
||||
components: { Local },
|
||||
// components: { QiNiu, Local },
|
||||
data() {
|
||||
return {
|
||||
activeName: 'first'
|
||||
|
@ -1,98 +0,0 @@
|
||||
<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>
|
@ -1,189 +0,0 @@
|
||||
<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
|
||||
third-party archives.
|
||||
|
||||
Copyright 2019-2025 Zheng Jie
|
||||
Copyright 2019-2025 Tz
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -1,26 +1,17 @@
|
||||
<h1 style="text-align: center">ELADMIN 后台管理系统</h1>
|
||||
<h1 style="text-align: center">区块链医疗数据共享平台管理</h1>
|
||||
|
||||
#### 项目简介
|
||||
一个基于 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`
|
||||
|
||||
#### 项目源码
|
||||
#### 项目结构
|
||||
项目采用按功能分模块的开发方式,结构如下
|
||||
|
||||
| github | gitee |
|
||||
|--------------------------------------| --- |
|
||||
| https://github.com/elunez/eladmin-mp | https://gitee.com/elunez/eladmin-mp |
|
||||
- `eladmin-common` 为系统的公共模块,各种工具类,公共配置存在该模块
|
||||
|
||||
#### 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>
|
||||
- `eladmin-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
|
||||
|
||||
使用优惠码: `BWHNCXNVXV`,可获得 6.81% 的折扣, [查看介绍](https://eladmin.vip/pages/040101/)
|
||||
#### 主要特性
|
||||
- 使用最新技术栈,社区资源丰富。
|
||||
- 高效率开发,代码生成器可一键生成前后端代码
|
||||
@ -41,14 +32,7 @@
|
||||
- 岗位管理:配置各个部门的职位
|
||||
- 字典管理:可维护常用一些固定的数据,如:状态,性别等
|
||||
- 系统日志:记录用户操作日志与异常日志,方便开发人员定位排错
|
||||
- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456
|
||||
- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然
|
||||
- 代码生成:高灵活度生成前后端代码,减少大量重复的工作任务
|
||||
- 邮件工具:配合富文本,发送html格式的邮件
|
||||
- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据
|
||||
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
|
||||
- 服务监控:监控服务器的负载情况
|
||||
- 运维管理:一键部署你的应用
|
||||
- 档案管理:医院对用户档案的隐私保护和档案上链追溯管理,授权查看等权限限制
|
||||
|
||||
#### 项目结构
|
||||
项目采用按功能分模块的开发方式,结构如下
|
||||
@ -57,12 +41,6 @@
|
||||
|
||||
- `eladmin-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
|
||||
|
||||
- `eladmin-logging` 为系统的日志模块,其他模块如果需要记录日志需要引入该模块
|
||||
|
||||
- `eladmin-tools` 为第三方工具模块,包含:邮件、七牛云存储、本地存储、支付宝
|
||||
|
||||
- `eladmin-generator` 为系统的代码生成模块,支持生成前后端CRUD代码
|
||||
|
||||
#### 详细结构
|
||||
|
||||
```
|
||||
@ -89,26 +67,4 @@
|
||||
- sysrunner 程序启动后处理数据
|
||||
- modules 系统相关模块(登录授权、系统监控、定时任务、系统模块、运维模块)
|
||||
- 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 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -30,7 +30,7 @@ import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* 通用字段, is_del 根据需求自行添加
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2019年10月24日20:46:32
|
||||
*/
|
||||
@Getter
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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 Zheng Jie
|
||||
* @author Tz
|
||||
* @description
|
||||
* @date 2023-06-08
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
*/
|
||||
@Service(value = "el")
|
||||
public class AuthorityConfig {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -44,7 +44,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2025-01-13
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description
|
||||
* @date 2025-01-11
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description 自定义 p6spy sql输出格式
|
||||
* @date 2024-12-26
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description
|
||||
* @date 2023-06-13
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description
|
||||
* @date 2023-06-12
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @website <a href="https://eladmin.vip">...</a>
|
||||
* @description
|
||||
* @date 2020-05-18
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -37,7 +37,7 @@ import java.util.List;
|
||||
/**
|
||||
* WebMvcConfigurer
|
||||
*
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-30
|
||||
*/
|
||||
@Configuration
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2023 Zheng Jie
|
||||
* Copyright 2019-2023 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
@Configuration
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author ZhangHouYing
|
||||
* @author Tz
|
||||
* @date 2019-08-24 15:44
|
||||
*/
|
||||
@Configuration
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
* 统一异常处理
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
public class EntityExistException extends RuntimeException {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
public class EntityNotFoundException extends RuntimeException {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
@Data
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.*;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -25,7 +25,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description 匿名标记工具
|
||||
* @date 2025-01-13
|
||||
**/
|
||||
|
@ -19,7 +19,7 @@ import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description 计算类
|
||||
* @date 2024-12-27
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @description 用于关闭各种连接,缺啥补啥
|
||||
* @date 2021-03-05
|
||||
**/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -18,7 +18,7 @@ package me.zhengjie.utils;
|
||||
/**
|
||||
* 常用静态常量
|
||||
*
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-12-26
|
||||
*/
|
||||
public class ElConstant {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -24,7 +24,7 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
public class EncryptUtils {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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 工具包
|
||||
*
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-12-27
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -6,7 +6,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页结果封装类
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-23
|
||||
* @param <T>
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,7 +20,7 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* 分页工具
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-12-10
|
||||
*/
|
||||
public class PageUtil extends cn.hutool.core.util.PageUtil {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,7 +22,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 获取 HttpServletRequest
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
public class RequestHolder {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -35,7 +35,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2019-01-17
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.*;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
*/
|
||||
public class ThrowableUtil {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,7 +22,7 @@ import lombok.Getter;
|
||||
* <p>
|
||||
* 验证码业务场景
|
||||
* </p>
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2020-05-02
|
||||
*/
|
||||
@Getter
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,7 +22,7 @@ import lombok.Getter;
|
||||
* <p>
|
||||
* 验证码业务场景对应的 Redis 中的 key
|
||||
* </p>
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2020-05-02
|
||||
*/
|
||||
@Getter
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,7 +22,7 @@ import lombok.Getter;
|
||||
* <p>
|
||||
* 数据权限枚举
|
||||
* </p>
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @date 2020-05-07
|
||||
*/
|
||||
@Getter
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2025 Zheng Jie
|
||||
* Copyright 2019-2025 Tz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,7 +19,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @author Tz
|
||||
* @website https://eladmin.vip
|
||||
* @description
|
||||
* @date 2020-06-10
|
||||
|
@ -1,37 +0,0 @@
|
||||
<?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>
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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,51 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* 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("打包失败");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -1,417 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#数据库类型转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
|
@ -1,49 +0,0 @@
|
||||
<?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>
|
@ -1,27 +0,0 @@
|
||||
<?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>
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
<?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="${package}.mapper.${className}Mapper">
|
||||
<#if columns??>
|
||||
<resultMap id="BaseResultMap" type="${package}.domain.${className}">
|
||||
<#list columns as column>
|
||||
<#if column.columnKey = 'PRI'>
|
||||
<id column="${column.columnName}" property="${column.changeColumnName}"/>
|
||||
</#if>
|
||||
<#if column.columnKey != 'PRI'>
|
||||
<result column="${column.columnName}" property="${column.changeColumnName}"/>
|
||||
</#if>
|
||||
</#list>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
<#list columns as column>${column.columnName}<#if column_has_next>, </#if></#list>
|
||||
</sql>
|
||||
</#if>
|
||||
|
||||
<select id="findAll" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List"/>
|
||||
from ${tableName}
|
||||
<#if queryColumns??>
|
||||
<where>
|
||||
<#list queryColumns as column>
|
||||
<if test="criteria.${column.changeColumnName} != null">
|
||||
<#if column.queryType = '='>
|
||||
and ${column.columnName} = ${symbol}{criteria.${column.changeColumnName}}
|
||||
</#if>
|
||||
<#if column.queryType = 'Like'>
|
||||
and ${column.columnName} like concat('%',${symbol}{criteria.${column.changeColumnName}},'%')
|
||||
</#if>
|
||||
<#if column.queryType = '!='>
|
||||
and ${column.columnName} != ${symbol}{criteria.${column.changeColumnName}}
|
||||
</#if>
|
||||
<#if column.queryType = 'NotNull'>
|
||||
and ${column.columnName} is not null
|
||||
</#if>
|
||||
<#if column.queryType = '>='>
|
||||
and ${column.columnName} >= ${symbol}{criteria.${column.changeColumnName}}
|
||||
</#if>
|
||||
<#if column.queryType = '<='>
|
||||
and ${column.columnName} <= ${symbol}{criteria.${column.changeColumnName}}
|
||||
</#if>
|
||||
</if>
|
||||
</#list>
|
||||
<#if betweens??>
|
||||
<#list betweens as column>
|
||||
<if test="criteria.${column.changeColumnName} != null and criteria.${column.changeColumnName}.size() > 0">
|
||||
AND ${column.columnName} BETWEEN ${symbol}{criteria.${column.changeColumnName}[0]} AND ${symbol}{criteria.${column.changeColumnName}[1]}
|
||||
</if>
|
||||
</#list>
|
||||
</#if>
|
||||
</where>
|
||||
</#if>
|
||||
<#if pkIdName != 'none'>
|
||||
order by ${pkIdName} desc
|
||||
</#if>
|
||||
</select>
|
||||
</mapper>
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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}.service.impl;
|
||||
|
||||
import ${package}.domain.${className};
|
||||
<#if columns??>
|
||||
<#list columns as column>
|
||||
<#if column.columnKey = 'UNI'>
|
||||
<#if column_index = 1>
|
||||
import me.zhengjie.exception.EntityExistException;
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
import me.zhengjie.utils.FileUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import ${package}.service.${className}Service;
|
||||
import ${package}.domain.dto.${className}QueryCriteria;
|
||||
import ${package}.mapper.${className}Mapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import me.zhengjie.utils.PageUtil;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import me.zhengjie.utils.PageResult;
|
||||
|
||||
/**
|
||||
* @description 服务实现
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${className}> implements ${className}Service {
|
||||
|
||||
private final ${className}Mapper ${changeClassName}Mapper;
|
||||
|
||||
@Override
|
||||
public PageResult<${className}> queryAll(${className}QueryCriteria criteria, Page<Object> page){
|
||||
return PageUtil.toPage(${changeClassName}Mapper.findAll(criteria, page));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<${className}> queryAll(${className}QueryCriteria criteria){
|
||||
return ${changeClassName}Mapper.findAll(criteria);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void create(${className} resources) {
|
||||
${changeClassName}Mapper.insert(resources);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(${className} resources) {
|
||||
${className} ${changeClassName} = getById(resources.get${pkCapitalColName}());
|
||||
${changeClassName}.copy(resources);
|
||||
${changeClassName}Mapper.updateById(${changeClassName});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteAll(List<${pkColumnType}> ids) {
|
||||
${changeClassName}Mapper.deleteBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(List<${className}> all, HttpServletResponse response) throws IOException {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (${className} ${changeClassName} : all) {
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
<#list columns as column>
|
||||
<#if column.columnKey != 'PRI'>
|
||||
<#if column.remark != ''>
|
||||
map.put("${column.remark}", ${changeClassName}.get${column.capitalColumnName}());
|
||||
<#else>
|
||||
map.put(" ${column.changeColumnName}", ${changeClassName}.get${column.capitalColumnName}());
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function add(data) {
|
||||
return request({
|
||||
url: 'api/${changeClassName}',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function del(ids) {
|
||||
return request({
|
||||
url: 'api/${changeClassName}/',
|
||||
method: 'delete',
|
||||
data: ids
|
||||
})
|
||||
}
|
||||
|
||||
export function edit(data) {
|
||||
return request({
|
||||
url: 'api/${changeClassName}',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export default { add, edit, del }
|
@ -1,169 +0,0 @@
|
||||
<#--noinspection ALL-->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--工具栏-->
|
||||
<div class="head-container">
|
||||
<#if hasQuery>
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<#if queryColumns??>
|
||||
<#list queryColumns as column>
|
||||
<#if column.queryType != 'BetWeen'>
|
||||
<label class="el-form-item-label"><#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if></label>
|
||||
<el-input v-model="query.${column.changeColumnName}" clearable placeholder="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>" style="width: 185px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
<#if betweens??>
|
||||
<#list betweens as column>
|
||||
<#if column.queryType = 'BetWeen'>
|
||||
<date-range-picker
|
||||
v-model="query.${column.changeColumnName}"
|
||||
start-placeholder="${column.changeColumnName}Start"
|
||||
end-placeholder="${column.changeColumnName}Start"
|
||||
class="date-item"
|
||||
/>
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
<rrOperation :crud="crud" />
|
||||
</div>
|
||||
</#if>
|
||||
<!--如果想在工具栏加入更多按钮,可以使用插槽方式, slot = 'left' or 'right'-->
|
||||
<crudOperation :permission="permission" />
|
||||
<!--表单组件-->
|
||||
<el-dialog :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" <#if isNotNullColumns??>:rules="rules"</#if> size="small" label-width="80px">
|
||||
<#if columns??>
|
||||
<#list columns as column>
|
||||
<#if column.formShow>
|
||||
<el-form-item label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>"<#if column.istNotNull> prop="${column.changeColumnName}"</#if>>
|
||||
<#if column.formType = 'Input'>
|
||||
<el-input v-model="form.${column.changeColumnName}" style="width: 370px;" />
|
||||
<#elseif column.formType = 'Textarea'>
|
||||
<el-input v-model="form.${column.changeColumnName}" :rows="3" type="textarea" style="width: 370px;" />
|
||||
<#elseif column.formType = 'Radio'>
|
||||
<#if (column.dictName)?? && (column.dictName)!="">
|
||||
<el-radio v-model="form.${column.changeColumnName}" v-for="item in dict.${column.dictName}" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
|
||||
<#else>
|
||||
未设置字典,请手动设置 Radio
|
||||
</#if>
|
||||
<#elseif column.formType = 'Select'>
|
||||
<#if (column.dictName)?? && (column.dictName)!="">
|
||||
<el-select v-model="form.${column.changeColumnName}" filterable placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in dict.${column.dictName}"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
<#else>
|
||||
未设置字典,请手动设置 Select
|
||||
</#if>
|
||||
<#else>
|
||||
<el-date-picker v-model="form.${column.changeColumnName}" type="datetime" style="width: 370px;" />
|
||||
</#if>
|
||||
</el-form-item>
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
</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" size="small" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<#if columns??>
|
||||
<#list columns as column>
|
||||
<#if column.columnShow>
|
||||
<#if (column.dictName)?? && (column.dictName)!="">
|
||||
<el-table-column prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>">
|
||||
<template slot-scope="scope">
|
||||
{{ dict.label.${column.dictName}[scope.row.${column.changeColumnName}] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#else>
|
||||
<el-table-column prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>" />
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
<el-table-column v-if="checkPer(['admin','${changeClassName}:edit','${changeClassName}:del'])" label="操作" width="150px" align="center">
|
||||
<template slot-scope="scope">
|
||||
<udOperation
|
||||
:data="scope.row"
|
||||
:permission="permission"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--分页组件-->
|
||||
<pagination />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import crud${className} from '@/api/${changeClassName}'
|
||||
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'
|
||||
|
||||
const defaultForm = { <#if columns??><#list columns as column>${column.changeColumnName}: null<#if column_has_next>, </#if></#list></#if> }
|
||||
export default {
|
||||
name: '${className}',
|
||||
components: { pagination, crudOperation, rrOperation, udOperation },
|
||||
mixins: [presenter(), header(), form(defaultForm), crud()],
|
||||
<#if hasDict>
|
||||
dicts: [<#if hasDict??><#list dicts as dict>'${dict}'<#if dict_has_next>, </#if></#list></#if>],
|
||||
</#if>
|
||||
cruds() {
|
||||
return CRUD({ title: '${apiAlias}', url: 'api/${changeClassName}', idField: '${pkChangeColName}', sort: '${pkChangeColName},desc', crudMethod: { ...crud${className} }})
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
permission: {
|
||||
add: ['admin', '${changeClassName}:add'],
|
||||
edit: ['admin', '${changeClassName}:edit'],
|
||||
del: ['admin', '${changeClassName}:del']
|
||||
},
|
||||
rules: {
|
||||
<#if isNotNullColumns??>
|
||||
<#list isNotNullColumns as column>
|
||||
<#if column.istNotNull>
|
||||
${column.changeColumnName}: [
|
||||
{ required: true, message: '<#if column.remark != ''>${column.remark}</#if>不能为空', trigger: 'blur' }
|
||||
]<#if column_has_next>,</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
}<#if hasQuery>,
|
||||
queryTypeOptions: [
|
||||
<#if queryColumns??>
|
||||
<#list queryColumns as column>
|
||||
<#if column.queryType != 'BetWeen'>
|
||||
{ key: '${column.changeColumnName}', display_name: '<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>' }<#if column_has_next>,</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
]
|
||||
</#if>
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 钩子:在获取表格数据之前执行,false 则代表不获取数据
|
||||
[CRUD.HOOK.beforeRefresh]() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user