Merge branch 'projects/mesxc-test' into projects/mesxc-dy
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* @Author: zwq
|
||||
* @Date: 2021-07-19 15:18:30
|
||||
* @LastEditors: zhp
|
||||
* @LastEditTime: 2024-03-26 09:57:35
|
||||
* @LastEditTime: 2024-03-28 15:28:07
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
@@ -16,35 +16,32 @@
|
||||
许昌安彩AGV原片周转看板
|
||||
<h3 class="unit">单位:河南汇融数字科技有限公司</h3>
|
||||
<h3 class="time">{{ times }}</h3>
|
||||
<!-- <el-button
|
||||
type="text"
|
||||
class="title-button"
|
||||
:style="{ right: 33 + 'px', top: 37 + 'px' }"
|
||||
@click="changeFullScreen"
|
||||
>
|
||||
<svg-icon v-if="isFullScreen" icon-class="unFullScreenView" />
|
||||
<svg-icon v-else icon-class="fullScreenView" />
|
||||
</el-button> -->
|
||||
<el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px', fontSize: '32px' }"
|
||||
@click="changeFullScreen">
|
||||
<svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
|
||||
<svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row class="container-main flex-col" type="flex">
|
||||
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15 * beilv" type="flex" class="flex-1">
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :beilv="1" :size="'middle'" :title="'搬运任务'" :title-icon="'task'" :back="'energy'">
|
||||
<base-table1 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="qualityYearTableProps"
|
||||
:table-data="qualityYearList" />
|
||||
<base-container :beilv="1" :size="'eqStatus'" :title="'搬运任务'" :title-icon="'task'" :back="'energy'">
|
||||
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="qualityYearTableProps"
|
||||
:table-data="qualityYearList" /> -->
|
||||
<dv-scroll-board :config="taskConfig" style="width:100%;height:350px" ref='taskScrollBoard' />
|
||||
</base-container>
|
||||
</el-col>
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :beilv="1" :size="'middle'" :title="'周转进度'" :title-icon="'order'" :back="'energy'">
|
||||
<div style="width:100%; overflow: hidden scroll;">
|
||||
<base-container :beilv="1" :size="'eqStatus'" :title="'周转进度'" :title-icon="'order'" :back="'energy'">
|
||||
<div class="order" style="width:100%; overflow: hidden scroll;height: 350px;">
|
||||
<el-row v-for="op in orderProcessList" :key="op.id" style="margin-bottom: 1em">
|
||||
<p v-if="op.outRate === 1" class="now-secondary-title" style="color:#4679FD">
|
||||
<i class="el-icon-check" />
|
||||
{{ op.name }}
|
||||
</p>
|
||||
<p v-else class="now-secondary-title">{{ op.name }}</p>
|
||||
<el-progress define-back-color="rgba(32, 57, 96, 1)" text-color="white" :percentage="op.outRate * 100"
|
||||
class="custom-progress-bar" />
|
||||
<el-progress :stroke-width="10" define-back-color="rgba(32, 57, 96, 1)" text-color="white"
|
||||
:percentage="op.outRate * 100" class="custom-progress-bar" />
|
||||
</el-row>
|
||||
</div>
|
||||
</base-container>
|
||||
@@ -53,17 +50,19 @@
|
||||
|
||||
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="12 * beilv" type="flex" class="flex-1">
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :beilv="1" :height="256" :size="'middle'" :title="'库存管理'" :title-icon="'productLine'"
|
||||
<base-container :beilv="1" :height="280" :size="'eqStatus'" :title="'库存管理'" :title-icon="'productLine'"
|
||||
:back="'energy'">
|
||||
<base-table :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="inventoryTableProps"
|
||||
:table-data="inventoryList" />
|
||||
<!-- <base-table :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="inventoryTableProps"
|
||||
:table-data="inventoryList" /> -->
|
||||
<dv-scroll-board :config="inventoryConfig" style="width:100%;height:380px" ref='inventoryScrollBoard' />
|
||||
</base-container>
|
||||
</el-col>
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :beilv="1" :height="318 + 338 + 16" :size="'middle'" :title="'库位信息'" :title-icon="'info'"
|
||||
<base-container :beilv="1" :height="318 + 338 + 16" :size="'eqStatus'" :title="'库位信息'" :title-icon="'info'"
|
||||
:back="'energy'">
|
||||
<base-table2 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="locationTableProps"
|
||||
:table-data="locationList" />
|
||||
<!-- <base-table2 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="locationTableProps"
|
||||
:table-data="locationList" /> -->
|
||||
<dv-scroll-board :config="locationConfig" style="width:100%;height:380px" ref='locationScrollBoard' />
|
||||
</base-container>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -191,6 +190,15 @@ const inventoryList = [
|
||||
{
|
||||
eqName: ' 螺丝刀', eqCode: '备件库', level: '', product: ' 123', productCode: 'WLXX20220919000147', unit: '个', time: '2023年9月10日'
|
||||
},
|
||||
{
|
||||
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
|
||||
},
|
||||
{
|
||||
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
|
||||
},
|
||||
{
|
||||
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
|
||||
},
|
||||
{
|
||||
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
|
||||
}
|
||||
@@ -267,6 +275,39 @@ export default {
|
||||
inventoryTableProps,
|
||||
inventoryList,
|
||||
locationList,
|
||||
taskConfig: {
|
||||
header: ['序号', '作业号', '执行叉车', '库位', '成品规格', '成品编码', '时间'],
|
||||
headerBGC: 'rgba(32, 55, 96, 0.8)',
|
||||
oddRowBGC: 'rgba(32, 55, 96, 0.8)',
|
||||
evenRowBGC: 'rgba(14, 32, 62, 0.8)',
|
||||
columnWidth: [80, 120, 90, 140, 140, 150,130],
|
||||
align: ['center'],
|
||||
data: [],
|
||||
// index:true,
|
||||
rowNum: 10
|
||||
},
|
||||
inventoryConfig: {
|
||||
header: ['序号', '物件名称', '存放区域', '规格', '数量', '单位', '编码', '入库时间'],
|
||||
headerBGC: 'rgba(32, 55, 96, 0.8)',
|
||||
oddRowBGC: 'rgba(32, 55, 96, 0.8)',
|
||||
evenRowBGC: 'rgba(14, 32, 62, 0.8)',
|
||||
columnWidth: [80, 100, 90, 140, 80, 70, 180, 120],
|
||||
align: ['center'],
|
||||
data: [],
|
||||
// index:true,
|
||||
rowNum: 10
|
||||
},
|
||||
locationConfig: {
|
||||
header: ['序号', '库位名称', '存放物件名称', '数量', '存放位置', '编码', '单位', '入库时间'],
|
||||
headerBGC: 'rgba(32, 55, 96, 0.8)',
|
||||
oddRowBGC: 'rgba(32, 55, 96, 0.8)',
|
||||
evenRowBGC: 'rgba(14, 32, 62, 0.8)',
|
||||
columnWidth: [80, 100, 120, 80, 100, 180, 70, 120],
|
||||
align: ['center'],
|
||||
data: [],
|
||||
// index:true,
|
||||
rowNum: 10
|
||||
},
|
||||
locationTableProps,
|
||||
qualityYearList,
|
||||
isFullScreen: false,
|
||||
@@ -294,6 +335,20 @@ export default {
|
||||
{
|
||||
name: '作业号RQ20230911',
|
||||
outRate: '0.4'
|
||||
},
|
||||
{
|
||||
name: '作业号RQ20230911',
|
||||
outRate: '0.4'
|
||||
},
|
||||
{
|
||||
name: '作业号RQ20230911',
|
||||
outRate: '0.4'
|
||||
}, {
|
||||
name: '作业号RQ20230911',
|
||||
outRate: '0.4'
|
||||
}, {
|
||||
name: '作业号RQ20230911',
|
||||
outRate: '0.4'
|
||||
}
|
||||
],
|
||||
// qualityTableProps1,
|
||||
@@ -316,6 +371,16 @@ export default {
|
||||
},
|
||||
|
||||
watch: {
|
||||
isFullScreen: function (val) {
|
||||
if (val) {
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
console.log(_this.beilv2);
|
||||
} else {
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
}
|
||||
},
|
||||
clientWidth(val) {
|
||||
if (!this.timer) {
|
||||
this.clientWidth = val
|
||||
@@ -343,6 +408,9 @@ export default {
|
||||
}, 86400000)
|
||||
},
|
||||
mounted() {
|
||||
this.getTask()
|
||||
this.getInventoryData()
|
||||
this.getLocationData()
|
||||
const _this = this;
|
||||
window.onresize = () => {
|
||||
return (() => {
|
||||
@@ -355,6 +423,60 @@ export default {
|
||||
getTimes() {
|
||||
setInterval(this.getTimesInterval, 1000);
|
||||
},
|
||||
getTask() {
|
||||
let eqArr = this.qualityYearList.map((item, index) => [
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
</span>`,
|
||||
// formatDate(item.planStartTime) || '',
|
||||
`
|
||||
<span style="color:rgba(255,255,255,0.5)" >${item.eqName || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.eqCode || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.level || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.product || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.productCode || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.time || ''}</span>`,
|
||||
|
||||
])
|
||||
this.taskConfig.data = eqArr
|
||||
this.$refs['taskScrollBoard'].updateRows(eqArr)
|
||||
},
|
||||
getInventoryData() {
|
||||
let eqArr = this.inventoryList.map((item, index) => [
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
</span>`,
|
||||
// formatDate(item.planStartTime) || '',
|
||||
`
|
||||
<span style="color:rgba(255,255,255,0.5)" >${item.eqName || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.eqCode || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.level || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.product || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.unit || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.productCode || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.time || ''}</span>`,
|
||||
])
|
||||
this.inventoryConfig.data = eqArr
|
||||
this.$refs['inventoryScrollBoard'].updateRows(eqArr)
|
||||
},
|
||||
getLocationData() {
|
||||
let eqArr = this.locationList.map((item, index) => [
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
</span>`,
|
||||
// formatDate(item.planStartTime) || '',
|
||||
`
|
||||
<span style="color:rgba(255,255,255,0.5)" >${item.eqName || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.eqCode || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.product || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.level || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.productCode || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.unit || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.time || ''}</span>`,
|
||||
])
|
||||
this.locationConfig.data = eqArr
|
||||
this.$refs['locationScrollBoard'].updateRows(eqArr)
|
||||
},
|
||||
getTimesInterval: function () {
|
||||
let _this = this;
|
||||
let year = new Date().getFullYear(); //获取当前时间的年份
|
||||
@@ -383,25 +505,25 @@ export default {
|
||||
this.isFullScreen = screenfull.isFullscreen
|
||||
},
|
||||
init() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.on('change', this.change)
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.off('change', this.change)
|
||||
}
|
||||
},
|
||||
changeFullScreen() {
|
||||
console.log(this.beilv);
|
||||
if (!screenfull.enabled) {
|
||||
if (!screenfull.isEnabled) {
|
||||
this.$message({
|
||||
message: 'you browser can not work',
|
||||
type: 'warning'
|
||||
})
|
||||
return false
|
||||
}
|
||||
screenfull.toggle(this.$refs.container)
|
||||
screenfull.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,6 +532,9 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.visual-container {
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
@@ -418,26 +543,29 @@ export default {
|
||||
// opacity: .8;
|
||||
.container-title {
|
||||
width: 100%;
|
||||
background: url('../../assets/img/OperationalOverview/title.png') no-repeat;
|
||||
background: url('../../assets/img/OperationalOverview/AGV.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #00fff0;
|
||||
text-align: center;
|
||||
word-spacing:8px;
|
||||
letter-spacing: 8px;
|
||||
// word-spacing: 8px;
|
||||
position: relative;
|
||||
.unit{
|
||||
position: absolute;
|
||||
left: 290px;
|
||||
top:25px;
|
||||
color: rgba($color: #ffffff, $alpha: 8);
|
||||
font-size: 20px;
|
||||
}
|
||||
.time{
|
||||
position: absolute;
|
||||
left: 1360px;
|
||||
top:25px;
|
||||
color: rgba($color: #ffffff, $alpha: 8);
|
||||
font-size: 20px;
|
||||
}
|
||||
.unit {
|
||||
position: absolute;
|
||||
left: 240px;
|
||||
top: 25px;
|
||||
color: rgba(255, 255, 255, 0.80);
|
||||
font-size: 20px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
.time {
|
||||
position: absolute;
|
||||
left: 1400px;
|
||||
top: 25px;
|
||||
color: rgba(255, 255, 255, 0.80);
|
||||
font-size: 20px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
.title-button {
|
||||
color: #00fff0;
|
||||
font-size: 20px;
|
||||
@@ -489,7 +617,9 @@ export default {
|
||||
// .container-main {
|
||||
// padding: 5px;
|
||||
// }
|
||||
|
||||
.order::-webkit-scrollbar{
|
||||
display: none
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" >
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2024-01-29 16:50:26
|
||||
* @LastEditTime: 2024-03-26 16:30:12
|
||||
* @LastEditTime: 2024-03-28 16:35:49
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -17,15 +17,11 @@
|
||||
许昌安彩冷端看板
|
||||
<h3 class="unit">单位:河南汇融数字科技有限公司</h3>
|
||||
<h3 class="time">{{ times }}</h3>
|
||||
<!-- <el-button
|
||||
type="text"
|
||||
class="title-button"
|
||||
:style="{ right: 33 + 'px', top: 37 + 'px' }"
|
||||
@click="changeFullScreen"
|
||||
>
|
||||
<svg-icon v-if="isFullScreen" icon-class="unFullScreenView" />
|
||||
<svg-icon v-else icon-class="fullScreenView" />
|
||||
</el-button> -->
|
||||
<el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px',fontSize:'32px'}"
|
||||
@click="changeFullScreen">
|
||||
<svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
|
||||
<svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row class="container-main flex-col" type="flex">
|
||||
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15" type="flex" class="flex-1">
|
||||
@@ -61,15 +57,26 @@
|
||||
|
||||
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="10" type="flex" class="flex-1">
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :no-content-padding="true" :height="256" :title="'废片 缺陷数据'" :size="'middle'"
|
||||
<base-container :no-content-padding="true" :height="256" :title="'废片 缺陷数据'" :size="'eqStatus'"
|
||||
:title-icon="'scrap'">
|
||||
<!-- <div style="width: 45%;position: absolute; top: 3em; right: 3em;">
|
||||
<top-radio-group />
|
||||
</div> -->
|
||||
<!-- <el-row :gutter="9"> -->
|
||||
<!-- <el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="24"> -->
|
||||
<pile-bar-chart ref="pileChart" :name-list="EnergyMonitoringNameList" :data-list="EnergyMonitoringList"
|
||||
:height="359" />
|
||||
<pile-bar-chart style="margin-bottom: -15px" ref="firstPileChart" :height="90" />
|
||||
<second-pile-bar-chart style="margin-bottom: -15px" id=" 'second' " ref="secondPileChart" :height="90" />
|
||||
<third-pile-bar-chart style="margin-bottom: -15px" id=" 'third' " ref="thirdPileChart" :height="90" />
|
||||
<fourth-pile-bar-chart style="margin-bottom: -15px" id=" 'fourth' " ref="fourthPileChart" :height="90" />
|
||||
<fifth-pile-bar-chart style="margin-bottom: -15px" id=" 'fifth' " ref="fifthPileChart" :height="100" />
|
||||
<!-- <pile-bar-chart ref="secondPileChart"
|
||||
:height="90" />
|
||||
<pile-bar-chart ref="thirdPileChart"
|
||||
:height="90" />
|
||||
<pile-bar-chart ref="fourthPileChart"
|
||||
:height="90" />
|
||||
<pile-bar-chart ref="fifthPileChart"
|
||||
:height="90" /> -->
|
||||
<!-- </el-col> -->
|
||||
<!-- <el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-table3
|
||||
@@ -90,21 +97,21 @@
|
||||
</div> -->
|
||||
<!-- 像下面这样表格里的limit值,也许可以用js动态计算出来 -->
|
||||
<el-col :span="8" style="">
|
||||
<div style="font-size:20px;margin: 5px 0 10px 0">熔化风机</div>
|
||||
<div style="color:rgba(82, 255, 248, 1);font-size:20px;margin: 5px 0 10px 0">熔化风机</div>
|
||||
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :table-config="EqMonitoringPropsFun"
|
||||
:table-data="funList" /> -->
|
||||
<dv-scroll-board :config="funConfig" style="width:100%;height:310px" ref='funScrollBoard' />
|
||||
</el-col>
|
||||
<span class="eqLine"></span>
|
||||
<el-col :span="8">
|
||||
<div style="font-size:20px;margin: 5px 0 10px 0;">退火风机</div>
|
||||
<div style="color:rgba(82, 255, 248, 1);font-size:20px;margin: 5px 0 10px 0;">退火风机</div>
|
||||
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :table-config="EqMonitoringPropsFun"
|
||||
:table-data="annealFunList" /> -->
|
||||
<dv-scroll-board :config="annealFunConfig" style="width:100%;height:310px" ref='annealFunScrollBoard' />
|
||||
</el-col>
|
||||
<span class="eqLineTwo"></span>
|
||||
<el-col :span="8" style="float: right;">
|
||||
<div style="font-size:20px;margin: 5px 0 10px 0;">产线设备</div>
|
||||
<div style="color:rgba(82, 255, 248, 1);font-size:20px;margin: 5px 0 10px 0;">产线设备</div>
|
||||
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :table-config="EqMonitoringProps"
|
||||
:table-data="realEqList" /> -->
|
||||
<dv-scroll-board :config="realEqConfig" style="width:100%;height:310px" ref='realEqScrollBoard' />
|
||||
@@ -136,6 +143,11 @@ import baseContainer from './components/baseContainer'
|
||||
import baseTable1 from './components/baseTable'
|
||||
import screenfull from 'screenfull'
|
||||
import pileBarChart from './components/pileBarChart'
|
||||
import secondPileBarChart from './components/pileBarChart'
|
||||
import thirdPileBarChart from './components/pileBarChart'
|
||||
import fourthPileBarChart from './components/pileBarChart'
|
||||
import fifthPileBarChart from './components/pileBarChart'
|
||||
|
||||
import colorDiv from './components/colorDiv'
|
||||
import moment from "moment";
|
||||
import doubleYChart from './components/coldDoubleYChart'
|
||||
@@ -152,7 +164,11 @@ export default {
|
||||
pileBarChart,
|
||||
doubleYChart,
|
||||
LinearBarChart,
|
||||
ISRAChart
|
||||
ISRAChart,
|
||||
secondPileBarChart,
|
||||
thirdPileBarChart ,
|
||||
fourthPileBarChart,
|
||||
fifthPileBarChart ,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -256,6 +272,16 @@ export default {
|
||||
},
|
||||
|
||||
watch: {
|
||||
isFullScreen:function (val) {
|
||||
if (val) {
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
console.log(_this.beilv2);
|
||||
} else {
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
}
|
||||
},
|
||||
clientWidth(val) {
|
||||
if (!this.timer) {
|
||||
this.clientWidth = val
|
||||
@@ -275,6 +301,7 @@ export default {
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, 86400000)
|
||||
// this.getData()
|
||||
},
|
||||
destroyed() {
|
||||
this.CutWebsocketClose()
|
||||
@@ -287,21 +314,96 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(moment(this.logoutTime - 28800000).format('HH:mm:ss'));
|
||||
let nameList = []
|
||||
let nameWasteList = []
|
||||
let topNameList = []
|
||||
let productList = []
|
||||
let wasteList = []
|
||||
let yieldList = []
|
||||
// let sumAreaList = []
|
||||
// let yieldList = []
|
||||
// this.cutTableDataList =
|
||||
let coldDetData = [
|
||||
{
|
||||
"first": 0.8834,
|
||||
"lineName": "Y61",
|
||||
"product": 0.8834,
|
||||
"productArea": 35069.28,
|
||||
"second": 0,
|
||||
'sumArea': 38400,
|
||||
'wastArea': 3330.72,
|
||||
"yield": 0.9133
|
||||
},
|
||||
{
|
||||
"first": 0.847,
|
||||
"lineName": "Y62",
|
||||
"product": 0.847,
|
||||
"productArea": 26765.46,
|
||||
"second": 0,
|
||||
'sumArea': 1111111,
|
||||
'wastArea': 22222,
|
||||
"yield": 0.9133
|
||||
},
|
||||
{
|
||||
"first": 0.8668,
|
||||
"lineName": "Y63",
|
||||
"product": 0.8668,
|
||||
"productArea": 26448.46,
|
||||
"second": 0,
|
||||
'sumArea': 1111111,
|
||||
'wastArea': 22222,
|
||||
"yield": 0.9133
|
||||
},
|
||||
{
|
||||
"first": 0.9064,
|
||||
"lineName": "Y64",
|
||||
"product": 0.9064,
|
||||
"productArea": 26667.32,
|
||||
"second": 0,
|
||||
'sumArea': 1111111,
|
||||
'wastArea': 22222,
|
||||
"yield": 0.9133
|
||||
},
|
||||
{
|
||||
"first": 0.8838,
|
||||
"lineName": "Y65",
|
||||
"product": 0.8838,
|
||||
"productArea": 26554.32,
|
||||
"second": 0,
|
||||
'sumArea': 1111111,
|
||||
'wastArea': 22222,
|
||||
"yield": 0.9133
|
||||
}
|
||||
]
|
||||
coldDetData.forEach((ele, index) => {
|
||||
nameList.push(ele.lineName)
|
||||
topNameList.push('产线: ' + ele.lineName + ' ' + '总面积:' + ele.sumArea)
|
||||
productList.push(ele.productArea)
|
||||
wasteList.push(ele.wastArea)
|
||||
nameWasteList.push('缺陷面积:' + ele.wastArea)
|
||||
yieldList.push({
|
||||
name: '良品',
|
||||
yield:ele.yield
|
||||
})
|
||||
// sumAreaList.push(ele.sumArea)
|
||||
// yieldList.push((ele.yield * 100).toFixed(3))
|
||||
})
|
||||
this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
|
||||
this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
|
||||
this.$refs.thirdPileChart.initChart(nameList, [topNameList[2]], [nameWasteList[2]], [productList[2]], [wasteList[2]])
|
||||
this.$refs.fourthPileChart.initChart(nameList, [topNameList[3]], [nameWasteList[3]], [productList[3]], [wasteList[3]])
|
||||
this.$refs.fifthPileChart.initChart(nameList, [topNameList[4]], [nameWasteList[4]], [productList[4]], [wasteList[4]])
|
||||
// this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
|
||||
this.getTimes()
|
||||
// console.log(moment(this.logoutTime - 28800000).format('HH:mm:ss'));
|
||||
this.funInitWebSocket()
|
||||
// if (num > 0) {
|
||||
if (!this.wsIsOpen) {
|
||||
getDcsMsg()
|
||||
this.wsIsOpen = true
|
||||
console.log('开启websocket==========')
|
||||
}
|
||||
// } else {
|
||||
|
||||
// }
|
||||
this.CutInitWebSocket()
|
||||
this.SJGInitWebSocket()
|
||||
// this.getList()
|
||||
this.getTimes()
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
window.onresize = () => {
|
||||
@@ -312,6 +414,39 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// getData() {
|
||||
// let detData = [
|
||||
// {
|
||||
// name: '1',
|
||||
// run: '运行',
|
||||
// },
|
||||
// {
|
||||
// name: '2',
|
||||
// run: '未运行',
|
||||
// },
|
||||
// {
|
||||
// name: '3',
|
||||
// run: '运行',
|
||||
// },
|
||||
// {
|
||||
// name: '4',
|
||||
// run: '未运行',
|
||||
// },
|
||||
// {
|
||||
// name: '1',
|
||||
// run: '运行',
|
||||
// },
|
||||
// ]
|
||||
// this.realEqList = detData.map((item, index) => [
|
||||
// // console.log(item)
|
||||
// `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
|
||||
// ])
|
||||
// this.realEqConfig.data = this.realEqList
|
||||
// this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
|
||||
// },
|
||||
CutWebsocketClose(e) {
|
||||
this.Cutws.ws.onclose = (event) => { console.log(event );}
|
||||
},
|
||||
@@ -381,16 +516,19 @@ export default {
|
||||
})
|
||||
this.$refs['ISRAChart'].updateChart(chartData)
|
||||
} else if (this.SJGWsData.type === 'equipment') {
|
||||
this.realEqList = this.SJGWsData.detData.map((ele, index) => [
|
||||
this.realEqList = this.SJGWsData.detData.map((item, index) => [
|
||||
// console.log(item)
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${ele.name || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${ele.run || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
|
||||
])
|
||||
}
|
||||
this.realEqConfig.data = this.realEqList
|
||||
this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
|
||||
this.$nextTick(() => {
|
||||
this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
|
||||
|
||||
})
|
||||
};
|
||||
// if (typeof (WebSocket) === 'undefined') {
|
||||
// alert('您的浏览器不支持WebSocket')
|
||||
@@ -451,9 +589,13 @@ export default {
|
||||
wasteList.push(ele.wastArea)
|
||||
nameWasteList.push('缺陷面积:' + ele.wastArea)
|
||||
sumAreaList.push(ele.sumArea)
|
||||
yieldList.push((ele.yield * 100).toFixed(3))
|
||||
yieldList.push(parseFloat((ele.yield * 100).toFixed(3)))
|
||||
})
|
||||
this.$refs.pileChart.initChart(nameList, topNameList, nameWasteList, productList, wasteList)
|
||||
this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
|
||||
this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
|
||||
this.$refs.thirdPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
|
||||
this.$refs.fourthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
|
||||
this.$refs.fifthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
|
||||
this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
|
||||
}
|
||||
};
|
||||
@@ -495,7 +637,8 @@ export default {
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${i || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${this.funWsData.data.annealFanInfo[i] || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
|
||||
])
|
||||
}
|
||||
this.annealFunConfig.data = arr
|
||||
@@ -509,7 +652,8 @@ export default {
|
||||
arr.push([
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${index || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${i || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${this.funWsData.data.fanInfo[i] || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
|
||||
])
|
||||
}
|
||||
this.funConfig.data = arr
|
||||
@@ -594,106 +738,34 @@ export default {
|
||||
// console.log(size[0] + '*' + size[1] + '*' + size[2]);
|
||||
return size[0] + '*' + size[1] + '*' + size[2]
|
||||
},
|
||||
// 数据接收
|
||||
// cutWebsocketOnMessage(e) {
|
||||
// this.cutWsData = e?.data ? JSON.parse(e?.data) : {}
|
||||
// if (this.cutWsData.type === 'cutting' && this.cutWsData.name === 'table') {
|
||||
// let cutArr = this.cutWsData.productHourData.map((item, index) => [
|
||||
// `<span style="color:rgba(255,255,255,0.7)" >${index + 1 || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.7)" >${item.lineName || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.7)">${this.formatTime(item.time) || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.7)">${this.getSize(item.size) || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.7)">${item.productArea + '㎡' || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.7)">${item.wasteArea + '㎡' || ''}</span>`,
|
||||
// `<div style = "${(item.product * 100).toFixed(2) > 91 ? 'display:block;color:#00FFF7' : 'display:none;'}">${(item.product * 100).toFixed(2) + '%' || ''}</div>
|
||||
// <div style = "${(item.product * 100).toFixed(2) < 91 ? 'display:block; color:rgba(255, 209, 96, 1)' : 'display:none;'}">${(item.product * 100).toFixed(2) + '%' || ''}</div>`
|
||||
// ])
|
||||
// this.cutConfig.data = cutArr
|
||||
// this.$refs['cutScrollBoard'].updateRows(cutArr)
|
||||
// } else if (this.cutWsData.type === 'cutting' && this.cutWsData.name === 'chart' && this.cutWsData.dateType === 'day') {
|
||||
// let nameList = []
|
||||
// let nameWasteList = []
|
||||
// let topNameList = []
|
||||
// let productList = []
|
||||
// let wasteList = []
|
||||
// let sumAreaList = []
|
||||
// let yieldList = []
|
||||
// // this.cutTableDataList =
|
||||
// this.cutWsData.coldDetData.forEach((ele, index) => {
|
||||
// nameList.push(ele.lineName)
|
||||
// topNameList.push('产线: ' + ele.lineName + ' ' + '总面积:' + ele.sumArea)
|
||||
// productList.push(ele.productArea)
|
||||
// wasteList.push(ele.wastArea)
|
||||
// nameWasteList.push('缺陷面积:' + ele.wastArea)
|
||||
// sumAreaList.push(ele.sumArea)
|
||||
// yieldList.push((ele.yield *100).toFixed(3))
|
||||
// })
|
||||
// this.$refs.pileChart.initChart(nameList, topNameList, nameWasteList, productList, wasteList)
|
||||
// this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
|
||||
// }
|
||||
// },
|
||||
// SJGWebsocketOnOpen() {
|
||||
// console.log('socket连接成功')
|
||||
// this.SJGWebsocket.onmessage()
|
||||
// },
|
||||
// 连接建立失败重连
|
||||
// SJGWebsocketOnError(e) {
|
||||
// this.SJGInitWebSocket()
|
||||
// },
|
||||
// 数据接收
|
||||
// SJGWebsocketOnMessage(e) {
|
||||
// this.SJGWsData = e?.data ? JSON.parse(e?.data) : {}
|
||||
// if (this.SJGWsData.type === 'isra') {
|
||||
// console.log('222222', this.SJGWsData.detData)
|
||||
// console.log(this.SJGWsData.detData);
|
||||
// let chartData = this.SJGWsData.detData.map((item, index) => {
|
||||
// return {
|
||||
// name: item.type,
|
||||
// num:item.num
|
||||
// }
|
||||
// })
|
||||
// this.$refs['ISRAChart'].updateChart(chartData)
|
||||
// } else if (this.SJGWsData.type === 'equipment') {
|
||||
// this.realEqList = this.SJGWsData.detData.map((ele, index) =>[
|
||||
// // console.log(item)
|
||||
// `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${ele.name || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${ele.run || ''}</span>`,
|
||||
// ])
|
||||
// }
|
||||
// this.realEqConfig.data = this.realEqList
|
||||
// this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
|
||||
// },
|
||||
windowWidth(value) {
|
||||
this.clientWidth = value
|
||||
this.beilv2 = this.clientWidth / 1920
|
||||
},
|
||||
change() {
|
||||
console.log(this.isFullScreen);
|
||||
this.isFullScreen = screenfull.isFullscreen
|
||||
},
|
||||
init() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.on('change', this.change)
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.off('change', this.change)
|
||||
}
|
||||
},
|
||||
changeFullScreen() {
|
||||
this.containerWidth = 223223223
|
||||
if (!screenfull.enabled) {
|
||||
// this.containerWidth = 223223223
|
||||
if (!screenfull.isEnabled) {
|
||||
this.$message({
|
||||
message: 'you browser can not work',
|
||||
type: 'warning'
|
||||
})
|
||||
return false
|
||||
}
|
||||
screenfull.toggle(this.$refs.container)
|
||||
screenfull.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -714,14 +786,16 @@ export default {
|
||||
background-size: 100% 100%;
|
||||
color: rgba(0, 255, 247, 1);
|
||||
text-align: center;
|
||||
letter-spacing: 8px;
|
||||
word-spacing: 8px;
|
||||
.unit {
|
||||
position: absolute;
|
||||
left: 260px;
|
||||
left: 290px;
|
||||
top: 25px;
|
||||
color: rgba(255, 255, 255, 0.80);
|
||||
font-size: 20px;
|
||||
}
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.time {
|
||||
position: absolute;
|
||||
@@ -729,6 +803,7 @@ export default {
|
||||
color: rgba(255, 255, 255, 0.80);
|
||||
top: 25px;
|
||||
font-size: 20px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.title-button {
|
||||
@@ -780,6 +855,10 @@ export default {
|
||||
top: 2em;
|
||||
}
|
||||
|
||||
.screen-btn {
|
||||
color: #00fff0;
|
||||
font-size: 32px;
|
||||
}
|
||||
// .container-main {
|
||||
// padding: 5px;
|
||||
// }
|
||||
@@ -868,6 +947,7 @@ background: linear-gradient(to bottom,rgba(60,
|
||||
margin-left: 3em;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
@@ -926,4 +1006,5 @@ background: linear-gradient(to bottom,rgba(60,
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2022-01-21 14:43:06
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2022-01-24 13:27:41
|
||||
* @LastEditors: zhp
|
||||
* @LastEditTime: 2024-03-28 16:30:54
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
@@ -61,7 +61,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
// this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: zwq
|
||||
* @Date: 2022-01-21 14:43:06
|
||||
* @LastEditors: zhp
|
||||
* @LastEditTime: 2024-01-25 17:41:44
|
||||
* @LastEditTime: 2024-03-28 16:45:24
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
@@ -90,6 +90,7 @@ export default {
|
||||
bottom: 0,
|
||||
itemHeight: 10,
|
||||
itemWidth: 10,
|
||||
icon:'roundRect',
|
||||
formatter: function(name) {
|
||||
let pieLegendVale = {}
|
||||
lData.filter((item, index) => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: gtz
|
||||
* @Date: 2022-01-19 15:58:17
|
||||
* @LastEditors: zhp
|
||||
* @LastEditTime: 2024-02-22 10:26:59
|
||||
* @LastEditTime: 2024-03-27 10:26:35
|
||||
* @Description: file content
|
||||
* @FilePath: \mt-bus-fe\src\views\OperationalOverview\components\baseContainer\index.vue
|
||||
-->
|
||||
@@ -158,6 +158,7 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
|
||||
|
||||
|
||||
.base-container {
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
@@ -192,7 +193,7 @@ export default {
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
&__eqStatus {
|
||||
background: url(../../../../assets/img/high.png) no-repeat;
|
||||
background: url(../../../../assets/img/large.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-09-21 09:06:28
|
||||
* @LastEditTime: 2024-03-26 16:16:50
|
||||
* @LastEditTime: 2024-03-28 16:31:20
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -78,7 +78,7 @@ export default {
|
||||
this.$el.addEventListener('resize', () => {
|
||||
console.log('resziing.....');
|
||||
});
|
||||
this.initChart()
|
||||
// this.initChart()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
@@ -112,7 +112,7 @@ export default {
|
||||
}
|
||||
// barBorderRadius: this.borderRadius
|
||||
},
|
||||
barWidth: 12,
|
||||
barWidth: 18,
|
||||
data: outputNumList
|
||||
},
|
||||
{
|
||||
@@ -147,72 +147,40 @@ export default {
|
||||
]
|
||||
// const colors = ['#5470C6', '#91CC75', '#EE6666']
|
||||
this.chart = echarts.init(document.getElementById(this.id))
|
||||
this.chart.setOption({
|
||||
// color: colors,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross'
|
||||
}
|
||||
},
|
||||
grid: { top: 90, right: 60, bottom: 20, left: 90 },
|
||||
legend: {
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
top: '0%',
|
||||
right: '20px',
|
||||
data: ['产线产量', '产线良品率'],
|
||||
textStyle: {
|
||||
fontSize: 12 * this.beilv,
|
||||
color: '#ced1d5'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
color: '#25528f',
|
||||
width: '1' // 坐标线的宽度
|
||||
if (!nameList && !passRateList && !outputNumList) {
|
||||
// 隐藏echarts图表
|
||||
this.chart.clear(); // 清空图表
|
||||
this.chart.setOption({ // 设置空的option
|
||||
title: {
|
||||
show: false
|
||||
},
|
||||
series: []
|
||||
});
|
||||
} else {
|
||||
// 显示echarts图表
|
||||
this.chart.setOption({
|
||||
// color: colors,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}'
|
||||
// textStyle: {
|
||||
// color: 'rgba(255,255,255,0.5)' // 坐标值得具体的颜色
|
||||
// }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
grid: { top: 90, right: 60, bottom: 20, left: 20, containLabel: true },
|
||||
legend: {
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
top: '0%',
|
||||
right: '20px',
|
||||
data: ['产线产量', '产线良品率'],
|
||||
textStyle: {
|
||||
fontSize: 12 * this.beilv,
|
||||
color: '#ced1d5'
|
||||
}
|
||||
},
|
||||
data: nameList
|
||||
},
|
||||
// yAxis: {
|
||||
|
||||
// },
|
||||
yAxis: [
|
||||
{
|
||||
// min: function() { // 取最小值向下取整为最小刻度
|
||||
// return 0
|
||||
// },
|
||||
// max: function(value) { // 取最大值向上取整为最大刻度
|
||||
// return Math.ceil(value.max)
|
||||
// },
|
||||
scale: true,
|
||||
type: 'value',
|
||||
name: '良品率/%',
|
||||
nameTextStyle: {// y轴上方单位的颜色
|
||||
color: '#fff',
|
||||
align: "left",
|
||||
},
|
||||
position: 'right',
|
||||
alignTicks: true,
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
color: '#25528f',
|
||||
@@ -223,72 +191,118 @@ export default {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}'
|
||||
formatter: '{value}%'
|
||||
// }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
}
|
||||
}
|
||||
// type: 'value'
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: colors[0]
|
||||
// }
|
||||
// },
|
||||
},
|
||||
{
|
||||
// min: function() { // 取最小值向下取整为最小刻度
|
||||
// return 0
|
||||
// },
|
||||
// max: function(value) { // 取最大值向上取整为最大刻度
|
||||
// return Math.ceil(value.max)
|
||||
// },
|
||||
scale: true,
|
||||
type: 'value',
|
||||
name: '产量/片', // y轴上方的单位
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
// fontSize: 10,
|
||||
align: "right",
|
||||
},
|
||||
// position: 'left',
|
||||
alignTicks: true,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
color: '#25528f', // 左边线的颜色
|
||||
width: '1' // 坐标线的宽度
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
// textStyle: {
|
||||
// color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}'
|
||||
formatter: '{value} 片'
|
||||
// color: 'rgba(255,255,255,0.5)' // 坐标值得具体的颜色
|
||||
// }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
}
|
||||
},
|
||||
data: nameList
|
||||
},
|
||||
// yAxis: {
|
||||
|
||||
// },
|
||||
yAxis: [
|
||||
{
|
||||
// min: function() { // 取最小值向下取整为最小刻度
|
||||
// return 0
|
||||
// },
|
||||
// max: function(value) { // 取最大值向上取整为最大刻度
|
||||
// return Math.ceil(value.max)
|
||||
// },
|
||||
scale: true,
|
||||
type: 'value',
|
||||
name: '良品率/%',
|
||||
nameTextStyle: {// y轴上方单位的颜色
|
||||
color: '#fff',
|
||||
align: "left",
|
||||
},
|
||||
position: 'right',
|
||||
alignTicks: true,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
// type: 'solid',
|
||||
color: '#25528f',
|
||||
// width: '1' // 坐标线的宽度
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}'
|
||||
formatter: '{value}%'
|
||||
// }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
}
|
||||
}
|
||||
// type: 'value'
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: colors[0]
|
||||
// }
|
||||
// },
|
||||
},
|
||||
{
|
||||
// min: function() { // 取最小值向下取整为最小刻度
|
||||
// return 0
|
||||
// },
|
||||
// max: function(value) { // 取最大值向上取整为最大刻度
|
||||
// return Math.ceil(value.max)
|
||||
// },
|
||||
scale: true,
|
||||
type: 'value',
|
||||
name: '产量/片', // y轴上方的单位
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
// fontSize: 10,
|
||||
align: "right",
|
||||
},
|
||||
// position: 'left',
|
||||
alignTicks: true,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
// type: 'solid',
|
||||
color: '#25528f', // 左边线的颜色
|
||||
// width: '1' // 坐标线的宽度
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
// textStyle: {
|
||||
// color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
|
||||
color: "#fff",
|
||||
// show: true,
|
||||
lineStyle: {
|
||||
color: "#25528f",
|
||||
},
|
||||
// }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
}
|
||||
}
|
||||
// type: 'value'
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: colors[1]
|
||||
// }jik078u7uut9890999999999999999999999999999999999999999999999999999999999999995u8
|
||||
// },
|
||||
}
|
||||
// type: 'value'
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: colors[1]
|
||||
// }jik078u7uut9890999999999999999999999999999999999999999999999999999999999999995u8
|
||||
// },
|
||||
}
|
||||
],
|
||||
series: series
|
||||
})
|
||||
],
|
||||
series: series
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export default {
|
||||
// this.dataList.forEach(ele => {
|
||||
// console.log(ele);
|
||||
// this.series = []
|
||||
this.initChart()
|
||||
// this.initChart()
|
||||
// this.$nextTick(() => {
|
||||
// // this.initChart()
|
||||
// })
|
||||
@@ -87,8 +87,17 @@ export default {
|
||||
// console.log('1111', dataList);
|
||||
// console.log(1)
|
||||
this.chart = echarts.init(document.getElementById(this.id))
|
||||
// if (dataList.length !== 0) {
|
||||
// this.$set(this.series, "data", dataList);
|
||||
if (!nameList && !dataList) {
|
||||
// 隐藏echarts图表
|
||||
this.chart.clear(); // 清空图表
|
||||
this.chart.setOption({ // 设置空的option
|
||||
title: {
|
||||
show: false
|
||||
},
|
||||
series: []
|
||||
});
|
||||
} else {
|
||||
// 显示echarts图表
|
||||
this.series = [{
|
||||
type: 'bar',
|
||||
data: dataList,
|
||||
@@ -109,92 +118,96 @@ export default {
|
||||
}
|
||||
// barBorderRadius: this.borderRadius
|
||||
},
|
||||
barWidth: 12,
|
||||
barWidth: 18,
|
||||
}]
|
||||
// }
|
||||
// if (nameList.length !== 0) {
|
||||
// }
|
||||
// if (nameList.length !== 0) {
|
||||
this.nameList = nameList
|
||||
// }
|
||||
this.chart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
// 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
grid: { top: 90, right: 60, bottom: 20, left: 90 },
|
||||
// legend: {
|
||||
// itemWidth: 10,
|
||||
// itemHeight: 10,
|
||||
// // right: '20px',
|
||||
// data: nameList,
|
||||
// textStyle: {
|
||||
// fontSize: 12 * this.beilv,
|
||||
// color: '#ced1d5'
|
||||
// }
|
||||
// },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
color: '#25528f', // 左边线的颜色
|
||||
width: '1' // 坐标线的宽度
|
||||
// }
|
||||
this.chart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
// 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}'
|
||||
grid: { top: 90, right: 60, bottom: 20, left: 30, containLabel: true },
|
||||
// legend: {
|
||||
// itemWidth: 10,
|
||||
// itemHeight: 10,
|
||||
// // right: '20px',
|
||||
// data: nameList,
|
||||
// textStyle: {
|
||||
// fontSize: 12 * this.beilv,
|
||||
// color: '#ced1d5'
|
||||
// }
|
||||
// },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
color: '#25528f', // 左边线的颜色
|
||||
width: '1' // 坐标线的宽度
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}'
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
}
|
||||
},
|
||||
data: this.nameList
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#25528f'
|
||||
yAxis: {
|
||||
name: '单位kwh',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}/kwh'
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#25528f",
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "#25528f",
|
||||
},
|
||||
}
|
||||
},
|
||||
data: this.nameList
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位kwh',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
// formatter: '{value}/kwh'
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#25528f",
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "#25528f",
|
||||
},
|
||||
}
|
||||
},
|
||||
// legend: {
|
||||
// itemHeight: 10,
|
||||
// itemWidth: 10,
|
||||
// x: 'center', // 可设定图例在左、右、居中
|
||||
// y: 'top', // 可设定图例在上、下、居中
|
||||
// show: this.showLegend,
|
||||
// data: this.dataList,
|
||||
// right: '1%',
|
||||
// textStyle: {
|
||||
// fontSize: 12 * this.beilv,
|
||||
// color: '#ced1d5'
|
||||
// }
|
||||
// },
|
||||
series: this.series
|
||||
})
|
||||
// legend: {
|
||||
// itemHeight: 10,
|
||||
// itemWidth: 10,
|
||||
// x: 'center', // 可设定图例在左、右、居中
|
||||
// y: 'top', // 可设定图例在上、下、居中
|
||||
// show: this.showLegend,
|
||||
// data: this.dataList,
|
||||
// right: '1%',
|
||||
// textStyle: {
|
||||
// fontSize: 12 * this.beilv,
|
||||
// color: '#ced1d5'
|
||||
// }
|
||||
// },
|
||||
series: this.series
|
||||
})
|
||||
}
|
||||
// if (dataList.length !== 0) {
|
||||
// this.$set(this.series, "data", dataList);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-12-27 13:54:52
|
||||
* @LastEditTime: 2024-03-26 10:50:30
|
||||
* @LastEditTime: 2024-03-28 16:30:14
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -15,6 +15,7 @@
|
||||
import * as echarts from 'echarts';
|
||||
import 'echarts/theme/macarons' // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
import { raw } from 'body-parser';
|
||||
|
||||
export default {
|
||||
name: 'OverviewBar',
|
||||
@@ -42,7 +43,7 @@ export default {
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 200
|
||||
default: 100
|
||||
},
|
||||
showLegend: {
|
||||
type: Boolean,
|
||||
@@ -77,7 +78,7 @@ export default {
|
||||
// this.dataList.forEach(ele => {
|
||||
// console.log(ele);
|
||||
// this.series = []
|
||||
this.initChart()
|
||||
// this.initChart()
|
||||
// this.$nextTick(() => {
|
||||
// // this.initChart()
|
||||
// })
|
||||
@@ -94,7 +95,8 @@ export default {
|
||||
let rawData = []
|
||||
let colors = ['#0fdedb', '#2359ec']
|
||||
rawData.push(passRateList, wasteList)
|
||||
const totalData = [];
|
||||
const totalData = [];
|
||||
// if (rawData.length != 0 && raw,Data,length != 0) {
|
||||
for (let i = 0; i < rawData[0].length; ++i) {
|
||||
let sum = 0;
|
||||
for (let j = 0; j < rawData.length; ++j) {
|
||||
@@ -102,7 +104,8 @@ export default {
|
||||
}
|
||||
totalData.push(sum);
|
||||
}
|
||||
console.log('total', totalData);
|
||||
// }
|
||||
console.log('total', totalData)
|
||||
this.chart = echarts.init(document.getElementById(this.id))
|
||||
const series = [
|
||||
'良品',
|
||||
@@ -116,34 +119,49 @@ export default {
|
||||
name,
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
barWidth: 10,
|
||||
label: {
|
||||
show: true,
|
||||
formatter: (params) => Math.round(params.value * 1000) / 10 + '%'
|
||||
},
|
||||
barWidth: 12,
|
||||
// label: {
|
||||
// show: true,
|
||||
// formatter: (params) => Math.round(params.value * 1000) / 10 + '%'
|
||||
// },
|
||||
color:colors[sid],
|
||||
data: rawData.length != 0 ? rawData[sid].map((d, did) =>
|
||||
totalData[did] <= 0 ? 0 : d / totalData[did]
|
||||
) : []
|
||||
};
|
||||
});
|
||||
// this.charts.resize({
|
||||
// //width: width,
|
||||
// //height: height,
|
||||
// // es6解构
|
||||
// width,
|
||||
// height
|
||||
// })
|
||||
this.chart.setOption({
|
||||
legend: {
|
||||
formatter: function (name) {
|
||||
//通过name获取到数组对象中的单个对象
|
||||
let singleData = series.filter(function (item) {
|
||||
return item.name == name
|
||||
})
|
||||
return name + parseFloat((singleData[0].data * 100).toFixed(3)) + '%'
|
||||
},
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
top:'10',
|
||||
bottom: '20',
|
||||
left: '20',
|
||||
icon: 'rect',
|
||||
textStyle: {
|
||||
color: '#ffffff'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top:'80',
|
||||
top:'0',
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
// bottom: '3%',
|
||||
width: 'auto',
|
||||
height: '300',
|
||||
height: '95',
|
||||
containLabel: true
|
||||
},
|
||||
yAxis: [
|
||||
@@ -170,7 +188,7 @@ export default {
|
||||
verticalAlign: 'bottom',
|
||||
fontSize: 12,
|
||||
align: 'left',
|
||||
padding: [0, 0, 15, -5]
|
||||
padding: [0, 0, 10, -5]
|
||||
}
|
||||
},
|
||||
data: topNameList
|
||||
@@ -198,7 +216,7 @@ export default {
|
||||
verticalAlign: 'bottom',
|
||||
fontSize: 12,
|
||||
align: 'right',
|
||||
padding: [0, 0, 15, -5]
|
||||
padding: [0, 0, 10, -5]
|
||||
}
|
||||
},
|
||||
data: nameWasteList
|
||||
@@ -210,6 +228,10 @@ export default {
|
||||
},
|
||||
series:series
|
||||
})
|
||||
this.chart.resize({
|
||||
width: 'auto',
|
||||
height: 90
|
||||
});;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: zwq
|
||||
* @Date: 2021-07-19 15:18:30
|
||||
* @LastEditors: zhp
|
||||
* @LastEditTime: 2024-03-26 15:43:27
|
||||
* @LastEditTime: 2024-03-28 16:10:47
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
@@ -16,16 +16,19 @@
|
||||
许昌安彩深加工看板
|
||||
<h3 class="unit">单位:河南汇融数字科技有限公司</h3>
|
||||
<h3 class="time">{{ times }}</h3>
|
||||
<el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px',fontSize:'32px'}"
|
||||
@click="changeFullScreen">
|
||||
<svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
|
||||
<svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row class="container-main flex-col" type="flex">
|
||||
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15" type="flex" class="flex-1" style="height: 50%;">
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="8" height="100%">
|
||||
<base-container :title="'设备报警'" :size="'small'" :height="318" :title-icon="'eqAlarm'">
|
||||
<dv-scroll-board class="eqTable" :config="eqConfig" style="width:100%;height:350px" ref='eqScrollBoard' />
|
||||
|
||||
</base-container>
|
||||
</el-col>
|
||||
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="8" height="100%">
|
||||
<base-container :title="'各工序缺陷汇总'" :size="'small'" :title-icon="'scrap'">
|
||||
<dv-scroll-board :config="processConfig" style="width:100%;height:350px" ref='processScrollBoard' />
|
||||
@@ -33,13 +36,14 @@
|
||||
</el-col>
|
||||
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="8" height="100%">
|
||||
<base-container :height="318" :size="'small'" :title="'工单监控'" :title-icon="'order'">
|
||||
<div style="width:100%; overflow: hidden scroll;">
|
||||
<base-container :height="318" :size="'small'" :title="'工单监控'" :title-icon="'eqMonitoring'">
|
||||
<div class="order" style="width:100%; overflow: hidden scroll;height: 350px;">
|
||||
<el-row v-for="op in orderList" :key="op.id" style="margin-bottom: 1em">
|
||||
<!-- <el-col :span="12"> -->
|
||||
|
||||
<p class="now-secondary-title">{{ op.name }}</p>
|
||||
<el-progress define-back-color="rgba(32, 57, 96, 1)" text-color="white"
|
||||
:percentage="op.progressRate * 100" class="custom-progress-bar" />
|
||||
<el-progress :stroke-width="10" define-back-color="rgba(32, 57, 96, 1)" text-color="white"
|
||||
:percentage="op.progressRate" class="custom-progress-bar" />
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
@@ -49,8 +53,8 @@
|
||||
|
||||
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="12" type="flex" class="flex-1">
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :show-yes-time="true" :no-content-padding="true" :height="256" :size="'middle'" :title="'能源监控'"
|
||||
:title-icon="'energyMonitoring'">
|
||||
<base-container :show-yes-time="true" :no-content-padding="true" :height="256" :size="'eqStatus'"
|
||||
:title="'能源监控'" :title-icon="'energyMonitoring'">
|
||||
<el-row :gutter="9">
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="24">
|
||||
<linear-bar-chart ref="EnergyMonitoringChart" :name-list="EnergyMonitoringNameList"
|
||||
@@ -60,7 +64,7 @@
|
||||
</base-container>
|
||||
</el-col>
|
||||
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
|
||||
<base-container :show-time="true" :no-content-padding="true" :height="318 + 338 + 16" :size="'middle'"
|
||||
<base-container :show-time="true" :no-content-padding="true" :height="318 + 338 + 16" :size="'eqStatus'"
|
||||
:title="'产线产量及良品率'" :title-icon="'productLine'">
|
||||
<double-y-chart ref="productLineChart" :id=" 'doubleYChart' " :height="390" :show-legend="true" />
|
||||
</base-container>
|
||||
@@ -234,7 +238,6 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// ...mapGetters(['sidebar']),
|
||||
styles() {
|
||||
const v = Math.floor(this.value * this.beilv2 * 100) / 10000
|
||||
return {
|
||||
@@ -243,8 +246,17 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
isFullScreen: function (val) {
|
||||
if (val) {
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
console.log(_this.beilv2);
|
||||
} else {
|
||||
const _this = this;
|
||||
_this.beilv2 = document.documentElement.clientWidth / 1920
|
||||
}
|
||||
},
|
||||
clientWidth(val) {
|
||||
if (!this.timer) {
|
||||
this.clientWidth = val
|
||||
@@ -255,12 +267,10 @@ export default {
|
||||
_this.timer = false
|
||||
}, 500)
|
||||
}
|
||||
// 这里可以添加修改时的方法
|
||||
this.windowWidth(val);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getData()
|
||||
this.init()
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
@@ -271,20 +281,67 @@ export default {
|
||||
this.SJGWebsocketClose()
|
||||
},
|
||||
mounted() {
|
||||
let eqArr = this.qualityYearList.map((item, index) => [
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
</span>`,
|
||||
// formatDate(item.planStartTime) || '',
|
||||
`
|
||||
<span style="color:rgba(255,255,255,0.5)" >${item.name || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.code || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.status || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.error || ''}</span>`,
|
||||
])
|
||||
this.eqConfig.data = eqArr
|
||||
this.$refs['eqScrollBoard'].updateRows(eqArr)
|
||||
this.$refs.productLineChart.initChart(['D61', 'D62', 'D63', 'D64', 'D65',], [98, 97, 98.7, 98.5, 98.3,], [3134, 2323, 3232, 3233, 2321])
|
||||
// let detData = [
|
||||
// {
|
||||
// id:'1',
|
||||
// name: '测试工单',
|
||||
// progressRate:0.933333
|
||||
// },
|
||||
// {
|
||||
// id: '2',
|
||||
// name: '测试工单2',
|
||||
// progressRate: 0.932323
|
||||
// }, {
|
||||
// id: '3',
|
||||
// name: '测试工单3',
|
||||
// progressRate: 0.23232
|
||||
// }, {
|
||||
// id: '4',
|
||||
// name: '测试工单4',
|
||||
// progressRate: 0.32323
|
||||
// }
|
||||
// // {
|
||||
// // id: '5',
|
||||
// // name: '测试工单',
|
||||
// // progressRate: 0.5555
|
||||
// // }, {
|
||||
// // id: '6',
|
||||
// // name: '测试工单',
|
||||
// // progressRate: 0.66564
|
||||
// // },
|
||||
// ]
|
||||
// this.orderList = detData.map((ele, index) => {
|
||||
// if (ele.progressRate && ele.progressRate != 1) {
|
||||
// return {
|
||||
// id: ele.id,
|
||||
// name: ele.name,
|
||||
// progressRate: parseFloat((ele.progressRate * 100).toFixed(3))
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// let EnergyNameList = ['Y61', 'Y62', 'Y63', 'Y64', 'Y65',]
|
||||
// this.EnergyMonitoringNameList = EnergyNameList
|
||||
// let EnergyDataList = [1, 2, 3, 4, 5]
|
||||
// // this.wsData.data.forEach((ele) => {
|
||||
// // EnergyDataList.push(ele.useQuantity)
|
||||
// // })
|
||||
// this.EnergyMonitoringList = EnergyDataList
|
||||
// // console.log(EnergyDataList)
|
||||
// this.$refs.EnergyMonitoringChart.initChart(this.EnergyMonitoringNameList, this.EnergyMonitoringList)
|
||||
// let eqArr = this.qualityYearList.map((item, index) => [
|
||||
// `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
// </span>`,
|
||||
// // formatDate(item.planStartTime) || '',
|
||||
// `
|
||||
// <span style="color:rgba(255,255,255,0.5)" >${item.name || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.code || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.status || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.error || ''}</span>`,
|
||||
// ])
|
||||
// this.eqConfig.data = eqArr
|
||||
// this.$refs['eqScrollBoard'].updateRows(eqArr)
|
||||
// this.$refs.productLineChart.initChart(['D61', 'D62', 'D63', 'D64', 'D65',], [98, 97, 98.7, 98.5, 98.3,], [3134, 2323, 3232, 3233, 2321])
|
||||
// this.getList()
|
||||
this.initWebSocket()
|
||||
this.SJGInitWebSocket()
|
||||
@@ -298,7 +355,9 @@ export default {
|
||||
this.beilv2 = _this.clientWidth / 1920
|
||||
})()
|
||||
}
|
||||
this.getData()
|
||||
},
|
||||
|
||||
// beforeDestroy() {
|
||||
// //离开页面删除检测器和所有侦听器
|
||||
// // erd.uninstall(document); //这里用ref是因为vue离开页面后获取不到dom
|
||||
@@ -448,11 +507,11 @@ export default {
|
||||
// console.log('22222', this.wsData.data)
|
||||
if (this.SJGWsData.type === 'order') {
|
||||
this.orderList = this.SJGWsData.detData.map((ele, index) => {
|
||||
if (ele.progressRate != 1) {
|
||||
if (ele.progressRate && ele.progressRate != 1) {
|
||||
return {
|
||||
id: ele.id,
|
||||
name: ele.name,
|
||||
progressRate: ele.progressRate.toFixed(3)
|
||||
progressRate: parseFloat((ele.progressRate * 100).toFixed(3))
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -464,7 +523,7 @@ export default {
|
||||
`<span style="color:rgba(255,255,255,0.5)" >${item.name || ''}
|
||||
</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.code || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.status || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)"><span style="color:rgba(255,255,255,0.5)"></span> ${item.status || ''}</span>`,
|
||||
`<span style="color:rgba(255,255,255,0.5)">${item.error || ''}</span>`,
|
||||
])
|
||||
this.eqConfig.data = eqArr
|
||||
@@ -489,122 +548,10 @@ export default {
|
||||
} else if (this.SJGInitWebSocket === 'inspection') {
|
||||
}
|
||||
};
|
||||
// if (typeof (WebSocket) === 'undefined') {
|
||||
// alert('您的浏览器不支持WebSocket')
|
||||
// } else {
|
||||
// let date = new Date().valueOf()
|
||||
// // console.log(date);
|
||||
// console.log(process.env);
|
||||
// const SJGWsUrl = process.env.VUE_APP_Socket_API + `/websocket/message?userId=SJG${date}`
|
||||
// this.SJGWebsocket = new WebSocket(SJGWsUrl)
|
||||
// // 监听 WebSocket 连接
|
||||
// this.SJGWebsocket.onopen = this.SJGWebsocketOnOpen
|
||||
// // 监听 WebSocket 错误信息
|
||||
// this.SJGWebsocket.onerror = this.SJGWebsocketOnError
|
||||
// // 监听 WebSocket 消息
|
||||
// this.SJGWebsocket.onmessage = this.SJGWebsocketOnMessage
|
||||
// // 监听 webSocket 断开信息
|
||||
// this.SJGWebsocket.onclose = this.SJGWebsocketClose
|
||||
// }
|
||||
},
|
||||
// SJGWebsocketOnOpen() {
|
||||
// console.log('socket连接成功')
|
||||
// // console.log(this.SJGWebsocket.onmessage);
|
||||
// this.SJGWebsocket.onmessage()
|
||||
// },
|
||||
// // 连接建立失败重连
|
||||
// SJGWebsocketOnError(e) {
|
||||
// // console.log('11111', e)
|
||||
// this.SJGInitWebSocket()
|
||||
// },
|
||||
// 数据接收
|
||||
// SJGWebsocketOnMessage(e) {
|
||||
// console.log(1111, e)
|
||||
// this.SJGWsData = e?.data ? JSON.parse(e?.data) : {}
|
||||
// // console.log(this.wsData.detData);
|
||||
// // console.log('22222', this.wsData.data)
|
||||
// if (this.SJGWsData.type === 'order') {
|
||||
// this.orderList = this.SJGWsData.detData.map((ele, index) => {
|
||||
// if (ele.progressRate != 1) {
|
||||
// return {
|
||||
// id: ele.id,
|
||||
// name: ele.name,
|
||||
// progressRate: ele.progressRate.toFixed(3)
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// console.log(this.orderList)
|
||||
// } else if (this.SJGWsData.type === 'equipment') {
|
||||
// let eqArr = this.SJGWsData.detData.map((item, index) => [
|
||||
// `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)" >${item.name || ''}
|
||||
// </span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.code || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.status || ''}</span>`,
|
||||
// `<span style="color:rgba(255,255,255,0.5)">${item.error || ''}</span>`,
|
||||
// ])
|
||||
// this.eqConfig.data = eqArr
|
||||
// this.$refs['eqScrollBoard'].updateRows(eqArr)
|
||||
// // console.log(SJGWsData.orderList)
|
||||
// } else if (this.SJGWsData.type === 'productline') {
|
||||
// console.log('aaaaaaaaaaaaaaaaaaa', this.SJGWsData);
|
||||
// let nameList = []
|
||||
// let passRateList = []
|
||||
// let outputNumList = []
|
||||
// this.SJGWsData.detData.forEach((ele) => {
|
||||
// // if (item.id == ele.productionLineId) {
|
||||
// // if (item.name.substr(0, 1) == "D") {
|
||||
// // console.log(ele)
|
||||
// nameList.push(ele.lineName)
|
||||
// outputNumList.push(ele.outputNum)
|
||||
// passRateList.push(ele.passRate)
|
||||
// // }
|
||||
// // }
|
||||
// })
|
||||
// this.$refs.productLineChart.initChart(nameList, passRateList, outputNumList)
|
||||
// } else if (this.SJGInitWebSocket === 'inspection') {
|
||||
// }
|
||||
// },
|
||||
SJGWebsocketClose(e) {
|
||||
this.SJGws.ws.onclose = (event) => { console.log(event); }
|
||||
},
|
||||
// // 连接建立之后执行send方法发送数据
|
||||
// websocketOnOpen() {
|
||||
// console.log('socket连接成功')
|
||||
// this.websocket.onmessage()
|
||||
// },
|
||||
// 连接建立失败重连
|
||||
// websocketOnError(e) {
|
||||
// console.log('11111', e)
|
||||
// this.initWebSocket()
|
||||
// },
|
||||
// 数据接收
|
||||
// websocketOnMessage(e) {
|
||||
// // console.log(1111, e)
|
||||
// this.wsData = e?.data ? JSON.parse(e?.data) : {}
|
||||
// // console.log('22222', this.wsData.data)
|
||||
// if (this.wsData.type === 'EnergyMonitoring') {
|
||||
// let EnergyNameList = []
|
||||
// this.wsData.data.forEach((ele) => {
|
||||
// EnergyNameList.push(ele.lineName)
|
||||
// })
|
||||
// this.EnergyMonitoringNameList = EnergyNameList
|
||||
// let EnergyDataList = []
|
||||
// this.wsData.data.forEach((ele) => {
|
||||
// EnergyDataList.push(ele.useQuantity
|
||||
// )
|
||||
// })
|
||||
// this.EnergyMonitoringList = EnergyDataList
|
||||
// console.log(EnergyDataList)
|
||||
// this.$refs.EnergyMonitoringChart.initChart(this.EnergyMonitoringNameList, this.EnergyMonitoringList)
|
||||
// }
|
||||
// },
|
||||
// 数据发送
|
||||
// websocketSend() {
|
||||
// this.websocket.send('11111')
|
||||
// },
|
||||
// // 关闭
|
||||
websocketClose(e) {
|
||||
this.wsHeartbeat.ws.onclose = (event) => { console.log(event); }
|
||||
},
|
||||
@@ -613,28 +560,32 @@ export default {
|
||||
this.beilv2 = this.clientWidth / 1920
|
||||
},
|
||||
change() {
|
||||
console.log(this.isFullScreen);
|
||||
debugger;
|
||||
this.isFullScreen = screenfull.isFullscreen
|
||||
},
|
||||
init() {
|
||||
if (screenfull.enabled) {
|
||||
console.log(screenfull.isEnabled);
|
||||
if (screenfull.isEnabled) {
|
||||
debugger;
|
||||
screenfull.on('change', this.change)
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.off('change', this.change)
|
||||
}
|
||||
},
|
||||
changeFullScreen() {
|
||||
this.containerWidth = 223223223
|
||||
if (!screenfull.enabled) {
|
||||
// this.containerWidth = 223223223
|
||||
if (!screenfull.isEnabled) {
|
||||
this.$message({
|
||||
message: 'you browser can not work',
|
||||
type: 'warning'
|
||||
})
|
||||
return false
|
||||
}
|
||||
screenfull.toggle(this.$refs.container)
|
||||
screenfull.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -654,25 +605,24 @@ export default {
|
||||
background: url('../../assets/img/OperationalOverview/title.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #00fff0;
|
||||
// word-spacing: 8px;
|
||||
word-spacing: 8px;
|
||||
letter-spacing: 8px;
|
||||
text-align: center;
|
||||
.unit {
|
||||
position: absolute;
|
||||
left: 290px;
|
||||
top: 25px;
|
||||
letter-spacing: 0px;
|
||||
color: rgba($color: #ffffff, $alpha: 8);
|
||||
color: rgba(255, 255, 255, 0.80);
|
||||
font-size: 20px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.time {
|
||||
position: absolute;
|
||||
left: 1360px;
|
||||
color: rgba(255, 255, 255, 0.80);
|
||||
top: 25px;
|
||||
letter-spacing: 0px;
|
||||
color: rgba($color: #ffffff, $alpha: 8);
|
||||
font-size: 20px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
.title-button {
|
||||
color: #00fff0;
|
||||
@@ -785,6 +735,9 @@ export default {
|
||||
margin-left: 3em;
|
||||
}
|
||||
}
|
||||
.order::-webkit-scrollbar {
|
||||
display: none
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
/*
|
||||
* @Author: zhp
|
||||
* @Date: 2024-01-29 17:05:25
|
||||
* @LastEditTime: 2024-01-29 17:05:25
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
*/
|
||||
/**
|
||||
* 发起websocket请求函数
|
||||
* @param {string} url ws连接地址
|
||||
@@ -49,7 +42,7 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
|
||||
this.lockReconnect = true;
|
||||
this.wsCreateHandler && clearTimeout(this.wsCreateHandler);
|
||||
// 关闭心跳检查
|
||||
// heartCheck.stop();
|
||||
heartCheck.stop();
|
||||
}
|
||||
};
|
||||
const initWsEventHandle = () => {
|
||||
@@ -57,13 +50,13 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
|
||||
// 连接成功
|
||||
this.wsObj.onopen = (event) => {
|
||||
onWsOpen(event);
|
||||
// heartCheck.start();
|
||||
heartCheck.start();
|
||||
};
|
||||
|
||||
// 监听服务器端返回的信息
|
||||
this.wsObj.onmessage = (event) => {
|
||||
onWsMessage(event);
|
||||
// heartCheck.start();
|
||||
heartCheck.start();
|
||||
};
|
||||
|
||||
this.wsObj.onclose = (event) => {
|
||||
@@ -130,7 +123,7 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
|
||||
if (this.lockReconnect) {
|
||||
return;
|
||||
}
|
||||
writeToScreen("3秒后重连");
|
||||
writeToScreen("5秒后重连");
|
||||
this.lockReconnect = true;
|
||||
// 没连接上会一直重连,设置延迟避免请求过多
|
||||
this.wsCreateHandler && clearTimeout(this.wsCreateHandler);
|
||||
@@ -139,10 +132,40 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
|
||||
this.createWebSoket();
|
||||
this.lockReconnect = false;
|
||||
writeToScreen("重连完成");
|
||||
}, 3000);
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
// 心跳检查(看看websocket是否还在正常连接中)
|
||||
// 心跳检查(看看websocket是否还在正常连接中,不需要服务端返回,单向的)
|
||||
let _this = this
|
||||
let heartCheck = {
|
||||
timeout: 55000,
|
||||
timeoutObj: null,
|
||||
// 重启
|
||||
reset() {
|
||||
clearTimeout(this.timeoutObj);
|
||||
this.start();
|
||||
},
|
||||
// 停止
|
||||
stop() {
|
||||
clearTimeout(this.timeoutObj);
|
||||
},
|
||||
// 开启定时器
|
||||
start() {
|
||||
this.timeoutObj && clearTimeout(this.timeoutObj);
|
||||
this.timeoutObj = setTimeout(() => {
|
||||
writeToScreen("心跳检查,发送ping到后台");
|
||||
try {
|
||||
const datas = { ping: true };
|
||||
_this.wsObj.send(JSON.stringify(datas));
|
||||
} catch (err) {
|
||||
writeToScreen("发送ping异常");
|
||||
}
|
||||
}, this.timeout);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// 心跳检查(看看websocket是否还在正常连接中,和服务端通信,双向的)
|
||||
// let heartCheck = {
|
||||
// timeout: 15000,
|
||||
// timeoutObj: null,
|
||||
@@ -167,7 +190,7 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
|
||||
// writeToScreen("心跳检查,发送ping到后台");
|
||||
// try {
|
||||
// const datas = { ping: true };
|
||||
// this.wsObj.send(JSON.stringify(datas));
|
||||
// _this.wsObj.send(JSON.stringify(datas));
|
||||
// } catch (err) {
|
||||
// writeToScreen("发送ping异常");
|
||||
// }
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="定义编号" align="center" prop="id" width="400" />
|
||||
<el-table-column label="定义名称" align="center" prop="name" width="100">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" @click="handleBpmnDetail(scope.row)">
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="定义分类" align="center" prop="category" width="100">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="表单信息" align="center" prop="formType" width="200">
|
||||
<template v-slot="scope">
|
||||
<el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
|
||||
<span>{{ scope.row.formName }}</span>
|
||||
</el-button>
|
||||
<el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
|
||||
<span>{{ scope.row.formCustomCreatePath }}</span>
|
||||
</el-button>
|
||||
<label v-else>暂无表单</label>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
|
||||
<el-tag size="medium" type="warning" v-else>未部署</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="version" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
|
||||
<el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.deploymentTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="定义描述" align="center" prop="description" width="300" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleAssignRule(scope.row)"
|
||||
v-hasPermi="['bpm:task-assign-rule:update']">分配规则</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 流程表单配置详情 -->
|
||||
<el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
|
||||
<parser :key="new Date().getTime()" :form-conf="detailForm" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 流程模型图的预览 -->
|
||||
<el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
|
||||
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- ========== 流程任务分配规则 ========== -->
|
||||
<taskAssignRuleDialog ref="taskAssignRuleDialog" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getProcessDefinitionBpmnXML, getProcessDefinitionPage} from "@/api/bpm/definition";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {decodeFields} from "@/utils/formGenerator";
|
||||
import Parser from '@/components/parser/Parser'
|
||||
import taskAssignRuleDialog from "../taskAssignRule/taskAssignRuleDialog";
|
||||
|
||||
export default {
|
||||
name: "BpmProcessDefinition",
|
||||
components: {
|
||||
Parser,
|
||||
taskAssignRuleDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
|
||||
// 流程表单详情
|
||||
detailOpen: false,
|
||||
detailForm: {
|
||||
fields: []
|
||||
},
|
||||
|
||||
// BPMN 数据
|
||||
showBpmnOpen: false,
|
||||
bpmnXML: null,
|
||||
bpmnControlForm: {
|
||||
prefix: "flowable"
|
||||
},
|
||||
|
||||
// 数据字典
|
||||
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const key = this.$route.query && this.$route.query.key
|
||||
if (key) {
|
||||
this.queryParams['key'] = key
|
||||
}
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询流程定义列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getProcessDefinitionPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
/** 流程表单的详情按钮操作 */
|
||||
handleFormDetail(row) {
|
||||
// 流程表单
|
||||
if (row.formId) {
|
||||
// 设置值
|
||||
this.detailForm = {
|
||||
...JSON.parse(row.formConf),
|
||||
fields: decodeFields(row.formFields)
|
||||
}
|
||||
// 弹窗打开
|
||||
this.detailOpen = true
|
||||
// 业务表单
|
||||
} else if (row.formCustomCreatePath) {
|
||||
this.$router.push({ path: row.formCustomCreatePath});
|
||||
}
|
||||
},
|
||||
/** 流程图的详情按钮操作 */
|
||||
handleBpmnDetail(row) {
|
||||
getProcessDefinitionBpmnXML(row.id).then(response => {
|
||||
this.bpmnXML = response.data
|
||||
// 弹窗打开
|
||||
this.showBpmnOpen = true
|
||||
})
|
||||
},
|
||||
/** 处理任务分配规则列表的按钮操作 */
|
||||
handleAssignRule(row) {
|
||||
this.$refs['taskAssignRuleDialog'].initProcessDefinition(row.id);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.my-process-designer {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
</style>
|
||||
@@ -1,567 +0,0 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="left-board">
|
||||
<div class="logo-wrapper">
|
||||
<div class="logo">流程表单</div>
|
||||
</div>
|
||||
<el-scrollbar class="left-scrollbar">
|
||||
<!-- 左边:表单项 -->
|
||||
<div class="components-list">
|
||||
<div v-for="(item, listIndex) in leftComponents" :key="listIndex">
|
||||
<div class="components-title">
|
||||
<svg-icon icon-class="component" />
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<draggable
|
||||
class="components-draggable"
|
||||
:list="item.list"
|
||||
:group="{ name: 'componentsGroup', pull: 'clone', put: false }"
|
||||
:clone="cloneComponent"
|
||||
draggable=".components-item"
|
||||
:sort="false"
|
||||
@end="onEnd"
|
||||
>
|
||||
<div
|
||||
v-for="(element, index) in item.list"
|
||||
:key="index"
|
||||
class="components-item"
|
||||
@click="addComponent(element)"
|
||||
>
|
||||
<div class="components-body">
|
||||
<svg-icon :icon-class="element.__config__.tagIcon" />
|
||||
{{ element.__config__.label }}
|
||||
</div>
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
|
||||
<!-- 左边:动态表单 -->
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="表单名" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入表单名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
|
||||
<div class="center-board">
|
||||
<div class="action-bar">
|
||||
<el-button icon="el-icon-check" type="text" @click="save">保存</el-button>
|
||||
<!-- <el-button icon="el-icon-video-play" type="text" @click="run">-->
|
||||
<!-- 运行-->
|
||||
<!-- </el-button>-->
|
||||
<el-button icon="el-icon-view" type="text" @click="showJson">
|
||||
查看json
|
||||
</el-button>
|
||||
<!-- <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="(item, index) in drawingList"
|
||||
:key="item.renderKey"
|
||||
:drawing-list="drawingList"
|
||||
:current-item="item"
|
||||
: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"
|
||||
@fetch-data="fetchData"
|
||||
/>
|
||||
|
||||
<!-- <form-drawer-->
|
||||
<!-- :visible.sync="drawerVisible"-->
|
||||
<!-- :form-data="formData"-->
|
||||
<!-- size="100%"-->
|
||||
<!-- :generate-conf="generateConf"-->
|
||||
<!-- />-->
|
||||
|
||||
<json-drawer
|
||||
size="60%"
|
||||
:visible.sync="jsonDrawerVisible"
|
||||
:json-str="JSON.stringify(formData)"
|
||||
@refresh="refreshJson"
|
||||
/>
|
||||
|
||||
<!-- <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 { debounce } from 'throttle-debounce'
|
||||
import { saveAs } from 'file-saver'
|
||||
import ClipboardJS from 'clipboard'
|
||||
import render from '@/components/render/render'
|
||||
import FormDrawer from '@/views/infra/build/FormDrawer'
|
||||
import JsonDrawer from '@/views/infra/build/JsonDrawer'
|
||||
import RightPanel from '@/views/infra/build/RightPanel'
|
||||
import {
|
||||
inputComponents, selectComponents, layoutComponents, formConf
|
||||
} from '@/components/generator/config'
|
||||
import {beautifierConf, titleCase, deepClone, isObjectObject} from '@/utils'
|
||||
import {
|
||||
makeUpHtml, vueTemplate, vueScript, cssStyle
|
||||
} from '@/components/generator/html'
|
||||
import { makeUpJs } from '@/components/generator/js'
|
||||
import { makeUpCss } from '@/components/generator/css'
|
||||
import drawingDefalut from '@/components/generator/drawingDefalut'
|
||||
import logo from '@/assets/logo/logo.png'
|
||||
import CodeTypeDialog from '@/views/infra/build/CodeTypeDialog'
|
||||
import DraggableItem from '@/views/infra/build/DraggableItem'
|
||||
import {
|
||||
getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
|
||||
} from '@/utils/db'
|
||||
import loadBeautifier from '@/utils/loadBeautifier'
|
||||
import {CommonStatusEnum} from "@/utils/constants";
|
||||
import {createForm, getForm, updateForm} from "@/api/bpm/form";
|
||||
import {decodeFields} from "@/utils/formGenerator";
|
||||
|
||||
let beautifier
|
||||
const emptyActiveData = { style: {}, autosize: {} }
|
||||
let oldActiveId
|
||||
let tempActiveData
|
||||
const drawingListInDB = getDrawingList()
|
||||
const formConfInDB = getFormConf()
|
||||
const idGlobal = getIdGlobal()
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
render,
|
||||
FormDrawer,
|
||||
JsonDrawer,
|
||||
RightPanel,
|
||||
CodeTypeDialog,
|
||||
DraggableItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logo,
|
||||
idGlobal,
|
||||
formConf,
|
||||
inputComponents,
|
||||
selectComponents,
|
||||
layoutComponents,
|
||||
labelWidth: 100,
|
||||
// drawingList: drawingDefalut,
|
||||
drawingData: {}, // 生成后的表单数据
|
||||
activeId: drawingDefalut[0].__config__.formId,
|
||||
|
||||
drawingList: [], // 表单项的数组
|
||||
// activeId: undefined,
|
||||
// activeData: {},
|
||||
|
||||
drawerVisible: false,
|
||||
formData: {},
|
||||
dialogVisible: false,
|
||||
jsonDrawerVisible: false,
|
||||
generateConf: null,
|
||||
showFileName: false,
|
||||
activeData: drawingDefalut[0], // 右边编辑器激活的表单项
|
||||
saveDrawingListDebounce: debounce(340, saveDrawingList),
|
||||
saveIdGlobalDebounce: debounce(340, saveIdGlobal),
|
||||
leftComponents: [
|
||||
{
|
||||
title: '输入型组件',
|
||||
list: inputComponents
|
||||
},
|
||||
{
|
||||
title: '选择型组件',
|
||||
list: selectComponents
|
||||
},
|
||||
{
|
||||
title: '布局型组件',
|
||||
list: layoutComponents
|
||||
}
|
||||
],
|
||||
|
||||
// 表单参数
|
||||
form: {
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "表单名不能为空", trigger: "blur" }],
|
||||
status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
// eslint-disable-next-line func-names
|
||||
'activeData.__config__.label': function (val, oldVal) {
|
||||
if (
|
||||
this.activeData.placeholder === undefined
|
||||
|| !this.activeData.__config__.tag
|
||||
|| oldActiveId !== this.activeId
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
|
||||
},
|
||||
activeId: {
|
||||
handler(val) {
|
||||
oldActiveId = val
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
drawingList: {
|
||||
handler(val) {
|
||||
this.saveDrawingListDebounce(val)
|
||||
if (val.length === 0) this.idGlobal = 100
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
idGlobal: {
|
||||
handler(val) {
|
||||
this.saveIdGlobalDebounce(val)
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 【add by 芋道源码】不读缓存
|
||||
// if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {
|
||||
// this.drawingList = drawingListInDB
|
||||
// } else {
|
||||
// this.drawingList = drawingDefalut
|
||||
// }
|
||||
// this.activeFormItem(this.drawingList[0])
|
||||
// if (formConfInDB) {
|
||||
// this.formConf = formConfInDB
|
||||
// }
|
||||
loadBeautifier(btf => {
|
||||
beautifier = btf
|
||||
})
|
||||
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('代码复制失败')
|
||||
})
|
||||
},
|
||||
created() {
|
||||
// 读取表单配置
|
||||
const formId = this.$route.query && this.$route.query.formId
|
||||
if (formId) {
|
||||
getForm(formId).then(response => {
|
||||
const data = response.data
|
||||
this.form = {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
status: data.status,
|
||||
remark: data.remark
|
||||
}
|
||||
this.formConf = JSON.parse(data.conf)
|
||||
this.drawingList = decodeFields(data.fields)
|
||||
// 设置激活的表单项
|
||||
this.activeData = this.drawingList[0]
|
||||
this.activeId = this.activeData.__config__.formId
|
||||
// 设置 idGlobal,避免重复
|
||||
this.idGlobal += this.drawingList.length
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setObjectValueReduce(obj, strKeys, data) {
|
||||
const arr = strKeys.split('.')
|
||||
arr.reduce((pre, item, i) => {
|
||||
if (arr.length === i + 1) {
|
||||
pre[item] = data
|
||||
} else if (!isObjectObject(pre[item])) {
|
||||
pre[item] = {}
|
||||
}
|
||||
return pre[item]
|
||||
}, obj)
|
||||
},
|
||||
setRespData(component, resp) {
|
||||
const { dataPath, renderKey, dataConsumer } = component.__config__
|
||||
if (!dataPath || !dataConsumer) return
|
||||
const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)
|
||||
|
||||
// 将请求回来的数据,赋值到指定属性。
|
||||
// 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';
|
||||
// 此时赋值代码可写成 component[dataConsumer] = respData;
|
||||
// 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce
|
||||
this.setObjectValueReduce(component, dataConsumer, respData)
|
||||
const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
|
||||
if (i > -1) this.$set(this.drawingList, i, component)
|
||||
},
|
||||
fetchData(component) {
|
||||
const { dataType, method, url } = component.__config__
|
||||
if (dataType === 'dynamic' && method && url) {
|
||||
this.setLoading(component, true)
|
||||
this.$axios({
|
||||
method,
|
||||
url
|
||||
}).then(resp => {
|
||||
this.setLoading(component, false)
|
||||
this.setRespData(component, resp.data)
|
||||
})
|
||||
}
|
||||
},
|
||||
setLoading(component, val) {
|
||||
const { directives } = component
|
||||
if (Array.isArray(directives)) {
|
||||
const t = directives.find(d => d.name === 'loading')
|
||||
if (t) t.value = val
|
||||
}
|
||||
},
|
||||
activeFormItem(currentItem) {
|
||||
this.activeData = currentItem
|
||||
this.activeId = currentItem.__config__.formId
|
||||
},
|
||||
onEnd(obj) {
|
||||
if (obj.from !== obj.to) {
|
||||
this.fetchData(tempActiveData)
|
||||
this.activeData = tempActiveData
|
||||
this.activeId = this.idGlobal
|
||||
}
|
||||
},
|
||||
addComponent(item) {
|
||||
const clone = this.cloneComponent(item)
|
||||
this.fetchData(clone)
|
||||
this.drawingList.push(clone)
|
||||
this.activeFormItem(clone)
|
||||
},
|
||||
cloneComponent(origin) {
|
||||
const clone = deepClone(origin)
|
||||
const config = clone.__config__
|
||||
config.span = this.formConf.span // 生成代码时,会根据span做精简判断
|
||||
this.createIdAndKey(clone)
|
||||
clone.placeholder !== undefined && (clone.placeholder += config.label)
|
||||
tempActiveData = clone
|
||||
return tempActiveData
|
||||
},
|
||||
createIdAndKey(item) {
|
||||
const config = item.__config__
|
||||
config.formId = ++this.idGlobal
|
||||
config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
|
||||
if (config.layout === 'colFormItem') {
|
||||
item.__vModel__ = `field${this.idGlobal}`
|
||||
} else if (config.layout === 'rowFormItem') {
|
||||
config.componentName = `row${this.idGlobal}`
|
||||
!Array.isArray(config.children) && (config.children = [])
|
||||
delete config.label // rowFormItem无需配置label属性
|
||||
}
|
||||
if (Array.isArray(config.children)) {
|
||||
config.children = config.children.map(childItem => this.createIdAndKey(childItem))
|
||||
}
|
||||
return item
|
||||
},
|
||||
// 获得表单数据
|
||||
AssembleFormData() {
|
||||
this.formData = {
|
||||
fields: deepClone(this.drawingList),
|
||||
...this.formConf
|
||||
}
|
||||
},
|
||||
save() {
|
||||
// this.AssembleFormData()
|
||||
// console.log(this.formData)
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
const form = {
|
||||
conf: JSON.stringify(this.formConf), // 表单配置
|
||||
fields: this.encodeFields(), // 表单项的数组
|
||||
...this.form // 表单名等
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateForm(form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.close()
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createForm(form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.close()
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 关闭按钮 */
|
||||
close() {
|
||||
this.$tab.closeOpenPage({ path: "/bpm/manager/form" });
|
||||
},
|
||||
encodeFields() {
|
||||
const fields = []
|
||||
this.drawingList.forEach(item => {
|
||||
fields.push(JSON.stringify(item))
|
||||
})
|
||||
return fields
|
||||
},
|
||||
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' })
|
||||
saveAs(blob, data.fileName)
|
||||
},
|
||||
execCopy(data) {
|
||||
document.getElementById('copyNode').click()
|
||||
},
|
||||
empty() {
|
||||
this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
|
||||
() => {
|
||||
this.drawingList = []
|
||||
this.idGlobal = 100
|
||||
}
|
||||
)
|
||||
},
|
||||
drawingItemCopy(item, list) {
|
||||
let clone = deepClone(item)
|
||||
clone = this.createIdAndKey(clone)
|
||||
list.push(clone)
|
||||
this.activeFormItem(clone)
|
||||
},
|
||||
drawingItemDelete(index, list) {
|
||||
list.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)
|
||||
},
|
||||
showJson() {
|
||||
this.AssembleFormData()
|
||||
this.jsonDrawerVisible = true
|
||||
},
|
||||
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)
|
||||
const config = newTag.__config__
|
||||
newTag.__vModel__ = this.activeData.__vModel__
|
||||
config.formId = this.activeId
|
||||
config.span = this.activeData.__config__.span
|
||||
this.activeData.__config__.tag = config.tag
|
||||
this.activeData.__config__.tagIcon = config.tagIcon
|
||||
this.activeData.__config__.document = config.document
|
||||
if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
|
||||
config.defaultValue = this.activeData.__config__.defaultValue
|
||||
}
|
||||
Object.keys(newTag).forEach(key => {
|
||||
if (this.activeData[key] !== undefined) {
|
||||
newTag[key] = this.activeData[key]
|
||||
}
|
||||
})
|
||||
this.activeData = newTag
|
||||
this.updateDrawingList(newTag, this.drawingList)
|
||||
},
|
||||
updateDrawingList(newTag, list) {
|
||||
const index = list.findIndex(item => item.__config__.formId === this.activeId)
|
||||
if (index > -1) {
|
||||
list.splice(index, 1, newTag)
|
||||
} else {
|
||||
list.forEach(item => {
|
||||
if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
|
||||
})
|
||||
}
|
||||
},
|
||||
refreshJson(data) {
|
||||
this.drawingList = deepClone(data.fields)
|
||||
delete data.fields
|
||||
this.formConf = data
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
@import '@/styles/home';
|
||||
</style>
|
||||
@@ -1,161 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="表单名" prop="name">
|
||||
<el-input v-model="queryParams.name" 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 :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['bpm:form:create']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="表单名" align="center" prop="name" />
|
||||
<el-table-column label="开启状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)"
|
||||
v-hasPermi="['bpm:form:query']">详情</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['bpm:form:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['bpm:form:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!--表单配置详情-->
|
||||
<el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
|
||||
<div class="test-form">
|
||||
<parser :key="new Date().getTime()" :form-conf="detailForm" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {deleteForm, getForm, getFormPage} from "@/api/bpm/form";
|
||||
import Parser from '@/components/parser/Parser'
|
||||
import {decodeFields} from "@/utils/formGenerator";
|
||||
|
||||
export default {
|
||||
name: "BpmForm",
|
||||
components: {
|
||||
Parser
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 工作流的列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
},
|
||||
// 表单详情
|
||||
detailOpen: false,
|
||||
detailForm: {
|
||||
fields: []
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getFormPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 详情按钮操作 */
|
||||
handleDetail(row) {
|
||||
getForm(row.id).then(response => {
|
||||
// 设置值
|
||||
const data = response.data
|
||||
this.detailForm = {
|
||||
...JSON.parse(data.conf),
|
||||
fields: decodeFields(data.fields)
|
||||
}
|
||||
// 弹窗打开
|
||||
this.detailOpen = true
|
||||
})
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.$router.push({
|
||||
name: "BpmFormEditor"
|
||||
});
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.$router.push({
|
||||
name: "BpmFormEditor",
|
||||
query:{
|
||||
formId: row.id
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除工作表单的编号为"' + id + '"的数据项?').then(function() {
|
||||
return deleteForm(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,246 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="组名" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入组名" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['bpm:user-group:create']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="组名" align="center" prop="name" />
|
||||
<el-table-column label="描述" align="center" prop="description" />
|
||||
<el-table-column label="成员" align="center">
|
||||
<template v-slot="scope">
|
||||
<span v-for="userId in scope.row.memberUserIds">
|
||||
{{ getUserNickname(userId) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['bpm:user-group:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['bpm:user-group:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="组名" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入组名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="form.description" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="成员" prop="memberUserIds">
|
||||
<el-select v-model="form.memberUserIds" multiple placeholder="请选择成员">
|
||||
<el-option v-for="user in users" :key="parseInt(user.id)" :label="user.nickname" :value="parseInt(user.id)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createUserGroup, updateUserGroup, deleteUserGroup, getUserGroup, getUserGroupPage } from "@/api/bpm/userGroup";
|
||||
import {CommonStatusEnum} from "@/utils/constants";
|
||||
import {listSimpleUsers} from "@/api/system/user";
|
||||
|
||||
export default {
|
||||
name: "BpmUserGroup",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 用户组列表
|
||||
list: [],
|
||||
// 用户列表
|
||||
users: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
createTime: []
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "组名不能为空", trigger: "blur" }],
|
||||
description: [{ required: true, message: "描述不能为空", trigger: "blur" }],
|
||||
memberUserIds: [{ required: true, message: "成员不能为空", trigger: "change" }],
|
||||
status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 获得用户列表
|
||||
listSimpleUsers().then(response => {
|
||||
this.users = response.data;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getUserGroupPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
memberUserIds: [],
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加用户组";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getUserGroup(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改用户组";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateUserGroup(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createUserGroup(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除用户组编号为"' + id + '"的数据项?').then(function() {
|
||||
return deleteUserGroup(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
getUserNickname(userId) {
|
||||
for (const user of this.users) {
|
||||
if (user.id === userId) {
|
||||
return user.nickname;
|
||||
}
|
||||
}
|
||||
return '未知(' + userId + ')';
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,548 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="流程标识" prop="key">
|
||||
<el-input v-model="queryParams.key" placeholder="请输入流程标识" clearable style="width: 240px;"
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入流程名称" clearable style="width: 240px;"
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程分类" prop="category">
|
||||
<el-select v-model="queryParams.category" placeholder="流程分类" clearable style="width: 240px">
|
||||
<el-option v-for="dict in categoryDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['bpm:model:create']">新建流程</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" icon="el-icon-upload2" size="mini" @click="handleImport"
|
||||
v-hasPermi="['bpm:model:import']">导入流程</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="流程标识" align="center" prop="key" />
|
||||
<el-table-column label="流程名称" align="center" prop="name" width="200">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" @click="handleBpmnDetail(scope.row)">
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流程分类" align="center" prop="category" width="100">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="表单信息" align="center" prop="formType" width="200">
|
||||
<template v-slot="scope">
|
||||
<el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
|
||||
<span>{{ scope.row.formName }}</span>
|
||||
</el-button>
|
||||
<el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
|
||||
<span>{{ scope.row.formCustomCreatePath }}</span>
|
||||
</el-button>
|
||||
<label v-else>暂无表单</label>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最新部署的流程定义" align="center">
|
||||
<el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-tag size="medium" v-if="scope.row.processDefinition">v{{ scope.row.processDefinition.version }}</el-tag>
|
||||
<el-tag size="medium" type="warning" v-else>未部署</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="激活状态" align="center" prop="processDefinition.version" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-switch v-if="scope.row.processDefinition" v-model="scope.row.processDefinition.suspensionState"
|
||||
:active-value="1" :inactive-value="2" @change="handleChangeState(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span v-if="scope.row.processDefinition">{{ parseTime(scope.row.processDefinition.deploymentTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="450" fixed="right">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['bpm:model:update']">修改流程</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-setting" @click="handleDesign(scope.row)"
|
||||
v-hasPermi="['bpm:model:update']">设计流程</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleAssignRule(scope.row)"
|
||||
v-hasPermi="['bpm:task-assign-rule:query']">分配规则</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-thumb" @click="handleDeploy(scope.row)"
|
||||
v-hasPermi="['bpm:model:deploy']">发布流程</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-ice-cream-round" @click="handleDefinitionList(scope.row)"
|
||||
v-hasPermi="['bpm:process-definition:query']">流程定义</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['bpm:model:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 流程表单配置详情 -->
|
||||
<el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
|
||||
<parser :key="new Date().getTime()" :form-conf="detailForm" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 流程模型图的预览 -->
|
||||
<el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
|
||||
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="110px">
|
||||
<el-form-item label="流程标识" prop="key">
|
||||
<el-input v-model="form.key" placeholder="请输入流标标识" style="width: 330px;" :disabled="!!form.id" />
|
||||
<el-tooltip v-if="!form.id" class="item" effect="light" content="新建后,流程标识不可修改!" placement="top">
|
||||
<i style="padding-left: 5px;" class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
<el-tooltip v-else class="item" effect="light" content="流程标识不可修改!" placement="top">
|
||||
<i style="padding-left: 5px;" class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入流程名称" :disabled="!!form.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.id" label="流程分类" prop="category">
|
||||
<el-select v-model="form.category" placeholder="请选择流程分类" clearable style="width: 100%">
|
||||
<el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程描述" prop="description">
|
||||
<el-input type="textarea" v-model="form.description" clearable />
|
||||
</el-form-item>
|
||||
<div v-if="form.id">
|
||||
<el-form-item label="表单类型" prop="formType">
|
||||
<el-radio-group v-model="form.formType">
|
||||
<el-radio v-for="dict in modelFormTypeDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{dict.label}}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.formType === 10" label="流程表单" prop="formId">
|
||||
<el-select v-model="form.formId" clearable style="width: 100%">
|
||||
<el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.formType === 20" label="表单提交路由" prop="formCustomCreatePath" >
|
||||
<el-input v-model="form.formCustomCreatePath" placeholder="请输入表单提交路由" style="width: 330px;" />
|
||||
<el-tooltip class="item" effect="light" content="自定义表单的提交路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/create" placement="top">
|
||||
<i style="padding-left: 5px;" class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.formType === 20" label="表单查看路由" prop="formCustomViewPath">
|
||||
<el-input v-model="form.formCustomViewPath" placeholder="请输入表单查看路由" style="width: 330px;" />
|
||||
<el-tooltip class="item" effect="light" content="自定义表单的查看路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/view" placement="top">
|
||||
<i style="padding-left: 5px;" class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 用户导入对话框 -->
|
||||
<el-dialog title="导入流程" :visible.sync="upload.open" width="400px" append-to-body>
|
||||
<el-upload ref="upload" :limit="1" accept=".bpmn, .xml" :headers="upload.headers" :action="upload.url"
|
||||
:disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
|
||||
:auto-upload="false" name="bpmnFile" :data="upload.form" drag>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或
|
||||
<em>点击上传</em>
|
||||
</div>
|
||||
<div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“bpm”或“xml”格式文件!</div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<el-form ref="uploadForm" size="mini" label-width="90px" :model="upload.form" :rules="upload.rules" @submit.native.prevent>
|
||||
<el-form-item label="流程标识" prop="key">
|
||||
<el-input v-model="upload.form.key" placeholder="请输入流标标识" style="width: 250px;" />
|
||||
<el-tooltip class="item" effect="light" content="新建后,流程标识不可修改!" placement="top">
|
||||
<i style="padding-left: 5px;" class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程名称" prop="name">
|
||||
<el-input v-model="upload.form.name" placeholder="请输入流程名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程描述" prop="description">
|
||||
<el-input type="textarea" v-model="upload.form.description" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="uploadClose">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ========== 流程任务分配规则 ========== -->
|
||||
<taskAssignRuleDialog ref="taskAssignRuleDialog" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
deleteModel,
|
||||
deployModel,
|
||||
getModelPage,
|
||||
getModel,
|
||||
updateModelState,
|
||||
createModel,
|
||||
updateModel
|
||||
} from "@/api/bpm/model";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {getForm, getSimpleForms} from "@/api/bpm/form";
|
||||
import {decodeFields} from "@/utils/formGenerator";
|
||||
import Parser from '@/components/parser/Parser'
|
||||
import {getBaseHeader} from "@/utils/request";
|
||||
import taskAssignRuleDialog from "../taskAssignRule/taskAssignRuleDialog";
|
||||
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
|
||||
export default {
|
||||
name: "BpmModel",
|
||||
components: {
|
||||
Parser,
|
||||
Treeselect,
|
||||
taskAssignRuleDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
|
||||
// BPMN 数据
|
||||
showBpmnOpen: false,
|
||||
bpmnXML: null,
|
||||
bpmnControlForm: {
|
||||
prefix: "flowable"
|
||||
},
|
||||
|
||||
// 流程表单详情
|
||||
detailOpen: false,
|
||||
detailForm: {
|
||||
fields: []
|
||||
},
|
||||
|
||||
// 流程表单
|
||||
title: "",
|
||||
open: false,
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
|
||||
name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
|
||||
formType: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
|
||||
formId: [{ required: true, message: "业务表单不能为空", trigger: "blur" }],
|
||||
category: [{ required: true, message: "流程分类不能为空", trigger: "blur" }],
|
||||
formCustomCreatePath: [{ required: true, message: "表单提交路由不能为空", trigger: "blur" }],
|
||||
formCustomViewPath: [{ required: true, message: "表单查看路由不能为空", trigger: "blur" }],
|
||||
},
|
||||
|
||||
// 流程导入参数
|
||||
upload: {
|
||||
// 是否显示弹出层(用户导入)
|
||||
open: false,
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 设置上传的请求头部
|
||||
headers: getBaseHeader(),
|
||||
// 上传的地址
|
||||
url: process.env.VUE_APP_BASE_API + '/admin-api' + "/bpm/model/import",
|
||||
// 表单
|
||||
form: {},
|
||||
// 校验规则
|
||||
rules: {
|
||||
key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
|
||||
name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
|
||||
},
|
||||
},
|
||||
// 流程表单的下拉框的数据
|
||||
forms: [],
|
||||
|
||||
// 数据字典
|
||||
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
|
||||
modelFormTypeDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_FORM_TYPE),
|
||||
taskAssignRuleDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 获得流程表单的下拉框的数据
|
||||
getSimpleForms().then(response => {
|
||||
this.forms = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询流程模型列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getModelPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
key: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
category: undefined,
|
||||
formType: undefined,
|
||||
formId: undefined,
|
||||
formCustomCreatePath: undefined,
|
||||
formCustomViewPath: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.title = "新建模型";
|
||||
this.open = true;
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
this.title = "修改模型";
|
||||
this.open = true;
|
||||
// 设置 form
|
||||
this.form = {
|
||||
...row
|
||||
};
|
||||
// 触发一次校验
|
||||
// this.$refs["form"].validate();
|
||||
},
|
||||
/** 设计按钮操作 */
|
||||
handleDesign(row) {
|
||||
this.$router.push({
|
||||
name: "BpmModelEditor",
|
||||
query:{
|
||||
modelId: row.id
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 更新
|
||||
if (this.form.id) {
|
||||
updateModel({
|
||||
...this.form,
|
||||
formId: this.form.formType === 10 ? this.form.formId : undefined,
|
||||
formCustomCreatePath: this.form.formType === 20 ? this.form.formCustomCreatePath : undefined,
|
||||
formCustomViewPath: this.form.formType === 20 ? this.form.formCustomViewPath : undefined,
|
||||
}).then(response => {
|
||||
this.$modal.msgSuccess("修改模型成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 创建
|
||||
createModel(this.form).then(response => {
|
||||
this.open = false;
|
||||
this.getList();
|
||||
this.$alert('<strong>新建模型成功!</strong>后续需要执行如下 4 个步骤:' +
|
||||
'<div>1. 点击【修改流程】按钮,配置流程的分类、表单信息</div>' +
|
||||
'<div>2. 点击【设计流程】按钮,绘制流程图</div>' +
|
||||
'<div>3. 点击【分配规则】按钮,设置每个用户任务的审批人</div>' +
|
||||
'<div>4. 点击【发布流程】按钮,完成流程的最终发布</div>' +
|
||||
'另外,每次流程修改后,都需要点击【发布流程】按钮,才能正式生效!!!',
|
||||
'重要提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
type: 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const that = this;
|
||||
this.$modal.confirm('是否删除该流程!!').then(function() {
|
||||
deleteModel(row.id).then(response => {
|
||||
that.getList();
|
||||
that.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 部署按钮操作 */
|
||||
handleDeploy(row) {
|
||||
const that = this;
|
||||
this.$modal.confirm('是否部署该流程!!').then(function() {
|
||||
deployModel(row.id).then(response => {
|
||||
that.getList();
|
||||
that.$modal.msgSuccess("部署成功");
|
||||
})
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 流程表单的详情按钮操作 */
|
||||
handleFormDetail(row) {
|
||||
// 流程表单
|
||||
if (row.formId) {
|
||||
getForm(row.formId).then(response => {
|
||||
// 设置值
|
||||
const data = response.data
|
||||
this.detailForm = {
|
||||
...JSON.parse(data.conf),
|
||||
fields: decodeFields(data.fields)
|
||||
}
|
||||
// 弹窗打开
|
||||
this.detailOpen = true
|
||||
})
|
||||
// 业务表单
|
||||
} else if (row.formCustomCreatePath) {
|
||||
this.$router.push({ path: row.formCustomCreatePath});
|
||||
}
|
||||
},
|
||||
/** 流程图的详情按钮操作 */
|
||||
handleBpmnDetail(row) {
|
||||
getModel(row.id).then(response => {
|
||||
this.bpmnXML = response.data.bpmnXml
|
||||
// 弹窗打开
|
||||
this.showBpmnOpen = true
|
||||
})
|
||||
},
|
||||
/** 跳转流程定义的列表 */
|
||||
handleDefinitionList(row) {
|
||||
this.$router.push({
|
||||
name: "BpmProcessDefinition",
|
||||
query:{
|
||||
key: row.key
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 更新状态操作 */
|
||||
handleChangeState(row) {
|
||||
const id = row.id;
|
||||
let state = row.processDefinition.suspensionState;
|
||||
let statusState = state === 1 ? '激活' : '挂起';
|
||||
this.$modal.confirm('是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?').then(function() {
|
||||
return updateModelState(id, state);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess(statusState + "成功");
|
||||
}).catch(() => {
|
||||
// 取消后,进行恢复按钮
|
||||
row.processDefinition.suspensionState = (state === 1 ? 2 : 1);
|
||||
});
|
||||
},
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
this.upload.open = true;
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true;
|
||||
},
|
||||
// 文件上传成功处理
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
if (response.code !== 0) {
|
||||
this.$modal.msgError(response.msg)
|
||||
return;
|
||||
}
|
||||
// 重置表单
|
||||
this.uploadClose();
|
||||
// 提示,并刷新
|
||||
this.$modal.msgSuccess("导入流程成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】");
|
||||
this.getList();
|
||||
},
|
||||
uploadClose() {
|
||||
// 关闭弹窗
|
||||
this.upload.open = false;
|
||||
// 重置上传状态和文件
|
||||
this.upload.isUploading = false;
|
||||
this.$refs.upload.clearFiles();
|
||||
// 重置表单
|
||||
this.upload.form = {};
|
||||
this.resetForm("uploadForm");
|
||||
},
|
||||
/** 提交上传文件 */
|
||||
submitFileForm() {
|
||||
this.$refs["uploadForm"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
this.$refs.upload.submit();
|
||||
})
|
||||
},
|
||||
/** 处理任务分配规则列表的按钮操作 */
|
||||
handleAssignRule(row) {
|
||||
this.$refs['taskAssignRuleDialog'].initModel(row.id);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.my-process-designer {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
</style>
|
||||
@@ -1,170 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 流程设计器,负责绘制流程等 -->
|
||||
<my-process-designer v-if="xmlString !== undefined" :key="`designer-${reloadIndex}`" v-model="xmlString" v-bind="controlForm"
|
||||
keyboard ref="processDesigner" @init-finished="initModeler"
|
||||
@save="save"/>
|
||||
|
||||
<!-- 流程属性器,负责编辑每个流程节点的属性 -->
|
||||
<my-properties-panel :key="`penal-${reloadIndex}`" :bpmn-modeler="modeler" :prefix="controlForm.prefix" class="process-panel"
|
||||
:model="model" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import translations from "@/components/bpmnProcessDesigner/src/translations";
|
||||
// 自定义元素选中时的弹出菜单(修改 默认任务 为 用户任务)
|
||||
import CustomContentPadProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/content-pad";
|
||||
// 自定义左侧菜单(修改 默认任务 为 用户任务)
|
||||
import CustomPaletteProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/palette";
|
||||
// import xmlObj2json from "./utils/xml2json";
|
||||
import MyProcessPalette from "@/components/bpmnProcessDesigner/package/palette/ProcessPalette";
|
||||
import {createModel, getModel, updateModel} from "@/api/bpm/model";
|
||||
// 自定义侧边栏
|
||||
// import MyProcessPanel from "../package/process-panel/ProcessPanel";
|
||||
|
||||
export default {
|
||||
name: "BpmModelEditor",
|
||||
components: { MyProcessPalette },
|
||||
data() {
|
||||
return {
|
||||
xmlString: undefined, // BPMN XML
|
||||
modeler: null,
|
||||
reloadIndex: 0,
|
||||
controlDrawerVisible: false,
|
||||
translationsSelf: translations,
|
||||
controlForm: {
|
||||
simulation: true,
|
||||
labelEditing: false,
|
||||
labelVisible: false,
|
||||
prefix: "flowable",
|
||||
headerButtonSize: "mini",
|
||||
additionalModel: [CustomContentPadProvider, CustomPaletteProvider]
|
||||
},
|
||||
addis: {
|
||||
CustomContentPadProvider,
|
||||
CustomPaletteProvider
|
||||
},
|
||||
// 流程模型的信息
|
||||
model: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 如果 modelId 非空,说明是修改流程模型
|
||||
const modelId = this.$route.query && this.$route.query.modelId
|
||||
if (modelId) {
|
||||
getModel(modelId).then(response => {
|
||||
this.xmlString = response.data.bpmnXml
|
||||
this.model = {
|
||||
...response.data,
|
||||
bpmnXml: undefined, // 清空 bpmnXml 属性
|
||||
}
|
||||
// this.controlForm.processId = response.data.key
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initModeler(modeler) {
|
||||
setTimeout(() => {
|
||||
this.modeler = modeler;
|
||||
console.log(modeler);
|
||||
}, 10);
|
||||
},
|
||||
save(bpmnXml) {
|
||||
const data = {
|
||||
...this.model,
|
||||
bpmnXml: bpmnXml, // this.bpmnXml 只是初始化流程图,后续修改无法通过它获得
|
||||
}
|
||||
|
||||
// 修改的提交
|
||||
if (data.id) {
|
||||
updateModel(data).then(response => {
|
||||
this.$modal.msgSuccess("修改成功")
|
||||
// 跳转回去
|
||||
this.close()
|
||||
})
|
||||
return
|
||||
}
|
||||
// 添加的提交
|
||||
createModel(data).then(response => {
|
||||
this.$modal.msgSuccess("保存成功")
|
||||
// 跳转回去
|
||||
this.close()
|
||||
})
|
||||
},
|
||||
/** 关闭按钮 */
|
||||
close() {
|
||||
this.$tab.closeOpenPage({ path: "/bpm/manager/model" });
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
//body {
|
||||
// overflow: hidden;
|
||||
// margin: 0;
|
||||
// box-sizing: border-box;
|
||||
//}
|
||||
//.app {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// box-sizing: border-box;
|
||||
// display: inline-grid;
|
||||
// grid-template-columns: 100px auto max-content;
|
||||
//}
|
||||
.demo-control-bar {
|
||||
position: fixed;
|
||||
right: 8px;
|
||||
bottom: 8px;
|
||||
z-index: 1;
|
||||
.open-control-dialog {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
font-size: 32px;
|
||||
background: rgba(64, 158, 255, 1);
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 芋艿:去掉多余的 faq
|
||||
//.info-tip {
|
||||
// position: fixed;
|
||||
// top: 40px;
|
||||
// right: 500px;
|
||||
// z-index: 10;
|
||||
// color: #999999;
|
||||
//}
|
||||
|
||||
.control-form {
|
||||
.el-radio {
|
||||
width: 100%;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
.element-overlays {
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 4px;
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
.my-process-designer {
|
||||
height: calc(100vh - 84px);
|
||||
}
|
||||
.process-panel__container {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 55px;
|
||||
height: calc(100vh - 84px);
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,75 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<el-date-picker clearable size="small" v-model="form.startTime" type="date" value-format="timestamp" placeholder="选择开始时间" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="endTime">
|
||||
<el-date-picker clearable size="small" v-model="form.endTime" type="date" value-format="timestamp" placeholder="选择结束时间" />
|
||||
</el-form-item>
|
||||
<el-form-item label="请假类型" prop="type">
|
||||
<el-select v-model="form.type" placeholder="请选择">
|
||||
<el-option v-for="dict in typeDictData" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="原因" prop="reason">
|
||||
<el-col :span="10">
|
||||
<el-input type="textarea" :rows="3" v-model="form.reason" placeholder="请输入原因" />
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm">提 交</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createLeave} from "@/api/bpm/leave"
|
||||
import { getDictDatas, DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
export default {
|
||||
name: "BpmOALeaveCreate",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 表单参数
|
||||
form: {
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
type: undefined,
|
||||
reason: undefined,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
startTime: [{ required: true, message: "开始时间不能为空", trigger: "blur" }],
|
||||
endTime: [{ required: true, message: "结束时间不能为空", trigger: "blur" }],
|
||||
type: [{ required: true, message: "请假类型不能为空", trigger: "change" }],
|
||||
reason: [{ required: true, message: "请假原因不能为空", trigger: "change" }],
|
||||
},
|
||||
|
||||
typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加的提交
|
||||
createLeave(this.form).then(response => {
|
||||
this.$modal.msgSuccess("发起成功");
|
||||
this.$tab.closeOpenPage({ path: "/bpm/oa/leave" });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-form ref="form" :model="form" label-width="100px">
|
||||
<el-form-item label="开始时间:" prop="startTime"> {{parseTime(form.startTime, '{y}-{m}-{d}')}} </el-form-item>
|
||||
<el-form-item label="结束时间:" prop="endTime"> {{parseTime(form.endTime, '{y}-{m}-{d}')}} </el-form-item>
|
||||
<el-form-item label="请假类型:" prop="type">
|
||||
<dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="form.type"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="原因:" prop="reason"> {{ form.reason }}</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLeave} from "@/api/bpm/leave"
|
||||
import {getDictDatas, DICT_TYPE} from '@/utils/dict'
|
||||
export default {
|
||||
name: "BpmOALeaveDetail",
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
type: [String, Number],
|
||||
default: undefined
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
leaveId: undefined, // 请假编号
|
||||
// 表单参数
|
||||
form: {
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
type: undefined,
|
||||
reason: undefined,
|
||||
},
|
||||
|
||||
typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.leaveId = this.id || this.$route.query.id;
|
||||
if (!this.leaveId) {
|
||||
this.$message.error('未传递 id 参数,无法查看 OA 请假信息');
|
||||
return;
|
||||
}
|
||||
this.getDetail();
|
||||
},
|
||||
methods: {
|
||||
/** 获得请假信息 */
|
||||
getDetail() {
|
||||
getLeave(this.leaveId).then(response => {
|
||||
this.form = response.data;
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,173 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="请假类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择请假类型" clearable>
|
||||
<el-option v-for="dict in leaveTypeDictData" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="申请时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结果" prop="result">
|
||||
<el-select v-model="queryParams.result" placeholder="请选择流结果" clearable>
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="原因" prop="reason">
|
||||
<el-input v-model="queryParams.reason" placeholder="请输入原因" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini"
|
||||
v-hasPermi="['bpm:oa-leave:create']" @click="handleAdd">发起请假</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="申请编号" align="center" prop="id" />
|
||||
<el-table-column label="状态" align="center" prop="result">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间" align="center" prop="startTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.startTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="endTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.endTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请假类型" align="center" prop="type">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原因" align="center" prop="reason" />
|
||||
<el-table-column label="申请时间" align="center" prop="applyTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleCancel(scope.row)"
|
||||
v-hasPermi="['bpm:oa-leave:create']" v-if="scope.row.result === 1">取消请假</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)"
|
||||
v-hasPermi="['bpm:oa-leave:query']">详情</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleProcessDetail(scope.row)">审批进度</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLeavePage } from "@/api/bpm/leave"
|
||||
import { getDictDatas, DICT_TYPE } from '@/utils/dict'
|
||||
import {cancelProcessInstance} from "@/api/bpm/processInstance";
|
||||
|
||||
export default {
|
||||
name: "BpmOALeave",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 请假申请列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
result: null,
|
||||
type: null,
|
||||
reason: null,
|
||||
createTime: []
|
||||
},
|
||||
|
||||
leaveTypeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
|
||||
leaveResultData: getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getLeavePage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.$router.push({ name: "BpmOALeaveCreate"});
|
||||
},
|
||||
/** 详情按钮操作 */
|
||||
handleDetail(row) {
|
||||
this.$router.push({ name: "BpmOALeaveDetail", query: { id: row.id}});
|
||||
},
|
||||
/** 查看审批进度的操作 */
|
||||
handleProcessDetail(row) {
|
||||
this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.processInstanceId}});
|
||||
},
|
||||
/** 取消请假 */
|
||||
handleCancel(row) {
|
||||
const id = row.processInstanceId;
|
||||
this.$prompt('请输入取消原因?', "取消流程", {
|
||||
type: 'warning',
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
|
||||
inputErrorMessage: "取消原因不能为空",
|
||||
}).then(({ value }) => {
|
||||
return cancelProcessInstance(id, value);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("取消成功");
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,168 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 第一步,通过流程定义的列表,选择对应的流程 -->
|
||||
<div v-if="!selectProcessInstance">
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="流程名称" align="center" prop="name" width="200">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" @click="handleBpmnDetail(scope.row)">
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流程分类" align="center" prop="category" width="100">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流程描述" align="center" prop="description" width="300" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" size="small" icon="el-icon-plus" @click="handleSelect(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 第二步,填写表单,进行流程的提交 -->
|
||||
<div v-else>
|
||||
<el-card class="box-card" >
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="el-icon-document">申请信息【{{ selectProcessInstance.name }}】</span>
|
||||
<el-button style="float: right;" type="primary" @click="selectProcessInstance = undefined">选择其它流程</el-button>
|
||||
</div>
|
||||
<el-col :span="16" :offset="6">
|
||||
<div>
|
||||
<parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-card>
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="el-icon-picture-outline">流程图</span>
|
||||
</div>
|
||||
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {decodeFields} from "@/utils/formGenerator";
|
||||
import Parser from '@/components/parser/Parser'
|
||||
import {createProcessInstance} from "@/api/bpm/processInstance";
|
||||
|
||||
// 流程实例的发起
|
||||
export default {
|
||||
name: "ProcessInstanceCreate",
|
||||
components: {
|
||||
Parser
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 表格数据
|
||||
list: [],
|
||||
|
||||
// 流程表单详情
|
||||
detailForm: {
|
||||
fields: []
|
||||
},
|
||||
|
||||
// BPMN 数据
|
||||
bpmnXML: null,
|
||||
bpmnControlForm: {
|
||||
prefix: "flowable"
|
||||
},
|
||||
|
||||
// 流程表单
|
||||
selectProcessInstance: undefined, // 选择的流程实例
|
||||
|
||||
// 数据字典
|
||||
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询流程定义列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getProcessDefinitionList({
|
||||
suspensionState: 1
|
||||
}).then(response => {
|
||||
this.list = response.data
|
||||
this.loading = false
|
||||
}
|
||||
);
|
||||
},
|
||||
/** 处理选择流程的按钮操作 **/
|
||||
handleSelect(row) {
|
||||
// 设置选择的流程
|
||||
this.selectProcessInstance = row;
|
||||
|
||||
// 流程表单
|
||||
if (row.formId) {
|
||||
// 设置对应的表单
|
||||
this.detailForm = {
|
||||
...JSON.parse(row.formConf),
|
||||
fields: decodeFields(row.formFields)
|
||||
}
|
||||
|
||||
// 加载流程图
|
||||
getProcessDefinitionBpmnXML(row.id).then(response => {
|
||||
this.bpmnXML = response.data
|
||||
})
|
||||
} else if (row.formCustomCreatePath) {
|
||||
this.$router.push({ path: row.formCustomCreatePath});
|
||||
// 这里暂时无需加载流程图,因为跳出到另外个 Tab;
|
||||
}
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm(params) {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
// 设置表单禁用
|
||||
const conf = params.conf;
|
||||
conf.disabled = true; // 表单禁用
|
||||
conf.formBtns = false; // 按钮隐藏
|
||||
|
||||
// 提交表单,创建流程
|
||||
const variables = params.values;
|
||||
createProcessInstance({
|
||||
processDefinitionId: this.selectProcessInstance.id,
|
||||
variables: variables
|
||||
}).then(response => {
|
||||
this.$modal.msgSuccess("发起流程成功");
|
||||
// 关闭当前窗口
|
||||
this.$tab.closeOpenPage();
|
||||
this.$router.go(-1);
|
||||
}).catch(() => {
|
||||
conf.disabled = false; // 表单开启
|
||||
conf.formBtns = true; // 按钮展示
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.my-process-designer {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
.box-card {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,400 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 审批信息 -->
|
||||
<el-card class="box-card" v-loading="processInstanceLoading" v-for="(item, index) in runningTasks" :key="index">
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="el-icon-picture-outline">审批任务【{{ item.name }}】</span>
|
||||
</div>
|
||||
<el-col :span="16" :offset="6" >
|
||||
<el-form :ref="'form' + index" :model="auditForms[index]" :rules="auditRule" label-width="100px">
|
||||
<el-form-item label="流程名" v-if="processInstance && processInstance.name">
|
||||
{{ processInstance.name }}
|
||||
</el-form-item>
|
||||
<el-form-item label="流程发起人" v-if="processInstance && processInstance.startUser">
|
||||
{{ processInstance.startUser.nickname }}
|
||||
<el-tag type="info" size="mini">{{ processInstance.startUser.deptName }}</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="审批建议" prop="reason">
|
||||
<el-input type="textarea" v-model="auditForms[index].reason" placeholder="请输入审批建议" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;">
|
||||
<el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button>
|
||||
<el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button>
|
||||
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办</el-button>
|
||||
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button>
|
||||
<el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-card>
|
||||
<!-- 申请信息 -->
|
||||
<el-card class="box-card" v-loading="processInstanceLoading">
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="el-icon-document">申请信息【{{ processInstance.name }}】</span>
|
||||
</div>
|
||||
<el-col v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 10"
|
||||
:span="16" :offset="6">
|
||||
<div >
|
||||
<parser :key="new Date().getTime()" :form-conf="detailForm" />
|
||||
</div>
|
||||
</el-col>
|
||||
<div v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 20">
|
||||
<async-biz-form-component :id="this.processInstance.businessKey"></async-biz-form-component>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 审批记录 -->
|
||||
<el-card class="box-card" v-loading="tasksLoad">
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="el-icon-picture-outline">审批记录</span>
|
||||
</div>
|
||||
<el-col :span="16" :offset="4" >
|
||||
<div class="block">
|
||||
<el-timeline>
|
||||
<el-timeline-item v-for="(item, index) in tasks" :key="index"
|
||||
:icon="getTimelineItemIcon(item)" :type="getTimelineItemType(item)">
|
||||
<p style="font-weight: 700">任务:{{ item.name }}</p>
|
||||
<el-card :body-style="{ padding: '10px' }">
|
||||
<label v-if="item.assigneeUser" style="font-weight: normal; margin-right: 30px;">
|
||||
审批人:{{ item.assigneeUser.nickname }}
|
||||
<el-tag type="info" size="mini">{{ item.assigneeUser.deptName }}</el-tag>
|
||||
</label>
|
||||
<label style="font-weight: normal" v-if="item.createTime">创建时间:</label>
|
||||
<label style="color:#8a909c; font-weight: normal">{{ parseTime(item.createTime) }}</label>
|
||||
<label v-if="item.endTime" style="margin-left: 30px;font-weight: normal">审批时间:</label>
|
||||
<label v-if="item.endTime" style="color:#8a909c;font-weight: normal"> {{ parseTime(item.endTime) }}</label>
|
||||
<label v-if="item.durationInMillis" style="margin-left: 30px;font-weight: normal">耗时:</label>
|
||||
<label v-if="item.durationInMillis" style="color:#8a909c;font-weight: normal"> {{ getDateStar(item.durationInMillis) }} </label>
|
||||
<p v-if="item.reason">
|
||||
<el-tag :type="getTimelineItemType(item)">{{ item.reason }}</el-tag>
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-card>
|
||||
|
||||
<!-- 高亮流程图 -->
|
||||
<el-card class="box-card" v-loading="processInstanceLoading">
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="el-icon-picture-outline">流程图</span>
|
||||
</div>
|
||||
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :activityData="activityList"
|
||||
:processInstanceData="processInstance" :taskData="tasks" />
|
||||
</el-card>
|
||||
|
||||
<!-- 对话框(转派审批人) -->
|
||||
<el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body>
|
||||
<el-form ref="updateAssigneeForm" :model="updateAssignee.form" :rules="updateAssignee.rules" label-width="110px">
|
||||
<el-form-item label="新审批人" prop="assigneeUserId">
|
||||
<el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%">
|
||||
<el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitUpdateAssigneeForm">确 定</el-button>
|
||||
<el-button @click="cancelUpdateAssigneeForm">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getProcessDefinitionBpmnXML} from "@/api/bpm/definition";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import store from "@/store";
|
||||
import {decodeFields} from "@/utils/formGenerator";
|
||||
import Parser from '@/components/parser/Parser'
|
||||
import {getProcessInstance} from "@/api/bpm/processInstance";
|
||||
import {approveTask, getTaskListByProcessInstanceId, rejectTask, updateTaskAssignee} from "@/api/bpm/task";
|
||||
import {getDate} from "@/utils/dateUtils";
|
||||
import {listSimpleUsers} from "@/api/system/user";
|
||||
import {getActivityList} from "@/api/bpm/activity";
|
||||
import Vue from "vue";
|
||||
|
||||
// 流程实例的详情页,可用于审批
|
||||
export default {
|
||||
name: "ProcessInstanceDetail",
|
||||
components: {
|
||||
Parser
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
processInstanceLoading: true,
|
||||
// 流程实例
|
||||
id: undefined, // 流程实例的编号
|
||||
processInstance: {},
|
||||
|
||||
// 流程表单详情
|
||||
detailForm: {
|
||||
fields: []
|
||||
},
|
||||
|
||||
// BPMN 数据
|
||||
bpmnXML: null,
|
||||
bpmnControlForm: {
|
||||
prefix: "flowable"
|
||||
},
|
||||
activityList: [],
|
||||
|
||||
// 审批记录
|
||||
tasksLoad: true,
|
||||
tasks: [],
|
||||
|
||||
// 审批表单
|
||||
runningTasks: [],
|
||||
auditForms: [],
|
||||
auditRule: {
|
||||
reason: [{ required: true, message: "审批建议不能为空", trigger: "blur" }],
|
||||
},
|
||||
|
||||
// 转派审批人
|
||||
userOptions: [],
|
||||
updateAssignee: {
|
||||
open: false,
|
||||
form: {
|
||||
assigneeUserId: undefined,
|
||||
},
|
||||
rules: {
|
||||
assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }],
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.id = this.$route.query.id;
|
||||
if (!this.id) {
|
||||
this.$message.error('未传递 id 参数,无法查看流程信息');
|
||||
return;
|
||||
}
|
||||
this.getDetail();
|
||||
|
||||
// 获得用户列表
|
||||
this.userOptions = [];
|
||||
listSimpleUsers().then(response => {
|
||||
this.userOptions.push(...response.data);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/** 获得流程实例 */
|
||||
getDetail() {
|
||||
// 获得流程实例相关
|
||||
this.processInstanceLoading = true;
|
||||
getProcessInstance(this.id).then(response => {
|
||||
if (!response.data) {
|
||||
this.$message.error('查询不到流程信息!');
|
||||
return;
|
||||
}
|
||||
// 设置流程信息
|
||||
this.processInstance = response.data;
|
||||
|
||||
//将业务表单,注册为动态组件
|
||||
const path = this.processInstance.processDefinition.formCustomViewPath;
|
||||
Vue.component("async-biz-form-component", function(resolve) {
|
||||
require([`@/views${path}`], resolve);
|
||||
});
|
||||
|
||||
// 设置表单信息
|
||||
if (this.processInstance.processDefinition.formType === 10) {
|
||||
this.detailForm = {
|
||||
...JSON.parse(this.processInstance.processDefinition.formConf),
|
||||
disabled: true, // 表单禁用
|
||||
formBtns: false, // 按钮隐藏
|
||||
fields: decodeFields(this.processInstance.processDefinition.formFields)
|
||||
}
|
||||
// 设置表单的值
|
||||
this.detailForm.fields.forEach(item => {
|
||||
const val = this.processInstance.formVariables[item.__vModel__]
|
||||
if (val) {
|
||||
item.__config__.defaultValue = val
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 加载流程图
|
||||
getProcessDefinitionBpmnXML(this.processInstance.processDefinition.id).then(response => {
|
||||
this.bpmnXML = response.data
|
||||
});
|
||||
// 加载活动列表
|
||||
getActivityList({
|
||||
processInstanceId: this.processInstance.id
|
||||
}).then(response => {
|
||||
this.activityList = response.data;
|
||||
});
|
||||
|
||||
// 取消加载中
|
||||
this.processInstanceLoading = false;
|
||||
});
|
||||
|
||||
// 获得流程任务列表(审批记录)
|
||||
this.tasksLoad = true;
|
||||
this.runningTasks = [];
|
||||
this.auditForms = [];
|
||||
getTaskListByProcessInstanceId(this.id).then(response => {
|
||||
// 审批记录
|
||||
this.tasks = [];
|
||||
// 移除已取消的审批
|
||||
response.data.forEach(task => {
|
||||
if (task.result !== 4) {
|
||||
this.tasks.push(task);
|
||||
}
|
||||
});
|
||||
// 排序,将未完成的排在前面,已完成的排在后面;
|
||||
this.tasks.sort((a, b) => {
|
||||
// 有已完成的情况,按照完成时间倒序
|
||||
if (a.endTime && b.endTime) {
|
||||
return b.endTime - a.endTime;
|
||||
} else if (a.endTime) {
|
||||
return 1;
|
||||
} else if (b.endTime) {
|
||||
return -1;
|
||||
// 都是未完成,按照创建时间倒序
|
||||
} else {
|
||||
return b.createTime - a.createTime;
|
||||
}
|
||||
});
|
||||
|
||||
// 需要审核的记录
|
||||
const userId = store.getters.userId;
|
||||
this.tasks.forEach(task => {
|
||||
if (task.result !== 1) { // 只有待处理才需要
|
||||
return;
|
||||
}
|
||||
if (!task.assigneeUser || task.assigneeUser.id !== userId) { // 自己不是处理人
|
||||
return;
|
||||
}
|
||||
this.runningTasks.push({...task});
|
||||
this.auditForms.push({
|
||||
reason: ''
|
||||
})
|
||||
});
|
||||
|
||||
// 取消加载中
|
||||
this.tasksLoad = false;
|
||||
});
|
||||
},
|
||||
getDateStar(ms) {
|
||||
return getDate(ms);
|
||||
},
|
||||
getTimelineItemIcon(item) {
|
||||
if (item.result === 1) {
|
||||
return 'el-icon-time';
|
||||
}
|
||||
if (item.result === 2) {
|
||||
return 'el-icon-check';
|
||||
}
|
||||
if (item.result === 3) {
|
||||
return 'el-icon-close';
|
||||
}
|
||||
if (item.result === 4) {
|
||||
return 'el-icon-remove-outline';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
getTimelineItemType(item) {
|
||||
if (item.result === 1) {
|
||||
return 'primary';
|
||||
}
|
||||
if (item.result === 2) {
|
||||
return 'success';
|
||||
}
|
||||
if (item.result === 3) {
|
||||
return 'danger';
|
||||
}
|
||||
if (item.result === 4) {
|
||||
return 'info';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/** 处理审批通过和不通过的操作 */
|
||||
handleAudit(task, pass) {
|
||||
const index = this.runningTasks.indexOf(task);
|
||||
this.$refs['form' + index][0].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
id: task.id,
|
||||
reason: this.auditForms[index].reason
|
||||
}
|
||||
if (pass) {
|
||||
approveTask(data).then(response => {
|
||||
this.$modal.msgSuccess("审批通过成功!");
|
||||
this.getDetail(); // 获得最新详情
|
||||
});
|
||||
} else {
|
||||
rejectTask(data).then(response => {
|
||||
this.$modal.msgSuccess("审批不通过成功!");
|
||||
this.getDetail(); // 获得最新详情
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 处理转派审批人 */
|
||||
handleUpdateAssignee(task) {
|
||||
// 设置表单
|
||||
this.resetUpdateAssigneeForm();
|
||||
this.updateAssignee.form.id = task.id;
|
||||
// 设置为打开
|
||||
this.updateAssignee.open = true;
|
||||
},
|
||||
/** 提交转派审批人 */
|
||||
submitUpdateAssigneeForm() {
|
||||
this.$refs['updateAssigneeForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
updateTaskAssignee(this.updateAssignee.form).then(response => {
|
||||
this.$modal.msgSuccess("转派任务成功!");
|
||||
this.updateAssignee.open = false;
|
||||
this.getDetail(); // 获得最新详情
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 取消转派审批人 */
|
||||
cancelUpdateAssigneeForm() {
|
||||
this.updateAssignee.open = false;
|
||||
this.resetUpdateAssigneeForm();
|
||||
},
|
||||
/** 重置转派审批人 */
|
||||
resetUpdateAssigneeForm() {
|
||||
this.updateAssignee.form = {
|
||||
id: undefined,
|
||||
assigneeUserId: undefined,
|
||||
};
|
||||
this.resetForm("updateAssigneeForm");
|
||||
},
|
||||
/** 处理审批退回的操作 */
|
||||
handleDelegate(task) {
|
||||
this.$modal.msgError("暂不支持【委派】功能,可以使用【转派】替代!");
|
||||
},
|
||||
/** 处理审批退回的操作 */
|
||||
handleBack(task) {
|
||||
this.$modal.msgError("暂不支持【退回】功能!");
|
||||
// 可参考 http://blog.wya1.com/article/636697030/details/7296
|
||||
// const data = {
|
||||
// id: task.id,
|
||||
// assigneeUserId: 1
|
||||
// }
|
||||
// backTask(data).then(response => {
|
||||
// this.$modal.msgSuccess("回退成功!");
|
||||
// this.getDetail(); // 获得最新详情
|
||||
// });
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.my-process-designer {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
.box-card {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,182 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="流程名" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属流程" prop="processDefinitionId">
|
||||
<el-input v-model="queryParams.processDefinitionId" placeholder="请输入流程定义的编号" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程分类" prop="category">
|
||||
<el-select v-model="queryParams.category" placeholder="请选择流程分类" clearable>
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="提交时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="结果" prop="result">
|
||||
<el-select v-model="queryParams.result" placeholder="请选择流结果" clearable>
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['bpm:process-instance:query']">发起流程</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" width="320" />
|
||||
<el-table-column label="流程名" align="center" prop="name" />
|
||||
<el-table-column label="流程分类" align="center" prop="category">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前审批任务" align="center" prop="tasks">
|
||||
<template v-slot="scope">
|
||||
<el-button v-for="task in scope.row.tasks" :key="task.id" type="text"">
|
||||
<span>{{ task.name }}</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结果" align="center" prop="result">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提交时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.endTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" size="small" icon="el-icon-delete" v-if="scope.row.result === 1"
|
||||
v-hasPermi="['bpm:process-instance:cancel']" @click="handleCancel(scope.row)">取消</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)"
|
||||
v-hasPermi="['bpm:process-instance:query']">详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMyProcessInstancePage, cancelProcessInstance } from "@/api/bpm/processInstance";
|
||||
|
||||
export default {
|
||||
name: "BpmProcessInstance",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 工作流的流程实例的拓展列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
processDefinitionId: null,
|
||||
category: null,
|
||||
status: null,
|
||||
result: null,
|
||||
createTime: []
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getMyProcessInstancePage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 **/
|
||||
handleAdd() {
|
||||
this.$router.push({ name: "BpmProcessInstanceCreate"})
|
||||
},
|
||||
/** 取消按钮操作 */
|
||||
handleCancel(row) {
|
||||
const id = row.id;
|
||||
this.$prompt('请输入取消原因?', "取消流程", {
|
||||
type: 'warning',
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
|
||||
inputErrorMessage: "取消原因不能为空",
|
||||
}).then(({ value }) => {
|
||||
return cancelProcessInstance(id, value);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("取消成功");
|
||||
})
|
||||
},
|
||||
/** 处理详情按钮 */
|
||||
handleDetail(row) {
|
||||
this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.id}});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="流程名" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="任务编号" align="center" prop="id" width="320" fixed />
|
||||
<el-table-column label="任务名称" align="center" prop="name" width="200" />
|
||||
<el-table-column label="所属流程" align="center" prop="processInstance.name" width="200" />
|
||||
<el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" width="120" />
|
||||
<el-table-column label="结果" align="center" prop="result">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批意见" align="center" prop="reason" width="200" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批时间" align="center" prop="endTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.endTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="耗时" align="center" prop="durationInMillis" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ getDateStar(scope.row.durationInMillis) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)"
|
||||
v-hasPermi="['bpm:task:query']">详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getDoneTaskPage} from '@/api/bpm/task'
|
||||
import {getDate} from "@/utils/dateUtils";
|
||||
|
||||
export default {
|
||||
name: "BpmDoneTask",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 已办任务列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
createTime: []
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getDoneTaskPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
getDateStar(ms) {
|
||||
return getDate(ms);
|
||||
},
|
||||
/** 处理审批按钮 */
|
||||
handleAudit(row) {
|
||||
this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.processInstance.id}});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="流程名" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="任务编号" align="center" prop="id" width="320" />
|
||||
<el-table-column label="任务名称" align="center" prop="name" />
|
||||
<el-table-column label="所属流程" align="center" prop="processInstance.name" />
|
||||
<el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="version" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
|
||||
<el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)"
|
||||
v-hasPermi="['bpm:task:update']">审批</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getTodoTaskPage} from '@/api/bpm/task'
|
||||
|
||||
export default {
|
||||
name: "BpmTodoTask",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 待办任务列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
createTime: []
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
getTodoTaskPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 处理审批按钮 */
|
||||
handleAudit(row) {
|
||||
this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.processInstance.id}});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,337 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 列表弹窗 -->
|
||||
<el-dialog title="任务分配规则" :visible.sync="visible" width="800px" append-to-body>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="任务名" align="center" prop="taskDefinitionName" width="120" fixed />
|
||||
<el-table-column label="任务标识" align="center" prop="taskDefinitionKey" width="120" show-tooltip-when-overflow />
|
||||
<el-table-column label="规则类型" align="center" prop="type" width="120">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规则范围" align="center" prop="options" width="440px">
|
||||
<template v-slot="scope">
|
||||
<el-tag size="medium" v-if="scope.row.options" :key="option" v-for="option in scope.row.options">
|
||||
{{ getAssignRuleOptionName(scope.row.type, option) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="modelId" label="操作" align="center" width="80" fixed="right">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdateTaskAssignRule(scope.row)"
|
||||
v-hasPermi="['bpm:task-assign-rule:update']">修改</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
<!-- 添加/修改弹窗 -->
|
||||
<el-dialog title="修改任务规则" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="taskAssignRuleForm" :model="form" :rules="rules" label-width="110px">
|
||||
<el-form-item label="任务名称" prop="taskDefinitionName">
|
||||
<el-input v-model="form.taskDefinitionName" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="任务标识" prop="taskDefinitionKey">
|
||||
<el-input v-model="form.taskDefinitionKey" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="规则类型" prop="type">
|
||||
<el-select v-model="form.type" clearable style="width: 100%">
|
||||
<el-option v-for="dict in taskAssignRuleTypeDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type === 10" label="指定角色" prop="roleIds">
|
||||
<el-select v-model="form.roleIds" multiple clearable style="width: 100%">
|
||||
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type === 20 || form.type === 21" label="指定部门" prop="deptIds">
|
||||
<treeselect v-model="form.deptIds" :options="deptTreeOptions" multiple flat :defaultExpandLevel="3"
|
||||
placeholder="请选择指定部门" :normalizer="normalizer"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type === 22" label="指定岗位" prop="postIds">
|
||||
<el-select v-model="form.postIds" multiple clearable style="width: 100%">
|
||||
<el-option v-for="item in postOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type === 30 || form.type === 31 || form.type === 32" label="指定用户" prop="userIds">
|
||||
<el-select v-model="form.userIds" multiple clearable style="width: 100%">
|
||||
<el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type === 40" label="指定用户组" prop="userGroupIds">
|
||||
<el-select v-model="form.userGroupIds" multiple clearable style="width: 100%">
|
||||
<el-option v-for="item in userGroupOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type === 50" label="指定脚本" prop="scripts">
|
||||
<el-select v-model="form.scripts" multiple clearable style="width: 100%">
|
||||
<el-option v-for="dict in taskAssignScriptDictDatas" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitAssignRuleForm">确 定</el-button>
|
||||
<el-button @click="cancelAssignRuleForm">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createTaskAssignRule, getTaskAssignRuleList, updateTaskAssignRule} from "@/api/bpm/taskAssignRule";
|
||||
import {listSimpleRoles} from "@/api/system/role";
|
||||
import {listSimpleDepts} from "@/api/system/dept";
|
||||
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import {listSimplePosts} from "@/api/system/post";
|
||||
import {listSimpleUsers} from "@/api/system/user";
|
||||
import {listSimpleUserGroups} from "@/api/bpm/userGroup";
|
||||
|
||||
export default {
|
||||
name: "BpmTaskAssignRule",
|
||||
components: {
|
||||
Treeselect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 如下参数,可传递
|
||||
modelId: undefined, // 流程模型的编号。如果 modelId 非空,则用于流程模型的查看与配置
|
||||
processDefinitionId: undefined, // 流程定义的编号。如果 processDefinitionId 非空,则用于流程定义的查看,不支持配置
|
||||
visible: false,
|
||||
|
||||
// 任务分配规则表单
|
||||
row: undefined, // 选中的流程模型
|
||||
list: [], // 选中流程模型的任务分配规则们
|
||||
loading: false, // 加载中
|
||||
open: false, // 是否打开
|
||||
form: {}, // 表单
|
||||
rules: { // 表单校验规则
|
||||
type: [{ required: true, message: "规则类型不能为空", trigger: "change" }],
|
||||
roleIds: [{required: true, message: "指定角色不能为空", trigger: "change" }],
|
||||
deptIds: [{required: true, message: "指定部门不能为空", trigger: "change" }],
|
||||
postIds: [{required: true, message: "指定岗位不能为空", trigger: "change"}],
|
||||
userIds: [{required: true, message: "指定用户不能为空", trigger: "change"}],
|
||||
userGroupIds: [{required: true, message: "指定用户组不能为空", trigger: "change"}],
|
||||
scripts: [{required: true, message: "指定脚本不能为空", trigger: "change"}],
|
||||
},
|
||||
|
||||
// 各种下拉框
|
||||
roleOptions: [],
|
||||
deptOptions: [],
|
||||
deptTreeOptions: [],
|
||||
postOptions: [],
|
||||
userOptions: [],
|
||||
userGroupOptions: [],
|
||||
|
||||
// 数据字典
|
||||
modelFormTypeDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_FORM_TYPE),
|
||||
taskAssignRuleTypeDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE),
|
||||
taskAssignScriptDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_SCRIPT),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
initModel(modelId) {
|
||||
this.modelId = modelId;
|
||||
this.processDefinitionId = undefined;
|
||||
|
||||
// 初始化所有下拉框
|
||||
this.init0();
|
||||
},
|
||||
initProcessDefinition(processDefinitionId) {
|
||||
this.modelId = undefined;
|
||||
this.processDefinitionId = processDefinitionId;
|
||||
|
||||
// 初始化所有下拉框
|
||||
this.init0();
|
||||
},
|
||||
/** 初始化 */
|
||||
init0() {
|
||||
// 设置可见
|
||||
this.visible = true;
|
||||
// 获得列表
|
||||
this.getList();
|
||||
|
||||
// 获得角色列表
|
||||
this.roleOptions = [];
|
||||
listSimpleRoles().then(response => {
|
||||
this.roleOptions.push(...response.data);
|
||||
});
|
||||
// 获得部门列表
|
||||
this.deptOptions = [];
|
||||
this.deptTreeOptions = [];
|
||||
listSimpleDepts().then(response => {
|
||||
this.deptOptions.push(...response.data);
|
||||
this.deptTreeOptions.push(...this.handleTree(response.data, "id"));
|
||||
});
|
||||
// 获得岗位列表
|
||||
this.postOptions = [];
|
||||
listSimplePosts().then(response => {
|
||||
this.postOptions.push(...response.data);
|
||||
});
|
||||
// 获得用户列表
|
||||
this.userOptions = [];
|
||||
listSimpleUsers().then(response => {
|
||||
this.userOptions.push(...response.data);
|
||||
});
|
||||
// 获得用户组列表
|
||||
this.userGroupOptions = [];
|
||||
listSimpleUserGroups().then(response => {
|
||||
this.userGroupOptions.push(...response.data);
|
||||
});
|
||||
},
|
||||
/** 获得任务分配规则列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getTaskAssignRuleList({
|
||||
modelId: this.modelId,
|
||||
processDefinitionId: this.processDefinitionId,
|
||||
}).then(response => {
|
||||
this.loading = false;
|
||||
this.list = response.data;
|
||||
})
|
||||
},
|
||||
/** 处理修改任务分配规则的按钮操作 */
|
||||
handleUpdateTaskAssignRule(row) {
|
||||
// 先重置标识
|
||||
this.resetAssignRuleForm();
|
||||
// 设置表单
|
||||
this.form = {
|
||||
...row,
|
||||
options: [],
|
||||
roleIds: [],
|
||||
deptIds: [],
|
||||
postIds: [],
|
||||
userIds: [],
|
||||
userGroupIds: [],
|
||||
scripts: [],
|
||||
};
|
||||
// 将 options 赋值到对应的 roleIds 等选项
|
||||
if (row.type === 10) {
|
||||
this.form.roleIds.push(...row.options);
|
||||
} else if (row.type === 20 || row.type === 21) {
|
||||
this.form.deptIds.push(...row.options);
|
||||
} else if (row.type === 22) {
|
||||
this.form.postIds.push(...row.options);
|
||||
} else if (row.type === 30 || row.type === 31 || row.type === 32) {
|
||||
this.form.userIds.push(...row.options);
|
||||
} else if (row.type === 40) {
|
||||
this.form.userGroupIds.push(...row.options);
|
||||
} else if (row.type === 50) {
|
||||
this.form.scripts.push(...row.options);
|
||||
}
|
||||
this.open = true;
|
||||
},
|
||||
/** 提交任务分配规则的表单 */
|
||||
submitAssignRuleForm() {
|
||||
this.$refs["taskAssignRuleForm"].validate(valid => {
|
||||
if (valid) {
|
||||
// 构建表单
|
||||
let form = {
|
||||
...this.form,
|
||||
taskDefinitionName: undefined,
|
||||
};
|
||||
// 将 roleIds 等选项赋值到 options 中
|
||||
if (form.type === 10) {
|
||||
form.options = form.roleIds;
|
||||
} else if (form.type === 20 || form.type === 21) {
|
||||
form.options = form.deptIds;
|
||||
} else if (form.type === 22) {
|
||||
form.options = form.postIds;
|
||||
} else if (form.type === 30 || form.type === 31 || form.type === 32) {
|
||||
form.options = form.userIds;
|
||||
} else if (form.type === 40) {
|
||||
form.options = form.userGroupIds;
|
||||
} else if (form.type === 50) {
|
||||
form.options = form.scripts;
|
||||
}
|
||||
form.roleIds = undefined;
|
||||
form.deptIds = undefined;
|
||||
form.postIds = undefined;
|
||||
form.userIds = undefined;
|
||||
form.userGroupIds = undefined;
|
||||
form.scripts = undefined;
|
||||
// 新增
|
||||
if (!form.id) {
|
||||
form.modelId = this.modelId; // 模型编号
|
||||
createTaskAssignRule(form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
// 修改
|
||||
} else {
|
||||
form.taskDefinitionKey = undefined; // 无法修改
|
||||
updateTaskAssignRule(form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 取消任务分配规则的表单 */
|
||||
cancelAssignRuleForm() {
|
||||
this.open = false;
|
||||
this.resetAssignRuleForm();
|
||||
},
|
||||
/** 表单重置 */
|
||||
resetAssignRuleForm() {
|
||||
this.form = {};
|
||||
this.resetForm("taskAssignRuleForm");
|
||||
},
|
||||
getAssignRuleOptionName(type, option) {
|
||||
if (type === 10) {
|
||||
for (const roleOption of this.roleOptions) {
|
||||
if (roleOption.id === option) {
|
||||
return roleOption.name;
|
||||
}
|
||||
}
|
||||
} else if (type === 20 || type === 21) {
|
||||
for (const deptOption of this.deptOptions) {
|
||||
if (deptOption.id === option) {
|
||||
return deptOption.name;
|
||||
}
|
||||
}
|
||||
} else if (type === 22) {
|
||||
for (const postOption of this.postOptions) {
|
||||
if (postOption.id === option) {
|
||||
return postOption.name;
|
||||
}
|
||||
}
|
||||
} else if (type === 30 || type === 31 || type === 32) {
|
||||
for (const userOption of this.userOptions) {
|
||||
if (userOption.id === option) {
|
||||
return userOption.nickname;
|
||||
}
|
||||
}
|
||||
} else if (type === 40) {
|
||||
for (const userGroupOption of this.userGroupOptions) {
|
||||
if (userGroupOption.id === option) {
|
||||
return userGroupOption.name;
|
||||
}
|
||||
}
|
||||
} else if (type === 50) {
|
||||
option = option + ''; // 转换成 string
|
||||
for (const dictData of this.taskAssignScriptDictDatas) {
|
||||
if (dictData.value === option) {
|
||||
return dictData.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
return '未知(' + option + ')';
|
||||
},
|
||||
// 格式化部门的下拉框
|
||||
normalizer(node) {
|
||||
return {
|
||||
id: node.id,
|
||||
label: node.name,
|
||||
children: node.children
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -2,42 +2,18 @@
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<search-bar
|
||||
:formConfigs="formConfig"
|
||||
ref="searchBarForm"
|
||||
@headBtnClick="buttonClick"
|
||||
/>
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="80"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
<base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
|
||||
:max-height="tableH">
|
||||
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="80" label="操作" :method-list="tableBtn"
|
||||
@clickBtn="handleClick" />
|
||||
</base-table>
|
||||
<pagination
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
|
||||
@pagination="getList" />
|
||||
<!-- 新增 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="centervisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
|
||||
@confirm="handleConfirm" :before-close="handleCancel">
|
||||
<energy-plc-add ref="energyPlc" @successSubmit="successSubmit" />
|
||||
</base-dialog>
|
||||
</div>
|
||||
@@ -50,7 +26,8 @@ import EnergyPlcAdd from './components/energyPlcAdd.vue'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: 'plcTableName',
|
||||
label: '关联表名'
|
||||
label: '关联表名',
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'code',
|
||||
@@ -60,7 +37,9 @@ const tableProps = [
|
||||
},
|
||||
{
|
||||
prop: 'name',
|
||||
label: '标识名'
|
||||
label: '标识名',
|
||||
minWidth: 150,
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'enName',
|
||||
@@ -109,21 +88,21 @@ export default {
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:energy-plc:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:energy-plc:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
: undefined
|
||||
].filter((v) => v),
|
||||
tableH: this.tableHeight(260),
|
||||
collectionList: [
|
||||
{value: 0,label: '否'},
|
||||
{value: 1,label: '是'}
|
||||
{ value: 0, label: '否' },
|
||||
{ value: 1, label: '是' }
|
||||
],
|
||||
// 总条数
|
||||
total: 0,
|
||||
@@ -167,7 +146,7 @@ export default {
|
||||
getList() {
|
||||
getEnergyPlcPage(this.queryParams).then(response => {
|
||||
let arr = response.data.list || [];
|
||||
arr&&arr.map(item => {
|
||||
arr && arr.map(item => {
|
||||
this.collectionList.map(i => {
|
||||
if (item.collection === i.value) {
|
||||
item.collection = i.label
|
||||
@@ -188,7 +167,7 @@ export default {
|
||||
this.centervisible = true
|
||||
break
|
||||
default:
|
||||
this.handleDelete(val.data)
|
||||
this.handleDelete(val.data)
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
@@ -205,13 +184,13 @@ export default {
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
this.$modal.confirm('是否确认删除关联表名为"' + row.name + '"的数据项?').then(function() {
|
||||
return deleteEnergyPlc(row.id);
|
||||
}).then(() => {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
this.$modal.confirm('是否确认删除关联表名为"' + row.name + '"的数据项?').then(function () {
|
||||
return deleteEnergyPlc(row.id);
|
||||
}).then(() => {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => { });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,47 +2,23 @@
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<search-bar
|
||||
:formConfigs="formConfig"
|
||||
ref="searchBarForm"
|
||||
@headBtnClick="buttonClick"
|
||||
/>
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="160"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
<base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
|
||||
:max-height="tableH">
|
||||
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="160" label="操作" :method-list="tableBtn"
|
||||
@clickBtn="handleClick" />
|
||||
</base-table>
|
||||
<pagination
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
|
||||
@pagination="getList" />
|
||||
<!-- 新增 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="centervisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
width='30%'
|
||||
>
|
||||
<base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
|
||||
@confirm="handleConfirm" :before-close="handleCancel" width='30%'>
|
||||
<energy-plc-connect-add ref="energyPlcConnect" :objList="objList" @successSubmit="successSubmit" />
|
||||
</base-dialog>
|
||||
<!-- 参数绑定/查看 -->
|
||||
<energy-plc-param v-if="paramVisible" ref="plcParam" @closeDrawer="closeDrawer" :energyTypeList="energyTypeList"></energy-plc-param>
|
||||
<energy-plc-param v-if="paramVisible" ref="plcParam" @closeDrawer="closeDrawer"
|
||||
:energyTypeList="energyTypeList"></energy-plc-param>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -60,20 +36,24 @@ const tableProps = [
|
||||
},
|
||||
{
|
||||
prop: 'objCode',
|
||||
label: '对象编码'
|
||||
label: '对象编码',
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'plcTableName',
|
||||
prop: 'plcTableName',
|
||||
label: '关联表名'
|
||||
},
|
||||
{
|
||||
prop: 'plcTableCode',
|
||||
label: '关联表编码',
|
||||
minWidth: 150,
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'cnName',
|
||||
label: '标识名'
|
||||
label: '标识名',
|
||||
minWidth: 150,
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'varNum',
|
||||
@@ -113,9 +93,9 @@ export default {
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:energy-plc-connect:bind')
|
||||
? {
|
||||
type: 'connect',
|
||||
btnName: '绑定'
|
||||
}
|
||||
type: 'connect',
|
||||
btnName: '绑定'
|
||||
}
|
||||
: undefined,
|
||||
{
|
||||
type: 'detail',
|
||||
@@ -123,15 +103,15 @@ export default {
|
||||
},
|
||||
this.$auth.hasPermi('base:energy-plc-connect:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:energy-plc-connect:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
: undefined
|
||||
].filter((v) => v),
|
||||
tableH: this.tableHeight(260),
|
||||
@@ -230,13 +210,13 @@ export default {
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
this.$modal.confirm('是否确认删除对象为"' + row.objName + '"的数据项?').then(function() {
|
||||
return deleteEnergyPlcConnect(row.id);
|
||||
}).then(() => {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
this.$modal.confirm('是否确认删除对象为"' + row.objName + '"的数据项?').then(function () {
|
||||
return deleteEnergyPlcConnect(row.id);
|
||||
}).then(() => {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
closeDrawer() {
|
||||
this.getList()
|
||||
|
||||
@@ -46,7 +46,8 @@ const tableProps = [
|
||||
prop: 'tableName',
|
||||
label: '能源表名',
|
||||
filter: publicFormatter('table_name'),
|
||||
minWidth: 110
|
||||
minWidth: 110,
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'recordTime',
|
||||
|
||||
@@ -20,15 +20,18 @@ import * as XLSX from 'xlsx/xlsx.mjs'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: 'objName',
|
||||
label: '统计对象'
|
||||
label: '统计对象',
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'objCode',
|
||||
label: '对象编码'
|
||||
label: '对象编码',
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'energyTypeName',
|
||||
label: '能源类型'
|
||||
label: '能源类型',
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'startValue',
|
||||
|
||||
@@ -2,46 +2,23 @@
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<search-bar
|
||||
:formConfigs="formConfig"
|
||||
ref="searchBarForm"
|
||||
@headBtnClick="buttonClick"
|
||||
/>
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="160"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
<base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
|
||||
:max-height="tableH">
|
||||
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="160" label="操作" :method-list="tableBtn"
|
||||
@clickBtn="handleClick" />
|
||||
</base-table>
|
||||
<pagination
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
|
||||
@pagination="getList" />
|
||||
<!-- 新增 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="centervisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
|
||||
@confirm="handleConfirm" :before-close="handleCancel">
|
||||
<energy-statistics-add ref="energyStatistics" @successSubmit="successSubmit" />
|
||||
</base-dialog>
|
||||
<!-- 参数绑定/查看 -->
|
||||
<energy-statistics-det ref="plcParam" @closeDrawer="closeDrawer" :energyTypeList="energyTypeList"></energy-statistics-det>
|
||||
<energy-statistics-det ref="plcParam" @closeDrawer="closeDrawer"
|
||||
:energyTypeList="energyTypeList"></energy-statistics-det>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -63,7 +40,7 @@ const tableProps = [
|
||||
showOverflowtooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'type',
|
||||
prop: 'type',
|
||||
label: '统计类型',
|
||||
filter: publicFormatter('statistic_type')
|
||||
},
|
||||
@@ -81,7 +58,7 @@ const tableProps = [
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: "energyStatistics",
|
||||
name: "EnergyStatistics",
|
||||
components: { EnergyStatisticsAdd, EnergyStatisticsDet },
|
||||
data() {
|
||||
return {
|
||||
@@ -112,26 +89,26 @@ export default {
|
||||
tableProps,
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('monitoring:energy-statistics:bind')
|
||||
? {
|
||||
? {
|
||||
type: 'connect',
|
||||
btnName: '绑定'
|
||||
}
|
||||
: undefined,
|
||||
: undefined,
|
||||
{
|
||||
type: 'detail',
|
||||
btnName: '详情'
|
||||
},
|
||||
this.$auth.hasPermi('monitoring:energy-statistics:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('monitoring:energy-statistics:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
: undefined
|
||||
].filter((v) => v),
|
||||
tableH: this.tableHeight(260),
|
||||
@@ -224,13 +201,13 @@ export default {
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
this.$modal.confirm('是否确认删除方案名称为"' + row.name + '"的数据项?').then(function() {
|
||||
return deleteEnergyStatistics(row.id);
|
||||
}).then(() => {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
this.$modal.confirm('是否确认删除方案名称为"' + row.name + '"的数据项?').then(function () {
|
||||
return deleteEnergyStatistics(row.id);
|
||||
}).then(() => {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
closeDrawer() {
|
||||
this.getList()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-11-08 14:00:52
|
||||
* @LastEditTime: 2024-03-25 14:09:33
|
||||
* @LastEditTime: 2024-03-29 08:46:42
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -25,24 +25,24 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// state: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
state() {
|
||||
return this.injectData.enabled === 1 ? true : false
|
||||
state: false
|
||||
}
|
||||
},
|
||||
// computed: {
|
||||
// state() {
|
||||
// return this.injectData.enabled === 1 ? true : false
|
||||
// }
|
||||
// },
|
||||
mounted() {
|
||||
// this.mapToState()
|
||||
this.mapToState()
|
||||
},
|
||||
|
||||
methods: {
|
||||
// mapToState() {
|
||||
// if (this.injectData.prop === 'enabled') {
|
||||
// this.state = this.injectData.enabled === 1 ? true : false
|
||||
// }
|
||||
// },
|
||||
mapToState() {
|
||||
if (this.injectData.prop === 'enabled') {
|
||||
this.state = this.injectData.enabled === 1 ? true : false
|
||||
}
|
||||
},
|
||||
changeHandler() {
|
||||
// let params = {}
|
||||
let payload = {}
|
||||
|
||||
@@ -2,43 +2,18 @@
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<search-bar
|
||||
:formConfigs="formConfig"
|
||||
ref="searchBarForm"
|
||||
@headBtnClick="buttonClick"
|
||||
/>
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="120"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
<base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
|
||||
:max-height="tableH">
|
||||
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
|
||||
@clickBtn="handleClick" />
|
||||
</base-table>
|
||||
<pagination
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
|
||||
@pagination="getList" />
|
||||
<!-- 新增 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="centervisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
width='50%'
|
||||
>
|
||||
<base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
|
||||
@confirm="handleConfirm" :before-close="handleCancel" width='50%'>
|
||||
<group-class-add ref="classList" @successSubmit="successSubmit" />
|
||||
</base-dialog>
|
||||
</div>
|
||||
@@ -85,7 +60,7 @@ const tableProps = [
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: "GroupClass",
|
||||
name: "GroupClasses",
|
||||
components: { GroupClassAdd },
|
||||
data() {
|
||||
return {
|
||||
@@ -115,33 +90,33 @@ export default {
|
||||
],
|
||||
tableProps,
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:group-classes:cancel')
|
||||
this.$auth.hasPermi('base:group-classes:cancel')
|
||||
? {
|
||||
type: 'cancel',
|
||||
btnName: '作废',
|
||||
showParam: {
|
||||
type: '&',
|
||||
data: [
|
||||
{
|
||||
type: 'unequal',
|
||||
name: 'status',
|
||||
value: '不可用'
|
||||
}
|
||||
]
|
||||
}
|
||||
type: 'cancel',
|
||||
btnName: '作废',
|
||||
showParam: {
|
||||
type: '&',
|
||||
data: [
|
||||
{
|
||||
type: 'unequal',
|
||||
name: 'status',
|
||||
value: '不可用'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:group-classes:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
type: 'edit',
|
||||
btnName: '编辑'
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:group-classes:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
type: 'delete',
|
||||
btnName: '删除'
|
||||
}
|
||||
: undefined
|
||||
].filter((v) => v),
|
||||
tableH: this.tableHeight(260),
|
||||
@@ -213,7 +188,7 @@ export default {
|
||||
this.discard(val.data)
|
||||
break
|
||||
default:
|
||||
this.handleDelete(val.data)
|
||||
this.handleDelete(val.data)
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
@@ -235,33 +210,33 @@ export default {
|
||||
obj.endTime = row.endTime
|
||||
obj.enableTime = row.enableTime
|
||||
obj.disableTime = Date.parse(new Date())
|
||||
this.$modal.confirm('是否确认作废班次名称为"' + row.name + '"的数据项?').then(function() {
|
||||
return updateGroupClasses({ ...obj })
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("操作成功");
|
||||
}).catch(() => {});
|
||||
this.$modal.confirm('是否确认作废班次名称为"' + row.name + '"的数据项?').then(function () {
|
||||
return updateGroupClasses({ ...obj })
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("操作成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
console.log(row)
|
||||
let _this = this
|
||||
if (row.status === '可用') {// 可用
|
||||
_this.$modal.confirm('删除的班次"' + row.name + '"可能会影响交接班计划,请点取消再次确认!').then(function() {
|
||||
return _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function() {
|
||||
return deleteGroupClasses(row.id);
|
||||
}).then(() => {
|
||||
_this.getList();
|
||||
_this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
})
|
||||
} else {
|
||||
_this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function() {
|
||||
_this.$modal.confirm('删除的班次"' + row.name + '"可能会影响交接班计划,请点取消再次确认!').then(function () {
|
||||
return _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function () {
|
||||
return deleteGroupClasses(row.id);
|
||||
}).then(() => {
|
||||
_this.getList();
|
||||
_this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
}).catch(() => { });
|
||||
})
|
||||
} else {
|
||||
_this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function () {
|
||||
return deleteGroupClasses(row.id);
|
||||
}).then(() => {
|
||||
_this.getList();
|
||||
_this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => { });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,13 +279,13 @@ export default {
|
||||
handleJobLog(row) {
|
||||
if (row.id) {
|
||||
this.$router.push({
|
||||
path:"/job/log",
|
||||
path:"/system/job/log",
|
||||
query:{
|
||||
jobId: row.id
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$router.push("/job/log");
|
||||
this.$router.push("/system/job/log");
|
||||
}
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="定时任务" url="https://doc.iocoder.cn/job/" />
|
||||
<doc-alert title="异步任务" url="https://doc.iocoder.cn/async-task/" />
|
||||
<doc-alert title="消息队列" url="https://doc.iocoder.cn/message-queue/" />
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
||||
<el-form-item label="处理器的名字" prop="handlerName">
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="queryParams.title" placeholder="请输入标题" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['market:banner:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="标题" align="center" prop="title"/>
|
||||
|
||||
<el-table-column label="缩略图" align="center" prop="picUrl">
|
||||
<template v-slot="scope">
|
||||
<img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="缩略图片" class="img-height"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="跳转链接" align="center" prop="url"/>
|
||||
<el-table-column label="排序" align="center" prop="sort"/>
|
||||
<el-table-column label="描述" align="center" prop="memo"/>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['market:banner:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['market:banner:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入标题"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="缩略图" prop="picUrl">
|
||||
<imageUpload v-model="form.picUrl" :limit="1"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="跳转链接" prop="url">
|
||||
<el-input v-model="form.url" placeholder="请输入跳转链接"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input v-model="form.sort" placeholder="请输入排序"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="memo">
|
||||
<el-input v-model="form.memo" type="textarea" placeholder="请输入描述"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createBanner,
|
||||
deleteBanner,
|
||||
getBanner,
|
||||
getBannerPage,
|
||||
updateBanner
|
||||
} from "@/api/mall/market/banner";
|
||||
import ImageUpload from '@/components/ImageUpload';
|
||||
|
||||
export default {
|
||||
name: "Banner",
|
||||
components: {
|
||||
ImageUpload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 品牌列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
title: null,
|
||||
status: null,
|
||||
createTime: []
|
||||
},
|
||||
// 商品分类树选项
|
||||
categoryOptions: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
title: [{required: true, message: "标题不能不空", trigger: "blur"}],
|
||||
picUrl: [{required: true, message: "图片地址不能为空", trigger: "blur"}],
|
||||
url: [{required: true, message: "跳转地址不能为空", trigger: "blur"}],
|
||||
sort: [{required: true, message: "排序不能为空", trigger: "blur"}],
|
||||
status: [{required: true, message: "状态不能为空", trigger: "change"}],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getBannerPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
title: undefined,
|
||||
link: undefined,
|
||||
imgUrl: undefined,
|
||||
sort: undefined,
|
||||
memo: undefined,
|
||||
status: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加Banner";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getBanner(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改Banner";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateBanner(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createBanner(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除Banner编号为"' + id + '"的数据项?').then(function () {
|
||||
return deleteBanner(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
//
|
||||
.img-height {
|
||||
height: 150px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,247 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="品牌名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入品牌名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['product:brand:create']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="品牌编号" align="center" prop="id"/>
|
||||
<el-table-column label="品牌名称" align="center" prop="name"/>
|
||||
<el-table-column label="品牌图片" align="center" prop="picUrl">
|
||||
<template v-slot="scope">
|
||||
<img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="分类图片" style="height: 100px;" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="品牌排序" align="center" prop="sort"/>
|
||||
<el-table-column label="品牌描述" align="center" prop="description"/>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:brand:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:brand:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="品牌名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入品牌名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌图片" prop="picUrl">
|
||||
<imageUpload v-model="form.picUrl" :limit="1"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌排序" prop="sort">
|
||||
<el-input v-model="form.sort" placeholder="请输入品牌排序"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" placeholder="请输入内容"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createBrand,
|
||||
deleteBrand,
|
||||
getBrand,
|
||||
getBrandPage,
|
||||
updateBrand
|
||||
} from "@/api/mall/product/brand";
|
||||
import ImageUpload from '@/components/ImageUpload';
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import {CommonStatusEnum} from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: "ProductBrand",
|
||||
components: {
|
||||
ImageUpload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 品牌列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
categoryId: null,
|
||||
name: null,
|
||||
status: null,
|
||||
createTime: []
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{required: true, message: "品牌名称不能为空", trigger: "blur"}],
|
||||
picUrl: [{required: true, message: "品牌图片不能为空", trigger: "blur"}],
|
||||
sort: [{required: true, message: "品牌排序不能为空", trigger: "blur"}],
|
||||
status: [{required: true, message: "状态不能为空", trigger: "change"}],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getBrandPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
picUrl: undefined,
|
||||
sort: 0,
|
||||
description: undefined,
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加品牌";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getBrand(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改品牌";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateBrand(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createBrand(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除品牌编号为"' + id + '"的数据项?').then(function () {
|
||||
return deleteBrand(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,270 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="分类名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入分类名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['product:category:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">展开/折叠</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-if="refreshTable" v-loading="loading" :data="list" row-key="id" :default-expand-all="isExpandAll"
|
||||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
|
||||
<el-table-column label="分类名称" prop="name"/>
|
||||
<el-table-column label="分类图片" align="center" prop="picUrl">
|
||||
<template v-slot="scope">
|
||||
<img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="分类图片" style="height: 100px"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="分类排序" align="center" prop="sort"/>
|
||||
<el-table-column label="开启状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:category:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:category:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="上级分类" prop="parentId">
|
||||
<Treeselect v-model="form.parentId" :options="parentCategoryOptions" :normalizer="normalizer" :show-count="true"
|
||||
:defaultExpandLevel="1" placeholder="上级分类"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入分类名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类图片" prop="picUrl">
|
||||
<ImageUpload v-model="form.picUrl" :limit="1" :is-show-tip="false" />
|
||||
<div v-if="form.parentId === 0" style="font-size: 10px">推荐 200x100 图片分辨率</div>
|
||||
<div v-else style="font-size: 10px">推荐 100x100 图片分辨率</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类排序" prop="sort">
|
||||
<el-input-number v-model="form.sort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类描述">
|
||||
<el-input v-model="form.description" type="textarea" placeholder="请输入分类描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createProductCategory,
|
||||
deleteProductCategory,
|
||||
getProductCategory,
|
||||
getProductCategoryList,
|
||||
updateProductCategory
|
||||
} from "@/api/mall/product/category";
|
||||
import Editor from '@/components/Editor';
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import ImageUpload from '@/components/ImageUpload';
|
||||
import {CommonStatusEnum} from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: "ProductCategory",
|
||||
components: {
|
||||
Editor, Treeselect, ImageUpload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 商品分类列表
|
||||
list: [],
|
||||
// 商品分类树选项
|
||||
parentCategoryOptions: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否展开,默认全部折叠
|
||||
isExpandAll: false,
|
||||
// 重新渲染表格状态
|
||||
refreshTable: true,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
name: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
parentId: [{required: true, message: "请选择上级分类", trigger: "blur"}],
|
||||
name: [{required: true, message: "分类名称不能为空", trigger: "blur"}],
|
||||
picUrl: [{required: true, message: "分类图片不能为空", trigger: "blur"}],
|
||||
sort: [{required: true, message: "分类排序不能为空", trigger: "blur"}],
|
||||
status: [{required: true, message: "开启状态不能为空", trigger: "blur"}],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
// 执行查询
|
||||
getProductCategoryList(params).then(response => {
|
||||
this.list = this.handleTree(response.data, "id", "parentId");
|
||||
this.loading = false;
|
||||
// 属性下拉框
|
||||
this.parentCategoryOptions = [];
|
||||
const menu = {id: 0, name: '顶级分类', children: []};
|
||||
menu.children = this.handleTree(response.data, "id", "parentId");
|
||||
this.parentCategoryOptions.push(menu);
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
parentId: undefined,
|
||||
name: undefined,
|
||||
pirUrl: undefined,
|
||||
sort: 0,
|
||||
description: undefined,
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 展开/折叠操作 */
|
||||
toggleExpandAll() {
|
||||
this.refreshTable = false;
|
||||
this.isExpandAll = !this.isExpandAll;
|
||||
this.$nextTick(() => {
|
||||
this.refreshTable = true;
|
||||
});
|
||||
},
|
||||
/** 转换菜单数据结构 */
|
||||
normalizer(node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children;
|
||||
}
|
||||
return {
|
||||
id: node.id,
|
||||
label: node.name,
|
||||
children: node.children
|
||||
};
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加商品分类";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getProductCategory(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改商品分类";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateProductCategory(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createProductCategory(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除商品分类编号为"' + id + '"的数据项?').then(function () {
|
||||
return deleteProductCategory(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,207 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['product:property:create']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名称" align="center" :show-overflow-tooltip="true">
|
||||
<template v-slot="scope">
|
||||
<router-link :to="'/property/value/' + scope.row.id" class="link-type">
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:property:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:property:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createProperty, updateProperty, deleteProperty, getProperty, getPropertyPage } from "@/api/mall/product/property";
|
||||
|
||||
export default {
|
||||
name: "ProductProperty",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 属性项列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
createTime: []
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
name:'',
|
||||
remark:"",
|
||||
id: null,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: "名称不能为空", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getPropertyPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
name:'',
|
||||
remark:"",
|
||||
id: null,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加属性项";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getProperty(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改属性项";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateProperty(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createProperty(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除名称为"' + row.name + '"的数据项?').then(function() {
|
||||
return deleteProperty(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,240 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="属性项" prop="propertyId">
|
||||
<el-select v-model="queryParams.propertyId">
|
||||
<el-option v-for="item in propertyOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['system:dict:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="dataList">
|
||||
<el-table-column label="编号" align="center" prop="id"/>
|
||||
<el-table-column label="名称" align="center" prop="name"/>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:dict:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:dict:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
|
||||
<el-form-item label="属性项">
|
||||
<el-input v-model="form.propertyId" :disabled="true"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入名称"/>
|
||||
</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="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createPropertyValue,
|
||||
deletePropertyValue,
|
||||
getProperty,
|
||||
getPropertyList,
|
||||
getPropertyValue,
|
||||
getPropertyValuePage,
|
||||
updatePropertyValue
|
||||
} from '@/api/mall/product/property'
|
||||
|
||||
export default {
|
||||
name: "ProductPropertyValue",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 字典表格数据
|
||||
dataList: [],
|
||||
// 默认字典类型
|
||||
defaultPropertyId: "",
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 类型数据字典
|
||||
propertyOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
propertyId: undefined,
|
||||
name: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{required: true, message: "名称不能为空", trigger: "blur"}
|
||||
]
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const propertyId = this.$route.params && this.$route.params.propertyId;
|
||||
this.getProperty(propertyId);
|
||||
this.getPropertyList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询字典类型详细 */
|
||||
getProperty(propertyId) {
|
||||
getProperty(propertyId).then(response => {
|
||||
this.queryParams.propertyId = response.data.id;
|
||||
this.defaultPropertyId = response.data.id;
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
/** 查询字典类型列表 */
|
||||
getPropertyList() {
|
||||
getPropertyList().then(response => {
|
||||
this.propertyOptions = response.data
|
||||
});
|
||||
},
|
||||
/** 查询字典数据列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getPropertyValuePage(this.queryParams).then(response => {
|
||||
this.dataList = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
propertyId: undefined,
|
||||
name: undefined,
|
||||
remark: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.queryParams.propertyId = this.defaultPropertyId;
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加属性值";
|
||||
this.form.propertyId = this.queryParams.propertyId;
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getPropertyValue(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改属性值";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function () {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.id !== undefined) {
|
||||
updatePropertyValue(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
createPropertyValue(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ids = row.id;
|
||||
this.$modal.confirm('是否确认删除字典编码为"' + ids + '"的数据项?').then(function () {
|
||||
return deletePropertyValue(ids);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$modal.confirm('是否确认导出所有数据项?').then(() => {
|
||||
this.exportLoading = true;
|
||||
return exportData(queryParams);
|
||||
}).then(response => {
|
||||
this.$download.excel(response, '字典数据.xls');
|
||||
this.exportLoading = false;
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,392 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="商品名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品编码" prop="code">
|
||||
<el-input v-model="queryParams.code" placeholder="请输入商品编码" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品分类" prop="categoryIds">
|
||||
<el-cascader v-model="queryParams.categoryIds" placeholder="请输入商品分类"
|
||||
:options="categoryList" :props="propName" clearable ref="category"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品品牌" prop="brandId">
|
||||
<el-select v-model="queryParams.brandId" placeholder="请输入商品品牌" clearable @keyup.enter.native="handleQuery">
|
||||
<el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- TODO 待实现:商品类型 -->
|
||||
<!-- TODO 待实现:商品标签 -->
|
||||
<!-- TODO 待实现:营销活动 -->
|
||||
<!-- TODO 前端优化:商品销量、商品价格,排的整齐一点 -->
|
||||
<el-form-item label="商品销量">
|
||||
<el-col :span="7" style="padding-left:0">
|
||||
<el-form-item prop="salesCountMin">
|
||||
<el-input v-model="queryParams.salesCountMin" placeholder="最低销量" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">-</el-col>
|
||||
<el-col :span="7" style="padding-left:0">
|
||||
<el-form-item prop="salesCountMax">
|
||||
<el-input v-model="queryParams.salesCountMax" placeholder="最高销量" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品价格" prop="code">
|
||||
<el-col :span="7" style="padding-left:0">
|
||||
<el-form-item prop="marketPriceMin">
|
||||
<el-input v-model="queryParams.marketPriceMin" placeholder="最低价格" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">-</el-col>
|
||||
<el-col :span="7" style="padding-left:0">
|
||||
<el-form-item prop="marketPriceMax">
|
||||
<el-input v-model="queryParams.marketPriceMax" placeholder="最高价格" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['product:spu:create']">添加商品</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"/>
|
||||
</el-row>
|
||||
|
||||
<el-tabs v-model="activeTabs" type="card" @tab-click="handleClick">
|
||||
<!-- 全部 -->
|
||||
<el-tab-pane label="全部" name="all">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="商品信息" align="center" width="260">
|
||||
<template v-slot="scope">
|
||||
<div class="product-info">
|
||||
<img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height" />
|
||||
<div class="message">{{ scope.row.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- TODO 前端优化:可以有个 + 号,点击后,展示每个 sku -->
|
||||
</el-table-column>
|
||||
<el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
|
||||
<el-table-column label="库存" align="center" prop="totalStock"/>
|
||||
<el-table-column label="销量" align="center" prop="salesCount"/>
|
||||
<el-table-column label="排序" align="center" prop="sort"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:spu:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:spu:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 销售中 -->
|
||||
<el-tab-pane label="销售中" name="on">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="商品信息" align="center" width="260">
|
||||
<template v-slot="scope">
|
||||
<div class="product-info">
|
||||
<img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/>
|
||||
<div class="message">{{ scope.row.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
|
||||
<el-table-column label="库存" align="center" prop="totalStock"/>
|
||||
<el-table-column label="销量" align="center" prop="salesCount"/>
|
||||
<el-table-column label="排序" align="center" prop="sort"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:spu:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:spu:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 仓库中 -->
|
||||
<el-tab-pane label="仓库中" name="off">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="商品信息" align="center" width="260">
|
||||
<template v-slot="scope">
|
||||
<div class="product-info">
|
||||
<img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/>
|
||||
<div class="message">{{ scope.row.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
|
||||
<el-table-column label="库存" align="center" prop="totalStock"/>
|
||||
<el-table-column label="销量" align="center" prop="salesCount"/>
|
||||
<el-table-column label="排序" align="center" prop="sort"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:spu:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:spu:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 预警中 -->
|
||||
<el-tab-pane label="预警中" name="remind">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="商品信息" align="center" width="260">
|
||||
<template v-slot="scope">
|
||||
<div class="product-info">
|
||||
<img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/>
|
||||
<div class="message">{{ scope.row.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
|
||||
<el-table-column label="库存" align="center" prop="totalStock"/>
|
||||
<el-table-column label="销量" align="center" prop="salesCount"/>
|
||||
<el-table-column label="排序" align="center" prop="sort"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['product:spu:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['product:spu:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {deleteSpu, getSpuPage,} from "@/api/mall/product/spu";
|
||||
import {getProductCategoryList} from "@/api/mall/product/category";
|
||||
import {getBrandList} from "@/api/mall/product/brand";
|
||||
import {ProductSpuStatusEnum} from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: "ProductSpu",
|
||||
data() {
|
||||
return {
|
||||
activeTabs: "all",
|
||||
propName: {
|
||||
checkStrictly: true,
|
||||
label: "name",
|
||||
value: "id",
|
||||
},
|
||||
brandList: [],
|
||||
categoryList: [],
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 商品spu列表
|
||||
list: [],
|
||||
dateRangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
code: null,
|
||||
categoryIds: [],
|
||||
categoryId: null,
|
||||
brandId: null,
|
||||
status: null,
|
||||
salesCountMin: null,
|
||||
salesCountMax: null,
|
||||
marketPriceMin: null,
|
||||
marketPriceMax: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getListCategory()
|
||||
this.getListBrand()
|
||||
},
|
||||
methods: {
|
||||
/** 查询分类列表 */
|
||||
getListCategory() {
|
||||
// 执行查询
|
||||
getProductCategoryList().then((response) => {
|
||||
this.categoryList = this.handleTree(response.data, "id", "parentId");
|
||||
});
|
||||
},
|
||||
/** 查询品牌列表 */
|
||||
getListBrand() {
|
||||
// 执行查询
|
||||
getBrandList().then((response) => {
|
||||
this.brandList = response.data;
|
||||
});
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.marketPriceMin = this.queryParams.marketPriceMin === null ? null : params.marketPriceMin * 100;
|
||||
params.marketPriceMax = this.queryParams.marketPriceMax === null ? null : params.marketPriceMax * 100;
|
||||
params.categoryId = this.queryParams.categoryIds[this.queryParams.categoryIds.length - 1];
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, "createTime");
|
||||
// 执行查询
|
||||
getSpuPage(params).then((response) => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = [];
|
||||
this.$refs.category.$refs.panel.checkedValue = [];//也可以是指定的值,默认返回值是数组,也可以返回单个值
|
||||
this.$refs.category.$refs.panel.activePath = [];
|
||||
this.$refs.category.$refs.panel.syncActivePath();
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.$router.push({ name: 'ProductSpuCreate'})
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.$router.push({ name: 'ProductSpuUpdate', params: { spuId: row.id }})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除商品spu编号为"' + id + '"的数据项?')
|
||||
.then(function () {
|
||||
return deleteSpu(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
formatPrice(row, column, cellValue) {
|
||||
return '¥' + this.divide(cellValue, 100);
|
||||
},
|
||||
// 选中 tab
|
||||
handleClick(val) {
|
||||
if (val.name === "all") {
|
||||
this.queryParams.status = undefined;
|
||||
this.queryParams.alarmStock = undefined;
|
||||
} else if (val.name === "on") {
|
||||
this.queryParams.status = ProductSpuStatusEnum.ENABLE.status;
|
||||
this.queryParams.alarmStock = undefined;
|
||||
} else if (val.name === "off") {
|
||||
this.queryParams.status = ProductSpuStatusEnum.DISABLE.status;
|
||||
this.queryParams.alarmStock = undefined;
|
||||
} else if (val.name === "remind") {
|
||||
this.queryParams.status = undefined;
|
||||
this.queryParams.alarmStock = true;
|
||||
}
|
||||
this.getList();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.app-container {
|
||||
.el-tag + .el-tag {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
display: flex;
|
||||
|
||||
.img-height {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-left: 10px;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
word-break: break-all;
|
||||
-webkit-box-orient: vertical;
|
||||
white-space: normal;
|
||||
overflow: hidden;
|
||||
height: 50px;
|
||||
line-height: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,580 +0,0 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- TODO 样式优化:表单宽度、表单项对齐、hr 粗细; -->
|
||||
<el-tabs v-model="activeName" class="tabs">
|
||||
<!-- 基础设置 -->
|
||||
<!-- TODO @luowenfeng:基础设置,分成基础信息、配送信息 -->
|
||||
<el-tab-pane label="基础设置" name="basic">
|
||||
<el-form ref="basic" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%">
|
||||
<el-form-item label="商品名称" prop="name">
|
||||
<el-input v-model="baseForm.name" placeholder="请输入商品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="促销语">
|
||||
<el-input type="textarea" v-model="baseForm.sellPoint" placeholder="请输入促销语"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品主图" prop="picUrls">
|
||||
<ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10" class="mall-image"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品视频" prop="videoUrl">
|
||||
<VideoUpload v-model="baseForm.videoUrl" :value="baseForm.videoUrl"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品品牌" prop="brandId">
|
||||
<el-select v-model="baseForm.brandId" placeholder="请选择商品品牌">
|
||||
<el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品分类" prop="categoryIds">
|
||||
<el-cascader v-model="baseForm.categoryIds" placeholder="商品分类" style="width: 100%"
|
||||
:options="categoryList" :props="propName" clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否上架" prop="status">
|
||||
<el-radio-group v-model="baseForm.status">
|
||||
<el-radio :label="1">立即上架</el-radio>
|
||||
<el-radio :label="0">放入仓库</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 价格库存 -->
|
||||
<!-- TODO @luowenfeng:rates=》priceStack 会更好哈 -->
|
||||
<el-tab-pane label="价格库存" name="rates" class="rates">
|
||||
<el-form ref="rates" :model="ratesForm" :rules="rules">
|
||||
<el-form-item label="启用多规格">
|
||||
<el-switch v-model="specSwitch" @change="changeSpecSwitch"/>
|
||||
</el-form-item>
|
||||
<!-- 动态添加规格属性 -->
|
||||
<div v-show="ratesForm.spec === 2">
|
||||
<div v-for="(specs, index) in dynamicSpec" :key="index" class="dynamic-spec">
|
||||
<!-- 删除按钮 -->
|
||||
<el-button type="danger" icon="el-icon-delete" circle class="spec-delete" @click="removeSpec(index)"/>
|
||||
<div class="spec-header">
|
||||
规格项:
|
||||
<el-select v-model="specs.specId" filterable placeholder="请选择" @change="changeSpec">
|
||||
<el-option v-for="item in propertyPageList" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="spec-values">
|
||||
<template v-for="(v, i) in specs.specValue">
|
||||
<el-input v-model="v.name" class="spec-value" :key="i" disabled/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<el-button type="primary" @click="dynamicSpec.push({specValue: []}); ratesForm.rates = []">添加规格项目</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 规格明细 -->
|
||||
<el-form-item label="规格明细">
|
||||
<el-table :data="ratesForm.rates" border style="width: 100%" ref="ratesTable">
|
||||
<template v-if="this.specSwitch">
|
||||
<el-table-column :key="index" v-for="(item, index) in dynamicSpec.filter(v => v.specName !== undefined)"
|
||||
:label="item.specName">
|
||||
<template v-slot="scope">
|
||||
<el-input v-if="scope.row.spec" v-model="scope.row.spec[index]" disabled/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column label="规格图片" width="120px" :render-header="addRedStar" key="90">
|
||||
<template v-slot="scope">
|
||||
<ImageUpload v-model="scope.row.picUrl" :limit="1" :isShowTip="false" style="width: 100px; height: 50px"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="市场价(元)" :render-header="addRedStar" key="92">
|
||||
<template v-slot="scope">
|
||||
<el-form-item :prop="'rates.'+ scope.$index + '.marketPrice'" :rules="[{required: true, trigger: 'change'}]">
|
||||
<el-input v-model="scope.row.marketPrice"
|
||||
oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="销售价(元)" :render-header="addRedStar" key="93">
|
||||
<template v-slot="scope">
|
||||
<el-form-item :prop="'rates.'+ scope.$index + '.price'"
|
||||
:rules="[{required: true, trigger: 'change'}]">
|
||||
<el-input v-model="scope.row.price"
|
||||
oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="成本价" :render-header="addRedStar" key="94">
|
||||
<template v-slot="scope">
|
||||
<el-form-item :prop="'rates.'+ scope.$index + '.costPrice'"
|
||||
:rules="[{required: true, trigger: 'change'}]">
|
||||
<el-input v-model="scope.row.costPrice"
|
||||
oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" :render-header="addRedStar" key="95">
|
||||
<template v-slot="scope">
|
||||
<el-form-item :prop="'rates.'+ scope.$index + '.stock'" :rules="[{required: true, trigger: 'change'}]">
|
||||
<el-input v-model="scope.row.stock" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="预警库存" key="96">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.warnStock" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="体积" key="97">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.volume" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="重量" key="98">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.weight" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="条码" key="99">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.barCode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="this.specSwitch">
|
||||
<el-table-column fixed="right" label="操作" width="50" key="100">
|
||||
<template v-slot="scope">
|
||||
<el-button @click="scope.row.status = 1" type="text" size="small"
|
||||
v-show="scope.row.status === undefined || scope.row.status === 0 ">禁用
|
||||
</el-button>
|
||||
<el-button @click="scope.row.status = 0" type="text" size="small" v-show="scope.row.status === 1">
|
||||
启用
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="虚拟销量" prop="virtualSalesCount">
|
||||
<el-input v-model="baseForm.virtualSalesCount" placeholder="请输入虚拟销量"
|
||||
oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
<el-tab-pane label="商品详情" name="detail">
|
||||
<el-form ref="detail" :model="baseForm" :rules="rules">
|
||||
<el-form-item prop="description">
|
||||
<editor v-model="baseForm.description" :min-height="380"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 销售设置 -->
|
||||
<el-tab-pane label="高级设置" name="senior">
|
||||
<el-form ref="senior" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%">
|
||||
<el-form-item label="排序字段">
|
||||
<el-input v-model="baseForm.sort" placeholder="请输入排序字段" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否展示库存" prop="showStock">
|
||||
<el-radio-group v-model="baseForm.showStock">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<div class="buttons">
|
||||
<el-button type="info" round @click="cancel">取消</el-button>
|
||||
<el-button type="success" round @click="submit">确认</el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getBrandList} from "@/api/mall/product/brand";
|
||||
import {getProductCategoryList} from "@/api/mall/product/category";
|
||||
import {createSpu, getSpuDetail, updateSpu} from "@/api/mall/product/spu";
|
||||
import {getPropertyListAndValue,} from "@/api/mall/product/property";
|
||||
import Editor from "@/components/Editor";
|
||||
import ImageUpload from "@/components/ImageUpload";
|
||||
import VideoUpload from "@/components/VideoUpload";
|
||||
|
||||
export default {
|
||||
name: "ProductSave",
|
||||
components: {
|
||||
Editor,
|
||||
ImageUpload,
|
||||
VideoUpload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
specSwitch: false,
|
||||
activeName: "basic",
|
||||
propName: {
|
||||
checkStrictly: true,
|
||||
label: "name",
|
||||
value: "id",
|
||||
},
|
||||
// 基础设置
|
||||
baseForm: {
|
||||
id: null,
|
||||
name: null,
|
||||
sellPoint: null,
|
||||
categoryIds: null,
|
||||
sort: null,
|
||||
description: null,
|
||||
picUrls: null,
|
||||
videoUrl: null,
|
||||
status: 0,
|
||||
virtualSalesCount: 0,
|
||||
showStock: true,
|
||||
brandId: null,
|
||||
},
|
||||
|
||||
categoryList: [],
|
||||
// 价格库存
|
||||
ratesForm: {
|
||||
spec: 1,
|
||||
// 规格明细
|
||||
rates: [{}]
|
||||
},
|
||||
dynamicSpec: [
|
||||
// {
|
||||
// specId: 86,
|
||||
// specName: "颜色",
|
||||
// specValue:[{
|
||||
// name: "红色",
|
||||
// id: 225,
|
||||
// }]
|
||||
// },
|
||||
],
|
||||
propertyPageList: [],
|
||||
brandList: [],
|
||||
specValue: null,
|
||||
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{required: true, message: "商品名称不能为空", trigger: "blur"},],
|
||||
description: [{required: true, message: "描述不能为空", trigger: "blur"},],
|
||||
categoryIds: [{required: true, message: "分类id不能为空", trigger: "blur"},],
|
||||
status: [{required: true, message: "商品状态不能为空", trigger: "blur"}],
|
||||
brandId: [{required: true, message: "商品品牌不能为空", trigger: "blur"}],
|
||||
picUrls: [{required: true, message: "商品轮播图地址不能为空", trigger: "blur"}],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getListBrand();
|
||||
this.getListCategory();
|
||||
this.getPropertyPageList();
|
||||
const spuId = this.$route.params && this.$route.params.spuId;
|
||||
if (spuId != null) {
|
||||
this.updateType(spuId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeSpec(index) {
|
||||
this.dynamicSpec.splice(index, 1);
|
||||
this.changeSpecSwitch()
|
||||
},
|
||||
// 必选标识
|
||||
addRedStar(h, {column}) {
|
||||
return [
|
||||
h('span', {style: 'color: #F56C6C'}, '*'),
|
||||
h('span', ' ' + column.label)
|
||||
];
|
||||
},
|
||||
changeSpecSwitch() {
|
||||
this.specSwitch ? this.ratesForm.spec = 2 : this.ratesForm.spec = 1;
|
||||
this.$refs.ratesTable.doLayout();
|
||||
if (this.ratesForm.spec === 1) {
|
||||
this.ratesForm.rates = [{}]
|
||||
} else {
|
||||
this.ratesForm.rates = []
|
||||
if (this.dynamicSpec.length > 0) {
|
||||
this.buildRatesFormRates()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 构建规格明细笛卡尔积
|
||||
buildRatesFormRates() {
|
||||
let rates = [];
|
||||
this.dynamicSpec.map(v => v.specValue.map(m => m.name))
|
||||
.reduce((last, current) => {
|
||||
const array = [];
|
||||
last.forEach(par1 => {
|
||||
current.forEach(par2 => {
|
||||
let v
|
||||
// 当两个对象合并时,需使用[1,2]方式生成数组,而当数组和对象合并时,需使用concat
|
||||
if (par1 instanceof Array) {
|
||||
v = par1.concat(par2)
|
||||
} else {
|
||||
v = [par1, par2];
|
||||
}
|
||||
array.push(v)
|
||||
});
|
||||
});
|
||||
return array;
|
||||
})
|
||||
.forEach(v => {
|
||||
let spec = v;
|
||||
// 当v为单个规格项时,会变成字符串。造成表格只截取第一个字符串,而不是数组的第一个元素
|
||||
if (typeof v == 'string') {
|
||||
spec = Array.of(v)
|
||||
}
|
||||
rates.push({spec: spec, status: 0, name: Array.of(v).join()})
|
||||
});
|
||||
this.ratesForm.rates = rates
|
||||
},
|
||||
/** 查询分类 */
|
||||
getListCategory() {
|
||||
// 执行查询
|
||||
getProductCategoryList().then((response) => {
|
||||
this.categoryList = this.handleTree(response.data, "id", "parentId");
|
||||
});
|
||||
},
|
||||
/** 查询品牌列表 */
|
||||
getListBrand() {
|
||||
// 执行查询
|
||||
getBrandList().then((response) => {
|
||||
this.brandList = response.data;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
var currentView = this.$store.state.tagsView.visitedViews[0]
|
||||
for (currentView of this.$store.state.tagsView.visitedViews) {
|
||||
if (currentView.path === this.$route.path) {
|
||||
break
|
||||
}
|
||||
}
|
||||
this.$store.dispatch('tagsView/delView', currentView)
|
||||
.then(() => {
|
||||
this.$router.push("/product/spu")
|
||||
})
|
||||
},
|
||||
submit() {
|
||||
this.$refs[this.activeName].validate((valid) => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
let rates = JSON.parse(JSON.stringify(this.ratesForm.rates));
|
||||
|
||||
// 价格元转分
|
||||
rates.forEach(r => {
|
||||
r.marketPrice = r.marketPrice * 100;
|
||||
r.price = r.price * 100;
|
||||
r.costPrice = r.costPrice * 100;
|
||||
})
|
||||
|
||||
// 动态规格调整字段
|
||||
if (this.specSwitch) {
|
||||
rates.forEach(r => {
|
||||
let properties = []
|
||||
Array.of(r.spec).forEach(s => {
|
||||
let obj;
|
||||
if (s instanceof Array) {
|
||||
obj = s;
|
||||
} else {
|
||||
obj = Array.of(s);
|
||||
}
|
||||
obj.forEach((v, i) => {
|
||||
let specValue = this.dynamicSpec[i].specValue.find(o => o.name === v);
|
||||
let propertie = {};
|
||||
propertie.propertyId = this.dynamicSpec[i].specId;
|
||||
propertie.valueId = specValue.id;
|
||||
properties.push(propertie);
|
||||
})
|
||||
})
|
||||
r.properties = properties;
|
||||
})
|
||||
} else {
|
||||
rates[0].name = this.baseForm.name;
|
||||
rates[0].status = this.baseForm.status;
|
||||
}
|
||||
let form = this.baseForm
|
||||
if (form.picUrls instanceof Array) {
|
||||
form.picUrls = form.picUrls.flatMap(m => m.split(','))
|
||||
} else if (form.picUrls.split(',') instanceof Array) {
|
||||
form.picUrls = form.picUrls.split(',').flatMap(m => m.split(','))
|
||||
} else {
|
||||
form.picUrls = Array.of(form.picUrls)
|
||||
}
|
||||
form.skus = rates;
|
||||
form.specType = this.ratesForm.spec;
|
||||
|
||||
let category = form.categoryIds instanceof Array ? form.categoryIds: Array.of(form.categoryIds)
|
||||
console.log(category)
|
||||
form.categoryId = category[category.length - 1];
|
||||
|
||||
if (form.id == null) {
|
||||
createSpu(form).then(() => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
}).then(()=>{
|
||||
this.cancel();
|
||||
})
|
||||
} else {
|
||||
updateSpu(form).then(() => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
}).then(()=>{
|
||||
this.cancel();
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
/** 查询规格 */
|
||||
getPropertyPageList() {
|
||||
// 执行查询
|
||||
getPropertyListAndValue().then((response) => {
|
||||
this.propertyPageList = response.data;
|
||||
});
|
||||
},
|
||||
// 添加规格项目
|
||||
changeSpec(val) {
|
||||
let obj = this.propertyPageList.find(o => o.id === val);
|
||||
let spec = this.dynamicSpec.find(o => o.specId === val)
|
||||
spec.specId = obj.id;
|
||||
spec.specName = obj.name;
|
||||
spec.specValue = obj.values;
|
||||
this.buildRatesFormRates();
|
||||
},
|
||||
updateType(id) {
|
||||
getSpuDetail(id).then((response) => {
|
||||
let data = response.data;
|
||||
this.baseForm.id = data.id;
|
||||
this.baseForm.name = data.name;
|
||||
this.baseForm.sellPoint = data.sellPoint;
|
||||
this.baseForm.categoryIds = data.categoryId;
|
||||
this.baseForm.videoUrl = data.videoUrl;
|
||||
this.baseForm.sort = data.sort;
|
||||
this.baseForm.description = data.description;
|
||||
this.baseForm.picUrls = data.picUrls;
|
||||
this.baseForm.status = data.status;
|
||||
this.baseForm.virtualSalesCount = data.virtualSalesCount;
|
||||
this.baseForm.showStock = data.showStock;
|
||||
this.baseForm.brandId = data.brandId;
|
||||
this.ratesForm.spec = data.specType;
|
||||
data.skus.forEach(r => {
|
||||
r.marketPrice = this.divide(r.marketPrice, 100)
|
||||
r.price = this.divide(r.price, 100)
|
||||
r.costPrice = this.divide(r.costPrice, 100)
|
||||
})
|
||||
if (this.ratesForm.spec === 2) {
|
||||
this.specSwitch = true;
|
||||
data.productPropertyViews.forEach(p => {
|
||||
let obj = {};
|
||||
obj.specId = p.propertyId;
|
||||
obj.specName = p.name;
|
||||
obj.specValue = p.propertyValues;
|
||||
this.dynamicSpec.push(obj);
|
||||
})
|
||||
data.skus.forEach(s => {
|
||||
s.spec = [];
|
||||
s.properties.forEach(sp => {
|
||||
let spec = data.productPropertyViews.find(o => o.propertyId === sp.propertyId).propertyValues.find(v => v.id === sp.valueId).name;
|
||||
s.spec.push(spec)
|
||||
})
|
||||
})
|
||||
}
|
||||
this.ratesForm.rates = data.skus
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container{
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.dynamic-spec {
|
||||
background-color: #f2f2f2;
|
||||
width: 85%;
|
||||
margin: auto;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.spec-header {
|
||||
padding: 30px;
|
||||
padding-bottom: 20px;
|
||||
|
||||
.spec-name {
|
||||
display: inline;
|
||||
|
||||
input {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spec-values {
|
||||
width: 84%;
|
||||
padding: 25px;
|
||||
margin: auto;
|
||||
padding-top: 5px;
|
||||
|
||||
.spec-value {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
width: 13%;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.spec-delete {
|
||||
float: right;
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
border-bottom: 2px solid #f2f2f2;
|
||||
|
||||
.el-tab-pane {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 库存价格图片样式修改
|
||||
.rates {
|
||||
.component-upload-image {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.el-upload--picture-card {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
line-height: 60px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.el-upload-list__item {
|
||||
width: 100px !important;
|
||||
height: 50px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
margin-top: 20px;
|
||||
height: 36px;
|
||||
|
||||
button {
|
||||
float: right;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.mall-image {
|
||||
.el-upload--picture-card {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
line-height: 90px;
|
||||
}
|
||||
|
||||
.el-upload-list__item {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,164 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="会员昵称" prop="nickname">
|
||||
<el-input v-model="queryParams.nickname" placeholder="请输入会员昵称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- Tab 选项:真正的内容在 Lab -->
|
||||
<el-tabs v-model="activeTab" type="card" @tab-click="tabClick" style="margin-top: -40px;">
|
||||
<el-tab-pane v-for="tab in statusTabs" :key="tab.value" :label="tab.label" :name="tab.value" />
|
||||
</el-tabs>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="会员信息" align="center" prop="nickname" /> <!-- TODO 芋艿:以后支持头像,支持跳转 -->
|
||||
<el-table-column label="优惠劵" align="center" prop="name" />
|
||||
<el-table-column label="优惠券类型" align="center" prop="discountType">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_DISCOUNT_TYPE" :value="scope.row.discountType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="领取方式" align="center" prop="takeType">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE" :value="scope.row.takeType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_COUPON_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="领取时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="使用时间" align="center" prop="useTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.useTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['promotion:coupon:delete']">回收</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deleteCoupon, getCouponPage } from "@/api/mall/promotion/coupon";
|
||||
import { DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
|
||||
export default {
|
||||
name: "PromotionCoupon",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 优惠劵列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
createTime: [],
|
||||
status: undefined,
|
||||
},
|
||||
// Tab 筛选
|
||||
activeTab: 'all',
|
||||
statusTabs: [{
|
||||
label: '全部',
|
||||
value: 'all'
|
||||
}],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 设置 statuses 过滤
|
||||
for (const dict of getDictDatas(DICT_TYPE.PROMOTION_COUPON_STATUS)) {
|
||||
this.statusTabs.push({
|
||||
label: dict.label,
|
||||
value: dict.value
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getCouponPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('回收将会收回会员领取的待使用的优惠券,已使用的将无法回收,确定要回收所选优惠券吗?').then(function() {
|
||||
return deleteCoupon(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("回收成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** tab 切换 */
|
||||
tabClick(tab) {
|
||||
this.queryParams.status = tab.name === 'all' ? undefined : tab.name;
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,404 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="82px">
|
||||
<el-form-item label="优惠券名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入优惠劵名" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠券类型" prop="discountType">
|
||||
<el-select v-model="queryParams.discountType" placeholder="请选择优惠券类型" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠券状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择优惠券状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['promotion:coupon-template:create']">新增</el-button>
|
||||
<el-button type="info" plain icon="el-icon-s-operation" size="mini"
|
||||
@click="() => this.$router.push('/promotion/coupon')"
|
||||
v-hasPermi="['promotion:coupon:query']">会员优惠劵</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="优惠券名称" align="center" prop="name" />
|
||||
<el-table-column label="优惠券类型" align="center" prop="discountType">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_DISCOUNT_TYPE" :value="scope.row.discountType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="优惠金额 / 折扣" align="center" prop="discount" :formatter="discountFormat" />
|
||||
<el-table-column label="发放数量" align="center" prop="totalCount" />
|
||||
<el-table-column label="剩余数量" align="center" prop="totalCount" :formatter="row => (row.totalCount - row.takeCount)" />
|
||||
<el-table-column label="领取上限" align="center" prop="takeLimitCount" :formatter="takeLimitCountFormat" />
|
||||
<el-table-column label="有效期限" align="center" prop="validityType" width="180" :formatter="validityTypeFormat" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['promotion:coupon-template:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['promotion:coupon-template:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
|
||||
<el-form-item label="优惠券名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入优惠券名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠券类型" prop="discountType">
|
||||
<el-radio-group v-model="form.discountType">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.discountType === PromotionDiscountTypeEnum.PRICE.type" label="优惠券面额" prop="discountPrice">
|
||||
<el-input-number v-model="form.discountPrice" placeholder="请输入优惠金额,单位:元"
|
||||
style="width: 400px" :precision="2" :min="0" /> 元
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.discountType === PromotionDiscountTypeEnum.PERCENT.type" label="优惠券折扣" prop="discountPercent">
|
||||
<el-input-number v-model="form.discountPercent" placeholder="优惠券折扣不能小于 1 折,且不可大于 9.9 折"
|
||||
style="width: 400px" :precision="1" :min="1" :max="9.9" /> 折
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.discountType === PromotionDiscountTypeEnum.PERCENT.type" label="最多优惠" prop="discountLimitPrice">
|
||||
<el-input-number v-model="form.discountLimitPrice" placeholder="请输入最多优惠"
|
||||
style="width: 400px" :precision="2" :min="0" /> 元
|
||||
</el-form-item>
|
||||
<el-form-item label="满多少元可以使用" prop="usePrice">
|
||||
<el-input-number v-model="form.usePrice" placeholder="无门槛请设为 0"
|
||||
style="width: 400px" :precision="2" :min="0" /> 元
|
||||
</el-form-item>
|
||||
<el-form-item label="领取方式" prop="takeType">
|
||||
<el-radio-group v-model="form.takeType">
|
||||
<el-radio :key="1" :label="1">直接领取</el-radio>
|
||||
<el-radio :key="2" :label="2">指定发放</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.takeType === 1" label="发放数量" prop="totalCount">
|
||||
<el-input-number v-model="form.totalCount" placeholder="发放数量,没有之后不能领取或发放,-1 为不限制"
|
||||
style="width: 400px" :precision="0" :min="-1" /> 张
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.takeType === 1" label="每人限领个数" prop="takeLimitCount">
|
||||
<el-input-number v-model="form.takeLimitCount" placeholder="设置为 -1 时,可无限领取"
|
||||
style="width: 400px" :precision="0" :min="-1" /> 张
|
||||
</el-form-item>
|
||||
<el-form-item label="有效期类型" prop="validityType">
|
||||
<el-radio-group v-model="form.validityType">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.validityType === CouponTemplateValidityTypeEnum.DATE.type" label="固定日期" prop="validTimes">
|
||||
<el-date-picker v-model="form.validTimes" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange"
|
||||
:default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.validityType === CouponTemplateValidityTypeEnum.TERM.type" label="领取日期" prop="fixedStartTerm">
|
||||
第 <el-input-number v-model="form.fixedStartTerm" placeholder="0 为今天生效"
|
||||
style="width: 165px" :precision="0" :min="0"/> 至
|
||||
<el-input-number v-model="form.fixedEndTerm" placeholder="请输入结束天数"
|
||||
style="width: 165px" :precision="0" :min="0"/> 天有效
|
||||
</el-form-item>
|
||||
<el-form-item label="活动商品" prop="productScope">
|
||||
<el-radio-group v-model="form.productScope">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.productScope === PromotionProductScopeEnum.SPU.scope" prop="productSpuIds">
|
||||
<el-select v-model="form.productSpuIds" placeholder="请选择活动商品" clearable size="small"
|
||||
multiple filterable style="width: 400px">
|
||||
<el-option v-for="item in productSpus" :key="item.id" :label="item.name" :value="item.id">
|
||||
<span style="float: left">{{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.minPrice / 100.0).toFixed(2) }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createCouponTemplate,
|
||||
updateCouponTemplate,
|
||||
deleteCouponTemplate,
|
||||
getCouponTemplate,
|
||||
getCouponTemplatePage,
|
||||
updateCouponTemplateStatus
|
||||
} from "@/api/mall/promotion/couponTemplate";
|
||||
import {
|
||||
CommonStatusEnum,
|
||||
CouponTemplateValidityTypeEnum,
|
||||
PromotionDiscountTypeEnum,
|
||||
PromotionProductScopeEnum
|
||||
} from "@/utils/constants";
|
||||
import { getSpuSimpleList } from "@/api/mall/product/spu";
|
||||
import { parseTime } from "@/utils/ruoyi";
|
||||
import {changeRoleStatus} from "@/api/system/role";
|
||||
|
||||
export default {
|
||||
name: "PromotionCouponTemplate",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 优惠劵列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
type: null,
|
||||
createTime: [],
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "优惠券名称不能为空", trigger: "blur" }],
|
||||
discountType: [{ required: true, message: "优惠券类型不能为空", trigger: "change" }],
|
||||
discountPrice: [{ required: true, message: "优惠券面额不能为空", trigger: "blur" }],
|
||||
discountPercent: [{ required: true, message: "优惠券折扣不能为空", trigger: "blur" }],
|
||||
discountLimitPrice: [{ required: true, message: "最多优惠不能为空", trigger: "blur" }],
|
||||
usePrice: [{ required: true, message: "满多少元可以使用不能为空", trigger: "blur" }],
|
||||
takeType: [{ required: true, message: "领取方式不能为空", trigger: "change" }],
|
||||
totalCount: [{ required: true, message: "发放数量不能为空", trigger: "blur" }],
|
||||
takeLimitCount: [{ required: true, message: "每人限领个数不能为空", trigger: "blur" }],
|
||||
validityType: [{ required: true, message: "有效期类型不能为空", trigger: "change" }],
|
||||
validTimes: [{ required: true, message: "固定日期不能为空", trigger: "change" }],
|
||||
fixedStartTerm: [{ required: true, message: "开始领取天数不能为空", trigger: "blur" }],
|
||||
fixedEndTerm: [{ required: true, message: "开始领取天数不能为空", trigger: "blur" }],
|
||||
productScope: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
|
||||
productSpuIds: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
|
||||
},
|
||||
// 商品列表
|
||||
productSpus: [],
|
||||
// 如下的变量,主要为了 v-if 判断可以使用到
|
||||
PromotionProductScopeEnum: PromotionProductScopeEnum,
|
||||
CouponTemplateValidityTypeEnum: CouponTemplateValidityTypeEnum,
|
||||
PromotionDiscountTypeEnum: PromotionDiscountTypeEnum,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getCouponTemplatePage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
// 查询商品列表
|
||||
getSpuSimpleList().then(response => {
|
||||
this.productSpus = response.data
|
||||
})
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
discountType: PromotionDiscountTypeEnum.PRICE.type,
|
||||
discountPrice: undefined,
|
||||
discountPercent: undefined,
|
||||
discountLimitPrice: undefined,
|
||||
usePrice: undefined,
|
||||
takeType: 1,
|
||||
totalCount: undefined,
|
||||
takeLimitCount: undefined,
|
||||
validityType: CouponTemplateValidityTypeEnum.DATE.type,
|
||||
validTimes: [],
|
||||
validStartTime: undefined,
|
||||
validEndTime: undefined,
|
||||
fixedStartTerm: undefined,
|
||||
fixedEndTerm: undefined,
|
||||
productScope: PromotionProductScopeEnum.ALL.scope,
|
||||
productSpuIds: [],
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加优惠劵";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getCouponTemplate(id).then(response => {
|
||||
this.form = {
|
||||
...response.data,
|
||||
discountPrice: response.data.discountPrice !== undefined ? response.data.discountPrice / 100.0 : undefined,
|
||||
discountPercent: response.data.discountPercent !== undefined ? response.data.discountPercent / 10.0 : undefined,
|
||||
discountLimitPrice: response.data.discountLimitPrice !== undefined ? response.data.discountLimitPrice / 100.0 : undefined,
|
||||
usePrice: response.data.usePrice !== undefined ? response.data.usePrice / 100.0 : undefined,
|
||||
validTimes: [response.data.validStartTime, response.data.validEndTime]
|
||||
}
|
||||
this.open = true;
|
||||
this.title = "修改优惠劵";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 金额相关字段的缩放
|
||||
let data = {
|
||||
...this.form,
|
||||
discountPrice: this.form.discountPrice !== undefined ? this.form.discountPrice * 100 : undefined,
|
||||
discountPercent: this.form.discountPercent !== undefined ? this.form.discountPercent * 10 : undefined,
|
||||
discountLimitPrice: this.form.discountLimitPrice !== undefined ? this.form.discountLimitPrice * 100 : undefined,
|
||||
usePrice: this.form.usePrice !== undefined ? this.form.usePrice * 100 : undefined,
|
||||
validStartTime: this.form.validTimes && this.form.validTimes.length === 2 ? this.form.validTimes[0] : undefined,
|
||||
validEndTime: this.form.validTimes && this.form.validTimes.length === 2 ? this.form.validTimes[1] : undefined,
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateCouponTemplate(data).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createCouponTemplate(data).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 优惠劵模板状态修改 */
|
||||
handleStatusChange(row) {
|
||||
// 此时,row 已经变成目标状态了,所以可以直接提交请求和提示
|
||||
let text = row.status === CommonStatusEnum.ENABLE ? "启用" : "停用";
|
||||
this.$modal.confirm('确认要"' + text + '""' + row.name + '"优惠劵吗?').then(function() {
|
||||
return updateCouponTemplateStatus(row.id, row.status);
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess(text + "成功");
|
||||
}).catch(function() {
|
||||
// 异常时,需要将 row.status 状态重置回之前的
|
||||
row.status = row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE
|
||||
: CommonStatusEnum.ENABLE;
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除优惠劵编号为"' + id + '"的数据项?').then(function() {
|
||||
return deleteCouponTemplate(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
// 格式化【优惠金额/折扣】
|
||||
discountFormat(row, column) {
|
||||
if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return `¥${(row.discountPrice / 100.0).toFixed(2)}`;
|
||||
}
|
||||
if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return `¥${(row.discountPrice / 100.0).toFixed(2)}`;
|
||||
}
|
||||
return '未知【' + row.discountType + '】';
|
||||
},
|
||||
// 格式化【领取上限】
|
||||
takeLimitCountFormat(row, column) {
|
||||
if (row.takeLimitCount === -1) {
|
||||
return '无领取限制';
|
||||
}
|
||||
return `${row.takeLimitCount} 张/人`
|
||||
},
|
||||
// 格式化【有效期限】
|
||||
validityTypeFormat(row, column) {
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
|
||||
return `${parseTime(row.validStartTime)} 至 ${parseTime(row.validEndTime)}`
|
||||
}
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
|
||||
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
}
|
||||
return '未知【' + row.validityType + '】';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,383 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="活动名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入活动名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['promotion:discount-activity:create']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="活动名称" align="center" prop="name" />
|
||||
<el-table-column label="活动时间" align="center" prop="startTime" width="240">
|
||||
<template v-slot="scope">
|
||||
<div>开始:{{ parseTime(scope.row.startTime) }}</div>
|
||||
<div>结束:{{ parseTime(scope.row.endTime) }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type"
|
||||
v-hasPermi="['promotion:discount-activity:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleClose(scope.row)"
|
||||
v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type &&
|
||||
scope.row.status !== PromotionActivityStatusEnum.END.type"
|
||||
v-hasPermi="['promotion:discount-activity:close']">关闭</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-if="scope.row.status === PromotionActivityStatusEnum.CLOSE.type"
|
||||
v-hasPermi="['promotion:discount-activity:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="1000px" v-dialogDrag append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="活动名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入活动名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间" prop="startAndEndTime">
|
||||
<el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange" :default-time="['00:00:00', '23:59:59']"
|
||||
value-format="timestamp" placeholder="选择开始时间" style="width: 880px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品选择">
|
||||
<el-select v-model="form.skuIds" placeholder="请选择活动商品" clearable size="small"
|
||||
multiple filterable style="width: 880px" @change="changeFormSku">
|
||||
<el-option v-for="item in productSkus" :key="item.id" :label="item.spuName + ' ' + item.name" :value="item.id">
|
||||
<span style="float: left">{{ item.spuName }} {{ item.name}}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price / 100.0).toFixed(2) }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-table v-loading="loading" :data="form.products">
|
||||
<el-table-column label="商品名称" align="center" width="200">
|
||||
<template v-slot="scope">
|
||||
{{ scope.row.spuName }} {{ scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品价格" align="center" prop="price">
|
||||
<template v-slot="scope">
|
||||
¥{{ (scope.row.price / 100.0).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" align="center" prop="stock" />
|
||||
<el-table-column label="优惠类型" align="center" property="discountType">
|
||||
<template v-slot="scope">
|
||||
<el-select v-model="scope.row.discountType" placeholder="请选择优惠类型">
|
||||
<el-option v-for="dict in getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="优惠" align="center" prop="startTime" width="250">
|
||||
<template v-slot="scope">
|
||||
<el-form-item v-if="scope.row.discountType === PromotionDiscountTypeEnum.PRICE.type" prop="discountPrice">
|
||||
减 <el-input-number v-model="scope.row.discountPrice" placeholder="请输入优惠金额"
|
||||
style="width: 190px" :precision="2" :min="0" :max="scope.row.price / 100.0 - 0.01" /> 元
|
||||
</el-form-item>
|
||||
<el-form-item v-if="scope.row.discountType === PromotionDiscountTypeEnum.PERCENT.type" prop="discountPercent">
|
||||
打 <el-input-number v-model="scope.row.discountPercent" placeholder="请输入优惠折扣"
|
||||
style="width: 190px" :precision="1" :min="1" :max="9.9" /> 折
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="removeFormSku(scope.row.skuId)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createDiscountActivity,
|
||||
updateDiscountActivity,
|
||||
deleteDiscountActivity,
|
||||
getDiscountActivity,
|
||||
getDiscountActivityPage,
|
||||
closeDiscountActivity
|
||||
} from "@/api/mall/promotion/discountActivity";
|
||||
import {
|
||||
PromotionActivityStatusEnum, PromotionDiscountTypeEnum,
|
||||
PromotionProductScopeEnum
|
||||
} from "@/utils/constants";
|
||||
import { getSkuOptionList } from "@/api/mall/product/sku";
|
||||
import { deepClone } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "PromotionDiscountActivity",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 限时折扣活动列表
|
||||
list: [],
|
||||
// 弹出层名称
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
createTime: [],
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
skuIds: [], // 选中的 SKU
|
||||
products: [], // 商品信息
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "活动名称不能为空", trigger: "blur" }],
|
||||
startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
|
||||
skuIds: [{ required: true, message: "选择商品不能为空", trigger: "blur" }],
|
||||
},
|
||||
// 商品 SKU 列表
|
||||
productSkus: [],
|
||||
// 如下的变量,主要为了 v-if 判断可以使用到
|
||||
PromotionProductScopeEnum: PromotionProductScopeEnum,
|
||||
PromotionActivityStatusEnum: PromotionActivityStatusEnum,
|
||||
PromotionDiscountTypeEnum: PromotionDiscountTypeEnum,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getDiscountActivityPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
// 获得 SKU 商品列表
|
||||
getSkuOptionList().then(response => {
|
||||
this.productSkus = response.data;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
startAndEndTime: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
remark: undefined,
|
||||
skuIds: [],
|
||||
products: [],
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加限时折扣活动";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getDiscountActivity(id).then(response => {
|
||||
this.form = response.data;
|
||||
// 修改数据
|
||||
this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
|
||||
this.form.skuIds = response.data.products.map(item => item.skuId);
|
||||
this.form.products.forEach(product => {
|
||||
// 获得对应的 SKU 信息
|
||||
const sku = this.productSkus.find(item => item.id === product.skuId);
|
||||
if (!sku) {
|
||||
return;
|
||||
}
|
||||
// 设置商品信息
|
||||
product.name = sku.name;
|
||||
product.spuName = sku.spuName;
|
||||
product.price = sku.price;
|
||||
product.stock = sku.stock;
|
||||
product.discountPrice = product.discountPrice !== undefined ? product.discountPrice / 100.0 : undefined;
|
||||
product.discountPercent = product.discountPercent !== undefined ? product.discountPercent / 10.0 : undefined;
|
||||
});
|
||||
// 打开弹窗
|
||||
this.open = true;
|
||||
this.title = "修改限时折扣活动";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 处理数据
|
||||
const data = deepClone(this.form); // 必须深拷贝,不然后面的 products 操作会有影响
|
||||
data.startTime = this.form.startAndEndTime[0];
|
||||
data.endTime = this.form.startAndEndTime[1];
|
||||
data.products.forEach(product => {
|
||||
product.discountPrice = product.discountPrice !== undefined ? product.discountPrice * 100 : undefined;
|
||||
product.discountPercent = product.discountPercent !== undefined ? product.discountPercent * 10 : undefined;
|
||||
});
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateDiscountActivity(data).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createDiscountActivity(data).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除限时折扣活动编号为"' + id + '"的数据项?').then(function() {
|
||||
return deleteDiscountActivity(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 关闭按钮操作 */
|
||||
handleClose(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认关闭限时折扣活动编号为"' + id + '"的数据项?').then(function() {
|
||||
return closeDiscountActivity(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("关闭成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 当 Form 的 SKU 发生变化时 */
|
||||
changeFormSku(skuIds) {
|
||||
// 处理【新增】
|
||||
skuIds.forEach(skuId => {
|
||||
// 获得对应的 SKU 信息
|
||||
const sku = this.productSkus.find(item => item.id === skuId);
|
||||
if (!sku) {
|
||||
return;
|
||||
}
|
||||
// 判断已存在,直接跳过
|
||||
const product = this.form.products.find(item => item.skuId === skuId);
|
||||
if (product) {
|
||||
return;
|
||||
}
|
||||
this.form.products.push({
|
||||
skuId: sku.id,
|
||||
name: sku.name,
|
||||
price: sku.price,
|
||||
stock: sku.stock,
|
||||
spuId: sku.spuId,
|
||||
spuName: sku.spuName,
|
||||
discountType: PromotionDiscountTypeEnum.PRICE.type,
|
||||
});
|
||||
});
|
||||
// 处理【移除】
|
||||
this.form.products.map((product, index) => {
|
||||
if (!skuIds.includes(product.skuId)) {
|
||||
this.form.products.splice(index, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 移除 Form 的 SKU */
|
||||
removeFormSku(skuId) {
|
||||
this.form.skuIds.map((id, index) => {
|
||||
if (skuId === id) {
|
||||
this.form.skuIds.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.changeFormSku(this.form.skuIds);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,306 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="活动名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入活动名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['promotion:reward-activity:create']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="活动名称" align="center" prop="name" />
|
||||
<el-table-column label="活动时间" align="center" prop="startTime" width="240">
|
||||
<template v-slot="scope">
|
||||
<div>开始:{{ parseTime(scope.row.startTime) }}</div>
|
||||
<div>结束:{{ parseTime(scope.row.endTime) }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type"
|
||||
v-hasPermi="['promotion:reward-activity:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleClose(scope.row)"
|
||||
v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type &&
|
||||
scope.row.status !== PromotionActivityStatusEnum.END.type"
|
||||
v-hasPermi="['promotion:reward-activity:close']">关闭</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-if="scope.row.status === PromotionActivityStatusEnum.CLOSE.type"
|
||||
v-hasPermi="['promotion:reward-activity:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="活动名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入活动名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间" prop="startAndEndTime">
|
||||
<el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange" :default-time="['00:00:00', '23:59:59']"
|
||||
value-format="timestamp" placeholder="选择开始时间" style="width: 480px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="条件类型" prop="conditionType">
|
||||
<el-radio-group v-model="form.conditionType">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_CONDITION_TYPE)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠设置" prop="conditionType">
|
||||
<!-- TODO 芋艿:待实现! -->
|
||||
</el-form-item>
|
||||
<el-form-item label="活动商品" prop="productScope">
|
||||
<el-radio-group v-model="form.productScope">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.productScope === PromotionProductScopeEnum.SPU.scope" prop="productSpuIds">
|
||||
<el-select v-model="form.productSpuIds" placeholder="请选择活动商品" clearable size="small"
|
||||
multiple filterable style="width: 400px">
|
||||
<el-option v-for="item in productSpus" :key="item.id" :label="item.name" :value="item.id">
|
||||
<span style="float: left">{{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.minPrice / 100.0).toFixed(2) }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createRewardActivity,
|
||||
updateRewardActivity,
|
||||
deleteRewardActivity,
|
||||
getRewardActivity,
|
||||
getRewardActivityPage,
|
||||
closeRewardActivity
|
||||
} from "@/api/mall/promotion/rewardActivity";
|
||||
import {
|
||||
PromotionConditionTypeEnum,
|
||||
PromotionProductScopeEnum,
|
||||
PromotionActivityStatusEnum
|
||||
} from "@/utils/constants";
|
||||
import {getSpuSimpleList} from "@/api/mall/product/spu";
|
||||
|
||||
export default {
|
||||
name: "PromotionRewardActivity",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 满减送活动列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "活动名称不能为空", trigger: "blur" }],
|
||||
startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
|
||||
conditionType: [{ required: true, message: "条件类型不能为空", trigger: "change" }],
|
||||
productScope: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
|
||||
productSpuIds: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
|
||||
},
|
||||
// 商品列表
|
||||
productSpus: [],
|
||||
// 如下的变量,主要为了 v-if 判断可以使用到
|
||||
PromotionProductScopeEnum: PromotionProductScopeEnum,
|
||||
PromotionActivityStatusEnum: PromotionActivityStatusEnum,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 查询商品列表
|
||||
getSpuSimpleList().then(response => {
|
||||
this.productSpus = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getRewardActivityPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
startAndEndTime: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
conditionType: PromotionConditionTypeEnum.PRICE.type,
|
||||
remark: undefined,
|
||||
productScope: PromotionProductScopeEnum.ALL.scope,
|
||||
productSpuIds: undefined,
|
||||
rules: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加满减送活动";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getRewardActivity(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
|
||||
this.open = true;
|
||||
this.title = "修改满减送活动";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
this.form.startTime = this.form.startAndEndTime[0];
|
||||
this.form.endTime = this.form.startAndEndTime[1];
|
||||
// TODO 芋艿:临时实现
|
||||
this.form.rules = [
|
||||
{
|
||||
limit: 1,
|
||||
discountPrice: 10,
|
||||
freeDelivery: true,
|
||||
point: 10,
|
||||
couponIds: [10, 20],
|
||||
couponCounts: [1, 2]
|
||||
}, {
|
||||
limit: 2,
|
||||
discountPrice: 20,
|
||||
freeDelivery: false,
|
||||
point: 20,
|
||||
couponIds: [30, 40],
|
||||
couponCounts: [3, 4]
|
||||
}
|
||||
];
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateRewardActivity(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createRewardActivity(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除满减送活动编号为"' + id + '"的数据项?').then(function() {
|
||||
return deleteRewardActivity(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 关闭按钮操作 */
|
||||
handleClose(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认关闭满减送活动编号为"' + id + '"的数据项?').then(function() {
|
||||
return closeRewardActivity(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("关闭成功");
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,491 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
|
||||
label-width="68px">
|
||||
<el-form-item label="活动名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入秒杀活动名称" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="活动状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)" :key="dict.value"
|
||||
:label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="参与场次" prop="timeId">
|
||||
<el-select v-model="queryParams.timeId" placeholder="请选择参与场次" clearable size="small">
|
||||
<el-option v-for="item in seckillTimeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['promotion:seckill-activity:create']">新增秒杀活动</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-menu" size="mini" @click="openSeckillTime"
|
||||
v-hasPermi="['promotion:seckill-activity:create']">管理参与场次</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="活动名称" align="center" prop="name" />
|
||||
<el-table-column label="活动状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参与场次" prop="timeIds" width="250">
|
||||
<template v-slot="scope">
|
||||
<span v-for="item in seckillTimeList" :key="item.id"
|
||||
v-if="scope.row.timeIds.includes(item.id)">
|
||||
<el-tag style="margin:4px;" size="small">{{ item.name }}</el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="活动开始时间" align="center" prop="startTime" width="190">
|
||||
<template v-slot="scope">
|
||||
<span>{{ "开始: " + parseTime(scope.row.startTime) }}</span>
|
||||
<span>{{ "结束: " + parseTime(scope.row.endTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="付款订单数" align="center" prop="orderCount" />
|
||||
<el-table-column label="付款人数" align="center" prop="userCount" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['promotion:seckill-activity:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-close" @click="handleClose(scope.row)"
|
||||
v-hasPermi="['promotion:seckill-activity:delete']">关闭</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['promotion:seckill-activity:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="1200px" v-dialogDrag append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="活动名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入秒杀活动名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间" prop="startAndEndTime">
|
||||
<el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange"
|
||||
value-format="timestamp" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
style="width: 1080px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="form.sort" controls-position="right" :min="0" :max="10000">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="场次选择">
|
||||
<el-select v-model="form.timeIds" placeholder="请选择参与场次" clearable size="small" multiple filterable
|
||||
style="width: 880px">
|
||||
<el-option v-for="item in seckillTimeList" :key="item.id" :label="item.name" :value="item.id">
|
||||
<span style="float: left">{{ item.name + ': { ' }} {{ item.startTime }} -- {{ item.endTime +
|
||||
' }'
|
||||
}}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px"></span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品选择">
|
||||
<el-select v-model="form.skuIds" placeholder="请选择活动商品" clearable size="small" multiple filterable
|
||||
style="width: 880px" @change="changeFormSku">
|
||||
<el-option v-for="item in productSkus" :key="item.id" :label="item.spuName + ' ' + item.name"
|
||||
:value="item.id">
|
||||
<span style="float: left">{{ item.spuName }} {{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price /
|
||||
100.0).toFixed(2)
|
||||
}}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-row>
|
||||
<el-button type="primary" size="mini" @click="batchEditProduct('limitBuyCount')">限购</el-button>
|
||||
<el-button type="primary" size="mini" @click="batchEditProduct('seckillPrice')">秒杀价</el-button>
|
||||
<el-button type="primary" size="mini" @click="batchEditProduct('seckillStock')">秒杀库存</el-button>
|
||||
</el-row>
|
||||
<el-table v-loading="loading" ref="productsTable" :data="form.products">
|
||||
<el-table-column type="selection" width="55">
|
||||
</el-table-column>
|
||||
<el-table-column label="商品名称" align="center" width="200">
|
||||
<template v-slot="scope">
|
||||
{{ scope.row.spuName }} {{ scope.row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品价格" align="center" prop="price">
|
||||
<template v-slot="scope">
|
||||
¥{{ (scope.row.price / 100.0).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" align="center" prop="productStock" />
|
||||
<el-table-column label="限购(0为不限购)" align="center" width="150">
|
||||
<template v-slot="scope">
|
||||
<el-input-number v-model="scope.row.limitBuyCount" size="mini" :min="0" :max="10000">
|
||||
</el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="秒杀价(元)" align="center" width="150">
|
||||
<template v-slot="scope">
|
||||
<el-input-number v-model="scope.row.seckillPrice" size="mini" :precision="2" :min="0"
|
||||
:max="10000">
|
||||
</el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="秒杀库存" align="center" width="150" prop="seckillStock">
|
||||
<template v-slot="scope">
|
||||
<el-input-number v-model="scope.row.seckillStock" size="mini" :min="0" :max="10000">
|
||||
</el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete"
|
||||
@click="removeFormSku(scope.row.skuId)">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSkuOptionList } from "@/api/mall/product/sku";
|
||||
import { createSeckillActivity, updateSeckillActivity, closeSeckillActivity, deleteSeckillActivity, getSeckillActivity, getSeckillActivityPage, exportSeckillActivityExcel } from "@/api/mall/promotion/seckillActivity";
|
||||
import { getSeckillTimeList } from "@/api/mall/promotion/seckillTime";
|
||||
import { deepClone } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "PromotionSeckillActivity",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 秒杀活动列表
|
||||
list: [],
|
||||
// 秒杀场次列表
|
||||
seckillTimeList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
timeId: null,
|
||||
createTime: [],
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
skuIds: [], // 选中的 SKU
|
||||
products: [], // 商品信息
|
||||
timeIds: [], //选中的秒杀场次id
|
||||
},
|
||||
// 商品 SKU 列表
|
||||
productSkus: [],
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "秒杀活动名称不能为空", trigger: "blur" }],
|
||||
status: [{ required: true, message: "活动状态不能为空", trigger: "blur" }],
|
||||
startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
|
||||
sort: [{ required: true, message: "排序不能为空", trigger: "blur" }],
|
||||
timeIds: [{ required: true, message: "秒杀场次不能为空", trigger: "blur" }],
|
||||
totalPrice: [{ required: true, message: "订单实付金额,单位:分不能为空", trigger: "blur" }],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
watch: {
|
||||
$route: 'getList'
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 从秒杀时段跳转过来并鞋带timeId参数进行查询
|
||||
const timeId = this.$route.params && this.$route.params.timeId;
|
||||
if (timeId) {
|
||||
this.queryParams.timeId = timeId
|
||||
}
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getSeckillActivityPage(this.queryParams).then(response => {
|
||||
console.log(response.data.list, "查询出的值");
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
if (timeId) {
|
||||
//查询完成后设置为空
|
||||
this.$route.params.timeId = undefined
|
||||
}
|
||||
// 获得 SKU 商品列表
|
||||
getSkuOptionList().then(response => {
|
||||
this.productSkus = response.data;
|
||||
});
|
||||
// 获取参与场次列表
|
||||
getSeckillTimeList().then(response => {
|
||||
this.seckillTimeList = response.data;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
sort: undefined,
|
||||
timeIds: [],
|
||||
totalPrice: undefined,
|
||||
skuIds: [],
|
||||
products: [],
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/**打开秒杀场次管理页面 */
|
||||
openSeckillTime() {
|
||||
this.$tab.openPage("秒杀场次管理", "/promotion/seckill-time");
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加秒杀活动";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getSeckillActivity(id).then(response => {
|
||||
this.form = response.data;
|
||||
// 修改数据
|
||||
this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
|
||||
this.form.skuIds = response.data.products.map(item => item.skuId);
|
||||
this.form.products.forEach(product => {
|
||||
// 获得对应的 SKU 信息
|
||||
const sku = this.productSkus.find(item => item.id === product.skuId);
|
||||
if (!sku) {
|
||||
return;
|
||||
}
|
||||
// 设置商品信息
|
||||
product.name = sku.name;
|
||||
product.spuName = sku.spuName;
|
||||
product.price = sku.price;
|
||||
product.productStock = sku.stock;
|
||||
this.$set(product, 'seckillStock', product.stock);
|
||||
product.seckillPrice = product.seckillPrice !== undefined ? product.seckillPrice / 100 : undefined;
|
||||
|
||||
});
|
||||
// 打开弹窗
|
||||
this.open = true;
|
||||
this.title = "修改限时折扣活动";
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 处理数据
|
||||
const data = deepClone(this.form);
|
||||
data.startTime = this.form.startAndEndTime[0];
|
||||
data.endTime = this.form.startAndEndTime[1];
|
||||
data.products.forEach(product => {
|
||||
product.stock = product.seckillStock;
|
||||
product.seckillPrice = product.seckillPrice !== undefined ? product.seckillPrice * 100 : undefined;
|
||||
});
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateSeckillActivity(data).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createSeckillActivity(data).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 关闭按钮操作 */
|
||||
handleClose(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认关闭秒杀活动编号为"' + id + '"的数据项?').then(function () {
|
||||
return closeSeckillActivity(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("关闭成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除秒杀活动编号为"' + id + '"的数据项?').then(function () {
|
||||
return deleteSeckillActivity(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
/** 批量修改商品秒杀价,秒杀库存,每人限购数量 */
|
||||
batchEditProduct(editType) {
|
||||
const selectProducts = this.$refs.productsTable.selection;
|
||||
if (selectProducts.length === 0) {
|
||||
this.$modal.msgError("请选择需要修改的商品");
|
||||
return;
|
||||
}
|
||||
let promptTitle = '请输入';
|
||||
let regularPattern = /^[\s\S]*.*[^\s][\s\S]*$/; // 判断非空,且非空格
|
||||
//限购数
|
||||
if (editType === 'limitBuyCount') {
|
||||
promptTitle = '限购数';
|
||||
regularPattern = /^[0-9]*$/; //数字
|
||||
}
|
||||
//秒杀价
|
||||
if (editType === 'seckillPrice') {
|
||||
promptTitle = '秒杀价(元)';
|
||||
regularPattern = /^[0-9]+(\.[0-9]{1,2})?$/; // 有一位或两位小数的正数
|
||||
}
|
||||
//秒杀库存
|
||||
if (editType === 'seckillStock') {
|
||||
promptTitle = '秒杀库存';
|
||||
regularPattern = /^[0-9]*$/; //数字
|
||||
}
|
||||
|
||||
this.$prompt(promptTitle, '提示', {
|
||||
confirmButtonText: '保存',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: regularPattern,
|
||||
inputErrorMessage: promptTitle + '格式不正确'
|
||||
}).then(({ value }) => {
|
||||
if (editType === 'limitBuyCount') {
|
||||
selectProducts.forEach((item) => {
|
||||
item.limitBuyCount = value;
|
||||
})
|
||||
}
|
||||
if (editType === 'seckillPrice') {
|
||||
selectProducts.forEach((item) => {
|
||||
item.seckillPrice = value;
|
||||
})
|
||||
}
|
||||
if (editType === 'seckillStock') {
|
||||
selectProducts.forEach((item) => {
|
||||
item.seckillStock = value;
|
||||
})
|
||||
}
|
||||
}).catch();
|
||||
},
|
||||
/** 当 Form 的 SKU 发生变化时 */
|
||||
changeFormSku(skuIds) {
|
||||
// 处理【新增】
|
||||
skuIds.forEach(skuId => {
|
||||
// 获得对应的 SKU 信息
|
||||
const sku = this.productSkus.find(item => item.id === skuId);
|
||||
if (!sku) {
|
||||
return;
|
||||
}
|
||||
// 判断已存在,直接跳过
|
||||
const product = this.form.products.find(item => item.skuId === skuId);
|
||||
if (product) {
|
||||
return;
|
||||
}
|
||||
this.form.products.push({
|
||||
skuId: sku.id,
|
||||
name: sku.name,
|
||||
price: sku.price,
|
||||
productStock: sku.stock,
|
||||
spuId: sku.spuId,
|
||||
spuName: sku.spuName,
|
||||
limitBuyCount: 1,
|
||||
seckillStock: sku.stock,
|
||||
seckillPrice: sku.price,
|
||||
});
|
||||
});
|
||||
// 处理【移除】
|
||||
this.form.products.map((product, index) => {
|
||||
if (!skuIds.includes(product.skuId)) {
|
||||
this.form.products.splice(index, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 移除 Form 的 SKU */
|
||||
removeFormSku(skuId) {
|
||||
this.form.skuIds.map((id, index) => {
|
||||
if (skuId === id) {
|
||||
this.form.skuIds.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.changeFormSku(this.form.skuIds);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['promotion:seckill-time:create']">新增秒杀时段</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="秒杀时段名称" align="center" prop="name" />
|
||||
<el-table-column label="开始时间点" align="center" prop="startTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ scope.row.startTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间点" align="center" prop="endTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ scope.row.endTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="秒杀活动数量" align="center" prop="seckillActivityCount" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleOpenSeckillActivity(scope.row)">
|
||||
查看秒杀活动</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['promotion:seckill-time:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['promotion:seckill-time:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
|
||||
<el-form-item label="秒杀场次名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入秒杀时段名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="秒杀时间段" prop="startAndEndTime">
|
||||
<el-time-picker is-range v-model="form.startAndEndTime" range-separator="至" start-placeholder="开始时间"
|
||||
end-placeholder="结束时间" placeholder="选择时间范围" value-format="HH:mm:ss">
|
||||
</el-time-picker>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createSeckillTime, updateSeckillTime, deleteSeckillTime, getSeckillTime, getSeckillTimePage, exportSeckillTimeExcel, getSeckillTimeList } from "@/api/mall/promotion/seckillTime";
|
||||
import router from "@/router";
|
||||
import { deepClone } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "PromotionSeckillTime",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
// total: 0,
|
||||
// 秒杀时段列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: "秒杀时段名称不能为空", trigger: "blur" }],
|
||||
startAndEndTime: [{ required: true, message: "秒杀时间段不能为空", trigger: "blur" }],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getSeckillTimeList().then(response => {
|
||||
this.list = response.data;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
startAndEndTime: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/**查看当前秒杀时段的秒杀活动 */
|
||||
handleOpenSeckillActivity(row) {
|
||||
router.push({ name: 'SeckillActivity', params: { timeId: row.id } })
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加秒杀时段";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getSeckillTime(id).then(response => {
|
||||
response.data.startAndEndTime = [response.data.startTime, response.data.endTime]
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改秒杀时段";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
console.log(valid, "是否通过");
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 处理数据
|
||||
const data = deepClone(this.form);
|
||||
data.startTime = this.form.startAndEndTime[0];
|
||||
data.endTime = this.form.startAndEndTime[1];
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateSeckillTime(data).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createSeckillTime(data).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除秒杀时段编号为"' + id + '"的数据项?').then(function () {
|
||||
return deleteSeckillTime(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,229 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="商品名称" prop="spuName">
|
||||
<el-input v-model="queryParams.spuName" placeholder="请输入商品 SPU 名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款编号" prop="no">
|
||||
<el-input v-model="queryParams.no" placeholder="请输入退款编号" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单编号" prop="orderNo">
|
||||
<el-input v-model="queryParams.orderNo" placeholder="请输入订单编号" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="售后状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择售后状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="售后方式" prop="way">
|
||||
<el-select v-model="queryParams.way" placeholder="请选择售后方式" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_WAY)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="售后类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择售后类型" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:picker-options="datePickerOptions" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- Tab 选项:真正的内容在 Table -->
|
||||
<el-tabs v-model="activeTab" type="card" @tab-click="tabClick" style="margin-top: -40px;">
|
||||
<el-tab-pane v-for="tab in statusTabs" :key="tab.value" :label="tab.label" :name="tab.value" />
|
||||
</el-tabs>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="退款编号" align="center" prop="no" />
|
||||
<el-table-column label="订单编号" align="center" prop="orderNo" /> <!-- TODO 芋艿:未来要加个订单链接 -->
|
||||
<el-table-column label="商品信息" align="center" prop="spuName" width="auto" min-width="300">
|
||||
<!-- TODO @小红:样式不太对,辛苦改改 -->
|
||||
<!-- <div v-slot="{ row }" class="goods-info">-->
|
||||
<!-- <img :src="row.picUrl"/>-->
|
||||
<!-- <span class="ellipsis-2" :title="row.name">{{row.name}}</span>-->
|
||||
<!-- </div>-->
|
||||
</el-table-column>
|
||||
<el-table-column label="订单金额" align="center" prop="refundPrice">
|
||||
<template v-slot="scope">
|
||||
<span>¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="买家" align="center" prop="user.nickname" /> <!-- TODO 芋艿:未来要加个会员链接 -->
|
||||
<el-table-column label="申请时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="售后状态" align="center">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.TRADE_AFTER_SALE_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="售后方式" align="center">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.TRADE_AFTER_SALE_WAY" :value="scope.row.way" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-thumb"
|
||||
>处理退款</el-button>
|
||||
<!-- @click="handleUpdate(scope.row)" v-hasPermi="['trade:after-sale:update']"-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAfterSalePage } from "@/api/mall/trade/afterSale";
|
||||
import { datePickerOptions } from "@/utils/constants";
|
||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
|
||||
|
||||
export default {
|
||||
name: "TradeAfterSale",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 交易售后列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
no: null,
|
||||
status: null,
|
||||
orderNo: null,
|
||||
spuName: null,
|
||||
createTime: [],
|
||||
way: null,
|
||||
type: null,
|
||||
},
|
||||
// Tab 筛选
|
||||
activeTab: 'all',
|
||||
statusTabs: [{
|
||||
label: '全部',
|
||||
value: 'all'
|
||||
}],
|
||||
// 静态变量
|
||||
datePickerOptions: datePickerOptions
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 设置 statuses 过滤
|
||||
for (const dict of getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_STATUS)) {
|
||||
this.statusTabs.push({
|
||||
label: dict.label,
|
||||
value: dict.value
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getAfterSalePage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.activeTab = this.queryParams.status ? this.queryParams.status : 'all'; // 处理 tab
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.activeTab = 'all'; // 处理 tab
|
||||
this.handleQuery();
|
||||
},
|
||||
/** tab 切换 */
|
||||
tabClick(tab) {
|
||||
this.queryParams.status = tab.name === 'all' ? undefined : tab.name;
|
||||
this.getList();
|
||||
},
|
||||
goToDetail (row) {
|
||||
this.$router.push({ path: '/mall/trade/order/detail', query: { orderNo: row.orderNo }})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .table-wrapper {
|
||||
.el-table__row{
|
||||
.el-table__cell {
|
||||
border-bottom: none;
|
||||
.cell{
|
||||
.el-table {
|
||||
.el-table__row {
|
||||
>.el-table__cell {
|
||||
.goods-info{
|
||||
display: flex;
|
||||
img{
|
||||
margin-right: 10px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
}
|
||||
.ellipsis-2 {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
-webkit-line-clamp: 2; /* 要显示的行数 */
|
||||
-webkit-box-orient: vertical;
|
||||
word-break: break-all;
|
||||
line-height: 22px !important;
|
||||
max-height: 44px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,279 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container order-detail-page">
|
||||
<!-- 订单信息 -->
|
||||
<el-descriptions title="订单信息">
|
||||
<el-descriptions-item label="订单号">{{ order.no }}</el-descriptions-item>
|
||||
<el-descriptions-item label="配送方式">物流配送</el-descriptions-item> <!-- TODO 芋艿:待实现 -->
|
||||
<el-descriptions-item label="营销活动">物流配送</el-descriptions-item> <!-- TODO 芋艿:待实现 -->
|
||||
<el-descriptions-item label="订单类型">
|
||||
<dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="order.type" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="收货人">{{ order.receiverName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="买家留言">{{ order.userRemark }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单来源">
|
||||
<dict-tag :type="DICT_TYPE.TERMINAL" :value="order.terminal" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ order.receiverMobile }}</el-descriptions-item>
|
||||
<el-descriptions-item label="商家备注">{{ order.remark }}</el-descriptions-item>
|
||||
<el-descriptions-item label="支付单号">{{ order.payOrderId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="付款方式">
|
||||
<dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="order.payChannelCode" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="买家">{{ order.user.nickname }}</el-descriptions-item> <!-- TODO 芋艿:待实现:跳转会员 -->
|
||||
<el-descriptions-item label="收货地址">
|
||||
{{ order.receiverAreaName }} {{ order.receiverDetailAddress }}
|
||||
<el-link v-clipboard:copy="order.receiverAreaName + ' ' + order.receiverDetailAddress"
|
||||
v-clipboard:success="clipboardSuccess" icon="el-icon-document-copy" type="primary"/>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 订单状态 -->
|
||||
<el-descriptions title="订单状态" :column="1">
|
||||
<el-descriptions-item label="订单状态">
|
||||
<dict-tag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="order.status" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-class-name="no-colon">
|
||||
<el-button type="primary" size="small">调整价格</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">备注</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">发货</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">关闭订单</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">修改地址</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">打印电子面单</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">打印发货单</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
<el-button type="primary" size="small">确认收货</el-button> <!-- TODO 芋艿:待实现 -->
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提醒" label-style="color: red">
|
||||
买家付款成功后,货款将直接进入您的商户号(微信、支付宝)<br />
|
||||
请及时关注你发出的包裹状态,确保可以配送至买家手中 <br />
|
||||
如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 物流信息 TODO -->
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<el-descriptions title="商品信息" :column="6">
|
||||
<el-descriptions-item labelClassName="no-colon">
|
||||
<el-table :data="order.items" border>
|
||||
<el-table-column prop="spuName" label="商品" width="700">
|
||||
<template v-slot="{ row }">
|
||||
{{row.spuName}}
|
||||
<el-tag size="medium" v-for="property in row.properties" :key="property.propertyId">
|
||||
{{property.propertyName}}:{{property.valueName}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="originalUnitPrice" label="单价(元)" width="180">
|
||||
<template v-slot="{ row }">
|
||||
¥{{ (row.originalUnitPrice / 100.0).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="count" label="数量" width="180"/>
|
||||
<el-table-column prop="originalPrice" label="小计(元)" width="180">
|
||||
<template v-slot="{ row }">
|
||||
¥{{ (row.originalPrice / 100.0).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="afterSaleStatus" label="退款状态">
|
||||
<template v-slot="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS" :value="row.afterSaleStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-for="(item,index) in 5" label-class-name="no-colon" :key="item" /> <!-- 占位 -->
|
||||
<el-descriptions-item label="商品总额">¥{{ (order.originalPrice / 100.0).toFixed(2) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="运费金额">¥{{ (order.deliveryPrice / 100.0).toFixed(2) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单调价">¥{{ (order.adjustPrice / 100.0).toFixed(2) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="商品优惠" label-style="color: red">
|
||||
¥{{ ((order.originalPrice - order.originalPrice) / 100.0).toFixed(2) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="订单优惠" label-style="color: red">
|
||||
¥{{ (order.discountPrice / 100.0).toFixed(2) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="积分抵扣" label-style="color: red">
|
||||
¥{{ (order.pointPrice / 100.0).toFixed(2) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-for="(item,index) in 5" label-class-name="no-colon" :key="item" /> <!-- 占位 -->
|
||||
<el-descriptions-item label="应付金额">
|
||||
¥{{ (order.payPrice / 100.0).toFixed(2) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<template v-for="(group, index) in detailGroups">
|
||||
<el-descriptions v-bind="group.groupProps" :key="`group_${index}`" :title="group.title">
|
||||
|
||||
<!-- 订单操作日志 -->
|
||||
<el-descriptions-item v-if="group.key === 'orderLog'" labelClassName="no-colon">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(activity, index) in detailInfo[group.key]"
|
||||
:key="index"
|
||||
:timestamp="activity.timestamp"
|
||||
>
|
||||
{{activity.content}}
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-descriptions-item>
|
||||
|
||||
<!-- 物流信息 -->
|
||||
<el-descriptions-item v-if="group.key === 'expressInfo'" labelClassName="no-colon">
|
||||
<el-tabs type="card">
|
||||
<!-- 循环包裹物流信息 -->
|
||||
<el-tab-pane v-for="(pkgInfo, pInIdx) in detailInfo[group.key]" :key="`pkgInfo_${pInIdx}`" :label="pkgInfo.label">
|
||||
<!-- 包裹详情 -->
|
||||
<el-descriptions>
|
||||
<el-descriptions-item v-for="(pkgChild, pkgCIdx) in group.children" v-bind="pkgChild.childProps" :key="`pkgChild_${pkgCIdx}`" :label="pkgChild.label">
|
||||
<!-- 包裹商品列表 -->
|
||||
<template v-if="pkgChild.valueKey === 'goodsList' && pkgInfo[pkgChild.valueKey]">
|
||||
<div v-for="(goodInfo, goodInfoIdx) in pkgInfo[pkgChild.valueKey]" :key="`goodInfo_${goodInfoIdx}`" style="display: flex;">
|
||||
<el-image
|
||||
style="width: 100px;height: 100px;flex: none"
|
||||
:src="goodInfo.imgUrl">
|
||||
</el-image>
|
||||
<el-descriptions :column="1">
|
||||
<el-descriptions-item labelClassName="no-colon">{{goodInfo.name}}</el-descriptions-item>
|
||||
<el-descriptions-item label="数量">{{goodInfo.count}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 包裹物流详情 -->
|
||||
<el-timeline v-else-if="pkgChild.valueKey==='wlxq'">
|
||||
<el-timeline-item
|
||||
v-for="(activity, index) in pkgInfo[pkgChild.valueKey]"
|
||||
:key="index"
|
||||
:timestamp="activity.timestamp"
|
||||
>
|
||||
{{activity.content}}
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
|
||||
<template v-else>
|
||||
{{pkgInfo[pkgChild.valueKey]}}
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getOrderDetail } from "@/api/mall/trade/order";
|
||||
|
||||
export default {
|
||||
name: "TradeOrderDetail",
|
||||
data () {
|
||||
return {
|
||||
detailGroups: [
|
||||
{
|
||||
title: '物流信息',
|
||||
key: 'expressInfo',
|
||||
children: [
|
||||
{ label: '发货时间', valueKey: 'fhsj'},
|
||||
{ label: '物流公司', valueKey: 'wlgs'},
|
||||
{ label: '运单号', valueKey: 'ydh'},
|
||||
{ label: '物流状态', valueKey: 'wlzt', childProps: { span: 3 }},
|
||||
{ label: '物流详情', valueKey: 'wlxq'}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '订单操作日志',
|
||||
key: 'orderLog'
|
||||
}
|
||||
],
|
||||
detailInfo: {
|
||||
expressInfo: [ // 物流信息
|
||||
{
|
||||
label: '包裹1',
|
||||
name: 'bg1',
|
||||
fhsj: '2022-11-03 16:50:45',
|
||||
wlgs: '极兔',
|
||||
ydh: '2132123',
|
||||
wlzt: '不支持此快递公司',
|
||||
wlxq: [
|
||||
{
|
||||
content: '正在派送途中,请您准备签收(派件人:王涛,电话:13854563814)',
|
||||
timestamp: '2018-04-15 15:00:16'
|
||||
},
|
||||
{
|
||||
content: '快件到达 【烟台龙口东江村委营业点】',
|
||||
timestamp: '2018-04-13 14:54:19'
|
||||
},
|
||||
{
|
||||
content: '快件已发车',
|
||||
timestamp: '2018-04-11 12:55:52'
|
||||
},
|
||||
{
|
||||
content: '快件已发车',
|
||||
timestamp: '2018-04-11 12:55:52'
|
||||
},
|
||||
{
|
||||
content: '快件已发车',
|
||||
timestamp: '2018-04-11 12:55:52'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
orderLog: [ // 订单操作日志
|
||||
{
|
||||
content: '买家【乌鸦】关闭了订单',
|
||||
timestamp: '2018-04-15 15:00:16'
|
||||
},
|
||||
{
|
||||
content: '买家【乌鸦】下单了',
|
||||
timestamp: '2018-04-15 15:00:16'
|
||||
}
|
||||
],
|
||||
goodsInfo: [] // 商品详情tableData
|
||||
},
|
||||
order: {
|
||||
items: [],
|
||||
user: {},
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getOrderDetail(this.$route.query.id).then(res => {
|
||||
this.order = res.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
clipboardSuccess() {
|
||||
this.$modal.msgSuccess("复制成功");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-descriptions){
|
||||
&:not(:nth-child(1)) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.el-descriptions__title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&::before{
|
||||
content: '';
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
width: 3px;
|
||||
height: 20px;
|
||||
background-color: #409EFF;
|
||||
}
|
||||
}
|
||||
.el-descriptions-item__container{
|
||||
margin: 0 10px;
|
||||
.no-colon{
|
||||
margin: 0;
|
||||
&::after{
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,281 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<!-- TODO: inline 看看是不是需要; v-show= 那块逻辑还是要的 -->
|
||||
<el-row :gutter="20">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-col :span="6" :xs="24">
|
||||
<el-form-item label="搜索方式" prop="searchValue">
|
||||
<el-input v-model="queryParams.searchValue" style="width: 240px">
|
||||
<el-select v-model="queryParams.searchType" slot="prepend" style="width: 100px">
|
||||
<el-option v-for="dict in searchTypes" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" :xs="24">
|
||||
<el-form-item label="订单类型" prop="type">
|
||||
<el-select v-model="queryParams.type" clearable style="width: 240px">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_ORDER_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" :xs="24">
|
||||
<el-form-item label="订单状态" prop="status">
|
||||
<el-select v-model="queryParams.status" clearable style="width: 240px">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_ORDER_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" :xs="24">
|
||||
<el-form-item label="订单来源" prop="terminal">
|
||||
<el-select v-model="queryParams.terminal" clearable style="width: 240px">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.TERMINAL)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" :xs="24">
|
||||
<el-form-item label="支付方式" prop="payChannelCode">
|
||||
<el-select v-model="queryParams.payChannelCode" clearable style="width: 240px">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" :xs="24">
|
||||
<el-form-item label="下单时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:picker-options="datePickerOptions" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" :xs="24" style="line-height: 32px">
|
||||
<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-col>
|
||||
</el-form>
|
||||
</el-row>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- tab切换 -->
|
||||
<!-- TODO @小程:看看能不能往上挪 -40px,和【隐藏搜索】【刷新】对齐 -->
|
||||
<el-tabs v-model="activeTab" type="card" @tab-click="tabClick">
|
||||
<el-tab-pane v-for="tab in statusTabs" :key="tab.value" :label="tab.label" :name="tab.value">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list" :show-header="false" class="order-table">
|
||||
<el-table-column>
|
||||
<template v-slot="{ row }">
|
||||
<el-row type="flex" align="middle">
|
||||
<el-col :span="5">
|
||||
订单号:{{row.no}}
|
||||
<el-popover title="支付单号:" :content="row.payOrderId + ''" placement="right" width="200" trigger="click">
|
||||
<el-button slot="reference" type="text">更多</el-button>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
<el-col :span="5">下单时间:{{ parseTime(row.createTime) }}</el-col>
|
||||
<el-col :span="4">订单来源:
|
||||
<dict-tag :type="DICT_TYPE.TERMINAL" :value="row.terminal" />
|
||||
</el-col>
|
||||
<el-col :span="4">支付方式:
|
||||
<dict-tag v-if="row.payChannelCode" :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="row.payChannelCode" />
|
||||
<span v-else>未支付</span>
|
||||
</el-col>
|
||||
<el-col :span="6" align="right">
|
||||
<el-button type="text" @click="goToDetail(row)">详情</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 订单下的商品 -->
|
||||
<el-table :data="row.items" border :show-header="true">
|
||||
<el-table-column label="商品" prop="goods" header-align="center" width="auto" min-width="300">
|
||||
<template v-slot="{ row, $index }">
|
||||
<div class="goods-info">
|
||||
<img :src="row.picUrl"/>
|
||||
<span class="ellipsis-2" :title="row.spuName">{{row.spuName}}</span>
|
||||
<!-- TODO @小程:下面是商品属性,想当度一行,放在商品名下面 -->
|
||||
<el-tag size="medium" v-for="property in row.properties" :key="property.propertyId">
|
||||
{{property.propertyName}}:{{property.valueName}}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价(元)/数量" prop="fee" align="center" width="115">
|
||||
<template v-slot="{ row }">
|
||||
<div>¥{{ (row.originalUnitPrice / 100.0).toFixed(2) }}</div>
|
||||
<div>{{row.count}} 件</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- TODO @小程:这里应该是一个订单下,多个商品,只展示订单上的总金额,就是 order.payPrice -->
|
||||
<el-table-column label="实付金额(元)" prop="amount" align="center" width="100"/>
|
||||
<!-- TODO @小程:这里应该是一个订单下,多个商品,只展示订单上的收件信息;使用 order.receiverXXX 开头的字段 -->
|
||||
<el-table-column label="买家/收货人" prop="buyer" header-align="center" width="auto" min-width="300">
|
||||
<template v-slot="{ row }">
|
||||
<!-- TODO @芋艿:以后增加一个会员详情界面 -->
|
||||
<div>{{row.buyer}}</div>
|
||||
<div>{{row.receiver}}{{row.tel}}</div>
|
||||
<div class="ellipsis-2" :title="row.address">{{row.address}}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- TODO @小程:这里应该是一个订单下,多个商品,交易状态是统一的;使用 order.status 字段 -->
|
||||
<el-table-column label="交易状态" prop="status" align="center" width="100"/>
|
||||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getOrderPage } from "@/api/mall/trade/order";
|
||||
import { datePickerOptions } from "@/utils/constants";
|
||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
|
||||
|
||||
export default {
|
||||
name: "TradeOrder",
|
||||
data () {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 交易售后列表
|
||||
list: [],
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchType: 'no',
|
||||
searchValue: '',
|
||||
type: null,
|
||||
status: null,
|
||||
payChannelCode: null,
|
||||
createTime: [],
|
||||
},
|
||||
// Tab 筛选
|
||||
activeTab: 'all',
|
||||
statusTabs: [{
|
||||
label: '全部',
|
||||
value: 'all'
|
||||
}],
|
||||
// 静态变量
|
||||
datePickerOptions: datePickerOptions,
|
||||
searchTypes: [
|
||||
{ label: '订单号', value: 'no' },
|
||||
{ label: '会员编号', value: 'userId' },
|
||||
{ label: '会员昵称', value: 'userNickname' },
|
||||
{ label: '会员手机号', value: 'userMobile' },
|
||||
{ label: '收货人姓名', value: 'receiverName' },
|
||||
{ label: '收货人手机号码', value: 'receiverMobile' },
|
||||
],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 设置 statuses 过滤
|
||||
for (const dict of getDictDatas(DICT_TYPE.TRADE_ORDER_STATUS)) {
|
||||
this.statusTabs.push({
|
||||
label: dict.label,
|
||||
value: dict.value
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getOrderPage({
|
||||
...this.queryParams,
|
||||
searchType: undefined,
|
||||
searchValue: undefined,
|
||||
no: this.queryParams.searchType === 'no' ? this.queryParams.searchValue : undefined,
|
||||
userId: this.queryParams.searchType === 'userId' ? this.queryParams.searchValue : undefined,
|
||||
userNickname: this.queryParams.searchType === 'userNickname' ? this.queryParams.searchValue : undefined,
|
||||
userMobile: this.queryParams.searchType === 'userMobile' ? this.queryParams.searchValue : undefined,
|
||||
receiverName: this.queryParams.searchType === 'receiverName' ? this.queryParams.searchValue : undefined,
|
||||
receiverMobile: this.queryParams.searchType === 'receiverMobile' ? this.queryParams.searchValue : undefined,
|
||||
}).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.activeTab = this.queryParams.status ? this.queryParams.status : 'all'; // 处理 tab
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** tab 切换 */
|
||||
tabClick(tab) {
|
||||
this.queryParams.status = tab.name === 'all' ? undefined : tab.name;
|
||||
this.getList();
|
||||
},
|
||||
goToDetail (row) {
|
||||
this.$router.push({ name: 'TradeOrderDetail', query: { id: row.id }})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .order-table{
|
||||
border-bottom: none;
|
||||
&::before{
|
||||
height: 0;
|
||||
}
|
||||
.el-table__row{
|
||||
.el-table__cell{
|
||||
border-bottom: none;
|
||||
.cell{
|
||||
.el-table {
|
||||
.el-table__row{
|
||||
>.el-table__cell{
|
||||
.goods-info{
|
||||
display: flex;
|
||||
img{
|
||||
margin-right: 10px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
}
|
||||
.ellipsis-2{
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
-webkit-line-clamp: 2; /* 要显示的行数 */
|
||||
-webkit-box-orient: vertical;
|
||||
word-break: break-all;
|
||||
line-height: 22px !important;
|
||||
max-height: 44px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,290 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号接入" url="https://doc.iocoder.cn/mp/account/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['mp:account:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="名称" align="center" prop="name"/>
|
||||
<el-table-column label="微信号" align="center" prop="account" width="180"/>
|
||||
<el-table-column label="appId" align="center" prop="appId" width="180"/>
|
||||
<!-- <el-table-column label="appSecret" align="center" prop="appSecret" width="180"/>-->
|
||||
<!-- <el-table-column label="token" align="center" prop="token"/>-->
|
||||
<!-- <el-table-column label="消息加解密密钥" align="center" prop="aesKey"/>-->
|
||||
<el-table-column label="服务器地址(URL)" align="center" prop="appId" width="360">
|
||||
<template v-slot="scope">
|
||||
{{ 'http://服务端地址/mp/open/' + scope.row.appId }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="二维码" align="center" prop="qrCodeUrl">
|
||||
<template v-slot="scope">
|
||||
<img v-if="scope.row.qrCodeUrl" :src="scope.row.qrCodeUrl" alt="二维码" style="height: 100px;" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark"/>
|
||||
<!-- <el-table-column label="创建时间" align="center" prop="createTime" width="180">-->
|
||||
<!-- <template v-slot="scope">-->
|
||||
<!-- <span>{{ parseTime(scope.row.createTime) }}</span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['mp:account:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['mp:account:delete']">删除
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-refresh" @click="handleGenerateQrCode(scope.row)"
|
||||
v-hasPermi="['mp:account:qr-code']">生成二维码
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-share" @click="handleCleanQuota(scope.row)"
|
||||
v-hasPermi="['mp:account:clear-quota']">清空 API 配额
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="微信号" prop="account">
|
||||
<span slot="label">
|
||||
<el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 账号详情] 中能找到「微信号」" placement="top">
|
||||
<i class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
微信号
|
||||
</span>
|
||||
<el-input v-model="form.account" placeholder="请输入微信号"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="appId" prop="appId">
|
||||
<span slot="label">
|
||||
<el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者ID(AppID)」" placement="top">
|
||||
<i class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
appId
|
||||
</span>
|
||||
<el-input v-model="form.appId" placeholder="请输入公众号 appId"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="appSecret" prop="appSecret">
|
||||
<span slot="label">
|
||||
<el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者密码(AppSecret)」" placement="top">
|
||||
<i class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
appSecret
|
||||
</span>
|
||||
<el-input v-model="form.appSecret" placeholder="请输入公众号 appSecret"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="token" prop="token">
|
||||
<el-input v-model="form.token" placeholder="请输入公众号token"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="消息加解密密钥" prop="aesKey">
|
||||
<el-input v-model="form.aesKey" placeholder="请输入消息加解密密钥"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
clearAccountQuota,
|
||||
createAccount,
|
||||
deleteAccount,
|
||||
generateAccountQrCode,
|
||||
getAccount,
|
||||
getAccountPage,
|
||||
updateAccount
|
||||
} from '@/api/mp/account'
|
||||
|
||||
export default {
|
||||
name: 'MpAccount',
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 公众号账号列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
account: null,
|
||||
appId: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{required: true, message: '名称不能为空', trigger: 'blur'}],
|
||||
account: [{required: true, message: '公众号账号不能为空', trigger: 'blur'}],
|
||||
appId: [{required: true, message: '公众号 appId 不能为空', trigger: 'blur'}],
|
||||
appSecret: [{required: true, message: '公众号密钥不能为空', trigger: 'blur'}],
|
||||
token: [{required: true, message: '公众号 token 不能为空', trigger: 'blur'}],
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams}
|
||||
// 执行查询
|
||||
getAccountPage(params).then(response => {
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
account: undefined,
|
||||
appId: undefined,
|
||||
appSecret: undefined,
|
||||
token: undefined,
|
||||
aesKey: undefined,
|
||||
remark: undefined,
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = []
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加公众号账号'
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const id = row.id
|
||||
getAccount(id).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改公众号账号'
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateAccount(this.form).then(response => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
return
|
||||
}
|
||||
// 添加的提交
|
||||
createAccount(this.form).then(response => {
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id
|
||||
this.$modal.confirm('是否确认删除公众号账号编号为"' + row.name + '"的数据项?').then(function () {
|
||||
return deleteAccount(id)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
/** 生成二维码的按钮操作 */
|
||||
handleGenerateQrCode(row) {
|
||||
const id = row.id
|
||||
this.$modal.confirm('是否确认生成公众号账号编号为"' + row.name + '"的二维码?').then(function () {
|
||||
return generateAccountQrCode(id)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('生成二维码成功')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
/** 清空二维码 API 配额的按钮操作 */
|
||||
handleCleanQuota(row) {
|
||||
const id = row.id
|
||||
this.$modal.confirm('是否确认清空生成公众号账号编号为"' + row.name + '"的 API 配额?').then(function () {
|
||||
return clearAccountQuota(id)
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('清空 API 配额成功')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,384 +0,0 @@
|
||||
<!--
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 www.joolun.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
芋道源码:
|
||||
① 移除 avue 框架,使用 element-ui 重写
|
||||
② 重写代码,保持和现有项目保持一致
|
||||
-->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="自动回复" url="https://doc.iocoder.cn/mp/auto-reply/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- tab 切换 -->
|
||||
<el-tabs v-model="type" @tab-click="handleClick">
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['mp:auto-reply:create']" v-if="type !== '1' || list.length <= 0">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
<!-- tab 项 -->
|
||||
<el-tab-pane name="1">
|
||||
<span slot="label"><i class="el-icon-star-off"></i> 关注时回复</span>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="2">
|
||||
<span slot="label"><i class="el-icon-chat-line-round"></i> 消息回复</span>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="3">
|
||||
<span slot="label"><i class="el-icon-news"></i> 关键词回复</span>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="请求消息类型" align="center" prop="requestMessageType" v-if="type === '2'" />
|
||||
<el-table-column label="关键词" align="center" prop="requestKeyword" v-if="type === '3'" />
|
||||
<el-table-column label="匹配类型" align="center" prop="requestMatch" v-if="type === '3'">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH" :value="scope.row.requestMatch"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="回复消息类型" align="center">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.MP_MESSAGE_TYPE" :value="scope.row.responseMessageType"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="回复内容" align="center">
|
||||
<template v-slot="scope">
|
||||
<div v-if="scope.row.responseMessageType === 'text'">{{ scope.row.responseContent }}</div>
|
||||
<div v-else-if="scope.row.responseMessageType === 'voice'">
|
||||
<wx-voice-player :url="scope.row.responseMediaUrl" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.responseMessageType === 'image'">
|
||||
<a target="_blank" :href="scope.row.responseMediaUrl">
|
||||
<img :src="scope.row.responseMediaUrl" style="width: 100px">
|
||||
</a>
|
||||
</div>
|
||||
<div v-else-if="scope.row.responseMessageType === 'video' || scope.row.responseMessageType === 'shortvideo'">
|
||||
<wx-video-player :url="scope.row.responseMediaUrl" style="margin-top: 10px" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.responseMessageType === 'news'">
|
||||
<wx-news :articles="scope.row.responseArticles" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.responseMessageType === 'music'">
|
||||
<wx-music :title="scope.row.responseTitle" :description="scope.row.responseDescription"
|
||||
:thumb-media-url="scope.row.responseThumbMediaUrl"
|
||||
:music-url="scope.row.responseMusicUrl" :hq-music-url="scope.row.responseHqMusicUrl" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['mp:auto-reply:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['mp:auto-reply:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加或修改自动回复的对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="消息类型" prop="requestMessageType" v-if="type === '2'">
|
||||
<el-select v-model="form.requestMessageType" placeholder="请选择">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.MP_MESSAGE_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"
|
||||
v-if="requestMessageTypes.includes(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="匹配类型" prop="requestMatch" v-if="type === '3'">
|
||||
<el-select v-model="form.requestMatch" placeholder="请选择匹配类型" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH)"
|
||||
:key="dict.value" :label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词" prop="requestKeyword" v-if="type === '3'">
|
||||
<el-input v-model="form.requestKeyword" placeholder="请输入内容" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="回复消息">
|
||||
<wx-reply-select :objData="objData" v-if="hackResetWxReplySelect" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
|
||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
|
||||
import WxMsg from '@/views/mp/components/wx-msg/main.vue';
|
||||
import WxLocation from '@/views/mp/components/wx-location/main.vue';
|
||||
import WxMusic from '@/views/mp/components/wx-music/main.vue';
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
import WxReplySelect from '@/views/mp/components/wx-reply/main.vue'
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
import { createAutoReply, deleteAutoReply, getAutoReply, getAutoReplyPage, updateAutoReply } from "@/api/mp/autoReply";
|
||||
|
||||
export default {
|
||||
name: 'MpAutoReply',
|
||||
components: {
|
||||
WxVideoPlayer,
|
||||
WxVoicePlayer,
|
||||
WxMsg,
|
||||
WxLocation,
|
||||
WxMusic,
|
||||
WxNews,
|
||||
WxReplySelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// tab 类型(1、关注时回复;2、消息回复;3、关键词回复)
|
||||
type: '3',
|
||||
// 允许选择的请求消息类型
|
||||
requestMessageTypes: ['text', 'image', 'voice', 'video', 'shortvideo', 'location', 'link'],
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 自动回复列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
accountId: undefined,
|
||||
},
|
||||
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 回复消息
|
||||
objData: {
|
||||
type : 'text'
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
requestKeyword: [{ required: true, message: "请求的关键字不能为空", trigger: "blur" }],
|
||||
requestMatch: [{ required: true, message: "请求的关键字的匹配不能为空", trigger: "blur" }],
|
||||
},
|
||||
hackResetWxReplySelect: false, // 重置 WxReplySelect 组件,解决无法清除的问题
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询自动回复')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
// 处理查询参数
|
||||
let params = {
|
||||
...this.queryParams,
|
||||
type: this.type
|
||||
}
|
||||
// 执行查询
|
||||
getAutoReplyPage(params).then(response => {
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
this.type = tab.name
|
||||
this.handleQuery()
|
||||
},
|
||||
|
||||
/** 新增按钮操作 */
|
||||
handleAdd(){
|
||||
this.reset();
|
||||
this.resetEditor();
|
||||
// 打开表单,并设置初始化
|
||||
this.open = true
|
||||
this.title = '新增自动回复';
|
||||
this.objData = {
|
||||
type : 'text',
|
||||
accountId: this.queryParams.accountId,
|
||||
}
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
this.resetEditor();
|
||||
const id = row.id;
|
||||
getAutoReply(id).then(response => {
|
||||
// 设置属性
|
||||
this.form = {...response.data}
|
||||
this.$delete(this.form, 'responseMessageType');
|
||||
this.$delete(this.form, 'responseContent');
|
||||
this.$delete(this.form, 'responseMediaId');
|
||||
this.$delete(this.form, 'responseMediaUrl');
|
||||
this.$delete(this.form, 'responseDescription');
|
||||
this.$delete(this.form, 'responseArticles');
|
||||
this.objData = {
|
||||
type: response.data.responseMessageType,
|
||||
accountId: this.queryParams.accountId,
|
||||
content: response.data.responseContent,
|
||||
mediaId: response.data.responseMediaId,
|
||||
url: response.data.responseMediaUrl,
|
||||
title: response.data.responseTitle,
|
||||
description: response.data.responseDescription,
|
||||
thumbMediaId: response.data.responseThumbMediaId,
|
||||
thumbMediaUrl: response.data.responseThumbMediaUrl,
|
||||
articles: response.data.responseArticles,
|
||||
musicUrl: response.data.responseMusicUrl,
|
||||
hqMusicUrl: response.data.responseHqMusicUrl,
|
||||
}
|
||||
|
||||
// 打开表单
|
||||
this.open = true
|
||||
this.title = '修改自动回复';
|
||||
})
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 处理回复消息
|
||||
const form = {...this.form};
|
||||
form.responseMessageType = this.objData.type;
|
||||
form.responseContent = this.objData.content;
|
||||
form.responseMediaId = this.objData.mediaId;
|
||||
form.responseMediaUrl = this.objData.url;
|
||||
form.responseTitle = this.objData.title;
|
||||
form.responseDescription = this.objData.description;
|
||||
form.responseThumbMediaId = this.objData.thumbMediaId;
|
||||
form.responseThumbMediaUrl = this.objData.thumbMediaUrl;
|
||||
form.responseArticles = this.objData.articles;
|
||||
form.responseMusicUrl = this.objData.musicUrl;
|
||||
form.responseHqMusicUrl = this.objData.hqMusicUrl;
|
||||
|
||||
if (this.form.id !== undefined) {
|
||||
updateAutoReply(form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
createAutoReply(form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
accountId: this.queryParams.accountId,
|
||||
type: this.type,
|
||||
requestKeyword: undefined,
|
||||
requestMatch: this.type === '3' ? 1 : undefined,
|
||||
requestMessageType: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单 Editor 重置
|
||||
resetEditor() {
|
||||
this.hackResetWxReplySelect = false // 销毁组件
|
||||
this.$nextTick(() => {
|
||||
this.hackResetWxReplySelect = true // 重建组件
|
||||
})
|
||||
},
|
||||
handleDelete: function(row) {
|
||||
const ids = row.id;
|
||||
this.$modal.confirm('是否确认删除此数据?').then(function() {
|
||||
return deleteAutoReply(ids);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,230 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
芋道源码:
|
||||
① 调整 uploadData 属性,只需要传入 accountId 即可
|
||||
-->
|
||||
<template>
|
||||
<div id="wxEditor">
|
||||
<div v-loading="quillUpdateImg" element-loading-text="请稍等,图片上传中">
|
||||
<!-- 图片上传组件辅助-->
|
||||
<el-upload class="avatar-uploader" name="file" :action="actionUrl" :headers="headers"
|
||||
:show-file-list="false" :data="uploadData"
|
||||
:on-success="uploadSuccess" :on-error="uploadError" :before-upload="beforeUpload">
|
||||
</el-upload>
|
||||
<quill-editor class="editor" v-model="content" ref="myQuillEditor" :options="editorOption"
|
||||
@change="onEditorChange($event)">
|
||||
</quill-editor>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 工具栏配置
|
||||
const toolbarOptions = [
|
||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||
["blockquote", "code-block"], // 引用 代码块
|
||||
[{ header: 1 }, { header: 2 }], // 1、2 级标题
|
||||
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||
[{ script: "sub" }, { script: "super" }], // 上标/下标
|
||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||
// [{'direction': 'rtl'}], // 文本方向
|
||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||
[{ font: [] }], // 字体种类
|
||||
[{ align: [] }], // 对齐方式
|
||||
["clean"], // 清除文本格式
|
||||
["link", "image", "video"] // 链接、图片、视频
|
||||
]
|
||||
|
||||
import { quillEditor } from "vue-quill-editor"
|
||||
import "quill/dist/quill.core.css"
|
||||
import "quill/dist/quill.snow.css"
|
||||
import "quill/dist/quill.bubble.css"
|
||||
import { getAccessToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
/* 公众号账号编号 */
|
||||
accountId: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
/* 编辑器的内容 */
|
||||
value: {
|
||||
type: String
|
||||
},
|
||||
/* 图片大小 */
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 4000 // kb
|
||||
}
|
||||
},
|
||||
name: 'wxEditor',
|
||||
components: {
|
||||
quillEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editorType: '1',
|
||||
content: this.value.replace(/data-src/g, "src"),
|
||||
|
||||
quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
|
||||
editorOption: {
|
||||
theme: "snow", // or 'bubble'
|
||||
placeholder: "请输入文章内容",
|
||||
modules: {
|
||||
toolbar: {
|
||||
container: toolbarOptions,
|
||||
// container: "#toolbar",
|
||||
handlers: {
|
||||
image: function(value) {
|
||||
if (value) {
|
||||
// 触发input框选择图片文件
|
||||
document.querySelector(".avatar-uploader input").click();
|
||||
} else {
|
||||
this.quill.format("image", false);
|
||||
}
|
||||
},
|
||||
link: function(value) {
|
||||
if (value) {
|
||||
const href = prompt('注意!只支持公众号图文链接');
|
||||
this.quill.format("link", href);
|
||||
} else {
|
||||
this.quill.format("link", false);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
actionUrl: process.env.VUE_APP_BASE_API +'/admin-api/mp/material/upload-news-image', // 这里写你要上传的图片服务器地址
|
||||
headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
|
||||
uploadData: {
|
||||
"type": 'image', // TODO 芋艿:试试要不要换成 thumb
|
||||
"accountId": this.accountId,
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onEditorChange(editor) {
|
||||
//内容改变事件
|
||||
this.$emit("input", this.content)
|
||||
},
|
||||
|
||||
// 富文本图片上传前
|
||||
beforeUpload() {
|
||||
// 显示 loading 动画
|
||||
this.quillUpdateImg = true
|
||||
},
|
||||
|
||||
// 图片上传成功
|
||||
// 注意!由于微信公众号的图片有访问限制,所以会显示“此图片来自微信公众号,未经允许不可引用”
|
||||
uploadSuccess(res, file) {
|
||||
// res为图片服务器返回的数据
|
||||
// 获取富文本组件实例
|
||||
let quill = this.$refs.myQuillEditor.quill
|
||||
// 如果上传成功
|
||||
const link = res.data
|
||||
if (link){
|
||||
// 获取光标所在位置
|
||||
let length = quill.getSelection().index;
|
||||
// 插入图片 res.info为服务器返回的图片地址
|
||||
quill.insertEmbed(length, 'image', link)
|
||||
// 调整光标到最后
|
||||
quill.setSelection(length + 1)
|
||||
} else {
|
||||
this.$message.error('图片插入失败')
|
||||
}
|
||||
// loading 动画消失
|
||||
this.quillUpdateImg = false;
|
||||
},
|
||||
// 富文本图片上传失败
|
||||
uploadError() {
|
||||
// loading 动画消失
|
||||
this.quillUpdateImg = false;
|
||||
this.$message.error("图片插入失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.editor {
|
||||
line-height: normal !important;
|
||||
height: 500px;
|
||||
}
|
||||
.ql-snow .ql-tooltip[data-mode=link]::before {
|
||||
content: "请输入链接地址:";
|
||||
}
|
||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||
border-right: 0;
|
||||
content: '保存';
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode=video]::before {
|
||||
content: "请输入视频地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: '14px';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
|
||||
content: '10px';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
|
||||
content: '18px';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
|
||||
content: '32px';
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||
content: '文本';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||
content: '标题1';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||
content: '标题2';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||
content: '标题3';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||
content: '标题4';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||
content: '标题5';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||
content: '标题6';
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: '标准字体';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
|
||||
content: '衬线字体';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
|
||||
content: '等宽字体';
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<!--
|
||||
【微信消息 - 定位】
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<el-link type="primary" target="_blank" :href="'https://map.qq.com/?type=marker&isopeninfowin=1&markertype=1&pointx=' + locationY + '&pointy=' + locationX + '&name=' + label + '&ref=yudao'">
|
||||
<img :src="'https://apis.map.qq.com/ws/staticmap/v2/?zoom=10&markers=color:blue|label:A|' + locationX + ',' + locationY + '&key=' + qqMapKey + '&size=250*180'">
|
||||
<p/><i class="el-icon-map-location"></i>{{label}}
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "wxLocation",
|
||||
props: {
|
||||
locationX: {
|
||||
required: true,
|
||||
type: Number
|
||||
},
|
||||
locationY: {
|
||||
required: true,
|
||||
type: Number
|
||||
},
|
||||
label: { // 地名
|
||||
required: true,
|
||||
type: String
|
||||
},
|
||||
qqMapKey: { // QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
|
||||
required: false,
|
||||
type: String,
|
||||
default: 'TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E' // 需要自定义
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,247 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
芋道源码:
|
||||
① 移除 avue 组件,使用 ElementUI 原生组件
|
||||
-->
|
||||
<template>
|
||||
<!-- 类型:图片 -->
|
||||
<div v-if="objData.type === 'image'">
|
||||
<div class="waterfall" v-loading="loading">
|
||||
<div class="waterfall-item" v-for="item in list" :key="item.mediaId">
|
||||
<img class="material-img" :src="item.url">
|
||||
<p class="item-name">{{item.name}}</p>
|
||||
<el-row class="ope-row">
|
||||
<el-button size="mini" type="success" @click="selectMaterial(item)">选择
|
||||
<i class="el-icon-circle-check el-icon--right"></i>
|
||||
</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getMaterialPage"/>
|
||||
</div>
|
||||
<!-- 类型:语音 -->
|
||||
<div v-else-if="objData.type === 'voice'">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="mediaId" />
|
||||
<el-table-column label="文件名" align="center" prop="name" />
|
||||
<el-table-column label="语音" align="center">
|
||||
<template v-slot="scope">
|
||||
<wx-voice-player :url="scope.row.url" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-circle-plus"
|
||||
@click="selectMaterial(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getPage"/>
|
||||
</div>
|
||||
<div v-else-if="objData.type === 'video'">
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="mediaId" />
|
||||
<el-table-column label="文件名" align="center" prop="name" />
|
||||
<el-table-column label="标题" align="center" prop="title" />
|
||||
<el-table-column label="介绍" align="center" prop="introduction" />
|
||||
<el-table-column label="视频" align="center">
|
||||
<template v-slot="scope">
|
||||
<wx-video-player :url="scope.row.url" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-circle-plus"
|
||||
@click="selectMaterial(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getMaterialPage"/>
|
||||
</div>
|
||||
<div v-else-if="objData.type === 'news'">
|
||||
<div class="waterfall" v-loading="loading">
|
||||
<div class="waterfall-item" v-for="item in list" :key="item.mediaId" v-if="item.content && item.content.newsItem">
|
||||
<wx-news :articles="item.content.newsItem" />
|
||||
<el-row class="ope-row">
|
||||
<el-button size="mini" type="success" @click="selectMaterial(item)">
|
||||
选择<i class="el-icon-circle-check el-icon--right"></i>
|
||||
</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getMaterialPage"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
|
||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
|
||||
import { getMaterialPage } from "@/api/mp/material";
|
||||
import { getFreePublishPage } from "@/api/mp/freePublish";
|
||||
import { getDraftPage } from "@/api/mp/draft";
|
||||
|
||||
export default {
|
||||
name: "wxMaterialSelect",
|
||||
components: {
|
||||
WxNews,
|
||||
WxVoicePlayer,
|
||||
WxVideoPlayer
|
||||
},
|
||||
props: {
|
||||
objData: {
|
||||
type: Object, // type - 类型;accountId - 公众号账号编号
|
||||
required: true
|
||||
},
|
||||
newsType:{ // 图文类型:1、已发布图文;2、草稿箱图文
|
||||
type: String,
|
||||
default: "1"
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 数据列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
accountId: this.objData.accountId,
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getPage()
|
||||
},
|
||||
methods:{
|
||||
selectMaterial(item) {
|
||||
this.$emit('selectMaterial', item)
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1
|
||||
this.getPage()
|
||||
},
|
||||
getPage() {
|
||||
this.loading = true
|
||||
if (this.objData.type === 'news' && this.newsType === '1') { // 【图文】+ 【已发布】
|
||||
this.getFreePublishPage();
|
||||
} else if (this.objData.type === 'news' && this.newsType === '2') { // 【图文】+ 【草稿】
|
||||
this.getDraftPage();
|
||||
} else { // 【素材】
|
||||
this.getMaterialPage();
|
||||
}
|
||||
},
|
||||
getMaterialPage() {
|
||||
getMaterialPage({
|
||||
...this.queryParams,
|
||||
type: this.objData.type
|
||||
}).then(response => {
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
getFreePublishPage() {
|
||||
getFreePublishPage(this.queryParams).then(response => {
|
||||
// 将 thumbUrl 转成 picUrl,保证 wx-news 组件可以预览封面
|
||||
response.data.list.forEach(item => {
|
||||
const newsItem = item.content.newsItem;
|
||||
newsItem.forEach(article => {
|
||||
article.picUrl = article.thumbUrl;
|
||||
})
|
||||
})
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
getDraftPage() {
|
||||
getDraftPage((this.queryParams)).then(response => {
|
||||
// 将 thumbUrl 转成 picUrl,保证 wx-news 组件可以预览封面
|
||||
response.data.list.forEach(item => {
|
||||
const newsItem = item.content.newsItem;
|
||||
newsItem.forEach(article => {
|
||||
article.picUrl = article.thumbUrl;
|
||||
})
|
||||
})
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/*瀑布流样式*/
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap:10px;
|
||||
column-count: 5;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
}
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color:red;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
/*瀑布流样式*/
|
||||
</style>
|
||||
@@ -1,101 +0,0 @@
|
||||
.avue-card{
|
||||
&__item{
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid #e8e8e8;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
color: rgba(0,0,0,.65);
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5;
|
||||
list-style: none;
|
||||
font-feature-settings: "tnum";
|
||||
cursor: pointer;
|
||||
height:200px;
|
||||
&:hover{
|
||||
border-color: rgba(0,0,0,.09);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,.09);
|
||||
}
|
||||
&--add{
|
||||
border:1px dashed #000;
|
||||
width: 100%;
|
||||
color: rgba(0,0,0,.45);
|
||||
background-color: #fff;
|
||||
border-color: #d9d9d9;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
i{
|
||||
margin-right: 10px;
|
||||
}
|
||||
&:hover{
|
||||
color: #40a9ff;
|
||||
background-color: #fff;
|
||||
border-color: #40a9ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
&__body{
|
||||
display: flex;
|
||||
padding: 24px;
|
||||
}
|
||||
&__detail{
|
||||
flex:1
|
||||
}
|
||||
&__avatar{
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 48px;
|
||||
overflow: hidden;
|
||||
margin-right: 12px;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
&__title{
|
||||
color: rgba(0,0,0,.85);
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
&:hover{
|
||||
color:#1890ff;
|
||||
}
|
||||
}
|
||||
&__info{
|
||||
color: rgba(0,0,0,.45);
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
overflow: hidden;
|
||||
height: 64px;
|
||||
}
|
||||
&__menu{
|
||||
display: flex;
|
||||
justify-content:space-around;
|
||||
height: 50px;
|
||||
background: #f7f9fa;
|
||||
color: rgba(0,0,0,.45);
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
&:hover{
|
||||
color:#1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** joolun 额外加的 */
|
||||
.avue-comment__main {
|
||||
flex: unset!important;
|
||||
border-radius: 5px!important;
|
||||
margin: 0 8px!important;
|
||||
}
|
||||
.avue-comment__header {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
.avue-comment__body {
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/* 来自 https://github.com/nmxiaowei/avue/blob/master/styles/src/element-ui/comment.scss */
|
||||
.avue-comment{
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
&--reverse{
|
||||
flex-direction:row-reverse;
|
||||
.avue-comment__main{
|
||||
&:before,&:after{
|
||||
left: auto;
|
||||
right: -8px;
|
||||
border-width: 8px 0 8px 8px;
|
||||
}
|
||||
&:before{
|
||||
border-left-color: #dedede;
|
||||
}
|
||||
&:after{
|
||||
border-left-color: #f8f8f8;
|
||||
margin-right: 1px;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
&__avatar{
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
}
|
||||
&__header{
|
||||
padding: 5px 15px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
&__author{
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
&__main{
|
||||
flex:1;
|
||||
margin: 0 20px;
|
||||
position: relative;
|
||||
border: 1px solid #dedede;
|
||||
border-radius: 2px;
|
||||
&:before,&:after{
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: -8px;
|
||||
right: 100%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
display: block;
|
||||
content: " ";
|
||||
border-color: transparent;
|
||||
border-style: solid solid outset;
|
||||
border-width: 8px 8px 8px 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
&:before {
|
||||
border-right-color: #dedede;
|
||||
z-index: 1;
|
||||
}
|
||||
&:after{
|
||||
border-right-color: #f8f8f8;
|
||||
margin-left: 1px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
&__body{
|
||||
padding: 15px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
font-family: Segoe UI,Lucida Grande,Helvetica,Arial,Microsoft YaHei,FreeSans,Arimo,Droid Sans,wenquanyi micro hei,Hiragino Sans GB,Hiragino Sans GB W3,FontAwesome,sans-serif;color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
blockquote{
|
||||
margin:0;
|
||||
font-family: Georgia,Times New Roman,Times,Kai,Kaiti SC,KaiTi,BiauKai,FontAwesome,serif;
|
||||
padding: 1px 0 1px 15px;
|
||||
border-left: 4px solid #ddd;
|
||||
}
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
芋道源码:
|
||||
① 移除暂时用不到的 websocket
|
||||
② 代码优化,补充注释,提升阅读性
|
||||
-->
|
||||
<template>
|
||||
<div class="msg-main">
|
||||
<div class="msg-div" :id="'msg-div' + nowStr">
|
||||
<!-- 加载更多 -->
|
||||
<div v-loading="loading"></div>
|
||||
<div v-if="!loading">
|
||||
<div class="el-table__empty-block" v-if="loadMore" @click="loadingMore"><span class="el-table__empty-text">点击加载更多</span></div>
|
||||
<div class="el-table__empty-block" v-if="!loadMore"><span class="el-table__empty-text">没有更多了</span></div>
|
||||
</div>
|
||||
<!-- 消息列表 -->
|
||||
<div class="execution" v-for="item in list" :key='item.id'>
|
||||
<div class="avue-comment" :class="item.sendFrom === 2 ? 'avue-comment--reverse' : ''">
|
||||
<div class="avatar-div">
|
||||
<img :src="item.sendFrom === 1 ? user.avatar : mp.avatar" class="avue-comment__avatar">
|
||||
<div class="avue-comment__author">{{item.sendFrom === 1 ? user.nickname : mp.nickname }}</div>
|
||||
</div>
|
||||
<div class="avue-comment__main">
|
||||
<div class="avue-comment__header">
|
||||
<div class="avue-comment__create_time">{{ parseTime(item.createTime) }}</div>
|
||||
</div>
|
||||
<div class="avue-comment__body" :style="item.sendFrom === 2 ? 'background: #6BED72;' : ''">
|
||||
<!-- 【事件】区域 -->
|
||||
<div v-if="item.type === 'event' && item.event === 'subscribe'">
|
||||
<el-tag type="success" size="mini">关注</el-tag>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'unsubscribe'">
|
||||
<el-tag type="danger" size="mini">取消关注</el-tag>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'CLICK'">
|
||||
<el-tag size="mini">点击菜单</el-tag>【{{ item.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'VIEW'">
|
||||
<el-tag size="mini">点击菜单链接</el-tag>【{{ item.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'scancode_waitmsg'">
|
||||
<el-tag size="mini">扫码结果</el-tag>【{{ item.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'scancode_push'">
|
||||
<el-tag size="mini">扫码结果</el-tag>【{{ item.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'pic_sysphoto'">
|
||||
<el-tag size="mini">系统拍照发图</el-tag>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'pic_photo_or_album'">
|
||||
<el-tag size="mini">拍照或者相册</el-tag>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'pic_weixin'">
|
||||
<el-tag size="mini">微信相册</el-tag>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event' && item.event === 'location_select'">
|
||||
<el-tag size="mini">选择地理位置</el-tag>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'event'">
|
||||
<el-tag type="danger" size="mini">未知事件类型</el-tag>
|
||||
</div>
|
||||
<!-- 【消息】区域 -->
|
||||
<div v-else-if="item.type === 'text'">{{ item.content }}</div>
|
||||
<div v-else-if="item.type === 'voice'">
|
||||
<wx-voice-player :url="item.mediaUrl" :content="item.recognition" />
|
||||
</div>
|
||||
<div v-else-if="item.type === 'image'">
|
||||
<a target="_blank" :href="item.mediaUrl">
|
||||
<img :src="item.mediaUrl" style="width: 100px">
|
||||
</a>
|
||||
</div>
|
||||
<div v-else-if="item.type === 'video' || item.type === 'shortvideo'" style="text-align: center">
|
||||
<wx-video-player :url="item.mediaUrl" />
|
||||
</div>
|
||||
<div v-else-if="item.type === 'link'" class="avue-card__detail">
|
||||
<el-link type="success" :underline="false" target="_blank" :href="item.url">
|
||||
<div class="avue-card__title"><i class="el-icon-link"></i>{{ item.title }}</div>
|
||||
</el-link>
|
||||
<div class="avue-card__info" style="height: unset">{{item.description}}</div>
|
||||
</div>
|
||||
<!-- TODO 芋艿:待完善 -->
|
||||
<div v-else-if="item.type === 'location'">
|
||||
<wx-location :label="item.label" :location-y="item.locationY" :location-x="item.locationX" />
|
||||
</div>
|
||||
<div v-else-if="item.type === 'news'" style="width: 300px"> <!-- TODO 芋艿:待测试;详情页也存在类似的情况 -->
|
||||
<wx-news :articles="item.articles" />
|
||||
</div>
|
||||
<div v-else-if="item.type === 'music'">
|
||||
<wx-music :title="item.title" :description="item.description" :thumb-media-url="item.thumbMediaUrl"
|
||||
:music-url="item.musicUrl" :hq-music-url="item.hqMusicUrl" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="msg-send" v-loading="sendLoading">
|
||||
<wx-reply-select ref="replySelect" :objData="objData" />
|
||||
<el-button type="success" size="small" class="send-but" @click="sendMsg">发送(S)</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMessagePage, sendMessage } from '@/api/mp/message'
|
||||
import WxReplySelect from '@/views/mp/components/wx-reply/main.vue'
|
||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
|
||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
import WxLocation from '@/views/mp/components/wx-location/main.vue';
|
||||
import WxMusic from '@/views/mp/components/wx-music/main.vue';
|
||||
import { getUser } from "@/api/mp/mpuser";
|
||||
|
||||
export default {
|
||||
name: "wxMsg",
|
||||
components: {
|
||||
WxReplySelect,
|
||||
WxVideoPlayer,
|
||||
WxVoicePlayer,
|
||||
WxNews,
|
||||
WxLocation,
|
||||
WxMusic
|
||||
},
|
||||
props: {
|
||||
userId: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nowStr: new Date().getTime(), // 当前的时间戳,用于每次消息加载后,回到原位置;具体见 :id="'msg-div' + nowStr" 处
|
||||
loading: false, // 消息列表是否正在加载中
|
||||
loadMore: true, // 是否可以加载更多
|
||||
list: [], // 消息列表
|
||||
queryParams: {
|
||||
pageNo: 1, // 当前页数
|
||||
pageSize: 14, // 每页显示多少条
|
||||
accountId: undefined,
|
||||
},
|
||||
user: { // 由于微信不再提供昵称,直接使用“用户”展示
|
||||
nickname: '用户',
|
||||
avatar: require("@/assets/images/profile.jpg"),
|
||||
accountId: 0, // 公众号账号编号
|
||||
},
|
||||
mp: {
|
||||
nickname: '公众号',
|
||||
avatar: require("@/assets/images/wechat.png"),
|
||||
},
|
||||
|
||||
// ========= 消息发送 =========
|
||||
sendLoading: false, // 发送消息是否加载中
|
||||
objData: { // 微信发送消息
|
||||
type: 'text',
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 获得用户信息
|
||||
getUser(this.userId).then(response => {
|
||||
this.user.nickname = response.data.nickname && response.data.nickname.length > 0 ?
|
||||
response.data.nickname : this.user.nickname;
|
||||
this.user.avatar = response.data.avatar && this.user.avatar.length > 0 ?
|
||||
response.data.avatar : this.user.avatar;
|
||||
this.user.accountId = response.data.accountId;
|
||||
// 设置公众号账号编号
|
||||
this.queryParams.accountId = response.data.accountId;
|
||||
this.objData.accountId = response.data.accountId;
|
||||
|
||||
// 加载消息
|
||||
console.log(this.queryParams)
|
||||
this.refreshChange()
|
||||
})
|
||||
},
|
||||
methods:{
|
||||
sendMsg(){
|
||||
if (!this.objData) {
|
||||
return;
|
||||
}
|
||||
// 公众号限制:客服消息,公众号只允许发送一条
|
||||
if (this.objData.type === 'news'
|
||||
&& this.objData.articles.length > 1) {
|
||||
this.objData.articles = [this.objData.articles[0]]
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '图文消息条数限制在 1 条以内,已默认发送第一条',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
// 执行发送
|
||||
this.sendLoading = true
|
||||
sendMessage(Object.assign({
|
||||
userId: this.userId
|
||||
}, {
|
||||
...this.objData
|
||||
})).then(response => {
|
||||
this.sendLoading = false
|
||||
// 添加到消息列表,并滚动
|
||||
this.list = [...this.list , ...[response.data] ]
|
||||
this.scrollToBottom()
|
||||
// 重置 objData 状态
|
||||
this.$refs['replySelect'].deleteObj(); // 重置,避免 tab 的数据未清理
|
||||
}).catch(() => {
|
||||
this.sendLoading = false
|
||||
})
|
||||
},
|
||||
loadingMore() {
|
||||
this.queryParams.pageNo++
|
||||
this.getPage(this.queryParams)
|
||||
},
|
||||
getPage(page, params) {
|
||||
this.loading = true
|
||||
getMessagePage(Object.assign({
|
||||
pageNo: page.pageNo,
|
||||
pageSize: page.pageSize,
|
||||
userId: this.userId,
|
||||
accountId: page.accountId,
|
||||
}, params)).then(response => {
|
||||
// 计算当前的滚动高度
|
||||
const msgDiv = document.getElementById('msg-div' + this.nowStr);
|
||||
let scrollHeight = 0
|
||||
if(msgDiv){
|
||||
scrollHeight = msgDiv.scrollHeight
|
||||
}
|
||||
|
||||
// 处理数据
|
||||
const data = response.data.list.reverse();
|
||||
this.list = [...data, ...this.list]
|
||||
this.loading = false
|
||||
if (data.length < this.queryParams.pageSize || data.length === 0){
|
||||
this.loadMore = false
|
||||
}
|
||||
this.queryParams.pageNo = page.pageNo
|
||||
this.queryParams.pageSize = page.pageSize
|
||||
|
||||
// 滚动到原来的位置
|
||||
if(this.queryParams.pageNo === 1) { // 定位到消息底部
|
||||
this.scrollToBottom()
|
||||
} else if (data.length !== 0) { // 定位滚动条
|
||||
this.$nextTick(() => {
|
||||
if (scrollHeight !== 0){
|
||||
msgDiv.scrollTop = document.getElementById('msg-div'+this.nowStr).scrollHeight - scrollHeight - 100
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 刷新回调
|
||||
*/
|
||||
refreshChange() {
|
||||
this.getPage(this.queryParams)
|
||||
},
|
||||
/** 定位到消息底部 */
|
||||
scrollToBottom: function () {
|
||||
this.$nextTick(() => {
|
||||
let div = document.getElementById('msg-div' + this.nowStr)
|
||||
div.scrollTop = div.scrollHeight
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
|
||||
@import './comment.scss';
|
||||
@import './card.scss';
|
||||
|
||||
.msg-main {
|
||||
margin-top: -30px;
|
||||
padding: 10px;
|
||||
}
|
||||
.msg-div {
|
||||
height: 50vh;
|
||||
overflow: auto;
|
||||
background-color: #eaeaea;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.msg-send {
|
||||
padding: 10px;
|
||||
}
|
||||
.avatar-div {
|
||||
text-align: center;
|
||||
width: 80px;
|
||||
}
|
||||
.send-but {
|
||||
float: right;
|
||||
margin-top: 8px!important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<!--
|
||||
【微信消息 - 音乐】
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<el-link type="success" :underline="false" target="_blank" :href="hqMusicUrl ? hqMusicUrl : musicUrl">
|
||||
<div class="avue-card__body" style="padding:10px;background-color: #fff;border-radius: 5px">
|
||||
<div class="avue-card__avatar">
|
||||
<img :src="thumbMediaUrl" alt=""/>
|
||||
</div>
|
||||
<div class="avue-card__detail">
|
||||
<div class="avue-card__title" style="margin-bottom:unset">{{ title }}</div>
|
||||
<div class="avue-card__info" style="height: unset">{{ description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "wxMusic",
|
||||
props: {
|
||||
title: {
|
||||
required: false,
|
||||
type: String
|
||||
},
|
||||
description: {
|
||||
required: false,
|
||||
type: String
|
||||
},
|
||||
musicUrl: {
|
||||
required: false,
|
||||
type: String
|
||||
},
|
||||
hqMusicUrl: {
|
||||
required: false,
|
||||
type: String
|
||||
},
|
||||
thumbMediaUrl: {
|
||||
required: true,
|
||||
type: String
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 card.scc */
|
||||
@import '../wx-msg/card.scss';
|
||||
</style>
|
||||
@@ -1,104 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
【微信消息 - 图文】
|
||||
芋道源码:
|
||||
① 代码优化,补充注释,提升阅读性
|
||||
-->
|
||||
<template>
|
||||
<div class="news-home">
|
||||
<div v-for="(article, index) in articles" :key="index" class="news-div">
|
||||
<!-- 头条 -->
|
||||
<a target="_blank" :href="article.url" v-if="index === 0">
|
||||
<div class="news-main">
|
||||
<div class="news-content">
|
||||
<img class="material-img" :src="article.picUrl" width="280px" height="120px"/>
|
||||
<div class="news-content-title">
|
||||
<span>{{article.title}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<!-- 二条/三条等等 -->
|
||||
<a target="_blank" :href="article.url" v-else>
|
||||
<div class="news-main-item">
|
||||
<div class="news-content-item">
|
||||
<div class="news-content-item-title">{{article.title}}</div>
|
||||
<div class="news-content-item-img">
|
||||
<img class="material-img" :src="article.picUrl" height="100%"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "wxNews",
|
||||
props: {
|
||||
articles: {
|
||||
type: Array // title - 标题;description - 描述;picUrl - 图片连接;url - 跳转链接
|
||||
}
|
||||
},
|
||||
// created() {
|
||||
// console.log(this.articles)
|
||||
// },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.news-home {
|
||||
background-color: #FFFFFF;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.news-main {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.news-content {
|
||||
background-color: #acadae;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.news-content-title {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: black;
|
||||
width: 98%;
|
||||
padding: 1%;
|
||||
opacity: 0.65;
|
||||
white-space: normal;
|
||||
box-sizing: unset!important
|
||||
}
|
||||
.news-main-item {
|
||||
background-color: #FFFFFF;
|
||||
padding: 5px 0;
|
||||
border-top: 1px solid #eaeaea;
|
||||
}
|
||||
.news-content-item {
|
||||
position: relative;
|
||||
}
|
||||
.news-content-item-title {
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
width: 70%;
|
||||
margin-left: 1%;
|
||||
white-space: normal
|
||||
}
|
||||
.news-content-item-img {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
background-color: #acadae;
|
||||
margin-right: 1%;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,547 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
芋道源码:
|
||||
① 移除多余的 rep 为前缀的变量,让 message 消息更简单
|
||||
② 代码优化,补充注释,提升阅读性
|
||||
③ 优化消息的临时缓存策略,发送消息时,只清理被发送消息的 tab,不会强制切回到 text 输入
|
||||
④ 支持发送【视频】消息时,支持新建视频
|
||||
-->
|
||||
<template>
|
||||
<el-tabs type="border-card" v-model="objData.type" @tab-click="handleClick">
|
||||
<!-- 类型 1:文本 -->
|
||||
<el-tab-pane name="text">
|
||||
<span slot="label"><i class="el-icon-document"></i> 文本</span>
|
||||
<el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="objData.content" @input="inputContent" />
|
||||
</el-tab-pane>
|
||||
<!-- 类型 2:图片 -->
|
||||
<el-tab-pane name="image">
|
||||
<span slot="label"><i class="el-icon-picture"></i> 图片</span>
|
||||
<el-row>
|
||||
<!-- 情况一:已经选择好素材、或者上传好图片 -->
|
||||
<div class="select-item" v-if="objData.url">
|
||||
<img class="material-img" :src="objData.url">
|
||||
<p class="item-name" v-if="objData.name">{{objData.name}}</p>
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="deleteObj"></el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 情况二:未做完上述操作 -->
|
||||
<div v-else>
|
||||
<el-row style="text-align: center">
|
||||
<!-- 选择素材 -->
|
||||
<el-col :span="12" class="col-select">
|
||||
<el-button type="success" @click="openMaterial">
|
||||
素材库选择<i class="el-icon-circle-check el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dialog title="选择图片" :visible.sync="dialogImageVisible" width="90%" append-to-body>
|
||||
<wx-material-select :obj-data="objData" @selectMaterial="selectMaterial" />
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
<!-- 文件上传 -->
|
||||
<el-col :span="12" class="col-add">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeImageUpload" :on-success="handleUploadSuccess">
|
||||
<el-button type="primary">上传图片</el-button>
|
||||
<div slot="tip" class="el-upload__tip">支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M</div>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<!-- 类型 3:语音 -->
|
||||
<el-tab-pane name="voice">
|
||||
<span slot="label"><i class="el-icon-phone"></i> 语音</span>
|
||||
<el-row>
|
||||
<div class="select-item2" v-if="objData.url">
|
||||
<p class="item-name">{{objData.name}}</p>
|
||||
<div class="item-infos">
|
||||
<wx-voice-player :url="objData.url" />
|
||||
</div>
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="deleteObj"></el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-row style="text-align: center">
|
||||
<!-- 选择素材 -->
|
||||
<el-col :span="12" class="col-select">
|
||||
<el-button type="success" @click="openMaterial">
|
||||
素材库选择<i class="el-icon-circle-check el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dialog title="选择语音" :visible.sync="dialogVoiceVisible" width="90%" append-to-body>
|
||||
<WxMaterialSelect :objData="objData" @selectMaterial="selectMaterial"></WxMaterialSelect>
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
<!-- 文件上传 -->
|
||||
<el-col :span="12" class="col-add">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeVoiceUpload" :on-success="handleUploadSuccess">
|
||||
<el-button type="primary">点击上传</el-button>
|
||||
<div slot="tip" class="el-upload__tip">格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s</div>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<!-- 类型 4:视频 -->
|
||||
<el-tab-pane name="video">
|
||||
<span slot="label"><i class="el-icon-share"></i> 视频</span>
|
||||
<el-row>
|
||||
<el-input v-model="objData.title" placeholder="请输入标题" @input="inputContent" />
|
||||
<div style="margin: 20px 0;"></div>
|
||||
<el-input v-model="objData.description" placeholder="请输入描述" @input="inputContent" />
|
||||
<div style="margin: 20px 0;"></div>
|
||||
<div style="text-align: center;">
|
||||
<wx-video-player v-if="objData.url" :url="objData.url" />
|
||||
</div>
|
||||
<div style="margin: 20px 0;"></div>
|
||||
<el-row style="text-align: center">
|
||||
<!-- 选择素材 -->
|
||||
<el-col :span="12">
|
||||
<el-button type="success" @click="openMaterial">
|
||||
素材库选择<i class="el-icon-circle-check el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dialog title="选择视频" :visible.sync="dialogVideoVisible" width="90%" append-to-body>
|
||||
<wx-material-select :objData="objData" @selectMaterial="selectMaterial" />
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
<!-- 文件上传 -->
|
||||
<el-col :span="12">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeVideoUpload" :on-success="handleUploadSuccess">
|
||||
<el-button type="primary">新建视频<i class="el-icon-upload el-icon--right"></i></el-button>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<!-- 类型 5:图文 -->
|
||||
<el-tab-pane name="news">
|
||||
<span slot="label"><i class="el-icon-news"></i> 图文</span>
|
||||
<el-row>
|
||||
<div class="select-item" v-if="objData.articles">
|
||||
<wx-news :articles="objData.articles" />
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="deleteObj" />
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 选择素材 -->
|
||||
<div v-if="!objData.content">
|
||||
<el-row style="text-align: center">
|
||||
<el-col :span="24">
|
||||
<el-button type="success" @click="openMaterial">{{newsType === '1' ? '选择已发布图文' : '选择草稿箱图文'}}<i class="el-icon-circle-check el-icon--right"></i></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-dialog title="选择图文" :visible.sync="dialogNewsVisible" width="90%" append-to-body>
|
||||
<wx-material-select :objData="objData" @selectMaterial="selectMaterial" :newsType="newsType" />
|
||||
</el-dialog>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<!-- 类型 6:音乐 -->
|
||||
<el-tab-pane name="music">
|
||||
<span slot="label"><i class="el-icon-service"></i> 音乐</span>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<div class="thumb-div">
|
||||
<img style="width: 100px" v-if="objData.thumbMediaUrl" :src="objData.thumbMediaUrl">
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
||||
<div class="thumb-but">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeThumbImageUpload" :on-success="handleUploadSuccess">
|
||||
<el-button slot="trigger" size="mini" type="text">本地上传</el-button>
|
||||
<el-button size="mini" type="text" @click="openMaterial" style="margin-left: 5px">素材库选择</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog title="选择图片" :visible.sync="dialogThumbVisible" width="80%" append-to-body>
|
||||
<wx-material-select :objData="{type:'image', accountId: objData.accountId}" @selectMaterial="selectMaterial" />
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-input v-model="objData.title" placeholder="请输入标题" @input="inputContent" />
|
||||
<div style="margin: 20px 0;"></div>
|
||||
<el-input v-model="objData.description" placeholder="请输入描述" @input="inputContent" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div style="margin: 20px 0;"></div>
|
||||
<el-input v-model="objData.musicUrl" placeholder="请输入音乐链接" @input="inputContent" />
|
||||
<div style="margin: 20px 0;"></div>
|
||||
<el-input v-model="objData.hqMusicUrl" placeholder="请输入高质量音乐链接" @input="inputContent" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue'
|
||||
import WxMaterialSelect from '@/views/mp/components/wx-material-select/main.vue'
|
||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
|
||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
|
||||
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
|
||||
export default {
|
||||
name: "wxReplySelect",
|
||||
components: {
|
||||
WxNews,
|
||||
WxMaterialSelect,
|
||||
WxVoicePlayer,
|
||||
WxVideoPlayer
|
||||
},
|
||||
props: {
|
||||
objData: { // 消息对象。
|
||||
type: Object, // 设置为 Object 的原因,方便属性的传递
|
||||
required: true,
|
||||
},
|
||||
newsType:{ // 图文类型:1、已发布图文;2、草稿箱图文
|
||||
type: String,
|
||||
default: "1"
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tempPlayerObj: {
|
||||
type: '2'
|
||||
},
|
||||
|
||||
tempObj: new Map().set( // 临时缓存,切换消息类型的 tab 的时候,可以保存对应的数据;
|
||||
this.objData.type, // 消息类型
|
||||
Object.assign({}, this.objData)), // 消息内容
|
||||
|
||||
// ========== 素材选择的弹窗,是否可见 ==========
|
||||
dialogNewsVisible: false, // 图文
|
||||
dialogImageVisible: false, // 图片
|
||||
dialogVoiceVisible: false, // 语音
|
||||
dialogVideoVisible: false, // 视频
|
||||
dialogThumbVisible: false, // 缩略图
|
||||
|
||||
// ========== 文件上传(图片、语音、视频) ==========
|
||||
fileList: [], // 文件列表
|
||||
uploadData: {
|
||||
"accountId": undefined,
|
||||
"type": this.objData.type,
|
||||
"title":'',
|
||||
"introduction":''
|
||||
},
|
||||
actionUrl: process.env.VUE_APP_BASE_API + '/admin-api/mp/material/upload-temporary',
|
||||
headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
beforeThumbImageUpload(file){
|
||||
const isType = file.type === 'image/jpeg'
|
||||
|| file.type === 'image/png'
|
||||
|| file.type === 'image/gif'
|
||||
|| file.type === 'image/bmp'
|
||||
|| file.type === 'image/jpg';
|
||||
if (!isType) {
|
||||
this.$message.error('上传图片格式不对!');
|
||||
return false;
|
||||
}
|
||||
const isLt = file.size / 1024 / 1024 < 2;
|
||||
if (!isLt) {
|
||||
this.$message.error('上传图片大小不能超过 2M!');
|
||||
return false;
|
||||
}
|
||||
this.uploadData.accountId = this.objData.accountId;
|
||||
return true;
|
||||
},
|
||||
beforeVoiceUpload(file){
|
||||
// 校验格式
|
||||
const isType = file.type === 'audio/mp3'
|
||||
|| file.type === 'audio/mpeg'
|
||||
|| file.type === 'audio/wma'
|
||||
|| file.type === 'audio/wav'
|
||||
|| file.type === 'audio/amr';
|
||||
if (!isType) {
|
||||
this.$message.error('上传语音格式不对!' + file.type);
|
||||
return false;
|
||||
}
|
||||
// 校验大小
|
||||
const isLt = file.size / 1024 / 1024 < 2;
|
||||
if (!isLt) {
|
||||
this.$message.error('上传语音大小不能超过 2M!');
|
||||
return false;
|
||||
}
|
||||
this.uploadData.accountId = this.objData.accountId;
|
||||
return true;
|
||||
},
|
||||
beforeImageUpload(file) {
|
||||
// 校验格式
|
||||
const isType = file.type === 'image/jpeg'
|
||||
|| file.type === 'image/png'
|
||||
|| file.type === 'image/gif'
|
||||
|| file.type === 'image/bmp'
|
||||
|| file.type === 'image/jpg';
|
||||
if (!isType) {
|
||||
this.$message.error('上传图片格式不对!');
|
||||
return false;
|
||||
}
|
||||
// 校验大小
|
||||
const isLt = file.size / 1024 / 1024 < 2;
|
||||
if (!isLt) {
|
||||
this.$message.error('上传图片大小不能超过 2M!');
|
||||
return false;
|
||||
}
|
||||
this.uploadData.accountId = this.objData.accountId;
|
||||
return true;
|
||||
},
|
||||
beforeVideoUpload(file){
|
||||
// 校验格式
|
||||
const isType = file.type === 'video/mp4';
|
||||
if (!isType) {
|
||||
this.$message.error('上传视频格式不对!');
|
||||
return false;
|
||||
}
|
||||
// 校验大小
|
||||
const isLt = file.size / 1024 / 1024 < 10;
|
||||
if (!isLt) {
|
||||
this.$message.error('上传视频大小不能超过 10M!');
|
||||
return false;
|
||||
}
|
||||
this.uploadData.accountId = this.objData.accountId;
|
||||
return true;
|
||||
},
|
||||
handleUploadSuccess(response, file, fileList) {
|
||||
if (response.code !== 0) {
|
||||
this.$message.error('上传出错:' + response.msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 清空上传时的各种数据
|
||||
this.fileList = []
|
||||
this.uploadData.title = ''
|
||||
this.uploadData.introduction = ''
|
||||
|
||||
// 上传好的文件,本质是个素材,所以可以进行选中
|
||||
let item = response.data
|
||||
this.selectMaterial(item)
|
||||
},
|
||||
/**
|
||||
* 切换消息类型的 tab
|
||||
*
|
||||
* @param tab tab
|
||||
*/
|
||||
handleClick(tab) {
|
||||
// 设置后续文件上传的文件类型
|
||||
this.uploadData.type = this.objData.type;
|
||||
if (this.uploadData.type === 'music') { // 【音乐】上传的是缩略图
|
||||
this.uploadData.type = 'thumb';
|
||||
}
|
||||
|
||||
// 从 tempObj 临时缓存中,获取对应的数据,并设置回 objData
|
||||
let tempObjItem = this.tempObj.get(this.objData.type)
|
||||
if (tempObjItem) {
|
||||
this.objData.content = tempObjItem.content ? tempObjItem.content : null
|
||||
this.objData.mediaId = tempObjItem.mediaId ? tempObjItem.mediaId : null
|
||||
this.objData.url = tempObjItem.url ? tempObjItem.url : null
|
||||
this.objData.name = tempObjItem.url ? tempObjItem.name : null
|
||||
this.objData.title = tempObjItem.title ? tempObjItem.title : null
|
||||
this.objData.description = tempObjItem.description ? tempObjItem.description : null
|
||||
return;
|
||||
}
|
||||
// 如果获取不到,需要把 objData 复原
|
||||
// 必须使用 $set 赋值,不然 input 无法输入内容
|
||||
this.$set(this.objData, 'content', '');
|
||||
this.$delete(this.objData, 'mediaId');
|
||||
this.$delete(this.objData, 'url');
|
||||
this.$set(this.objData, 'title', '');
|
||||
this.$set(this.objData, 'description', '');
|
||||
|
||||
},
|
||||
/**
|
||||
* 选择素材,将设置设置到 objData 变量
|
||||
*
|
||||
* @param item 素材
|
||||
*/
|
||||
selectMaterial(item) {
|
||||
// 选择好素材,所以隐藏弹窗
|
||||
this.closeMaterial();
|
||||
|
||||
// 创建 tempObjItem 对象,并设置对应的值
|
||||
let tempObjItem = {}
|
||||
tempObjItem.type = this.objData.type;
|
||||
if (this.objData.type === 'news') {
|
||||
tempObjItem.articles = item.content.newsItem
|
||||
this.objData.articles = item.content.newsItem
|
||||
} else if (this.objData.type === 'music') { // 音乐需要特殊处理,因为选择的是图片的缩略图
|
||||
tempObjItem.thumbMediaId = item.mediaId
|
||||
this.objData.thumbMediaId = item.mediaId
|
||||
tempObjItem.thumbMediaUrl = item.url
|
||||
this.objData.thumbMediaUrl = item.url
|
||||
// title、introduction、musicUrl、hqMusicUrl:从 objData 到 tempObjItem,避免上传素材后,被覆盖掉
|
||||
tempObjItem.title = this.objData.title || ''
|
||||
tempObjItem.introduction = this.objData.introduction || ''
|
||||
tempObjItem.musicUrl = this.objData.musicUrl || ''
|
||||
tempObjItem.hqMusicUrl = this.objData.hqMusicUrl || ''
|
||||
} else if (this.objData.type === 'image'
|
||||
|| this.objData.type === 'voice') {
|
||||
tempObjItem.mediaId = item.mediaId
|
||||
this.objData.mediaId = item.mediaId
|
||||
tempObjItem.url = item.url;
|
||||
this.objData.url = item.url;
|
||||
tempObjItem.name = item.name
|
||||
this.objData.name = item.name
|
||||
} else if (this.objData.type === 'video') {
|
||||
tempObjItem.mediaId = item.mediaId
|
||||
this.objData.mediaId = item.mediaId
|
||||
tempObjItem.url = item.url;
|
||||
this.objData.url = item.url;
|
||||
tempObjItem.name = item.name
|
||||
this.objData.name = item.name
|
||||
// title、introduction:从 item 到 tempObjItem,因为素材里有 title、introduction
|
||||
if (item.title) {
|
||||
this.objData.title = item.title || ''
|
||||
tempObjItem.title = item.title || ''
|
||||
}
|
||||
if (item.introduction) {
|
||||
this.objData.description = item.introduction || '' // 消息使用的是 description,素材使用的是 introduction,所以转换下
|
||||
tempObjItem.description = item.introduction || ''
|
||||
}
|
||||
} else if (this.objData.type === 'text') {
|
||||
this.objData.content = item.content || ''
|
||||
}
|
||||
// 最终设置到临时缓存
|
||||
this.tempObj.set(this.objData.type, tempObjItem)
|
||||
},
|
||||
openMaterial() {
|
||||
if (this.objData.type === 'news') {
|
||||
this.dialogNewsVisible = true
|
||||
} else if(this.objData.type === 'image') {
|
||||
this.dialogImageVisible = true
|
||||
} else if(this.objData.type === 'voice') {
|
||||
this.dialogVoiceVisible = true
|
||||
} else if(this.objData.type === 'video') {
|
||||
this.dialogVideoVisible = true
|
||||
} else if(this.objData.type === 'music') {
|
||||
this.dialogThumbVisible = true
|
||||
}
|
||||
},
|
||||
closeMaterial() {
|
||||
this.dialogNewsVisible = false
|
||||
this.dialogImageVisible = false
|
||||
this.dialogVoiceVisible = false
|
||||
this.dialogVideoVisible = false
|
||||
this.dialogThumbVisible = false
|
||||
},
|
||||
deleteObj() {
|
||||
if (this.objData.type === 'news') {
|
||||
this.$delete(this.objData, 'articles');
|
||||
} else if(this.objData.type === 'image') {
|
||||
this.objData.mediaId = null
|
||||
this.$delete(this.objData, 'url');
|
||||
this.objData.name = null
|
||||
} else if(this.objData.type === 'voice') {
|
||||
this.objData.mediaId = null
|
||||
this.$delete(this.objData, 'url');
|
||||
this.objData.name = null
|
||||
} else if(this.objData.type === 'video') {
|
||||
this.objData.mediaId = null
|
||||
this.$delete(this.objData, 'url');
|
||||
this.objData.name = null
|
||||
this.objData.title = null
|
||||
this.objData.description = null
|
||||
} else if(this.objData.type === 'music') {
|
||||
this.objData.thumbMediaId = null
|
||||
this.objData.thumbMediaUrl = null
|
||||
this.objData.title = null
|
||||
this.objData.description = null
|
||||
this.objData.musicUrl = null
|
||||
this.objData.hqMusicUrl = null
|
||||
} else if(this.objData.type === 'text') {
|
||||
this.objData.content = null
|
||||
}
|
||||
// 覆盖缓存
|
||||
this.tempObj.set(this.objData.type, Object.assign({}, this.objData));
|
||||
},
|
||||
/**
|
||||
* 输入时,缓存每次 objData 到 tempObj 中
|
||||
*
|
||||
* why?不确定为什么 v-model="objData.content" 不能自动缓存,所以通过这样的方式
|
||||
*/
|
||||
inputContent(str) {
|
||||
// 覆盖缓存
|
||||
this.tempObj.set(this.objData.type, Object.assign({}, this.objData));
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.public-account-management{
|
||||
.el-input{
|
||||
width: 70%;
|
||||
margin-right: 2%;
|
||||
}
|
||||
}
|
||||
.pagination{
|
||||
text-align: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
.select-item{
|
||||
width: 280px;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.select-item2{
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.ope-row{
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.item-name{
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
.el-form-item__content{
|
||||
line-height:unset!important;
|
||||
}
|
||||
.col-select{
|
||||
border: 1px solid rgb(234, 234, 234);
|
||||
padding: 50px 0px;
|
||||
height: 160px;
|
||||
width: 49.5%;
|
||||
}
|
||||
.col-select2{
|
||||
border: 1px solid rgb(234, 234, 234);
|
||||
padding: 50px 0px;
|
||||
height: 160px;
|
||||
}
|
||||
.col-add{
|
||||
border: 1px solid rgb(234, 234, 234);
|
||||
padding: 50px 0px;
|
||||
height: 160px;
|
||||
width: 49.5%;
|
||||
float: right
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px solid #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 100px!important;
|
||||
height: 100px!important;
|
||||
line-height: 100px!important;
|
||||
text-align: center;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
}
|
||||
.thumb-div{
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
.item-infos{
|
||||
width: 30%;
|
||||
margin: auto
|
||||
}
|
||||
</style>
|
||||
@@ -1,91 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
【微信消息 - 视频】
|
||||
芋道源码:
|
||||
① bug 修复:
|
||||
1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容;
|
||||
存在的问题:mediaId 有效期是 3 天,超过时间后无法播放
|
||||
2)重构后的做法:后端接收到微信公众号的视频消息后,将视频消息的 media_id 的文件内容保存到文件服务器中,这样前端可以直接使用 URL 播放。
|
||||
② 体验优化:弹窗关闭后,自动暂停视频的播放
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<!-- 提示 -->
|
||||
<div @click="playVideo()">
|
||||
<i class="el-icon-video-play" style="font-size: 40px!important;" ></i>
|
||||
<p>点击播放视频</p>
|
||||
</div>
|
||||
|
||||
<!-- 弹窗播放 -->
|
||||
<el-dialog title="视频播放" :visible.sync="dialogVideo" width="40%" append-to-body @close="closeDialog">
|
||||
<video-player v-if="playerOptions.sources[0].src" class="video-player vjs-custom-skin" ref="videoPlayer"
|
||||
:playsinline="true" :options="playerOptions"
|
||||
@play="onPlayerPlay($event)" @pause="onPlayerPause($event)">
|
||||
</video-player>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 引入 videoPlayer 相关组件。教程:https://juejin.cn/post/6923056942281654285
|
||||
import { videoPlayer } from 'vue-video-player'
|
||||
require('video.js/dist/video-js.css')
|
||||
require('vue-video-player/src/custom-theme.css')
|
||||
|
||||
export default {
|
||||
name: "wxVideoPlayer",
|
||||
props: {
|
||||
url: { // 视频地址,例如说:https://www.iocoder.cn/xxx.mp4
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
components: {
|
||||
videoPlayer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVideo:false,
|
||||
playerOptions: {
|
||||
playbackRates: [0.5, 1.0, 1.5, 2.0], // 播放速度
|
||||
autoplay: false, // 如果 true,浏览器准备好时开始回放。
|
||||
muted: false, // 默认情况下将会消除任何音频。
|
||||
loop: false, // 导致视频一结束就重新开始。
|
||||
preload: 'auto', // 建议浏览器在 <video> 加载元素后是否应该开始下载视频数据。auto 浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
|
||||
language: 'zh-CN',
|
||||
aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
|
||||
fluid: true, // 当true时,Video.js player 将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
|
||||
sources: [{
|
||||
type: "video/mp4",
|
||||
src: "" // 你的视频地址(必填)【重要】
|
||||
}],
|
||||
poster: "", // 你的封面地址
|
||||
width: document.documentElement.clientWidth,
|
||||
notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖 Video.js 无法播放媒体源时显示的默认信息。
|
||||
controlBar: {
|
||||
timeDivider: true,
|
||||
durationDisplay: true,
|
||||
remainingTimeDisplay: false,
|
||||
fullscreenToggle: true //全屏按钮
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
playVideo(){
|
||||
this.dialogVideo = true
|
||||
// 设置地址
|
||||
this.$set(this.playerOptions.sources[0], 'src', this.url)
|
||||
},
|
||||
closeDialog(){
|
||||
// 暂停播放
|
||||
this.$refs.videoPlayer.player.pause()
|
||||
},
|
||||
onPlayerPlay(player) {
|
||||
},
|
||||
onPlayerPause(player) {
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,98 +0,0 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
【微信消息 - 语音】
|
||||
芋道源码:
|
||||
① bug 修复:
|
||||
1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容;
|
||||
存在的问题:mediaId 有效期是 3 天,超过时间后无法播放
|
||||
2)重构后的做法:后端接收到微信公众号的视频消息后,将视频消息的 media_id 的文件内容保存到文件服务器中,这样前端可以直接使用 URL 播放。
|
||||
② 代码优化:将 props 中的 objData 调成为 data 中对应的属性,并补充相关注释
|
||||
-->
|
||||
<template>
|
||||
<div class="wx-voice-div" @click="playVoice">
|
||||
<i :class="playing !== true ? 'el-icon-video-play': 'el-icon-video-pause'">
|
||||
<span class="amr-duration" v-if="duration">{{ duration }} 秒</span>
|
||||
</i>
|
||||
<div v-if="content">
|
||||
<el-tag type="success" size="mini">语音识别</el-tag>
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 因为微信语音是 amr 格式,所以需要用到 amr 解码器:https://www.npmjs.com/package/benz-amr-recorder
|
||||
const BenzAMRRecorder = require('benz-amr-recorder')
|
||||
|
||||
export default {
|
||||
name: "wxVoicePlayer",
|
||||
props: {
|
||||
url: { // 语音地址,例如说:https://www.iocoder.cn/xxx.amr
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
content: { // 语音文本
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
amr: undefined, // BenzAMRRecorder 对象
|
||||
playing: false, // 是否在播放中
|
||||
duration: undefined, // 播放时长
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
playVoice() {
|
||||
debugger
|
||||
// 情况一:未初始化,则创建 BenzAMRRecorder
|
||||
if (this.amr === undefined){
|
||||
this.amrInit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.amr.isPlaying()) {
|
||||
this.amrStop();
|
||||
} else {
|
||||
this.amrPlay();
|
||||
}
|
||||
},
|
||||
amrInit() {
|
||||
const amr = new BenzAMRRecorder();
|
||||
this.amr = amr;
|
||||
// 设置播放
|
||||
const that = this
|
||||
amr.initWithUrl(this.url).then(function() {
|
||||
that.amrPlay()
|
||||
that.duration = amr.getDuration();
|
||||
})
|
||||
// 监听暂停
|
||||
amr.onEnded(function() {
|
||||
that.playing = false;
|
||||
})
|
||||
},
|
||||
amrPlay() {
|
||||
this.playing = true;
|
||||
this.amr.play()
|
||||
},
|
||||
amrStop() {
|
||||
this.playing = false;
|
||||
this.amr.stop()
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wx-voice-div {
|
||||
padding: 5px;
|
||||
background-color: #eaeaea;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.amr-duration {
|
||||
font-size: 11px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,700 +0,0 @@
|
||||
<!--
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 www.joolun.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
芋道源码:
|
||||
① 优化代码,和项目的代码保持一致
|
||||
② 清理冗余代码,保证代码整洁
|
||||
③ 增加注释,提升可读性
|
||||
-->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号图文" url="https://doc.iocoder.cn/mp/article/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['mp:draft:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<div class="waterfall" v-loading="loading">
|
||||
<div v-if="item.content && item.content.newsItem" class="waterfall-item" v-for="item in list"
|
||||
:key='item.articleId'>
|
||||
<wx-news :articles="item.content.newsItem" />
|
||||
<!-- 操作按钮 -->
|
||||
<el-row class="ope-row">
|
||||
<el-button type="success" circle @click="handlePublish(item)" v-hasPermi="['mp:free-publish:submit']">发布</el-button>
|
||||
<el-button type="primary" icon="el-icon-edit" circle @click="handleUpdate(item)" v-hasPermi="['mp:draft:update']" />
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="handleDelete(item)" v-hasPermi="['mp:draft:delete']" />
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页记录 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 添加或修改草稿对话框 -->
|
||||
<el-dialog :title="operateMaterial === 'add' ? '新建图文' : '修改图文'"
|
||||
append-to-body width="80%" top="20px" :visible.sync="dialogNewsVisible"
|
||||
:before-close="dialogNewsClose" :close-on-click-modal="false">
|
||||
<div class="left">
|
||||
<div class="select-item">
|
||||
<div v-for="(news, index) in articlesAdd" :key='news.id'>
|
||||
<div class="news-main father" v-if="index === 0" :class="{'activeAddNews': isActiveAddNews === index}"
|
||||
@click="activeNews(index)">
|
||||
<div class="news-content">
|
||||
<img class="material-img" v-if="news.thumbUrl" :src="news.thumbUrl"/>
|
||||
<div class="news-content-title">{{news.title}}</div>
|
||||
</div>
|
||||
<div class="child" v-if="articlesAdd.length>1">
|
||||
<el-button type="mini" icon="el-icon-sort-down" @click="downNews(index)">下移</el-button>
|
||||
<el-button v-if="operateMaterial === 'add'" type="mini" icon="el-icon-delete"
|
||||
@click="minusNews(index)">删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="news-main-item father" v-if="index>0" :class="{'activeAddNews': isActiveAddNews === index}"
|
||||
@click="activeNews(index)">
|
||||
<div class="news-content-item">
|
||||
<div class="news-content-item-title ">{{news.title}}</div>
|
||||
<div class="news-content-item-img">
|
||||
<img class="material-img" v-if="news.thumbUrl" :src="news.thumbUrl" height="100%"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="child">
|
||||
<el-button v-if="articlesAdd.length > index+1" type="mini" icon="el-icon-sort-down"
|
||||
@click="downNews(index)">下移
|
||||
</el-button>
|
||||
<el-button type="mini" icon="el-icon-sort-up" @click="upNews(index)">上移</el-button>
|
||||
<el-button v-if="operateMaterial=== 'add'" type="mini" icon="el-icon-delete"
|
||||
@click="minusNews(index)">删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="news-main-plus" @click="plusNews" v-if="articlesAdd.length<8 && operateMaterial==='add'">
|
||||
<i class="el-icon-circle-plus icon-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right" v-loading="addMaterialLoading" v-if="articlesAdd.length > 0">
|
||||
<br /> <br /> <br /> <br />
|
||||
<!-- 标题、作者、原文地址 -->
|
||||
<el-input v-model="articlesAdd[isActiveAddNews].title" placeholder="请输入标题(必填)" />
|
||||
<el-input v-model="articlesAdd[isActiveAddNews].author" placeholder="请输入作者" style="margin-top: 5px;" />
|
||||
<el-input v-model="articlesAdd[isActiveAddNews].contentSourceUrl" placeholder="请输入原文地址" style="margin-top: 5px;" />
|
||||
<!-- 封面和摘要 -->
|
||||
<div class="input-tt">封面和摘要:</div>
|
||||
<div>
|
||||
<div class="thumb-div">
|
||||
<img class="material-img" v-if="articlesAdd[isActiveAddNews].thumbUrl"
|
||||
:src="articlesAdd[isActiveAddNews].thumbUrl" :class="isActiveAddNews === 0 ? 'avatar':'avatar1'">
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon"
|
||||
:class="isActiveAddNews === 0 ? 'avatar':'avatar1'"></i>
|
||||
<div class="thumb-but">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeThumbImageUpload" :on-success="handleUploadSuccess">
|
||||
<el-button slot="trigger" size="mini" type="primary">本地上传</el-button>
|
||||
<el-button size="mini" type="primary" @click="openMaterial" style="margin-left: 5px">素材库选择</el-button>
|
||||
<div slot="tip" class="el-upload__tip">支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-dialog title="选择图片" :visible.sync="dialogImageVisible" width="80%" append-to-body>
|
||||
<wx-material-select ref="materialSelect" :objData="{type: 'image', accountId: this.queryParams.accountId}"
|
||||
@selectMaterial="selectMaterial" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
<el-input :rows="8" type="textarea" v-model="articlesAdd[isActiveAddNews].digest" placeholder="请输入摘要"
|
||||
class="digest" maxlength="120" style="float: right" />
|
||||
</div>
|
||||
<!--富文本编辑器组件-->
|
||||
<el-row>
|
||||
<wx-editor v-model="articlesAdd[isActiveAddNews].content" :account-id="this.uploadData.accountId"
|
||||
v-if="hackResetEditor"/>
|
||||
</el-row>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogNewsVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm">提 交</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxEditor from '@/views/mp/components/wx-editor/WxEditor.vue';
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
import WxMaterialSelect from '@/views/mp/components/wx-material-select/main.vue'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
import {createDraft, deleteDraft, getDraftPage, updateDraft} from "@/api/mp/draft";
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
import {deleteFreePublish, submitFreePublish} from "@/api/mp/freePublish";
|
||||
|
||||
export default {
|
||||
name: 'MpDraft',
|
||||
components: {
|
||||
WxEditor,
|
||||
WxNews,
|
||||
WxMaterialSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 数据列表
|
||||
list: [],
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
accountId: undefined,
|
||||
},
|
||||
|
||||
// ========== 文件上传 ==========
|
||||
actionUrl: process.env.VUE_APP_BASE_API + "/admin-api/mp/material/upload-permanent", // 上传永久素材的地址
|
||||
headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
|
||||
fileList: [],
|
||||
uploadData: {
|
||||
"type": 'image',
|
||||
// "accountId": 1,
|
||||
},
|
||||
|
||||
// ========== 草稿新建 or 修改 ==========
|
||||
dialogNewsVisible: false,
|
||||
addMaterialLoading: false, // 添加草稿的 loading 标识
|
||||
articlesAdd: [],
|
||||
isActiveAddNews: 0,
|
||||
dialogImageVisible: false,
|
||||
operateMaterial: 'add',
|
||||
articlesMediaId: '',
|
||||
hackResetEditor: false,
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.setAccountId(this.accounts[0].id);
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// ======================== 列表查询 ========================
|
||||
/** 设置账号编号 */
|
||||
setAccountId(accountId) {
|
||||
this.queryParams.accountId = accountId;
|
||||
this.uploadData.accountId = accountId;
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询草稿箱')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
getDraftPage(this.queryParams).then(response => {
|
||||
// 将 thumbUrl 转成 picUrl,保证 wx-news 组件可以预览封面
|
||||
response.data.list.forEach(item => {
|
||||
const newsItem = item.content.newsItem;
|
||||
newsItem.forEach(article => {
|
||||
article.picUrl = article.thumbUrl;
|
||||
})
|
||||
})
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1
|
||||
// 默认选中第一个
|
||||
if (this.queryParams.accountId) {
|
||||
this.setAccountId(this.queryParams.accountId)
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.setAccountId(this.accounts[0].id)
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
|
||||
// ======================== 新增/修改草稿 ========================
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.resetEditor();
|
||||
this.reset();
|
||||
// 打开表单,并设置初始化
|
||||
this.operateMaterial = 'add'
|
||||
this.dialogNewsVisible = true
|
||||
},
|
||||
/** 更新按钮操作 */
|
||||
handleUpdate(item){
|
||||
this.resetEditor();
|
||||
this.reset();
|
||||
this.articlesMediaId = item.mediaId
|
||||
this.articlesAdd = JSON.parse(JSON.stringify(item.content.newsItem))
|
||||
// 打开表单,并设置初始化
|
||||
this.operateMaterial = 'edit'
|
||||
this.dialogNewsVisible = true
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.addMaterialLoading = true
|
||||
if (this.operateMaterial === 'add') {
|
||||
createDraft(this.queryParams.accountId, this.articlesAdd).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.dialogNewsVisible = false;
|
||||
this.getList()
|
||||
}).finally(() => {
|
||||
this.addMaterialLoading = false
|
||||
})
|
||||
} else {
|
||||
updateDraft(this.queryParams.accountId, this.articlesMediaId, this.articlesAdd).then(response => {
|
||||
this.$modal.msgSuccess("更新成功");
|
||||
this.dialogNewsVisible = false;
|
||||
this.getList()
|
||||
}).finally(() => {
|
||||
this.addMaterialLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
// 关闭弹窗
|
||||
dialogNewsClose(done) {
|
||||
this.$modal.confirm('修改内容可能还未保存,确定关闭吗?').then(() => {
|
||||
this.reset()
|
||||
this.resetEditor()
|
||||
done()
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.isActiveAddNews = 0
|
||||
this.articlesAdd = [this.buildEmptyArticle()]
|
||||
},
|
||||
// 表单 Editor 重置
|
||||
resetEditor() {
|
||||
this.hackResetEditor = false // 销毁组件
|
||||
this.$nextTick(() => {
|
||||
this.hackResetEditor = true // 重建组件
|
||||
})
|
||||
},
|
||||
// 将图文向下移动
|
||||
downNews(index) {
|
||||
let temp = this.articlesAdd[index]
|
||||
this.articlesAdd[index] = this.articlesAdd[index+1]
|
||||
this.articlesAdd[index + 1] = temp
|
||||
this.isActiveAddNews = index + 1
|
||||
},
|
||||
// 将图文向上移动
|
||||
upNews(index) {
|
||||
let temp = this.articlesAdd[index]
|
||||
this.articlesAdd[index] = this.articlesAdd[index - 1]
|
||||
this.articlesAdd[index - 1] = temp
|
||||
this.isActiveAddNews = index - 1
|
||||
},
|
||||
// 选中指定 index 的图文
|
||||
activeNews(index) {
|
||||
this.resetEditor();
|
||||
this.isActiveAddNews = index
|
||||
},
|
||||
// 删除指定 index 的图文
|
||||
minusNews(index) {
|
||||
this.$modal.confirm('确定删除该图文吗?').then(() => {
|
||||
this.articlesAdd.splice(index,1);
|
||||
if (this.isActiveAddNews === index) {
|
||||
this.isActiveAddNews = 0
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 添加一个图文
|
||||
plusNews() {
|
||||
this.articlesAdd.push(this.buildEmptyArticle())
|
||||
this.isActiveAddNews = this.articlesAdd.length - 1
|
||||
},
|
||||
// 创建空的 article
|
||||
buildEmptyArticle() {
|
||||
return {
|
||||
"title": '',
|
||||
"thumbMediaId": '',
|
||||
"author": '',
|
||||
"digest": '',
|
||||
"showCoverPic": '',
|
||||
"content": '',
|
||||
"contentSourceUrl": '',
|
||||
"needOpenComment":'',
|
||||
"onlyFansCanComment":'',
|
||||
"thumbUrl":''
|
||||
}
|
||||
},
|
||||
|
||||
// ======================== 文件上传 ========================
|
||||
beforeThumbImageUpload(file) {
|
||||
this.addMaterialLoading = true
|
||||
const isType = file.type === 'image/jpeg'
|
||||
|| file.type === 'image/png'
|
||||
|| file.type === 'image/gif'
|
||||
|| file.type === 'image/bmp'
|
||||
|| file.type === 'image/jpg';
|
||||
if (!isType) {
|
||||
this.$message.error('上传图片格式不对!')
|
||||
this.addMaterialLoading = false
|
||||
return false;
|
||||
}
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isLt) {
|
||||
this.$message.error('上传图片大小不能超过 2M!')
|
||||
this.addMaterialLoading = false
|
||||
return false;
|
||||
}
|
||||
// 校验通过
|
||||
return true;
|
||||
},
|
||||
handleUploadSuccess(response, file, fileList) {
|
||||
this.addMaterialLoading = false // 关闭 loading
|
||||
if (response.code !== 0) {
|
||||
this.$message.error('上传出错:' + response.msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 重置上传文件的表单
|
||||
this.fileList = []
|
||||
|
||||
// 设置草稿的封面字段
|
||||
this.articlesAdd[this.isActiveAddNews].thumbMediaId = response.data.mediaId
|
||||
this.articlesAdd[this.isActiveAddNews].thumbUrl = response.data.url
|
||||
},
|
||||
// 选择 or 上传完素材,设置回草稿
|
||||
selectMaterial(item) {
|
||||
this.dialogImageVisible = false
|
||||
this.articlesAdd[this.isActiveAddNews].thumbMediaId = item.mediaId
|
||||
this.articlesAdd[this.isActiveAddNews].thumbUrl = item.url
|
||||
},
|
||||
// 打开素材选择
|
||||
openMaterial() {
|
||||
this.dialogImageVisible = true
|
||||
try {
|
||||
this.$refs['materialSelect'].queryParams.accountId = this.queryParams.accountId // 强制设置下 accountId,避免二次查询不对
|
||||
this.$refs['materialSelect'].handleQuery(); // 刷新列表,失败也无所谓
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
// ======================== 草稿箱发布 ========================
|
||||
handlePublish(item) {
|
||||
const accountId = this.queryParams.accountId;
|
||||
const mediaId = item.mediaId;
|
||||
const content = '你正在通过发布的方式发表内容。 发布不占用群发次数,一天可多次发布。已发布内容不会推送给用户,也不会展示在公众号主页中。 发布后,你可以前往发表记录获取链接,也可以将发布内容添加到自定义菜单、自动回复、话题和页面模板中。';
|
||||
this.$modal.confirm(content).then(function() {
|
||||
return submitFreePublish(accountId, mediaId);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("发布成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleDelete(item) {
|
||||
const accountId = this.queryParams.accountId;
|
||||
const mediaId = item.mediaId;
|
||||
this.$modal.confirm('此操作将永久删除该草稿, 是否继续?').then(function() {
|
||||
return deleteDraft(accountId, mediaId);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
float: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.add_but {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.ope-row {
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eaeaea;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-upload__tip {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
/*新增图文*/
|
||||
.left {
|
||||
display: inline-block;
|
||||
width: 35%;
|
||||
vertical-align: top;
|
||||
margin-top: 200px;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
margin-top: -40px;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: unset !important;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #165dff;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
border: 1px solid #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 230px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.avatar1 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.digest {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/*新增图文*/
|
||||
/*瀑布流样式*/
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap: 10px;
|
||||
column-count: 5;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*瀑布流样式*/
|
||||
.news-main {
|
||||
background-color: #FFFFFF;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.news-content {
|
||||
background-color: #acadae;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.news-content-title {
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
color: #FFFFFF;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
width: 98%;
|
||||
padding: 1%;
|
||||
opacity: 0.65;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.news-main-item {
|
||||
background-color: #FFFFFF;
|
||||
padding: 5px 0px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.news-content-item {
|
||||
position: relative;
|
||||
margin-left: -3px
|
||||
}
|
||||
|
||||
.news-content-item-title {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.news-content-item-img {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
background-color: #acadae
|
||||
}
|
||||
|
||||
.input-tt {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.activeAddNews {
|
||||
border: 5px solid #2bb673;
|
||||
}
|
||||
|
||||
.news-main-plus {
|
||||
width: 280px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.icon-plus {
|
||||
margin: 10px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.select-item {
|
||||
width: 60%;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
.father .child {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 25px;
|
||||
}
|
||||
|
||||
.father:hover .child {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.thumb-div {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.thumb-but {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.material-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,395 +0,0 @@
|
||||
<!--
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 www.joolun.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
芋道源码:
|
||||
① 优化代码,和项目的代码保持一致
|
||||
-->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号图文" url="https://doc.iocoder.cn/mp/article/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<div class="waterfall" v-loading="loading">
|
||||
<div v-if="item.content && item.content.newsItem" class="waterfall-item" v-for="item in list"
|
||||
:key='item.articleId'>
|
||||
<wx-news :articles="item.content.newsItem" />
|
||||
<!-- 操作 -->
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="handleDelete(item)"
|
||||
v-hasPermi="['mp:free-publish:delete']" />
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getFreePublishPage, deleteFreePublish } from "@/api/mp/freePublish";
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
|
||||
export default {
|
||||
name: 'MpFreePublish',
|
||||
components: {
|
||||
WxNews
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 已发表列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
queryParamsSize: 10 // 每页显示多少条
|
||||
},
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询已发表图文')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
getFreePublishPage(this.queryParams).then(response => {
|
||||
// 将 thumbUrl 转成 picUrl,保证 wx-news 组件可以预览封面
|
||||
response.data.list.forEach(item => {
|
||||
const newsItem = item.content.newsItem;
|
||||
newsItem.forEach(article => {
|
||||
article.picUrl = article.thumbUrl;
|
||||
})
|
||||
})
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(item){
|
||||
const articleId = item.articleId;
|
||||
const accountId = this.queryParams.accountId;
|
||||
this.$modal.confirm('删除后用户将无法访问此页面,确定删除?').then(function() {
|
||||
return deleteFreePublish(accountId, articleId);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
float: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.add_but {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.ope-row {
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eaeaea;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-upload__tip {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
/*新增图文*/
|
||||
.left {
|
||||
display: inline-block;
|
||||
width: 35%;
|
||||
vertical-align: top;
|
||||
margin-top: 200px;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
margin-top: -40px;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: unset !important;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #165dff;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
border: 1px solid #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 230px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.avatar1 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.digest {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/*新增图文*/
|
||||
/*瀑布流样式*/
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap: 10px;
|
||||
column-count: 5;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*瀑布流样式*/
|
||||
.news-main {
|
||||
background-color: #FFFFFF;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.news-content {
|
||||
background-color: #acadae;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.news-content-title {
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
color: #FFFFFF;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
width: 98%;
|
||||
padding: 1%;
|
||||
opacity: 0.65;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.news-main-item {
|
||||
background-color: #FFFFFF;
|
||||
padding: 5px 0px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.news-content-item {
|
||||
position: relative;
|
||||
margin-left: -3px
|
||||
}
|
||||
|
||||
.news-content-item-title {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.news-content-item-img {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
background-color: #acadae
|
||||
}
|
||||
|
||||
.input-tt {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.activeAddNews {
|
||||
border: 5px solid #2bb673;
|
||||
}
|
||||
|
||||
.news-main-plus {
|
||||
width: 280px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.icon-plus {
|
||||
margin: 10px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.select-item {
|
||||
width: 60%;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
.father .child {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 25px;
|
||||
}
|
||||
|
||||
.father:hover .child {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.thumb-div {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.thumb-but {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.material-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,440 +0,0 @@
|
||||
<!--
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 www.joolun.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
芋道源码:
|
||||
① 清理冗余 css 内容,清理冗余 data 变量
|
||||
② 美化样式,支持播放,提升使用体验
|
||||
③ 优化代码,特别是方法名和变量,提升可读性
|
||||
-->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号素材" url="https://doc.iocoder.cn/mp/material/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-tabs v-model="type" @tab-click="handleClick">
|
||||
<!-- tab 1:图片 -->
|
||||
<el-tab-pane name="image">
|
||||
<span slot="label"><i class="el-icon-picture"></i> 图片</span>
|
||||
<div class="add_but" v-hasPermi="['mp:material:upload-permanent']">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeImageUpload" :on-success="handleUploadSuccess">
|
||||
<el-button size="mini" type="primary">点击上传</el-button>
|
||||
<sapn slot="tip" class="el-upload__tip" style="margin-left: 5px">支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M</sapn>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="waterfall" v-loading="loading">
|
||||
<div class="waterfall-item" v-for="item in list" :key='item.id'>
|
||||
<a target="_blank" :href="item.url">
|
||||
<img class="material-img" :src="item.url">
|
||||
<div class="item-name">{{item.name}}</div>
|
||||
</a>
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="handleDelete(item)"
|
||||
v-hasPermi="['mp:material:delete']"/>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- tab 2:语音 -->
|
||||
<el-tab-pane name="voice">
|
||||
<span slot="label"><i class="el-icon-microphone"></i> 语音</span>
|
||||
<div class="add_but" v-hasPermi="['mp:material:upload-permanent']">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:on-success="handleUploadSuccess" :before-upload="beforeVoiceUpload">
|
||||
<el-button size="mini" type="primary">点击上传</el-button>
|
||||
<span slot="tip" class="el-upload__tip" style="margin-left: 5px">格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s</span>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px;">
|
||||
<el-table-column label="编号" align="center" prop="mediaId" />
|
||||
<el-table-column label="文件名" align="center" prop="name" />
|
||||
<el-table-column label="语音" align="center">
|
||||
<template v-slot="scope">
|
||||
<wx-voice-player :url="scope.row.url" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" icon="el-icon-download" size="small" plain @click="handleDownload(scope.row)">下载</el-button>
|
||||
<el-button type="text" icon="el-icon-delete" size="small" plain @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['mp:material:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- tab 3:视频 -->
|
||||
<el-tab-pane name="video">
|
||||
<span slot="label"><i class="el-icon-video-play"></i> 视频</span>
|
||||
<div class="add_but" v-hasPermi="['mp:material:upload-permanent']">
|
||||
<el-button size="mini" type="primary" @click="handleAddVideo">新建视频</el-button>
|
||||
</div>
|
||||
<!-- 新建视频的弹窗 -->
|
||||
<el-dialog title="新建视频" :visible.sync="dialogVideoVisible" append-to-body width="600px"
|
||||
v-loading="addMaterialLoading">
|
||||
<el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
|
||||
:before-upload="beforeVideoUpload" :on-success="handleUploadSuccess"
|
||||
ref="uploadVideo" :auto-upload="false">
|
||||
<el-button slot="trigger" size="mini" type="primary">选择视频</el-button>
|
||||
<span class="el-upload__tip" style="margin-left: 10px;">格式支持 MP4,文件大小不超过 10MB</span>
|
||||
</el-upload>
|
||||
<el-form :model="uploadData" :rules="uploadRules" ref="uploadForm" label-width="80px">
|
||||
<el-row>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="uploadData.title" placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题" />
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-form-item label="描述" prop="introduction">
|
||||
<el-input :rows="3" type="textarea" v-model="uploadData.introduction"
|
||||
placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容" />
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancelVideo">取 消</el-button>
|
||||
<el-button type="primary" @click="submitVideo">提 交</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px;">
|
||||
<el-table-column label="编号" align="center" prop="mediaId" />
|
||||
<el-table-column label="文件名" align="center" prop="name" />
|
||||
<el-table-column label="标题" align="center" prop="title" />
|
||||
<el-table-column label="介绍" align="center" prop="introduction" />
|
||||
<el-table-column label="视频" align="center">
|
||||
<template v-slot="scope">
|
||||
<wx-video-player :url="scope.row.url" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button type="text" icon="el-icon-download" size="small" plain @click="handleDownload(scope.row)">下载</el-button>
|
||||
<el-button type="text" icon="el-icon-delete" size="small" plain @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['mp:material:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
|
||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
import { getMaterialPage, deletePermanentMaterial } from "@/api/mp/material";
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
|
||||
export default {
|
||||
name: 'MpMaterial',
|
||||
components: {
|
||||
WxVoicePlayer,
|
||||
WxVideoPlayer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 'image',
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 数据列表
|
||||
list: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
accountId: undefined,
|
||||
permanent: true,
|
||||
},
|
||||
|
||||
actionUrl: process.env.VUE_APP_BASE_API + '/admin-api/mp/material/upload-permanent',
|
||||
headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
|
||||
fileList:[],
|
||||
uploadData: {
|
||||
"type": 'image',
|
||||
"title":'',
|
||||
"introduction":''
|
||||
},
|
||||
// === 视频上传,独有变量 ===
|
||||
dialogVideoVisible: false,
|
||||
addMaterialLoading: false,
|
||||
uploadRules: { // 视频上传的校验规则
|
||||
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
|
||||
introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }],
|
||||
},
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.setAccountId(this.accounts[0].id);
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// ======================== 列表查询 ========================
|
||||
/** 设置账号编号 */
|
||||
setAccountId(accountId) {
|
||||
this.queryParams.accountId = accountId;
|
||||
this.uploadData.accountId = accountId;
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询草稿箱')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
getMaterialPage({
|
||||
...this.queryParams,
|
||||
type: this.type
|
||||
}).then(response => {
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1
|
||||
// 默认选中第一个
|
||||
if (this.queryParams.accountId) {
|
||||
this.setAccountId(this.queryParams.accountId)
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.setAccountId(this.accounts[0].id)
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
// 设置 type
|
||||
this.uploadData.type = tab.name
|
||||
// 从第一页开始查询
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
// ======================== 文件上传 ========================
|
||||
beforeImageUpload(file) {
|
||||
const isType = file.type === 'image/jpeg'
|
||||
|| file.type === 'image/png'
|
||||
|| file.type === 'image/gif'
|
||||
|| file.type === 'image/bmp'
|
||||
|| file.type === 'image/jpg';
|
||||
if (!isType) {
|
||||
this.$message.error('上传图片格式不对!')
|
||||
return false;
|
||||
}
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isLt) {
|
||||
this.$message.error('上传图片大小不能超过 2M!')
|
||||
return false;
|
||||
}
|
||||
this.loading = true
|
||||
return true;
|
||||
},
|
||||
beforeVoiceUpload(file){
|
||||
const isType = file.type === 'audio/mp3'
|
||||
|| file.type === 'audio/wma'
|
||||
|| file.type === 'audio/wav'
|
||||
|| file.type === 'audio/amr';
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isType) {
|
||||
this.$message.error('上传语音格式不对!')
|
||||
return false;
|
||||
}
|
||||
if (!isLt) {
|
||||
this.$message.error('上传语音大小不能超过 2M!')
|
||||
return false;
|
||||
}
|
||||
this.loading = true
|
||||
return true;
|
||||
},
|
||||
beforeVideoUpload(file){
|
||||
const isType = file.type === 'video/mp4'
|
||||
if (!isType) {
|
||||
this.$message.error('上传视频格式不对!')
|
||||
return false;
|
||||
}
|
||||
const isLt = file.size / 1024 / 1024 < 10
|
||||
if (!isLt) {
|
||||
this.$message.error('上传视频大小不能超过 10M!')
|
||||
return false
|
||||
}
|
||||
this.addMaterialLoading = true
|
||||
return true
|
||||
},
|
||||
handleUploadSuccess(response, file, fileList) {
|
||||
this.loading = false
|
||||
this.addMaterialLoading = false
|
||||
if (response.code !== 0) {
|
||||
this.$message.error('上传出错:' + response.msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 清空上传时的各种数据
|
||||
this.dialogVideoVisible = false
|
||||
this.fileList = []
|
||||
this.uploadData.title = ''
|
||||
this.uploadData.introduction = ''
|
||||
|
||||
// 加载数据
|
||||
this.getList()
|
||||
},
|
||||
// 下载文件
|
||||
handleDownload(row) {
|
||||
window.open(row.url,'_blank')
|
||||
},
|
||||
// 提交 video 新建的表单
|
||||
submitVideo() {
|
||||
this.$refs['uploadForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
this.$refs.uploadVideo.submit()
|
||||
})
|
||||
},
|
||||
handleAddVideo() {
|
||||
this.resetVideo();
|
||||
this.dialogVideoVisible = true
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancelVideo() {
|
||||
this.dialogVideoVisible = false;
|
||||
this.resetVideo();
|
||||
},
|
||||
/** 表单重置 */
|
||||
resetVideo() {
|
||||
this.fileList = []
|
||||
this.uploadData.title = ''
|
||||
this.uploadData.introduction = ''
|
||||
this.resetForm("uploadForm");
|
||||
},
|
||||
|
||||
// ======================== 其它操作 ========================
|
||||
handleDelete(item) {
|
||||
const id = item.id
|
||||
this.$modal.confirm('此操作将永久删除该文件, 是否继续?').then(function() {
|
||||
return deletePermanentMaterial(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/*瀑布流样式*/
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap:10px;
|
||||
column-count: 5;
|
||||
margin-top: 10px; /* 芋道源码:增加 10px,避免顶着上面 */
|
||||
}
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
}
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color:red;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
/*瀑布流样式*/
|
||||
</style>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,714 +0,0 @@
|
||||
<!--
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 www.joolun.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
芋道源码:
|
||||
① less 切到 scss,减少对 less 和 less-loader 的依赖
|
||||
②
|
||||
-->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号菜单" url="https://doc.iocoder.cn/mp/menu/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="public-account-management clearfix" v-loading="loading">
|
||||
<!--左边配置菜单-->
|
||||
<div class="left">
|
||||
<div class="weixin-hd">
|
||||
<div class="weixin-title">{{ name }}</div>
|
||||
</div>
|
||||
<div class="weixin-menu menu_main clearfix">
|
||||
<div class="menu_bottom" v-for="(item, i) of menuList" :key="i" >
|
||||
<!-- 一级菜单 -->
|
||||
<div @click="menuClick(i, item)" class="menu_item el-icon-s-fold" :class="{'active': isActive === i}">{{item.name}}</div>
|
||||
<!-- 以下为二级菜单-->
|
||||
<div class="submenu" v-if="isSubMenuFlag === i">
|
||||
<div class="subtitle menu_bottom" v-if="item.children" v-for="(subItem, k) in item.children" :key="k">
|
||||
<div class="menu_subItem" :class="{'active': isSubMenuActive === i + '' + k}" @click="subMenuClick(subItem, i, k)">
|
||||
{{subItem.name}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
|
||||
<div class="menu_bottom menu_addicon" v-if="!item.children || item.children.length < 5" @click="addSubMenu(i,item)">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 一级菜单加号 -->
|
||||
<div class="menu_bottom menu_addicon" v-if="this.menuList.length < 3" @click="addMenu"><i class="el-icon-plus"></i></div>
|
||||
</div>
|
||||
<div class="save_div">
|
||||
<el-button class="save_btn" type="success" size="small" @click="handleSave" v-hasPermi="['mp:menu:save']">保存并发布菜单</el-button>
|
||||
<el-button class="save_btn" type="danger" size="small" @click="handleDelete" v-hasPermi="['mp:menu:delete']">清空菜单</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!--右边配置-->
|
||||
<div v-if="showRightFlag" class="right">
|
||||
<div class="configure_page">
|
||||
<div class="delete_btn">
|
||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteMenu(tempObj)">删除当前菜单</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<span>菜单名称:</span>
|
||||
<el-input class="input_width" v-model="tempObj.name" placeholder="请输入菜单名称" :maxlength="nameMaxLength" clearable />
|
||||
</div>
|
||||
<div v-if="showConfigureContent">
|
||||
<div class="menu_content">
|
||||
<span>菜单标识:</span>
|
||||
<el-input class="input_width" v-model="tempObj.menuKey" placeholder="请输入菜单 KEY" clearable />
|
||||
</div>
|
||||
<div class="menu_content">
|
||||
<span>菜单内容:</span>
|
||||
<el-select v-model="tempObj.type" clearable placeholder="请选择" class="menu_option">
|
||||
<el-option v-for="item in menuOptions" :label="item.label" :value="item.value" :key="item.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type === 'view'">
|
||||
<span>跳转链接:</span>
|
||||
<el-input class="input_width" v-model="tempObj.url" placeholder="请输入链接" clearable />
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type === 'miniprogram'">
|
||||
<div class="applet">
|
||||
<span>小程序的 appid :</span>
|
||||
<el-input class="input_width" v-model="tempObj.miniProgramAppId" placeholder="请输入小程序的appid" clearable />
|
||||
</div>
|
||||
<div class="applet">
|
||||
<span>小程序的页面路径:</span>
|
||||
<el-input class="input_width" v-model="tempObj.miniProgramPagePath"
|
||||
placeholder="请输入小程序的页面路径,如:pages/index" clearable />
|
||||
</div>
|
||||
<div class="applet">
|
||||
<span>小程序的备用网页:</span>
|
||||
<el-input class="input_width" v-model="tempObj.url" placeholder="不支持小程序的老版本客户端将打开本网页" clearable />
|
||||
</div>
|
||||
<p class="blue">tips:需要和公众号进行关联才可以把小程序绑定带微信菜单上哟!</p>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type === 'article_view_limited'">
|
||||
<el-row>
|
||||
<div class="select-item" v-if="tempObj && tempObj.replyArticles">
|
||||
<wx-news :articles="tempObj.replyArticles" />
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="deleteMaterial" />
|
||||
</el-row>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-row>
|
||||
<el-col :span="24" style="text-align: center">
|
||||
<el-button type="success" @click="openMaterial">
|
||||
素材库选择<i class="el-icon-circle-check el-icon--right"></i>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-dialog title="选择图文" :visible.sync="dialogNewsVisible" width="90%">
|
||||
<wx-material-select :objData="{type: 'news', accountId: this.accountId}" @selectMaterial="selectMaterial" />
|
||||
</el-dialog>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type === 'click' || tempObj.type === 'scancode_waitmsg'">
|
||||
<wx-reply-select :objData="tempObj.reply" v-if="hackResetWxReplySelect" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 一进页面就显示的默认页面,当点击左边按钮的时候,就不显示了-->
|
||||
<div v-else class="right">
|
||||
<p>请选择菜单配置</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxReplySelect from '@/views/mp/components/wx-reply/main.vue'
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
import WxMaterialSelect from '@/views/mp/components/wx-material-select/main.vue'
|
||||
import { deleteMenu, getMenuList, saveMenu } from "@/api/mp/menu";
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
|
||||
export default {
|
||||
name: 'MpMenu',
|
||||
components: {
|
||||
WxReplySelect,
|
||||
WxNews,
|
||||
WxMaterialSelect
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
// ======================== 列表查询 ========================
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 查询参数
|
||||
accountId: undefined,
|
||||
name:'', // 公众号名
|
||||
menuList: {
|
||||
children: [],
|
||||
},
|
||||
|
||||
// ======================== 菜单操作 ========================
|
||||
isActive: -1,// 一级菜单点中样式
|
||||
isSubMenuActive: -1, // 一级菜单点中样式
|
||||
isSubMenuFlag: -1, // 二级菜单显示标志
|
||||
|
||||
// ======================== 菜单编辑 ========================
|
||||
showRightFlag: false, // 右边配置显示默认详情还是配置详情
|
||||
nameMaxLength: 0, // 菜单名称最大长度;1 级是 4 字符;2 级是 7 字符;
|
||||
showConfigureContent: true, // 是否展示配置内容;如果有子菜单,就不显示配置内容
|
||||
hackResetWxReplySelect: false, // 重置 WxReplySelect 组件
|
||||
tempObj: {}, // 右边临时变量,作为中间值牵引关系
|
||||
tempSelfObj: { // 一些临时值放在这里进行判断,如果放在 tempObj,由于引用关系,menu 也会多了多余的参数
|
||||
},
|
||||
dialogNewsVisible: false, // 跳转图文时的素材选择弹窗
|
||||
menuOptions: [{
|
||||
value: 'view',
|
||||
label: '跳转网页'
|
||||
}, {
|
||||
value: 'miniprogram',
|
||||
label: '跳转小程序'
|
||||
}, {
|
||||
value: 'click',
|
||||
label: '点击回复'
|
||||
}, {
|
||||
value: 'article_view_limited',
|
||||
label: '跳转图文消息'
|
||||
}, {
|
||||
value: 'scancode_push',
|
||||
label: '扫码直接返回结果'
|
||||
}, {
|
||||
value: 'scancode_waitmsg',
|
||||
label: '扫码回复'
|
||||
}, {
|
||||
value: 'pic_sysphoto',
|
||||
label: '系统拍照发图'
|
||||
}, {
|
||||
value: 'pic_photo_or_album',
|
||||
label: '拍照或者相册'
|
||||
}, {
|
||||
value: 'pic_weixin',
|
||||
label: '微信相册'
|
||||
}, {
|
||||
value: 'location_select',
|
||||
label: '选择地理位置'
|
||||
}],
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.setAccountId(this.accounts[0].id);
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// ======================== 列表查询 ========================
|
||||
/** 设置账号编号 */
|
||||
setAccountId(accountId) {
|
||||
this.accountId = accountId;
|
||||
this.name = this.accounts.find(item => item.id === accountId)?.name;
|
||||
},
|
||||
getList() {
|
||||
this.loading = false;
|
||||
getMenuList(this.accountId).then(response => {
|
||||
response.data = this.convertMenuList(response.data);
|
||||
this.menuList = this.handleTree(response.data, "id");
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.resetForm();
|
||||
// 默认选中第一个
|
||||
if (this.accountId) {
|
||||
this.setAccountId(this.accountId)
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm();
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.setAccountId(this.accounts[0].id)
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
// 将后端返回的 menuList,转换成前端的 menuList
|
||||
convertMenuList(list) {
|
||||
const menuList = [];
|
||||
list.forEach(item => {
|
||||
const menu = {
|
||||
...item,
|
||||
};
|
||||
if (item.type === 'click' || item.type === 'scancode_waitmsg') {
|
||||
this.$delete(menu, 'replyMessageType');
|
||||
this.$delete(menu, 'replyContent');
|
||||
this.$delete(menu, 'replyMediaId');
|
||||
this.$delete(menu, 'replyMediaUrl');
|
||||
this.$delete(menu, 'replyDescription');
|
||||
this.$delete(menu, 'replyArticles');
|
||||
menu.reply = {
|
||||
type: item.replyMessageType,
|
||||
accountId: item.accountId,
|
||||
content: item.replyContent,
|
||||
mediaId: item.replyMediaId,
|
||||
url: item.replyMediaUrl,
|
||||
title: item.replyTitle,
|
||||
description: item.replyDescription,
|
||||
thumbMediaId: item.replyThumbMediaId,
|
||||
thumbMediaUrl: item.replyThumbMediaUrl,
|
||||
articles: item.replyArticles,
|
||||
musicUrl: item.replyMusicUrl,
|
||||
hqMusicUrl: item.replyHqMusicUrl,
|
||||
}
|
||||
}
|
||||
menuList.push(menu);
|
||||
});
|
||||
return menuList;
|
||||
},
|
||||
// 重置表单,清空表单数据
|
||||
resetForm() {
|
||||
// 菜单操作
|
||||
this.isActive = -1;
|
||||
this.isSubMenuActive = -1;
|
||||
this.isSubMenuFlag = -1;
|
||||
|
||||
// 菜单编辑
|
||||
this.showRightFlag = false;
|
||||
this.nameMaxLength = 0;
|
||||
this.showConfigureContent = 0;
|
||||
this.hackResetWxReplySelect = true;
|
||||
this.hackResetWxReplySelect = false;
|
||||
this.tempObj = {};
|
||||
this.tempSelfObj = {};
|
||||
this.dialogNewsVisible = false;
|
||||
},
|
||||
|
||||
// ======================== 菜单操作 ========================
|
||||
// 一级菜单点击事件
|
||||
menuClick(i, item) {
|
||||
// 右侧的表单相关
|
||||
this.resetEditor();
|
||||
this.showRightFlag = true; // 右边菜单
|
||||
this.tempObj = item; // 这个如果放在顶部,flag 会没有。因为重新赋值了。
|
||||
this.tempSelfObj.grand = "1"; // 表示一级菜单
|
||||
this.tempSelfObj.index = i; // 表示一级菜单索引
|
||||
this.nameMaxLength = 4
|
||||
this.showConfigureContent = !(item.children && item.children.length > 0); // 有子菜单,就不显示配置内容
|
||||
|
||||
// 左侧的选中
|
||||
this.isActive = i; // 一级菜单选中样式
|
||||
this.isSubMenuFlag = i; // 二级菜单显示标志
|
||||
this.isSubMenuActive = -1; // 二级菜单去除选中样式
|
||||
},
|
||||
// 二级菜单点击事件
|
||||
subMenuClick(subItem, index, k) {
|
||||
// 右侧的表单相关
|
||||
this.resetEditor();
|
||||
this.showRightFlag = true; // 右边菜单
|
||||
this.tempObj = subItem; // 将点击的数据放到临时变量,对象有引用作用
|
||||
this.tempSelfObj.grand = "2"; // 表示二级菜单
|
||||
this.tempSelfObj.index = index; // 表示一级菜单索引
|
||||
this.tempSelfObj.secondIndex = k; // 表示二级菜单索引
|
||||
this.nameMaxLength = 7
|
||||
this.showConfigureContent = true;
|
||||
|
||||
// 左侧的选中
|
||||
this.isActive = -1; // 一级菜单去除样式
|
||||
this.isSubMenuActive = index + "" + k; // 二级菜单选中样式
|
||||
},
|
||||
// 添加横向一级菜单
|
||||
addMenu() {
|
||||
const menuKeyLength = this.menuList.length;
|
||||
const addButton = {
|
||||
name: "菜单名称",
|
||||
children: [],
|
||||
reply: { // 用于存储回复内容
|
||||
'type': 'text',
|
||||
'accountId': this.accountId // 保证组件里,可以使用到对应的公众号
|
||||
}
|
||||
}
|
||||
this.$set(this.menuList, menuKeyLength, addButton)
|
||||
this.menuClick(this.menuKeyLength - 1, addButton)
|
||||
},
|
||||
// 添加横向二级菜单;item 表示要操作的父菜单
|
||||
addSubMenu(i, item) {
|
||||
// 清空父菜单的属性,因为它只需要 name 属性即可
|
||||
if (!item.children || item.children.length <= 0) {
|
||||
this.$set( item, 'children',[])
|
||||
this.$delete( item, 'type')
|
||||
this.$delete( item, 'menuKey')
|
||||
this.$delete( item, 'miniProgramAppId')
|
||||
this.$delete( item, 'miniProgramPagePath')
|
||||
this.$delete( item, 'url')
|
||||
this.$delete( item, 'reply')
|
||||
this.$delete( item, 'articleId')
|
||||
this.$delete( item, 'replyArticles')
|
||||
// 关闭配置面板
|
||||
this.showConfigureContent = false
|
||||
}
|
||||
|
||||
let subMenuKeyLength = item.children.length; // 获取二级菜单key长度
|
||||
let addButton = {
|
||||
name: "子菜单名称",
|
||||
reply: { // 用于存储回复内容
|
||||
'type': 'text',
|
||||
'accountId': this.accountId // 保证组件里,可以使用到对应的公众号
|
||||
}
|
||||
}
|
||||
this.$set(item.children, subMenuKeyLength, addButton);
|
||||
this.subMenuClick(item.children[subMenuKeyLength], i, subMenuKeyLength)
|
||||
},
|
||||
// 删除当前菜单
|
||||
deleteMenu(item) {
|
||||
this.$modal.confirm('确定要删除吗?').then(() => {
|
||||
// 删除数据
|
||||
if (this.tempSelfObj.grand === "1") { // 一级菜单的删除方法
|
||||
this.menuList.splice(this.tempSelfObj.index, 1);
|
||||
} else if (this.tempSelfObj.grand === "2") { // 二级菜单的删除方法
|
||||
this.menuList[this.tempSelfObj.index].children.splice(this.tempSelfObj.secondIndex, 1);
|
||||
}
|
||||
// 提示
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
|
||||
// 处理菜单的选中
|
||||
this.tempObj = {};
|
||||
this.showRightFlag = false;
|
||||
this.isActive = -1;
|
||||
this.isSubMenuActive = -1;
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
// ======================== 菜单编辑 ========================
|
||||
handleSave() {
|
||||
this.$modal.confirm('确定要保证并发布该菜单吗?').then(() => {
|
||||
this.loading = true
|
||||
return saveMenu(this.accountId, this.convertMenuFormList());
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("发布成功");
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
});
|
||||
},
|
||||
// 表单 Editor 重置
|
||||
resetEditor() {
|
||||
this.hackResetWxReplySelect = false // 销毁组件
|
||||
this.$nextTick(() => {
|
||||
this.hackResetWxReplySelect = true // 重建组件
|
||||
})
|
||||
},
|
||||
handleDelete() {
|
||||
this.$modal.confirm('确定要清空所有菜单吗?').then(() => {
|
||||
this.loading = true
|
||||
return deleteMenu(this.accountId);
|
||||
}).then(() => {
|
||||
this.handleQuery();
|
||||
this.$modal.msgSuccess("清空成功");
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.loading = false
|
||||
});
|
||||
},
|
||||
// 将前端的 menuList,转换成后端接收的 menuList
|
||||
convertMenuFormList() {
|
||||
const menuList = [];
|
||||
this.menuList.forEach(item => {
|
||||
let menu = this.convertMenuForm(item);
|
||||
menuList.push(menu);
|
||||
// 处理子菜单
|
||||
if (!item.children || item.children.length <= 0) {
|
||||
return;
|
||||
}
|
||||
menu.children = [];
|
||||
item.children.forEach(subItem => {
|
||||
menu.children.push(this.convertMenuForm(subItem))
|
||||
})
|
||||
})
|
||||
return menuList;
|
||||
},
|
||||
// 将前端的 menu,转换成后端接收的 menu
|
||||
convertMenuForm(menu) {
|
||||
let result = {
|
||||
...menu,
|
||||
children: undefined, // 不处理子节点
|
||||
reply: undefined, // 稍后复制
|
||||
}
|
||||
if (menu.type === 'click' || menu.type === 'scancode_waitmsg') {
|
||||
result.replyMessageType = menu.reply.type;
|
||||
result.replyContent = menu.reply.content;
|
||||
result.replyMediaId = menu.reply.mediaId;
|
||||
result.replyMediaUrl = menu.reply.url;
|
||||
result.replyTitle = menu.reply.title;
|
||||
result.replyDescription = menu.reply.description;
|
||||
result.replyThumbMediaId = menu.reply.thumbMediaId;
|
||||
result.replyThumbMediaUrl = menu.reply.thumbMediaUrl;
|
||||
result.replyArticles = menu.reply.articles;
|
||||
result.replyMusicUrl = menu.reply.musicUrl;
|
||||
result.replyHqMusicUrl = menu.reply.hqMusicUrl;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// ======================== 菜单编辑(素材选择) ========================
|
||||
openMaterial() {
|
||||
this.dialogNewsVisible = true
|
||||
},
|
||||
selectMaterial(item) {
|
||||
const articleId = item.articleId;
|
||||
const articles = item.content.newsItem;
|
||||
// 提示,针对多图文
|
||||
if (articles.length > 1) {
|
||||
this.$alert('您选择的是多图文,将默认跳转第一篇', '提示', {
|
||||
confirmButtonText: '确定'
|
||||
})
|
||||
}
|
||||
this.dialogNewsVisible = false
|
||||
|
||||
// 设置菜单的回复
|
||||
this.tempObj.articleId = articleId;
|
||||
this.tempObj.replyArticles = [];
|
||||
articles.forEach(article => {
|
||||
this.tempObj.replyArticles.push({
|
||||
title: article.title,
|
||||
description: article.digest,
|
||||
picUrl: article.picUrl,
|
||||
url: article.url,
|
||||
})
|
||||
})
|
||||
},
|
||||
deleteMaterial() {
|
||||
this.$delete(this.tempObj,'articleId')
|
||||
this.$delete(this.tempObj,'replyArticles')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<!--本组件样式-->
|
||||
<style lang="scss" scoped="scoped">
|
||||
/* 公共颜色变量 */
|
||||
.clearfix{*zoom:1;}
|
||||
.clearfix::after{content: "";display: table; clear: both;}
|
||||
div{
|
||||
text-align: left;
|
||||
}
|
||||
.weixin-hd{
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 426px;
|
||||
left:0px;
|
||||
width: 300px;
|
||||
height:64px;
|
||||
background: transparent url("assets/menu_head.png") no-repeat 0 0;
|
||||
background-position: 0 0;
|
||||
background-size: 100%
|
||||
}
|
||||
.weixin-title{
|
||||
color:#fff;
|
||||
font-size:14px;
|
||||
width:100%;
|
||||
text-align: center;
|
||||
position:absolute;
|
||||
top: 33px;
|
||||
left: 0px;
|
||||
}
|
||||
.weixin-menu{
|
||||
background: transparent url("assets/menu_foot.png") no-repeat 0 0;
|
||||
padding-left: 43px;
|
||||
font-size: 12px
|
||||
}
|
||||
.menu_option{
|
||||
width: 40%!important;
|
||||
}
|
||||
.public-account-management{
|
||||
min-width: 1200px;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
.left{
|
||||
float: left;
|
||||
display: inline-block;
|
||||
width: 350px;
|
||||
height: 715px;
|
||||
background: url("assets/iphone_backImg.png") no-repeat;
|
||||
background-size: 100% auto;
|
||||
padding: 518px 25px 88px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
/*第一级菜单*/
|
||||
.menu_main{
|
||||
.menu_bottom{
|
||||
position: relative;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 85.5px;
|
||||
text-align: center;
|
||||
border: 1px solid #ebedee;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
&.menu_addicon{
|
||||
height: 46px;
|
||||
line-height: 46px;
|
||||
}
|
||||
.menu_item{
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
&.active{
|
||||
border: 1px solid #2bb673;
|
||||
}
|
||||
}
|
||||
.menu_subItem{
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
&.active{
|
||||
border: 1px solid #2bb673;
|
||||
}
|
||||
}
|
||||
}
|
||||
i{
|
||||
color:#2bb673;
|
||||
}
|
||||
/*第二级菜单*/
|
||||
.submenu{
|
||||
position: absolute;
|
||||
width: 85.5px;
|
||||
bottom: 45px;
|
||||
.subtitle{
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
.save_div{
|
||||
margin-top: 15px;
|
||||
text-align: center;
|
||||
.save_btn{
|
||||
bottom: 20px;
|
||||
left: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*右边菜单内容*/
|
||||
.right {
|
||||
float: left;
|
||||
width: 63%;
|
||||
background-color: #e8e7e7;
|
||||
padding: 20px;
|
||||
margin-left: 20px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
.configure_page {
|
||||
.delete_btn {
|
||||
text-align: right;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.menu_content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.configur_content {
|
||||
margin-top: 20px;
|
||||
background-color: #fff;
|
||||
padding: 20px 10px;
|
||||
border-radius: 5px
|
||||
}
|
||||
.blue {
|
||||
color:#29b6f6;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.applet{
|
||||
margin-bottom: 20px;
|
||||
span{
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
.input_width {
|
||||
width: 40%;
|
||||
}
|
||||
.material{
|
||||
.input_width{
|
||||
width: 30%;
|
||||
}
|
||||
.el-textarea{
|
||||
width: 80%
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-input {
|
||||
width: 70%;
|
||||
margin-right: 2%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!--素材样式-->
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
text-align: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
.select-item {
|
||||
width: 280px;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.select-item2 {
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.ope-row {
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,238 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号消息" url="https://doc.iocoder.cn/mp/message/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- TODO 等待处理 -->
|
||||
<el-form-item label="消息类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择消息类型" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.MP_MESSAGE_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户标识" prop="openid">
|
||||
<el-input v-model="queryParams.openid" placeholder="请输入用户标识" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="发送时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消息类型" align="center" prop="type" width="80"/>
|
||||
<el-table-column label="发送方" align="center" prop="sendFrom" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-tag v-if="scope.row.sendFrom === 1" type="success">粉丝</el-tag>
|
||||
<el-tag v-else type="info">公众号</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用户标识" align="center" prop="openid" width="300" />
|
||||
<el-table-column label="内容" prop="content">
|
||||
<template v-slot="scope">
|
||||
<!-- 【事件】区域 -->
|
||||
<div v-if="scope.row.type === 'event' && scope.row.event === 'subscribe'">
|
||||
<el-tag type="success" size="mini">关注</el-tag>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'unsubscribe'">
|
||||
<el-tag type="danger" size="mini">取消关注</el-tag>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'CLICK'">
|
||||
<el-tag size="mini">点击菜单</el-tag>【{{ scope.row.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'VIEW'">
|
||||
<el-tag size="mini">点击菜单链接</el-tag>【{{ scope.row.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'scancode_waitmsg'">
|
||||
<el-tag size="mini">扫码结果</el-tag>【{{ scope.row.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'scancode_push'">
|
||||
<el-tag size="mini">扫码结果</el-tag>【{{ scope.row.eventKey }}】
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'pic_sysphoto'">
|
||||
<el-tag size="mini">系统拍照发图</el-tag>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'pic_photo_or_album'">
|
||||
<el-tag size="mini">拍照或者相册</el-tag>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'pic_weixin'">
|
||||
<el-tag size="mini">微信相册</el-tag>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event' && scope.row.event === 'location_select'">
|
||||
<el-tag size="mini">选择地理位置</el-tag>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'event'">
|
||||
<el-tag type="danger" size="mini">未知事件类型</el-tag>
|
||||
</div>
|
||||
<!-- 【消息】区域 -->
|
||||
<div v-else-if="scope.row.type === 'text'">{{ scope.row.content }}</div>
|
||||
<div v-else-if="scope.row.type === 'voice'">
|
||||
<wx-voice-player :url="scope.row.mediaUrl" :content="scope.row.recognition" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'image'">
|
||||
<a target="_blank" :href="scope.row.mediaUrl">
|
||||
<img :src="scope.row.mediaUrl" style="width: 100px">
|
||||
</a>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'video' || scope.row.type === 'shortvideo'">
|
||||
<wx-video-player :url="scope.row.mediaUrl" style="margin-top: 10px" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'link'">
|
||||
<el-tag size="mini">链接</el-tag>:
|
||||
<a :href="scope.row.url" target="_blank">{{scope.row.title}}</a>
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'location'">
|
||||
<wx-location :label="scope.row.label" :location-y="scope.row.locationY" :location-x="scope.row.locationX" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'music'">
|
||||
<wx-music :title="scope.row.title" :description="scope.row.description" :thumb-media-url="scope.row.thumbMediaUrl"
|
||||
:music-url="scope.row.musicUrl" :hq-music-url="scope.row.hqMusicUrl" />
|
||||
</div>
|
||||
<div v-else-if="scope.row.type === 'news'">
|
||||
<wx-news :articles="scope.row.articles" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-tag type="danger" size="mini">未知消息类型</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleSend(scope.row)"
|
||||
v-hasPermi="['mp:message:send']">消息
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 发送消息的弹窗 -->
|
||||
<el-dialog title="粉丝消息列表" :visible.sync="open" width="50%">
|
||||
<wx-msg :user-id="userId" v-if="open" />
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
|
||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
|
||||
import WxMsg from '@/views/mp/components/wx-msg/main.vue';
|
||||
import WxLocation from '@/views/mp/components/wx-location/main.vue';
|
||||
import WxMusic from '@/views/mp/components/wx-music/main.vue';
|
||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||
import { getMessagePage } from "@/api/mp/message";
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
|
||||
export default {
|
||||
name: "MpMessage",
|
||||
components: {
|
||||
WxVideoPlayer,
|
||||
WxVoicePlayer,
|
||||
WxMsg,
|
||||
WxLocation,
|
||||
WxMusic,
|
||||
WxNews
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 粉丝消息列表
|
||||
list: [],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
openid: null,
|
||||
accountId: null,
|
||||
type: null,
|
||||
createTime: []
|
||||
},
|
||||
// 操作的用户编号
|
||||
userId: 0,
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询消息')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getMessagePage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
this.handleQuery();
|
||||
},
|
||||
handleSend(row) {
|
||||
this.userId = row.userId;
|
||||
this.open = true;
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,364 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号统计" url="https://doc.iocoder.cn/mp/statistics/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form ref="queryForm" size="small" :inline="true" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="accountId" @change="getSummary">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间范围" prop="date">
|
||||
<el-date-picker v-model="date" style="width: 260px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:picker-options="datePickerOptions" :default-time="['00:00:00', '23:59:59']"
|
||||
@change="getSummary">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 图表 -->
|
||||
<el-row>
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<span>用户增减数据</span>
|
||||
</div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="userSummaryChart" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<span>累计用户数据</span>
|
||||
</div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="userCumulateChart" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<span>消息概况数据</span>
|
||||
</div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="upstreamMessageChart" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<span>接口分析数据</span>
|
||||
</div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="interfaceSummaryChart" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 引入基本模板
|
||||
import * as echarts from 'echarts'
|
||||
// 引入柱状图组件
|
||||
require('echarts/lib/chart/bar')
|
||||
// 引入柱拆线组件
|
||||
require('echarts/lib/chart/line')
|
||||
// 引入提示框和title组件
|
||||
require('echarts/lib/component/tooltip')
|
||||
require('echarts/lib/component/title')
|
||||
require('echarts/lib/component/legend')
|
||||
|
||||
import { getInterfaceSummary, getUserSummary, getUserCumulate, getUpstreamMessage} from '@/api/mp/statistics'
|
||||
import { datePickerOptions } from "@/utils/constants";
|
||||
import {addTime, beginOfDay, betweenDay, endOfDay, formatDate} from "@/utils/dateUtils";
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
|
||||
export default {
|
||||
name: 'MpStatistics',
|
||||
data() {
|
||||
return {
|
||||
date : [beginOfDay(new Date(new Date().getTime() - 3600 * 1000 * 24 * 7)), // -7 天
|
||||
endOfDay(new Date(new Date().getTime() - 3600 * 1000 * 24))], // -1 天
|
||||
accountId: undefined,
|
||||
accounts: [],
|
||||
|
||||
xAxisDate: [], // X 轴的日期范围
|
||||
userSummaryOption: { // 用户增减数据
|
||||
color: ['#67C23A', '#e5323e'],
|
||||
legend: {
|
||||
data: ['新增用户','取消关注的用户']
|
||||
},
|
||||
tooltip: {},
|
||||
xAxis: {
|
||||
data: [] // X 轴的日期范围
|
||||
},
|
||||
yAxis: {
|
||||
minInterval: 1
|
||||
},
|
||||
series: [{
|
||||
name: '新增用户',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
barGap: 0,
|
||||
data: [] // 新增用户的数据
|
||||
}, {
|
||||
name: '取消关注的用户',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: [] // 取消关注的用户的数据
|
||||
}]
|
||||
},
|
||||
userCumulateOption: { // 累计用户数据
|
||||
legend: {
|
||||
data: ['累计用户量']
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: []
|
||||
},
|
||||
yAxis: {
|
||||
minInterval: 1
|
||||
},
|
||||
series: [{
|
||||
name:'累计用户量',
|
||||
data: [], // 累计用户量的数据
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
upstreamMessageOption: { // 消息发送概况数据
|
||||
color: ['#67C23A', '#e5323e'],
|
||||
legend: {
|
||||
data: ['用户发送人数', '用户发送条数']
|
||||
},
|
||||
tooltip: {},
|
||||
xAxis: {
|
||||
data: [] // X 轴的日期范围
|
||||
},
|
||||
yAxis: {
|
||||
minInterval: 1
|
||||
},
|
||||
series: [{
|
||||
name: '用户发送人数',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: [] // 用户发送人数的数据
|
||||
}, {
|
||||
name: '用户发送条数',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: [] // 用户发送条数的数据
|
||||
}]
|
||||
},
|
||||
interfaceSummaryOption: { // 接口分析况数据
|
||||
color: ['#67C23A', '#e5323e', '#E6A23C', '#409EFF'],
|
||||
legend: {
|
||||
data: ['被动回复用户消息的次数','失败次数', '最大耗时','总耗时']
|
||||
},
|
||||
tooltip: {},
|
||||
xAxis: {
|
||||
data: [] // X 轴的日期范围
|
||||
},
|
||||
yAxis: {},
|
||||
series: [{
|
||||
name: '被动回复用户消息的次数',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
barGap: 0,
|
||||
data: [] // 被动回复用户消息的次数的数据
|
||||
}, {
|
||||
name: '失败次数',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: [] // 失败次数的数据
|
||||
}, {
|
||||
name: '最大耗时',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: [] // 最大耗时的数据
|
||||
}, {
|
||||
name: '总耗时',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: [] // 总耗时的数据
|
||||
}]
|
||||
},
|
||||
|
||||
// 静态变量
|
||||
datePickerOptions: datePickerOptions,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.accountId = this.accounts[0].id;
|
||||
}
|
||||
// 加载数据
|
||||
this.getSummary();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getSummary() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.accountId) {
|
||||
this.$message.error('未选中公众号,无法统计数据')
|
||||
return false
|
||||
}
|
||||
// 必须选择 7 天内,因为公众号有时间跨度限制为 7
|
||||
if (betweenDay(this.date[0], this.date[1]) >= 7) {
|
||||
this.$message.error('时间间隔 7 天以内,请重新选择')
|
||||
return false
|
||||
}
|
||||
this.xAxisDate = []
|
||||
const days = betweenDay(this.date[0], this.date[1]) // 相差天数
|
||||
for(let i = 0; i <= days; i++){
|
||||
this.xAxisDate.push(formatDate(addTime(this.date[0], 3600 * 1000 * 24 * i), 'yyyy-MM-dd'));
|
||||
}
|
||||
|
||||
// 初始化图表
|
||||
this.initUserSummaryChart();
|
||||
this.initUserCumulateChart();
|
||||
this.initUpstreamMessageChart();
|
||||
this.interfaceSummaryChart();
|
||||
},
|
||||
initUserSummaryChart() {
|
||||
this.userSummaryOption.xAxis.data = [];
|
||||
this.userSummaryOption.series[0].data = [];
|
||||
this.userSummaryOption.series[1].data = [];
|
||||
getUserSummary({
|
||||
accountId: this.accountId,
|
||||
date: [formatDate(this.date[0], 'yyyy-MM-dd HH:mm:ss'), formatDate(this.date[1], 'yyyy-MM-dd HH:mm:ss'),]
|
||||
}).then(response => {
|
||||
this.userSummaryOption.xAxis.data = this.xAxisDate;
|
||||
// 处理数据
|
||||
this.xAxisDate.forEach((date, index) => {
|
||||
response.data.forEach((item) => {
|
||||
// 匹配日期
|
||||
const refDate = formatDate(new Date(item.refDate), 'yyyy-MM-dd');
|
||||
if (refDate.indexOf(date) === -1) {
|
||||
return;
|
||||
}
|
||||
// 设置数据到对应的位置
|
||||
this.userSummaryOption.series[0].data[index] = item.newUser;
|
||||
this.userSummaryOption.series[1].data[index] = item.cancelUser;
|
||||
})
|
||||
})
|
||||
// 绘制图表
|
||||
const userSummaryChart = echarts.init(this.$refs.userSummaryChart);
|
||||
userSummaryChart.setOption(this.userSummaryOption)
|
||||
}).catch(() => {})
|
||||
},
|
||||
initUserCumulateChart() {
|
||||
this.userCumulateOption.xAxis.data = [];
|
||||
this.userCumulateOption.series[0].data = [];
|
||||
// 发起请求
|
||||
getUserCumulate({
|
||||
accountId: this.accountId,
|
||||
date: [formatDate(this.date[0], 'yyyy-MM-dd HH:mm:ss'), formatDate(this.date[1], 'yyyy-MM-dd HH:mm:ss'),]
|
||||
}).then(response => {
|
||||
this.userCumulateOption.xAxis.data = this.xAxisDate;
|
||||
// 处理数据
|
||||
response.data.forEach((item, index) => {
|
||||
this.userCumulateOption.series[0].data[index] = item.cumulateUser;
|
||||
})
|
||||
// 绘制图表
|
||||
const userCumulateChart = echarts.init(this.$refs.userCumulateChart);
|
||||
userCumulateChart.setOption(this.userCumulateOption)
|
||||
}).catch(() => {})
|
||||
},
|
||||
initUpstreamMessageChart() {
|
||||
this.upstreamMessageOption.xAxis.data = [];
|
||||
this.upstreamMessageOption.series[0].data = [];
|
||||
this.upstreamMessageOption.series[1].data = [];
|
||||
// 发起请求
|
||||
getUpstreamMessage({
|
||||
accountId: this.accountId,
|
||||
date: [formatDate(this.date[0], 'yyyy-MM-dd HH:mm:ss'), formatDate(this.date[1], 'yyyy-MM-dd HH:mm:ss'),]
|
||||
}).then(response => {
|
||||
this.upstreamMessageOption.xAxis.data = this.xAxisDate;
|
||||
// 处理数据
|
||||
response.data.forEach((item, index) => {
|
||||
this.upstreamMessageOption.series[0].data[index] = item.messageUser;
|
||||
this.upstreamMessageOption.series[1].data[index] = item.messageCount;
|
||||
})
|
||||
// 绘制图表
|
||||
const upstreamMessageChart = echarts.init(this.$refs.upstreamMessageChart);
|
||||
upstreamMessageChart.setOption(this.upstreamMessageOption);
|
||||
}).catch(() => {})
|
||||
},
|
||||
interfaceSummaryChart() {
|
||||
this.interfaceSummaryOption.xAxis.data = [];
|
||||
this.interfaceSummaryOption.series[0].data = [];
|
||||
this.interfaceSummaryOption.series[1].data = [];
|
||||
this.interfaceSummaryOption.series[2].data = [];
|
||||
this.interfaceSummaryOption.series[3].data = [];
|
||||
// 发起请求
|
||||
getInterfaceSummary({
|
||||
accountId: this.accountId,
|
||||
date: [formatDate(this.date[0], 'yyyy-MM-dd HH:mm:ss'), formatDate(this.date[1], 'yyyy-MM-dd HH:mm:ss'),]
|
||||
}).then(response => {
|
||||
this.interfaceSummaryOption.xAxis.data = this.xAxisDate;
|
||||
// 处理数据
|
||||
response.data.forEach((item, index) => {
|
||||
this.interfaceSummaryOption.series[0].data[index] = item.callbackCount;
|
||||
this.interfaceSummaryOption.series[1].data[index] = item.failCount;
|
||||
this.interfaceSummaryOption.series[2].data[index] = item.maxTimeCost;
|
||||
this.interfaceSummaryOption.series[3].data[index] = item.totalTimeCost;
|
||||
})
|
||||
// 绘制图表
|
||||
const interfaceSummaryChart = echarts.init(this.$refs.interfaceSummaryChart);
|
||||
interfaceSummaryChart.setOption(this.interfaceSummaryOption);
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,243 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号标签" url="https://doc.iocoder.cn/mp/tag/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标签名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入标签名称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['mp:tag:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="el-icon-refresh" size="mini" @click="handleSync"
|
||||
v-hasPermi="['mp:tag:sync']">同步
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id"/>
|
||||
<el-table-column label="标签名称" align="center" prop="name"/>
|
||||
<el-table-column label="粉丝数" align="center" prop="count"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['mp:tag:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['mp:tag:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="标签名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入标签名称"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createTag,
|
||||
updateTag,
|
||||
deleteTag,
|
||||
getTag,
|
||||
getTagPage,
|
||||
syncTag,
|
||||
} from '@/api/mp/tag'
|
||||
import { getSimpleAccounts} from '@/api/mp/account'
|
||||
|
||||
export default {
|
||||
name: 'MpTag',
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 公众号标签列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
accountId: null,
|
||||
name: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
accountId: undefined,
|
||||
name: undefined,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入标签名称', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询标签')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams}
|
||||
// 执行查询
|
||||
getTagPage(params).then(response => {
|
||||
this.list = response.data.list
|
||||
this.total = response.data.total
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
accountId: undefined,
|
||||
name: undefined,
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加公众号标签'
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const id = row.id
|
||||
getTag(id).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改公众号标签'
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
this.form.accountId = this.queryParams.accountId;
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateTag(this.form).then(response => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
return
|
||||
}
|
||||
// 添加的提交
|
||||
createTag(this.form).then(response => {
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id
|
||||
this.$modal.confirm('是否确认删除公众号标签编号为"' + id + '"的数据项?').then(function () {
|
||||
return deleteTag(id)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
/** 同步标签 */
|
||||
handleSync() {
|
||||
const accountId = this.queryParams.accountId
|
||||
this.$modal.confirm('是否确认同步标签?').then(function () {
|
||||
return syncTag(accountId)
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('同步标签成功')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,236 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="公众号粉丝" url="https://doc.iocoder.cn/mp/user/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="公众号" prop="accountId">
|
||||
<el-select v-model="queryParams.accountId" placeholder="请选择公众号">
|
||||
<el-option v-for="item in accounts" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户标识" prop="openid">
|
||||
<el-input v-model="queryParams.openid" placeholder="请输入用户标识" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="昵称" prop="nickname">
|
||||
<el-input v-model="queryParams.nickname" placeholder="请输入昵称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="el-icon-refresh" size="mini" @click="handleSync"
|
||||
v-hasPermi="['mp:user:sync']">同步
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="用户标识" align="center" prop="openid" width="260" />
|
||||
<el-table-column label="昵称" align="center" prop="nickname" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="标签" align="center" prop="tagIds" width="200">
|
||||
<template v-slot="scope">
|
||||
<span v-for="(tagId, index) in scope.row.tagIds" :key="index">
|
||||
<el-tag>{{ tags.find(tag => tag.tagId === tagId)?.name }} </el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订阅状态" align="center" prop="subscribeStatus">
|
||||
<template v-slot="scope">
|
||||
<el-tag v-if="scope.row.subscribeStatus === 0" type="success">已订阅</el-tag>
|
||||
<el-tag v-else type="danger">未订阅</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订阅时间" align="center" prop="subscribeTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.subscribeTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['mp:user:update']">修改</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="昵称" prop="nickname">
|
||||
<el-input v-model="form.nickname" placeholder="请输入昵称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="标签" prop="tagIds">
|
||||
<el-select v-model="form.tagIds" multiple clearable placeholder="请选择标签">
|
||||
<el-option v-for="item in tags" :key="parseInt(item.tagId)" :label="item.name" :value="parseInt(item.tagId)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { updateUser, getUser, getUserPage, syncUser } from "@/api/mp/mpuser";
|
||||
import { getSimpleAccounts } from "@/api/mp/account";
|
||||
import { getSimpleTags } from "@/api/mp/tag";
|
||||
|
||||
export default {
|
||||
name: "MpUser",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 微信公众号粉丝列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
accountId: null,
|
||||
openid: null,
|
||||
nickname: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {},
|
||||
|
||||
// 公众号账号列表
|
||||
accounts: [],
|
||||
// 公众号标签列表
|
||||
tags: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
getSimpleAccounts().then(response => {
|
||||
this.accounts = response.data;
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
// 加载数据
|
||||
this.getList();
|
||||
})
|
||||
|
||||
// 加载标签
|
||||
getSimpleTags().then(response => {
|
||||
this.tags = response.data;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 如果没有选中公众号账号,则进行提示。
|
||||
if (!this.queryParams.accountId) {
|
||||
this.$message.error('未选中公众号,无法查询用户')
|
||||
return false
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
// 执行查询
|
||||
getUserPage(params).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
nickname: undefined,
|
||||
remark: undefined,
|
||||
tagIds: [],
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
// 默认选中第一个
|
||||
if (this.accounts.length > 0) {
|
||||
this.queryParams.accountId = this.accounts[0].id;
|
||||
}
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getUser(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改公众号粉丝";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateUser(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 同步标签 */
|
||||
handleSync() {
|
||||
const accountId = this.queryParams.accountId
|
||||
this.$modal.confirm('是否确认同步粉丝?').then(function () {
|
||||
return syncUser(accountId)
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('开始从微信公众号同步粉丝信息,同步需要一段时间,建议稍后再查询')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -21,7 +21,7 @@
|
||||
</el-col>
|
||||
<el-col :span='4'>
|
||||
<div class="blodTip">产品名称</div>
|
||||
<div class="lightTip">{{ orderMsg.productName }}</div>
|
||||
<div class="lightTip" :title='orderMsg.productName'>{{ orderMsg.productName }}</div>
|
||||
</el-col>
|
||||
<el-col :span='4'>
|
||||
<div class="blodTip">产品规格</div>
|
||||
@@ -282,6 +282,9 @@ export default {
|
||||
font-weight: 400;
|
||||
color: rgba(102, 102, 102, 0.75);
|
||||
margin-bottom: 12px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +1,21 @@
|
||||
<template>
|
||||
<div class="app-container orderMonitoring">
|
||||
<!-- 搜索工作栏 -->
|
||||
<search-bar
|
||||
:formConfigs="formConfig"
|
||||
ref="searchBarForm"
|
||||
@headBtnClick="buttonClick"
|
||||
/>
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<el-tabs v-model="activeName" @tab-click="toggleTab">
|
||||
<el-tab-pane label="数据列表" name="dataList"></el-tab-pane>
|
||||
<el-tab-pane label="环形图" name="barChart"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<!-- 表 -->
|
||||
<div v-if="activeName === 'dataList'">
|
||||
<base-table
|
||||
:page="1"
|
||||
:limit="1000000000000"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
row-key="id"
|
||||
:tree-props="{children: 'orderMonitorVOS', hasChildren: 'hasChildren'}"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
<base-table :page="1" :limit="1000000000000" :table-props="tableProps" :table-data="list" :max-height="tableH"
|
||||
row-key="id" :tree-props="{ children: 'orderMonitorVOS', hasChildren: 'hasChildren' }">
|
||||
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="100" label="操作" :method-list="tableBtn"
|
||||
@clickBtn="handleClick" />
|
||||
</base-table>
|
||||
</div>
|
||||
<!-- 图 -->
|
||||
<monitoring-ring-charts ref='monitoringRingCharts' v-else :chart-list='chartList'/>
|
||||
<monitoring-ring-charts ref='monitoringRingCharts' v-else :chart-list='chartList' />
|
||||
<!-- <pagination
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@@ -168,65 +151,65 @@ export default {
|
||||
},
|
||||
tableProps,
|
||||
list: [],
|
||||
tableH: this.tableHeight(305),
|
||||
tableH: this.tableHeight(260),
|
||||
total: 0,
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:order-completion-monitoring:orderDet')
|
||||
this.$auth.hasPermi('base:order-completion-monitoring:orderDet')
|
||||
? {
|
||||
type: 'orderDetail',
|
||||
btnName: '详情',
|
||||
showTip: '订单/工单详情',
|
||||
showParam: {
|
||||
type: '&',
|
||||
data: [
|
||||
{
|
||||
type: 'more',
|
||||
name: 'orderNum',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
type: 'orderDetail',
|
||||
btnName: '详情',
|
||||
showTip: '订单/工单详情',
|
||||
showParam: {
|
||||
type: '&',
|
||||
data: [
|
||||
{
|
||||
type: 'more',
|
||||
name: 'orderNum',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:order-completion-monitoring:qualityDet')
|
||||
this.$auth.hasPermi('base:order-completion-monitoring:qualityDet')
|
||||
? {
|
||||
type: 'qualityDetail',
|
||||
btnName: '质量',
|
||||
showTip: '质量详情',
|
||||
showParam: {
|
||||
type: '&',
|
||||
data: [
|
||||
{
|
||||
type: 'more',
|
||||
name: 'orderNum',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
type: 'unequal',
|
||||
name: 'woIdString',
|
||||
value: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
type: 'qualityDetail',
|
||||
btnName: '质量',
|
||||
showTip: '质量详情',
|
||||
showParam: {
|
||||
type: '&',
|
||||
data: [
|
||||
{
|
||||
type: 'more',
|
||||
name: 'orderNum',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
type: 'unequal',
|
||||
name: 'woIdString',
|
||||
value: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
// this.$auth.hasPermi('base:order-completion-monitoring:sendOut')
|
||||
// ? {
|
||||
// type: 'sendOutDetail',
|
||||
// btnName: '发货',
|
||||
// showTip: '发货详情',
|
||||
// showParam: {
|
||||
// type: '&',
|
||||
// data: [
|
||||
// {
|
||||
// type: 'more',
|
||||
// name: 'workOrderNum',
|
||||
// value: 1
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// : undefined
|
||||
// this.$auth.hasPermi('base:order-completion-monitoring:sendOut')
|
||||
// ? {
|
||||
// type: 'sendOutDetail',
|
||||
// btnName: '发货',
|
||||
// showTip: '发货详情',
|
||||
// showParam: {
|
||||
// type: '&',
|
||||
// data: [
|
||||
// {
|
||||
// type: 'more',
|
||||
// name: 'workOrderNum',
|
||||
// value: 1
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// : undefined
|
||||
].filter((v) => v),
|
||||
chartList: []
|
||||
}
|
||||
@@ -234,7 +217,7 @@ export default {
|
||||
components: { MonitoringRingCharts },
|
||||
mounted() {
|
||||
window.addEventListener('resize', () => {
|
||||
this.tableH = this.tableHeight(305)
|
||||
this.tableH = this.tableHeight(260)
|
||||
})
|
||||
let start = moment().subtract(30, 'days').format('yyyy-MM-DD')
|
||||
let end = moment().format('yyyy-MM-DD')
|
||||
@@ -245,10 +228,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getPage() {
|
||||
orderGroupMonitor({...this.queryParams}).then(res => {
|
||||
orderGroupMonitor({ ...this.queryParams }).then(res => {
|
||||
let arr = res.data || []
|
||||
if (arr.length > 0) {
|
||||
let color = ['#7164FF','#288AFF','#63BDFF','#8EF0AB','#FFCE6A']
|
||||
let color = ['#7164FF', '#288AFF', '#63BDFF', '#8EF0AB', '#FFCE6A']
|
||||
let arr2 = []
|
||||
arr.map(item => {
|
||||
item.orderType = '集团订单'//前端写死订单类型
|
||||
@@ -261,11 +244,11 @@ export default {
|
||||
obj.num = item.planQuantity || 0
|
||||
let sunNum = 0
|
||||
if (item.orderMonitorVOS && item.orderMonitorVOS.length > 0) {
|
||||
for(let i = 0; i < item.orderMonitorVOS.length; i++) {
|
||||
for (let i = 0; i < item.orderMonitorVOS.length; i++) {
|
||||
item.orderMonitorVOS[i].orderType = '厂务订单'//前端写死订单类型
|
||||
item.orderMonitorVOS[i].id = item.orderMonitorVOS[i].orderid
|
||||
item.orderMonitorVOS[i].orderNum = item.orderMonitorVOS[i].workOrderNum
|
||||
woIdString+=item.orderMonitorVOS[i].woIdString?item.orderMonitorVOS[i].woIdString:''
|
||||
woIdString += item.orderMonitorVOS[i].woIdString ? item.orderMonitorVOS[i].woIdString : ''
|
||||
//==============图数据
|
||||
let subObj = {}
|
||||
subObj.value = item.orderMonitorVOS[i].actualquantity
|
||||
@@ -273,9 +256,9 @@ export default {
|
||||
if (i < 5) {
|
||||
subObj.color = color[i]
|
||||
} else {
|
||||
subObj.color = color[i%5]
|
||||
subObj.color = color[i % 5]
|
||||
}
|
||||
sunNum+=(item.orderMonitorVOS[i].actualquantity || 0)
|
||||
sunNum += (item.orderMonitorVOS[i].actualquantity || 0)
|
||||
arr3.push(subObj)
|
||||
}
|
||||
}
|
||||
@@ -295,7 +278,7 @@ export default {
|
||||
this.$refs.monitoringRingCharts.initChart()
|
||||
})
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
// 显示无数据的图片
|
||||
this.chartList = []
|
||||
}
|
||||
@@ -320,24 +303,24 @@ export default {
|
||||
case 'orderDetail':
|
||||
if (val.data.orderType === '集团订单') {
|
||||
this.$router.push({// 去厂务订单详情
|
||||
path: '/order/base/order-manage/order-detail-data?orderIdString='+ val.data.orderIds.join(',')
|
||||
path: '/order/base/order-manage/order-detail-data?orderIdString=' + val.data.orderIds.join(',')
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
this.$router.push({// 去工单详情
|
||||
path: '/core/core-work-order-detail?woIdString='+val.data.woIdString
|
||||
path: '/core/core-work-order-detail?woIdString=' + val.data.woIdString
|
||||
})
|
||||
}
|
||||
break
|
||||
case 'qualityDetail':
|
||||
this.$router.push({
|
||||
path: '/quality/base/quality-inspection-data/detection-information/statistical-data?woIdString='+val.data.woIdString
|
||||
path: '/quality/base/quality-inspection-data/detection-information/statistical-data?woIdString=' + val.data.woIdString
|
||||
})
|
||||
break
|
||||
default:
|
||||
// this.$router.push({
|
||||
// path: '/delivery/delivery-log?orderId='+encodeURI(val.data.name)
|
||||
// })
|
||||
}
|
||||
// this.$router.push({
|
||||
// path: '/delivery/delivery-log?orderId='+encodeURI(val.data.name)
|
||||
// })
|
||||
}
|
||||
},
|
||||
toggleTab() {
|
||||
if (this.activeName === 'barChart' && this.chartList.length > 0) {
|
||||
@@ -346,7 +329,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
@@ -360,31 +343,39 @@ export default {
|
||||
height: 2px;
|
||||
background-color: #e4e7ed;
|
||||
}
|
||||
|
||||
.el-tabs__nav-wrap::after {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.el-tabs__item {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.el-tabs__item:hover {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
.el-tabs__item.is-active {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
.el-tabs__item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.searchBarBox {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.boxTitle {
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #000000;
|
||||
margin:0 10px 16px 0;
|
||||
margin: 0 10px 16px 0;
|
||||
}
|
||||
|
||||
.blueTitle {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px">
|
||||
<el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px"
|
||||
v-loading="transferParam.loading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
<el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
|
||||
<template slot="append">%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="开放平台APPID" prop="aliPayConfig.appId">
|
||||
<el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="渠道状态" prop="status">
|
||||
<el-radio-group v-model="form.status" size="medium">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="网关地址" prop="aliPayConfig.serverUrl">
|
||||
<el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium">
|
||||
<el-radio v-for="dict in aliPayServerDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType">
|
||||
<el-radio-group v-model="form.aliPayConfig.signType" size="medium">
|
||||
<el-radio v-for="dict in aliPaySignTypeDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode">
|
||||
<el-radio-group v-model="form.aliPayConfig.mode" size="medium">
|
||||
<el-radio v-for="dict in aliPayModeDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="form.aliPayConfig.mode === 1">
|
||||
<el-form-item label-width="180px" label="商户私钥" prop="aliPayConfig.privateKey">
|
||||
<el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey"
|
||||
placeholder="请输入商户私钥" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="支付宝公钥字符串" prop="aliPayConfig.alipayPublicKey">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{minRows: 8, maxRows: 8}"
|
||||
v-model="form.aliPayConfig.alipayPublicKey"
|
||||
placeholder="请输入支付宝公钥字符串" clearable
|
||||
:style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="form.aliPayConfig.mode === 2">
|
||||
<el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent">
|
||||
<el-input v-model="form.aliPayConfig.appCertContent" type="textarea"
|
||||
placeholder="请上传商户公钥应用证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload
|
||||
action=""
|
||||
ref="privateKeyContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:http-request="appCertUpload"
|
||||
:before-upload="fileBeforeUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent">
|
||||
<el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea"
|
||||
placeholder="请上传支付宝公钥证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload
|
||||
ref="privateCertContentFile"
|
||||
action=""
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:before-upload="fileBeforeUpload"
|
||||
:http-request="alipayPublicCertUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent">
|
||||
<el-input
|
||||
v-model="form.aliPayConfig.rootCertContent"
|
||||
type="textarea"
|
||||
placeholder="请上传根证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}"
|
||||
:style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload
|
||||
ref="privateCertContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
action=""
|
||||
:before-upload="fileBeforeUpload"
|
||||
:http-request="rootCertUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label-width="180px" label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
|
||||
|
||||
const defaultForm = {
|
||||
code: '',
|
||||
status: null,
|
||||
remark: '',
|
||||
feeRate: null,
|
||||
appId: '',
|
||||
merchantId: null,
|
||||
aliPayConfig: {
|
||||
appId: '',
|
||||
serverUrl: null,
|
||||
signType: '',
|
||||
mode: null,
|
||||
privateKey: '',
|
||||
alipayPublicKey: '',
|
||||
appCertContent: '',
|
||||
alipayPublicCertContent: '',
|
||||
rootCertContent: ''
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "aliPayChannelForm",
|
||||
components: {},
|
||||
props: {
|
||||
// 传输的参数
|
||||
transferParam: {
|
||||
// 加载动画
|
||||
"loading": false,
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 是否显示
|
||||
"aliPayOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
// 商户对象
|
||||
"payMerchant": {
|
||||
// 编号
|
||||
"id": null,
|
||||
// 名称
|
||||
"name": null
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title:'',
|
||||
form: JSON.parse(JSON.stringify(defaultForm)),
|
||||
rules: {
|
||||
feeRate: [{
|
||||
required: true,
|
||||
message: '请输入渠道费率',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.appId': [{
|
||||
required: true,
|
||||
message: '请输入开放平台上创建的应用的 ID',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
status: [{
|
||||
required: true,
|
||||
message: '渠道状态不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.serverUrl': [{
|
||||
required: true,
|
||||
message: '请传入网关地址',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.signType': [{
|
||||
required: true,
|
||||
message: '请传入签名算法类型',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.mode': [{
|
||||
required: true,
|
||||
message: '公钥类型不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.privateKey': [{
|
||||
required: true,
|
||||
message: '请输入商户私钥',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.alipayPublicKey': [{
|
||||
required: true,
|
||||
message: '请输入支付宝公钥字符串',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.appCertContent': [{
|
||||
required: true,
|
||||
message: '请上传商户公钥应用证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.alipayPublicCertContent': [{
|
||||
required: true,
|
||||
message: '请上传支付宝公钥证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.rootCertContent': [{
|
||||
required: true,
|
||||
message: '请上传指定根证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
},
|
||||
fileAccept: ".crt",
|
||||
// 渠道状态 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
|
||||
// 支付宝加密方式
|
||||
aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE),
|
||||
// 版本状态 数据字典
|
||||
aliPayModeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_MODE),
|
||||
// 支付宝网关地址
|
||||
aliPayServerDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SERVER_TYPE),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
transferParam: {
|
||||
deep: true, // 深度监听
|
||||
handler(newVal) {
|
||||
if (newVal.aliPayOpen) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
this.form.merchantId = newVal.payMerchant.id;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit === true && newVal.loading) {
|
||||
this.title = "编辑支付渠道";
|
||||
this.init();
|
||||
} else {
|
||||
this.title = "创建支付渠道";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
|
||||
.then(response => {
|
||||
this.form.id = response.data.id;
|
||||
this.form.feeRate = response.data.feeRate;
|
||||
this.form.status = response.data.status;
|
||||
this.form.remark = response.data.remark;
|
||||
|
||||
let config = JSON.parse(response.data.config);
|
||||
this.form.aliPayConfig.appId = config.appId;
|
||||
this.form.aliPayConfig.serverUrl = config.serverUrl;
|
||||
this.form.aliPayConfig.signType = config.signType;
|
||||
this.form.aliPayConfig.mode = config.mode;
|
||||
this.form.aliPayConfig.privateKey = config.privateKey;
|
||||
this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey;
|
||||
this.form.aliPayConfig.appCertContent = config.appCertContent;
|
||||
this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent;
|
||||
this.form.aliPayConfig.rootCertContent = config.rootCertContent;
|
||||
this.transferParam.loading = false;
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.transferParam.aliPayOpen = false;
|
||||
this.form = JSON.parse(JSON.stringify(defaultForm));
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$refs['aliPayForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
let data = this.form;
|
||||
data.config = JSON.stringify(this.form.aliPayConfig);
|
||||
if (this.transferParam.edit) {
|
||||
updateChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.close();
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
|
||||
createChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
fileBeforeUpload(file) {
|
||||
let format = '.' + file.name.split(".")[1];
|
||||
if (format !== this.fileAccept) {
|
||||
this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
|
||||
return false;
|
||||
}
|
||||
let isRightSize = file.size / 1024 / 1024 < 2
|
||||
if (!isRightSize) {
|
||||
this.$message.error('文件大小超过 2MB')
|
||||
}
|
||||
return isRightSize
|
||||
},
|
||||
appCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.aliPayConfig.appCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
alipayPublicCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.aliPayConfig.alipayPublicCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
rootCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.aliPayConfig.rootCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,299 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px">
|
||||
<el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px"
|
||||
v-loading="transferParam.loading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
<el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
|
||||
<template slot="append">%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="公众号APPID" prop="weChatConfig.appId">
|
||||
<el-input v-model="form.weChatConfig.appId" placeholder="请输入公众号APPID" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="商户号" prop="weChatConfig.mchId">
|
||||
<el-input v-model="form.weChatConfig.mchId" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="渠道状态" prop="status">
|
||||
<el-radio-group v-model="form.status" size="medium">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
|
||||
<el-radio-group v-model="form.weChatConfig.apiVersion" size="medium">
|
||||
<el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="商户密钥" prop="weChatConfig.mchKey"
|
||||
v-if="form.weChatConfig.apiVersion === 'v2'">
|
||||
<el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户密钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<div v-if="form.weChatConfig.apiVersion === 'v3'">
|
||||
<el-form-item label-width="180px" label="API V3密钥" prop="weChatConfig.apiV3Key">
|
||||
<el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入API V3密钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_key.perm证书" prop="weChatConfig.privateKeyContent">
|
||||
<el-input v-model="form.weChatConfig.privateKeyContent" type="textarea"
|
||||
placeholder="请上传apiclient_key.perm证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateKeyContentFile">
|
||||
<el-upload ref="privateKeyContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:headers="header"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:http-request="privateKeyUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="weChatConfig.privateCertContent">
|
||||
<el-input v-model="form.weChatConfig.privateCertContent" type="textarea"
|
||||
placeholder="请上传apiclient_cert.perm证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateCertContentFile">
|
||||
<el-upload ref="privateCertContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:headers="header"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:http-request="privateCertUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label-width="180px" label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
|
||||
|
||||
const defaultForm = {
|
||||
code: '',
|
||||
status: null,
|
||||
remark: '',
|
||||
feeRate: null,
|
||||
appId: '',
|
||||
merchantId: null,
|
||||
weChatConfig: {
|
||||
appId: '',
|
||||
mchId: '',
|
||||
apiVersion: '',
|
||||
mchKey: '',
|
||||
privateKeyContent: '',
|
||||
privateCertContent: '',
|
||||
apiV3Key:'',
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "wechatChannelForm",
|
||||
components: {},
|
||||
props: {
|
||||
// 传输的参数
|
||||
transferParam: {
|
||||
// 加载动画
|
||||
"loading": false,
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 是否显示
|
||||
"wechatOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
// 商户对象
|
||||
"payMerchant": {
|
||||
// 编号
|
||||
"id": null,
|
||||
// 名称
|
||||
"name": null
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title:'',
|
||||
form: JSON.parse(JSON.stringify(defaultForm)),
|
||||
rules: {
|
||||
feeRate: [{
|
||||
required: true,
|
||||
message: '请输入渠道费率',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.mchId': [{
|
||||
required: true,
|
||||
message: '请传入商户号',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.appId': [{
|
||||
required: true,
|
||||
message: '请输入公众号APPID',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
status: [{
|
||||
required: true,
|
||||
message: '渠道状态不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.apiVersion': [{
|
||||
required: true,
|
||||
message: 'API版本不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.mchKey': [{
|
||||
required: true,
|
||||
message: '请输入商户密钥',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.privateKeyContent': [{
|
||||
required: true,
|
||||
message: '请上传apiclient_key.perm证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.privateCertContent': [{
|
||||
required: true,
|
||||
message: '请上传apiclient_cert.perm证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.apiV3Key': [{
|
||||
required: true,
|
||||
message: '请上传apiV3密钥值',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
},
|
||||
// 文件上传的header
|
||||
header: {
|
||||
"Authorization": null
|
||||
},
|
||||
fileAccept: ".pem",
|
||||
// 渠道状态 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
|
||||
versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
transferParam: {
|
||||
deep: true, // 深度监听
|
||||
handler(newVal) {
|
||||
if (newVal.wechatOpen) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
this.form.merchantId = newVal.payMerchant.id;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit && newVal.loading) {
|
||||
this.title = "编辑支付渠道";
|
||||
this.init();
|
||||
} else {
|
||||
this.title = "创建支付渠道";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
|
||||
.then(response => {
|
||||
this.form.id = response.data.id;
|
||||
this.form.feeRate = response.data.feeRate;
|
||||
this.form.appId = response.data.appId;
|
||||
this.form.status = response.data.status;
|
||||
this.form.remark = response.data.remark;
|
||||
|
||||
let config = JSON.parse(response.data.config);
|
||||
this.form.weChatConfig.appId = config.appId;
|
||||
this.form.weChatConfig.apiVersion = config.apiVersion;
|
||||
this.form.weChatConfig.mchId = config.mchId;
|
||||
this.form.weChatConfig.mchKey = config.mchKey;
|
||||
this.form.weChatConfig.privateKeyContent = config.privateKeyContent;
|
||||
this.form.weChatConfig.privateCertContent = config.privateCertContent;
|
||||
this.form.weChatConfig.apiV3Key = config.apiV3Key;
|
||||
this.transferParam.loading = false;
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.transferParam.wechatOpen = false;
|
||||
this.form = JSON.parse(JSON.stringify(defaultForm));
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$refs['wechatJsApiForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
let data = this.form;
|
||||
data.config = JSON.stringify(this.form.weChatConfig);
|
||||
if (this.transferParam.edit) {
|
||||
updateChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.close();
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
|
||||
createChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
pemFileBeforeUpload(file) {
|
||||
let format = '.' + file.name.split(".")[1];
|
||||
if (format !== this.fileAccept) {
|
||||
this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
|
||||
return false;
|
||||
}
|
||||
let isRightSize = file.size / 1024 / 1024 < 2
|
||||
if (!isRightSize) {
|
||||
this.$message.error('文件大小超过 2MB')
|
||||
}
|
||||
return isRightSize
|
||||
},
|
||||
privateKeyUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.privateKeyContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
privateCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.privateCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,484 +0,0 @@
|
||||
<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="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入应用名" clearable
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户名称" prop="merchantName">
|
||||
<el-input v-model="queryParams.merchantName" placeholder="请输入商户名称" clearable
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable>
|
||||
<el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label"
|
||||
:value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['pay:app:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['pay:app:export']">导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="应用编号" align="center" prop="id"/>
|
||||
<el-table-column label="应用名" align="center" prop="name"/>
|
||||
<el-table-column label="开启状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商户名称" align="center" prop="payMerchant.name"/>
|
||||
<el-table-column label="支付宝配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_BAR.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_BAR.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_APP.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['pay:app:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['pay:app:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="160px">
|
||||
<el-form-item label="应用名" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入应用名"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属商户" prop="merchantId">
|
||||
<el-select
|
||||
v-model="form.merchantId"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请选择所属商户"
|
||||
:remote-method="handleGetMerchantListByName"
|
||||
:loading="loading">
|
||||
<el-option
|
||||
v-for="item in merchantList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="支付结果的回调地址" prop="payNotifyUrl">
|
||||
<el-input v-model="form.payNotifyUrl" placeholder="请输入支付结果的回调地址"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款结果的回调地址" prop="refundNotifyUrl">
|
||||
<el-input v-model="form.refundNotifyUrl" placeholder="请输入退款结果的回调地址"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<wechat-channel-form :transferParam="channelParam"></wechat-channel-form>
|
||||
<ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage, exportAppExcel} from "@/api/pay/app";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {PayType, PayChannelEnum, CommonStatusEnum} from "@/utils/constants";
|
||||
import {getMerchantListByName} from "@/api/pay/merchant";
|
||||
import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
|
||||
import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm";
|
||||
|
||||
export default {
|
||||
name: "PayApp",
|
||||
components: {
|
||||
"wechatChannelForm": wechatChannelForm,
|
||||
"aliPayChannelForm": aliPayChannelForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 支付应用信息列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
remark: null,
|
||||
payNotifyUrl: null,
|
||||
refundNotifyUrl: null,
|
||||
merchantName: null,
|
||||
createTime: []
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{required: true, message: "应用名不能为空", trigger: "blur"}],
|
||||
status: [{required: true, message: "开启状态不能为空", trigger: "blur"}],
|
||||
payNotifyUrl: [{required: true, message: "支付结果的回调地址不能为空", trigger: "blur"}],
|
||||
refundNotifyUrl: [{required: true, message: "退款结果的回调地址不能为空", trigger: "blur"}],
|
||||
merchantId: [{required: true, message: "商户编号不能为空", trigger: "blur"}],
|
||||
},
|
||||
// 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
|
||||
sysCommonStatusEnum: CommonStatusEnum,
|
||||
// 支付渠道枚举
|
||||
payChannelEnum: PayChannelEnum,
|
||||
// 支付类型
|
||||
payType: PayType,
|
||||
// 商户列表
|
||||
merchantList: [],
|
||||
// 是否显示支付窗口
|
||||
payOpen: false,
|
||||
// 微信组件传参参数
|
||||
channelParam: {
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 微信是否显示
|
||||
"wechatOpen": false,
|
||||
// 支付宝是否显示
|
||||
"aliPayOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
// 商户对象
|
||||
"payMerchant": {
|
||||
// 编号
|
||||
"id": null,
|
||||
// 名称
|
||||
"name": null
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.handleGetMerchantListByName(null);
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getAppPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
payNotifyUrl: undefined,
|
||||
refundNotifyUrl: undefined,
|
||||
merchantId: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加支付应用信息";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getApp(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改支付应用信息";
|
||||
});
|
||||
},
|
||||
// 用户状态修改
|
||||
handleStatusChange(row) {
|
||||
let text = row.status === CommonStatusEnum.ENABLE ? "启用" : "停用";
|
||||
this.$modal.confirm('确认要"' + text + '""' + row.name + '"应用吗?').then(function () {
|
||||
return changeAppStatus(row.id, row.status);
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess(text + "成功");
|
||||
}).catch(function () {
|
||||
row.status = row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE
|
||||
: CommonStatusEnum.ENABLE;
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateApp(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createApp(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
this.$modal.confirm('是否确认删除支付应用信息编号为"' + row.id + '"的数据项?').then(function () {
|
||||
return deleteApp(row.id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
// 执行导出
|
||||
this.$modal.confirm('是否确认导出所有支付应用信息数据项?').then(function () {
|
||||
return exportAppExcel(params);
|
||||
}).then(response => {
|
||||
this.$download.excel(response, '支付应用信息.xls');
|
||||
}).catch(() => {});
|
||||
},
|
||||
/**
|
||||
* 根据商户名称模糊匹配商户信息
|
||||
* @param name 商户名称
|
||||
*/
|
||||
handleGetMerchantListByName(name) {
|
||||
getMerchantListByName(name).then(response => {
|
||||
this.merchantList = response.data;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 修改支付渠道信息
|
||||
*/
|
||||
handleUpdateChannel(row, payCode, type) {
|
||||
this.settingChannelParam(row, payCode, type)
|
||||
this.channelParam.edit = true;
|
||||
this.channelParam.loading = true;
|
||||
|
||||
},
|
||||
/**
|
||||
* 新增支付渠道信息
|
||||
*/
|
||||
handleCreateChannel(row, payCode, type) {
|
||||
this.settingChannelParam(row, payCode, type)
|
||||
this.channelParam.edit = false;
|
||||
this.channelParam.loading = false;
|
||||
},
|
||||
/**
|
||||
* 设置支付渠道信息
|
||||
*/
|
||||
settingChannelParam(row, payCode, type) {
|
||||
if (type === PayType.WECHAT) {
|
||||
this.channelParam.wechatOpen = true;
|
||||
this.channelParam.aliPayOpen = false;
|
||||
}
|
||||
if (type === PayType.ALIPAY) {
|
||||
this.channelParam.aliPayOpen = true;
|
||||
this.channelParam.wechatOpen = false;
|
||||
}
|
||||
this.channelParam.edit = false;
|
||||
this.channelParam.loading = false;
|
||||
this.channelParam.appId = row.id;
|
||||
this.channelParam.payCode = payCode;
|
||||
this.channelParam.payMerchant = row.payMerchant;
|
||||
},
|
||||
/**
|
||||
* 根据渠道编码判断渠道列表中是否存在
|
||||
* @param channels 渠道列表
|
||||
* @param channelCode 渠道编码
|
||||
*/
|
||||
judgeChannelExist(channels, channelCode) {
|
||||
return channels.indexOf(channelCode) !== -1;
|
||||
},
|
||||
refreshTable() {
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,214 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">发起订单</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="订单编号" align="center" prop="id" />
|
||||
<el-table-column label="用户编号" align="center" prop="userId" />
|
||||
<el-table-column label="商品名字" align="center" prop="spuName" />
|
||||
<el-table-column label="支付价格" align="center" prop="price">
|
||||
<template v-slot="scope">
|
||||
<span>¥{{ (scope.row.price / 100.0).toFixed(2) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款金额" align="center" prop="refundPrice">
|
||||
<template v-slot="scope">
|
||||
<span>¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付单号" align="center" prop="payOrderId" />
|
||||
<el-table-column label="是否支付" align="center" prop="payed">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.payed" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付时间" align="center" prop="payTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.payTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款时间" align="center" prop="refundTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.refundTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)"
|
||||
v-if="!scope.row.payed">前往支付</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleRefund(scope.row)"
|
||||
v-if="scope.row.payed && !scope.row.payRefundId">发起退款</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" v-dialogDrag append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="商品" prop="spuId">
|
||||
<el-select v-model="form.spuId" placeholder="请输入下单商品" clearable size="small" style="width: 380px" >
|
||||
<el-option v-for="item in spus" :key="item.id" :label="item.name" :value="item.id">
|
||||
<span style="float: left">{{ item.name}}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price / 100.0).toFixed(2) }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createDemoOrder, getDemoOrderPage, refundDemoOrder} from "@/api/pay/demo";
|
||||
import {deleteMerchant} from "@/api/pay/merchant";
|
||||
|
||||
export default {
|
||||
name: "PayDemoOrder",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 示例订单列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
spuId: [{ required: true, message: "商品编号不能为空", trigger: "blur" }],
|
||||
},
|
||||
// 商品数组
|
||||
spus: [{
|
||||
id: 1,
|
||||
name: '华为手机',
|
||||
price: 1,
|
||||
}, {
|
||||
id: 2,
|
||||
name: '小米电视',
|
||||
price: 10,
|
||||
}, {
|
||||
id: 3,
|
||||
name: '苹果手表',
|
||||
price: 100,
|
||||
}, {
|
||||
id: 4,
|
||||
name: '华硕笔记本',
|
||||
price: 1000,
|
||||
}, {
|
||||
id: 5,
|
||||
name: '蔚来汽车',
|
||||
price: 200000,
|
||||
}]
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getDemoOrderPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
spuId: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "发起订单";
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createDemoOrder(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 支付按钮操作 */
|
||||
handlePay(row) {
|
||||
this.$router.push({
|
||||
name: 'PayOrderSubmit',
|
||||
query:{
|
||||
id: row.payOrderId
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 退款按钮操作 */
|
||||
handleRefund(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认退款编号为"' + id + '"的示例订单?').then(function() {
|
||||
return refundDemoOrder(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("发起退款成功!");
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,282 +0,0 @@
|
||||
<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="no">
|
||||
<el-input v-model="queryParams.no" placeholder="请输入商户号" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户全称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入商户全称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户简称" prop="shortName">
|
||||
<el-input v-model="queryParams.shortName" placeholder="请输入商户简称" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable>
|
||||
<el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @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-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['pay:merchant:create']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport"
|
||||
v-hasPermi="['pay:merchant:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="商户编号" align="center" prop="id" />
|
||||
<el-table-column label="商户号" align="center" prop="no" />
|
||||
<el-table-column label="商户全称" align="center" prop="name" />
|
||||
<el-table-column label="商户简称" align="center" prop="shortName" />
|
||||
<el-table-column label="开启状态" align="center" prop="status" >
|
||||
<template v-slot="scope">
|
||||
<el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['pay:merchant:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['pay:merchant:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<!-- <el-form-item label="商户号" prop="no">-->
|
||||
<!-- <el-input v-model="form.no" placeholder="请输入商户号" />-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="商户全称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入商户全称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商户简称" prop="shortName">
|
||||
<el-input v-model="form.shortName" placeholder="请输入商户简称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createMerchant,
|
||||
updateMerchant,
|
||||
changeMerchantStatus,
|
||||
deleteMerchant,
|
||||
getMerchant,
|
||||
getMerchantPage,
|
||||
exportMerchantExcel
|
||||
} from "@/api/pay/merchant";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {CommonStatusEnum} from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: "PayMerchant",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 支付商户信息列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
no: null,
|
||||
name: null,
|
||||
shortName: null,
|
||||
status: null,
|
||||
remark: null,
|
||||
createTime: []
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
no: [{ required: true, message: "商户号不能为空", trigger: "blur" }],
|
||||
name: [{ required: true, message: "商户全称不能为空", trigger: "blur" }],
|
||||
shortName: [{ required: true, message: "商户简称不能为空", trigger: "blur" }],
|
||||
status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
|
||||
},
|
||||
// 商户状态数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS)
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getMerchantPage(this.queryParams).then(response => {
|
||||
console.log(response.data);
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
no: undefined,
|
||||
name: undefined,
|
||||
shortName: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加支付商户信息";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
getMerchant(row.id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改支付商户信息";
|
||||
});
|
||||
},
|
||||
// 用户状态修改
|
||||
handleStatusChange(row) {
|
||||
let text = row.status === CommonStatusEnum.ENABLE ? "启用" : "停用";
|
||||
this.$modal.confirm('确认要"' + text + '""' + row.name + '"商户吗?').then(function() {
|
||||
return changeMerchantStatus(row.id, row.status);
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess(text + "成功");
|
||||
}).catch(function() {
|
||||
row.status = row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE
|
||||
: CommonStatusEnum.ENABLE;
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateMerchant(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createMerchant(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal.confirm('是否确认删除支付商户信息编号为"' + id + '"的数据项?').then(function() {
|
||||
return deleteMerchant(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
// 执行导出
|
||||
this.$modal.confirm('是否确认导出所有支付商户信息数据项?').then(() => {
|
||||
this.exportLoading = true;
|
||||
return exportMerchantExcel(params);
|
||||
}).then(response => {
|
||||
this.$download.excel(response, '支付商户信息.xls');
|
||||
this.exportLoading = false;
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,439 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
||||
<el-form-item label="所属商户" prop="merchantId">
|
||||
<el-select v-model="queryParams.merchantId" clearable @clear="()=>{queryParams.merchantId = null}"
|
||||
filterable remote reserve-keyword placeholder="请选择所属商户" @change="handleGetAppListByMerchantId"
|
||||
:remote-method="handleGetMerchantListByName" :loading="merchantLoading">
|
||||
<el-option v-for="item in merchantList" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用编号" prop="appId">
|
||||
<el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
|
||||
<el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="渠道编码" prop="channelCode">
|
||||
<el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable
|
||||
@clear="()=>{queryParams.channelCode = null}">
|
||||
<el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户订单编号" prop="merchantOrderId">
|
||||
<el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户订单编号" clearable
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="渠道订单号" prop="channelOrderNo">
|
||||
<el-input v-model="queryParams.channelOrderNo" placeholder="请输入渠道订单号" clearable
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small">
|
||||
<el-option v-for="dict in payOrderDictDatum" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款状态" prop="refundStatus">
|
||||
<el-select v-model="queryParams.refundStatus" placeholder="请选择退款状态" clearable>
|
||||
<el-option v-for="dict in payOrderRefundDictDatum" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="回调商户状态" prop="notifyStatus">
|
||||
<el-select v-model="queryParams.notifyStatus" placeholder="请选择订单回调商户状态" clearable>
|
||||
<el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<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="['pay:order:export']">导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="订单编号" align="center" prop="id" width="80"/>
|
||||
<!-- <el-table-column label="商户名称" align="center" prop="merchantName" width="120"/>-->
|
||||
<!-- <el-table-column label="应用名称" align="center" prop="appName" width="120"/>-->
|
||||
<el-table-column label="支付渠道" align="center" width="130">
|
||||
<template v-slot="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p>商户名称: {{ scope.row.merchantName }}</p>
|
||||
<p>应用名称: {{ scope.row.appName }}</p>
|
||||
<p>渠道名称: {{ scope.row.channelCodeName }}</p>
|
||||
<div slot="reference" class="name-wrapper">
|
||||
{{ scope.row.channelCodeName }}
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付订单" align="left" width="280">
|
||||
<template v-slot="scope">
|
||||
<p class="order-font"><el-tag size="mini">商户</el-tag> {{scope.row.merchantOrderId}}</p>
|
||||
<p class="order-font"><el-tag size="mini" type="warning">支付</el-tag> {{scope.row.channelOrderNo}}</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>-->
|
||||
<!-- <el-table-column label="渠道订单号" align="center" prop="channelOrderNo" width="140"/>-->
|
||||
<el-table-column label="商品标题" align="center" prop="subject" width="180" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="支付金额" align="center" prop="amount" width="100">
|
||||
<template v-slot="scope">
|
||||
¥{{ parseFloat(scope.row.amount / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手续金额" align="center" prop="channelFeeAmount" width="100">
|
||||
<template v-slot="scope">
|
||||
¥{{ parseFloat(scope.row.channelFeeAmount / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款金额" align="center" prop="refundAmount" width="100">
|
||||
<template v-slot="scope">
|
||||
¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="退款状态" align="center" prop="refundStatus">-->
|
||||
<!-- <template v-slot="scope">-->
|
||||
<!-- <span>{{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, scope.row.refundStatus) }}</span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column label="回调状态" align="center" prop="notifyStatus" width="100">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="100">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付时间" align="center" prop="successTime" width="100">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.successTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)"
|
||||
v-hasPermi="['pay:order:query']">查看详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog title="订单详情" :visible.sync="open" width="50%">
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="商户名称">{{ orderDetail.merchantName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="商品名称">{{ orderDetail.subject }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="商户订单号">
|
||||
<el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="渠道订单号">
|
||||
<el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="支付订单号">
|
||||
<el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small">
|
||||
{{ orderDetail.payOrderExtension.no }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="金额">
|
||||
<el-tag type="success" size="small">{{ parseFloat(orderDetail.amount / 100, 2) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="手续费">
|
||||
<el-tag type="warning" size="small">{{ parseFloat(orderDetail.channelFeeAmount / 100, 2) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="手续费比例">
|
||||
{{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}%
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="支付状态">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="回调状态">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="orderDetail.notifyStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ parseTime(orderDetail.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="支付时间">{{ parseTime(orderDetail.successTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="失效时间">{{ parseTime(orderDetail.expireTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="通知时间">{{ parseTime(orderDetail.notifyTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="支付渠道">{{ orderDetail.channelCodeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item>
|
||||
<el-descriptions-item label="退款状态">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="orderDetail.refundStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item>
|
||||
<el-descriptions-item label="退款金额">
|
||||
<el-tag type="warning">
|
||||
{{ parseFloat(orderDetail.refundAmount / 100, 2) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
|
||||
<el-descriptions-item label="商品描述">
|
||||
{{ orderDetail.body }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="支付通道异步回调内容">
|
||||
{{ orderDetail.payOrderExtension.channelNotifyData }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getOrderDetail, getOrderPage, exportOrderExcel} from "@/api/pay/order";
|
||||
import {getMerchantListByName} from "@/api/pay/merchant";
|
||||
import {getAppListByMerchantId} from "@/api/pay/app";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import { getNowDateTime} from "@/utils/ruoyi";
|
||||
|
||||
const defaultOrderDetail = {
|
||||
merchantName: '',
|
||||
appName: '',
|
||||
channelCodeName: '',
|
||||
subject: '',
|
||||
merchantOrderId: null,
|
||||
channelOrderNo: '',
|
||||
body: '',
|
||||
amount: null,
|
||||
channelFeeRate: null,
|
||||
channelFeeAmount: null,
|
||||
userIp: '',
|
||||
status: null,
|
||||
notifyUrl: '',
|
||||
notifyStatus: null,
|
||||
refundStatus: null,
|
||||
refundTimes: '',
|
||||
refundAmount: null,
|
||||
createTime: '',
|
||||
successTime: '',
|
||||
notifyTime: '',
|
||||
expireTime: '',
|
||||
payOrderExtension: {
|
||||
channelNotifyData: '',
|
||||
no: ''
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "PayOrder",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 支付订单列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
merchantId: null,
|
||||
appId: null,
|
||||
channelId: null,
|
||||
channelCode: null,
|
||||
merchantOrderId: null,
|
||||
subject: null,
|
||||
body: null,
|
||||
notifyUrl: null,
|
||||
notifyStatus: null,
|
||||
amount: null,
|
||||
channelFeeRate: null,
|
||||
channelFeeAmount: null,
|
||||
status: null,
|
||||
userIp: null,
|
||||
successExtensionId: null,
|
||||
refundStatus: null,
|
||||
refundTimes: null,
|
||||
refundAmount: null,
|
||||
channelUserId: null,
|
||||
channelOrderNo: null,
|
||||
expireTime: [],
|
||||
successTime: [],
|
||||
notifyTime: [],
|
||||
createTime: []
|
||||
},
|
||||
// 商户加载遮罩层
|
||||
merchantLoading: false,
|
||||
// 商户列表集合
|
||||
merchantList: null,
|
||||
// 支付应用列表集合
|
||||
appList: null,
|
||||
// 支付渠道编码字典数据集合
|
||||
payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE),
|
||||
// 订单回调商户状态字典数据集合
|
||||
payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS),
|
||||
// 订单状态字典数据集合
|
||||
payOrderDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_STATUS),
|
||||
// 订单退款状态字典数据集合
|
||||
payOrderRefundDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_REFUND_STATUS),
|
||||
orderDetail: JSON.parse(JSON.stringify(defaultOrderDetail)),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 初始化默认时间
|
||||
this.initTime();
|
||||
this.getList();
|
||||
this.handleGetMerchantListByName(null);
|
||||
},
|
||||
methods: {
|
||||
initTime(){
|
||||
this.queryParams.createTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")];
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 判断选择的日期是否超过了一个月
|
||||
let oneMonthTime = 31 * 24 * 3600 * 1000;
|
||||
if (this.queryParams.createTime == null){
|
||||
this.initTime();
|
||||
} else {
|
||||
let minDateTime = new Date(this.queryParams.createTime[0]).getTime();
|
||||
let maxDateTime = new Date(this.queryParams.createTime[1]).getTime()
|
||||
if (maxDateTime - minDateTime > oneMonthTime) {
|
||||
this.$message.error('时间范围最大为 31 天!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getOrderPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.initTime();
|
||||
this.handleQuery();
|
||||
},
|
||||
/**
|
||||
* 查看订单详情
|
||||
*/
|
||||
handleQueryDetails(row) {
|
||||
this.orderDetail = JSON.parse(JSON.stringify(defaultOrderDetail));
|
||||
getOrderDetail(row.id).then(response => {
|
||||
this.orderDetail = response.data;
|
||||
if (response.data.payOrderExtension === null) {
|
||||
this.orderDetail.payOrderExtension = Object.assign(defaultOrderDetail.payOrderExtension, {});
|
||||
}
|
||||
this.open = true;
|
||||
});
|
||||
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
// 执行导出
|
||||
this.$modal.confirm('是否确认导出所有支付订单数据项?').then(function () {
|
||||
return exportOrderExcel(params);
|
||||
}).then(response => {
|
||||
this.$download.excel(response, '支付订单.xls');
|
||||
}).catch(() => {});
|
||||
},
|
||||
/**
|
||||
* 根据商户名称模糊匹配商户信息
|
||||
* @param name 商户名称
|
||||
*/
|
||||
handleGetMerchantListByName(name) {
|
||||
getMerchantListByName(name).then(response => {
|
||||
this.merchantList = response.data;
|
||||
this.merchantLoading = false;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 根据商户 ID 查询支付应用信息
|
||||
*/
|
||||
handleGetAppListByMerchantId() {
|
||||
this.queryParams.appId = null;
|
||||
getAppListByMerchantId(this.queryParams.merchantId).then(response => {
|
||||
this.appList = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.desc-label {
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.tag-purple {
|
||||
color: #722ed1;
|
||||
background: #f9f0ff;
|
||||
border-color: #d3adf7;
|
||||
}
|
||||
|
||||
.tag-cyan {
|
||||
color: #13c2c2;
|
||||
background: #e6fffb;
|
||||
border-color: #87e8de;
|
||||
}
|
||||
|
||||
.tag-pink {
|
||||
color: #eb2f96;
|
||||
background: #fff0f6;
|
||||
border-color: #ffadd2;
|
||||
}
|
||||
|
||||
.order-font{
|
||||
font-size: 12px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,397 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 支付信息 -->
|
||||
<el-card v-loading="loading">
|
||||
<el-descriptions title="支付信息" :column="3" border>
|
||||
<el-descriptions-item label="支付单号">{{ payOrder.id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="商品标题">{{ payOrder.subject }}</el-descriptions-item>
|
||||
<el-descriptions-item label="商品内容">{{ payOrder.body }}</el-descriptions-item>
|
||||
<el-descriptions-item label="支付金额">¥{{ (payOrder.amount / 100.0).toFixed(2) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ parseTime(payOrder.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="过期时间">{{ parseTime(payOrder.expireTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 支付选择框 -->
|
||||
<el-card style="margin-top: 10px" v-loading="submitLoading" element-loading-text="提交支付中...">
|
||||
<!-- 支付宝 -->
|
||||
<el-descriptions title="选择支付宝支付">
|
||||
</el-descriptions>
|
||||
<div class="pay-channel-container">
|
||||
<div class="box" v-for="channel in aliPayChannels" :key="channel.code" @click="submit(channel.code)">
|
||||
<img :src="icons[channel.code]">
|
||||
<div class="title">{{ channel.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 微信支付 -->
|
||||
<el-descriptions title="选择微信支付" style="margin-top: 20px;" />
|
||||
<div class="pay-channel-container">
|
||||
<div class="box" v-for="channel in wxPayChannels" :key="channel.code">
|
||||
<img :src="icons[channel.code]">
|
||||
<div class="title">{{ channel.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 其它支付 -->
|
||||
<el-descriptions title="选择其它支付" style="margin-top: 20px;" />
|
||||
<div class="pay-channel-container">
|
||||
<div class="box" v-for="channel in otherPayChannels" :key="channel.code">
|
||||
<img :src="icons[channel.code]">
|
||||
<div class="title">{{ channel.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 展示形式:二维码 URL -->
|
||||
<el-dialog :title="qrCode.title" :visible.sync="qrCode.visible" width="350px" append-to-body
|
||||
:close-on-press-escape="false">
|
||||
<qrcode-vue :value="qrCode.url" size="310" level="L" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 展示形式:IFrame -->
|
||||
<el-dialog :title="iframe.title" :visible.sync="iframe.visible" width="800px" height="800px" append-to-body
|
||||
:close-on-press-escape="false">
|
||||
<iframe :src="iframe.url" width="100%" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 展示形式:Form -->
|
||||
<div ref="formRef" v-html="form.value" />
|
||||
|
||||
<!-- 展示形式:BarCode 条形码 -->
|
||||
<el-dialog :title="barCode.title" :visible.sync="barCode.visible" width="500px" append-to-body
|
||||
:close-on-press-escape="false">
|
||||
<el-form ref="form" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="条形码" prop="name">
|
||||
<el-input v-model="barCode.value" placeholder="请输入条形码" required />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div style="text-align: right">
|
||||
或使用
|
||||
<el-link type="danger" target="_blank"
|
||||
href="https://baike.baidu.com/item/条码支付/10711903">(扫码枪/扫码盒)</el-link>
|
||||
扫码
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submit0(barCode.channelCode)"
|
||||
:disabled="barCode.value.length === 0">确认支付</el-button>
|
||||
<el-button @click="barCode.visible = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
|
||||
import { getOrder, submitOrder } from '@/api/pay/order';
|
||||
import {PayChannelEnum, PayDisplayModeEnum, PayOrderStatusEnum} from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: "PayOrderSubmit",
|
||||
components: {
|
||||
QrcodeVue,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: undefined, // 请假编号
|
||||
loading: false, // 支付信息的 loading
|
||||
payOrder: {}, // 支付信息
|
||||
aliPayChannels: [], // 阿里支付的渠道
|
||||
wxPayChannels: [], // 微信支付的渠道
|
||||
otherPayChannels: [], // 其它的支付渠道
|
||||
icons: {
|
||||
alipay_qr: require("@/assets/images/pay/icon/alipay_qr.svg"),
|
||||
alipay_app: require("@/assets/images/pay/icon/alipay_app.svg"),
|
||||
alipay_wap: require("@/assets/images/pay/icon/alipay_wap.svg"),
|
||||
alipay_pc: require("@/assets/images/pay/icon/alipay_pc.svg"),
|
||||
alipay_bar: require("@/assets/images/pay/icon/alipay_bar.svg"),
|
||||
wx_app: require("@/assets/images/pay/icon/wx_app.svg"),
|
||||
wx_lite: require("@/assets/images/pay/icon/wx_lite.svg"),
|
||||
wx_pub: require("@/assets/images/pay/icon/wx_pub.svg"),
|
||||
mock: require("@/assets/images/pay/icon/mock.svg"),
|
||||
},
|
||||
submitLoading: false, // 提交支付的 loading
|
||||
interval: undefined, // 定时任务,轮询是否完成支付
|
||||
qrCode: { // 展示形式:二维码
|
||||
url: '',
|
||||
title: '',
|
||||
visible: false,
|
||||
},
|
||||
iframe: { // 展示形式:iframe
|
||||
url: '',
|
||||
title: '',
|
||||
visible: false
|
||||
},
|
||||
form: { // 展示形式:form
|
||||
html: '',
|
||||
},
|
||||
barCode: { // 展示形式:条形码
|
||||
channelCode: '',
|
||||
value: '',
|
||||
title: '',
|
||||
visible: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.id = this.$route.query.id;
|
||||
this.getDetail();
|
||||
this.initPayChannels();
|
||||
},
|
||||
methods: {
|
||||
/** 初始化支付渠道 */
|
||||
initPayChannels() {
|
||||
// 微信支付
|
||||
for (const dict of getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)) {
|
||||
const payChannel = {
|
||||
name: dict.label,
|
||||
code: dict.value
|
||||
}
|
||||
if (dict.value.indexOf('wx_') === 0) {
|
||||
this.wxPayChannels.push(payChannel);
|
||||
} else if (dict.value.indexOf('alipay_') === 0) {
|
||||
this.aliPayChannels.push(payChannel);
|
||||
} else {
|
||||
this.otherPayChannels.push(payChannel);
|
||||
}
|
||||
}
|
||||
},
|
||||
/** 获得支付信息 */
|
||||
getDetail() {
|
||||
// 1.1 未传递订单编号
|
||||
if (!this.id) {
|
||||
this.$message.error('未传递支付单号,无法查看对应的支付信息');
|
||||
this.goBackToList();
|
||||
return;
|
||||
}
|
||||
getOrder(this.id).then(response => {
|
||||
// 1.2 无法查询到支付信息
|
||||
if (!response.data) {
|
||||
this.$message.error('支付订单不存在,请检查!');
|
||||
this.goBackToList();
|
||||
return;
|
||||
}
|
||||
// 1.3 订单已支付
|
||||
if (response.data.status !== PayOrderStatusEnum.WAITING.status) {
|
||||
this.$message.error('支付订单不处于待支付状态,请检查!');
|
||||
this.goBackToList();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 可以展示
|
||||
this.payOrder = response.data;
|
||||
});
|
||||
},
|
||||
/** 提交支付 */
|
||||
submit(channelCode) {
|
||||
// 条形码支付,需要特殊处理
|
||||
if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
|
||||
this.barCode = {
|
||||
channelCode: channelCode,
|
||||
value: '',
|
||||
title: '“支付宝”条码支付',
|
||||
visible: true
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 默认的提交处理
|
||||
this.submit0(channelCode)
|
||||
},
|
||||
submit0(channelCode) {
|
||||
this.submitLoading = true
|
||||
submitOrder({
|
||||
id: this.id,
|
||||
channelCode: channelCode,
|
||||
...this.buildSubmitParam(channelCode)
|
||||
}).then(response => {
|
||||
const data = response.data
|
||||
if (data.displayMode === PayDisplayModeEnum.IFRAME.mode) {
|
||||
this.displayIFrame(channelCode, data)
|
||||
} else if (data.displayMode === PayDisplayModeEnum.URL.mode) {
|
||||
this.displayUrl(channelCode, data)
|
||||
} else if (data.displayMode === PayDisplayModeEnum.FORM.mode) {
|
||||
this.displayForm(channelCode, data)
|
||||
} else if (data.displayMode === PayDisplayModeEnum.QR_CODE.mode) {
|
||||
this.displayQrCode(channelCode, data)
|
||||
}
|
||||
|
||||
// 打开轮询任务
|
||||
this.createQueryInterval()
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
});
|
||||
},
|
||||
/** 构建提交支付的额外参数 */
|
||||
buildSubmitParam(channelCode) {
|
||||
// ① 支付宝 PC 支付时,有多种展示形态
|
||||
if (channelCode === PayChannelEnum.ALIPAY_PC.code) {
|
||||
// 情况【前置模式】:将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体支持的枚举值有以下几种:
|
||||
// 0:订单码-简约前置模式,对应 iframe 宽度不能小于 600px,高度不能小于 300px
|
||||
// return {
|
||||
// "channelExtras": {
|
||||
// "qr_pay_mode": "0"
|
||||
// }
|
||||
// }
|
||||
// 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于 600px
|
||||
// return {
|
||||
// "channelExtras": {
|
||||
// "qr_pay_mode": "1"
|
||||
// }
|
||||
// }
|
||||
// 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于 75px
|
||||
// return {
|
||||
// "channelExtras": {
|
||||
// "qr_pay_mode": "3"
|
||||
// }
|
||||
// }
|
||||
// 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小
|
||||
// return {
|
||||
// "channelExtras": {
|
||||
// "qr_pay_mode": "4"
|
||||
// }
|
||||
// }
|
||||
// 情况【跳转模式】:跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。支持传入的枚举值有
|
||||
return {
|
||||
"channelExtras": {
|
||||
"qr_pay_mode": "2"
|
||||
}
|
||||
}
|
||||
// 情况【表单模式】:直接提交当前页面到支付宝
|
||||
// return {
|
||||
// displayMode: PayDisplayModeEnum.FORM.mode
|
||||
// }
|
||||
}
|
||||
|
||||
// ② 支付宝 Wap 支付时,引导手机扫码支付
|
||||
if (channelCode === PayChannelEnum.ALIPAY_WAP.code) {
|
||||
return {
|
||||
displayMode: PayDisplayModeEnum.QR_CODE.mode
|
||||
}
|
||||
}
|
||||
|
||||
// ③ 支付宝 BarCode 支付时,需要传递 authCode 条形码
|
||||
if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
|
||||
return {
|
||||
"channelExtras": {
|
||||
"auth_code": this.barCode.value
|
||||
}
|
||||
}
|
||||
}
|
||||
return {}
|
||||
},
|
||||
/** 提交支付后,IFrame 内置 URL 的展示形式 */
|
||||
displayIFrame(channelCode, data) {
|
||||
// TODO 芋艿:目前有点奇怪,支付宝总是会显示“支付环境存在风险”
|
||||
this.iframe = {
|
||||
title: '支付窗口',
|
||||
url: data.displayContent,
|
||||
visible: true
|
||||
}
|
||||
this.submitLoading = false
|
||||
},
|
||||
/** 提交支付后,URL 的展示形式 */
|
||||
displayUrl(channelCode, data) {
|
||||
window.open(data.displayContent)
|
||||
this.submitLoading = false
|
||||
},
|
||||
/** 提交支付后,Form 的展示形式 */
|
||||
displayForm(channelCode, data) {
|
||||
// 渲染支付页面
|
||||
this.form = {
|
||||
value: data.displayContent
|
||||
}
|
||||
// 防抖避免重复支付
|
||||
this.$nextTick(() => {
|
||||
// 提交支付表单
|
||||
this.$refs.formRef.children[0].submit();
|
||||
setTimeout(() => {
|
||||
this.submitLoading = false
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
/** 提交支付后(支付宝扫码支付) */
|
||||
displayQrCode(channelCode, data) {
|
||||
let title = '请使用手机浏览器“扫一扫”';
|
||||
if (channelCode === PayChannelEnum.ALIPAY_WAP.code) {
|
||||
// 考虑到 WAP 测试,所以引导手机浏览器搞
|
||||
} else if (channelCode.indexOf('alipay_') === 0) {
|
||||
title = '请使用支付宝“扫一扫”扫码支付';
|
||||
} else if (channelCode.indexOf('wx_') === 0) {
|
||||
title = '请使用微信“扫一扫”扫码支付';
|
||||
}
|
||||
this.qrCode = {
|
||||
title: title,
|
||||
url: data.displayContent,
|
||||
visible: true
|
||||
}
|
||||
this.submitLoading = false
|
||||
},
|
||||
/** 轮询查询任务 */
|
||||
createQueryInterval() {
|
||||
if (this.interval) {
|
||||
return
|
||||
}
|
||||
this.interval = setInterval(() => {
|
||||
getOrder(this.id).then(response => {
|
||||
// 已支付
|
||||
if (response.data.status === PayOrderStatusEnum.SUCCESS.status) {
|
||||
this.clearQueryInterval();
|
||||
this.$message.success('支付成功!');
|
||||
this.goBackToList();
|
||||
}
|
||||
// 已取消
|
||||
if (response.data.status === PayOrderStatusEnum.CLOSED.status) {
|
||||
this.clearQueryInterval();
|
||||
this.$message.error('支付已关闭!');
|
||||
this.goBackToList();
|
||||
}
|
||||
})
|
||||
}, 1000 * 2)
|
||||
},
|
||||
/** 清空查询任务 */
|
||||
clearQueryInterval() {
|
||||
// 清空各种弹窗
|
||||
this.qrCode = {
|
||||
title: '',
|
||||
url: '',
|
||||
visible: false
|
||||
}
|
||||
// 清空任务
|
||||
clearInterval(this.interval)
|
||||
this.interval = undefined
|
||||
},
|
||||
/** 回到列表 **/
|
||||
goBackToList() {
|
||||
this.$tab.closePage();
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.pay-channel-container {
|
||||
display: flex;
|
||||
margin-top: -10px;
|
||||
.box {
|
||||
width: 130px;
|
||||
border: 1px solid #e6ebf5;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
margin-right: 10px;
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.title {
|
||||
padding-top: 5px
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,486 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
||||
<el-form-item label="所属商户" prop="merchantId">
|
||||
<el-select v-model="queryParams.merchantId" clearable @clear="()=>{queryParams.merchantId = null}"
|
||||
filterable remote reserve-keyword placeholder="请选择所属商户" @change="handleGetAppListByMerchantId"
|
||||
:remote-method="handleGetMerchantListByName" :loading="merchantLoading">
|
||||
<el-option v-for="item in merchantList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用编号" prop="appId">
|
||||
<el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
|
||||
<el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="渠道编码" prop="channelCode">
|
||||
<el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable
|
||||
@clear="()=>{queryParams.channelCode = null}">
|
||||
<el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable>
|
||||
<el-option v-for="dict in payRefundOrderTypeDictDatum" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户退款订单号" prop="merchantRefundNo">
|
||||
<el-input v-model="queryParams.merchantRefundNo" placeholder="请输入商户退款订单号" clearable
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable>
|
||||
<el-option v-for="dict in payRefundOrderDictDatum" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款回调状态" prop="notifyStatus">
|
||||
<el-select v-model="queryParams.notifyStatus" placeholder="请选择通知商户退款结果的回调状态" clearable>
|
||||
<el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)"
|
||||
:label="dict.label" :value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<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="['pay:refund:export']">导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id"/>
|
||||
<!-- <el-table-column label="商户名称" align="center" prop="merchantName" width="120"/>-->
|
||||
<!-- <el-table-column label="应用名称" align="center" prop="appName" width="120"/>-->
|
||||
<el-table-column label="支付渠道" align="center" width="130">
|
||||
<template v-slot="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p>商户名称: {{ scope.row.merchantName }}</p>
|
||||
<p>应用名称: {{ scope.row.appName }}</p>
|
||||
<p>渠道名称: {{ scope.row.channelCodeName }}</p>
|
||||
<div slot="reference" class="name-wrapper">
|
||||
{{ scope.row.channelCodeName }}
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140"/>-->
|
||||
<!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>-->
|
||||
<el-table-column label="商户订单号" align="left" width="230">
|
||||
<template v-slot="scope">
|
||||
<p class="order-font">
|
||||
<el-tag size="mini">退款</el-tag>
|
||||
{{ scope.row.merchantRefundNo }}
|
||||
</p>
|
||||
<p class="order-font">
|
||||
<el-tag type="success">交易</el-tag>
|
||||
{{ scope.row.merchantOrderId }}
|
||||
</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250">
|
||||
<template v-slot="scope">
|
||||
<p class="order-font">
|
||||
<el-tag size="mini">交易</el-tag>
|
||||
{{ scope.row.tradeNo }}
|
||||
</p>
|
||||
<p class="order-font">
|
||||
<el-tag size="mini" type="warning">渠道</el-tag>
|
||||
{{ scope.row.channelOrderNo }}
|
||||
</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付金额(元)" align="center" prop="payAmount" width="100">
|
||||
<template v-slot="scope" class="">
|
||||
¥{{ parseFloat(scope.row.payAmount / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款金额(元)" align="center" prop="refundAmount" width="100">
|
||||
<template v-slot="scope">
|
||||
¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款类型" align="center" prop="type" width="80">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款状态" align="center" prop="status">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="回调状态" align="center" prop="notifyStatus">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款原因" align="center" prop="reason" width="140" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="100">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款成功时间" align="center" prop="successTime" width="100">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.successTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)"
|
||||
v-hasPermi="['pay:order:query']">查看详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog title="退款订单详情" :visible.sync="open" width="700px" append-to-body>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="商户名称">{{ refundDetail.merchantName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="商户退款单号">
|
||||
<el-tag size="mini">{{ refundDetail.merchantRefundNo }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="商户订单号">{{ refundDetail.merchantOrderId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="支付金额">
|
||||
{{ parseFloat(refundDetail.payAmount / 100).toFixed(2) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="退款金额" size="mini">
|
||||
<el-tag class="tag-purple" size="mini">{{ parseFloat(refundDetail.refundAmount / 100).toFixed(2) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="退款类型">
|
||||
<template v-slot="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="refundDetail.type" />
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="退款状态">
|
||||
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="refundDetail.status" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ parseTime(refundDetail.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="退款成功时间">{{ parseTime(refundDetail.successTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="退款失效时间">{{ parseTime(refundDetail.expireTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">{{ parseTime(refundDetail.updateTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="支付渠道">
|
||||
{{ refundDetail.channelCodeName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="支付IP" size="mini">
|
||||
{{refundDetail.userIp}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item>
|
||||
<el-descriptions-item label="回调状态">
|
||||
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="refundDetail.notifyStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="回调时间">{{ parseTime(refundDetail.notifyTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider></el-divider>
|
||||
<el-descriptions :column="2" label-class-name="desc-label">
|
||||
<el-descriptions-item label="渠道订单号">{{ refundDetail.channelOrderNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="渠道退款单号">{{ refundDetail.channelRefundNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="渠道错误码">{{refundDetail.channelErrorCode}}</el-descriptions-item>
|
||||
<el-descriptions-item label="渠道错误码描述">{{refundDetail.channelErrorMsg}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<br>
|
||||
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
|
||||
<el-descriptions-item label="渠道额外参数">{{ refundDetail.channelExtras }}</el-descriptions-item>
|
||||
<el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getRefundPage, exportRefundExcel, getRefund} from "@/api/pay/refund";
|
||||
import {getMerchantListByName} from "@/api/pay/merchant";
|
||||
import {getAppListByMerchantId} from "@/api/pay/app";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {
|
||||
PayOrderRefundStatusEnum,
|
||||
PayRefundStatusEnum
|
||||
} from "@/utils/constants";
|
||||
import {getNowDateTime} from "@/utils/ruoyi";
|
||||
|
||||
const defaultRefundDetail = {
|
||||
id: null,
|
||||
appId: null,
|
||||
appName: '',
|
||||
channelCode: '',
|
||||
channelCodeName: '',
|
||||
channelErrorCode: '',
|
||||
channelErrorMsg: '',
|
||||
channelExtras: '',
|
||||
channelId: null,
|
||||
channelOrderNo: '',
|
||||
channelRefundNo: '',
|
||||
createTime: null,
|
||||
expireTime: null,
|
||||
merchantId: null,
|
||||
merchantName: '',
|
||||
merchantOrderId: '',
|
||||
merchantRefundNo: '',
|
||||
notifyStatus: null,
|
||||
notifyTime: null,
|
||||
notifyUrl: '',
|
||||
orderId: null,
|
||||
payAmount: null,
|
||||
reason: '',
|
||||
refundAmount: null,
|
||||
status: null,
|
||||
subject: '',
|
||||
successTime: null,
|
||||
tradeNo: '',
|
||||
type: null,
|
||||
userIp: ''
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "PayRefund",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 退款订单列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
merchantId: null,
|
||||
appId: null,
|
||||
channelId: null,
|
||||
channelCode: null,
|
||||
orderId: null,
|
||||
tradeNo: null,
|
||||
merchantOrderId: null,
|
||||
merchantRefundNo: null,
|
||||
notifyUrl: null,
|
||||
notifyStatus: null,
|
||||
status: null,
|
||||
type: null,
|
||||
payAmount: null,
|
||||
refundAmount: null,
|
||||
reason: null,
|
||||
userIp: null,
|
||||
channelOrderNo: null,
|
||||
channelRefundNo: null,
|
||||
channelErrorCode: null,
|
||||
channelErrorMsg: null,
|
||||
channelExtras: null,
|
||||
expireTime: [],
|
||||
successTime: [],
|
||||
notifyTime: [],
|
||||
createTime: []
|
||||
},
|
||||
// 商户加载遮罩层
|
||||
merchantLoading: false,
|
||||
// 商户列表集合
|
||||
merchantList: null,
|
||||
// 支付应用列表集合
|
||||
appList: null,
|
||||
// 支付渠道编码字典数据集合
|
||||
payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE),
|
||||
// 订单退款状态字典数据集合
|
||||
payRefundOrderDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_STATUS),
|
||||
// 退款订单类别字典数据集合
|
||||
payRefundOrderTypeDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_TYPE),
|
||||
// 订单回调商户状态字典数据集合
|
||||
payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS),
|
||||
// el-tag订单退款状态type值
|
||||
refundStatusType: '',
|
||||
// 退款订单详情
|
||||
refundDetail: JSON.parse(JSON.stringify(defaultRefundDetail)),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.initTime();
|
||||
this.getList();
|
||||
this.handleGetMerchantListByName(null);
|
||||
},
|
||||
methods: {
|
||||
initTime(){
|
||||
this.queryParams.createTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")];
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
// 判断选择的日期是否超过了一个月
|
||||
let oneMonthTime = 31 * 24 * 3600 * 1000;
|
||||
if (this.queryParams.createTime == null){
|
||||
this.initTime();
|
||||
} else {
|
||||
let minDateTime = new Date(this.queryParams.createTime[0]).getTime();
|
||||
let maxDateTime = new Date(this.queryParams.createTime[1]).getTime()
|
||||
if (maxDateTime - minDateTime > oneMonthTime) {
|
||||
this.$message.error('时间范围最大为 31 天!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getRefundPage(this.queryParams).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
// 执行导出
|
||||
this.$modal.confirm('是否确认导出所有退款订单数据项?').then(function () {
|
||||
return exportRefundExcel(params);
|
||||
}).then(response => {
|
||||
this.$download.excel(response, '退款订单.xls');
|
||||
}).catch(() => {});
|
||||
},
|
||||
/**
|
||||
* 根据商户名称模糊匹配商户信息
|
||||
* @param name 商户名称
|
||||
*/
|
||||
handleGetMerchantListByName(name) {
|
||||
getMerchantListByName(name).then(response => {
|
||||
this.merchantList = response.data;
|
||||
this.merchantLoading = false;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 根据商户 ID 查询支付应用信息
|
||||
*/
|
||||
handleGetAppListByMerchantId() {
|
||||
this.queryParams.appId = null;
|
||||
getAppListByMerchantId(this.queryParams.merchantId).then(response => {
|
||||
this.appList = response.data;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 根据退款类别得到样式名称
|
||||
* @param refundType 退款类别
|
||||
*/
|
||||
findByRefundTypeGetStyle(refundType) {
|
||||
switch (refundType) {
|
||||
case PayOrderRefundStatusEnum.NO.status:
|
||||
return "success";
|
||||
case PayOrderRefundStatusEnum.SOME.status:
|
||||
return "warning";
|
||||
case PayOrderRefundStatusEnum.ALL.status:
|
||||
return "danger";
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 根据退款状态得到样式名称
|
||||
* @param refundStatus 退款状态
|
||||
*/
|
||||
findByRefundStatusGetStyle(refundStatus) {
|
||||
switch (refundStatus) {
|
||||
case PayRefundStatusEnum.CREATE.status:
|
||||
return "info";
|
||||
case PayRefundStatusEnum.SUCCESS.status:
|
||||
return "success";
|
||||
case PayRefundStatusEnum.FAILURE.status:
|
||||
case PayRefundStatusEnum.CLOSE.status:
|
||||
return "danger";
|
||||
case PayRefundStatusEnum.PROCESSING_NOTIFY.status:
|
||||
case PayRefundStatusEnum.PROCESSING_QUERY.status:
|
||||
case PayRefundStatusEnum.UNKNOWN_RETRY.status:
|
||||
case PayRefundStatusEnum.UNKNOWN_QUERY.status:
|
||||
return "warning";
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 查看订单详情
|
||||
*/
|
||||
handleQueryDetails(row) {
|
||||
this.refundDetail = JSON.parse(JSON.stringify(defaultRefundDetail));
|
||||
getRefund(row.id).then(response => {
|
||||
this.refundDetail = response.data;
|
||||
this.open = true;
|
||||
});
|
||||
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.desc-label {
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.tag-purple {
|
||||
color: #722ed1;
|
||||
background: #f9f0ff;
|
||||
border-color: #d3adf7;
|
||||
}
|
||||
|
||||
.tag-cyan {
|
||||
color: #13c2c2;
|
||||
background: #e6fffb;
|
||||
border-color: #87e8de;
|
||||
}
|
||||
|
||||
.tag-pink {
|
||||
color: #eb2f96;
|
||||
background: #fff0f6;
|
||||
border-color: #ffadd2;
|
||||
}
|
||||
|
||||
.order-font {
|
||||
font-size: 12px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2024-01-24 15:15:24
|
||||
* @LastEditTime: 2024-03-26 09:34:12
|
||||
* @LastEditTime: 2024-03-27 09:27:23
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -16,9 +16,9 @@
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-month:query')" type="primary" size="small"
|
||||
<el-button v-if="this.$auth.hasPermi('base:report-auto-original-glass:query')" type="primary" size="small"
|
||||
@click="getDataList">查询</el-button>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-month:export')" type="primary" size="small" plain
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-day:export')" type="primary" size="small" plain
|
||||
@click="handleExport">导出</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -187,8 +187,8 @@ export default {
|
||||
this.endTimeStamp = this.format(val.setHours(7, 0, 0)) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000
|
||||
this.startTimeStamp = this.format(val.setHours(7, 0, 1) - 24 * 60 * 60 * 1000) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000
|
||||
// console.log(this.listQuery.reportTime);
|
||||
this.listQuery.reportTime[1] = this.format(val.setHours(7, 0, 1)) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000
|
||||
this.listQuery.reportTime[0] = this.format(val.setHours(7, 0, 0) + 24 * 60 * 60 * 1000) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000
|
||||
this.listQuery.reportTime[0] = this.format(val.setHours(7, 0, 1)) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000
|
||||
this.listQuery.reportTime[1] = this.format(val.setHours(7, 0, 0) + 24 * 60 * 60 * 1000) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000
|
||||
console.log(this.listQuery.reportTime);
|
||||
} else {
|
||||
this.listQuery.reportTime = []
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<!--
|
||||
* @Author: Do not edit
|
||||
* @Date: 2023-12-13 14:10:04
|
||||
* @LastEditTime: 2024-03-22 09:45:23
|
||||
* @LastEditTime: 2024-03-29 09:43:52
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<el-row style="float: right; margin-bottom: 5px">
|
||||
<el-button v-if="!edit" size="small" @click="edit = true">编辑</el-button>
|
||||
<el-button v-if="!edit" :disabled="noData" size="small" @click="edit = true">编辑</el-button>
|
||||
<el-button v-if="edit" size="small" @click="handleReturn()">返回</el-button>
|
||||
<el-button v-if="edit" size="small" @click="updateData">保存</el-button>
|
||||
</el-row>
|
||||
@@ -20,7 +20,7 @@
|
||||
<el-table-column v-for="(y, index2) in it.children" :key="index2" :prop="y.prop" :label="y.label">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="!edit">{{ scope.row[y.prop] }}</span>
|
||||
<el-input @change="handleChange" :disabled="y.prop == 'dailyOutputTrend' || y.prop === 'originalGlassStatisticsTrend'
|
||||
<el-input type="number" @change="handleChange" :disabled="y.prop == 'dailyOutputTrend' || y.prop === 'originalGlassStatisticsTrend'
|
||||
|| y.prop === 'actualProductTrend' || y.prop === 'originalGlassPassTrend' || y.prop === 'originalGlassPassNow' || y.prop === 'originalGlassPassHis'
|
||||
" v-else v-model="scope.row[y.prop]"></el-input>
|
||||
</template>
|
||||
@@ -158,9 +158,19 @@ const cols = [
|
||||
cols,
|
||||
remark:null,
|
||||
edit: false,
|
||||
noData:false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
watch: {
|
||||
data: {
|
||||
handler(newv, oldv) {
|
||||
if (newv.length != 0) {
|
||||
this.noData = false
|
||||
} else {
|
||||
this.noData = true
|
||||
}
|
||||
}
|
||||
},
|
||||
time: {
|
||||
immediate: true,
|
||||
handler(newv, oldv) {
|
||||
@@ -206,12 +216,10 @@ const cols = [
|
||||
},
|
||||
methods: {
|
||||
handleReturn() {
|
||||
// this.disabled = true
|
||||
this.edit = false
|
||||
console.log(this.$parent.getDataList());
|
||||
},
|
||||
handleChange(e) {
|
||||
// console.log(q)
|
||||
console.log(e);
|
||||
},
|
||||
updateData() {
|
||||
let obj = {}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-month:query')" type="primary" size="small"
|
||||
<el-button v-if="this.$auth.hasPermi('base:report-auto-original-glass:query')" type="primary" size="small"
|
||||
@click="getDataList">查询</el-button>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-month:export')" type="primary" size="small" plain
|
||||
@click="handleExport">导出</el-button>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-weekly:query')" type="primary" size="small"
|
||||
<el-button v-if="this.$auth.hasPermi('base:report-auto-original-glass:query')" type="primary" size="small"
|
||||
@click="getDataList">查询</el-button>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-weekly:export')" type="primary" size="small" plain
|
||||
@click="handleExport">导出</el-button>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-year:query')" type="primary" size="small"
|
||||
<el-button v-if="this.$auth.hasPermi('base:report-auto-original-glass:query')" type="primary" size="small"
|
||||
@click="getDataList">查询</el-button>
|
||||
<el-button v-if="this.$auth.hasPermi('report:glass-year:export')" type="primary" size="small" plain
|
||||
@click="handleExport">导出</el-button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-12-12 13:45:25
|
||||
* @LastEditTime: 2024-03-26 09:41:07
|
||||
* @LastEditTime: 2024-03-29 09:48:24
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -17,7 +17,7 @@
|
||||
@click="handleExport">导出</el-button>
|
||||
</el-form>
|
||||
<el-row style="float: right; margin-bottom: 5px">
|
||||
<el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
|
||||
<el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
|
||||
</el-row>
|
||||
@@ -28,59 +28,61 @@
|
||||
<el-table-column :label="'许昌安彩日成品生产汇总' + '(' + timeTips + ')'" align="center">
|
||||
<el-table-column prop="lineName" label="生产线" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.lineName }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="投入数㎡" align="center">
|
||||
<el-table-column prop="inputNow" label="今日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputHis" label="昨日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' :
|
||||
null}} </span>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ? parseFloat((scope.row.inputTrend *
|
||||
100).toFixed(2)) + '%' : scope.row.inputTrend == 0 ? 0 : null }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成良品产量" align="center">
|
||||
<el-table-column prop="goodProductNow" label="今日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductHis" label="昨日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) +
|
||||
'%' : null }} </span>
|
||||
<span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend == 0 ? 0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="原片漏检率" align="center">
|
||||
<el-table-column prop="missCheckNow" label="今日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
@@ -89,7 +91,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckHis" label="昨日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
@@ -98,19 +100,18 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
|
||||
parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend == 0 ? 0 : null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="综合良品率" align="center">
|
||||
<el-table-column prop="goodProductPassNow" label="今日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
|
||||
100).toFixed(2)) +
|
||||
@@ -120,7 +121,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassHis" label="昨日" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
|
||||
100).toFixed(2)) +
|
||||
@@ -130,12 +131,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
|
||||
0 ? 0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
@@ -284,6 +286,7 @@ export default {
|
||||
urlOptions: {
|
||||
exportURL: exportProductExcel
|
||||
},
|
||||
noData:false,
|
||||
isSave:false,
|
||||
disabled: true,
|
||||
sumArr: [],
|
||||
@@ -456,6 +459,8 @@ export default {
|
||||
handleReturn() {
|
||||
this.disabled = true
|
||||
this.isSave = false
|
||||
this.getDataList()
|
||||
|
||||
},
|
||||
format(shijianchuo) {
|
||||
//shijianchuo是整数,否则要parseInt转换
|
||||
@@ -629,6 +634,11 @@ export default {
|
||||
params: this.listQuery
|
||||
})
|
||||
console.log(res)
|
||||
if (res.data.list.length == 0) {
|
||||
this.noData = true
|
||||
} else {
|
||||
this.noData = false
|
||||
}
|
||||
// let sum = undefined
|
||||
// res.data.list.forEach((ele, index) => {
|
||||
// if (ele.det === false) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-12-12 13:45:25
|
||||
* @LastEditTime: 2024-03-26 09:41:33
|
||||
* @LastEditTime: 2024-03-29 09:48:32
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -17,7 +17,7 @@
|
||||
@click="handleExport">导出</el-button>
|
||||
</el-form>
|
||||
<el-row style="float: right; margin-bottom: 5px">
|
||||
<el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
|
||||
<el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
|
||||
</el-row>
|
||||
@@ -28,114 +28,122 @@
|
||||
<el-table-column :label="'许昌安彩月成品生产汇总' + '(' + timeTips + ')'" align="center">
|
||||
<el-table-column prop="lineId" label="生产线" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.lineName }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="投入数㎡" align="center">
|
||||
<el-table-column prop="inputNow" label="本月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputHis" label="上月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend *
|
||||
100).toFixed(2)) + '%' : undefined }} </span>
|
||||
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ?
|
||||
parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' : scope.row.inputTrend == 0 ? 0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成良品产量" align="center">
|
||||
<el-table-column prop="goodProductNow" label="本月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductHis" label="上月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend *
|
||||
100).toFixed(2)) + '%' : undefined }} </span>
|
||||
<span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend == 0 ? 0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="原片漏检率" align="center">
|
||||
<el-table-column prop="missCheckNow" label="本月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckHis" label="上月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
|
||||
parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend == 0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="综合良品率" align="center">
|
||||
<el-table-column prop="goodProductPassNow" label="本月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassHis" label="上月" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
@@ -288,6 +296,7 @@ export default {
|
||||
isSave:false,
|
||||
disabled: true,
|
||||
sumArr: [],
|
||||
noData:false,
|
||||
timeTips:'',
|
||||
searchBarFormConfig: [
|
||||
// {
|
||||
@@ -666,6 +675,11 @@ export default {
|
||||
params: this.dataForm
|
||||
})
|
||||
console.log(res)
|
||||
if (res.data.list.length == 0) {
|
||||
this.noData = true
|
||||
} else {
|
||||
this.noData = false
|
||||
}
|
||||
// let sum = undefined
|
||||
// res.data.list.forEach((ele, index) => {
|
||||
// if (ele.det === false) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-12-12 13:45:25
|
||||
* @LastEditTime: 2024-03-18 15:26:52
|
||||
* @LastEditTime: 2024-03-29 08:51:46
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -25,7 +25,7 @@
|
||||
background: '#F2F4F9',
|
||||
color: '#606266'
|
||||
}">
|
||||
<el-table-column :label="'许昌安彩周成品发货及库存日报' + '(' + timeTips + ')'" align="center">
|
||||
<el-table-column :label="'许昌安彩成品发货及库存日报' + '(' + timeTips + ')'" align="center">
|
||||
<el-table-column prop="glassType" label="品种" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.glassType" :disabled="disabled"></el-input>
|
||||
@@ -39,7 +39,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格" align="center">
|
||||
<el-table-column label="成品" align="center">
|
||||
<el-table-column width="180" label="成品" align="center">
|
||||
<!-- <el-table-column :show-header="false"> -->
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.productionGlassSize" :disabled="disabled"></el-input>
|
||||
@@ -59,7 +59,7 @@
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table-column>
|
||||
<el-table-column prop="originalGlassSize" label="原片" align="center">
|
||||
<el-table-column width="180" prop="originalGlassSize" label="原片" align="center">
|
||||
<!-- <el-table-column prop="originalGlassSize"> -->
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.originalGlassSize" :disabled="disabled">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-12-12 13:45:25
|
||||
* @LastEditTime: 2024-03-26 09:41:51
|
||||
* @LastEditTime: 2024-03-29 09:48:41
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -20,7 +20,7 @@
|
||||
@click="handleExport">导出</el-button>
|
||||
</el-form>
|
||||
<el-row style="float: right; margin-bottom: 5px">
|
||||
<el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
|
||||
<el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
|
||||
</el-row>
|
||||
@@ -31,114 +31,126 @@
|
||||
<el-table-column :label="'许昌安彩周成品生产汇总' + '(' + timeTips + ')'" align="center">
|
||||
<el-table-column prop="lineId" label="生产线" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.lineName }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="投入数㎡" align="center">
|
||||
<el-table-column prop="inputNow" label="本周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputHis" label="上周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend *
|
||||
100).toFixed(2)) + '%' : undefined }} </span>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ?
|
||||
parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' : scope.row.inputTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成良品产量" align="center">
|
||||
<el-table-column prop="goodProductNow" label="本周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductHis" label="上周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend *
|
||||
100).toFixed(2)) + '%' : undefined }} </span>
|
||||
<span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="原片漏检率" align="center">
|
||||
<el-table-column prop="missCheckNow" label="本周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckHis" label="上周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
|
||||
parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="综合良品率" align="center">
|
||||
<el-table-column prop="goodProductPassNow" label="本周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassHis" label="上周" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
@@ -296,6 +308,7 @@ export default {
|
||||
isSave:false,
|
||||
disabled: true,
|
||||
sumArr: [],
|
||||
noData:false,
|
||||
weekValue1: null,//最多24周
|
||||
weekValue2: null,
|
||||
searchBarFormConfig: [
|
||||
@@ -629,6 +642,11 @@ export default {
|
||||
})
|
||||
// console.log(this.queryParams);
|
||||
console.log(res)
|
||||
if (res.data.list.length == 0) {
|
||||
this.noData = true
|
||||
} else {
|
||||
this.noData = false
|
||||
}
|
||||
// let sum = undefined
|
||||
// res.data.list.forEach((ele, index) => {
|
||||
// if (ele.det === false) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: zhp
|
||||
* @Date: 2023-12-12 13:45:25
|
||||
* @LastEditTime: 2024-03-26 09:42:08
|
||||
* @LastEditTime: 2024-03-29 09:48:49
|
||||
* @LastEditors: zhp
|
||||
* @Description:
|
||||
-->
|
||||
@@ -21,7 +21,7 @@
|
||||
<el-button v-if="isSave" type="success" @click="saveDataList()">保存</el-button> -->
|
||||
</el-form>
|
||||
<el-row style="float: right; margin-bottom: 5px">
|
||||
<el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
|
||||
<el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
|
||||
<el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
|
||||
</el-row>
|
||||
@@ -33,114 +33,126 @@
|
||||
<el-table-column :label="'许昌安彩年成品生产汇总' + '(' + timeTips + ')'" align="center">
|
||||
<el-table-column prop="lineId" label="生产线" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.lineName }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="投入数㎡" align="center">
|
||||
<el-table-column prop="inputNow" label="今年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputHis" label="去年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inputTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend *
|
||||
100).toFixed(2)) + '%' : undefined }} </span>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
|
||||
<span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ?
|
||||
parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' : scope.row.inputTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成良品产量" align="center">
|
||||
<el-table-column prop="goodProductNow" label="今年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductNow }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductHis" label="去年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductHis }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend *
|
||||
100).toFixed(2)) + '%' : undefined }} </span>
|
||||
<span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="原片漏检率" align="center">
|
||||
<el-table-column prop="missCheckNow" label="今年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckHis" label="去年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
|
||||
<span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="missCheckTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
|
||||
parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="综合良品率" align="center">
|
||||
<el-table-column prop="goodProductPassNow" label="今年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassHis" label="去年" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
100).toFixed(2)) +
|
||||
'%' : null }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goodProductPassTrend" label="增减" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
<el-input v-if="!disabled" type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
|
||||
</el-input>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
|
||||
100).toFixed(2)) +
|
||||
'%' : undefined }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
|
||||
parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
|
||||
0 ?
|
||||
0 :
|
||||
null
|
||||
}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
@@ -291,6 +303,7 @@ export default {
|
||||
yearValue2: null,
|
||||
// dynamicProps: [],
|
||||
tableProps,
|
||||
noData:false,
|
||||
reportTime: [],
|
||||
startTimeStamp: '',
|
||||
endTimeStamp: '',
|
||||
@@ -567,7 +580,12 @@ export default {
|
||||
})
|
||||
// console.log(this.queryParams);
|
||||
console.log(res)
|
||||
let sum = undefined
|
||||
if (res.data.list.length == 0) {
|
||||
this.noData = true
|
||||
} else {
|
||||
this.noData = false
|
||||
}
|
||||
// let sum = undefined
|
||||
// res.data.list.forEach((ele, index) => {
|
||||
// if (ele.det === false) {
|
||||
// sum = res.data.list.splice(index, 1)
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
<div class="itemBox">
|
||||
<div class="itemClass" v-for="(item, index) in realtimeList" :key='index'>
|
||||
<div class="itemSub">
|
||||
<p class="itemNum">{{item.checkValue ? (item.checkValue).toFixed(2) : '-'}}</p>
|
||||
<p class="itemNum">{{ item.checkValue ? (item.checkValue).toFixed(2) : '-' }}</p>
|
||||
<p class="itemDescribe" :title="item.name">
|
||||
<img src="./../../../../../assets/images/detectionData.png" alt="">
|
||||
{{item.name}}</p>
|
||||
{{ item.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -24,8 +25,8 @@
|
||||
<span>检测指标趋势图</span>
|
||||
</div>
|
||||
<!-- 搜索工作栏 -->
|
||||
<search-area @submit="getTrend"/>
|
||||
<line-chart :chartData="chartData" v-show='Object.keys(chartData).length !== 0' :timeDim="queryParams.timeDim"/>
|
||||
<search-area @submit="getTrend" />
|
||||
<line-chart :chartData="chartData" v-show='Object.keys(chartData).length !== 0' :timeDim="queryParams.timeDim" />
|
||||
<!-- 没有数据 -->
|
||||
<div class="no-data-bg" v-show='Object.keys(chartData).length === 0'></div>
|
||||
</div>
|
||||
@@ -37,11 +38,11 @@ import LineChart from './../../components/lineChart'
|
||||
import SearchArea from './../../components/searchArea'
|
||||
import moment from 'moment'
|
||||
export default {
|
||||
name: 'Voc',
|
||||
data(){
|
||||
name: 'VocManagement',
|
||||
data() {
|
||||
return {
|
||||
realtimeList:[],
|
||||
queryParams:{
|
||||
realtimeList: [],
|
||||
queryParams: {
|
||||
checkType: 3,
|
||||
timeDim: null,
|
||||
timeRange: []
|
||||
@@ -53,18 +54,18 @@ export default {
|
||||
mounted() {
|
||||
this.getMsg()
|
||||
this.queryParams.timeDim = this.getDictDatas(this.DICT_TYPE.TIME_DIM)[0].value // 默认时
|
||||
this.queryParams.timeRange = [moment().startOf('day')+0, moment().endOf('day')-59*61*1000]
|
||||
this.queryParams.timeRange = [moment().startOf('day') + 0, moment().endOf('day') - 59 * 61 * 1000]
|
||||
this.getTrend()
|
||||
},
|
||||
methods: {
|
||||
getMsg() {
|
||||
environmentalCheckRealtime({checkType: 3}).then(res => {
|
||||
environmentalCheckRealtime({ checkType: 3 }).then(res => {
|
||||
console.log(res)
|
||||
this.realtimeList = res.data || []
|
||||
})
|
||||
},
|
||||
getTrend() {
|
||||
environmentalCheckRealtimeTrend({...this.queryParams}).then(res => {
|
||||
environmentalCheckRealtimeTrend({ ...this.queryParams }).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.chartData = res.data
|
||||
} else {
|
||||
@@ -85,34 +86,41 @@ export default {
|
||||
<style lang='scss' scoped>
|
||||
.voc {
|
||||
background-color: #f2f4f9;
|
||||
|
||||
.box1 {
|
||||
height: 172px;
|
||||
padding: 12px 16px 0;
|
||||
margin-bottom: 8px;
|
||||
background-color: #fff;
|
||||
border-radius: 9px;
|
||||
|
||||
.itemBox {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
overflow: auto;
|
||||
|
||||
.itemClass {
|
||||
width: 198px;
|
||||
height: 88px;
|
||||
// border: 1px solid green;
|
||||
padding: 12px 0px 12px 18px;
|
||||
|
||||
.itemSub {
|
||||
width: 176px;
|
||||
height: 65px;
|
||||
padding-right: 26px;
|
||||
border-right: 1px solid #E8E8E8;
|
||||
P{
|
||||
|
||||
P {
|
||||
margin: 0;
|
||||
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.itemNum {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
@@ -120,33 +128,41 @@ export default {
|
||||
color: #3E6AF7;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.itemDescribe {
|
||||
font-size: 16px;
|
||||
text-align: right;
|
||||
white-space: nowrap; /* 防止换行 */
|
||||
overflow: hidden; /* 隐藏超出部分 */
|
||||
text-overflow: ellipsis; /* 添加省略号 */
|
||||
white-space: nowrap;
|
||||
/* 防止换行 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出部分 */
|
||||
text-overflow: ellipsis;
|
||||
/* 添加省略号 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.itemClass:last-child > .itemSub{
|
||||
|
||||
.itemClass:last-child>.itemSub {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.box2 {
|
||||
background-color: #fff;
|
||||
border-radius: 9px;
|
||||
padding: 16px;
|
||||
height: calc(100vh - 308px);
|
||||
}
|
||||
|
||||
.boxTitle {
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #000000;
|
||||
margin:0 10px 20px 0;
|
||||
margin: 0 10px 20px 0;
|
||||
}
|
||||
|
||||
.blueTitle {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
@emitFun="handleEmitFun">
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
@@ -55,7 +56,6 @@
|
||||
:has-files="true"
|
||||
:disabled="editMode === 'detail'"
|
||||
:rows="computedRows" />
|
||||
<!-- :has-files="['files', 'files2']" -->
|
||||
</base-dialog>
|
||||
|
||||
<!-- 设备 详情 - 编辑 -->
|
||||
@@ -91,13 +91,13 @@
|
||||
pageSize: 10,
|
||||
},
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:core-equipment-attr:update')
|
||||
this.$auth.hasPermi('base:core-equipment-attr:update') // ('se:firefight-attr:update') // TODO 此处需用firefight-attr权限还是core-equipment-attr 权限?
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment-attr:delete')
|
||||
this.$auth.hasPermi('base:core-equipment-attr:delete') // ('se:firefight-attr:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
@@ -116,6 +116,7 @@
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||
import EquipmentDrawer from '../components/firefightingDrawer';
|
||||
import BaseDialogWrapper from '../components/BaseDialogWrapper.vue';
|
||||
|
||||
@@ -134,26 +135,26 @@ export default {
|
||||
components: {
|
||||
Editor,
|
||||
EquipmentDrawer,
|
||||
BaseDialog: BaseDialogWrapper
|
||||
BaseDialog: BaseDialogWrapper,
|
||||
},
|
||||
mixins: [basicPageMixin],
|
||||
mixins: [basicPageMixin, tableHeightMixin],
|
||||
data() {
|
||||
return {
|
||||
searchBarKeys: ['name', 'code'],
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi(`base:core-equipment:update`)
|
||||
this.$auth.hasPermi(`se:firefight:update`)
|
||||
? {
|
||||
type: 'detail',
|
||||
btnName: '详情',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment:update')
|
||||
this.$auth.hasPermi('se:firefight:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment:delete')
|
||||
this.$auth.hasPermi('se:firefight:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
@@ -161,24 +162,28 @@ export default {
|
||||
: undefined,
|
||||
].filter((v) => v),
|
||||
tableProps: [
|
||||
// {
|
||||
// prop: 'createTime',
|
||||
// label: '添加时间',
|
||||
// fixed: true,
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'name', label: '设备名称' },
|
||||
{ width: 256, prop: 'code', label: '设备编码' },
|
||||
{ prop: 'location', label: '位置' },
|
||||
{ prop: 'responsiblePeopleName', label: '负责人' },
|
||||
{ prop: 'name', label: '设备名称', showOverflowtooltip: true },
|
||||
{
|
||||
width: 200,
|
||||
prop: 'code',
|
||||
label: '设备编码',
|
||||
showOverflowtooltip: true,
|
||||
},
|
||||
{ prop: 'location', label: '位置', showOverflowtooltip: true },
|
||||
{
|
||||
prop: 'responsiblePeopleName',
|
||||
label: '负责人',
|
||||
showOverflowtooltip: true,
|
||||
},
|
||||
{
|
||||
prop: 'dueDate',
|
||||
width: 200,
|
||||
label: '有效期至',
|
||||
howOverflowTooltip: true,
|
||||
filter: (val) =>
|
||||
val != null ? moment(val).format('yyyy-MM-DD HH:mm:ss') : '--',
|
||||
},
|
||||
{ prop: 'remark', label: '备注' },
|
||||
{ prop: 'remark', label: '备注', showOverflowtooltip: true },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
@@ -203,18 +208,14 @@ export default {
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: this.$auth.hasPermi('base:core-equipment:export')
|
||||
? 'button'
|
||||
: '',
|
||||
type: this.$auth.hasPermi('se:firefight:export') ? 'button' : '',
|
||||
btnName: '导出',
|
||||
name: 'export',
|
||||
plain: true,
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: this.$auth.hasPermi('base:core-equipment:create')
|
||||
? 'button'
|
||||
: '',
|
||||
type: this.$auth.hasPermi('se:firefight:create') ? 'button' : '',
|
||||
btnName: '新增',
|
||||
name: 'add',
|
||||
plain: true,
|
||||
@@ -293,7 +294,7 @@ export default {
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
code: '',
|
||||
name: '',
|
||||
},
|
||||
@@ -345,9 +346,6 @@ export default {
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
activated() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
@@ -413,34 +411,16 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
this.$refs['drawer'].init();
|
||||
});
|
||||
// this.reset();
|
||||
// this.showUploadComponents = false;
|
||||
// this.editMode = 'edit';
|
||||
// const id = row.id;
|
||||
// getEquipment(id).then((response) => {
|
||||
// this.form = response.data;
|
||||
// this.open = true;
|
||||
// this.title = '修改设备';
|
||||
// });
|
||||
},
|
||||
handleDetail(row, mode='detail') {
|
||||
const {id} = row;
|
||||
handleDetail(row, mode = 'detail') {
|
||||
const { id } = row;
|
||||
this.form.id = id;
|
||||
// 打开抽屉
|
||||
this.editMode = mode;
|
||||
this.editVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs['drawer'].init();
|
||||
})
|
||||
// this.reset();
|
||||
// this.showUploadComponents = false;
|
||||
// const id = row.id;
|
||||
// this.editMode = 'detail';
|
||||
// getEquipment(id).then((response) => {
|
||||
// this.form = response.data;
|
||||
// this.open = true;
|
||||
// this.title = '查看详情';
|
||||
// });
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
@@ -514,33 +494,6 @@ export default {
|
||||
this.$refs['drawer'].init();
|
||||
});
|
||||
},
|
||||
// overwrite basicPageMixin 里的 处理表格按钮 方法
|
||||
// handleTableBtnClick({ data, type }) {
|
||||
// switch (type) {
|
||||
// case 'edit':
|
||||
// this.reset();
|
||||
// this.editMode = 'edit';
|
||||
// this.showUploadComponents = true;
|
||||
// this.form.id = data.id;
|
||||
// this.editVisible = true;
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs['drawer'].init();
|
||||
// });
|
||||
// break;
|
||||
// case 'delete':
|
||||
// this.handleDelete(data);
|
||||
// break;
|
||||
// case 'detail':
|
||||
// const { id } = data;
|
||||
// this.viewDetail(id);
|
||||
// break;
|
||||
// }
|
||||
// },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.SpecialEquipmentForFireFighting {
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
@emitFun="handleEmitFun">
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
@@ -115,6 +116,7 @@
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||
import EquipmentDrawer from '../components/manageDrawer';
|
||||
import BaseDialogWrapper from '../components/BaseDialogWrapper.vue';
|
||||
|
||||
@@ -133,26 +135,26 @@ export default {
|
||||
components: {
|
||||
Editor,
|
||||
EquipmentDrawer,
|
||||
BaseDialog: BaseDialogWrapper
|
||||
BaseDialog: BaseDialogWrapper,
|
||||
},
|
||||
mixins: [basicPageMixin],
|
||||
mixins: [basicPageMixin, tableHeightMixin],
|
||||
data() {
|
||||
return {
|
||||
searchBarKeys: ['name', 'code'],
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi(`base:core-equipment:update`)
|
||||
this.$auth.hasPermi(`se:manage:update`)
|
||||
? {
|
||||
type: 'detail',
|
||||
btnName: '详情',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment:update')
|
||||
this.$auth.hasPermi('se:manage:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment:delete')
|
||||
this.$auth.hasPermi('se:manage:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
@@ -167,11 +169,20 @@ export default {
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'name', label: '设备名称' },
|
||||
{ width: 256, prop: 'code', label: '设备编码' },
|
||||
{ prop: 'location', label: '位置' },
|
||||
{ prop: 'responsiblePeopleName', label: '负责人' },
|
||||
{ prop: 'remark', label: '备注' },
|
||||
{ prop: 'name', label: '设备名称', showOverflowtooltip: true },
|
||||
{
|
||||
width: 256,
|
||||
prop: 'code',
|
||||
label: '设备编码',
|
||||
showOverflowtooltip: true,
|
||||
},
|
||||
{ prop: 'location', label: '位置', showOverflowtooltip: true },
|
||||
{
|
||||
prop: 'responsiblePeopleName',
|
||||
label: '负责人',
|
||||
showOverflowtooltip: true,
|
||||
},
|
||||
{ prop: 'remark', label: '备注', showOverflowtooltip: true },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
@@ -196,7 +207,7 @@ export default {
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: this.$auth.hasPermi('base:core-equipment:export')
|
||||
type: this.$auth.hasPermi('se:manage:export')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '导出',
|
||||
@@ -205,7 +216,7 @@ export default {
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: this.$auth.hasPermi('base:core-equipment:create')
|
||||
type: this.$auth.hasPermi('se:manage:create')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '新增',
|
||||
@@ -277,7 +288,7 @@ export default {
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
code: '',
|
||||
name: '',
|
||||
},
|
||||
@@ -329,9 +340,6 @@ export default {
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
activated() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
@@ -407,15 +415,15 @@ export default {
|
||||
// this.title = '修改设备';
|
||||
// });
|
||||
},
|
||||
handleDetail(row, mode='detail') {
|
||||
const {id} = row;
|
||||
handleDetail(row, mode = 'detail') {
|
||||
const { id } = row;
|
||||
this.form.id = id;
|
||||
// 打开抽屉
|
||||
this.editMode = mode;
|
||||
this.editVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs['drawer'].init();
|
||||
})
|
||||
});
|
||||
// this.reset();
|
||||
// this.showUploadComponents = false;
|
||||
// const id = row.id;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
:max-height="tableH"
|
||||
@emitFun="handleEmitFun">
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
@@ -90,13 +91,13 @@
|
||||
pageSize: 10,
|
||||
},
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:core-equipment-attr:update')
|
||||
this.$auth.hasPermi('se:safety-attr:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment-attr:delete')
|
||||
this.$auth.hasPermi('se:safety-attr:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
@@ -115,6 +116,7 @@
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||
import EquipmentDrawer from '../components/safetyDrawer';
|
||||
import {
|
||||
createEquipment,
|
||||
@@ -128,30 +130,30 @@ import AssetsUpload from '../components/AssetsUpload.vue';
|
||||
import BaseDialogWrapper from '../components/BaseDialogWrapper.vue';
|
||||
|
||||
export default {
|
||||
name: 'SpecialEquipmentForSafety',
|
||||
name: 'specialEquipmentForSafety',
|
||||
components: {
|
||||
Editor,
|
||||
EquipmentDrawer,
|
||||
BaseDialog: BaseDialogWrapper,
|
||||
},
|
||||
mixins: [basicPageMixin],
|
||||
mixins: [basicPageMixin, tableHeightMixin],
|
||||
data() {
|
||||
return {
|
||||
searchBarKeys: ['name', 'code'],
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi(`base:core-equipment:update`)
|
||||
this.$auth.hasPermi(`se:safety:update`)
|
||||
? {
|
||||
type: 'detail',
|
||||
btnName: '详情',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment:update')
|
||||
this.$auth.hasPermi('se:safety:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:core-equipment:delete')
|
||||
this.$auth.hasPermi('se:safety:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
@@ -166,11 +168,20 @@ export default {
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'name', label: '设备名称' },
|
||||
{ width: 256, prop: 'code', label: '设备编码' },
|
||||
{ prop: 'location', label: '位置' },
|
||||
{ prop: 'responsiblePeopleName', label: '负责人' },
|
||||
{ prop: 'remark', label: '备注' },
|
||||
{ prop: 'name', label: '设备名称', showOverflowtooltip: true },
|
||||
{
|
||||
width: 200,
|
||||
prop: 'code',
|
||||
label: '设备编码',
|
||||
showOverflowtooltip: true,
|
||||
},
|
||||
{ prop: 'location', label: '位置', showOverflowtooltip: true },
|
||||
{
|
||||
prop: 'responsiblePeopleName',
|
||||
label: '负责人',
|
||||
showOverflowtooltip: true,
|
||||
},
|
||||
{ prop: 'remark', label: '备注', showOverflowtooltip: true },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
@@ -195,7 +206,7 @@ export default {
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: this.$auth.hasPermi('base:core-equipment:export')
|
||||
type: this.$auth.hasPermi('se:safety:export')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '导出',
|
||||
@@ -204,7 +215,7 @@ export default {
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: this.$auth.hasPermi('base:core-equipment:create')
|
||||
type: this.$auth.hasPermi('se:safety:create')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '新增',
|
||||
@@ -275,7 +286,7 @@ export default {
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
code: '',
|
||||
name: '',
|
||||
},
|
||||
@@ -327,9 +338,6 @@ export default {
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
activated() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user