first commit

This commit is contained in:
2026-01-08 14:58:16 +08:00
commit 556e5d64aa
9575 changed files with 1621095 additions and 0 deletions
@@ -0,0 +1,240 @@
const PROPOSAL_INFO = {
name: "ProposalInfo",
template: /*language=HTML*/ `
<van-action-sheet v-model="visible" title="查看详情">
<div class="detail-container">
<van-cell-group title="基本信息">
<van-cell title="提案名称">
<div style="font-weight:bold;">
{{ viewData.name }}
</div>
</van-cell>
<van-cell title="提案编号">{{ viewData.code }}</van-cell>
<van-cell title="提案人">{{ viewData.createUserName }}</van-cell>
<van-cell title="提案时间">{{ viewData.createTime }}</van-cell>
<van-cell title="教代会届次">{{ viewData.fullName }}</van-cell>
<van-cell title="提案人单位">{{ viewData.unitName }}</van-cell>
<van-cell :title="viewData.mannerCode!=='W03'?'代表团名称':'委员会名称'">
{{ viewData.mannerCode !== 'W03' ? viewData.delegationName : viewData.committeeName }}
</van-cell>
<van-cell title="提案类别">
{{viewData.typeName}}
</van-cell>
<van-cell title="建议承办单位">
{{viewData.suggestUnits}}
</van-cell>
<van-cell title="立案结果">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="viewData.caseFilingResult"></dict-tag>
</van-cell>
<!--<van-cell title="调研情况" class="direction-column-cell">
<div v-html="viewData.researchFindings"></div>
</van-cell>-->
<van-cell title="提案案由" class="direction-column-cell">
<div v-html="viewData.brief"></div>
</van-cell>
<van-cell title="建议措施" class="direction-column-cell">
<div v-html="viewData.measures"></div>
</van-cell>
<van-cell title="附件" class="direction-column-cell">
<file-preview :files="viewData.files" complete_result></file-preview>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <div slot="label">-->
<!-- <van-image :src="viewData.signature"-->
<!-- style="width: 100%;height: 150px;border: 1px dashed"></van-image>-->
<!-- </div>-->
<!-- </van-cell>-->
</van-cell-group>
<!--并案信息-->
<van-cell-group title="并案信息" v-if="viewData.merges && viewData.merges.length">
<van-cell v-for="(merge, index) in viewData.merges" :key="merge.id"
:title="(index + 1) + '. ' + merge.name"
:label="'提案编号:' + merge.code + ' | 提案人:' + merge.createUserName + ' | 类别:' + merge.typeName + ' | 代表团:' + merge.delegationName"
is-link
@click="openView(merge)">
</van-cell>
</van-cell-group>
<!--委员会成员意见-->
<template v-if="viewData.commissionerOpinions && viewData.commissionerOpinions.length">
<div class="process-title" style="margin-bottom: 0!important;">
委员会成员意见
</div>
<div v-for="(opinion, index) in viewData.commissionerOpinions" :key="index"
style="margin-bottom: 16px;">
<van-cell :title="opinion.commissionerName + '(' + opinion.commissionerLoginName + ')'"
class="direction-column-cell">
</van-cell>
<van-cell title="立案结果">
<div style="display: flex;justify-content: end;">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="opinion.caseFilingResult"></dict-tag>
<template v-if="opinion.caseFilingType">
(
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
:value="opinion.caseFilingType"></dict-tag>
)
</template>
</div>
</van-cell>
<van-cell title="意见" v-if="opinion.opinionText">
<div>{{ opinion.opinionText }}</div>
</van-cell>
<van-cell title="时间" v-if="opinion.opinionTime">
{{ opinion.opinionTime }}
</van-cell>
</div>
</template>
<template v-for="task in doneTasks">
<van-cell-group :title="task.displayName" v-if="task.ext.isFirstTaskNode">
<van-cell title="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})
</van-cell>
<van-cell title="申请时间">{{ task.finishTime }}</van-cell>
<van-cell title="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</van-cell>
</van-cell-group>
<!--邀请附议人-->
<van-cell-group :title="task.displayName"
v-else-if="task.taskName === 'invite'">
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
</van-cell>
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
<van-cell title="附议人" v-if="task.taskName === 'invite'"
class="direction-column-cell">
<el-table :data="task?.taskFormData?.seconder">
<el-table-column label="姓名" prop="userName"></el-table-column>
<el-table-column label="工号" prop="loginName"></el-table-column>
<el-table-column label="性别" prop="sex"></el-table-column>
<el-table-column label="单位" prop="unitName" show-overflow-tooltip></el-table-column>
<el-table-column label="分工会" prop="unionName"
show-overflow-tooltip></el-table-column>
<el-table-column label="代表团" prop="delegationName"
show-overflow-tooltip></el-table-column>
</el-table>
</van-cell>
</van-cell-group>
<!--提案委员会立案-->
<van-cell-group :title="task.displayName"
v-else-if="task.taskName === 'committee'">
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
</van-cell>
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
<van-cell title="立案结果">
<div style="display: flex;justify-content: center">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="task.ext.tf_caseFilingResult"></dict-tag>
<template v-if="task.ext.tf_caseFilingType">
(
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
:value="task.ext.tf_caseFilingType"></dict-tag>
)
</template>
</div>
</van-cell>
<van-cell title="主办单位">{{ task.ext.tf_masterUnitName }}</van-cell>
<van-cell title="协办单位">{{ task?.ext?.tf_slaveUnitNameStr }}</van-cell>
</van-cell-group>
<van-cell-group :title="task.displayName" v-else>
<van-cell title="办理单位" v-if="['master_reply','slave_reply'].includes(task.taskName)">
{{task.ext.underTakeName}}
</van-cell>
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
</van-cell>
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
<van-cell title="办理评价" v-if="['feedback'].includes(task.taskName)">
<dict-tag :options="dict.type.PROPOSAL_FEEDBACK"
:value="task.ext.tf_feedback"></dict-tag>
</van-cell>
<van-cell title="办理结果" v-else>
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</van-cell>
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
<div v-html="task.taskFormData.tf_opinion"></div>
</van-cell>
</van-cell-group>
</template>
</div>
<slot></slot>
</van-action-sheet>
`,
dicts: ["PROPOSAL_TYPE", "PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE", "PROCESS_TASK_SUBMIT_TYPE", "PROPOSAL_FEEDBACK"],
data() {
return {
visible:false,
viewData: {},
doneTasks: [],
row: null,
originalRow: null, // 用于保存原始数据,支持返回功能
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
this.getDoneTasks()
},
// 关闭
onClose(){
this.visible = false
},
// 获取申请信息
getInfo() {
this.$axios.post("/platform/proposal/common/proposalInfo", {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
// 查看提案
openView(row) {
// 如果传入的是并案对象,则打开新的详情页面
if (row && typeof row === 'object' && row.id) {
// 创建一个新的提案详情组件实例来显示并案详情
this.$nextTick(() => {
// 可以通过事件总线或者其他方式来打开新的详情页面
// 这里暂时使用简单的方式,直接在当前组件中显示
const currentRow = this.row;
this.row = row;
this.getInfo();
// 保存原来的数据,以便返回时恢复
this.originalRow = currentRow;
})
} else {
// 原有的逻辑,通过ID查看
this.$nextTick(() => {
if (this.$refs.infoDialogRef) {
this.$refs.infoDialogRef.onOpen(row)
}
})
}
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
}
};
@@ -0,0 +1,202 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="提案查询" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" @change="sessionChange"></van-dropdown-item>
<van-dropdown-item
v-if="pageForm.sessionId"
v-model="pageForm.delegationId"
:options="delegationOptions"
@change="doSearch"
></van-dropdown-item>
<!-- <van-dropdown-item-->
<!-- v-model="pageForm.unionId"-->
<!-- :options="unionOptions"-->
<!-- @change="pageForm.unitId=null;listUnit();doSearch()"-->
<!-- ></van-dropdown-item>-->
<!-- <van-dropdown-item v-model="pageForm.unitId" :options="unitOptions" @change="doSearch"></van-dropdown-item>-->
<!-- <van-dropdown-item v-model="pageForm.undertakeUnitId" :options="underTakeOptions" @change="doSearch"></van-dropdown-item>-->
<!-- <van-dropdown-item ref="moreDropItem" title="筛选" multiple :options="moreOptions" @change="doSearch"></van-dropdown-item>-->
</van-dropdown-menu>
</van-sticky>
<div>
<van-list v-if="tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="没有更多了" @load="pageData">
<div class="table-list">
<div class="table-card" v-for="row in tableData" :key="row.id+row.processTaskId">
<van-cell>
<template slot="title">
<div class="flex-align">
<span class="font-size3 bold">{{row.name}}</span>
</div>
</template>
</van-cell>
<van-cell title="提案编号" :value="row.code"></van-cell>
<van-cell title="提案人" :value="row.createUserName"></van-cell>
<van-cell title="提案类型" :value="row.typeId"></van-cell>
<van-cell title="届次" :value="row.sessionName"></van-cell>
<van-cell title="代表团" :value="row.delegationName"></van-cell>
<van-cell title="当前节点" :value="row.processInstanceNodeName"></van-cell>
<van-cell class="table-card-footer">
<van-button size="small" @click="openView(row)">查看</van-button>
</van-cell>
</div>
</div>
</van-list>
<van-empty v-else image="/assets/platform/plugins/vant-green/images/nodata/nodata.png" description="暂无数据"></van-empty>
</div>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="提案信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
unionId: null,
unitId: null,
delegationId: null
},
tableData: [],
tableLoading: false,
tableFinished: false,
sessionOptions: [],
delegationOptions: [
{
text: "全部代表团",
value: null
}
],
underTakeOptions: [],
unionOptions: [],
unitOptions: [],
moreOptions: {},
id: "",
formValidSuccess: false,
infoShow: false
}
},
components: {
info: H5_PROPOSAL_INFO_COMPONENT
},
methods: {
historyBack,
sessionChange(val) {
this.pageForm.delegationId = null
if (this.pageForm.sessionId) {
this.listDelegation()
} else {
this.delegationOptions = [
{
text: "全部代表团",
value: null
}
]
}
this.doSearch()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({ text: v.fullName, value: v.id })))
}
})
},
listDelegation() {
this.$axios.post("/platform/proposal/common/listDelegation", { sessionId: this.pageForm.sessionId }).then((res) => {
if (res.code === 0) {
this.delegationOptions = [
{
text: "全部代表团",
value: null
}
].concat(res.data.map((v) => ({ text: v.name, value: v.id })))
}
})
},
listUnderTake() {
this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => {
if (res.code === 0) {
this.underTakeOptions = res.data
}
})
},
listUnion() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
},
listUnit() {
this.$businessTool.listUnit(this.pageForm.unionId).then((res) => (this.unitOptions = res))
},
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
pageData() {
this.tableLoading = true
this.$axios
.post("/platform/proposal/query/comprehensive/pageData", {
pageForm: JSON.stringify(this.pageForm)
})
.then((resp) => {
this.tableData = this.tableData.concat(resp.data.list)
this.pageForm.totalCount = resp.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
} else {
this.pageForm.pageNumber++
}
this.tableLoading = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
}
},
created() {
this.pageData()
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,232 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="委员会成员意见" placeholder
fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/commissioner/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{row.taskName}}</table-column>
<table-column label="委员意见">
<van-tag type="primary">立案:{{row.CONFIRM_FILING_COUNT}}</van-tag>
<van-tag type="warning">建议:{{row.SUGGESTION_COUNT}}</van-tag>
<van-tag>不予立案:{{row.NOT_COUNT}}</van-tag>
</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="!row.pcoId" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>审核</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">提案委员会成员意见</div>
<van-form ref="formRef">
<van-field
v-model="formData.caseFilingResultName"
name="caseFilingResultName"
label="立案结果"
placeholder="请选择立案结果"
:rules="[{ required: true, message: '请选择立案结果' }]"
required
is-link
@click="showCaseFilingResultPicker = true"
></van-field>
<van-popup v-model="showCaseFilingResultPicker" position="bottom">
<van-picker
show-toolbar
:columns="dict.type.PROPOSAL_CASE_FILING_RESULT.map(item => ({text: item.label, value: item.code}))"
@confirm="onCaseFilingResultConfirm"
@cancel="showCaseFilingResultPicker = false"
></van-picker>
</van-popup>
<template v-if="['CONFIRM_FILING'].includes(formData.caseFilingResult)">
<van-field
v-model="formData.caseFilingTypeName"
name="caseFilingTypeName"
label="立案结果"
placeholder="请选择立案类型"
:rules="[{ required: true, message: '请选择立案类型' }]"
required
is-link
@click="showCaseFilingTypePicker = true"
></van-field>
<van-popup v-model="showCaseFilingTypePicker" position="bottom">
<van-picker
show-toolbar
:columns="dict.type.PROPOSAL_CASE_FILING_TYPE.map(item => ({text: item.label, value: item.code}))"
@confirm="onCaseFilingTypeConfirm"
@cancel="showCaseFilingTypePicker = false"
></van-picker>
</van-popup>
</template>
<van-field
v-model="formData.opinion"
name="opinion"
label="审批意见"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
required
maxlength="100"
show-word-limit
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button block @click="$refs.proposalInfoRef.onClose()">取消</van-button>
<van-button type="primary" block @click="doSubmit">提交</van-button>
</div>
</div>
</proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
store,
dicts: ["PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE"],
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false,
showCaseFilingResultPicker: false,
showCaseFilingTypePicker: false
}
},
components: {
"proposal-info": PROPOSAL_INFO
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
// 确定立案类型
onCaseFilingResultConfirm(value) {
this.$set(this.formData, "caseFilingResultName", value.text)
this.$set(this.formData, "caseFilingResult", value.value)
this.showCaseFilingResultPicker = false
},
// 确定立案类型
onCaseFilingTypeConfirm(value) {
this.$set(this.formData, "caseFilingTypeName", value.text)
this.$set(this.formData, "caseFilingType", value.value)
this.showCaseFilingTypePicker = false
},
onApproval(row) {
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
proposalId: row.id,
caseFilingResult: null,
caseFilingType: null,
opinion: null
}
},
async doSubmit() {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: '提示',
message: "您确定要提交吗?",
}).then(() => {
this.$axios.post('/platform/proposal/commissioner/doApproval', this.formData).then(res => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,190 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/delegation/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>审核</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
<i class="fa fa-reply"></i>
<span>撤回</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">{{formData.taskName}}</div>
<van-form ref="formRef">
<van-field
v-model="formData.tf_opinion"
name="tf_opinion"
label="审批意见"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
required
maxlength="100"
show-word-limit
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
<van-button type="danger" block @click="handleTaskAction(2)">不同意</van-button>
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
</div>
</div>
</proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false
}
},
components: {
"proposal-info": PROPOSAL_INFO
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
onApproval(row) {
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
},
async handleTaskAction(val) {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
onRevoke(row){
this.$dialog.confirm({
title: "提示",
message: "您确定要撤回吗?"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,267 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="反馈评价" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已评价" name="1"></van-tab>
<van-tab title="未评价" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/feedbackEvaluation/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>评价</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
<i class="fa fa-reply"></i>
<span>撤回</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">{{formData.taskName}}</div>
<van-form ref="formRef">
<van-field
v-model="formData.tf_feedback_name"
name="tf_feedback_name"
label="满意度"
placeholder="请选择满意度"
:rules="[{ required: true, message: '请选择满意度' }]"
required
is-link
@click="showFeedBackPicker = true"
></van-field>
<van-popup v-model="showFeedBackPicker" position="bottom">
<van-picker
show-toolbar
:columns="dict.type.PROPOSAL_FEEDBACK.map(item => ({text: item.label, value: item.code}))"
@confirm="onFeedBackConfirm"
@cancel="showFeedBackPicker = false"
></van-picker>
</van-popup>
<van-field
v-model="formData.tf_opinion"
name="tf_opinion"
label="审批意见"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
required
maxlength="100"
show-word-limit
></van-field>
<template v-if="['SATISFIED','FAIRLY_SATISFIED'].includes(formData.tf_feedback)">
<van-field
v-model="formData.tf_address"
name="tf_address"
label="通讯地址"
placeholder="请输入通讯地址"
:rules="[{ required: true, message: '请输入通讯地址' }]"
required
show-word-limit
></van-field>
<!--联系电话-->
<van-field
v-model="formData.tf_phone"
name="tf_phone"
label="联系电话"
placeholder="请输入联系电话"
:rules="[{ required: true, message: '请输入联系电话' }]"
required
show-word-limit
></van-field>
<!--邮政编码-->
<van-field
v-model="formData.tf_postcode"
name="tf_postcode"
label="邮政编码"
placeholder="请输入邮政编码"
:rules="[{ required: true, message: '请输入邮政编码' }]"
required
show-word-limit
></van-field>
</template>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click="$refs.proposalInfoRef.onClose()">取消</van-button>
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
</div>
</div>
</proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
dicts: ["PROPOSAL_FEEDBACK"],
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false,
showFeedBackPicker: false
}
},
components: {
"proposal-info": PROPOSAL_INFO
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
onApproval(row) {
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName,
instanceId: row.instanceId
}
},
onFeedBackConfirm({value, text}) {
this.formData.tf_feedback_name = text
this.formData.tf_feedback = value
this.showFeedBackPicker = false
},
async handleTaskAction(val) {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(async () => {
debugger
const formData = {
...this.formData,
submitType: val
}
// 不满意
if (this.formData.tf_feedback === 'DISSATISFIED') {
const caseInfo = await this.getCaseInfo(this.formData.instanceId)
formData.tf_masterUnitId = caseInfo.tf_masterUnitId
}
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify(formData)
}).then((res) => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
// 获取立案信息
async getCaseInfo(instId) {
const {
data,
code
} = await this.$axios.post('/platform/proposal/feedbackEvaluation/caseInfo', {instId})
if (code === 0) {
return data
}
},
onRevoke(row) {
this.$dialog.confirm({
title: "提示",
message: "您确定要撤回吗?"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,171 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的提案" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入提案名称搜索"
v-model="pageForm.name"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="doSearch"
v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
</van-sticky>
<table-list api="/platform/proposal/mine/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{ (row.startTaskId) ? row.taskName : '待提交' }}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskKey === 'startTask' || !row.instanceId"
@click="onEdit(row)">
<i class="fa fa-edit"></i>
<span>编辑</span>
</div>
<div class="action-btn"
v-if="row.taskKey === 'invite' || row.taskKey === 'second'"
@click="onInvite(row)">
<i class="fa fa-user-plus"></i>
<span>邀请附议人</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
<i class="fa fa-undo"></i>
<span>撤回</span>
</div>
<div class="action-btn delete" v-if="row.taskKey === 'startTask' || !row.instanceId"
@click="onDelete(row)">
<i class="fa fa-trash"></i>
<span>删除</span>
</div>
</template>
</table-list>
<invite-seconder @refresh="doSearch" ref="inviteSeconderRef"></invite-seconder>
<proposal-info ref="proposalInfoRef"></proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
<!--#include("inviteSeconder.js"){}#-->
const vue = new Vue({
el: "#app",
store,
components: {
"invite-seconder": PROPOSAL_INVITE_SECONDER_COMPONENT,
"proposal-info": PROPOSAL_INFO
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null
},
sessionOptions: [],
infoShow: false
}
},
methods: {
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{text: "全部届次", value: null}])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
onEdit(row) {
this.$pjaxReplace("/platform/proposal/write/h5?bizId=" + row.id + "&taskId=" + (row.startTaskId || ''))
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
onRevoke(row) {
this.$dialog
.confirm({
title: "提示",
message: "您确定要撤销申请吗?"
})
.then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if(res.code===0){
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
onDelete(id) {
this.$dialog
.confirm({
title: "提示",
message: "您确定要删除吗?"
})
.then(() => {
this.$axios.post("/platform/proposal/mine/delete", {id}).then((resp) => {
if (resp.code === 0) {
this.$toast.success(resp.msg)
this.doSearch()
}
})
})
},
onInvite(row) {
this.$axios.post("/platform/proposal/mine/inviteCheck", {id: row.id}).then((res) => {
if (res.code === 0) {
this.$refs.inviteSeconderRef.onOpen(row)
}
})
},
onReady() {
this.listSession()
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,158 @@
const PROPOSAL_INVITE_SECONDER_COMPONENT = {
template: `
<van-action-sheet v-model="visible" title="邀请附议人" class="height100">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
placeholder="请输入工号或者姓名查询"
@search="doSearch"
></van-search>
<van-tabs v-model="isInvite" @click="isInviteClick">
<van-tab title="已邀请" name="1"></van-tab>
<van-tab title="可邀请" name="0"></van-tab>
</van-tabs>
<van-checkbox-group v-model="tableSelection" v-if="tableData && tableData.length>0">
<van-cell-group >
<van-cell
v-for="(item, index) in tableData"
clickable
:key="item.loginName"
@click="tableRowToggle(index)"
>
<span slot="title">
{{item.userName}}
({{item.loginName}})
</span>
<span slot="label" class="font-size0 van-color-text-assist">
{{item.unitName}}
</span>
<van-checkbox
:name="item"
:ref="'checkboxes'+item.loginName"
slot="right-icon"
v-if="!pageForm.isInvite"></van-checkbox>
</van-cell>
</van-cell-group>
<div class="p10">
<van-pagination
v-model="pageForm.pageNumber"
:total-items="pageForm.totalCount"
:items-per-page="pageForm.pageSize"
@change="pageData"
></van-pagination>
<van-button @click="invite" type="primary" block :disabled="pageForm.isInvite" class="mt10">邀请</van-button>
</div>
</van-checkbox-group>
<van-empty v-else :figure="2"></van-empty>
</van-action-sheet>
`,
data() {
return {
visible: false,
secondedNum: 0,
record: {},
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 5,
totalCount: 0,
isInvite: false,
searchKeyword: null
},
config: {},
isInvite: "0",
tableSelection: []
}
},
methods: {
async onOpen(record) {
this.visible = true
this.record = record
await this.getConfig()
this.pageData()
},
detail(id) {
},
invite() {
if (this.tableSelection.length === 0) {
this.$toast("请先选择附议人后在点击邀请")
return
}
const loginNames = [...new Set(this.tableSelection.map((s) => s.loginName))]
const userName = [...new Set(this.tableSelection.map((s) => s.userName))]
console.log(this.tableSelection)
this.$dialog.confirm({
title: '提示',
message: "您确定要邀请" + userName.join("、") + "代表附议吗?",
}).then(() => {
this.$axios.post("/platform/proposal/mine/inviteSeconder", {
proposalId: this.record.id,
seconders: JSON.stringify(loginNames)
}).then((res) => {
if (res.code === 0) {
this.pageData()
this.$toast.success(res.msg)
this.tableSelection = []
// this.visible = false
this.$emit("refresh", null)
}
})
}).catch(() => {
})
},
pageData() {
this.$axios.post("/platform/proposal/mine/listSeconder", {
...this.pageForm,
sessionId: this.record.sessionId,
proposalId: this.record.id
})
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
this.echoCheckBox()
}
})
},
// 翻页回显勾选
echoCheckBox() {
this.$nextTick(() => {
this.tableData.forEach((item) => {
const checkboxRef = this.$refs['checkboxes' + item.loginName]
if (checkboxRef && this.tableSelection.map((s) => s.loginName).includes(item.loginName)) {
checkboxRef[0].toggle()
}
})
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
isInviteClick(index, title) {
this.pageForm.isInvite = index === "1"
this.doSearch()
},
tableRowToggle(index) {
console.log(index)
},
async getConfig() {
const {code, data} = await this.$axios.post("/platform/proposal/common/config")
if (code === 0) {
this.config = data
}
}
}
}
@@ -0,0 +1,197 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="分管校领导审批" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/schoolLeaderApproval/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>审核</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
<i class="fa fa-reply"></i>
<span>撤回</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">{{formData.taskName}}</div>
<van-form ref="formRef">
<van-field
v-model="formData.tf_opinion"
name="tf_opinion"
label="审批意见"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
required
maxlength="100"
show-word-limit
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click="handleTaskAction('back')">退回答复</van-button>
<van-button type="primary" block @click="handleTaskAction('agree')">同意答复</van-button>
</div>
</div>
</proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false
}
},
components: {
"proposal-info": PROPOSAL_INFO
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
onApproval(row) {
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskKey: row.taskKey,
taskName: row.taskName,
proposalId: row.id
}
},
async handleTaskAction(val) {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(() => {
const formData = {
...this.formData,
tf_approval: val
}
delete formData.taskKey
delete formData.taskName
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify(formData)
}).then((res) => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
onRevoke(row){
this.$dialog.confirm({
title: "提示",
message: "您确定要撤回吗?"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,182 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="附议提案" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已附议" name="1"></van-tab>
<van-tab title="未附议" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/seconded/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>附议</span>
</div>
<!-- <div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">-->
<!-- <i class="fa fa-reply"></i>-->
<!-- <span>撤回</span>-->
<!-- </div>-->
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">{{formData.taskName}}</div>
<van-form ref="formRef">
<van-field
v-model="formData.tf_opinion"
name="tf_opinion"
label="审批意见"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
required
maxlength="100"
show-word-limit
></van-field>
<!-- <van-field label="签字" name="approvalSignature" v-model="formData.signature" required class="direction-column-field">-->
<!-- <h5-signature v-model="formData.approvalSignature" slot="input"></h5-signature>-->
<!-- </van-field>-->
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
</div>
</div>
</proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false,
rules: {
approvalSignature: [{required: true, message: "请签字"}]
}
}
},
components: {
"proposal-info": PROPOSAL_INFO
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
onApproval(row) {
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName,
tf_opinion: "同意该提案"
}
},
async handleTaskAction(val) {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,247 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<style scoped>
.van-button--small {
height: 26px;
}
</style>
<div id="app">
<van-nav-bar title="承办单位意见" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已反馈" name="1"></van-tab>
<van-tab title="未反馈" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/suggestion/pageData" :page_form.sync="pageForm" ref="tableListRef" title="name" @ready="onReady">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="建议承办单位"> {{ JSON.parse(row.suggestUnits)?.map(item => item).join('') || '' }}</table-column>
<table-column label="意见数">{{row.count}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" @click="openSuggestion(row)" v-if="pageForm.approval === true">
<i class="fa fa-eye"></i>
<span>查看意见</span>
</div>
<div class="action-btn" @click="onAudit(row)">
<i class="fa fa-edit"></i>
<span>反馈意见</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">承办单位意见</div>
<van-form ref="formRef">
<van-field
v-model="formData.result"
name="result"
label="承办意向"
placeholder="请选择承办意向"
:rules="[{ required: true, message: '必填' }]"
required
is-link
@click="showPicker = true"
></van-field>
<van-popup v-model="showPicker" position="bottom">
<van-picker
show-toolbar
:columns="dict.type.UNDERTAKE_SUGGESTION.map(item => item.code)"
@confirm="(val) => {formData.result = val; showPicker = false}"
@cancel="showPicker = false"
></van-picker>
</van-popup>
<van-field
v-model="formData.opinion"
name="opinion"
label="反馈意见"
placeholder="请输入反馈意见"
:rules="[{ required: true, message: '必填' }]"
required
show-word-limit
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button block @click="">取消</van-button>
<van-button type="primary" block @click="doSubmit">提交</van-button>
</div>
</div>
</proposal-info>
<van-action-sheet v-model="visible" title="意见信息">
<div class="detail-container">
<van-cell-group :key="index" v-for="item,index in suggestionList">
<template #title>
<div style="display: flex; justify-content: space-between; align-items: center">
<div>{{ '意见' + (index + 1) }}</div>
<div>
<van-button type="danger" @click="onDelete(item)" size="small">删除</van-button>
</div>
</div>
</template>
<van-cell title="反馈人">{{ item.userName }}</van-cell>
<van-cell title="所属单位">{{ item.unitName }}</van-cell>
<van-cell title="反馈时间">{{ item.time }}</van-cell>
<van-cell title="反馈结果">{{ item.result }}</van-cell>
<van-cell title="反馈意见" class="direction-column-cell">
<span v-html="item.opinion"></span>
</van-cell>
</van-cell-group>
</div>
</van-action-sheet>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
dicts: ["UNDERTAKE_SUGGESTION"],
components: {
"proposal-info": PROPOSAL_INFO
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false,
showPicker: false,
suggestionList: [],
visible: false,
}
},
methods: {
onDelete(row) {
this.$dialog.confirm({
title: "提示",
message: "您确定要删除吗?"
}).then(() => {
this.$axios.post('/platform/proposal/suggestion/delete', { id: row.id, })
.then(res => {
if(res.code === 0) {
this.$toast.success(res.msg)
this.visible = false
this.doSearch()
} else {
this.$message.fail(res.msg)
}
})
}).catch(() => {})
},
openSuggestion(row) {
this.$axios.post('/platform/proposal/suggestion/selectSuggestion', {
proposalId: row.id,
}).then(res => {
if(res.code === 0) {
this.suggestionList = res.data
if(this.suggestionList.length === 0) {
this.$toast('暂无意见数')
return
}
this.visible = true
} else {
this.$toast.fail(res.msg)
}
})
},
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onAudit(row) {
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
proposalId: row.id,
}
},
async doSubmit() {
try {
await this.$refs.formRef.validate()
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(() => {
this.$axios.post("/platform/proposal/suggestion/suggest", this.formData)
.then((res) => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {})
} catch (error) {}
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
}
},
})
</script>
<!--#
}
#-->
@@ -0,0 +1,289 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="承办单位答复" placeholder
fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/unitReply/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="承办单位">{{row.underTakeName}}{{row.underTakeIsMaster ? '主办' : '协办'}}
</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>答复</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
<i class="fa fa-reply"></i>
<span>撤回</span>
</div>
<!--承办单位领导、超级管理员才能转办-->
<div class="action-btn" v-if="!pageForm.approval && $auth.hasRoleOr('SYSADMIN,PROPOSAL_UNIT_LEADER')"
@click="openTransfer(row)">
<i class="fa fa-arrow-right"></i>
<span>转交</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">{{formData.taskName}}</div>
<van-form ref="formRef">
<van-field :value="formData.underTakeName"
label="承办单位"
readonly></van-field>
<van-field
v-model="formData.tf_implementStateName"
name="tf_implementStateName"
label="落实情况"
placeholder="请选择落实情况"
:rules="[{ required: true, message: '请选择落实情况' }]"
required
is-link
@click="showImplementPicker = true"
></van-field>
<van-popup v-model="showImplementPicker" position="bottom">
<van-picker
show-toolbar
:columns="dict.type.PROPOSAL_REPLY_IMPLEMENT.map(item => ({text: item.label, value: item.code}))"
@confirm="onImplementConfirm"
@cancel="showImplementPicker = false"
></van-picker>
</van-popup>
<van-field
v-model="formData.tf_opinion"
name="tf_opinion"
label="答复内容"
placeholder="请输入答复内容"
:rules="[{ required: true, message: '请填写答复内容' }]"
required
maxlength="100"
show-word-limit
></van-field>
<van-field
v-if="supportCandidate && formData.underTakeIsMaster"
v-model="formData.tf_nextNodeOperatorName"
name="tf_nextNodeOperatorName"
label="校领导"
placeholder="校领导"
:rules="[{ required: true, message: '请选择校领导' }]"
required
is-link
@click="showCandidatesPicker = true"
></van-field>
<van-popup v-model="showCandidatesPicker" position="bottom">
<van-picker
show-toolbar
:columns="candidates.map(item => ({text: item.userName, value: item.userId}))"
@confirm="onCandidatesConfirm"
@cancel="showCandidatesPicker = false"
></van-picker>
</van-popup>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button block @click="$refs.proposalInfoRef.onClose()">取消</van-button>
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
</div>
</div>
</proposal-info>
<transfer ref="transferRef"></transfer>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
<!--#include("transfer.js"){}#-->
const vue = new Vue({
el: "#app",
store,
dicts: ['PROPOSAL_REPLY_IMPLEMENT'],
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false,
showImplementPicker: false,
supportCandidate: false,
candidates: [],
showCandidatesPicker: false,
}
},
components: {
"proposal-info": PROPOSAL_INFO,
"transfer": transfer
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
onApproval(row) {
this.loadCandidates(row.taskId)
this.showApprovalForm = true
this.$refs.proposalInfoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskKey: row.taskKey,
taskName: row.taskName,
proposalId: row.id,
underTakeName: row.underTakeName,
underTakeIsMaster: row.underTakeIsMaster
}
},
// 加载候选人列表
loadCandidates(taskId) {
$.get("/flow/common/candidate", {taskId}).then((res) => {
if (res.code === 0) {
this.candidates = res.data.candidates
this.supportCandidate = res.data.support
}
})
},
onImplementConfirm(value) {
this.$set(this.formData, "tf_implementStateName", value.text)
this.$set(this.formData, "tf_implementState", value.value)
this.showImplementPicker = false
},
onCandidatesConfirm(value) {
this.$set(this.formData, "tf_nextNodeOperatorName", value.text)
this.$set(this.formData, "tf_nextNodeOperator", value.value)
this.showCandidatesPicker = false
},
async handleTaskAction(val) {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(() => {
delete this.formData.underTakeIsMaster
delete this.formData.underTakeName
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.proposalInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
onRevoke(row) {
this.$dialog.confirm({
title: "提示",
message: "您确定要撤回吗?"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
// 打开转办
openTransfer(row){
this.$refs.transferRef.openTransfer(row)
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,147 @@
const transfer = {
template: /*language=HTML*/ `
<van-action-sheet v-model="showTransferDialog" title="提案转办">
<div class="transfer-dialog">
<!-- 提案信息 -->
<div class="proposal-info-card">
<div class="info-item"><label>提案编号:</label><span>{{transferForm.code}}</span></div>
<div class="info-item"><label>提案名称:</label><span>{{transferForm.name}}</span></div>
<div class="info-item"><label>代表团:</label><span>{{transferForm.delegationName}}</span></div>
</div>
<!-- 用户选择 -->
<van-field v-model="searchKeyword" label="转交给" placeholder="搜索用户" required readonly @click="showUserList=true"></van-field>
<van-popup v-model="showUserList" position="bottom">
<van-search v-model="keyword" placeholder="搜索用户" @search="selectTransferUser(keyword)" @cancel="showUserList=false"></van-search>
<van-empty v-if="transferUserOptions.length === 0" class="empty-tip">请搜索需要转办的用户</van-empty>
<van-cell v-for="item in transferUserOptions" :key="item.id" :title="item.username" @click="selectUser(item)"></van-cell>
</van-popup>
<!-- 底部按钮 -->
<div class="button-group">
<van-button block plain @click="showTransferDialog = false" class="cancel-btn">取消</van-button>
<van-button block type="info" @click="handleTransfer" class="submit-btn">提交</van-button>
</div>
</div>
</van-action-sheet>
`,
data() {
return {
showTransferDialog: false,
transferForm: {},
transferUserOptions: [],
searchKeyword: '',
showUserList: false,
keyword: ''
}
},
methods: {
openTransfer(row) {
this.showTransferDialog = true
this.transferForm = { taskId: row.taskId, name: row.name, code: row.code, delegationName: row.delegationName }
this.searchKeyword = ''
},
selectUser(item) {
this.transferForm.userId = item.id
this.searchKeyword = item.username
this.showUserList = false
},
selectTransferUser(keyword) {
this.$axios.post("/platform/proposal/unitReply/selectViceUser", {keyword}).then(res => {
if (res.code === 0) this.transferUserOptions = res.data
})
},
// 转办
handleTransfer() {
if (!this.transferForm.userId) {
this.$toast('请选择转交用户')
return
}
const transferUserName = this.transferUserOptions.find(item => item.id === this.transferForm.userId)?.username
const name = this.transferForm.name
this.$dialog.confirm({
title: '提示',
message: `您确定要将` + name + `提案转交给` + transferUserName + `办理吗?`,
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.$axios.post('/platform/proposal/unitReply/transfer', this.transferForm).then(res => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.showTransferDialog = false
this.doSearch()
}
})
}).catch(() => {
// 取消操作
})
}
},
style: /*language=CSS*/ `
.transfer-dialog {
height: 100%;
background: #fff;
padding: 16px 16px 65px;
}
.proposal-info-card {
background: #f8f9fa;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
.proposal-info-content {
display: flex;
flex-direction: column;
gap: 12px;
}
.info-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item label {
font-size: 12px;
color: #969799;
}
.info-item span {
font-size: 14px;
color: #323233;
font-weight: 500;
}
.button-group {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 16px;
background: #fff;
border-top: 1px solid #ebedf0;
z-index: 10;
display: flex;
justify-content: space-between;
column-gap: 10px;
padding: 10px
}
.cancel-btn,
.submit-btn {
}
.empty-tip {
text-align: center;
padding: 50px 16px;
color: #969799;
font-size: 14px;
}
`
}
@@ -0,0 +1,111 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.name"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入提案名称搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
<!-- <van-tabs v-model="pageForm.approvalText"-->
<!-- @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">-->
<!-- <van-tab title="已审核" name="1"></van-tab>-->
<!-- <van-tab title="未审核" name="0"></van-tab>-->
<!-- </van-tabs>-->
</van-sticky>
<table-list api="/platform/proposal/vice/delegation/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
<table-column label="提案类别">{{row.typeName}}</table-column>
<table-column label="提案人">{{row.createUserName}}</table-column>
<table-column label="代表团">{{row.delegationName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
</template>
</table-list>
<proposal-info ref="proposalInfoRef"></proposal-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
const vue = new Vue({
el: "#app",
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
name: null,
sessionId: null,
approvalText: "0",
approval: false
},
sessionOptions: [],
formData: {},
showApprovalForm: false
}
},
components: {
"proposal-info": PROPOSAL_INFO
},
methods: {
onReady() {
this.listSession()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = [
{
text: "全部届次",
value: null
}
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.doSearch()
}
}
})
},
onView(row) {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,769 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<style>
.suggestion-unit-picker {
height: 100%;
display: flex;
flex-direction: column;
}
.picker-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
background-color: #f8f8f8;
border-bottom: 1px solid #eee;
}
.picker-cancel, .picker-confirm {
background: none;
border: none;
font-size: 16px;
color: #1989fa;
cursor: pointer;
}
.picker-cancel {
color: #969799;
}
.picker-title {
font-size: 16px;
font-weight: 500;
color: #323233;
}
.search-container {
padding: 12px 16px;
background-color: #fff;
border-bottom: 1px solid #eee;
}
.options-container {
flex: 1;
overflow-y: auto;
background-color: #fff;
}
.option-item {
display: flex;
align-items: center;
width: 100%;
}
.option-text {
margin-left: 12px;
flex: 1;
font-size: 14px;
color: #323233;
}
.van-checkbox {
margin-right: 0;
}
.van-cell {
padding: 12px 16px;
}
.van-cell:active {
background-color: #f2f3f5;
}
.notice-dialog-content {
max-width: 100%;
width: 100%;
padding: 0 16px; /* 左右留白 */
box-sizing: border-box;
}
.notice-dialog-content p {
width: 100% !important;
max-width: 100% !important;
text-indent: 2em; /* 中文首行缩进更规范 */
}
</style>
<div id="app" v-cloak>
<van-nav-bar title="撰写提案" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed z-index="999"
class="custom-nav"></van-nav-bar>
<div class="form-container">
<van-form ref="formRef">
<!-- 基本信息 -->
<van-cell-group title="基本信息">
<van-field
v-model="formData.createUserName"
label="代表姓名"
readonly
:rules="[{ required: true, message: '请填写提案人' }]"
></van-field>
<van-field
v-model="formData.createTime"
label="提案时间"
readonly
:rules="[{ required: true, message: '请填写提案时间' }]"
></van-field>
<van-field
v-model="formData.sessionName"
is-link
readonly
name="sessionName"
label="所属教代会"
placeholder="请选择所属教代会"
@click="showSessionPicker = true"
:rules="[{ required: true, message: '请选择所属教代会' }]"
></van-field>
<van-popup v-model="showSessionPicker" position="bottom">
<van-picker
show-toolbar
:columns="sessionOptions.map(item => ({text: item.fullName, value: item.id}))"
@confirm="onSessionConfirm"
@cancel="showSessionPicker = false"
></van-picker>
</van-popup>
<van-field
v-model="formData.delegationName"
label="所属代表团"
readonly
:rules="[{ required: true, message: '请选择所属代表团' }]"
></van-field>
<van-field
v-if="formData.mannerCode=='W03'"
v-model="formData.committeeName"
is-link
readonly
name="committeeName"
label="所属委员会"
placeholder="请选择所属委员会"
@click="showCommitteePicker = true"
:rules="[{ required: true, message: '请选择所属委员会' }]"
></van-field>
<van-popup v-model="showCommitteePicker" position="bottom">
<van-picker
show-toolbar
:columns="committeeOptions.map(item => ({text: item.name, value: item.id}))"
@confirm="onCommitteeConfirm"
@cancel="showCommitteePicker = false"
></van-picker>
</van-popup>
<van-field
v-model="formData.unitName"
name="mobile"
label="单位"
readonly
:rules="[{ required: true, message: '请填写单位' }]"
></van-field>
<van-field
v-model="formData.mobile"
label="联系电话"
type="tel"
placeholder="请输入联系电话"
:rules="[{ required: true, message: '请填写联系电话' }]"
></van-field>
</van-cell-group>
<van-cell-group title="提案信息" class="form-group">
<van-field
v-model="formData.name"
name="name"
label="提案名称"
placeholder="请输入提案名称"
:rules="[{ required: true, message: '请填写提案名称' }]"
required
maxlength="100"
show-word-limit
></van-field>
<van-field
v-model="formData.sourceName"
is-link
readonly
name="提案方式"
label="提案方式"
placeholder="请选择提案方式"
@click="showSourcePicker = true"
:rules="[{ required: true, message: '请选择提案方式' }]"
required
></van-field>
<van-popup v-model="showSourcePicker" position="bottom">
<van-picker
show-toolbar
:columns="sourceOptions.map(item => ({text: item.name, value: item.code}))"
@confirm="onSourceConfirm"
@cancel="showSourcePicker = false"
></van-picker>
</van-popup>
<van-field
v-model="formData.typeName"
is-link
readonly
name="typeName"
label="提案类别"
placeholder="请选择提案类别"
@click="showTypePicker = true"
:rules="[{ required: true, message: '请选择提案类别' }]"
required
></van-field>
<van-popup v-model="showTypePicker" position="bottom">
<van-picker
show-toolbar
:columns="typeOptions.map(item => ({text: item.name, value: item.id}))"
@confirm="onTypeConfirm"
@cancel="showTypePicker = false"
></van-picker>
</van-popup>
<van-field
:value="formData.suggestUnits.length > 0 ? formData.suggestUnits.join(', ') : ''"
is-link
readonly
name="suggestUnits"
label="建议承办单位"
placeholder="请选择建议承办单位"
@click="showSuggestionUnitPicker = true"
:rules="[{ required: true, message: '请选择建议承办单位' }]"
required
></van-field>
<van-popup v-model="showSuggestionUnitPicker" position="bottom" :style="{ height: '70%' }">
<div class="suggestion-unit-picker">
<!-- 头部工具栏 -->
<div class="picker-toolbar">
<button class="picker-cancel" @click="onSuggestionUnitCancel">取消</button>
<div class="picker-title">选择建议承办单位</div>
<button class="picker-confirm" @click="onSuggestionUnitConfirm">确认</button>
</div>
<!-- 搜索框 -->
<div class="search-container">
<van-search
v-model="suggestionUnitSearchText"
placeholder="搜索承办单位"
@input="onSuggestionUnitSearch"
></van-search>
</div>
<!-- 选项列表 -->
<div class="options-container">
<van-checkbox-group v-model="selectedSuggestionUnits">
<van-cell-group>
<van-cell
v-for="item in filteredSuggestionUnits"
:key="item.id"
clickable
@click="toggleSuggestionUnit(item)"
>
<template #title>
<div class="option-item">
<van-checkbox
:name="item.name"
:checked="selectedSuggestionUnits.includes(item.name)"
@click.stop
/>
<span class="option-text">{{ item.name }}</span>
</div>
</template>
</van-cell>
</van-cell-group>
</van-checkbox-group>
</div>
</div>
</van-popup>
</van-cell-group>
<van-cell-group title="提案内容" class="form-group">
<!--<van-field
v-model="formData.researchFindings"
name="researchFindings"
label="调研情况"
type="textarea"
rows="4"
autosize
placeholder="请输入调研情况"
:rules="[{ required: true, message: '请填写调研情况' }]"
required
></van-field>-->
<van-field
v-model="formData.brief"
label="提案案由"
type="textarea"
rows="6"
autosize
placeholder="请输入案由"
:rules="[{ required: true, message: '请填写案由' }]"
required
></van-field>
<van-field
v-model="formData.measures"
label="建议措施"
type="textarea"
rows="6"
autosize
placeholder="请输入建议措施"
:rules="[{ required: true, message: '请填写建议措施' }]"
required
></van-field>
</van-cell-group>
<!-- 附件上传 -->
<van-cell-group title="附件上传" class="form-group">
<van-field label="附件" name="files" class="direction-column-field">
<h5-file-upload
slot="input"
:value.sync="formData.files"
:upload_number="10"
upload_mode="file"
upload_result_category="array"
upload_result_type="url"
complete_result
></h5-file-upload>
</van-field>
</van-cell-group>
<!-- 按钮区域 -->
<div class="form-actions" v-if="isWriteTime">
<van-button plain type="info" @click="onSave">保存</van-button>
<van-button type="primary" @click="onSubmit" v-if="!taskId">提交</van-button>
<van-button type="primary" @click="onSubmitAgain" v-else>提交</van-button>
</div>
</van-form>
</div>
<!-- 提案撰写须知弹窗 -->
<van-action-sheet v-model="noticeDialogVisible"
title="提案撰写须知"
cancel-text="我已知晓"
close-on-click-action>
<div class="notice-dialog-content" v-html="proposalConfig.writeRemind"></div>
</van-action-sheet>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formData: {
suggestUnits: []
},
sessionOptions: [],
sourceOptions: [],
delegationOptions: [],
committeeOptions: [],
typeOptions: [],
showSessionPicker: false,
showSourcePicker: false,
showTypePicker: false,
showCommitteePicker: false,
// 移除不必要的变量声明,这些值现在直接存储在formData对象中
fileList: [],
proposalConfig: {},
noticeDialogVisible: false,
isWriteTime: true,
// 建议承办单位
suggestUnitOptions: [],
showSuggestionUnitPicker: false,
selectedSuggestionUnits: [], // 当前选中的承办单位
suggestionUnitSearchText: '', // 搜索文本
filteredSuggestionUnits: [] // 过滤后的承办单位列表
}
},
methods: {
// 选择器确认事件
onSessionConfirm(value) {
this.formData.sessionId = value.value;
const selectedOption = this.sessionOptions.find(item => item.id === value.value);
if (selectedOption) {
this.$set(this.formData, 'sessionName', selectedOption.fullName);
}
this.showSessionPicker = false;
this.meetingChange(value.value);
},
onSourceConfirm(value) {
this.formData.source = value.value;
this.$set(this.formData, 'sourceName', value.text);
this.showSourcePicker = false;
},
onTypeConfirm(value) {
this.formData.typeId = value.value;
this.$set(this.formData, 'typeName', value.text);
this.showTypePicker = false;
},
onSuggestionUnitConfirm() {
// 将选中的承办单位保存到表单数据中
this.formData.suggestUnits = [...this.selectedSuggestionUnits];
this.showSuggestionUnitPicker = false;
},
onSuggestionUnitCancel() {
// 取消时恢复到之前的选择状态
this.selectedSuggestionUnits = [...this.formData.suggestUnits];
this.suggestionUnitSearchText = '';
this.showSuggestionUnitPicker = false;
},
// 切换承办单位选择状态
toggleSuggestionUnit(item) {
const index = this.selectedSuggestionUnits.indexOf(item.name);
if (index > -1) {
this.selectedSuggestionUnits.splice(index, 1);
} else {
this.selectedSuggestionUnits.push(item.name);
}
},
// 搜索承办单位
onSuggestionUnitSearch(value) {
this.suggestionUnitSearchText = value;
this.filterSuggestionUnits();
},
// 过滤承办单位列表
filterSuggestionUnits() {
if (!this.suggestionUnitSearchText) {
this.filteredSuggestionUnits = this.suggestUnitOptions;
} else {
this.filteredSuggestionUnits = this.suggestUnitOptions.filter(item =>
item.name.toLowerCase().includes(this.suggestionUnitSearchText.toLowerCase())
);
}
},
onCommitteeConfirm(value) {
this.formData.committeeId = value.value;
this.$set(this.formData, 'committeeName', value.text);
this.showCommitteePicker = false;
},
async onSave() {
// 表单验证
try {
await this.$refs.formRef.validate();
this.$toast.loading({
message: '保存中...',
forbidClick: true,
});
this.$axios.post("/platform/proposal/write/save", {info: JSON.stringify(this.formData)})
.then((res) => {
this.$toast.clear();
if (res.code === 0) {
this.$toast.success(res.msg);
pjaxReplace('/platform/proposal/mine/h5')
} else {
this.$toast.fail(res.msg || '保存失败');
}
})
.catch(err => {
this.$toast.clear();
this.$toast.fail('网络错误,请稍后重试');
});
} catch (error) {
// 表单验证失败
console.log('表单验证失败', error);
}
},
// 提交
async onSubmit() {
try {
await this.$refs.formRef.validate();
if (!this.formData.name || this.formData.name.trim().length < 1) {
this.$toast("请填写提案名称");
return;
}
if (this.formData.brief.length < this.proposalConfig.briefMinLength) {
this.$toast("案由" + this.proposalConfig.briefMinLength + "字");
return;
}
this.$dialog.confirm({
title: '提示',
message: '您确定要提交吗?',
}).then(() => {
this.$toast.loading({
message: '提交中...',
forbidClick: true,
});
this.$axios.post('/platform/proposal/write/submit', {info: JSON.stringify(this.formData)})
.then(res => {
this.$toast.clear();
if (res.code === 0) {
this.$toast.success("提交成功");
pjaxReplace('/platform/proposal/mine/h5')
} else {
this.$toast.fail(res.msg || '提交失败');
}
})
.catch(err => {
this.$toast.clear();
this.$toast.fail('网络错误,请稍后重试');
});
}).catch(() => {
// 取消提交
});
} catch (error) {
// 表单验证失败
console.log('表单验证失败', error);
}
},
// 重新提交
async onSubmitAgain() {
try {
await this.$refs.formRef.validate();
if (!this.formData.name || this.formData.name.trim().length < 1) {
this.$toast("请填写提案名称");
return;
}
if (this.formData.brief.length < this.proposalConfig.briefMinLength) {
this.$toast("提案内容和依据最少为" + this.proposalConfig.briefMinLength + "字");
return;
}
this.$dialog.confirm({
title: '提示',
message: '您确定要提交吗?',
}).then(() => {
this.$toast.loading({
message: '提交中...',
forbidClick: true,
});
this.$axios.post('/platform/proposal/write/submitAgain', {
info: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
this.$toast.clear();
if (res.code === 0) {
this.$toast.success("提交成功");
setTimeout(() => {
pjaxReplace('/platform/proposal/mine/h5')
}, 1500);
} else {
this.$toast.fail(res.msg || '提交失败');
}
}).catch(err => {
this.$toast.clear();
this.$toast.fail('网络错误,请稍后重试');
});
}).catch(() => {
// 取消提交
});
} catch (error) {
// 表单验证失败
console.log('表单验证失败', error);
}
},
// 获取提案类别
listProposalType() {
this.$axios.post("/platform/proposal/common/listProposalType").then((res) => {
if (res.code === 0) {
this.typeOptions = res.data;
}
});
},
// 获取配置
getProposalConfig() {
return this.$axios.post("/platform/proposal/common/config").then((res) => {
if (res.code === 0) {
this.proposalConfig = res.data;
}
});
},
//教代会change
async meetingChange(val) {
this.formData.delegationId = null;
this.formData.committeeId = null;
this.formData.delegationName = '';
this.formData.committeeName = '';
await this.listDelegation();
await this.searchMineDelegation();
await this.listSource();
// 检查是否在撰写时间内
this.checkWriteTime();
},
// 获取代表团
listDelegation() {
return this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.formData.sessionId}).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data;
}
});
},
// 建议承办单位
listSuggestUnit() {
this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => {
if (res.code === 0) {
this.suggestUnitOptions = res.data
}
})
},
// 查询开启的教代会
listOpenSession(isModify = false) {
this.$axios.post("/platform/proposal/common/listOpenSession").then(async (res) => {
if (res.code === 0) {
this.sessionOptions = res.data;
if (!isModify && this.sessionOptions && this.sessionOptions.length > 0) {
this.$set(this.formData, "sessionId", this.sessionOptions[0].id);
this.$set(this.formData, "sessionName", this.sessionOptions[0].fullName);
await this.listDelegation();
await this.listSource();
// 获取代表团
await this.searchMineDelegation();
// 检查是否在撰写时间内
this.checkWriteTime();
} else {
await this.listDelegation();
await this.listSource();
this.echoPicker()
}
}
});
},
//查询自己有权限的撰写方式
listSource() {
return this.$axios.post("/platform/proposal/write/listSource", {sessionId: this.formData.sessionId}).then((res) => {
if (res.code === 0) {
this.sourceOptions = res.data;
}
});
},
//查询自己有权限的代表团
searchMineDelegation() {
return this.$axios.post("/platform/proposal/write/searchMineDelegation", {sessionId: this.formData.sessionId}).then((res) => {
if (res.code === 0) {
this.$set(this.formData, "delegationId", res.data);
// 设置代表团名称
const delegation = this.delegationOptions.find(item => item.id === res.data);
if (delegation) {
this.formData.delegationName = delegation.name;
}
}
});
},
// 检查是否在撰写时间内
checkWriteTime() {
this.$axios.post("/platform/proposal/write/checkWriteTime", {sessionId: this.formData.sessionId}).then((res) => {
if (res.code === 0) {
if (!res.data) {
this.$toast("当前时间不在撰写时间段内");
this.isWriteTime = false;
} else {
this.isWriteTime = true;
}
}
});
},
// 回显
echoPicker() {
// 设置选择器显示值
this.$set(this.formData, "sessionName", this.sessionOptions.find(item => item.id === this.formData.sessionId)?.fullName)
const delegation = this.delegationOptions.find(item => item.id === this.formData.delegationId);
this.$set(this.formData, "delegationName", delegation?.name)
const source = this.sourceOptions.find(item => item.code === this.formData.source);
this.$set(this.formData, "sourceName", source?.name)
const type = this.typeOptions.find(item => item.id === this.formData.typeId);
this.$set(this.formData, "typeName", type?.name)
},
init() {
if (this.bizId) {
this.$axios.post("/platform/proposal/write/detail", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data;
this.listOpenSession(true);
}
});
} else {
this.noticeDialogVisible = true;
this.listOpenSession(false);
// 设置用户信息
this.$set(this.formData, "createUserId", this.$store.state.user.id);
this.$set(this.formData, "createUserName", this.$store.state.user.username);
this.$set(this.formData, "createUserLoginName", this.$store.state.user.loginname);
this.$set(this.formData, "createTime", this.$moment().format("YYYY-MM-DD"));
this.$set(this.formData, "mobile", this.$store.state.user.mobile);
this.$set(this.formData, "unitName", this.$store.state.user.unit?.name);
}
}
},
created() {
this.init();
this.listSuggestUnit();
this.listProposalType();
this.getProposalConfig();
},
watch: {
// 监听suggestUnitOptions变化,初始化过滤列表
suggestUnitOptions: {
handler(newVal) {
this.filteredSuggestionUnits = newVal;
},
immediate: true
},
// 监听选择器显示状态,重置搜索和选择状态
showSuggestionUnitPicker(newVal) {
if (newVal) {
// 打开选择器时,初始化选择状态
this.selectedSuggestionUnits = [...this.formData.suggestUnits];
this.suggestionUnitSearchText = '';
this.filterSuggestionUnits();
}
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,228 @@
const H5_SUGGESTION_TC_INFO_COMPONENT = {
name: "ProposalInfo",
template: /*language=HTML*/ `
<div>
<div class="process-title">基本信息</div>
<van-cell-group>
<van-cell title="意见编号">{{ viewData.code }}</van-cell>
<van-cell title="撰写人">{{ viewData.createUserName }}</van-cell>
<van-cell title="撰写时间">{{ viewData.createTime }}</van-cell>
<van-cell title="教代会届次">{{ viewData.fullName }}</van-cell>
<van-cell title="撰写人单位">{{ viewData.unitName }}</van-cell>
<van-cell :title="viewData.mannerCode!=='W03'?'代表团名称':'委员会名称'">
{{ viewData.mannerCode !== 'W03' ? viewData.delegationName : viewData.committeeName }}
</van-cell>
<van-cell title="意见类别">
{{viewData.typeName}}
</van-cell>
<van-cell title="意见内容">
<div slot="label" class="font-size1 van-color-text-primary break-all" style="white-space: normal;">
<div v-html="viewData.brief"></div>
</div>
</van-cell>
<van-cell title="附件">
<div slot="label">
{{viewData.files}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <div slot="label">-->
<!-- <van-image :src="viewData.signature"-->
<!-- style="width: 100%;height: 150px;border: 1px dashed"></van-image>-->
<!-- </div>-->
<!-- </van-cell>-->
</van-cell-group>
<div class="process-title">
附议人信息
</div>
<van-cell-group>
<van-cell title="提案名称" v-for="item in viewData.seconders">
<template slot="title">
<span class="font-size1">{{item.createVariable.userName}}</span>
<span class="margin-left10 font-size1 van-color-text-regular">/ {{item.createVariable.loginName}}</span>
</template>
<template slot="label">
<span class="font-size0 van-color-text-assist">{{item.createVariable.unitName}}</span>
</template>
<template>
<span class="font-size2 van-color-text-placeholder bold">
<span v-if="item.extVariable && item.extVariable.bpmTaskApprovalType">
<van-tag size="mini" type="success"
v-if="item.extVariable.bpmTaskApprovalType==='PASS'">同意</van-tag>
<van-tag size="mini" type="danger" v-if="item.extVariable.bpmTaskApprovalType==='REJECT'">拒绝</van-tag>
</span>
<span v-else>
<van-tag size="mini">未附议</van-tag>
</span>
</span>
</template>
</van-cell>
</van-cell-group>
<div>
<div v-for="nodeTask in viewData.nodeTasks" :key="nodeTask.id">
<div class="process-title" v-if="nodeTask.nodeCode !== 20">
{{nodeTask.nodeName}}
</div>
<div v-if="nodeTask.nodeCode === 30">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="审核人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="审核时间">{{ task.endOn}}</van-cell>
<van-cell title="审核结果">
<div v-if="task.extVariable">
<van-tag type="success" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'PASS'">同意
</van-tag>
<van-tag type="danger" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'BACK'">退回重新填写
</van-tag>
<van-tag type="danger" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'REJECT'">建议撤销
</van-tag>
</div>
</van-cell>
<van-cell title="审核意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 60 || nodeTask.nodeCode === 70">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="审核人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="审核时间">{{ task.endOn}}</van-cell>
<van-cell title="审核结果">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="task.extVariable.caseFilingResult">
</dict-tag>
</van-cell>
<template
v-if="task.extVariable.caseFilingResult!=='NOT' && task.extVariable.caseFilingResult!==''">
<van-cell title="主办单位" :span="3">{{ task.extVariable.hostUnit}}</van-cell>
<van-cell title="协办单位" :span="3">
<div style="white-space: normal">
{{ task.extVariable.helpUnits.join(',')}}
</div>
</van-cell>
</template>
<van-cell title="审核意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 80">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="承办单位">
{{ task.createVariable.underTakeName}}
({{ task.createVariable.isMaster ? '主办' : '协办'}})
</van-cell>
<van-cell title="答复人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="答复时间">{{ task.endOn}}</van-cell>
<van-cell title="答复内容">
<div v-html="task.extVariable.approvalOpinion"></div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 90">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="承办单位">
{{ task.createVariable.underTakeName}}
({{ task.createVariable.isMaster ? '主办' : '协办'}})
</van-cell>
<van-cell title="校领导">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="审批时间">{{ task.endOn}}</van-cell>
<van-cell title="审批结果" :span="3">
<van-tag size="mini" type="success"
v-if="task.extVariable.bpmTaskApprovalType==='PASS'">同意
</van-tag>
<van-tag size="mini" type="danger"
v-if="task.extVariable.bpmTaskApprovalType==='BACK_OTHER_NODE'">退回重新答复
</van-tag>
</van-cell>
<van-cell title="审批意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 100">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="反馈人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="反馈时间">{{ task.endOn}}</van-cell>
<van-cell title="反馈结果">
{{ task.extVariable.feedBackScore}}
</van-cell>
<van-cell title="反馈意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
</div>
</div>
</div>
`,
dicts: ["SUGGESTION_CASE_FILING_RESULT"],
data() {
return {
viewData: {},
viewDialogVisible: false
}
},
methods: {
onOpen(id) {
this.$axios.post("/platform/suggestion/tc/common/suggestionInfo", { id }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
openView(id) {
// this.viewDialogVisible = true
// this.$nextTick(() => {
// this.$refs.infoDialogRef.onOpen(id)
// })
}
}
}
@@ -0,0 +1,236 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入意见内容搜索"
v-model="pageForm.brief"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<van-pull-refresh v-model="tableRefreshing" @refresh="doSearch" style="min-height: calc(100vh - 90px)">
<van-list v-if="tableData && tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="" @load="pageData">
<div v-for="row in tableData" class="list-card">
<div class="list-card-body">
<div class="van-multi-ellipsis--l2" style="padding: 0 16px; font-weight: bold">{{row.brief}}</div>
<van-cell :value="row.code" title="意见编号"></van-cell>
<van-cell :value="row.createUserName" title="撰写人"></van-cell>
<van-cell :value="row.typeName" title="意见类别"></van-cell>
<van-cell :value="row.sessionName" title="届次"></van-cell>
<van-cell :value="row.delegationName" title="代表团"></van-cell>
<van-cell :value="row.processInstanceNodeName" title="当前节点"></van-cell>
<div class="list-card-footer">
<van-button @click="openView(row)" size="small">查看</van-button>
<van-button v-if="row.processInstanceTaskStatus==='ACTIVE'" @click="openApproval(row)" size="small" type="primary">
审核
</van-button>
<van-button
v-if="row.processInstanceTaskStatus==='COMPLETE' && !row.nextTaskIsComplete"
@click="openRevoke(row.processInstanceTaskId)"
size="small"
type="danger"
>
撤回
</van-button>
</div>
</div>
</div>
</van-list>
<van-empty
v-if="tableData.length===0"
image="/assets/platform/plugins/vant-green/images/nodata/nodata.png"
description="暂无数据"
></van-empty>
</van-pull-refresh>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
<div v-if="showApprovalForm">
<div class="process-title">{{formData.processInstanceNodeName}}</div>
<van-form ref="vanFormRef">
<van-field
label="审核意见"
name="approvalOpinion"
v-model="formData.approvalOpinion"
required
:rules="[{ required: true, message: '请输入审核意见' }]"
placeholder="请输入审核意见"
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click.submit="doApproval('BACK')">退回重新填写</van-button>
<van-button type="danger" block @click.submit="doApproval('REJECT')">建议撤销</van-button>
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
</div>
</div>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
components: {
info: H5_SUGGESTION_TC_INFO_COMPONENT
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null,
approvalText: "0",
approval: false
},
tableData: [],
tableLoading: false,
tableFinished: false,
tableRefreshing: false,
sessionOptions: [],
infoShow: false,
formData: {},
showApprovalForm: false,
rules: {
approvalSignature: [{ required: true, message: "请签字" }]
}
}
},
methods: {
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
openApproval(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
this.formData = row.approvalParam
this.showApprovalForm = true
})
},
doApproval(approvalType) {
this.formData.bpmTaskApprovalType = approvalType
this.$refs.vanFormRef
.validate()
.then(() => {
this.$axios
.post("/platform/suggestion/tc/delegation/approval", {
approval: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.infoShow = false
this.$toast.success(res.msg)
this.doSearch()
}
})
})
.catch((err) => {})
},
openRevoke(taskId) {
this.$dialog
.confirm({
title: "撤回",
message: "您确定要撤回吗?",
confirmButtonText: "确定",
cancelButtonText: "取消"
})
.then(() => {
this.$axios.post("/platform/suggestion/tc/delegation/revoke", { taskId }).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
sessionChange(val) {
this.doSearch()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{ text: "全部届次", value: null }])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.pageData()
}
}
})
},
pageData() {
this.tableLoading = true
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/tc/delegation/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
}
this.pageForm.pageNumber++
}
})
.finally(() => {
loading.close()
this.tableLoading = false
this.tableRefreshing = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
}
},
created() {
this.pageData()
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,197 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的意见" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入意见内容搜索"
v-model="pageForm.brief"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
</van-sticky>
<van-pull-refresh v-model="tableRefreshing" @refresh="doSearch" style="min-height: calc(100vh - 90px)">
<van-list v-if="tableData && tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="" @load="pageData">
<div v-for="row in tableData" :key="row.id" class="list-card">
<div class="list-card-body">
<div class="van-multi-ellipsis--l2" style="padding: 0 16px; font-weight: bold">{{row.brief}}</div>
<van-cell :value="row.code" title="意见编号"></van-cell>
<van-cell :value="row.createUserName" title="撰写人"></van-cell>
<van-cell :value="row.typeName" title="意见类别"></van-cell>
<van-cell :value="row.sessionName" title="届次"></van-cell>
<van-cell :value="row.delegationName" title="代表团"></van-cell>
<van-cell :value="row.processInstanceNodeName" title="当前节点"></van-cell>
<div class="list-card-footer">
<van-button @click="openView(row)" size="small">查看</van-button>
<van-button @click="openEdit(row)" v-if="[10,40].includes(row.processInstanceNodeCode)" size="small">编辑</van-button>
<van-button
@click="$refs.inviteSeconderRef.onOpen(row)"
v-if="[10,20].includes(row.processInstanceNodeCode)"
size="small"
type="primary"
>
邀请附议人
</van-button>
<van-button
@click="openRevoke(row)"
v-if="[20].includes(row.processInstanceNodeCode) && !row.nextTaskIsComplete"
size="small"
type="danger"
>
撤销
</van-button>
<van-button v-if="[10,40,50].includes(row.processInstanceNodeCode)" @click="del(row.id)" size="small" type="danger">
删除
</van-button>
</div>
</div>
</div>
</van-list>
<van-empty v-if="tableData.length===0" description="没有更多了"></van-empty>
</van-pull-refresh>
<invite-seconder @refresh="doSearch" ref="inviteSeconderRef"></invite-seconder>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="提案信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("inviteSeconder.js"){}#-->
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
components: {
"invite-seconder": SUGGESTION_TC_INVITE_SECONDER_COMPONENT,
info: H5_SUGGESTION_TC_INFO_COMPONENT
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null
},
tableData: [],
tableLoading: false,
tableFinished: false,
tableRefreshing: false,
sessionOptions: [],
infoShow: false
}
},
methods: {
sessionChange(val) {
this.doSearch()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{ text: "全部届次", value: null }])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.pageData()
}
}
})
},
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
openEdit(row) {
this.$pjaxReplace("/platform/h5/suggestion/tc/write?id=" + row.id)
},
pageData() {
this.tableLoading = true
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/tc/mine/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
}
this.pageForm.pageNumber++
}
})
.finally(() => {
loading.close()
this.tableLoading = false
this.tableRefreshing = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
},
openRevoke(row) {
this.$dialog
.confirm({
title: "提示",
message: "您确定要撤销申请吗?"
})
.then(() => {
this.$axios.post("/platform/suggestion/tc/mine/revokeApply", { id: row.id }).then((resp) => {
this.$toast.success(resp.msg)
this.doSearch()
})
})
},
del(id) {
this.$dialog
.confirm({
title: "提示",
message: "您确定要删除吗?"
})
.then(() => {
this.$axios.post("/platform/suggestion/tc/mine/delete", { id }).then((resp) => {
if (resp.code === 0) {
this.$toast.success(resp.msg)
this.doSearch()
}
})
})
}
},
created() {
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,135 @@
const SUGGESTION_TC_INVITE_SECONDER_COMPONENT = {
template: `
<van-action-sheet v-model="visible" title="邀请附议人" class="height100">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
placeholder="请输入工号或者姓名查询"
@search="doSearch"
></van-search>
<van-tabs v-model="isInvite" @click="isInviteClick">
<van-tab title="已邀请" name="1"></van-tab>
<van-tab title="可邀请" name="0"></van-tab>
</van-tabs>
<van-checkbox-group v-model="tableSelection" v-if="tableData && tableData.length>0">
<van-cell-group >
<van-cell
v-for="(item, index) in tableData"
clickable
:key="pageForm.isInvite +':'+ item.loginName"
@click="tableRowToggle(index)"
>
<span slot="title">
{{item.userName}}
({{item.loginName}})
<van-tag :plain="false">
{{item.sex || '未知'}}
</van-tag>
</span>
<span slot="label" class="font-size0 van-color-text-assist">
{{item.unitName}}
</span>
<van-checkbox
:name="item"
ref="checkboxes"
slot="right-icon"
v-if="!pageForm.isInvite"></van-checkbox>
</van-cell>
</van-cell-group>
<div class="p10">
<van-pagination
v-model="pageForm.pageNumber"
:total-items="pageForm.totalCount"
:items-per-page="pageForm.pageSize"
@change="pageData"
></van-pagination>
<van-button @click="invite" type="primary" block :disabled="pageForm.isInvite" class="mt10">邀请</van-button>
</div>
</van-checkbox-group>
<van-empty v-else :figure="2"></van-empty>
</van-action-sheet>
`,
data() {
return {
visible: false,
secondedNum: 0,
record: {},
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 5,
totalCount: 0,
isInvite: false,
searchKeyword: null
},
isInvite: "0",
tableSelection: []
}
},
methods: {
onOpen(record) {
this.visible = true
this.record = record
this.pageData()
},
detail(id) {},
invite() {
if (this.tableSelection.length === 0) {
this.$toast("请先选择附议人后在点击邀请")
return
}
/* this.visible = false
this.$emit("refresh", null)*/
const loginNames = this.tableSelection.map((s) => s.loginName)
this.$axios
.post("/platform/suggestion/tc/mine/inviteSeconder", {
task: JSON.stringify({
processTaskId: this.record.processTaskId,
processInstId: this.record.processInstId
}),
proposalId: this.record.id,
seconders: JSON.stringify(loginNames)
})
.then((res) => {
if (res.code === 0) {
this.pageData()
this.$toast.success(res.msg)
this.tableSelection = []
// this.visible = false
this.$emit("refresh", null)
}
})
},
pageData() {
this.$axios
.post("/platform/suggestion/tc/mine/listSeconder", {
...this.pageForm,
sessionId: this.record.sessionId,
proposalId: this.record.id
})
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
isInviteClick(index, title) {
this.pageForm.isInvite = index === "1"
this.doSearch()
},
tableRowToggle(index) {
console.log(index)
}
}
}
@@ -0,0 +1,198 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="意见附议" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入意见内容搜索"
v-model="pageForm.brief"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已附议" name="1"></van-tab>
<van-tab title="未附议" name="0"></van-tab>
</van-tabs>
</van-sticky>
<van-pull-refresh v-model="tableRefreshing" @refresh="doSearch" style="min-height: calc(100vh - 90px)">
<van-list v-if="tableData && tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="" @load="pageData">
<div v-for="row in tableData" class="list-card">
<div class="list-card-body">
<div class="van-multi-ellipsis--l2" style="padding: 0 16px; font-weight: bold">{{row.brief}}</div>
<van-cell :value="row.code" title="意见编号"></van-cell>
<van-cell :value="row.createUserName" title="撰写人"></van-cell>
<van-cell :value="row.typeName" title="意见类别"></van-cell>
<van-cell :value="row.sessionName" title="届次"></van-cell>
<van-cell :value="row.delegationName" title="代表团"></van-cell>
<van-cell :value="row.processInstanceNodeName" title="当前节点"></van-cell>
<div class="list-card-footer">
<van-button @click="openView(row)" size="small">查看</van-button>
<van-button v-if="row.processInstanceTaskStatus==='ACTIVE'" @click="openApproval(row)" type="primary" size="small">
附议
</van-button>
</div>
</div>
</div>
</van-list>
<van-empty v-if="tableData.length===0" description="没有更多了"></van-empty>
</van-pull-refresh>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
<div v-if="showApprovalForm">
<div class="process-title">{{formData.processInstanceNodeName}}</div>
<form @submit.prevent="">
<van-field label="签字" name="approvalSignature" v-model="formData.signature" required class="direction-column-field">
<h5-signature v-model="formData.approvalSignature" slot="input"></h5-signature>
</van-field>
</form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click.submit="doApproval('REJECT')">拒绝</van-button>
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
</div>
</div>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
components: {
info: H5_SUGGESTION_TC_INFO_COMPONENT
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null,
approvalText: "0",
approval: false
},
tableData: [],
tableLoading: false,
tableFinished: false,
tableRefreshing: false,
sessionOptions: [],
infoShow: false,
formData: {},
showApprovalForm: false,
rules: {
approvalSignature: [{ required: true, message: "请签字" }]
}
}
},
methods: {
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
openApproval(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
this.formData = row.approvalParam
this.showApprovalForm = true
})
},
doApproval(approvalType) {
this.formData.bpmTaskApprovalType = approvalType
formRules(this.rules, this.formData, (valid) => {
if (valid) {
this.$axios
.post("/platform/suggestion/tc/seconded/approval", {
approval: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.infoShow = false
this.$toast.success(res.msg)
this.doSearch()
}
})
}
})
},
sessionChange(val) {
this.doSearch()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{ text: "全部届次", value: null }])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.pageData()
}
}
})
},
pageData() {
this.tableLoading = true
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/tc/seconded/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
}
this.pageForm.pageNumber++
}
})
.finally(() => {
loading.close()
this.tableLoading = false
this.tableRefreshing = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
}
},
created() {
this.pageData()
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,274 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar title="撰写意见" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
<van-cell-group>
<van-form @submit="doSave">
<van-field v-model="formData.createUserName" name="createUserName" label="代表姓名" readonly></van-field>
<van-field v-model="formData.createTime" name="createTime" label="提案时间" readonly></van-field>
<van-field
v-model="formData.sessionName"
name="sessionName"
label="所属教代会"
required
readonly
clickable
@click="showSessionPicker = true"
placeholder="请选择"
:rules="[{ required: true, message: '请选择教代会' }]"
></van-field>
<van-popup v-model="showSessionPicker" position="bottom">
<van-picker
show-toolbar
:columns="sessionOptions"
value-key="fullName"
@cancel="showSessionPicker = false"
@confirm="sessionConfirm"
></van-picker>
</van-popup>
<van-field
v-model="formData.delegationName"
name="delegationName"
label="所属代表团"
required
readonly
clickable
@click="showDelegationPicker = true"
placeholder="请选择"
:rules="[{ required: true, message: '请选择代表团' }]"
></van-field>
<van-popup v-model="showDelegationPicker" position="bottom">
<van-picker
show-toolbar
:columns="delegationOptions"
value-key="name"
@cancel="showDelegationPicker = false"
@confirm="delegationConfirm"
></van-picker>
</van-popup>
<van-field v-model="formData.unitName" name="unitName" label="单位" readonly></van-field>
<van-field
v-model="formData.mobile"
name="mobile"
label="联系电话"
required
readonly
:rules="[{ required: true, message: '请填写联系电话' }]"
></van-field>
<van-field
v-model="formData.typeName"
name="typeName"
label="意见类别"
required
readonly
clickable
@click="showTypePicker = true"
placeholder="请选择"
:rules="[{ required: true, message: '请选择意见类别' }]"
></van-field>
<van-popup v-model="showTypePicker" position="bottom">
<van-picker show-toolbar :columns="typeOptions" value-key="name" @cancel="showTypePicker = false" @confirm="typeConfirm"></van-picker>
</van-popup>
<van-field label="意见内容" name="brief" v-model="formData.brief" required class="direction-column-field">
<template #input>
<text-editor v-model="formData.brief"></text-editor>
</template>
</van-field>
<van-field label="附件" name="files" class="direction-column-field">
<h5-file-upload
slot="input"
:value.sync="formData.files"
:upload_number="5"
upload_mode="file"
upload_result_category="array"
upload_result_type="url"
complete_result
></h5-file-upload>
</van-field>
<van-cell cell-class="form-button-cell" v-if="showButton">
<van-button type="primary" size="large" block native-type="submit">保存到我的意见</van-button>
</van-cell>
</van-form>
</van-cell-group>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
store,
data() {
return {
formData: {},
showSourcePicker: false,
showSessionPicker: false,
showDelegationPicker: false,
showCommitteePicker: false,
showTypePicker: false,
sourceOptions: [],
sessionOptions: [],
delegationOptions: [],
typeOptions: [],
proposalConfig: {},
noticeDialogVisible: false,
showButton: true
}
},
methods: {
doSave(values) {
if (!this.formData.brief) {
this.$toast("请填写意见内容")
return
}
const briefLength = removeHTMLTag(this.formData.brief)
if (briefLength < this.suggestionConfig.briefMinLength) {
this.$toast("意见内容最少" + this.suggestionConfig.briefMinLength + "个字")
return
}
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/tc/write/save", { info: JSON.stringify(this.formData) })
.then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.$pjaxReplace("/platform/h5/suggestion/tc/mine")
}
})
.finally(() => {
loading.clear()
})
},
sessionConfirm(val) {
this.showSessionPicker = false
this.formData.sessionName = val.fullName
this.formData.sessionId = val.id
},
delegationConfirm(val) {
this.showDelegationPicker = false
this.formData.delegationId = val.id
this.formData.delegationName = val.name
},
typeConfirm(val) {
this.showTypePicker = false
this.formData.typeId = val.id
this.formData.typeName = val.name
},
listSuggestionType() {
this.$axios.post("/platform/suggestion/tc/common/listProposalType").then((res) => {
if (res.code === 0) {
this.typeOptions = res.data
}
})
},
getSuggestionConfig() {
return this.$axios.post("/platform/suggestion/tc/common/config").then((res) => {
if (res.code === 0) {
this.suggestionConfig = res.data
}
})
},
//教代会change
async meetingChange(val) {
this.$set(this.formData, "delegationId", null)
this.formData.delegationOptions = []
this.listDelegation()
this.searchSelfDelegation()
},
// 查询当前用户所在代表团
listDelegation() {
return this.$axios.post("/platform/proposal/common/listDelegation", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
})
},
// 查询开放的教代会届次
listOpenSession(isModify = false) {
return this.$axios.post("/platform/suggestion/tc/common/listOpenSession").then(async (res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (!isModify && this.sessionOptions) {
this.$set(this.formData, "sessionId", this.sessionOptions[0].id)
this.$set(this.formData, "sessionName", this.sessionOptions[0].fullName)
await this.listDelegation()
await this.searchSelfDelegation()
}
if (isModify) {
const session = this.sessionOptions.find((v) => v.id === this.formData.sessionId)
this.$set(this.formData, "sessionName", session?.fullName)
await this.listDelegation()
const delegation = this.delegationOptions.find((v) => v.id === this.formData.delegationId)
this.$set(this.formData, "delegationName", delegation?.name)
if (this.formData.typeId) {
this.typeConfirm(this.typeOptions.find((v) => v.id === this.formData.typeId))
}
}
// await this.listDelegation()
}
})
},
//查询自己有权限的代表团
searchSelfDelegation() {
return this.$axios.post("/platform/suggestion/tc/write/selfDelegation", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.$set(this.formData, "delegationId", res.data)
this.$set(this.formData, "delegationName", this.delegationOptions.find((item) => item.id === res.data)?.name)
}
})
},
init() {
const id = GetQueryString("id")
if (id) {
this.$axios.post("/platform/suggestion/tc/write/detail", { id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.listOpenSession(true)
}
})
} else {
this.noticeDialogVisible = true
this.listOpenSession(false)
this.$set(this.formData, "createUserId", this.$store.state.user.id)
this.$set(this.formData, "createUserName", this.$store.state.user.username)
this.$set(this.formData, "createUserLoginName", this.$store.state.user.loginname)
this.$set(this.formData, "createTime", this.$moment().format("YYYY-MM-DD"))
this.$set(this.formData, "mobile", this.$store.state.user.mobile)
this.$set(this.formData, "unitName", this.$store.state.user.unit?.name)
}
}
},
created() {
this.init()
this.listSuggestionType()
this.getSuggestionConfig()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,228 @@
const H5_SUGGESTION_WC_INFO_COMPONENT = {
name: "ProposalInfo",
template: /*language=HTML*/ `
<div>
<div class="process-title">基本信息</div>
<van-cell-group>
<van-cell title="意见编号">{{ viewData.code }}</van-cell>
<van-cell title="撰写人">{{ viewData.createUserName }}</van-cell>
<van-cell title="撰写时间">{{ viewData.createTime }}</van-cell>
<van-cell title="工代会届次">{{ viewData.fullName }}</van-cell>
<van-cell title="撰写人单位">{{ viewData.unitName }}</van-cell>
<van-cell :title="viewData.mannerCode!=='W03'?'代表团名称':'委员会名称'">
{{ viewData.mannerCode !== 'W03' ? viewData.delegationName : viewData.committeeName }}
</van-cell>
<van-cell title="意见类别">
{{viewData.typeName}}
</van-cell>
<van-cell title="意见内容">
<div slot="label" class="font-size1 van-color-text-primary break-all" style="white-space: normal;">
<div v-html="viewData.brief"></div>
</div>
</van-cell>
<van-cell title="附件">
<div slot="label">
{{viewData.files}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <div slot="label">-->
<!-- <van-image :src="viewData.signature"-->
<!-- style="width: 100%;height: 150px;border: 1px dashed"></van-image>-->
<!-- </div>-->
<!-- </van-cell>-->
</van-cell-group>
<div class="process-title">
附议人信息
</div>
<van-cell-group>
<van-cell title="提案名称" v-for="item in viewData.seconders">
<template slot="title">
<span class="font-size1">{{item.createVariable.userName}}</span>
<span class="margin-left10 font-size1 van-color-text-regular">/ {{item.createVariable.loginName}}</span>
</template>
<template slot="label">
<span class="font-size0 van-color-text-assist">{{item.createVariable.unitName}}</span>
</template>
<template>
<span class="font-size2 van-color-text-placeholder bold">
<span v-if="item.extVariable && item.extVariable.bpmTaskApprovalType">
<van-tag size="mini" type="success"
v-if="item.extVariable.bpmTaskApprovalType==='PASS'">同意</van-tag>
<van-tag size="mini" type="danger" v-if="item.extVariable.bpmTaskApprovalType==='REJECT'">拒绝</van-tag>
</span>
<span v-else>
<van-tag size="mini">未附议</van-tag>
</span>
</span>
</template>
</van-cell>
</van-cell-group>
<div>
<div v-for="nodeTask in viewData.nodeTasks" :key="nodeTask.id">
<div class="process-title" v-if="nodeTask.nodeCode !== 20">
{{nodeTask.nodeName}}
</div>
<div v-if="nodeTask.nodeCode === 30">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="审核人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="审核时间">{{ task.endOn}}</van-cell>
<van-cell title="审核结果">
<div v-if="task.extVariable">
<van-tag type="success" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'PASS'">同意
</van-tag>
<van-tag type="danger" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'BACK'">退回重新填写
</van-tag>
<van-tag type="danger" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'REJECT'">建议撤销
</van-tag>
</div>
</van-cell>
<van-cell title="审核意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 60 || nodeTask.nodeCode === 70">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="审核人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="审核时间">{{ task.endOn}}</van-cell>
<van-cell title="审核结果">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="task.extVariable.caseFilingResult">
</dict-tag>
</van-cell>
<template
v-if="task.extVariable.caseFilingResult!=='NOT' && task.extVariable.caseFilingResult!==''">
<van-cell title="主办单位" :span="3">{{ task.extVariable.hostUnit}}</van-cell>
<van-cell title="协办单位" :span="3">
<div style="white-space: normal">
{{ task.extVariable.helpUnits.join(',')}}
</div>
</van-cell>
</template>
<van-cell title="审核意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 80">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="承办单位">
{{ task.createVariable.underTakeName}}
({{ task.createVariable.isMaster ? '主办' : '协办'}})
</van-cell>
<van-cell title="答复人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="答复时间">{{ task.endOn}}</van-cell>
<van-cell title="答复内容">
<div v-html="task.extVariable.approvalOpinion"></div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 90">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="承办单位">
{{ task.createVariable.underTakeName}}
({{ task.createVariable.isMaster ? '主办' : '协办'}})
</van-cell>
<van-cell title="校领导">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="审批时间">{{ task.endOn}}</van-cell>
<van-cell title="审批结果" :span="3">
<van-tag size="mini" type="success"
v-if="task.extVariable.bpmTaskApprovalType==='PASS'">同意
</van-tag>
<van-tag size="mini" type="danger"
v-if="task.extVariable.bpmTaskApprovalType==='BACK_OTHER_NODE'">退回重新答复
</van-tag>
</van-cell>
<van-cell title="审批意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
<div v-if="nodeTask.nodeCode === 100">
<van-cell-group v-for="task in nodeTask.tasks" :key="task.id">
<van-cell title="反馈人">{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</van-cell>
<van-cell title="反馈时间">{{ task.endOn}}</van-cell>
<van-cell title="反馈结果">
{{ task.extVariable.feedBackScore}}
</van-cell>
<van-cell title="反馈意见">
<div style="white-space: normal">
{{ task.extVariable.approvalOpinion}}
</div>
</van-cell>
<!-- <van-cell title="签字">-->
<!-- <van-image :src="task.extVariable.approvalSignature"-->
<!-- v-if="task.extVariable && task.extVariable.approvalSignature"-->
<!-- class="signature-image"></van-image>-->
<!-- </van-cell>-->
</van-cell-group>
</div>
</div>
</div>
</div>
`,
dicts: ["SUGGESTION_CASE_FILING_RESULT"],
data() {
return {
viewData: {},
viewDialogVisible: false
}
},
methods: {
onOpen(id) {
this.$axios.post("/platform/suggestion/tc/common/suggestionInfo", { id }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
openView(id) {
// this.viewDialogVisible = true
// this.$nextTick(() => {
// this.$refs.infoDialogRef.onOpen(id)
// })
}
}
}
@@ -0,0 +1,236 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入意见内容搜索"
v-model="pageForm.brief"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<van-pull-refresh v-model="tableRefreshing" @refresh="doSearch" style="min-height: calc(100vh - 90px)">
<van-list v-if="tableData && tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="" @load="pageData">
<div v-for="row in tableData" class="list-card">
<div class="list-card-body">
<div class="van-multi-ellipsis--l2" style="padding: 0 16px; font-weight: bold">{{row.brief}}</div>
<van-cell :value="row.code" title="意见编号"></van-cell>
<van-cell :value="row.createUserName" title="撰写人"></van-cell>
<van-cell :value="row.typeName" title="意见类别"></van-cell>
<van-cell :value="row.sessionName" title="届次"></van-cell>
<van-cell :value="row.delegationName" title="代表团"></van-cell>
<van-cell :value="row.processInstanceNodeName" title="当前节点"></van-cell>
<div class="list-card-footer">
<van-button @click="openView(row)" size="small">查看</van-button>
<van-button v-if="row.processInstanceTaskStatus==='ACTIVE'" @click="openApproval(row)" size="small" type="primary">
审核
</van-button>
<van-button
v-if="row.processInstanceTaskStatus==='COMPLETE' && !row.nextTaskIsComplete"
@click="openRevoke(row.processInstanceTaskId)"
size="small"
type="danger"
>
撤回
</van-button>
</div>
</div>
</div>
</van-list>
<van-empty
v-if="tableData.length===0"
image="/assets/platform/plugins/vant-green/images/nodata/nodata.png"
description="暂无数据"
></van-empty>
</van-pull-refresh>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
<div v-if="showApprovalForm">
<div class="process-title">{{formData.processInstanceNodeName}}</div>
<van-form ref="vanFormRef">
<van-field
label="审核意见"
name="approvalOpinion"
v-model="formData.approvalOpinion"
required
:rules="[{ required: true, message: '请输入审核意见' }]"
placeholder="请输入审核意见"
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click.submit="doApproval('BACK')">退回重新填写</van-button>
<van-button type="danger" block @click.submit="doApproval('REJECT')">建议撤销</van-button>
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
</div>
</div>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
components: {
info: H5_SUGGESTION_WC_INFO_COMPONENT
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null,
approvalText: "0",
approval: false
},
tableData: [],
tableLoading: false,
tableFinished: false,
tableRefreshing: false,
sessionOptions: [],
infoShow: false,
formData: {},
showApprovalForm: false,
rules: {
approvalSignature: [{ required: true, message: "请签字" }]
}
}
},
methods: {
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
openApproval(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
this.formData = row.approvalParam
this.showApprovalForm = true
})
},
doApproval(approvalType) {
this.formData.bpmTaskApprovalType = approvalType
this.$refs.vanFormRef
.validate()
.then(() => {
this.$axios
.post("/platform/suggestion/wc/delegation/approval", {
approval: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.infoShow = false
this.$toast.success(res.msg)
this.doSearch()
}
})
})
.catch((err) => {})
},
openRevoke(taskId) {
this.$dialog
.confirm({
title: "撤回",
message: "您确定要撤回吗?",
confirmButtonText: "确定",
cancelButtonText: "取消"
})
.then(() => {
this.$axios.post("/platform/suggestion/wc/delegation/revoke", { taskId }).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
})
},
sessionChange(val) {
this.doSearch()
},
listSession() {
this.$axios.post("/platform/suggestion/wc/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{ text: "全部届次", value: null }])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.pageData()
}
}
})
},
pageData() {
this.tableLoading = true
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/tc/delegation/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
}
this.pageForm.pageNumber++
}
})
.finally(() => {
loading.close()
this.tableLoading = false
this.tableRefreshing = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
}
},
created() {
this.pageData()
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,197 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的意见" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入意见内容搜索"
v-model="pageForm.brief"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
</van-sticky>
<van-pull-refresh v-model="tableRefreshing" @refresh="doSearch" style="min-height: calc(100vh - 90px)">
<van-list v-if="tableData && tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="" @load="pageData">
<div v-for="row in tableData" class="list-card">
<div class="list-card-body">
<div class="van-multi-ellipsis--l2" style="padding: 0 16px; font-weight: bold">{{row.brief}}</div>
<van-cell :value="row.code" title="意见编号"></van-cell>
<van-cell :value="row.createUserName" title="撰写人"></van-cell>
<van-cell :value="row.typeName" title="意见类别"></van-cell>
<van-cell :value="row.sessionName" title="届次"></van-cell>
<van-cell :value="row.delegationName" title="代表团"></van-cell>
<van-cell :value="row.processInstanceNodeName" title="当前节点"></van-cell>
<div class="list-card-footer">
<van-button @click="openView(row)" size="small">查看</van-button>
<van-button @click="openEdit(row)" v-if="[10,40].includes(row.processInstanceNodeCode)" size="small">编辑</van-button>
<van-button
@click="$refs.inviteSeconderRef.onOpen(row)"
v-if="[10,20].includes(row.processInstanceNodeCode)"
size="small"
type="primary"
>
邀请附议人
</van-button>
<van-button
@click="openRevoke(row)"
v-if="[20].includes(row.processInstanceNodeCode) && !row.nextTaskIsComplete"
size="small"
type="danger"
>
撤销
</van-button>
<van-button v-if="[10,40,50].includes(row.processInstanceNodeCode)" @click="del(row.id)" size="small" type="danger">
删除
</van-button>
</div>
</div>
</div>
</van-list>
<van-empty v-if="tableData.length===0" description="没有更多了"></van-empty>
</van-pull-refresh>
<invite-seconder @refresh="doSearch" ref="inviteSeconderRef"></invite-seconder>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="提案信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("inviteSeconder.js"){}#-->
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
components: {
"invite-seconder": SUGGESTION_WC_INVITE_SECONDER_COMPONENT,
info: H5_SUGGESTION_WC_INFO_COMPONENT
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null
},
tableData: [],
tableLoading: false,
tableFinished: false,
tableRefreshing: false,
sessionOptions: [],
infoShow: false
}
},
methods: {
sessionChange(val) {
this.doSearch()
},
listSession() {
this.$axios.post("/platform/suggestion/wc/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{ text: "全部届次", value: null }])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.pageData()
}
}
})
},
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
openEdit(row) {
this.$pjaxReplace("/platform/h5/suggestion/wc/write?id=" + row.id)
},
pageData() {
this.tableLoading = true
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/wc/mine/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
}
this.pageForm.pageNumber++
}
})
.finally(() => {
loading.close()
this.tableLoading = false
this.tableRefreshing = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
},
openRevoke(row) {
this.$dialog
.confirm({
title: "提示",
message: "您确定要撤销申请吗?"
})
.then(() => {
this.$axios.post("/platform/suggestion/wc/mine/revokeApply", { id: row.id }).then((resp) => {
this.$toast.success(resp.msg)
this.doSearch()
})
})
},
del(id) {
this.$dialog
.confirm({
title: "提示",
message: "您确定要删除吗?"
})
.then(() => {
this.$axios.post("/platform/suggestion/wc/mine/delete", { id }).then((resp) => {
if (resp.code === 0) {
this.$toast.success(resp.msg)
this.doSearch()
}
})
})
}
},
created() {
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,135 @@
const SUGGESTION_WC_INVITE_SECONDER_COMPONENT = {
template: `
<van-action-sheet v-model="visible" title="邀请附议人" class="height100">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
placeholder="请输入工号或者姓名查询"
@search="doSearch"
></van-search>
<van-tabs v-model="isInvite" @click="isInviteClick">
<van-tab title="已邀请" name="1"></van-tab>
<van-tab title="可邀请" name="0"></van-tab>
</van-tabs>
<van-checkbox-group v-model="tableSelection" v-if="tableData && tableData.length>0">
<van-cell-group >
<van-cell
v-for="(item, index) in tableData"
clickable
:key="pageForm.isInvite +':'+ item.loginName"
@click="tableRowToggle(index)"
>
<span slot="title">
{{item.userName}}
({{item.loginName}})
<van-tag :plain="false">
{{item.sex || '未知'}}
</van-tag>
</span>
<span slot="label" class="font-size0 van-color-text-assist">
{{item.unitName}}
</span>
<van-checkbox
:name="item"
ref="checkboxes"
slot="right-icon"
v-if="!pageForm.isInvite"></van-checkbox>
</van-cell>
</van-cell-group>
<div class="p10">
<van-pagination
v-model="pageForm.pageNumber"
:total-items="pageForm.totalCount"
:items-per-page="pageForm.pageSize"
@change="pageData"
></van-pagination>
<van-button @click="invite" type="primary" block :disabled="pageForm.isInvite" class="mt10">邀请</van-button>
</div>
</van-checkbox-group>
<van-empty v-else :figure="2"></van-empty>
</van-action-sheet>
`,
data() {
return {
visible: false,
secondedNum: 0,
record: {},
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 5,
totalCount: 0,
isInvite: false,
searchKeyword: null
},
isInvite: "0",
tableSelection: []
}
},
methods: {
onOpen(record) {
this.visible = true
this.record = record
this.pageData()
},
detail(id) {},
invite() {
if (this.tableSelection.length === 0) {
this.$toast("请先选择附议人后在点击邀请")
return
}
/* this.visible = false
this.$emit("refresh", null)*/
const loginNames = this.tableSelection.map((s) => s.loginName)
this.$axios
.post("/platform/suggestion/wc/mine/inviteSeconder", {
task: JSON.stringify({
processTaskId: this.record.processTaskId,
processInstId: this.record.processInstId
}),
proposalId: this.record.id,
seconders: JSON.stringify(loginNames)
})
.then((res) => {
if (res.code === 0) {
this.pageData()
this.$toast.success(res.msg)
this.tableSelection = []
// this.visible = false
this.$emit("refresh", null)
}
})
},
pageData() {
this.$axios
.post("/platform/suggestion/wc/mine/listSeconder", {
...this.pageForm,
sessionId: this.record.sessionId,
proposalId: this.record.id
})
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
isInviteClick(index, title) {
this.pageForm.isInvite = index === "1"
this.doSearch()
},
tableRowToggle(index) {
console.log(index)
}
}
}
@@ -0,0 +1,209 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="意见附议" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
:reverse-color="false"
:show-action="false"
@search="doSearch"
input-align="left"
placeholder="请输入意见内容搜索"
v-model="pageForm.brief"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
</van-dropdown-menu>
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已附议" name="1"></van-tab>
<van-tab title="未附议" name="0"></van-tab>
</van-tabs>
</van-sticky>
<van-pull-refresh v-model="tableRefreshing" @refresh="doSearch" style="min-height: calc(100vh - 90px)">
<van-list v-if="tableData && tableData.length>0" v-model="tableLoading" :finished="tableFinished" finished-text="" @load="pageData">
<div v-for="row in tableData" class="list-card">
<div class="list-card-body">
<div class="van-multi-ellipsis--l2" style="padding: 0 16px; font-weight: bold">{{row.brief}}</div>
<van-cell :value="row.code" title="意见编号"></van-cell>
<van-cell :value="row.createUserName" title="撰写人"></van-cell>
<van-cell :value="row.typeName" title="意见类别"></van-cell>
<van-cell :value="row.sessionName" title="届次"></van-cell>
<van-cell :value="row.delegationName" title="代表团"></van-cell>
<van-cell :value="row.processInstanceNodeName" title="当前节点"></van-cell>
<div class="list-card-footer">
<van-button @click="openView(row)" size="small">查看</van-button>
<van-button v-if="row.processInstanceTaskStatus==='ACTIVE'" @click="openApproval(row)" type="primary" size="small">
附议
</van-button>
</div>
</div>
</div>
</van-list>
<van-empty
v-if="tableData.length===0"
image="/assets/platform/plugins/vant-green/images/nodata/nodata.png"
description="暂无数据"
></van-empty>
</van-pull-refresh>
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
<van-sticky>
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
</van-sticky>
<div style="height: calc(100vh - 44px); overflow-y: auto">
<info ref="infoRef"></info>
<div v-if="showApprovalForm">
<div class="process-title">{{formData.processInstanceNodeName}}</div>
<van-form ref="vanFormRef">
<van-field
label="签字"
name="approvalSignature"
v-model="formData.signature"
required
:rules="[{ required: true, message: '请签字' }]"
class="direction-column-field"
>
<h5-signature v-model="formData.approvalSignature" slot="input"></h5-signature>
</van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click.submit="doApproval('REJECT')">拒绝</van-button>
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
</div>
</div>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
store,
components: {
info: H5_SUGGESTION_WC_INFO_COMPONENT
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null,
approvalText: "0",
approval: false
},
tableData: [],
tableLoading: false,
tableFinished: false,
tableRefreshing: false,
sessionOptions: [],
infoShow: false,
formData: {},
showApprovalForm: false
}
},
methods: {
openView(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
})
},
openApproval(row) {
this.infoShow = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
this.formData = row.approvalParam
this.showApprovalForm = true
})
},
doApproval(approvalType) {
this.formData.bpmTaskApprovalType = approvalType
this.$refs.vanFormRef
.validate()
.then(() => {
this.$axios
.post("/platform/suggestion/wc/seconded/approval", {
approval: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.infoShow = false
this.$toast.success(res.msg)
this.doSearch()
}
})
})
.catch(() => {})
},
sessionChange(val) {
this.doSearch()
},
listSession() {
this.$axios.post("/platform/suggestion/wc/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
.map((v) => ({
text: v.fullName,
value: v.id
}))
.concat([{ text: "全部届次", value: null }])
if (this.sessionOptions.length > 0) {
this.pageForm.sessionId = this.sessionOptions[0].value
this.pageData()
}
}
})
},
pageData() {
this.tableLoading = true
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/wc/delegation/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
if (this.tableData.length >= this.pageForm.totalCount) {
this.tableFinished = true
}
this.pageForm.pageNumber++
}
})
.finally(() => {
loading.close()
this.tableLoading = false
this.tableRefreshing = false
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.tableData = []
this.pageData()
}
},
created() {
this.pageData()
this.listSession()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,273 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar title="撰写意见" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
<van-cell-group>
<van-form @submit="doSave">
<van-field v-model="formData.createUserName" name="createUserName" label="代表姓名" readonly></van-field>
<van-field v-model="formData.createTime" name="createTime" label="提案时间" readonly></van-field>
<van-field
v-model="formData.sessionName"
name="sessionName"
label="所属教代会"
required
readonly
clickable
@click="showSessionPicker = true"
placeholder="请选择"
:rules="[{ required: true, message: '请选择教代会' }]"
></van-field>
<van-popup v-model="showSessionPicker" position="bottom">
<van-picker
show-toolbar
:columns="sessionOptions"
value-key="fullName"
@cancel="showSessionPicker = false"
@confirm="sessionConfirm"
></van-picker>
</van-popup>
<van-field
v-model="formData.delegationName"
name="delegationName"
label="所属代表团"
required
readonly
clickable
@click="showDelegationPicker = true"
placeholder="请选择"
:rules="[{ required: true, message: '请选择代表团' }]"
></van-field>
<van-popup v-model="showDelegationPicker" position="bottom">
<van-picker
show-toolbar
:columns="delegationOptions"
value-key="name"
@cancel="showDelegationPicker = false"
@confirm="delegationConfirm"
></van-picker>
</van-popup>
<van-field v-model="formData.unitName" name="unitName" label="单位" readonly></van-field>
<van-field
v-model="formData.mobile"
name="mobile"
label="联系电话"
required
readonly
:rules="[{ required: true, message: '请填写联系电话' }]"
></van-field>
<van-field
v-model="formData.typeName"
name="typeName"
label="意见类别"
required
readonly
clickable
@click="showTypePicker = true"
placeholder="请选择"
:rules="[{ required: true, message: '请选择意见类别' }]"
></van-field>
<van-popup v-model="showTypePicker" position="bottom">
<van-picker show-toolbar :columns="typeOptions" value-key="name" @cancel="showTypePicker = false" @confirm="typeConfirm"></van-picker>
</van-popup>
<van-field label="意见内容" name="brief" v-model="formData.brief" required class="direction-column-field">
<template #input>
<text-editor v-model="formData.brief"></text-editor>
</template>
</van-field>
<van-field label="附件" name="files" class="direction-column-field">
<h5-file-upload
slot="input"
:value.sync="formData.files"
:upload_number="5"
upload_mode="file"
upload_result_category="array"
upload_result_type="url"
complete_result
></h5-file-upload>
</van-field>
<van-cell cell-class="form-button-cell" v-if="showButton">
<van-button type="primary" size="large" block native-type="submit">保存到我的意见</van-button>
</van-cell>
</van-form>
</van-cell-group>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
store,
data() {
return {
formData: {},
showSourcePicker: false,
showSessionPicker: false,
showDelegationPicker: false,
showCommitteePicker: false,
showTypePicker: false,
sourceOptions: [],
sessionOptions: [],
delegationOptions: [],
typeOptions: [],
proposalConfig: {},
noticeDialogVisible: false,
showButton: true
}
},
methods: {
doSave(values) {
if (!this.formData.brief) {
this.$toast("请填写意见内容")
return
}
const briefLength = removeHTMLTag(this.formData.brief)
if (briefLength < this.suggestionConfig.briefMinLength) {
this.$toast("意见内容最少" + this.suggestionConfig.briefMinLength + "个字")
return
}
const loading = createListLoading()
this.$axios
.post("/platform/suggestion/wc/write/save", { info: JSON.stringify(this.formData) })
.then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.$pjaxReplace("/platform/h5/suggestion/wc/mine")
}
})
.finally(() => {
loading.clear()
})
},
sessionConfirm(val) {
this.showSessionPicker = false
this.formData.sessionName = val.fullName
this.formData.sessionId = val.id
},
delegationConfirm(val) {
this.showDelegationPicker = false
this.formData.delegationId = val.id
this.formData.delegationName = val.name
},
typeConfirm(val) {
this.showTypePicker = false
this.formData.typeId = val.id
this.formData.typeName = val.name
},
listSuggestionType() {
this.$axios.post("/platform/suggestion/tc/common/listProposalType").then((res) => {
if (res.code === 0) {
this.typeOptions = res.data
}
})
},
getSuggestionConfig() {
return this.$axios.post("/platform/suggestion/tc/common/config").then((res) => {
if (res.code === 0) {
this.suggestionConfig = res.data
}
})
},
//教代会change
async meetingChange(val) {
this.$set(this.formData, "delegationId", null)
this.formData.delegationOptions = []
this.listDelegation()
this.searchSelfDelegation()
},
listDelegation() {
return this.$axios.post("/platform/suggestion/wc/common/listDelegation", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
})
},
// 查询开放的教代会届次
listOpenSession(isModify = false) {
return this.$axios.post("/platform/suggestion/wc/common/listOpenSession").then(async (res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (!isModify && this.sessionOptions) {
this.$set(this.formData, "sessionId", this.sessionOptions[0].id)
this.$set(this.formData, "sessionName", this.sessionOptions[0].fullName)
await this.listDelegation()
await this.searchSelfDelegation()
}
if (isModify) {
const session = this.sessionOptions.find((v) => v.id === this.formData.sessionId)
this.$set(this.formData, "sessionName", session?.fullName)
await this.listDelegation()
const delegation = this.delegationOptions.find((v) => v.id === this.formData.delegationId)
this.$set(this.formData, "delegationName", delegation?.name)
if (this.formData.typeId) {
this.typeConfirm(this.typeOptions.find((v) => v.id === this.formData.typeId))
}
}
// await this.listDelegation()
}
})
},
//查询自己有权限的代表团
searchSelfDelegation() {
return this.$axios.post("/platform/suggestion/wc/write/selfDelegation", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.$set(this.formData, "delegationId", res.data)
this.$set(this.formData, "delegationName", this.delegationOptions.find((item) => item.id === res.data)?.name)
}
})
},
init() {
const id = GetQueryString("id")
if (id) {
this.$axios.post("/platform/suggestion/wc/write/detail", { id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.listOpenSession(true)
}
})
} else {
this.noticeDialogVisible = true
this.listOpenSession(false)
this.$set(this.formData, "createUserId", this.$store.state.user.id)
this.$set(this.formData, "createUserName", this.$store.state.user.username)
this.$set(this.formData, "createUserLoginName", this.$store.state.user.loginname)
this.$set(this.formData, "createTime", this.$moment().format("YYYY-MM-DD"))
this.$set(this.formData, "mobile", this.$store.state.user.mobile)
this.$set(this.formData, "unitName", this.$store.state.user.unit?.name)
}
}
},
created() {
this.init()
this.listSuggestionType()
this.getSuggestionConfig()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,91 @@
const SUGGESTION_BOX_INFO = {
template: /*language=HTML*/ `
<van-action-sheet v-model="visible" title="查看详情">
<div class="detail-container">
<van-cell-group title="基本信息">
<van-cell title="姓名">{{viewData.userName}}</van-cell>
<van-cell title="工号">{{viewData.loginName}}</van-cell>
<van-cell title="单位">{{viewData.unitName}}</van-cell>
<van-cell title="工会">{{viewData.unionName}}</van-cell>
<van-cell title="标题">{{viewData.title}}</van-cell>
<van-cell title="意见建议内容" class="direction-column-cell">{{viewData.content}}</van-cell>
</van-cell-group>
<template v-for="task in doneTasks">
<van-cell-group :title="task.displayName" v-if="task.ext.isFirstTaskNode">
<van-cell title="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})
</van-cell>
<van-cell title="申请时间">{{ task.finishTime }}</van-cell>
<van-cell title="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</van-cell>
</van-cell-group>
<van-cell-group :title="task.displayName" v-else>
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
</van-cell>
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
<van-cell title="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</van-cell>
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
<div v-html="task.taskFormData.tf_opinion"></div>
</van-cell>
</van-cell-group>
</template>
</div>
<slot></slot>
</van-action-sheet>
`,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data(){
return{
visible: false,
viewData: {},
doneTasks: [],
row: null,
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
this.getDoneTasks()
},
// 关闭
onClose(){
this.visible = false
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/suggestionBox/common/info', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data || {}
}
})
},
// 查看提案
openView(id) {
this.$nextTick(() => {
this.$refs.infoDialogRef.onOpen(id)
})
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
}
}
@@ -0,0 +1,133 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的建言献策" placeholder
fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入关键字搜索"
@search="doSearch"
></van-search>
</van-sticky>
<table-list api="/platform/suggestionBox/mine/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef" title="title">
<template v-slot="{index,row}">
<table-column label="申请人">{{row.userName}}</table-column>
<table-column label="申请时间">{{row.submitTime}}</table-column>
<table-column label="当前节点">{{row.taskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskKey === 'startTask' || !row.instanceId"
@click="onEdit(row)">
<i class="fa fa-edit"></i>
<span>编辑</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(item)">
<i class="fa fa-undo"></i>
<span>撤回</span>
</div>
<div class="action-btn delete" v-if="row.taskKey === 'startTask' || !row.instanceId"
@click="onDelete(row)">
<i class="fa fa-trash"></i>
<span>删除</span>
</div>
</template>
</table-list>
<suggestion-box-info ref="suggestionBoxInfoRef"></suggestion-box-info>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: '#app',
store,
components: {
'suggestion-box-info': SUGGESTION_BOX_INFO
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null
},
}
},
methods: {
historyBack,
onReady(){
this.doSearch()
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
// 查看详情
onView(row) {
this.showApprovalForm = false
this.$refs.suggestionBoxInfoRef.onOpen(row)
},
// 编辑
onEdit(row) {
this.$pjaxReplace("/platform/suggestionBox/write/h5?bizId=" + row.id + "&taskId=" + (row.startTaskId || ''))
},
// 撤回
onRevoke(row) {
this.$dialog.confirm({
title: '提示',
message: '您确定要撤回吗?',
}).then(() => {
this.$axios.post('/flow/common/revokeTask', {taskId: row.startTaskId}).then(res => {
if (res.code === 0) {
this.$toast.success('撤回成功');
this.doSearch();
}
})
}).catch(() => {
});
},
onDelete(id) {
this.$dialog.confirm({
title: '提示',
message: '您确定要删除吗?',
}).then(() => {
this.$axios.post('/platform/suggestionBox/mine/delete', {id}).then(res => {
if (res.code === 0) {
this.$toast.success('删除成功');
this.doSearch();
}
})
}).catch(() => {
});
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,83 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="建言献策查询" placeholder
fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入关键字搜索"
@search="doSearch"
></van-search>
</van-sticky>
<table-list api="/platform/suggestionBox/query/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef" title="title">
<template v-slot="{index,row}">
<table-column label="申请人">{{row.userName}}</table-column>
<table-column label="申请时间">{{row.submitTime}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
</template>
</table-list>
<suggestion-box-info ref="suggestionBoxInfoRef"></suggestion-box-info>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: '#app',
store,
components: {
'suggestion-box-info': SUGGESTION_BOX_INFO
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
},
}
},
methods: {
historyBack,
onReady() {
this.doSearch()
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
// 查看详情
onView(row) {
this.showApprovalForm = false
this.$refs.suggestionBoxInfoRef.onOpen(row)
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,167 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar title="填写建言献策" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
<div class="form-container">
<van-form ref="formRef">
<van-cell-group title="基本信息">
<van-field v-model="formData.userName" label="姓名" readonly></van-field>
<van-field v-model="formData.loginName" label="工号" readonly></van-field>
<van-field v-model="formData.unitName" label="单位" readonly></van-field>
<van-field v-model="formData.unionName" label="工会" readonly></van-field>
<van-field
v-model="formData.title"
name="title"
label="标题"
placeholder="请输入标题"
:rules="[{ required: true, message: '请填写标题' }]"
required
maxlength="100"
show-word-limit
></van-field>
<van-field
v-model="formData.content"
name="content"
label="意见建议内容"
type="textarea"
placeholder="请输入内容"
:rules="[{ required: true, message: '请填写内容' }]"
maxlength="500"
show-word-limit
rows="5"
></van-field>
</van-cell-group>
<!-- 按钮区域 -->
<div class="form-actions">
<van-button plain type="info" @click="onSave">保存</van-button>
<van-button type="primary" @click="onSubmit" v-if="!taskId">提交</van-button>
<van-button type="primary" @click="onFinishTask" v-else>提交</van-button>
</div>
</van-form>
</div>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formData: {},
formRules: {
title: [{required: true, message: "必填", trigger: ["change", "blur"]}],
content: [{required: true, message: "必填", trigger: ["change", "blur"]}]
}
}
},
methods: {
historyBack,
// 保存
async onSave() {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: '提示',
message: '您确定保存吗?',
}).then(() => {
this.$axios.post('/platform/suggestionBox/write/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$toast.success("保存成功");
pjaxReplace("/platform/suggestionBox/mine/h5")
}
})
}).catch(() => {
// 取消操作
});
} catch (e) {
// 表单验证失败
console.log('表单验证失败', error);
}
},
// 提交
async onSubmit() {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: '提示',
message: '您确定提交吗?',
}).then(() => {
this.$axios.post('/platform/suggestionBox/write/submit', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$toast.success("提交成功");
pjaxReplace("/platform/suggestionBox/mine/h5")
}
})
}).catch(() => {
// 取消操作
});
} catch (e) {
// 表单验证失败
console.log('表单验证失败', error);
}
},
// 再次提交
async onFinishTask() {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: '提示',
message: '您确定要提交吗?',
}).then(() => {
this.$axios.post('/platform/suggestionBox/write/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$toast.success("提交成功");
pjaxReplace("/platform/h5/suggestionBox/mine")
}
})
}).catch(() => {
// 取消操作
});
} catch (e) {
// 表单验证失败
console.log('表单验证失败', error);
}
},
// 初始化
init() {
if (this.bizId) {
this.$axios.post("/platform/suggestionBox/write/info", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data;
}
})
} else {
const {username, loginname, id, unit, union, mobile} = this.$store.state.user;
this.formData = {
userName: username,
loginName: loginname,
submitterId: id,
unitId: unit?.id,
unitName: unit?.name,
unionId: union?.id,
unionName: union?.name,
concat: mobile
}
}
}
},
created() {
this.init();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,176 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="建言献策审核" placeholder
fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入关键字搜索"
@search="doSearch"
></van-search>
<van-tabs v-model="pageForm.approvalText"
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
<van-tab title="已审核" name="1"></van-tab>
<van-tab title="未审核" name="0"></van-tab>
</van-tabs>
</van-sticky>
<table-list api="/platform/suggestionBox/xgh/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef" title="title">
<template v-slot="{index,row}">
<table-column label="申请人">{{row.userName}}</table-column>
<table-column label="申请时间">{{row.submitTime}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
<i class="fa fa-edit"></i>
<span>审核</span>
</div>
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(item)">
<i class="fa fa-undo"></i>
<span>撤回</span>
</div>
</template>
</table-list>
<suggestion-box-info ref="suggestionBoxInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">{{formData.taskName}}</div>
<van-form ref="formRef">
<van-field
v-model="formData.tf_opinion"
name="tf_opinion"
label="审批意见"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
required
maxlength="100"
show-word-limit
></van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
</div>
</div>
</suggestion-box-info>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: '#app',
store,
components: {
'suggestion-box-info': SUGGESTION_BOX_INFO
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: "",
sessionId: null,
approvalText: "0",
approval: false
},
formData: {},
showApprovalForm: false
}
},
methods: {
historyBack,
onReady() {
this.doSearch()
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
// 查看详情
onView(row) {
this.showApprovalForm = false
this.$refs.suggestionBoxInfoRef.onOpen(row)
},
onApproval(row) {
this.showApprovalForm = true
this.$refs.suggestionBoxInfoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
},
async handleTaskAction(val) {
try {
await this.$refs.formRef.validate();
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.suggestionBoxInfoRef.onClose()
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {
})
} catch (error) {
}
},
// 撤回
onRevoke(row) {
this.$dialog.confirm({
title: '提示',
message: '您确定要撤回吗?',
}).then(() => {
this.$axios.post('/flow/common/revokeTask', {taskId: row.startTaskId}).then(res => {
if (res.code === 0) {
this.$toast.success('撤回成功');
this.doSearch();
}
})
}).catch(() => {
});
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,172 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak style="padding-bottom: 70px;">
<van-nav-bar title="代表阅览" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
<van-sticky offset-top="46px">
<van-search
v-model="pageForm.searchKeyword"
:show-action="false"
:reverse-color="false"
input-align="left"
placeholder="请输入姓名/工号搜索"
@search="doSearch"
></van-search>
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions"
@change="sessionChange"></van-dropdown-item>
<van-dropdown-item
v-if="pageForm.sessionId"
v-model="pageForm.delegationId"
:options="delegationOptions"
@change="doSearch"
></van-dropdown-item>
<!-- <van-dropdown-item ref="moreDropDownItemOption" title="更多查询" multiple :options="moreOptions"-->
<!-- @change="moreOptionChange">-->
<!-- <van-button type="primary" class="margin-top20 width100" @click="$refs.moreDropDownItemOption.toggle()">-->
<!-- 查询-->
<!-- </van-button>-->
<!-- </van-dropdown-item>-->
</van-dropdown-menu>
</van-sticky>
<div class="export-buttons" style="position: fixed; bottom: 0; left: 0; right: 0; padding: 10px; display: flex; gap: 10px; background: white; border-top: 1px solid #eee; z-index: 1000; box-shadow: 0 -2px 8px rgba(0,0,0,0.1);">
<van-button type="primary" size="medium" @click="exportXlsx" style="flex: 1;">
<i class="fa fa-file-excel-o"></i> 导出Excel
</van-button>
<van-button type="info" size="medium" @click="exportDocx" style="flex: 1;">
<i class="fa fa-file-word-o"></i> 导出Word
</van-button>
</div>
<table-list api="/platform/teacherCongress/delegate/read/pageData" :page_form.sync="pageForm" json
@ready="onReady"
ref="tableListRef"
style="padding-bottom: 65px">
<template v-slot="{index,row}">
<table-column label="代表姓名">{{row.userName}}</table-column>
<table-column label="代表工号">{{row.loginName}}</table-column>
<table-column label="代表团">{{delegationOptions.find(v=>v.id===row.delegationId)?.name}}</table-column>
<table-column label="代表身份">
{{moreOptions.find(v=>v.title==='代表身份')?.options.find(v=>v.id===row.roleId)?.name}}
</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
</template>
</table-list>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
store,
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: null,
sessionId: null,
delegationId: null,
roleId: null
},
sessionOptions: [],
delegationOptions: [],
roleOptions: [],
moreOptions: []
}
},
methods: {
historyBack,
moreOptionChange(options) {
this.moreOptions = options
this.moreOptions.forEach((item) => {
const checkedItems = item.options.filter((obj) => obj.checked)
if (item.title === "代表身份") {
this.$set(
this.pageForm,
"roleIds",
checkedItems.map((v) => v.id)
)
}
})
this.doSearch()
},
sessionChange() {
this.pageForm.delegationId = null
if (this.pageForm.sessionId) {
this.listDelegation()
} else {
this.delegationOptions = [
{
text: "全部代表团",
value: null
}
]
}
this.doSearch()
},
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data.map((v) => ({text: v.fullName, value: v.id}))
this.pageForm.sessionId = res.data[0].id
this.sessionChange()
}
})
},
listDelegation() {
this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.pageForm.sessionId}).then((res) => {
if (res.code === 0) {
this.delegationOptions = [
{
text: "全部代表团",
value: null
}
].concat(res.data.map((v) => ({...v, text: v.name, value: v.id})))
}
})
},
listRole() {
this.$axios.post("/platform/teacherCongress/common/listDelegateRole").then((res) => {
if (res.code === 0) {
this.moreOptions.push({
title: "代表身份",
options: res.data.map((v) => ({...v, text: v.name}))
})
}
})
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
onReady() {
this.listRole()
this.listSession()
},
exportXlsx() {
this.$downLoad("/platform/teacherCongress/delegate/read/exportXlsx", this.pageForm)
},
exportDocx() {
this.$downLoad("/platform/teacherCongress/delegate/read/exportDocx", this.pageForm)
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,908 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<style>
*{
box-sizing: border-box;
}
.mobile-seat-container {
background: #f7f8fa;
min-height: 100vh;
padding-bottom: 160px;
}
.mobile-header {
background: white;
padding: 16px;
border-bottom: 1px solid #ebedf0;
/*position: sticky;*/
/*top: 0;*/
z-index: 10;
}
.mobile-header .meeting-title {
font-size: 18px;
font-weight: 600;
color: #323233;
margin-bottom: 4px;
}
.mobile-header .meeting-time {
font-size: 14px;
color: #969799;
}
.mobile-stage {
text-align: center;
padding: 8px;
background: transparent;
margin: 16px;
border-radius: 16px;
position: relative;
overflow: hidden;
}
.stage-svg {
width: 100%;
height: 80px;
margin-bottom: 8px;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.15));
}
.stage-text {
font-size: 18px;
font-weight: 700;
color: #1565c0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
background: linear-gradient(45deg, #1976d2, #42a5f5);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-top: -4px;
}
.mobile-legend {
display: flex;
justify-content: space-around;
padding: 12px 16px;
background: white;
margin: 0 16px 16px;
border-radius: 8px;
font-size: 12px;
}
.mobile-legend-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.mobile-legend-seat {
width: 20px;
height: 20px;
}
.mobile-seat-area {
padding: 0;
}
.zoom-controls {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
padding: 8px 16px;
margin-bottom: 8px;
/*background: rgba(128, 128, 128, 0.1);*/
border-radius: 8px;
}
.zoom-controls .van-button {
background: rgba(128, 128, 128, 0.2) !important;
border: 1px solid rgba(128, 128, 128, 0.3) !important;
color: #666 !important;
font-size: 11px;
padding: 2px 6px !important;
height: 24px !important;
min-width: auto !important;
}
.zoom-controls .van-button:disabled {
background: rgba(128, 128, 128, 0.1) !important;
color: #ccc !important;
}
.zoom-level {
display: flex;
align-items: center;
gap: 3px;
font-size: 10px;
font-weight: 500;
color: #666;
padding: 3px 6px;
background: rgba(128, 128, 128, 0.15);
border-radius: 6px;
min-width: 45px;
justify-content: center;
}
.seat-grid-container {
width: 100%;
min-height: 300px;
position: relative;
padding: 16px;
}
.mobile-seat-grid {
display: grid;
/*grid-template-columns: repeat(10, 1fr);*/
gap: 4px;
background: white;
padding: 12px;
border-radius: 12px;
width: 100%;
user-select: none;
-webkit-user-select: none;
overflow: auto;
max-height: 60vh;
-webkit-overflow-scrolling: touch;
/* 隐藏滚动条 */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE 和 Edge */
}
/* 隐藏 Webkit 浏览器的滚动条 */
.mobile-seat-grid::-webkit-scrollbar {
display: none;
}
.mobile-seat {
width: 32px;
height: 32px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
position: relative;
touch-action: manipulation;
transform-origin: center;
}
.mobile-seat-icon {
width: 24px;
height: 24px;
margin-bottom: 1px;
}
.mobile-seat-number {
font-size: 8px;
font-weight: 600;
text-align: center;
line-height: 1;
}
/* 座位状态样式 */
.mobile-seat.available .seat-back {
fill: #f8f9fa;
stroke: #dee2e6;
stroke-width: 1;
}
.mobile-seat.available .seat-cushion {
fill: #ffffff;
stroke: #dee2e6;
stroke-width: 1;
}
.mobile-seat.available .seat-armrest {
fill: #e9ecef;
stroke: #dee2e6;
stroke-width: 1;
}
.mobile-seat.available .mobile-seat-number {
color: #666;
}
.mobile-seat.available:active .seat-back {
fill: #e3f2fd;
stroke: #1867b0;
}
.mobile-seat.available:active .seat-cushion {
fill: #f0f8ff;
stroke: #1867b0;
}
.mobile-seat.available:active .seat-armrest {
fill: #e3f2fd;
stroke: #1867b0;
}
.mobile-seat.occupied .seat-back {
fill: #adb5bd;
stroke: #6c757d;
stroke-width: 1;
}
.mobile-seat.occupied .seat-cushion {
fill: #d0d0d0;
stroke: #6c757d;
stroke-width: 1;
}
.mobile-seat.occupied .seat-armrest {
fill: #adb5bd;
stroke: #6c757d;
stroke-width: 1;
}
.mobile-seat.occupied .mobile-seat-number {
color: #666;
}
.mobile-seat.occupied {
cursor: not-allowed;
}
.mobile-seat.selected .seat-back {
fill: #0d47a1;
stroke: #1867b0;
stroke-width: 2;
}
.mobile-seat.selected .seat-cushion {
fill: #1867b0;
stroke: #0d47a1;
stroke-width: 2;
}
.mobile-seat.selected .seat-armrest {
fill: #0d47a1;
stroke: #1867b0;
stroke-width: 2;
}
.mobile-seat.selected .mobile-seat-number {
font-weight: 700;
}
.mobile-seat.my-seat .seat-back {
fill: #c62828;
stroke: #ff3742;
stroke-width: 2;
}
.mobile-seat.my-seat .seat-cushion {
fill: #ff4757;
stroke: #c62828;
stroke-width: 2;
}
.mobile-seat.my-seat .seat-armrest {
fill: #c62828;
stroke: #ff3742;
stroke-width: 2;
}
.mobile-seat.my-seat .mobile-seat-number {
font-weight: 700;
}
.mobile-seat.disabled .seat-back {
fill: #f5f5f5;
stroke: #cccccc;
stroke-width: 1;
}
.mobile-seat.disabled .seat-cushion {
fill: #f0f0f0;
stroke: #cccccc;
stroke-width: 1;
}
.mobile-seat.disabled .seat-armrest {
fill: #f5f5f5;
stroke: #cccccc;
stroke-width: 1;
}
.mobile-seat.disabled .mobile-seat-number {
color: #999;
}
.mobile-seat.disabled {
cursor: not-allowed;
opacity: 0.6;
}
.mobile-bottom-panel {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
border-top: 1px solid #ebedf0;
padding: 16px;
z-index: 200;
}
.mobile-selected-info {
background: #f0f8ff;
border: 1px solid #1989fa;
border-radius: 8px;
padding: 12px;
margin-bottom: 12px;
font-size: 14px;
}
.mobile-selected-info .seat-info {
color: #1989fa;
font-weight: 600;
}
.mobile-my-seat-info {
background: #fff2f0;
border: 1px solid #ff4757;
border-radius: 8px;
padding: 12px;
margin-top: 16px;
font-size: 14px;
}
.mobile-my-seat-info .seat-info {
color: #ff4757;
font-weight: 600;
}
.mobile-loading {
text-align: center;
padding: 60px 20px;
color: #969799;
}
/* 会议选择弹窗样式 */
.meeting-modal-content {
max-height: 70vh;
overflow-y: auto;
}
.meeting-modal-content .van-nav-bar__text {
display: none;
}
.meeting-item {
border: 1px solid #ebedf0;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
background: white;
transition: all 0.2s ease;
}
.meeting-item:active {
background: #f0f8ff;
border-color: #1989fa;
}
.meeting-item.selected {
background: #f0f8ff;
border-color: #1989fa;
}
.meeting-name {
font-size: 16px;
font-weight: 600;
color: #323233;
margin-bottom: 8px;
}
.meeting-info {
font-size: 14px;
color: #646566;
margin-bottom: 4px;
}
.meeting-time {
font-size: 12px;
color: #969799;
}
@media (max-width: 375px) {
.mobile-seat-grid {
grid-template-columns: repeat(8, 28px);
gap: 3px;
padding: 10px;
}
.mobile-seat {
width: 28px;
height: 28px;
}
.mobile-seat-icon {
width: 20px;
height: 20px;
}
.mobile-seat-number {
font-size: 8px;
}
}
</style>
<div id="app" v-cloak>
<van-nav-bar title="会议选座" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
<!-- 会议选择弹窗 -->
<van-popup v-model="showMeetingModal" position="bottom" :close-on-click-overlay="false">
<div class="meeting-modal-content">
<van-nav-bar title="选择会议"></van-nav-bar>
<div style="padding: 16px;">
<div v-for="meeting in meetings" :key="meeting.id"
:class="['meeting-item', { selected: selectedMeetingId === meeting.id }]"
@click="selectMeeting(meeting)">
<div class="meeting-name">{{ meeting.name }}</div>
<div class="meeting-info">地点:{{ meeting.address }}</div>
<div class="meeting-time">时间:{{ meeting.startTime }} 至 {{ meeting.endTime }}</div>
</div>
<div style="display: flex; gap: 22px">
<van-button block @click="showMeetingModal = false" style="margin-top: 16px;">
取消选择
</van-button>
<van-button block type="info" :disabled="!selectedMeetingId"
@click="confirmMeetingSelection" style="margin-top: 16px;">
确认选择
</van-button>
</div>
</div>
</div>
</van-popup>
<div class="mobile-seat-container">
<!-- 头部信息 -->
<div class="mobile-header" v-if="meeting">
<div class="meeting-title">{{ meeting.name }}</div>
<div class="meeting-time">{{ meeting.startTime }} 至 {{ meeting.endTime }}</div>
</div>
<!-- 主席台 -->
<div class="mobile-stage">
<svg class="stage-svg" viewBox="0 0 320 100" xmlns="http://www.w3.org/2000/svg">
<!-- 背景装饰 -->
<rect x="0" y="0" width="320" height="100" fill="url(#bgGradient)" rx="12" ry="12"/>
<!-- 主舞台基座 -->
<ellipse cx="160" cy="75" rx="140" ry="15" fill="url(#baseGradient)" opacity="0.8"/>
<!-- 主舞台平台 -->
<path d="M 30 45 Q 30 35 40 35 L 280 35 Q 290 35 290 45 L 285 65 Q 285 70 280 70 L 40 70 Q 35 70 35 65 Z"
fill="url(#stageGradient)" stroke="url(#stageStroke)" stroke-width="2"/>
<!-- 台阶层次 -->
<path d="M 45 50 Q 45 45 50 45 L 270 45 Q 275 45 275 50 L 272 62 Q 272 65 270 65 L 50 65 Q 47 65 47 62 Z"
fill="url(#stepGradient)" stroke="#1976d2" stroke-width="1"/>
<!-- 装饰花纹 -->
<path d="M 60 52 Q 65 50 70 52 Q 75 54 80 52" stroke="#ffffff" stroke-width="1.5" fill="none" opacity="0.7"/>
<path d="M 240 52 Q 245 50 250 52 Q 255 54 260 52" stroke="#ffffff" stroke-width="1.5" fill="none" opacity="0.7"/>
<!-- 中央装饰 -->
<circle cx="160" cy="52" r="8" fill="url(#centerGradient)" stroke="#ffffff" stroke-width="1" opacity="0.9"/>
<circle cx="160" cy="52" r="4" fill="#ffd700" opacity="0.8"/>
<!-- 聚光灯光束 -->
<path d="M 80 20 L 85 35 L 75 35 Z" fill="url(#lightGradient)" opacity="0.6"/>
<path d="M 160 15 L 167 35 L 153 35 Z" fill="url(#lightGradient)" opacity="0.8"/>
<path d="M 240 20 L 245 35 L 235 35 Z" fill="url(#lightGradient)" opacity="0.6"/>
<!-- 聚光灯 -->
<circle cx="80" cy="18" r="4" fill="#ffd700" stroke="#ffb300" stroke-width="1"/>
<circle cx="160" cy="13" r="5" fill="#ffd700" stroke="#ffb300" stroke-width="1"/>
<circle cx="240" cy="18" r="4" fill="#ffd700" stroke="#ffb300" stroke-width="1"/>
<!-- 星光效果 -->
<g opacity="0.8">
<path d="M 100 25 L 102 30 L 107 30 L 103 33 L 105 38 L 100 35 L 95 38 L 97 33 L 93 30 L 98 30 Z" fill="#ffd700"/>
<path d="M 220 28 L 222 32 L 226 32 L 223 35 L 225 39 L 220 36 L 215 39 L 217 35 L 214 32 L 218 32 Z" fill="#ffd700"/>
</g>
<!-- 渐变定义 -->
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#e3f2fd;stop-opacity:1" />
<stop offset="100%" style="stop-color:#bbdefb;stop-opacity:1" />
</linearGradient>
<linearGradient id="stageGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#1e88e5;stop-opacity:1" />
<stop offset="30%" style="stop-color:#1976d2;stop-opacity:1" />
<stop offset="70%" style="stop-color:#1565c0;stop-opacity:1" />
<stop offset="100%" style="stop-color:#0d47a1;stop-opacity:1" />
</linearGradient>
<linearGradient id="stageStroke" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#42a5f5;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1565c0;stop-opacity:1" />
</linearGradient>
<linearGradient id="stepGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#42a5f5;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1976d2;stop-opacity:1" />
</linearGradient>
<linearGradient id="baseGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#90caf9;stop-opacity:0.6" />
<stop offset="100%" style="stop-color:#1976d2;stop-opacity:0.8" />
</linearGradient>
<radialGradient id="centerGradient" cx="50%" cy="50%" r="50%">
<stop offset="0%" style="stop-color:#ffffff;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1976d2;stop-opacity:1" />
</radialGradient>
<linearGradient id="lightGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#fff9c4;stop-opacity:0.9" />
<stop offset="100%" style="stop-color:#fff59d;stop-opacity:0.3" />
</linearGradient>
</defs>
</svg>
<div class="stage-text">主席台</div>
</div>
<!-- 图例 -->
<div class="mobile-legend">
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f8f9fa" stroke="#dee2e6"
stroke-width="1"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ffffff" stroke="#dee2e6"
stroke-width="1"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
stroke-width="1"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
stroke-width="1"/>
</svg>
<span>可选</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#adb5bd" stroke="#6c757d"
stroke-width="1"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#d0d0d0" stroke="#6c757d"
stroke-width="1"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
stroke-width="1"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
stroke-width="1"/>
</svg>
<span>占用</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#0d47a1" stroke="#1867b0"
stroke-width="2"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#1867b0" stroke="#0d47a1"
stroke-width="2"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
stroke-width="2"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
stroke-width="2"/>
</svg>
<span>选中</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#c62828" stroke="#ff3742"
stroke-width="2"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ff4757" stroke="#c62828"
stroke-width="2"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
stroke-width="2"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
stroke-width="2"/>
</svg>
<span>我的</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f5f5f5" stroke="#cccccc"
stroke-width="1"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#f0f0f0" stroke="#cccccc"
stroke-width="1"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
stroke-width="1"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
stroke-width="1"/>
</svg>
<span>禁用</span>
</div>
</div>
<!-- 座位区域 -->
<div class="mobile-seat-area">
<van-loading v-if="loading" type="spinner" color="#1989fa" class="mobile-loading">
正在加载座位信息...
</van-loading>
<div v-else class="seat-grid-container">
<div class="mobile-seat-grid" id="seatGrid" :style="gridStyle">
<div v-for="seat in seats" :key="seat.id"
:class="getSeatClass(seat)"
class="mobile-seat"
@click="selectSeat(seat)">
<svg class="mobile-seat-icon" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" class="seat-back"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" class="seat-cushion"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
</svg>
<span class="mobile-seat-number">{{ seat.rowNumber }}-{{ seat.colNumber }}</span>
</div>
</div>
</div>
</div>
<!-- 缩放控制按钮 -->
<div class="zoom-controls">
<van-button type="default" size="mini" @click="zoomOut" :disabled="currentScale <= 0.5">
<van-icon name="minus" size="12" />
缩小
</van-button>
<div class="zoom-level">
<van-icon name="search" size="12" />
{{ Math.round(currentScale * 100) }}%
</div>
<van-button type="default" size="mini" @click="resetZoom">
<van-icon name="replay" size="12" />
重置
</van-button>
<van-button type="default" size="mini" @click="zoomIn" :disabled="currentScale >= 3">
<van-icon name="plus" size="12" />
放大
</van-button>
</div>
<!-- 我的座位信息 -->
<div v-if="myCurrentSeat" class="mobile-my-seat-info" style="margin: 16px;">
<div style="margin-bottom: 4px;">我的座位</div>
<div class="seat-info">{{ myCurrentSeat.rowNumber }}-{{ myCurrentSeat.colNumber }} (第{{ myCurrentSeat.rowNumber }}排第{{
myCurrentSeat.colNumber }}列)
</div>
</div>
</div>
<!-- 底部操作面板 -->
<div class="mobile-bottom-panel">
<div v-if="selectedSeat" class="mobile-selected-info">
<div style="margin-bottom: 4px;">已选择座位</div>
<div class="seat-info">{{ selectedSeat.rowNumber }}-{{ selectedSeat.colNumber }} (第{{ selectedSeat.rowNumber }}排第{{
selectedSeat.colNumber }}列)
</div>
</div>
<div style="display: flex; gap: 22px">
<van-button type="info" block @click="showMeetingModal = true">
切换会议
</van-button>
<van-button type="info" block :disabled="!selectedSeat || submitting"
:loading="submitting" @click="confirmSelection">
{{ submitting ? '提交中...' : '确认选座' }}
</van-button>
</div>
</div>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
data() {
return {
meetings: [], // 会议列表
selectedMeetingId: null, // 选中的会议ID
showMeetingModal: true, // 显示会议选择弹窗
meeting: null,
seats: [],
selectedSeat: null,
myCurrentSeat: null,
loading: false,
submitting: false,
currentScale: 1, // 当前缩放比例
seatConfig: {
rows: 8,
cols: 12
},
}
},
mounted() {
this.loadMeetings();
this.$nextTick(() => {
this.initPinchZoom();
});
},
computed: {
gridStyle() {
return {
'grid-template-columns': 'repeat(' + this.seatConfig.cols + ', 1fr)'
}
}
},
methods: {
// 加载会议列表
loadMeetings() {
$.post('/platform/guildHall/meeting/selectList').then(res => {
if (res.code === 0) {
this.meetings = res.data
}
})
},
// 选择会议
selectMeeting(meeting) {
this.selectedMeetingId = meeting.id;
},
// 确认会议选择
confirmMeetingSelection() {
if (!this.selectedMeetingId) {
this.$toast('请选择一个会议');
return;
}
const selectedMeeting = this.meetings.find(m => m.id === this.selectedMeetingId);
if (selectedMeeting) {
this.meeting = selectedMeeting
this.loadSeats();
}
},
// 查询选座情况
async loadSeats() {
if (!this.meeting.id) {
return;
}
this.loading = true;
const {
code,
data,
msg
} = await $.post('/platform/guildHall/selectSeat/loadSeats', {meetingId: this.meeting.id})
if (code === 0) {
this.seats = data;
this.myCurrentSeat = this.seats.find(seat => seat.isMine);
// 根据现有数据计算行列数
const maxRow = Math.max(...this.seats.map(s => parseInt(s.rowNumber)))
const maxCol = Math.max(...this.seats.map(s => parseInt(s.colNumber)))
this.seatConfig.rows = maxRow
this.seatConfig.cols = maxCol
}
this.loading = false
this.showMeetingModal = false;
},
selectSeat(seat) {
if (!seat.enable) {
this.$toast('该座位已被禁用');
return;
}
if (seat.isOccupied && !seat.isMine) {
this.$toast('该座位已被占用');
return;
}
if (seat.isMine) {
this.$toast('这是您当前的座位');
return;
}
this.selectedSeat = seat;
// 添加触觉反馈
if (navigator.vibrate) {
navigator.vibrate(50);
}
},
async confirmSelection() {
if (!this.selectedSeat) {
this.$toast('请先选择座位');
return;
}
this.submitting = true;
const {code, data, msg} = await $.post('/platform/guildHall/selectSeat/doSelect', {
meetingId: this.meeting.id,
rowNumber: this.selectedSeat.rowNumber,
colNumber: this.selectedSeat.colNumber
})
this.submitting = false
if (code === 0) {
this.$toast.success("选座成功")
this.selectedSeat = null;
this.loadSeats();
} else {
this.$toast.fail(msg || '选座失败');
}
},
getSeatClass(seat) {
if (!seat.enable) {
return 'disabled';
}
if (seat.isMine) return 'my-seat';
if (seat === this.selectedSeat) return 'selected';
if (seat.isOccupied) return 'occupied';
return 'available';
},
getSeatTitle(seat) {
if (seat.isMine) return '我的座位';
if (seat === this.selectedSeat) return '当前选择';
if (seat.status === 1) return '已被占用';
return '点击选择此座位';
},
formatTime(time) {
if (!time) return '';
return new Date(time).toLocaleString('zh-CN');
},
// 放大
zoomIn() {
if (this.currentScale < 3) {
this.currentScale = Math.min(3, this.currentScale + 0.2);
this.applyZoom();
}
},
// 缩小
zoomOut() {
if (this.currentScale > 0.5) {
this.currentScale = Math.max(0.5, this.currentScale - 0.2);
this.applyZoom();
}
},
// 重置缩放
resetZoom() {
this.currentScale = 1;
this.applyZoom();
},
// 应用缩放
applyZoom() {
const seats = document.querySelectorAll('.mobile-seat');
const seatGrid = document.querySelector('.mobile-seat-grid');
seats.forEach(seat => {
seat.style.transform = 'scale(' + this.currentScale + ')';
seat.style.transformOrigin = 'center center';
seat.style.transition = 'transform 0.2s ease';
});
// 动态调整网格间距
if (seatGrid) {
const baseGap = 4;
const adjustedGap = baseGap * this.currentScale * 5;
seatGrid.style.gap = adjustedGap + 'px';
}
},
// 初始化双指缩放功能(已替换为按钮控制)
initPinchZoom() {
// 双指缩放功能已被按钮控制替代,保留此方法以避免错误
console.log('双指缩放功能已替换为按钮控制');
}
}
})
</script>
<!--#
}
#-->