commit
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form ref="addform" :model="formData" label-width="120px">
|
||||
<el-form ref="addform" :model="formData" :rules="formRules" label-width="120px">
|
||||
|
||||
<el-row gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="活动名称" prop="title">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="formData.title" :disabled="title_disabled" clearable
|
||||
placeholder="请输入活动名称"></el-input>
|
||||
placeholder="请输入标题"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -256,13 +256,18 @@
|
||||
<el-form-item label="发送方式" prop="sendTypes">
|
||||
<el-checkbox-group v-model="formData.sendTypes" size="medium">
|
||||
<el-checkbox :disabled="hold" border label="DingTalk">钉钉</el-checkbox>
|
||||
<!-- <el-checkbox :disabled="hold" border label="1">PC门户</el-checkbox>-->
|
||||
<!-- <el-checkbox :disabled="hold" border label="2">移动校园</el-checkbox>-->
|
||||
<!-- <el-checkbox :disabled="hold" border label="4">短信</el-checkbox>-->
|
||||
<!-- <el-checkbox :disabled="hold" border label="5">微信企业号</el-checkbox>-->
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="发送链接" prop="link">
|
||||
<el-input
|
||||
:disabled="hold"
|
||||
v-model="formData.link"
|
||||
placeholder="请输入发送链接">
|
||||
</el-input>
|
||||
<div style="color:#ee0a24;">不填写发送链接发送文本消息,填写发送链接发送卡片消息</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="发送内容" prop="content">
|
||||
<el-input
|
||||
:disabled="hold"
|
||||
@@ -271,7 +276,6 @@
|
||||
placeholder="请输入内容"
|
||||
type="textarea">
|
||||
</el-input>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
@@ -406,6 +410,12 @@ module.exports = {
|
||||
fileList: [],
|
||||
},
|
||||
importLoading: false,
|
||||
|
||||
formRules: {
|
||||
title: [{required: true, message: '请输入发送标题', trigger: ['blur', 'change']}],
|
||||
sendTypes: [{required: true, message: '请输入发送方式', trigger: ['blur', 'change']}],
|
||||
content: [{required: true, message: '请输入发送内容', trigger: ['blur', 'change']}],
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
/**
|
||||
*Desc:
|
||||
*Create by: jug
|
||||
*Create time:2023/5/8/14:52
|
||||
*/
|
||||
<template>
|
||||
<div>
|
||||
<el-tabs class="customer-tab" type="card" @tab-click="jump" v-model="tabName">
|
||||
<el-tab-pane v-for="(tab, index) in tabs" :name="tab.refName" :key="index" :label="tab.name"
|
||||
v-if="tab.visible"
|
||||
></el-tab-pane>
|
||||
<el-tab-pane v-for="(tab, index) in tabs" :name="tab.refName" :key="index" :label="tab.name"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="scroll-content" @scroll="onScroll" :style="{height:h+'px'}">
|
||||
<div v-for="(item,index) in tabs" :key="item.refName" class="scroll-item" v-if="item.visible">
|
||||
<div v-for="(item,index) in tabs" :key="item.refName" class="scroll-item">
|
||||
<div class="line-name">
|
||||
<h5>{{ item.name }}</h5>
|
||||
</div>
|
||||
@@ -14,10 +17,6 @@
|
||||
<slot :name="item.refName"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scroll-item">
|
||||
<slot name="audit"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -38,92 +37,100 @@ module.exports = {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabName: null
|
||||
tabName: null,
|
||||
tabIndex: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
jump(tab, event) {
|
||||
let target = document.querySelector('.scroll-content')
|
||||
let scrollItems = document.querySelectorAll('.scroll-item')
|
||||
// 判断滚动条是否滚动到底部
|
||||
if (target.scrollHeight <= target.scrollTop + target.clientHeight) {
|
||||
this.tabIndex = tab.index.toString()
|
||||
}
|
||||
let totalY = scrollItems[tab.index].offsetTop - scrollItems[0].offsetTop // 锚点元素距离其offsetParent(这里是body)顶部的距离(待滚动的距离)
|
||||
let distance = document.querySelector('.scroll-content').scrollTop // 滚动条距离滚动区域顶部的距离
|
||||
// let distance = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset // 滚动条距离滚动区域顶部的距离(滚动区域为窗口)
|
||||
// 滚动动画实现, 使用setTimeout的递归实现平滑滚动,将距离细分为50小段,10ms滚动一次
|
||||
// 计算每一小段的距离
|
||||
let step = totalY / 50
|
||||
if (totalY > distance) {
|
||||
smoothDown(document.querySelector('.scroll-content'))
|
||||
} else {
|
||||
let newTotal = distance - totalY
|
||||
step = newTotal / 50
|
||||
smoothUp(document.querySelector('.scroll-content'))
|
||||
}
|
||||
const scrollItems = this.$el.querySelectorAll('.scroll-item')
|
||||
const targetItem = scrollItems[tab.index]
|
||||
|
||||
// 参数element为滚动区域
|
||||
function smoothDown(element) {
|
||||
if (distance < totalY) {
|
||||
distance += step
|
||||
element.scrollTop = distance
|
||||
setTimeout(smoothDown.bind(this, element), 10)
|
||||
} else {
|
||||
element.scrollTop = totalY
|
||||
}
|
||||
}
|
||||
|
||||
// 参数element为滚动区域
|
||||
function smoothUp(element) {
|
||||
if (distance > totalY) {
|
||||
distance -= step
|
||||
element.scrollTop = distance
|
||||
setTimeout(smoothUp.bind(this, element), 10)
|
||||
} else {
|
||||
element.scrollTop = totalY
|
||||
}
|
||||
}
|
||||
|
||||
console.log(this.tabName)
|
||||
// ✅ 用 scrollIntoView 替代手动计算,更可靠
|
||||
targetItem?.scrollIntoView({behavior: 'auto', block: 'start'})
|
||||
this.tabName = tab.name
|
||||
|
||||
},
|
||||
onScroll(e) {
|
||||
if (e.target.scrollTop === 0) {
|
||||
this.tabName = this.tabs[0].refName
|
||||
const container = e.target
|
||||
const {scrollTop, scrollHeight, clientHeight} = container
|
||||
|
||||
// ✅ 1. 优先判断:是否滚动到底部(预留 1px 容差)
|
||||
if (scrollTop + clientHeight >= scrollHeight - 1) {
|
||||
const lastIndex = this.tabs.length - 1
|
||||
if (this.tabIndex !== lastIndex) {
|
||||
this.tabIndex = lastIndex
|
||||
this.tabName = this.tabs[lastIndex]?.refName
|
||||
}
|
||||
return // ✅ 命中底部直接返回,避免后续逻辑干扰
|
||||
}
|
||||
|
||||
// ✅ 2. 顶部边界:scrollTop 为 0 时选中第一个
|
||||
if (scrollTop === 0) {
|
||||
if (this.tabIndex !== 0) {
|
||||
this.tabIndex = 0
|
||||
this.tabName = this.tabs[0]?.refName
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
$('#app > div.guava-main-content > span > div.el-card').each((idx, item) => {
|
||||
if ($(item).is(':visible')) {
|
||||
const scrollItems = $(item).find('.scroll-item')
|
||||
for (let i = scrollItems.length - 1; i >= 0; i--) {
|
||||
let judge = e.target.scrollTop >= scrollItems[i].offsetTop - scrollItems[0].offsetTop - 300
|
||||
if (judge) {
|
||||
this.tabIndex = i.toString()
|
||||
this.tabName = this.tabs[this.tabIndex].refName
|
||||
break
|
||||
}
|
||||
// ✅ 3. 中间区域:正常遍历匹配(移除 jQuery,用 this.$el 局部查询)
|
||||
const scrollItems = this.$el.querySelectorAll('.scroll-item')
|
||||
const threshold = 100 // 可视区域偏移阈值
|
||||
|
||||
for (let i = scrollItems.length - 1; i >= 0; i--) {
|
||||
const itemTop = scrollItems[i].offsetTop - scrollItems[0].offsetTop
|
||||
if (scrollTop + threshold >= itemTop) {
|
||||
if (this.tabIndex !== i) {
|
||||
this.tabIndex = i
|
||||
this.tabName = this.tabs[i]?.refName
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
scrollToTop(){
|
||||
const tryScroll = () => {
|
||||
const scrollEl = this.$el.querySelector('.scroll-content')
|
||||
if (!scrollEl) return
|
||||
|
||||
// 检查内容是否已渲染(scrollHeight > clientHeight 说明有滚动空间)
|
||||
if (scrollEl.scrollHeight <= scrollEl.clientHeight) {
|
||||
// 内容还没加载完,100ms 后重试
|
||||
setTimeout(tryScroll, 100)
|
||||
return
|
||||
}
|
||||
|
||||
// ✅ 内容就绪,执行滚动
|
||||
scrollEl.scrollTo({ top: 0, behavior: 'auto' })
|
||||
this.tabIndex = 0
|
||||
this.tabName = this.tabs[0]?.refName
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
setTimeout(tryScroll, 200)
|
||||
})
|
||||
},
|
||||
|
||||
scrollEnd() {
|
||||
this.$nextTick(() => {
|
||||
// 等待 slot 内容渲染(根据内容复杂度调整 200~400ms)
|
||||
setTimeout(() => {
|
||||
$('#app > div.guava-main-content > span > div.el-card').each((idx, item) => {
|
||||
if ($(item).is(':visible')) {
|
||||
const scrollContent = $(item).find('.scroll-content')[0]
|
||||
scrollContent.scrollTop = scrollContent.scrollHeight
|
||||
}
|
||||
})
|
||||
// document.querySelector('.scroll-content').scrollTop = document.querySelector('.scroll-content').scrollHeight
|
||||
this.tabName = 'audit'
|
||||
const scrollEl = this.$el.querySelector('.scroll-content')
|
||||
if (!scrollEl || !this.tabs?.length) return
|
||||
|
||||
// ✅ 1. 滚动到底部
|
||||
scrollEl.scrollTop = scrollEl.scrollHeight
|
||||
|
||||
// ✅ 2. 选中最后一个 tab
|
||||
const lastIndex = this.tabs.length - 1
|
||||
this.tabIndex = lastIndex
|
||||
this.tabName = this.tabs[lastIndex].refName
|
||||
|
||||
// ✅ 3. 可选:强制触发一次 onScroll 同步状态(节流场景下更可靠)
|
||||
this.onScroll?.({ target: scrollEl })
|
||||
}, 250)
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -175,7 +182,7 @@ module.exports = {
|
||||
.line-name::before {
|
||||
content: "";
|
||||
width: 5px;
|
||||
background: #11879f;
|
||||
background: rgb(24, 103, 176);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
@@ -207,4 +214,4 @@ module.exports = {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,471 +1,523 @@
|
||||
<template>
|
||||
<el-tabs tab-position="top" v-model="activeName" v-loading="loading">
|
||||
<div>
|
||||
<el-tab-plus :tabs="tabs" :h="elTabPlusScrollHeight" ref="etp">
|
||||
<template #basic-info>
|
||||
<el-descriptions border class="custom-desc">
|
||||
<el-descriptions-item label="提案名称" span="3">
|
||||
<div style="font-weight:bold;">
|
||||
{{ viewData.proposalName }}
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提案编号">{{ viewData.proposalCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提案人">{{
|
||||
viewData.createUserName + "-" + viewData.loginname
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提案时间">{{ viewData.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教代会届次"> {{ viewData.meetingName || "暂无" }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提案人工会">{{ viewData.unionName }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="viewData.mannerCode!=='W03'?'代表团名称':'委员会名称'">
|
||||
{{ viewData.mannerCode !== "W03" ? viewData.delegationName : viewData.committeeName }}
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-tab-pane label="提案基础信息" name="1">
|
||||
<el-descriptions border>
|
||||
<el-descriptions-item label="提案名称" span="3">
|
||||
<div style="font-weight:bold;">
|
||||
{{ viewData.proposalName }}
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提案编号">{{ viewData.proposalCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提案人">{{
|
||||
viewData.createUserName + "-" + viewData.loginname
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提案时间">{{ viewData.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教代会届次"> {{ viewData.meetingName || "暂无" }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提案人工会">{{ viewData.unionName }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="viewData.mannerCode!=='W03'?'代表团名称':'委员会名称'">
|
||||
{{ viewData.mannerCode !== "W03" ? viewData.delegationName : viewData.committeeName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提案类型">{{ viewData.typeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="立案结果" span="2"> {{
|
||||
viewData.resultName ? viewData.resultName : "暂无"
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="提案方式" >{{ viewData.mannerName }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="建议落实部门" >{{ viewData.implementUnitName }}</el-descriptions-item>-->
|
||||
|
||||
<el-descriptions-item label="提案类型">{{ viewData.typeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="立案结果" span="2"> {{
|
||||
viewData.resultName ? viewData.resultName : "暂无"
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="提案方式" >{{ viewData.mannerName }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="建议落实部门" >{{ viewData.implementUnitName }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="提案内容" span="3">
|
||||
<div class="text-left" v-html="viewData.brief"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="可行性分析" span="3">
|
||||
<div class="text-left" v-html="viewData.measures"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="附件" span="3">
|
||||
<file-upload v-if="viewData.files&&viewData.files.length"
|
||||
:files="viewData.files" :view="true"></file-upload>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="签  字" span="3">
|
||||
<el-image v-if="viewData.createUserSign" :src="viewData.createUserSign" class="item-sign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-descriptions-item label="提案内容" span="3">
|
||||
<div class="text-left" v-html="viewData.brief"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="可行性分析" span="3">
|
||||
<div class="text-left" v-html="viewData.measures"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="附件" span="3">
|
||||
<file-upload v-if="viewData.files&&viewData.files.length"
|
||||
:files="viewData.files" :view="true"></file-upload>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="签  字" span="3">
|
||||
<el-image v-if="viewData.createUserSign" :src="viewData.createUserSign" class="item-sign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<slot name="seconded"></slot>
|
||||
</template>
|
||||
|
||||
<slot name="seconded"></slot>
|
||||
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="提案并案信息" name="99" v-if="viewData.isConjoin !== 0">
|
||||
<el-table :data="viewData.conJoinList" border>
|
||||
<el-table-column prop="proposalCode" label="提案编号"></el-table-column>
|
||||
<el-table-column prop="username" label="提案人"></el-table-column>
|
||||
<el-table-column prop="proposalName" label="提案名称">
|
||||
<template slot-scope="{row}">
|
||||
<template #conjoin-info>
|
||||
<el-table :data="viewData.conJoinList" border>
|
||||
<el-table-column prop="proposalCode" label="提案编号"></el-table-column>
|
||||
<el-table-column prop="username" label="提案人"></el-table-column>
|
||||
<el-table-column prop="proposalName" label="提案名称">
|
||||
<template slot-scope="{row}">
|
||||
<span @click="openView(row.id)"
|
||||
style="color: #236eb4; cursor: pointer; text-decoration: underline">{{ row.proposalName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="附议信息" name="2" v-if="viewData.seconded">
|
||||
<el-table :data="viewData.seconded" border>
|
||||
<el-table-column prop="username" label="姓名"></el-table-column>
|
||||
<el-table-column prop="unitname" label="单位"></el-table-column>
|
||||
<el-table-column label="邀请时间" prop="inviteTime">
|
||||
<template slot-scope="{row}">
|
||||
{{ row.inviteTime }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="secondedTime" label="附议时间"></el-table-column>
|
||||
<el-table-column prop="isAgree" label="附议结果">
|
||||
<template slot-scope="{row}">
|
||||
<template v-if="row.isAgree==null">
|
||||
<span class="text-muted">未附议</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span v-if="row.isAgree" class="text-success">同意</span>
|
||||
<span v-else class="text-danger">拒绝</span>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column header-align="center" align="center" prop="signData" label="附议人签字">
|
||||
<template slot-scope="{row}">
|
||||
<el-image class="item-sign" :src="row.signData" fit="contain" v-if="row.signData"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="团长审核" name="3" v-if="viewData.delegationAudit&&viewData.delegationAudit.length>0">
|
||||
<el-descriptions border>
|
||||
<template v-for="(o,i) in viewData.delegationAudit">
|
||||
<el-descriptions-item label="审核人">{{ o.username + "-" + o.loginName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">
|
||||
{{ o.flag ? "通过" : "退回" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="3" label="审核意见">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item span="3" label="团长签字">
|
||||
<template>
|
||||
<image class="item-sign" :src="o.auditSign " fit="contain" v-if="o.auditSign"></image>
|
||||
<span v-else>暂无</span>
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="提案工作组意见" name="4"
|
||||
v-if="viewData.membersOpinions && viewData.membersOpinions.length>0">
|
||||
<template v-for="(o,i) in viewData.membersOpinions">
|
||||
<el-descriptions border :column="3">
|
||||
<el-descriptions-item label="审核人">
|
||||
{{ o.username + "-" + o.loginName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="立案意见">
|
||||
{{ o.dictName || "暂无" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见" span="3">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="签字" span="3">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
|
||||
<el-tab-pane v-if="viewData.caseAuditId && viewData.caseAudit" label="提案工作组立案审核" name="5">
|
||||
<template v-for="(o,i) in viewData.caseAudit">
|
||||
<el-descriptions border :column="3">
|
||||
<el-descriptions-item label="审核人">
|
||||
{{ o.username + "-" + o.loginName }}
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="立案结果">
|
||||
{{ viewData.resultName ? viewData.resultName : '暂无' }}
|
||||
<!– {{ viewData.determineTypeCode ? '(' + viewData.laLevelName + ')' : '' }}–>
|
||||
</el-descriptions-item>-->
|
||||
<el-descriptions-item label="审核结果">
|
||||
{{ o.flag ? "通过" : "退回修改" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item v-if="hostUnit!=''" label="承办单位" span="3">
|
||||
{{ hostUnit }}(主办)
|
||||
<template v-if="helpUnit&&helpUnit.length>0">
|
||||
,{{ helpUnit }}(协办)
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
|
||||
<!-- <el-descriptions-item label="承办单位" span="3" v-if="hostUnit!=''">
|
||||
{{ hostUnit }}(主办),
|
||||
{{ helpUnit }}(协办)
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="viewData.resultCode!=='notGive'" label="承办单位" span="3">
|
||||
<template v-for="(item,index) in viewData.undertake">
|
||||
{{ item.unitName }}
|
||||
({{ item.undertakeType === 1 ? '主办' : '协办' }})
|
||||
{{ index + 1 === viewData.undertake.length ? '' : '、' }}
|
||||
</template>
|
||||
</el-descriptions-item>-->
|
||||
<el-descriptions-item label="审核意见" span="3">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="签字" span="3">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<template #seconded-info>
|
||||
<el-table :data="viewData.seconded" border>
|
||||
<el-table-column prop="username" label="姓名"></el-table-column>
|
||||
<el-table-column prop="unitname" label="单位"></el-table-column>
|
||||
<el-table-column label="邀请时间" prop="inviteTime">
|
||||
<template slot-scope="{row}">
|
||||
{{ row.inviteTime }}
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-table-column>
|
||||
<el-table-column prop="secondedTime" label="附议时间"></el-table-column>
|
||||
<el-table-column prop="isAgree" label="附议结果">
|
||||
<template slot-scope="{row}">
|
||||
<template v-if="row.isAgree==null">
|
||||
<span class="text-muted">未附议</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span v-if="row.isAgree" class="text-success">同意</span>
|
||||
<span v-else class="text-danger">拒绝</span>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<el-tab-pane label="承办单位意见" name="6"
|
||||
v-if="viewData.underTakeFirstOpinion&&viewData.underTakeFirstOpinion.length>0">
|
||||
<el-descriptions border>
|
||||
<template v-for="(o,i) in viewData.underTakeFirstOpinion">
|
||||
<el-descriptions-item label="承办单位">{{ o.underTakeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="时间">{{ o.opionTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">
|
||||
<el-tag v-if="o.canTake">同意承办</el-tag>
|
||||
<el-tag v-else type="danger">无法承办</el-tag>
|
||||
|
||||
<template #delegation-audit-info>
|
||||
<el-descriptions border>
|
||||
<template v-for="(o,i) in viewData.delegationAudit">
|
||||
<el-descriptions-item label="审核人">{{ o.username + "-" + o.loginName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">
|
||||
{{ o.flag ? "通过" : "退回" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="3" label="审核意见">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item span="3" label="团长签字">
|
||||
<template>
|
||||
<image class="item-sign" :src="o.auditSign " fit="contain" v-if="o.auditSign"></image>
|
||||
<span v-else>暂无</span>
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<template #members-opinions-info>
|
||||
<template v-for="(o,i) in viewData.membersOpinions">
|
||||
<el-descriptions border :column="3">
|
||||
<el-descriptions-item label="审核人">
|
||||
{{ o.username + "-" + o.loginName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="立案意见">
|
||||
{{ o.dictName || "暂无" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见" span="3">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="签字" span="3">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #case-audit-info>
|
||||
<template v-for="(o,i) in viewData.caseAudit">
|
||||
<el-descriptions border :column="3">
|
||||
<el-descriptions-item label="审核人">
|
||||
{{ o.username + "-" + o.loginName }}
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="立案结果">
|
||||
{{ viewData.resultName ? viewData.resultName : '暂无' }}
|
||||
<!– {{ viewData.determineTypeCode ? '(' + viewData.laLevelName + ')' : '' }}–>
|
||||
</el-descriptions-item>-->
|
||||
<el-descriptions-item label="审核结果">
|
||||
{{ o.flag ? "通过" : "退回修改" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item v-if="hostUnit!=''" label="承办单位" span="3">
|
||||
{{ hostUnit }}(主办)
|
||||
<template v-if="helpUnit&&helpUnit.length>0">
|
||||
,{{ helpUnit }}(协办)
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
|
||||
<!-- <el-descriptions-item label="承办单位" span="3" v-if="hostUnit!=''">
|
||||
{{ hostUnit }}(主办),
|
||||
{{ helpUnit }}(协办)
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="3" label="意见">{{ o.opinion }}</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="提案工作组确认承办单位" name="10" v-if="viewData.caseUnitAuditId && viewData.caseUnitAudit">
|
||||
<el-descriptions border>
|
||||
<el-descriptions-item label="审核人">
|
||||
{{ viewData.caseUnitAudit.username + "-" + viewData.caseUnitAudit.loginName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">{{ viewData.resultName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ viewData.caseUnitAudit.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="承办单位" span="3" v-if="viewData.resultCode!=='notGive'">
|
||||
<template v-for="(item,index) in viewData.undertake">
|
||||
<el-descriptions-item v-if="viewData.resultCode!=='notGive'" label="承办单位" span="3">
|
||||
<template v-for="(item,index) in viewData.undertake">
|
||||
{{ item.unitName }}
|
||||
({{ item.undertakeType === 1 ? "主办" : "协办" }})
|
||||
{{ index + 1 === viewData.undertake.length ? "" : "、" }}
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见" span="3">{{ viewData.caseUnitAudit.opinion }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="签字" span="3">
|
||||
<el-image v-if="viewData.caseUnitAudit.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="viewData.caseUnitAudit.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
({{ item.undertakeType === 1 ? '主办' : '协办' }})
|
||||
{{ index + 1 === viewData.undertake.length ? '' : '、' }}
|
||||
</template>
|
||||
</el-descriptions-item>-->
|
||||
<el-descriptions-item label="审核意见" span="3">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="签字" span="3">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<el-tab-pane label="分管校领导批示" name="8" v-if="viewData.branchLeaderOpinion && viewData.branchLeaderOpinion.length>0">
|
||||
{{ viewData.branchLeaderOpinion }}
|
||||
<template v-if="viewData.branchLeaderOpinion && viewData.branchLeaderOpinion.length>0">
|
||||
<el-descriptions :column="2" border class="wrap-table">
|
||||
<template v-for="(o,i) in viewData.branchLeaderOpinion">
|
||||
<el-descriptions-item label="审批人">{{ o.username }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审批时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="审批意见">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="分管校领导签字">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
<template #undertake-first-audit-info>
|
||||
<el-descriptions border>
|
||||
<template v-for="(o,i) in viewData.underTakeFirstOpinion">
|
||||
<el-descriptions-item label="承办单位">{{ o.underTakeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="时间">{{ o.opionTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">
|
||||
<el-tag v-if="o.canTake">同意承办</el-tag>
|
||||
<el-tag v-else type="danger">无法承办</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="3" label="意见">{{ o.opinion }}</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<template #case-unit-audit-info>
|
||||
<el-descriptions border>
|
||||
<el-descriptions-item label="审核人">
|
||||
{{ viewData.caseUnitAudit.username + "-" + viewData.caseUnitAudit.loginName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">{{ viewData.resultName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ viewData.caseUnitAudit.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="承办单位" span="3" v-if="viewData.resultCode!=='notGive'">
|
||||
<template v-for="(item,index) in viewData.undertake">
|
||||
{{ item.unitName }}
|
||||
({{ item.undertakeType === 1 ? "主办" : "协办" }})
|
||||
{{ index + 1 === viewData.undertake.length ? "" : "、" }}
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见" span="3">{{ viewData.caseUnitAudit.opinion }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="签字" span="3">
|
||||
<el-image v-if="viewData.caseUnitAudit.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="viewData.caseUnitAudit.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<el-tab-pane label="承办单位办理" name="11"
|
||||
v-if="viewData.replyInfo && viewData.replyInfo.length>0 && viewData.replyInfo.some(v=>v.isReply || v.leaderCheckResult!=null)">
|
||||
<template v-for="(o,i) in viewData.replyInfo.filter(v=>v.isReply || v.leaderCheckResult!=null)">
|
||||
<el-descriptions border column="3" style="margin-top: 10px">
|
||||
<el-descriptions-item label="承办单位">{{
|
||||
o.unitName
|
||||
}}({{ o.undertakeType === 1 ? "主办" : "协办" }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理人">{{ o.dfrUserName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ o.replyTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理次数">{{ o.replyNumber }}</el-descriptions-item>
|
||||
<el-descriptions-item label="落实情况" span="2">{{ o.implementState }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理内容" span="3">
|
||||
<div class="text-left" v-html="o.replyContent"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="承办单位签字" span="3">
|
||||
<el-image v-if="o.replySignData"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.replySignData"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="附件" span="3">
|
||||
<file-upload v-if="JSON.parse(o.replyFiles)&&JSON.parse(o.replyFiles).length"
|
||||
:files="JSON.parse(o.replyFiles)" :view="true"></file-upload>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<template #undertake-reply-audit-info>
|
||||
<template v-for="(o,i) in viewData.replyInfo.filter(v=>v.isReply || v.leaderCheckResult!=null)">
|
||||
<el-descriptions border column="3" style="margin-top: 10px">
|
||||
<el-descriptions-item label="承办单位">{{
|
||||
o.unitName
|
||||
}}({{ o.undertakeType === 1 ? "主办" : "协办" }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理人">{{ o.dfrUserName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ o.replyTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理次数">{{ o.replyNumber }}</el-descriptions-item>
|
||||
<el-descriptions-item label="落实情况" span="2">{{ o.implementState }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理内容" span="3">
|
||||
<div class="text-left" v-html="o.replyContent"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="承办单位签字" span="3">
|
||||
<el-image v-if="o.replySignData"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.replySignData"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="附件" span="3">
|
||||
<file-upload v-if="JSON.parse(o.replyFiles)&&JSON.parse(o.replyFiles).length"
|
||||
:files="JSON.parse(o.replyFiles)" :view="true"></file-upload>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #branch-leader-reply-opinion-audit-info>
|
||||
<template
|
||||
v-if="viewData.branchLeaderSuffixAuditOpinion && viewData.branchLeaderSuffixAuditOpinion.length>0">
|
||||
<el-descriptions :column="2" border class="wrap-table">
|
||||
<template v-for="(o,i) in viewData.branchLeaderSuffixAuditOpinion">
|
||||
<el-descriptions-item label="审批人">{{ o.username }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审批时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="审批意见">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="分管校领导签字">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<el-tab-pane label="分管校领导审批" name="14"
|
||||
v-if="viewData.branchLeaderSuffixAuditOpinion && viewData.branchLeaderSuffixAuditOpinion.length>0">
|
||||
<template
|
||||
v-if="viewData.branchLeaderSuffixAuditOpinion && viewData.branchLeaderSuffixAuditOpinion.length>0">
|
||||
<el-descriptions :column="2" border class="wrap-table">
|
||||
<template v-for="(o,i) in viewData.branchLeaderSuffixAuditOpinion">
|
||||
<el-descriptions-item label="审批人">{{ o.username }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审批时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="审批意见">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="分管校领导签字">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
<template #feedback-audit-info>
|
||||
<el-descriptions border column="4">
|
||||
<template v-for="(o,i) in viewData.feedback">
|
||||
<el-descriptions-item label="反馈人">{{ o.username }}({{ o.loginname }})</el-descriptions-item>
|
||||
<el-descriptions-item label="反馈时间">{{ o.feedbackTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="反馈次数">{{ o.feedbackNumber }}</el-descriptions-item>
|
||||
<el-descriptions-item label="对办理结果评价">{{ o.feedbackResult }}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="对承办单位办理态度评价">{{ o.feedbackCodeByUnderTake }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="反馈意见" span="5">
|
||||
<div class="text-left" v-html="o.feedbackOpinion"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="反馈人签字" span="4">
|
||||
<el-image v-if="o.scoreSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.scoreSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<template #audit>
|
||||
<slot name="handle"></slot>
|
||||
</template>
|
||||
</el-tab-plus>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- <el-tabs tab-position="top" v-model="activeName" v-loading="loading">
|
||||
<el-tab-pane label="分管校领导批示" name="8"
|
||||
v-if="viewData.branchLeaderOpinion && viewData.branchLeaderOpinion.length>0">
|
||||
{{ viewData.branchLeaderOpinion }}
|
||||
<template v-if="viewData.branchLeaderOpinion && viewData.branchLeaderOpinion.length>0">
|
||||
<el-descriptions :column="2" border class="wrap-table">
|
||||
<template v-for="(o,i) in viewData.branchLeaderOpinion">
|
||||
<el-descriptions-item label="审批人">{{ o.username }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审批时间">{{ o.auditTime }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="审批意见">{{ o.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item span="4" label="分管校领导签字">
|
||||
<el-image v-if="o.auditSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.auditSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="反馈评分信息" name="13" v-if="viewData.feedback&&viewData.feedback.length>0">
|
||||
<el-descriptions border column="4">
|
||||
<template v-for="(o,i) in viewData.feedback">
|
||||
<el-descriptions-item label="反馈人">{{ o.username }}({{ o.loginname }})</el-descriptions-item>
|
||||
<el-descriptions-item label="反馈时间">{{ o.feedbackTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="反馈次数">{{ o.feedbackNumber }}</el-descriptions-item>
|
||||
<el-descriptions-item label="对办理结果评价">{{ o.feedbackResult }}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="对承办单位办理态度评价">{{ o.feedbackCodeByUnderTake }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="反馈意见" span="5">
|
||||
<div class="text-left" v-html="o.feedbackOpinion"></div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="反馈人签字" span="4">
|
||||
<el-image v-if="o.scoreSign"
|
||||
style="width: 300px; height: 100px"
|
||||
:src="o.scoreSign"
|
||||
fit="contain"></el-image>
|
||||
<span v-else>暂无</span>
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="handle" :label="label" name="999">
|
||||
<slot name="handle"></slot>
|
||||
</el-tab-pane>
|
||||
</el-tabs>-->
|
||||
|
||||
|
||||
<el-tab-pane v-if="handle" :label="label" name="999">
|
||||
<slot name="handle"></slot>
|
||||
</el-tab-pane>
|
||||
|
||||
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
module.exports = {
|
||||
props: {
|
||||
id: String,
|
||||
handle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: "审核"
|
||||
},
|
||||
panes: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
props: {
|
||||
id: String,
|
||||
handle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hostUnit: "",
|
||||
helpUnit: [],
|
||||
unitOptions: [],
|
||||
activeName: "1",
|
||||
activeCollapse: "",
|
||||
loading: true,
|
||||
viewData: {},
|
||||
config: {}
|
||||
}
|
||||
label: {
|
||||
type: String,
|
||||
default: "审核"
|
||||
},
|
||||
components: {
|
||||
"file-upload": httpVueLoader("/components/plugins/FileUpload.vue")
|
||||
},
|
||||
methods: {
|
||||
hasPane(name) {
|
||||
if (!this.handle) {
|
||||
return true
|
||||
}
|
||||
return this.panes.includes(name)
|
||||
},
|
||||
async openView(id, activeName = "1") {
|
||||
this.loading = true
|
||||
this.viewData = await proposal.getProposalInfo(id)
|
||||
|
||||
console.log(this.viewData)
|
||||
|
||||
if (!this.viewData) {
|
||||
this.$notify.error({ title: "失败", message: "获取提案信息失败" })
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
const { files, feedback, caseAudit, resultCode } = this.viewData
|
||||
this.helpUnit = []
|
||||
if (caseAudit != null && resultCode !== "notGive" && caseAudit.other != null) {
|
||||
const other = JSON.parse(caseAudit.other)
|
||||
if (this.unitOptions.find(v => v.id === other.hostUnit)) {
|
||||
this.hostUnit = this.unitOptions.find(v => v.id === other.hostUnit).unitName
|
||||
if (other.helpUnit && other.helpUnit.length > 0) {
|
||||
other.helpUnit.forEach((v, i) => {
|
||||
const helpUnit = this.unitOptions.find(z => other.helpUnit[i] === z.id).unitName
|
||||
this.helpUnit.push(helpUnit)
|
||||
})
|
||||
this.helpUnit = this.helpUnit.join("、")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (files) {
|
||||
this.viewData.files = JSON.parse(files)
|
||||
}
|
||||
|
||||
if (feedback) {
|
||||
this.viewData.feedback.map(v => {
|
||||
v.files = JSON.parse(v.files)
|
||||
})
|
||||
}
|
||||
|
||||
this.activeName = this.handle ? "999" : activeName
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.config = await proposal.getProposalConfig()
|
||||
this.unitOptions = await proposal.getProposalUndertake()
|
||||
panes: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hostUnit: "",
|
||||
helpUnit: [],
|
||||
unitOptions: [],
|
||||
activeName: "1",
|
||||
activeCollapse: "",
|
||||
loading: true,
|
||||
viewData: {},
|
||||
config: {},
|
||||
tabs: [],
|
||||
elTabPlusScrollHeight: 700,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'el-tab-plus': httpVueLoader('/components/plugins/ELTabPlus.vue'),
|
||||
"file-upload": httpVueLoader("/components/plugins/FileUpload.vue")
|
||||
},
|
||||
methods: {
|
||||
hasPane(name) {
|
||||
if (!this.handle) {
|
||||
return true
|
||||
}
|
||||
return this.panes.includes(name)
|
||||
},
|
||||
async openView(id) {
|
||||
this.loading = true
|
||||
this.viewData = await proposal.getProposalInfo(id)
|
||||
|
||||
if (!this.viewData) {
|
||||
this.$notify.error({title: "失败", message: "获取提案信息失败"})
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
const {files, feedback, caseAudit, resultCode} = this.viewData
|
||||
this.helpUnit = []
|
||||
if (caseAudit != null && resultCode !== "notGive" && caseAudit.other != null) {
|
||||
const other = JSON.parse(caseAudit.other)
|
||||
if (this.unitOptions.find(v => v.id === other.hostUnit)) {
|
||||
this.hostUnit = this.unitOptions.find(v => v.id === other.hostUnit).unitName
|
||||
if (other.helpUnit && other.helpUnit.length > 0) {
|
||||
other.helpUnit.forEach((v, i) => {
|
||||
const helpUnit = this.unitOptions.find(z => other.helpUnit[i] === z.id).unitName
|
||||
this.helpUnit.push(helpUnit)
|
||||
})
|
||||
this.helpUnit = this.helpUnit.join("、")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (files) {
|
||||
this.viewData.files = JSON.parse(files)
|
||||
}
|
||||
|
||||
if (feedback) {
|
||||
this.viewData.feedback.map(v => {
|
||||
v.files = JSON.parse(v.files)
|
||||
})
|
||||
}
|
||||
|
||||
this.formatTab()
|
||||
this.loading = false
|
||||
},
|
||||
formatTab() {
|
||||
let tabs = []
|
||||
tabs.push({name: '提案基础信息', refName: 'basic-info'})
|
||||
if (this.viewData.isConjoin !== 0) {
|
||||
tabs.push({name: '提案并案信息', refName: 'conjoin-info'})
|
||||
}
|
||||
if (this.viewData.seconded) {
|
||||
tabs.push({name: '附议信息', refName: 'seconded-info'})
|
||||
}
|
||||
if (this.viewData.delegationAudit && this.viewData.delegationAudit.length > 0) {
|
||||
tabs.push({name: '团长审核', refName: 'delegation-audit-info'})
|
||||
}
|
||||
if (this.viewData.membersOpinions && this.viewData.membersOpinions.length > 0) {
|
||||
tabs.push({name: '提案工作组意见', refName: 'members-opinions-info'})
|
||||
}
|
||||
if (this.viewData.caseAuditId && this.viewData.caseAudit) {
|
||||
tabs.push({name: '提案工作组立案审核', refName: 'case-audit-info'})
|
||||
}
|
||||
if (this.viewData.underTakeFirstOpinion && this.viewData.underTakeFirstOpinion.length > 0) {
|
||||
tabs.push({name: '承办单位意见', refName: 'undertake-first-audit-info'})
|
||||
}
|
||||
if (this.viewData.caseUnitAuditId && this.viewData.caseUnitAudit) {
|
||||
tabs.push({name: '提案工作组确认承办单位', refName: 'case-unit-audit-info'})
|
||||
}
|
||||
if (this.viewData.replyInfo && this.viewData.replyInfo.length > 0 && this.viewData.replyInfo.some(v => v.isReply || v.leaderCheckResult != null)) {
|
||||
tabs.push({name: '承办单位办理', refName: 'undertake-reply-audit-info'})
|
||||
}
|
||||
if (this.viewData.branchLeaderSuffixAuditOpinion && this.viewData.branchLeaderSuffixAuditOpinion.length > 0) {
|
||||
tabs.push({name: '分管校领导审批', refName: 'branch-leader-reply-opinion-audit-info'})
|
||||
}
|
||||
if (this.viewData.feedback && this.viewData.feedback.length > 0) {
|
||||
tabs.push({name: '反馈评分信息', refName: 'feedback-audit-info'})
|
||||
}
|
||||
|
||||
//如果是审核让页面跳到最下面并且选中最后一个
|
||||
if (this.handle) {
|
||||
tabs.push({name: this.label, refName: 'audit'})
|
||||
if (this.$refs.etp) {
|
||||
this.$refs.etp.scrollEnd()
|
||||
}
|
||||
} else {
|
||||
//如果是查看让页面跳到最上面并且选中第一个
|
||||
if (this.$refs.etp) {
|
||||
this.$refs.etp.scrollToTop()
|
||||
}
|
||||
}
|
||||
this.tabs = tabs
|
||||
},
|
||||
getHeight() {
|
||||
const h = window.innerHeight - 50 - 20 - 54 - 40 - 50 - 10 - 10
|
||||
this.elTabPlusScrollHeight = h
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.config = await proposal.getProposalConfig()
|
||||
this.unitOptions = await proposal.getProposalUndertake()
|
||||
this.getHeight()
|
||||
window.addEventListener('resize', this.getHeight)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.el-descriptions__table {
|
||||
table-layout: fixed !important;
|
||||
table-layout: fixed !important;
|
||||
}
|
||||
|
||||
.el-descriptions-item__cell {
|
||||
text-align: center !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
|
||||
.item-center {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
margin-right: 110px;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
margin-right: 110px;
|
||||
}
|
||||
|
||||
.item-center .el-form-item__content {
|
||||
font-size: 18px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.item-sign {
|
||||
width: 200px;
|
||||
height: 130px;
|
||||
width: 200px;
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
.item-form {
|
||||
padding: 0 25px;
|
||||
padding: 0 25px;
|
||||
}
|
||||
|
||||
.el-collapse-item__wrap {
|
||||
padding: 10px 10px;
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
.el-collapse-item__header {
|
||||
border-bottom: 1px solid #eee;
|
||||
font-weight: 700;
|
||||
border-bottom: 1px solid #eee;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.item-number {
|
||||
color: red;
|
||||
font-weight: 600
|
||||
color: red;
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
.el-collapse-item__header {
|
||||
position: relative;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.el-collapse-item__arrow {
|
||||
color: #1582dc;
|
||||
font-weight: 800 !important;
|
||||
color: #1582dc;
|
||||
font-weight: 800 !important;
|
||||
}
|
||||
|
||||
/*.el-tabs__header{*/
|
||||
@@ -504,15 +556,22 @@ module.exports = {
|
||||
/*}*/
|
||||
|
||||
.wrap-table tbody:nth-child(3n+3):after {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 15px;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.wrap-table-4 tbody:nth-child(4n+4):after {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 15px;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.custom-desc .el-descriptions-item__label {
|
||||
width: 15% !important;
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,877 @@
|
||||
<!--#layout("/mobile/platform.html"){#-->
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: rgb(0, 78, 100);
|
||||
--primary-light: rgba(0, 78, 100, 0.1);
|
||||
--secondary-color: #37A6BD;
|
||||
--text-color: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-light: #999999;
|
||||
--bg-color: #f5f7fa;
|
||||
--card-bg: #ffffff;
|
||||
--border-color: #eeeeee;
|
||||
--success-color: #07c160;
|
||||
--warning-color: #ff976a;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
background-color: var(--bg-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 筛选区域样式 */
|
||||
.filter-section {
|
||||
background-color: var(--card-bg);
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.filter-section.collapsed {
|
||||
max-height: 84px;
|
||||
}
|
||||
|
||||
.filter-section.expanded {
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
.filter-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.filter-title {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.filter-toggle {
|
||||
color: var(--text-secondary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-toggle .van-icon {
|
||||
transition: transform 0.3s;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.filter-toggle .van-icon.rotate {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.filter-content.hidden {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.filter-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
margin-right: 10px;
|
||||
min-width: 60px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.filter-options {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.filter-tag {
|
||||
padding: 4px 10px;
|
||||
border-radius: 16px;
|
||||
font-size: 12px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 6px;
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.filter-tag.active {
|
||||
background-color: var(--primary-light);
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.filter-search {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.filter-search .van-search {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.filter-search .van-search__content {
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
.suggestion-list {
|
||||
padding: 16px;
|
||||
background-color: var(--bg-color);
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.van-pull-refresh, .van-list {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.suggestion-card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.suggestion-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.suggestion-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-color);
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.suggestion-status {
|
||||
font-size: 12px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 12px;
|
||||
margin-left: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.status-processing {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.suggestion-content {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
background-color: var(--bg-color);
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
word-break: break-all;
|
||||
white-space: pre-line;
|
||||
max-height: 3.2em;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.suggestion-submitter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.suggestion-submitter .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.suggestion-unit {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.suggestion-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
color: var(--text-light);
|
||||
border-top: 1px solid #f5f5f5;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.suggestion-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.suggestion-time .van-icon {
|
||||
font-size: 14px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.suggestion-action {
|
||||
color: var(--primary-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.suggestion-action .van-icon {
|
||||
font-size: 14px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.empty-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 64px 16px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 64px;
|
||||
color: #ddd;
|
||||
margin-bottom: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 15px;
|
||||
color: var(--text-light);
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 详情弹窗样式 */
|
||||
.detail-popup {
|
||||
padding: 24px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.detail-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: var(--text-light);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
color: var(--text-color);
|
||||
line-height: 1.8;
|
||||
font-size: 15px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.submitter-info {
|
||||
background-color: var(--bg-color);
|
||||
border-radius: 8px;
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: var(--text-secondary);
|
||||
width: 80px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: var(--text-color);
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-reply {
|
||||
background-color: #f9f9f9;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.detail-attachments {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.attachment-item {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.attachment-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.reply-form {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.reply-textarea {
|
||||
box-sizing: border-box;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
font-size: 14px;
|
||||
background-color: var(--card-bg);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.reply-attachments {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.reply-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.no-reply {
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
background-color: var(--bg-color);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.no-reply-icon {
|
||||
font-size: 36px;
|
||||
color: #ccc;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.no-reply-text {
|
||||
font-size: 14px;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.van-button--primary {
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* 下拉刷新和上拉加载样式 */
|
||||
.van-pull-refresh__track {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.van-list {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
/* 统计面板 */
|
||||
.stats-panel {
|
||||
background-color: var(--card-bg);
|
||||
padding: 16px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.stats-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="意见箱管理" left-arrow @click-left="pjaxReplace('/platform/suggestionBox/h5')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<!-- 统计面板 -->
|
||||
<div class="stats-panel">
|
||||
<div class="stats-item">
|
||||
<div class="stats-value">{{ stats.total }}</div>
|
||||
<div class="stats-label">总意见数</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-value">{{ stats.pending }}</div>
|
||||
<div class="stats-label">待回复</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-value">{{ stats.replied }}</div>
|
||||
<div class="stats-label">已回复</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-value">{{ stats.today }}</div>
|
||||
<div class="stats-label">今日新增</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 筛选区域 -->
|
||||
<div class="filter-section" :class="filters.isCollapsed ? 'collapsed' : 'expanded'">
|
||||
<div class="filter-header">
|
||||
<div class="filter-title">筛选条件</div>
|
||||
<div class="filter-toggle" @click="toggleFilterCollapse">
|
||||
<span>{{ filters.isCollapsed ? '展开' : '收起' }}</span>
|
||||
<van-icon :name="filters.isCollapsed ? 'arrow-down' : 'arrow-up'"
|
||||
:class="{ rotate: !filters.isCollapsed }"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-search">
|
||||
<van-search v-model="filters.keyword" placeholder="搜索意见标题、内容或提交人"
|
||||
@search="onSearch"></van-search>
|
||||
</div>
|
||||
|
||||
<div class="filter-content" :class="{ hidden: filters.isCollapsed }">
|
||||
<div class="filter-row">
|
||||
<div class="filter-label">状态</div>
|
||||
<div class="filter-options">
|
||||
<div class="filter-tag" :class="{ active: filters.status === '' }" @click="setFilter('status', '')">
|
||||
全部
|
||||
</div>
|
||||
<div class="filter-tag" :class="{ active: filters.status === '0' }"
|
||||
@click="setFilter('status', '0')">
|
||||
待回复
|
||||
</div>
|
||||
<div class="filter-tag" :class="{ active: filters.status === '1' }"
|
||||
@click="setFilter('status', '1')">
|
||||
已回复
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-row">
|
||||
<div class="filter-label">时间</div>
|
||||
<div class="filter-options">
|
||||
<div class="filter-tag" :class="{ active: filters.time === '' }" @click="setFilter('time', '')">全部
|
||||
</div>
|
||||
<div class="filter-tag" :class="{ active: filters.time === 'today' }"
|
||||
@click="setFilter('time', 'today')">今日
|
||||
</div>
|
||||
<div class="filter-tag" :class="{ active: filters.time === 'week' }"
|
||||
@click="setFilter('time', 'week')">
|
||||
本周
|
||||
</div>
|
||||
<div class="filter-tag" :class="{ active: filters.time === 'month' }"
|
||||
@click="setFilter('time', 'month')">本月
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="suggestion-list">
|
||||
<!-- 下拉刷新和上拉加载更多 -->
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="loadMore"
|
||||
>
|
||||
<!-- 空状态 -->
|
||||
<div class="empty-list" v-if="suggestions.length === 0 && !loading">
|
||||
<van-icon name="comment-circle-o" class="empty-icon"></van-icon>
|
||||
<div class="empty-text">暂无符合条件的意见</div>
|
||||
</div>
|
||||
|
||||
<!-- 意见列表 -->
|
||||
<div class="suggestion-card" v-for="(item, index) in suggestions" :key="item.id"
|
||||
@click="showDetail(item)">
|
||||
<div class="suggestion-header">
|
||||
<div class="suggestion-title">{{ item.title || '意见反馈' }}</div>
|
||||
<div class="suggestion-status" :class="getStatusClass(item.isReply)">
|
||||
{{ getStatusText(item.isReply) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="suggestion-submitter">
|
||||
<van-icon name="contact"/>
|
||||
<span>{{ item.submitterName }}</span>
|
||||
<span class="suggestion-unit">{{ item.submitterUnitName }}</span>
|
||||
</div>
|
||||
<div class="suggestion-content">{{ item.content }}</div>
|
||||
<div class="suggestion-footer">
|
||||
<div class="suggestion-time">
|
||||
<van-icon name="clock-o"/>
|
||||
<span>{{ formatDate(item.submitTime) }}</span>
|
||||
</div>
|
||||
<div class="suggestion-action">
|
||||
{{ item.reply ? '查看详情' : '去回复' }}
|
||||
<van-icon name="arrow"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
|
||||
<!-- 详情弹出层 -->
|
||||
<van-popup v-model="showDetailPopup" round closeable position="bottom">
|
||||
<div class="detail-popup" v-if="currentSuggestion">
|
||||
<div class="detail-header">
|
||||
<div class="detail-title">{{ currentSuggestion.title || '意见反馈' }}</div>
|
||||
<div class="detail-meta">
|
||||
<span>{{ formatDate(currentSuggestion.submitTime) }}</span>
|
||||
<span :class="getStatusClass(currentSuggestion.isReply)">{{ getStatusText(currentSuggestion.isReply) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">提交人信息</div>
|
||||
<div class="submitter-info">
|
||||
<div class="info-item">
|
||||
<span class="info-label">姓名:</span>
|
||||
<span class="info-value">{{ currentSuggestion.submitterName || '未填写' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">工号:</span>
|
||||
<span class="info-value">{{ currentSuggestion.submitterLoginName || '未填写' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">单位:</span>
|
||||
<span class="info-value">{{ currentSuggestion.submitterUnitName || '未填写' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">联系方式:</span>
|
||||
<span class="info-value">{{ currentSuggestion.concat || '未填写' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">意见内容</div>
|
||||
<div class="detail-content">{{ currentSuggestion.content }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section"
|
||||
v-if="currentSuggestion.attachments && currentSuggestion.attachments.length > 0">
|
||||
<div class="detail-label">附件</div>
|
||||
<div class="detail-attachments">
|
||||
<vant-file-upload :del="false" :files.sync="currentSuggestion.attachments"
|
||||
view></vant-file-upload>
|
||||
<!-- <div class="attachment-item" v-for="(file, idx) in currentSuggestion.attachments" :key="idx"
|
||||
@click.stop="previewImage(file.url, idx)">
|
||||
<img :src="file.url" class="attachment-image">
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="currentSuggestion.reply">
|
||||
<div class="detail-label">已回复内容</div>
|
||||
<div class="detail-reply detail-content">{{ currentSuggestion.reply }}</div>
|
||||
<div class="detail-meta" style="margin-top: 10px;">
|
||||
回复时间:{{ formatDate(currentSuggestion.replyTime) }}
|
||||
</div>
|
||||
<!-- <div v-if="currentSuggestion.replyAttachments && currentSuggestion.replyAttachments.length > 0"
|
||||
style="margin-top: 12px;">
|
||||
<div class="detail-label">回复附件</div>
|
||||
<div class="detail-attachments">
|
||||
<vant-file-upload :del="false" :files.sync="currentSuggestion.attachments"
|
||||
view></vant-file-upload>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">{{ currentSuggestion.isReply ? '修改回复' : '回复意见' }}</div>
|
||||
<div class="reply-form">
|
||||
<textarea class="reply-textarea" v-model="currentSuggestion.replyContent"
|
||||
placeholder="请输入回复内容..."></textarea>
|
||||
|
||||
<!-- <div class="reply-attachments">-->
|
||||
<!-- <vant-file-upload :files.sync="formData.replyAttachments" :max="15"></vant-file-upload>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<div class="reply-actions">
|
||||
<van-button style="border-radius: 10px" block type="info" :color="themeColor"
|
||||
@click="submitReply">提交回复
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
mixins: [mobileMixins],
|
||||
data() {
|
||||
return {
|
||||
refreshing: false,
|
||||
loading: false,
|
||||
finished: false,
|
||||
showDetailPopup: false,
|
||||
currentSuggestion: null,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
suggestions: [],
|
||||
replyContent: '',
|
||||
replyAttachments: [],
|
||||
filters: {
|
||||
status: '', // 状态筛选
|
||||
time: '', // 时间筛选
|
||||
keyword: '', // 关键词搜索
|
||||
isCollapsed: true // 筛选区域是否折叠
|
||||
},
|
||||
stats: {
|
||||
total: 0,
|
||||
pending: 0,
|
||||
replied: 0,
|
||||
today: 0
|
||||
},
|
||||
formData: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadStats();
|
||||
this.loadData();
|
||||
},
|
||||
methods: {
|
||||
// 加载统计数据
|
||||
loadStats() {
|
||||
$.post('/platform/suggestionBox/admin/getStats').done((res) => {
|
||||
if (res.code === 0 && res.data) {
|
||||
this.stats = {
|
||||
total: res.data.total || 0,
|
||||
pending: res.data.pending || 0,
|
||||
replied: res.data.replied || 0,
|
||||
today: res.data.today || 0
|
||||
};
|
||||
}
|
||||
}).fail(() => {
|
||||
this.$toast.fail('统计数据加载失败');
|
||||
});
|
||||
},
|
||||
|
||||
// 加载意见数据
|
||||
loadData() {
|
||||
this.loading = true;
|
||||
$.post('/platform/suggestionBox/admin/pageData', {
|
||||
pageNumber: this.pageNumber,
|
||||
pageSize: this.pageSize,
|
||||
status: this.filters.status,
|
||||
timeRange: this.filters.time,
|
||||
keyword: this.filters.keyword
|
||||
}).done((res) => {
|
||||
if (res.code === 0 && res.data) {
|
||||
if (this.pageNumber === 1) {
|
||||
this.suggestions = res.data.list || [];
|
||||
} else {
|
||||
this.suggestions = this.suggestions.concat(res.data.list || []);
|
||||
}
|
||||
|
||||
this.finished = !res.data.list || res.data.list.length < this.pageSize;
|
||||
} else {
|
||||
this.finished = true;
|
||||
}
|
||||
this.loading = false;
|
||||
this.refreshing = false;
|
||||
}).fail(() => {
|
||||
this.loading = false;
|
||||
this.refreshing = false;
|
||||
this.finished = true;
|
||||
});
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
onRefresh() {
|
||||
this.pageNumber = 1;
|
||||
this.finished = false;
|
||||
this.loadStats();
|
||||
this.loadData();
|
||||
},
|
||||
|
||||
// 上拉加载更多
|
||||
loadMore() {
|
||||
this.pageNumber++;
|
||||
this.loadData();
|
||||
},
|
||||
|
||||
// 设置筛选条件
|
||||
setFilter(type, value) {
|
||||
this.filters[type] = value;
|
||||
this.pageNumber = 1;
|
||||
this.finished = false;
|
||||
this.loadData();
|
||||
},
|
||||
|
||||
// 搜索
|
||||
onSearch() {
|
||||
this.pageNumber = 1;
|
||||
this.finished = false;
|
||||
this.loadData();
|
||||
},
|
||||
|
||||
// 查看详情
|
||||
showDetail(suggestion) {
|
||||
if (suggestion.attachments && typeof suggestion.attachments === 'string') {
|
||||
try{
|
||||
suggestion.attachments = JSON.parse(suggestion.attachments);
|
||||
}catch (e){
|
||||
suggestion.attachments = [];
|
||||
}
|
||||
}
|
||||
console.log(suggestion)
|
||||
this.currentSuggestion = suggestion;
|
||||
this.showDetailPopup = true;
|
||||
},
|
||||
|
||||
// 提交回复
|
||||
submitReply() {
|
||||
if (!this.currentSuggestion.replyContent || !this.currentSuggestion.replyContent.trim()) {
|
||||
this.$toast('请输入回复内容');
|
||||
return;
|
||||
}
|
||||
|
||||
this.$dialog.confirm({
|
||||
title: '确认提交',
|
||||
message: '确定提交此回复内容吗?'
|
||||
}).then(() => {
|
||||
// 提交回复
|
||||
$.post('/platform/suggestionBox/admin/reply', {
|
||||
reply: JSON.stringify(this.currentSuggestion)
|
||||
}).done((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success('回复成功');
|
||||
this.showDetailPopup = false;
|
||||
this.loadStats();
|
||||
this.pageData();
|
||||
} else {
|
||||
this.$toast.fail(res.msg || '回复失败');
|
||||
}
|
||||
}).fail(() => {
|
||||
this.$toast.fail('网络错误,请重试');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 获取状态class
|
||||
getStatusClass(isReply) {
|
||||
if (!isReply || isReply === 0) return 'status-pending';
|
||||
if (isReply === 1) return 'status-processing';
|
||||
return 'status-completed';
|
||||
},
|
||||
|
||||
// 获取状态文本
|
||||
getStatusText(isReply) {
|
||||
if (!isReply || isReply === 0) return '待回复';
|
||||
if (isReply === 1) return '已回复';
|
||||
return '已处理';
|
||||
},
|
||||
|
||||
// 格式化日期
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
const date = new Date(dateStr);
|
||||
return date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');
|
||||
},
|
||||
|
||||
// 预览图片
|
||||
previewImage(url, index, type = 'submission') {
|
||||
if (!url) return;
|
||||
|
||||
// 创建图片查看器
|
||||
const urls = type === 'reply'
|
||||
? this.currentSuggestion.replyAttachments.map(file => file.url)
|
||||
: this.currentSuggestion.attachments.map(file => file.url);
|
||||
|
||||
this.$imagePreview({
|
||||
images: urls,
|
||||
startPosition: index
|
||||
});
|
||||
},
|
||||
|
||||
// 切换筛选区域折叠状态
|
||||
toggleFilterCollapse() {
|
||||
this.filters.isCollapsed = !this.filters.isCollapsed;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--#}#-->
|
||||
@@ -0,0 +1,531 @@
|
||||
<!--#
|
||||
layout("/mobile/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="意见箱" fixed placeholder @click-left="pjaxReplace('/mobile/index')" left-text="返回" left-arrow></van-nav-bar>
|
||||
|
||||
<!-- 顶部Banner区域 -->
|
||||
<div class="banner-section">
|
||||
<div class="banner-content">
|
||||
<div class="banner-text">
|
||||
<h2>我们重视您的意见</h2>
|
||||
<p>每一条建议都将认真对待</p>
|
||||
</div>
|
||||
<div class="banner-image">
|
||||
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTI1LjYgMTAyLjdsLTE5LTE2LjhtLTQuNy0yMy43bDExLjUtNi44TTU3LjQgMTZsMTEuNSAxMS43TTMxLjIgNTMuOGwyMy42IDcuOSIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6I2ZmZjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtvcGFjaXR5Oi40Ii8+PHBhdGggZD0iTTY0LjEgMzEuN0w0NyA0OS45Yy0zIDMuMi0zLjEgOC4xLS4xIDExLjJsMjQuNCAyNWMzIDMuMSA3LjkgMy4yIDExIC4xTDk5IDY5YzMtMy4yIDMuMS04LjEuMS0xMS4yTDc0LjcgMzIuOGMtMyAzLjEtNy45IDMuMS0xMC42LTEuMXoiIHN0eWxlPSJmaWxsOiNmZmY7c3Ryb2tlOiNmZmY7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBkPSJNMTA4LjkgOTUuN2wtMTUuOC0xMi0xMi4yIDEzIDE0LjQgMTMuN2MuMyAyLjUgMi4zIDQuNSA0LjggNC41aDEzLjdjMi43IDAgNC45LTIuMiA0LjktNC45VjkzLjVjMC0yLjgtMi4xLTUtNC45LTV2OC40cy4xLTEuMi00LjkgMi44LjEtMyAuMS0zeiIgc3R5bGU9ImZpbGw6I2ZmZjtzdHJva2U6I2ZmZjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMCIvPjwvc3ZnPg=="
|
||||
alt="Feedback">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 功能卡片区域 -->
|
||||
<div class="cards-container">
|
||||
<!-- 提交意见 -->
|
||||
<div class="feature-card" @click="goToSubmitPage">
|
||||
<div class="card-icon submit-icon">
|
||||
<van-icon name="edit"/>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<h3>提交意见</h3>
|
||||
<p>分享您的想法和建议</p>
|
||||
</div>
|
||||
<div class="card-arrow">
|
||||
<van-icon name="arrow"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 我的意见 -->
|
||||
<div class="feature-card" @click="goToMyOpinionsPage">
|
||||
<div class="card-icon my-icon">
|
||||
<van-icon name="records"/>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<h3>我的意见</h3>
|
||||
<p>查看您提交的所有意见</p>
|
||||
</div>
|
||||
<div class="card-arrow">
|
||||
<van-icon name="arrow"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 意见管理(管理员) -->
|
||||
<div class="feature-card" v-if="isAdmin" @click="goToAllOpinionsPage">
|
||||
<div class="card-icon admin-icon">
|
||||
<van-icon name="manager"/>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<h3>意见管理</h3>
|
||||
<p>管理所有用户提交的意见</p>
|
||||
</div>
|
||||
<div class="card-arrow">
|
||||
<van-icon name="arrow"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 使用指南 -->
|
||||
<div class="guide-container" v-if="!isAdmin">
|
||||
<div class="guide-header">
|
||||
<h3>使用指南</h3>
|
||||
</div>
|
||||
<div class="guide-steps">
|
||||
<div class="guide-step">
|
||||
<div class="step-number">1</div>
|
||||
<div class="step-content">
|
||||
<h4>提交意见</h4>
|
||||
<p>点击"提交意见"按钮,填写您的意见和建议</p>
|
||||
</div>
|
||||
<div class="step-icon">
|
||||
<van-icon name="edit"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-divider"></div>
|
||||
<div class="guide-step">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-content">
|
||||
<h4>等待处理</h4>
|
||||
<p>我们将在3个工作日内处理您的意见</p>
|
||||
</div>
|
||||
<div class="step-icon">
|
||||
<van-icon name="underway-o"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-divider"></div>
|
||||
<div class="guide-step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-content">
|
||||
<h4>查看回复</h4>
|
||||
<p>在"我的意见"中查看官方回复</p>
|
||||
</div>
|
||||
<div class="step-icon">
|
||||
<van-icon name="comment-o"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 常见问题 -->
|
||||
<div class="faq-container" v-if="!isAdmin">
|
||||
<div class="faq-header">
|
||||
<h3>常见问题</h3>
|
||||
<span class="faq-subtitle">解答您的疑惑</span>
|
||||
</div>
|
||||
<div class="faq-list">
|
||||
<div class="faq-item" :class="{'faq-active': activeFaq === 1}" @click="toggleFaq(1)">
|
||||
<div class="faq-question">
|
||||
<span class="faq-icon"><van-icon name="question-o"/></span>
|
||||
<span>如何提交带附件的意见?</span>
|
||||
<span class="faq-arrow"><van-icon name="arrow-down"/></span>
|
||||
</div>
|
||||
<div class="faq-answer" v-show="activeFaq === 1">
|
||||
<p>在提交意见表单中,您可以上传最多3个文件作为附件,支持图片格式。点击附件上传区域,选择您要上传的文件即可。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faq-item" :class="{'faq-active': activeFaq === 2}" @click="toggleFaq(2)">
|
||||
<div class="faq-question">
|
||||
<span class="faq-icon"><van-icon name="question-o"/></span>
|
||||
<span>意见提交后多久能收到回复?</span>
|
||||
<span class="faq-arrow"><van-icon name="arrow-down"/></span>
|
||||
</div>
|
||||
<div class="faq-answer" v-show="activeFaq === 2">
|
||||
<p>我们会在3个工作日内处理您的意见,紧急问题会优先处理。您可以随时在"我的意见"中查看处理进度。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faq-item" :class="{'faq-active': activeFaq === 3}" @click="toggleFaq(3)">
|
||||
<div class="faq-question">
|
||||
<span class="faq-icon"><van-icon name="question-o"/></span>
|
||||
<span>我可以修改已提交的意见吗?</span>
|
||||
<span class="faq-arrow"><van-icon name="arrow-down"/></span>
|
||||
</div>
|
||||
<div class="faq-answer" v-show="activeFaq === 3">
|
||||
<p>提交后的意见暂不支持修改,如有补充,请重新提交并说明这是对之前意见的补充。我们会将相关意见关联处理。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: rgb(0, 78, 100);
|
||||
--primary-light: rgba(0, 78, 100, 0.1);
|
||||
--secondary-color: #37A6BD;
|
||||
--text-color: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-light: #999999;
|
||||
--bg-color: #f6f6f6;
|
||||
--card-bg: #ffffff;
|
||||
--border-color: #eeeeee;
|
||||
--success-color: #07c160;
|
||||
--warning-color: #ff976a;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
/* 顶部Banner */
|
||||
.banner-section {
|
||||
padding: 0;
|
||||
height: 180px;
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.banner-curve {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.banner-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24px 20px 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.banner-text {
|
||||
color: white;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.banner-text h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.banner-text p {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.banner-image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.banner-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* 功能卡片 */
|
||||
.cards-container {
|
||||
padding: 20px 16px 16px;
|
||||
margin-top: -20px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background-color: var(--bg-color);
|
||||
border-radius: 20px 20px 0 0;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.card-icon .van-icon {
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.submit-icon {
|
||||
background: linear-gradient(135deg, #1989fa 0%, #39b9f9 100%);
|
||||
}
|
||||
|
||||
.my-icon {
|
||||
background: linear-gradient(135deg, #07c160 0%, #10d878 100%);
|
||||
}
|
||||
|
||||
.admin-icon {
|
||||
background: linear-gradient(135deg, #ff6b6b 0%, #ffaa7f 100%);
|
||||
}
|
||||
|
||||
.card-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.card-info h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.card-info p {
|
||||
font-size: 13px;
|
||||
color: var(--text-light);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card-arrow {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/* 使用指南 */
|
||||
.guide-container {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
|
||||
.guide-header {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.guide-header h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.guide-steps {
|
||||
background: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.guide-step {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
margin-right: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-content h4 {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.step-content p {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
margin-left: 12px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.step-divider {
|
||||
height: 24px;
|
||||
width: 1px;
|
||||
background: #e8e8e8;
|
||||
margin: 8px 0 8px 15px;
|
||||
}
|
||||
|
||||
/* 常见问题 */
|
||||
.faq-container {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
|
||||
.faq-header {
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.faq-header h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-color);
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.faq-subtitle {
|
||||
font-size: 12px;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.faq-list {
|
||||
background: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.faq-item {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.faq-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.faq-question {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.faq-active .faq-question {
|
||||
background-color: var(--primary-light);
|
||||
}
|
||||
|
||||
.faq-icon {
|
||||
color: var(--primary-color);
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.faq-arrow {
|
||||
margin-left: auto;
|
||||
color: var(--text-light);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.faq-active .faq-arrow .van-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.faq-answer {
|
||||
padding: 0 16px 16px 44px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
border-top: 1px dashed var(--border-color);
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
.popup-title {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #ebedf0;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
padding: 16px;
|
||||
max-height: calc(100% - 60px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.suggestion-content {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.suggestion-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 6px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.suggestion-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.attachment-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: function () {
|
||||
return {
|
||||
isAdmin: false, // 控制是否为管理员
|
||||
allSuggestions: [],
|
||||
user: 'user1',
|
||||
activeFaq: null,
|
||||
totalSuggestions: 0,
|
||||
respondedPercent: 0,
|
||||
recentSuggestions: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userSuggestions: function () {
|
||||
return this.allSuggestions.filter(function (item) {
|
||||
return item.user === this.user;
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goToSubmitPage: function () {
|
||||
window.location.href = '/platform/suggestionBox/h5/write';
|
||||
},
|
||||
goToMyOpinionsPage: function () {
|
||||
window.location.href = '/platform/suggestionBox/h5/mine';
|
||||
},
|
||||
goToAllOpinionsPage: function () {
|
||||
window.location.href = '/platform/suggestionBox/admin/h5';
|
||||
},
|
||||
toggleFaq: function (id) {
|
||||
this.activeFaq = this.activeFaq === id ? null : id;
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
// 初始化数据
|
||||
this.isAdmin = "${@shiro.hasRole('sysadmin')}" === "true"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,549 @@
|
||||
<!--#layout("/mobile/platform.html"){#-->
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: rgb(0, 78, 100);
|
||||
--primary-light: rgba(0, 78, 100, 0.1);
|
||||
--secondary-color: #37A6BD;
|
||||
--text-color: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-light: #999999;
|
||||
--bg-color: #f5f7fa;
|
||||
--card-bg: #ffffff;
|
||||
--border-color: #eeeeee;
|
||||
--success-color: #07c160;
|
||||
--warning-color: #ff976a;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
background-color: var(--bg-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面样式 */
|
||||
.suggestion-list {
|
||||
padding: 16px;
|
||||
background-color: var(--bg-color);
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.van-pull-refresh, .van-list {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.suggestion-card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.2s ease;
|
||||
border: 1px solid rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.suggestion-card:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.suggestion-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.suggestion-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-color);
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.suggestion-status {
|
||||
font-size: 12px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 12px;
|
||||
margin-left: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.status-processing {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.suggestion-content {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
background-color: var(--bg-color);
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
word-break: break-all;
|
||||
white-space: pre-line;
|
||||
max-height: 3.2em;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.suggestion-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
color: var(--text-light);
|
||||
border-top: 1px solid #f5f5f5;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.suggestion-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.suggestion-time .van-icon {
|
||||
font-size: 14px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.suggestion-action {
|
||||
color: var(--primary-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.suggestion-action .van-icon {
|
||||
font-size: 14px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.empty-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 64px 16px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 64px;
|
||||
color: #ddd;
|
||||
margin-bottom: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 15px;
|
||||
color: var(--text-light);
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 详情弹窗样式 */
|
||||
.detail-popup {
|
||||
padding: 24px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.detail-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: var(--text-light);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
color: var(--text-color);
|
||||
line-height: 1.8;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.detail-reply {
|
||||
background-color: #f9f9f9;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.detail-attachments {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.attachment-item {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.attachment-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.loader {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/*!* 自定义导航栏样式 *!*/
|
||||
/*.van-nav-bar {*/
|
||||
/* background-color: var(--primary-color);*/
|
||||
/*}*/
|
||||
|
||||
/*.van-nav-bar .van-nav-bar__title {*/
|
||||
/* color: white;*/
|
||||
/* font-weight: 500;*/
|
||||
/*}*/
|
||||
|
||||
/*.van-nav-bar .van-icon, .van-nav-bar .van-nav-bar__text {*/
|
||||
/* color: white;*/
|
||||
/*}*/
|
||||
|
||||
.van-button--primary {
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* 下拉刷新和上拉加载样式 */
|
||||
.van-pull-refresh__track {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.van-list {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.no-reply {
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
background-color: var(--bg-color);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.no-reply-icon {
|
||||
font-size: 36px;
|
||||
color: #ccc;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.no-reply-text {
|
||||
font-size: 14px;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.submitter-info {
|
||||
background-color: var(--bg-color);
|
||||
border-radius: 8px;
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: var(--text-secondary);
|
||||
width: 80px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: var(--text-color);
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="我的意见建议" left-arrow @click-left="pjaxReplace('/platform/suggestionBox/h5')" fixed placeholder left-text="返回"></van-nav-bar>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="suggestion-list">
|
||||
<!-- 下拉刷新和上拉加载更多 -->
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="loadMore"
|
||||
>
|
||||
<!-- 空状态 -->
|
||||
<div class="empty-list" v-if="suggestions.length === 0 && !loading">
|
||||
<van-icon name="comment-circle-o" class="empty-icon"/>
|
||||
<div class="empty-text">您还没有提交过意见</div>
|
||||
<van-button type="primary" size="normal" round @click="goToSubmitPage">去提交意见</van-button>
|
||||
</div>
|
||||
|
||||
<!-- 意见列表 -->
|
||||
<div class="suggestion-card" v-for="(item, index) in suggestions" :key="item.id"
|
||||
@click="showDetail(item)">
|
||||
<div class="suggestion-header">
|
||||
<div class="suggestion-title">{{ item.title || '意见反馈' }}</div>
|
||||
<div class="suggestion-status" :class="getStatusClass(item.isReply)">
|
||||
{{ getStatusText(item.isReply) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="suggestion-content">{{ item.content }}</div>
|
||||
<div class="suggestion-footer">
|
||||
<div class="suggestion-time">
|
||||
<van-icon name="clock-o"/>
|
||||
<span>{{ formatDate(item.submitTime) }}</span>
|
||||
</div>
|
||||
<div class="suggestion-action">
|
||||
查看详情
|
||||
<van-icon name="arrow"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
|
||||
<!-- 详情弹出层 -->
|
||||
<van-popup v-model="showDetailPopup" round closeable position="bottom" :style="{ height: '80%' }">
|
||||
<div class="detail-popup" v-if="currentSuggestion">
|
||||
<div class="detail-header">
|
||||
<div class="detail-title">{{ currentSuggestion.title || '意见反馈' }}</div>
|
||||
<div class="detail-meta">
|
||||
<span>{{ formatDate(currentSuggestion.submitTime) }}</span>
|
||||
<span :class="getStatusClass(currentSuggestion.isReply)">{{ getStatusText(currentSuggestion.isReply) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">提交人信息</div>
|
||||
<div class="submitter-info">
|
||||
<div class="info-item">
|
||||
<span class="info-label">姓名:</span>
|
||||
<span class="info-value">{{ currentSuggestion.submitterName || '未填写' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">工号:</span>
|
||||
<span class="info-value">{{ currentSuggestion.submitterLoginName || '未填写' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">单位:</span>
|
||||
<span class="info-value">{{ currentSuggestion.submitterUnitName || '未填写' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">联系方式:</span>
|
||||
<span class="info-value">{{ currentSuggestion.concat || '未填写' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">意见内容</div>
|
||||
<div class="detail-content">{{ currentSuggestion.content }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section"
|
||||
v-if="currentSuggestion.attachments && currentSuggestion.attachments.length > 0">
|
||||
<div class="detail-label">附件</div>
|
||||
<div class="detail-attachments">
|
||||
<vant-file-upload :del="false" :files.sync="currentSuggestion.attachments"
|
||||
view></vant-file-upload>
|
||||
<!-- <div class="attachment-item" v-for="(file, idx) in currentSuggestion.attachments" :key="idx"
|
||||
@click.stop="previewImage(file.url, idx)">
|
||||
<img :src="file.url" class="attachment-image">
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="currentSuggestion.isReply">
|
||||
<div class="detail-label">回复</div>
|
||||
<div class="detail-reply detail-content">{{ currentSuggestion.replyContent }}</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="detail-section">
|
||||
<div class="detail-label">回复</div>
|
||||
<div class="no-reply">
|
||||
<van-icon name="chat-o" class="no-reply-icon"/>
|
||||
<div class="no-reply-text">暂无回复</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const vue = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
refreshing: false,
|
||||
loading: false,
|
||||
finished: false,
|
||||
showDetailPopup: false,
|
||||
currentSuggestion: null,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
suggestions: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData();
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.loading = true;
|
||||
$.post('/platform/suggestionBox/pageData', {
|
||||
pageNumber: this.pageNumber,
|
||||
pageSize: this.pageSize
|
||||
}).done((res) => {
|
||||
if (res.code === 0 && res.data) {
|
||||
if (this.pageNumber === 1) {
|
||||
this.suggestions = res.data.list || [];
|
||||
} else {
|
||||
this.suggestions = this.suggestions.concat(res.data.list || []);
|
||||
}
|
||||
|
||||
this.finished = !res.data.list || res.data.list.length < this.pageSize;
|
||||
} else {
|
||||
this.finished = true;
|
||||
}
|
||||
this.loading = false;
|
||||
this.refreshing = false;
|
||||
}).fail(() => {
|
||||
this.loading = false;
|
||||
this.refreshing = false;
|
||||
this.finished = true;
|
||||
});
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
onRefresh() {
|
||||
this.pageNumber = 1;
|
||||
this.finished = false;
|
||||
this.loadData();
|
||||
},
|
||||
|
||||
// 上拉加载更多
|
||||
loadMore() {
|
||||
this.pageNumber++;
|
||||
this.loadData();
|
||||
},
|
||||
|
||||
// 查看详情
|
||||
showDetail(suggestion) {
|
||||
if (suggestion.attachments && typeof suggestion.attachments === 'string') {
|
||||
try {
|
||||
suggestion.attachments = JSON.parse(suggestion.attachments);
|
||||
} catch (e) {
|
||||
suggestion.attachments = [];
|
||||
}
|
||||
}
|
||||
this.currentSuggestion = suggestion;
|
||||
this.showDetailPopup = true;
|
||||
},
|
||||
|
||||
// 获取状态class
|
||||
getStatusClass(isReply) {
|
||||
if (!isReply || isReply === 0) return 'status-pending';
|
||||
if (isReply === 1) return 'status-processing';
|
||||
return 'status-completed';
|
||||
},
|
||||
|
||||
// 获取状态文本
|
||||
getStatusText(isReply) {
|
||||
if (!isReply || isReply === 0) return '待处理';
|
||||
if (isReply === 1) return '处理中';
|
||||
return '已处理';
|
||||
},
|
||||
|
||||
// 格式化日期
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
const date = new Date(dateStr);
|
||||
return date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');
|
||||
},
|
||||
|
||||
// 前往提交意见页面
|
||||
goToSubmitPage() {
|
||||
pjaxReplace("/platform/suggestionBox/h5/write")
|
||||
},
|
||||
|
||||
// 预览图片
|
||||
previewImage(url, index) {
|
||||
if (!url) return;
|
||||
|
||||
// 创建图片查看器
|
||||
const urls = this.currentSuggestion.attachments.map(file => file.url);
|
||||
this.$imagePreview({
|
||||
images: urls,
|
||||
startPosition: index
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
window.addEventListener('pageshow', e => {
|
||||
if (e.persisted || (window.performance && window.performance.navigation.type === 2)) {
|
||||
vue.loadData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<!--#}#-->
|
||||
@@ -0,0 +1,297 @@
|
||||
<!--#layout("/mobile/platform.html"){#-->
|
||||
|
||||
<style>
|
||||
.form-container {
|
||||
background-color: #f6f6f6;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #f6f6f6;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: rgb(0, 78, 100);
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.section-title span {
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
padding: 12px 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
width: 80px;
|
||||
color: #333;
|
||||
padding: 8px 8px 8px 0;
|
||||
}
|
||||
|
||||
.input-control {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.input-control input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: right;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.textarea-container {
|
||||
padding: 10px 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.textarea-container textarea {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border: none;
|
||||
outline: none;
|
||||
resize: none;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.word-count {
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.upload-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.upload-item, .upload-btn {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
background: #f5f5f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.uploaded-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 0 0 0 4px;
|
||||
}
|
||||
|
||||
.submit-area {
|
||||
padding: 20px 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-sticky>
|
||||
<van-nav-bar title="我要提意见" left-arrow left-text="返回"
|
||||
@click-left="pjaxReplace('/platform/suggestionBox/h5')"></van-nav-bar>
|
||||
</van-sticky>
|
||||
|
||||
<div class="form-container">
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<div class="dot"></div>
|
||||
<span>填写人信息</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<div class="input-label">姓名</div>
|
||||
<div class="input-control">
|
||||
<input type="text" v-model="formData.submitterName" placeholder="请输入姓名" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<div class="input-label">工号</div>
|
||||
<div class="input-control">
|
||||
<input type="text" v-model="formData.submitterLoginName" placeholder="请输入工号" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<div class="input-label">手机号码</div>
|
||||
<div class="input-control">
|
||||
<input type="tel" v-model="formData.concat" placeholder="请输入手机号码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<div class="input-label">所在单位</div>
|
||||
<div class="input-control">
|
||||
<input type="text" v-model="formData.submitterUnitName" placeholder="请输入所在单位" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<div class="dot"></div>
|
||||
<span>填写标题</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<div class="input-label">标题</div>
|
||||
<div class="input-control">
|
||||
<input type="text" v-model="formData.title" placeholder="请输入意见标题">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<div class="dot"></div>
|
||||
<span>填写意见建议内容</span>
|
||||
</div>
|
||||
<div class="textarea-container">
|
||||
<textarea v-model="formData.content" placeholder="请描述您要填写的意见建议内容..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<div class="dot"></div>
|
||||
<span>照片上传</span>
|
||||
</div>
|
||||
|
||||
<div class="upload-area">
|
||||
<vant-file-upload :files.sync="formData.attachments" :max="15"></vant-file-upload>
|
||||
<!-- <div class="upload-grid">-->
|
||||
<!-- <div class="upload-item" v-for="(item, index) in formData.fileList" :key="index">-->
|
||||
<!-- <img :src="item.content || item.url" class="uploaded-image">-->
|
||||
<!-- <div class="delete-btn" @click="deleteImage(index)">-->
|
||||
<!-- <van-icon name="cross" />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="upload-btn" v-if="formData.fileList.length < 3" @click="triggerUpload">-->
|
||||
<!-- <input type="file" ref="fileInput" style="display:none" accept="image/*" @change="onFileChange" multiple>-->
|
||||
<!-- <van-icon name="plus" size="24" />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="submit-area">
|
||||
<van-button @click="submitForm" style="border-radius: 10px" block type="info" :color="themeColor">
|
||||
提 交
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
mixins: [mobileMixins],
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
name: '',
|
||||
mobile: '',
|
||||
idCard: '',
|
||||
department: '',
|
||||
content: '',
|
||||
address: '',
|
||||
fileList: []
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
history.back();
|
||||
},
|
||||
|
||||
async submitForm() {
|
||||
if (!this.formData.concat.trim()) {
|
||||
this.$toast('请输入手机号码');
|
||||
return;
|
||||
}
|
||||
//正则验证
|
||||
if (!/^1[3-9]\d{9}$/.test(this.formData.concat)) {
|
||||
this.$toast('请输入正确的手机号码');
|
||||
return;
|
||||
}
|
||||
if (!this.formData.content.trim()) {
|
||||
this.$toast('请输入投诉内容');
|
||||
return;
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: '您确定要提交吗?'
|
||||
}).then(async () => {
|
||||
const {
|
||||
code,
|
||||
data,
|
||||
msg
|
||||
} = await $.post('/platform/suggestionBox/submit', {suggestion: JSON.stringify(this.formData)})
|
||||
if (code === 0) {
|
||||
this.$toast.success('提交成功')
|
||||
setTimeout(() => {
|
||||
pjaxReplace("/platform/suggestionBox/h5/mine")
|
||||
}, 200)
|
||||
} else {
|
||||
this.$toast(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const id = GetQueryString("id")
|
||||
if (!id) {
|
||||
this.$set(this.formData, 'submitterId', "${@shiro.getPrincipalProperty('id')}")
|
||||
this.$set(this.formData, 'submitterName', "${@shiro.getPrincipalProperty('username')}")
|
||||
this.$set(this.formData, 'submitterLoginName', "${@shiro.getPrincipalProperty('loginname')}")
|
||||
this.$set(this.formData, 'submitterUnitId', "${@shiro.getPrincipalProperty('unitid')}")
|
||||
this.$set(this.formData, 'submitterUnitName', "${@shiro.getPrincipalProperty('unit').getName()}")
|
||||
this.$set(this.formData, 'submitterUnionId', "${@shiro.getPrincipalProperty('union').getId()}")
|
||||
this.$set(this.formData, 'submitterUnionName', "${@shiro.getPrincipalProperty('union').getUnionname()}")
|
||||
this.$set(this.formData, 'concat', "${@shiro.getPrincipalProperty('mobile')}")
|
||||
console.log(this.formData)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!--#}#-->
|
||||
@@ -406,15 +406,19 @@ layout("/layouts/platform.html"){
|
||||
this.tableLoading = false
|
||||
if (data.code == 0) {
|
||||
data.data.list.forEach(v => {
|
||||
const a = JSON.parse(v.sendTypes).map(z => {
|
||||
if (z == "msg") {
|
||||
return "短信"
|
||||
} else {
|
||||
return "微信"
|
||||
}
|
||||
if (v.sendTypes){
|
||||
const a = JSON.parse(v.sendTypes).map(z => {
|
||||
if (z === "DingTalk") {
|
||||
return "钉钉"
|
||||
} else {
|
||||
return "钉钉"
|
||||
}
|
||||
|
||||
})
|
||||
v.sendTypesName = a.toString()
|
||||
})
|
||||
v.sendTypesName = a.toString()
|
||||
} else {
|
||||
v.sendTypesName = "钉钉"
|
||||
}
|
||||
})
|
||||
this.tableData = data.data.list;
|
||||
this.pageForm.totalCount = data.data.totalCount;
|
||||
|
||||
@@ -214,6 +214,9 @@ layout("/layouts/platform.html"){
|
||||
:visible.sync="dialogVisible"
|
||||
width="50%">
|
||||
<el-timeline>
|
||||
<el-timeline-item timestamp="更新规则" placement="top">
|
||||
<div style="color:red;"> 更新人员不会改变是否会员数据,只会改变基础数据。会员是管理员邀请入会,在【数据更新记录】中新入职的人员会自动发送钉钉邀请入会</div>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="数据源" placement="top">
|
||||
<el-radio-group class="checkGroup" v-model="sourceTime" style="width: 100%">
|
||||
<el-row v-for="item in latelyUpdateTimes" style="margin-bottom: 10px">
|
||||
|
||||
@@ -24,13 +24,6 @@ layout("/layouts/platform.html"){
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="btn-group tool-button mt5 mr10">
|
||||
<el-checkbox-group v-model="pageForm.sendTypes" @change="doSearch">
|
||||
<el-checkbox-button label="msg" border>短信发送</el-checkbox-button>
|
||||
<el-checkbox-button label="WeChat" border>微信发送</el-checkbox-button>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="btn-group tool-button ">
|
||||
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
</div>
|
||||
@@ -77,7 +70,8 @@ layout("/layouts/platform.html"){
|
||||
<template scope="{row}">
|
||||
<el-button @click="doSend(row)" size="mini" type="success" v-if="!row.hold">发送</el-button>
|
||||
<el-button @click="openView(row)" size="mini" v-if="row.hold">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)" v-if="!row.hold">编辑</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)" v-if="!row.hold">编辑
|
||||
</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row.id)">删除</el-button>
|
||||
|
||||
</template>
|
||||
@@ -101,7 +95,7 @@ layout("/layouts/platform.html"){
|
||||
sendTypes: [],
|
||||
},
|
||||
tableColumns: [
|
||||
{prop: 'title', label: '活动名称'},
|
||||
{prop: 'title', label: '标题'},
|
||||
// {prop: 'module', label: '所属模块'},
|
||||
// {prop: 'teacherMeetingName', label: '所属教代会'},
|
||||
{prop: 'type', label: '人员范围', sortable: true},
|
||||
@@ -167,17 +161,21 @@ layout("/layouts/platform.html"){
|
||||
$.post(loc() + "/pageData", pageForm, (data) => {
|
||||
sublime.closeLoadingbar();
|
||||
this.tableLoading = false
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
data.data.list.forEach(v => {
|
||||
const a = JSON.parse(v.sendTypes).map(z => {
|
||||
if (z == "msg") {
|
||||
return "短信"
|
||||
} else {
|
||||
return "微信"
|
||||
}
|
||||
if (v.sendTypes) {
|
||||
const a = JSON.parse(v.sendTypes).map(z => {
|
||||
if (z === "DingTalk") {
|
||||
return "钉钉"
|
||||
} else {
|
||||
return "钉钉"
|
||||
}
|
||||
|
||||
})
|
||||
v.sendTypesName = a.toString()
|
||||
})
|
||||
v.sendTypesName = a.toString()
|
||||
} else {
|
||||
v.sendTypesName = "钉钉"
|
||||
}
|
||||
})
|
||||
this.tableData = data.data.list;
|
||||
this.pageForm.totalCount = data.data.totalCount;
|
||||
|
||||
@@ -43,7 +43,7 @@ layout("/layouts/platform.html"){
|
||||
</el-row>
|
||||
</template>
|
||||
<div>
|
||||
<msg-notify :hold="hold" :notify_id="notify_id" ref="a"
|
||||
<msg-notify :hold="hold" :notify_id="notify_id" ref="msgNotifyRef"
|
||||
v-model="msgData"></msg-notify>
|
||||
</div>
|
||||
|
||||
@@ -97,11 +97,6 @@ layout("/layouts/platform.html"){
|
||||
pageSize: 5,
|
||||
totalCount: 0,
|
||||
},
|
||||
formRules: {
|
||||
title: [{required: true, message: '请输入发送标题', trigger: ['blur', 'change']}],
|
||||
sendTypes: [{required: true, message: '请输入发送方式', trigger: ['blur', 'change']}],
|
||||
content: [{required: true, message: '请输入发送内容', trigger: ['blur', 'change']}],
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -155,6 +150,7 @@ layout("/layouts/platform.html"){
|
||||
this.selectDialogVisible = true
|
||||
},
|
||||
async doAdd(flag) {
|
||||
await this.$refs.msgNotifyRef.$refs.addform.validate()
|
||||
this.formData = this.msgData
|
||||
if (this.formData.sendMode === 'four' && !this.formData.existsLoginNameRedisKey) {
|
||||
this.$notify.warning('请先上传文件核对人员在选择发送!')
|
||||
|
||||
@@ -35,6 +35,9 @@ layout("/layouts/platform.html"){
|
||||
style="width: 80px;">
|
||||
<el-option label="姓名" value="u.username"></el-option>
|
||||
<el-option label="工号" value="u.loginname"></el-option>
|
||||
<el-option label="模块" value="mnu.apiModule"></el-option>
|
||||
<el-option label="标题" value="mnu.title"></el-option>
|
||||
<el-option label="内容" value="mnu.content"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
|
||||
@@ -57,12 +60,6 @@ layout("/layouts/platform.html"){
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="btn-group tool-button mt5 mr10">
|
||||
<el-checkbox-group v-model="pageForm.sendTypes" @change="doSearch">
|
||||
<el-checkbox-button label="msg" border>短信发送</el-checkbox-button>
|
||||
<el-checkbox-button label="WeChat" border>微信发送</el-checkbox-button>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="btn-group tool-button ">
|
||||
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
</div>
|
||||
@@ -112,10 +109,11 @@ layout("/layouts/platform.html"){
|
||||
{prop: 'username', label: '姓名'},
|
||||
{prop: 'loginname', label: '工号'},
|
||||
{prop: 'unitname', label: '单位', sortable: true},
|
||||
{prop: 'unionname', label: '工会', sortable: true},
|
||||
{prop: 'title', label: '所属活动'},
|
||||
{prop: 'title', label: '标题'},
|
||||
{prop: 'sendTypesName', label: '发送类型'},
|
||||
{prop: 'apiModule', label: '发送模块'},
|
||||
{prop: 'content', label: '消息内容'},
|
||||
{prop: 'link', label: '发送链接'},
|
||||
{prop: 'sendTime', label: '发送时间', sortable: true},
|
||||
]
|
||||
}
|
||||
@@ -145,17 +143,17 @@ layout("/layouts/platform.html"){
|
||||
sublime.closeLoadingbar();
|
||||
this.tableLoading = false
|
||||
if (data.code == 0) {
|
||||
console.log(data.data.list)
|
||||
data.data.list.forEach(v => {
|
||||
const a = JSON.parse(v.sendTypes).map(z => {
|
||||
if (z == "msg") {
|
||||
return "短信"
|
||||
} else {
|
||||
return "微信"
|
||||
}
|
||||
|
||||
})
|
||||
v.sendTypesName = a.toString()
|
||||
if (v.sendTypes) {
|
||||
const a = JSON.parse(v.sendTypes).map(z => {
|
||||
if (z === "DingTalk") {
|
||||
return "钉钉"
|
||||
}
|
||||
})
|
||||
v.sendTypesName = a.toString()
|
||||
} else {
|
||||
v.sendTypesName = "钉钉"
|
||||
}
|
||||
})
|
||||
this.tableData = data.data.list;
|
||||
this.pageForm.totalCount = data.data.totalCount;
|
||||
@@ -169,6 +167,7 @@ layout("/layouts/platform.html"){
|
||||
this.pageData();
|
||||
this.unions = await getUnions()
|
||||
this.flushUnits()
|
||||
await this.getTitleList(null)
|
||||
}
|
||||
|
||||
})
|
||||
@@ -177,4 +176,4 @@ layout("/layouts/platform.html"){
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
#-->
|
||||
|
||||
@@ -87,7 +87,7 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
|
||||
<template #view>
|
||||
<proposal-info ref="info"></proposal-info>
|
||||
<proposal-info ref="infoRef"></proposal-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
@@ -140,7 +140,7 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
components: {
|
||||
'guava': httpVueLoader('/components/plugins/Guava.vue'),
|
||||
'proposal-info': httpVueLoader('/components/proposal/ProposalInfo.vue?v=1.0.1'),
|
||||
'proposal-info': httpVueLoader('/components/proposal/ProposalInfo.vue?v=' + new Date().getTime()),
|
||||
'proposal-table': httpVueLoader('/components/proposal/ProposalTable.vue'),
|
||||
},
|
||||
methods: {
|
||||
@@ -192,7 +192,7 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.view()
|
||||
this.$refs.info.openView(row.id)
|
||||
this.$refs.infoRef.openView(row.id)
|
||||
},
|
||||
pageData() {
|
||||
sublime.showLoadingbar();
|
||||
|
||||
@@ -83,63 +83,45 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
|
||||
<template #edit>
|
||||
<proposal-info ref="audit"></proposal-info>
|
||||
|
||||
<el-form style="margin-top: 20px" :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<!-- <vi-title :title="proTableData.length > 1 ? '并案信息' : '提案信息'"></vi-title>-->
|
||||
<!-- <el-form-item>-->
|
||||
|
||||
<!-- <el-table :data="proTableData" tooltip-effect="dark"-->
|
||||
<!-- style="width: 100%">-->
|
||||
<!-- <el-table-column align="left" header-align="left" prop="proposalCode"-->
|
||||
<!-- label="提案编号"></el-table-column>-->
|
||||
<!-- <el-table-column align="left" header-align="left" prop="username"-->
|
||||
<!-- label="提案人"-->
|
||||
<!-- show-overflow-tooltip></el-table-column>-->
|
||||
<!-- <el-table-column align="left" header-align="left" prop="proposalName" label="提案名称"-->
|
||||
<!-- show-overflow-tooltip>-->
|
||||
<!-- <template slot-scope="{row}">-->
|
||||
<!-- <span @click="openView(row)"-->
|
||||
<!-- style="color: #236eb4; cursor: pointer; text-decoration: underline">{{row.proposalName}}</span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
<!-- </el-form-item>-->
|
||||
<vi-title title="分管校领导审批信息"></vi-title>
|
||||
<div style="text-align: center;margin-top: -40px;"
|
||||
v-if="formData.auditUnderTakeList && formData.auditUnderTakeList.length>1">
|
||||
<span class="text-danger">温馨提醒:该提案的承办单位【{{formData.auditUnderTakeName}}】是由您来分管的,只需要审批一次即可。</span>
|
||||
</div>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="审核人">
|
||||
<el-input v-model="formData.username" readonly></el-input>
|
||||
<proposal-info ref="audit" label="分管校领导审批" handle>
|
||||
<template #handle>
|
||||
<el-form style="margin-top: 20px" :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<div style="text-align: center;margin-top: -40px;"
|
||||
v-if="formData.auditUnderTakeList && formData.auditUnderTakeList.length>1">
|
||||
<span class="text-danger">温馨提醒:该提案的承办单位【{{formData.auditUnderTakeName}}】是由您来分管的,只需要审批一次即可。</span>
|
||||
</div>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="审核人">
|
||||
<el-input v-model="formData.username" readonly></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="auditTime" label="审核时间">
|
||||
<el-input v-model="formData.auditTime" readonly></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="审批意见" prop="opinion">
|
||||
<el-input type="textarea" v-model="formData.opinion" rows="4" maxlength="1000"
|
||||
placeholder="请填写您的审批意见"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="auditTime" label="审核时间">
|
||||
<el-input v-model="formData.auditTime" readonly></el-input>
|
||||
<el-form-item v-if="isSign()" prop="sign" label="签  字">
|
||||
<sign prefix="proposal" :qz.sync="formData.sign"></sign>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="审批意见" prop="opinion">
|
||||
<el-input type="textarea" v-model="formData.opinion" rows="4" maxlength="1000"
|
||||
placeholder="请填写您的审批意见"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="isSign()" prop="sign" label="签  字">
|
||||
<sign prefix="proposal" :qz.sync="formData.sign"></sign>
|
||||
</el-form-item>
|
||||
|
||||
<el-row style="margin: 40px 0;text-align: right">
|
||||
<el-button @click="$refs.guava.index()">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="submitDisabled" @click="doAudit(true)">
|
||||
提交
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row style="margin: 40px 0;text-align: right">
|
||||
<el-button @click="$refs.guava.index()">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="submitDisabled" @click="doAudit(true)">
|
||||
提交
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
</el-form>
|
||||
</template>
|
||||
</proposal-info>
|
||||
</template>
|
||||
|
||||
<template #view>
|
||||
|
||||
@@ -133,7 +133,6 @@ layout("/layouts/platform.html"){
|
||||
<proposal-info ref="audit" label="提案工作组立案" handle>
|
||||
<template #handle>
|
||||
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<vi-title title="审核信息"></vi-title>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="审核人">
|
||||
|
||||
@@ -109,7 +109,6 @@ layout("/layouts/platform.html"){
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<vi-title title="审核信息"></vi-title>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="审核人">
|
||||
|
||||
@@ -64,7 +64,6 @@ layout("/layouts/platform.html"){
|
||||
<proposal-info ref="audit" label="团长审核" handle>
|
||||
<template #handle>
|
||||
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<vi-title title="审核信息"></vi-title>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="审核人">
|
||||
|
||||
@@ -79,7 +79,6 @@ layout("/layouts/platform.html"){
|
||||
<proposal-info ref="audit" label="反馈评价" handle>
|
||||
<template #handle>
|
||||
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="150px">
|
||||
<vi-title title="反馈评价信息"></vi-title>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="反馈人">
|
||||
|
||||
@@ -119,7 +119,6 @@ layout("/layouts/platform.html"){
|
||||
<proposal-info ref="audit" label="承办单位答复" handle>
|
||||
<template #handle>
|
||||
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<vi-title title="承办单位答复"></vi-title>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="username" label="答复单位">
|
||||
|
||||
@@ -73,7 +73,6 @@ layout("/layouts/platform.html"){
|
||||
<proposal-info ref="audit" label="附议提案" handle>
|
||||
<template #handle>
|
||||
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<vi-title title="附议信息"></vi-title>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="username" label="附议人">
|
||||
|
||||
@@ -91,7 +91,6 @@ layout("/layouts/platform.html"){
|
||||
<proposal-info ref="audit" label="承办单位提出意见" handle>
|
||||
<template #handle>
|
||||
<el-form :model="formData" ref="auditForm" :rules="formRules" label-width="120px">
|
||||
<vi-title title="审核信息"></vi-title>
|
||||
<el-form-item label="承办单位">
|
||||
<el-input v-model="formData.underTakeName" readonly></el-input>
|
||||
</el-form-item>
|
||||
|
||||
Reference in New Issue
Block a user