This commit is contained in:
2025-08-29 18:02:55 +08:00
106 changed files with 4920 additions and 147 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -15,7 +15,7 @@
append-to-body
>
<div class="qrcode-container" style="text-align: center;">
<qrcode :value="url" :options="{ width: 126 }" class="signature-qrcode"></qrcode>
<qrcode v-if="url" :value="url" :options="{ width: width }" class="signature-qrcode"></qrcode>
</div>
<template #footer>
<el-button @click="dialogVisible = false">关闭</el-button>
@@ -26,7 +26,7 @@
<!-- 内联模式 -->
<template v-else-if="mode === 'inline'">
<div class="qrcode-inline-container">
<qrcode :value="url" :options="{ width: 126 }" class="signature-qrcode"></qrcode>
<qrcode v-if="url" :value="url" :options="{ width: width }" class="signature-qrcode"></qrcode>
</div>
</template>
</div>
@@ -41,7 +41,7 @@ module.exports = {
// 二维码内容
url: {
type: String,
required: true
required: true,
},
// 显示模式:dialog(默认)或 inline
mode: {
@@ -53,6 +53,10 @@ module.exports = {
value: {
type: Boolean,
default: false
},
width: {
type: Number,
default: 200
}
},
@@ -60,6 +60,8 @@
<!--Sortable-->
<script src="${base!}/assets/platform/plugins/sortablejs/sortable.min.js"></script>
<script src="${base!}/assets/platform/plugins/vuedraggable/vuedraggable.umd.min.js"></script>
<!--vue-count-to-->
<script src="${base!}/assets/platform/plugins/vue-count-to/vue-count-to.min.js"></script>
<!--vxe-->
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vxe/vxe-pc-ui.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vxe/vxe-table.css" />
@@ -83,6 +83,9 @@ layout("/layouts/platform.html"){
<el-form-item prop="code" label="字典代码">
<el-input maxlength="100" placeholder="字典代码" v-model="formData.code" auto-complete="off" tabindex="5" type="text"></el-input>
</el-form-item>
<el-form-item prop="remark" label="字典备注">
<el-input maxlength="100" placeholder="字典备注" v-model="formData.remark" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
@@ -100,6 +103,9 @@ layout("/layouts/platform.html"){
<el-form-item prop="code" label="字典代码">
<el-input maxlength="100" placeholder="字典代码" v-model="formData.code" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="remark" label="字典备注">
<el-input maxlength="100" placeholder="字典备注" v-model="formData.remark" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
@@ -179,7 +179,7 @@ layout("/layouts/platform.html"){
async initData() {
this.$set(this.formData, "applyStartYear", new Date().getFullYear() - 1 + "")
this.$set(this.formData, "applyEndYear", new Date().getFullYear() + "")
const id = GetQueryString("id")
const id = GetQueryString("bizId")
if (id) {
const resp = await this.$axios.post("/platform/club/evaluate/apply/info", { id })
if (resp.code === 0) {
@@ -0,0 +1,70 @@
const meetingInfo = {
template: /*language=HTML*/ `
<div>
<el-descriptions :column="3" border>
<el-descriptions-item label="会议名称">{{ viewData.name }}</el-descriptions-item>
<el-descriptions-item label="会议地点">{{ viewData.address }}</el-descriptions-item>
<el-descriptions-item label="会议类型">{{ viewData.typeName }}</el-descriptions-item>
<el-descriptions-item label="会议描述" :span="3">
<div v-html="viewData.description"></div>
</el-descriptions-item>
<el-descriptions-item label="场次信息" :span="3">
<el-table v-if="viewData.timePeriods && viewData.timePeriods.length > 0"
:data="viewData.timePeriods" max-height="300" size="mini">
<el-table-column prop="periodName" label="场次名称"></el-table-column>
<el-table-column prop="startTime" label="开始时间"></el-table-column>
<el-table-column prop="endTime" label="结束时间"></el-table-column>
<el-table-column prop="canLeave" label="是否可以请假">
<template slot-scope="{ row }">
<span v-if="row.canLeave">是</span>
<span v-else>否</span>
</template>
</el-table-column>
</el-table>
<span v-else>暂无场次信息</span>
</el-descriptions-item>
<el-descriptions-item label="会议参与人员" :span="3">
<el-table v-if="viewData.users && viewData.users.length > 0"
:data="viewData.users" max-height="300" size="mini">
<el-table-column fixed prop="loginName" label="工号" width="150"></el-table-column>
<el-table-column prop="userName" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="人事编制" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column>
</el-table>
<span v-else>暂无会议参与人员信息</span>
</el-descriptions-item>
</el-descriptions>
</div>
`,
store,
data() {
return {
viewData: {},
}
},
methods: {
onOpen(row) {
this.$axios.post('/platform/meeting/manage/info', {id: row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
},
style: /*language=CSS*/ `
.el-descriptions-item__label {
width: 200px;
min-width: 200px;
max-width: 200px;
}
.el-tabs__header {
margin: 0;
}
`
}
@@ -0,0 +1,392 @@
const basicForm = {
template: /*language=HTML*/ `
<div>
<el-steps :active="activeName" finish-status="success" simple>
<el-step title="会议基本信息"></el-step>
<el-step title="场次信息"></el-step>
<el-step title="会议参与人员"></el-step>
</el-steps>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="110px" label-position="left" class="mt20">
<div v-show="activeName === 0">
<el-form-item label="会议名称" prop="name">
<el-input type="text" v-model="formData.name" maxlength="50"
placeholder="请输入会议名称"></el-input>
</el-form-item>
<el-form-item label="会议地点" prop="address">
<el-input type="text" v-model="formData.address" maxlength="100"
placeholder="请输入会议地点"></el-input>
</el-form-item>
<el-form-item label="会议类型" prop="typeId">
<el-select v-model="formData.typeId" style="width: 100%" placeholder="请选择会议类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="typeOptions.find(o => o.id === formData.typeId)?.designId === 'JDHHY'" label="所属教代会" prop="teacherCongressSessionId">
<el-select v-model="formData.teacherCongressSessionId" style="width: 100%" placeholder="请选择所属教代会" filterable clearable>
<el-option v-for="item in teacherCongressOptions"
:value="item.id"
:key="item.id"
:label="item.fullName"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="typeOptions.find(o => o.id === formData.typeId)?.designId === 'GDHHY'" label="所属工代会" prop="workerCongressSessionId">
<el-select v-model="formData.workerCongressSessionId" style="width: 100%" placeholder="请选择所属工代会" filterable clearable>
<el-option v-for="item in workerCongressOptions"
:value="item.id"
:key="item.id"
:label="item.fullName"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="会议描述" prop="description">
<text-editor v-model="formData.description"></text-editor>
</el-form-item>
</div>
<div v-show="activeName === 1">
<el-form-item label="场次信息">
<el-table :data="formData.timePeriods" style="width: 100%" size="small">
<el-table-column label="场次名称" prop="periodName">
<template slot-scope="{ row }">
<el-input maxlength="20" v-model="row.periodName" placeholder="请输入场次名称" size="small"></el-input>
</template>
</el-table-column>
<el-table-column label="开始时间" prop="startTime">
<template slot-scope="{ row }">
<el-date-picker
size="small"
placeholder="请选择开始时间"
type="datetime"
v-model="row.startTime"
format="yyyy-MM-dd HH:mm"
value-format="yyyy-MM-dd HH:mm">
</el-date-picker>
</template>
</el-table-column>
<el-table-column label="结束时间" prop="endTime">
<template slot-scope="{ row }">
<el-date-picker
size="small"
placeholder="请选择结束时间"
type="datetime"
v-model="row.endTime"
format="yyyy-MM-dd HH:mm"
value-format="yyyy-MM-dd HH:mm">
</el-date-picker>
</template>
</el-table-column>
<el-table-column label="是否可以请假" prop="canLeave">
<template slot-scope="{ row }">
<el-radio-group v-model="row.canLeave" size="small">
<el-radio-button :label="true">是</el-radio-button>
<el-radio-button :label="false">否</el-radio-button>
</el-radio-group>
</template>
</el-table-column>
<el-table-column width="80">
<template slot="header" slot-scope="{ row }">
<el-button size="mini" type="primary" icon="el-icon-plus"
@click="formData.timePeriods.push({ canLeave: false })"></el-button>
</template>
<template slot-scope="scope">
<el-button :disabled="formData.timePeriods.length <= 1"
@click="formData.timePeriods.splice(scope.$index, 1)"
icon="el-icon-delete"
size="mini"
type="danger"></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</div>
<div v-show="activeName === 2">
<el-form-item label="参与人员信息">
<el-row class="mb10">
<el-button icon="el-icon-search" @click="openSelect" size="small">选择用户</el-button>
<el-button icon="el-icon-delete" @click="clearSelect" type="danger" size="small">清空用户</el-button>
</el-row>
<el-table :data="userTableData" style="width: 100%" size="mini" max-height="300">
<el-table-column fixed prop="loginName" label="工号" width="150"></el-table-column>
<el-table-column prop="userName" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="人事编制" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button @click="userTableData.splice(scope.$index, 1)"
icon="el-icon-delete"
size="mini"
type="danger"></el-button>
</template>
</el-table-column>
</el-table>
<p style="color: var(--color-primary)">总计:{{userTableData.length}}人</p>
</el-form-item>
</div>
</el-form>
<el-row class="mt10" justify="end" type="flex">
<el-button @click="$emit('refresh')">取消</el-button>
<el-button v-if="activeName === 1" type="primary" @click="activeName = 0">上一步</el-button>
<el-button v-if="activeName === 2" type="primary" @click="activeName = 1">上一步</el-button>
<el-button v-if="activeName === 0" type="primary" @click="next()">下一步</el-button>
<el-button v-if="activeName === 1" type="primary" @click="activeName = 2">下一步</el-button>
<el-button @click="onSave" type="primary">保存</el-button>
<el-button @click="onSubmit" type="primary">提交</el-button>
</el-row>
<el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="70%" append-to-body>
<div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 260px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginName"></el-option>
<el-option label="姓名" value="u.userName"></el-option>
<el-option label="手机" value="u.mobile"></el-option>
</el-select>
</el-input>
<el-select v-model="pageForm.sex" placeholder="请选择性别" clearable>
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits" placeholder="请选择所属工会" filterable clearable>
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable>
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-select v-model="pageForm.roleId" placeholder="请选择角色" filterable clearable>
<el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-button icon="el-icon-search" @click="doSearch" type="primary"></el-button>
</div>
<div class="left-span-label mt20">人员列表</div>
<el-table
:data="tableData"
@selection-change="handleSelectionChange"
row-key="id"
ref="tableRef"
>
<el-table-column type="selection" reserve-selection width="60"></el-table-column>
<el-table-column fixed prop="loginName" label="工号" width="150"></el-table-column>
<el-table-column prop="userName" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="人事编制" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
<span slot="footer" class="dialog-footer">
<el-button @click="selectDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSelect">确 定</el-button>
</span>
</el-dialog>
</div>
`,
props: {
unionList: {
type: Array,
required: true
},
unitList: {
type: Array,
required: true
}
},
mixins: [initTableMixins],
data() {
return {
activeName: 0,
formData: {
timePeriods: [{ canLeave: false }],
},
formRules: {
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
address: [{required: true, message: '必填', trigger: ['blur', 'change']}],
typeId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
teacherCongressSessionId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
workerCongressSessionId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
typeOptions: [],
userTableData: [],
selectDialogVisible: false,
roleList: [],
selectUsers: [],
pageForm: {
searchName: 'u.userName',
},
teacherCongressOptions: [],
workerCongressOptions: [],
}
},
methods: {
next() {
const type = this.typeOptions.find(o => o.id === this.formData.typeId)
if(type.designId === 'JDHHY' && !this.formData.teacherCongressSessionId) {
this.$message.warning('请选择所属教代会')
return
}
if(type.designId === 'GDHHY' && !this.formData.workerCongressSessionId) {
this.$message.warning('请选择所属工代会')
return
}
this.activeName = 1
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.unitList = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.unitList = data
})
}
this.doSearch()
},
handleSelectionChange(val) {
this.selectUsers = val
},
doSelect() {
const tableLoginNames = this.userTableData.map(v => v.loginName)
for (const o of this.selectUsers) {
if(!tableLoginNames.includes(o.loginName)){
this.userTableData.push(o)
}
}
if(this.$refs.tableRef){
this.$refs.tableRef.clearSelection()
}
this.selectDialogVisible = false
},
async getRoleList() {
const resp = await this.$axios.post("/platform/sys/msg/getRoleList")
return resp.data
},
openSelect() {
this.selectDialogVisible = true
this.pageData()
},
clearSelect() {
this.userTableData = []
if(this.$refs.tableRef){
this.$refs.tableRef.clearSelection()
}
},
onOpen(row) {
if(row && row.id) {
this.$axios.post('/platform/meeting/manage/info', { id: row.id }).then(res => {
this.formData = res.data
this.userTableData = this.formData.users
})
}
},
onSave() {
this.$confirm("您确定要保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/meeting/manage/submit', {
data: JSON.stringify(this.formData),
users: JSON.stringify(this.userTableData)
}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.$emit('refresh')
} else {
this.$message.warning(res.msg)
}
})
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
if(this.formData.timePeriods.length === 0) {
this.$message.warning("请至少添加一条场次信息")
return
}
for (let i = 0; i < this.formData.timePeriods.length; i++) {
const item = this.formData.timePeriods[i]
if(!item.periodName) {
this.$message.warning("第" + (i + 1) + "条场次信息中,场次名称必填")
return
}
if(!item.startTime) {
this.$message.warning("第" + (i + 1) + "条场次信息中,开始时间必填")
return
}
if(!item.endTime) {
this.$message.warning("第" + (i + 1) + "条场次信息中,结束时间必填")
return
}
}
if (this.userTableData.length === 0) {
this.$message.warning("请选择会议参与人员")
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/meeting/manage/submit", {
data: JSON.stringify(this.formData),
users: JSON.stringify(this.userTableData)
})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$emit('refresh')
} else {
this.$message.warning(resp.msg)
}
})
}
})
},
queryMeetingType() {
this.$axios.post("/platform/meeting/type/queryMeetingType")
.then((res) => {
this.typeOptions = res.data
})
},
pageData() {
this.$axios.post("/platform/meeting/manage/userPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
queryTeacherCongress() {
this.$axios.post("/platform/meeting/manage/queryTeacherCongress")
.then((res) => {
this.teacherCongressOptions = res.data
})
},
queryWorkerCongress() {
this.$axios.post("/platform/meeting/manage/queryWorkerCongress")
.then((res) => {
this.workerCongressOptions = res.data
})
},
},
async created() {
this.queryMeetingType()
this.queryTeacherCongress()
this.queryWorkerCongress()
this.roleList = await this.getRoleList()
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,154 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度:">
<el-date-picker
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="请选择年度"
@change="doSearch"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="名称/地点:">
<el-input placeholder="请输入名称或地点查询" clearable v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch">
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="会议列表">
<el-button type="primary" size="small" @click="onAdd">
<i class="ti-plus"></i>
新增会议
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'createdAt'">
<span>{{ $moment(row.createdAt).format('YYYY-MM-DD') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="230">
<template v-slot="{ row }">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button @click="onDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<basic-form ref="basicFormRef" @refresh="refresh" :union-list="unionList" :unit-list="unitList"></basic-form>
</template>
<template #view>
<meeting-info ref="infoRef"></meeting-info>
</template>
</guava>
</div>
<script>
<!--#include('../common/meetingInfo.js'){}#-->
<!--#include('basicForm.js'){}#-->
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"basic-form": basicForm,
"meeting-info": meetingInfo,
},
data() {
return {
tableColumns: [
{prop: 'name', label: '会议名称'},
{prop: 'typeName', label: '会议类型'},
{prop: 'address', label: '会议地点'},
{prop: 'createdAt', label: '创建时间'},
],
unionList: [],
unitList: [],
}
},
methods: {
refresh() {
this.doSearch()
this.$refs.guava.index()
},
onAdd() {
this.$refs.guava.edit(() => {
this.$refs.basicFormRef.onOpen()
})
},
onView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
onEdit(row) {
this.$refs.guava.edit(() => {
this.$refs.basicFormRef.onOpen(row)
})
},
onDelete(row) {
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/meeting/manage/delete", { id: row.id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
},
async created() {
this.unitList = await this.$businessTool.listUnit()
this.unionList = await this.$businessTool.listUnion()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,328 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.qrcode {
min-width: 240px;
text-align: center;
display: flex;
flex-direction: column;
}
.real-data {
display: flex;
flex-wrap: wrap;
}
.real-data .data-card {
border-radius: 10px;
width: calc((100% - 80px) / 4);
min-width: 100px;
background-image: linear-gradient(141deg, #9fb8ad 0%, #1fc8db 51%, #2cb5e8 75%);
margin: 10px 0 10px 20px;
padding: 10px;
color: #ffffff;
display: flex;
flex-direction: column;
position: relative;
}
.real-data .data-card .data-card-title {
font-size: 20px;
max-width: 100%;
text-overflow: ellipsis;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
flex: 1;
position: absolute;
}
.real-data .data-card .data-card-num {
font-size: 90px;
flex: auto;
display: flex;
justify-content: center;
align-items: center;
}
.real-data .data-card .flow-border {
position: absolute;
display: block;
}
.timePeriod_card {
border-top: 5px solid #106898;
border-left: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;
border-right: 1px solid #ebeef5;
}
.timePeriod_card .el-form-item {
margin-bottom: 0 !important;
}
img {
height: 100% !important;
width: 100%;
}
.operation {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 1111;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度:">
<el-date-picker
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="请选择年度"
@change="doSearch"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="名称/地点:">
<el-input placeholder="请输入名称或地点查询" clearable v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="会议类型:">
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
placeholder="请选择慰问类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="会议列表"></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize" ref="meetingTable">
<el-table-column type="expand">
<template slot-scope="scope">
<el-row :gutter="20" justify="start" style="flex-wrap: wrap" type="flex"
v-if="scope.row.timePeriods && scope.row.timePeriods.length > 0">
<el-col :xl="5" v-for="tp,index in scope.row.timePeriods" :key="index">
<el-card class="mb10 timePeriod_card" shadow="hover">
<el-form label-width="80px">
<el-form-item label="名称">{{tp.periodName}}</el-form-item>
<el-form-item label="会议时间">{{tp.startTime}}</el-form-item>
<el-form-item label="结束时间">{{tp.endTime}}</el-form-item>
</el-form>
<el-row justify="space-around" style="border-top: 1px solid #ebeef5;padding: 10px 0 0 0" type="flex">
<el-button @click="exportSignature(tp.id)" size="medium" type="text">
导出签字表
</el-button>
<el-button @click="openOnline(tp.id,scope.row.id)" size="medium" type="text">
扫描二维码
</el-button>
</el-row>
</el-card>
</el-col>
</el-row>
<el-row v-else>
<el-empty description="没有时间段"></el-empty>
</el-row>
</template>
</el-table-column>
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'createdAt'">
<span>{{ $moment(row.createdAt).format('YYYY-MM-DD') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="230">
<template v-slot="{ row }">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="toggleRowTimePeriod(row)" size="mini" type="primary">展开</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<div style="min-width: 500px;height: 100%;position: relative">
<el-row type="flex">
<el-col :span="4" class="qrcode">
<qr-code-plus :url="qrCodeUrl" ref="qrCodePlusRef" mode="inline"></qr-code-plus>
</el-col>
<el-col :span="20" class="real-data">
<template v-for="rd of realTimeData">
<div class="data-card">
<div class="data-card-title">
{{rd.label}}
</div>
<div class="data-card-num">
<count-to :end-val="rd.value" :start-val="getLastValue(rd.key)"></count-to>
</div>
</div>
</template>
</el-col>
</el-row>
<el-table :data="userData" :max-height="signTableHeight" class="mt20" ref="signTable">
<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"></el-table-column>
<el-table-column label="签到时间" prop="signInDateTime"></el-table-column>
<el-table-column label="签到名次">
<template slot-scope="scope">
{{userData.length - scope.$index}}
</template>
</el-table-column>
</el-table>
</div>
</template>
<template #view>
<meeting-info ref="infoRef"></meeting-info>
</template>
</guava>
</div>
<script>
<!--#include('../common/meetingInfo.js'){}#-->
let pollingInterval = null
const intervalTime = 3500
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"meeting-info": meetingInfo,
},
data() {
return {
tableColumns: [
{prop: 'name', label: '会议名称'},
{prop: 'typeName', label: '会议类型'},
{prop: 'address', label: '会议地点'},
{prop: 'createdAt', label: '创建时间'},
],
typeOptions: [],
meetingId: '',
timePeriodId: '',
qrCodeUrl: '',
lastTimeData: [],
realTimeData: [],
userData: [],
signTableHeight: 600
}
},
methods: {
toggleRowTimePeriod(row) {
this.$refs['meetingTable'].toggleRowExpansion(row)
},
exportSignature(timePeriodId) {
this.$downLoad(loc() + '/exportSignature/' + timePeriodId)
},
openOnline(timePeriodId, meetingId) {
this.meetingId = meetingId
this.timePeriodId = timePeriodId
this.$refs.guava.edit(() => {
this.calcSignTableHeight()
this.generateQrCodeUrl(timePeriodId, meetingId)
this.stopInterval()
pollingInterval = this.startPolling(this.getRealTimeData)
})
},
calcSignTableHeight() {
this.$nextTick(() => {
setTimeout(() => {
const offsetTop = this.$refs.signTable.$el.offsetTop
const th = window.innerHeight - 54 - 40 - offsetTop
this.$set(this, 'signTableHeight', th)
})
})
},
async generateQrCodeUrl(tpId, meetingId) {
const resp = await this.$axios.post(loc() + '/generateQrCodeUrl', {tpId, meetingId})
if (resp.code === 0) {
this.qrCodeUrl = resp.data
} else {
this.$message.warning(resp.msg)
}
},
async getRealTimeData() {
this.lastTimeData = clone(this.realTimeData)
const resp = await this.$axios.post(loc() + '/getRealTimeData/' + this.timePeriodId)
if (resp.code === 0) {
this.lastTimeData = clone(this.realTimeData)
this.$set(this, 'realTimeData', resp.data.countData)
let ud = clone(this.userData)
ud.unshift(...resp.data.userData)
let uMap = new Map()
for (let u of ud) {
if (!uMap.has(u.loginname)) {
uMap.set(u.loginname, u)
}
}
this.$set(this, 'userData', [...uMap.values()])
}
},
startPolling(func) {
this.lastTimeData = []
this.realTimeData = []
this.userData = []
func()
return setInterval(func, intervalTime)
},
stopInterval() {
if (pollingInterval) {
clearInterval(pollingInterval)
}
},
getLastValue(key) {
if (this.lastTimeData && this.lastTimeData.length > 0) {
return this.lastTimeData.find(v => v.key === key).value
} else {
return 0
}
},
onView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
queryMeetingType() {
this.$axios.post('/platform/meeting/type/queryMeetingType')
.then((resp) => {
this.typeOptions = resp.data
})
},
},
async created() {
this.queryMeetingType()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,82 @@
const basicForm = {
template: /*language=HTML*/ `
<div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="110px" label-position="left">
<el-form-item label="类型编码" prop="code">
<el-input type="text" v-model="formData.code" maxlength="50"
placeholder="请输入类型编码"></el-input>
</el-form-item>
<el-form-item label="类型名称" prop="name">
<el-input type="text" v-model="formData.name" maxlength="50"
placeholder="请输入类型名称"></el-input>
</el-form-item>
<el-form-item label="所属流程" prop="designId">
<el-select v-model="formData.designId" placeholder="请选择所属流程" filterable clearable style="width: 100%">
<el-option v-for="item in designOptions" :key="item.name" :value="item.name" :label="item.displayName"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否启用" prop="enable">
<el-switch
v-model="formData.enable"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
</el-form-item>
</el-form>
<el-row class="mt10" justify="end" type="flex">
<el-button @click="$emit('refresh')">取消</el-button>
<el-button @click="onSubmit" type="primary">提交</el-button>
</el-row>
</div>
`,
data() {
return {
formData: {
enable: true
},
formRules: {
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
code: [{required: true, message: '必填', trigger: ['blur', 'change']}],
enable: [{required: true, message: '必填', trigger: ['blur', 'change']}],
designId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
designOptions: [],
}
},
methods: {
onOpen(row) {
this.queryDesignList()
if(row && row.id) {
this.formData = clone(row)
}
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/meeting/type/submit", this.formData)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$emit('refresh')
} else {
this.$message.warning(resp.msg)
}
})
}
})
},
queryDesignList() {
this.$axios.post("/platform/meeting/type/queryDesignList")
.then((res) => {
this.designOptions = res.data
})
},
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,139 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="名称/编码:">
<el-input placeholder="请输入名称或编码查询" clearable v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch">
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="类型列表">
<el-button type="primary" size="small" @click="onAdd">
<i class="ti-plus"></i>
新增类型
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'enable'">
<el-switch
@change="switchChange(row)"
v-model="row.enable"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="230">
<template v-slot="{ row }">
<el-button @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button @click="onDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<basic-form ref="basicFormRef" @refresh="refresh"></basic-form>
</template>
</guava>
</div>
<script>
<!--#include('basicForm.js'){}#-->
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"basic-form": basicForm,
},
data() {
return {
tableColumns: [
{prop: 'code', label: '类型编码'},
{prop: 'name', label: '类型名称'},
{prop: 'enable', label: '是否启用'},
],
}
},
methods: {
refresh() {
this.doSearch()
this.$refs.guava.index()
},
onAdd() {
this.$refs.guava.edit(() => {
this.$refs.basicFormRef.onOpen()
})
},
onEdit(row) {
this.$refs.guava.edit(() => {
this.$refs.basicFormRef.onOpen(row)
})
},
onDelete(row) {
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/meeting/type/delete", { id: row.id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
switchChange(row) {
this.$axios.post("/platform/meeting/type/submit", row).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -265,7 +265,7 @@ const basicForm = {
return true
}
if (this.$auth.hasRoleOr(["BRANCH_UNION_ADMIN", "BRANCH_UNION_CHAIRMAN"])) {
return roles.some(r => r === 'H04')
return roles.some(r => r === 'BRANCH_UNION_ADMIN' || r === 'BRANCH_UNION_CHAIRMAN')
}
},
async getConfig() {
@@ -0,0 +1,517 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<snaker-start slot="header" label="工会报销" define_key="GHBX"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
<el-descriptions :column="2" border>
<el-descriptions-item label="经办人">{{formData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{formData.loginName}}</el-descriptions-item>
<el-descriptions-item label="报销类别">
<el-form-item label="报销类别" prop="reimburseType">
<el-radio-group v-model="formData.reimburseType" size="medium">
<el-radio :label="item.code" border v-for="item in dict.type.UNION_REIMBURSE_TYPE">
{{item.name}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="支付方式">
<el-form-item label="支付方式" prop="paymentWay">
<el-radio-group v-model="formData.paymentWay" size="medium">
<el-radio :label="item.code" border v-for="item in dict.type.UNION_REIMBURSE_PAYMENT_WAY">
{{item.name}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="报销项目" span="2">
<el-form-item label="报销项目" prop="reimburseProject">
<el-radio-group v-model="formData.reimburseProject" size="medium">
<el-radio :label="item.code" border v-for="item in reimburseProjects">
{{item.name}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="报销经费来源" span="2">
<el-form-item label="报销经费来源" prop="reimburseFundSource">
<el-radio-group v-model="formData.reimburseFundSource" size="medium" @change="reimburseFundSourceChange">
<el-radio :label="item.code" border v-for="item in dict.type.UNION_REIMBURSE_FUND_SOURCE">
{{item.name}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系方式">
<el-form-item prop="mobile" label="联系方式">
<el-input v-model="formData.mobile" show-word-limit
placeholder="请输入联系方式"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属社团" v-if="formData.reimburseFundSource === 'UNION_REIMBURSE_FUND_SOURCE_3'">
<el-form-item label="所属社团" prop="clubId">
<el-select v-model="formData.clubId" style="width: 100%"
placeholder="请选择所属社团" filterable clearable>
<el-option v-for="item in clubOptions" :key="item.id" :label="item.clubName" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="经费余额">{{formData.fundBalance}}</el-descriptions-item>
<el-descriptions-item label="户名">
<el-form-item prop="bankUserName" label="户名">
<el-input v-model="formData.bankUserName" show-word-limit
placeholder="请输入户名"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="银行账号">
<el-form-item prop="bankCardNumber" label="银行账号">
<el-input v-model="formData.bankCardNumber" show-word-limit
placeholder="请输入银行账号"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="开户行">
<el-form-item prop="bankOfDeposit" label="开户行">
<el-input v-model="formData.bankOfDeposit" show-word-limit
placeholder="请输入开户行"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="慰问对象" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="慰问对象" prop="condolenceId">
<el-select
style="width: 100%"
v-model="formData.condolenceId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入姓名或工号查询"
:remote-method="createRemoteMethod(userOptions)"
@change="userChange">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.userName+''+item.loginName+''+''+item.unitName+''+''+item.sex+''"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系方式" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item prop="condolenceMobile" label="联系方式">
<el-input v-model="formData.condolenceMobile" show-word-limit
placeholder="请输入联系方式"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="慰问类型" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="慰问类型" prop="type">
<el-select v-model="formData.condolenceType" @change="typeChange" style="width: 100%"
placeholder="请选择慰问类型">
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
:disabled="item.isDisabled"
:label="item.name"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="慰问金额" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
{{formData.money}}
</el-descriptions-item>
<el-descriptions-item label="慰问时间" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="慰问时间" prop="condolenceTime">
<el-date-picker
clearable
style="width: 100%"
v-model="formData.condolenceTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择慰问时间">
</el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="活动名称" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="活动名称" prop="activityName">
<el-input type="text" v-model="formData.activityName" placeholder="请输入活动名称"
maxlength="60"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="活动类型" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_2'">
<el-form-item label="活动类型" prop="activityType">
<el-select v-model="formData.activityType" placeholder="请选择活动类型" style="width: 100%">
<el-option label="分工会活动" value="1"></el-option>
<el-option label="校工会活动" value="2"></el-option>
<el-option label="协会(社团)活动" value="3"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="活动人数" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_2'">
<el-form-item label="活动人数" prop="activityNumber">
<el-input v-model="formData.activityNumber" placeholder="请输入活动人数"
type="number"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="活动地点" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="活动地点" prop="activityPlace">
<el-input v-model="formData.activityPlace" placeholder="请输入活动地点" type="text"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="报销金额" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="报销金额" prop="money">
<el-input v-model="formData.money" placeholder="输入报销金额"
type="number"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="活动时间" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
<el-form-item label="活动时间" prop="activityTime">
<el-date-picker v-model="formData.activityTime"
placeholder="活动时间"
style="width: 100%" type="date"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="发票张数" v-if="formData.reimburseType === 'UNION_REIMBURSE_TYPE_1'">
<el-form-item label="发票张数" prop="invoiceNumber">
<el-input-number v-model="formData.invoiceNumber"
:max="1000" :min="0" controls-position="right"
placeholder="请填写发票张数"
style="width: 100%"></el-input-number>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="发票号码" v-if="formData.reimburseType === 'UNION_REIMBURSE_TYPE_1'">
<el-form-item id="invoice" label="发票号码" prop="invoice">
<el-input v-model="formData.invoice"
placeholder="请填写发票号码,如有多个请用逗号分隔"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="支付内容" :span="2">
<el-form-item prop="remark" label="支付内容">
<el-input maxlength="500" v-model="formData.paymentNotes" placeholder="请填写支付内容"
type="textarea" :autosize="{ minRows: 4, maxRows: 8}"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item :span="2" >
<template slot="label">
附件
</template>
<el-form-item prop="files" label="附件">
<file-upload
:value.sync="formData.files"
:upload_number="5"
upload_result_category="array"
complete_result
upload_mode="drag"
></file-upload>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" plain @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit" v-if="!taskId">提交</el-button>
<el-button type="primary" @click="onFinishTask" v-else>提交1</el-button>
</el-row>
</el-card>
</div>
<script>
new Vue({
el: '#app',
store,
dicts: ["UNION_REIMBURSE_TYPE", "UNION_REIMBURSE_PAYMENT_WAY", "UNION_REIMBURSE_FUND_SOURCE"],
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formData: {
reimburseType: "",
},
formRules: {
reimburseType: [{required: true, message: '请选择报销类别', trigger: ["change", "blur"]}],
paymentWay: [{required: true, message: '请选择支付方式', trigger: ["change", "blur"]}],
reimburseProject: [{required: true, message: '请选择报销项目', trigger: ["change", "blur"]}],
reimburseFundSource: [{required: true, message: '请选择经费来源', trigger: ["change", "blur"]}],
mobile: [{required: true, message: '请填写联系方式', trigger: ["change", "blur"]}],
bankUserName: [{required: true, message: '请填写户名', trigger: ["change", "blur"]}],
bankCardNumber: [{required: true, message: '请填写银行账号', trigger: ["change", "blur"]}],
bankOfDeposit: [{required: true, message: '请填写开户行', trigger: ["change", "blur"]}],
condolencePeopleMobile: [{required: true, message: '请填写联系方式', trigger: ["change", "blur"]}],
condolenceTime: [{required: true, message: '请选择慰问时间', trigger: ["change", "blur"]}],
invoiceNumber: [{required: true, message: '请填写发票张数', trigger: ["change", "blur"]}],
invoice: [{required: true, message: '请填写发票号码', trigger: ["change", "blur"]}],
paymentNotes: [{required: true, message: '请填写支付内容', trigger: ["change", "blur"]}],
},
chooseType: {},
userOptions: [],
typeOptions: [],
reimburseProjectList: [],
reimburseProjects: [],
clubOptions: []
}
},
// 监听报销类别发生变化,报销项目联动改变
watch: {
"formData.reimburseType"(newVal) {
if (newVal === 'UNION_REIMBURSE_TYPE_1') {
this.reimburseProjects = this.reimburseProjectList.filter((o) => {
return ['1', 'UNION_REIMBURSE_TYPE_1'].includes(o.remark)
})
} else {
this.reimburseProjects = this.reimburseProjectList.filter((o) => {
return ['1', 'UNION_REIMBURSE_TYPE_2'].includes(o.remark)
})
}
},
// 添加对社团选择的监听
"formData.clubId"(newVal) {
// 当经费来源是社团且选择了具体社团时,重新查询余额
if (this.formData.reimburseFundSource === 'UNION_REIMBURSE_FUND_SOURCE_3' && newVal) {
// 选择了具体社团,获取社团名称并保存
const selectedClub = this.clubOptions.find(club => club.id === newVal);
if (selectedClub) {
this.$set(this.formData, 'clubName', selectedClub.clubName);
}
this.reimburseFundSourceChange();
}
}
},
methods: {
createRemoteMethod(options) {
return (keyword) => {
this.selectQueryUser(keyword, options)
}
},
//查询慰问对象
selectQueryUser(keyword, options) {
options.length = 0
this.$axios.post("/platform/UnionReimburse/apply/listUser", {keyword: keyword}).then((res) => {
if (res.code === 0) {
options.push(...res.data)
}
})
},
userChange(val) {
const user = this.userOptions.find(o => o.id === val)
if (user) {
const { userName,mobile } = user
this.$set(this.formData, "condolenceName", userName)
this.$set(this.formData, "condolenceMobile", mobile)
}
},
//
typeChange(id) {
this.chooseType = this.typeOptions.find(o => o.id === id)
if (this.chooseType) {
this.$set(this.formData, "money", this.chooseType.money)
this.$set(this.formData, "way", this.chooseType.way)
}
},
// 保存
onSave() {
// 余额校验
if (this.formData.money && this.formData.fundBalance) {
const balance = parseFloat(this.formData.fundBalance);
const money = parseFloat(this.formData.money);
if (balance < money) {
this.$message.warning("经费余额不足");
return;
}
}
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/unionReimburse/apply/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
window.location.href = '/platform/unionReimburse/mine'
}
})
})
},
// 提交
onSubmit() {
// 余额校验
if (this.formData.money && this.formData.fundBalance) {
const balance = parseFloat(this.formData.fundBalance);
const money = parseFloat(this.formData.money);
if (balance < money) {
this.$message.warning("经费余额不足");
return;
}
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/unionReimburse/apply/submit', {
data: JSON.stringify(this.formData)
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
window.location.href = '/platform/unionReimburse/mine'
}
})
})
},
// 再次提交
onFinishTask() {
// 余额校验
if (this.formData.money && this.formData.fundBalance) {
const balance = parseFloat(this.formData.fundBalance);
const money = parseFloat(this.formData.money);
if (balance < money) {
this.$message.warning("经费余额不足");
return;
}
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/unionReimburse/apply/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
window.location.href = '/platform/unionReimburse/mine'
}
})
})
},
// 初始化
async init() {
this.reimburseProjectList = await this.$businessTool.getDictOptions("UNION_REIMBURSE_PROJECT")
if (this.bizId) {
this.$axios.post("/platform/unionReimburse/apply/info", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.selectQueryUser(this.formData.loginName, this.userOptions)
this.chooseType = this.typeOptions.find(o => o.id === this.formData.type)
}
})
} else {
const { username, loginname, id, unit, union, mobile } = this.$store.state.user
this.formData = {
userName: username,
loginName: loginname,
unitId: unit?.id,
unitName: unit?.name,
unionId: union?.id,
unionName: union?.name,
reimburseType: "UNION_REIMBURSE_TYPE_1",
mobile: mobile
}
}
},
//慰问类型查询
queryCondolenceType() {
this.$axios.post("/platform/unionReimburse/apply/queryCondolenceType")
.then((resp) => {
this.typeOptions = resp.data
})
},
//经费来源查询
reimburseFundSourceChange() {
// 检查是否有选择经费来源
if (!this.formData.reimburseFundSource) {
this.$set(this.formData, 'fundBalance', '');
return;
}
// 如果是社团经费来源,但没有选择具体社团,则不查询
if (this.formData.reimburseFundSource === 'UNION_REIMBURSE_FUND_SOURCE_3' && !this.formData.clubId) {
this.$set(this.formData, 'fundBalance', '');
return;
}
// 定义API映射关系
const apiMap = {
'UNION_REIMBURSE_FUND_SOURCE_1': {
url: "/platform/unionReimburse/apply/getSchoolBudget",
},
'UNION_REIMBURSE_FUND_SOURCE_2': {
url: "/platform/unionReimburse/apply/getUnionBalance",
},
'UNION_REIMBURSE_FUND_SOURCE_3': {
url: "/platform/unionReimburse/apply/getClubBudget",
}
};
const fundSource = this.formData.reimburseFundSource;
const apiInfo = apiMap[fundSource];
// 如果没有匹配的API,清空经费余额并返回
if (!apiInfo) {
this.$set(this.formData, 'fundBalance', '');
return;
}
// 构造请求参数
const params = {
reimburseFundSource: fundSource
};
// 如果是社团经费,需要传递社团ID
if (fundSource === 'UNION_REIMBURSE_FUND_SOURCE_3' && this.formData.clubId) {
params.clubId = this.formData.clubId;
}
// 显示加载状态
this.$set(this.formData, 'fundBalance', '查询中...');
// 发送请求
this.$axios.post(apiInfo.url, params)
.then(response => {
if (response.code === 0) {
// 显示经费余额(只显示数字,不显示"元")
this.$set(this.formData, 'fundBalance', response.data || '0.00');
} else {
this.$set(this.formData, 'fundBalance', '查询失败');
}
})
.catch(error => {
console.error("经费余额查询失败:", error);
this.$set(this.formData, 'fundBalance', '查询失败');
this.$message.error("经费余额查询失败");
});
}
},
created() {
this.queryCondolenceType()
this.init()
//社团查询
this.$businessTool.listClub().then((res) => (this.clubOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,208 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="工会名称">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择工会名称" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="单位名称">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择单位名称" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="报销项目">
<el-select v-model="pageForm.reimburseProject" @change="doSearch" style="width: 100%"
placeholder="请选择报销项目" clearable>
<el-option v-for="item in dict.type.UNION_REIMBURSE_PROJECT"
:value="item.code"
:key="item.code"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="经办人">
<el-select
style="width: 100%"
v-model="pageForm.userName"
filterable
clearable
remote
reserve-keyword
placeholder="请输入经办人姓名或工号查询"
:remote-method="createRemoteMethod(userOptions)"
@change="userChange">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.userName+''+item.loginName+''+''+item.unitName+''+''+item.sex+''"
:value="item.id">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="申请列表">
<el-button @click="onExport" icon="el-icon-s-promotion" type="primary" size="small">导出</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="经办人工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="reimburseType" label="报销类别">
<template slot-scope="{row}">
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
:value="row.reimburseType">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="reimburseProject" label="报销项目">
<template slot-scope="{row}">
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
:value="row.reimburseProject">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="money" label="金额"></el-table-column>
<el-table-column prop="createTime" label="申请时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="$auth.hasRole('SYSADMIN')" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<union-reimburse-info ref="unionReimburseInfoRef">
</union-reimburse-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["UNION_REIMBURSE_TYPE","UNION_REIMBURSE_PROJECT"],
//分页数据
mixins: [initTableMixins],
components: {
"union-reimburse-info": unionReimburseInfo
},
data() {
return {
unionOptions: [],
unitOptions: [],
userOptions: [],
}
}
,
methods: {
//查询经办人
createRemoteMethod(options) {
return (keyword) => {
this.selectQueryUser(keyword, options)
}
},
selectQueryUser(keyword, options) {
options.length = 0
this.$axios.post("/platform/UnionReimburse/apply/listUser", {keyword: keyword}).then((res) => {
if (res.code === 0) {
options.push(...res.data)
}
})
},
userChange(val) {
const user = this.userOptions.find(o => o.id === val)
if (user) {
const { userName } = user
this.$set(this.pageForm, "userName", userName)
}
},
onView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.unionReimburseInfoRef.onOpen(row)
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/unionReimburse/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
onExport() {
this.$downLoad(loc() + '/onExport', this.pageForm)
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
//单位查询
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,140 @@
const unionReimburseInfo = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border class="flow-task-form">
<el-descriptions-item label="经办人">{{viewData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
<el-descriptions-item label="单位">{{viewData.unitName}}</el-descriptions-item>
<el-descriptions-item label="工会">{{viewData.unionName}}</el-descriptions-item>
<el-descriptions-item label="报销类别">
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
:value="viewData.reimburseType">
</dict-tag>
</el-descriptions-item>
<el-descriptions-item label="支付方式">
<dict-tag :options="dict.type.UNION_REIMBURSE_PAYMENT_WAY"
:value="viewData.paymentWay">
</dict-tag>
</el-descriptions-item>
<el-descriptions-item label="报销项目">
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
:value="viewData.reimburseProject">
</dict-tag>
</el-descriptions-item>
<el-descriptions-item label="报销经费来源">
<dict-tag :options="dict.type.UNION_REIMBURSE_FUND_SOURCE"
:value="viewData.reimburseFundSource">
</dict-tag>
</el-descriptions-item>
<el-descriptions-item label="联系方式" >{{viewData.mobile}}</el-descriptions-item>
<el-descriptions-item label="所属社团" v-if="viewData.reimburseFundSource === 'UNION_REIMBURSE_FUND_SOURCE_3'">{{viewData.clubName}}</el-descriptions-item>
<el-descriptions-item label="经费余额" >{{viewData.fundBalance}}</el-descriptions-item>
<el-descriptions-item label="户名" >{{viewData.bankUserName}}</el-descriptions-item>
<el-descriptions-item label="银行账号" >{{viewData.bankCardNumber}}</el-descriptions-item>
<el-descriptions-item label="开户行" >{{viewData.bankOfDeposit}}</el-descriptions-item>
<el-descriptions-item label="慰问对象" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">{{viewData.condolenceName}}</el-descriptions-item>
<el-descriptions-item label="联系方式" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">{{viewData.condolenceMobile}}</el-descriptions-item>
<el-descriptions-item label="慰问类型" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">{{viewData.typeName}}</el-descriptions-item>
<el-descriptions-item label="慰问金额" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">{{viewData.money}}</el-descriptions-item>
<el-descriptions-item label="慰问时间" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">{{viewData.condolenceTime}}</el-descriptions-item>
<el-descriptions-item label="活动名称" v-if="viewData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">{{viewData.activityName}}</el-descriptions-item>
<el-descriptions-item label="活动类型" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_2'">{{viewData.activityType}}</el-descriptions-item>
<el-descriptions-item label="活动人数" v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_2'">{{viewData.activityNumber}}</el-descriptions-item>
<el-descriptions-item label="活动地点" v-if="viewData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">{{viewData.activityPlace}}</el-descriptions-item>
<el-descriptions-item label="报销金额" v-if="viewData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">{{viewData.money}}</el-descriptions-item>
<el-descriptions-item label="活动时间" v-if="viewData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">{{viewData.activityTime}}</el-descriptions-item>
<el-descriptions-item label="发票张数" v-if="viewData.reimburseType === 'UNION_REIMBURSE_TYPE_1'">{{viewData.invoiceNumber}}</el-descriptions-item>
<el-descriptions-item label="发票号码" v-if="viewData.reimburseType === 'UNION_REIMBURSE_TYPE_1'">{{viewData.invoice}}</el-descriptions-item>
<el-descriptions-item label="支付内容" :span="2">{{viewData.paymentNotes}}</el-descriptions-item>
<el-descriptions-item label="附件" :span="2">
<file-preview v-if="viewData.files && viewData.files.length > 0" :files="viewData.files" complete_result></file-preview>
<span v-else>暂无附件</span>
</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
}}({{task.ext.initiatorAccount}})
</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName
}}({{task.taskFormData.loginName}})
</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
task.taskFormData.opinion }}
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
store,
dicts: ["UNION_REIMBURSE_TYPE", "UNION_REIMBURSE_PAYMENT_WAY", "UNION_REIMBURSE_FUND_SOURCE","UNION_REIMBURSE_PROJECT","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()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/unionReimburse/apply/info', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
// 查看流程图
openChart(){
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId,this.row.instanceId)
}
}
}
@@ -0,0 +1,209 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="工会名称">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择工会名称" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="单位名称">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择单位名称" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="报销项目">
<el-select v-model="pageForm.reimburseProject" @change="doSearch" style="width: 100%"
placeholder="请选择报销项目" clearable>
<el-option v-for="item in dict.type.UNION_REIMBURSE_PROJECT"
:value="item.code"
:key="item.code"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="经办人">
<el-select
style="width: 100%"
v-model="pageForm.userName"
filterable
clearable
remote
reserve-keyword
placeholder="请输入经办人姓名或工号查询"
:remote-method="createRemoteMethod(userOptions)"
@change="userChange">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.userName+''+item.loginName+''+''+item.unitName+''+''+item.sex+''"
:value="item.id">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="经办人工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="reimburseType" label="报销类别">
<template slot-scope="{row}">
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
:value="row.reimburseType">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="reimburseProject" label="报销项目">
<template slot-scope="{row}">
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
:value="row.reimburseProject">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="money" label="金额"></el-table-column>
<el-table-column prop="createTime" label="申请时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
</el-button>
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<union-reimburse-info ref="unionReimburseInfoRef"></union-reimburse-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["UNION_REIMBURSE_TYPE","UNION_REIMBURSE_PROJECT"],
//分页数据
mixins: [initTableMixins],
components: {
"union-reimburse-info": unionReimburseInfo
},
data() {
return {
unionOptions: [],
unitOptions: [],
userOptions: [],
}
}
,
methods: {
//查询经办人
createRemoteMethod(options) {
return (keyword) => {
this.selectQueryUser(keyword, options)
}
},
selectQueryUser(keyword, options) {
options.length = 0
this.$axios.post("/platform/UnionReimburse/apply/listUser", {keyword: keyword}).then((res) => {
if (res.code === 0) {
options.push(...res.data)
}
})
},
userChange(val) {
const user = this.userOptions.find(o => o.id === val)
if (user) {
const { userName } = user
this.$set(this.pageForm, "userName", userName)
}
},
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.unionReimburseInfoRef.onOpen(row)
})
},
onEdit(row) {
window.location.href = '/platform/unionReimburse/apply?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/unionReimburse/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
}
},
created() {
this.pageData()
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
//单位查询
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,255 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="工会名称">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择工会名称" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="单位名称">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择单位名称" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="报销项目">
<el-select v-model="pageForm.reimburseProject" @change="doSearch" style="width: 100%"
placeholder="请选择报销项目" clearable>
<el-option v-for="item in dict.type.UNION_REIMBURSE_PROJECT"
:value="item.code"
:key="item.code"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="经办人">
<el-select
style="width: 100%"
v-model="pageForm.userName"
filterable
clearable
remote
reserve-keyword
placeholder="请输入经办人姓名或工号查询"
:remote-method="createRemoteMethod(userOptions)"
@change="userChange">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.userName+''+item.loginName+''+''+item.unitName+''+''+item.sex+''"
:value="item.id">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="经办人工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="reimburseType" label="报销类别">
<template slot-scope="{row}">
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
:value="row.reimburseType">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="reimburseProject" label="报销项目">
<template slot-scope="{row}">
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
:value="row.reimburseProject">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="money" label="金额"></el-table-column>
<el-table-column prop="createTime" label="申请时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskState === 10" @click="openAudit(row)" size="mini" type="primary">审核
</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<union-reimburse-info ref="unionReimburseInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">
{{formData.taskName}}
</div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
<el-form-item label="审批意见" prop="tf_opinion"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
</el-row>
</div>
</union-reimburse-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["UNION_REIMBURSE_TYPE","UNION_REIMBURSE_PROJECT"],
//分页数据
mixins: [initTableMixins],
components: {
"union-reimburse-info": unionReimburseInfo
},
data() {
return {
pageForm: {
approval: false
},
formData: {},
showApprovalForm: false,
unionOptions: [],
unitOptions: [],
userOptions: [],
}
}
,
methods: {
//查询经办人
createRemoteMethod(options) {
return (keyword) => {
this.selectQueryUser(keyword, options)
}
},
selectQueryUser(keyword, options) {
options.length = 0
this.$axios.post("/platform/UnionReimburse/apply/listUser", {keyword: keyword}).then((res) => {
if (res.code === 0) {
options.push(...res.data)
}
})
},
userChange(val) {
const user = this.userOptions.find(o => o.id === val)
if (user) {
const { userName } = user
this.$set(this.pageForm, "userName", userName)
}
},
onView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.unionReimburseInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.unionReimburseInfoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
//单位查询
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
}
})
</script>
<!--#
}
#-->