forked from qiushanhe/dm-manage-web
Merge pull request 'dev-zcx' (#12) from dev-zcx into master
Reviewed-on: http://114.55.169.15:3000/qiushanhe/dm-manage-web/pulls/12dev-qsh
commit
ca533e85e3
@ -1,8 +1,8 @@ |
||||
# 页面标题 |
||||
VUE_APP_TITLE = 对嘛管理系统 |
||||
VUE_APP_TITLE = 莳松管理系统 |
||||
|
||||
# 生产环境配置 |
||||
ENV = 'production' |
||||
|
||||
# 对嘛管理系统/生产环境 |
||||
# 莳松管理系统/生产环境 |
||||
VUE_APP_BASE_API = '/duima' |
||||
|
||||
@ -1,10 +1,10 @@ |
||||
# 页面标题 |
||||
VUE_APP_TITLE = 对嘛管理系统 |
||||
VUE_APP_TITLE = 莳松管理系统 |
||||
|
||||
NODE_ENV = production |
||||
|
||||
# 测试环境配置 |
||||
ENV = 'staging' |
||||
|
||||
# 对嘛管理系统/测试环境 |
||||
# 莳松管理系统/测试环境 |
||||
VUE_APP_BASE_API = '/stage-api' |
||||
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
@ -0,0 +1,54 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询报销列表
|
||||
export function listExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/account/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 新增报销
|
||||
export function addExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/account', |
||||
method: 'post', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 修改报销
|
||||
export function updateExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/account', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 删除报销
|
||||
export function removeExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/account/' + data, |
||||
method: 'delete' |
||||
}); |
||||
} |
||||
|
||||
// 导出报销
|
||||
export function exportExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/account/export', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 审核报销
|
||||
export function checkExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/account/check', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询报销列表
|
||||
export function listExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/meituan/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 新增报销
|
||||
export function addExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/meituan', |
||||
method: 'post', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 修改报销
|
||||
export function updateExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/meituan', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 删除报销
|
||||
export function removeExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/meituan/' + data, |
||||
method: 'delete' |
||||
}); |
||||
} |
||||
|
||||
// 导出报销
|
||||
export function exportExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/meituan/export', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 审核报销
|
||||
export function checkExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/meituan/check', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询报销列表
|
||||
export function listExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/office/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 新增报销
|
||||
export function addExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/office', |
||||
method: 'post', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 修改报销
|
||||
export function updateExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/office', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 删除报销
|
||||
export function removeExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/office/remove/' + data, |
||||
method: 'delete' |
||||
}); |
||||
} |
||||
|
||||
// 导出报销
|
||||
export function exportExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/office/export', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 审核报销
|
||||
export function checkExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/office/check', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询报销列表
|
||||
export function listExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/placeSign/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 新增报销
|
||||
export function addExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/placeSign', |
||||
method: 'post', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 修改报销
|
||||
export function updateExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/placeSign', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 删除报销
|
||||
export function removeExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/placeSign/' + data, |
||||
method: 'delete' |
||||
}); |
||||
} |
||||
|
||||
// 导出报销
|
||||
export function exportExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/placeSign/export', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 审核报销
|
||||
export function checkExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/placeSign/check', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询报销列表
|
||||
export function listExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/sign/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 新增报销
|
||||
export function addExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/sign', |
||||
method: 'post', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 修改报销
|
||||
export function updateExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/sign', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
|
||||
// 删除报销
|
||||
export function removeExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/sign/remove/' + data, |
||||
method: 'delete' |
||||
}); |
||||
} |
||||
|
||||
// 导出报销
|
||||
export function exportExpense(query) { |
||||
return request({ |
||||
url: '/finance/expense/sign/export', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
||||
// 审核报销
|
||||
export function checkExpense(data) { |
||||
return request({ |
||||
url: '/finance/expense/sign/check', |
||||
method: 'put', |
||||
data: data |
||||
}); |
||||
} |
||||
@ -0,0 +1,56 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
// 获取首页统计信息
|
||||
export function getCount() { |
||||
return request({ |
||||
url: '/system/home/count', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function getTodayPeopleRange() { |
||||
return request({ |
||||
url: '/system/home/range/today', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function getMonthPeopleRange() { |
||||
return request({ |
||||
url: '/system/home/range/month', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
//查询成交率
|
||||
export function dealRate() { |
||||
return request({ |
||||
url: '/system/home/rate/total', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
|
||||
|
||||
//查询本月成交率
|
||||
export function getMonthDealRateRange() { |
||||
return request({ |
||||
url: '/system/home/rate/month', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
//查询上月成交率
|
||||
export function getLastDealRateRange() { |
||||
return request({ |
||||
url: '/system/home/rate/last', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
//查询考勤异常信息
|
||||
export function getCheckin() { |
||||
return request({ |
||||
url: '/system/home/checkin', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询场地学员统计
|
||||
export function listReport(query) { |
||||
return request({ |
||||
url: '/statistic/area/student/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
import request from '@/utils/request'; |
||||
|
||||
// 查询场地学员统计
|
||||
export function listReport(query) { |
||||
return request({ |
||||
url: '/statistic/place/student/list', |
||||
method: 'get', |
||||
params: query |
||||
}); |
||||
} |
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
@ -0,0 +1,111 @@ |
||||
<template> |
||||
<div :class="className" :style="{height:height,width:width}" /> |
||||
</template> |
||||
|
||||
<script> |
||||
import echarts from 'echarts'; |
||||
require('echarts/theme/macarons'); // echarts theme |
||||
import resize from './mixins/resize'; |
||||
|
||||
const animationDuration = 6000; |
||||
|
||||
export default { |
||||
mixins: [resize], |
||||
props: { |
||||
className: { |
||||
type: String, |
||||
default: 'chart' |
||||
}, |
||||
width: { |
||||
type: String, |
||||
default: '100%' |
||||
}, |
||||
height: { |
||||
type: String, |
||||
default: '300px' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
chart: null |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.$nextTick(() => { |
||||
this.initChart(); |
||||
}); |
||||
}, |
||||
beforeDestroy() { |
||||
if (!this.chart) { |
||||
return; |
||||
} |
||||
this.chart.dispose(); |
||||
this.chart = null; |
||||
}, |
||||
methods: { |
||||
initChart() { |
||||
this.chart = echarts.init(this.$el, 'macarons'); |
||||
|
||||
this.chart.setOption({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
// 坐标轴指示器,坐标轴触发有效 |
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' |
||||
} |
||||
}, |
||||
grid: { |
||||
top: 10, |
||||
left: '2%', |
||||
right: '2%', |
||||
bottom: '3%', |
||||
containLabel: true |
||||
}, |
||||
xAxis: [ |
||||
{ |
||||
type: 'category', |
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
||||
axisTick: { |
||||
alignWithLabel: true |
||||
} |
||||
} |
||||
], |
||||
yAxis: [ |
||||
{ |
||||
type: 'value', |
||||
axisTick: { |
||||
show: false |
||||
} |
||||
} |
||||
], |
||||
series: [ |
||||
{ |
||||
name: 'pageA', |
||||
type: 'bar', |
||||
stack: 'vistors', |
||||
barWidth: '60%', |
||||
data: [79, 52, 200, 334, 390, 330, 220], |
||||
animationDuration |
||||
}, |
||||
{ |
||||
name: 'pageB', |
||||
type: 'bar', |
||||
stack: 'vistors', |
||||
barWidth: '60%', |
||||
data: [80, 52, 200, 334, 390, 330, 220], |
||||
animationDuration |
||||
}, |
||||
{ |
||||
name: 'pageC', |
||||
type: 'bar', |
||||
stack: 'vistors', |
||||
barWidth: '60%', |
||||
data: [30, 52, 200, 334, 390, 330, 220], |
||||
animationDuration |
||||
} |
||||
] |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
@ -1,111 +1,101 @@ |
||||
<template> |
||||
<div :class="className" :style="{height:height,width:width}" /> |
||||
<div class="chart" style="height:200px;width:100%;" /> |
||||
</template> |
||||
|
||||
<script> |
||||
import echarts from 'echarts'; |
||||
require('echarts/theme/macarons'); // echarts theme |
||||
import resize from './mixins/resize'; |
||||
import * as echarts from 'echarts' |
||||
require('echarts/theme/macarons') // echarts theme |
||||
import resize from './mixins/resize' |
||||
import { getTodayPeopleRange, getMonthPeopleRange } from '@/api/home' |
||||
|
||||
const animationDuration = 6000; |
||||
const animationDuration = 6000 |
||||
|
||||
export default { |
||||
mixins: [resize], |
||||
props: { |
||||
className: { |
||||
type: String, |
||||
default: 'chart' |
||||
}, |
||||
width: { |
||||
type: String, |
||||
default: '100%' |
||||
}, |
||||
height: { |
||||
type: String, |
||||
default: '300px' |
||||
} |
||||
}, |
||||
// props: { |
||||
// className: { |
||||
// type: String, |
||||
// default: 'chart' |
||||
// }, |
||||
// width: { |
||||
// type: String, |
||||
// default: '100%' |
||||
// }, |
||||
// height: { |
||||
// type: String, |
||||
// default: '300px' |
||||
// } |
||||
// }, |
||||
data() { |
||||
return { |
||||
chart: null |
||||
}; |
||||
chart: null, |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.$nextTick(() => { |
||||
this.initChart(); |
||||
}); |
||||
getTodayPeopleRange().then((resp) => { |
||||
this.initChart(resp.data) |
||||
}) |
||||
}) |
||||
}, |
||||
beforeDestroy() { |
||||
if (!this.chart) { |
||||
return; |
||||
return |
||||
} |
||||
this.chart.dispose(); |
||||
this.chart = null; |
||||
this.chart.dispose() |
||||
this.chart = null |
||||
}, |
||||
methods: { |
||||
initChart() { |
||||
this.chart = echarts.init(this.$el, 'macarons'); |
||||
initChart(item) { |
||||
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
||||
this.chart.setOption({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
// 坐标轴指示器,坐标轴触发有效 |
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' |
||||
} |
||||
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow' |
||||
}, |
||||
}, |
||||
grid: { |
||||
top: 10, |
||||
left: '2%', |
||||
right: '2%', |
||||
bottom: '3%', |
||||
containLabel: true |
||||
containLabel: true, |
||||
}, |
||||
legend: { |
||||
data: ['人数'], |
||||
}, |
||||
xAxis: [ |
||||
{ |
||||
type: 'category', |
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
||||
axisTick: { |
||||
alignWithLabel: true |
||||
} |
||||
} |
||||
data: item.people, |
||||
// axisTick: { |
||||
// alignWithLabel: true |
||||
// } |
||||
}, |
||||
], |
||||
yAxis: [ |
||||
{ |
||||
type: 'value', |
||||
axisTick: { |
||||
show: false |
||||
} |
||||
} |
||||
// axisTick: { |
||||
// show: false |
||||
// } |
||||
}, |
||||
], |
||||
series: [ |
||||
{ |
||||
name: 'pageA', |
||||
name: '成交学员数', |
||||
type: 'bar', |
||||
stack: 'vistors', |
||||
barWidth: '60%', |
||||
data: [79, 52, 200, 334, 390, 330, 220], |
||||
animationDuration |
||||
// stack: 'vistors', |
||||
barWidth: 40, |
||||
data: item.data, |
||||
// animationDuration |
||||
}, |
||||
{ |
||||
name: 'pageB', |
||||
type: 'bar', |
||||
stack: 'vistors', |
||||
barWidth: '60%', |
||||
data: [80, 52, 200, 334, 390, 330, 220], |
||||
animationDuration |
||||
}, |
||||
{ |
||||
name: 'pageC', |
||||
type: 'bar', |
||||
stack: 'vistors', |
||||
barWidth: '60%', |
||||
data: [30, 52, 200, 334, 390, 330, 220], |
||||
animationDuration |
||||
} |
||||
] |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
], |
||||
}) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
@ -0,0 +1,102 @@ |
||||
<template> |
||||
<!-- 本月成交排行榜 --> |
||||
<div class="chart" style="height:200px;width:100%;" /> |
||||
</template> |
||||
|
||||
<script> |
||||
import * as echarts from 'echarts' |
||||
require('echarts/theme/macarons') // echarts theme |
||||
import resize from './mixins/resize' |
||||
import { getTodayPeopleRange, getMonthPeopleRange } from '@/api/home' |
||||
|
||||
const animationDuration = 6000 |
||||
|
||||
export default { |
||||
mixins: [resize], |
||||
// props: { |
||||
// className: { |
||||
// type: String, |
||||
// default: 'chart' |
||||
// }, |
||||
// width: { |
||||
// type: String, |
||||
// default: '100%' |
||||
// }, |
||||
// height: { |
||||
// type: String, |
||||
// default: '300px' |
||||
// } |
||||
// }, |
||||
data() { |
||||
return { |
||||
chart: null, |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.$nextTick(() => { |
||||
getMonthPeopleRange().then((resp) => { |
||||
this.initChart(resp.data) |
||||
}) |
||||
}) |
||||
}, |
||||
beforeDestroy() { |
||||
if (!this.chart) { |
||||
return |
||||
} |
||||
this.chart.dispose() |
||||
this.chart = null |
||||
}, |
||||
methods: { |
||||
initChart(item) { |
||||
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
||||
this.chart.setOption({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
// 坐标轴指示器,坐标轴触发有效 |
||||
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow' |
||||
}, |
||||
}, |
||||
grid: { |
||||
top: 10, |
||||
left: '2%', |
||||
right: '2%', |
||||
bottom: '3%', |
||||
containLabel: true, |
||||
}, |
||||
legend: { |
||||
data: ['人数'], |
||||
}, |
||||
xAxis: [ |
||||
{ |
||||
type: 'category', |
||||
data: item.people, |
||||
// axisTick: { |
||||
// alignWithLabel: true |
||||
// } |
||||
}, |
||||
], |
||||
yAxis: [ |
||||
{ |
||||
type: 'value', |
||||
// axisTick: { |
||||
// show: false |
||||
// } |
||||
}, |
||||
], |
||||
series: [ |
||||
{ |
||||
name: '成交学员数', |
||||
type: 'bar', |
||||
// stack: 'vistors', |
||||
barWidth: 40, |
||||
data: item.data, |
||||
// animationDuration |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
@ -0,0 +1,102 @@ |
||||
<template> |
||||
<!-- 本月成交排行榜 --> |
||||
<div class="chart" style="height:200px;width:100%;" /> |
||||
</template> |
||||
|
||||
<script> |
||||
import * as echarts from 'echarts' |
||||
require('echarts/theme/macarons') // echarts theme |
||||
import resize from './mixins/resize' |
||||
import { getMonthDealRateRange } from '@/api/home' |
||||
|
||||
const animationDuration = 6000 |
||||
|
||||
export default { |
||||
mixins: [resize], |
||||
// props: { |
||||
// className: { |
||||
// type: String, |
||||
// default: 'chart' |
||||
// }, |
||||
// width: { |
||||
// type: String, |
||||
// default: '100%' |
||||
// }, |
||||
// height: { |
||||
// type: String, |
||||
// default: '300px' |
||||
// } |
||||
// }, |
||||
data() { |
||||
return { |
||||
chart: null, |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.$nextTick(() => { |
||||
getMonthDealRateRange().then((resp) => { |
||||
this.initChart(resp.data) |
||||
}) |
||||
}) |
||||
}, |
||||
beforeDestroy() { |
||||
if (!this.chart) { |
||||
return |
||||
} |
||||
this.chart.dispose() |
||||
this.chart = null |
||||
}, |
||||
methods: { |
||||
initChart(item) { |
||||
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
||||
this.chart.setOption({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
// 坐标轴指示器,坐标轴触发有效 |
||||
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow' |
||||
}, |
||||
}, |
||||
grid: { |
||||
top: 10, |
||||
left: '2%', |
||||
right: '2%', |
||||
bottom: '3%', |
||||
containLabel: true, |
||||
}, |
||||
legend: { |
||||
data: ['成交率'], |
||||
}, |
||||
xAxis: [ |
||||
{ |
||||
type: 'category', |
||||
data: item.people, |
||||
// axisTick: { |
||||
// alignWithLabel: true |
||||
// } |
||||
}, |
||||
], |
||||
yAxis: [ |
||||
{ |
||||
type: 'value', |
||||
// axisTick: { |
||||
// show: false |
||||
// } |
||||
}, |
||||
], |
||||
series: [ |
||||
{ |
||||
name: '成交率', |
||||
type: 'bar', |
||||
// stack: 'vistors', |
||||
barWidth: 40, |
||||
data: item.data, |
||||
// animationDuration |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
@ -0,0 +1,102 @@ |
||||
<template> |
||||
<!-- 本月成交排行榜 --> |
||||
<div class="chart" style="height:200px;width:100%;" /> |
||||
</template> |
||||
|
||||
<script> |
||||
import * as echarts from 'echarts' |
||||
require('echarts/theme/macarons') // echarts theme |
||||
import resize from './mixins/resize' |
||||
import { getLastDealRateRange } from '@/api/home' |
||||
|
||||
const animationDuration = 6000 |
||||
|
||||
export default { |
||||
mixins: [resize], |
||||
// props: { |
||||
// className: { |
||||
// type: String, |
||||
// default: 'chart' |
||||
// }, |
||||
// width: { |
||||
// type: String, |
||||
// default: '100%' |
||||
// }, |
||||
// height: { |
||||
// type: String, |
||||
// default: '300px' |
||||
// } |
||||
// }, |
||||
data() { |
||||
return { |
||||
chart: null, |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.$nextTick(() => { |
||||
getLastDealRateRange().then((resp) => { |
||||
this.initChart(resp.data) |
||||
}) |
||||
}) |
||||
}, |
||||
beforeDestroy() { |
||||
if (!this.chart) { |
||||
return |
||||
} |
||||
this.chart.dispose() |
||||
this.chart = null |
||||
}, |
||||
methods: { |
||||
initChart(item) { |
||||
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
||||
this.chart.setOption({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
// 坐标轴指示器,坐标轴触发有效 |
||||
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow' |
||||
}, |
||||
}, |
||||
grid: { |
||||
top: 10, |
||||
left: '2%', |
||||
right: '2%', |
||||
bottom: '3%', |
||||
containLabel: true, |
||||
}, |
||||
legend: { |
||||
data: ['成交率'], |
||||
}, |
||||
xAxis: [ |
||||
{ |
||||
type: 'category', |
||||
data: item.people, |
||||
// axisTick: { |
||||
// alignWithLabel: true |
||||
// } |
||||
}, |
||||
], |
||||
yAxis: [ |
||||
{ |
||||
type: 'value', |
||||
// axisTick: { |
||||
// show: false |
||||
// } |
||||
}, |
||||
], |
||||
series: [ |
||||
{ |
||||
name: '成交率', |
||||
type: 'bar', |
||||
// stack: 'vistors', |
||||
barWidth: 40, |
||||
data: item.data, |
||||
// animationDuration |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
@ -1,24 +1,289 @@ |
||||
export const defaultColumns = { |
||||
1: [ |
||||
{ key: 0, prop: 'spotName', label: `报名点`, visible: true }, |
||||
{ key: 1, prop: 'expenseType', label: `报销款项`, visible: true }, |
||||
{ key: 2, prop: 'expenseTotal', label: `报销金额`, visible: true }, |
||||
{ key: 3, prop: 'applyUser', label: `申请人`, visible: true }, |
||||
{ key: 4, prop: 'applyDate', label: `申请时间`, visible: true }, |
||||
{ key: 5, prop: 'applyRemark', label: `申请备注`, visible: true }, |
||||
{ key: 6, prop: 'auditStatus', label: `审批状态`, visible: true }, |
||||
{ key: 7, prop: 'auditUser', label: `审批人`, visible: true }, |
||||
{ key: 8, prop: 'auditDate', label: `审批时间`, visible: true } |
||||
1: [{ |
||||
key: 0, |
||||
prop: 'spotName', |
||||
label: `报名点`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销款项`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'expenseTotal', |
||||
label: `报销金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'applyUser', |
||||
label: `申请人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'applyDate', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'applyRemark', |
||||
label: `申请备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'auditStatus', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'auditUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'auditDate', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
], |
||||
2: [ |
||||
{ key: 0, prop: 'stuName', label: `成交学员`, visible: true }, |
||||
{ key: 1, prop: 'expenseType', label: `报销款项`, visible: true }, |
||||
{ key: 2, prop: 'expenseTotal', label: `报销金额`, visible: true }, |
||||
{ key: 3, prop: 'applyUser', label: `申请人`, visible: true }, |
||||
{ key: 4, prop: 'applyDate', label: `申请时间`, visible: true }, |
||||
{ key: 5, prop: 'applyRemark', label: `申请备注`, visible: true }, |
||||
{ key: 6, prop: 'auditStatus', label: `审批状态`, visible: true }, |
||||
{ key: 7, prop: 'auditUser', label: `审批人`, visible: true }, |
||||
{ key: 8, prop: 'auditDate', label: `审批时间`, visible: true } |
||||
2: [{ |
||||
key: 0, |
||||
prop: 'stuName', |
||||
label: `成交学员`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销款项`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'expenseTotal', |
||||
label: `报销金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'applyUser', |
||||
label: `申请人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'applyDate', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'applyRemark', |
||||
label: `申请备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'auditStatus', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'auditUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'auditDate', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
], |
||||
3: [{ |
||||
key: 0, |
||||
prop: 'shop', |
||||
label: `门店`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'expenseTotal', |
||||
label: `申请日期`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'applyUser', |
||||
label: `成交班型`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'applyDate', |
||||
label: `成交价格`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'applyDate1', |
||||
label: `实际入账`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'applyDate1', |
||||
label: `手续费`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'applyRemark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'auditStatus', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 9, |
||||
prop: 'auditUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 10, |
||||
prop: 'auditDate', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
], |
||||
4: [{ |
||||
key: 0, |
||||
prop: 'stuName', |
||||
label: `报销人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销款项`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'applyDate', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'expenseTotal', |
||||
label: `报销金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'applyUser', |
||||
label: `发票`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'applyRemark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'auditStatus', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'auditUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'auditDate', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
], |
||||
5: [{ |
||||
key: 0, |
||||
prop: 'stuName', |
||||
label: `报销人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销款项`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'applyDate', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'applyUser', |
||||
label: `充值对公账号`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'expenseTotal', |
||||
label: `报销金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'applyRemark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'auditStatus', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'auditUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'auditDate', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
] |
||||
}; |
||||
|
||||
@ -0,0 +1,151 @@ |
||||
<template> |
||||
<el-dialog v-if="show" title="账户充值报销" :visible.sync="show" width="500px"> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> |
||||
<el-form-item label="报销人" prop="createUser"> |
||||
<el-select v-model="form.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销项目" prop="expenseType"> |
||||
<el-input v-model="form.expenseType" placeholder="请输入" /> |
||||
</el-form-item> |
||||
<el-form-item label="日期" prop="expenseDate"> |
||||
<el-date-picker v-model="form.expenseDate" value-format="yyyy-MM-dd" type="date" /> |
||||
</el-form-item> |
||||
<el-form-item label="对公账户" prop="account"> |
||||
<el-input v-model="form.account" placeholder="请输入" /> |
||||
</el-form-item> |
||||
<el-form-item label="报销金额" prop="money"> |
||||
<el-input v-model="form.money" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<span slot="footer"> |
||||
<!--有权限 且 新增或修改时展示 --> |
||||
<!-- <el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(0)">保存</el-button> --> |
||||
<el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(1)">提交</el-button> |
||||
<!--有权限 且 审核时展示 --> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(2)">通过</el-button> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(3)">驳回</el-button> |
||||
<el-button @click="show = false">关闭</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import { addExpense, updateExpense, checkExpense } from '@/api/finance/expense/accountExpense' |
||||
|
||||
export default { |
||||
props: { |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
show: false, |
||||
showColumns: [], |
||||
userId: localStorage.getItem('userId'), |
||||
form: { |
||||
createUser: undefined, |
||||
expenseDate: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0 |
||||
}, |
||||
rules: { |
||||
createUser: { required: true, message: '请选择', trigger: 'blur' }, |
||||
expenseType: { required: true, message: '请输入', trigger: 'blur' }, |
||||
expenseDate: { required: true, message: '请输入', trigger: 'blur' }, |
||||
money: { required: true, message: '请输入', trigger: 'blur' }, |
||||
account: { required: true, message: '请输入', trigger: 'blur' } |
||||
}, |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(data) { |
||||
this.$nextTick(() => { |
||||
this.resetForm(); |
||||
if (data) { |
||||
this.form = this.deepClone(data); |
||||
// this.$refs['form'].resetFields(); |
||||
} |
||||
this.show = true |
||||
}); |
||||
}, |
||||
resetForm() { |
||||
this.form = { |
||||
createUser: this.userId, |
||||
expenseDate: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0 |
||||
} |
||||
}, |
||||
handleSave(state) { |
||||
this.form.state = state; |
||||
this.$refs.form.validate(async valid => { |
||||
if (valid) { |
||||
|
||||
if (state == 1) { |
||||
this.$confirm('提交后将进入审核阶段,是否提交确认提交?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
this.handleExpenseSave(); |
||||
}) |
||||
.catch(function () { }); |
||||
} else { |
||||
this.handleExpenseSave(); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
handleExpenseSave() { |
||||
// 提交申请 |
||||
if (this.form.expenseId) { |
||||
updateExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('修改成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} else { |
||||
addExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('新增成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
|
||||
handleCheck(state) { |
||||
this.form.state = state; |
||||
checkExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('审核成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
}, |
||||
|
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,46 @@ |
||||
<template> |
||||
<el-form ref="searchForm" :model="searchForm" inline label-width="100px"> |
||||
<el-form-item label="报销人:" label-width="90px"> |
||||
<el-select v-model="searchForm.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销时间:"> |
||||
<el-date-picker v-model="searchForm.createTimeRange" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="$emit('update:value', searchForm)" /> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
value: { |
||||
type: Object, |
||||
default: () => ({}) |
||||
}, |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: {} |
||||
}; |
||||
}, |
||||
watch: { |
||||
value: { |
||||
handler(val) { |
||||
this.searchForm = this.deepClone(val); |
||||
}, |
||||
deep: true, |
||||
immediate: true |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
@ -0,0 +1,61 @@ |
||||
export const defaultColumns = [{ |
||||
key: 0, |
||||
prop: 'createUserName', |
||||
label: `姓名`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销项目`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'expenseDate', |
||||
label: `日期`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'account', |
||||
label: `充值对公账号`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'money', |
||||
label: `报销金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'remark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'createTime', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'state', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'checkUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 9, |
||||
prop: 'checkTime', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
] |
||||
@ -0,0 +1,142 @@ |
||||
<template> |
||||
<div> |
||||
<SearchForm v-show="showSearch" :value.sync="searchForm" ref="SearchForm" @search="_getTableList" :userOptions="userOptions" /> |
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="primary" plain icon="el-icon-plus" v-hasPermi="['finance:expense:account:add']" @click="handleDialog(null)">新增</el-button> |
||||
<el-button type="warning" icon="el-icon-download" v-hasPermi="['finance:expense:account:export']" @click="handleExport">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :show-search.sync="showSearch" :columns="columns" @queryTable="_getTableList" /> |
||||
</el-row> |
||||
<el-table :data="tableList"> |
||||
<el-table-column type="selection" width="50" align="center" /> |
||||
<template v-for="item in columns"> |
||||
<el-table-column v-if="item.visible && item.prop != 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop" /> |
||||
<el-table-column v-if="item.visible && item.prop == 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop"> |
||||
<template scope="scope"> |
||||
<el-tag v-if="scope.row.state == 0">保存中</el-tag> |
||||
<el-tag type="warning" v-if="scope.row.state == 1">待审核</el-tag> |
||||
<el-tag type="success" v-if="scope.row.state == 2">已审核</el-tag> |
||||
<el-tag type="danger" v-if="scope.row.state == 3">驳回</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
</template> |
||||
<el-table-column label="操作" fixed="right" align="center" width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="handleDialog(scope.row)">详情</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 1" v-hasPermi="['finance:expense:account:check']" @click="handleDialog(scope.row)">审核</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 0" v-hasPermi="['finance:expense:account:remove']" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<pagination :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
<AccountDialog ref="AccountDialog" @refreshDataList="_getTableList" :userOptions="userOptions" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SearchForm from './SearchForm.vue'; |
||||
import AccountDialog from './AccountDialog.vue'; |
||||
import { defaultColumns } from './columns.js'; |
||||
import empApi from '@/api/system/employee'; |
||||
|
||||
|
||||
import { listExpense, removeExpense, exportExpense } from '@/api/finance/expense/accountExpense' |
||||
|
||||
export default { |
||||
// name: "AccountExpense", |
||||
components: { |
||||
SearchForm, AccountDialog |
||||
}, |
||||
props: { |
||||
type: { |
||||
type: String, |
||||
default: '1' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
createUser: undefined, |
||||
createTimeRange: [], |
||||
pageNum: 1, |
||||
pageSize: 20 |
||||
}, |
||||
showSearch: true, |
||||
tableList: [], |
||||
total: 0, |
||||
columns: [], |
||||
userOptions: [] |
||||
}; |
||||
}, |
||||
watch: { |
||||
type: { |
||||
handler() { |
||||
this.columns = defaultColumns |
||||
this._getTableList(); |
||||
this.getEmployee() |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
methods: { |
||||
async _getTableList() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
// api.list(params) |
||||
listExpense(params).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.tableList = resp.rows |
||||
this.total = resp.total |
||||
} |
||||
}) |
||||
// this.tableList = []; |
||||
// for (let i = 0; i < 20; i++) { |
||||
// this.tableList.push({ applyUser: `数据${i + 1}` }); |
||||
// } |
||||
}, |
||||
handleDialog(row) { |
||||
this.$refs.AccountDialog && this.$refs.AccountDialog.init(row); |
||||
}, |
||||
//删除 |
||||
handleDelete(item) { |
||||
this.$confirm('是否确认删除该条报销(“' + item.expenseType + '/' + item.expenseDate + '”)?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
removeExpense(item.expenseId).then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.$message.success('删除成功'); |
||||
this._getTableList(); |
||||
} |
||||
}); |
||||
}) |
||||
.catch(function () { }); |
||||
}, |
||||
handleExport() { |
||||
this.$confirm('是否确认导出所查询报销信息项?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(async () => { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
this.download('finance/expense/account/export', tempForm, `账户充值报销信息_${new Date().getTime()}.xlsx`); |
||||
}); |
||||
}, |
||||
getEmployee() { |
||||
empApi.getEmployee().then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.userOptions = resp.data; |
||||
} |
||||
}); |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,179 @@ |
||||
<template> |
||||
<el-dialog v-if="show" title="美团刷单报销" :visible.sync="show" width="500px"> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> |
||||
<el-form-item label="门店" prop="shop"> |
||||
<el-input v-model="form.shop" placeholder="请输入" /> |
||||
</el-form-item> |
||||
<el-form-item label="报销人" prop="createUser"> |
||||
<el-select v-model="form.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="日期" prop="expenseDate"> |
||||
<el-date-picker v-model="form.expenseDate" value-format="yyyy-MM-dd" type="date" /> |
||||
</el-form-item> |
||||
<el-form-item label="成交班型" prop="signClass"> |
||||
<el-input v-model="form.signClass" placeholder="请输入" /> |
||||
|
||||
<!-- <el-select v-model="form.typeId" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in classTypeOptions" :key="dict.typeId" :label="dict.schoolName +'-'+ dict.placeName +'-'+ dict.typeName" :value="dict.typeId" /> |
||||
</el-select> --> |
||||
</el-form-item> |
||||
<el-form-item label="成交价格" prop="signPrice"> |
||||
<el-input v-model="form.signPrice" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="实际入账" prop="actualEntry"> |
||||
<el-input v-model="form.actualEntry" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="手续费" prop="commission"> |
||||
<el-input v-model="form.commission" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<span slot="footer"> |
||||
<!--有权限 且 新增或修改时展示 --> |
||||
<!-- <el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(0)">保存</el-button> --> |
||||
<el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(1)">提交</el-button> |
||||
<!--有权限 且 审核时展示 --> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(2)">通过</el-button> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(3)">驳回</el-button> |
||||
<el-button @click="show = false">关闭</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import { addExpense, updateExpense, checkExpense } from '@/api/finance/expense/meituanExpense' |
||||
import { getClassTypeTableList } from '@/api/sch/classType'; |
||||
|
||||
|
||||
export default { |
||||
props: { |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
userId: localStorage.getItem('userId'), |
||||
show: false, |
||||
showColumns: [], |
||||
form: { |
||||
createUser: undefined, |
||||
expenseDate: undefined, |
||||
shop: undefined, |
||||
typeId: undefined, |
||||
signPrice: undefined, |
||||
actualEntry: undefined, |
||||
commission: undefined, |
||||
remark: undefined, |
||||
state: 0 |
||||
}, |
||||
rules: { |
||||
createUser: { required: true, message: '请选择', trigger: 'blur' }, |
||||
shop: { required: true, message: '请输入', trigger: 'blur' }, |
||||
expenseDate: { required: true, message: '请输入', trigger: 'blur' }, |
||||
signClass: { required: true, message: '请输入', trigger: 'blur' }, |
||||
signPrice: { required: true, message: '请输入', trigger: 'blur' }, |
||||
actualEntry: { required: true, message: '请输入', trigger: 'blur' }, |
||||
commission: { required: true, message: '请输入', trigger: 'blur' } |
||||
}, |
||||
classTypeOptions: [] |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(data) { |
||||
this.getClassTypes() |
||||
this.$nextTick(() => { |
||||
this.resetForm(); |
||||
if (data) { |
||||
this.form = this.deepClone(data); |
||||
// this.$refs['form'].resetFields(); |
||||
} |
||||
this.show = true |
||||
}); |
||||
}, |
||||
resetForm() { |
||||
this.form = { |
||||
createUser: this.userId, |
||||
expenseDate: undefined, |
||||
shop: undefined, |
||||
typeId: undefined, |
||||
signPrice: undefined, |
||||
actualEntry: undefined, |
||||
commission: undefined, |
||||
remark: undefined, |
||||
state: 0 |
||||
} |
||||
}, |
||||
handleSave(state) { |
||||
this.form.state = state; |
||||
this.$refs.form.validate(async valid => { |
||||
if (valid) { |
||||
|
||||
if (state == 1) { |
||||
this.$confirm('提交后将进入审核阶段,是否提交确认提交?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
this.handleExpenseSave(); |
||||
}) |
||||
.catch(function () { }); |
||||
} else { |
||||
this.handleExpenseSave(); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
handleExpenseSave() { |
||||
// 提交申请 |
||||
if (this.form.expenseId) { |
||||
updateExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('修改成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} else { |
||||
addExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('新增成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
|
||||
handleCheck(state) { |
||||
this.form.state = state; |
||||
checkExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('审核成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
}, |
||||
getClassTypes() { |
||||
getClassTypeTableList({}).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.classTypeOptions = resp.rows; |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,49 @@ |
||||
<template> |
||||
<el-form ref="searchForm" :model="searchForm" inline label-width="100px"> |
||||
<el-form-item label="门店" label-width="90px"> |
||||
<el-input v-model="searchForm.shop" placeholder="请输入" /> |
||||
</el-form-item> |
||||
<el-form-item label="报销人:" label-width="90px"> |
||||
<el-select v-model="searchForm.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销时间:"> |
||||
<el-date-picker v-model="searchForm.createTimeRange" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="$emit('update:value', searchForm)" /> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
value: { |
||||
type: Object, |
||||
default: () => ({}) |
||||
}, |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: {} |
||||
}; |
||||
}, |
||||
watch: { |
||||
value: { |
||||
handler(val) { |
||||
this.searchForm = this.deepClone(val); |
||||
}, |
||||
deep: true, |
||||
immediate: true |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
@ -0,0 +1,73 @@ |
||||
export const defaultColumns = [{ |
||||
key: 0, |
||||
prop: 'shop', |
||||
label: `门店`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'createUserName', |
||||
label: `报销人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'expenseDate', |
||||
label: `日期`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'signClass', |
||||
label: `成交班型`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'signPrice', |
||||
label: `报销金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'actualEntry', |
||||
label: `实际入账`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'commission', |
||||
label: `手续费`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'remark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'createTime', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'state', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 9, |
||||
prop: 'checkUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 10, |
||||
prop: 'checkTime', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
] |
||||
@ -0,0 +1,143 @@ |
||||
<template> |
||||
<div> |
||||
<SearchForm v-show="showSearch" :value.sync="searchForm" ref="SearchForm" @search="_getTableList" :userOptions="userOptions" /> |
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="primary" plain icon="el-icon-plus" v-hasPermi="['finance:expense:meituan:add']" @click="handleDialog(null)">新增</el-button> |
||||
<el-button type="warning" icon="el-icon-download" v-hasPermi="['finance:expense:meituan:export']" @click="handleExport">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :show-search.sync="showSearch" :columns="columns" @queryTable="_getTableList" /> |
||||
</el-row> |
||||
<el-table :data="tableList"> |
||||
<el-table-column type="selection" width="50" align="center" /> |
||||
<template v-for="item in columns"> |
||||
<el-table-column v-if="item.visible && item.prop != 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop" /> |
||||
<el-table-column v-if="item.visible && item.prop == 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop"> |
||||
<template slot-scope="scope"> |
||||
<el-tag v-if="scope.row.state == 0">保存中</el-tag> |
||||
<el-tag type="warning" v-if="scope.row.state == 1">待审核</el-tag> |
||||
<el-tag type="success" v-if="scope.row.state == 2">已审核</el-tag> |
||||
<el-tag type="danger" v-if="scope.row.state == 3">驳回</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
</template> |
||||
<el-table-column label="操作" fixed="right" align="center" width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="handleDialog(scope.row)">详情</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 1" v-hasPermi="['finance:expense:meituan:check']" @click="handleDialog(scope.row)">审核</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 0" v-hasPermi="['finance:expense:meituan:remove']" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<pagination :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
<MeituanDialog ref="MeituanDialog" @refreshDataList="_getTableList" :userOptions="userOptions" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SearchForm from './SearchForm.vue'; |
||||
import MeituanDialog from './MeituanDialog.vue'; |
||||
import { defaultColumns } from './columns.js'; |
||||
import empApi from '@/api/system/employee'; |
||||
|
||||
|
||||
import { listExpense, removeExpense, exportExpense } from '@/api/finance/expense/meituanExpense' |
||||
|
||||
export default { |
||||
// name: "AccountExpense", |
||||
components: { |
||||
SearchForm, MeituanDialog |
||||
}, |
||||
props: { |
||||
type: { |
||||
type: String, |
||||
default: '1' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
createUser: undefined, |
||||
createTimeRange: [], |
||||
shop: undefined, |
||||
pageNum: 1, |
||||
pageSize: 20 |
||||
}, |
||||
showSearch: true, |
||||
tableList: [], |
||||
total: 0, |
||||
columns: [], |
||||
userOptions: [] |
||||
}; |
||||
}, |
||||
watch: { |
||||
type: { |
||||
handler() { |
||||
this.columns = defaultColumns |
||||
this._getTableList(); |
||||
this.getEmployee() |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
methods: { |
||||
async _getTableList() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
// api.list(params) |
||||
listExpense(params).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.tableList = resp.rows |
||||
this.total = resp.total |
||||
} |
||||
}) |
||||
// this.tableList = []; |
||||
// for (let i = 0; i < 20; i++) { |
||||
// this.tableList.push({ applyUser: `数据${i + 1}` }); |
||||
// } |
||||
}, |
||||
handleDialog(row) { |
||||
this.$refs.MeituanDialog && this.$refs.MeituanDialog.init(row); |
||||
}, |
||||
//删除 |
||||
handleDelete(item) { |
||||
this.$confirm('是否确认删除该条报销(“' + item.shop + '/' + item.expenseDate + '”)?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
removeExpense(item.expenseId).then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.$message.success('删除成功'); |
||||
this._getTableList(); |
||||
} |
||||
}); |
||||
}) |
||||
.catch(function () { }); |
||||
}, |
||||
handleExport() { |
||||
this.$confirm('是否确认导出所查询报销信息项?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(async () => { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
this.download('finance/expense/meituan/export', tempForm, `美团刷单报销信息_${new Date().getTime()}.xlsx`); |
||||
}); |
||||
}, |
||||
getEmployee() { |
||||
empApi.getEmployee().then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.userOptions = resp.data; |
||||
} |
||||
}); |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,190 @@ |
||||
<template> |
||||
<el-dialog v-if="show" title="办公费用报销" :visible.sync="show" width="500px"> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> |
||||
<el-form-item label="报销人" prop="createUser"> |
||||
<el-select v-model="form.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销项目" prop="expenseType"> |
||||
<el-input v-model="form.expenseType" placeholder="请输入" /> |
||||
</el-form-item> |
||||
<el-form-item label="日期" prop="expenseDate"> |
||||
<el-date-picker v-model="form.expenseDate" value-format="yyyy-MM-dd" type="date" /> |
||||
</el-form-item> |
||||
<el-form-item label="报销金额" prop="money"> |
||||
<el-input v-model="form.money" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="发票" prop="files"> |
||||
<el-upload class="avatar-uploader" accept="image/*" action="https://jsonplaceholder.typicode.com/posts/" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"> |
||||
<img v-if="form.files" :src="form.files" class="avatar"> |
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<span slot="footer"> |
||||
<!--有权限 且 新增或修改时展示 --> |
||||
<!-- <el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(0)">保存</el-button> --> |
||||
<el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(1)">提交</el-button> |
||||
<!--有权限 且 审核时展示 --> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(2)">通过</el-button> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(3)">驳回</el-button> |
||||
<el-button @click="show = false">关闭</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import { addExpense, updateExpense, checkExpense } from '@/api/finance/expense/officeExpense' |
||||
|
||||
export default { |
||||
props: { |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
show: false, |
||||
showColumns: [], |
||||
form: { |
||||
createUser: undefined, |
||||
expenseDate: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
files: undefined, |
||||
state: 0 |
||||
}, |
||||
rules: { |
||||
createUser: { required: true, message: '请选择', trigger: 'blur' }, |
||||
expenseType: { required: true, message: '请输入', trigger: 'blur' }, |
||||
expenseDate: { required: true, message: '请输入', trigger: 'blur' }, |
||||
money: { required: true, message: '请输入', trigger: 'blur' }, |
||||
account: { required: true, message: '请输入', trigger: 'blur' } |
||||
}, |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(data) { |
||||
this.$nextTick(() => { |
||||
this.resetForm(); |
||||
if (data) { |
||||
this.form = this.deepClone(data); |
||||
// this.$refs['form'].resetFields(); |
||||
} |
||||
this.show = true |
||||
}); |
||||
}, |
||||
resetForm() { |
||||
this.form = { |
||||
createUser: undefined, |
||||
expenseDate: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0 |
||||
} |
||||
}, |
||||
handleSave(state) { |
||||
this.form.state = state; |
||||
this.$refs.form.validate(async valid => { |
||||
if (valid) { |
||||
|
||||
if (state == 1) { |
||||
this.$confirm('提交后将进入审核阶段,是否提交确认提交?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
this.handleExpenseSave(); |
||||
}) |
||||
.catch(function () { }); |
||||
} else { |
||||
this.handleExpenseSave(); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
handleExpenseSave() { |
||||
// 提交申请 |
||||
if (this.form.expenseId) { |
||||
updateExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('修改成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} else { |
||||
addExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('新增成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
|
||||
handleCheck(state) { |
||||
this.form.state = state; |
||||
checkExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('审核成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
}, |
||||
handleAvatarSuccess(res, file) { |
||||
console.log(file) |
||||
this.form.files = URL.createObjectURL(file.raw); |
||||
}, |
||||
beforeAvatarUpload(file) { |
||||
const isLt2M = file.size / 1024 / 1024 < 10; |
||||
if (!isLt2M) { |
||||
this.$message.error('上传文件大小不能超过 10MB!'); |
||||
} |
||||
return isLt2M; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.avatar-uploader .el-upload { |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 6px; |
||||
cursor: pointer; |
||||
position: relative; |
||||
overflow: hidden; |
||||
} |
||||
.avatar-uploader .el-upload:hover { |
||||
border-color: #409eff; |
||||
} |
||||
.avatar-uploader-icon { |
||||
font-size: 28px; |
||||
color: #8c939d; |
||||
width: 178px; |
||||
height: 178px; |
||||
line-height: 178px; |
||||
text-align: center; |
||||
} |
||||
.avatar { |
||||
width: 178px; |
||||
height: 178px; |
||||
display: block; |
||||
} |
||||
</style> |
||||
|
||||
@ -0,0 +1,46 @@ |
||||
<template> |
||||
<el-form ref="searchForm" :model="searchForm" inline label-width="100px"> |
||||
<el-form-item label="报销人:" label-width="90px"> |
||||
<el-select v-model="searchForm.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销时间:"> |
||||
<el-date-picker v-model="searchForm.createTimeRange" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="$emit('update:value', searchForm)" /> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
value: { |
||||
type: Object, |
||||
default: () => ({}) |
||||
}, |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: {} |
||||
}; |
||||
}, |
||||
watch: { |
||||
value: { |
||||
handler(val) { |
||||
this.searchForm = this.deepClone(val); |
||||
}, |
||||
deep: true, |
||||
immediate: true |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
@ -0,0 +1,55 @@ |
||||
export const defaultColumns = [{ |
||||
key: 0, |
||||
prop: 'createUserName', |
||||
label: `报销人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'expenseType', |
||||
label: `报销项目`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'expenseDate', |
||||
label: `日期`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'money', |
||||
label: `金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'remark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'createTime', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'state', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'checkUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'checkTime', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
] |
||||
@ -0,0 +1,142 @@ |
||||
<template> |
||||
<div> |
||||
<SearchForm v-show="showSearch" :value.sync="searchForm" ref="SearchForm" @search="_getTableList" :userOptions="userOptions" /> |
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="primary" plain icon="el-icon-plus" v-hasPermi="['finance:expense:meituan:add']" @click="handleDialog(null)">新增</el-button> |
||||
<el-button type="warning" icon="el-icon-download" v-hasPermi="['finance:expense:meituan:export']" @click="handleExport">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :show-search.sync="showSearch" :columns="columns" @queryTable="_getTableList" /> |
||||
</el-row> |
||||
<el-table :data="tableList"> |
||||
<el-table-column type="selection" width="50" align="center" /> |
||||
<template v-for="item in columns"> |
||||
<el-table-column v-if="item.visible && item.prop != 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop" /> |
||||
<el-table-column v-if="item.visible && item.prop == 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop"> |
||||
<template scope="scope"> |
||||
<el-tag v-if="scope.row.state == 0">保存中</el-tag> |
||||
<el-tag type="warning" v-if="scope.row.state == 1">待审核</el-tag> |
||||
<el-tag type="success" v-if="scope.row.state == 2">已审核</el-tag> |
||||
<el-tag type="danger" v-if="scope.row.state == 3">驳回</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
</template> |
||||
<el-table-column label="操作" fixed="right" align="center" width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="handleDialog(scope.row)">详情</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 1" v-hasPermi="['finance:expense:meituan:check']" @click="handleDialog(scope.row)">审核</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 0" v-hasPermi="['finance:expense:meituan:remove']" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<pagination :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
<OfficeDialog ref="OfficeDialog" @refreshDataList="_getTableList" :userOptions="userOptions" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SearchForm from './SearchForm.vue'; |
||||
import OfficeDialog from './OfficeDialog.vue'; |
||||
import { defaultColumns } from './columns.js'; |
||||
import empApi from '@/api/system/employee'; |
||||
|
||||
|
||||
import { listExpense, removeExpense, exportExpense } from '@/api/finance/expense/officeExpense' |
||||
|
||||
export default { |
||||
// name: "AccountExpense", |
||||
components: { |
||||
SearchForm, OfficeDialog |
||||
}, |
||||
props: { |
||||
type: { |
||||
type: String, |
||||
default: '1' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
createUser: undefined, |
||||
createTimeRange: [], |
||||
pageNum: 1, |
||||
pageSize: 20 |
||||
}, |
||||
showSearch: true, |
||||
tableList: [], |
||||
total: 0, |
||||
columns: [], |
||||
userOptions: [] |
||||
}; |
||||
}, |
||||
watch: { |
||||
type: { |
||||
handler() { |
||||
this.columns = defaultColumns |
||||
this._getTableList(); |
||||
this.getEmployee() |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
methods: { |
||||
async _getTableList() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
// api.list(params) |
||||
listExpense(params).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.tableList = resp.rows |
||||
this.total = resp.total |
||||
} |
||||
}) |
||||
// this.tableList = []; |
||||
// for (let i = 0; i < 20; i++) { |
||||
// this.tableList.push({ applyUser: `数据${i + 1}` }); |
||||
// } |
||||
}, |
||||
handleDialog(row) { |
||||
this.$refs.OfficeDialog && this.$refs.OfficeDialog.init(row); |
||||
}, |
||||
//删除 |
||||
handleDelete(item) { |
||||
this.$confirm('是否确认删除该条报销(“' + item.expenseType + '/' + item.expenseDate + '”)?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
removeExpense(item.expenseId).then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.$message.success('删除成功'); |
||||
this._getTableList(); |
||||
} |
||||
}); |
||||
}) |
||||
.catch(function () { }); |
||||
}, |
||||
handleExport() { |
||||
this.$confirm('是否确认导出所查询报销信息项?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(async () => { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
this.download('finance/expense/office/export', tempForm, `办公费用报销信息_${new Date().getTime()}.xlsx`); |
||||
}); |
||||
}, |
||||
getEmployee() { |
||||
empApi.getEmployee().then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.userOptions = resp.data; |
||||
} |
||||
}); |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,216 @@ |
||||
<template> |
||||
<el-dialog v-if="show" title="报名点报销" :visible.sync="show" width="600px"> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> |
||||
<el-form-item label="检索"> |
||||
<el-autocomplete v-model="searchValue" :fetch-suggestions="querySearchAsync" style="width: 100%;" placeholder="请输入姓名/联系方式进行学员检索" @select="handleSelect"> |
||||
<template slot-scope="{ item }"> |
||||
<span class="name">{{ item.name }}</span> |
||||
<span class="addr">{{ item.phone }}</span> |
||||
</template> |
||||
</el-autocomplete> |
||||
</el-form-item> |
||||
<el-form-item label="姓名" prop="name"> |
||||
<el-input v-model="form.name" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="联系方式" prop="phone"> |
||||
<el-input v-model="form.phone" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="报名时间" prop="dealDate"> |
||||
<el-date-picker v-model="form.dealDate" value-format="yyyy-MM-dd" type="date" disabled></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="成交价格" prop="signPrice"> |
||||
<el-input v-model="form.signPrice" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="报名驾校" prop="schoolName"> |
||||
<el-input v-model="form.schoolName" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="班型" prop="className"> |
||||
<el-input v-model="form.className" placeholder="请输入" type="number" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="利润" prop="profit"> |
||||
<el-input v-model="form.profit" placeholder="请输入" type="number" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="额外支出项目" prop="expenseType"> |
||||
<el-select v-model="form.expenseType" placeholder="请选择" filterable clearable disabled> |
||||
<el-option v-for="dict in extraOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="额外支出金额" prop="money"> |
||||
<el-input v-model="form.money" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="学员归属" prop="followUser"> |
||||
<el-select v-model="form.followUser" placeholder="请选择" filterable clearable disabled> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<span slot="footer"> |
||||
<!--有权限 且 新增或修改时展示 --> |
||||
<!-- <el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(0)">保存</el-button> --> |
||||
<el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(1)">提交</el-button> |
||||
<!--有权限 且 审核时展示 --> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(2)">通过</el-button> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(3)">驳回</el-button> |
||||
<el-button @click="show = false">关闭</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import { addExpense, updateExpense, checkExpense } from '@/api/finance/expense/signExpense' |
||||
import { listSign } from '@/api/zs/placeSign' |
||||
|
||||
export default { |
||||
props: { |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
}, |
||||
extraOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
show: false, |
||||
showColumns: [], |
||||
searchValue: undefined, |
||||
form: { |
||||
signId: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0, |
||||
// 登记信息 |
||||
name: undefined, |
||||
phone: undefined, |
||||
dealDate: undefined, |
||||
signPrice: undefined, |
||||
schoolName: undefined, |
||||
className: undefined, |
||||
profit: undefined |
||||
|
||||
}, |
||||
rules: { |
||||
name: { required: true, message: '请输入', trigger: 'blur' }, |
||||
phone: { required: true, message: '请输入', trigger: 'blur' }, |
||||
expenseType: { required: true, message: '请输入', trigger: 'blur' }, |
||||
money: { required: true, message: '请输入', trigger: 'blur' }, |
||||
}, |
||||
restaurants: [], |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(data) { |
||||
this.$nextTick(() => { |
||||
this.resetForm(); |
||||
if (data) { |
||||
this.form = this.deepClone(data); |
||||
// this.$refs['form'].resetFields(); |
||||
} |
||||
this.show = true |
||||
}); |
||||
}, |
||||
resetForm() { |
||||
this.form = { |
||||
signId: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0, |
||||
name: undefined, |
||||
phone: undefined, |
||||
dealDate: undefined, |
||||
signPrice: undefined, |
||||
schoolName: undefined, |
||||
className: undefined, |
||||
profit: undefined |
||||
|
||||
} |
||||
}, |
||||
//检索查询登记信息 |
||||
async querySearchAsync(queryString, cb) { |
||||
if (queryString) { |
||||
const resp = listSign({ |
||||
name: queryString |
||||
}); |
||||
cb(resp.rows); |
||||
} |
||||
}, |
||||
//选择对应的查询结果 |
||||
handleSelect(item) { |
||||
this.$set(this.form, "signId", item.signId); |
||||
this.$set(this.form, "name", item.name); |
||||
this.$set(this.form, "phone", item.phone); |
||||
this.$set(this.form, "dealDate", item.dealDate); |
||||
this.$set(this.form, "signPrice", item.signPrice); |
||||
this.$set(this.form, "schoolName", item.schoolName); |
||||
this.$set(this.form, "className", item.className); |
||||
this.$set(this.form, "profit", item.profit); |
||||
}, |
||||
handleSave(state) { |
||||
this.form.state = state; |
||||
this.$refs.form.validate(async valid => { |
||||
if (valid) { |
||||
|
||||
if (state == 1) { |
||||
this.$confirm('提交后将进入审核阶段,是否提交确认提交?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
this.handleExpenseSave(); |
||||
}) |
||||
.catch(function () { }); |
||||
} else { |
||||
this.handleExpenseSave(); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
handleExpenseSave() { |
||||
// 提交申请 |
||||
if (this.form.expenseId) { |
||||
updateExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('修改成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} else { |
||||
addExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('新增成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
|
||||
handleCheck(state) { |
||||
this.form.state = state; |
||||
checkExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('审核成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
}, |
||||
|
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,55 @@ |
||||
<template> |
||||
<el-form ref="searchForm" :model="searchForm" inline label-width="100px"> |
||||
<el-form-item label="报名点:" label-width="90px"> |
||||
<el-select v-model="searchForm.signPlace" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in signPlaceOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销人:" label-width="90px"> |
||||
<el-select v-model="searchForm.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销时间:"> |
||||
<el-date-picker v-model="searchForm.createTimeRange" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="$emit('update:value', searchForm)" /> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
value: { |
||||
type: Object, |
||||
default: () => ({}) |
||||
}, |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
}, |
||||
signPlaceOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: {} |
||||
}; |
||||
}, |
||||
watch: { |
||||
value: { |
||||
handler(val) { |
||||
this.searchForm = this.deepClone(val); |
||||
}, |
||||
deep: true, |
||||
immediate: true |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
@ -0,0 +1,96 @@ |
||||
export const defaultColumns = [{ |
||||
key: 0, |
||||
prop: 'signPlace', |
||||
label: `报名点`, |
||||
visible: true |
||||
}, { |
||||
key: 1, |
||||
prop: 'name', |
||||
label: `姓名`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'phone', |
||||
label: `联系方式`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'dealDate', |
||||
label: `报名时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'signPrice', |
||||
label: `成交价`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'className', |
||||
label: `班型`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'schoolName', |
||||
label: `报名驾校`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'profit', |
||||
label: `利润`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'expenseType', |
||||
label: `额外支出项目`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 9, |
||||
prop: 'money', |
||||
label: `额外支出金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 10, |
||||
prop: 'followUserName', |
||||
label: `学员归属`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 11, |
||||
prop: 'remark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 12, |
||||
prop: 'createTime', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 13, |
||||
prop: 'state', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 14, |
||||
prop: 'checkUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 15, |
||||
prop: 'checkTime', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
] |
||||
@ -0,0 +1,155 @@ |
||||
<template> |
||||
<div> |
||||
<SearchForm v-show="showSearch" :value.sync="searchForm" ref="SearchForm" @search="_getTableList" :userOptions="userOptions" :signPlaceOptions="signPlaceOptions" /> |
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="primary" plain icon="el-icon-plus" v-hasPermi="['finance:expense:placeSign:add']" @click="handleDialog(null)">新增</el-button> |
||||
<el-button type="warning" icon="el-icon-download" v-hasPermi="['finance:expense:placeSign:export']" @click="handleExport">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :show-search.sync="showSearch" :columns="columns" @queryTable="_getTableList" /> |
||||
</el-row> |
||||
<el-table :data="tableList"> |
||||
<el-table-column type="selection" width="50" align="center" /> |
||||
<template v-for="item in columns"> |
||||
<el-table-column v-if="item.visible && item.prop != 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop" /> |
||||
<el-table-column v-if="item.visible && item.prop == 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop"> |
||||
<template scope="scope"> |
||||
<el-tag v-if="scope.row.state == 0">保存中</el-tag> |
||||
<el-tag type="warning" v-if="scope.row.state == 1">待审核</el-tag> |
||||
<el-tag type="success" v-if="scope.row.state == 2">已审核</el-tag> |
||||
<el-tag type="danger" v-if="scope.row.state == 3">驳回</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
</template> |
||||
<el-table-column label="操作" fixed="right" align="center" width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="handleDialog(scope.row)">详情</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 1" v-hasPermi="['finance:expense:placeSign:check']" @click="handleDialog(scope.row)">审核</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 0" v-hasPermi="['finance:expense:placeSign:remove']" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<pagination :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
<PlaceSignDialog ref="PlaceSignDialog" @refreshDataList="_getTableList" :userOptions="userOptions" :extraOptions="extraOptions" :signPlaceOptions="signPlaceOptions" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SearchForm from './SearchForm.vue'; |
||||
import PlaceSignDialog from './PlaceSignDialog.vue'; |
||||
import { defaultColumns } from './columns.js'; |
||||
import empApi from '@/api/system/employee'; |
||||
|
||||
import { listExpense, removeExpense, exportExpense } from '@/api/finance/expense/placeSignExpense' |
||||
|
||||
export default { |
||||
// name: "AccountExpense", |
||||
components: { |
||||
SearchForm, PlaceSignDialog |
||||
}, |
||||
props: { |
||||
type: { |
||||
type: String, |
||||
default: '1' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
createUser: undefined, |
||||
createTimeRange: [], |
||||
signPlace: undefined, |
||||
pageNum: 1, |
||||
pageSize: 20 |
||||
}, |
||||
showSearch: true, |
||||
tableList: [], |
||||
total: 0, |
||||
columns: [], |
||||
userOptions: [], |
||||
extraOptions: [], |
||||
signPlaceOptions: [] |
||||
|
||||
}; |
||||
}, |
||||
watch: { |
||||
type: { |
||||
handler() { |
||||
this.columns = defaultColumns |
||||
this._getTableList(); |
||||
this.getEmployee() |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
created() { |
||||
// 额外支出 |
||||
this.getDicts('dm_extra_pay').then((response) => { |
||||
this.extraOptions = response.data; |
||||
}); |
||||
// 报名点 |
||||
this.getDicts('sign_place').then((response) => { |
||||
this.signPlaceOptions = response.data; |
||||
}); |
||||
}, |
||||
methods: { |
||||
async _getTableList() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
// api.list(params) |
||||
listExpense(params).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.tableList = resp.rows |
||||
this.total = resp.total |
||||
} |
||||
}) |
||||
// this.tableList = []; |
||||
// for (let i = 0; i < 20; i++) { |
||||
// this.tableList.push({ applyUser: `数据${i + 1}` }); |
||||
// } |
||||
}, |
||||
handleDialog(row) { |
||||
this.$refs.PlaceSignDialog && this.$refs.PlaceSignDialog.init(row); |
||||
}, |
||||
//删除 |
||||
handleDelete(item) { |
||||
this.$confirm('是否确认删除该条线索(“' + item.expenseType + '/' + item.expenseDate + '”)?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
removeExpense(item.expenseId).then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.$message.success('删除成功'); |
||||
this._getTableList(); |
||||
} |
||||
}); |
||||
}) |
||||
.catch(function () { }); |
||||
}, |
||||
handleExport() { |
||||
this.$confirm('是否确认导出所查询学员信息项?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(async () => { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
this.download('finance/expense/account/export', tempForm, `账户充值报销信息_${new Date().getTime()}.xlsx`); |
||||
}); |
||||
}, |
||||
getEmployee() { |
||||
empApi.getEmployee().then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.userOptions = resp.data; |
||||
} |
||||
}); |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,46 @@ |
||||
<template> |
||||
<el-form ref="searchForm" :model="searchForm" inline label-width="100px"> |
||||
<el-form-item label="报销人:" label-width="90px"> |
||||
<el-select v-model="searchForm.createUser" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="报销时间:"> |
||||
<el-date-picker v-model="searchForm.createTimeRange" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="$emit('update:value', searchForm)" /> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
value: { |
||||
type: Object, |
||||
default: () => ({}) |
||||
}, |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: {} |
||||
}; |
||||
}, |
||||
watch: { |
||||
value: { |
||||
handler(val) { |
||||
this.searchForm = this.deepClone(val); |
||||
}, |
||||
deep: true, |
||||
immediate: true |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
@ -0,0 +1,217 @@ |
||||
<template> |
||||
<el-dialog v-if="show" title="成交登记报销" :visible.sync="show" width="500px"> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> |
||||
<el-form-item label="检索"> |
||||
<el-autocomplete v-model="searchValue" :fetch-suggestions="querySearchAsync" style="width: 100%;" placeholder="请输入姓名/联系方式进行学员检索" :trigger-on-focus="false" @select="handleSelect"> |
||||
<template slot-scope="{ item }"> |
||||
<span class="name">{{ item.name }}</span> |
||||
<span class="addr">/{{ item.phone }}</span> |
||||
</template> |
||||
</el-autocomplete> |
||||
</el-form-item> |
||||
<el-form-item label="姓名" prop="name"> |
||||
<el-input v-model="form.name" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="联系方式" prop="phone"> |
||||
<el-input v-model="form.phone" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="报名时间" prop="dealDate"> |
||||
<el-date-picker v-model="form.dealDate" value-format="yyyy-MM-dd" type="date" disabled></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="成交价格" prop="signPrice"> |
||||
<el-input v-model="form.signPrice" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="报名驾校" prop="schoolName"> |
||||
<el-input v-model="form.schoolName" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="班型" prop="className"> |
||||
<el-input v-model="form.className" placeholder="请输入" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="利润" prop="profit"> |
||||
<el-input v-model="form.profit" placeholder="请输入" type="number" disabled /> |
||||
</el-form-item> |
||||
<el-form-item label="额外支出项目" prop="expenseType"> |
||||
<el-select v-model="form.expenseType" placeholder="请选择" filterable clearable> |
||||
<el-option v-for="dict in extraOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="额外支出金额" prop="money"> |
||||
<el-input v-model="form.money" placeholder="请输入" type="number" /> |
||||
</el-form-item> |
||||
<el-form-item label="学员归属" prop="followUser"> |
||||
<el-select v-model="form.followUser" placeholder="请选择" multiple filterable clearable disabled> |
||||
<el-option v-for="dict in userOptions" :key="dict.id" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<span slot="footer"> |
||||
<!--有权限 且 新增或修改时展示 --> |
||||
<!-- <el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(0)">保存</el-button> --> |
||||
<el-button type="primary" v-if="form.state==0 || form.state==3" v-hasPermi="['finance:expense:account:add', 'finance:expense:account:edit']" @click="handleSave(1)">提交</el-button> |
||||
<!--有权限 且 审核时展示 --> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(2)">通过</el-button> |
||||
<el-button type="primary" v-if="form.state==1" v-hasPermi="['finance:expense:account:check']" @click="handleCheck(3)">驳回</el-button> |
||||
<el-button @click="show = false">关闭</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import { addExpense, updateExpense, checkExpense } from '@/api/finance/expense/signExpense' |
||||
import { getSignList } from '@/api/zs/sign' |
||||
|
||||
export default { |
||||
props: { |
||||
userOptions: { |
||||
type: Array, |
||||
default: [] |
||||
}, |
||||
extraOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
show: false, |
||||
showColumns: [], |
||||
searchValue: undefined, |
||||
form: { |
||||
signId: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0, |
||||
// 登记信息 |
||||
name: undefined, |
||||
phone: undefined, |
||||
dealDate: undefined, |
||||
signPrice: undefined, |
||||
schoolName: undefined, |
||||
className: undefined, |
||||
profit: undefined |
||||
|
||||
}, |
||||
rules: { |
||||
name: { required: true, message: '请输入', trigger: 'blur' }, |
||||
phone: { required: true, message: '请输入', trigger: 'blur' }, |
||||
expenseType: { required: true, message: '请输入', trigger: 'blur' }, |
||||
money: { required: true, message: '请输入', trigger: 'blur' }, |
||||
}, |
||||
restaurants: [], |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(data) { |
||||
this.$nextTick(() => { |
||||
this.resetForm(); |
||||
if (data) { |
||||
this.form = this.deepClone(data); |
||||
// this.$refs['form'].resetFields(); |
||||
} |
||||
this.show = true |
||||
}); |
||||
}, |
||||
resetForm() { |
||||
this.form = { |
||||
signId: undefined, |
||||
expenseType: undefined, |
||||
money: undefined, |
||||
remark: undefined, |
||||
state: 0, |
||||
name: undefined, |
||||
phone: undefined, |
||||
dealDate: undefined, |
||||
signPrice: undefined, |
||||
schoolName: undefined, |
||||
className: undefined, |
||||
profit: undefined |
||||
|
||||
} |
||||
}, |
||||
//检索查询登记信息 |
||||
async querySearchAsync(queryString, cb) { |
||||
if (queryString) { |
||||
const resp = await getSignList({ |
||||
name: queryString |
||||
}); |
||||
cb(resp.rows); |
||||
} |
||||
}, |
||||
//选择对应的查询结果 |
||||
handleSelect(item) { |
||||
this.$set(this.form, "signId", item.signId); |
||||
this.$set(this.form, "name", item.name); |
||||
this.$set(this.form, "phone", item.phone); |
||||
this.$set(this.form, "dealDate", item.dealDate); |
||||
this.$set(this.form, "signPrice", item.signPrice); |
||||
this.$set(this.form, "schoolName", item.schoolName); |
||||
this.$set(this.form, "className", item.className); |
||||
this.$set(this.form, "profit", item.profit); |
||||
this.$set(this.form, "followUser", item.followUser); |
||||
}, |
||||
handleSave(state) { |
||||
this.form.state = state; |
||||
this.$refs.form.validate(async valid => { |
||||
if (valid) { |
||||
|
||||
if (state == 1) { |
||||
this.$confirm('提交后将进入审核阶段,是否提交确认提交?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
this.handleExpenseSave(); |
||||
}) |
||||
.catch(function () { }); |
||||
} else { |
||||
this.handleExpenseSave(); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
handleExpenseSave() { |
||||
// 提交申请 |
||||
if (this.form.expenseId) { |
||||
updateExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('修改成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} else { |
||||
addExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('新增成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
|
||||
handleCheck(state) { |
||||
this.form.state = state; |
||||
checkExpense(this.form).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.$message.success('审核成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.show = false; |
||||
} |
||||
}) |
||||
}, |
||||
|
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -0,0 +1,91 @@ |
||||
export const defaultColumns = [{ |
||||
key: 0, |
||||
prop: 'name', |
||||
label: `姓名`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 1, |
||||
prop: 'phone', |
||||
label: `联系方式`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 2, |
||||
prop: 'dealDate', |
||||
label: `报名时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 3, |
||||
prop: 'signPrice', |
||||
label: `成交价`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 4, |
||||
prop: 'className', |
||||
label: `班型`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 5, |
||||
prop: 'schoolName', |
||||
label: `报名驾校`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 6, |
||||
prop: 'profit', |
||||
label: `利润`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 7, |
||||
prop: 'expenseType', |
||||
label: `额外支出项目`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 8, |
||||
prop: 'money', |
||||
label: `额外支出金额`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 9, |
||||
prop: 'followUserName', |
||||
label: `学员归属`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 10, |
||||
prop: 'remark', |
||||
label: `备注`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 11, |
||||
prop: 'createTime', |
||||
label: `申请时间`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 12, |
||||
prop: 'state', |
||||
label: `审批状态`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 13, |
||||
prop: 'checkUser', |
||||
label: `审批人`, |
||||
visible: true |
||||
}, |
||||
{ |
||||
key: 14, |
||||
prop: 'checkTime', |
||||
label: `审批时间`, |
||||
visible: true |
||||
} |
||||
] |
||||
@ -0,0 +1,149 @@ |
||||
<template> |
||||
<div> |
||||
<SearchForm v-show="showSearch" :value.sync="searchForm" ref="SearchForm" @search="_getTableList" :userOptions="userOptions" /> |
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="primary" plain icon="el-icon-plus" v-hasPermi="['finance:expense:meituan:add']" @click="handleDialog(null)">新增</el-button> |
||||
<el-button type="warning" icon="el-icon-download" v-hasPermi="['finance:expense:meituan:export']" @click="handleExport">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :show-search.sync="showSearch" :columns="columns" @queryTable="_getTableList" /> |
||||
</el-row> |
||||
<el-table :data="tableList"> |
||||
<el-table-column type="selection" width="50" align="center" /> |
||||
<template v-for="item in columns"> |
||||
<el-table-column v-if="item.visible && item.prop != 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop" /> |
||||
<el-table-column v-if="item.visible && item.prop == 'state'" :key="item.prop" :label="item.label" align="center" min-width="100" :prop="item.prop"> |
||||
<template scope="scope"> |
||||
<el-tag v-if="scope.row.state == 0">保存中</el-tag> |
||||
<el-tag type="warning" v-if="scope.row.state == 1">待审核</el-tag> |
||||
<el-tag type="success" v-if="scope.row.state == 2">已审核</el-tag> |
||||
<el-tag type="danger" v-if="scope.row.state == 3">驳回</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
</template> |
||||
<el-table-column label="操作" fixed="right" align="center" width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="handleDialog(scope.row)">详情</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 1" v-hasPermi="['finance:expense:meituan:check']" @click="handleDialog(scope.row)">审核</el-button> |
||||
<el-button type="text" v-if="scope.row.state == 0" v-hasPermi="['finance:expense:meituan:remove']" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<pagination :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
<SignDialog ref="SignDialog" @refreshDataList="_getTableList" :userOptions="userOptions" :extraOptions="extraOptions" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SearchForm from './SearchForm.vue'; |
||||
import SignDialog from './SignDialog.vue'; |
||||
import { defaultColumns } from './columns.js'; |
||||
import empApi from '@/api/system/employee'; |
||||
|
||||
|
||||
import { listExpense, removeExpense, exportExpense } from '@/api/finance/expense/signExpense' |
||||
|
||||
export default { |
||||
// name: "AccountExpense", |
||||
components: { |
||||
SearchForm, SignDialog |
||||
}, |
||||
props: { |
||||
type: { |
||||
type: String, |
||||
default: '1' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
createUser: undefined, |
||||
createTimeRange: [], |
||||
pageNum: 1, |
||||
pageSize: 20 |
||||
}, |
||||
showSearch: true, |
||||
tableList: [], |
||||
total: 0, |
||||
columns: [], |
||||
userOptions: [], |
||||
extraOptions: [] |
||||
}; |
||||
}, |
||||
watch: { |
||||
type: { |
||||
handler() { |
||||
this.columns = defaultColumns |
||||
this._getTableList(); |
||||
this.getEmployee() |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
created() { |
||||
// 额外支出 |
||||
this.getDicts('dm_extra_pay').then((response) => { |
||||
this.extraOptions = response.data; |
||||
}); |
||||
}, |
||||
methods: { |
||||
async _getTableList() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
// api.list(params) |
||||
listExpense(params).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.tableList = resp.rows |
||||
this.total = resp.total |
||||
} |
||||
}) |
||||
// this.tableList = []; |
||||
// for (let i = 0; i < 20; i++) { |
||||
// this.tableList.push({ applyUser: `数据${i + 1}` }); |
||||
// } |
||||
}, |
||||
handleDialog(row) { |
||||
this.$refs.SignDialog && this.$refs.SignDialog.init(row); |
||||
}, |
||||
//删除 |
||||
handleDelete(item) { |
||||
this.$confirm('是否确认删除该条线索(“' + item.expenseType + '/' + item.expenseDate + '”)?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}) |
||||
.then((res) => { |
||||
removeExpense(item.expenseId).then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.$message.success('删除成功'); |
||||
this._getTableList(); |
||||
} |
||||
}); |
||||
}) |
||||
.catch(function () { }); |
||||
}, |
||||
handleExport() { |
||||
this.$confirm('是否确认导出所查询学员信息项?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(async () => { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
this.download('finance/expense/account/export', tempForm, `账户充值报销信息_${new Date().getTime()}.xlsx`); |
||||
}); |
||||
}, |
||||
getEmployee() { |
||||
empApi.getEmployee().then((resp) => { |
||||
if (resp.code === 200) { |
||||
this.userOptions = resp.data; |
||||
} |
||||
}); |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
||||
|
||||
@ -1,19 +1,443 @@ |
||||
<template> |
||||
<div class="main-content"> |
||||
<el-card> |
||||
<div>这是首页</div> |
||||
</el-card> |
||||
<div class="dashboard-editor-container"> |
||||
<!-- 招生团队首页 --> |
||||
<div> |
||||
<el-row :gutter="40" class="panel-group" style="margin-bottom: 20px"> |
||||
<!-- <el-col :span="6"> |
||||
<el-card> |
||||
<div slot="header"> |
||||
问候 |
||||
</div> |
||||
<div class="task-pane"> |
||||
<p>亲爱的{{user.nickName}},您好!</p> |
||||
<p>人生的路,漫长且孤独,短暂也快乐,漫长的是考验,短暂的是幸福,平坦的路途,让我们心怀感恩,泥泞的路途,让我们努力加油。</p> |
||||
</div> |
||||
</el-card> |
||||
</el-col> --> |
||||
<el-col :span="6"> |
||||
<el-card> |
||||
<div slot="header"> |
||||
计划总结 |
||||
<span style="float:right"> |
||||
<el-button type="text" size="mini" @click="handleEditTask(1)">本月计划</el-button> |
||||
<el-button type="text" size="mini" @click="handleEditTask(2 )">今日计划</el-button> |
||||
</span> |
||||
</div> |
||||
<div class="task-pane"> |
||||
<div v-html="task" /> |
||||
</div> |
||||
</el-card> |
||||
</el-col> |
||||
|
||||
<el-col :span="6"> |
||||
<el-card> |
||||
<div slot="header">团队业绩概况</div> |
||||
<div class="card-panel"> |
||||
<div class="card-panel-icon-wrapper icon-people"> |
||||
<svg-icon icon-class="peoples" class-name="card-panel-icon" style="color: #EE7621;" /> |
||||
</div> |
||||
<div class="card-panel-description"> |
||||
<div> |
||||
<span class="card-panel-text">本月报名数:</span> |
||||
<count-to :start-val="0" :end-val="count.monthSign" :duration="5" class="card-panel-num" /> |
||||
</div> |
||||
<div style="margin-top: 20px"> |
||||
<span class="card-panel-text">今日报名数:</span> |
||||
<count-to :start-val="0" :end-val="count.todaySign" :duration="5" class="card-panel-num" /> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</el-col> |
||||
|
||||
<el-col :span="6"> |
||||
<el-card> |
||||
<div slot="header">转化率</div> |
||||
<div class="card-panel"> |
||||
<div class="card-panel-icon-wrapper icon-people"> |
||||
<svg-icon icon-class="peoples" class-name="card-panel-icon" style="color: #EE7621;" /> |
||||
</div> |
||||
<div class="card-panel-description"> |
||||
<div> |
||||
<span class="card-panel-text">本月转化率:</span> |
||||
<span class="card-panel-num">{{rate.currentSignRate}}</span> |
||||
<!-- <count-to |
||||
:start-val="0" |
||||
:end-val="rate.currentSignRate" |
||||
:duration="0.1" |
||||
class="card-panel-num" |
||||
/>--> |
||||
</div> |
||||
<div style="margin-top: 20px"> |
||||
<span class="card-panel-text">上月转化率:</span> |
||||
<span class="card-panel-num">{{rate.lastSignRate}}</span> |
||||
<!-- <count-to |
||||
:start-val="0" |
||||
:end-val="rate.lastSignRate" |
||||
:duration="5" |
||||
class="card-panel-num" |
||||
/>--> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</el-col> |
||||
<!-- </el-row> |
||||
<el-row :gutter="40" class="panel-group" style="margin-bottom: 20px"> --> |
||||
|
||||
<!-- 考勤信息 --> |
||||
<el-col :span="6"> |
||||
<el-card> |
||||
<div slot="header">打卡异常信息</div> |
||||
<div class="card-panel"> |
||||
<el-carousel :interval="3000" arrow="always"> |
||||
<el-carousel-item v-for="item in countNum" :key="item"> |
||||
<ul style="overflow:auto"> |
||||
<li v-for="i in 5" :key="i" class="infinite-list-item"> |
||||
<span v-for="(d,index ) in checkin_datas" :key="index" v-if="index == ((item-1)*5 + i - 1)"> |
||||
<span style="float:left">{{d.name}}</span> |
||||
<span style="float:right">{{d.error_days}} 天</span> |
||||
</span> |
||||
</li> |
||||
</ul> |
||||
</el-carousel-item> |
||||
</el-carousel> |
||||
</div> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
|
||||
<!-- 成交数排行榜 --> |
||||
<el-row :gutter="32"> |
||||
<!-- 本月个人成交数排行榜 --> |
||||
<el-col :xs="12" :sm="12" :lg="24"> |
||||
<div class="chart-wrapper"> |
||||
<span>本月成交排行榜</span> |
||||
<bar-chart-1 /> |
||||
</div> |
||||
</el-col> |
||||
<!-- 今日个人成交数排行榜 --> |
||||
<el-col :xs="12" :sm="12" :lg="24"> |
||||
<div class="chart-wrapper"> |
||||
<span>今日成交排行榜</span> |
||||
<bar-chart /> |
||||
</div> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
<!-- 成交率排行榜 --> |
||||
<el-row :gutter="32"> |
||||
<!-- 本月个人成交率排行榜 --> |
||||
<el-col :xs="12" :sm="12" :lg="24"> |
||||
<div class="chart-wrapper"> |
||||
<span>本月成交率排行榜</span> |
||||
<bar-chart-2 /> |
||||
</div> |
||||
</el-col> |
||||
|
||||
<!-- 上月个人成交率排行榜 --> |
||||
<el-col :xs="12" :sm="12" :lg="24"> |
||||
<div class="chart-wrapper"> |
||||
<span>上月成交率排行榜</span> |
||||
<bar-chart-3 /> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
|
||||
<!-- 添加或修改公告对话框 --> |
||||
<el-dialog :title="title" :visible.sync="open" width="780px" append-to-body> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> |
||||
<el-row> |
||||
<el-col :span="24" v-if="taskType === 2"> |
||||
<el-form-item label="日期" prop="day"> |
||||
<el-date-picker v-model="form.day" value-format="yyyy-MM-dd" format="yyyy-MM-dd" type="date" disabled /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="24"> |
||||
<el-form-item label="任务内容"> |
||||
<editor v-model="form.content" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer" style="padding-top:20px"> |
||||
<el-button type="primary" @click="submitForm">确 定</el-button> |
||||
<el-button @click="open=false">取 消</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import BarChart from './dashboard/BarChart' |
||||
import { getCount, dealRate, getCheckin } from '@/api/home' |
||||
import { saveTask, getTask } from '@/api/system/summary' |
||||
import CountTo from 'vue-count-to' |
||||
import BarChart1 from './dashboard/BarChart1' |
||||
import { getUserProfile } from '@/api/system/user' |
||||
import BarChart2 from './dashboard/BarChart2' |
||||
import BarChart3 from './dashboard/BarChart3' |
||||
import editor from '@/components/Editor' |
||||
|
||||
export default { |
||||
name: 'Index', |
||||
components: { |
||||
BarChart, |
||||
BarChart1, |
||||
BarChart2, |
||||
BarChart3, |
||||
CountTo, |
||||
editor, |
||||
}, |
||||
data() { |
||||
return {}; |
||||
return { |
||||
count: {}, |
||||
user: {}, |
||||
userId: localStorage.getItem('userId'), |
||||
rate: {}, |
||||
checkin_datas: [], |
||||
task: undefined, |
||||
countNum: 0, |
||||
title: undefined, |
||||
open: false, |
||||
form: { |
||||
taskType: 1, |
||||
userId: undefined, |
||||
month: undefined, |
||||
day: undefined, |
||||
content: undefined, |
||||
}, |
||||
// 表单校验 |
||||
rules: { |
||||
day: [{ required: true, message: '日期不能为空', trigger: 'blur' }], |
||||
content: [ |
||||
{ required: true, message: '任务内容不能为空', trigger: 'blur' }, |
||||
], |
||||
}, |
||||
taskType: 1, |
||||
} |
||||
}, |
||||
created() { |
||||
this.getUser() |
||||
getCount().then((response) => { |
||||
this.count = response.data |
||||
}) |
||||
dealRate().then((response) => { |
||||
this.rate = response.data |
||||
}) |
||||
this.getCheckin() |
||||
this.getTask(1) |
||||
}, |
||||
methods: { |
||||
getUser() { |
||||
getUserProfile().then((response) => { |
||||
this.user = response.data |
||||
}) |
||||
}, |
||||
getCheckin() { |
||||
getCheckin().then((resp) => { |
||||
this.checkin_datas = resp.data |
||||
this.countNum = Math.ceil(this.checkin_datas.length / 5) |
||||
}) |
||||
}, |
||||
handleEditTask(type) { |
||||
this.taskType = type |
||||
if (type === 2) { |
||||
this.title = '今日任务' |
||||
} else { |
||||
this.title = '本月任务' |
||||
} |
||||
this.getTask(type) |
||||
this.open = true |
||||
}, |
||||
submitForm() { |
||||
this.$refs['form'].validate((valid) => { |
||||
if (valid) { |
||||
saveTask(this.form).then((response) => { |
||||
if (response.code === 200) { |
||||
this.$message.success('保存成功') |
||||
this.open = false |
||||
if (this.taskType == 1) { |
||||
this.task = this.form.content |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
}) |
||||
}, |
||||
getTask(type) { |
||||
this.form = { |
||||
taskType: type, |
||||
userId: this.userId, |
||||
month: undefined, |
||||
day: undefined, |
||||
content: undefined, |
||||
} |
||||
//查询当前任务,编辑查询当前月的,细化查询当日的 |
||||
let now = new Date() |
||||
let year = now.getFullYear() //得到年份 |
||||
let month = now.getMonth() + 1 //得到月份 |
||||
let day = now.getDate() //得到日期 |
||||
this.$set(this.form, 'month', month) |
||||
if (type === 2) { |
||||
this.$set(this.form, 'day', year + '-' + month + '-' + day) |
||||
} |
||||
getTask(this.form).then((resp) => { |
||||
if (resp.code == 200 && resp.data) { |
||||
this.form = resp.data |
||||
if (type == 1) { |
||||
this.task = resp.data.content |
||||
} |
||||
} |
||||
}) |
||||
}, |
||||
}, |
||||
methods: {} |
||||
}; |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"></style> |
||||
<style lang="scss" scoped> |
||||
.task-pane { |
||||
overflow-y: auto; |
||||
height: 120px; |
||||
max-height: 120px; |
||||
} |
||||
.dashboard-editor-container { |
||||
padding: 25px; |
||||
background-color: rgb(240, 242, 245); |
||||
position: relative; |
||||
|
||||
.chart-wrapper { |
||||
background: #fff; |
||||
padding: 16px 16px 0; |
||||
margin-bottom: 20px; |
||||
} |
||||
} |
||||
|
||||
@media (max-width: 1024px) { |
||||
.chart-wrapper { |
||||
padding: 8px; |
||||
} |
||||
|
||||
.card-panel-col { |
||||
width: 50%; |
||||
} |
||||
} |
||||
</style> |
||||
|
||||
<style lang="scss" scoped> |
||||
.panel-group { |
||||
margin-top: 5px; |
||||
|
||||
.card-panel-col { |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.card-panel { |
||||
height: 120px; |
||||
cursor: pointer; |
||||
font-size: 12px; |
||||
position: relative; |
||||
overflow: hidden; |
||||
color: #666; |
||||
background: #fff; |
||||
box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05); |
||||
border-color: rgba(0, 0, 0, 0.05); |
||||
|
||||
&:hover { |
||||
.card-panel-icon-wrapper { |
||||
color: #fff; |
||||
} |
||||
|
||||
.icon-people { |
||||
background: #40c9c6; |
||||
} |
||||
|
||||
.icon-message { |
||||
background: #36a3f7; |
||||
} |
||||
|
||||
.icon-money { |
||||
background: #f4516c; |
||||
} |
||||
|
||||
.icon-shopping { |
||||
background: #34bfa3; |
||||
} |
||||
} |
||||
|
||||
.icon-people { |
||||
color: #40c9c6; |
||||
} |
||||
|
||||
.icon-message { |
||||
color: #36a3f7; |
||||
} |
||||
|
||||
.icon-money { |
||||
color: #f4516c; |
||||
} |
||||
|
||||
.icon-shopping { |
||||
color: #34bfa3; |
||||
} |
||||
|
||||
.card-panel-icon-wrapper { |
||||
float: left; |
||||
margin: 20px 0 0 10px; |
||||
padding: 16px; |
||||
transition: all 0.38s ease-out; |
||||
border-radius: 6px; |
||||
} |
||||
|
||||
.card-panel-icon { |
||||
float: left; |
||||
font-size: 48px; |
||||
} |
||||
|
||||
.card-panel-description { |
||||
float: right; |
||||
font-weight: bold; |
||||
margin: 26px; |
||||
margin-left: 0px; |
||||
|
||||
.card-panel-text { |
||||
line-height: 18px; |
||||
color: rgba(0, 0, 0, 0.45); |
||||
font-size: 16px; |
||||
margin-bottom: 12px; |
||||
} |
||||
|
||||
.card-panel-num { |
||||
font-size: 20px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.infinite-list-item { |
||||
height: 20px; |
||||
margin: 2px; |
||||
list-style: none; |
||||
} |
||||
} |
||||
|
||||
@media (max-width: 550px) { |
||||
.card-panel-description { |
||||
display: none; |
||||
} |
||||
|
||||
.card-panel-icon-wrapper { |
||||
float: none !important; |
||||
width: 100%; |
||||
height: 100%; |
||||
margin: 0 !important; |
||||
|
||||
.svg-icon { |
||||
display: block; |
||||
margin: 14px auto !important; |
||||
float: none !important; |
||||
} |
||||
} |
||||
} |
||||
</style> |
||||
|
||||
@ -0,0 +1,55 @@ |
||||
<template> |
||||
<div> |
||||
<el-form ref="searchForm" :model="searchForm" inline> |
||||
<el-form-item label="区域" prop="area"> |
||||
<el-select v-model="searchForm.area" filterable placeholder="请选择" clearable size="mini"> |
||||
<el-option v-for="(dict, index) in areaOptions" :key="index" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="月份" prop="month"> |
||||
<el-date-picker v-model="searchForm.month" type="month" placeholder="选择月" value-format="yyyy-MM" format="yyyy-MM"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import DMRadio from '@/components/DMRadio'; |
||||
const date = new Date(); |
||||
const month = date.getFullYear() + "-" + (date.getMonth() + 1); |
||||
export default { |
||||
components: { |
||||
DMRadio |
||||
}, |
||||
props: { |
||||
areaOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
area: undefined, |
||||
month: month |
||||
}, |
||||
} |
||||
|
||||
}, |
||||
created() { |
||||
}, |
||||
methods: { |
||||
resetQuery() { |
||||
this.searchForm = { |
||||
placeId: undefined, |
||||
month: undefined |
||||
}; |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
@ -0,0 +1,105 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<!-- 搜索插件 --> |
||||
<SearchForm v-show="showSearch" ref="SearchForm" @search="_getTableList" :areaOptions="areaOptions" /> |
||||
|
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['statistic:areaStudent:export']">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :showSearch.sync="showSearch" :columns="columns" @queryTable="_getTableList"></right-toolbar> |
||||
</el-row> |
||||
|
||||
<el-table v-loading="loading" :data="dataList"> |
||||
<el-table-column type="index" width="55" align="center" /> |
||||
<el-table-column label="区域" align="center" min-width="120" prop="areaName" /> |
||||
<el-table-column label="月份" align="center" min-width="120" prop="month" /> |
||||
<el-table-column label="线索数" align="center" min-width="120" prop="clueNum" /> |
||||
<el-table-column label="成交数" align="center" min-width="120" prop="signNum" /> |
||||
<el-table-column label="成交率" align="center" min-width="120" sortable prop="dealRate" /> |
||||
<el-table-column label="平均利润" align="center" min-width="120" sortable prop="avgProfit" /> |
||||
</el-table> |
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { listReport } from "@/api/statistic/areaStudent"; |
||||
import SearchForm from "./components/SearchForm.vue"; |
||||
import { getAllPlaces } from '@/api/sch/place' |
||||
|
||||
const date = new Date(); |
||||
const month = date.getFullYear() + "-" + (date.getMonth() + 1); |
||||
export default { |
||||
name: "AreaStudent", |
||||
components: { |
||||
SearchForm |
||||
}, |
||||
data() { |
||||
return { |
||||
// 遮罩层 |
||||
loading: true, |
||||
// 选中数组 |
||||
ids: [], |
||||
// 非单个禁用 |
||||
single: true, |
||||
// 非多个禁用 |
||||
multiple: true, |
||||
// 显示搜索条件 |
||||
showSearch: true, |
||||
// 总条数 |
||||
total: 0, |
||||
// 列表数据 |
||||
dataList: [], |
||||
// 弹出层标题 |
||||
title: "", |
||||
// 是否显示弹出层 |
||||
open: false, |
||||
// 查询参数 |
||||
searchForm: { |
||||
month: month, |
||||
pageNum: 1, |
||||
pageSize: 10 |
||||
}, |
||||
columns: [], |
||||
dialogVisible: false, |
||||
areaOptions: [] |
||||
}; |
||||
}, |
||||
created() { |
||||
this._getTableList(); |
||||
this.getDicts('dm_area').then((response) => { |
||||
this.areaOptions = response.data; |
||||
}); |
||||
}, |
||||
methods: { |
||||
/** 查询报名点成交登记列表 */ |
||||
_getTableList() { |
||||
this.loading = true; |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
listReport(params).then(response => { |
||||
this.dataList = response.data; |
||||
// this.total = response.total; |
||||
this.loading = false; |
||||
}); |
||||
}, |
||||
async getAllPlaces() { |
||||
const resp = await getAllPlaces(); |
||||
if (resp.code == 200) { |
||||
this.placeOptions = resp.data; |
||||
} |
||||
|
||||
}, |
||||
/** 导出按钮操作 */ |
||||
handleExport() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
this.download('/statistic/area/student/export', params, `区域学员报表_${new Date().getTime()}.xlsx`) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
@ -0,0 +1,57 @@ |
||||
<template> |
||||
<div> |
||||
<el-form ref="searchForm" :model="searchForm" inline> |
||||
<el-form-item label="场地"> |
||||
<el-select v-model="searchForm.placeId" filterable placeholder="请选择" clearable size="mini"> |
||||
<el-option v-for="(dict, index) in placeOptions" :key="index" :label="dict.name" :value="dict.placeId" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="月份" prop="month"> |
||||
<el-date-picker v-model="searchForm.month" type="month" placeholder="选择月" value-format="yyyy-MM" format="yyyy-MM"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label-width="0"> |
||||
<el-button type="primary" icon="el-icon-search" @click="$emit('search')">搜索</el-button> |
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import DMRadio from '@/components/DMRadio'; |
||||
const date = new Date(); |
||||
const month = date.getFullYear() + "-" + (date.getMonth() + 1); |
||||
export default { |
||||
components: { |
||||
DMRadio |
||||
}, |
||||
props: { |
||||
placeOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
searchForm: { |
||||
placeId: undefined, |
||||
month: month |
||||
}, |
||||
dateRange: [] |
||||
} |
||||
|
||||
}, |
||||
created() { |
||||
|
||||
}, |
||||
methods: { |
||||
resetQuery() { |
||||
this.searchForm = { |
||||
placeId: undefined, |
||||
month: undefined |
||||
}; |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
@ -0,0 +1,103 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<!-- 搜索插件 --> |
||||
<SearchForm v-show="showSearch" ref="SearchForm" @search="_getTableList" :placeOptions="placeOptions" /> |
||||
|
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['statistic:placeStudent:export']">导出</el-button> |
||||
</el-col> |
||||
<right-toolbar :showSearch.sync="showSearch" :columns="columns" @queryTable="_getTableList"></right-toolbar> |
||||
</el-row> |
||||
|
||||
<el-table v-loading="loading" :data="dataList"> |
||||
<el-table-column type="index" width="55" align="center" /> |
||||
<el-table-column label="场地名" align="center" min-width="120" prop="placeName" /> |
||||
<el-table-column label="月份" align="center" min-width="120" prop="month" /> |
||||
<el-table-column label="线索数" align="center" min-width="120" prop="clueNum" /> |
||||
<el-table-column label="成交数" align="center" min-width="120" prop="signNum" /> |
||||
<el-table-column label="成交率" align="center" min-width="120" sortable prop="dealRate" /> |
||||
<el-table-column label="平均利润" align="center" min-width="120" sortable prop="avgProfit" /> |
||||
</el-table> |
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="searchForm.pageNum" :limit.sync="searchForm.pageSize" @pagination="_getTableList" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { listReport } from "@/api/statistic/placeStudent"; |
||||
import SearchForm from "./components/SearchForm.vue"; |
||||
import { getAllPlaces } from '@/api/sch/place' |
||||
|
||||
const date = new Date(); |
||||
const month = date.getFullYear() + "-" + (date.getMonth() + 1); |
||||
export default { |
||||
name: "PlaceStudent", |
||||
components: { |
||||
SearchForm |
||||
}, |
||||
data() { |
||||
return { |
||||
// 遮罩层 |
||||
loading: true, |
||||
// 选中数组 |
||||
ids: [], |
||||
// 非单个禁用 |
||||
single: true, |
||||
// 非多个禁用 |
||||
multiple: true, |
||||
// 显示搜索条件 |
||||
showSearch: true, |
||||
// 总条数 |
||||
total: 0, |
||||
// 列表数据 |
||||
dataList: [], |
||||
// 弹出层标题 |
||||
title: "", |
||||
// 是否显示弹出层 |
||||
open: false, |
||||
// 查询参数 |
||||
searchForm: { |
||||
month: month, |
||||
pageNum: 1, |
||||
pageSize: 10 |
||||
}, |
||||
columns: [], |
||||
dialogVisible: false, |
||||
placeOptions: [] |
||||
}; |
||||
}, |
||||
created() { |
||||
this.getAllPlaces() |
||||
this._getTableList(); |
||||
}, |
||||
methods: { |
||||
/** 查询报名点成交登记列表 */ |
||||
_getTableList() { |
||||
this.loading = true; |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
listReport(params).then(response => { |
||||
this.dataList = response.data; |
||||
// this.total = response.total; |
||||
this.loading = false; |
||||
}); |
||||
}, |
||||
async getAllPlaces() { |
||||
const resp = await getAllPlaces(); |
||||
if (resp.code == 200) { |
||||
this.placeOptions = resp.data; |
||||
} |
||||
|
||||
}, |
||||
/** 导出按钮操作 */ |
||||
handleExport() { |
||||
const tempForm = this.$refs.SearchForm?.searchForm || {}; |
||||
const params = { ...this.searchForm, ...tempForm }; |
||||
this.download('/statistic/area/student/export', params, `场地学员报表_${new Date().getTime()}.xlsx`) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
@ -0,0 +1,296 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-row :gutter="20"> |
||||
<!-- 字典类型 --> |
||||
<el-col :span="4"> |
||||
<el-menu :default-active="navselected" @select="selectItems" class="el-menu-vertical-demo"> |
||||
<el-menu-item :index="index.toString()" v-for="(item, index) in typeList" :key="item.dictId"> |
||||
<span slot="title">{{ item.dictName }}</span> |
||||
</el-menu-item> |
||||
</el-menu> |
||||
</el-col> |
||||
<!-- 字典数据 --> |
||||
<el-col :span="20"> |
||||
<el-row :gutter="10" class="mb8"> |
||||
<template> |
||||
<el-col :span="8"> |
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:dict:add']">新增</el-button> |
||||
</el-col> |
||||
</template> |
||||
</el-row> |
||||
|
||||
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange" size="mini"> |
||||
<el-table-column label="字典标签" align="center" prop="dictLabel" /> |
||||
<!-- <el-table-column label="字典编码" align="center" prop="dictValue" /> --> |
||||
<el-table-column label="字典排序" align="center" prop="dictSort" /> |
||||
<el-table-column label="状态" align="center" prop="status"> |
||||
<template slot-scope="scope"> |
||||
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" /> |
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ parseTime(scope.row.createTime) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope" v-if="ishidden&&!scope.row.default"> |
||||
<!-- <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dict:edit']">修改</el-button> --> |
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dict:remove']">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> |
||||
</el-col> |
||||
</el-row> |
||||
<!-- 添加或修改参数配置对话框 --> |
||||
<el-dialog :title="title" :visible.sync="open" :width="dialogWidth" append-to-body v-loading="loading" :close-on-click-modal="false"> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> |
||||
<el-form-item label="数据标签" prop="dictLabel"> |
||||
<el-input v-model="form.dictLabel" placeholder="请输入数据标签" /> |
||||
</el-form-item> |
||||
<el-form-item label="显示排序" prop="dictSort"> |
||||
<el-input-number v-model="form.dictSort" controls-position="right" :min="0" /> |
||||
</el-form-item> |
||||
<el-form-item label="状态" prop="status"> |
||||
<el-radio-group v-model="form.status"> |
||||
<el-radio label="0">正常</el-radio> |
||||
<el-radio label="1">停用</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button type="primary" @click="submitForm">确 定</el-button> |
||||
<el-button @click="open=false">取 消</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { listType, } from "@/api/system/dict/type"; |
||||
import { listData, getData, delData, addData, updateData, changeDictDataStatus, } from "@/api/system/dict/data"; |
||||
|
||||
export default { |
||||
name: "Dict", |
||||
data() { |
||||
return { |
||||
// 遮罩层 |
||||
loading: true, |
||||
// 选中数组 |
||||
ids: [], |
||||
// 非单个禁用 |
||||
single: true, |
||||
// 非多个禁用 |
||||
multiple: true, |
||||
// 显示搜索条件 |
||||
showSearch: true, |
||||
// 总条数 |
||||
total: 0, |
||||
// 字典表格数据 |
||||
typeList: [], |
||||
//字典模板表格数据 |
||||
dataList: [], |
||||
// 弹出层标题 |
||||
title: "", |
||||
// 是否显示弹出层 |
||||
open: false, |
||||
// 数据标签回显样式 |
||||
listClassOptions: [ |
||||
{ |
||||
value: "default", |
||||
label: "默认" |
||||
}, |
||||
{ |
||||
value: "primary", |
||||
label: "主要" |
||||
}, |
||||
{ |
||||
value: "success", |
||||
label: "成功" |
||||
}, |
||||
{ |
||||
value: "info", |
||||
label: "信息" |
||||
}, |
||||
{ |
||||
value: "warning", |
||||
label: "警告" |
||||
}, |
||||
{ |
||||
value: "danger", |
||||
label: "危险" |
||||
} |
||||
], |
||||
// 类型数据字典 |
||||
typeOptions: [], |
||||
// 日期范围 |
||||
dateRange: [], |
||||
menuleftnav: undefined, |
||||
// 查询参数 |
||||
queryParams: { |
||||
pageNum: 1, |
||||
pageSize: 10, |
||||
dictName: undefined, |
||||
dictType: undefined, |
||||
status: undefined |
||||
}, |
||||
// 表单参数 |
||||
form: {}, |
||||
// 表单校验 |
||||
rules: { |
||||
dictLabel: [ |
||||
{ required: true, message: "数据标签不能为空", trigger: "blur" } |
||||
], |
||||
dictValue: [ |
||||
{ required: true, message: "数据键值不能为空", trigger: "blur" } |
||||
], |
||||
dictSort: [ |
||||
{ required: true, message: "数据顺序不能为空", trigger: "blur" } |
||||
] |
||||
}, |
||||
navselected: "0", |
||||
ishidden: true, |
||||
dialogWidth: '500px' |
||||
}; |
||||
}, |
||||
|
||||
created() { |
||||
this.getTypeList(); |
||||
//this.getDataTemplateList(); |
||||
}, |
||||
methods: { |
||||
/** 查询字典类型列表 */ |
||||
getTypeList() { |
||||
this.loading = true; |
||||
listType().then((response) => { |
||||
this.typeList = response.rows; |
||||
this.loading = false; |
||||
//左边菜单加载完毕才加载右边的菜单 |
||||
this.queryParams.dictType = this.typeList[this.navselected].dictType; |
||||
this.getList(); |
||||
}); |
||||
}, |
||||
/** 查询字典数据列表 */ |
||||
getList() { |
||||
this.loading = true; |
||||
listData(this.queryParams).then(response => { |
||||
this.dataList = response.rows; |
||||
this.total = response.total; |
||||
this.loading = false; |
||||
}); |
||||
}, |
||||
selectItems(index) { |
||||
this.menuleftnav = index; |
||||
this.queryParams.dictType = this.typeList[index].dictType; |
||||
this.getList(); |
||||
}, |
||||
|
||||
// 表单重置 |
||||
reset() { |
||||
this.form = { |
||||
dictCode: undefined, |
||||
dictLabel: undefined, |
||||
dictValue: undefined, |
||||
cssClass: undefined, |
||||
listClass: 'default', |
||||
dictSort: 0, |
||||
status: '0', |
||||
remark: undefined |
||||
}; |
||||
this.resetForm("form"); |
||||
}, |
||||
/** 搜索按钮操作 */ |
||||
handleQuery() { |
||||
this.queryParams.pageNum = 1; |
||||
this.queryParams.dictType = this.typeList[this.menuleftnav].dictType; |
||||
this.getList(); |
||||
}, |
||||
/** 新增按钮操作 */ |
||||
handleAdd() { |
||||
this.reset(); |
||||
this.open = true; |
||||
this.title = "添加字典数据"; |
||||
this.$set( |
||||
this.form, |
||||
"dictType", |
||||
this.typeList[this.menuleftnav].dictType |
||||
); |
||||
}, |
||||
/** 修改按钮操作 */ |
||||
handleUpdate(row) { |
||||
this.reset(); |
||||
const dictCode = row.dictCode || this.ids |
||||
getData(dictCode).then(response => { |
||||
this.form = response.data; |
||||
this.open = true; |
||||
this.title = "修改字典数据"; |
||||
}); |
||||
}, |
||||
/** 提交按钮 */ |
||||
submitForm: function () { |
||||
this.form.dictType = this.queryParams.dictType; |
||||
this.form.dictValue = this.form.dictLabel |
||||
this.$refs["form"].validate(valid => { |
||||
if (valid) { |
||||
if (this.form.dictCode != undefined) { |
||||
updateData(this.form).then(response => { |
||||
if (response.code == 200) { |
||||
this.$modal.msgSuccess("修改成功"); |
||||
this.open = false; |
||||
this.getList(); |
||||
} |
||||
|
||||
}); |
||||
} else { |
||||
addData(this.form).then(response => { |
||||
if (response.code == 200) { |
||||
this.$modal.msgSuccess("新增成功"); |
||||
this.open = false; |
||||
this.getList(); |
||||
} |
||||
|
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
/** 删除按钮操作 */ |
||||
handleDelete(row) { |
||||
const dictCodes = row.dictCode || this.ids; |
||||
this.$modal.confirm('是否确认删除字典编码为"' + row.dictValue + '"的数据项?').then(function () { |
||||
return delData(dictCodes); |
||||
}).then((resp) => { |
||||
if (resp.code == 200) { |
||||
this.getList(); |
||||
this.$modal.msgSuccess("删除成功"); |
||||
} |
||||
|
||||
}).catch(() => { }); |
||||
}, |
||||
// 字典模板状态修改 |
||||
handleStatusChange(row) { |
||||
let text = row.status === true ? "启用" : "停用"; |
||||
this.$modal |
||||
.confirm('确认要"' + text + '""' + row.dictLabel + '"标签吗?') |
||||
.then(function () { |
||||
return changeDictDataStatus(row.dictCode, row.status); |
||||
}) |
||||
.then((resp) => { |
||||
if (resp.code == 200) { |
||||
this.$modal.msgSuccess(text + "成功"); |
||||
} |
||||
}) |
||||
.catch(function () { |
||||
row.status = row.status === false ? true : false; |
||||
}); |
||||
}, |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
@ -0,0 +1,106 @@ |
||||
<template> |
||||
<div> |
||||
<el-dialog |
||||
v-bind="$attrs" |
||||
width="500px" |
||||
:close-on-click-modal="false" |
||||
:modal-append-to-body="false" |
||||
v-on="$listeners" |
||||
@open="onOpen" |
||||
@close="onClose" |
||||
> |
||||
<el-row :gutter="15"> |
||||
<el-form |
||||
ref="elForm" |
||||
:model="formData" |
||||
:rules="rules" |
||||
size="medium" |
||||
label-width="100px" |
||||
> |
||||
<el-col :span="24"> |
||||
<el-form-item label="生成类型" prop="type"> |
||||
<el-radio-group v-model="formData.type"> |
||||
<el-radio-button |
||||
v-for="(item, index) in typeOptions" |
||||
:key="index" |
||||
:label="item.value" |
||||
:disabled="item.disabled" |
||||
> |
||||
{{ item.label }} |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item v-if="showFileName" label="文件名" prop="fileName"> |
||||
<el-input v-model="formData.fileName" placeholder="请输入文件名" clearable /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-form> |
||||
</el-row> |
||||
|
||||
<div slot="footer"> |
||||
<el-button @click="close"> |
||||
取消 |
||||
</el-button> |
||||
<el-button type="primary" @click="handleConfirm"> |
||||
确定 |
||||
</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
inheritAttrs: false, |
||||
props: ['showFileName'], |
||||
data() { |
||||
return { |
||||
formData: { |
||||
fileName: undefined, |
||||
type: 'file' |
||||
}, |
||||
rules: { |
||||
fileName: [{ |
||||
required: true, |
||||
message: '请输入文件名', |
||||
trigger: 'blur' |
||||
}], |
||||
type: [{ |
||||
required: true, |
||||
message: '生成类型不能为空', |
||||
trigger: 'change' |
||||
}] |
||||
}, |
||||
typeOptions: [{ |
||||
label: '页面', |
||||
value: 'file' |
||||
}, { |
||||
label: '弹窗', |
||||
value: 'dialog' |
||||
}] |
||||
} |
||||
}, |
||||
computed: { |
||||
}, |
||||
watch: {}, |
||||
mounted() {}, |
||||
methods: { |
||||
onOpen() { |
||||
if (this.showFileName) { |
||||
this.formData.fileName = `${+new Date()}.vue` |
||||
} |
||||
}, |
||||
onClose() { |
||||
}, |
||||
close(e) { |
||||
this.$emit('update:visible', false) |
||||
}, |
||||
handleConfirm() { |
||||
this.$refs.elForm.validate(valid => { |
||||
if (!valid) return |
||||
this.$emit('confirm', { ...this.formData }) |
||||
this.close() |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
@ -0,0 +1,100 @@ |
||||
<script> |
||||
import draggable from 'vuedraggable' |
||||
import render from '@/utils/generator/render' |
||||
|
||||
const components = { |
||||
itemBtns(h, element, index, parent) { |
||||
const { copyItem, deleteItem } = this.$listeners |
||||
return [ |
||||
<span class="drawing-item-copy" title="复制" onClick={event => { |
||||
copyItem(element, parent); event.stopPropagation() |
||||
}}> |
||||
<i class="el-icon-copy-document" /> |
||||
</span>, |
||||
<span class="drawing-item-delete" title="删除" onClick={event => { |
||||
deleteItem(index, parent); event.stopPropagation() |
||||
}}> |
||||
<i class="el-icon-delete" /> |
||||
</span> |
||||
] |
||||
} |
||||
} |
||||
const layouts = { |
||||
colFormItem(h, element, index, parent) { |
||||
const { activeItem } = this.$listeners |
||||
let className = this.activeId === element.formId ? 'drawing-item active-from-item' : 'drawing-item' |
||||
if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered' |
||||
return ( |
||||
<el-col span={element.span} class={className} |
||||
nativeOnClick={event => { activeItem(element); event.stopPropagation() }}> |
||||
<el-form-item label-width={element.labelWidth ? `${element.labelWidth}px` : null} |
||||
label={element.label} required={element.required}> |
||||
<render key={element.renderKey} conf={element} onInput={ event => { |
||||
this.$set(element, 'defaultValue', event) |
||||
}} /> |
||||
</el-form-item> |
||||
{components.itemBtns.apply(this, arguments)} |
||||
</el-col> |
||||
) |
||||
}, |
||||
rowFormItem(h, element, index, parent) { |
||||
const { activeItem } = this.$listeners |
||||
const className = this.activeId === element.formId ? 'drawing-row-item active-from-item' : 'drawing-row-item' |
||||
let child = renderChildren.apply(this, arguments) |
||||
if (element.type === 'flex') { |
||||
child = <el-row type={element.type} justify={element.justify} align={element.align}> |
||||
{child} |
||||
</el-row> |
||||
} |
||||
return ( |
||||
<el-col span={element.span}> |
||||
<el-row gutter={element.gutter} class={className} |
||||
nativeOnClick={event => { activeItem(element); event.stopPropagation() }}> |
||||
<span class="component-name">{element.componentName}</span> |
||||
<draggable list={element.children} animation={340} group="componentsGroup" class="drag-wrapper"> |
||||
{child} |
||||
</draggable> |
||||
{components.itemBtns.apply(this, arguments)} |
||||
</el-row> |
||||
</el-col> |
||||
) |
||||
} |
||||
} |
||||
|
||||
function renderChildren(h, element, index, parent) { |
||||
if (!Array.isArray(element.children)) return null |
||||
return element.children.map((el, i) => { |
||||
const layout = layouts[el.layout] |
||||
if (layout) { |
||||
return layout.call(this, h, el, i, element.children) |
||||
} |
||||
return layoutIsNotFound() |
||||
}) |
||||
} |
||||
|
||||
function layoutIsNotFound() { |
||||
throw new Error(`没有与${this.element.layout}匹配的layout`) |
||||
} |
||||
|
||||
export default { |
||||
components: { |
||||
render, |
||||
draggable |
||||
}, |
||||
props: [ |
||||
'element', |
||||
'index', |
||||
'drawingList', |
||||
'activeId', |
||||
'formConf' |
||||
], |
||||
render(h) { |
||||
const layout = layouts[this.element.layout] |
||||
|
||||
if (layout) { |
||||
return layout.call(this, h, this.element, this.index, this.drawingList) |
||||
} |
||||
return layoutIsNotFound() |
||||
} |
||||
} |
||||
</script> |
||||
@ -0,0 +1,123 @@ |
||||
<template> |
||||
<div class="icon-dialog"> |
||||
<el-dialog |
||||
v-bind="$attrs" |
||||
width="980px" |
||||
:modal-append-to-body="false" |
||||
v-on="$listeners" |
||||
@open="onOpen" |
||||
@close="onClose" |
||||
> |
||||
<div slot="title"> |
||||
选择图标 |
||||
<el-input |
||||
v-model="key" |
||||
size="mini" |
||||
:style="{width: '260px'}" |
||||
placeholder="请输入图标名称" |
||||
prefix-icon="el-icon-search" |
||||
clearable |
||||
/> |
||||
</div> |
||||
<ul class="icon-ul"> |
||||
<li |
||||
v-for="icon in iconList" |
||||
:key="icon" |
||||
:class="active===icon?'active-item':''" |
||||
@click="onSelect(icon)" |
||||
> |
||||
<i :class="icon" /> |
||||
<div>{{ icon }}</div> |
||||
</li> |
||||
</ul> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import iconList from '@/utils/generator/icon.json' |
||||
|
||||
const originList = iconList.map(name => `el-icon-${name}`) |
||||
|
||||
export default { |
||||
inheritAttrs: false, |
||||
props: ['current'], |
||||
data() { |
||||
return { |
||||
iconList: originList, |
||||
active: null, |
||||
key: '' |
||||
} |
||||
}, |
||||
watch: { |
||||
key(val) { |
||||
if (val) { |
||||
this.iconList = originList.filter(name => name.indexOf(val) > -1) |
||||
} else { |
||||
this.iconList = originList |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
onOpen() { |
||||
this.active = this.current |
||||
this.key = '' |
||||
}, |
||||
onClose() {}, |
||||
onSelect(icon) { |
||||
this.active = icon |
||||
this.$emit('select', icon) |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.icon-ul { |
||||
margin: 0; |
||||
padding: 0; |
||||
font-size: 0; |
||||
li { |
||||
list-style-type: none; |
||||
text-align: center; |
||||
font-size: 14px; |
||||
display: inline-block; |
||||
width: 16.66%; |
||||
box-sizing: border-box; |
||||
height: 108px; |
||||
padding: 15px 6px 6px 6px; |
||||
cursor: pointer; |
||||
overflow: hidden; |
||||
&:hover { |
||||
background: #f2f2f2; |
||||
} |
||||
&.active-item{ |
||||
background: #e1f3fb; |
||||
color: #7a6df0 |
||||
} |
||||
> i { |
||||
font-size: 30px; |
||||
line-height: 50px; |
||||
} |
||||
} |
||||
} |
||||
.icon-dialog { |
||||
::v-deep .el-dialog { |
||||
border-radius: 8px; |
||||
margin-bottom: 0; |
||||
margin-top: 4vh !important; |
||||
display: flex; |
||||
flex-direction: column; |
||||
max-height: 92vh; |
||||
overflow: hidden; |
||||
box-sizing: border-box; |
||||
.el-dialog__header { |
||||
padding-top: 14px; |
||||
} |
||||
.el-dialog__body { |
||||
margin: 0 20px 20px 20px; |
||||
padding: 0; |
||||
overflow: auto; |
||||
} |
||||
} |
||||
} |
||||
</style> |
||||
@ -0,0 +1,946 @@ |
||||
<template> |
||||
<div class="right-board"> |
||||
<el-tabs v-model="currentTab" class="center-tabs"> |
||||
<el-tab-pane label="组件属性" name="field" /> |
||||
<el-tab-pane label="表单属性" name="form" /> |
||||
</el-tabs> |
||||
<div class="field-box"> |
||||
<a class="document-link" target="_blank" :href="documentLink" title="查看组件文档"> |
||||
<i class="el-icon-link" /> |
||||
</a> |
||||
<el-scrollbar class="right-scrollbar"> |
||||
<!-- 组件属性 --> |
||||
<el-form v-show="currentTab==='field' && showField" size="small" label-width="90px"> |
||||
<el-form-item v-if="activeData.changeTag" label="组件类型"> |
||||
<el-select |
||||
v-model="activeData.tagIcon" |
||||
placeholder="请选择组件类型" |
||||
:style="{width: '100%'}" |
||||
@change="tagChange" |
||||
> |
||||
<el-option-group v-for="group in tagList" :key="group.label" :label="group.label"> |
||||
<el-option |
||||
v-for="item in group.options" |
||||
:key="item.label" |
||||
:label="item.label" |
||||
:value="item.tagIcon" |
||||
> |
||||
<svg-icon class="node-icon" :icon-class="item.tagIcon" /> |
||||
<span> {{ item.label }}</span> |
||||
</el-option> |
||||
</el-option-group> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.vModel!==undefined" label="字段名"> |
||||
<el-input v-model="activeData.vModel" placeholder="请输入字段名(v-model)" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.componentName!==undefined" label="组件名"> |
||||
{{ activeData.componentName }} |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.label!==undefined" label="标题"> |
||||
<el-input v-model="activeData.label" placeholder="请输入标题" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.placeholder!==undefined" label="占位提示"> |
||||
<el-input v-model="activeData.placeholder" placeholder="请输入占位提示" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['start-placeholder']!==undefined" label="开始占位"> |
||||
<el-input v-model="activeData['start-placeholder']" placeholder="请输入占位提示" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['end-placeholder']!==undefined" label="结束占位"> |
||||
<el-input v-model="activeData['end-placeholder']" placeholder="请输入占位提示" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.span!==undefined" label="表单栅格"> |
||||
<el-slider v-model="activeData.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.layout==='rowFormItem'" label="栅格间隔"> |
||||
<el-input-number v-model="activeData.gutter" :min="0" placeholder="栅格间隔" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.layout==='rowFormItem'" label="布局模式"> |
||||
<el-radio-group v-model="activeData.type"> |
||||
<el-radio-button label="default" /> |
||||
<el-radio-button label="flex" /> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.justify!==undefined&&activeData.type==='flex'" label="水平排列"> |
||||
<el-select v-model="activeData.justify" placeholder="请选择水平排列" :style="{width: '100%'}"> |
||||
<el-option |
||||
v-for="(item, index) in justifyOptions" |
||||
:key="index" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.align!==undefined&&activeData.type==='flex'" label="垂直排列"> |
||||
<el-radio-group v-model="activeData.align"> |
||||
<el-radio-button label="top" /> |
||||
<el-radio-button label="middle" /> |
||||
<el-radio-button label="bottom" /> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.labelWidth!==undefined" label="标签宽度"> |
||||
<el-input v-model.number="activeData.labelWidth" type="number" placeholder="请输入标签宽度" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="组件宽度"> |
||||
<el-input v-model="activeData.style.width" placeholder="请输入组件宽度" clearable /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.vModel!==undefined" label="默认值"> |
||||
<el-input |
||||
:value="setDefaultValue(activeData.defaultValue)" |
||||
placeholder="请输入默认值" |
||||
@input="onDefaultValueInput" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag==='el-checkbox-group'" label="至少应选"> |
||||
<el-input-number |
||||
:value="activeData.min" |
||||
:min="0" |
||||
placeholder="至少应选" |
||||
@input="$set(activeData, 'min', $event?$event:undefined)" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag==='el-checkbox-group'" label="最多可选"> |
||||
<el-input-number |
||||
:value="activeData.max" |
||||
:min="0" |
||||
placeholder="最多可选" |
||||
@input="$set(activeData, 'max', $event?$event:undefined)" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.prepend!==undefined" label="前缀"> |
||||
<el-input v-model="activeData.prepend" placeholder="请输入前缀" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.append!==undefined" label="后缀"> |
||||
<el-input v-model="activeData.append" placeholder="请输入后缀" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['prefix-icon']!==undefined" label="前图标"> |
||||
<el-input v-model="activeData['prefix-icon']" placeholder="请输入前图标名称"> |
||||
<el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('prefix-icon')"> |
||||
选择 |
||||
</el-button> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['suffix-icon'] !== undefined" label="后图标"> |
||||
<el-input v-model="activeData['suffix-icon']" placeholder="请输入后图标名称"> |
||||
<el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('suffix-icon')"> |
||||
选择 |
||||
</el-button> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-cascader'" label="选项分隔符"> |
||||
<el-input v-model="activeData.separator" placeholder="请输入选项分隔符" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.autosize !== undefined" label="最小行数"> |
||||
<el-input-number v-model="activeData.autosize.minRows" :min="1" placeholder="最小行数" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.autosize !== undefined" label="最大行数"> |
||||
<el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="最大行数" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.min !== undefined" label="最小值"> |
||||
<el-input-number v-model="activeData.min" placeholder="最小值" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.max !== undefined" label="最大值"> |
||||
<el-input-number v-model="activeData.max" placeholder="最大值" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.step !== undefined" label="步长"> |
||||
<el-input-number v-model="activeData.step" placeholder="步数" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-input-number'" label="精度"> |
||||
<el-input-number v-model="activeData.precision" :min="0" placeholder="精度" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-input-number'" label="按钮位置"> |
||||
<el-radio-group v-model="activeData['controls-position']"> |
||||
<el-radio-button label=""> |
||||
默认 |
||||
</el-radio-button> |
||||
<el-radio-button label="right"> |
||||
右侧 |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.maxlength !== undefined" label="最多输入"> |
||||
<el-input v-model="activeData.maxlength" placeholder="请输入字符长度"> |
||||
<template slot="append"> |
||||
个字符 |
||||
</template> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['active-text'] !== undefined" label="开启提示"> |
||||
<el-input v-model="activeData['active-text']" placeholder="请输入开启提示" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['inactive-text'] !== undefined" label="关闭提示"> |
||||
<el-input v-model="activeData['inactive-text']" placeholder="请输入关闭提示" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['active-value'] !== undefined" label="开启值"> |
||||
<el-input |
||||
:value="setDefaultValue(activeData['active-value'])" |
||||
placeholder="请输入开启值" |
||||
@input="onSwitchValueInput($event, 'active-value')" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['inactive-value'] !== undefined" label="关闭值"> |
||||
<el-input |
||||
:value="setDefaultValue(activeData['inactive-value'])" |
||||
placeholder="请输入关闭值" |
||||
@input="onSwitchValueInput($event, 'inactive-value')" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item |
||||
v-if="activeData.type !== undefined && 'el-date-picker' === activeData.tag" |
||||
label="时间类型" |
||||
> |
||||
<el-select |
||||
v-model="activeData.type" |
||||
placeholder="请选择时间类型" |
||||
:style="{ width: '100%' }" |
||||
@change="dateTypeChange" |
||||
> |
||||
<el-option |
||||
v-for="(item, index) in dateOptions" |
||||
:key="index" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.name !== undefined" label="文件字段名"> |
||||
<el-input v-model="activeData.name" placeholder="请输入上传文件字段名" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.accept !== undefined" label="文件类型"> |
||||
<el-select |
||||
v-model="activeData.accept" |
||||
placeholder="请选择文件类型" |
||||
:style="{ width: '100%' }" |
||||
clearable |
||||
> |
||||
<el-option label="图片" value="image/*" /> |
||||
<el-option label="视频" value="video/*" /> |
||||
<el-option label="音频" value="audio/*" /> |
||||
<el-option label="excel" value=".xls,.xlsx" /> |
||||
<el-option label="word" value=".doc,.docx" /> |
||||
<el-option label="pdf" value=".pdf" /> |
||||
<el-option label="txt" value=".txt" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.fileSize !== undefined" label="文件大小"> |
||||
<el-input v-model.number="activeData.fileSize" placeholder="请输入文件大小"> |
||||
<el-select slot="append" v-model="activeData.sizeUnit" :style="{ width: '66px' }"> |
||||
<el-option label="KB" value="KB" /> |
||||
<el-option label="MB" value="MB" /> |
||||
<el-option label="GB" value="GB" /> |
||||
</el-select> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.action !== undefined" label="上传地址"> |
||||
<el-input v-model="activeData.action" placeholder="请输入上传地址" clearable /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['list-type'] !== undefined" label="列表类型"> |
||||
<el-radio-group v-model="activeData['list-type']" size="small"> |
||||
<el-radio-button label="text"> |
||||
text |
||||
</el-radio-button> |
||||
<el-radio-button label="picture"> |
||||
picture |
||||
</el-radio-button> |
||||
<el-radio-button label="picture-card"> |
||||
picture-card |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item |
||||
v-if="activeData.buttonText !== undefined" |
||||
v-show="'picture-card' !== activeData['list-type']" |
||||
label="按钮文字" |
||||
> |
||||
<el-input v-model="activeData.buttonText" placeholder="请输入按钮文字" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['range-separator'] !== undefined" label="分隔符"> |
||||
<el-input v-model="activeData['range-separator']" placeholder="请输入分隔符" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['picker-options'] !== undefined" label="时间段"> |
||||
<el-input |
||||
v-model="activeData['picker-options'].selectableRange" |
||||
placeholder="请输入时间段" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.format !== undefined" label="时间格式"> |
||||
<el-input |
||||
:value="activeData.format" |
||||
placeholder="请输入时间格式" |
||||
@input="setTimeValue($event)" |
||||
/> |
||||
</el-form-item> |
||||
<template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.tag) > -1"> |
||||
<el-divider>选项</el-divider> |
||||
<draggable |
||||
:list="activeData.options" |
||||
:animation="340" |
||||
group="selectItem" |
||||
handle=".option-drag" |
||||
> |
||||
<div v-for="(item, index) in activeData.options" :key="index" class="select-item"> |
||||
<div class="select-line-icon option-drag"> |
||||
<i class="el-icon-s-operation" /> |
||||
</div> |
||||
<el-input v-model="item.label" placeholder="选项名" size="small" /> |
||||
<el-input |
||||
placeholder="选项值" |
||||
size="small" |
||||
:value="item.value" |
||||
@input="setOptionValue(item, $event)" |
||||
/> |
||||
<div class="close-btn select-line-icon" @click="activeData.options.splice(index, 1)"> |
||||
<i class="el-icon-remove-outline" /> |
||||
</div> |
||||
</div> |
||||
</draggable> |
||||
<div style="margin-left: 20px;"> |
||||
<el-button |
||||
style="padding-bottom: 0" |
||||
icon="el-icon-circle-plus-outline" |
||||
type="text" |
||||
@click="addSelectItem" |
||||
> |
||||
添加选项 |
||||
</el-button> |
||||
</div> |
||||
<el-divider /> |
||||
</template> |
||||
|
||||
<template v-if="['el-cascader'].indexOf(activeData.tag) > -1"> |
||||
<el-divider>选项</el-divider> |
||||
<el-form-item label="数据类型"> |
||||
<el-radio-group v-model="activeData.dataType" size="small"> |
||||
<el-radio-button label="dynamic"> |
||||
动态数据 |
||||
</el-radio-button> |
||||
<el-radio-button label="static"> |
||||
静态数据 |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
|
||||
<template v-if="activeData.dataType === 'dynamic'"> |
||||
<el-form-item label="标签键名"> |
||||
<el-input v-model="activeData.labelKey" placeholder="请输入标签键名" /> |
||||
</el-form-item> |
||||
<el-form-item label="值键名"> |
||||
<el-input v-model="activeData.valueKey" placeholder="请输入值键名" /> |
||||
</el-form-item> |
||||
<el-form-item label="子级键名"> |
||||
<el-input v-model="activeData.childrenKey" placeholder="请输入子级键名" /> |
||||
</el-form-item> |
||||
</template> |
||||
|
||||
<el-tree |
||||
v-if="activeData.dataType === 'static'" |
||||
draggable |
||||
:data="activeData.options" |
||||
node-key="id" |
||||
:expand-on-click-node="false" |
||||
:render-content="renderContent" |
||||
/> |
||||
<div v-if="activeData.dataType === 'static'" style="margin-left: 20px"> |
||||
<el-button |
||||
style="padding-bottom: 0" |
||||
icon="el-icon-circle-plus-outline" |
||||
type="text" |
||||
@click="addTreeItem" |
||||
> |
||||
添加父级 |
||||
</el-button> |
||||
</div> |
||||
<el-divider /> |
||||
</template> |
||||
|
||||
<el-form-item v-if="activeData.optionType !== undefined" label="选项样式"> |
||||
<el-radio-group v-model="activeData.optionType"> |
||||
<el-radio-button label="default"> |
||||
默认 |
||||
</el-radio-button> |
||||
<el-radio-button label="button"> |
||||
按钮 |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['active-color'] !== undefined" label="开启颜色"> |
||||
<el-color-picker v-model="activeData['active-color']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['inactive-color'] !== undefined" label="关闭颜色"> |
||||
<el-color-picker v-model="activeData['inactive-color']" /> |
||||
</el-form-item> |
||||
|
||||
<el-form-item v-if="activeData['allow-half'] !== undefined" label="允许半选"> |
||||
<el-switch v-model="activeData['allow-half']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['show-text'] !== undefined" label="辅助文字"> |
||||
<el-switch v-model="activeData['show-text']" @change="rateTextChange" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['show-score'] !== undefined" label="显示分数"> |
||||
<el-switch v-model="activeData['show-score']" @change="rateScoreChange" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['show-stops'] !== undefined" label="显示间断点"> |
||||
<el-switch v-model="activeData['show-stops']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.range !== undefined" label="范围选择"> |
||||
<el-switch v-model="activeData.range" @change="rangeChange" /> |
||||
</el-form-item> |
||||
<el-form-item |
||||
v-if="activeData.border !== undefined && activeData.optionType === 'default'" |
||||
label="是否带边框" |
||||
> |
||||
<el-switch v-model="activeData.border" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-color-picker'" label="颜色格式"> |
||||
<el-select |
||||
v-model="activeData['color-format']" |
||||
placeholder="请选择颜色格式" |
||||
:style="{ width: '100%' }" |
||||
@change="colorFormatChange" |
||||
> |
||||
<el-option |
||||
v-for="(item, index) in colorFormatOptions" |
||||
:key="index" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item |
||||
v-if="activeData.size !== undefined && |
||||
(activeData.optionType === 'button' || |
||||
activeData.border || |
||||
activeData.tag === 'el-color-picker')" |
||||
label="选项尺寸" |
||||
> |
||||
<el-radio-group v-model="activeData.size"> |
||||
<el-radio-button label="medium"> |
||||
中等 |
||||
</el-radio-button> |
||||
<el-radio-button label="small"> |
||||
较小 |
||||
</el-radio-button> |
||||
<el-radio-button label="mini"> |
||||
迷你 |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['show-word-limit'] !== undefined" label="输入统计"> |
||||
<el-switch v-model="activeData['show-word-limit']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-input-number'" label="严格步数"> |
||||
<el-switch v-model="activeData['step-strictly']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-cascader'" label="是否多选"> |
||||
<el-switch v-model="activeData.props.props.multiple" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-cascader'" label="展示全路径"> |
||||
<el-switch v-model="activeData['show-all-levels']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-cascader'" label="可否筛选"> |
||||
<el-switch v-model="activeData.filterable" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.clearable !== undefined" label="能否清空"> |
||||
<el-switch v-model="activeData.clearable" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.showTip !== undefined" label="显示提示"> |
||||
<el-switch v-model="activeData.showTip" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.multiple !== undefined" label="多选文件"> |
||||
<el-switch v-model="activeData.multiple" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData['auto-upload'] !== undefined" label="自动上传"> |
||||
<el-switch v-model="activeData['auto-upload']" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.readonly !== undefined" label="是否只读"> |
||||
<el-switch v-model="activeData.readonly" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.disabled !== undefined" label="是否禁用"> |
||||
<el-switch v-model="activeData.disabled" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-select'" label="是否可搜索"> |
||||
<el-switch v-model="activeData.filterable" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.tag === 'el-select'" label="是否多选"> |
||||
<el-switch v-model="activeData.multiple" @change="multipleChange" /> |
||||
</el-form-item> |
||||
<el-form-item v-if="activeData.required !== undefined" label="是否必填"> |
||||
<el-switch v-model="activeData.required" /> |
||||
</el-form-item> |
||||
|
||||
<template v-if="activeData.layoutTree"> |
||||
<el-divider>布局结构树</el-divider> |
||||
<el-tree |
||||
:data="[activeData]" |
||||
:props="layoutTreeProps" |
||||
node-key="renderKey" |
||||
default-expand-all |
||||
draggable |
||||
> |
||||
<span slot-scope="{ node, data }"> |
||||
<span class="node-label"> |
||||
<svg-icon class="node-icon" :icon-class="data.tagIcon" /> |
||||
{{ node.label }} |
||||
</span> |
||||
</span> |
||||
</el-tree> |
||||
</template> |
||||
|
||||
<template v-if="activeData.layout === 'colFormItem' && activeData.tag !== 'el-button'"> |
||||
<el-divider>正则校验</el-divider> |
||||
<div |
||||
v-for="(item, index) in activeData.regList" |
||||
:key="index" |
||||
class="reg-item" |
||||
> |
||||
<span class="close-btn" @click="activeData.regList.splice(index, 1)"> |
||||
<i class="el-icon-close" /> |
||||
</span> |
||||
<el-form-item label="表达式"> |
||||
<el-input v-model="item.pattern" placeholder="请输入正则" /> |
||||
</el-form-item> |
||||
<el-form-item label="错误提示" style="margin-bottom:0"> |
||||
<el-input v-model="item.message" placeholder="请输入错误提示" /> |
||||
</el-form-item> |
||||
</div> |
||||
<div style="margin-left: 20px"> |
||||
<el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg"> |
||||
添加规则 |
||||
</el-button> |
||||
</div> |
||||
</template> |
||||
</el-form> |
||||
<!-- 表单属性 --> |
||||
<el-form v-show="currentTab === 'form'" size="small" label-width="90px"> |
||||
<el-form-item label="表单名"> |
||||
<el-input v-model="formConf.formRef" placeholder="请输入表单名(ref)" /> |
||||
</el-form-item> |
||||
<el-form-item label="表单模型"> |
||||
<el-input v-model="formConf.formModel" placeholder="请输入数据模型" /> |
||||
</el-form-item> |
||||
<el-form-item label="校验模型"> |
||||
<el-input v-model="formConf.formRules" placeholder="请输入校验模型" /> |
||||
</el-form-item> |
||||
<el-form-item label="表单尺寸"> |
||||
<el-radio-group v-model="formConf.size"> |
||||
<el-radio-button label="medium"> |
||||
中等 |
||||
</el-radio-button> |
||||
<el-radio-button label="small"> |
||||
较小 |
||||
</el-radio-button> |
||||
<el-radio-button label="mini"> |
||||
迷你 |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item label="标签对齐"> |
||||
<el-radio-group v-model="formConf.labelPosition"> |
||||
<el-radio-button label="left"> |
||||
左对齐 |
||||
</el-radio-button> |
||||
<el-radio-button label="right"> |
||||
右对齐 |
||||
</el-radio-button> |
||||
<el-radio-button label="top"> |
||||
顶部对齐 |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item label="标签宽度"> |
||||
<el-input-number v-model="formConf.labelWidth" placeholder="标签宽度" /> |
||||
</el-form-item> |
||||
<el-form-item label="栅格间隔"> |
||||
<el-input-number v-model="formConf.gutter" :min="0" placeholder="栅格间隔" /> |
||||
</el-form-item> |
||||
<el-form-item label="禁用表单"> |
||||
<el-switch v-model="formConf.disabled" /> |
||||
</el-form-item> |
||||
<el-form-item label="表单按钮"> |
||||
<el-switch v-model="formConf.formBtns" /> |
||||
</el-form-item> |
||||
<el-form-item label="显示未选中组件边框"> |
||||
<el-switch v-model="formConf.unFocusedComponentBorder" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-scrollbar> |
||||
</div> |
||||
|
||||
<treeNode-dialog :visible.sync="dialogVisible" title="添加选项" @commit="addNode" /> |
||||
<icons-dialog :visible.sync="iconsVisible" :current="activeData[currentIconModel]" @select="setIcon" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { isArray } from 'util' |
||||
import draggable from 'vuedraggable' |
||||
import TreeNodeDialog from './TreeNodeDialog' |
||||
import { isNumberStr } from '@/utils/index' |
||||
import IconsDialog from './IconsDialog' |
||||
import { |
||||
inputComponents, |
||||
selectComponents, |
||||
layoutComponents |
||||
} from '@/utils/generator/config' |
||||
|
||||
const dateTimeFormat = { |
||||
date: 'yyyy-MM-dd', |
||||
week: 'yyyy 第 WW 周', |
||||
month: 'yyyy-MM', |
||||
year: 'yyyy', |
||||
datetime: 'yyyy-MM-dd HH:mm:ss', |
||||
daterange: 'yyyy-MM-dd', |
||||
monthrange: 'yyyy-MM', |
||||
datetimerange: 'yyyy-MM-dd HH:mm:ss' |
||||
} |
||||
|
||||
export default { |
||||
components: { |
||||
draggable, |
||||
TreeNodeDialog, |
||||
IconsDialog |
||||
}, |
||||
props: ['showField', 'activeData', 'formConf'], |
||||
data() { |
||||
return { |
||||
currentTab: 'field', |
||||
currentNode: null, |
||||
dialogVisible: false, |
||||
iconsVisible: false, |
||||
currentIconModel: null, |
||||
dateTypeOptions: [ |
||||
{ |
||||
label: '日(date)', |
||||
value: 'date' |
||||
}, |
||||
{ |
||||
label: '周(week)', |
||||
value: 'week' |
||||
}, |
||||
{ |
||||
label: '月(month)', |
||||
value: 'month' |
||||
}, |
||||
{ |
||||
label: '年(year)', |
||||
value: 'year' |
||||
}, |
||||
{ |
||||
label: '日期时间(datetime)', |
||||
value: 'datetime' |
||||
} |
||||
], |
||||
dateRangeTypeOptions: [ |
||||
{ |
||||
label: '日期范围(daterange)', |
||||
value: 'daterange' |
||||
}, |
||||
{ |
||||
label: '月范围(monthrange)', |
||||
value: 'monthrange' |
||||
}, |
||||
{ |
||||
label: '日期时间范围(datetimerange)', |
||||
value: 'datetimerange' |
||||
} |
||||
], |
||||
colorFormatOptions: [ |
||||
{ |
||||
label: 'hex', |
||||
value: 'hex' |
||||
}, |
||||
{ |
||||
label: 'rgb', |
||||
value: 'rgb' |
||||
}, |
||||
{ |
||||
label: 'rgba', |
||||
value: 'rgba' |
||||
}, |
||||
{ |
||||
label: 'hsv', |
||||
value: 'hsv' |
||||
}, |
||||
{ |
||||
label: 'hsl', |
||||
value: 'hsl' |
||||
} |
||||
], |
||||
justifyOptions: [ |
||||
{ |
||||
label: 'start', |
||||
value: 'start' |
||||
}, |
||||
{ |
||||
label: 'end', |
||||
value: 'end' |
||||
}, |
||||
{ |
||||
label: 'center', |
||||
value: 'center' |
||||
}, |
||||
{ |
||||
label: 'space-around', |
||||
value: 'space-around' |
||||
}, |
||||
{ |
||||
label: 'space-between', |
||||
value: 'space-between' |
||||
} |
||||
], |
||||
layoutTreeProps: { |
||||
label(data, node) { |
||||
return data.componentName || `${data.label}: ${data.vModel}` |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
documentLink() { |
||||
return ( |
||||
this.activeData.document |
||||
|| 'https://element.eleme.cn/#/zh-CN/component/installation' |
||||
) |
||||
}, |
||||
dateOptions() { |
||||
if ( |
||||
this.activeData.type !== undefined |
||||
&& this.activeData.tag === 'el-date-picker' |
||||
) { |
||||
if (this.activeData['start-placeholder'] === undefined) { |
||||
return this.dateTypeOptions |
||||
} |
||||
return this.dateRangeTypeOptions |
||||
} |
||||
return [] |
||||
}, |
||||
tagList() { |
||||
return [ |
||||
{ |
||||
label: '输入型组件', |
||||
options: inputComponents |
||||
}, |
||||
{ |
||||
label: '选择型组件', |
||||
options: selectComponents |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
methods: { |
||||
addReg() { |
||||
this.activeData.regList.push({ |
||||
pattern: '', |
||||
message: '' |
||||
}) |
||||
}, |
||||
addSelectItem() { |
||||
this.activeData.options.push({ |
||||
label: '', |
||||
value: '' |
||||
}) |
||||
}, |
||||
addTreeItem() { |
||||
++this.idGlobal |
||||
this.dialogVisible = true |
||||
this.currentNode = this.activeData.options |
||||
}, |
||||
renderContent(h, { node, data, store }) { |
||||
return ( |
||||
<div class="custom-tree-node"> |
||||
<span>{node.label}</span> |
||||
<span class="node-operation"> |
||||
<i on-click={() => this.append(data)} |
||||
class="el-icon-plus" |
||||
title="添加" |
||||
></i> |
||||
<i on-click={() => this.remove(node, data)} |
||||
class="el-icon-delete" |
||||
title="删除" |
||||
></i> |
||||
</span> |
||||
</div> |
||||
) |
||||
}, |
||||
append(data) { |
||||
if (!data.children) { |
||||
this.$set(data, 'children', []) |
||||
} |
||||
this.dialogVisible = true |
||||
this.currentNode = data.children |
||||
}, |
||||
remove(node, data) { |
||||
const { parent } = node |
||||
const children = parent.data.children || parent.data |
||||
const index = children.findIndex(d => d.id === data.id) |
||||
children.splice(index, 1) |
||||
}, |
||||
addNode(data) { |
||||
this.currentNode.push(data) |
||||
}, |
||||
setOptionValue(item, val) { |
||||
item.value = isNumberStr(val) ? +val : val |
||||
}, |
||||
setDefaultValue(val) { |
||||
if (Array.isArray(val)) { |
||||
return val.join(',') |
||||
} |
||||
if (['string', 'number'].indexOf(val) > -1) { |
||||
return val |
||||
} |
||||
if (typeof val === 'boolean') { |
||||
return `${val}` |
||||
} |
||||
return val |
||||
}, |
||||
onDefaultValueInput(str) { |
||||
if (isArray(this.activeData.defaultValue)) { |
||||
// 数组 |
||||
this.$set( |
||||
this.activeData, |
||||
'defaultValue', |
||||
str.split(',').map(val => (isNumberStr(val) ? +val : val)) |
||||
) |
||||
} else if (['true', 'false'].indexOf(str) > -1) { |
||||
// 布尔 |
||||
this.$set(this.activeData, 'defaultValue', JSON.parse(str)) |
||||
} else { |
||||
// 字符串和数字 |
||||
this.$set( |
||||
this.activeData, |
||||
'defaultValue', |
||||
isNumberStr(str) ? +str : str |
||||
) |
||||
} |
||||
}, |
||||
onSwitchValueInput(val, name) { |
||||
if (['true', 'false'].indexOf(val) > -1) { |
||||
this.$set(this.activeData, name, JSON.parse(val)) |
||||
} else { |
||||
this.$set(this.activeData, name, isNumberStr(val) ? +val : val) |
||||
} |
||||
}, |
||||
setTimeValue(val, type) { |
||||
const valueFormat = type === 'week' ? dateTimeFormat.date : val |
||||
this.$set(this.activeData, 'defaultValue', null) |
||||
this.$set(this.activeData, 'value-format', valueFormat) |
||||
this.$set(this.activeData, 'format', val) |
||||
}, |
||||
spanChange(val) { |
||||
this.formConf.span = val |
||||
}, |
||||
multipleChange(val) { |
||||
this.$set(this.activeData, 'defaultValue', val ? [] : '') |
||||
}, |
||||
dateTypeChange(val) { |
||||
this.setTimeValue(dateTimeFormat[val], val) |
||||
}, |
||||
rangeChange(val) { |
||||
this.$set( |
||||
this.activeData, |
||||
'defaultValue', |
||||
val ? [this.activeData.min, this.activeData.max] : this.activeData.min |
||||
) |
||||
}, |
||||
rateTextChange(val) { |
||||
if (val) this.activeData['show-score'] = false |
||||
}, |
||||
rateScoreChange(val) { |
||||
if (val) this.activeData['show-text'] = false |
||||
}, |
||||
colorFormatChange(val) { |
||||
this.activeData.defaultValue = null |
||||
this.activeData['show-alpha'] = val.indexOf('a') > -1 |
||||
this.activeData.renderKey = +new Date() // 更新renderKey,重新渲染该组件 |
||||
}, |
||||
openIconsDialog(model) { |
||||
this.iconsVisible = true |
||||
this.currentIconModel = model |
||||
}, |
||||
setIcon(val) { |
||||
this.activeData[this.currentIconModel] = val |
||||
}, |
||||
tagChange(tagIcon) { |
||||
let target = inputComponents.find(item => item.tagIcon === tagIcon) |
||||
if (!target) target = selectComponents.find(item => item.tagIcon === tagIcon) |
||||
this.$emit('tag-change', target) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.right-board { |
||||
width: 350px; |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
padding-top: 3px; |
||||
.field-box { |
||||
position: relative; |
||||
height: calc(100vh - 42px); |
||||
box-sizing: border-box; |
||||
overflow: hidden; |
||||
} |
||||
.el-scrollbar { |
||||
height: 100%; |
||||
} |
||||
} |
||||
.select-item { |
||||
display: flex; |
||||
border: 1px dashed #fff; |
||||
box-sizing: border-box; |
||||
& .close-btn { |
||||
cursor: pointer; |
||||
color: #f56c6c; |
||||
} |
||||
& .el-input + .el-input { |
||||
margin-left: 4px; |
||||
} |
||||
} |
||||
.select-item + .select-item { |
||||
margin-top: 4px; |
||||
} |
||||
.select-item.sortable-chosen { |
||||
border: 1px dashed #409eff; |
||||
} |
||||
.select-line-icon { |
||||
line-height: 32px; |
||||
font-size: 22px; |
||||
padding: 0 4px; |
||||
color: #777; |
||||
} |
||||
.option-drag { |
||||
cursor: move; |
||||
} |
||||
.time-range { |
||||
.el-date-editor { |
||||
width: 227px; |
||||
} |
||||
::v-deep .el-icon-time { |
||||
display: none; |
||||
} |
||||
} |
||||
.document-link { |
||||
position: absolute; |
||||
display: block; |
||||
width: 26px; |
||||
height: 26px; |
||||
top: 0; |
||||
left: 0; |
||||
cursor: pointer; |
||||
background: #409eff; |
||||
z-index: 1; |
||||
border-radius: 0 0 6px 0; |
||||
text-align: center; |
||||
line-height: 26px; |
||||
color: #fff; |
||||
font-size: 18px; |
||||
} |
||||
.node-label{ |
||||
font-size: 14px; |
||||
} |
||||
.node-icon{ |
||||
color: #bebfc3; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,149 @@ |
||||
<template> |
||||
<div> |
||||
<el-dialog |
||||
v-bind="$attrs" |
||||
:close-on-click-modal="false" |
||||
:modal-append-to-body="false" |
||||
v-on="$listeners" |
||||
@open="onOpen" |
||||
@close="onClose" |
||||
> |
||||
<el-row :gutter="0"> |
||||
<el-form |
||||
ref="elForm" |
||||
:model="formData" |
||||
:rules="rules" |
||||
size="small" |
||||
label-width="100px" |
||||
> |
||||
<el-col :span="24"> |
||||
<el-form-item |
||||
label="选项名" |
||||
prop="label" |
||||
> |
||||
<el-input |
||||
v-model="formData.label" |
||||
placeholder="请输入选项名" |
||||
clearable |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="24"> |
||||
<el-form-item |
||||
label="选项值" |
||||
prop="value" |
||||
> |
||||
<el-input |
||||
v-model="formData.value" |
||||
placeholder="请输入选项值" |
||||
clearable |
||||
> |
||||
<el-select |
||||
slot="append" |
||||
v-model="dataType" |
||||
:style="{width: '100px'}" |
||||
> |
||||
<el-option |
||||
v-for="(item, index) in dataTypeOptions" |
||||
:key="index" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
:disabled="item.disabled" |
||||
/> |
||||
</el-select> |
||||
</el-input> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-form> |
||||
</el-row> |
||||
<div slot="footer"> |
||||
<el-button |
||||
type="primary" |
||||
@click="handleConfirm" |
||||
> |
||||
确定 |
||||
</el-button> |
||||
<el-button @click="close"> |
||||
取消 |
||||
</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import { isNumberStr } from '@/utils/index' |
||||
|
||||
export default { |
||||
components: {}, |
||||
inheritAttrs: false, |
||||
props: [], |
||||
data() { |
||||
return { |
||||
id: 100, |
||||
formData: { |
||||
label: undefined, |
||||
value: undefined |
||||
}, |
||||
rules: { |
||||
label: [ |
||||
{ |
||||
required: true, |
||||
message: '请输入选项名', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
value: [ |
||||
{ |
||||
required: true, |
||||
message: '请输入选项值', |
||||
trigger: 'blur' |
||||
} |
||||
] |
||||
}, |
||||
dataType: 'string', |
||||
dataTypeOptions: [ |
||||
{ |
||||
label: '字符串', |
||||
value: 'string' |
||||
}, |
||||
{ |
||||
label: '数字', |
||||
value: 'number' |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
computed: {}, |
||||
watch: { |
||||
// eslint-disable-next-line func-names |
||||
'formData.value': function (val) { |
||||
this.dataType = isNumberStr(val) ? 'number' : 'string' |
||||
} |
||||
}, |
||||
created() {}, |
||||
mounted() {}, |
||||
methods: { |
||||
onOpen() { |
||||
this.formData = { |
||||
label: undefined, |
||||
value: undefined |
||||
} |
||||
}, |
||||
onClose() {}, |
||||
close() { |
||||
this.$emit('update:visible', false) |
||||
}, |
||||
handleConfirm() { |
||||
this.$refs.elForm.validate(valid => { |
||||
if (!valid) return |
||||
if (this.dataType === 'number') { |
||||
this.formData.value = parseFloat(this.formData.value) |
||||
} |
||||
this.formData.id = this.id++ |
||||
this.$emit('commit', this.formData) |
||||
this.close() |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
@ -0,0 +1,783 @@ |
||||
<template> |
||||
<div class="container"> |
||||
<div class="left-board"> |
||||
<div class="logo-wrapper"> |
||||
<div class="logo"> |
||||
<img :src="logo" alt="logo"> Form Generator |
||||
</div> |
||||
</div> |
||||
<el-scrollbar class="left-scrollbar"> |
||||
<div class="components-list"> |
||||
<div class="components-title"> |
||||
<svg-icon icon-class="component" />输入型组件 |
||||
</div> |
||||
<draggable |
||||
class="components-draggable" |
||||
:list="inputComponents" |
||||
:group="{ name: 'componentsGroup', pull: 'clone', put: false }" |
||||
:clone="cloneComponent" |
||||
draggable=".components-item" |
||||
:sort="false" |
||||
@end="onEnd" |
||||
> |
||||
<div |
||||
v-for="(element, index) in inputComponents" :key="index" class="components-item" |
||||
@click="addComponent(element)" |
||||
> |
||||
<div class="components-body"> |
||||
<svg-icon :icon-class="element.tagIcon" /> |
||||
{{ element.label }} |
||||
</div> |
||||
</div> |
||||
</draggable> |
||||
<div class="components-title"> |
||||
<svg-icon icon-class="component" />选择型组件 |
||||
</div> |
||||
<draggable |
||||
class="components-draggable" |
||||
:list="selectComponents" |
||||
:group="{ name: 'componentsGroup', pull: 'clone', put: false }" |
||||
:clone="cloneComponent" |
||||
draggable=".components-item" |
||||
:sort="false" |
||||
@end="onEnd" |
||||
> |
||||
<div |
||||
v-for="(element, index) in selectComponents" |
||||
:key="index" |
||||
class="components-item" |
||||
@click="addComponent(element)" |
||||
> |
||||
<div class="components-body"> |
||||
<svg-icon :icon-class="element.tagIcon" /> |
||||
{{ element.label }} |
||||
</div> |
||||
</div> |
||||
</draggable> |
||||
<div class="components-title"> |
||||
<svg-icon icon-class="component" /> 布局型组件 |
||||
</div> |
||||
<draggable |
||||
class="components-draggable" :list="layoutComponents" |
||||
:group="{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent" |
||||
draggable=".components-item" :sort="false" @end="onEnd" |
||||
> |
||||
<div |
||||
v-for="(element, index) in layoutComponents" :key="index" class="components-item" |
||||
@click="addComponent(element)" |
||||
> |
||||
<div class="components-body"> |
||||
<svg-icon :icon-class="element.tagIcon" /> |
||||
{{ element.label }} |
||||
</div> |
||||
</div> |
||||
</draggable> |
||||
</div> |
||||
</el-scrollbar> |
||||
</div> |
||||
|
||||
<div class="center-board"> |
||||
<div class="action-bar"> |
||||
<el-button icon="el-icon-download" type="text" @click="download"> |
||||
导出vue文件 |
||||
</el-button> |
||||
<el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy"> |
||||
复制代码 |
||||
</el-button> |
||||
<el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty"> |
||||
清空 |
||||
</el-button> |
||||
</div> |
||||
<el-scrollbar class="center-scrollbar"> |
||||
<el-row class="center-board-row" :gutter="formConf.gutter"> |
||||
<el-form |
||||
:size="formConf.size" |
||||
:label-position="formConf.labelPosition" |
||||
:disabled="formConf.disabled" |
||||
:label-width="formConf.labelWidth + 'px'" |
||||
> |
||||
<draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup"> |
||||
<draggable-item |
||||
v-for="(element, index) in drawingList" |
||||
:key="element.renderKey" |
||||
:drawing-list="drawingList" |
||||
:element="element" |
||||
:index="index" |
||||
:active-id="activeId" |
||||
:form-conf="formConf" |
||||
@activeItem="activeFormItem" |
||||
@copyItem="drawingItemCopy" |
||||
@deleteItem="drawingItemDelete" |
||||
/> |
||||
</draggable> |
||||
<div v-show="!drawingList.length" class="empty-info"> |
||||
从左侧拖入或点选组件进行表单设计 |
||||
</div> |
||||
</el-form> |
||||
</el-row> |
||||
</el-scrollbar> |
||||
</div> |
||||
|
||||
<right-panel |
||||
:active-data="activeData" |
||||
:form-conf="formConf" |
||||
:show-field="!!drawingList.length" |
||||
@tag-change="tagChange" |
||||
/> |
||||
|
||||
<code-type-dialog |
||||
:visible.sync="dialogVisible" |
||||
title="选择生成类型" |
||||
:show-file-name="showFileName" |
||||
@confirm="generate" |
||||
/> |
||||
<input id="copyNode" type="hidden"> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import draggable from 'vuedraggable' |
||||
import beautifier from 'js-beautify' |
||||
import ClipboardJS from 'clipboard' |
||||
import render from '@/utils/generator/render' |
||||
import RightPanel from './RightPanel' |
||||
import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config' |
||||
import { beautifierConf, titleCase } from '@/utils/index' |
||||
import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html' |
||||
import { makeUpJs } from '@/utils/generator/js' |
||||
import { makeUpCss } from '@/utils/generator/css' |
||||
import drawingDefault from '@/utils/generator/drawingDefault' |
||||
import logo from '@/assets/logo/logo.png' |
||||
import CodeTypeDialog from './CodeTypeDialog' |
||||
import DraggableItem from './DraggableItem' |
||||
|
||||
let oldActiveId |
||||
let tempActiveData |
||||
|
||||
export default { |
||||
components: { |
||||
draggable, |
||||
render, |
||||
RightPanel, |
||||
CodeTypeDialog, |
||||
DraggableItem |
||||
}, |
||||
data() { |
||||
return { |
||||
logo, |
||||
idGlobal: 100, |
||||
formConf, |
||||
inputComponents, |
||||
selectComponents, |
||||
layoutComponents, |
||||
labelWidth: 100, |
||||
drawingList: drawingDefault, |
||||
drawingData: {}, |
||||
activeId: drawingDefault[0].formId, |
||||
drawerVisible: false, |
||||
formData: {}, |
||||
dialogVisible: false, |
||||
generateConf: null, |
||||
showFileName: false, |
||||
activeData: drawingDefault[0] |
||||
} |
||||
}, |
||||
created() { |
||||
// 防止 firefox 下 拖拽 会新打卡一个选项卡 |
||||
document.body.ondrop = event => { |
||||
event.preventDefault() |
||||
event.stopPropagation() |
||||
} |
||||
}, |
||||
watch: { |
||||
// eslint-disable-next-line func-names |
||||
'activeData.label': function (val, oldVal) { |
||||
if ( |
||||
this.activeData.placeholder === undefined |
||||
|| !this.activeData.tag |
||||
|| oldActiveId !== this.activeId |
||||
) { |
||||
return |
||||
} |
||||
this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val |
||||
}, |
||||
activeId: { |
||||
handler(val) { |
||||
oldActiveId = val |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
mounted() { |
||||
const clipboard = new ClipboardJS('#copyNode', { |
||||
text: trigger => { |
||||
const codeStr = this.generateCode() |
||||
this.$notify({ |
||||
title: '成功', |
||||
message: '代码已复制到剪切板,可粘贴。', |
||||
type: 'success' |
||||
}) |
||||
return codeStr |
||||
} |
||||
}) |
||||
clipboard.on('error', e => { |
||||
this.$message.error('代码复制失败') |
||||
}) |
||||
}, |
||||
methods: { |
||||
activeFormItem(element) { |
||||
this.activeData = element |
||||
this.activeId = element.formId |
||||
}, |
||||
onEnd(obj, a) { |
||||
if (obj.from !== obj.to) { |
||||
this.activeData = tempActiveData |
||||
this.activeId = this.idGlobal |
||||
} |
||||
}, |
||||
addComponent(item) { |
||||
const clone = this.cloneComponent(item) |
||||
this.drawingList.push(clone) |
||||
this.activeFormItem(clone) |
||||
}, |
||||
cloneComponent(origin) { |
||||
const clone = JSON.parse(JSON.stringify(origin)) |
||||
clone.formId = ++this.idGlobal |
||||
clone.span = formConf.span |
||||
clone.renderKey = +new Date() // 改变renderKey后可以实现强制更新组件 |
||||
if (!clone.layout) clone.layout = 'colFormItem' |
||||
if (clone.layout === 'colFormItem') { |
||||
clone.vModel = `field${this.idGlobal}` |
||||
clone.placeholder !== undefined && (clone.placeholder += clone.label) |
||||
tempActiveData = clone |
||||
} else if (clone.layout === 'rowFormItem') { |
||||
delete clone.label |
||||
clone.componentName = `row${this.idGlobal}` |
||||
clone.gutter = this.formConf.gutter |
||||
tempActiveData = clone |
||||
} |
||||
return tempActiveData |
||||
}, |
||||
AssembleFormData() { |
||||
this.formData = { |
||||
fields: JSON.parse(JSON.stringify(this.drawingList)), |
||||
...this.formConf |
||||
} |
||||
}, |
||||
generate(data) { |
||||
const func = this[`exec${titleCase(this.operationType)}`] |
||||
this.generateConf = data |
||||
func && func(data) |
||||
}, |
||||
execRun(data) { |
||||
this.AssembleFormData() |
||||
this.drawerVisible = true |
||||
}, |
||||
execDownload(data) { |
||||
const codeStr = this.generateCode() |
||||
const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' }) |
||||
this.$download.saveAs(blob, data.fileName) |
||||
}, |
||||
execCopy(data) { |
||||
document.getElementById('copyNode').click() |
||||
}, |
||||
empty() { |
||||
this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then( |
||||
() => { |
||||
this.drawingList = [] |
||||
} |
||||
) |
||||
}, |
||||
drawingItemCopy(item, parent) { |
||||
let clone = JSON.parse(JSON.stringify(item)) |
||||
clone = this.createIdAndKey(clone) |
||||
parent.push(clone) |
||||
this.activeFormItem(clone) |
||||
}, |
||||
createIdAndKey(item) { |
||||
item.formId = ++this.idGlobal |
||||
item.renderKey = +new Date() |
||||
if (item.layout === 'colFormItem') { |
||||
item.vModel = `field${this.idGlobal}` |
||||
} else if (item.layout === 'rowFormItem') { |
||||
item.componentName = `row${this.idGlobal}` |
||||
} |
||||
if (Array.isArray(item.children)) { |
||||
item.children = item.children.map(childItem => this.createIdAndKey(childItem)) |
||||
} |
||||
return item |
||||
}, |
||||
drawingItemDelete(index, parent) { |
||||
parent.splice(index, 1) |
||||
this.$nextTick(() => { |
||||
const len = this.drawingList.length |
||||
if (len) { |
||||
this.activeFormItem(this.drawingList[len - 1]) |
||||
} |
||||
}) |
||||
}, |
||||
generateCode() { |
||||
const { type } = this.generateConf |
||||
this.AssembleFormData() |
||||
const script = vueScript(makeUpJs(this.formData, type)) |
||||
const html = vueTemplate(makeUpHtml(this.formData, type)) |
||||
const css = cssStyle(makeUpCss(this.formData)) |
||||
return beautifier.html(html + script + css, beautifierConf.html) |
||||
}, |
||||
download() { |
||||
this.dialogVisible = true |
||||
this.showFileName = true |
||||
this.operationType = 'download' |
||||
}, |
||||
run() { |
||||
this.dialogVisible = true |
||||
this.showFileName = false |
||||
this.operationType = 'run' |
||||
}, |
||||
copy() { |
||||
this.dialogVisible = true |
||||
this.showFileName = false |
||||
this.operationType = 'copy' |
||||
}, |
||||
tagChange(newTag) { |
||||
newTag = this.cloneComponent(newTag) |
||||
newTag.vModel = this.activeData.vModel |
||||
newTag.formId = this.activeId |
||||
newTag.span = this.activeData.span |
||||
delete this.activeData.tag |
||||
delete this.activeData.tagIcon |
||||
delete this.activeData.document |
||||
Object.keys(newTag).forEach(key => { |
||||
if (this.activeData[key] !== undefined |
||||
&& typeof this.activeData[key] === typeof newTag[key]) { |
||||
newTag[key] = this.activeData[key] |
||||
} |
||||
}) |
||||
this.activeData = newTag |
||||
this.updateDrawingList(newTag, this.drawingList) |
||||
}, |
||||
updateDrawingList(newTag, list) { |
||||
const index = list.findIndex(item => item.formId === this.activeId) |
||||
if (index > -1) { |
||||
list.splice(index, 1, newTag) |
||||
} else { |
||||
list.forEach(item => { |
||||
if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='scss'> |
||||
body, html{ |
||||
margin: 0; |
||||
padding: 0; |
||||
background: #fff; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
-webkit-font-smoothing: antialiased; |
||||
text-rendering: optimizeLegibility; |
||||
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji; |
||||
} |
||||
|
||||
input, textarea{ |
||||
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji; |
||||
} |
||||
|
||||
.editor-tabs{ |
||||
background: #121315; |
||||
.el-tabs__header{ |
||||
margin: 0; |
||||
border-bottom-color: #121315; |
||||
.el-tabs__nav{ |
||||
border-color: #121315; |
||||
} |
||||
} |
||||
.el-tabs__item{ |
||||
height: 32px; |
||||
line-height: 32px; |
||||
color: #888a8e; |
||||
border-left: 1px solid #121315 !important; |
||||
background: #363636; |
||||
margin-right: 5px; |
||||
user-select: none; |
||||
} |
||||
.el-tabs__item.is-active{ |
||||
background: #1e1e1e; |
||||
border-bottom-color: #1e1e1e!important; |
||||
color: #fff; |
||||
} |
||||
.el-icon-edit{ |
||||
color: #f1fa8c; |
||||
} |
||||
.el-icon-document{ |
||||
color: #a95812; |
||||
} |
||||
} |
||||
|
||||
// home |
||||
.right-scrollbar { |
||||
.el-scrollbar__view { |
||||
padding: 12px 18px 15px 15px; |
||||
} |
||||
} |
||||
.left-scrollbar .el-scrollbar__wrap { |
||||
box-sizing: border-box; |
||||
overflow-x: hidden !important; |
||||
margin-bottom: 0 !important; |
||||
} |
||||
.center-tabs{ |
||||
.el-tabs__header{ |
||||
margin-bottom: 0!important; |
||||
} |
||||
.el-tabs__item{ |
||||
width: 50%; |
||||
text-align: center; |
||||
} |
||||
.el-tabs__nav{ |
||||
width: 100%; |
||||
} |
||||
} |
||||
.reg-item{ |
||||
padding: 12px 6px; |
||||
background: #f8f8f8; |
||||
position: relative; |
||||
border-radius: 4px; |
||||
.close-btn{ |
||||
position: absolute; |
||||
right: -6px; |
||||
top: -6px; |
||||
display: block; |
||||
width: 16px; |
||||
height: 16px; |
||||
line-height: 16px; |
||||
background: rgba(0, 0, 0, 0.2); |
||||
border-radius: 50%; |
||||
color: #fff; |
||||
text-align: center; |
||||
z-index: 1; |
||||
cursor: pointer; |
||||
font-size: 12px; |
||||
&:hover{ |
||||
background: rgba(210, 23, 23, 0.5) |
||||
} |
||||
} |
||||
& + .reg-item{ |
||||
margin-top: 18px; |
||||
} |
||||
} |
||||
.action-bar{ |
||||
& .el-button+.el-button { |
||||
margin-left: 15px; |
||||
} |
||||
& i { |
||||
font-size: 20px; |
||||
vertical-align: middle; |
||||
position: relative; |
||||
top: -1px; |
||||
} |
||||
} |
||||
|
||||
.custom-tree-node{ |
||||
width: 100%; |
||||
font-size: 14px; |
||||
.node-operation{ |
||||
float: right; |
||||
} |
||||
i[class*="el-icon"] + i[class*="el-icon"]{ |
||||
margin-left: 6px; |
||||
} |
||||
.el-icon-plus{ |
||||
color: #409EFF; |
||||
} |
||||
.el-icon-delete{ |
||||
color: #157a0c; |
||||
} |
||||
} |
||||
|
||||
.left-scrollbar .el-scrollbar__view{ |
||||
overflow-x: hidden; |
||||
} |
||||
|
||||
.el-rate{ |
||||
display: inline-block; |
||||
vertical-align: text-top; |
||||
} |
||||
.el-upload__tip{ |
||||
line-height: 1.2; |
||||
} |
||||
|
||||
$selectedColor: #f6f7ff; |
||||
$lighterBlue: #409EFF; |
||||
|
||||
.container { |
||||
position: relative; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.components-list { |
||||
padding: 8px; |
||||
box-sizing: border-box; |
||||
height: 100%; |
||||
.components-item { |
||||
display: inline-block; |
||||
width: 48%; |
||||
margin: 1%; |
||||
transition: transform 0ms !important; |
||||
} |
||||
} |
||||
.components-draggable{ |
||||
padding-bottom: 20px; |
||||
} |
||||
.components-title{ |
||||
font-size: 14px; |
||||
color: #222; |
||||
margin: 6px 2px; |
||||
.svg-icon{ |
||||
color: #666; |
||||
font-size: 18px; |
||||
} |
||||
} |
||||
|
||||
.components-body { |
||||
padding: 8px 10px; |
||||
background: $selectedColor; |
||||
font-size: 12px; |
||||
cursor: move; |
||||
border: 1px dashed $selectedColor; |
||||
border-radius: 3px; |
||||
.svg-icon{ |
||||
color: #777; |
||||
font-size: 15px; |
||||
} |
||||
&:hover { |
||||
border: 1px dashed #787be8; |
||||
color: #787be8; |
||||
.svg-icon { |
||||
color: #787be8; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.left-board { |
||||
width: 260px; |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
height: 100vh; |
||||
} |
||||
.left-scrollbar{ |
||||
height: calc(100vh - 42px); |
||||
overflow: hidden; |
||||
} |
||||
.center-scrollbar { |
||||
height: calc(100vh - 42px); |
||||
overflow: hidden; |
||||
border-left: 1px solid #f1e8e8; |
||||
border-right: 1px solid #f1e8e8; |
||||
box-sizing: border-box; |
||||
} |
||||
.center-board { |
||||
height: 100vh; |
||||
width: auto; |
||||
margin: 0 350px 0 260px; |
||||
box-sizing: border-box; |
||||
} |
||||
.empty-info{ |
||||
position: absolute; |
||||
top: 46%; |
||||
left: 0; |
||||
right: 0; |
||||
text-align: center; |
||||
font-size: 18px; |
||||
color: #ccb1ea; |
||||
letter-spacing: 4px; |
||||
} |
||||
.action-bar{ |
||||
position: relative; |
||||
height: 42px; |
||||
text-align: right; |
||||
padding: 0 15px; |
||||
box-sizing: border-box;; |
||||
border: 1px solid #f1e8e8; |
||||
border-top: none; |
||||
border-left: none; |
||||
.delete-btn{ |
||||
color: #F56C6C; |
||||
} |
||||
} |
||||
.logo-wrapper{ |
||||
position: relative; |
||||
height: 42px; |
||||
background: #fff; |
||||
border-bottom: 1px solid #f1e8e8; |
||||
box-sizing: border-box; |
||||
} |
||||
.logo{ |
||||
position: absolute; |
||||
left: 12px; |
||||
top: 6px; |
||||
line-height: 30px; |
||||
color: #00afff; |
||||
font-weight: 600; |
||||
font-size: 17px; |
||||
white-space: nowrap; |
||||
> img{ |
||||
width: 30px; |
||||
height: 30px; |
||||
vertical-align: top; |
||||
} |
||||
.github{ |
||||
display: inline-block; |
||||
vertical-align: sub; |
||||
margin-left: 15px; |
||||
> img{ |
||||
height: 22px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.center-board-row { |
||||
padding: 12px 12px 15px 12px; |
||||
box-sizing: border-box; |
||||
& > .el-form { |
||||
// 69 = 12+15+42 |
||||
height: calc(100vh - 69px); |
||||
} |
||||
} |
||||
.drawing-board { |
||||
height: 100%; |
||||
position: relative; |
||||
.components-body { |
||||
padding: 0; |
||||
margin: 0; |
||||
font-size: 0; |
||||
} |
||||
.sortable-ghost { |
||||
position: relative; |
||||
display: block; |
||||
overflow: hidden; |
||||
&::before { |
||||
content: " "; |
||||
position: absolute; |
||||
left: 0; |
||||
right: 0; |
||||
top: 0; |
||||
height: 3px; |
||||
background: rgb(89, 89, 223); |
||||
z-index: 2; |
||||
} |
||||
} |
||||
.components-item.sortable-ghost { |
||||
width: 100%; |
||||
height: 60px; |
||||
background-color: $selectedColor; |
||||
} |
||||
.active-from-item { |
||||
& > .el-form-item{ |
||||
background: $selectedColor; |
||||
border-radius: 6px; |
||||
} |
||||
& > .drawing-item-copy, & > .drawing-item-delete{ |
||||
display: initial; |
||||
} |
||||
& > .component-name{ |
||||
color: $lighterBlue; |
||||
} |
||||
} |
||||
.el-form-item{ |
||||
margin-bottom: 15px; |
||||
} |
||||
} |
||||
.drawing-item{ |
||||
position: relative; |
||||
cursor: move; |
||||
&.unfocus-bordered:not(.activeFromItem) > div:first-child { |
||||
border: 1px dashed #ccc; |
||||
} |
||||
.el-form-item{ |
||||
padding: 12px 10px; |
||||
} |
||||
} |
||||
.drawing-row-item{ |
||||
position: relative; |
||||
cursor: move; |
||||
box-sizing: border-box; |
||||
border: 1px dashed #ccc; |
||||
border-radius: 3px; |
||||
padding: 0 2px; |
||||
margin-bottom: 15px; |
||||
.drawing-row-item { |
||||
margin-bottom: 2px; |
||||
} |
||||
.el-col{ |
||||
margin-top: 22px; |
||||
} |
||||
.el-form-item{ |
||||
margin-bottom: 0; |
||||
} |
||||
.drag-wrapper{ |
||||
min-height: 80px; |
||||
} |
||||
&.active-from-item{ |
||||
border: 1px dashed $lighterBlue; |
||||
} |
||||
.component-name{ |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
font-size: 12px; |
||||
color: #bbb; |
||||
display: inline-block; |
||||
padding: 0 6px; |
||||
} |
||||
} |
||||
.drawing-item, .drawing-row-item{ |
||||
&:hover { |
||||
& > .el-form-item{ |
||||
background: $selectedColor; |
||||
border-radius: 6px; |
||||
} |
||||
& > .drawing-item-copy, & > .drawing-item-delete{ |
||||
display: initial; |
||||
} |
||||
} |
||||
& > .drawing-item-copy, & > .drawing-item-delete{ |
||||
display: none; |
||||
position: absolute; |
||||
top: -10px; |
||||
width: 22px; |
||||
height: 22px; |
||||
line-height: 22px; |
||||
text-align: center; |
||||
border-radius: 50%; |
||||
font-size: 12px; |
||||
border: 1px solid; |
||||
cursor: pointer; |
||||
z-index: 1; |
||||
} |
||||
& > .drawing-item-copy{ |
||||
right: 56px; |
||||
border-color: $lighterBlue; |
||||
color: $lighterBlue; |
||||
background: #fff; |
||||
&:hover{ |
||||
background: $lighterBlue; |
||||
color: #fff; |
||||
} |
||||
} |
||||
& > .drawing-item-delete{ |
||||
right: 24px; |
||||
border-color: #F56C6C; |
||||
color: #F56C6C; |
||||
background: #fff; |
||||
&:hover{ |
||||
background: #F56C6C; |
||||
color: #fff; |
||||
} |
||||
} |
||||
} |
||||
|
||||
</style> |
||||
@ -0,0 +1,60 @@ |
||||
<template> |
||||
<el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="表名称" prop="tableName"> |
||||
<el-input placeholder="请输入仓库名称" v-model="info.tableName" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="表描述" prop="tableComment"> |
||||
<el-input placeholder="请输入" v-model="info.tableComment" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="实体类名称" prop="className"> |
||||
<el-input placeholder="请输入" v-model="info.className" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="作者" prop="functionAuthor"> |
||||
<el-input placeholder="请输入" v-model="info.functionAuthor" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="24"> |
||||
<el-form-item label="备注" prop="remark"> |
||||
<el-input type="textarea" :rows="3" v-model="info.remark"></el-input> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
info: { |
||||
type: Object, |
||||
default: null |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
rules: { |
||||
tableName: [ |
||||
{ required: true, message: "请输入表名称", trigger: "blur" } |
||||
], |
||||
tableComment: [ |
||||
{ required: true, message: "请输入表描述", trigger: "blur" } |
||||
], |
||||
className: [ |
||||
{ required: true, message: "请输入实体类名称", trigger: "blur" } |
||||
], |
||||
functionAuthor: [ |
||||
{ required: true, message: "请输入作者", trigger: "blur" } |
||||
] |
||||
} |
||||
}; |
||||
} |
||||
}; |
||||
</script> |
||||
@ -0,0 +1,234 @@ |
||||
<template> |
||||
<el-card> |
||||
<el-tabs v-model="activeName"> |
||||
<el-tab-pane label="基本信息" name="basic"> |
||||
<basic-info-form ref="basicInfo" :info="info" /> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="字段信息" name="columnInfo"> |
||||
<el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight"> |
||||
<el-table-column label="序号" type="index" min-width="5%" class-name="allowDrag" /> |
||||
<el-table-column |
||||
label="字段列名" |
||||
prop="columnName" |
||||
min-width="10%" |
||||
:show-overflow-tooltip="true" |
||||
/> |
||||
<el-table-column label="字段描述" min-width="10%"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model="scope.row.columnComment"></el-input> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
label="物理类型" |
||||
prop="columnType" |
||||
min-width="10%" |
||||
:show-overflow-tooltip="true" |
||||
/> |
||||
<el-table-column label="Java类型" min-width="11%"> |
||||
<template slot-scope="scope"> |
||||
<el-select v-model="scope.row.javaType"> |
||||
<el-option label="Long" value="Long" /> |
||||
<el-option label="String" value="String" /> |
||||
<el-option label="Integer" value="Integer" /> |
||||
<el-option label="Double" value="Double" /> |
||||
<el-option label="BigDecimal" value="BigDecimal" /> |
||||
<el-option label="Date" value="Date" /> |
||||
<el-option label="Boolean" value="Boolean" /> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="java属性" min-width="10%"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model="scope.row.javaField"></el-input> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column label="插入" min-width="5%"> |
||||
<template slot-scope="scope"> |
||||
<el-checkbox true-label="1" false-label="0" v-model="scope.row.isInsert"></el-checkbox> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="编辑" min-width="5%"> |
||||
<template slot-scope="scope"> |
||||
<el-checkbox true-label="1" false-label="0" v-model="scope.row.isEdit"></el-checkbox> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="列表" min-width="5%"> |
||||
<template slot-scope="scope"> |
||||
<el-checkbox true-label="1" false-label="0" v-model="scope.row.isList"></el-checkbox> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="查询" min-width="5%"> |
||||
<template slot-scope="scope"> |
||||
<el-checkbox true-label="1" false-label="0" v-model="scope.row.isQuery"></el-checkbox> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="查询方式" min-width="10%"> |
||||
<template slot-scope="scope"> |
||||
<el-select v-model="scope.row.queryType"> |
||||
<el-option label="=" value="EQ" /> |
||||
<el-option label="!=" value="NE" /> |
||||
<el-option label=">" value="GT" /> |
||||
<el-option label=">=" value="GTE" /> |
||||
<el-option label="<" value="LT" /> |
||||
<el-option label="<=" value="LTE" /> |
||||
<el-option label="LIKE" value="LIKE" /> |
||||
<el-option label="BETWEEN" value="BETWEEN" /> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="必填" min-width="5%"> |
||||
<template slot-scope="scope"> |
||||
<el-checkbox true-label="1" false-label="0" v-model="scope.row.isRequired"></el-checkbox> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="显示类型" min-width="12%"> |
||||
<template slot-scope="scope"> |
||||
<el-select v-model="scope.row.htmlType"> |
||||
<el-option label="文本框" value="input" /> |
||||
<el-option label="文本域" value="textarea" /> |
||||
<el-option label="下拉框" value="select" /> |
||||
<el-option label="单选框" value="radio" /> |
||||
<el-option label="复选框" value="checkbox" /> |
||||
<el-option label="日期控件" value="datetime" /> |
||||
<el-option label="图片上传" value="imageUpload" /> |
||||
<el-option label="文件上传" value="fileUpload" /> |
||||
<el-option label="富文本控件" value="editor" /> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="字典类型" min-width="12%"> |
||||
<template slot-scope="scope"> |
||||
<el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择"> |
||||
<el-option |
||||
v-for="dict in dictOptions" |
||||
:key="dict.dictType" |
||||
:label="dict.dictName" |
||||
:value="dict.dictType"> |
||||
<span style="float: left">{{ dict.dictName }}</span> |
||||
<span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span> |
||||
</el-option> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="生成信息" name="genInfo"> |
||||
<gen-info-form ref="genInfo" :info="info" :tables="tables" :menus="menus"/> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
<el-form label-width="100px"> |
||||
<el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;"> |
||||
<el-button type="primary" @click="submitForm()">提交</el-button> |
||||
<el-button @click="close()">返回</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getGenTable, updateGenTable } from "@/api/tool/gen"; |
||||
import { optionselect as getDictOptionselect } from "@/api/system/dict/type"; |
||||
import { listMenu as getMenuTreeselect } from "@/api/system/menu"; |
||||
import basicInfoForm from "./basicInfoForm"; |
||||
import genInfoForm from "./genInfoForm"; |
||||
import Sortable from 'sortablejs' |
||||
|
||||
export default { |
||||
name: "GenEdit", |
||||
components: { |
||||
basicInfoForm, |
||||
genInfoForm |
||||
}, |
||||
data() { |
||||
return { |
||||
// 选中选项卡的 name |
||||
activeName: "columnInfo", |
||||
// 表格的高度 |
||||
tableHeight: document.documentElement.scrollHeight - 245 + "px", |
||||
// 表信息 |
||||
tables: [], |
||||
// 表列信息 |
||||
columns: [], |
||||
// 字典信息 |
||||
dictOptions: [], |
||||
// 菜单信息 |
||||
menus: [], |
||||
// 表详细信息 |
||||
info: {} |
||||
}; |
||||
}, |
||||
created() { |
||||
const tableId = this.$route.params && this.$route.params.tableId; |
||||
if (tableId) { |
||||
// 获取表详细信息 |
||||
getGenTable(tableId).then(res => { |
||||
this.columns = res.data.rows; |
||||
this.info = res.data.info; |
||||
this.tables = res.data.tables; |
||||
}); |
||||
/** 查询字典下拉列表 */ |
||||
getDictOptionselect().then(response => { |
||||
this.dictOptions = response.data; |
||||
}); |
||||
/** 查询菜单下拉列表 */ |
||||
getMenuTreeselect().then(response => { |
||||
this.menus = this.handleTree(response.data, "menuId"); |
||||
}); |
||||
} |
||||
}, |
||||
methods: { |
||||
/** 提交按钮 */ |
||||
submitForm() { |
||||
const basicForm = this.$refs.basicInfo.$refs.basicInfoForm; |
||||
const genForm = this.$refs.genInfo.$refs.genInfoForm; |
||||
Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => { |
||||
const validateResult = res.every(item => !!item); |
||||
if (validateResult) { |
||||
const genTable = Object.assign({}, basicForm.model, genForm.model); |
||||
genTable.columns = this.columns; |
||||
genTable.params = { |
||||
treeCode: genTable.treeCode, |
||||
treeName: genTable.treeName, |
||||
treeParentCode: genTable.treeParentCode, |
||||
parentMenuId: genTable.parentMenuId |
||||
}; |
||||
updateGenTable(genTable).then(res => { |
||||
this.$modal.msgSuccess(res.msg); |
||||
if (res.code === 200) { |
||||
this.close(); |
||||
} |
||||
}); |
||||
} else { |
||||
this.$modal.msgError("表单校验未通过,请重新检查提交内容"); |
||||
} |
||||
}); |
||||
}, |
||||
getFormPromise(form) { |
||||
return new Promise(resolve => { |
||||
form.validate(res => { |
||||
resolve(res); |
||||
}); |
||||
}); |
||||
}, |
||||
/** 关闭按钮 */ |
||||
close() { |
||||
const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: this.$route.query.pageNum } }; |
||||
this.$tab.closeOpenPage(obj); |
||||
} |
||||
}, |
||||
mounted() { |
||||
const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0]; |
||||
const sortable = Sortable.create(el, { |
||||
handle: ".allowDrag", |
||||
onEnd: evt => { |
||||
const targetRow = this.columns.splice(evt.oldIndex, 1)[0]; |
||||
this.columns.splice(evt.newIndex, 0, targetRow); |
||||
for (let index in this.columns) { |
||||
this.columns[index].sort = parseInt(index) + 1; |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
}; |
||||
</script> |
||||
@ -0,0 +1,299 @@ |
||||
<template> |
||||
<el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item prop="tplCategory"> |
||||
<span slot="label">生成模板</span> |
||||
<el-select v-model="info.tplCategory" @change="tplSelectChange"> |
||||
<el-option label="单表(增删改查)" value="crud" /> |
||||
<el-option label="树表(增删改查)" value="tree" /> |
||||
<el-option label="主子表(增删改查)" value="sub" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item prop="packageName"> |
||||
<span slot="label"> |
||||
生成包路径 |
||||
<el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-input v-model="info.packageName" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="12"> |
||||
<el-form-item prop="moduleName"> |
||||
<span slot="label"> |
||||
生成模块名 |
||||
<el-tooltip content="可理解为子系统名,例如 system" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-input v-model="info.moduleName" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="12"> |
||||
<el-form-item prop="businessName"> |
||||
<span slot="label"> |
||||
生成业务名 |
||||
<el-tooltip content="可理解为功能英文名,例如 user" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-input v-model="info.businessName" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="12"> |
||||
<el-form-item prop="functionName"> |
||||
<span slot="label"> |
||||
生成功能名 |
||||
<el-tooltip content="用作类描述,例如 用户" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-input v-model="info.functionName" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="12"> |
||||
<el-form-item> |
||||
<span slot="label"> |
||||
上级菜单 |
||||
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<treeselect |
||||
:append-to-body="true" |
||||
v-model="info.parentMenuId" |
||||
:options="menus" |
||||
:normalizer="normalizer" |
||||
:show-count="true" |
||||
placeholder="请选择系统菜单" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="12"> |
||||
<el-form-item prop="genType"> |
||||
<span slot="label"> |
||||
生成代码方式 |
||||
<el-tooltip content="默认为zip压缩包下载,也可以自定义生成路径" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-radio v-model="info.genType" label="0">zip压缩包</el-radio> |
||||
<el-radio v-model="info.genType" label="1">自定义路径</el-radio> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
<el-col :span="24" v-if="info.genType == '1'"> |
||||
<el-form-item prop="genPath"> |
||||
<span slot="label"> |
||||
自定义路径 |
||||
<el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-input v-model="info.genPath"> |
||||
<el-dropdown slot="append"> |
||||
<el-button type="primary"> |
||||
最近路径快速选择 |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item @click.native="info.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</el-input> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
|
||||
<el-row v-show="info.tplCategory == 'tree'"> |
||||
<h4 class="form-header">其他信息</h4> |
||||
<el-col :span="12"> |
||||
<el-form-item> |
||||
<span slot="label"> |
||||
树编码字段 |
||||
<el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-select v-model="info.treeCode" placeholder="请选择"> |
||||
<el-option |
||||
v-for="(column, index) in info.columns" |
||||
:key="index" |
||||
:label="column.columnName + ':' + column.columnComment" |
||||
:value="column.columnName" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item> |
||||
<span slot="label"> |
||||
树父编码字段 |
||||
<el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-select v-model="info.treeParentCode" placeholder="请选择"> |
||||
<el-option |
||||
v-for="(column, index) in info.columns" |
||||
:key="index" |
||||
:label="column.columnName + ':' + column.columnComment" |
||||
:value="column.columnName" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item> |
||||
<span slot="label"> |
||||
树名称字段 |
||||
<el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-select v-model="info.treeName" placeholder="请选择"> |
||||
<el-option |
||||
v-for="(column, index) in info.columns" |
||||
:key="index" |
||||
:label="column.columnName + ':' + column.columnComment" |
||||
:value="column.columnName" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row v-show="info.tplCategory == 'sub'"> |
||||
<h4 class="form-header">关联信息</h4> |
||||
<el-col :span="12"> |
||||
<el-form-item> |
||||
<span slot="label"> |
||||
关联子表的表名 |
||||
<el-tooltip content="关联子表的表名, 如:sys_user" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange"> |
||||
<el-option |
||||
v-for="(table, index) in tables" |
||||
:key="index" |
||||
:label="table.tableName + ':' + table.tableComment" |
||||
:value="table.tableName" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item> |
||||
<span slot="label"> |
||||
子表关联的外键名 |
||||
<el-tooltip content="子表关联的外键名, 如:user_id" placement="top"> |
||||
<i class="el-icon-question"></i> |
||||
</el-tooltip> |
||||
</span> |
||||
<el-select v-model="info.subTableFkName" placeholder="请选择"> |
||||
<el-option |
||||
v-for="(column, index) in subColumns" |
||||
:key="index" |
||||
:label="column.columnName + ':' + column.columnComment" |
||||
:value="column.columnName" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script> |
||||
import Treeselect from "@riophae/vue-treeselect"; |
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; |
||||
|
||||
export default { |
||||
components: { Treeselect }, |
||||
props: { |
||||
info: { |
||||
type: Object, |
||||
default: null |
||||
}, |
||||
tables: { |
||||
type: Array, |
||||
default: null |
||||
}, |
||||
menus: { |
||||
type: Array, |
||||
default: [] |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
subColumns: [], |
||||
rules: { |
||||
tplCategory: [ |
||||
{ required: true, message: "请选择生成模板", trigger: "blur" } |
||||
], |
||||
packageName: [ |
||||
{ required: true, message: "请输入生成包路径", trigger: "blur" } |
||||
], |
||||
moduleName: [ |
||||
{ required: true, message: "请输入生成模块名", trigger: "blur" } |
||||
], |
||||
businessName: [ |
||||
{ required: true, message: "请输入生成业务名", trigger: "blur" } |
||||
], |
||||
functionName: [ |
||||
{ required: true, message: "请输入生成功能名", trigger: "blur" } |
||||
], |
||||
} |
||||
}; |
||||
}, |
||||
created() {}, |
||||
watch: { |
||||
'info.subTableName': function(val) { |
||||
this.setSubTableColumns(val); |
||||
} |
||||
}, |
||||
methods: { |
||||
/** 转换菜单数据结构 */ |
||||
normalizer(node) { |
||||
if (node.children && !node.children.length) { |
||||
delete node.children; |
||||
} |
||||
return { |
||||
id: node.menuId, |
||||
label: node.menuName, |
||||
children: node.children |
||||
}; |
||||
}, |
||||
/** 选择子表名触发 */ |
||||
subSelectChange(value) { |
||||
this.info.subTableFkName = ''; |
||||
}, |
||||
/** 选择生成模板触发 */ |
||||
tplSelectChange(value) { |
||||
if(value !== 'sub') { |
||||
this.info.subTableName = ''; |
||||
this.info.subTableFkName = ''; |
||||
} |
||||
}, |
||||
/** 设置关联外键 */ |
||||
setSubTableColumns(value) { |
||||
for (var item in this.tables) { |
||||
const name = this.tables[item].tableName; |
||||
if (value === name) { |
||||
this.subColumns = this.tables[item].columns; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
@ -0,0 +1,120 @@ |
||||
<template> |
||||
<!-- 导入表 --> |
||||
<el-dialog title="导入表" :visible.sync="visible" width="800px" top="5vh" append-to-body> |
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> |
||||
<el-form-item label="表名称" prop="tableName"> |
||||
<el-input |
||||
v-model="queryParams.tableName" |
||||
placeholder="请输入表名称" |
||||
clearable |
||||
@keyup.enter.native="handleQuery" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item label="表描述" prop="tableComment"> |
||||
<el-input |
||||
v-model="queryParams.tableComment" |
||||
placeholder="请输入表描述" |
||||
clearable |
||||
@keyup.enter.native="handleQuery" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> |
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
<el-row> |
||||
<el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px"> |
||||
<el-table-column type="selection" width="55"></el-table-column> |
||||
<el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column> |
||||
<el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column> |
||||
<el-table-column prop="createTime" label="创建时间"></el-table-column> |
||||
<el-table-column prop="updateTime" label="更新时间"></el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="total>0" |
||||
:total="total" |
||||
:page.sync="queryParams.pageNum" |
||||
:limit.sync="queryParams.pageSize" |
||||
@pagination="getList" |
||||
/> |
||||
</el-row> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button type="primary" @click="handleImportTable">确 定</el-button> |
||||
<el-button @click="visible = false">取 消</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
|
||||
<script> |
||||
import { listDbTable, importTable } from "@/api/tool/gen"; |
||||
export default { |
||||
data() { |
||||
return { |
||||
// 遮罩层 |
||||
visible: false, |
||||
// 选中数组值 |
||||
tables: [], |
||||
// 总条数 |
||||
total: 0, |
||||
// 表数据 |
||||
dbTableList: [], |
||||
// 查询参数 |
||||
queryParams: { |
||||
pageNum: 1, |
||||
pageSize: 10, |
||||
tableName: undefined, |
||||
tableComment: undefined |
||||
} |
||||
}; |
||||
}, |
||||
methods: { |
||||
// 显示弹框 |
||||
show() { |
||||
this.getList(); |
||||
this.visible = true; |
||||
}, |
||||
clickRow(row) { |
||||
this.$refs.table.toggleRowSelection(row); |
||||
}, |
||||
// 多选框选中数据 |
||||
handleSelectionChange(selection) { |
||||
this.tables = selection.map(item => item.tableName); |
||||
}, |
||||
// 查询表数据 |
||||
getList() { |
||||
listDbTable(this.queryParams).then(res => { |
||||
if (res.code === 200) { |
||||
this.dbTableList = res.rows; |
||||
this.total = res.total; |
||||
} |
||||
}); |
||||
}, |
||||
/** 搜索按钮操作 */ |
||||
handleQuery() { |
||||
this.queryParams.pageNum = 1; |
||||
this.getList(); |
||||
}, |
||||
/** 重置按钮操作 */ |
||||
resetQuery() { |
||||
this.resetForm("queryForm"); |
||||
this.handleQuery(); |
||||
}, |
||||
/** 导入按钮操作 */ |
||||
handleImportTable() { |
||||
const tableNames = this.tables.join(","); |
||||
if (tableNames == "") { |
||||
this.$modal.msgError("请选择要导入的表"); |
||||
return; |
||||
} |
||||
importTable({ tables: tableNames }).then(res => { |
||||
this.$modal.msgSuccess(res.msg); |
||||
if (res.code === 200) { |
||||
this.visible = false; |
||||
this.$emit("ok"); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
@ -0,0 +1,337 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> |
||||
<el-form-item label="表名称" prop="tableName"> |
||||
<el-input |
||||
v-model="queryParams.tableName" |
||||
placeholder="请输入表名称" |
||||
clearable |
||||
@keyup.enter.native="handleQuery" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item label="表描述" prop="tableComment"> |
||||
<el-input |
||||
v-model="queryParams.tableComment" |
||||
placeholder="请输入表描述" |
||||
clearable |
||||
@keyup.enter.native="handleQuery" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item label="创建时间"> |
||||
<el-date-picker |
||||
v-model="dateRange" |
||||
style="width: 240px" |
||||
value-format="yyyy-MM-dd" |
||||
type="daterange" |
||||
range-separator="-" |
||||
start-placeholder="开始日期" |
||||
end-placeholder="结束日期" |
||||
></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> |
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<el-row :gutter="10" class="mb8"> |
||||
<el-col :span="1.5"> |
||||
<el-button |
||||
type="primary" |
||||
plain |
||||
icon="el-icon-download" |
||||
size="mini" |
||||
@click="handleGenTable" |
||||
v-hasPermi="['tool:gen:code']" |
||||
>生成</el-button> |
||||
</el-col> |
||||
<el-col :span="1.5"> |
||||
<el-button |
||||
type="info" |
||||
plain |
||||
icon="el-icon-upload" |
||||
size="mini" |
||||
@click="openImportTable" |
||||
v-hasPermi="['tool:gen:import']" |
||||
>导入</el-button> |
||||
</el-col> |
||||
<el-col :span="1.5"> |
||||
<el-button |
||||
type="success" |
||||
plain |
||||
icon="el-icon-edit" |
||||
size="mini" |
||||
:disabled="single" |
||||
@click="handleEditTable" |
||||
v-hasPermi="['tool:gen:edit']" |
||||
>修改</el-button> |
||||
</el-col> |
||||
<el-col :span="1.5"> |
||||
<el-button |
||||
type="danger" |
||||
plain |
||||
icon="el-icon-delete" |
||||
size="mini" |
||||
:disabled="multiple" |
||||
@click="handleDelete" |
||||
v-hasPermi="['tool:gen:remove']" |
||||
>删除</el-button> |
||||
</el-col> |
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
||||
</el-row> |
||||
|
||||
<el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange"> |
||||
<el-table-column type="selection" align="center" width="55"></el-table-column> |
||||
<el-table-column label="序号" type="index" width="50" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
label="表名称" |
||||
align="center" |
||||
prop="tableName" |
||||
:show-overflow-tooltip="true" |
||||
width="120" |
||||
/> |
||||
<el-table-column |
||||
label="表描述" |
||||
align="center" |
||||
prop="tableComment" |
||||
:show-overflow-tooltip="true" |
||||
width="120" |
||||
/> |
||||
<el-table-column |
||||
label="实体" |
||||
align="center" |
||||
prop="className" |
||||
:show-overflow-tooltip="true" |
||||
width="120" |
||||
/> |
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160" /> |
||||
<el-table-column label="更新时间" align="center" prop="updateTime" width="160" /> |
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope"> |
||||
<el-button |
||||
type="text" |
||||
size="small" |
||||
icon="el-icon-view" |
||||
@click="handlePreview(scope.row)" |
||||
v-hasPermi="['tool:gen:preview']" |
||||
>预览</el-button> |
||||
<el-button |
||||
type="text" |
||||
size="small" |
||||
icon="el-icon-edit" |
||||
@click="handleEditTable(scope.row)" |
||||
v-hasPermi="['tool:gen:edit']" |
||||
>编辑</el-button> |
||||
<el-button |
||||
type="text" |
||||
size="small" |
||||
icon="el-icon-delete" |
||||
@click="handleDelete(scope.row)" |
||||
v-hasPermi="['tool:gen:remove']" |
||||
>删除</el-button> |
||||
<el-button |
||||
type="text" |
||||
size="small" |
||||
icon="el-icon-refresh" |
||||
@click="handleSynchDb(scope.row)" |
||||
v-hasPermi="['tool:gen:edit']" |
||||
>同步</el-button> |
||||
<el-button |
||||
type="text" |
||||
size="small" |
||||
icon="el-icon-download" |
||||
@click="handleGenTable(scope.row)" |
||||
v-hasPermi="['tool:gen:code']" |
||||
>生成代码</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="total>0" |
||||
:total="total" |
||||
:page.sync="queryParams.pageNum" |
||||
:limit.sync="queryParams.pageSize" |
||||
@pagination="getList" |
||||
/> |
||||
<!-- 预览界面 --> |
||||
<el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body class="scrollbar"> |
||||
<el-tabs v-model="preview.activeName"> |
||||
<el-tab-pane |
||||
v-for="(value, key) in preview.data" |
||||
:label="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))" |
||||
:name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))" |
||||
:key="key" |
||||
> |
||||
<el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="value" v-clipboard:success="clipboardSuccess" style="float:right">复制</el-link> |
||||
<pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</el-dialog> |
||||
<import-table ref="import" @ok="handleQuery" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { listTable, previewTable, delTable, genCode, synchDb } from "@/api/tool/gen"; |
||||
import importTable from "./importTable"; |
||||
import hljs from "highlight.js/lib/highlight"; |
||||
import "highlight.js/styles/github-gist.css"; |
||||
hljs.registerLanguage("java", require("highlight.js/lib/languages/java")); |
||||
hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml")); |
||||
hljs.registerLanguage("html", require("highlight.js/lib/languages/xml")); |
||||
hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml")); |
||||
hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript")); |
||||
hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql")); |
||||
|
||||
export default { |
||||
name: "Gen", |
||||
components: { importTable }, |
||||
data() { |
||||
return { |
||||
// 遮罩层 |
||||
loading: true, |
||||
// 唯一标识符 |
||||
uniqueId: "", |
||||
// 选中数组 |
||||
ids: [], |
||||
// 选中表数组 |
||||
tableNames: [], |
||||
// 非单个禁用 |
||||
single: true, |
||||
// 非多个禁用 |
||||
multiple: true, |
||||
// 显示搜索条件 |
||||
showSearch: true, |
||||
// 总条数 |
||||
total: 0, |
||||
// 表数据 |
||||
tableList: [], |
||||
// 日期范围 |
||||
dateRange: "", |
||||
// 查询参数 |
||||
queryParams: { |
||||
pageNum: 1, |
||||
pageSize: 10, |
||||
tableName: undefined, |
||||
tableComment: undefined |
||||
}, |
||||
// 预览参数 |
||||
preview: { |
||||
open: false, |
||||
title: "代码预览", |
||||
data: {}, |
||||
activeName: "domain.java" |
||||
} |
||||
}; |
||||
}, |
||||
created() { |
||||
this.getList(); |
||||
}, |
||||
activated() { |
||||
const time = this.$route.query.t; |
||||
if (time != null && time != this.uniqueId) { |
||||
this.uniqueId = time; |
||||
this.queryParams.pageNum = Number(this.$route.query.pageNum); |
||||
this.getList(); |
||||
} |
||||
}, |
||||
methods: { |
||||
/** 查询表集合 */ |
||||
getList() { |
||||
this.loading = true; |
||||
listTable(this.addDateRange(this.queryParams, this.dateRange)).then(response => { |
||||
this.tableList = response.rows; |
||||
this.total = response.total; |
||||
this.loading = false; |
||||
} |
||||
); |
||||
}, |
||||
/** 搜索按钮操作 */ |
||||
handleQuery() { |
||||
this.queryParams.pageNum = 1; |
||||
this.getList(); |
||||
}, |
||||
/** 生成代码操作 */ |
||||
handleGenTable(row) { |
||||
const tableNames = row.tableName || this.tableNames; |
||||
if (tableNames == "") { |
||||
this.$modal.msgError("请选择要生成的数据"); |
||||
return; |
||||
} |
||||
if(row.genType === "1") { |
||||
genCode(row.tableName).then(response => { |
||||
this.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath); |
||||
}); |
||||
} else { |
||||
this.$download.zip("/tool/gen/batchGenCode?tables=" + tableNames, "ruoyi"); |
||||
} |
||||
}, |
||||
/** 同步数据库操作 */ |
||||
handleSynchDb(row) { |
||||
const tableName = row.tableName; |
||||
this.$modal.confirm('确认要强制同步"' + tableName + '"表结构吗?').then(function() { |
||||
return synchDb(tableName); |
||||
}).then(() => { |
||||
this.$modal.msgSuccess("同步成功"); |
||||
}).catch(() => {}); |
||||
}, |
||||
/** 打开导入表弹窗 */ |
||||
openImportTable() { |
||||
this.$refs.import.show(); |
||||
}, |
||||
/** 重置按钮操作 */ |
||||
resetQuery() { |
||||
this.dateRange = []; |
||||
this.resetForm("queryForm"); |
||||
this.handleQuery(); |
||||
}, |
||||
/** 预览按钮 */ |
||||
handlePreview(row) { |
||||
previewTable(row.tableId).then(response => { |
||||
this.preview.data = response.data; |
||||
this.preview.open = true; |
||||
this.preview.activeName = "domain.java"; |
||||
}); |
||||
}, |
||||
/** 高亮显示 */ |
||||
highlightedCode(code, key) { |
||||
const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm")); |
||||
var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length); |
||||
const result = hljs.highlight(language, code || "", true); |
||||
return result.value || ' '; |
||||
}, |
||||
/** 复制代码成功 */ |
||||
clipboardSuccess() { |
||||
this.$modal.msgSuccess("复制成功"); |
||||
}, |
||||
// 多选框选中数据 |
||||
handleSelectionChange(selection) { |
||||
this.ids = selection.map(item => item.tableId); |
||||
this.tableNames = selection.map(item => item.tableName); |
||||
this.single = selection.length != 1; |
||||
this.multiple = !selection.length; |
||||
}, |
||||
/** 修改按钮操作 */ |
||||
handleEditTable(row) { |
||||
const tableId = row.tableId || this.ids[0]; |
||||
const tableName = row.tableName || this.tableNames[0]; |
||||
const params = { pageNum: this.queryParams.pageNum }; |
||||
this.$tab.openPage("修改[" + tableName + "]生成配置", '/tool/gen-edit/index/' + tableId, params); |
||||
}, |
||||
/** 删除按钮操作 */ |
||||
handleDelete(row) { |
||||
const tableIds = row.tableId || this.ids; |
||||
this.$modal.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?').then(function() { |
||||
return delTable(tableIds); |
||||
}).then(() => { |
||||
this.getList(); |
||||
this.$modal.msgSuccess("删除成功"); |
||||
}).catch(() => {}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
@ -0,0 +1,15 @@ |
||||
<template> |
||||
<i-frame :src="url" /> |
||||
</template> |
||||
<script> |
||||
import iFrame from "@/components/iFrame/index"; |
||||
export default { |
||||
name: "Swagger", |
||||
components: { iFrame }, |
||||
data() { |
||||
return { |
||||
url: process.env.VUE_APP_BASE_API + "/swagger-ui/index.html" |
||||
}; |
||||
}, |
||||
}; |
||||
</script> |
||||
@ -0,0 +1,116 @@ |
||||
<template> |
||||
<el-dialog title="分发" :close-on-click-modal="false" append-to-body :visible.sync="visible" width="600px" @close="closeDialog"> |
||||
<el-form ref="dialogForm" :model="dialogForm" :rules="rules" label-width="110px"> |
||||
<el-row> |
||||
<el-col :span="24"> |
||||
<el-form-item label="场地" prop="newPlaceList"> |
||||
<span v-if="oldForm.placeNames">{{oldForm.placeNames}}</span> |
||||
|
||||
<el-select v-model="dialogForm.newPlaceList" filterable multiple placeholder="请选择" clearable style="width: 100%;"> |
||||
<el-option v-for="dict in placeOptions" :key="dict.placeId" :label="dict.name" :value="dict.placeId" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button plain @click="(visible = false)">取消</el-button> |
||||
<el-button v-jclick type="primary" :disabled="!canSubmit" @click="dialogFormSubmit()">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import { getCluePlaceList, saveCluePlace } from '@/api/zs/clue'; |
||||
import { getAllPlaces } from '@/api/sch/place'; |
||||
|
||||
export default { |
||||
name: 'DistributeFormDialog', |
||||
|
||||
data() { |
||||
return { |
||||
visible: false, |
||||
canSubmit: true, |
||||
dialogForm: {}, |
||||
oldForm: {}, |
||||
rules: { |
||||
newPlaceList: { |
||||
required: true, |
||||
message: '场地不能为空不能为空', |
||||
trigger: 'blur' |
||||
} |
||||
}, |
||||
placeOptions: [] |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(info = undefined) { |
||||
this.getPlaces() |
||||
this.visible = true; |
||||
this.$nextTick(() => { |
||||
this.resetDialogForm(); |
||||
this.$refs['dialogForm'].resetFields(); |
||||
if (info) { |
||||
|
||||
this.dialogForm.clueId = info; |
||||
//查询该线索的分发情况 |
||||
this.getDistributePlaces(info); |
||||
} |
||||
}); |
||||
}, |
||||
resetDialogForm() { |
||||
this.dialogForm = { |
||||
oldPlaceList: [], |
||||
newPlaceList: [], |
||||
placeIdList: [], |
||||
clueId: undefined |
||||
}; |
||||
this.oldForm = {} |
||||
}, |
||||
closeDialog() { |
||||
this.$emit('update:dialog.batchUpdateVisible', false); |
||||
}, |
||||
getDistributePlaces(clueId) { |
||||
getCluePlaceList({ clueId: clueId }).then(resp => { |
||||
if (resp.code == 200) { |
||||
this.oldForm = resp.data |
||||
this.dialogForm.oldPlaceList = this.oldForm.placeIdList; |
||||
if (this.oldForm.placeIdList && this.oldForm.placeIdList) { |
||||
this.placeOptions = this.placeOptions.filter(item => this.oldForm.placeIdList.indexOf(item.placeId) == -1) |
||||
} |
||||
} |
||||
|
||||
}) |
||||
}, |
||||
// 表单提交 |
||||
dialogFormSubmit() { |
||||
this.$refs.dialogForm.validate((valid) => { |
||||
if (valid) { |
||||
this.canSubmit = false; |
||||
this.dialogForm.placeIdList = this.dialogForm.oldPlaceList.concat(this.dialogForm.newPlaceList) |
||||
// 校验完成,调接口 |
||||
saveCluePlace(this.dialogForm) |
||||
.then((resp) => { |
||||
this.canSubmit = true; |
||||
if (resp.code == 200) { |
||||
this.$message.success('分发成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.visible = false; |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
this.canSubmit = true; |
||||
}); |
||||
} |
||||
}); |
||||
}, |
||||
getPlaces() { |
||||
getAllPlaces({ status: '0' }).then((resp) => { |
||||
this.placeOptions = resp.data; |
||||
|
||||
}); |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
|
||||
@ -0,0 +1,83 @@ |
||||
<template> |
||||
<el-dialog title="分发" :close-on-click-modal="false" append-to-body :visible.sync="visible" width="600px" @close="closeDialog"> |
||||
<el-form ref="dialogForm" :model="dialogForm" :rules="rules" label-width="110px"> |
||||
<el-row> |
||||
<el-col :span="24"> |
||||
<el-form-item label="备注" prop="clueMemo"> |
||||
<el-input v-model="dialogForm.clueMemo" type="textarea" :rows="20" maxlength="50000" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button plain @click="(visible = false)">取消</el-button> |
||||
<el-button v-jclick type="primary" :disabled="!canSubmit" @click="dialogFormSubmit()">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import { updateClue } from '@/api/zs/clue'; |
||||
|
||||
export default { |
||||
name: 'MemoFormDialog', |
||||
|
||||
data() { |
||||
return { |
||||
visible: false, |
||||
canSubmit: true, |
||||
dialogForm: {}, |
||||
rules: { |
||||
clueMemo: { |
||||
required: true, |
||||
message: '备注不能为空', |
||||
trigger: 'blur' |
||||
} |
||||
}, |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(info = undefined) { |
||||
this.visible = true; |
||||
this.$nextTick(() => { |
||||
this.resetDialogForm(); |
||||
this.$refs['dialogForm'].resetFields(); |
||||
if (info) { |
||||
|
||||
this.dialogForm = { ...info }; |
||||
} |
||||
}); |
||||
}, |
||||
resetDialogForm() { |
||||
this.dialogForm = {}; |
||||
}, |
||||
closeDialog() { |
||||
this.$emit('update:dialog.batchUpdateVisible', false); |
||||
}, |
||||
|
||||
// 表单提交 |
||||
dialogFormSubmit() { |
||||
this.$refs.dialogForm.validate((valid) => { |
||||
if (valid) { |
||||
this.canSubmit = false; |
||||
// 校验完成,调接口 |
||||
updateClue(this.dialogForm) |
||||
.then((resp) => { |
||||
this.canSubmit = true; |
||||
if (resp.code == 200) { |
||||
this.$message.success('跟进成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.visible = false; |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
this.canSubmit = true; |
||||
}); |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
|
||||
@ -0,0 +1,38 @@ |
||||
<template> |
||||
<el-dialog title="撞单信息" :close-on-click-modal="false" append-to-body :visible.sync="visible" width="400px" height="500"> |
||||
<div> |
||||
<el-table :data="consultRecord"> |
||||
<el-table-column min-width="140" prop="consultTime" label="咨询日期" /> |
||||
<el-table-column min-width="140" prop="consultUserName" label="咨询人" /> |
||||
</el-table> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import { getConsultRecord } from '@/api/zs/clue'; |
||||
export default { |
||||
name: 'ZhuangDanDialog', |
||||
data() { |
||||
return { |
||||
visible: false, |
||||
loading: true, |
||||
consultRecord: [] |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(info) { |
||||
this.visible = true; |
||||
this._getTableList(info); |
||||
}, |
||||
_getTableList(info) { |
||||
this.loading = true; |
||||
getConsultRecord({ phone: info }).then((resp) => { |
||||
if (resp && resp.code === 200 && resp.data) { |
||||
this.consultRecord = resp.data |
||||
} |
||||
}) |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
@ -0,0 +1,539 @@ |
||||
<template> |
||||
<el-dialog title="报名点信息" :close-on-click-modal="false" append-to-body :visible.sync="visible" width="900px" @close="closeDialog"> |
||||
<div> |
||||
<el-form ref="dialogForm" :model="dialogForm" :rules="dataRule" label-width="110px" @keyup.enter.native="dialogFormSubmit()" :disabled="type == 2 || dialogForm.checkState==1 || dialogForm.checkState==2"> |
||||
<el-tabs v-model="activeName" style="min-height: 450px;"> |
||||
<el-tab-pane label="基础信息" name="first"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="报名点" prop="signPlacePoint"> |
||||
<el-select v-model="dialogForm.signPlacePoint" filterable placeholder="请选择" value-key="schoolId" clearable size="mini"> |
||||
<el-option v-for="(dict, index) in signPlaceOptions" :key="index" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="类别" prop="signType"> |
||||
<el-input v-model="dialogForm.signType" placeholder="请输入类别" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="成交日期" prop="dealDate"> |
||||
<el-date-picker clearable v-model="dialogForm.dealDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择成交日期"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="姓名" prop="name"> |
||||
<el-input v-model="dialogForm.name" placeholder="请输入姓名" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="线索来源" prop="source"> |
||||
<el-select v-model="dialogForm.source" placeholder="请选择" clearable size="small"> |
||||
<el-option v-for="(dict, index) in sourceOptions" :key="index" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="身份证号" prop="idcard"> |
||||
<el-input v-model="dialogForm.idcard" placeholder="请输入身份证号" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="报名驾校" prop="signSchool"> |
||||
<el-select v-model="dialogForm.signSchool" filterable placeholder="请选择" value-key="schoolId" clearable size="small" @change="schoolChange"> |
||||
<el-option v-for="(dict, index) in schoolOptions" :key="index" :label="dict.schoolName" :value="dict.schoolId" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="联系方式" prop="phone"> |
||||
<el-input v-model="dialogForm.phone" placeholder="请输入联系方式" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="报名场地" prop="signPlace"> |
||||
<el-select v-model="dialogForm.signPlace" filterable placeholder="请选择" clearable value-key="placeId" size="small" @change="placeChange"> |
||||
<el-option v-for="(dict, index) in placeOptions" :key="index" :label="dict.name" :value="dict.placeId" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="报名价格" prop="signPrice"> |
||||
<el-input v-model="dialogForm.signPrice" placeholder="请输入报名价格" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="报名班型" prop="signClass"> |
||||
<el-select v-model="dialogForm.signClass" filterable placeholder="请选择" clearable value-key="typeId" size="small"> |
||||
<el-option v-for="(dict, index) in classTypeOptions" :key="index" :label="`${dict.licenseType}-${dict.typeName}`" :value="dict.typeId" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="利润" prop="profit"> |
||||
<el-input v-model="dialogForm.profit" placeholder="请输入利润" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="送审日期" prop="submissionTime"> |
||||
<el-date-picker clearable v-model="dialogForm.submissionTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择送审日期"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="支付方式" prop="extraPayWay"> |
||||
<el-input v-model="dialogForm.extraPayWay" placeholder="请输入支付方式" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="学员状态"> |
||||
<el-select v-model="dialogForm.stuStatus" multiple placeholder="请选择" clearable size="small"> |
||||
<el-option v-for="(dict, index) in studentStatusOptions" :key="index" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="归属人员" prop="followUserList"> |
||||
<el-select v-model="dialogForm.followUserList" multiple placeholder="请选择" clearable size="small"> |
||||
<el-option v-for="(dict, index) in userOptions" :key="index" :label="dict.name" :value="dict.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="24"> |
||||
<el-form-item label="备注" prop="memo"> |
||||
<el-input type="textarea" :rows="3" v-model="dialogForm.memo" placeholder="请输入备注" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="费用明细" name="second"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="培训费" prop="trainFee"> |
||||
<el-input v-model="dialogForm.trainFee" placeholder="请输入培训费" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="考试费" prop="examFee"> |
||||
<el-input v-model="dialogForm.examFee" placeholder="请输入考试费" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="学杂费" prop="learningFee"> |
||||
<el-input v-model="dialogForm.learningFee" placeholder="请输入学杂费" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="体检费" prop="physicalExamFee"> |
||||
<el-input v-model="dialogForm.physicalExamFee" placeholder="请输入体检费" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="额外支出" name="third"> |
||||
<el-row> |
||||
<el-table :data="dialogForm.extraPayList" border> |
||||
<el-table-column label="额外支出项目" align="center" min-width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-form-item :prop="'extraPayList.'+scope.$index+'.extraPayType'" :rules="dataRule.extraPayType" label-width="0px"> |
||||
<el-select v-model="scope.row.extraPayType" filterable placeholder="请选择" clearable size="small"> |
||||
<el-option v-for="(dict, index) in extraPayTypeOptions" :key="index" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="额外支出金额" align="center" min-width="160"> |
||||
<template slot-scope="scope"> |
||||
<el-form-item :prop="'extraPayList.'+scope.$index+'.extraPay'" :rules="dataRule.extraPay" label-width="0px"> |
||||
<el-input v-model="scope.row.extraPay" placeholder="请输入额外支出金额" type="number" /> |
||||
</el-form-item> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="removeExtraPay(scope.$index)">移除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</el-row> |
||||
<el-row style="text-align: center;"> |
||||
<el-button @click="addExtraPay">添加</el-button> |
||||
|
||||
<!-- <el-col :span="12"> |
||||
<el-form-item label="额外支出项目" prop="extraPayTypes"> |
||||
<el-select v-model="dialogForm.extraPayTypes" filterable multiple placeholder="请选择" clearable size="small"> |
||||
<el-option v-for="(dict, index) in extraPayTypeOptions" :key="index" :label="dict.dictLabel" :value="dict.dictValue" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="额外支出金额" prop="extraPay"> |
||||
<el-input v-model="dialogForm.extraPay" placeholder="请输入额外支出金额" type="number" /> |
||||
</el-form-item> |
||||
</el-col> --> |
||||
</el-row> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="账户信息" name="four"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="收款账户" prop="collectionAccount1"> |
||||
<el-input v-model="dialogForm.collectionAccount1" placeholder="请输入收款账户" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="入账时间" prop="entryTime1"> |
||||
<el-date-picker clearable v-model="dialogForm.entryTime1" type="date" value-format="yyyy-MM-dd" placeholder="请选择入账时间"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="入账金额" prop="entryMoney1"> |
||||
<el-input v-model="dialogForm.entryMoney1" placeholder="请输入入账金额" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="手续费" prop="commission1"> |
||||
<el-input v-model="dialogForm.commission1" placeholder="请输入手续费" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="收款账户2" prop="collectionAccount2"> |
||||
<el-input v-model="dialogForm.collectionAccount2" placeholder="请输入收款账户" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="入账时间2" prop="entryTime2"> |
||||
<el-date-picker clearable v-model="dialogForm.entryTime2" type="date" value-format="yyyy-MM-dd" placeholder="请选择入账时间"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="入账金额2" prop="entryMoney2"> |
||||
<el-input v-model="dialogForm.entryMoney2" placeholder="请输入入账金额" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="手续费2" prop="commission2"> |
||||
<el-input v-model="dialogForm.commission2" placeholder="请输入手续费" type="number" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
|
||||
</el-form> |
||||
|
||||
</div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button v-if="type==1 && (dialogForm.checkState == 0 || dialogForm.checkState == 3)" v-jclick type="primary" :disabled="!canSubmit" @click="dialogFormSubmit()">确定</el-button> |
||||
<el-button v-if="type==2 && dialogForm.checkState == 1" v-jclick type="primary" @click="handleCheck(2)">通过</el-button> |
||||
<el-button v-if="type==2 && dialogForm.checkState == 1" v-jclick type="primary" @click="handleCheck(3)">驳回</el-button> |
||||
<el-button plain @click="(visible=false)">取消</el-button> |
||||
|
||||
</span> |
||||
</el-dialog> |
||||
</template> |
||||
|
||||
<script> |
||||
import { listOffice } from "@/api/zs/office"; |
||||
import { addSign, updateSign, checkSign } from "@/api/zs/placeSign"; |
||||
import schoolAPi from '@/api/sch/school' |
||||
import empApi from '@/api/system/employee' |
||||
import { getAllPlaces } from '@/api/sch/place' |
||||
import { getClassTypeTableList } from '@/api/sch/classType' |
||||
|
||||
|
||||
export default { |
||||
name: "OfficeSignDialogForm", |
||||
props: { |
||||
signPlaceOptions: { |
||||
type: Array, |
||||
default: [] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
visible: false, |
||||
canSubmit: true, |
||||
dialogForm: {}, |
||||
dataRule: { |
||||
signPlacePoint: [{ required: true, message: '报名点不能为空', trigger: 'blur,change' }], |
||||
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }], |
||||
idcard: [{ required: true, message: '身份证号不能为空', trigger: 'blur' }], |
||||
phone: [{ required: true, message: '手机号不能为空', trigger: 'blur' }], |
||||
source: [{ required: true, message: '线索来源不能为空', trigger: 'blur, change' }], |
||||
signType: [{ required: true, message: '报名类别不能为空', trigger: 'blur,change' }], |
||||
dealDate: [{ required: true, message: '报名日期不能为空', trigger: 'blur,change' }], |
||||
signSchool: [{ required: true, message: '报名驾校不能为空', trigger: 'blur,change' }], |
||||
signPlace: [{ required: true, message: '报名场地不能为空', trigger: 'blur,change' }], |
||||
signClass: [{ required: true, message: '报名班型不能为空', trigger: 'blur,change' }], |
||||
signPrice: [{ required: true, message: '报名价格不能为空', trigger: 'blur' }], |
||||
profit: [{ required: true, message: '利润不能为空', trigger: 'blur' }], |
||||
trainFee: [{ required: true, message: '培训费不能为空', trigger: 'blur' }], |
||||
examFee: [{ required: true, message: '考试费不能为空', trigger: 'blur' }], |
||||
learningFee: [{ required: true, message: '学杂费不能为空', trigger: 'blur' }], |
||||
physicalExamFee: [{ required: true, message: '体检费不能为空', trigger: 'blur' }], |
||||
extraPayType: [{ required: true, message: '额外支付项目不能为空', trigger: 'blur' }], |
||||
extraPay: [{ required: true, message: '额外支付金额不能为空', trigger: 'blur' }], |
||||
extraPayWay: [{ required: true, message: '支付方式不能为空', trigger: 'blur' }], |
||||
collectionAccount1: [{ required: true, message: '收款账号不能为空', trigger: 'blur' }], |
||||
entryTime1: [{ required: true, message: '入账时间不能为空', trigger: 'blur' }], |
||||
entryMoney1: [{ required: true, message: '入账金额不能为空', trigger: 'blur' }], |
||||
commission1: [{ required: true, message: '手续费不能为空', trigger: 'blur' }], |
||||
submissionTime: [{ required: true, message: '送审时间不能为空', trigger: 'blur, change' }], |
||||
stuStatus: [{ required: true, message: '学员状态不能为空', trigger: 'blur,change' }], |
||||
followUserList: [{ required: true, message: '归属人员不能为空', trigger: 'blur,change' }], |
||||
}, |
||||
officeOptions: [], |
||||
schoolOptions: [], |
||||
placeOptions: [], |
||||
classTypeOptions: [], |
||||
userOptions: [], |
||||
sourceOptions: [], |
||||
extraPayTypeOptions: [], |
||||
type: 1, |
||||
schoolIdList: [], |
||||
activeName: "first", |
||||
studentStatusOptions: [] |
||||
}; |
||||
}, |
||||
methods: { |
||||
init(info = undefined, type) { |
||||
this.visible = true; |
||||
this.initData(); |
||||
this.$nextTick(() => { |
||||
this.resetDialogForm(); |
||||
this.$refs['dialogForm'].resetFields(); |
||||
if (info) { |
||||
this.dialogForm = this.deepClone(info); |
||||
if (this.dialogForm.signSchool) { |
||||
this.getAllPlaces(this.dialogForm.signSchool) |
||||
this.getClassTypes(this.dialogForm.signSchool, this.dialogForm.signPlace) |
||||
} |
||||
} |
||||
|
||||
}); |
||||
if (type) { |
||||
this.type = type |
||||
} |
||||
|
||||
}, |
||||
initData() { |
||||
this.getSchools(); |
||||
this.getEmployee(); |
||||
this.getUserOfficeInfo(); |
||||
//线索来源 |
||||
this.getDicts('dm_source').then((response) => { |
||||
this.sourceOptions = response.data |
||||
}) |
||||
//额外支出类型 |
||||
this.getDicts('dm_extra_pay').then((response) => { |
||||
this.extraPayTypeOptions = response.data |
||||
}) |
||||
//报名类别 |
||||
this.getDicts('student_status').then((response) => { |
||||
this.studentStatusOptions = response.data |
||||
}) |
||||
}, |
||||
resetDialogForm() { |
||||
this.dialogForm = { |
||||
placeSignId: null, |
||||
signPlacePoint: null, |
||||
name: null, |
||||
idcard: null, |
||||
phone: null, |
||||
source: null, |
||||
dealDate: null, |
||||
signType: null, |
||||
signSchool: null, |
||||
schoolName: null, |
||||
signPlace: null, |
||||
placeName: null, |
||||
signClass: null, |
||||
className: null, |
||||
signPrice: null, |
||||
profit: null, |
||||
followUser: null, |
||||
followUserName: null, |
||||
trainFee: null, |
||||
examFee: null, |
||||
learningFee: null, |
||||
physicalExamFee: null, |
||||
memo: null, |
||||
checkState: 0, |
||||
rejectReason: null, |
||||
createTime: null, |
||||
createUser: null, |
||||
updateTime: null, |
||||
signDate: null, |
||||
delFlag: null, |
||||
submissionTime: null, |
||||
stuStatus: "0", |
||||
collectionAccount1: null, |
||||
entryTime1: null, |
||||
entryMoney1: null, |
||||
commission1: null, |
||||
collectionAccount2: null, |
||||
entryTime2: null, |
||||
entryMoney2: null, |
||||
commission2: null, |
||||
extraPayType: null, |
||||
extraPay: null, |
||||
extraPayWay: null, |
||||
extraPayList: [] |
||||
}; |
||||
}, |
||||
closeDialog() { |
||||
this.$emit('update:dialogVisible', false); |
||||
}, |
||||
// 表单提交 |
||||
dialogFormSubmit() { |
||||
this.dialogForm.checkState = 1 |
||||
this.$refs.dialogForm.validate((valid) => { |
||||
if (valid) { |
||||
this.canSubmit = false; |
||||
|
||||
if (this.dialogForm.placeSignId) { |
||||
// 校验完成,调接口 |
||||
updateSign(this.dialogForm) |
||||
.then((resp) => { |
||||
this.canSubmit = true; |
||||
if (resp.code == 200) { |
||||
this.$message.success('保存成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.visible = false; |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
this.canSubmit = true; |
||||
}); |
||||
} else { |
||||
addSign(this.dialogForm) |
||||
.then((resp) => { |
||||
this.canSubmit = true; |
||||
if (resp.code == 200) { |
||||
this.$message.success('保存成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.visible = false; |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
this.canSubmit = true; |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
//审核登记 |
||||
handleCheck(status) { |
||||
checkSign({ placeSignId: this.dialogForm.placeSignId, checkState: status }) |
||||
.then((resp) => { |
||||
this.canSubmit = true; |
||||
if (resp.code == 200) { |
||||
this.$message.success('保存成功'); |
||||
this.$emit('refreshDataList'); |
||||
this.visible = false; |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
this.canSubmit = true; |
||||
}); |
||||
}, |
||||
getSchools() { |
||||
schoolAPi.pageList().then((resp) => { |
||||
this.schoolOptions = resp.rows |
||||
}) |
||||
}, |
||||
getPlaces(schoolId) { |
||||
getAllPlaces({ schoolId: schoolId, status: '0' }).then((resp) => { |
||||
this.placeOptions = resp.data |
||||
}) |
||||
}, |
||||
getClassTypes(schoolId, placeId) { |
||||
getClassTypeTableList({ schoolId: schoolId, placeId: placeId, status: '0' }).then( |
||||
(resp) => { |
||||
this.classTypeOptions = resp.rows |
||||
} |
||||
) |
||||
}, |
||||
//查询员工 |
||||
getEmployee() { |
||||
empApi.getEmployee().then((resp) => { |
||||
if (resp.code == 200) { |
||||
this.userOptions = resp.data |
||||
} |
||||
}) |
||||
}, |
||||
//查询当前账号关联的报名点信息 |
||||
getUserOfficeInfo() { |
||||
let userId = localStorage.getItem('userId'); |
||||
empApi.getSignPlace(userId).then((resp) => { |
||||
if (resp.code == 200) { |
||||
if (resp.data) { |
||||
this.dialogForm.signPlacePoint = resp.data |
||||
} |
||||
} |
||||
}) |
||||
}, |
||||
//驾校change事件 |
||||
schoolChange(e) { |
||||
this.$set(this.dialogForm, 'signPlace', undefined) |
||||
this.$set(this.dialogForm, 'signClass', undefined) |
||||
this.classTypeOptions = [] |
||||
this.getPlaces(e) |
||||
}, |
||||
//場地change事件 |
||||
placeChange() { |
||||
this.$set(this.dialogForm, 'signClass', undefined) |
||||
this.classTypeOptions = [] |
||||
if (this.dialogForm.signPlace) { |
||||
const place = this.placeOptions.find( |
||||
(item) => item.placeId === this.dialogForm.signPlace |
||||
) |
||||
this.getClassTypes(this.dialogForm.signSchool, this.dialogForm.signPlace) |
||||
} |
||||
}, |
||||
addExtraPay() { |
||||
this.dialogForm.extraPayList.push({ |
||||
extraPayType: undefined, |
||||
extraPay: undefined |
||||
}) |
||||
}, |
||||
removeExtraPay(index) { |
||||
this.dialogForm.extraPayList.splice(index, 1) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue