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,54 @@
const childManageInfo = {
template: /*language=HTML*/ `
<div>
<table-tool label="子女信息"></table-tool>
<el-descriptions :column="3" border>
<el-descriptions-item label="就读年级">
<dict-tag :options="dict.type.CHILD_MANAGE_GRADE"
:value="viewData.childrenGrade">
</dict-tag></el-descriptions-item>
<el-descriptions-item label="入学年份">{{viewData.childrenYear}}</el-descriptions-item>
<el-descriptions-item label="姓名">{{viewData.childrenName}}</el-descriptions-item>
<el-descriptions-item label="身份证号">{{viewData.childrenIdCard}}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{$moment(viewData.childrenBirthday).format('YYYY-MM-DD')}}</el-descriptions-item>
<el-descriptions-item label="性别">{{viewData.childrenSex}}</el-descriptions-item>
<el-descriptions-item label="国籍">{{viewData.childrenCountry}}</el-descriptions-item>
<el-descriptions-item label="就读学校">{{viewData.childrenCurrentSchool}}</el-descriptions-item>
<el-descriptions-item label="中考总成绩">{{viewData.childrenMiddleScore}}</el-descriptions-item>
<el-descriptions-item label="学科组合">{{viewData.childrenSubjectCombination}}</el-descriptions-item>
<el-descriptions-item label="户籍所在地" :span="2">{{viewData.childrenHuKouAddress}}</el-descriptions-item>
<el-descriptions-item label="监护人1">{{viewData.guardianUserName1}}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{viewData.guardianMobile1}}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{viewData.guardianUnitName1}}</el-descriptions-item>
<el-descriptions-item label="监护人2">{{viewData.guardianUserName2}}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{viewData.guardianMobile2}}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{viewData.guardianUnitName2}}</el-descriptions-item>
<el-descriptions-item label="备注">{{viewData.note}}</el-descriptions-item>
</el-descriptions>
<slot></slot>
</div>
`,
dicts: ["CHILD_MANAGE_GRADE"],
data() {
return {
viewData: {},
row: null
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.getInfo()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/childManage/write/findOne', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
}
}
@@ -0,0 +1,228 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
placeholder="请选择年度"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="就读年级">
<el-select clearable placeholder="请选择就读年级"
style="width: 100%;"
v-model="pageForm.childrenGrade">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.CHILD_MANAGE_GRADE"></el-option>
</el-select>
</search-item>
<search-item label="姓名">
<el-input @keyup.enter.native="doSearch" clearable
placeholder="请输入内容"
v-model="pageForm.searchKeyword">
<el-select placeholder="查询类型" slot="prepend"
style="width: 100px;"
v-model="pageForm.searchName">
<el-option label="子女姓名" value="info.childrenName"></el-option>
<el-option label="监护人" value="info.guardianUserName"></el-option>
</el-select>
</el-input>
</search-item>
<search-item label="性别">
<el-select clearable placeholder="请选择子女性别"
style="width: 100%;"
v-model="pageForm.childrenSex">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" clearable style="width: 100%"
@change="flushUnits" @clear="flushUnits">
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" style="width: 100%" v-model="pageForm.unitId" clearable
filterable>
<el-option v-for="item in unitOptions" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="统计列表">
<el-button @click="doExportExcel" size="mini" type="primary">导出汇总名单
</el-button>
</table-tool>
<!-- 添加横向滚动容器 -->
<div class="table-container">
<el-table :data="tableData" @sort-change="pageOrder" style="width: 2000px">
<el-table-column type="index" width="60" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="childrenGrade" label="年级" width="100">
<template slot-scope="{row}">
<dict-tag :options="dict.type.CHILD_MANAGE_GRADE"
:value="row.childrenGrade">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="childrenYear" label="入学年份" width="100"></el-table-column>
<el-table-column prop="childrenName" label="子女姓名" width="120"></el-table-column>
<el-table-column prop="childrenSex" label="性别" width="80"></el-table-column>
<el-table-column prop="childrenBirthday" label="出生日期" width="120"></el-table-column>
<el-table-column prop="childrenBirthday" label="年龄" width="80">
<template v-slot="scope">
<span>{{ calculateAge(scope.row.childrenBirthday) }}</span>
</template>
</el-table-column>
<el-table-column prop="childrenCurrentSchool" label="就读学校" width="150"></el-table-column>
<el-table-column prop="guardianUserName1" label="监护人1" width="120"></el-table-column>
<el-table-column prop="guardianMobile1" label="手机号码" width="120"></el-table-column>
<el-table-column prop="guardianUnitName1" label="所在单位" width="150"></el-table-column>
<el-table-column prop="guardianUserName2" label="监护人2" width="120"></el-table-column>
<el-table-column prop="guardianMobile2" label="手机号码" width="120"></el-table-column>
<el-table-column prop="guardianUnitName2" label="所在单位" width="150"></el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作" width="250">
<template scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">
查看
</el-button>
<el-button @click="openEdit(row)" size="mini" type="primary">
编辑
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<child-manage-info ref="childManageInfoRef">
</child-manage-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["CHILD_MANAGE_GRADE"],
mixins: [initTableMixins],
components: {
"child-manage-info": childManageInfo
},
data() {
return {
pageDataUrl: "/platform/childManage/manage/pageData",
pageForm: {
year: moment().format("YYYY"),
},
unionOptions: [],
unitOptions: []
}
},
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.childManageInfoRef.onOpen(row)
})
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
}
},
calculateAge(birthday) {
console.log('Birthday:', birthday);
if (!birthday) return '';
const birthDate = new Date(birthday);
if (isNaN(birthDate.getTime())) {
console.log('Invalid date:', birthday);
return '';
}
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
console.log('Calculated age:', age);
return age >= 0 ? age : '未出生';
},
openEdit(row) {
commonUtil.pjaxPush('/platform/childManage/write/index?bizId=' + row.id + '&manage=1')
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/childManage/manage/doDelete", {id: id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
doExportExcel() {
this.$downLoad("/platform/childManage/manage/doExportExcel", {
data: JSON.stringify(this.pageForm)
})
},
},
async created() {
this.pageData()
this.unionOptions = await this.$businessTool.listUnion()
this.unitOptions = await this.$businessTool.listUnit()
}
})
</script>
<style>
.table-container {
overflow-x: auto;
overflow-y: visible;
width: 100%;
}
/* 确保操作列在滚动时保持固定 */
.el-table .el-table__fixed-right {
height: 100% !important;
background-color: #fff;
z-index: 10;
}
/* 设置表格单元格的最小宽度 */
.el-table .el-table__body td {
min-width: 60px;
}
</style>
<!--#
}
#-->
@@ -0,0 +1,173 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
placeholder="请选择年度"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="填报列表">
</table-tool>
<!-- 添加一个带有横向滚动的容器 -->
<div class="table-container">
<el-table :data="tableData" @sort-change="pageOrder" style="width: 2000px">
<el-table-column type="index" width="60" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="childrenGrade" label="年级" width="100">
<template slot-scope="{row}">
<dict-tag :options="dict.type.CHILD_MANAGE_GRADE"
:value="row.childrenGrade">
</dict-tag>
</template>
</el-table-column>
<el-table-column prop="childrenYear" label="入学年份" width="100"></el-table-column>
<el-table-column prop="childrenName" label="子女姓名" width="120"></el-table-column>
<el-table-column prop="childrenSex" label="性别" width="80"></el-table-column>
<el-table-column prop="childrenBirthday" label="出生日期" width="120"></el-table-column>
<el-table-column prop="childrenBirthday" label="年龄" width="80">
<template v-slot="scope">
<span>{{ calculateAge(scope.row.childrenBirthday) }}</span>
</template>
</el-table-column>
<el-table-column prop="childrenCurrentSchool" label="就读学校" width="150"></el-table-column>
<el-table-column prop="guardianUserName1" label="监护人1" width="120"></el-table-column>
<el-table-column prop="guardianMobile1" label="手机号码" width="120"></el-table-column>
<el-table-column prop="guardianUnitName1" label="所在单位" width="150"></el-table-column>
<el-table-column prop="guardianUserName2" label="监护人2" width="120"></el-table-column>
<el-table-column prop="guardianMobile2" label="手机号码" width="120"></el-table-column>
<el-table-column prop="guardianUnitName2" label="所在单位" width="150"></el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作" width="250">
<template scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">
查看
</el-button>
<el-button @click="openEdit(row)" size="mini" type="primary">
编辑
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<child-manage-info ref="childManageInfoRef">
</child-manage-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["CHILD_MANAGE_GRADE"],
mixins: [initTableMixins],
components: {
"child-manage-info": childManageInfo
},
data() {
return {
pageDataUrl: "/platform/childManage/mine/pageData",
pageForm: {
year: moment().format("YYYY"),
}
}
},
methods: {
openView(row) {
this.$refs.guava.view(()=>{
this.$refs.childManageInfoRef.onOpen(row)
})
},
calculateAge(birthday) {
console.log('Birthday:', birthday);
if (!birthday) return '';
const birthDate = new Date(birthday);
if (isNaN(birthDate.getTime())) {
console.log('Invalid date:', birthday);
return '';
}
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
console.log('Calculated age:', age);
return age >= 0 ? age : '未出生';
},
openEdit(row) {
commonUtil.pjaxPush('/platform/childManage/write/index?bizId=' + row.id)
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/childManage/mine/doDelete", {id: id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
}
},
async created() {
this.pageData()
}
})
</script>
<style>
.table-container {
overflow-x: auto;
overflow-y: visible;
width: 100%;
}
/* 确保操作列在滚动时保持固定 */
.el-table .el-table__fixed-right {
height: 100% !important;
background-color: #fff;
}
/* 设置表格单元格的最小宽度 */
.el-table .el-table__body td {
min-width: 60px;
}
/* 确保固定列显示在最上层 */
.el-table__fixed-right {
z-index: 10;
}
</style>
<!--#
}
#-->
@@ -0,0 +1,245 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<h3 style="color: var(--color-primary)" slot="header">信息填报</h3>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
<table-tool label="子女信息"></table-tool>
<el-descriptions :column="2" border>
<el-descriptions-item label="就读年级">
<el-form-item prop="childRelationship">
<dict-select v-model="formData.childRelationship" code="CHILD_MANAGE_GRADE" style="width: 100%" placeholder="请选择就读年级">
</dict-select>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="入学年份">
<el-form-item prop="childrenBirthday">
<el-date-picker
v-model="formData.childrenYear"
type="year"
placeholder="请选择入学年份"
style="width: 100%;"
value-format="yyyy">
</el-date-picker>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="姓名">
<el-form-item prop="childrenName">
<el-input v-model="formData.childrenName" placeholder="请输入子女姓名"
maxlength="30"></el-input>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="身份证号">
<el-form-item prop="childrenIdCard">
<el-input v-model="formData.childrenIdCard" placeholder="请输入身份证号"
maxlength="19">
<el-button slot="append" icon="el-icon-search" @click="getIsRepeatByIdCard"></el-button>
</el-input>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="出生日期">
<el-form-item prop="childrenBirthday">
<el-date-picker
v-model="formData.childrenBirthday"
type="date"
placeholder="请选择子女出生年月"
style="width: 100%;"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="childrenSex">
<el-select clearable placeholder="请选择性别"
style="width: 100%;"
v-model="formData.childrenSex">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="国籍">
<el-form-item prop="childrenCountry">
<el-input v-model="formData.childrenCountry" placeholder="请输入子女国籍"
maxlength="30"></el-input>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="就读学校">
<el-form-item prop="childrenCurrentSchool">
<el-input v-model="formData.childrenCurrentSchool" placeholder="请输入现就读学校"
maxlength="30"></el-input>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="中考总成绩">
<el-form-item prop="childrenMiddleScore">
<el-input v-model="formData.childrenMiddleScore" placeholder="请输入中考总成绩"
maxlength="30" type="number"></el-input>
</el-form-item></el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="学科组合">
<el-form-item prop="childrenSubjectCombination">
<el-input v-model="formData.childrenSubjectCombination" placeholder="请输入学科组合"
maxlength="30"></el-input>
</el-form-item></el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="户籍所在地">
<el-form-item prop="childrenHuKouAddress">
<el-input v-model="formData.childrenHuKouAddress" placeholder="请输入户籍所在地"
maxlength="30"></el-input>
</el-form-item></el-descriptions-item>
</el-descriptions-item>
</el-descriptions>
<table-tool label="监护人信息"></table-tool>
<el-descriptions :column="2" border>
<el-descriptions-item label="监护人1">
<el-form-item label="监护人1" prop="guardianUserName1">
<el-input v-model="formData.guardianUserName1" readonly></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工号" >
<el-form-item prop="guardianLoginName1">{{formData.guardianLoginName1}}
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="手机号码">
<el-form-item prop="guardianMobile1">
<el-input v-model="formData.guardianMobile1" placeholder="请输入手机号码" maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所在单位">
<el-form-item prop="unitName1">
<el-input v-model="formData.guardianUnitName1" readonly></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="监护人2">
<el-form-item label="监护人2" prop="guardianUserName2">
<el-input v-model="formData.guardianUserName2" placeholder="请输入监护人姓名" maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工号">
<el-form-item prop="guardianLoginName2">
<el-input v-model="formData.guardianLoginName2" placeholder="没有则不填" maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="手机号码">
<el-form-item prop="guardianMobile2">
<el-input v-model="formData.guardianMobile2" placeholder="请输入手机号码" maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所在单位">
<el-form-item prop="guardianUnitName2">
<el-input v-model="formData.guardianUnitName2" placeholder="请输入所在单位" maxlength="100"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="备注">
<el-form-item prop="note">
<el-input v-model="formData.note" placeholder="请填写备注"
maxlength="50"></el-input>
</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-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
data() {
return {
bizId: GetQueryString("bizId"),
formData: {},
formRules: {
childRelationship: [{ required: true, message: '请选择就读年级', trigger: 'change' }],
childrenYear: [{ required: true, message: '请选择入学年份', trigger: 'change' }],
childrenName: [{ required: true, message: '请输入子女姓名', trigger: 'blur' }],
childrenIdCard: [{ required: true, message: '请输入子女身份证号', trigger: 'blur' }, {pattern: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/, message: '请输入正确的身份证号码', trigger: 'blur'}],
childrenBirthday: [{ required: true, message: '请选择子女出生日期', trigger: 'change' }],
childrenSex: [{ required: true, message: '请选择性别', trigger: 'change' }],
guardianMobile1: [{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }],
guardianMobile2: [{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }]
}
}
},
methods: {
async getIsRepeatByIdCard() {
if (!this.formData.childrenIdCard) {
this.$message.error("请填写子女身份证号码")
return
}
const res = await this.$axios.post('/platform/childManage/write/getIsRepeatByIdCard', {
idCard: this.formData.childrenIdCard,
id: this.formData.id
})
if (res.code === 0) {
if (res.data > 0) {
this.$message.error("该身份证在本年度已填报!")
return true
} else {
this.$message.success("该身份证在本年度暂未填报!")
return false
}
}
},
// 保存方法
onSave() {
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/childManage/write/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
if (GetQueryString('manage') === '1') {
commonUtil.pjaxPush('/platform/childManage/manage/index')
}else {
commonUtil.pjaxPush('/platform/childManage/mine/index')
}
}
})
})
},
async findOne(id) {
const resp = await $.get('/platform/childManage/write/findOne', {id})
if (resp.code === 0) {
return resp.data
}
},
init() {
if (this.bizId) {
this.findOne(this.bizId).then(async data => {
this.formData = data
})
} else {
const {id, username, loginname, mobile, union, unit} = this.$store.state.user
this.formData = {
userId: id,
userName: username,
loginName: loginname,
unitName: unit.name,
unitId: unit.id,
unionName: union.name,
unionId: union.id,
mobile: mobile,
// 自动填充监护人1信息
guardianUserName1: username,
guardianLoginName1: loginname,
guardianMobile1: mobile,
guardianUnitName1: unit.name,
guardianUnitId1: unit.id,
guardianUnionName1: union.name,
guardianUnionId1: union.id
}
}
}
},
created() {
this.init()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,45 @@
<div id="member_apply_branch_union_approval_form">
<el-form :model="formData" ref="formRef" 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>
<snaker-flow-task-form-action @task-action="handleTaskAction" @cancel="handleCancel"></snaker-flow-task-form-action>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_apply_branch_union_approval_form",
data() {
return {
businessId: GetQueryString("businessId"),
formData: {
tf_opinion: ""
},
}
},
methods: {
handleTaskAction(val) {
console.log(val)
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...val,
...this.formData
})
}).then(res => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.GlobalBroadcastChannel.postMessage({
type: "task-complete",
payload: val
})
}
})
},
handleCancel(val) {
console.log(val)
},
}
})
</script>
@@ -0,0 +1,196 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="申请列表">
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.audit">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='sign'">
<el-image v-if="row.sign" :src="row.sign" style="height: 60px"></el-image>
<el-tag type="warning" v-else>暂无</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">
查看
</el-button>
<el-button v-if="row.taskState === 10" @click="openApproval(row)" size="mini" type="primary">
审核
</el-button>
<el-button v-if="row.canRevoke" @click="openRevoke(row)" size="mini" type="danger">
撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<info ref="infoRef">
<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>
</info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
audit: false
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "sign", label: "签字" },
{ prop: "curTaskName", label: "当前节点" },
{ prop: "instanceState", label: "流程状态" }
],
// 审核相关
showApprovalForm: false,
formData: {
tf_opinion: ""
},
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
openApproval(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.infoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
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()
}
}).finally(() => {
loading.close()
})
})
},
openRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(()=>{
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,93 @@
const COMMON_QUERY = {
template: /*language=HTML*/ `
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<template v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN', 'BRANCH_UNION_CHAIRMAN'])">
<search-item label="所属工会">
<el-select
@change="flushUnits"
@clear="flushUnits"
clearable
filterable
placeholder="请选择所属工会"
style="width: 100%"
v-model="pageForm.unionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%" v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userStates" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personTypes" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBys" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE" multiple collapse-tags></dict-select>
</search-item>
</template>
</search>
`,
store,
mixins: [initTableMixins],
data() {
return{
unions: [],
units: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
userStates: [],
personTypes: [],
preparedBys: [],
}
}
},
methods: {
doSearch(){
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
this.$emit('search', pageForm)
},
async initData(){
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unions = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
} else if (this.$auth.hasRole("BRANCH_UNION_CHAIRMAN")) {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
})
}
},
async flushUnits(){
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
}
}
},
async created() {
this.initData()
}
}
@@ -0,0 +1,139 @@
const INFO = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ $moment(viewData.birthday).format("YYYY年MM月DD日") }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</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="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="编制类别">{{ viewData.preparedBy }}</el-descriptions-item>
<template v-if="viewData.loginname == $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"></div>
<el-tag type="warning" v-else>暂无</el-tag>
</el-descriptions-item>
</template>
<el-descriptions-item label="签字信息" :span="3" v-if="viewData.sign">
<el-image :src="viewData.sign"
class="signature-image"></el-image>
</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>
<template v-if="task.taskFormData.tf_allocation_unionId">
<el-descriptions-item label="分配工会" :span="1.5">
{{ task.taskFormData.tf_allocation_unionName }}
</el-descriptions-item>
<el-descriptions-item label="分配前工会" :span="1.5">
{{ task.taskFormData.tf_self_unionName }}
</el-descriptions-item>
</template>
<el-descriptions-item label="办理意见" :span="3" 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: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
row: {},
viewData: {},
doneTasks: []
}
},
methods: {
onOpen(row) {
this.row = row
this.info()
this.getDoneTasks()
},
info() {
this.$axios.post("/platform/member/apply/mine/findMemberApplyRecord", { 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,127 @@
const MEMBER_APPLY_AUDIT_INFO = {
template: /*language=HTML*/ `
<div>
<el-tabs v-model="activeName">
<el-tab-pane label="申请信息" name="basicInfo">
<el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ moment(viewData.birthday).format("YYYY年MM月DD日") }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.userUnitName }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.userUnionName }}</el-descriptions-item>
<el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center" header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<div v-if="viewData.vita" class="text-left" v-html="viewData.vita"></div>
<el-tag type="warning" v-else>暂无</el-tag>
</el-descriptions-item>
<el-descriptions-item label="签字信息" :span="3">
<el-image v-if="viewData.sign" :src="viewData.sign"
class="signature-image"></el-image>
<el-tag type="warning" v-else>暂无</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane v-if="viewData.nodeTasks && viewData.nodeTasks.length > 0" label="审核信息" name="audit">
<div>
<div v-for="nodeTask in viewData.nodeTasks" :key="nodeTask.id">
<div class="process-title">
{{nodeTask.nodeName}}
</div>
<el-descriptions :column="3" border v-for="task in nodeTask.tasks" :key="task.id"
style="margin-bottom: 10px">
<el-descriptions-item label="审核人">
{{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}}
</el-descriptions-item>
<el-descriptions-item label="审核时间">{{ task.endOn}}</el-descriptions-item>
<el-descriptions-item label="审核结果">
<div v-if="task.extVariable">
<el-tag type="success" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'PASS'">同意
</el-tag>
<el-tag type="danger" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'BACK'">退回
</el-tag>
<el-tag type="danger" size="mini"
v-if="task.extVariable.bpmTaskApprovalType === 'REJECT'">拒绝
</el-tag>
</div>
</el-descriptions-item>
<el-descriptions-item label="审核意见" :span="3">
{{ task.extVariable.approvalOpinion }}
</el-descriptions-item>
<template v-if="$auth.hasRoleOr('SYSADMIN') && task.extVariable.approvalRemark">
<el-descriptions-item label="审核说明" :span="3">
{{ task.extVariable.approvalRemark }}
</el-descriptions-item>
</template>
<el-descriptions-item label="签字" :span="3">
<el-image :src="task.extVariable.approvalSignature"
v-if="task.extVariable && task.extVariable.approvalSignature"
class="signature-image"></el-image>
</el-descriptions-item>
</el-descriptions>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
`,
data() {
return{
activeName: "basicInfo",
viewData: {
nodeTasks: {}
}
}
},
methods: {
async onOpen(id){
const resp = await $.post('/platform/member/apply/mine/findMemberApplyRecord', {id})
if (resp.code === 0) {
this.viewData = resp.data
this.$emit('union-name', this.viewData.userUnionName)
if (this.viewData.families) {
this.viewData.families = JSON.parse(this.viewData.families)
} else {
this.viewData.families = []
}
}
}
}
}
@@ -0,0 +1,163 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="申请列表">
<el-button size="small" type="primary" @click="onApply">申请入会</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='sign'">
<el-image v-if="row.sign" :src="row.sign" style="height: 60px"></el-image>
<el-tag type="warning" v-else>暂无</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="220" fixed="right">
<template slot-scope="{row}">
<el-button @click="openView(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>
<info ref="info"></info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "sign", label: "签字" },
{ prop: "taskName", label: "当前节点"},
{ prop: "instanceState", label: "流程状态"}
],
unions: [],
units: []
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
onApply() {
commonUtil.pjaxPush('/platform/member/apply/submit')
},
openView(row) {
this.$refs.guava.view(() => {
this.$refs.info.onOpen(row)
})
},
onEdit(row) {
commonUtil.pjaxPush('/platform/member/apply/submit?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", { taskId: row.startTaskId }).then((resp) => {
this.$message.success(resp.msg)
this.pageData()
}).finally(() => {
loading.close()
})
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post("/platform/member/apply/mine/onDelete", { id }).then((res) => {
if (res.code === 0) {
this.doSearch()
this.$message.success(res.msg)
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,84 @@
<div id="member_apply_school_union_approval_form">
<el-form :model="formData" ref="approvalFormRef" label-position="left" label-width="110px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="分配工会关系" prop="tf_allocation_unionId"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select clearable filterable placeholder="请选择工会" style="width: 100%;"
@change="assignmentUnionName"
v-model="formData.tf_allocation_unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="当前所在工会" prop="tf_self_unionName">
<el-input v-model="formData.tf_self_unionName" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<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-item label="电子签名" prop="approvalSignature" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">-->
<!-- <pc-signature v-model="formData.approvalSignature"></pc-signature>-->
<!-- </el-form-item>-->
</el-form>
<snaker-flow-task-form-action @task-action="handleTaskAction"
@cancel="handleCancel">
</snaker-flow-task-form-action>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_apply_school_union_approval_form",
store,
data() {
return {
businessId: GetQueryString("businessId"),
formData: {
tf_opinion: "",
tf_self_unionName: this.$store.state.user.union.name
},
unions: []
}
},
methods: {
handleTaskAction(val) {
console.log(val)
const data = {
...val,
...this.formData
}
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify(data)
}).then(res => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.GlobalBroadcastChannel.postMessage({
type: "task-complete",
payload: val
})
}
})
},
handleCancel(val) {
console.log(val)
},
// 分配工会名称
assignmentUnionName(val) {
const union = this.unions.find(item => item.id === val)
this.$set(this.formData, "tf_allocation_unionName", union.name)
},
},
created() {
this.$businessTool.listUnion().then(data => {
this.unions = data
})
}
})
</script>
@@ -0,0 +1,227 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="申请列表">
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.audit">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='sign'">
<el-image v-if="row.sign" :src="row.sign" style="height: 60px"></el-image>
<el-tag type="warning" v-else>暂无</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
<el-button v-if="row.taskState === 10" @click="openApproval(row)" size="mini" type="primary">
审核
</el-button>
<el-button v-if="row.canRevoke" @click="openRevoke(row)" size="mini" type="danger">
撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<info ref="infoRef">
<div v-if="showApprovalForm">
<div class="process-title">
{{formData.taskName}}
</div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="130px" label-suffix="">
<el-row :gutter="20" v-if="formData.origin === 'HMC'">
<el-col :span="12">
<el-form-item label="分配工会关系" prop="tf_allocation_unionId"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select clearable filterable placeholder="请选择工会" style="width: 100%;"
@change="assignmentUnionName"
v-model="formData.tf_allocation_unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="当前所在工会" prop="tf_self_unionName">
<el-input v-model="formData.tf_self_unionName" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<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>
</info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
audit: false
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "sign", label: "签字" },
{ prop: "curTaskName", label: "当前节点" },
{ prop: "instanceState", label: "流程状态" }
],
// 审核相关
showApprovalForm: false,
formData: {
tf_opinion: ""
},
unions: [],
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
openApproval(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
origin: row.origin,
processTaskId: row.taskId,
taskName: row.curTaskName
}
if (row.origin === "HMC") {
this.$set(this.formData, "tf_self_unionName", this.$store.state.user.union.name)
}
this.$refs.infoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
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()
}
}).finally(() => {
loading.close()
})
})
},
openRevoke(taskId) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", { taskId }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
// 分配工会名称
assignmentUnionName(val) {
const union = this.unions.find(item => item.id === val)
this.$set(this.formData, "tf_allocation_unionName", union.name)
},
},
created() {
this.pageData()
this.$businessTool.listUnion().then(data => {
this.unions = data
})
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,466 @@
<div id="member_apply">
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">
<el-form-item prop="loginname">
<el-input v-model="formData.loginname" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="姓名">
<el-form-item prop="username">
<el-input v-model="formData.username" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="sex">
<el-radio-group v-model="formData.sex" size="small">
<el-radio border label="男"></el-radio>
<el-radio border label="女"></el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="民族">
<el-form-item prop="nation">
<dict-select style="width: 100%" placeholder="请选择民族" v-model="formData.nation"
code="USER_NATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="出生日期">
<el-form-item prop="birthday">
<el-date-picker v-model="formData.birthday" type="date"
placeholder="请选择出生日期"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="政治面貌">
<el-form-item prop="political">
<dict-select style="width: 100%" placeholder="请选择政治面貌" v-model="formData.political"
code="USER_POLITICAL"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学历">
<el-form-item prop="education">
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
code="USER_EDUCATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学位">
<el-form-item prop="academicDegree">
<dict-select style="width: 100%" placeholder="请选择学位" v-model="formData.academicDegree"
code="USER_ACADEMIC_DEGREE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="党政职务">
<el-form-item prop="position">
<el-input v-model="formData.position" placeholder="请输入党政职务"
maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
disabled @change="getUnionName(formData.unitId)"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionName">
<el-input v-model="formData.unionName" disabled placeholder="请输入所属工会"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
code="USER_CAMPUS"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="formData.userState" code="USER_STATE"
disabled style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="教职工类别">
<el-form-item prop="personType">
<dict-select v-model="formData.personType" code="USER_PERSON_TYPE"
disabled style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="身份证号码">
<el-form-item prop="idCard">
<el-input v-model="formData.idCard" disabled placeholder="请输入身份证号码" maxlength="18"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" disabled placeholder="请输入联系电话" maxlength="32"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="电子邮箱">
<el-form-item prop="email">
<el-input v-model="formData.email" placeholder="请输入电子邮箱" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="家庭主要成员" :span="3">
<el-form-item prop="families">
<el-table :data="formData.families" border size="small">
<el-table-column label="关系" prop="relation">
<template slot-scope="{row}">
<el-input v-model="row.relation" maxlength="50"
placeholder="请输入与本人关系"></el-input>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name">
<template slot-scope="{row}">
<el-input v-model="row.name" maxlength="50" placeholder="请输入姓名"></el-input>
</template>
</el-table-column>
<el-table-column label="工作单位" prop="unit">
<template slot-scope="{row}">
<el-input v-model="row.unit" maxlength="100"
placeholder="请输入工作单位"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" maxlength="100" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column width="100px">
<template slot="header" slot-scope="scope">
<el-button type="primary" size="mini"
@click="formData.families.push({})">添加
</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="formData.families.length===0"
@click="formData.families.splice(scope.$index,1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<el-form-item prop="personalData">
<text-editor v-model="formData.personalData"></text-editor>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="入会意愿" :span="3">
<el-form-item prop="isVoluntary">
<el-checkbox
size="medium"
style="width: 95%; color: #F56C6C; display: flex; align-items: center;"
v-model="formData.isVoluntary">
<div>
<span style="flex: 1; word-wrap: break-word; word-break: break-all; white-space: normal;">
我自愿申请加入学校工会,并委托学校按规定代为扣缴工会会员会费。
</span>
</div>
<div>
<span style="flex: 1; word-wrap: break-word; word-break: break-all; white-space: normal;">
我将严格遵守工会章程,认真执行工会决议,积极参与工会活动,主动融入“学校健康幸福家”建设,为营造温暖、和谐、奋进的校园氛围贡献力量,以实际行动助力学校各项事业发展。
</span>
</div>
</el-checkbox>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="签字" :span="3">
<el-form-item prop="sign">
<pc-signature v-model="formData.sign"></pc-signature>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<snaker-flow-task-form-action @task-action="handleTaskAction" @save-draft="handleSaveDraft"></snaker-flow-task-form-action>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_apply",
store,
data() {
return {
businessId: GetQueryString("businessId"),
instanceId: GetQueryString("instanceId"),
units: [],
formData: {
families: []
},
formRules: {
username: [{required: false, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: false, message: "必填", trigger: ["change", "blur"]}],
isVoluntary: [{required: true, message: "必填", trigger: ["change", "blur"]}],
sign: [{required: true, message: "必填", trigger: ["change", "blur"]}],
email: [
{
validator: (rule, value, callback) => {
if (!value) {
callback();
} else if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
callback();
} else {
callback(new Error("邮箱格式错误"));
}
},
trigger: ["change", "blur"]
}
],
idCard: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}(\d|[Xx])$/.test(value)) {
// 18位身份证号码格式正确
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 15位身份证号码格式正确
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(18位)
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(15位)
callback();
} else {
// 格式错误,返回错误信息
callback(new Error("身份证号码格式错误"));
}
},
trigger: ["change", "blur"]
}
],
mobile: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1][345789][0-9]{9}$/.test(value)) {
// 手机号格式正确
callback();
} else if (/^\d+-\d+$/.test(value) && value.length <= 16) {
// 座机号格式正确
callback();
} else {
// 格式错误,返回错误信息
callback(new Error(value.includes('-') ? '座机号码格式错误' : '手机号码格式错误'));
}
},
trigger: ["change", "blur"]
}
]
},
}
},
methods: {
// 提交
handleTaskAction(val) {
this.$refs.formRef.validate((valid) => {
if (valid) {
if (!this.instanceId) {
this.handleApply(val)
} else {
this.handleReApply(val)
}
}
})
},
// 提交申请
handleApply(val) {
this.$confirm("您确定要提交吗?", "提示", { type: "warning" })
.then(() => {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios
.post("/flow/common/startInstanceAndExecute", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.GlobalBroadcastChannel.postMessage({
type: "task-complete"
})
}
})
}
})
})
},
// 重新提交申请
handleReApply(val) {
this.$confirm("您确定要提交吗?", "提示", { type: "warning" })
.then(() => {
this.$axios
.post("/flow/common/executeTask", {
data: JSON.stringify({
processTaskId: val.taskId,
processInstanceId: val.instanceId,
submitType: val.submitType,
f_data: JSON.stringify(this.formData)
})
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
window.GlobalBroadcastChannel.postMessage({
type: "task-complete"
})
}
})
})
},
// 保存
handleSaveDraft(val) {
this.$confirm("您确定要保存吗?", "提示", { type: "warning" })
.then(() => {
this.$axios
.post("/flow/common/startInstance", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage(
{
type: "task-complete"
},
"*"
)
}
})
})
},
// 取消
handleCancel() {
},
async validateApply() {
if (this.formData.id) {
return
}
// const resp = await $.post('/platform/member/apply/submit/validateApply')
// if (resp.code === 0 && resp.data > 0) {
// this.$confirm("您有其他入会流程正在进行中,请勿重复申请,如需查看详情,可前往我的申请界面,是否前往?", "提示", { type: "warning" })
// .then(() => {
// this.member = true
// this.$store.dispatch("pjaxRoute", "/platform/member/apply/mine")
// })
// .catch(() => {
// this.member = true
// })
// }
},
async init() {
let user
const resp = await $.post('/platform/member/apply/submit/getSelfUserInfo')
if (resp.code === 0) {
if (!resp.data) {
user = this.$store.state.user
} else {
user = resp.data
}
} else {
user = this.$store.state.user
}
this.member = user.member
if (this.id) {
this.$axios.post("/platform/member/apply/submit/findApplyById", { id: this.id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
} else {
const {
id,
username,
loginname,
sex,
nation,
birthday,
political,
education,
academicDegree,
position,
unitId,
unitName,
unit,
unionId,
unionName,
union,
campus,
userState,
personType,
idCard,
mobile,
email,
families,
personalData
} = user
this.$set(this.formData, "userId", id)
this.$set(this.formData, "username", username)
this.$set(this.formData, "loginname", loginname)
this.$set(this.formData, "birthday", birthday)
this.$set(this.formData, "sex", sex)
this.$set(this.formData, "idCard", idCard)
this.$set(this.formData, "nation", nation)
this.$set(this.formData, "political", political)
this.$set(this.formData, "position", position)
this.$set(this.formData, "education", education)
this.$set(this.formData, "academicDegree", academicDegree)
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "userState", userState)
this.$set(this.formData, "personType", personType)
this.$set(this.formData, "unitName", unit ? unit.name : unitName)
this.$set(this.formData, "unitId", unit ? unit.id : unitId)
this.$set(this.formData, "unionName", union ? union.name : unionName)
this.$set(this.formData, "unionId", union ? union.id : unionId)
this.$set(this.formData, "mobile", mobile)
this.$set(this.formData, "email", email)
this.$set(this.formData, "families", families ? families : [])
this.$set(this.formData, "personalData", personalData)
}
},
},
async created() {
this.init()
this.units = await this.$businessTool.listUnit()
await this.validateApply()
}
})
</script>
@@ -0,0 +1,442 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<snaker-start slot="header" label="入会申请" define_key="HYRH"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">
<el-form-item prop="loginname">
<el-input v-model="formData.loginname" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="姓名">
<el-form-item prop="username">
<el-input v-model="formData.username" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="sex">
<el-radio-group v-model="formData.sex" size="small">
<el-radio border label="男"></el-radio>
<el-radio border label="女"></el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="民族">
<el-form-item prop="nation">
<dict-select style="width: 100%" placeholder="请选择民族" v-model="formData.nation"
code="USER_NATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="出生日期">
<el-form-item prop="birthday">
<el-date-picker v-model="formData.birthday" type="date"
placeholder="请选择出生日期"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="政治面貌">
<el-form-item prop="political">
<dict-select style="width: 100%" placeholder="请选择政治面貌" v-model="formData.political"
code="USER_POLITICAL"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学历">
<el-form-item prop="education">
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
code="USER_EDUCATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学位">
<el-form-item prop="academicDegree">
<dict-select style="width: 100%" placeholder="请选择学位" v-model="formData.academicDegree"
code="USER_ACADEMIC_DEGREE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="党政职务">
<el-form-item prop="position">
<el-input v-model="formData.position" placeholder="请输入党政职务"
maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
disabled @change="getUnionName(formData.unitId)"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionName">
<el-input v-model="formData.unionName" disabled placeholder="请输入所属工会"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
code="USER_CAMPUS"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="formData.userState" code="USER_STATE"
disabled style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="教职工类别">
<el-form-item prop="personType">
<dict-select v-model="formData.personType" code="USER_PERSON_TYPE"
disabled style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="编制类别">
<el-form-item prop="preparedBy">
<dict-select v-model="formData.preparedBy" code="USER_PREPARED_BY_TYPE"
disabled style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="身份证号码">
<el-form-item prop="idCard">
<el-input v-model="formData.idCard" disabled placeholder="请输入身份证号码" maxlength="18"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" disabled placeholder="请输入联系电话" maxlength="32"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="电子邮箱">
<el-form-item prop="email">
<el-input v-model="formData.email" placeholder="请输入电子邮箱" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="家庭主要成员" :span="3">
<el-form-item prop="families">
<el-table :data="formData.families" border size="small">
<el-table-column label="关系" prop="relation">
<template slot-scope="{row}">
<el-input v-model="row.relation" maxlength="50"
placeholder="请输入与本人关系"></el-input>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name">
<template slot-scope="{row}">
<el-input v-model="row.name" maxlength="50" placeholder="请输入姓名"></el-input>
</template>
</el-table-column>
<el-table-column label="工作单位" prop="unit">
<template slot-scope="{row}">
<el-input v-model="row.unit" maxlength="100"
placeholder="请输入工作单位"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" maxlength="100" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column width="100px">
<template slot="header" slot-scope="scope">
<el-button type="primary" size="mini"
@click="formData.families.push({})">添加
</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="formData.families.length===0"
@click="formData.families.splice(scope.$index,1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<el-form-item prop="personalData">
<text-editor v-model="formData.personalData"></text-editor>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="入会意愿" :span="3">
<el-form-item prop="isVoluntary">
<el-checkbox
size="medium"
style="width: 95%; color: #F56C6C; display: flex; align-items: center;"
v-model="formData.isVoluntary">
<div>
<span style="flex: 1; word-wrap: break-word; word-break: break-all; white-space: normal;">
我自愿申请加入学校工会,并委托学校按规定代为扣缴工会会员会费。
</span>
</div>
<div>
<span style="flex: 1; word-wrap: break-word; word-break: break-all; white-space: normal;">
我将严格遵守工会章程,认真执行工会决议,积极参与工会活动,主动融入“学校健康幸福家”建设,为营造温暖、和谐、奋进的校园氛围贡献力量,以实际行动助力学校各项事业发展。
</span>
</div>
</el-checkbox>
</el-form-item>
</el-descriptions-item>
<!-- <el-descriptions-item label="签字" :span="3">-->
<!-- <el-form-item prop="sign">-->
<!-- <pc-signature v-model="formData.sign"></pc-signature>-->
<!-- </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>提交</el-button>
</el-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
id: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
units: [],
formData: {
families: []
},
formRules: {
username: [{required: false, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: false, message: "必填", trigger: ["change", "blur"]}],
isVoluntary: [{required: true, message: "必填", trigger: ["change", "blur"]}],
sign: [{required: true, message: "必填", trigger: ["change", "blur"]}],
/*email: [
{
validator: (rule, value, callback) => {
if (!value) {
callback();
} else if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
callback();
} else {
callback(new Error("邮箱格式错误"));
}
},
trigger: ["change", "blur"]
}
],
idCard: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}(\d|[Xx])$/.test(value)) {
// 18位身份证号码格式正确
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 15位身份证号码格式正确
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(18位)
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(15位)
callback();
} else {
// 格式错误,返回错误信息
callback(new Error("身份证号码格式错误"));
}
},
trigger: ["change", "blur"]
}
],
mobile: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1][345789][0-9]{9}$/.test(value)) {
// 手机号格式正确
callback();
} else if (/^\d+-\d+$/.test(value) && value.length <= 16) {
// 座机号格式正确
callback();
} else {
// 格式错误,返回错误信息
callback(new Error(value.includes('-') ? '座机号码格式错误' : '手机号码格式错误'));
}
},
trigger: ["change", "blur"]
}
]*/
},
}
},
methods: {
onSave() {
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/apply/submit/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush('/platform/member/apply/mine')
}
}).finally(() => {
loading.close()
})
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/apply/submit/submit', {
data: JSON.stringify(this.formData)
}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush('/platform/member/apply/mine')
}
}).finally(() => {
loading.close()
})
})
}
})
},
onFinishTask() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/apply/submit/submitAgain', {
data: JSON.stringify(this.formData),
taskId: this.taskId,
}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush('/platform/member/apply/mine')
}
}).finally(() => {
loading.close()
})
})
},
async init() {
let user
const resp = await $.post('/platform/member/apply/submit/getSelfUserInfo')
if (resp.code === 0) {
if (!resp.data) {
user = this.$store.state.user
} else {
user = resp.data
}
} else {
user = this.$store.state.user
}
if (this.id) {
const res = await this.$axios.post("/platform/member/apply/submit/findApplyById", { id: this.id })
debugger
if (res.code === 0) {
this.formData = res.data
}
} else {
const {
id,
username,
loginname,
sex,
nation,
birthday,
political,
education,
academicDegree,
position,
unitId,
unitName,
unit,
unionId,
unionName,
union,
campus,
userState,
personType,
preparedBy,
idCard,
mobile,
email,
families,
personalData
} = user
this.$set(this.formData, "userId", id)
this.$set(this.formData, "username", username)
this.$set(this.formData, "loginname", loginname)
this.$set(this.formData, "birthday", birthday)
this.$set(this.formData, "sex", sex)
this.$set(this.formData, "idCard", idCard)
this.$set(this.formData, "nation", nation)
this.$set(this.formData, "political", political)
this.$set(this.formData, "position", position)
this.$set(this.formData, "education", education)
this.$set(this.formData, "academicDegree", academicDegree)
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "userState", userState)
this.$set(this.formData, "personType", personType)
this.$set(this.formData, "preparedBy", preparedBy)
this.$set(this.formData, "unitName", unit ? unit.name : unitName)
this.$set(this.formData, "unitId", unit ? unit.id : unitId)
this.$set(this.formData, "unionName", union ? union.name : unionName)
this.$set(this.formData, "unionId", union ? union.id : unionId)
this.$set(this.formData, "mobile", mobile)
this.$set(this.formData, "email", email)
this.$set(this.formData, "families", families ? families : [])
this.$set(this.formData, "personalData", personalData)
}
},
},
created() {
this.init()
this.$businessTool.listUnit().then((data) => {
this.units = data
})
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,198 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="申请列表">
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.audit">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='sign'">
<el-image v-if="row.sign" :src="row.sign" style="height: 60px"></el-image>
<el-tag type="warning" v-else>暂无</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">
查看
</el-button>
<el-button v-if="row.taskState === 10" @click="openApproval(row)" size="mini" type="primary">
审核
</el-button>
<el-button v-if="row.canRevoke" @click="openRevoke(row)" size="mini" type="danger">
撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<info ref="infoRef">
<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>
</info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
audit: false
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "sign", label: "签字" },
{ prop: "curTaskName", label: "当前节点" },
{ prop: "instanceState", label: "流程状态" }
],
// 审核相关
showApprovalForm: false,
formData: {
tf_opinion: ""
},
}
},
components: {
"info": INFO,
"common-query": COMMON_QUERY,
},
methods: {
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
openApproval(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.infoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
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()
}
}).finally(() => {
loading.close()
})
})
},
openRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,144 @@
<div id="member_apply_view">
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ $moment(viewData.birthday).format("YYYY年MM月DD日") }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</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="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center" header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"></div>
<el-tag type="warning" v-else>暂无</el-tag>
</el-descriptions-item>
<el-descriptions-item label="签字信息" :span="3">
<el-image v-if="viewData.sign" :src="viewData.sign"
class="signature-image"></el-image>
<el-tag type="warning" v-else>暂无</el-tag>
</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="task-panel mt10">
<div class="task-panel-header">{{ 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>
<template v-if="task.taskFormData.tf_allocation_unionId">
<el-descriptions-item label="分配工会" :span="1.5">
{{ task.taskFormData.tf_allocation_unionName }}
</el-descriptions-item>
<el-descriptions-item label="分配前工会" :span="1.5">
{{ task.taskFormData.tf_self_unionName }}
</el-descriptions-item>
</template>
<el-descriptions-item label="办理意见" :span="3" v-if="!task.ext.isFirstTaskNode">{{ task.taskFormData.opinion }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_apply_view",
store,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
businessId: GetQueryString("businessId"),
instanceId: GetQueryString("instanceId"),
viewData: {},
doneTasks: []
}
},
methods: {
info() {
this.$axios.post("/platform/member/apply/mine/findMemberApplyRecord", { id: this.businessId }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", { instanceId: this.instanceId }).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
}
},
created() {
this.info()
this.getDoneTasks()
}
})
</script>
<style>
.task-panel {
background: white;
border-radius: 4px;
overflow: hidden;
}
.task-panel-header {
background: rgb(250, 250, 250);
border: 1px solid rgb(228, 231, 237);
border-bottom: none;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.el-descriptions-item__label.is-bordered-label {
width: 15%;
}
</style>
@@ -0,0 +1,118 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<member-audit-table ref="tableRef" @open-change-view="openChangeInfo" @open-edit="openEdit"
@open-approval="openApproval" @open-view="openView"></member-audit-table>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #public>
<member-audit-change-info ref="memberAuditChangeInfoViewRef"></member-audit-change-info>
<div v-if="showApprovalForm">
<el-form :model="formData" ref="approvalFormRef" label-position="left" label-width="80px">
<el-form-item label="审核意见" prop="approvalOpinion" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.approvalOpinion"></user-opinion-textarea>
</el-form-item>
<el-form-item label="电子签名" prop="approvalSignature" :rules="[{required:false,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.approvalSignature"></pc-signature>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button plain @click="$refs.guava.index()">取消</el-button>
<el-button type="danger" @click="doApproval('BACK')">退回重新填写</el-button>
<el-button type="danger" @click="doApproval('REJECT')">拒绝</el-button>
<el-button type="primary" @click="doApproval('PASS')">同意</el-button>
</el-row>
</div>
</template>
<template #edit>
<member-change :id="id" :url="url" :edit="true" ref="memberChangeRef" @submit-ready="changeSuccess"></member-change>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/audit/memberAuditTable.js"){}#-->
<!--#include("../../common/audit/memberAuditChangeInfo.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../../common/change/memberChange.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data: {
showApprovalForm: false,
id: '',
url: '',
},
components: {
"member-audit-table": MEMBER_AUDIT_TABLE,
"member-audit-change-info": MEMBER_AUDIT_CHANGE_INFO,
"member-info": MEMBER_INFO,
"member-change": MEMBER_CHANGE,
},
methods: {
doApproval(approvalType) {
this.formData.bpmTaskApprovalType = approvalType
this.$refs.approvalFormRef.validate((valid) => {
if (valid) {
this.$axios
.post(loc() + "/approval", {
approval: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
}
})
},
openApproval(data) {
this.$refs.guava.public(() => {
this.showApprovalForm = true
this.formData = row.approvalParam
this.$refs.memberAuditChangeInfoViewRef.onOpen({recordId: data.id, userId: data.userId})
})
},
openChangeInfo(data){
this.$refs.guava.public(() => {
this.showApprovalForm = false
this.$refs.memberAuditChangeInfoViewRef.onOpen({recordId: data.id, userId: data.userId})
})
},
openView(userId){
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(userId)
})
},
doSearch() {
this.$refs.tableRef.doSearch()
},
changeSuccess() {
this.$refs.guava.index(() => {
this.doSearch()
})
},
openEdit(row) {
this.id = row.id
this.url = '/platform/member/branchUnion/manage/list/generalMemberChange'
this.$refs.guava.edit(() => {
this.$refs.memberChangeRef.init()
})
}
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,98 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<member-manage-query ref="queryRef" @query-ready="onQueryReady"></member-manage-query>
<member-manage-table ref="tableRef" v-if="isQueryReady" @refresh="tableReady" @change-member="changeMember"
@view-member="viewMember" @add-member="addMember" @refresh-table="changeSuccess"></member-manage-table>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #edit>
<member-apply :admin-operate="true"></member-apply>
</template>
<template #public>
<member-change :id="id" :url="url" ref="memberChangeRef" @submit-ready="changeSuccess"></member-change>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/manage/memberManageQuery.js"){}#-->
<!--#include("../../common/manage/memberManageTable.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../../common/apply/memberApply.js"){}#-->
<!--#include("../../common/change/memberChange.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data: {
id: '',
username: '',
url:'',
isQueryReady: false,
hasShownMessage: false
},
components: {
"member-manage-query": MEMBER_MANAGE_QUERY,
"member-manage-table": MEMBER_MANAGE_TABLE,
"member-info": MEMBER_INFO,
"member-apply": MEMBER_APPLY,
"member-change": MEMBER_CHANGE,
},
methods: {
changeMember(data){
this.id = data.id
this.username = data.username
this.url = '/platform/member/branchUnion/manage/list/generalMemberChange'
this.$refs.guava.public(() => {
this.$refs.memberChangeRef.init()
})
},
viewMember(val){
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(val)
})
},
addMember(){
this.$refs.guava.edit()
},
onQueryReady(pageForm) {
this.isQueryReady = true;
this.$nextTick(() => {
if (this.$refs.tableRef) {
this.$refs.tableRef.pageData();
this.$refs.tableRef.pageForm = pageForm
}
})
},
tableReady(pageForm){
this.$refs.queryRef.pageForm = pageForm
},
changeSuccess(){
this.$refs.guava.index()
this.$nextTick(()=>{
this.$refs.tableRef.pageData()
})
if (this.hasShownMessage) return
setTimeout(() => {
this.$message.success('您已成功提交【'+ this.username +'】老师的变更,可前往分工会审核菜单查看审核记录');
}, 1000);
this.hasShownMessage = true;
}
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,51 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<member-record @open-view="openView" @open-change-info="openChangeInfo"></member-record>
</template>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #public>
<member-audit-change-info ref="memberAuditChangeInfoRef"></member-audit-change-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/record/memberRecord.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../../common/audit/memberAuditChangeInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
store,
components: {
"member-record": MEMBER_RECORD,
"member-info": MEMBER_INFO,
"member-audit-change-info": MEMBER_AUDIT_CHANGE_INFO
},
data: {
userId: ''
},
methods: {
openChangeInfo(row) {
this.$refs.guava.public(() => {
this.$refs.memberAuditChangeInfoRef.onOpen({recordId: row.id, userId: row.userId})
})
},
openView(data) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(data)
})
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,551 @@
<!--#
layout("/layouts/platform.html"){
#-->
<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"></el-input>
</search-item>
<search-item label="名单事项">
<el-select
clearable
filterable
placeholder="请选择"
style="width: 100%"
@change="changeProject"
v-model="pageForm.verificationProjectId"
>
<el-option :key="item.id" :label="item.projectName" :value="item.id" v-for="item in verificationList"></el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select
@change="flushUnits"
@clear="flushUnits"
clearable
filterable
placeholder="请选择所属工会"
style="width: 100%"
v-model="pageForm.unionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%" v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch" code="USER_STATE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch" code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch" code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool
:label="'人员核对列表' + '【' + ( buttonData.disableSubmit ? buttonData.buttonContent : buttonData.submitCountContent ) + '】'"
>
<el-button type="primary" size="small" @click="exportExcel">导出名单事项核对记录</el-button>
<el-button v-if="buttonData.isFeedback" type="primary" size="small" @click="viewFeedback()">查看反馈结果</el-button>
<el-button v-if="buttonData.disableSubmit" style="margin-left: 10px" type="primary" size="small" @click="incorrectSubmission">
有误提交
</el-button>
<el-button v-if="buttonData.disableSubmit" style="margin-left: 10px" type="primary" size="small" @click="openCorrectSubmission">
无误提交
</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" class="vi-table" ref="table" row-key="id" style="width: 100%">
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
align="center"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='isChanged'">
<el-link v-if="row.isChanged" @click="openChangeInfo(row)" :underline="false" type="primary">变更</el-link>
<el-link v-else :underline="false" type="danger" disabled>未变更</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='branchUnionChecked'">
<el-tag size="mini" v-if="row.branchUnionChecked" type="success">已核对</el-tag>
<el-tag size="mini" v-else type="danger">未核对</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='currentState'">
<el-tooltip
class="item"
effect="dark"
:content="'校工会审核意见:' + (row.verificationOption ? row.verificationOption : '暂无' )"
placement="top"
>
<el-link v-if="row.currentState == 1" :underline="false" type="danger">拒绝</el-link>
<!-- <el-link v-else-if="!row.branchUnionChecked" :underline="false" type="info" disabled>待分工会提交</el-link>-->
<el-link v-else-if="(row.currentState == 0 || !row.currentState)" :underline="false" type="info" disabled>
待审核
</el-link>
<el-link v-else :underline="false" type="primary" disabled>通过</el-link>
</el-tooltip>
</template>
</el-table-column>
<el-table-column v-if="buttonData.disableSubmit" label="操作" fixed="right" width="300px">
<template scope="{row}">
<el-button v-if="row.isChanged" size="mini" type="primary" @click="openChangeInfo(row)">查看变更</el-button>
<el-button v-if="row.currentState !== 2" size="mini" type="primary" @click="openChange(row)">
{{ row.isChanged ? '重新变更' : '变更' }}
</el-button>
<el-button v-if="row.isChanged && row.currentState != 2" size="mini" type="danger" @click="revokeChange(row)">
撤销变更
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #edit>
<member-change :id="userId" :url="url" ref="memberChangeRef" @submit-ready="changeSuccess"></member-change>
</template>
<template #public>
<member-verification-change ref="memberVerificationChangeRef"></member-verification-change>
</template>
</guava>
<el-dialog title="无误提交" :visible.sync="correctSubmissionDialog" width="50%" append-to-body>
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules" size="small">
<el-form-item prop="feedbackContent" label="当前需核对人数">
<el-input :value="totalCount" size="small" readonly></el-input>
</el-form-item>
<el-form-item prop="feedbackNum" label="反馈人数">
<el-input-number v-model="formData.feedbackNum" style="width: 100%" placeholder="请填写反馈人数" size="small"></el-input-number>
</el-form-item>
<template v-if="verificationData.welfareJson && verificationData.welfareJson.length > 0">
<el-form-item prop="welfareJson" label="福利选择人数">
<el-table :data="formData.welfareJson" border size="small">
<el-table-column label="福利名称" prop="welfareName">
<template slot-scope="{row}">
<el-input v-model="row.welfareName" readonly maxlength="50" placeholder="请输入福利名称"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" readonly maxlength="100" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column label="选择人数" prop="chooseNumber">
<template slot-scope="{row}">
<el-input-number
style="width: 100%"
v-model="row.chooseNumber"
:min="0"
placeholder="请输入选择此福利的人数"
></el-input-number>
</template>
</el-table-column>
</el-table>
</el-form-item>
</template>
<template v-if="verificationData.isNeedFeedbackFile">
<el-form-item required label="附件上传" prop="feedbackFiles">
<file-upload
:value.sync="formData.feedbackFiles"
:upload_number="2"
upload_result_category="array"
complete_result
upload_mode="drag"
accept=".doc,.docx,.xls,.xlsx,.pdf"
></file-upload>
</el-form-item>
</template>
</el-form>
<el-row class="mt20" justify="end" type="flex">
<el-button @click="correctSubmissionDialog = false">取消</el-button>
<el-button type="primary" @click="correctSubmission">提交</el-button>
</el-row>
</el-dialog>
<el-dialog title="反馈结果" :visible.sync="feedbackDialog" width="50%" append-to-body>
<el-descriptions :column="2" border>
<el-descriptions-item label="事项名称">{{ viewData.projectName }}</el-descriptions-item>
<el-descriptions-item label="工会名称">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="反馈日期">{{ viewData.feedbackDate }}</el-descriptions-item>
<el-descriptions-item label="反馈人数">{{ viewData.feedbackNum }}</el-descriptions-item>
<template v-if="viewData.welfareJson">
<el-descriptions-item span="2" label="福利选择人数">
<el-table :data="viewData.welfareJson" border size="small">
<el-table-column label="福利名称" prop="welfareName"></el-table-column>
<el-table-column label="备注" prop="remark"></el-table-column>
<el-table-column label="选择人数" prop="chooseNumber"></el-table-column>
</el-table>
</el-descriptions-item>
</template>
<el-descriptions-item span="2" label="核对时间">{{ viewData.startDate + '至' + viewData.endDate }}</el-descriptions-item>
<el-descriptions-item span="2" label="内容及要求" span="2">{{ viewData.content }}</el-descriptions-item>
<el-descriptions-item span="2" label="反馈附件">
<file-preview :files="viewData.feedbackFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../../common/info/memberInfo.js"){}#-->
<!--#include("../../../common/change/memberChange.js"){}#-->
<!--#include("../../../common/verification/memberVerificationChange.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"member-info": MEMBER_INFO,
"member-change": MEMBER_CHANGE,
"member-verification-change": MEMBER_VERIFICATION_CHANGE
},
data() {
return {
userId: "",
verificationChangeInfoUserId: "",
url: "/platform/member/branchUnion/verification/check/doCheckMember",
verificationList: [],
verificationData: {},
unions: [],
units: [],
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true, width: "100px" },
{ prop: "userState", label: "在职状态", sortable: true },
// {prop: "preparedBy", label: "编制类别", sortable: true},
// {prop: 'personType', label: '教职工类别', sortable: true},
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "isChanged", label: "变更状态", sortable: true },
{ prop: "branchUnionChecked", label: "核对状态", sortable: true },
{ prop: "currentState", label: "校工会状态", sortable: true }
],
formRules: {
feedbackNum: [
{ required: true, message: "请填写反馈人数", trigger: ["blur", "change"] },
{ type: "number", message: "反馈人数必须为数字" }
],
feedbackFiles: [{ required: true, message: "请上传反馈附件", trigger: ["blur", "change"] }],
welfareJson: [{ required: true, message: "请填写福利选择人数", trigger: ["blur", "change"] }]
},
pageForm: {
verificationProjectId: "",
unionId: "",
unitId: "",
userState: "",
personType: ""
},
buttonData: {
disableSubmit: false,
buttonContent: "",
submitCountContent: "",
isFeedback: false
},
correctSubmissionDialog: false,
feedbackDialog: false,
viewData: {},
totalCount: 0
}
},
methods: {
exportExcel() {
this.$downLoad("/platform/member/branchUnion/verification/check/exportExcel", this.pageForm)
},
viewFeedback() {
this.$axios
.post("/platform/member/branchUnion/verification/check/getVerificationFeedback", {
verificationProjectId: this.pageForm.verificationProjectId,
unionId: this.$store.state.user.union.id
})
.then((res) => {
if (res.code === 0) {
this.viewData = res.data
this.feedbackDialog = true
} else {
this.$message.error(res.msg)
}
})
},
/**
* 有误提交
*/
incorrectSubmission() {
//确定要提交吗,请确保数据已核对完毕
this.$confirm("确定要提交吗?,请确保数据已核对完毕", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios
.post("/platform/member/branchUnion/verification/check/incorrectSubmission", {
verificationProjectId: this.pageForm.verificationProjectId
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.buttonData.disableSubmit = false
this.pageData()
this.validateSubmitButton()
} else {
this.$message.warning(res.msg)
}
})
})
.catch(() => {})
},
openCorrectSubmission() {
this.$confirm("您确认要无误提交吗?提交后所有数据将无法撤销,点击确认后将填写反馈人数,是否确认?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.verificationData = this.verificationList.find((v) => v.id === this.pageForm.verificationProjectId)
if (this.verificationData.welfareJson && this.verificationData.welfareJson.length > 0) {
this.formData.welfareJson = this.verificationData.welfareJson
} else {
this.formData.welfareJson = []
}
console.log(this.verificationData)
this.correctSubmissionDialog = true
})
},
/**
* 无误提交
*/
correctSubmission() {
if (this.formData.feedbackNum !== this.totalCount) {
this.$message.warning("反馈人数与实际反馈人数不一致,无法提交;如有疑问,请联系校工会")
return
}
let data = clone(this.formData)
if (this.formData.welfareJson && this.formData.welfareJson.length > 0) {
data.welfareJson = this.formData.welfareJson.map((v) => ({
...v,
chooseNumber: v.chooseNumber || 0
}))
const totalChooseNumber = data.welfareJson.reduce((sum, item) => sum + item.chooseNumber, 0)
if (totalChooseNumber !== this.totalCount) {
this.$message.warning("上报的福利选择人数与当前需核对人数不一致,无法提交;如有疑问,请联系校工会")
return
}
data.welfareJson = JSON.stringify(data.welfareJson)
}
if (data.feedbackFiles) {
data.feedbackFiles = JSON.stringify(data.feedbackFiles)
}
data.verificationProjectId = this.pageForm.verificationProjectId
this.$axios
.post("/platform/member/branchUnion/verification/check/correctSubmission", {
data: JSON.stringify(data)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.correctSubmissionDialog = false
this.pageData()
this.validateSubmitButton()
this.formData = {}
} else {
this.$message.warning(res.msg)
}
})
},
/**
* 变更数据查看
* @param row
*/
openChangeInfo(row) {
this.$refs.guava.public(() => {
this.$refs.memberVerificationChangeRef.onOpen({ id: row.userId, projectId: this.pageForm.verificationProjectId })
})
},
/**
* 撤销变更
*/
revokeChange(row) {
this.$confirm("确定要撤销变更吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
const formData = new FormData()
formData.userId = row.userId
formData.verificationProjectId = this.pageForm.verificationProjectId
this.$axios
.post("/platform/member/branchUnion/verification/check/branchUnionRevokeChange", {
data: JSON.stringify(formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
} else {
this.$message.warning(res.msg)
}
})
})
.catch(() => {})
},
// 基本信息查看
openView(row) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(row.userId)
})
},
openChange(row) {
if (row.currentState == 2) {
// 该条记录校工会核对时已通过,您确定要继续变更吗?
this.$confirm("该条记录校工会核对时已通过,您确定要继续变更吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.openChangeNext(row)
})
.catch((e) => {
console.log("取消" + e)
})
} else {
this.openChangeNext(row)
}
},
openChangeNext(row) {
this.userId = row.userId
const data = this.verificationList.find((v) => v.id === row.verificationProjectId)
this.$refs.guava.edit(() => {
this.$refs.memberChangeRef.verificationInit({
renewFields: data.renewFields,
verificationProjectId: row.verificationProjectId,
changeOrigin: "BRANCH_UNION_VERIFICATION"
})
})
// this.$nextTick(() => {
// this.$refs.memberChangeRef.verificationInit({
// renewFields: data.renewFields,
// verificationProjectId: row.verificationProjectId,
// changeOrigin: "BRANCH_UNION_VERIFICATION"
// })
// })
},
getVerificationList() {
this.$axios.post("/platform/member/branchUnion/verification/check/getVerificationList").then((res) => {
if (res.code === 0) {
this.verificationList = res.data
if (this.verificationList.length > 0) {
this.$set(this.pageForm, "verificationProjectId", this.verificationList[0].id)
this.verificationData = this.verificationList[0]
this.validateSubmitButton()
}
this.pageData()
}
})
},
changeSuccess() {
this.$refs.guava.index()
this.doSearch()
},
initData() {
const isAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])
if (isAdmin) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unions = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
}
},
changeProject() {
this.doSearch()
this.validateSubmitButton()
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
//校验提交按钮是否能使用
validateSubmitButton() {
this.$axios
.post("/platform/member/branchUnion/verification/check/validateSubmitButton", {
verificationProjectId: this.pageForm.verificationProjectId
})
.then((res) => {
if (res.code === 0) {
const data = res.data
this.buttonData.disableSubmit = data.buttonStatus
this.buttonData.buttonContent = data.buttonContent
this.buttonData.submitCountContent = data.submitCountContent
this.buttonData.isFeedback = data.isFeedback
} else {
this.buttonData.disableSubmit = false
}
})
},
pageData() {
this.$axios.post("/platform/member/branchUnion/verification/check/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
// if (!this.totalCount) {
// this.totalCount = res.data.totalCount
// }
this.totalCount = res.data.totalCount
}
})
}
},
async created() {
this.getVerificationList()
this.initData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,44 @@
<div id="member_change_branch_union_approval">
<el-form :model="formData" ref="formRef" 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>
<snaker-flow-task-form-action @task-action="handleTaskAction" @cancel="handleCancel"></snaker-flow-task-form-action>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_change_branch_union_approval",
store,
data() {
return {
formData: {
tf_opinion: ""
},
}
},
methods: {
handleTaskAction(val) {
const data = {
...val,
...this.formData
}
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify(data)
}).then(res => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage({
type: "task-complete"
}, "*")
}
})
},
handleCancel(val) {
console.log(val)
},
}
})
</script>
@@ -0,0 +1,206 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="审核列表">
<el-radio-group @change="search" class="mr5" size="small" v-model="pageForm.audit">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='changeTypes'">
<span style="color: #0e78c5;cursor: pointer" @click="openView(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="200px">
<template slot-scope="{row}">
<el-button @click="openView(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>
<info ref="infoRef">
<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>
</info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
audit: false
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: 'preparedBy', label: '编制类别', sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "changeTypes", label: "变更类型", sortable: true, width: 200 },
{ prop: "applyDateTime", label: "申请时间", sortable: true },
{ prop: "curTaskName", label: "当前节点"},
{ prop: "instanceState", label: "流程状态"}
],
changeTypeData: [],
// 审核相关
formData: {},
showApprovalForm: false
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
openView(row){
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.infoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
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()
}
}).finally(() => {
loading.close()
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
getChangeTypes(changeTypes) {
const changeTypesList = JSON.parse(changeTypes)
if (!changeTypesList) return null
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
},
async created() {
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,89 @@
const COMMON_QUERY = {
template: /*language=HTML*/ `
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userStates" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personTypes" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBys" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE" multiple collapse-tags></dict-select>
</search-item>
</search>
`,
store,
mixins: [initTableMixins],
data() {
return{
unions: [],
units: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
userStates: [],
personTypes: [],
preparedBys: [],
}
}
},
methods: {
doSearch(){
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
this.$emit('search', pageForm)
},
async initData(){
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN")) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unions = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
})
}
},
async flushUnits(){
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
}
},
async created() {
this.initData()
}
}
@@ -0,0 +1,180 @@
const INFO = {
template: /*language=HTML*/ `
<div>
<div class="process-title">申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-tabs v-model="activeName">
<el-tab-pane label="基础信息" name="basicInfo">
<el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ viewData.birthday ?
$moment(viewData.birthday).format("YYYY年MM月DD日") : '暂无' }}
</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</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="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="编制类别">{{ viewData.preparedBy }}</el-descriptions-item>
<template v-if="viewData.userState == '退休'">
<el-descriptions-item label="退休日期">{{ viewData.retireDate ?
$moment(viewData.retireDate).format("YYYY-MM-DD") : '暂无' }}
</el-descriptions-item>
<el-descriptions-item label="福利享受截止日期">{{
$moment(viewData.welfareStopDate).format("YYYY-MM-DD") }}
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<el-descriptions-item label="会员状态">{{ viewData.member ? '会员' : '非会员' }}
</el-descriptions-item>
<el-descriptions-item label="福利会员状态">{{ viewData.welfareMember ? '福利会员' : '非福利会员'
}}
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<!-- <template v-if="viewData.loginname == $store.state.user.loginname">-->
<template>
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center"
header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<template slot="label">个人简况</template>
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"></div>
<span v-else>无数据</span>
</el-descriptions-item>
</template>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="变更信息" name="changeInfo" v-if="viewData.changeInfos">
<el-table :data="viewData.changeInfos" :size="tableSize" @sort-change="pageOrder" ref="table"
row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column prop="fieldName" label="变更字段" header-align="center"></el-table-column>
<el-table-column prop="sourceValue" label="原数据" header-align="center">
<template slot-scope="{row}">
<div v-html="row.sourceValue"></div>
</template>
</el-table-column>
<el-table-column prop="newValue" label="新数据" header-align="center">
<template slot-scope="{row}">
<div v-html="row.newValue"></div>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<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,
mixins: [initTableMixins],
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data(){
return {
viewData: {},
doneTasks: [],
row: null,
activeName: "basicInfo",
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
console.log(row.id)
this.info()
this.getDoneTasks()
},
// 获取申请信息
info() {
this.$axios.post("/platform/member/change/mine/findMemberChangeRecord", { 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,111 @@
const MEMBER_ALL_CHANGE_INFO = {
template: /*language=HTML*/ `
<el-tabs v-model="activeName">
<el-tab-pane label="基础信息" name="basicInfo">
<el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ $moment(viewData.birthday).format("YYYY年MM月DD日") }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</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="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="编制类别">{{ viewData.preparedBy }}</el-descriptions-item>
<template v-if="viewData.userState == '退休'">
<el-descriptions-item label="退休日期">{{ viewData.retireDate ? $moment(viewData.retireDate).format("YYYY-MM-DD") : '暂无' }}</el-descriptions-item>
<el-descriptions-item label="福利享受截止日期">{{ $moment(viewData.welfareStopDate).format("YYYY-MM-DD") }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<el-descriptions-item label="会员状态">{{ viewData.member ? '会员' : '非会员' }}</el-descriptions-item>
<el-descriptions-item label="福利会员状态">{{ viewData.welfareMember ? '福利会员' : '非福利会员' }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<template v-if="viewData.loginname == $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center" header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<template slot="label">个人简况</template>
<div v-if="viewData.vita" class="text-left" v-html="viewData.vita"></div>
<span v-else>无数据</span>
</el-descriptions-item>
</template>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="历史变更记录" name="changeInfo" v-if="viewData.allChangeInfo">
<el-timeline>
<el-timeline-item placement="top" v-for="(changeData, index) in viewData.allChangeInfo"
:key="index" :timestamp="changeData.timestamp">
<el-card>
<h4>{{ changeData.changeOriginName }}</h4>
<el-table :data="changeData.changeInfos" size="mini" ref="table" row-key="id" style="width: 100%">
<el-table-column align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column prop="fieldName" label="变更字段" header-align="center"></el-table-column>
<el-table-column prop="sourceValue" label="原数据" header-align="center">
<template slot-scope="{row}">
<div v-html="row.sourceValue"></div>
</template>
</el-table-column>
<el-table-column prop="newValue" label="新数据" header-align="center">
<template slot-scope="{row}">
<div v-html="row.newValue"></div>
</template>
</el-table-column>
</el-table>
</el-card>
</el-timeline-item>
</el-timeline>
</el-tab-pane>
</el-tabs>
`,
store,
data(){
return{
viewData: {},
activeName: "basicInfo"
}
},
methods:{
onOpen(userId){
this.$axios.post('/platform/member/change/manage/getAllChangeMemberInfo', {userId})
.then(resp => {
if (resp.code === 0) {
this.viewData = resp.data
} else {
this.$message.warning(resp.msg)
}
})
}
}
}
@@ -0,0 +1,486 @@
const MEMBER_CHANGE = {
template: /*language=HTML*/ `
<el-card shadow="never">
<snaker-start slot="header" label="会员变更" define_key="HYBG"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">
<el-form-item prop="loginname">
<el-input v-model="formData.loginname" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="姓名">
<el-form-item prop="username">
<el-input v-model="formData.username" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="sex">
<el-radio-group :disabled="allowFields('sex')" v-model="formData.sex" size="small">
<el-radio border label="男">男</el-radio>
<el-radio border label="女">女</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="民族">
<el-form-item prop="nation">
<dict-select style="width: 100%" placeholder="请选择民族" v-model="formData.nation"
:disabled="allowFields('nation')" code="USER_NATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="出生日期">
<el-form-item prop="birthday">
<el-date-picker v-model="formData.birthday"
type="date"
:disabled="allowFields('birthday')"
placeholder="请选择出生日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="政治面貌">
<el-form-item prop="political">
<dict-select style="width: 100%" placeholder="请选择政治面貌" v-model="formData.political"
:disabled="allowFields('political')" code="USER_POLITICAL"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学历">
<el-form-item prop="education">
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
:disabled="allowFields('education')" code="USER_EDUCATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学位">
<el-form-item prop="academicDegree">
<dict-select style="width: 100%" placeholder="请选择学位" v-model="formData.academicDegree"
:disabled="allowFields('academicDegree')"
code="USER_ACADEMIC_DEGREE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="党政职务">
<el-form-item prop="position">
<el-input v-model="formData.position" placeholder="请输入党政职务"
:disabled="allowFields('position')" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<!--<template v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN')">
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionId">
<el-select clearable filterable placeholder="请选择所属工会" style="width: 100%"
v-model="formData.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
</template>-->
<template>
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
:disabled="allowFields('unitId')" @change="getUnionName"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionName">
<el-input v-model="formData.unionName" disabled placeholder="请输入所属工会"></el-input>
</el-form-item>
</el-descriptions-item>
</template>
<el-descriptions-item label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
:disabled="allowFields('campus')" code="USER_CAMPUS"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="身份证号码">
<el-form-item prop="idCard">
<el-input v-model="formData.idCard" :disabled="allowFields('idCard')"
placeholder="请输入身份证号码" maxlength="18"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" :disabled="allowFields('mobile')"
placeholder="请输入联系电话" maxlength="15"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="电子邮箱">
<el-form-item prop="email">
<el-input v-model="formData.email" :disabled="allowFields('email')"
placeholder="请输入电子邮箱" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="formData.userState" code="USER_STATE"
:disabled="allowFields('userState')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="教职工类别">
<el-form-item prop="personType">
<dict-select v-model="formData.personType" code="USER_PERSON_TYPE"
:disabled="allowFields('personType')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="编制类别">
<el-form-item prop="preparedBy">
<dict-select v-model="formData.preparedBy" code="USER_PREPARED_BY_TYPE"
:disabled="allowFields('preparedBy')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<template v-if="formData.userState == '退休'">
<el-descriptions-item label="退休日期">
<el-form-item prop="retireDate">
<el-date-picker v-model="formData.retireDate"
type="date"
placeholder="请选择退休日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利享受截止日期">
<el-form-item prop="welfareStopDate">
<el-date-picker v-model="formData.welfareStopDate"
type="date"
:disabled="isView"
placeholder="请选择福利享受截止日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<el-descriptions-item label="会员状态" :span="1.5">
<el-form-item prop="member">
<el-radio-group v-model="formData.member" size="small">
<el-radio border :label="true">会员</el-radio>
<el-radio border :label="false">非会员</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利会员状态" :span="1.5">
<el-form-item prop="welfareMember">
<el-radio-group v-model="formData.welfareMember" size="small">
<el-radio border :label="true">福利会员</el-radio>
<el-radio border :label="false">非福利会员</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<template v-if="formData.loginname == $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-form-item prop="families">
<el-table :data="formData.families" border size="small">
<el-table-column label="关系" prop="relation">
<template slot-scope="{row}">
<el-input v-model="row.relation" maxlength="50"
placeholder="请输入与本人关系"></el-input>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name">
<template slot-scope="{row}">
<el-input v-model="row.name" maxlength="50"
placeholder="请输入姓名"></el-input>
</template>
</el-table-column>
<el-table-column label="工作单位" prop="unit">
<template slot-scope="{row}">
<el-input v-model="row.unit" maxlength="100"
placeholder="请输入工作单位"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" maxlength="100"
placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column width="100px">
<template slot="header" slot-scope="scope">
<el-button type="primary" size="mini" :disabled="allowFields('families')"
@click="formData.families.push({})">添加
</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="formData.families.length===0 || allowFields('families')"
@click="formData.families.splice(scope.$index,1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="个人简历" :span="3">
<el-form-item prop="personalData">
<text-editor v-model="formData.personalData"></text-editor>
</el-form-item>
</el-descriptions-item>
</template>
</el-descriptions>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" plain @click="$emit('do-back')">返回</el-button>
<el-button type="primary" @click="onSubmit">提交变更</el-button>
</el-row>
<!-- <el-row justify="end" type="flex" class="mt10">-->
<!-- <el-button @click="$emit('do-back')" v-if="formData.id || !isShow" type="primary">返 回</el-button>-->
<!-- <template v-if="isShow">-->
<!-- <el-button @click="doSave" type="primary">保存变更</el-button>-->
<!-- </template>-->
<!-- <el-button @click="doSubmit" type="primary">提交变更</el-button>-->
<!-- </el-row>-->
</el-card>
`,
props: {
id: { type: String, default: '' },
},
mixins: [initTableMixins],
store,
data(){
return{
isShow: true,
user: {},
units: [],
unions: [],
// 允许变更的字段
allowChangeFields: [],
formData: {
families: [],
},
formRules: {
username: [{required: false, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: false, message: "必填", trigger: ["change", "blur"]}],
/*email: [
{
validator: (rule, value, callback) => {
if (!value) {
callback();
} else if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
callback();
} else {
callback(new Error("邮箱格式错误"));
}
},
trigger: ["change", "blur"]
}
],
idCard: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}(\d|[Xx])$/.test(value)) {
// 18位身份证号码格式正确
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 15位身份证号码格式正确
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(18位)
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(15位)
callback();
} else {
// 格式错误,返回错误信息
callback(new Error("身份证号码格式错误"));
}
},
trigger: ["change", "blur"]
}
],
mobile: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1][345789][0-9]{9}$/.test(value)) {
// 手机号格式正确
callback();
} else if (/^\d+-\d+$/.test(value) && value.length <= 16) {
// 座机号格式正确
callback();
} else {
// 格式错误,返回错误信息
callback(new Error(value.includes('-') ? '座机号码格式错误' : '手机号码格式错误'));
}
},
trigger: ["change", "blur"]
}
]*/
},
welfareProjectList: []
}
},
methods: {
getUnionName(val){
debugger
const data = this.units.find(v => v.id === val)
this.$set(this.formData, 'unionName', data ? data.unionName : '')
},
allowFields(prop) {
return !this.allowChangeFields.map(v => v.code).includes(prop)
},
doSave(){
this.$confirm("保存后可在我的申请里面再次编辑,您确定要保存吗?", "提示", { type: "warning" })
.then(() => {
const formData = this.formData
if (formData.families) {
formData.families = JSON.stringify(this.formData.families)
}
this.$emit('do-save', formData)
})
.catch()
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("提交后将进入审核流程,无法再进行编辑,您确定要提交申请吗?", "提示", { type: "warning" })
.then(() => {
const formData = this.formData
if (formData.families) {
formData.families = JSON.stringify(this.formData.families)
}
this.$emit('do-submit', formData)
})
.catch()
}
})
},
async init(userId){
if (userId) {
this.isShow = false
await this.getUserById(userId)
} else {
this.isShow = true
this.user = this.$store.state.user
}
this.getFormDataValue(this.id)
this.allowChangeFields = await this.$businessTool.getDictOptions("ALLOW_CHANGE_FIELDS")
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_MEMBER_ADMIN, SCHOOL_UNION_ADMIN')) {
this.units = await this.$businessTool.listUnit()
this.unions = await this.$businessTool.listUnion()
} else {
this.units = await this.$businessTool.listUnit(this.user.union.id)
}
},
async getUserById(userId){
const resp = await $.post("/platform/member/change/apply/getUserByIdForMemberChange", { userId })
if (resp.code === 0) {
this.user = resp.data
}
},
getFormDataValue(id){
if (id) {
$.post("/platform/member/change/apply/findChangeById", { id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.formData.unionid = this.user.unionid
if (this.formData.families) {
this.formData.families = JSON.parse(this.formData.families)
} else {
this.formData.families = []
}
}
})
} else {
const {
id,
username,
loginname,
sex,
member,
welfareMember,
nation,
birthday,
political,
education,
academicDegree,
position,
unit,
union,
campus,
userState,
personType,
preparedBy,
idCard,
mobile,
email,
families,
personalData
} = this.user
this.$set(this.formData, "userId", id)
this.$set(this.formData, "username", username)
this.$set(this.formData, "loginname", loginname)
this.$set(this.formData, "birthday", birthday)
this.$set(this.formData, "sex", sex)
this.$set(this.formData, "member", member === 1)
this.$set(this.formData, "welfareMember", welfareMember === 1)
this.$set(this.formData, "idCard", idCard)
this.$set(this.formData, "nation", nation)
this.$set(this.formData, "political", political)
this.$set(this.formData, "position", position)
this.$set(this.formData, "education", education)
this.$set(this.formData, "academicDegree", academicDegree)
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "userState", userState)
this.$set(this.formData, "personType", personType)
this.$set(this.formData, "preparedBy", preparedBy)
this.$set(this.formData, "unitName", unit ? unit.name : null)
this.$set(this.formData, "unitId", unit ? unit.id : null)
this.$set(this.formData, "unionName", union ? union.name : null)
this.$set(this.formData, "unionId", union ? union.id : null)
this.$set(this.formData, "mobile", mobile)
this.$set(this.formData, "email", email)
this.$set(this.formData, "families", families ? families : [])
this.$set(this.formData, "personalData", personalData)
}
}
},
created(){
this.init()
},
style: /*language=CSS*/ `
.el-descriptions-item__label {
width: 15% !important;
}
`
}
@@ -0,0 +1,402 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="性别">
<dict-select v-model="pageForm.sex" placeholder="性别" @change="doSearch"
code="USER_SEX"></dict-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="更新日期">
<el-date-picker :picker-options="pickerOptions" @change="changeDateRangeChange"
align="right" end-placeholder="结束日期" format="yyyy-MM-dd"
range-separator="-" start-placeholder="开始日期" style="width: 100%"
type="datetimerange" v-model="pageForm.changeDateRange"
value-format="yyyy-MM-dd"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="人员列表(工会小组或分工会提交的变更还需校工会审核哦)">
<el-radio-group @change="doSearch" class="mr5"
size="small"
v-model="pageForm.isMember">
<el-radio-button :label="null">全部教工</el-radio-button>
<el-radio-button :label="1">会员</el-radio-button>
<el-radio-button :label="0">非会员</el-radio-button>
</el-radio-group>
<span class="text-danger">人员异动:</span>
<el-radio-group @change="doSearch" class="mr5" size="small"
v-model="pageForm.changed">
<el-radio-button :label="2">全部</el-radio-button>
<el-radio-button :label="1">异动</el-radio-button>
<el-radio-button :label="0">未异动</el-radio-button>
</el-radio-group>
<!--<div v-if="pageForm.changed == '1'" class="div-enum">
<dict-select v-model="pageForm.USER_CHANGE_TYPE" placeholder="异动类型" @change="doSearch"
code="UserType"></dict-select>
</div>-->
<el-button type="primary" size="small" icon="el-icon-printer" @click="exportExcel">导出会员名单</el-button>
<el-popover
placement="bottom"
trigger="click"
width="200">
<div style="padding:4px 0;border-bottom:1px solid #eee;">
<el-button size="mini" @click="checkAll">全选</el-button>
<el-button size="mini" @click="invertCheck">反选</el-button>
</div>
<div style="max-height:40vh;overflow-y:auto;padding:6px 0;">
<el-checkbox-group v-model="checkedFields">
<el-checkbox
v-for="f in tableColumns"
:key="f.prop"
:label="f.prop"
style="display:block;margin:6px 0;">
{{ f.label }}
</el-checkbox>
</el-checkbox-group>
</div>
<el-button
slot="reference"
type="text"
icon="el-icon-s-operation"
size="small"
style="margin-left:12px;">
列设置
</el-button>
</el-popover>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
class="vi-table" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px" fixed="left"></el-table-column>
<el-table-column :label="column.label" :prop="column.prop"
:sortable="column.sortable" :width="column.width"
align="center" header-align="center" min-width="100px"
v-if="checkedFields.includes(column.prop)" :fixed="column.fixed"
show-overflow-tooltip v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row.id)" type="primary">{{row.loginname}}</el-link>
</template>
</el-table-column>
<el-table-column header-align="center" label="异动信息">
<el-table-column align="center" header-align="center" label="更新时间"
min-width="145px" prop="changeTime"
show-overflow-tooltip sortable>
</el-table-column>
<el-table-column align="center" header-align="center" label="异动类型"
prop="changeType" show-overflow-tooltip sortable>
<template scope="{row}">
<span style="color: #0e78c5;cursor: pointer" @click="openUserChangeInfo(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column align="center" header-align="center" label="会员" prop="member"
show-overflow-tooltip sortable>
<template scope="{row}">
<span class="text-success " v-if="row.member==1">
<i class="fa fa-circle ml5"></i>
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i>
</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="福利会员" prop="member"
show-overflow-tooltip sortable>
<template scope="{row}">
<span class="text-success " v-if="row.welfareMember==1">
<i class="fa fa-circle ml5"></i>
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i>
</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="100px" fixed="right">
<template scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'view',data:row}">
查看
</el-dropdown-item>
<el-dropdown-item
:command="{type:'change',data:row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN','BRANCH_UNION_CHAIRMAN','BRANCH_UNION_CHAIRMAN','BRANCH_UNION_GROUP_LEADER'])">
变更
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #public>
<member-change ref="memberChangeRef" @do-back="$refs.guava.index()" @do-submit="doSubmit"></member-change>
</template>
<template #edit>
<member-all-change ref="memberAllChangeRef"></member-all-change>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../common/memberChange.js"){}#-->
<!--#include("../common/memberAllChangeInfo.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data: {
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}]
},
pageForm: {
unionId: "",
unitId: "",
sex: "",
searchKeyword: "",
changed: 2,
isMember: 1,
changeTypes: [],
},
unions: [],
units: [],
id: "",
tableColumns: [
{ prop: "loginname", label: "工号", width: 120, fixed: "left"},
{ prop: "username", label: "姓名", width: 120, fixed: "left" },
{ prop: "sex", label: "性别", width: 120},
{ prop: "birthday", label: "出生年月", width: 120, sortable: true },
{ prop: "nationality", label: "国籍", width: 120, sortable: true, checked: 0 },
{ prop: "nation", label: "民族", width: 120, sortable: true},
{ prop: "mobile", label: "联系电话", width: 120 },
{ prop: "political", label: "政治面貌", width: 120, sortable: true},
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "编制类别", width: 120, sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true, checked: 0 },
{ prop: "unionName", label: "所属工会", width: 120, sortable: true },
{ prop: "unitName", label: "所属单位", width: 120, sortable: true },
{ prop: "idCardType", label: "证件类型", width: 120, sortable: true, checked: 0 },
{ prop: "idCard", label: "证件号码", width: 120, sortable: true, checked: 0 },
{ prop: "marriage", label: "婚姻状况", width: 120, sortable: true, checked: 0 },
{ prop: "jobCategory", label: "岗位类别", width: 120, sortable: true, checked: 0 },
{ prop: "professionalTitle", label: "职称", width: 120, sortable: true, checked: 0 },
{ prop: "professionalLevel", label: "职级", width: 120, sortable: true, checked: 0 },
{ prop: "employeeSource", label: "职工来源", width: 120, sortable: true, checked: 0 },
{ prop: "administrativeLevel", label: "行政级别(管理岗位)", width: 120, sortable: true, checked: 0 },
{ prop: "positionSeries", label: "岗位系列", width: 120, sortable: true, checked: 0 },
{ prop: "positionLevel", label: "岗级", width: 120, sortable: true, checked: 0 },
{ prop: "administrativePositionLevel", label: "行政岗级", width: 120, sortable: true, checked: 0 },
{ prop: "arrivalAtSchoolDate", label: "来校时间", width: 120, sortable: true, checked: 0 },
{ prop: "teachingTime", label: "从教年月", width: 120, sortable: true, checked: 0 },
{ prop: "expectedLeaveSchoolDate", label: "预计/最后离校时间", width: 120, sortable: true, checked: 0 },
],
changeTypeData: [],
checkedFields: []
},
components: {
"member-info": MEMBER_INFO,
"member-change": MEMBER_CHANGE,
"member-all-change": MEMBER_ALL_CHANGE_INFO,
},
methods: {
dropdownCommand(command) {
const {type, data} = command
if (type === 'view') {
this.openView(data.id)
} else if (type === 'change') {
this.openChange(data.id)
}
},
openChange(id) {
this.$refs.guava.public(() => {
this.$refs.memberChangeRef.init(id)
})
},
openView(id) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(id)
})
},
openUserChangeInfo(row) {
this.$refs.guava.edit(() => {
this.$refs.memberAllChangeRef.onOpen(row.id)
})
},
async doSubmit(data) {
const loading = createLoading('正在提交中')
const resp = await this.$axios.post("/platform/member/change/manage/doSubmitChange", data)
loading.close()
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$refs.guava.index()
this.pageData()
} else {
this.$message.error(resp.msg)
}
},
getChangeTypes(changeTypes){
if (!changeTypes) return null
const changeTypesList = JSON.parse(changeTypes)
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
changeDateRangeChange(val) {
if (val && val.length > 0) {
this.pageForm.changeDateBefore = val[0]
this.pageForm.changeDateEnd = val[1]
}
},
/**
* 导出会员名单
*/
exportExcel() {
const pageForm = clone(this.pageForm)
const data = this.tableColumns.filter(item => this.checkedFields.includes(item.prop)).map(item => {
return {prop: item.prop, label: item.label}
})
pageForm.columns = JSON.stringify(data)
this.$downLoad("/platform/member/change/manage/doExport", pageForm)
},
async initData() {
const isAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])
if (isAdmin) {
this.unions = await this.$businessTool.listUnion(this.pageForm.unionId)
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
}
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then(data => {
this.units = data
})
}
},
checkAll() {
this.checkedFields = this.tableColumns.map(c => c.prop);
},
invertCheck() {
const all = this.tableColumns.map(c => c.prop);
this.checkedFields = all.filter(p => !this.checkedFields.includes(p));
}
},
computed: {
showColumns() {
return this.tableColumns.filter(c => this.checkedFields.includes(c.prop));
}
},
mounted() {
this.checkedFields = this.tableColumns.filter(c => c.checked !== 0).map(c => c.prop);
},
created() {
this.initData()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,159 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool :app="this" label="申请列表">
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='changeTypes'">
<span style="color: #0e78c5;cursor: pointer" @click="openView(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="openView(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>
<info ref="infoRef"></info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
data(){
return{
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "changeTypes", label: "变更类型", sortable: true, width: 200 },
{ prop: "applyDateTime", label: "申请时间", sortable: true },
{ prop: "curTaskName", label: "当前节点"},
{ prop: "instanceState", label: "流程状态"}
],
changeTypeData: [],
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
onEdit(row) {
commonUtil.pjaxPush('/platform/member/change/apply?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
}).finally(() => {
loading.close()
})
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post("/platform/member/change/mine/onDelete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
getChangeTypes(changeTypes){
const changeTypesList = JSON.parse(changeTypes)
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
}
},
async created(){
this.pageData()
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,208 @@
<!--#
layout("/layouts/platform.html"){
#-->
<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"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="变更类型">
<dict-select v-model="pageForm.changeType" placeholder="变更类型" @change="doSearch"
code="MEMBER_CHANGE_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="变更列表" :app="this"></table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id"
@sort-change="pageOrder"
resizable
v-loading="tableLoading" :size="tableSize" class="vi-table">
<el-table-column align="center" header-align="center" type="index"
:index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template v-if="column.prop=='loginname'" scope="{row}">
<el-link type="primary" @click="openUserView(row)">{{row.loginname}}</el-link>
</template>
</el-table-column>
<el-table-column label="异动信息" header-align="center">
<el-table-column label="更新时间" prop="changeTime" min-width="130px"
header-align="center"
sortable
align="center" show-overflow-tooltip>
</el-table-column>
<el-table-column label="异动类型" prop="changeTypes" header-align="center"
width="150px"
align="center" show-overflow-tooltip sortable>
<template scope="{row}">
<span style="color: #0e78c5;cursor: pointer" @click="openView(row)">
{{ getChangeTypes(row.changeTypes) }}
</span>
</template>
</el-table-column>
</el-table-column>
<!-- <el-table-column label="审核状态">-->
<!-- <template scope="{row}">-->
<!-- <vi-table-state v-if="row.stateId" :state="row"></vi-table-state>-->
<!-- <vi-table-state v-else :state="{stateColor:'#1890ff',stateName:'暂无'}"></vi-table-state>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px" fixed="right">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-all-change ref="memberAllChangeRef"></member-all-change>
</template>
<template #edit>
<member-info ref="memberInfoRef"></member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../common/memberAllChangeInfo.js"){}#-->
new Vue({
el:'#app',
store,
mixins: [initTableMixins],
data(){
return{
userId:'',
tableColumns: [
{prop: 'loginname', label: '工号'},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别', sortable: true, width: '100px'},
{prop: 'birthday', label: '出生年月', sortable: true},
{prop: 'personType', label: '教职工类别', sortable: true},
{prop: 'userState', label: '在职状态', sortable: true},
{prop: 'unionName', label: '所属工会', sortable: true},
{prop: 'unitName', label: '所属单位', sortable: true},
],
unions: [],
units: [],
changeTypeData: [],
}
},
components: {
'member-info': MEMBER_INFO,
"member-all-change": MEMBER_ALL_CHANGE_INFO,
},
methods: {
openUserView(row){
this.$refs.guava.edit(() => {
this.$refs.memberInfoRef.onOpen(row.userId)
})
},
openView(row){
this.$refs.guava.view(() => {
this.$refs.memberAllChangeRef.onOpen(row.userId)
})
},
getChangeTypes(changeTypes){
if (!changeTypes) return null
const changeTypesList = JSON.parse(changeTypes)
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
}
},
pageData() {
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(pageForm.userStates)
pageForm.personTypes = JSON.stringify(pageForm.personTypes)
pageForm.changeTypes = JSON.stringify(pageForm.changeTypes)
pageForm.changeOrigins = JSON.stringify(pageForm.changeOrigins)
this.$axios.post(loc() + '/pageData', pageForm)
.then(res => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
} else {
this.$message.error(res.msg)
}
})
},
},
async created() {
this.pageData();
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN")) {
this.unions = await this.$businessTool.listUnion()
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
}
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,44 @@
<div id="member_change_school_union_approval">
<el-form :model="formData" ref="formRef" 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>
<snaker-flow-task-form-action @task-action="handleTaskAction" @cancel="handleCancel"></snaker-flow-task-form-action>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_change_school_union_approval",
store,
data() {
return {
formData: {
tf_opinion: ""
},
}
},
methods: {
handleTaskAction(val) {
const data = {
...val,
...this.formData
}
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify(data)
}).then(res => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage({
type: "task-complete"
}, "*")
}
})
},
handleCancel(val) {
console.log(val)
},
}
})
</script>
@@ -0,0 +1,208 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="审核列表">
<el-radio-group @change="search" class="mr5" size="small" v-model="pageForm.audit">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openUserView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='changeTypes'">
<span style="color: #0e78c5;cursor: pointer" @click="openView(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="200px">
<template slot-scope="{row}">
<el-button @click="openView(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>
<info ref="infoRef">
<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>
</info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
audit: false
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: 'preparedBy', label: '编制类别', sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "changeTypes", label: "变更类型", sortable: true, width: 200 },
{ prop: "applyDateTime", label: "申请时间", sortable: true },
{ prop: "curTaskName", label: "当前节点"},
{ prop: "instanceState", label: "流程状态"}
],
changeTypeData: [],
// 审核相关
formData: {},
showApprovalForm: false
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
openView(row){
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.infoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
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()
}
}).finally(() => {
loading.close()
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
getChangeTypes(changeTypes) {
const changeTypesList = JSON.parse(changeTypes)
if (!changeTypesList) return null
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
},
async created() {
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,532 @@
<div id="member_change">
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">
<el-form-item prop="loginname">
<el-input v-model="formData.loginname" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="姓名">
<el-form-item prop="username">
<el-input v-model="formData.username" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="sex">
<el-radio-group :disabled="allowFields('sex')" v-model="formData.sex" size="small">
<el-radio border label="男"></el-radio>
<el-radio border label="女"></el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="民族">
<el-form-item prop="nation">
<dict-select style="width: 100%" placeholder="请选择民族" v-model="formData.nation"
:disabled="allowFields('nation')" code="USER_NATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="出生日期">
<el-form-item prop="birthday">
<el-date-picker v-model="formData.birthday"
type="date"
:disabled="allowFields('birthday')"
placeholder="请选择出生日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="政治面貌">
<el-form-item prop="political">
<dict-select style="width: 100%" placeholder="请选择政治面貌" v-model="formData.political"
:disabled="allowFields('political')" code="USER_POLITICAL"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学历">
<el-form-item prop="education">
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
:disabled="allowFields('education')" code="USER_EDUCATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学位">
<el-form-item prop="academicDegree">
<dict-select style="width: 100%" placeholder="请选择学位" v-model="formData.academicDegree"
:disabled="allowFields('academicDegree')" code="USER_ACADEMIC_DEGREE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="党政职务">
<el-form-item prop="position">
<el-input v-model="formData.position" placeholder="请输入党政职务"
:disabled="allowFields('position')" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<template v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN')">
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionId">
<el-select clearable filterable placeholder="请选择所属工会" style="width: 100%"
v-model="formData.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
</template>
<template v-else>
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
:disabled="allowFields('unitId')" @change="getUnionName"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionName">
<el-input v-model="formData.unionName" disabled placeholder="请输入所属工会"></el-input>
</el-form-item>
</el-descriptions-item>
</template>
<el-descriptions-item label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
:disabled="allowFields('campus')" code="USER_CAMPUS"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="身份证号码">
<el-form-item prop="idCard">
<el-input v-model="formData.idCard" :disabled="allowFields('idCard')" placeholder="请输入身份证号码" maxlength="18"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" :disabled="allowFields('mobile')" placeholder="请输入联系电话" maxlength="15"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="电子邮箱">
<el-form-item prop="email">
<el-input v-model="formData.email" :disabled="allowFields('email')" placeholder="请输入电子邮箱" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="formData.userState" code="USER_STATE"
:disabled="allowFields('userState')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="教职工类别">
<el-form-item prop="personType">
<dict-select v-model="formData.personType" code="USER_PERSON_TYPE"
:disabled="allowFields('personType')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<template v-if="formData.userState == '退休'">
<el-descriptions-item label="退休日期">
<el-form-item prop="retireDate">
<el-date-picker v-model="formData.retireDate"
type="date"
placeholder="请选择出生日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利享受截止日期">
<el-form-item prop="welfareStopDate">
<el-date-picker v-model="formData.welfareStopDate"
type="date"
:disabled="isView"
placeholder="请选择福利享受截止日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<el-descriptions-item label="会员状态" :span="1.5">
<el-form-item prop="member">
<el-radio-group v-model="formData.member" size="small">
<el-radio border :label="true">会员</el-radio>
<el-radio border :label="false">非会员</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利会员状态" :span="1.5">
<el-form-item prop="welfareMember">
<el-radio-group v-model="formData.welfareMember" size="small">
<el-radio border :label="true">福利会员</el-radio>
<el-radio border :label="false">非福利会员</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<!--<template v-if="formData.member == 1">
<el-descriptions-item label="是否加入会员组别">
<el-form-item prop="member">
<el-radio-group v-model="formData.isJoinActivityMemberScope" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
</template>
<template v-if="formData.member == 0">
<el-descriptions-item label="是否退出会员组别">
<el-form-item prop="member">
<el-radio-group v-model="formData.isExitActivityMemberScope" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
</template>
<template v-if="formData.member != null && !formData.welfareMember">
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<template v-if="formData.welfareMember == true">
<el-descriptions-item label="是否加入福利项目">
<el-form-item prop="isJoinWelfareProject">
<el-radio-group v-model="formData.isJoinWelfareProject" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<template v-if="formData.isJoinWelfareProject">
<el-descriptions-item label="选择福利项目">
<el-form-item prop="welfareProjectId">
<el-select clearable filterable placeholder="请选择福利项目" style="width: 100%"
v-model="formData.welfareProjectId">
<el-option v-for="item in welfareProjectList"
:key="id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
</template>
<template v-else>
<el-descriptions-item></el-descriptions-item>
</template>
</template>-->
<template v-if="">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-form-item prop="families">
<el-table :data="formData.families" border size="small">
<el-table-column label="关系" prop="relation">
<template slot-scope="{row}">
<el-input v-model="row.relation" maxlength="50"
placeholder="请输入与本人关系"></el-input>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name">
<template slot-scope="{row}">
<el-input v-model="row.name" maxlength="50" placeholder="请输入姓名"></el-input>
</template>
</el-table-column>
<el-table-column label="工作单位" prop="unit">
<template slot-scope="{row}">
<el-input v-model="row.unit" maxlength="100"
placeholder="请输入工作单位"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" maxlength="100" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column width="100px">
<template slot="header" slot-scope="scope">
<el-button type="primary" size="mini" :disabled="allowFields('families')"
@click="formData.families.push({})">添加
</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="formData.families.length===0 || allowFields('families')"
@click="formData.families.splice(scope.$index,1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="个人简历" :span="3">
<el-form-item prop="personalData">
<text-editor v-model="formData.personalData"></text-editor>
</el-form-item>
</el-descriptions-item>
</template>
</el-descriptions>
</el-form>
<snaker-flow-task-form-action @task-action="handleTaskAction" @save-draft="handleSaveDraft" @cancel="handleCancel"></snaker-flow-task-form-action>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#member_change',
store,
data() {
return {
units: [],
unions: [],
// 允许变更的字段
allowChangeFields: [],
formData: {
families: [],
},
formRules: {
username: [{required: false, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: false, message: "必填", trigger: ["change", "blur"]}],
email: [
{
validator: (rule, value, callback) => {
if (!value) {
callback();
} else if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
callback();
} else {
callback(new Error("邮箱格式错误"));
}
},
trigger: ["change", "blur"]
}
],
idCard: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}(\d|[Xx])$/.test(value)) {
// 18位身份证号码格式正确
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 15位身份证号码格式正确
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(18位)
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(15位)
callback();
} else {
// 格式错误,返回错误信息
callback(new Error("身份证号码格式错误"));
}
},
trigger: ["change", "blur"]
}
],
mobile: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1][345789][0-9]{9}$/.test(value)) {
// 手机号格式正确
callback();
} else if (/^\d+-\d+$/.test(value) && value.length <= 16) {
// 座机号格式正确
callback();
} else {
// 格式错误,返回错误信息
callback(new Error(value.includes('-') ? '座机号码格式错误' : '手机号码格式错误'));
}
},
trigger: ["change", "blur"]
}
]
},
}
},
methods: {
// 提交
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", { type: "warning" })
.then(() => {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios
.post("/flow/common/startInstanceAndExecute", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage(
{
type: "task-complete"
},
"*"
)
}
})
}
})
})
},
// 保存
handleSaveDraft(val) {
this.$confirm("您确定要保存吗?", "提示", { type: "warning" })
.then(() => {
this.$axios
.post("/flow/common/startInstance", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage(
{
type: "task-complete"
},
"*"
)
}
})
})
},
// 取消
handleCancel() {
},
getUnionName(val){
const data = this.units.find(v => v.id === val)
this.$set(this.formData, 'unionName', data ? data.unionname : '')
},
allowFields(prop) {
return !this.allowChangeFields.map(v => v.code).includes(prop)
},
async init(userId){
if (userId) {
this.isShow = false
await this.getUserById(userId)
} else {
this.isShow = true
this.user = this.$store.state.user
}
this.getFormDataValue(this.id)
this.allowChangeFields = await this.$businessTool.getDictOptions("ALLOW_CHANGE_FIELDS")
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_MEMBER_ADMIN, SCHOOL_UNION_ADMIN')) {
this.units = await this.$businessTool.listUnit()
this.unions = await this.$businessTool.listUnion()
} else {
this.units = await this.$businessTool.listUnit(this.user.union.id)
}
},
async getUserById(userId){
const resp = await this.$axios.post("/platform/member/change/apply/getUserByIdForMemberChange", { userId })
if (resp.code === 0) {
this.user = resp.data
}
},
getFormDataValue(id){
if (id) {
this.$axios.post("/platform/member/change/apply/findChangeById", { id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.formData.unionid = this.user.unionid
if (this.formData.families) {
this.formData.families = JSON.parse(this.formData.families)
} else {
this.formData.families = []
}
}
})
} else {
const {
id,
username,
loginname,
sex,
member,
welfareMember,
nation,
birthday,
political,
education,
academicDegree,
position,
unit,
union,
campus,
userState,
personType,
preparedBy,
idCard,
mobile,
email,
families,
personalData
} = this.user
this.$set(this.formData, "userId", id)
this.$set(this.formData, "username", username)
this.$set(this.formData, "loginname", loginname)
this.$set(this.formData, "birthday", birthday)
this.$set(this.formData, "sex", sex)
this.$set(this.formData, "member", member === 1)
this.$set(this.formData, "welfareMember", welfareMember === 1)
this.$set(this.formData, "idCard", idCard)
this.$set(this.formData, "nation", nation)
this.$set(this.formData, "political", political)
this.$set(this.formData, "position", position)
this.$set(this.formData, "education", education)
this.$set(this.formData, "academicDegree", academicDegree)
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "userState", userState)
this.$set(this.formData, "personType", personType)
this.$set(this.formData, "preparedBy", preparedBy)
this.$set(this.formData, "unitName", unit ? unit.name : null)
this.$set(this.formData, "unitId", unit ? unit.id : null)
this.$set(this.formData, "unionName", union ? union.name : null)
this.$set(this.formData, "unionId", union ? union.id : null)
this.$set(this.formData, "mobile", mobile)
this.$set(this.formData, "email", email)
this.$set(this.formData, "families", families ? families : [])
this.$set(this.formData, "personalData", personalData)
}
}
},
created(){
this.init()
}
})
</script>
@@ -0,0 +1,537 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<el-card shadow="never">
<snaker-start slot="header" label="会员变更" define_key="HYBG"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-descriptions :column="3" border>
<el-descriptions-item label="工号">
<el-form-item prop="loginname">
<el-input v-model="formData.loginname" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="姓名">
<el-form-item prop="username">
<el-input v-model="formData.username" readonly size="small"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="sex">
<el-radio-group :disabled="allowFields('sex')" v-model="formData.sex" size="small">
<el-radio border label="男"></el-radio>
<el-radio border label="女"></el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="民族">
<el-form-item prop="nation">
<dict-select style="width: 100%" placeholder="请选择民族" v-model="formData.nation"
:disabled="allowFields('nation')" code="USER_NATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="出生日期">
<el-form-item prop="birthday">
<el-date-picker v-model="formData.birthday"
type="date"
:disabled="allowFields('birthday')"
placeholder="请选择出生日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="政治面貌">
<el-form-item prop="political">
<dict-select style="width: 100%" placeholder="请选择政治面貌" v-model="formData.political"
:disabled="allowFields('political')" code="USER_POLITICAL"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学历">
<el-form-item prop="education">
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
:disabled="allowFields('education')" code="USER_EDUCATION"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="学位">
<el-form-item prop="academicDegree">
<dict-select style="width: 100%" placeholder="请选择学位" v-model="formData.academicDegree"
:disabled="allowFields('academicDegree')" code="USER_ACADEMIC_DEGREE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="党政职务">
<el-form-item prop="position">
<el-input v-model="formData.position" placeholder="请输入党政职务"
:disabled="allowFields('position')" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<!--<template v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN')">
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionId">
<el-select clearable filterable placeholder="请选择所属工会" style="width: 100%"
v-model="formData.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
</template>-->
<template>
<el-descriptions-item label="工作单位">
<el-form-item prop="unitId">
<el-select clearable filterable placeholder="请选择工作单位" style="width: 100%"
:disabled="allowFields('unitId')" @change="getUnionName"
v-model="formData.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属工会">
<el-form-item prop="unionName">
<el-input v-model="formData.unionName" disabled placeholder="请输入所属工会"></el-input>
</el-form-item>
</el-descriptions-item>
</template>
<el-descriptions-item label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
:disabled="allowFields('campus')" code="USER_CAMPUS"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="身份证号码">
<el-form-item prop="idCard">
<el-input v-model="formData.idCard" :disabled="allowFields('idCard')" placeholder="请输入身份证号码" maxlength="18"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" :disabled="allowFields('mobile')" placeholder="请输入联系电话" maxlength="15"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="电子邮箱">
<el-form-item prop="email">
<el-input v-model="formData.email" :disabled="allowFields('email')" placeholder="请输入电子邮箱" maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="formData.userState" code="USER_STATE"
:disabled="allowFields('userState')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="教职工类别">
<el-form-item prop="personType">
<dict-select v-model="formData.personType" code="USER_PERSON_TYPE"
:disabled="allowFields('personType')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="编制类别">
<el-form-item prop="preparedBy">
<dict-select v-model="formData.preparedBy" code="USER_PREPARED_BY_TYPE"
:disabled="allowFields('preparedBy')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="会员状态" :span="1.5">
<el-form-item prop="member">
<el-radio-group v-model="formData.member" size="small">
<el-radio border :label="true">会员</el-radio>
<el-radio border :label="false">非会员</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利会员状态" :span="1.5">
<el-form-item prop="welfareMember">
<el-radio-group v-model="formData.welfareMember" size="small">
<el-radio border :label="true">福利会员</el-radio>
<el-radio border :label="false">非福利会员</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<!--<template v-if="formData.member == 1">
<el-descriptions-item label="是否加入会员组别">
<el-form-item prop="member">
<el-radio-group v-model="formData.isJoinActivityMemberScope" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
</template>
<template v-if="formData.member == 0">
<el-descriptions-item label="是否退出会员组别">
<el-form-item prop="member">
<el-radio-group v-model="formData.isExitActivityMemberScope" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
</template>
<template v-if="formData.member != null && !formData.welfareMember">
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<template v-if="formData.welfareMember == true">
<el-descriptions-item label="是否加入福利项目">
<el-form-item prop="isJoinWelfareProject">
<el-radio-group v-model="formData.isJoinWelfareProject" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<template v-if="formData.isJoinWelfareProject">
<el-descriptions-item label="选择福利项目">
<el-form-item prop="welfareProjectId">
<el-select clearable filterable placeholder="请选择福利项目" style="width: 100%"
v-model="formData.welfareProjectId">
<el-option v-for="item in welfareProjectList"
:key="id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
</template>
<template v-else>
<el-descriptions-item></el-descriptions-item>
</template>
</template>-->
<template v-if="formData.loginname == $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-form-item prop="families">
<el-table :data="formData.families" border size="small">
<el-table-column label="关系" prop="relation">
<template slot-scope="{row}">
<el-input v-model="row.relation" maxlength="50"
placeholder="请输入与本人关系"></el-input>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name">
<template slot-scope="{row}">
<el-input v-model="row.name" maxlength="50" placeholder="请输入姓名"></el-input>
</template>
</el-table-column>
<el-table-column label="工作单位" prop="unit">
<template slot-scope="{row}">
<el-input v-model="row.unit" maxlength="100"
placeholder="请输入工作单位"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" maxlength="100" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column width="100px">
<template slot="header" slot-scope="scope">
<el-button type="primary" size="mini" :disabled="allowFields('families')"
@click="formData.families.push({})">添加
</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="formData.families.length===0 || allowFields('families')"
@click="formData.families.splice(scope.$index,1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="个人简历" :span="3">
<el-form-item prop="personalData">
<text-editor v-model="formData.personalData"></text-editor>
</el-form-item>
</el-descriptions-item>
</template>
</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>提交</el-button>
</el-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
data(){
return{
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
units: [],
unions: [],
// 允许变更的字段
allowChangeFields: [],
formData: {
families: [],
},
formRules: {
username: [{required: false, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: false, message: "必填", trigger: ["change", "blur"]}],
/*email: [
{
validator: (rule, value, callback) => {
if (!value) {
callback();
} else if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
callback();
} else {
callback(new Error("邮箱格式错误"));
}
},
trigger: ["change", "blur"]
}
],
idCard: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}(\d|[Xx])$/.test(value)) {
// 18位身份证号码格式正确
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 15位身份证号码格式正确
callback();
} else if (/^[1-9]\d{5}(18|19|20)?\d{2}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(18位)
callback();
} else if (/^[1-9]\d{7}((0[1-9])|(10|11|12))(([0|1|2][0-9])|10|20|30|31)\d{3}$/.test(value)) {
// 外国人身份证号码格式正确(15位)
callback();
} else {
// 格式错误,返回错误信息
callback(new Error("身份证号码格式错误"));
}
},
trigger: ["change", "blur"]
}
],
mobile: [
{
validator: (rule, value, callback) => {
if (!value) {
// 如果值为空,直接通过校验
callback();
} else if (/^[1][345789][0-9]{9}$/.test(value)) {
// 手机号格式正确
callback();
} else if (/^\d+-\d+$/.test(value) && value.length <= 16) {
// 座机号格式正确
callback();
} else {
// 格式错误,返回错误信息
callback(new Error(value.includes('-') ? '座机号码格式错误' : '手机号码格式错误'));
}
},
trigger: ["change", "blur"]
}
]*/
},
}
},
methods: {
// 保存
onSave() {
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/change/apply/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success("保存成功")
commonUtil.pjaxPush('/platform/member/change/mine')
}
}).finally(() => {
loading.close()
})
})
},
// 提交
onSubmit() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/change/apply/submit', {
data: JSON.stringify(this.formData)
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/member/change/mine')
}
}).finally(() => {
loading.close()
})
})
},
onFinishTask() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/change/apply/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/member/change/mine')
}
}).finally(() => {
loading.close()
})
})
},
// 获取表单工会名称
getUnionName(val){
const data = this.units.find(v => v.id === val)
this.$set(this.formData, 'unionName', data ? data.unionName : '')
},
// 获取表单可编辑的字段信息
allowFields(prop) {
return !this.allowChangeFields.map(v => v.code).includes(prop)
},
// 初始化表单数据
async init(userId){
if (userId) {
this.isShow = false
await this.getUserById(userId)
} else {
this.isShow = true
this.user = this.$store.state.user
}
this.getFormDataValue()
this.allowChangeFields = await this.$businessTool.getDictOptions("ALLOW_CHANGE_FIELDS")
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_MEMBER_ADMIN, SCHOOL_UNION_ADMIN')) {
this.units = await this.$businessTool.listUnit()
this.unions = await this.$businessTool.listUnion()
} else {
this.units = await this.$businessTool.listUnit(this.user.union.id)
}
},
// 获取根据userId获取用户信息
async getUserById(userId){
const resp = await this.$axios.post("/platform/member/change/apply/getUserByIdForMemberChange", { userId })
if (resp.code === 0) {
this.user = resp.data
}
},
getFormDataValue(){
if (this.bizId) {
this.$axios.post("/platform/member/change/apply/findChangeById", { id: this.bizId }).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.formData.unionid = this.user.unionid
if (this.formData.families) {
this.formData.families = JSON.parse(this.formData.families)
} else {
this.formData.families = []
}
}
})
} else {
const {
id,
username,
loginname,
sex,
member,
welfareMember,
nation,
birthday,
political,
education,
academicDegree,
position,
unit,
union,
campus,
userState,
personType,
preparedBy,
idCard,
mobile,
email,
families,
personalData
} = this.user
this.$set(this.formData, "userId", id)
this.$set(this.formData, "username", username)
this.$set(this.formData, "loginname", loginname)
this.$set(this.formData, "birthday", birthday)
this.$set(this.formData, "sex", sex)
this.$set(this.formData, "member", member)
this.$set(this.formData, "welfareMember", welfareMember)
this.$set(this.formData, "idCard", idCard)
this.$set(this.formData, "nation", nation)
this.$set(this.formData, "political", political)
this.$set(this.formData, "position", position)
this.$set(this.formData, "education", education)
this.$set(this.formData, "academicDegree", academicDegree)
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "userState", userState)
this.$set(this.formData, "personType", personType)
this.$set(this.formData, "preparedBy", preparedBy)
this.$set(this.formData, "unitName", unit ? unit.name : null)
this.$set(this.formData, "unitId", unit ? unit.id : null)
this.$set(this.formData, "unionName", union ? union.name : null)
this.$set(this.formData, "unionId", union ? union.id : null)
this.$set(this.formData, "mobile", mobile)
this.$set(this.formData, "email", email)
this.$set(this.formData, "families", families ? families : [])
this.$set(this.formData, "personalData", personalData)
}
}
},
async created(){
this.init()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,60 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<member-change ref="memberChange" :id="id" @do-save="doSave" @do-submit="doSubmit"
@do-back="sublime.jumpPagePjax('/platform/member/change/mine')"></member-change>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/memberChange.js"){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
data(){
return{
id: GetQueryString('id')
}
},
components: {
'member-change': MEMBER_CHANGE,
},
methods: {
async doSave(formData){
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const resp = await $.post('/platform/member/change/apply/doSave', formData)
loading.close()
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$store.dispatch("pjaxRoute", "/platform/member/change/mine")
} else {
this.$message.error(resp.msg)
}
},
async doSubmit(formData){
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const resp = await $.post('/platform/member/change/apply/doSubmit', formData)
loading.close()
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$store.dispatch("pjaxRoute", "/platform/member/change/mine")
} else {
this.$message.error(resp.msg)
}
},
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,206 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="审核列表">
<el-radio-group @change="search" class="mr5" size="small" v-model="pageForm.audit">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='changeTypes'">
<span style="color: #0e78c5;cursor: pointer" @click="openView(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
<template scope="{row}" v-else-if="column.prop=='instanceState'">
<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="200px">
<template slot-scope="{row}">
<el-button @click="openView(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>
<info ref="infoRef">
<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>
</info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
audit: false
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: 'preparedBy', label: '编制类别', sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "changeTypes", label: "变更类型", sortable: true, width: 200 },
{ prop: "applyDateTime", label: "申请时间", sortable: true },
{ prop: "curTaskName", label: "当前节点"},
{ prop: "instanceState", label: "流程状态"}
],
changeTypeData: [],
// 审核相关
formData: {},
showApprovalForm: false
}
},
components: {
'info': INFO,
'common-query': COMMON_QUERY,
},
methods: {
openView(row){
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.infoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading()
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()
}
}).finally(() => {
loading.close()
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
const loading = createLoading()
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
loading.close()
})
})
},
search(pageForm){
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
getChangeTypes(changeTypes) {
const changeTypesList = JSON.parse(changeTypes)
if (!changeTypesList) return null
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
},
async created() {
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,165 @@
<div id="member_change_view">
<el-tabs v-model="activeName">
<el-tab-pane label="基础信息" name="basicInfo">
<el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ viewData.birthday ? $moment(viewData.birthday).format("YYYY年MM月DD日") : '暂无' }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</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="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="进校时间">{{ viewData.schoolTime }}</el-descriptions-item>
<template v-if="viewData.userState == '退休'">
<el-descriptions-item label="退休日期">{{ viewData.retireDate ? $moment(viewData.retireDate).format("YYYY-MM-DD") : '暂无' }}</el-descriptions-item>
<el-descriptions-item label="福利享受截止日期">{{ $moment(viewData.welfareStopDate).format("YYYY-MM-DD") }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<el-descriptions-item label="会员状态">{{ viewData.member ? '会员' : '非会员' }}</el-descriptions-item>
<el-descriptions-item label="福利会员状态">{{ viewData.welfareMember ? '福利会员' : '非福利会员' }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center" header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<template slot="label">个人简况</template>
<div v-if="viewData.vita" class="text-left" v-html="viewData.vita"></div>
<span v-else>无数据</span>
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="变更信息" name="changeInfo" v-if="viewData.changeInfos">
<el-table :data="viewData.changeInfos" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column prop="fieldName" label="变更字段" header-align="center"></el-table-column>
<el-table-column prop="sourceValue" label="原数据" header-align="center">
<template slot-scope="{row}">
<div v-html="row.sourceValue"></div>
</template>
</el-table-column>
<el-table-column prop="newValue" label="新数据" header-align="center">
<template slot-scope="{row}">
<div v-html="row.newValue"></div>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<template v-for="task in doneTasks">
<div class="task-panel mt10">
<div class="task-panel-header">{{ 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="办理意见" :span="3" v-if="!task.ext.isFirstTaskNode">{{ task.taskFormData.opinion }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#member_change_view",
mixins: [initTableMixins],
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
activeName: "basicInfo",
businessId: GetQueryString("businessId"),
instanceId: GetQueryString("instanceId"),
viewData: {
changeInfos: [],
},
doneTasks: []
}
},
methods: {
info() {
this.$axios.post("/platform/member/change/view/findMemberChangeRecord", { id: this.businessId }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", { instanceId: this.instanceId }).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
}
},
created() {
this.info()
this.getDoneTasks()
}
})
</script>
<style>
.task-panel {
background: white;
border-radius: 4px;
overflow: hidden;
}
.task-panel-header {
background: rgb(250, 250, 250);
border: 1px solid rgb(228, 231, 237);
border-bottom: none;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.el-descriptions-item__label.is-bordered-label {
width: 15%;
}
</style>
@@ -0,0 +1,28 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return{
}
},
methods: {
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,26 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return{
}
},
methods: {
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,26 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return{
}
},
methods: {
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,103 @@
const MEMBER_INFO = {
template: /*language=html*/ `
<div>
<!-- 基本信息 -->
<div class="process-title">基本信息</div>
<el-descriptions :column="3" border class="descriptions-form">
<!-- 第 1 行 -->
<el-descriptions-item label="姓名工号">{{ viewData.username + '(' + viewData.loginname + ')' }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ viewData.birthday ? $moment(viewData.birthday).format('YYYY-MM-DD') : null }}</el-descriptions-item>
<!-- 第 2 行 -->
<el-descriptions-item label="国籍">{{ viewData.nationality }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<!-- 第 3 行 -->
<el-descriptions-item label="证件类型">{{ viewData.idCardType }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idcard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<!-- 第 4 行 -->
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="婚姻状况">{{ viewData.marriage }}</el-descriptions-item>
<!-- 第 5 行 -->
<el-descriptions-item label="会员状态">{{ viewData.member ? '会员' : '非会员' }}</el-descriptions-item>
<el-descriptions-item label="福利会员状态">{{ viewData.welfareMember ? '福利会员' : '非福利会员' }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<!-- 退休补充 -->
<template v-if="viewData.userState == '退休'">
<el-descriptions-item label="退休日期">{{ viewData.retireDate ? $moment(viewData.retireDate).format("YYYY-MM-DD") : '暂无' }}</el-descriptions-item>
<el-descriptions-item label="福利享受截止日期">{{ viewData.welfareStopDate ? $moment(viewData.welfareStopDate).format("YYYY-MM-DD") : '暂无' }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
</template>
<!-- 仅本人可见 -->
<template v-if="viewData.loginname === $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families && viewData.families.length" :data="viewData.families" size="mini" border :header-cell-style="{background:'#eff3f6'}" style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center"/>
<el-table-column prop="name" label="姓名" align="center"/>
<el-table-column prop="unit" label="单位" align="center"/>
<el-table-column prop="remark" label="备注" align="center"/>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"/>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"/>
<span v-else>无数据</span>
</el-descriptions-item>
</template>
</el-descriptions>
<!-- 工作信息 -->
<div class="process-title">工作信息</div>
<el-descriptions :column="3" border>
<!-- 第 1 行 -->
<el-descriptions-item label="工作单位">{{ viewData.unitName }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item>
<!-- 第 2 行 -->
<el-descriptions-item label="进校时间">{{ viewData.arrivalAtSchoolDate ? $moment(viewData.arrivalAtSchoolDate).format('YYYY-MM-DD') : null }}</el-descriptions-item>
<el-descriptions-item label="从教年月">{{ viewData.teachingTime ? $moment(viewData.teachingTime).format('YYYY-MM-DD') : null }}</el-descriptions-item>
<el-descriptions-item label="预/已离校时间">{{ viewData.expectedLeaveSchoolDate ? $moment(viewData.expectedLeaveSchoolDate).format('YYYY-MM-DD') : null }}</el-descriptions-item>
<!-- 第 3 行 -->
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="编制类别">{{ viewData.preparedBy }}</el-descriptions-item>
<!-- 第 4 行 -->
<el-descriptions-item label="职称">{{ viewData.professionalTitle }}</el-descriptions-item>
<el-descriptions-item label="职级">{{ viewData.professionalLevel }}</el-descriptions-item>
<el-descriptions-item label="岗位系列">{{ viewData.positionSeries }}</el-descriptions-item>
<!-- 第 5 行 -->
<el-descriptions-item label="行政级别(管理岗位)">{{ viewData.administrativeLevel }}</el-descriptions-item>
<el-descriptions-item label="岗级">{{ viewData.positionLevel }}</el-descriptions-item>
<el-descriptions-item label="行政岗级">{{ viewData.administrativePositionLevel }}</el-descriptions-item>
</el-descriptions>
</div>
`,
store,
data() {
return {
viewData: {}
}
},
methods: {
onOpen(id) {
this.$axios.post("/platform/member/apply/common/findOne", { id }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
}
}
}
@@ -0,0 +1,136 @@
const MEMBER_MANAGE_QUERY = {
template: `
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="性别">
<dict-select v-model="pageForm.sex" placeholder="性别" @change="doSearch"
code="USER_SEX"></dict-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="更新日期">
<el-date-picker :picker-options="pickerOptions" @change="changeDateRangeChange"
align="right" end-placeholder="结束日期" format="yyyy-MM-dd"
range-separator="-" start-placeholder="开始日期" style="width: 100%"
type="datetimerange" v-model="pageForm.changeDateRange"
value-format="yyyy-MM-dd"></el-date-picker>
</search-item>
</search>
</el-card>
`,
mixins: [initTableMixins],
data() {
return {
pickerOptions: {
shortcuts: [
{
text: "最近一周",
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit("pick", [start, end])
}
},
{
text: "最近一个月",
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit("pick", [start, end])
}
},
{
text: "最近三个月",
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit("pick", [start, end])
}
}
]
},
pageForm: {
unionId: null,
unitId: null,
sex: null,
searchKeyword: null,
changed: 2,
isMember: 1,
isWelfareMember: null,
changeTypes: []
},
unions: [],
units: []
}
},
methods: {
changeDateRangeChange(val) {
if (val && val.length > 0) {
this.pageForm.changeDateBefore = val[0]
this.pageForm.changeDateEnd = val[1]
} else {
this.pageForm.changeDateBefore = null
this.pageForm.changeDateEnd = null
}
this.doSearch()
},
async initData() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.unions = await this.$businessTool.listUnion(this.pageForm.unionId)
this.units = await this.$businessTool.listUnit()
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
this.units = await this.$businessTool.listUnit(this.$store.state.user.union.id)
}
// this.$businessTool.getDictOptions("MEMBER_CHANGE_TYPE").then((data) => {
// this.changeTypes = data
// })
this.doSearch()
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
doSearch() {
this.$emit("query-ready", this.pageForm)
}
},
created() {
this.initData()
}
}
@@ -0,0 +1,259 @@
<!--#include("../change/memberChangeInfo.js"){}#-->
const MEMBER_MANAGE_TABLE = {
template: /*language=HTML*/ `
<div>
<el-card shadow="never" class="mt10">
<table-tool label="人员列表">
<span class="text-danger">会员:</span>
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.isMember">
<el-radio-button :label="null">全部</el-radio-button>
<el-radio-button :label="1">会员</el-radio-button>
<el-radio-button :label="0">非会员</el-radio-button>
</el-radio-group>
<!-- <span class="text-danger">福利会员:</span>-->
<!-- <el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.isWelfareMember">-->
<!-- <el-radio-button :label="null">全部</el-radio-button>-->
<!-- <el-radio-button :label="1">福利会员</el-radio-button>-->
<!-- <el-radio-button :label="0">非福利会员</el-radio-button>-->
<!-- </el-radio-group>-->
<span class="text-danger">人员异动:</span>
<el-radio-group @change="doSearch" class="mr5" size="small"
v-model="pageForm.changed">
<el-radio-button :label="2">全部</el-radio-button>
<el-radio-button :label="1">异动</el-radio-button>
<el-radio-button :label="0">未异动</el-radio-button>
</el-radio-group>
<!--<div v-if="pageForm.changed == '1'" class="div-enum">
<dict-select v-model="pageForm.USER_CHANGE_TYPE" placeholder="异动类型" @change="doSearch"
code="UserType"></dict-select>
</div>-->
<!--<el-button @click="addMember" type="primary" size="small">新增会员</el-button>-->
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id"
style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label" :prop="column.prop"
:sortable="column.sortable" :width="column.width"
align="center" header-align="center" min-width="100px"
show-overflow-tooltip v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='loginname'">
<el-link @click="openView(row.id)" type="primary">{{row.loginname}}</el-link>
</template>
</el-table-column>
<el-table-column header-align="center" label="异动信息">
<el-table-column align="center" header-align="center" label="更新时间"
min-width="145px" prop="changeTime"
show-overflow-tooltip sortable>
</el-table-column>
<el-table-column align="center" header-align="center" label="异动类型"
prop="changeType" show-overflow-tooltip sortable>
<template scope="{row}">
<span style="color: #0e78c5;cursor: pointer" @click="openUserChangeInfo(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column v-if="$auth.hasRole('BRANCH_UNION_CHAIRMAN')" header-align="center"
label="审核状态"
prop="auditState">
</el-table-column>
<el-table-column align="center" header-align="center" label="会员" prop="member"
show-overflow-tooltip sortable>
<template scope="{row}">
<span class="text-success" v-if="row.member==1">
<i class="fa fa-circle ml5"></i> 是
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i> 否
</span>
</template>
</el-table-column>
<!-- <el-table-column align="center" header-align="center" label="福利会员" prop="member"-->
<!-- show-overflow-tooltip sortable>-->
<!-- <template scope="{row}">-->
<!-- <span class="text-success" v-if="row.welfareMember==1">-->
<!-- <i class="fa fa-circle ml5"></i> 是-->
<!-- </span>-->
<!-- <span class="text-danger" v-else>-->
<!-- <i class="fa fa-circle ml5"></i> 否-->
<!-- </span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!--<el-table-column align="center" header-align="center" label="劳模" prop="member"
show-overflow-tooltip sortable>
<template scope="{row}">
<span class="text-success " v-if="row.isModelWorker==1">
<i class="fa fa-circle ml5"></i> 是
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i> 否
</span>
</template>
</el-table-column>-->
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline"
width="100px">
<template scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'view',data:row}">
查看
</el-dropdown-item>
<el-dropdown-item
:command="{type:'change',data:row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN','BRANCH_UNION_CHAIRMAN','BRANCH_UNION_CHAIRMAN'])">
变更
</el-dropdown-item>
<!--<el-dropdown-item
:command="{type:'setModelWorker',data:row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN','BRANCH_UNION_CHAIRMAN','BRANCH_UNION_CHAIRMAN']) && !row.isModelWorker">
设为劳模
</el-dropdown-item>
<el-dropdown-item
:command="{type:'cancelModelWorker',data:row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN','BRANCH_UNION_CHAIRMAN','BRANCH_UNION_CHAIRMAN']) && row.isModelWorker">
取消劳模
</el-dropdown-item>-->
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="变更信息" :visible.sync="changeInfoVisible" width="70%">
<member-change-info ref="memberChangeInfoRef"></member-change-info>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
components: {
"member-change-info": MEMBER_CHANGE_INFO
},
data() {
return {
changeTypeData: [],
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true, width: "100px" },
{ prop: "birthday", label: "出生年月", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true }
],
changeInfoVisible: false,
userId: "",
pageForm: {
isMember: 1,
changed: 2
}
}
},
methods: {
dropdownCommand(command) {
const { type, data } = command
if (type === "view") {
this.openView(data.id)
} else if (type === "change") {
this.openChange(data)
} else if (type === "setModelWorker") {
this.setModelWorker(data.id)
} else if (type === "cancelModelWorker") {
this.cancelModelWorker(data.id)
}
},
setModelWorker(userId) {
this.$confirm("确定要将此教工设置为劳模吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/member/modelWorker/manage/setModelWorker", { userId: userId }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.$emit("refresh-table")
} else {
this.$message.error(res.msg)
}
})
})
},
cancelModelWorker(userId) {
this.$confirm("确定要取消此教工的劳模身份码?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/member/modelWorker/manage/cancelModelWorker", { userIds: JSON.stringify([userId]) })
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.$emit("refresh-table")
} else {
this.$message.error(res.msg)
}
})
})
},
openChange(data) {
this.$emit("change-member", { id: data.id, username: data.username })
},
openView(id) {
this.$emit("view-member", id)
},
addMember() {
this.$emit("add-member")
},
openUserChangeInfo(row) {
this.changeInfoVisible = true
this.$nextTick(() => {
this.$refs.memberChangeInfoRef.onOpen(row.id, null)
})
},
getChangeTypes(changeTypes) {
if (changeTypes) {
const c = JSON.parse(changeTypes)
return c
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).name
})
.join(",")
}
return null
},
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
this.$emit("refresh", this.pageForm)
}
})
}
},
created() {
this.$businessTool.getAllDictOptions("MEMBER_CHANGE_TYPE").then((res) => {
this.changeTypeData = res
})
}
}
@@ -0,0 +1,96 @@
const MEMBER_VERIFICATION_CHANGE = {
template: `
<el-card shadow="never">
<div>
<div style="margin-bottom:20px">
<el-divider><h4 style="color: var(--color-primary)">当前信息</h4></el-divider>
</div>
<el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ viewData.sex }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ viewData.nation }}</el-descriptions-item>
<el-descriptions-item label="在职状态">{{ viewData.userState }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="学历">{{ viewData.education }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ viewData.political }}</el-descriptions-item>
<el-descriptions-item label="婚姻状况">{{ viewData.marriage || '' }}</el-descriptions-item>
<el-descriptions-item label="证件号码" span="2">{{ viewData.idCard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
<el-descriptions-item label="是否会员">{{ viewData.member ? '是' : '否' }}</el-descriptions-item>
<el-descriptions-item label="是否福利会员">{{ viewData.welfareMember ? '是' : '否' }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="所属工会、工作部门(学院)及职务" span="3">
<template slot="label">工作部门(学院)及岗位</template>
<div class="text-left">
{{ viewData.unionName + '-' + viewData.unitName + ( viewData.governmentPosition ? ( '(' + viewData.governmentPosition + ')' ) : '' ) }}
</div>
</el-descriptions-item>
</el-descriptions>
</div>
<div style="margin-top: 20px">
<div style="margin: 20px 0">
<el-divider><h4 style="color: var(--color-primary)">变更记录</h4></el-divider>
</div>
<el-table v-if="changeList && changeList.length > 0" ref="changeTable" :data="changeList" row-key="id"
style="width: 100%" border>
<el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column label="变更字段" prop="name"></el-table-column>
<el-table-column label="原数据" prop="value">
<template slot-scope="scope">
<div v-html="scope.row.value"></div>
</template>
</el-table-column>
<el-table-column label="新数据" prop="newValue">
<template slot-scope="scope">
<div v-html="scope.row.newValue"></div>
</template>
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="未获取到变更信息"></el-empty>
</div>
</el-card>
`,
mixins: [initTableMixins],
data() {
return {
changeList: [],
viewData: {}
}
},
methods: {
findOne(id, projectId) {
if (!id || !projectId) {
return
}
this.$set(this.formData, "userId", id)
this.$set(this.formData, "verificationProjectId", projectId)
this.$axios
.post(loc() + "/getVerificationChangeInfo", {
data: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.changeList = res.data
}
})
this.findUserInfo()
},
findUserInfo(id) {
if (!id) {
return
}
this.$axios.post("/platform/member/apply/common/findOne", { id: id }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
onOpen(data) {
this.findOne(data.id, data.projectId)
this.$nextTick(() => {
this.findUserInfo(data.id)
})
}
}
}
@@ -0,0 +1,135 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="非会员列表">
<el-button @click="doExport" size="mini" type="primary">导出</el-button>
<el-button :disabled="!selection || selection.length == 0"
@click="batchMake" size="mini" type="primary">批量设置为会员</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table"
row-key="id" @selection-change="handleSelectionChange" style="width: 100%">
<el-table-column :reserve-selection="true" type="selection" width="55"></el-table-column>
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
</el-table-column>
<el-table-column label="操作" fixed="right" width="200px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="singleMake(row)" size="mini" type="primary">设置为会员</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<member-info ref="memberInfo"></member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {},
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
],
selection: [],
}
},
components: {
"common-query": COMMON_QUERY,
"member-info": MEMBER_INFO
},
methods: {
// 查看信息
openView(row) {
this.$refs.guava.view(() => {
this.$refs.memberInfo.onOpen(row.id)
})
},
// 单个设置会员
singleMake(row) {
const data = [row.id]
const msg = "确定将【" + row.username + "】设置为会员吗?"
this.setMemberFun(msg, data)
},
// 批量设置会员
batchMake() {
const msg = "确定将【" + this.selection.length + "】条数据设置为会员吗?"
const data = this.selection.map(item => item.id)
this.setMemberFun(msg, data)
},
setMemberFun(msg, data) {
this.$confirm(msg, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
debugger
const loading = createLoading('正在提交中')
const resp = await this.$axios.post("/platform/member/info/batchMake/batchMake", {
userIds: JSON.stringify(data)
})
loading.close()
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
this.selection = []
this.$refs.table.clearSelection()
} else {
this.$message.error(resp.msg)
}
})
},
doExport() {
this.$downLoad("/platform/member/info/batchMake/doExport", this.pageForm)
},
handleSelectionChange(val){
this.selection = val;
},
search(pageForm) {
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,901 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
/* 主网格布局 */
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 200px 1fr;
gap: 20px;
width: 100%;
height: calc(100vh - 126px);
box-sizing: border-box;
}
/* 卡片基础样式 */
.card {
background-color: white;
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* 卡片标题样式 */
.card-title {
padding: 16px 20px 8px;
font-size: 16px;
font-weight: 600;
color: #333;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
}
/* 顶部统计卡片 */
.stats-card {
height: 200px;
padding: 20px;
box-sizing: border-box;
}
.stats-card .card-title {
padding: 0 0 8px 0;
border: none;
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.stat-value {
font-size: 32px;
font-weight: bold;
color: #217050;
margin: 10px 0;
line-height: 1.2;
}
.stat-meta {
font-size: 12px;
color: #999;
margin-top: auto;
}
.trend-up {
color: #52c41a;
}
.trend-down {
color: #ff4d4f;
}
/* 图表容器 */
.chart-container {
flex: 1;
min-height: 0;
padding: 10px;
}
/* 统计卡片中的图表容器 */
.stats-card .chart-container {
height: 120px;
min-height: 120px;
flex: none;
margin: 8px 0;
padding: 0;
}
/* 内容区域 - 左右布局 */
.content-left {
grid-column: 1 / 4;
display: grid;
grid-template-rows: 1fr 1fr;
gap: 20px;
min-height: 0;
}
.content-right {
grid-column: 4 / 5;
min-height: 0;
}
/* 左侧图表卡片 */
.content-left .card {
min-height: 0;
}
.content-left .card .chart-container {
flex: 1;
/*min-height: 200px;*/
}
/* 右侧表格样式 */
.content-right {
display: flex;
flex-direction: column;
}
.content-right .el-table {
flex: 1;
height: auto !important;
}
.content-right .card-title {
flex-shrink: 0;
}
/* 表格序号样式 */
.idx {
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
border-radius: 4px;
font-weight: bold;
margin: 0 auto;
}
.idx-rank {
background: linear-gradient(135deg, #217050, #2d8a5f);
color: white;
}
/* 响应式设计 */
@media (max-width: 1400px) {
.dashboard {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 200px 200px 1fr;
}
.stats-card:nth-child(1),
.stats-card:nth-child(2) {
grid-row: 1;
}
.stats-card:nth-child(3),
.stats-card:nth-child(4) {
grid-row: 2;
}
.content-left {
grid-column: 1 / 3;
grid-row: 3;
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr;
}
.content-right {
grid-column: 1 / 3;
grid-row: 4;
}
}
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr;
grid-template-rows: repeat(4, 180px) 1fr 300px;
gap: 15px;
}
.stats-card {
height: 180px;
padding: 15px;
}
.stats-card .chart-container {
height: 100px;
min-height: 100px;
}
.content-left {
grid-column: 1;
grid-row: 5;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
}
.content-right {
grid-column: 1;
grid-row: 6;
min-height: 300px;
}
.stat-value {
font-size: 24px;
}
}
/* Element UI 表格样式重写 */
.el-table {
font-size: 14px;
}
.el-table .el-table__header-wrapper {
background-color: #fafafa;
}
.el-table .el-table__body-wrapper {
max-height: calc(100% - 48px);
overflow-y: auto;
}
.el-table th {
background-color: #fafafa !important;
color: #333;
font-weight: 600;
}
.el-table td {
border-bottom: 1px solid #f0f0f0;
}
.el-table--border .el-table__inner-wrapper::after {
display: none;
}
/* Loading 样式优化 */
.el-loading-mask {
background-color: rgba(255, 255, 255, 0.8);
}
.el-loading-spinner .circular {
width: 32px;
height: 32px;
}
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr; /* 单列布局 */
grid-template-rows: repeat(6, auto); /* 自动高度,6行 */
gap: 15px;
}
/* 所有卡片独占一行 */
.stats-card,
.content-left,
.content-right {
grid-column: 1 !important; /* 强制占满整行 */
grid-row: auto !important; /* 自动行位置 */
height: auto; /* 高度自适应 */
min-height: 180px; /* 最小高度保障 */
}
/* 调整左侧内容区域为垂直堆叠 */
.content-left {
display: flex;
flex-direction: column;
gap: 15px;
}
/* 调整图表容器高度 */
.chart-container {
min-height: 200px;
}
/* 统计卡片调整 */
.stats-card {
padding: 15px;
}
.stats-card .chart-container {
height: 120px;
min-height: 120px;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<div class="dashboard">
<!-- 顶部四个统计卡片 - 高度固定200px -->
<div class="card stats-card">
<div class="card-title">会员数</div>
<div class="stat-value" v-loading="loading.memberNumber">
{{memberNumberData.memberNum}}
<span style="font-size: 14px">&ensp;</span>
</div>
<!-- <div class="stat-meta" v-loading="loading.memberNumber">-->
<!-- 年同比 {{memberNumberData.ratio}}&ensp;-->
<!-- <i :class="memberNumberData.diff >= 0 ? 'el-icon-top trend-up' : 'el-icon-bottom trend-down'"></i>-->
<!-- </div>-->
</div>
<div class="card stats-card">
<div class="card-title">增长趋势</div>
<div class="chart-container" id="growthTrendChart" v-loading="loading.growthTrend"></div>
</div>
<div class="card stats-card">
<div class="card-title">会员占比</div>
<div class="chart-container" id="memberPercentageChart" v-loading="loading.memberPercentage"></div>
</div>
<div class="card stats-card">
<div class="card-title">男女占比</div>
<div class="chart-container" id="memberSexPercentageChart" v-loading="loading.memberSexPercentage"></div>
</div>
<!-- 左侧内容区域 -->
<div class="content-left">
<!-- 工会会员数图表 -->
<div class="card">
<div class="card-title">工会会员数</div>
<div class="chart-container" id="unionMemberChart" v-loading="loading.unionMember"></div>
</div>
<!-- 人员类型图表 -->
<div class="card">
<div class="card-title">人员类型统计</div>
<div class="chart-container" id="personTypeMemberChart" v-loading="loading.personTypeMember"></div>
</div>
</div>
<!-- 右侧表格区域 -->
<div class="card content-right">
<div class="card-title">工会会员明细</div>
<el-table
:data="unionMember"
:header-cell-style="{background:'#FAFAFA'}"
style="width: 100%; height: calc(100% - 40px)"
row-key="id"
v-loading="loading.unionMember"
>
<el-table-column label="序号" width="100px" align="center">
<template scope="{$index}">
<div class="idx idx-rank" v-if="$index<3">{{$index+1}}</div>
<div class="idx" v-else>{{$index+1}}</div>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="分工会" prop="unioncode" show-overflow-tooltip sortable>
<template scope="{row}">{{row.unionname}}</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="会员人数"
prop="value"
show-overflow-tooltip
sortable
width="120px"
></el-table-column>
</el-table>
</div>
</div>
</guava>
</div>
<script nonce="${cspNonce!}">
const chart = {
growthTrendChart: undefined,
memberPercentageChart: undefined,
memberSexPercentageChart: undefined,
unionMemberChart: undefined,
personTypeMemberChart: undefined,
userStateMemberChart: undefined
}
const vue = new Vue({
el: "#app",
data(){
return{
loading: {
memberNumber: false,
growthTrend: false,
memberPercentage: false,
memberSexPercentage: false,
unionMember: false,
personTypeMember: false,
userStateMember: false
},
memberNumberData: {
memberNum: "--",
lastYearMemberNum: "--",
ratio: "0.0%",
diff: 0
},
memberPercentage: "--",
unionMember: []
}
},
methods: {
/**
* 会员数
* @returns {Promise<void>}
*/
async getMemberNumber() {
this.loading.memberNumber = true
this.$axios.post("/platform/member/info/board/memberNumber").then((resp) => {
if (resp.code === 0) {
const {
data: { memberNum, lastYearMemberNum }
} = resp
const diff = memberNum - lastYearMemberNum
const ratio = (lastYearMemberNum ? (Math.abs(diff) / lastYearMemberNum) * 100 : (diff / 1) * 10).toFixed(2) + " %"
this.memberNumberData = { memberNum, lastYearMemberNum, diff, ratio }
this.loading.memberNumber = false
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 增长趋势
* @returns {Promise<void>}
*/
async getGrowthTrend() {
this.loading.growthTrend = true
this.$axios.post("/platform/member/info/board/growthTrend").then((resp) => {
this.loading.growthTrend = false
if (resp.code === 0) {
const { data } = resp
const labels = data.map((v) => v.label)
const values = data.map((v) => v.value)
if (chart.growthTrendChart) {
chart.growthTrendChart.changeData(values)
return
}
chart.growthTrendChart = new G2Plot.TinyArea("growthTrendChart", {
autoFit: true,
data: values,
smooth: true,
// 核心配色方案
color: '#217050', // 主色线
areaStyle: {
fill: 'l(270) 0:#e8f5eb 1:#217050', // 线性渐变填充
opacity: 0.8
},
line: {
color: '#134330', // 深绿色线条
size: 2
},
// 数据点样式
point: {
size: 3,
style: {
fill: '#fff',
stroke: '#217050',
lineWidth: 2
}
},
showContent: true,
tooltip: {
customContent: function (i, data) {
if (labels[i]) {
return labels[i] + "-" + data[0]?.data?.y + "人"
}
return ""
}
}
})
chart.growthTrendChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 会员占比
* @returns {Promise<void>}
*/
async getMemberPercentage() {
this.loading.memberPercentage = true
this.$axios.post("/platform/member/info/board/memberPercentage").then((resp) => {
this.loading.memberPercentage = false
if (resp.code === 0) {
const { data } = resp
this.memberPercentage = data.toFixed(2)
if (chart.memberPercentageChart) {
chart.memberPercentageChart.changeData(data)
return
}
chart.memberPercentageChart = new G2Plot.Liquid("memberPercentageChart", {
outline: {
border: 4,
distance: 8
},
wave: {
length: 128
},
autoFit: true,
percent: data,
color: '#217050',
statistic: {
content: {
style: {
fontSize: 16,
fill: '#fff', // 白色文字
}
}
}
})
chart.memberPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 男女占比
* @returns {Promise<void>}
*/
async getMemberSexPercentage() {
this.loading.memberSexPercentage = true
this.$axios.post("/platform/member/info/board/memberSexPercentage").then((resp) => {
this.loading.memberSexPercentage = false
if (resp.code === 0) {
const { data } = resp
if (chart.memberSexPercentageChart) {
chart.memberSexPercentageChart.changeData(data)
return
}
chart.memberSexPercentageChart = new G2Plot.Pie("memberSexPercentageChart", {
data,
angleField: "value",
colorField: "type",
legend: false,
label: {
type: 'inner',
offset: '-30%',
style: {
fontSize: 14,
fontWeight: 'bold',
fill: '#fff', // 白色文字
textShadow: '0 1px 2px rgba(0,0,0,0.5)' // 增强可读性
},
formatter: (datum) => (datum.percent * 100).toFixed(1)
},
// 交互效果
interactions: [
{ type: 'element-active' },
],
color: ['#217050', '#f0a35c']
})
chart.memberSexPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 各工会会员数
* @returns {Promise<void>}
*/
async getUnionMember() {
this.loading.unionMember = true
this.$axios.post("/platform/member/info/board/unionMember").then((resp) => {
this.loading.unionMember = false
if (resp.code === 0) {
const { chartData, tableData } = resp.data
this.unionMember = tableData
const labels = chartData.map((v) => v.unionname)
const values = chartData.map((v) => v.value)
if (chart.unionMemberChart) {
chart.unionMemberChart.changeData(values)
return
}
chart.unionMemberChart = new G2Plot.Column("unionMemberChart", {
data: chartData,
autoFit: true,
xField: "unionname",
yField: "value",
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.unionMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 根据人员类型查找会员数
* @returns {Promise<void>}
*/
async getPersonTypeMember() {
this.loading.personTypeMember = true
this.$axios.post("/platform/member/info/board/personTypeMember").then((resp) => {
this.loading.personTypeMember = false
if (resp.code === 0) {
const { data } = resp
if (chart.personTypeMemberChart) {
chart.personTypeMemberChart.changeData(data)
return
}
chart.personTypeMemberChart = new G2Plot.Column("personTypeMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.personTypeMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 根据在职状态查找会员数
* @returns {Promise<void>}
*/
async getUserStateMember() {
this.loading.userStateMember = true
this.$axios.post("/platform/member/info/board/userStateMember").then((resp) => {
this.loading.userStateMember = false
if (resp.code === 0) {
const { data } = resp
if (chart.userStateMemberChart) {
chart.userStateMemberChart.changeData(data)
return
}
chart.userStateMemberChart = new G2Plot.Column("userStateMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.userStateMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
initData() {
this.getMemberNumber()
this.getGrowthTrend()
this.getMemberPercentage()
this.getMemberSexPercentage()
this.getUnionMember()
this.getPersonTypeMember()
// this.getUserStateMember()
}
},
mounted() {
this.initData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,718 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.top-col {
background-color: white;
position: relative;
box-sizing: border-box;
padding: 20px;
width: calc((100% - (20px * 3)) / 4);
}
.top-col:not(:last-child),
.center-col:not(:last-child) {
margin-right: 20px;
}
.col-title {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
margin-bottom: 10px;
}
.top-col-member-number {
font-size: 30px;
color: rgba(0, 0, 0, 0.85);
}
.top-col-chart {
height: 80px;
width: 100%;
position: relative;
}
.center-col {
background-color: white;
position: relative;
box-sizing: border-box;
padding: 20px;
width: calc((100% - (20px * 1)) / 2);
}
.idx {
display: flex;
justify-content: center;
align-items: center;
color: rgba(0, 0, 0, 0.85);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #f0f0f0;
font-size: 12px;
margin: 0 auto;
}
.idx-rank {
color: white !important;
background-color: #314659 !important;
}
.el-table__body-wrapper::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.el-table__body-wrapper {
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
overflow-x: hidden;
overflow-y: auto;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-row style="background-color: #f0f2f5" type="flex">
<el-col class="top-col" v-loading="loading.memberNumber">
<div class="col-title">会员数</div>
<div class="top-col-member-number">
{{memberNumberData.memberNum}}
<span style="font-size: 14px">&ensp;</span>
</div>
<div
style="
color: rgba(0, 0, 0, 0.85);
margin-top: 20px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: flex-end;
"
>
年同比 {{memberNumberData.ratio}}&ensp;
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
style="color: #67c23a"
v-if="memberNumberData.diff>=0"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
></path>
</svg>
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
style="color: #f56c6c"
v-else
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
></path>
</svg>
</div>
</el-col>
<el-col class="top-col" v-loading="loading.growthTrend">
<div class="col-title">增长趋势</div>
<div class="top-col-chart" id="growthTrendChart"></div>
</el-col>
<el-col class="top-col" v-loading="loading.memberPercentage">
<div class="col-title">会员占比</div>
<div class="top-col-chart" id="memberPercentageChart" style="position: absolute; height: 120px; right: -10%; bottom: 20px"></div>
</el-col>
<el-col class="top-col" v-loading="loading.memberSexPercentageChart">
<div class="col-title">男女占比</div>
<div class="top-col-chart" id="memberSexPercentageChart" style="position: absolute; height: 120px; right: -10%; bottom: 20px"></div>
</el-col>
</el-row>
<el-row style="background-color: #f0f2f5; margin-top: 20px" type="flex">
<el-col class="center-col" v-loading="loading.unionMember">
<div class="col-title">工会会员数</div>
<div id="unionMemberChart" style="width: 100%; height: 200px"></div>
<el-table
:data="unionMember"
:header-cell-style="{background:'#FAFAFA'}"
height="calc(100vh - 190px - 400px)"
row-key="id"
style="width: 100%; margin-top: 20px"
>
<el-table-column label="序号" width="100px" align="center">
<template scope="{$index}">
<div class="idx idx-rank" v-if="$index<3">{{$index+1}}</div>
<div class="idx" v-else>{{$index+1}}</div>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="分工会" prop="unioncode" show-overflow-tooltip sortable>
<template scope="{row}">{{row.unionname}}</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="会员人数"
prop="value"
show-overflow-tooltip
sortable
width="120px"
></el-table-column>
</el-table>
</el-col>
<el-col class="center-col">
<div class="col-title">在职状态</div>
<div
id="userStateMemberChart"
style="width: 100%; height: calc(50% - 35px); box-sizing: border-box; padding: 30px 10px"
v-loading="loading.userStateMember"
></div>
<div class="col-title">教职工类别</div>
<div
id="personTypeMemberChart"
style="width: 100%; height: calc(50% - 35px); box-sizing: border-box; padding: 30px 10px"
v-loading="loading.personTypeMember"
></div>
</el-col>
</el-row>
</guava>
</div>
<script nonce="${cspNonce!}">
const chart = {
growthTrendChart: undefined,
memberPercentageChart: undefined,
memberSexPercentageChart: undefined,
unionMemberChart: undefined,
personTypeMemberChart: undefined,
userStateMemberChart: undefined
}
new Vue({
el: "#app",
data: {
loading: {
memberNumber: false,
growthTrend: false,
memberPercentage: false,
memberSexPercentage: false,
unionMember: false,
personTypeMember: false,
userStateMember: false
},
memberNumberData: {
memberNum: "--",
lastYearMemberNum: "--",
ratio: "0.0%",
diff: 0
},
memberPercentage: "--",
unionMember: []
},
methods: {
/**
* 会员数
* @returns {Promise<void>}
*/
async getMemberNumber() {
this.loading.memberNumber = true
this.$axios.post("/platform/member/info/board/memberNumber").then((resp) => {
if (resp.code === 0) {
const {
data: { memberNum, lastYearMemberNum }
} = resp
const diff = memberNum - lastYearMemberNum
const ratio = (lastYearMemberNum ? (Math.abs(diff) / lastYearMemberNum) * 100 : (diff / 1) * 10).toFixed(2) + " %"
this.memberNumberData = { memberNum, lastYearMemberNum, diff, ratio }
this.loading.memberNumber = false
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 增长趋势
* @returns {Promise<void>}
*/
async getGrowthTrend() {
this.loading.growthTrend = true
this.$axios.post("/platform/member/info/board/growthTrend").then((resp) => {
this.loading.growthTrend = false
if (resp.code === 0) {
const { data } = resp
const labels = data.map((v) => v.label)
const values = data.map((v) => v.value)
if (chart.growthTrendChart) {
chart.growthTrendChart.changeData(values)
return
}
chart.growthTrendChart = new G2Plot.TinyArea("growthTrendChart", {
autoFit: true,
data: values,
smooth: true,
// 核心配色方案
color: '#217050', // 主色线
areaStyle: {
fill: 'l(270) 0:#e8f5eb 1:#217050', // 线性渐变填充
opacity: 0.8
},
line: {
color: '#134330', // 深绿色线条
size: 2
},
// 数据点样式
point: {
size: 3,
style: {
fill: '#fff',
stroke: '#217050',
lineWidth: 2
}
},
showContent: true,
tooltip: {
customContent: function (i, data) {
if (labels[i]) {
return labels[i] + "-" + data[0]?.data?.y + "人"
}
return ""
}
}
})
chart.growthTrendChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 会员占比
* @returns {Promise<void>}
*/
async getMemberPercentage() {
this.loading.memberPercentage = true
this.$axios.post("/platform/member/info/board/memberPercentage").then((resp) => {
this.loading.memberPercentage = false
if (resp.code === 0) {
const { data } = resp
this.memberPercentage = data.toFixed(2)
if (chart.memberPercentageChart) {
chart.memberPercentageChart.changeData(data)
return
}
chart.memberPercentageChart = new G2Plot.Liquid("memberPercentageChart", {
outline: {
border: 4,
distance: 8
},
wave: {
length: 128
},
autoFit: true,
percent: data,
color: '#217050',
statistic: {
content: {
style: {
fontSize: 16,
fill: '#fff', // 白色文字
}
}
}
})
chart.memberPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 男女占比
* @returns {Promise<void>}
*/
async getMemberSexPercentage() {
this.loading.memberSexPercentage = true
this.$axios.post("/platform/member/info/board/memberSexPercentage").then((resp) => {
this.loading.memberSexPercentage = false
if (resp.code === 0) {
const { data } = resp
if (chart.memberSexPercentageChart) {
chart.memberSexPercentageChart.changeData(data)
return
}
chart.memberSexPercentageChart = new G2Plot.Pie("memberSexPercentageChart", {
data,
angleField: "value",
colorField: "type",
legend: false,
label: {
type: 'inner',
offset: '-30%',
style: {
fontSize: 14,
fontWeight: 'bold',
fill: '#fff', // 白色文字
textShadow: '0 1px 2px rgba(0,0,0,0.5)' // 增强可读性
},
formatter: (datum) => (datum.percent * 100).toFixed(1)
},
// 交互效果
interactions: [
{ type: 'element-active' },
],
color: ['#217050', '#f0a35c']
})
chart.memberSexPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 各工会会员数
* @returns {Promise<void>}
*/
async getUnionMember() {
this.loading.unionMember = true
this.$axios.post("/platform/member/info/board/unionMember").then((resp) => {
this.loading.unionMember = false
if (resp.code === 0) {
const { chartData, tableData } = resp.data
this.unionMember = tableData
const labels = chartData.map((v) => v.unionname)
const values = chartData.map((v) => v.value)
if (chart.unionMemberChart) {
chart.unionMemberChart.changeData(values)
return
}
chart.unionMemberChart = new G2Plot.Column("unionMemberChart", {
data: chartData,
autoFit: true,
xField: "unionname",
yField: "value",
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.unionMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 根据人员类型查找会员数
* @returns {Promise<void>}
*/
async getPersonTypeMember() {
this.loading.personTypeMember = true
this.$axios.post("/platform/member/info/board/personTypeMember").then((resp) => {
this.loading.personTypeMember = false
if (resp.code === 0) {
const { data } = resp
if (chart.personTypeMemberChart) {
chart.personTypeMemberChart.changeData(data)
return
}
chart.personTypeMemberChart = new G2Plot.Column("personTypeMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.personTypeMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 根据在职状态查找会员数
* @returns {Promise<void>}
*/
async getUserStateMember() {
this.loading.userStateMember = true
this.$axios.post("/platform/member/info/board/userStateMember").then((resp) => {
this.loading.userStateMember = false
if (resp.code === 0) {
const { data } = resp
if (chart.userStateMemberChart) {
chart.userStateMemberChart.changeData(data)
return
}
chart.userStateMemberChart = new G2Plot.Column("userStateMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.userStateMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
initData() {
this.getMemberNumber()
this.getGrowthTrend()
this.getMemberPercentage()
this.getMemberSexPercentage()
this.getUnionMember()
this.getPersonTypeMember()
this.getUserStateMember()
}
},
mounted() {
this.initData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,116 @@
const COMMON_QUERY = {
template: /*language=HTML*/ `
<search @search="doSearch">
<search-item label="姓名/工号">
<el-select
clearable
v-model="pageForm.userIds"
filterable
remote
collapse-tags
placeholder="请输入姓名或工号"
:remote-method="queryUser"
@change="doSearch"
style="width: 100%"
multiple
>
<el-option v-for="o in userList" :label="o.username + '(' + o.loginname + ')'" :value="o.id"
:key="o.id"></el-option>
</el-select>
<!-- <el-input placeholder="请输入内容" clearable v-model="pageForm.searchKeyword"></el-input>-->
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态" v-if="!query_disable">
<dict-select v-model="pageForm.userStates" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="教职工类别" v-if="!query_disable">
<dict-select v-model="pageForm.personTypes" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBys" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE" multiple collapse-tags></dict-select>
</search-item>
</search>
`,
props: {
query_disable: {
type: Boolean,
default: false
}
},
mixins: [initTableMixins],
data() {
return{
userList: [],
unions: [],
units: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
userIds: [],
userStates: [],
personTypes: [],
preparedBys: [],
}
}
},
methods: {
async queryUser(val) {
const resp = await $.get("/open/common/userOptions", {query: val})
this.userList = resp.data
},
doSearch(){
const pageForm = clone(this.pageForm)
pageForm.userIds = JSON.stringify(this.pageForm.userIds)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
this.$emit('search', pageForm)
},
async initData(){
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN")) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unions = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
})
}
},
async flushUnits(){
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
}
},
async created() {
this.initData()
}
}
@@ -0,0 +1,316 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.search-other {
display: flex;
align-items: center;
margin-top: 20px;
}
.search-other-label {
width: 90px;
min-width: 90px;
color: rgb(100, 100, 100);
margin-right: 10px;
flex-shrink: 0;
}
.search-other > div {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: -6px;
}
.search-other .el-tag {
margin-right: 10px;
margin-bottom: 6px;
cursor: pointer;
}
.search-other .el-link {
margin-bottom: 6px;
margin-right: 10px;
}
.popover-container {
display: flex;
align-items: center;
line-height: 22px;
}
.popover-icon {
margin-right: 6px;
}
.popover-icon-waning {
color: #e6a23c;
font-size: 24px !important;
font-family: element-icons !important;
}
.popover-icon-waning:before {
content: "\e7a3";
}
.popover-footer {
text-align: right;
margin-top: 20px;
}
.el-popover__reference:nth-of-type(1) {
margin-left: 10px;
margin-right: 5px;
}
</style>
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search" query_disable></common-query>
</el-card>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="工号开头">
<el-input v-model="pageForm.startLoginNames" maxLength="100"
placeholder="多个请用英文逗号分隔"></el-input>
</search-item>
<search-item label="工号结尾">
<el-input v-model="pageForm.endLoginNames" maxLength="100"
placeholder="多个请用英文逗号分隔"></el-input>
</search-item>
</search>
<div class="search-other mt20">
<div class="search-other-label">在职状态</div>
<div>
<el-tag
style="margin-right: 10px;cursor: pointer"
v-for="item in dict.type.USER_STATE"
:key="item.code"
:type="item.name"
:effect="pageForm.userStates.includes(item.name)?'dark':'plain'"
@click="tagClick('userStates',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="dict.type.USER_STATE?.length && pageForm.userStates.length"
:underline="false"
@click="pageForm.userStates=[]; doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.userStates = dict.type.USER_STATE?.map(p=>p.code); doSearch()"
type="success">全部
</el-link>
</div>
</div>
<div class="search-other mt20">
<div class="search-other-label">教职工类别</div>
<div>
<el-tag
style="margin-right: 10px;cursor: pointer"
v-for="item in dict.type.USER_PERSON_TYPE"
:key="item.code"
:type="item.name"
:effect="pageForm.personTypes.includes(item.name)?'dark':'plain'"
@click="tagClick('personTypes',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="dict.type.USER_PERSON_TYPE?.length && pageForm.personTypes.length"
:underline="false"
@click="pageForm.personTypes=[]; doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.personTypes = dict.type.USER_PERSON_TYPE?.map(p=>p.code); doSearch()"
type="success">全部
</el-link>
</div>
</div>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="数据列表">
<el-button size="mini" icon="el-icon-s-tools" type="primary" @click="onBirthday">根据身份证设置生日</el-button>
<el-popover
v-for="item in popoverConfigs"
:key="item.text"
placement="left"
width="360"
title="温馨提醒"
v-model="item.visible">
<div class="popover-container">
<div class='popover-icon popover-icon-waning'></div>
<div>
<p>
<i class='el-icon-s-help' style='margin-right: 6px;'></i>
<span>如果先清空已有数据,后更新,请选择</span>
<span style='color: red'>更新</span>
<span style='font-weight: bolder'>(这将清空目前所有的会员,请谨慎操作!)</span>
</p>
<p class="mt5">
<i class='el-icon-s-help' style='margin-right: 6px;'></i>
<span>如果追加或更新数据,请选择</span>
<span style='color: red'>追加</span>
</p>
</div>
</div>
<div class="popover-footer">
<el-button size="mini" type="text" @click="item.visible = false">取消</el-button>
<el-button type="warning" size="mini" @click="handlePopoverAction(item, true)">追加</el-button>
<el-button type="primary" size="mini" @click="handlePopoverAction(item, false)">更新</el-button>
</div>
<el-button slot="reference" size="mini" icon="el-icon-s-tools" type="primary">{{ item.text }}</el-button>
</el-popover>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
</el-table-column>
<el-table-column label="操作" fixed="right" width="100">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
'member-info': MEMBER_INFO,
'common-query': COMMON_QUERY,
},
dicts: ['USER_PERSON_TYPE', 'USER_STATE'],
data() {
return {
visible: false,
pageForm: {
personTypes: [],
userStates: [],
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
],
personTypeOptions: [],
popoverConfigs: [
{text: '设置会员', func: this.onMember, visible: false},
{text: '设置福利会员', func: this.onWelfare, visible: false},
],
}
},
methods: {
handlePopoverAction(item, isAppend) {
item.func(isAppend)
item.visible = false
document.activeElement.blur()
},
onBirthday() {
this.$confirm("您确定要根据身份证号设置出生日期吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/member/info/dataManage/setBirthdayByIdCard").then((res) => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
})
},
onMember(append) {
const pageForm = clone(this.pageForm)
pageForm.personTypes = JSON.stringify(pageForm.personTypes)
pageForm.userStates = JSON.stringify(pageForm.userStates)
this.$axios.post("/platform/member/info/dataManage/setMemberByCnd", {
"pageForm": JSON.stringify(pageForm),
"append": append
}).then((res) => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
},
onWelfare(append) {
const pageForm = clone(this.pageForm)
pageForm.personTypes = JSON.stringify(pageForm.personTypes)
pageForm.userStates = JSON.stringify(pageForm.userStates)
pageForm.append = append
this.$axios.post("/platform/member/info/dataManage/setWelfareMemberByCnd", {
"pageForm": JSON.stringify(pageForm),
"append": append
}).then((res) => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
},
onView(row) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(row.id)
})
},
tagClick(key, val) {
const index = this.pageForm[key]?.findIndex(v => v === val)
if (index > -1) {
this.pageForm[key].splice(index, 1)
} else {
this.pageForm[key].push(val)
}
this.doSearch()
},
search(pageForm) {
if (pageForm) {
this.pageForm = {...this.pageForm, ...pageForm}
}
this.doSearch()
},
pageData() {
const pageForm = clone(this.pageForm)
pageForm.personTypes = JSON.stringify(pageForm.personTypes)
pageForm.userStates = JSON.stringify(pageForm.userStates)
this.$axios.post(loc() + "/pageData", pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,68 @@
const ARCHIVE_MEMBER = {
template: `
<el-dialog
:visible.sync="archiveDialogVisible"
width="30%">
<div style="margin-bottom: 30px">
<el-divider class="labelYear">{{labelYear}}</el-divider>
</div>
<el-form :model="formData" ref="form" :rules="formRules" label-width="80px">
<el-form-item prop="year" label="备份年份" style="align-content: center">
<el-date-picker
placeholder="请选择备份年份"
value-format="yyyy"
v-model="formData.year"
type="year" style="width: 100%"
:picker-options="pickerOptions">
</el-date-picker>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="archiveDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="archive">确 定</el-button>
</span>
</el-dialog>
`,
mixins: [initTableMixins],
data() {
return {
archiveDialogVisible: false,
formRules: {
year: [{ required: true, message: "请选择备份年份", trigger: ["blur", "change"] }]
},
pickerOptions: {
disabledDate(time) {
return time.getFullYear() > new Date().getFullYear() - 1
}
}
// labelYear: "把当前数据备份成为" + (new Date().getFullYear() - 1) + "年份的历史数据"
}
},
computed: {
labelYear() {
return "把当前数据备份成为以往年份的历史数据"
}
},
methods: {
async archive() {
this.$confirm("您确定要将当前数据备份为选择年份吗?已备份的数据将会被覆盖", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: async (a, b) => {
if ("confirm" === a) {
//确认后再执行
const resp = await this.$axios.post("/platform/member/info/group/archive", { year: this.formData.year })
if (resp.code === 0) {
this.archiveDialogVisible = false
this.$message.success("操作成功")
} else {
this.$message.error(resp.msg)
}
}
}
})
}
}
}
@@ -0,0 +1,238 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="会员列表">
<el-button type="primary" size="small" icon="el-icon-upload2" @click="openImport">导入会员</el-button>
<el-button
type="primary"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"
size="small"
icon="el-icon-time"
@click="openArchive"
>
备份历史会员
</el-button>
<el-button type="primary" size="small" icon="el-icon-download" @click="exportMember">会员档案导出</el-button>
<el-popover
placement="bottom"
trigger="click"
width="200">
<div style="padding:4px 0;border-bottom:1px solid #eee;">
<el-button size="mini" @click="checkAll">全选</el-button>
<el-button size="mini" @click="invertCheck">反选</el-button>
</div>
<div style="max-height:40vh;overflow-y:auto;padding:6px 0;">
<el-checkbox-group v-model="checkedFields">
<el-checkbox
v-for="f in tableColumns"
:key="f.prop"
:label="f.prop"
style="display:block;margin:6px 0;">
{{ f.label }}
</el-checkbox>
</el-checkbox-group>
</div>
<el-button
slot="reference"
type="text"
icon="el-icon-s-operation"
size="small"
style="margin-left:12px;">
列设置
</el-button>
</el-popover>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id" @sort-change="pageOrder" :size="tableSize" class="vi-table">
<el-table-column
align="center"
header-align="center"
type="index"
fixed="left"
:index="indexMethod"
label="序号"
width="80px"
></el-table-column>
<el-table-column
show-overflow-tooltip
align="center"
header-align="center"
v-for="column in tableColumns"
v-if="checkedFields.includes(column.prop)"
:label="column.label"
:fixed="column.fixed"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
min-width="50"
></el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center" label="操作" fixed="right" width="100px">
<template scope="scope">
<el-button size="mini" type="primary" @click="openView(scope.row.id)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-info ref="infoRef"></member-info>
</template>
</guava>
<archive-member ref="archiveMemberRef"></archive-member>
<el-dialog title="会员导入" :visible.sync="importDialog" width="50%" :close-on-click-modal="false" :close-on-press-escape="false">
<file-import
ref="viewImport"
is_show_radio
temp_url="/platform/member/info/group/downloadMemberTemplate"
post_url="/platform/member/info/group/importMember"
@flush="successImport"
></file-import>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("archiveMember.js"){}#-->
<!--#include("../common/commonQuery.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageForm: {},
tableColumns: [
{ prop: "loginname", label: "工号", width: 120, fixed: "left"},
{ prop: "username", label: "姓名", width: 120, fixed: "left" },
{ prop: "sex", label: "性别", width: 120},
{ prop: "birthday", label: "出生年月", width: 120, sortable: true },
{ prop: "nationality", label: "国籍", width: 120, sortable: true, checked: 0 },
{ prop: "nation", label: "民族", width: 120, sortable: true},
{ prop: "mobile", label: "联系电话", width: 120 },
{ prop: "political", label: "政治面貌", width: 120, sortable: true},
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "编制类别", width: 120, sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true, checked: 0 },
{ prop: "unionName", label: "所属工会", width: 120, sortable: true },
{ prop: "unitName", label: "所属单位", width: 120, sortable: true },
{ prop: "idCardType", label: "证件类型", width: 120, sortable: true, checked: 0 },
{ prop: "idCard", label: "证件号码", width: 120, sortable: true, checked: 0 },
{ prop: "marriage", label: "婚姻状况", width: 120, sortable: true, checked: 0 },
{ prop: "jobCategory", label: "岗位类别", width: 120, sortable: true, checked: 0 },
{ prop: "professionalTitle", label: "职称", width: 120, sortable: true, checked: 0 },
{ prop: "professionalLevel", label: "职级", width: 120, sortable: true, checked: 0 },
{ prop: "employeeSource", label: "职工来源", width: 120, sortable: true, checked: 0 },
{ prop: "administrativeLevel", label: "行政级别(管理岗位)", width: 120, sortable: true, checked: 0 },
{ prop: "positionSeries", label: "岗位系列", width: 120, sortable: true, checked: 0 },
{ prop: "positionLevel", label: "岗级", width: 120, sortable: true, checked: 0 },
{ prop: "administrativePositionLevel", label: "行政岗级", width: 120, sortable: true, checked: 0 },
{ prop: "arrivalAtSchoolDate", label: "来校时间", width: 120, sortable: true, checked: 0 },
{ prop: "teachingTime", label: "从教年月", width: 120, sortable: true, checked: 0 },
{ prop: "expectedLeaveSchoolDate", label: "预计/最后离校时间", width: 120, sortable: true, checked: 0 },
],
checkedFields: [],
importDialog: false
}
},
components: {
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime()),
"archive-member": ARCHIVE_MEMBER,
"member-info": MEMBER_INFO,
"common-query": COMMON_QUERY,
},
methods: {
openImport() {
this.importDialog = true
},
successImport() {
if(this.$refs.viewImport.$data.errorInfoData.errorCount === 0) {
this.importDialog = false
}
this.pageData()
},
exportMember() {
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
const data = this.tableColumns.filter(item => this.checkedFields.includes(item.prop)).map(item => {
return {prop: item.prop, label: item.label}
})
pageForm.columns = JSON.stringify(data)
this.$downLoad(loc() + "/exportMember", pageForm)
},
openArchive() {
this.$refs.archiveMemberRef.archiveDialogVisible = true
},
openView(userId) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(userId)
})
},
search(pageForm) {
this.pageForm = {
...this.pageForm,
...pageForm,
}
this.pageData()
},
pageData() {
this.tableLoading = true
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
this.$axios.post(loc() + "/pageData", pageForm)
.then((data) => {
if (data.code === 0) {
this.tableData = data.data.list
this.pageForm.totalCount = data.data.totalCount
} else {
this.$message.error(data.msg)
}
})
.finally(() => {
this.tableLoading = false
})
},
checkAll() {
this.checkedFields = this.tableColumns.map(c => c.prop);
},
invertCheck() {
const all = this.tableColumns.map(c => c.prop);
this.checkedFields = all.filter(p => !this.checkedFields.includes(p));
}
},
computed: {
showColumns() {
return this.tableColumns.filter(c => this.checkedFields.includes(c.prop));
}
},
created() {
this.checkedFields = this.tableColumns.filter(c => c.checked !== 0).map(c => c.prop);
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,171 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
type="year"
placeholder="请选择年度"
></el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="模糊查询">
<member-cnd @cnd="(v)=>pageForm={...pageForm,...v}"></member-cnd>
</search-item>
<search-item label="所属工会">
<el-select
@change="flushUnits"
@clear="flushUnits"
clearable
filterable
placeholder="请选择所属工会"
style="width: 100%"
v-model="pageForm.unionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%" v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch" code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch" code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select
v-model="pageForm.preparedBy"
placeholder="请选择编制类别"
@change="doSearch"
code="USER_PREPARED_BY_TYPE"
></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="用户列表">
<el-button icon="el-icon-printer" class="m10" type="primary" size="small" @click="doExportByUnion">按分工会导出</el-button>
<el-button icon="el-icon-printer" class="m10" type="primary" size="small" @click="doExport">导出</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" class="vi-table" ref="table" row-key="id" style="width: 100%">
<el-table-column
align="center"
header-align="center"
type="index"
:index="indexMethod"
label="序号"
width="80px"
></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
></el-table-column>
<el-table-column label="操作" width="100px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info/memberInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
dicts: ["USER_STATE", "USER_PERSON_TYPE", "MEMBER_CHANGE_TYPE"],
data() {
return {
pageForm: {
year: new Date().getFullYear() - 1 + "",
memberSearchName: "",
memberSearchKeyWord: ""
},
userId: "",
unions: [],
units: [],
tableColumns: [
{ prop: "loginname", label: "工号" },
{ prop: "username", label: "姓名" },
{ prop: "sex", label: "性别" },
{ prop: "mobile", label: "联系电话" },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true }
]
}
},
components: {
"member-cnd": httpVueLoader("/components/module/member/MemberCnd.vue?v=" + new Date().getTime()),
"member-info": MEMBER_INFO
},
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(row.id)
})
},
doExportByUnion() {
this.$downLoad("/platform/member/info/history/doExportByUnion", { year: this.pageForm.year })
},
doExport() {
this.$downLoad("/platform/member/info/history/doExport", this.pageForm)
},
async initData() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.unions = await this.$businessTool.listUnion(this.pageForm.unionId)
this.units = await this.$businessTool.listUnit()
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
this.units = await this.$businessTool.listUnit(this.$store.state.user.union.id)
}
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
}
}
},
created() {
this.pageData()
this.initData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,236 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="劳模列表">
<el-select v-model="pageForm.memberState" placeholder="会员筛选" clearable
style="width: 120px" @change="doSearch" class="mr10" size="small">
<el-option label="全部会员" value="all"></el-option>
<el-option label="会员" value="true"></el-option>
<el-option label="非会员" value="false"></el-option>
</el-select>
<el-select v-model="pageForm.welfareMemberState" placeholder="福利会员筛选" clearable
style="width: 120px" @change="doSearch" class="mr10" size="small">
<el-option label="全部福利会员" value="all"></el-option>
<el-option label="福利会员" value="true"></el-option>
<el-option label="非福利会员" value="false"></el-option>
</el-select>
<el-button size="small" @click="batchDelete" type="danger">
批量取消劳模
</el-button>
<!--<el-button size="small" @click="openImport" type="primary">
导入
</el-button>-->
<el-button size="small" @click="doExport" type="primary">
导出
</el-button>
</table-tool>
<el-table ref="table" :data="tableData" style="width: 100%" row-key="id" @sort-change="pageOrder"
:size="tableSize" @selection-change="tableHandleSelectionChange">
<el-table-column type="selection" :reserve-selection="true"></el-table-column>
<el-table-column align="center" header-align="center" type="index"
:index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template v-if="column.prop==='member'" scope="{row}">
<span v-if="row.member==1" class="text-success ">
<i class="fa fa-circle ml5"></i>
</span>
<span v-else class="text-danger">
<i class="fa fa-circle ml5"></i>
</span>
</template>
<template v-else-if="column.prop==='welfareMember'" scope="{row}">
<span v-if="row.welfareMember==1" class="text-success ">
<i class="fa fa-circle ml5"></i>
</span>
<span v-else class="text-danger">
<i class="fa fa-circle ml5"></i>
</span>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="180px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row.id)">查看</el-button>
<el-button size="mini" type="danger" @click="doDelete(row.id)">取消劳模</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<member-info ref="memberInfoRef" :id="userId"></member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/info/memberInfo.js"){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
data: {
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
threeUnitId: '',
unionGroupId: '',
personType: '',
userState: '',
memberState: '',
welfareMemberState: ''
},
unions: [],
units: [],
tableColumns: [
{prop: 'loginname', label: '工号'},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别'},
{prop: 'mobile', label: '联系电话'},
{prop: 'personType', label: '教职工类别'},
{prop: 'userState', label: '在职状态'},
{prop: 'unionName', label: '所属工会'},
{prop: 'unitName', label: '所属单位'},
{prop: 'member', label: '是否会员'},
{prop: 'welfareMember', label: '是否福利员'},
],
checkUsers: [],
userId: '',
},
components: {
"member-info": MEMBER_INFO,
},
methods: {
openView(userId) {
this.userId = userId
this.$refs.guava.view()
this.$nextTick(() => {
this.$refs.memberInfoRef.findOne()
})
},
openImport() {
},
doExport() {
this.$downLoad('/platform/member/modelWorker/manage/doExport', this.pageForm)
},
tableHandleSelectionChange(val) {
this.checkUsers = val;
},
batchDelete() {
if (!this.checkUsers.length) {
this.$message.warning("请先勾选需要取消劳模身份的数据!")
return
}
this.$confirm('您确定要取消这些教工的劳模身份吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const userIds = this.checkUsers.map(obj => obj.id);
this.$axios.post('/platform/member/modelWorker/manage/cancelModelWorker', {userIds: JSON.stringify(userIds)} )
.then((res) => {
if (res.code === 0) {
this.pageData()
this.$refs.table.clearSelection();
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
})
},
doDelete(userId) {
this.$confirm('您确定要取消该教工的劳模身份吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.checkUsers = []
this.checkUsers.push(userId)
this.$axios.post('/platform/member/modelWorker/manage/cancelModelWorker', {userIds: JSON.stringify(this.checkUsers)})
.then((res) => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
})
},
initData() {
const resp = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"]) ? this.pageForm.unionId : this.$store.state.user.union.id
this.$businessTool.listUnion(resp).then(data => {
this.unions = data
})
this.pageData()
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then(data => {
this.units = data
})
}
}
},
created() {
this.initData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,104 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<member-audit-table ref="tableRef" @open-change-view="openChangeInfo" @open-approval="openApproval"
@open-view="openView"></member-audit-table>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #public>
<member-audit-change-info ref="memberAuditChangeInfoViewRef"></member-audit-change-info>
<div v-if="showApprovalForm">
<el-form :model="formData" ref="approvalFormRef" label-position="left" label-width="80px">
<el-form-item label="审核意见" prop="approvalOpinion" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.approvalOpinion"></user-opinion-textarea>
</el-form-item>
<el-form-item label="审核说明" prop="approvalRemark">
<el-input v-model="formData.approvalRemark" type="textarea" :rows="4" placeholder="请输入审核说明"></el-input>
</el-form-item>
<el-form-item label="电子签名" prop="approvalSignature" :rules="[{required:false,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.approvalSignature"></pc-signature>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button plain @click="$refs.guava.index()">取消</el-button>
<el-button type="danger" @click="doApproval('BACK')">退回重新填写</el-button>
<el-button type="danger" @click="doApproval('REJECT')">拒绝</el-button>
<el-button type="primary" @click="doApproval('PASS')">同意</el-button>
</el-row>
</div>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/audit/memberAuditTable.js"){}#-->
<!--#include("../../common/audit/memberAuditRecord.js"){}#-->
<!--#include("../../common/audit/memberAuditChangeInfo.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data: {
showApprovalForm: false,
},
components: {
"member-audit-table": MEMBER_AUDIT_TABLE,
"member-audit-record": MEMBER_AUDIT_RECORD,
"member-audit-change-info": MEMBER_AUDIT_CHANGE_INFO,
"member-info": MEMBER_INFO,
},
methods: {
doApproval(approvalType) {
this.formData.bpmTaskApprovalType = approvalType
this.$refs.approvalFormRef.validate((valid) => {
if (valid) {
this.$axios
.post(loc() + "/approval", {
approval: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
}
})
},
openApproval(data) {
this.$refs.guava.public(() => {
this.showApprovalForm = true
this.formData = data.approvalParam
this.$refs.memberAuditChangeInfoViewRef.onOpen({recordId: data.id, userId: data.userId})
})
},
openView(userId){
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(userId)
})
},
openChangeInfo(data){
this.$refs.guava.public(() => {
this.showApprovalForm = false
this.$refs.memberAuditChangeInfoViewRef.onOpen({recordId: data.id, userId: data.userId})
})
},
doSearch() {
this.$refs.tableRef.doSearch()
},
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,93 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<member-manage-query ref="queryRef" @query-ready="onQueryReady"></member-manage-query>
<member-manage-table ref="tableRef" v-if="isQueryReady" @refresh="tableReady" @change-member="changeMember"
@view-member="viewMember" @add-member="addMember" @refresh-table="changeSuccess"></member-manage-table>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #edit>
<member-apply :admin-operate="true"></member-apply>
</template>
<template #public>
<member-change :id="id" :url="url" ref="memberChangeRef"
@submit-ready="changeSuccess"></member-change>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/manage/memberManageQuery.js"){}#-->
<!--#include("../../common/manage/memberManageTable.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../../common/apply/memberApply.js"){}#-->
<!--#include("../../common/change/memberChange.js"){}#-->
const vue = new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data: {
id: '',
url:'',
username: '',
isQueryReady: false,
hasShownMessage: false
},
components: {
"member-manage-query": MEMBER_MANAGE_QUERY,
"member-manage-table": MEMBER_MANAGE_TABLE,
"member-info": MEMBER_INFO,
"member-apply": MEMBER_APPLY,
"member-change": MEMBER_CHANGE,
},
methods: {
changeMember(data){
this.id = data.id
this.url = '/platform/member/schoolUnion/manage/list/generalMemberChange'
this.$refs.guava.public()
this.$nextTick(()=>{
this.$refs.memberChangeRef.init()
})
},
viewMember(val){
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(val)
})
},
addMember(){
this.$refs.guava.edit()
},
onQueryReady(pageForm) {
this.isQueryReady = true;
this.$nextTick(() => {
if (this.$refs.tableRef) {
this.$refs.tableRef.pageForm = pageForm
this.$refs.tableRef.pageData();
}
})
},
tableReady(pageForm){
this.$refs.queryRef.pageForm = pageForm
},
changeSuccess(){
this.$refs.guava.index(() => {
this.$refs.tableRef.pageData()
})
}
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,51 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<member-record @open-view="openView" @open-change-info="openChangeInfo"></member-record>
</template>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #public>
<member-audit-change-info ref="memberAuditChangeInfoRef" is_default_url></member-audit-change-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../common/record/memberRecord.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
<!--#include("../../common/audit/memberAuditChangeInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
store,
components: {
"member-record": MEMBER_RECORD,
"member-info": MEMBER_INFO,
"member-audit-change-info": MEMBER_AUDIT_CHANGE_INFO
},
data: {
userId: ''
},
methods: {
openChangeInfo(row) {
this.$refs.guava.public(() => {
this.$refs.memberAuditChangeInfoRef.onOpen({recordId: row.id, userId: row.userId})
})
},
openView(data) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(data)
})
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,375 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="名单事项">
<el-select clearable filterable placeholder="请选择" style="width: 100%"
@change="doSearch"
v-model="pageForm.verificationProjectId">
<el-option :key="item.id" :label="item.projectName" :value="item.id"
v-for="item in verificationList"></el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select @change="doSearch" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="分工会列表">
<template v-if="projectInfo && projectInfo.welfareJson && projectInfo.welfareJson.length > 0">
<el-button type="primary" size="small" @click="showWelfareUserInfo">查看各工会福利上报情况</el-button>
</template>
<el-button type="primary" size="small" @click="doExportByPageDataForExcel">导出页面数据</el-button>
<el-button type="primary" size="small" @click="exportChangeType('userState')">导出在职状态变更数</el-button>
<el-button type="primary" size="small" @click="exportChangeType('restore')">导出入会人数</el-button>
<el-button type="primary" size="small" @click="exportChangeType('withdrawal')">导出退会人数</el-button>
<el-button type="primary" size="small" @click="exportChangeType('member')">导出最终会员数</el-button>
<el-button type="primary" size="small" @click="exportChangeType('welfareMember')">导出最终福利会员数</el-button>
<el-button type="primary" size="small" @click="exportExcel">导出名单事项核对记录</el-button>
</table-tool>
<el-table v-if="tableData" :data="tableData" border show-summary>
<el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column label="工会名称" prop="unionName"></el-table-column>
<el-table-column label="需核对人数" prop="allNum"></el-table-column>
<el-table-column label="变更总人数" prop="changeNum"></el-table-column>
<el-table-column label="在职状态变更数" prop="userStateNum">
<template slot-scope="scope">
<el-link @click="openUserState(scope.row)" type="primary">{{ scope.row.userStateNum }}</el-link>
</template>
</el-table-column>
<el-table-column label="入会人数" prop="restoreNum">
<template slot-scope="scope">
<el-link @click="openRestore(scope.row)" type="primary">{{ scope.row.restoreNum }}</el-link>
</template>
</el-table-column>
<el-table-column label="退会人数" prop="withdrawalNum">
<template slot-scope="scope">
<el-link @click="openWithdrawal(scope.row)" type="primary">{{ scope.row.withdrawalNum }}</el-link>
</template>
</el-table-column>
<el-table-column label="最终会员数" prop="lastMemberNum">
<template slot-scope="scope">
<el-link @click="openLastMember(scope.row)" type="primary">{{ scope.row.lastMemberNum }}</el-link>
</template>
</el-table-column>
<el-table-column label="最终福利会员数" prop="lastWelfareMemberNum">
<template slot-scope="scope">
<el-link @click="openLastWelfareMember(scope.row)" type="primary">{{ scope.row.lastWelfareMemberNum }}</el-link>
</template>
</el-table-column>
<el-table-column label="分工会提交次数" prop="branchUnionSubmitNum"></el-table-column>
<el-table-column label="分工会提交状态" prop="branchUnionSubmit">
<template slot-scope="scope">
<el-tag size="mini" v-if="scope.row.branchUnionSubmit" type="success">已提交</el-tag>
<el-tag size="mini" v-else type="danger">未提交</el-tag>
</template>
</el-table-column>
<el-table-column label="反馈状态" prop="isFeedback">
<template slot-scope="scope">
<el-tag size="mini" v-if="scope.row.isFeedback" type="success">已反馈</el-tag>
<el-tag size="mini" v-else type="danger">未反馈</el-tag>
</template>
</el-table-column>
<el-table-column label="当前状态" prop="status"></el-table-column>
<el-table-column label="操作" width="280">
<template slot-scope="scope">
<el-button @click="viewUser(scope.row)" type="primary" size="mini">查看</el-button>
<el-button @click="openHandle(scope.row)" type="primary" size="mini"
v-if="!scope.row.isFeedback && scope.row.branchUnionSubmit !=0
&& scope.row.branchUnionSubmitNum !== scope.row.schoolUnionSubmitNum">审核</el-button>
<el-button @click="viewFeedback(scope.row)" type="primary" size="mini" v-if="scope.row.isFeedback">反馈结果</el-button>
<el-button @click="doRollback(scope.row)" type="danger" size="mini"
v-if="!scope.row.isRollback && scope.row.isFeedback">退回</el-button>
</template>
</el-table-column>
</el-table>
<el-empty v-else :image-size="200"></el-empty>
</el-card>
</template>
<template #edit>
<school-view-handle ref="schoolViewHandleRef" :verification-project-id="pageForm.verificationProjectId"
@open-change="openChange" :union-name="unionName" @success-submit="successSubmit"></school-view-handle>
</template>
<template #view>
<view-change-type-user ref="viewChangeTypeUserRef" :label-name="labelName"></view-change-type-user>
</template>
<template #public>
<table-tool>
<el-button size="small" type="primary" icon="el-icon-plus" @click="welfareChooseNumExport">导出数据</el-button>
</table-tool>
<el-table :data="welfareTableData" class="vi-table" ref="table" style="width: 100%" show-summary>
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column" :prop="column"
align="center" header-align="center" min-width="100px"
show-overflow-tooltip v-for="column in welfareTableHeader">
</el-table-column>
</el-table>
</template>
</guava>
<el-dialog title="反馈结果" :visible.sync="feedbackDialog" width="50%" append-to-body>
<el-descriptions :column="2" border>
<el-descriptions-item label="事项名称">{{ viewData.projectName }}</el-descriptions-item>
<el-descriptions-item label="工会名称">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="反馈日期">{{ viewData.feedbackDate }}</el-descriptions-item>
<el-descriptions-item label="反馈人数">{{ viewData.feedbackNum }}</el-descriptions-item>
<template v-if="viewData.welfareJson">
<el-descriptions-item span="2" label="福利选择人数">
<el-table :data="viewData.welfareJson" border size="small">
<el-table-column label="福利名称" prop="welfareName"></el-table-column>
<el-table-column label="备注" prop="remark"></el-table-column>
<el-table-column label="选择人数" prop="chooseNumber"></el-table-column>
</el-table>
</el-descriptions-item>
</template>
<el-descriptions-item span="2" label="核对时间">{{ viewData.startDate + '至' + viewData.endDate }}</el-descriptions-item>
<el-descriptions-item span="2" label="内容及要求" span="2">{{ viewData.content }}</el-descriptions-item>
<el-descriptions-item span="2" label="反馈附件">
<file-preview :files="viewData.feedbackFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
</el-dialog>
<el-dialog :visible.sync="memberChangeDialog" width="80%" append-to-body>
<member-change ref="memberChangeRef" :id="userId" :url="url" show-close
@submit-ready="memberChangeDialog = false;$refs.schoolViewHandleRef.doSearch()" @close="memberChangeDialog = false"></member-change>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("schoolViewAndHandle.js"){}#-->
<!--#include("viewChangeTypeUser.js"){}#-->
<!--#include("../../../change/common/memberChange.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data(){
return {
// 当前的名单核对事项详细信息
// projectInfo: {},
pageForm: {
verificationProjectId: "",
unionId: '',
},
unionId: '',
unionName: '',
unions: [],
verificationList: [],
feedbackDialog: false,
viewData: {},
labelName: '',
userId: '',
url: '/platform/member/schoolUnion/verification/check/doCheckMember',
memberChangeDialog: false,
welfareTableData: [],
welfareTableHeader: [],
}
},
computed:{
projectInfo(){
if(this.pageForm.verificationProjectId && this.verificationList){
return this.verificationList.find(v=>v.id === this.pageForm.verificationProjectId)
}
return null
}
},
components: {
"school-view-handle": SCHOOL_VIEW_AND_HANDLE,
"view-change-type-user": VIEW_CHANGE_TYPE_USER,
"member-change": MEMBER_CHANGE
},
methods: {
// 导出福利上报的人数
welfareChooseNumExport() {
this.$downLoad('/platform/member/schoolUnion/verification/check/welfareChooseNumExport', {
projectId: this.pageForm.verificationProjectId
})
},
showWelfareUserInfo() {
this.$refs.guava.public(() => {
// 去查上报的福利选择信息
this.$axios.post('/platform/member/schoolUnion/verification/check/getWelfareUserInfo',
{projectId: this.pageForm.verificationProjectId})
.then(res => {
if (res.code === 0) {
this.welfareTableData = res.data.tableData
this.welfareTableHeader = res.data.tableHeader
}
})
})
},
openChange(row) {
this.userId = row.userId
this.memberChangeDialog = true
const data = this.verificationList.find(v => v.id === this.pageForm.verificationProjectId)
this.$nextTick(() => {
this.$refs.memberChangeRef.verificationInit({
renewFields: data.renewFields,
verificationProjectId: data.id,
changeOrigin: "SCHOOL_UNION_VERIFICATION"
})
})
},
// 查看在职状态变更列表
openUserState(row) {
this.labelName = row.unionName + '在职状态变更列表'
this.showChangeTypeUser("userState", row)
},
// 查看入会人员列表
openRestore(row) {
this.labelName = row.unionName + '入会人员列表'
this.showChangeTypeUser("restore", row)
},
// 查看退会人员列表
openWithdrawal(row) {
this.labelName = row.unionName + '退会人员列表'
this.showChangeTypeUser("withdrawal", row)
},
// 查看最终会员人数
openLastMember(row) {
this.labelName = row.unionName + '最终会员列表'
this.showChangeTypeUser("member", row)
},
// 查看最终福利会员人数
openLastWelfareMember(row) {
this.labelName = row.unionName + '最终福利会员列表'
this.showChangeTypeUser("welfareMember", row)
},
showChangeTypeUser(changeType, row) {
this.$refs.guava.view(() => {
this.$refs.viewChangeTypeUserRef.pageForm.verificationProjectId = this.pageForm.verificationProjectId
this.$refs.viewChangeTypeUserRef.pageForm.changeType = changeType
this.$refs.viewChangeTypeUserRef.pageForm.unionId = row.unionId
this.$refs.viewChangeTypeUserRef.flushUnits()
this.$refs.viewChangeTypeUserRef.pageData()
})
},
exportChangeType(changeType) {
this.pageForm.changeType = changeType
this.$downLoad('/platform/member/schoolUnion/verification/check/exportAllChangeTypeUserExcel', this.pageForm)
},
exportExcel() {
this.$downLoad('/platform/member/schoolUnion/verification/check/exportExcel', this.pageForm)
},
doExportByPageDataForExcel(){
this.$downLoad('/platform/member/schoolUnion/verification/check/doExportByPageDataForExcel', this.pageForm)
},
viewFeedback(row){
this.$axios.post('/platform/member/branchUnion/verification/check/getVerificationFeedback',{
verificationProjectId: this.pageForm.verificationProjectId,
unionId: row.unionId,
}).then(res => {
if (res.code === 0) {
this.viewData = res.data
this.feedbackDialog = true
} else {
this.$message.error(res.msg)
}
})
},
async viewUser(row){
this.unionName = row.unionName
const units = await this.$businessTool.listUnit(row.unionId)
this.$refs.guava.edit(() => {
this.$refs.schoolViewHandleRef.unionId = row.unionId
this.$refs.schoolViewHandleRef.units = units
this.$refs.schoolViewHandleRef.pageData('0')
})
},
openHandle(row){
this.unionName = row.unionName
this.$refs.guava.edit()
this.$nextTick(()=> {
this.$refs.schoolViewHandleRef.isView = false
this.$refs.schoolViewHandleRef.unionId = row.unionId
this.$refs.schoolViewHandleRef.pageData('2')
})
},
// 退回
doRollback(data){
// 您确定要退回吗?
this.$prompt('请填写退回原因', '退回', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: '',
inputPattern: /^.+$/,
inputErrorMessage: '请填写退回原因',
type: 'warning'
}).then(({value}) => {
console.log(value)
this.$axios.post("/platform/member/schoolUnion/verification/check/doRollback", {
id: data.id,
rollbackReason: value,
}).then(res => {
if (res.code === 0) {
this.$message.success('退回成功')
this.pageData()
} else {
this.$message.error(res.msg)
}
})
})
},
getVerificationList() {
this.$axios.post("/platform/member/branchUnion/verification/check/getVerificationList").then(res => {
if (res.code === 0) {
this.verificationList = res.data
if (res.data && res.data.length > 0) {
this.$set(this.pageForm, "verificationProjectId", this.verificationList[0].id)
this.projectInfo = this.verificationList[0]
}
this.pageData()
this.initData()
}
})
},
successSubmit() {
this.$refs.guava.index(()=>{
this.pageData()
})
},
initData() {
this.$businessTool.listUnion().then(data => {
if (this.verificationList) {
const project = this.verificationList.find(v=>v.id === this.pageForm.verificationProjectId)
this.unions = data.filter(v=> project.unionIds.includes(v.id))
} else {
this.unions = data
}
})
},
pageData() {
this.$axios.post("/platform/member/schoolUnion/verification/check/pageData",this.pageForm)
.then(res => {
if (res.code === 0) {
this.tableData = res.data
}
})
},
},
created() {
this.getVerificationList()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,289 @@
<!--#include("../../../common/info/memberInfo.js"){}#-->
<!--#include("../../../common/verification/memberVerificationChange.js"){}#-->
const SCHOOL_VIEW_AND_HANDLE = {
template: `
<div>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool :label="unionName + '审核列表'">
<el-button v-if="!isView" @click="doSubmit" type="primary" size="small">提交</el-button>
<el-radio-group @change="doSearch" size="small" style="margin-left: 10px" v-model="pageForm.schoolUnionChecked">
<el-radio-button :label="0">全部</el-radio-button>
<el-radio-button :label="1">已核对</el-radio-button>
<el-radio-button :label="2">未核对</el-radio-button>
</el-radio-group>
</table-tool>
<el-table ref="table" :data="tableData" row-key="id" style="width: 100%" border>
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column
:label="column.label" :prop="column.prop"
:sortable="column.sortable" :width="column.width"
align="center" header-align="center" min-width="100px"
show-overflow-tooltip v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='isChanged'">
<el-link v-if="row.isChanged" @click="openChangeInfo(row)" :underline="false" type="primary">变更</el-link>
<el-link v-else :underline="false" type="danger" disabled>未变更</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='schoolUnionChecked'">
<el-tag size="mini" v-if="!row.isChanged">无需核对</el-tag>
<template v-else>
<el-tag size="mini" v-if="row.schoolUnionChecked" type="success">已核对</el-tag>
<el-tag size="mini" v-else type="danger">未核对</el-tag>
</template>
</template>
</el-table-column>
<el-table-column label="操作" align="center" header-align="center" width="220px">
<template scope="{row}">
<el-button @click="openView(row)" type="primary" size="mini" plain>查看</el-button>
<el-button @click="openHandle(row)" v-if="!isView && !row.schoolUnionChecked && row.isChanged" type="primary" size="mini">审核</el-button>
<el-button @click="openChange(row)" v-else-if="!row.isChanged" type="primary" size="mini" plain>变更</el-button>
<el-button @click="openChange(row)" v-else-if="row.schoolUnionChecked && row.isChanged" type="primary" size="mini" plain>再次变更</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog :title="titleName" width="70%" :visible.sync="doHandleVisible" :append-to-body="true">
<el-tabs type="border-card" v-model="activeName">
<el-tab-pane label="用户信息" name="1">
<member-info ref="memberInfoRef"></member-info>
</el-tab-pane>
<el-tab-pane label="变更详情" name="2">
<table-tool label="变更记录"></table-tool>
<el-table v-if="changeRecord" ref="changeTable" :data="changeRecord" row-key="id" style="width: 100%" border>
<el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column label="变更字段" prop="name"></el-table-column>
<el-table-column label="原数据" prop="value">
<template slot-scope="scope">
<div v-html="scope.row.value"></div>
</template>
</el-table-column>
<el-table-column label="新数据" prop="newValue">
<template slot-scope="scope">
<div v-html="scope.row.newValue"></div>
</template>
</el-table-column>
</el-table>
<el-empty v-else :image-size="100" description="暂无变更数据"></el-empty>
</el-tab-pane>
</el-tabs>
<div style="margin-top: 20px">
<el-form v-if="!submitFlag" :model="formData" ref="formRef" label-width="0" style="margin-top: 20px" :rules="formRules" size="small">
<table-tool label="审核意见"></table-tool>
<el-form-item prop="option">
<el-input type="textarea" maxlength="200" show-word-limit rows="4" v-model="option" placeholder="请填写审核意见"></el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<template v-if="submitFlag">
<el-button @click="doHandleVisible = false">关 闭</el-button>
</template>
<template v-else>
<el-button type="danger" @click="doHandle(false)">拒 绝</el-button>
<el-button type="primary" @click="doHandle(true)">通 过</el-button>
</template>
</span>
</el-dialog>
<el-dialog title="变更数据" width="70%" :visible.sync="changeInfoVisible" :append-to-body="true">
<member-verification-change ref="memberVerificationChangeRef"></member-verification-change>
<span slot="footer" class="dialog-footer">
<el-button @click="changeInfoVisible = false">关 闭</el-button>
</span>
</el-dialog>
</div>
`,
props: {
unionName: { type: String, required: true },
verificationProjectId: { type: String, required: true },
},
mixins: [initTableMixins],
components: {
"member-info": MEMBER_INFO,
"member-verification-change": MEMBER_VERIFICATION_CHANGE
},
data() {
return {
tableColumns: [
{ label: "姓名", prop: "username" },
{ label: "工号", prop: "loginname" },
{ label: "性别", prop: "sex" },
{ label: "在职状态", prop: "userState" },
{ label: "编制类别", prop: "preparedBy" },
{ label: "教职工类别", prop: "personType" },
{ label: "所属单位", prop: "unitName" },
{ label: "是否变更", prop: "isChanged" },
// { label: "分工会状态", prop: "branchUnionChecked" },
{ label: "校工会审核状态", prop: "schoolUnionChecked" },
// { label: "校工会审核状态", prop: "currentState" },
],
units: [],
unionId: '',
pageForm: {
unionId: '',
unionName: this.unionName,
verificationProjectId: '',
schoolUnionChecked: '2',
},
changeRecord: [],
doHandleVisible: false,
formData: {},
userId: '',
verificationChangeInfoUserId: '',
activeName: '3',
titleName: '',
option: '',
isView: true,
submitFlag: true,
changeInfoVisible:false,
}
},
methods: {
openChange(row) {
this.$emit('open-change', row)
},
openChangeInfo(row){
this.changeInfoVisible = true
this.$nextTick(() => {
this.$refs.memberVerificationChangeRef.onOpen({id:row.userId,projectId:this.verificationProjectId})
})
},
doHandle(flag) {
// flag true 通过,false 拒绝
if (!flag && !this.option) {
// 拒绝,必须要填写审核意见
this.$message.warning('请填写审核意见')
return
}
// 通过后将修改此用户的基本信息,是否确认?
this.$confirm('通过后,将修改此用户的基本信息,是否确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const formData = new FormData()
this.$set(formData, "userId", this.userId)
this.$set(formData, "verificationProjectId", this.pageForm.verificationProjectId)
this.$set(formData, "flag", flag)
this.$set(formData, "option", this.option)
this.$axios.post('/platform/member/schoolUnion/verification/check/doHandle',{
data: JSON.stringify(formData)
}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doHandleVisible = false
this.pageData()
} else {
this.$message.error(res.msg)
}
})
}).catch(() => {
this.doHandleVisible = false
})
},
//校工会提交
doSubmit(){
this.$confirm('请确保数据全部核对完毕,提交后会将该表格数据全部转为已核对状态,是否确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/member/schoolUnion/verification/check/schoolVerificationSubmit', {
data: JSON.stringify(this.pageForm)
}).then(res=> {
if (res.code === 0) {
this.isView = true
this.submitFlag = true
this.$message.success(res.msg)
this.pageData('0')
this.$emit("success-submit")
} else {
this.$message.error(res.msg)
}
})
})
},
showData(row){
this.userId = row.userId
this.$nextTick(() => {
this.$refs.memberInfoRef.onOpen(row.userId)
})
const formData = new FormData()
this.$set(formData, "userId", row.userId)
this.$set(formData, "verificationProjectId", this.pageForm.verificationProjectId)
this.$axios
.post("/platform/member/schoolUnion/verification/check/getVerificationChangeInfo", {
data: JSON.stringify(formData)
})
.then((res) => {
if (res.code === 0) {
this.changeRecord = {}
this.changeRecord = res.data
}
})
},
openView(row) {
this.titleName = row.username + '基本信息'
this.activeName = '1'
this.showData(row)
this.submitFlag = true
this.doHandleVisible = true
},
openHandle(row) {
this.activeName = '2'
this.submitFlag = false
this.titleName = '校工会审核'
this.showData(row)
this.doHandleVisible = true
},
pageData(o) {
this.pageForm.unionId = this.unionId
this.pageForm.verificationProjectId = this.verificationProjectId
if (o) {
this.$set(this.pageForm, 'schoolUnionChecked', o)
}
this.$axios.post("/platform/member/schoolUnion/verification/check/getCheckedMemberByUnionId", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
this.$emit("refresh", this.pageForm)
}
})
},
},
created() {
}
}
@@ -0,0 +1,119 @@
const VIEW_CHANGE_TYPE_USER = {
template: `
<div>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool :label="labelName">
<el-button @click="doExport" size="small" type="primary">导出人员</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='member'">
<span class="text-success" v-if="row.member=='是'">
<i class="fa fa-circle ml5"></i> 是
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i> 否
</span>
</template>
<template scope="{row}" v-else-if="column.prop=='welfareMember'">
<span class="text-success" v-if="row.welfareMember=='是'">
<i class="fa fa-circle ml5"></i> 是
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i> 否
</span>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
`,
props: {
labelName: { type: String, default: "" }
},
mixins: [initTableMixins],
store,
data() {
return {
units: [],
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "member", label: "会员", sortable: true },
{ prop: "welfareMember", label: "福利会员", sortable: true }
]
}
},
methods: {
doExport() {
this.$downLoad("/platform/member/schoolUnion/verification/check/exportChangeTypeUserByUnionIdExcel", this.pageForm)
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
pageData() {
if (this.pageForm.changeType === "userState") {
this.tableColumns.push(
{ prop: "oldUserState", label: "原在职状态", sortable: true },
{ prop: "newUserState", label: "新在职状态", sortable: true }
)
} else {
// 清除上述列
this.tableColumns = this.tableColumns.filter((item) => item.prop !== "oldUserState" && item.prop !== "newUserState")
}
this.$axios.post("/platform/member/schoolUnion/verification/check/getChangeTypeUserPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
}
}
@@ -0,0 +1,238 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
style="width: 100%"
v-model="pageForm.projectYear"
value-format="yyyy"
:clearable="false"
type="year"
:picker-options="pickerOptions"
placeholder="请选择年度">
</el-date-picker>
</search-item>
<search-item label="事项名称">
<el-input placeholder="请输入名单核对事项名称查询" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" border header-align="center" style="width: 100%">
<el-table-column type="index" label="序号" width="80px" :index="indexMethod"></el-table-column>
<el-table-column prop="projectName" label="事项名称" align="center"></el-table-column>
<el-table-column prop="content" label="事项内容及要求" show-overflow-tooltip align="center"></el-table-column>
<el-table-column prop="isNeedFeedback" label="是否需要反馈" align="center">
<template scope="{row}">
<span style="color: #00aa3a" v-if="row.isNeedFeedback == 1"></span>
<span style="color: #ac2925" v-else></span>
</template>
</el-table-column>
<el-table-column prop="isNeedFeedbackFile" label="是否需要反馈附件" align="center">
<template scope="{row}">
<span style="color: #00aa3a" v-if="row.isNeedFeedbackFile == 1"></span>
<span style="color: #ac2925" v-else></span>
</template>
</el-table-column>
<el-table-column prop="applyTimes" label="核对时间" align="center">
<template scope="{row}">
<span>{{ row.startDate + ' 至 ' + row.endDate }}</span>
</template>
</el-table-column>
<el-table-column prop="releaseDateTime" label="发布时间" align="center">
<template scope="{row}">
<span>{{ row.isEnabled ? row.releaseDateTime : '未发布'}}</span>
</template>
</el-table-column>
<el-table-column prop="applyDate" label="创建时间" align="center"></el-table-column>
<el-table-column label="操作" width="250" align="center">
<template slot-scope="{row}">
<el-link size="mini" type="primary" @click="openView(row)">查看</el-link>
<el-link size="mini" v-if="!row.isEnabled" type="primary" @click="openEdit(row)">编辑</el-link>
<el-link size="mini" type="primary" @click="openSetUser(row)">设置人员</el-link>
<el-link size="mini" v-if="!row.isEnabled" type="primary" @click="releaseVerificationProject(row)">发布</el-link>
<el-link size="mini" v-if="row.isEnabled" type="primary" @click="closeVerificationProject(row)">关闭</el-link>
<el-link size="mini" v-if="!row.isEnabled" type="primary" @click="removeVerificationProject(row)">删除</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<verification-set-user-list ref="memberListUserRef" :id="verificationProjectId" :unions="unions" @submit-ready="submitReady"
@show-selection-user="showSelectionUser"></verification-set-user-list>
</template>
<template #view>
<verification-show-selection-users ref="showSelectionUserViewRef" :unions="unions" :can-be-modified="false"></verification-show-selection-users>
</template>
</guava>
<verification-project-add ref="addProjectRef" @success-submit="successSubmit"></verification-project-add>
<el-dialog title="名单核对事项" :visible.sync="dialogFormVisible" width="70%" @close="closeDialogFormVisible" :close-on-click-modal="false">
<verification-show-selection-users ref="showSelectionUserRef" :unions="unions" :can-be-modified="true"></verification-show-selection-users>
<div slot="footer" class="dialog-footer">
<el-button @click="closeDialogFormVisible">关 闭</el-button>
<!-- <el-button type="primary" @click="$refs.showSelectionUserRef.doSubmit()">提 交</el-button>-->
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("verificationSetUserList.js"){}#-->
<!--#include("verificationProjectAdd.js"){}#-->
<!--#include("verificationShowSelectionUsers.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"verification-set-user-list": VERIFICATION_SET_USER_LIST,
"verification-project-add": VERIFICATION_PROJECT_ADD,
"verification-show-selection-users": VERIFICATION_SHOW_SELECTION_USERS,
},
data() {
return {
setUserRow: {},
dialogFormVisible: false,
verificationProjectId: "",
isQueryReady: false,
unions:[],
viewData: {},
activeName: "info",
pageForm: {
projectYear: moment().format('YYYY'),
},
pickerOptions: {
disabledDate(time) {
return (
time.getFullYear() > new Date().getFullYear()
);
}
},
}
},
methods: {
closeDialogFormVisible(){
this.dialogFormVisible = false
// this.$refs.memberListUserRef.pageData()
},
openEdit(row) {
this.$refs.addProjectRef.findOne(row.id)
this.$nextTick(()=>{
this.$refs.addProjectRef.openView()
})
},
removeVerificationProject(row) {
this.$confirm("该操作会将所有关于此事项的数据全部删除,确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/member/schoolUnion/verification/manage/removeVerificationProject", {
verificationProjectId: row.id
}).then(res => {
this.$message.success(res.msg)
this.pageData()
})
})
},
closeVerificationProject(row) {
this.$confirm("确定要关闭吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/member/schoolUnion/verification/manage/closeVerificationProject", {
verificationProjectId: row.id
}).then(res => {
this.$message.success(res.msg)
this.pageData()
})
})
},
releaseVerificationProject(row) {
this.$confirm("确定要发布吗?发布后将无法设置人员", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/member/schoolUnion/verification/manage/releaseVerificationProject", {
verificationProjectId: row.id
}).then(res => {
this.$message.success(res.msg)
this.pageData()
})
})
},
successSubmit(){
this.pageData()
},
submitReady(){
this.$confirm("提交成功,是否跳转至项目管理页面?", "提示", {
confirmButtonText: "跳转至管理页",
cancelButtonText: "停留当前页面",
type: "success"
}).then(() => {
this.$refs.guava.index()
})
},
showSelectionUser(){
this.dialogFormVisible = true
this.$nextTick(()=>{
this.$refs.showSelectionUserRef.showInit(this.setUserRow)
})
},
showUsersSubmit() {
this.dialogFormVisible = false
this.submitReady()
},
openAdd() {
this.$refs.addProjectRef.dialogFormVisible = true
},
openView(row) {
this.$axios.post("/platform/member/schoolUnion/verification/manage/getSelectionUser", { id: row.id }).then((res) => {
if (res.code === 0) {
// this.getUnions(row)
this.$refs.guava.view(() => {
this.$refs.showSelectionUserViewRef.showInit(row)
})
}
})
},
openSetUser(row){
this.verificationProjectId = row.id
this.setUserRow = row
this.getUnions(row)
this.$refs.guava.edit(() => {
this.$refs.memberListUserRef.pageData()
})
},
getUnions(row){
const unionIds = JSON.parse(row.unionIds)
this.$businessTool.listUnion().then(data => {
this.unions = data.filter(item => unionIds.includes(item.id))
})
}
},
created(){
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,169 @@
const VERIFICATION_PROJECT_ADD = {
template: /*language=html*/ `
<el-dialog title="名单核对事项" :visible.sync="dialogFormVisible" width="1000px" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="140px" :rules="formRules">
<el-form-item prop="projectName" label="事项名称">
<el-input v-model="formData.projectName" maxlength="100"></el-input>
</el-form-item>
<el-form-item prop="content" label="内容及要求">
<el-input v-model="formData.content" maxlength="500"
rows="3" type="textarea" show-word-limit></el-input>
</el-form-item>
<el-form-item prop="unionIds" label="推送分工会">
<el-transfer filterable :filter-method="filterMethod" :titles="['可选工会', '已选工会']"
filter-placeholder="请输入分工会名称" v-model="formData.unionIds"
:props="{key:'id',label:'name'}" :data="unionData">
</el-transfer>
</el-form-item>
<el-form-item prop="applyTimes" label="核对时间">
<el-date-picker v-model="formData.applyTimes" type="datetimerange"
range-separator="至" start-placeholder="开始日期"
value-format="yyyy-MM-dd HH:mm:ss"
end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="isNeedFeedback" label="是否需要反馈">
<el-radio-group v-model="formData.isNeedFeedback" size="small">
<el-radio :label="true" border>是</el-radio>
<el-radio :label="false" border>否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="isNeedFeedbackFile" label="是否需要反馈附件">
<el-radio-group v-model="formData.isNeedFeedbackFile" size="small">
<el-radio :label="true" border>是</el-radio>
<el-radio :label="false" border>否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item prop="welfareJson" label="福利填写">
<el-table :data="formData.welfareJson" border size="small">
<el-table-column label="福利名称" prop="welfareName">
<template slot-scope="{row}">
<el-input v-model="row.welfareName" maxlength="50" placeholder="请输入福利名称"></el-input>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template slot-scope="{row}">
<el-input v-model="row.remark" maxlength="100" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column width="100px">
<template slot="header" slot-scope="scope">
<el-button type="primary" size="mini" @click="formData.welfareJson.push({})">添加</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="formData.welfareJson.length===0"
@click="formData.welfareJson.splice(scope.$index,1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
`,
data() {
return {
dialogFormVisible: false,
formData: {
isNeedFeedback: true,
isNeedFeedbackFile: true,
unionIds: [],
welfareJson: []
},
formRules: {
projectName: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
content: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
applyTimes: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
// unionIds: [{required: true, message: "必填", trigger: ["change", "blur"]}],
isNeedFeedback: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
isNeedFeedbackFile: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
},
unionData: []
}
},
methods: {
openView() {
this.formData = {
userIds: [],
delegationId: null,
roleId: null,
applyTimes: []
}
this.dialogFormVisible = true
},
filterMethod(query, item) {
return item.name.indexOf(query) > -1
},
getAllUnions() {
this.$businessTool.listUnion().then((data) => {
this.unionData = data
})
},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
if (!this.formData.applyTimes || this.formData.applyTimes === 0) {
this.$message.warning("请选择核对时间")
return
}
if (this.formData.welfareJson && this.formData.welfareJson.length > 0) {
this.formData.welfareJson = JSON.stringify(this.formData.welfareJson)
}
this.formData.startDate = this.formData.applyTimes[0]
this.formData.endDate = this.formData.applyTimes[1]
this.$axios
.post("/platform/member/schoolUnion/verification/manage/insertOrUpdate", {
data: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.$emit("success-submit")
}
})
}
})
},
findOne(id) {
if (id) {
this.$axios.post("/platform/member/schoolUnion/verification/manage/findOne", { verificationProjectId: id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
if (this.formData.startDate && this.formData.endDate) {
this.$set(this.formData, "applyTimes", [this.formData.startDate, this.formData.endDate])
// this.formData.applyTimes = [this.formData.startDate, this.formData.endDate]
}
if (res.data.welfareJson) {
this.formData.welfareJson = JSON.parse(res.data.welfareJson)
} else {
this.formData.welfareJson = []
}
}
})
}
}
},
created() {
this.getAllUnions()
}
}
@@ -0,0 +1,64 @@
const VERIFICATION_QUERY = {
template: `
<el-card>
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="变更类型">
<dict-select v-model="pageForm.changeType" placeholder="变更类型" @change="doSearch"
code="MEMBER_CHANGE_TYPE"></dict-select>
</search-item>
</search>
</el-card>
`,
props: {
unions: { type: Array, default: [] }
},
mixins: [initTableMixins],
data() {
return {
units: []
}
},
methods: {
initData() {
this.doSearch()
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
doSearch() {
this.$emit("query-ready", this.pageForm)
}
},
created() {}
}
@@ -0,0 +1,498 @@
const VERIFICATION_SET_USER_LIST = {
template: /*language=html*/ `
<div>
<el-card>
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="性别">
<dict-select v-model="pageForm.sex" placeholder="性别" @change="doSearch"
code="USER_SEX"></dict-select>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="变更类型">
<dict-select v-model="pageForm.changeType" placeholder="变更类型" @change="doSearch"
code="MEMBER_CHANGE_TYPE"></dict-select>
</search-item>
<template v-if="pageForm.userState == '退休'">
<search-item label="福利项目">
<el-select @change="doSearch" clearable filterable
placeholder="福利项目" style="width: 100%;" v-model="pageForm.welfareProjectId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in welfareProjectList"></el-option>
</el-select>
</search-item>
<search-item v-if="pageForm.welfareProjectId" label="福利发放">
<el-radio-group v-model="pageForm.isGrantWelfare">
<el-radio-button :label="1">已发放</el-radio-button>
<el-radio-button :label="0">未发放</el-radio-button>
</el-radio-group>
</search-item>
<search-item label="退休时间">
<el-date-picker
v-model="pageForm.retireTime"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</search-item>
</template>
</search>
</el-card>
<el-card class="mt10">
<table-tool :label="'预选人员列表;当前人数:(' + pageForm.totalCount + '人)'">
<span>会员:</span>
<el-select v-model="pageForm.isMember" placeholder="会员状态" clearable
style="width: 120px" @change="pageData" class="mr10" size="small">
<el-option label="全部" :value="3"></el-option>
<el-option label="会员" :value="1"></el-option>
<el-option label="非会员" :value="0"></el-option>
</el-select>
<span>福利会员:</span>
<el-select v-model="pageForm.isWelfareMember" placeholder="福利会员状态" clearable
style="width: 120px" @change="pageData" class="mr10" size="small">
<el-option label="全部" :value="3"></el-option>
<el-option label="福利会员" :value="1"></el-option>
<el-option label="非福利会员" :value="0"></el-option>
</el-select>
<el-button @click="importUser" type="primary" size="small">导入预选人员</el-button>
<el-button @click="submitSelectUser" type="primary" size="small">提交预选人员</el-button>
<el-button @click="showSelectionUsers" type="primary" size="small">查看已提交人员</el-button>
</table-tool>
<vxe-table
border
show-overflow
keep-source
ref="tableRef"
height="500"
:column-config="{resizable: true}"
:loading="loading"
:mouse-config="{selected: true}"
:edit-config="{trigger: 'dblclick', mode: 'cell', showStatus: true}"
:keyboard-config="{isArrow: true, isDel: true, isEnter: true, isTab: true, isEdit: true}"
:scroll-y="{enabled: true}"
:data="tableData">
<vxe-column type="checkbox" width="60"></vxe-column>
<vxe-column type="seq" width="70"></vxe-column>
<vxe-column v-for="column in tableColumns"
:key="column.prop"
:field="column.prop"
:width="column.width"
:title="column.label">
<template slot="header" scope="{row}">
<span v-if="column.isDisClick">{{ column.label }}</span>
<el-checkbox v-else v-model="checkedColumnProps[column.prop]"
@change.prevent.native="changeCheckboxStatus($event, column.prop)">{{ column.label }}</el-checkbox>
</template>
<template scope="{row}" v-if="column.prop=='member'">
<span class="text-success" v-if="row.member">
<i class="fa fa-circle ml5"></i> 是
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i> 否
</span>
</template>
<template scope="{row}" v-else-if="column.prop=='welfareMember'">
<span class="text-success" v-if="row.welfareMember">
<i class="fa fa-circle ml5"></i> 是
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i> 否
</span>
</template>
</vxe-column>
</vxe-table>
</el-card>
<el-dialog :visible.sync="importDialog" width="50%" title="预选人员导入" append-to-body>
<el-timeline>
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" style="width: 200px"
@click="$downLoad('/platform/member/schoolUnion/verification/manage/downloadImport')"
icon="el-icon-download">下载模板</el-button>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="上传文件" placement="top">
<el-card>
<el-form>
<el-upload
name="file"
ref="upload"
:on-remove="
(file, fileList) => {
importData.fileList = fileHandleRemove(file, fileList)
}
"
:on-change="
(file, fileList) => {
importData.fileList = fileHandleChange(file, fileList, { type: ['xls', 'xlsx'] })
}
"
:auto-upload="false"
:limit="1"
action
:file-list="importData.fileList"
>
<el-button size="medium" type="" icon="el-icon-upload" style="width: 200px">选择文件</el-button>
<div class="el-upload__tip" slot="tip" style="color: #f56c6c">只能上传 xls/xlsx 文件</div>
</el-upload>
</el-form>
</el-card>
</el-timeline-item>
</el-timeline>
<div style="text-align: right">
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="doImport">确 定</el-button>
</span>
</div>
</el-dialog>
</div>
`,
props: {
id: { type: String, required: true },
unions: { type: Array, default: [] }
},
mixins: [initTableMixins],
data() {
return {
pageForm: {
verificationProjectId: "",
selectUserIds: [],
renewFields: [],
retireTime: [],
isMember: 3,
isWelfareMember: 3,
isGrantWelfare: null,
pageSize: 100000
},
units: [],
tableColumns: [],
selectUser: [],
renewFields: [],
checkedColumnProps: {},
loading: false,
welfareProjectList: [],
importDialog: false,
importData: {
fileList: []
}
}
},
watch: {
id: {
handler: function (val) {
if (val) {
this.getSelectionUser()
}
},
immediate: true
}
},
methods: {
submitSelectUser() {
const map = this.$refs.tableRef.getCheckboxRecords().map((v) => v.id)
if (!this.renewFields || this.renewFields.length === 0) {
this.$message.warning("请先勾选需要更改的字段")
return
}
//是否确认提交
this.$confirm("请仔细核对数据是否准确,是否确认提交?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
if (!map) {
this.$message.warning("暂无可提交的数据")
return
}
const loading = this.$loading({
lock: true,
text: "正在提交中,请稍后...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
})
this.pageForm.selectUserIds = JSON.stringify(map)
this.pageForm.verificationProjectId = this.id
this.pageForm.renewFields = JSON.stringify(this.renewFields)
this.$axios
.post("/platform/member/schoolUnion/verification/manage/modifySelection", {
list: JSON.stringify(this.pageForm)
})
.then((res) => {
loading.close()
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
this.$nextTick(() => {
this.$emit("submit-ready")
})
} else {
this.$message.error(res.msg)
}
})
})
console.log(map)
},
doSubmit() {
debugger
this.$confirm("如您未查看选择人员可先点击【查看选择人员】按钮进行细微调整,如仍要提交,请仔细核对数据是否准确,是否确认提交?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios
.post("/platform/member/schoolUnion/verification/manage/modifySelection", {
list: JSON.stringify(this.pageForm)
})
.then((res) => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
this.$nextTick(() => {
this.$emit("submit-ready")
})
} else {
this.$message.error(res.msg)
}
})
})
.catch(() => {})
},
showSelectionUsers() {
this.$emit("show-selection-user")
},
changeCheckboxStatus(event, prop) {
if (event && event.target) {
let isChecked = event.target.checked
this.checkedColumnProps[prop] = isChecked
if (isChecked) {
this.renewFields.push(prop)
} else {
this.renewFields.splice(this.renewFields.indexOf(prop), 1)
}
} else {
console.error("事件对象未定义或缺少 target 属性")
}
},
doSelectChange(val) {
this.selectUser = val
},
initTableColumns() {
this.tableColumns = []
this.$businessTool.getDictOptions("MEMBER_ALLOW_CHANGES_FIELD").then((data) => {
data.forEach((item) => {
if (!["unionId", "unitId"].includes(item.code)) {
this.tableColumns.push({ prop: item.code, label: item.name })
}
})
})
if (!this.tableColumns.some((column) => column.prop === "unionName")) {
this.tableColumns.push({ prop: "unionName", label: "所属工会", isDisClick: true })
}
if (!this.tableColumns.some((column) => column.prop === "unitName")) {
this.tableColumns.push({ prop: "unitName", label: "所属单位", isDisClick: true })
}
this.tableColumns.push({ prop: "loginname", label: "工号", isDisClick: true })
},
pageData() {
this.$set(this.pageForm, "verificationProjectId", this.id)
this.$axios.post("/platform/member/schoolUnion/verification/manage/getUserPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
// this.$nextTick(() => {
// this.getSelectionUser()
// })
}
})
},
getSelectionUser() {
if (!this.id) {
return
}
this.$axios.post("/platform/member/schoolUnion/verification/manage/getSelectionUser", { id: this.id }).then((res) => {
if (res.code === 0 && res.data.renewFields && res.data.renewFields.length > 0) {
this.checkedColumnProps = res.data.renewFields.reduce((acc, prop) => {
acc[prop] = true
return acc
}, {})
this.renewFields = []
this.renewFields = res.data.renewFields
}
})
},
doSearch() {
/*const data = this.$refs.tableRef.getCheckboxRecords().map((v) => v.id)
if (data && data.length > 0) {
const loading = this.$loading({
lock: true,
text: "自动保存中,请稍后...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
})
setTimeout(() => {
if (!this.renewFields || this.renewFields.length === 0) {
loading.close()
this.$message.warning("请先勾选需要更改的字段")
return
}
this.pageForm.selectUserIds = JSON.stringify(data)
this.pageForm.renewFields = JSON.stringify(this.renewFields)
this.pageForm.verificationProjectId = this.id
this.$axios
.post("/platform/member/schoolUnion/verification/manage/modifySelection", {
list: JSON.stringify(this.pageForm)
})
.then((res) => {
loading.close()
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
this.$nextTick(() => {
this.$emit("submit-ready")
})
} else {
this.$message.error(res.msg)
}
})
}, 500)
// debugger
// const records = this.tableData.filter((row) => data.includes(row))
// this.$refs.tableRef.setAllCheckboxRow(records)
}*/
this.pageData()
},
saveSelectedRows() {
const selected = this.$refs.tableRef.getCheckboxReserveRecords()
debugger
console.log(selected)
},
cleanTableSelection() {
this.pageForm.pageNumber = 1
this.doSearch()
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
getWelfareProjectList() {
this.$axios.post("/platform/welfare/project/mange/getWelfareList").then((res) => {
if (res.code === 0) {
this.welfareProjectList = res.data
}
})
},
fileHandleChange(file, fileList, { type, size }) {
const removeFile = () => {
fileList.splice(fileList.findIndex((v) => v === file))
}
if (!file.size) {
this.$message.warning("您选择的是空文件!")
removeFile()
}
if (type && type.length && !type.includes(file.name.split(".").pop().toLowerCase())) {
this.$message.warning("文件格式错误!")
removeFile()
}
if (size && !file.size < size) {
this.$message.warning("文件过大!")
removeFile()
}
return fileList
},
importUser() {
this.importDialog = true
this.importData = {
fileList: []
}
},
doImport() {
if (this.importData.fileList.length === 0) {
this.$message.error({
title: "错误",
message: "请选择文件!"
})
return
}
const data = new FormData()
this.importData.fileList.forEach((val) => {
data.append("file", val.raw, val.raw.name)
})
data.append("verificationProjectId", this.id)
const loading = this.$loading({
lock: true,
text: "正在导入中,请稍后...",
spinner: "el-icon-loading"
})
this.$axios.post("/platform/member/schoolUnion/verification/manage/doImport", data).then((res) => {
loading.close()
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
this.importDialog = false
this.$nextTick(() => {
const $table = this.$refs.tableRef
if ($table) {
$table.setAllCheckboxRow(true)
}
})
} else {
this.$message.warning("导入失败")
}
})
}
},
created() {
this.initTableColumns()
this.getWelfareProjectList()
// this.findList()
}
}
@@ -0,0 +1,185 @@
const VERIFICATION_SHOW_SELECTION_USERS = {
template: `
<div>
<el-tabs type="border-card">
<el-tab-pane label="人员数据">
<el-card>
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card class="mt10">
<el-table ref="listTable" :data="tableData" row-key="id" style="width: 100%">
<el-table-column type="index" label="序号" :index="indexMethod" width="80px"></el-table-column>
<el-table-column label="工号" prop="loginname"></el-table-column>
<el-table-column label="姓名" prop="username"></el-table-column>
<el-table-column label="性别" prop="sex"></el-table-column>
<el-table-column label="在职状态" prop="userState"></el-table-column>
<el-table-column label="编制类别" prop="preparedBy"></el-table-column>
<el-table-column label="教职工类别" prop="personType"></el-table-column>
<el-table-column label="所属工会" prop="unionName"></el-table-column>
<el-table-column label="所属单位" prop="unitName"></el-table-column>
<el-table-column label="操作" fixed="right" width="80px" v-if="canBeModified">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="doRemoveUser(scope.row.id)">移除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</el-tab-pane>
<el-tab-pane label="事项详情">
<el-descriptions class="margin-top" :column="3" border>
<el-descriptions-item label="事项名称" :span="3">{{ viewData.projectName }}</el-descriptions-item>
<el-descriptions-item label="事项内容" :span="3">{{ viewData.content }}</el-descriptions-item>
<el-descriptions-item label="创建时间" :span="3">{{ viewData.applyDate }}</el-descriptions-item>
<el-descriptions-item label="是否需要反馈" :span="3">{{ viewData.isNeedFeedback == 1 ? "是" : "否" }}</el-descriptions-item>
<el-descriptions-item label="是否需要反馈附件" :span="3">{{ viewData.isNeedFeedbackFile == 1 ? "是" : "否" }}</el-descriptions-item>
<el-descriptions-item label="发布时间" :span="3">{{ viewData.isEnabled ? viewData.releaseDateTime : '未发布' }}</el-descriptions-item>
<el-descriptions-item :span="3" label="核对时间">{{ viewData.startDate + " 至 " + viewData.endDate }}</el-descriptions-item>
<el-descriptions-item :span="3" label="需核对分工会">{{ viewData.unionNames }}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
</el-tabs>
</div>
`,
props: {
//是否能修改,默认可以修改
canBeModified: { type: Boolean, default: true },
unions: { type: Array, default: [] }
},
mixins: [initTableMixins],
data() {
return {
pageForm: {
renewFields: []
},
fieldNames: [],
units: [],
sourceLength: 0
}
},
methods: {
doRemoveUser(id, index) {
//是否要将该用户从此表格数据中移除?
this.$confirm("是否要将该用户从提交人员表格数据中移除?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
// const selectionIndex = this.pageForm.selectUserIds.indexOf(id)
// this.pageForm.selectUserIds.splice(selectionIndex, 1)
this.$axios.post("/platform/member/schoolUnion/verification/manage/removeMemberVerificationUserById", { id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
this.$emit("remove-user")
} else {
this.$message.error(res.msg)
}
})
// this.tableData.splice(index, 1)
})
.catch(() => {})
},
/*doModifySelection() {
this.$axios
.post("/platform/member/schoolUnion/verification/manage/modifySelection", {
list: JSON.stringify(this.pageForm)
})
.then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.$emit("modify-selection")
} else {
this.$message.error(res.msg)
}
})
.catch((e) => {
console.log(e)
})
},
doSubmit() {
this.$confirm("是否确认提交,提交后将修改之前数据,请仔细核对?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.doModifySelection()
this.$emit("show-users-submit")
})
.catch(() => {})
},*/
showInit(row) {
this.pageForm.verificationProjectId = row.id
this.findOne(row.id)
this.pageData()
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
pageData() {
this.$axios
.post("/platform/member/schoolUnion/verification/manage/getShowSelectionUsers", { data: JSON.stringify(this.pageForm) })
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
findOne(id) {
if (!id) {
return
}
this.$axios
.post("/platform/member/schoolUnion/verification/manage/findOne", {
verificationProjectId: id
})
.then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
}
},
created() {}
}
@@ -0,0 +1,167 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
style="width: 100%"
v-model="pageForm.currentYear"
value-format="yyyy"
:clearable="false"
type="year"
:picker-options="pickerOptions"
placeholder="请选择年度"
></el-date-picker>
</search-item>
<template v-if="pageForm.queryType == 'fgh'">
<search-item label="工会">
<el-select placeholder="分工会" v-model="pageForm.queryId" style="width: 100%" @change="doSearch" clearable filterable>
<el-option v-for="item in unions" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</template>
<template v-else>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" v-model="pageForm.queryId" style="width: 100%" @change="doSearch" clearable filterable>
<el-option v-for="item in units" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</template>
<search-item>
<el-radio-group v-model="pageForm.queryType" @change="pageForm.queryId = '';doSearch()">
<el-radio-button label="fgh">按分工会分析</el-radio-button>
<el-radio-button label="unit">按单位分析</el-radio-button>
</el-radio-group>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="会员分析"></table-tool>
<el-table :data="tableData" show-summary>
<el-table-column align="center" header-align="center" type="index" label="序号" width="80px"></el-table-column>
<el-table-column v-if="pageForm.queryType=='fgh'" align="center" header-align="center" label="分工会" width="220px">
<template scope="{row}">{{row.unionCode ? ''+row.unionCode+'' : null }}{{row.unionName}}</template>
</el-table-column>
<el-table-column v-if="pageForm.queryType=='unit'" align="center" header-align="center" label="单位" width="220px">
<template scope="{row}">{{row.unitCode?''+row.unitCode+'' : null}}{{row.unitName}}</template>
</el-table-column>
<!--<el-table-column align="center" header-align="center" label="年初数量"
sortable prop="lastYearMemberNum"></el-table-column>-->
<el-table-column align="center" header-align="center" label="新增人数" sortable prop="newMemberNum"></el-table-column>
<el-table-column
align="center"
header-align="center"
label="【新入职(恢复)"
sortable
label-class-name="addColumn"
prop="newResetMemberNum"
>
<template scope="{row}">
<span style="color: #c1c3c6">{{row.newResetMemberNum}}</span>
</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="校内转入】"
sortable
label-class-name="addColumn"
prop="memberUnitChangeNumIn"
>
<template scope="{row}">
<span style="color: #c1c3c6">{{row.memberUnitChangeNumIn}}</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="减少人数" sortable prop="reduceMemberNum"></el-table-column>
<el-table-column
align="center"
header-align="center"
label="【校内转出"
sortable
label-class-name="deleteColumn"
prop="memberUnitChangeNumOut"
>
<template scope="{row}">
<span style="color: #c1c3c6">{{row.memberUnitChangeNumOut}}</span>
</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="其他(退会)】"
sortable
label-class-name="deleteColumn"
prop="reduceOtherNum"
>
<template scope="{row}">
<span style="color: #c1c3c6">{{row.reduceOtherNum}}</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="当前数量" sortable prop="currentYearMemberNum"></el-table-column>
</el-table>
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
store,
data: {
pickerOptions: {
disabledDate(time) {
return time.getFullYear() > new Date().getFullYear()
}
},
unions: [],
units: [],
pageForm: {
currentYear: moment().format("YYYY"),
queryType: "fgh"
},
fullTableData: []
},
methods: {
doExport() {},
initData() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.$businessTool.listUnion().then((data) => {
this.unions = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
})
}
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
created() {
this.initData()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,271 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<template>
<query-form @search="search" ref="queryFormRef"></query-form>
<el-card shadow="never">
<table-tool label="会员列表">
<el-select
v-model="pageForm.searchType"
placeholder="是否会员"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="全部教工" value="all"></el-option>
<el-option label="会员" value="member"></el-option>
<el-option label="非会员" value="unMember"></el-option>
</el-select>
<el-select
v-model="pageForm.isUnit"
placeholder="是否有单位"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="有单位" value="true"></el-option>
<el-option label="无单位" value="false"></el-option>
</el-select>
<el-select
v-model="pageForm.isUnion"
placeholder="是否有工会"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="有工会" value="true"></el-option>
<el-option label="无工会" value="false"></el-option>
</el-select>
<el-button icon="el-icon-printer" type="primary" size="small" @click="doExport">导出</el-button>
<el-popover
placement="bottom"
trigger="click"
width="200">
<div style="padding:4px 0;border-bottom:1px solid #eee;">
<el-button size="mini" @click="checkAll">全选</el-button>
<el-button size="mini" @click="invertCheck">反选</el-button>
</div>
<div style="max-height:40vh;overflow-y:auto;padding:6px 0;">
<el-checkbox-group v-model="checkedFields">
<el-checkbox
v-for="f in tableColumns"
:key="f.prop"
:label="f.prop"
style="display:block;margin:6px 0;">
{{ f.label }}
</el-checkbox>
</el-checkbox-group>
</div>
<el-button
slot="reference"
type="text"
icon="el-icon-s-operation"
size="small"
style="margin-left:12px;">
列设置
</el-button>
</el-popover>
</table-tool>
<el-table
:data="tableData"
style="width: 100%"
stripe
border
:header-cell-style="{background:'#FAFAFA'}"
row-key="id"
@sort-change="pageOrder"
>
<el-table-column
align="center"
header-align="center"
type="index"
fixed="left"
:index="indexMethod"
label="序号"
width="80px"
></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
v-if="checkedFields.includes(column.prop)"
:label="column.label"
:prop="column.prop"
:width="column.width"
:fixed="column.fixed"
:sortable="column.sortable"
>
<template v-if="column.prop==='memberJoinTime'" scope="{row}">{{$moment(row.memberJoinTime).format('YYYY-MM-DD')}}</template>
<template v-else-if="column.prop==='birthday'" scope="{row}">
{{row.birthday ? $moment(row.birthday).format('YYYY-MM-DD') : null}}
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="100px" fixed="right">
<template scope="{row}">
<el-button size="mini" @click="openView(row.id)" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("queryForm.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
searchType: "member"
},
unions: [],
units: [],
childrenData: {},
tableColumns: [
{ prop: "loginname", label: "工号", width: 120, fixed: "left"},
{ prop: "username", label: "姓名", width: 120, fixed: "left" },
{ prop: "sex", label: "性别", width: 120},
{ prop: "birthday", label: "出生年月", width: 120, sortable: true },
{ prop: "nationality", label: "国籍", width: 120, sortable: true, checked: 0 },
{ prop: "nation", label: "民族", width: 120, sortable: true},
{ prop: "mobile", label: "联系电话", width: 120 },
{ prop: "political", label: "政治面貌", width: 120, sortable: true},
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "编制类别", width: 120, sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true, checked: 0 },
{ prop: "unionName", label: "所属工会", width: 120, sortable: true },
{ prop: "unitName", label: "所属单位", width: 120, sortable: true },
{ prop: "idCardType", label: "证件类型", width: 120, sortable: true, checked: 0 },
{ prop: "idCard", label: "证件号码", width: 120, sortable: true, checked: 0 },
{ prop: "marriage", label: "婚姻状况", width: 120, sortable: true, checked: 0 },
{ prop: "jobCategory", label: "岗位类别", width: 120, sortable: true, checked: 0 },
{ prop: "professionalTitle", label: "职称", width: 120, sortable: true, checked: 0 },
{ prop: "professionalLevel", label: "职级", width: 120, sortable: true, checked: 0 },
{ prop: "employeeSource", label: "职工来源", width: 120, sortable: true, checked: 0 },
{ prop: "administrativeLevel", label: "行政级别(管理岗位)", width: 120, sortable: true, checked: 0 },
{ prop: "positionSeries", label: "岗位系列", width: 120, sortable: true, checked: 0 },
{ prop: "positionLevel", label: "岗级", width: 120, sortable: true, checked: 0 },
{ prop: "administrativePositionLevel", label: "行政岗级", width: 120, sortable: true, checked: 0 },
{ prop: "arrivalAtSchoolDate", label: "来校时间", width: 120, sortable: true, checked: 0 },
{ prop: "teachingTime", label: "从教年月", width: 120, sortable: true, checked: 0 },
{ prop: "expectedLeaveSchoolDate", label: "预计/最后离校时间", width: 120, sortable: true, checked: 0 },
],
checkedFields: []
}
},
components: {
"query-form": MEMBER_STATISTICS_COMPREHENSIVE_QUERY_FORM,
"member-info": MEMBER_INFO
},
methods: {
openView(id) {
this.$refs.guava.view(() => {
this.$refs.memberInfoRef.onOpen(id)
})
},
doExport() {
const pageForm = clone(this.pageForm)
pageForm.userIds = JSON.stringify(this.pageForm.userIds)
pageForm.unionId = JSON.stringify(this.pageForm.unionId)
pageForm.unitId = JSON.stringify(this.pageForm.unitId)
pageForm.sexTypes = JSON.stringify(this.pageForm.sexTypes)
pageForm.memberTypes = JSON.stringify(this.pageForm.memberTypes)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
const data = this.tableColumns.filter(item => this.checkedFields.includes(item.prop)).map(item => {
return {prop: item.prop, label: item.label}
})
pageForm.columns = JSON.stringify(data)
this.$downLoad("/platform/member/statistics/comprehensive/doExport", pageForm)
},
search(pageForm) {
this.pageForm = {
...this.pageForm,
...pageForm,
}
this.pageData()
},
pageData() {
const pageForm = clone(this.pageForm)
pageForm.userIds = JSON.stringify(this.pageForm.userIds)
pageForm.age = JSON.stringify(this.pageForm.age)
pageForm.unionId = JSON.stringify(this.pageForm.unionId)
pageForm.unitId = JSON.stringify(this.pageForm.unitId)
pageForm.sexTypes = JSON.stringify(this.pageForm.sexTypes)
pageForm.memberTypes = JSON.stringify(this.pageForm.memberTypes)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
pageForm.memberStatus = JSON.stringify(this.pageForm.memberStatus)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
if (pageForm.birthdayRange && pageForm.birthdayRange.length > 0) {
pageForm.startDate = pageForm.birthdayRange[0]
pageForm.endDate = pageForm.birthdayRange[1]
}
if (pageForm.joinMemberRange && pageForm.joinMemberRange.length > 0) {
pageForm.startJoinDate = pageForm.joinMemberRange[0]
pageForm.endJoinDate = pageForm.joinMemberRange[1]
}
if (pageForm.leaveMemberRange && pageForm.leaveMemberRange.length > 0) {
pageForm.startLeaveDate = pageForm.leaveMemberRange[0]
pageForm.endLeaveDate = pageForm.leaveMemberRange[1]
}
this.$axios.post("/platform/member/statistics/comprehensive/pageData", pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
} else {
this.$message.error(res.msg)
}
})
},
checkAll() {
this.checkedFields = this.tableColumns.map(c => c.prop);
},
invertCheck() {
const all = this.tableColumns.map(c => c.prop);
this.checkedFields = all.filter(p => !this.checkedFields.includes(p));
}
},
computed: {
showColumns() {
return this.tableColumns.filter(c => this.checkedFields.includes(c.prop));
}
},
mounted() {
this.checkedFields = this.tableColumns.filter(c => c.checked !== 0).map(c => c.prop);
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,431 @@
const MEMBER_STATISTICS_COMPREHENSIVE_QUERY_FORM = {
template: /*language=HTML*/ `
<el-card shadow="never">
<el-row class="query-row">
<el-col class="query-row-title">姓名/工号:</el-col>
<el-col class="query-row-content">
<el-select
clearable
v-model="pageForm.userIds"
filterable
remote
collapse-tags
placeholder="输入工号或者姓名查找"
:remote-method="queryUser"
@change="doSearch"
style="width: 100%"
multiple
>
<el-option v-for="o in userList" :label="o.username + '(' + o.loginname + ')'" :value="o.id"
:key="o.id"></el-option>
</el-select>
</el-col>
</el-row>
<el-row class="query-row">
<el-col class="query-row-title">性别:</el-col>
<el-col class="query-row-content">
<el-tag
:effect="pageForm.sexTypes.includes(item.name)?'dark':'plain'"
:key="item.code"
:type="item.name"
@click="tagClick('sexTypes',item.name)"
style="margin-right: 10px;cursor: pointer"
v-for="item in sexTypeOptions">
{{ item.name }}
</el-tag>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row query-row-tag">
<el-col class="query-row-title">在职状态:</el-col>
<el-col class="query-row-content query-row-content-tag">
<el-tag
style="margin-right: 10px;cursor: pointer"
v-for="item in userStateOptions"
:key="item.code"
:type="item.name"
:effect="pageForm.userStates.includes(item.name)?'dark':'plain'"
@click="tagClick('userStates',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="userStateOptions.length&&pageForm.userStates.length"
:underline="false"
@click="pageForm.userStates=[];doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.userStates=userStateOptions.map(p=>p.code);doSearch()"
type="success">全部
</el-link>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row query-row-tag">
<el-col class="query-row-title">教职工类别:</el-col>
<el-col class="query-row-content query-row-content-tag">
<el-tag
style="margin-right: 10px;cursor: pointer"
v-for="item in personTypeOptions"
:key="item.code"
:type="item.name"
:effect="pageForm.personTypes.includes(item.name)?'dark':'plain'"
@click="tagClick('personTypes',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="personTypeOptions.length&&pageForm.personTypes.length"
:underline="false"
@click="pageForm.personTypes=[];doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.personTypes=personTypeOptions.map(p=>p.code);doSearch()"
type="success">全部
</el-link>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row query-row-tag">
<el-col class="query-row-title">编制类别:</el-col>
<el-col class="query-row-content query-row-content-tag">
<el-tag
style="margin-right: 10px;cursor: pointer"
v-for="item in preparedByOptions"
:key="item.code"
:type="item.name"
:effect="pageForm.preparedBys.includes(item.name)?'dark':'plain'"
@click="tagClick('preparedBys',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="preparedByOptions.length&&pageForm.preparedBys.length"
:underline="false"
@click="pageForm.preparedBys=[];doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.preparedBys=preparedByOptions.map(p=>p.code);doSearch()"
type="success">全部
</el-link>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row">
<el-col class="query-row-content">
<el-row>
<el-col :span="12">
<span>所属工会:</span>
<el-select placeholder="所属工会" v-model="pageForm.unionId"
clearable multiple style="margin-left: 38px;width: 80%"
@change="flushUnits();doSearch()"
@clear="flushUnits();doSearch()"
filterable>
<el-option v-for="item in unions" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="12">
<span>所属单位:</span>
<el-select placeholder="所属单位" v-model="pageForm.unitId"
clearable multiple style="margin-left: 33px;width: 80%" filterable>
<el-option v-for="item in units" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row class="query-row" type="flex" align="middle">
<el-col class="query-row-title">出生日期:</el-col>
<el-col class="query-row-content">
<el-date-picker
v-model="pageForm.startDate"
type="date"
@change="determineStartDate"
placeholder="选择开始日期">
</el-date-picker>
<el-date-picker
v-model="pageForm.endDate"
type="date"
@change="determineEndDate"
placeholder="选择结束日期">
</el-date-picker>
</el-col>
</el-row>
<el-row class="query-row" type="flex" align="middle">
<el-col class="query-row-title">年龄范围:</el-col>
<el-col class="query-row-content">
<el-row type="flex" style="align-items: center">
<el-col :span="15">
<el-slider
v-model="pageForm.age"
range
show-stops
:max="100">
</el-slider>
</el-col>
<el-col :span="9" class="pl20">
当前范围:{{ pageForm.age }}
</el-col>
</el-row>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row">
<el-col class="query-row-title">模糊查询:</el-col>
<el-col class="query-row-content">
<member-cnd @cnd="(v)=>pageForm={...pageForm,...v}"></member-cnd>
</el-col>
</el-row>
<el-row class="query-row" style="justify-content: end">
<el-checkbox v-model="pageForm.reverseSelection" label="是否反选" border
@change="doSearch"
class="reverseCheckBox"></el-checkbox>
<el-button type="danger" icon="el-icon-circle-close" @click="doReset">重置
</el-button>
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
</el-row>
</el-card>
`,
mixins: [initTableMixins],
store,
data() {
return {
userList: [],
pageForm: {
userIds: [],
isUnit: "",
isUnion: "",
unionId: [],
unitId: [],
unionGroupId: [],
threeUnitId: [],
searchName: "username",
personTypes: [],
preparedBys: [],
userStates: [],
memberStatus: [],
year: moment().format("YYYY"),
roleIds: [],
age: [0, 0],
minAge: 0,
maxAge: 0,
module: "",
sexTypes: [],
reverseSelection: false,
activityUserCnd: "",
startDate: "",
endDate: ""
},
personTypeOptions: [],
preparedByOptions: [],
userStateOptions: [],
memberStatusOptions: [],
unions: [],
units: [],
sexTypeOptions: [
{ code: "男", name: "男" },
{ code: "女", name: "女" }
],
pickerOptions: {
disabledDate: (time) => {
return time.getTime() > Date.now()
}
}
}
},
components: {
"member-cnd": httpVueLoader("/components/module/member/MemberCnd.vue?v=" + new Date().getTime())
},
methods: {
async queryUser(val) {
const resp = await $.get("/open/common/userOptions", {query: val})
this.userList = resp.data
},
determineEndDate() {
if (this.pageForm.startDate) {
if (Date.parse(this.pageForm.startDate) > Date.parse(this.pageForm.endDate)) {
this.pageForm.endDate = ""
this.$notify.warning("结束时间不能小于开始时间")
}
}
this.pageForm.endDate = this.pageForm.endDate.toLocaleDateString().replaceAll("/", "-")
},
determineStartDate() {
if (this.pageForm.endDate) {
if (Date.parse(this.pageForm.startDate) > Date.parse(this.pageForm.endDate)) {
this.pageForm.startDate = ""
this.$notify.warning("开始时间不能大于结束时间")
}
}
this.pageForm.startDate = this.pageForm.startDate.toLocaleDateString().replaceAll("/", "-")
},
tagClick(key, val) {
let idx = this.pageForm[key].indexOf(val)
if (idx !== -1) {
this.pageForm[key].splice(idx, 1)
} else {
this.pageForm[key].push(val)
}
this.doSearch()
},
/*checkPersonType(type) {
let idx = this.pageForm.personTypes.indexOf(type)
if (idx !== -1) {
this.pageForm.personTypes.splice(idx, 1)
} else {
this.pageForm.personTypes.push(type)
}
this.doSearch()
},*/
getDate(date) {
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
month = month >= 10 ? month : "0" + month
day = day >= 10 ? day : "0" + day
return year + "-" + month + "-" + day
},
checkUserStateType(state) {
let idx = this.pageForm.userStates.indexOf(state)
if (idx !== -1) {
this.pageForm.userStates.splice(idx, 1)
} else {
this.pageForm.userStates.push(state)
}
this.doSearch()
},
checkMemberStatusType(state) {
let idx = this.pageForm.memberStatus.indexOf(state)
if (idx !== -1) {
this.pageForm.memberStatus.splice(idx, 1)
} else {
this.pageForm.memberStatus.push(state)
}
this.doSearch()
},
doReset() {
this.pageForm.userIds = []
this.pageForm.memberTypes = []
this.pageForm.sexTypes = []
this.pageForm.personTypes = []
this.pageForm.preparedBys = []
this.pageForm.memberStatus = []
this.pageForm.userStates = []
this.pageForm.unionId = []
this.pageForm.unitId = []
this.pageForm.activityGroupId = []
this.pageForm.threeUnitId = []
this.pageForm.module = ""
this.pageForm.teacherMeetingId = ""
this.pageForm.roleIds = []
this.pageForm.clubId = ""
this.pageForm.activityGroupId = ""
this.pageForm.activityUserCnd = ""
this.pageForm.age = [0, 0]
this.pageForm.reverseSelection = false
this.doSearch()
},
getMenuOptions() {
this.$axios.post("/platform/sys/role/getMenuOptions").then((resp) => {
if (resp.code === 0) {
this.menuOptions = resp.data
}
})
},
async initData() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.unions = await this.$businessTool.listUnion(this.pageForm.unionId)
this.units = await this.$businessTool.listUnit()
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
this.units = await this.$businessTool.listUnit(this.$store.state.user.union.id)
}
this.$businessTool.getDictOptions("USER_PERSON_TYPE").then((data) => {
this.personTypeOptions = data
})
this.$businessTool.getDictOptions("USER_PREPARED_BY_TYPE").then((data) => {
this.preparedByOptions = data
})
this.$businessTool.getDictOptions("USER_STATE").then((data) => {
this.userStateOptions = data
})
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
setPageFormParams(params) {
this.pageForm.isUnit = params.isUnit
this.pageForm.isUnion = params.isUnion
this.pageData()
},
doSearch() {
this.$emit('search', this.pageForm)
}
},
created() {
this.initData()
this.doSearch()
},
style: /*language=CSS*/ `
/deep/ .reverseCheckBox {
margin: 0 10px 0 0 !important;
}
/deep/ .query-row {
min-height: 60px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
/deep/ .query-row:not(:last-child) {
border-bottom: 1px dashed rgb(230, 230, 230);
}
/deep/ .query-row-title {
width: 120px;
}
/deep/ .query-row > .query-title {
width: 100px;
max-width: 100px;
min-width: 100px;
overflow: hidden;
}
/deep/ .query-row > .query-content {
min-width: 200px;
overflow: hidden;
}
/deep/ .query-row > .query-content > .el-tag {
margin-bottom: 5px;
margin-top: 5px;
}
/deep/ .query-row-tag {
padding: 10px 0;
}
/deep/ .query-row-content-tag {
display: flex;
flex-wrap: wrap; /* 标签自动换行 */
align-items: center;
gap: 4px 6px; /* 横纵向间距 */
}
`
}
@@ -0,0 +1,128 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
style="width: 100%"
v-model="pageForm.currentYear"
value-format="yyyy"
:clearable="false"
type="year"
:picker-options="pickerOptions"
placeholder="请选择年度"
></el-date-picker>
</search-item>
<template v-if="pageForm.queryType == 'fgh'">
<search-item label="工会">
<el-select placeholder="分工会" v-model="pageForm.queryId" style="width: 100%" @change="doSearch" clearable filterable>
<el-option v-for="item in unions" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</template>
<template v-else>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" v-model="pageForm.queryId" style="width: 100%" @change="doSearch" clearable filterable>
<el-option v-for="item in units" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</template>
<search-item>
<el-radio-group v-model="pageForm.queryType" @change="pageForm.queryId = '';doSearch()">
<el-radio-button label="fgh">按分工会统计</el-radio-button>
<el-radio-button label="unit">按单位统计</el-radio-button>
</el-radio-group>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="会员统计"></table-tool>
<el-table :data="tableData" show-summary>
<el-table-column
align="center"
header-align="center"
type="index"
:index="indexMethod"
label="序号"
width="80px"
></el-table-column>
<el-table-column v-if="pageForm.queryType=='fgh'" align="center" header-align="center" label="分工会" width="220px">
<template scope="{row}">{{row.unionCode ? ''+row.unionCode+'' : null }}{{row.unionName}}</template>
</el-table-column>
<el-table-column v-if="pageForm.queryType=='unit'" align="center" header-align="center" label="单位" width="220px">
<template scope="{row}">{{row.unitCode?''+row.unitCode+'' : null}}{{row.unitName}}</template>
</el-table-column>
<el-table-column prop="totalNumber" label="总人数" align="center" sortable></el-table-column>
<el-table-column prop="maleMember" label="男会员" align="center" sortable></el-table-column>
<el-table-column prop="femaleMember" label="女会员" align="center" sortable></el-table-column>
<el-table-column prop="smallForty" label="小于等于40岁会员" align="center" sortable></el-table-column>
<el-table-column prop="smallFifty" label="40-50" align="center" sortable></el-table-column>
<el-table-column prop="smallFiftyFive" label="50-55" align="center" sortable></el-table-column>
<el-table-column prop="smallFiftyFive2" label="大于55" align="center" sortable></el-table-column>
</el-table>
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
store,
data: {
pickerOptions: {
disabledDate(time) {
return time.getFullYear() > new Date().getFullYear()
}
},
unions: [],
units: [],
pageForm: {
currentYear: moment().format("YYYY"),
queryType: "fgh"
}
},
methods: {
doExport() {},
initData() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.$businessTool.listUnion().then((data) => {
this.unions = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
})
}
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
created() {
this.initData()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,89 @@
const ADD_PROJECT_COMPONENT = {
template: `
<el-dialog title="名单核对事项" :visible.sync="dialogFormVisible" width="1000px" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="140px" :rules="formRules">
<el-form-item prop="projectName" label="事项名称">
<el-input v-model="formData.projectName" maxlength="100"></el-input>
</el-form-item>
<el-form-item prop="content" label="内容及要求">
<el-input v-model="formData.content" maxlength="500"
rows="3" type="textarea" show-word-limit></el-input>
</el-form-item>
<el-form-item prop="unionIds" label="推送分工会">
<el-transfer filterable :filter-method="filterMethod" :titles="['可选工会', '已选工会']"
filter-placeholder="请输入分工会名称" v-model="formData.unionIds"
:props="{key:'id',label:'name'}" :data="unionData">
</el-transfer>
</el-form-item>
<el-form-item prop="isNeedFeedback" label="是否需要反馈">
<el-radio-group v-model="formData.isNeedFeedback" size="small">
<el-radio :label="true" border>是</el-radio>
<el-radio :label="false" border>否</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="isNeedFeedbackFile" label="是否需要反馈附件">
<el-radio-group v-model="formData.isNeedFeedbackFile" size="small">
<el-radio :label="true" border>是</el-radio>
<el-radio :label="false" border>否</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
`,
data() {
return {
dialogFormVisible: false,
formData: {
isNeedFeedback: true,
isNeedFeedbackFile: true,
unionIds: []
},
formRules: {
projectName: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
content: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
// unionIds: [{required: true, message: "必填", trigger: ["change", "blur"]}],
isNeedFeedback: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
isNeedFeedbackFile: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
},
unionData: []
}
},
methods: {
onOpen() {
this.formData = {
userIds: [],
delegationId: null,
roleId: null
}
this.dialogFormVisible = true
},
filterMethod(query, item) {
return item.name.indexOf(query) > -1
},
async getAllUnions() {
this.unionData = await this.$businessTool.listUnion()
},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios("/platform/member/branch/listVerification/insertOrUpdate", {
data: JSON.stringify(this.formData)
}).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.$emit("refresh")
}
})
}
})
}
},
created() {
this.getAllUnions()
}
}
@@ -0,0 +1,83 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="事项名称">
<el-input placeholder="请输入名单核对事项名称查询" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" border size="small" header-align="center" style="width: 100%">
<el-table-column type="index" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="projectName" label="事项名称" align="center"></el-table-column>
<el-table-column prop="content" label="事项内容及要求" align="center"></el-table-column>
<el-table-column prop="isNeedFeedback" label="是否需要反馈" align="center">
<template scope="{row}">
<span style="color: #00aa3a" v-if="row.isNeedFeedback == 1"></span>
<span style="color: #ac2925" v-else></span>
</template>
</el-table-column>
<el-table-column prop="isNeedFeedbackFile" label="是否需要反馈附件" align="center">
<template scope="{row}">
<span style="color: #00aa3a" v-if="row.isNeedFeedbackFile == 1"></span>
<span style="color: #ac2925" v-else></span>
</template>
</el-table-column>
<el-table-column prop="releaseDateTime" label="发布时间" align="center"></el-table-column>
<el-table-column prop="applyDate" label="创建时间" align="center"></el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="{row}">
<el-link size="mini" type="primary" @click="">查看</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<list-user ref="memberListUserRef" @refresh="doSearch"></list-user>
</template>
</guava>
<add-project ref="addProjectRef"></add-project>
</div>
<script nonce="${cspNonce!}">
<!--#include("listUser.js"){}#-->
<!--#include("addProject.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"list-user": MEMBER_LIST_VERIFICATION_USER_COMPONENT,
"add-project": ADD_PROJECT_COMPONENT,
},
data() {
return {
}
},
methods: {
openAdd() {
this.$refs.addProjectRef.dialogFormVisible = true
}
},
created(){
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,70 @@
const MEMBER_LIST_VERIFICATION_USER_COMPONENT = {
template: `
<div>
<select @search="doSearch">
<search-item label="测试">
<el-input placeholder="测试" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
</select>
<el-table ref="listTable" :data="tableData" @selection-change="doSelectChange"
class="vi-table" row-key="id" style="width: 100%" border>
<el-table-column :reserve-selection="true" type="selection" align="center"></el-table-column>
<el-table-column type="index" label="序号" :index="indexMethod" align="center" width="80px"></el-table-column>
<el-table-column :prop="column.prop" :width="column.width"
align="center" header-align="center"
min-width="100px" show-overflow-tooltip
v-for="column in tableColumns">
<template slot="header" scope="{row}">
<el-checkbox @change="change($event, column.prop)">{{ column.label }}</el-checkbox>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</div>
`,
mixins: [initTableMixins],
dicts: ["ALLOW_FIELD_CHANGES"],
data() {
return {
tableColumns: [],
selectUser: [],
renewFields: []
}
},
methods: {
doRowClick(val) {
console.log(val)
},
change(flag, prop) {
if (flag) {
this.renewFields.push(prop)
} else {
this.renewFields.splice(this.renewFields.indexOf(prop), 1)
}
},
doSelectChange(val) {
this.selectUser = val
},
initTableColumns() {
this.tableColumns = []
this.dict.type.ALLOW_FIELD_CHANGES.forEach((item) => {
this.tableColumns.push({ prop: item.code, label: item.name })
})
},
pageData() {
this.$axios.post("/platform/member/branch/listVerification/getUserPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
created() {
this.pageData()
setTimeout(() => {
this.initTableColumns()
}, 1000)
}
}
@@ -0,0 +1,376 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.top_block {
width: 100%;
padding: 20px 80px;
border-bottom: 10px solid rgb(240, 240, 240);
}
.top_title {
font-size: 14px;
color: #808492;
height: 30px;
line-height: 30px;
margin-bottom: 5px;
}
.top_num {
font-size: 26px;
}
.cut-off-line {
width: 1px;
height: 70%;
position: absolute;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background-color: rgb(230, 230, 230);
}
.chartTitle {
font-size: 14px;
color: #808492;
margin-bottom: 20px;
}
</style>
<div id="app" v-cloak>
<div class="p10">
<el-card shadow="never">
<div class="top_block" v-loading="top_block_loading">
<el-row :gutter="60">
<div style="position: absolute; top: -35px; right: -8px">
<el-date-picker
class="year"
style="width: 120px"
size="mini"
v-model="numForm.startYear"
type="year"
:clearable="false"
value-format="yyyy"
@change="getNumData()"
placeholder="选择年"
></el-date-picker>
-
<el-date-picker
class="year"
style="width: 120px"
size="mini"
v-model="numForm.endYear"
type="year"
:clearable="false"
value-format="yyyy"
@change="getNumData()"
placeholder="选择年"
></el-date-picker>
</div>
<el-col :span="6" style="position: relative">
<div class="top_title">总缴费金额</div>
<div class="top_num">{{numData.payMoney?numData.payMoney:'0'}}</div>
<div class="cut-off-line"></div>
</el-col>
<el-col :span="6" style="position: relative">
<div class="top_title">退款金额</div>
<div class="top_num">{{numData.refundMoney?numData.refundMoney:'0'}}</div>
<div class="cut-off-line"></div>
</el-col>
<el-col :span="6" style="position: relative">
<div class="top_title">退款订单数</div>
<div class="top_num">{{numData.refundSize?numData.refundSize:'0'}}</div>
<div class="cut-off-line"></div>
</el-col>
<el-col :span="6" style="position: relative">
<div class="top_title">总缴费人数</div>
<div class="top_num">{{numData.paySize?numData.paySize:'0'}}</div>
</el-col>
</el-row>
</div>
<el-row style="padding: 30px 0; border-bottom: 10px solid rgb(240, 240, 240)">
<div style="position: absolute; top: 25px; right: 40px; z-index: 200">
<el-date-picker
class="year"
style="width: 120px"
size="mini"
v-model="oneForm.startYear"
type="year"
:clearable="false"
value-format="yyyy"
@change="getPayProjectChart();getPayMoneyChart()"
placeholder="选择年"
></el-date-picker>
-
<el-date-picker
class="year"
style="width: 120px"
size="mini"
v-model="oneForm.endYear"
type="year"
:clearable="false"
value-format="yyyy"
@change="getPayProjectChart();getPayMoneyChart()"
placeholder="选择年"
></el-date-picker>
</div>
<el-col :span="12" style="padding: 0 20px" v-loading="payProjectLoading">
<div class="chartTitle">已缴人数</div>
<div id="payProjectChart" style="width: 100%; height: 330px"></div>
</el-col>
<el-col :span="12" style="padding: 0 20px" v-loading="payMoneyLoading">
<div class="chartTitle">已缴金额</div>
<div id="payMoneyChart" style="width: 100%; height: 330px"></div>
</el-col>
</el-row>
<el-row style="padding: 30px 0; border-bottom: 10px solid rgb(240, 240, 240)">
<div style="position: absolute; top: 25px; right: 250px; z-index: 999">
<el-date-picker
class="year"
style="width: 120px"
size="mini"
v-model="unionForm.year"
type="year"
:clearable="false"
value-format="yyyy"
@change="getProjectList"
placeholder="选择年"
></el-date-picker>
</div>
<div style="position: absolute; top: 25px; right: 40px; z-index: 999">
<el-select
placeholder="请选择项目"
v-model="unionForm.paymentProjectId"
style="width: 100%"
size="mini"
:clearable="false"
@change="doSearch"
@clear="doSearch"
filterable
>
<el-option v-for="item in paymentProjectList"
:label="item.projectName" :value="item.id"></el-option>
</el-select>
</div>
<el-col :span="24" style="padding: 0 20px" v-loading="all_union_loading">
<div class="chartTitle" style="margin-bottom: 50px">
</div>
<div id="allUnionChart" style="width: 100%; height: 300px"></div>
</el-col>
</el-row>
</el-card>
</div>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
oneForm: {
startYear: new Date().getFullYear() - 2 + "",
endYear: new Date().getFullYear() + ""
},
twoForm: {
startYear: new Date().getFullYear() - 2 + "",
endYear: new Date().getFullYear() + ""
},
numForm: {
startYear: new Date().getFullYear() - 2 + "",
endYear: new Date().getFullYear() + ""
},
payProjectLoading: false,
refundProjectLoading: false,
payMoneyLoading: false,
top_block_loading: false,
numData: {},
all_union_loading: false,
unionForm: {
year: new Date().getFullYear() + ""
},
paymentProjectList: []
}
},
methods: {
async getNumData() {
this.top_block_loading = true
const resp = await this.$axios.post("/platform/member/payment/chartSummary/getNumData", this.numForm)
if (resp.code === 0) {
this.numData = resp.data
}
this.top_block_loading = false
},
async getPayProjectChart() {
this.payProjectLoading = true
const resp = await this.$axios.post("/platform/member/payment/chartSummary/getPayProjectChart", this.oneForm)
if (resp.code === 0) {
let { data } = resp
document.getElementById("payProjectChart").innerHTML = ""
const config = {
xField: "projectName",
yField: "num",
label: {
position: "middle", // 'top', 'bottom', 'middle',
style: {
fill: "#FFFFFF",
opacity: 0.6
}
},
xAxis: {
label: {
autoHide: true,
autoRotate: false
}
},
meta: {
projectName: {
alias: "项目"
},
num: {
alias: "缴费人数"
}
}
}
const plot = new G2Plot.Column(document.getElementById("payProjectChart"), {
data,
...config
})
plot.render()
}
this.payProjectLoading = false
},
async getPayMoneyChart() {
this.payMoneyLoading = true
const resp = await this.$axios.post("/platform/member/payment/chartSummary/getPayMoneyChart", this.oneForm)
if (resp.code === 0) {
let { data } = resp
document.getElementById("payMoneyChart").innerHTML = ""
const config = {
xField: "projectName",
yField: "money",
label: {
position: "middle", // 'top', 'bottom', 'middle',
style: {
fill: "#FFFFFF",
opacity: 0.6
}
},
xAxis: {
label: {
autoHide: true,
autoRotate: false
}
},
meta: {
projectName: {
alias: "项目"
},
money: {
alias: "金额(元)"
}
}
}
const plot = new G2Plot.Column(document.getElementById("payMoneyChart"), {
data,
...config
})
plot.render()
}
this.payMoneyLoading = false
},
async allUnionMoney() {
this.all_union_loading = true
const resp = await this.$axios.post("/platform/member/payment/chartSummary/allUnionMoney", {
paymentProjectId: this.unionForm.paymentProjectId
})
if (resp.code === 0) {
let { data } = resp
document.getElementById("allUnionChart").innerHTML = ""
const config = {
isStack: true,
legend: {
position: "top-right",
flipPage: false
},
autoFit: true,
title: {
visible: true,
text: ""
},
description: {
visible: true,
text: "单位(元)"
},
xField: "unionname",
yField: "money",
stackField: "type",
color: ["#5B8FF9", "#5AD8A6"],
xAxis: {
label: {
formatter: (v) => {
if (data.length > 30 && v.length > 3) {
return v.substr(0, 2) + "..."
} else if (data.length > 20 && v.length > 4) {
return v.substr(0, 3) + "..."
} else if (data.length > 10 && v.length > 6) {
return v.substr(0, 5) + "..."
}
return v
}
}
},
yAxis: {},
meta: {
unionname: {
alias: "工会"
},
money: {
alias: "金额"
}
},
connectedArea: {
visible: true,
triggerOn: false
}
}
const plot = new G2Plot.Column(document.getElementById("allUnionChart"), {
data,
...config
})
plot.render()
}
this.all_union_loading = false
},
async getProjectList() {
const resp = await this.$axios.post("/platform/member/payment/project/getAllProject", { year: this.unionForm.year })
if (resp.code === 0) {
this.paymentProjectList = resp.data
this.$set(this.unionForm, "paymentProjectId", (this.paymentProjectList && this.paymentProjectList.length > 0) ? this.paymentProjectList[0].id : null)
await this.allUnionMoney()
}
}
},
async created() {
await this.getPayProjectChart()
await this.getPayMoneyChart()
await this.getNumData()
await this.getProjectList()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,370 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-input-group__append {
border-left: 0;
padding: 0 13px;
height: 40px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch" ref="search">
<search-item label="缴费配置">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入缴费配置"
style="width: 100%"
v-model="pageForm.name">
</el-input>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="缴费配置列表">
<el-button @click="openAdd" size="small" type="primary">
新增缴费配置
</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table" row-key="id" style="width: 100%"
v-loading="tableLoading">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<el-switch
:active-value="false"
:inactive-value="true"
@change="(val)=>{configStatusChange(row.id)}"
active-color="#13ce66"
inactive-color="#ff4949"
v-model="row.isDisabled">
</el-switch>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px">
<template scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button :loading="submitLoading" plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'edit',data:scope.row}">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'remove',data:scope.row}">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<el-form :model="formData" ref="addForm" :rules="rules"
label-width="120px"
style="margin: 10px 0 0 0">
<div class="process-title">缴费配置</div>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="配置名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="缴费月份" prop="paymentMonth" size="medium">
<el-date-picker
v-model="formData.paymentMonth"
type="monthrange"
range-separator="至"
style="width: 100%"
value-format="yyyy-MM"
start-placeholder="开始月份"
end-placeholder="结束月份">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<div class="process-title">缴纳标准</div>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item class="is-required" label="会费缴纳情况" prop="payStandard">
<el-button @click="formData.payStandards.push({payPersonnel: null, payMode: '1', personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]})" icon="el-icon-plus" size="mini"
style="float: right;margin-bottom: 10px">
添加
</el-button>
<span style="color: red">说明:不同人员类型可根据不同缴费模式设置缴费标准。</span>
<el-table
:data="formData.payStandards"
border
v-fit-columns
size="mini"
style="width: 100%">
<el-table-column label="缴费人员" prop="payPersonnel" width="200">
<template scope="{row,$index}">
<el-form-item :prop="'payStandards.'+$index+'.payPersonnel'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<el-select placeholder="请选择在职状态" v-model="row.payPersonnel"
style="width: 100%" clearable>
<el-option v-for="item in userStateList" :label="item.name" :value="item.code"></el-option>
</el-select>
<!-- <el-input clearable maxlength="100" placeholder="请输入缴费人员"
v-model="row.payPersonnel"></el-input>-->
<!--<el-select placeholder="请选择人员类型" v-model="row.payPersonnel"
style="width: 100%" clearable>
<el-option v-for="item in memberTypeList" :label="item.name" :value="item.code"></el-option>
</el-select>-->
</el-form-item>
</template>
</el-table-column>
<el-table-column label="教职工类别" prop="personType" >
<template slot-scope="{row,$index}">
<el-select @change="row.payMode=null" placeholder="请选择人员类型" v-model="row.personType"
style="width: 100%" clearable>
<el-option v-for="item in personTypeList" :label="item.name" :value="item.code"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="缴费模式" prop="payMode" >
<template scope="{row,$index}">
<el-form-item :prop="'payStandards.'+$index+'.payMode'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<el-select placeholder="请选择缴费模式" v-model="row.payMode"
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>
</template>
</el-table-column>
<!-- <el-table-column label="在职状态" prop="userState" >
<template slot-scope="{row,$index}">
<el-select placeholder="请选择在职状态" v-model="row.userState"
style="width: 100%" clearable>
<el-option v-for="item in userStateList" :label="item.name" :value="item.code"></el-option>
</el-select>
</template>
</el-table-column>-->
<el-table-column label="缴费标准" prop="payModeValue" width="650">
<template scope="{row,$index}">
<div v-if="row.payMode=='2'">
<el-form-item :prop="'payStandards.'+$index+'.payModeValueList'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<div style="display:flex;justify-content: space-between;margin-left: 30px">
(
<template v-for="(o,i) in row.payModeValueList" >
<el-input placeholder="" style="width: 100px;"
v-model="o.name">
<el-button @click="row.payModeValueList.splice(i, 1)" slot="append" style="padding: 0 7px;"
icon="el-icon-circle-close"></el-button>
</el-input>
<span v-if="i !== row.payModeValueList.length - 1">+</span>
</template>
) * 0.5%
<div>
<el-button @click="row.payModeValueList.push({name: '',value:''})" size="mini">新增</el-button>
</div>
</div>
</el-form-item>
</div>
<div v-else-if="row.payMode == '1' || row.payMode == '3'">
<el-form-item :prop="'payStandards.'+$index+'.payModeValue'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<div v-if="row.payMode == '1'">
<el-input clearable maxlength="5" type="number" placeholder="请输入缴费金额"
v-model="row.payModeValue"></el-input>
</div>
<div v-if="row.payMode == '3'" style="text-align: center">
<span>导入名单</span>
</div>
<!-- <el-input clearable maxlength="100" placeholder="请填写缴费标准"-->
<!-- v-model="row.payModeValue"></el-input>-->
</el-form-item>
</div>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="80">
<template slot-scope="scope">
<el-button :disabled="formData.payStandards.length<=1"
@click="formData.payStandards.splice(scope.$index,1)" circle
icon="el-icon-delete"
size="mini"
type="danger"></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button @click="doSubmit" v-if="isSubmit" v-loading="submitLoading" style="float: right"
type="primary">
提交
</el-button>
</div>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
payModeList:[{code:'1',value:'固定金额缴纳'},{code:'2',value:'按比例缴纳'},{code:'3',value:'导入'}],
formData: {
payStandards: [{payPersonnel: null, payMode: null, personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]}]
},
rules: {
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
paymentMonth: [{required: true, message: '必填', trigger: ['blur', 'change']}],
exit: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
personTypeList:[],
userStateList:[],
memberTypeList:[],
pageForm:{},
tableData:[],
tableColumns:[
{prop: 'name', label: '配置名称'},
{prop: 'paymentStartMonth', label: '缴费起始月份'},
{prop: 'paymentEndMonth', label: '缴费截止月份'},
{prop: 'isDisabled', label: '开启状态'},
],
isSubmit: true,
}
},
methods: {
dropdownCommand(command) {
const {type, data} = command
if (type === 'view') {
this.openView(data)
} else if (type === 'edit') {
this.openEdit(data)
} else if (type === 'remove') {
this.doRemove(data.id)
}
},
openAdd(){
this.$refs.guava.view()
},
async doRemove(id) {
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await this.$axios.post(loc() + '/doRemove', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async configStatusChange(id) {
const resp = await this.$axios.post(loc() + '/openClosedConfig', { id: id })
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
openEdit(data) {
this.formData = {}
this.formData = {
...data,
paymentMonth:[data.paymentStartMonth, data.paymentEndMonth],
}
this.formData.payStandards= JSON.parse(this.formData.payStandards)
this.isSubmit = true
this.$refs.guava.view()
},
async doSubmit(){
this.formData.paymentStartMonth = this.formData.paymentMonth[0]
this.formData.paymentEndMonth = this.formData.paymentMonth[1]
const formData = clone(this.formData)
formData.payStandards = JSON.stringify(this.formData.payStandards)
const resp = await this.$axios.post(loc() + '/doAddOrModify',formData)
if (resp.code === 0){
this.$refs.guava.index()
await this.getPaymentConfig()
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
},
async getPaymentConfig(){
const resp = await this.$axios.post(loc() + '/getPaymentConfig')
if (resp.code === 0){
this.formData = {...resp.data}
if (!this.formData.payStandards){
this.formData = {
payStandards: [{payPersonnel: null, payMode: '1', personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]}]
}
}
}
}
},
async created() {
this.pageData()
this.personTypeList = await this.$businessTool.getDictOptions('USER_PERSON_TYPE')
//在职状态
this.userStateList = await this.$businessTool.getDictOptions('USER_STATE')
//会员类型
// this.memberTypeList = await getDictOptions('memberType')
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,368 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.payForm .el-form-item__label {
font-weight: bold;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
:clearable="false"
@change="doSearch"
placeholder="请选择年度"
type="year"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="缴费列表">
<el-radio-group @change="doSearch" class="mr10" size="small"
v-model="pageForm.isPay">
<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"
:size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table"
row-key="id"
style="width: 100%"
v-loading="tableLoading"
>
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isPayment'">
<template v-if="row.isPayment">
<el-tag v-if="row.isPayment && !row.isRefund" type="success">已缴费</el-tag>
<el-tag v-else type="danger">
{{ getRefundStates(row.refundState) }}
</el-tag>
</template>
<el-tag v-else type="danger">未缴费</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop==='paymentStartMonth'">
{{row.paymentStartMonth}}至{{row.paymentEndMonth}}
</template>
<template scope="{row}" v-else-if="column.prop==='paymentMoney'">
{{ row.payMoney ? (Number(row.paymentMoney) / 100) : 0 }}
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="200px">
<template scope="{row}">
<el-button @click="showPayInfo(row)" size="mini" type="primary">查看详情</el-button>
<el-button v-if="!row.isPayment" @click="openPay(row)" size="mini" type="primary">缴费</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<pay-info :trading-states="tradingStates" :refund-states="refundStates"
:trading-channels="tradingChannels" ref="payInfoRef"></pay-info>
</template>
</guava>
<el-diaLog :close-on-click-modal="false" :visible.sync="payVisible" title="缴费" width="50%"
:before-close="clickClose">
<el-form ref="form" :model="formData" :rules="formRules" label-width="170px"
label-suffix="" class="payForm">
<el-steps :active="payActive" finish-status="success">
<el-step title="计算缴费金额"></el-step>
<el-step title="生成缴费二维码"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<div v-if="payActive===0" class="mt25">
<el-form-item label="缴费所属时间">
<div>{{formData.paymentStartMonth}}至{{formData.paymentEndMonth}}</div>
</el-form-item>
<el-form-item label="缴费标准">
<div style="color: red"
v-if="formData.payModeValueList&&formData.payModeValueList.length>0">
(
<template v-for="(o,i) in formData.payModeValueList">
{{o.name}}
<template v-if="i !=formData.payModeValueList.length-1">+</template>
</template>
) * 0.5% * {{formData.paymentMonth}}个月
</div>
<div v-else>固定金额缴费</div>
</el-form-item>
<!--如果是根据比例算的-->
<div v-if="formData.payModeValueList&&formData.payModeValueList.length>0">
<div v-for="(o,i) in formData.payModeValueList" :key="o.id">
<el-form-item :label="o.name">
<el-input-number v-model="o.value" :min="0" :max="1000000"
:precision="2"
placeholder="请输入缴费金额"
@change="changePayModeValue(o)"></el-input-number>
</el-form-item>
</div>
</div>
<el-form-item label="支付金额">
<div style="color: #2cd000;font-size: 25px">¥ {{formData.paymentMoney}}</div>
</el-form-item>
</div>
<div v-if="payActive===1" class="mt25">
<el-form-item label="商品订单">
{{formData.transactionId}}
</el-form-item>
<el-form-item label="支付金额">
<div style="color: #2cd000;font-size: 25px">¥ {{formData.paymentMoney}}</div>
</el-form-item>
<div style="width: 100%;">
<el-row :gutter="20">
<el-col :span="12" v-loading="qrcodeLoading">
<div style="text-align: center">
<image :src="paySrc" style="width: 60%;left: 0;right: 0;margin: auto"></image>
<div style="display: flex;justify-content: center">
<span
style="font-weight: bold;
font-size: 15px;
color: #fbfbfb;
background-color: rgb(44, 208, 0);
height: 30px;
width: 60%;
display: flex;
justify-content: center;
align-items: center;">
请打开手机微信,扫一扫完成支付</span>
</div>
</div>
</el-col>
<el-col :span="12">
<div>
<el-image src="/assets/mobile/svg/memberPay/wx_img.png"></el-image>
</div>
</el-col>
</el-row>
</div>
</div>
<div v-if="payActive===3">
<div v-loading="submitLoading">
<div style="margin-top: 35px;background-color: RGB(245, 254, 243);">
<div
style="display: flex;align-items: center;height: 100px;margin-left: 10%">
<div>
<el-image
src="/assets/mobile/svg/memberPay/pcPaySuccess.svg"></el-image>
</div>
<div style="font-weight: bold;font-size: 25px;margin-left: 10px;">
支付成功!
</div>
</div>
</div>
<el-form-item label="商品订单">
{{formData.transactionId}}
</el-form-item>
<el-form-item label="支付金额">
<div style="color: #2cd000;font-size: 25px">¥ {{formData.paymentMoney}}
</div>
</el-form-item>
</div>
</div>
</el-form>
<div style="text-align: right">
<span>
<el-button @click="clickClose">关 闭</el-button>
<el-button @click="next" v-if="payActive===0&&formData.paymentMoney>0"
type="primary">下一步</el-button>
</span>
</div>
</el-diaLog>
</div>
<script src="${base!}/assets/platform/plugins/jr-qrcode/jr-qrcode.js"></script>
<script nonce="${cspNonce!}">
<!--#include("minePayInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
'pay-info': MINE_PAY_INFO,
},
data() {
return {
tableColumns: [
{ prop: "year", label: "年度", sortable: true },
{ prop: "projectName", label: "项目名称", sortable: true },
{ prop: "startTime", label: "缴费开始时间", sortable: true },
{ prop: "endTime", label: "缴费截止时间", sortable: true },
{ prop: "paymentStartMonth", label: "缴费所属时间", sortable: true },
{ prop: "paymentMoney", label: "缴费金额(元)", sortable: true },
{ prop: "isPayment", label: "缴费状态", sortable: true }
],
pageForm: {
isPay: false,
year: moment().format("YYYY")
},
payVisible: false,
payActive: 0,
intervalTimer: null,
qrcodeLoading: false,
payInfo: {},
tradingStates: [],
refundStates: [],
tradingChannels: [],
paySrc: ''
}
},
methods: {
async showPayInfo(row) {
this.$refs.guava.view(() => {
this.$refs.payInfoRef.onOpen(row.id)
})
},
clickClose() {
if (this.payActive === 3) {
this.payVisible = false
} else {
this.$confirm("您确定要关闭当前缴费吗?关闭后将不会保存当前数据", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.payVisible = false
})
}
clearInterval(this.intervalTimer)
},
next() {
this.$confirm("您确定要生成缴费二维码吗?当前需缴费【" + this.formData.paymentMoney + "】元", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
this.qrcodeLoading = true
const paymentMoney = Math.floor(this.formData.paymentMoney * 100)
this.payActive = this.payActive + 1
const resp = await $.post("/platform/member/payment/mine/pcOrderPay", {
paymentMoney: paymentMoney,
paymentInfoId: this.formData.paymentInfoId
})
if (resp.code === 0) {
const data = JSON.parse(resp.data)
this.$nextTick(() => {
// $("#qrcode").html("")
// $("#qrcode").qrcode({
// render: "canvas",
// width: $("#qrcode").width(),
// height: $("#qrcode").width(),
// text: data.code_url,
// correctLevel: 3
// })
this.paySrc = jrQrcode.getQrBase64(data.code_url, {
padding: 10, // 内边距
width: 200, // 图片宽度
height: 200, // 图片高度
correctLevel: 2, // 容错级别 0-3
foreground: '#000', // 前景色
background: '#fff' // 背景色
})
})
this.formData.transactionId = data.transactionId
await this.getIsPay()
}
this.qrcodeLoading = false
})
},
async getIsPay() {
this.intervalTimer = setInterval(async () => {
const resp = await this.$axios.post(loc() + "/getIsPay", { paymentInfoId: this.formData.paymentInfoId })
if (resp.code === 0) {
if (resp.data) {
this.payActive = 3
this.submitLoading = true
clearInterval(this.intervalTimer)
setTimeout(() => {
this.submitLoading = false
this.pageData()
}, 1500)
}
}
}, 4000)
},
changePayModeValue() {
let paymentMoney = this.formData.payModeValueList.reduce((a, b) => {
return a + b.value
}, 0)
this.$set(this.formData, "paymentMoney", parseFloat((paymentMoney * 0.005 * this.formData.paymentMonth).toFixed(2)))
},
openPay(row) {
debugger
this.payActive = 0
const payStandards = JSON.parse(row.payStandards)
const payStandard = payStandards.find(p => p.payPersonnel === row.userState && p.personType === row.personType)
this.$set(this.formData, "paymentMonth", row.paymentMonth)
this.$set(this.formData, "paymentStartMonth", row.paymentStartMonth)
this.$set(this.formData, "paymentEndMonth", row.paymentEndMonth)
this.$set(this.formData, "paymentInfoId", row.id)
if (payStandard && payStandard.payModeValue) {
this.$set(this.formData, "payModeValueList", [])
this.$set(this.formData, "paymentMoney", payStandard.payModeValue)
} else {
this.$set(this.formData, "payModeValueList", payStandard.payModeValueList)
this.$set(this.formData, "paymentMoney", 0)
}
this.payVisible = true
},
getRefundStates(data) {
if (!data) {
return
}
return this.refundStates.find(item => item.name === data).refundStateName
},
async getPaymentEnums() {
this.tradingStates = await this.$businessTool.getEnumOptions("TradingStateEnum")
this.refundStates = await this.$businessTool.getEnumOptions("RefundStateEnum")
this.tradingChannels = await this.$businessTool.getEnumOptions("TradingChannelEnum")
}
},
created() {
this.pageData()
this.getPaymentEnums()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,125 @@
const MINE_PAY_INFO = {
template: /*language=html*/ `
<div>
<el-descriptions title="缴费信息" :column="3" border>
<el-descriptions-item label="工号">{{ viewData.loginname }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ viewData.username }}</el-descriptions-item>
<el-descriptions-item label="缴费项目">{{ viewData.projectName }}</el-descriptions-item>
<el-descriptions-item label="所在工会">{{ viewData.unionname }}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{ viewData.unitname }}</el-descriptions-item>
<el-descriptions-item label="教职工类别">{{ viewData.personType }}</el-descriptions-item>
<el-descriptions-item label="缴费情况">
<el-tag v-if="viewData.personType">已缴费</el-tag>
<el-tag v-else type="warning">未缴费</el-tag>
</el-descriptions-item>
<el-descriptions-item label="缴费金额">{{ viewData.paymentMoney }}</el-descriptions-item>
<el-descriptions-item label="缴费月份时长">{{ viewData.paymentMonth }}</el-descriptions-item>
<template v-if="viewData.transList">
<el-descriptions-item label="缴费订单详情" :span="3">
<el-table :data="viewData.transList" class="vi-table" ref="table" row-key="id"
style="width: 100%" border>
<el-table-column label="系统单号" prop="outTradeNo"></el-table-column>
<el-table-column label="商户订单号" prop="transactionId"></el-table-column>
<el-table-column label="付款方式" prop="tradingChannel">
<template scope="{row}">
{{ getTradingChannel(row.tradingChannel) }}
</template>
</el-table-column>
<el-table-column label="订单金额(¥)" prop="tradingAmount">
<template scope="{row}">
{{ row.tradingAmount ? (Number(row.tradingAmount) / 100 ) : 0 }}
</template>
</el-table-column>
<el-table-column label="下单时间" prop="createdAt">
<template scope="{row}">
{{ moment(row.createdAt).format("YYYY-MM-DD HH:mm:ss") }}
</template>
</el-table-column>
<el-table-column label="订单状态" prop="tradingState">
<template scope="{row}">
{{ getTradingStates(row.tradingState) }}
</template>
</el-table-column>
<el-table-column label="退款详情" prop="isRefund" width="200">
<template scope="{row}">
<el-tag v-if="!row.isRefund">未退款</el-tag>
<el-tag v-else type="danger" style="cursor: pointer;"
@click="showRefundInfo(row)">此订单有退款,点我查看详情</el-tag>
</template>
</el-table-column>
</el-table>
</el-descriptions-item>
</template>
</el-descriptions>
<el-dialog title="退款详情" :visible.sync="refundDialogVisible" width="50%" append-to-body>
<el-descriptions :column="1" border>
<el-descriptions-item label="退款单号">{{ refundData.outRefundTradeNo }}</el-descriptions-item>
<el-descriptions-item label="退款商户号">{{ refundData.refundNo }}</el-descriptions-item>
<el-descriptions-item label="退款金额(¥)">
{{ refundData.total ? (Number(refundData.total) / 100) : 0 }}
</el-descriptions-item>
<el-descriptions-item label="退款时间">{{ moment(refundData.updatedAt).format("YYYY-MM-DD HH:mm:ss") }}</el-descriptions-item>
<el-descriptions-item label="退款状态">
{{ getRefundStates(refundData.refundState) }}
</el-descriptions-item>
</el-descriptions>
<span slot="footer" class="dialog-footer">
<el-button @click="refundDialogVisible = false;refundData = {}">关 闭</el-button>
</span>
</el-dialog>
</div>
`,
props: {
tradingStates: { type: Array, default: () => [] },
refundStates: { type: Array, default: () => [] },
tradingChannels: { type: Array, default: () => [] },
},
data() {
return{
viewData: {},
refundData: {},
refundDialogVisible: false
}
},
methods: {
showRefundInfo(row) {
this.refundData = {}
this.refundData = this.viewData.refundRecordList.find(item => item.paymentTransactionId === row.id)
if (this.refundData) {
this.refundDialogVisible = true
} else {
this.$message.error("此订单无退款记录")
}
},
async onOpen(id) {
const resp = await $.post('/platform/member/payment/mine/getPaymentInfoById', {id})
if (resp.code === 0) {
this.viewData = resp.data
} else {
this.$message.error("操作失败")
}
},
getTradingStates(data) {
if (!data) {
return
}
return this.tradingStates.find(item => item.name === data).tradingStateName
},
getRefundStates(data) {
if (!data) {
return
}
debugger
return this.refundStates.find(item => item.name === data).refundStateName
},
getTradingChannel(data) {
if (!data) {
return
}
return this.tradingChannels.find(item => item.name === data).tradingChannelName
},
}
}
@@ -0,0 +1,410 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-input-group__append {
border-left: 0;
padding: 0 7px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch" ref="searchRef">
<search-item label="年度">
<el-date-picker
:clearable="false"
clearable
@change="doSearch"
placeholder="请选择年度"
type="year" style="width: 100%"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="缴费项目">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入缴费项目"
style="width: 100%"
v-model="pageForm.projectName">
</el-input>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="缴费项目列表">
<el-button @click="openAdd" size="small" type="primary">
新增缴费项目
</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table" row-key="id" style="width: 100%"
v-loading="tableLoading">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<el-switch
:active-value="false"
:inactive-value="true"
@change="(val)=>{projectStatusChange(row.id)}"
active-color="#13ce66"
inactive-color="#ff4949"
v-model="row.isDisabled">
</el-switch>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px">
<template scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button :loading="submitLoading" plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'openCode',data:scope.row}">
二维码
</el-dropdown-item>
<el-dropdown-item :command="{type:'view',data:scope.row}">
查看
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',data:scope.row}">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'doRenew',data:scope.row}"
v-if="scope.row.created">
更新缴费人员
</el-dropdown-item>
<el-dropdown-item :command="{type:'doSet',data:scope.row}">
{{scope.row.created?'重置缴费人员':'生成缴费人员'}}
</el-dropdown-item>
<el-dropdown-item :command="{type:'remove',data:scope.row}">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<el-form :model="formData" :rules="formRules" label-width="100px" ref="form">
<div class="process-title">缴费项目信息</div>
<el-form-item label="项目名称" prop="projectName">
<el-input maxlength="100" placeholder="项目名称" v-model="formData.projectName"></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="缴费年度" prop="year">
<el-date-picker
:clearable="false"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="formData.year"
value-format="yyyy">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="创建日期" prop="createTime">
<el-date-picker
placeholder="创建日期"
readonly
style="width: 100%"
type="date"
v-model="formData.createTime"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="缴费配置" prop="configId" size="medium">
<el-select placeholder="请选择缴费配置" v-model="formData.configId"
style="width: 100%" clearable>
<el-option
v-for="item in configList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="缴费时间" prop="paymentTime" size="medium">
<el-date-picker
v-model="formData.paymentTime"
type="daterange"
value-format="yyyy-MM-dd"
range-separator="至"
style="width: 100%"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button @click="doSave" v-if="isSubmit" v-loading="submitLoading" style="float: right"
type="primary">
提交
</el-button>
</div>
</template>
<!-- <open-qr-code ref="openQRCode"></open-qr-code>-->
</guava>
<el-dialog title="二维码" width="30%" :visible.sync="dialogVisible" style="text-align: center">
<img :src="qrSrc" alt="二维码" />
</el-dialog>
</div>
<script src="${base!}/assets/platform/plugins/jr-qrcode/jr-qrcode.js"></script>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
isSubmit: true,
pageForm: {
year: moment().format('YYYY'),
},
tableColumns: [
{prop: 'year', label: '年度', sortable: true},
{prop: 'projectName', label: '项目名称', sortable: true},
{prop: 'startTime', label: '缴费开始时间', sortable: true},
{prop: 'endTime', label: '缴费截止时间', sortable: true},
{prop: 'createTime', label: '创建时间', sortable: true},
{prop: 'isDisabled', label: '开启状态'},
],
formData: {
year: moment().format('YYYY'),
},
formRules: {
projectName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
year: [{required: true, message: '必填', trigger: ['blur', 'change']}],
paymentMonth: [{required: true, message: '必填', trigger: ['blur', 'change']}],
paymentTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
configId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
paymentConfig: {},
monthSelect: [],
configList:[],
// 二维码展示
dialogVisible: false,
qrSrc: '',
}
},
components: {
// 'open-qr-code': httpVueLoader('/components/plugins/OpenQRCode.vue'),
},
methods: {
dropdownCommand(command) {
const {type, data} = command
if (type === 'openCode') {
this.openCode(data)
} else if (type === 'view') {
this.openView(data)
} else if (type === 'edit') {
this.openEdit(data)
} else if (type === 'doRenew') {
this.doRenewPayment(data.id)
} else if (type === 'doSet') {
this.doSetPayment(data)
} else if (type === 'remove') {
this.doRemove(data.id)
}
},
openCode(row) {
// this.$refs.openQRCode.openCode('/mobile/memberCost/list')
this.qrSrc = jrQrcode.getQrBase64("/mobile/memberCost/list", {
padding: 10, // 内边距
width: 400, // 图片宽度
height: 400, // 图片高度
correctLevel: 2, // 容错级别 0-3
foreground: '#000', // 前景色
background: '#fff' // 背景色
})
this.dialogVisible = true
},
openView(data) {
this.formData = {}
this.formData = {
...data,
paymentTime:[data.startTime, data.endTime],
}
this.isSubmit = false
this.$refs.guava.view()
},
openEdit(data) {
this.formData = {}
this.formData = {
...data,
paymentTime:[data.startTime, data.endTime],
}
this.isSubmit = true
this.$refs.guava.view()
},
async doRenewPayment(id) {
this.$confirm('系统根据现有的会员,更新当前缴费名单,对已经缴费人员没有影响,请确认是否更新?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" === a) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.submitLoading = true
const resp = await this.$axios.post(loc() + '/doSetPayment', {id: id, isRenew: true})
this.submitLoading = false
loading.close()
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
async doSetPayment(row) {
let msg = row.created ? "请确认是否重新生成缴费名单,如果确认,系统将清空已缴费的人员信息!" : "确定要生成缴费名单吗?"
this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" === a) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.submitLoading = true
const resp = await this.$axios.post(loc() + '/doSetPayment', {id: row.id, isRenew: false})
this.submitLoading = false
loading.close()
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
async doRemove(id) {
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await this.$axios.post(loc() + '/doRemove', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
openAdd() {
this.formData = {
createTime: moment().format('YYYY-MM-DD HH:mm:ss'),
year: moment().format('YYYY'),
}
this.$refs.guava.view()
},
async doSave() {
const formValid = await this.$refs["form"].validate()
if (formValid) {
this.submitLoading = true
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.formData.startTime=this.formData.paymentTime[0]
this.formData.endTime=this.formData.paymentTime[1]
const formData = clone(this.formData)
const resp = await this.$axios.post(loc() + '/doSave', formData)
loading.close()
this.submitLoading = false
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.$refs.guava.index()
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async projectStatusChange(id) {
const resp = await this.$axios.post(loc() + '/openClosedProject', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
async getPaymentConfigList(id) {
const resp = await this.$axios.post('/platform/member/payment/config/getPaymentConfigList')
if (resp.code === 0) {
this.configList = resp.data
}
},
},
async created() {
await this.getPaymentConfigList()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,185 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
:clearable="false"
@change="doSearch();getProjectList()"
placeholder="请选择年度"
type="year"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="缴费项目">
<el-select
placeholder="请选择项目"
v-model="pageForm.paymentProjectId"
style="width: 100%"
:clearable="false"
@change="doSearch"
@clear="doSearch"
filterable="true"
>
<el-option v-for="item in paymentProjectList"
:label="item.projectName" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" v-model="pageForm.searchKeyword" clearable></el-input>
</search-item>
<search-item label="交易单号">
<el-input placeholder="请输入交易单号"
v-model="pageForm.transactionId" clearable>
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="缴费列表">
<el-radio-group @change="doSearch" class="mr10" size="small"
v-model="pageForm.isRefund">
<el-radio-button :label="3">全部</el-radio-button>
<el-radio-button :label="0">未退款</el-radio-button>
<el-radio-button :label="1">已退款</el-radio-button>
</el-radio-group>
</table-tool>
<el-table
:data="tableData"
:size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table"
row-key="id"
style="width: 100%"
v-loading="tableLoading"
>
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isRefund'">
<span v-if="row.isRefund" style="color: red">已全额退款</span>
<span v-else style="color: #2cd000">支付成功</span>
</template>
<template scope="{row}" v-else-if="column.prop==='tradingAmount'">
{{row.tradingAmount*0.01}}
</template>
<template scope="{row}" v-else-if="column.prop==='refundTime'">
<span v-if="!row.refundTime"></span>
<span
v-else>{{moment(row.refundTime).format("YYYY-MM-DD HH:mm:ss")}}</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="200px">
<template scope="{row}">
<el-button :disabled="row.isRefund" @click="doRefund(row)"
size="mini" type="danger" :loading="submitLoading">退款
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
paymentProjectList: [],
pageForm: {
isRefund: 3,
year: moment().format("YYYY")
},
tableColumns: [
{ prop: "loginName", label: "工号", sortable: true },
{ prop: "userName", label: "姓名", sortable: true },
{ prop: "unitName", label: "单位", sortable: true },
{ prop: "unionName", label: "工会", sortable: true },
{ prop: "projectName", label: "项目名称", sortable: true },
{ prop: "tradingAmount", label: "缴费金额(元)", sortable: true },
{ prop: "paymentTime", label: "支付时间", sortable: true },
{ prop: "transactionId", label: "交易单号", sortable: true },
{ prop: "isRefund", label: "是否退款", sortable: true },
{ prop: "refundTime", label: "退款到账时间", sortable: true }
]
}
},
methods: {
doRefund(row) {
this.$confirm("退款将在24小时内到账,退款后将不能撤回!您确定要退款吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
this.submitLoading = true
const resp = await this.$axios.post("/platform/member/payment/refund/doRefund", {
id: row.id
})
this.submitLoading = false
if (resp.code === 0) {
this.doSearch()
this.$message({
type: "success",
message: resp.msg
})
} else {
this.$message({
type: "error",
message: resp.msg
})
}
})
},
async getProjectList() {
const resp = await this.$axios.post("/platform/member/payment/project/getAllProject", { year: this.pageForm.year })
if (resp.code === 0) {
this.paymentProjectList = resp.data
this.$set(this.pageForm, "paymentProjectId", this.paymentProjectList ? this.paymentProjectList[0].id : null)
}
}
},
async created() {
await this.getProjectList()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,486 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
:clearable="false"
@change="doSearch();getProjectList()"
placeholder="请选择年度"
type="year"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="缴费项目">
<el-select
placeholder="请选择项目"
v-model="pageForm.paymentProjectId"
style="width: 100%"
clearable
@change="doSearch"
@clear="doSearch"
filterable
>
<el-option v-for="item in paymentProjectList" :label="item.projectName" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="职工信息">
<el-input
placeholder="请输入内容"
clearable
v-model="pageForm.searchKeyword"
style="width: 100%"
@keyup.enter.native="doSearch"
>
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="姓名" value="u.username"></el-option>
<el-option label="工号" value="u.loginname"></el-option>
</el-select>
</el-input>
</search-item>
<template v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')">
<search-item label="所属工会">
<el-select
placeholder="请选择所属工会"
v-model="pageForm.unionId"
style="width: 100%"
clearable
@change="flushUnits"
@clear="flushUnits"
filterable
>
<el-option v-for="item in unions" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select
placeholder="请选择所属单位"
v-model="pageForm.unitId"
style="width: 100%"
clearable
filterable
>
<el-option v-for="item in units" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</template>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" style="width: 100%" clearable
placeholder="教职工类别" code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" style="width: 100%" clearable
placeholder="在职状态" code="USER_STATE"></dict-select>
</search-item>
<search-item label="入职时间">
<el-date-picker
@change="schoolDateChange"
end-placeholder="结束日期"
format="yyyy-MM-dd"
range-separator="-"
start-placeholder="开始日期"
style="width: 100%"
type="datetimerange"
v-model="pageForm.schoolTimeRange"
value-format="yyyy-MM-dd">
</el-date-picker>
</search-item>
<search-item label="退休时间">
<el-date-picker
@change="retireDateChange"
placeholder="请选择退休时间范围"
end-placeholder="结束日期"
format="yyyy-MM-dd"
range-separator="-"
start-placeholder="开始日期"
style="width: 100%"
type="datetimerange"
v-model="pageForm.retireDateRange"
value-format="yyyy-MM-dd">
</el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="缴费列表">
<el-radio-group @change="doSearch" class="mr10" size="small" v-model="pageForm.isPay">
<el-radio-button :label="null">全部</el-radio-button>
<el-radio-button :label="true">已缴</el-radio-button>
<el-radio-button :label="false">未缴</el-radio-button>
</el-radio-group>
<el-button @click="sendPaymentMsgAll" size="small" type="primary">一键催缴</el-button>
<el-button @click="openModify(false)" size="small" type="primary">批量设为已缴</el-button>
<el-button @click="doPaidToUnPaid(false)" size="small" type="primary">批量设为未缴</el-button>
<el-button v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')" icon="el-icon-s-promotion" type="primary" size="small" :loading="submitLoading" @click="openImport">
导入
</el-button>
<el-button icon="el-icon-document-add" type="primary" size="small" :loading="submitLoading" @click="doExport(false)">
导出
</el-button>
<el-button v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')" icon="el-icon-document-add" type="primary" size="small" :loading="submitLoading" @click="doExport(true)">
按基层工会导出
</el-button>
</table-tool>
<el-table
:data="tableData"
:size="tableSize"
@sort-change="pageOrder"
class="vi-table"
@selection-change="tableHandleSelectionChange"
ref="table"
row-key="id"
style="width: 100%"
v-loading="tableLoading"
>
<el-table-column :reserve-selection="true" type="selection"></el-table-column>
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isPayment'">
<span style="color: #00aa3a" v-if="row.isPayment">已缴</span>
<span style="color: red" v-else>未缴</span>
</template>
<template scope="{row}" v-else-if="column.prop==='paymentMoney'">
<span> {{ Number(row.paymentMoney) / 100 }}</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" prop="userOnline" width="250px">
<template scope="{row}">
<el-button v-if="row.isPayment" @click="doPaidToUnPaid(row.id,true)" size="mini" type="primary">设为未缴</el-button>
<el-button v-if="!row.isPayment" @click="sendPaymentMsg(row)" size="mini" type="primary">催缴</el-button>
<el-button v-if="!row.isPayment" @click="openModify(row.id,true)" size="mini" type="primary">设为已缴</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<file-import
ref="viewImport"
temp_url="/platform/member/payment/summary/downloadImportTemp"
post_url="/platform/member/payment/summary/doImport"
:project_id="pageForm.paymentProjectId"
@flush="successImport"
></file-import>
</template>
</guava>
<el-diaLog :close-on-click-modal="false" :visible.sync="modifyVisible" title="已缴设置" width="35%">
<el-form ref="form" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="缴费金额" prop="paymentMoney">
<el-input placeholder="请输入要缴费的金额" type="number" v-model="formData.paymentMoney"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input placeholder="请输入备注" type="text" v-model="formData.remark"></el-input>
</el-form-item>
</el-form>
<div style="text-align: right">
<span>
<el-button @click="modifyVisible = false">取 消</el-button>
<el-button @click="doSubmit" type="primary">确 定</el-button>
</span>
</div>
</el-diaLog>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
paymentProjectList: [],
units: [],
unions: [],
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名" },
{ prop: "mobile", label: "联系电话" },
{ prop: "schoolTime", label: "入职时间" },
{ prop: "retireDate", label: "退休时间" },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "unionname", label: "所属工会", sortable: true },
{ prop: "unitname", label: "所属单位", sortable: true },
{ prop: "isPayment", label: "是否缴费", sortable: true },
{ prop: "paymentMoney", label: "缴费金额", sortable: true }
],
pageForm: {
year: moment().format("YYYY"),
searchName: "u.username",
isPay: false,
searchKeyword: "",
unionId: "",
unitId: "",
threeUnitId: "",
unionGroupId: "",
personType: "",
userState: "",
paymentProjectId: "",
schoolTimeRange: [],
schoolTimeStart: "",
schoolTimeEnd: "",
retireDateRange: [],
retireDateStart: "",
retireDateEnd: "",
},
checkUsers: [],
modifyVisible: false,
formData: {
ids: []
},
formRules: {
paymentMoney: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
}
}
},
components: {
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue"),
},
methods: {
schoolDateChange(val) {
if (val) {
this.pageForm.schoolTimeStart = val[0]
this.pageForm.schoolTimeEnd = val[1]
} else {
this.pageForm.schoolTimeStart = ""
this.pageForm.schoolTimeEnd = ""
}
},
retireDateChange(val) {
if (val) {
this.pageForm.retireDateStart = val[0]
this.pageForm.retireDateEnd = val[1]
} else {
this.pageForm.retireDateStart = ""
this.pageForm.retireDateEnd = ""
}
},
sendPaymentMsgAll() {},
async sendPaymentMsg(row) {
const confirm = await this.$confirm("您确定对【" + row.username + "】会员进行催缴吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm !== "confirm") return
const resp = await this.$axios.post(loc() + "/sendPaymentMsg", { id: row.id })
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
/**
* 单个将未缴费设为已缴费
* @param id
* @param flag
*/
openModify(id, flag) {
this.formData = {
paymentMoney: "",
remark: ""
}
if (flag) {
this.checkUsers = []
this.checkUsers.push(id)
this.formData.ids = JSON.stringify(this.checkUsers)
} else {
const ids = this.checkUsers.map((obj) => obj.id)
this.formData.ids = JSON.stringify(ids)
}
if (!this.checkUsers.length) {
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
this.modifyVisible = true
this.formData.isPay = true
},
async doPaidToUnPaid(id, flag) {
this.formData = {
paymentMoney: "",
remark: ""
}
if (flag) {
this.checkUsers = []
this.checkUsers.push(id)
this.formData.ids = JSON.stringify(this.checkUsers)
} else {
const ids = this.checkUsers.map((obj) => obj.id)
this.formData.ids = JSON.stringify(ids)
}
if (!this.checkUsers.length) {
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
const confirm = await this.$confirm("您确定要设为【未缴】吗,此操作不可撤销!", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post(loc() + "/modify", this.formData)
if (resp.code === 0) {
this.$refs.table.clearSelection()
this.checkUsers = []
this.notifySuccess(resp.msg)
this.modifyVisible = false
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async doSubmit() {
if (!this.checkUsers.length) {
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
const formValid = await this.$refs["form"].validate()
if (formValid) {
const confirm = await this.$confirm("您确定要更改缴费信息吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post(loc() + "/modify", this.formData)
if (resp.code === 0) {
this.$refs.table.clearSelection()
this.checkUsers = []
this.notifySuccess(resp.msg)
this.modifyVisible = false
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
}
},
async doDelete(id) {
const confirm = await this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post(loc() + "/doRemoveById", { id: id })
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
openImport() {
this.$refs.guava.edit()
this.$nextTick(() => {
setTimeout(() => {
this.$refs.viewImport.resetImportData()
}, 500)
})
},
successImport() {
this.$refs.guava.index()
this.pageData()
},
doExport(isZip) {
const {year, paymentProjectId, searchName, searchKeyword, unionId, unitId, personType,
userState, isPay, schoolTimeStart, schoolTimeEnd, retireDateStart, retireDateEnd} = this.pageForm
this.$downLoad(loc() + '/doExport', {
searchName: searchName,
searchKeyword: searchKeyword,
unionId: unionId,
unitId: unitId,
isPay: isPay,
year: year,
isZip: isZip,
paymentProjectId: paymentProjectId,
personType: personType,
userState: userState,
schoolTimeStart: schoolTimeStart,
schoolTimeEnd: schoolTimeEnd,
retireDateStart: retireDateStart,
retireDateEnd: retireDateEnd
})
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
}
},
tableHandleSelectionChange(val) {
this.checkUsers = val
},
async getProjectList() {
const resp = await this.$axios.post("/platform/member/payment/project/getAllProject", { year: this.pageForm.year })
if (resp.code === 0) {
this.paymentProjectList = resp.data
this.$set(this.pageForm, "paymentProjectId", this.paymentProjectList ? this.paymentProjectList[0].id : null)
}
},
async doSearch() {
this.pageData()
}
},
async created() {
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN")) {
this.unions = await this.$businessTool.listUnion()
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
this.$set(this.pageForm, "unionId", this.unions ? this.unions[0].id : null)
this.flushUnits()
}
await this.getProjectList()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,337 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="search">
<search-item label="年度">
<el-date-picker
:clearable="false"
clearable
@change="doSearch"
placeholder="请选择年度"
type="year" style="width: 100%"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="缴费项目">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入缴费项目"
style="width: 100%"
v-model="pageForm.projectName">
</el-input>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="个人缴费列表">
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table" row-key="id" style="width: 100%"
v-loading="tableLoading">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isPayment'">
<span style="color: #00aa3a" v-if="row.isPayment">已缴</span>
<span style="color: red" v-else>未缴</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="是否确认金额">
<template scope="{row}">
<span style="color: #00aa3a" v-if="row.paymentMoney!=null">已确定</span>
<span style="color: red" v-else>未确定</span>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px">
<template scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button :loading="submitLoading" plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'view',data:scope.row}">
查看
</el-dropdown-item>
<el-dropdown-item v-if="!scope.row.isPayment" :command="{type:'edit',data:scope.row}">
设为已缴
</el-dropdown-item>
<el-dropdown-item v-if="scope.row.paymentMoney==null" :command="{type:'pay',data:scope.row}">
确定缴费金额
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #pay>
<el-form :model="formData" :rules="formRules" label-width="100px" ref="form">
<div class="process-title">缴费信息</div>
<el-form-item label="缴费项目" prop="projectName">
<span>{{formData.projectName}}</span>
</el-form-item>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="教职工类别" size="medium">
<span>{{formData.personType}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会员类型" size="medium">
<span>{{formData.payPersonnel}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="需缴费用" size="medium">
<div v-for="item in payStandard" style="display:flex;justify-content: space-between;margin-left: 30px">
<template v-if="item.payModeValueList.length>0" >
(
<template v-for="(o,i) in item.payModeValueList">
<el-input @change="getMoney(item)" placeholder="" style="width: 200px;" v-model="o.value">
<template slot="prepend">{{o.name}}</template>
</el-input>
<span v-if="(i+1)!=item.payModeValueList.length">+</span>
</template>
) * 0.5% *{{formData.paymentMonth}}个月
</template>
<template v-else>
<span>{{item.payModeValue}}</span>*{{formData.paymentMonth}}个月
</template>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="缴费金额" prop="paymentMoney" size="medium">
<el-input disabled="true" placeholder="" style="width: 200px;" v-model="formData.paymentMoney">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button @click="doSave" v-loading="submitLoading" style="float: right"
type="primary">
提交
</el-button>
</div>
</template>
<template #view>
<el-form :model="formData" label-width="100px" ref="form">
<div class="process-title">缴费信息</div>
<el-form-item label="缴费项目" prop="projectName">
<span>{{formData.projectName}}</span>
</el-form-item>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="教职工类别" size="medium">
<span>{{formData.personType}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会员类型" size="medium">
<span>{{formData.payPersonnel}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="缴纳标准" size="medium">
<div v-for="item in payStandard" style="display:flex;justify-content: space-between;margin-left: 30px">
<span v-if="item.payModeValueList.length>0" >
(
<span v-for="(o,i) in item.payModeValueList">
<span>{{o.name}}</span>
<span v-if="(i+1)!=item.payModeValueList.length">+</span>
</span>
) * 0.5% *{{formData.paymentMonth}}个月
</span>
<template v-else>
<span>{{item.payModeValue}}</span>*{{formData.paymentMonth}}个月
</template>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="缴费金额" size="medium">
<span>{{formData.paymentMoney}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="缴费月份" size="medium">
<span>{{formData.paymentStartMonth}} - {{formData.paymentEndMonth}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="缴费开始时间" size="medium">
<span>{{formData.startTime}} - {{formData.endTime}}</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
pageForm: {
year: moment().format('YYYY'),
},
tableColumns: [
{prop: 'year', label: '年度'},
{prop: 'projectName', label: '缴费项目名称'},
{prop: 'paymentStartMonth', label: '缴费开始月份'},
{prop: 'paymentEndMonth', label: '缴费截止月份'},
{prop: 'paymentMonth', label: '需要缴费月数'},
{prop: 'startTime', label: '缴费开始时间'},
{prop: 'endTime', label: '缴费截止时间'},
{prop: 'paymentMoney', label: '缴费金额'},
{prop: "isPayment", label: "是否缴费", sortable: true},
],
payStandard:{},
formRules: {
paymentMoney: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
}
},
methods: {
dropdownCommand(command) {
const {type, data} = command
if (type === 'edit') {
this.doPay(data)
} else if (type === 'pay'){
this.openPay(data)
} else if (type === 'view'){
this.openView(data)
}
},
openPay(data){
const payStandards=JSON.parse(data.payStandards)
this.payStandard=payStandards.filter(item => item.personType===data.personType&&item.payPersonnel===data.payPersonnel)
if (this.payStandard.length>0&&this.payStandard[0].payModeValueList===null){
this.formData.paymentMoney=+this.payStandard[0].payModeValue*+this.formData.paymentMonth
}
this.formData=data
this.$refs.guava.pay()
},
async doPay(data) {
const confirm = await this.$confirm("您确定要更改缴费信息吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const formData={
ids:JSON.stringify([data.id]),
paymentMoney:data.paymentMoney,
isPay:data.isPay,
remark:"缴费"
}
const resp = await this.$axios.post("/platform/member/payment/summary/modify", formData)
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
openView(data) {
const payStandards=JSON.parse(data.payStandards)
this.payStandard=payStandards.filter(item => item.personType===data.personType&&item.payPersonnel===data.payPersonnel)
if (this.payStandard.length>0&&this.payStandard[0].payModeValueList===null){
this.formData.paymentMoney=+this.payStandard[0].payModeValue*+this.formData.paymentMonth
}
this.formData=data
this.$refs.guava.view()
},
async doSave() {
const formValid = await this.$refs["form"].validate()
if (formValid) {
this.submitLoading = true
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const formData = clone(this.formData)
const resp = await this.$axios.post(loc() + '/doSave', formData)
loading.close()
this.submitLoading = false
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.$refs.guava.index()
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
getMoney(item){
this.formData.paymentMoney=0
let money=0
item.payModeValueList.forEach(o=>{
money=+o.value+money
})
this.formData.paymentMoney=money*0.005*+this.formData.paymentMonth
}
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,92 @@
const COMMON_QUERY = {
template: /*language=HTML*/ `
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<template v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_ADMIN, BRANCH_UNION_CHAIRMAN, BRANCH_UNION_GROUP_LEADER')">
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userStates" placeholder="请选择在职状态" @change="doSearch"
code="USER_STATE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personTypes" placeholder="请选择教职工类别" @change="doSearch"
code="USER_PERSON_TYPE" multiple collapse-tags></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBys" placeholder="请选择编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE" multiple collapse-tags></dict-select>
</search-item>
</template>
</search>
`,
store,
mixins: [initTableMixins],
data() {
return{
unions: [],
units: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
userStates: [],
personTypes: [],
preparedBys: [],
}
}
},
methods: {
doSearch(){
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
this.$emit('search', pageForm)
},
async initData(){
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN")) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unions = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
})
}
},
async flushUnits(){
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
}
},
async created() {
this.initData()
}
}
@@ -0,0 +1,277 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style scoped>
.drag-area {
border: 1px dashed #ddd;
padding: 10px;
margin-top: 10px;
min-height: 50px;
}
.drag-item {
background: #f5f5f5;
padding: 8px;
margin: 4px 0;
cursor: move;
}
.ghost {
opacity: 0.5;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="业务名称">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入业务名称"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="数据列表">
<el-button size="small" @click="openAdd" type="primary">添加</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" stripe border :header-cell-style="{background:'#FAFAFA'}"
row-key="id" @sort-change="pageOrder">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:width="column.width"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop === 'isActive'">
<el-switch v-model="row.isActive" @change="doUpdateActive(row)"></el-switch>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="200px" fixed="right">
<template scope="{row}">
<el-button size="mini" @click="openEdit(row)" type="primary">编辑</el-button>
<el-button size="mini" @click="onDelete(row)" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="120px">
<el-form-item label="业务名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入业务名称"></el-input>
</el-form-item>
<el-form-item label="业务编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入业务编码"></el-input>
</el-form-item>
<el-form-item label="排序编号" prop="sortNum">
<el-input-number v-model="formData.sortNum" placeholder="请输入排序编号" style="width: 100%"></el-input-number>
</el-form-item>
<el-form-item label="审核流程步骤" prop="workflowSteps">
<!-- 1. 步骤多选池 -->
<el-checkbox-group v-model="selectedSteps" @change="onCheckChange">
<el-checkbox
v-for="opt in stepOptions"
:key="opt.value"
:label="opt.value">
{{ opt.label }}
</el-checkbox>
</el-checkbox-group>
<!-- 2. 已选步骤(可拖拽排序) -->
<draggable
v-model="formData.workflowSteps"
handle=".handle"
class="drag-area"
ghost-class="ghost">
<div v-for="(step, idx) in formData.workflowSteps" :key="step.stepCode" class="drag-item handle">
<i class="el-icon-menu"></i>
<el-tag size="small" style="width: 15%">{{ '第' + (idx + 1) + '步' }}. {{ step.stepName }}</el-tag>
<el-select
v-if="!step.stepName.includes('核对')"
v-model="step.assignRole"
multiple
filterable
clearable
placeholder="处理角色"
size="mini"
style="width: 30%; margin:0 8px">
<el-option v-for="role in roles" :key="role.code"
:label="role.name" :value="role.code"></el-option>
</el-select>
<el-button type="danger" icon="el-icon-delete" size="mini" circle @click="removeStep(idx)"></el-button>
</div>
</draggable>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="doSave">提交配置</el-button>
</el-form-item>
</el-form>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return{
pageForm: {},
tableData: [],
tableColumns: [
{ prop: "name", label: "业务名称", sortable: true },
{ prop: "code", label: "业务编码", sortable: true },
{ prop: "sortNum", label: "排序编号", sortable: true },
{ prop: "isActive", label: "是否启用" }
],
formData: {
name: '',
code: '',
targetTable: '',
workflowSteps: []
},
formRules: {
name: [{ required: true, message: '请输入业务名称', trigger: ['blur', 'change'] }],
code: [{ required: true, message: '请输入业务编码', trigger: ['blur', 'change'] }],
sortNum: [{ required: true, message: '请输入排序编号', trigger: ['blur', 'change'] }],
workflowSteps: [{ required: true, message: '请填写审核流程步骤', trigger: ['blur', 'change'] }]
},
selectedSteps: [],
stepOptions: [
{ value: 'personal', label: '个人核对' },
{ value: 'unionGroupCheck', label: '工会小组核对' },
{ value: 'branchUnionCheck', label: '分工会核对' },
{ value: 'schoolUnionCheck', label: '校工会核对' },
{ value: 'unionGroupAudit', label: '工会小组审核' },
{ value: 'branchUnionAudit', label: '分工会审核' },
{ value: 'schoolUnionAudit', label: '校工会审核' },
],
roles: []
}
},
methods: {
openAdd() {
this.$refs.guava.edit()
},
doSave() {
if (!this.formData.workflowSteps) {
this.$message.error('请配置审核流程步骤')
}
this.$refs.formRef.validate(valid => {
if (valid) {
this.$confirm("您确定要提交吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const formData = clone(this.formData)
formData.workflowSteps = JSON.stringify(this.formData.workflowSteps)
this.$axios.post('/platform/personnel/check/verification/config/doAddOrModify', formData)
.then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
this.$refs.guava.index()
} else {
this.$message.error(res.msg)
}
})
})
}
})
},
doUpdateActive(row) {
this.$axios.post('/platform/personnel/check/verification/config/doUpdateActive', {id: row.id})
.then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
},
openEdit(row) {
this.$axios.post('/platform/personnel/check/verification/config/findOne', {id: row.id})
.then(res => {
if (res.code === 0) {
this.formData = res.data
this.selectedSteps = res.data.workflowSteps.map(v => v.stepCode)
this.$refs.guava.edit()
} else {
this.$message.error(res.msg)
}
})
},
onDelete(row) {
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/personnel/check/verification/config/onDelete', {id: row.id})
.then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
} else {
this.$message.error(res.msg)
}
})
})
},
onCheckChange(codes) {
// 先删掉已取消的
this.formData.workflowSteps = this.formData.workflowSteps
.filter(s => codes.includes(s.stepCode))
// 再追加新勾选的
const existCodes = this.formData.workflowSteps.map(s => s.stepCode)
codes.forEach(code => {
if (!existCodes.includes(code)) {
const data = this.stepOptions.find(opt => opt.value === code)
this.formData.workflowSteps.push({
stepName: data.label,
stepCode: data.value,
assignRole: []
})
}
})
},
removeStep(idx) {
const code = this.formData.workflowSteps[idx].stepCode
this.formData.workflowSteps.splice(idx, 1)
// 同步 checkbox
this.selectedSteps = this.selectedSteps.filter(c => c !== code)
},
async listRoles() {
const resp = await this.$axios.post('/platform/personnel/check/verification/config/listRoles')
if (resp.code === 0) {
this.roles = resp.data
}
}
},
created() {
this.pageData()
this.listRoles()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,83 @@
const basicInfoForm = {
template: /*language=HTML*/ `
<div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="120px">
<el-form-item label="事项名称" prop="title">
<el-input v-model="formData.title" placeholder="请输入事项名称"></el-input>
</el-form-item>
<el-form-item label="业务类型" prop="businessType">
<el-select v-model="formData.businessType" @change="setConfig" placeholder="请选择业务类型" style="width: 100%">
<el-option
v-for="item in businessList"
:key="item.code"
:label="item.name"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
v-model="formData.startTime"
type="datetime"
placeholder="选择开始时间"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%;">
</el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
v-model="formData.endTime"
type="datetime"
placeholder="选择结束时间"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%;">
</el-date-picker>
</el-form-item>
<el-form-item style="text-align: right">
<el-button type="primary" @click="doSubmit">下一步:配置流程</el-button>
</el-form-item>
</el-form>
</div>
`,
data() {
return {
businessList: [],
formData: {},
formRules: {
title: [{ required: true, message: '请输入事项名称', trigger: ['blur', 'change'] }],
businessType: [{ required: true, message: '请选择业务类型', trigger: ['blur', 'change'] }],
startTime: [{ required: true, message: '请选择开始时间', trigger: ['blur', 'change'] }],
endTime: [{ required: true, message: '请选择结束时间', trigger: ['blur', 'change'] }]
}
}
},
methods: {
async listBusiness() {
const resp = await this.$axios.post('/platform/personnel/check/verification/config/findAll')
if (resp.code === 0) {
this.businessList = resp.data
}
},
setConfig(val){
if (val) {
this.formData.businessConfig = this.businessList.find(item => item.code === val)
} else {
this.formData.businessConfig = {}
}
},
doSubmit() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$emit('next', { ...this.formData })
}
})
}
},
async created() {
await this.listBusiness()
}
}
@@ -0,0 +1,406 @@
const importAndMap = {
template: /*language=HTML*/ `
<div>
<h3>导入人员数据并配置字段</h3>
<div style="margin-top: 15px">
<!-- 文件上传 -->
<div class="upload-area">
<el-upload
drag
class="upload-box"
action="#"
:auto-upload="false"
:on-change="handleFileChange"
:file-list="fileList"
accept=".xlsx,.xls"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将 Excel 文件拖到此处,或<em>点击上传</em></div>
<div style="color: darkred">支持 .xlsx、.xls 格式,文件大小不超过 20MB,第一行必须为表头且表头中必须包含【工号】字段</div>
</el-upload>
</div>
<!-- 表头选择区域 -->
<div v-if="headers.length > 0" class="field-selection" style="margin-top: 20px;">
<h4>请选择需要核对的字段:</h4>
<p style="color: #999; margin-bottom: 10px;">
已从文件中读取到 {{ headers.length }} 个字段,勾选后将在审核流程中允许修改。
<br>
<small style="color: green">💡 提示:下方数据预览显示全部字段,用于核对数据准确性。</small>
</p>
<!-- 全选 / 反选 -->
<div style="margin-bottom: 10px;">
<el-button size="small" @click="selectAll">全选</el-button>
<el-button size="small" @click="deselectAll">取消全选</el-button>
</div>
<!-- 字段列表 -->
<el-table :data="headerList" size="small" max-height="500"
:show-header="true" style="width: 100%">
<!-- 列1:是否可编辑(核对时允许修改) -->
<el-table-column label="可修改" width="80" align="center">
<template slot-scope="scope">
<el-tooltip effect="dark" content="勾选后可在核对页面修改该字段" placement="top">
<el-checkbox v-model="scope.row.selected"></el-checkbox>
</el-tooltip>
</template>
</el-table-column>
<!-- 列2Excel 字段名称 -->
<el-table-column label="Excel 字段名" prop="name">
<template slot-scope="scope">
<strong>{{ scope.row.name }}</strong>
<!-- 高亮关键字段 -->
<el-tag size="mini" type="warning" v-if="isIdField(scope.row.name)"
style="margin-left: 5px">主键
</el-tag>
</template>
</el-table-column>
<!-- 列3:示例值 -->
<el-table-column label="示例值" prop="sample">
<template slot-scope="scope">
<span style="color: #666; font-family: monospace;">
{{ scope.row.sample || '空' }}
</span>
</template>
</el-table-column>
<!-- 列4:对应数据库字段(核心!自动匹配 + 可改) -->
<el-table-column label="映射到数据库字段" >
<template slot-scope="scope">
<el-select
v-model="scope.row.dbField"
filterable
placeholder="请选择对应字段"
style="width: 100%"
@change="onMappingChange(scope.row)"
>
<el-option
v-for="field in dbFieldOptions"
:key="field.value"
:label="field.label"
:value="field.value"
></el-option>
</el-select>
</template>
</el-table-column>
</el-table>
<!-- 数据预览 -->
<div style="margin-top: 20px;">
<h4>数据预览(前 5 条)</h4>
<div v-if="previewData.length === 0" style="color:#999; font-style:italic;">
暂无预览数据,请检查文件内容
</div>
<el-table v-else :data="previewData" border max-height="300" style="width: 100%">
<el-table-column
v-for="col in allPreviewColumns"
:key="col"
:prop="col"
:label="col"
></el-table-column>
</el-table>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="actions" style="margin-top: 30px; text-align: right;">
<el-button @click="$emit('prev')">上一步</el-button>
<el-button type="primary" @click="submitTask" :disabled="!canSubmit"
:loading="submitting">完成创建并导入数据</el-button>
</div>
</div>
`,
props: {
baseData: {type: Object}
},
data() {
return {
fileList: [],
workbook: null,
// 原始表头数组
headers: [],
// 解析出的原始二维数组
rawData: [],
headerList: [],
// 对象数组,用于预览
previewData: [],
submitting: false,
// 数据库字段选项
dbFieldOptions: [
{ value: "loginname", label: "工号" },
{ value: "username", label: "姓名" },
{ value: "sex", label: "性别"},
{ value: "birthday", label: "出生年月" },
{ value: "nationality", label: "国籍" },
{ value: "nation", label: "民族"},
{ value: "mobile", label: "联系电话" },
{ value: "political", label: "政治面貌"},
{ value: "userState", label: "在职状态" },
{ value: "personType", label: "教职工类别" },
{ value: "preparedBy", label: "编制类别" },
{ value: "postDoctoralJoinDate", label: "进站时间" },
{ value: "unionId", label: "所属工会" },
{ value: "unitId", label: "所属单位" },
{ value: "idCardType", label: "证件类型" },
{ value: "idCard", label: "证件号码" },
{ value: "marriage", label: "婚姻状况" },
{ value: "jobCategory", label: "岗位类别" },
{ value: "professionalTitle", label: "职称" },
{ value: "professionalLevel", label: "职级" },
{ value: "employeeSource", label: "职工来源" },
{ value: "administrativeLevel", label: "行政级别(管理岗位)" },
{ value: "positionSeries", label: "岗位系列" },
{ value: "positionLevel", label: "岗级" },
{ value: "administrativePositionLevel", label: "行政岗级" },
{ value: "arrivalAtSchoolDate", label: "来校时间" },
{ value: "teachingTime", label: "从教年月" },
{ value: "expectedLeaveSchoolDate", label: "预计/最后离校时间" },
],
excelToDbFieldMap:{
loginname: ['工号', '员工编号', '职工号', '学号', '账号', 'ID', '编号'],
username: ['姓名', '名字', '全名', '人员姓名'],
sex: ['性别', '男女性别'],
birthday: ['出生日期', '出生年月', '生日', 'DOB'],
mobile: ['电话', '手机号', '联系电话', '手机'],
idCard: ['身份证', '身份证号', '证件号码'],
arrivalAtSchoolDate: ['来校时间', '入职时间', '入职日期', '入职年月'],
}
}
},
computed: {
allPreviewColumns() {
return this.headers
},
selectedHeaders() {
return this.headerList.filter(h => h.selected).map(h => h.name)
},
canSubmit() {
return this.selectedHeaders.length > 0 && this.rawData.length > 0
}
},
methods: {
handleFileChange(file, fileList) {
this.fileList = fileList.map(item => {
// 确保 item.raw 存在(即用户选择的原始 File 对象)
if (item.raw) {
return item;
} else {
// 兼容已有文件
return { ...item, raw: item.url ? null : item.response?.data?.file };
}
});
// 只处理 .xlsx .xls 文件
const allowedTypes = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
if (!allowedTypes.includes(file.raw.type)) {
this.$message.error('请上传 Excel 文件(.xls 或 .xlsx')
this.fileList = this.fileList.filter(f => f.uid !== file.uid) // 移除无效文件
return
}
// 读取文件内容
this.readExcel(file.raw)
},
async readExcel(rawFile) {
try {
const reader = new FileReader()
reader.onload = (e) => {
const data = new Uint8Array(e.target.result)
const workbook = XLSX.read(data, { type: 'array' })
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]
const jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 })
if (jsonData.length < 2) {
this.$message.warning('数据为空或缺少表头')
return
}
this.headers = jsonData[0].filter(h => h)
this.rawData = jsonData.slice(1)
// 初始化字段选择列表
this.headerList = this.headers.map((h, idx) => ({
name: h,
sample: this.rawData[0] ? this.rawData[0][idx] : '',
selected: true,
dbField: this.autoMatchDbField(h)
}))
this.$message.success('成功加载 ' + this.rawData.length + ' 条数据,共 ' + this.headers.length + ' 个字段')
this.generatePreview()
}
reader.readAsArrayBuffer(rawFile)
//
} catch (err) {
this.$message.error('文件解析失败')
console.error(err)
}
},
onMappingChange() {
},
isIdField(header) {
// 主键字段,必填
return ['工号', '编号', '身份证'].some(k => header.includes(k))
},
resetState() {
this.headers = []
this.rawData = []
this.headerList = []
this.previewData = []
this.fileList = []
},
// 自动匹配数据库字段
autoMatchDbField(excelHeader) {
const cleanHeader = (excelHeader || '').toString().trim();
if (!cleanHeader) return '';
// 遍历所有数据库字段
for (const [dbField, keywords] of Object.entries(this.excelToDbFieldMap)) {
if (keywords.some(keyword => cleanHeader.includes(keyword))) {
return dbField;
}
}
// 如果没匹配上,也可以尝试精确匹配
const exactMatch = this.dbFieldOptions.find(opt =>
opt.label === cleanHeader || opt.value === cleanHeader
);
if (exactMatch) {
return exactMatch.value;
}
return ''; // 未匹配
},
generatePreview() {
try {
this.previewData = this.rawData.slice(0, 5).map(row => {
const obj = {}
this.headers.forEach((header, idx) => {
const cleanHeader = (header || '').trim()
if (!cleanHeader) return
obj[cleanHeader] = row[idx] == null ? '' : String(row[idx]).trim()
})
return obj
})
} catch (err) {
console.error('生成预览失败', err)
this.previewData = []
}
},
selectAll() {
this.headerList.forEach(h => h.selected = true)
},
deselectAll() {
this.headerList.forEach(h => h.selected = false)
},
gridFormatter(row, column) {
const val = row[column.property]
return val == null ? '-' : String(val)
},
async submitTask() {
if (!this.canSubmit) {
this.$message.warning('请至少选择一个字段')
return
}
this.submitting = true
try {
this.baseData.fieldConfig = this.headerList
.map(h => ({
fieldCode: h.dbField,
fieldName: h.name,
isRequired: h.selected,
sortOrder: this.headers.indexOf(h.name)
}))
const formData = new FormData()
formData.append('file', this.fileList[0].raw)
formData.append('baseData', JSON.stringify(this.baseData))
console.log(formData)
this.$emit('finish', formData)
} catch (err) {
this.$message.error('提交失败:' + (err.message || '未知错误'))
} finally {
this.submitting = false
}
},
},
mounted() {
const s = document.createElement("script")
s.type = "text/javascript"
s.src = "/assets/platform/plugins/xlsx/xlsx.full.min.js"
document.body.appendChild(s)
},
style: /*language=CSS*/ `
/deep/ .upload-area {
border: 2px dashed #d9d9d9;
border-radius: 8px;
padding: 4px;
text-align: center;
background: #fafafa;
transition: all 0.3s ease;
margin-bottom: 15px;
}
/deep/ .upload-area:hover {
border-color: #409eff;
background: #f0f9ff;
}
/deep/ .el-upload-dragger{
background: none !important;
border: none !important;
}
/deep/ .import-and-map {
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0,0,0,0.05);
}
/deep/ .upload-box {
width: 100%;
margin: 0 auto;
}
/deep/ .field-selection {
padding: 15px;
border: 1px solid #eee;
border-radius: 6px;
background: #f9f9f9;
}
/deep/ .actions {
text-align: right;
}
/deep/ .el-table th {
font-weight: bold;
color: #333;
}
`
}
@@ -0,0 +1,79 @@
<!--#include("basicInfoForm.js"){}#-->
<!--#include("workflowConfig.js"){}#-->
<!--#include("importAndMap.js"){}#-->
const Manage = {
template: /*language=HTML*/ `
<div class="create-task-page">
<!-- 步骤条 -->
<el-steps :active="currentStep" finish-status="success" align-center style="margin: 20px 0;">
<el-step title="基本信息"></el-step>
<el-step title="配置流程"></el-step>
<el-step title="导入数据 & 映射字段"></el-step>
</el-steps>
<div class="form-container">
<!-- 基本信息 -->
<div v-show="currentStep === 0">
<basicInfoForm ref="basicInfoFormRef" @next="gotoNext"/>
</div>
<!-- 流程配置 -->
<div v-show="currentStep === 1">
<workflowConfig ref="workflowConfigRef" :base-data.sync="formData" @prev="currentStep--" @next="gotoNext"/>
</div>
<!-- 导入 + 字段映射 -->
<div v-show="currentStep === 2">
<importAndMap
ref="importAndMapRef"
:base-data.sync="formData"
@finish="onFinish"
@prev="currentStep--"
/>
</div>
</div>
</div>
`,
data() {
return {
currentStep: 0,
newTaskId: '',
formData: {
businessConfig: {}
}
}
},
components: {
basicInfoForm,
workflowConfig,
importAndMap
},
methods: {
gotoNext(formData) {
this.formData = formData
this.currentStep++
if (this.currentStep === 1) {
this.$nextTick(() => {
this.$refs.workflowConfigRef.init()
})
}
},
onFinish(formData) {
this.$confirm('确定要提交吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const resp = await this.$axios.post('/platform/personnel/check/verification/manage/doAddOrModify', formData)
if (resp.code === 0){
this.$message.success(resp.msg)
}
})
},
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,128 @@
const workflowConfig = {
template: /*language=HTML*/ `
<div>
<h3>配置审核流程(勾选添加审核步骤,拖拽调整顺序,点击删除)</h3>
<div style="margin-top: 15px">
<el-checkbox-group v-model="selectedSteps" @change="onCheckChange">
<el-checkbox
v-for="opt in stepOptions"
:key="opt.value"
:label="opt.value">
{{ opt.label }}
</el-checkbox>
</el-checkbox-group>
<draggable
v-model="baseData.businessConfig.workflowSteps"
handle=".handle"
class="drag-area"
ghost-class="ghost">
<div v-for="(step, idx) in baseData.businessConfig.workflowSteps" :key="step.stepCode" class="drag-item handle">
<i class="el-icon-menu"></i>
<el-tag size="small" style="width: 15%">{{ '第' + (idx + 1) + '步' }}. {{ step.stepName }}
</el-tag>
<el-select
v-if="!step.stepName.includes('核对')"
v-model="step.assignRole"
multiple
filterable
clearable
placeholder="处理角色"
size="mini"
style="width: 30%; margin:0 8px">
<el-option v-for="role in roles" :key="role.code"
:label="role.name" :value="role.code"></el-option>
</el-select>
<el-button type="danger" icon="el-icon-delete" size="mini" circle
@click="removeStep(idx)"></el-button>
</div>
</draggable>
</div>
<div style="margin-top: 20px;text-align: right">
<el-button @click="$emit('prev')">上一步</el-button>
<el-button type="primary" @click="$emit('next', baseData)">下一步:导入数据</el-button>
</div>
</div>
`,
props: {
baseData: {type: Object}
},
data() {
return {
selectedSteps: [],
stepOptions: [
{ value: 'personal', label: '个人核对' },
{ value: 'unionGroupCheck', label: '工会小组核对' },
{ value: 'branchUnionCheck', label: '分工会核对' },
{ value: 'schoolUnionCheck', label: '校工会核对' },
{ value: 'unionGroupAudit', label: '工会小组审核' },
{ value: 'branchUnionAudit', label: '分工会审核' },
{ value: 'schoolUnionAudit', label: '校工会审核' },
],
roles: []
}
},
methods: {
onCheckChange(codes) {
// 先删掉已取消的
this.baseData.businessConfig.workflowSteps = this.baseData.businessConfig.workflowSteps
.filter(s => codes.includes(s.stepCode))
// 再追加新勾选的
const existCodes = this.baseData.businessConfig.workflowSteps.map(s => s.stepCode)
codes.forEach(code => {
if (!existCodes.includes(code)) {
const data = this.stepOptions.find(opt => opt.value === code)
this.baseData.businessConfig.workflowSteps.push({
stepName: data.label,
stepCode: data.value,
assignRole: []
})
}
})
},
removeStep(idx) {
const code = this.baseData.businessConfig.workflowSteps[idx].stepCode
this.baseData.businessConfig.workflowSteps.splice(idx, 1)
// 同步 checkbox
this.selectedSteps = this.selectedSteps.filter(c => c !== code)
},
async listRoles() {
const resp = await this.$axios.post('/platform/personnel/check/verification/config/listRoles')
if (resp.code === 0) {
this.roles = resp.data
}
},
init() {
this.selectedSteps = this.baseData.businessConfig.workflowSteps.map(s => s.stepCode)
}
},
created() {
this.listRoles()
},
style: /*language=CSS*/ `
/deep/ .drag-area {
border: 1px dashed #ddd;
padding: 10px;
margin-top: 10px;
min-height: 50px;
}
/deep/ .drag-item {
background: #f5f5f5;
padding: 8px;
margin: 4px 0;
cursor: move;
}
/deep/ .ghost {
opacity: 0.5;
}
`
}
@@ -0,0 +1,130 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
placeholder="请选择年度"
type="year"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="任务名称">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入任务名称"
clearable
style="width: 100%"
v-model="pageForm.searchKeyword"
></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="数据列表">
<el-button size="small" @click="openAdd" type="primary">新建</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" stripe border :header-cell-style="{background:'#FAFAFA'}"
row-key="id" @sort-change="pageOrder">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:width="column.width"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop === 'status'">
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="220px" fixed="right">
<template scope="{row}">
<el-button size="mini" @click="openView(row)" type="primary">查看</el-button>
<el-button size="mini" @click="openEdit(row)" type="primary">编辑</el-button>
<el-button size="mini" @click="onDelete(row)" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<info ref="infoRef"></info>
</template>
<template #edit>
<manage ref="manageRef"></manage>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("add/manage.js"){}#-->
<!--#include("info.js"){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return{
tableColumns: [
{ prop: "title", label: "任务名称", sortable: true },
{ prop: "fileName", label: "文件名称", sortable: true },
{ prop: "startTime", label: "开始时间", sortable: true },
{ prop: "endTime", label: "结束时间", sortable: true },
{ prop: "status", label: "当前状态" }
],
}
},
components: {
'info': INFO,
'manage': Manage,
},
methods: {
openAdd(){
this.$refs.guava.edit()
},
openView(row){
},
openEdit(row){
},
onDelete(row){
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/personnel/check/manage/onDelete', {id: row.id})
.then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
} else {
this.$message.error(res.msg)
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,16 @@
const INFO = {
template: /*language=HTML*/ `
`,
data() {
return {
}
},
methods: {
},
created() {
}
}
@@ -0,0 +1,36 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool></table-tool>
</el-card>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
tableColumns: []
}
},
methods: {
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,749 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.dashboard-title {
font-size: 22px;
font-weight: 600;
color: #217050;
}
.dashboard-cards {
margin: 20px 0;
}
.dashboard-charts {
margin-bottom: 20px;
}
.statistic-card .card-header {
font-size: 14px;
color: #606266;
}
.statistic-card .card-content {
text-align: center;
padding: 10px 0;
}
.statistic-card .statistic-value {
font-size: 30px;
font-weight: 600;
color: #217050;
margin-bottom: 10px;
}
.statistic-card .statistic-footer {
display: flex;
justify-content: space-around;
font-size: 14px;
color: #909399;
}
.chart-card .card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.chart-container {
height: 300px;
width: 100%;
padding: 10px 0;
}
.chart-container-large {
height: 400px;
}
.range-slider-container {
display: flex;
align-items: center;
width: 300px;
}
.range-slider-container .el-slider {
margin-right: 15px;
flex: 1;
}
.range-display {
width: 70px;
text-align: center;
color: #606266;
}
.filter-container {
padding-top: 10px;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<div slot="header" class="clearfix">
<span class="dashboard-title">单身教工统计分析</span>
<el-divider></el-divider>
</div>
<el-form :inline="true" class="filter-container">
<el-form-item label="工会">
<el-select v-model="filterForm.unionId" placeholder="选择工会" clearable>
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="filterForm.sex" placeholder="选择性别" clearable>
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="fetchData">筛选</el-button>
<el-button @click="resetFilter">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 总体统计卡片 -->
<el-row :gutter="20" class="dashboard-cards">
<el-col :span="6">
<el-card shadow="hover" class="statistic-card">
<div slot="header" class="card-header">
<i class="el-icon-user"></i>
单身教工总人数
</div>
<div class="card-content">
<div class="statistic-value">{{statistics.totalCount || 0}}</div>
<div class="statistic-footer">
<span>男:{{statistics.maleCount || 0}}</span>
<span>女:{{statistics.femaleCount || 0}}</span>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover" class="statistic-card">
<div slot="header" class="card-header">
<i class="el-icon-school"></i>
平均年龄
</div>
<div class="card-content">
<div class="statistic-value">{{statistics.averageAge || 0}}</div>
<div class="statistic-footer">
<span>最小:{{statistics.minAge || 0}}岁</span>
<span>最大:{{statistics.maxAge || 0}}岁</span>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover" class="statistic-card">
<div slot="header" class="card-header">
<i class="el-icon-reading"></i>
高学历占比
</div>
<div class="card-content">
<div class="statistic-value">{{statistics.highEduPercent || '0%'}}</div>
<div class="statistic-footer">
<span>硕士及以上人数:{{statistics.highEduCount || 0}}</span>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover" class="statistic-card">
<div slot="header" class="card-header">
<i class="el-icon-office-building"></i>
工会数量
</div>
<div class="card-content">
<div class="statistic-value">{{statistics.unionCount || 0}}</div>
<div class="statistic-footer">
<span>单位数量:{{statistics.unitCount || 0}}</span>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 图表区域 -->
<el-row :gutter="20" class="dashboard-charts">
<el-col :span="12">
<el-card shadow="hover" class="chart-card">
<div slot="header" class="card-header">
<span>性别分布</span>
<el-radio-group v-model="chartTypes.gender" size="mini" @change="renderGenderChart">
<el-radio-button label="pie">饼图</el-radio-button>
<el-radio-button label="column">柱状图</el-radio-button>
</el-radio-group>
</div>
<div id="genderChart" class="chart-container"></div>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="hover" class="chart-card">
<div slot="header" class="card-header">
<span>年龄分布</span>
<el-radio-group v-model="chartTypes.age" size="mini" @change="renderAgeChart">
<el-radio-button label="column">柱状图</el-radio-button>
<el-radio-button label="line">折线图</el-radio-button>
</el-radio-group>
</div>
<div id="ageChart" class="chart-container"></div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="dashboard-charts">
<el-col :span="12">
<el-card shadow="hover" class="chart-card">
<div slot="header" class="card-header">
<span>学历分布</span>
<el-radio-group v-model="chartTypes.education" size="mini" @change="renderEducationChart">
<el-radio-button label="pie">饼图</el-radio-button>
<el-radio-button label="column">柱状图</el-radio-button>
</el-radio-group>
</div>
<div id="educationChart" class="chart-container"></div>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="hover" class="chart-card">
<div slot="header" class="card-header">
<span>收入情况分布</span>
<el-radio-group v-model="chartTypes.income" size="mini" @change="renderIncomeChart">
<el-radio-button label="pie">饼图</el-radio-button>
<el-radio-button label="column">柱状图</el-radio-button>
</el-radio-group>
</div>
<div id="incomeChart" class="chart-container"></div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="dashboard-charts">
<el-col :span="24">
<el-card shadow="hover" class="chart-card">
<div slot="header" class="card-header">
<span>单位及工会分布</span>
<el-radio-group v-model="chartTypes.unit" size="mini" @change="renderUnitChart">
<el-radio-button label="bar">条形图</el-radio-button>
<el-radio-button label="treemap">矩形树图</el-radio-button>
</el-radio-group>
</div>
<div id="unitChart" class="chart-container chart-container-large"></div>
</el-card>
</el-col>
</el-row>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
data() {
return {
pageForm: {},
filterForm: {
unionId: "",
sex: "",
age: [20, 65]
},
unionOptions: [],
chartTypes: {
gender: "pie",
age: "column",
education: "pie",
income: "column",
unit: "bar"
},
charts: {},
teacherData: [],
statistics: {
totalCount: 0,
maleCount: 0,
femaleCount: 0,
averageAge: 0,
minAge: 0,
maxAge: 0,
highEduCount: 0,
highEduPercent: "0%",
unionCount: 0,
unitCount: 0
}
}
},
methods: {
fetchData() {
this.$axios.post("/platform/singleTeacher/chart/list", this.filterForm).then((res) => {
if (res.code === 0) {
this.teacherData = res.data
this.processData()
}
})
},
resetFilter() {
this.filterForm = {
unionId: "",
sex: "",
age: [20, 65]
}
this.fetchData()
},
processData() {
this.calculateStatistics()
this.renderCharts()
},
calculateStatistics() {
const data = this.teacherData
// 总数统计
this.statistics.totalCount = data.length
// 性别统计
this.statistics.maleCount = data.filter((item) => item.sex === "男").length
this.statistics.femaleCount = data.filter((item) => item.sex === "女").length
// 年龄统计
const ages = data.map((item) => this.calculateAge(item.birthday)).filter((age) => age !== null)
if (ages.length > 0) {
this.statistics.averageAge = Math.round(ages.reduce((a, b) => a + b, 0) / ages.length)
this.statistics.minAge = Math.min(...ages)
this.statistics.maxAge = Math.max(...ages)
}
// 学历统计
const highEdu = ["硕士研究生毕业", "博士研究生毕业"]
this.statistics.highEduCount = data.filter((item) => highEdu.includes(item.education)).length
this.statistics.highEduPercent = data.length > 0 ? Math.round((this.statistics.highEduCount / data.length) * 100) + "%" : "0%"
// 工会和单位统计
const unions = new Set(data.map((item) => item.unionName))
const units = new Set(data.map((item) => item.unitName))
this.statistics.unionCount = unions.size
this.statistics.unitCount = units.size
},
renderCharts() {
this.$nextTick(() => {
this.renderGenderChart()
this.renderAgeChart()
this.renderEducationChart()
this.renderIncomeChart()
this.renderUnitChart()
})
},
// 计算年龄
calculateAge(birthday) {
if (!birthday) return null
const birthDate = new Date(birthday)
const today = new Date()
let age = today.getFullYear() - birthDate.getFullYear()
const m = today.getMonth() - birthDate.getMonth()
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
age--
}
return age
},
// 性别分布图
renderGenderChart() {
const container = document.getElementById("genderChart")
if (!container) return
if (this.charts.genderChart) {
this.charts.genderChart.destroy()
}
const genderData = this.getGenderDistribution()
if (this.chartTypes.gender === "pie") {
this.charts.genderChart = new G2Plot.Pie("genderChart", {
data: genderData,
angleField: "value",
colorField: "type",
radius: 0.8,
label: {
type: "outer",
content: "{name}: {percentage}"
},
legend: { position: "right" },
interactions: [{ type: "element-active" }],
color: ["#217050", "#5fad85"]
})
} else {
this.charts.genderChart = new G2Plot.Column("genderChart", {
data: genderData,
xField: "type",
yField: "value",
label: {
position: "top"
},
color: ({ type }) => {
if (type === "男") return "#217050"
return "#5fad85"
},
columnWidthRatio: 0.4
})
}
this.charts.genderChart.render()
},
// 年龄分布图
renderAgeChart() {
const container = document.getElementById("ageChart")
if (!container) return
if (this.charts.ageChart) {
this.charts.ageChart.destroy()
}
const ageData = this.getAgeDistribution()
const commonConfig = {
data: ageData,
xField: "range",
yField: "count",
meta: {
range: { alias: "年龄段" },
count: { alias: "人数" }
},
color: "#217050",
xAxis: {
label: {
autoHide: false,
autoRotate: true
}
}
}
if (this.chartTypes.age === "column") {
this.charts.ageChart = new G2Plot.Column("ageChart", {
...commonConfig,
label: {
position: "top"
}
})
} else {
this.charts.ageChart = new G2Plot.Line("ageChart", {
...commonConfig,
smooth: true,
point: {
size: 5,
shape: "diamond"
}
})
}
this.charts.ageChart.render()
},
// 学历分布图
renderEducationChart() {
const container = document.getElementById("educationChart")
if (!container) return
if (this.charts.educationChart) {
this.charts.educationChart.destroy()
}
const educationData = this.getEducationDistribution()
if (this.chartTypes.education === "pie") {
this.charts.educationChart = new G2Plot.Pie("educationChart", {
data: educationData,
angleField: "count",
colorField: "education",
radius: 0.8,
label: {
type: "outer",
content: "{name}: {percentage}"
},
interactions: [{ type: "element-active" }],
legend: { position: "right" },
color: ["#217050", "#5fad85", "#89d0af", "#c2e6d4", "#136343"]
})
} else {
this.charts.educationChart = new G2Plot.Column("educationChart", {
data: educationData,
xField: "education",
yField: "count",
label: {
position: "top"
},
color: "#217050",
xAxis: {
label: {
autoHide: false,
autoRotate: true
}
}
})
}
this.charts.educationChart.render()
},
// 收入分布图
renderIncomeChart() {
const container = document.getElementById("incomeChart")
if (!container) return
if (this.charts.incomeChart) {
this.charts.incomeChart.destroy()
}
const incomeData = this.getIncomeDistribution()
if (this.chartTypes.income === "pie") {
this.charts.incomeChart = new G2Plot.Pie("incomeChart", {
data: incomeData,
angleField: "count",
colorField: "income",
radius: 0.8,
label: {
type: "outer",
content: "{name}: {percentage}"
},
interactions: [{ type: "element-active" }],
legend: { position: "right" },
color: ["#217050", "#5fad85", "#89d0af", "#c2e6d4", "#136343"]
})
} else {
this.charts.incomeChart = new G2Plot.Column("incomeChart", {
data: incomeData,
xField: "income",
yField: "count",
label: {
position: "top"
},
color: "#217050",
xAxis: {
label: {
autoHide: false,
autoRotate: true
}
}
})
}
this.charts.incomeChart.render()
},
// 单位工会分布图
renderUnitChart() {
const container = document.getElementById("unitChart")
if (!container) return
if (this.charts.unitChart) {
this.charts.unitChart.destroy()
}
const unitData = this.getUnitDistribution()
if (this.chartTypes.unit === "bar") {
this.charts.unitChart = new G2Plot.Bar("unitChart", {
data: unitData,
xField: "count",
yField: "unit",
seriesField: "unionName",
isStack: true,
legend: {
position: "top-right"
},
color: ["#217050", "#5fad85", "#89d0af", "#c2e6d4", "#136343"],
label: {
position: "middle",
layout: [{ type: "interval-adjust-position" }]
}
})
} else {
const processedData = this.getTreemapData()
this.charts.unitChart = new G2Plot.Treemap("unitChart", {
data: processedData,
colorField: "value",
legend: false,
color: ["#e8f5e9", "#c2e6d4", "#89d0af", "#5fad85", "#217050"]
})
}
this.charts.unitChart.render()
},
// 获取性别分布数据
getGenderDistribution() {
const data = this.teacherData
const genderCount = {}
data.forEach((item) => {
const gender = item.sex || "未知"
genderCount[gender] = (genderCount[gender] || 0) + 1
})
return Object.keys(genderCount).map((key) => ({
type: key,
value: genderCount[key]
}))
},
// 获取年龄分布数据
getAgeDistribution() {
const data = this.teacherData
const ageRanges = {
"25岁以下": 0,
"26-30岁": 0,
"31-35岁": 0,
"36-40岁": 0,
"41-45岁": 0,
"46-50岁": 0,
"51岁以上": 0
}
data.forEach((item) => {
if (!item.birthday) return
const age = this.calculateAge(item.birthday)
if (age <= 25) ageRanges["25岁以下"]++
else if (age <= 30) ageRanges["26-30岁"]++
else if (age <= 35) ageRanges["31-35岁"]++
else if (age <= 40) ageRanges["36-40岁"]++
else if (age <= 45) ageRanges["41-45岁"]++
else if (age <= 50) ageRanges["46-50岁"]++
else ageRanges["51岁以上"]++
})
return Object.keys(ageRanges).map((key) => ({
range: key,
count: ageRanges[key]
}))
},
// 获取学历分布数据
getEducationDistribution() {
const data = this.teacherData
const educationCount = {}
data.forEach((item) => {
const education = item.education || "未知"
educationCount[education] = (educationCount[education] || 0) + 1
})
return Object.keys(educationCount).map((key) => ({
education: key,
count: educationCount[key]
}))
},
// 获取收入分布数据
getIncomeDistribution() {
const data = this.teacherData
const incomeCount = {}
data.forEach((item) => {
const income = item.monthlyIncome || "未知"
incomeCount[income] = (incomeCount[income] || 0) + 1
})
return Object.keys(incomeCount).map((key) => ({
income: key,
count: incomeCount[key]
}))
},
// 获取单位分布数据
getUnitDistribution() {
const data = this.teacherData
const unitData = []
data.forEach((item) => {
const unit = item.unitName || "未知单位"
const union = item.unionName || "未知工会"
const existingUnit = unitData.find((u) => u.unit === unit && u.unionName === union)
if (existingUnit) {
existingUnit.count++
} else {
unitData.push({
unit,
unionName: union,
count: 1
})
}
})
return unitData.sort((a, b) => a.count - b.count)
},
// 矩形树图数据处理
getTreemapData() {
const data = this.teacherData
const unionMap = {}
// 按工会和单位分组统计
data.forEach((item) => {
const union = item.unionName || "未知工会"
const unit = item.unitName || "未知单位"
if (!unionMap[union]) {
unionMap[union] = {
name: union,
value: 0,
children: {}
}
}
unionMap[union].value++
if (!unionMap[union].children[unit]) {
unionMap[union].children[unit] = {
name: unit,
value: 0
}
}
unionMap[union].children[unit].value++
})
// 转换为G2Plot需要的格式
const result = {
name: "root",
children: []
}
Object.keys(unionMap).forEach((union) => {
const unionData = unionMap[union]
const children = []
Object.keys(unionData.children).forEach((unit) => {
children.push({
name: unit,
value: unionData.children[unit].value
})
})
result.children.push({
name: union,
value: unionData.value,
children
})
})
return result
}
},
mounted() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.fetchData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,293 @@
const formEdit = {
template: /*language=HTML*/ `
<el-dialog :title="formData.id ? '编辑单身教工信息' : '新增单身教工信息'" :visible.sync="visible" width="65%"
append-to-body>
<el-form ref="form" :model="formData" :rules="rules" label-width="120px" size="small"
class="single-teacher-form">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="选择用户" prop="userId" v-if="!formData.id">
<el-select
v-model="formData.userId"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索用户"
:remote-method="remoteSearchUsers"
:loading="userSearchLoading"
style="width: 100%"
@change="handleUserChange">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.username + '(' + item.loginname + ')'"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="用户信息" v-else>
<el-input v-model="formData.username" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="联系方式" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入联系方式"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出生年月" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
placeholder="选择日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="身高(cm)" prop="height">
<el-input v-model="formData.height" placeholder="请输入身高"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="籍贯" prop="nativePlace">
<el-input v-model="formData.nativePlace" placeholder="请输入籍贯"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="学历" prop="education">
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
code="USER_EDUCATION"></dict-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="婚姻状况" prop="maritalStatus">
<el-select v-model="formData.maritalStatus" placeholder="请选择婚姻状况"
style="width: 100%">
<el-option label="未婚" value="未婚"></el-option>
<el-option label="离婚" value="离婚"></el-option>
<el-option label="丧偶" value="丧偶"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="月收入" prop="monthlyIncome">
<el-select v-model="formData.monthlyIncome" placeholder="请选择月收入范围"
style="width: 100%">
<el-option label="5000以下" value="5000以下"></el-option>
<el-option label="5000-8000" value="5000-8000"></el-option>
<el-option label="8000-10000" value="8000-10000"></el-option>
<el-option label="10000-15000" value="10000-15000"></el-option>
<el-option label="15000以上" value="15000以上"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="住房情况" prop="housingSituation">
<el-select v-model="formData.housingSituation" placeholder="请选择住房情况"
style="width: 100%">
<el-option label="已购房" value="已购房"></el-option>
<el-option label="租房" value="租房"></el-option>
<el-option label="与父母同住" value="与父母同住"></el-option>
<el-option label="单位宿舍" value="单位宿舍"></el-option>
<el-option label="其他" value="其他"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="兴趣爱好" prop="hobby">
<el-input v-model="formData.hobby" placeholder="请输入兴趣爱好,多个用逗号分隔"></el-input>
</el-form-item>
<el-form-item label="形象照片" prop="photo" class="avatar-container">
<file-upload
:value.sync="formData.photo"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item label="生活照片" prop="picFiles" class="gallery-container">
<file-upload
:value.sync="formData.picFiles"
:upload_number="5"
upload_mode="image"
upload_result_category="array"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item label="交友意向" prop="intentionFriends">
<el-input type="textarea" v-model="formData.intentionFriends" :rows="3"
placeholder="请描述您的交友意向"></el-input>
</el-form-item>
<el-form-item label="个人介绍" prop="introduction">
<el-input type="textarea" v-model="formData.introduction" :rows="4"
placeholder="请简要介绍一下自己"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="visible = false">取 消</el-button>
<el-button type="primary" @click="submitForm" :loading="loading">确 定</el-button>
</div>
</el-dialog>
`,
data() {
return {
visible: false,
loading: false,
userSearchLoading: false,
userOptions: [],
formData: {
userId: "",
userName: "",
birthday: "",
mobile: "",
height: "",
hometown: "",
education: "",
hobby: "",
monthlyIncome: "",
housingSituation: "",
picFiles: [],
photo: "",
maritalStatus: "",
intentionFriends: "",
introduction: ""
},
rules: {
userId: [{ required: true, message: "请选择用户", trigger: ["change", "blur"] }],
mobile: [
{ required: true, message: "请输入联系方式", trigger: ["change", "blur"] },
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号码", trigger: ["change", "blur"] }
],
birthday: [{ required: true, message: "请选择出生年月", trigger: ["change", "blur"] }],
height: [{ pattern: /^\d{2,3}$/, message: "请输入正确的身高", trigger: ["change", "blur"] }],
education: [{ required: true, message: "请选择学历", trigger: ["change", "blur"] }],
maritalStatus: [{ required: true, message: "请选择婚姻状况", trigger: ["change", "blur"] }],
introduction: [{ required: true, message: "请填写个人介绍", trigger: ["change", "blur"] }]
}
}
},
methods: {
onOpen(data) {
this.visible = true
this.loading = false
this.userOptions = [] // 清空用户选项
if (data && data.id) {
this.formData = JSON.parse(JSON.stringify(data))
this.formData.picFiles = JSON.parse(this.formData.picFiles)
} else {
this.formData = {
userId: "",
userName: "",
birthday: "",
mobile: "",
height: "",
nativePlace: "",
education: "",
hobby: "",
monthlyIncome: "",
housingSituation: "",
picFiles: [],
photo: "",
maritalStatus: "",
intentionFriends: "",
introduction: ""
}
}
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate()
}
})
},
// 远程搜索用户
remoteSearchUsers(query) {
if (query !== "") {
this.userSearchLoading = true
this.$axios
.post("/platform/singleTeacher/ledger/queryNotSingleTeacher", { key: query })
.then((res) => {
if (res.code === 0) {
this.userOptions = res.data || []
} else {
this.$message.error(res.msg || "搜索用户失败")
}
})
.finally(() => {
this.userSearchLoading = false
})
} else {
this.userOptions = []
}
},
// 用户选择变更
handleUserChange(userId) {
const selectedUser = this.userOptions.find((item) => item.id === userId)
if (selectedUser) {
// 自动填充一些基础信息
this.formData.userName = selectedUser.name
this.formData.mobile = selectedUser.mobile || ""
this.formData.birthday = selectedUser.birthday || ""
this.formData.education = selectedUser.education || ""
this.formData.nativePlace = selectedUser.nativePlace || ""
}
},
submitForm() {
this.$refs.form.validate((valid) => {
if (valid) {
this.loading = true
// 构建提交的数据
const submitData = { ...this.formData }
// 发送请求
const url = submitData.id ? "/platform/singleTeacher/ledger/update" : "/platform/singleTeacher/ledger/insert"
this.$axios
.post(url, { singleTeacher: JSON.stringify(submitData) })
.then((res) => {
if (res.code === 0) {
this.$message.success(submitData.id ? "修改成功" : "添加成功")
this.visible = false
this.$emit("refresh")
} else {
this.$message.error(res.msg || "操作失败")
}
})
.finally(() => {
this.loading = false
})
}
})
}
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,156 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名工号">
<el-input placeholder="请输入姓名或者工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" clearable style="width: 100%">
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" style="width: 100%" v-model="pageForm.unitId" clearable
filterable>
<el-option v-for="item in unitOptions" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="性别">
<el-select v-model="pageForm.sex" placeholder="请选择性别" clearable style="width: 100%">
<el-option label="男性" value="男性"></el-option>
<el-option label="女性" value="女性"></el-option>
</el-select>
</search-item>
<search-item label="年龄区间">
<div style="display: flex; align-items: center">
<el-slider v-model="pageForm.age" range show-stops :max="100" style="flex: 1; padding: 0 12px"></el-slider>
<div style="width: 70px; flex-shrink: 0; text-align: right">{{ pageForm.age ? pageForm.age.join('-') : '' }}</div>
</div>
</search-item>
<search-item label="婚姻状况">
<el-select v-model="pageForm.marriage" placeholder="请选择婚姻状况" clearable style="width: 100%">
<el-option label="未婚" value="未婚"></el-option>
<el-option label="已婚" value="已婚"></el-option>
<el-option label="离异" value="离异"></el-option>
<el-option label="丧偶" value="丧偶"></el-option>
</el-select>
</search-item>
<search-item label="学历">
<el-select clearable placeholder="请选择学历"
style="width: 100%;"
v-model="pageForm.education">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.USER_EDUCATION"></el-option>
</el-select>
</search-item>
<search-item label="教职工类别">
<el-select clearable placeholder="请选择人员类型"
style="width: 100%;"
v-model="pageForm.personType">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.USER_PERSON_TYPE"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<el-select clearable placeholder="请选择在职状态"
style="width: 100%;"
v-model="pageForm.userState">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.USER_STATE"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="$refs.formEditRef.onOpen()">新增</el-button>
<el-button size="mini" type="primary" icon="el-icon-download" @click="exportExcel">导出</el-button>
</table-tool>
<el-table :data="tableData">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod" fixed="left"></el-table-column>
<el-table-column prop="username" label="姓名" width="100" sortable="custom" fixed="left"></el-table-column>
<el-table-column prop="loginname" label="工号" width="100" sortable="custom"></el-table-column>
<el-table-column prop="sex" label="性别" width="100" sortable="custom"></el-table-column>
<el-table-column prop="mobile" label="手机号码" width="120"></el-table-column>
<el-table-column prop="birthday" label="出生日期" width="120" sortable="custom"></el-table-column>
<el-table-column prop="education" label="学历" width="150" show-overflow-tooltip></el-table-column>
<el-table-column prop="maritalStatus" label="婚姻状况" width="120" sortable="custom"></el-table-column>
<el-table-column prop="unitName" label="单位名称" width="180" show-overflow-tooltip sortable="custom"></el-table-column>
<el-table-column prop="unionName" label="工会名称" width="150" show-overflow-tooltip sortable="custom"></el-table-column>
<el-table-column prop="introduction" label="介绍" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="$refs.formEditRef.onOpen(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="onDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<form-edit ref="formEditRef" @refresh="doSearch"></form-edit>
</div>
<script nonce="${cspNonce!}">
<!--#include("formEdit.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
dicts: ["USER_STATE", "USER_PERSON_TYPE", "USER_EDUCATION"],
components: {
"form-edit": formEdit
},
data() {
return {
unionOptions: [],
unitOptions: [],
pageForm: {
age: [0, 100]
}
}
},
methods: {
pageData() {
this.$axios.post("/platform/singleTeacher/ledger/pageData", { pageForm: JSON.stringify(this.pageForm) }).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const { code, msg } = await this.$axios.post("/platform/singleTeacher/ledger/delete", { id: id })
if (code === 0) {
this.$message.success(msg)
this.doSearch()
}
})
.catch(() => {})
},
exportExcel() {
this.$downLoad("/platform/singleTeacher/ledger/exportExcel", { pageForm: JSON.stringify(this.pageForm) })
}
},
created() {
this.pageData()
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,325 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.query-row {
height: 55px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.query-row:not(:last-child) {
border-bottom: 1px dashed rgb(230, 230, 230);
}
.query-row-title {
width: 120px;
}
</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"></el-input>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
<search-item label="编制类别">
<dict-select v-model="pageForm.preparedBy" placeholder="编制类别" @change="doSearch"
code="USER_PREPARED_BY_TYPE"></dict-select>
</search-item>
<!-- <search-item label="变更类型">-->
<!-- <dict-select v-model="pageForm.changeType" placeholder="变更类型" @change="doSearch"-->
<!-- code="MEMBER_CHANGE_TYPE"></dict-select>-->
<!-- </search-item>-->
<search-item label="变更来源">
<el-select clearable filterable placeholder="请选择变更来源" style="width: 100%"
v-model="pageForm.changeOrigin">
<el-option :key="item.name" :label="item.changeOriginName" :value="item.name"
v-for="item in changeOriginData"></el-option>
</el-select>
</search-item>
<search-item label="变更日期">
<el-date-picker :picker-options="pickerOptions" @change="changeDateRangeChange"
align="right" end-placeholder="结束日期" format="yyyy-MM-dd"
range-separator="-" start-placeholder="开始日期" style="width: 100%"
type="datetimerange" v-model="pageForm.changeDateRange"
value-format="yyyy-MM-dd"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<el-row type="flex" align="middle" class="query-row">
<el-col class="query-row-title">异动类型:</el-col>
<el-col class="query-row-content">
<el-tag
style="margin-right: 10px;margin-top: 5px;cursor: pointer"
v-for="item in changeTypeData"
:key="item.code"
:type="item.name"
:effect="pageForm.changeTypes.includes(item.code)?'dark':'plain'"
@click="tagClick('changeTypes',item.code)">
{{ item.changeTypeName }}
</el-tag>
<el-link type="danger"
v-if="changeTypeData.length && pageForm.changeTypes.length"
:underline="false"
@click="pageForm.changeTypes=[];doSearch()">清空
</el-link>
</el-col>
</el-row>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="变更记录(默认查询当天变更记录,如需查询更多变更记录,请选择上方【变更日期】后点击搜索)">
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod"
header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop == 'loginname'">
<el-link @click="openView(row)" type="primary">{{row.loginname}}</el-link>
</template>
<template scope="{row}" v-else-if="column.prop == 'changeTypes'">
<span style="color: #0e78c5;cursor: pointer" @click="openUserChangeInfo(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
<template scope="{row}" v-else-if="column.prop == 'changeOrigin'">
<span style="color: #0e78c5">
{{getChangeOrigin(row.changeOrigin)}}
</span>
</template>
</el-table-column>
<el-table-column label="操作" width="130px">
<template slot-scope="{row}">
<el-button @click="openUserChangeInfo(row)" size="mini" type="primary">查看变更</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
<template #public>
<member-all-change-info ref="memberAllChangeInfoRef"></member-all-change-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../member/common/info/memberInfo.js"){}#-->
<!--#include("../../member/change/common/memberAllChangeInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
store,
data() {
return{
pickerOptions: {
shortcuts: [
{
text: "最近一周",
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit("pick", [start, end])
}
},
{
text: "最近一个月",
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit("pick", [start, end])
}
},
{
text: "最近三个月",
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit("pick", [start, end])
}
}
]
},
pageForm: {
searchKeyword: "",
unionId: "",
unitId: "",
userState: "",
preparedBy: "",
personType: "",
changeDateRange: [],
changeTypes: [],
},
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true, width: "100px" },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "personType", label: "教职工类别", sortable: true },
{ prop: "preparedBy", label: "编制类别", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "changeTypes", label: "变更类型", sortable: true },
{ prop: "changeOrigin", label: "变更来源", sortable: true },
// { prop: "remark", label: "变更说明", sortable: true },
],
unions: [],
units: [],
changeOriginData: [],
changeTypeData: [],
}
},
components: {
'member-info': MEMBER_INFO,
'member-all-change-info': MEMBER_ALL_CHANGE_INFO,
},
methods: {
tagClick(key, val) {
let idx = this.pageForm[key].indexOf(val)
if (idx !== -1) {
this.pageForm[key].splice(idx, 1)
} else {
this.pageForm[key].push(val)
}
this.pageData()
},
setDefaultDateRange() {
const end = new Date(); // 当前时间
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); // 当前时间往前推90天
this.$set(this.pageForm, "changeDateRange", [start, end])
this.pageForm.changeDateBefore = start
this.pageForm.changeDateEnd = end
this.doSearch()
},
changeDateRangeChange(val){
if (val && val.length > 0) {
this.pageForm.changeDateBefore = val[0]
this.pageForm.changeDateEnd = val[1]
} else {
this.pageForm.changeDateBefore = null
this.pageForm.changeDateEnd = null
}
this.doSearch()
},
// 查看当前人员信息
openView(row) {
this.$refs.guava.view(() => {
return this.$refs.memberInfoRef.onOpen(row.userId)
})
},
// 全部变更
openUserChangeInfo(row) {
this.$refs.guava.public(() => {
return this.$refs.memberAllChangeInfoRef.onOpen(row.userId)
})
},
// // 当前变更
// openCurrentUserChangeInfo(row) {
// this.$refs.guava.public(() => {
// this.$refs.memberAuditChangeInfoRef.onOpen({userId:row.userId, recordId:row.id})
// })
// },
getChangeTypes(changeTypes) {
const changeTypesList = JSON.parse(changeTypes)
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
getChangeOrigin(changeOrigin) {
if (changeOrigin) {
return this.changeOriginData.find((item) => item.name === changeOrigin).changeOriginName
}
return null
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.units = data
})
}
},
async initData() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.unions = await this.$businessTool.listUnion(this.pageForm.unionId)
this.units = await this.$businessTool.listUnit()
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
this.units = await this.$businessTool.listUnit(this.$store.state.user.union.id)
}
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
this.changeOriginData = await this.$businessTool.getEnumOptions("MemberChangeOrigin")
},
async pageData() {
const pageForm = clone(this.pageForm)
pageForm.changeTypes = JSON.stringify(this.pageForm.changeTypes)
const resp = await $.post('/platform/sourcechange/manage/pageData', pageForm)
if (resp.code === 0) {
this.tableData = resp.data.list
this.pageForm.totalCount = resp.data.totalCount
} else {
this.$message.warning(resp.msg)
}
}
},
async created() {
await this.initData()
await this.setDefaultDateRange()
},
});
</script>
<!--#
}
#-->
@@ -0,0 +1,239 @@
const ADD_OR_MODIFY_SPECIAL_STAFF = {
template: /*language=HTML*/ `
<div>
<el-dialog :title="specialStaffTitle" :visible.sync="specialStaffDialog"
:close-on-click-modal="false" width="50%">
<el-form ref="form" :model="formData" :rules="formRules" label-width="145px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="工号" prop="userId">
<el-select v-model="formData.userId"
:remote-method="queryUser"
filterable
remote
:disabled="isView"
reserve-keyword
placeholder="请输入工号或者姓名查找"
style="width: 100%"
@change="getUserInfo">
<el-option v-for="item in users"
:key="item.id"
:label="item.username+'('+item.loginname+')' + '--' + (item.unionName || '无工会') + '('+item.unitName + ')'"
:value="item.id"></el-option>
</el-select>
<!-- <el-input v-model="formData.userName" :disabled="formData.userId!=null" placeholder="工号"></el-input>-->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="username">
<el-input v-model="formData.username" placeholder="请输入工号查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="所属单位(人事关系)" prop="personnelRelationUnitName">
<el-input v-model="formData.personnelRelationUnitName" placeholder="请输入工号或姓名查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属工会(人事关系)" prop="personnelRelationUnionName">
<el-input v-model="formData.personnelRelationUnionName" placeholder="请输入工号或姓名查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<template v-if="isThreeUnit">
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="所属科室(人事关系)" prop="personnelRelationThreeUnitName">
<el-input v-model="formData.personnelRelationThreeUnitName" placeholder="请输入工号或姓名查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工会小组(人事关系)" prop="personnelRelationUnionGroupName">
<el-input v-model="formData.personnelRelationUnionGroupName" placeholder="请输入工号或姓名查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
</template>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="特殊人员类型" prop="specialStaffType">
<dict-select v-model="formData.specialStaffType" placeholder="特别人员所属类型" @change="changeType"
style="width: 100%" :disabled="isView" code="SPECIAL_STAFF_TYPE"></dict-select>
</el-form-item>
</el-col>
</el-row>
<template v-if="formData.isManyUnit">
<el-row :gutter="10">
<el-col :span=12>
<el-form-item label="所属单位(工会关系)" prop="unionRelationUnitId">
<el-select
v-model="formData.unionRelationUnitId"
filterable
clearable
:disabled="isView"
placeholder="请选择工会关系单位"
style="width: 100%"
@change="unionRelationUnitChange">
<el-option v-for="unit in units" :key="unit.id"
:label="unit.name" :value="unit.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span=12>
<el-form-item label="所属工会(工会关系)" prop="unionRelationUnionName">
<el-input v-model="formData.unionRelationUnionName" placeholder="请选择工会关系单位查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<template v-if="isThreeUnit">
<el-row :gutter="10">
<el-col :span=12>
<el-form-item label="所属科室(工会关系)" prop="unionRelationThreeUnitId">
<el-select
v-model="formData.unionRelationThreeUnitId"
filterable
clearable
:disabled="isView"
placeholder="请选择工会关系所属科室"
style="width: 100%"
@change="unionRelationThreeUnitChange"
>
<el-option
v-for="unit in threeUnits"
:key="unit.id"
:label="unit.name"
:value="unit.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span=12>
<el-form-item label="工会小组(工会关系)" prop="unionRelationUnionGroupName">
<el-input :value="formData.unionRelationUnionGroupName" placeholder="请选择工会关系所属科室,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
</template>
</template>
<!-- 杭州医学院多单位人员 -->
<template v-if="formData.specialStaffType == 'HMC_RELATION'">
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="所属工会(工会关系)" prop="unionRelationUnionId">
<el-select v-model="formData.unionRelationUnionId" filterable
:disabled="isView" @change="unionRelationUnionChange"
clearable placeholder="请选择工会关系所属工会" style="width: 100%">
<el-option v-for="item in unionRelationUnionOptions" :key="item.id"
:label="item.unionname" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
<el-row :gutter="10">
<el-col :span=24>
<el-form-item label="备注" prop="specialStaffRemark">
<el-input type="textarea" :rows="3" placeholder="请输入人员备注"
v-model="formData.specialStaffRemark" maxlength="200" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row v-if="!isView" :gutter="10" style="text-align: right">
<el-button class="submit-btn" @click="specialStaffDialog = false">关闭</el-button>
<el-button class="submit-btn" @click="doSubmit" type="primary">提交</el-button>
</el-row>
</el-dialog>
</div>
`,
store,
props: {
isView: { type: Boolean, default: false }
},
data() {
return {
isThreeUnit: false,
formData: {},
units: [],
specialStaffTypeList: [],
users: [],
formRules: {
userId: [{ required: true, message: "请输入工号", trigger: "change" }],
specialStaffType: [{ required: true, message: "请选择人员类型", trigger: "change" }],
unionRelationUnionId: [{ required: true, message: "请选择工会关系所属工会", trigger: "change" }],
specialStaffRemark: [{ required: true, message: "请填写多单位人员备注", trigger: "change" }]
}
}
},
methods: {
getUserInfo(id) {
if (!id && !this.formData.userId) {
return
}
const url = !this.formData.userId
? "/platform/staff/special/manage/getSpecialStaffUserInfo"
: "/platform/staff/special/manage/getUserInfo"
const param = id ? id : this.formData.userId
this.$axios.post(url, { userId: param }).then((resp) => {
if (resp.code === 0) {
this.formData = resp.data
this.queryUser(this.formData.loginname)
}
})
},
changeType() {
const data = this.specialStaffTypeList.find((v) => v.code === this.formData.specialStaffType)
if (data && data.code === "MANY_UNIT") {
this.formData.isManyUnit = true
}
},
unionRelationUnitChange(v) {
const unit = this.units.find((item) => item.id === v)
if (unit) {
this.$set(this.formData, "unionRelationUnionId", unit.unionId)
this.$set(this.formData, "unionRelationUnionName", unit.unionName)
} else {
this.$set(this.formData, "unionRelationUnionId", null)
this.$set(this.formData, "unionRelationUnionName", null)
}
},
queryUser(keyWord) {
if (!keyWord) {
return
}
this.$axios.post("/platform/staff/special/manage/queryUser", { keyWord }).then((res) => {
this.users = res.data
})
},
doSubmit() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
this.$axios
.post("/platform/staff/special/manage/addSpecialStaff", {
data: JSON.stringify(this.formData)
})
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$emit("finish")
}
})
}
})
}
},
created() {
this.$businessTool.getDictOptions("SPECIAL_STAFF_TYPE").then((data) => {
this.specialStaffTypeList = data
})
this.$businessTool.listUnit().then((data) => {
this.units = data
})
}
}
@@ -0,0 +1,382 @@
<!--#
layout("/layouts/platform.html"){
#-->
<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"></el-input>
</search-item>
<search-item label="所属类型">
<dict-select v-model="pageForm.specialStaffType" placeholder="特别人员所属类型" @change="doSearch"
code="SPECIAL_STAFF_TYPE"></dict-select>
</search-item>
<search-item label="所属工会">
<el-select @change="flushUnits();doSearch()" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" placeholder="在职状态" @change="doSearch"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" placeholder="教职工类别" @change="doSearch"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="人员列表">
<el-button size="small" type="primary" @click="personnelAdd">新增人员</el-button>
</table-tool>
<el-table ref="table" :data="tableData" :size="tableSize" row-key="id"
style="width: 100%" @sort-change="pageOrder">
<el-table-column :index="indexMethod" header-align="center" label="序号" type="index" width="80px"></el-table-column>
<el-table-column v-for="column in tableColumns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
header-align="center"
show-overflow-tooltip>
<template scope="{row}" v-if="column.prop==='personnelRelationUnionName'">
<el-tag effect="plain">
{{row.personnelRelationUnionName || '无工会'}}
</el-tag>
</template>
<template scope="{row}" v-else-if="column.prop==='unionRelationUnionName'">
<el-tag>
{{row.unionRelationUnionName || '无工会'}}
</el-tag>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作">
<template scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="el-icon-s-tools"></i>
<i class="el-icon-arrow-down"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'view',data:scope.row}">
查看
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',data:scope.row}">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',data:scope.row}">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<el-dialog :title="specialStaffTitle" :visible.sync="specialStaffDialog"
:close-on-click-modal="false" width="50%">
<el-form ref="form" :model="formData" :rules="formRules" label-width="145px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="工号" prop="userId">
<el-select v-model="formData.userId"
:remote-method="queryUser"
filterable
remote
:disabled="isView"
reserve-keyword
placeholder="请输入工号或者姓名查找"
style="width: 100%"
@change="getUserInfo">
<el-option v-for="item in users"
:key="item.id"
:label="item.username+'('+item.loginname+')' + '--' + (item.unionName || '无工会') + '('+item.unitName + ')'"
:value="item.id"></el-option>
</el-select>
<!-- <el-input v-model="formData.userName" :disabled="formData.userId!=null" placeholder="工号"></el-input>-->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="username">
<el-input v-model="formData.username" placeholder="请输入工号查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="所属单位(人事关系)" prop="personnelRelationUnitName">
<el-input v-model="formData.personnelRelationUnitName" placeholder="请输入工号或姓名查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属工会(人事关系)" prop="personnelRelationUnionName">
<el-input v-model="formData.personnelRelationUnionName" placeholder="请输入工号或姓名查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="特殊人员类型" prop="specialStaffType">
<dict-select v-model="formData.specialStaffType" placeholder="特别人员所属类型" @change="changeType"
style="width: 100%" :disabled="isView" code="SPECIAL_STAFF_TYPE"></dict-select>
</el-form-item>
</el-col>
</el-row>
<template v-if="formData.isManyUnit && formData.specialStaffType != 'HMC_RELATION'">
<el-row :gutter="10">
<el-col :span=12>
<el-form-item label="所属单位(工会关系)" prop="unionRelationUnitId">
<el-select
v-model="formData.unionRelationUnitId"
filterable
clearable
:disabled="isView"
placeholder="请选择工会关系单位"
style="width: 100%"
@change="unionRelationUnitChange">
<el-option v-for="unit in units" :key="unit.id"
:label="unit.name" :value="unit.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span=12>
<el-form-item label="所属工会(工会关系)" prop="unionRelationUnionName">
<el-input v-model="formData.unionRelationUnionName" placeholder="请选择工会关系单位查询,查询后自动读取" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
</template>
<!-- 杭州医学院多单位人员 -->
<template v-if="formData.specialStaffType == 'HMC_RELATION'">
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="所属工会(工会关系)" prop="unionRelationUnionId">
<el-select v-model="formData.unionRelationUnionId" filterable
:disabled="isView" @change="unionRelationUnionChange"
clearable placeholder="请选择工会关系所属工会" style="width: 100%">
<el-option v-for="item in unionRelationUnionOptions" :key="item.id"
:label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
<el-row :gutter="10">
<el-col :span=24>
<el-form-item label="备注" prop="specialStaffRemark">
<el-input type="textarea" :rows="3" placeholder="请输入人员备注"
v-model="formData.specialStaffRemark" maxlength="200" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row v-if="!isView" :gutter="10" style="text-align: right">
<el-button class="submit-btn" @click="specialStaffDialog = false">关闭</el-button>
<el-button class="submit-btn" @click="doSubmit" type="primary">提交</el-button>
</el-row>
</el-dialog>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
dicts: ['SPECIAL_STAFF_TYPE'],
mixins: [initTableMixins],
data() {
return{
isView: true,
isThreeUnit: false,
tableColumns: [
{ prop: 'loginname', label: '工号' },
{ prop: 'username', label: '姓名' },
{ prop: 'sex', label: '性别' },
{ prop: 'mobile', label: '联系电话' },
{ prop: 'personType', label: '教职工类别', sortable: true },
{ prop: 'userState', label: '在职状态', sortable: true },
{ prop: 'distSpecialStaffType', label: '特别人员类型', sortable: true },
{ prop: 'personnelRelationUnionName', label: '人事关系工会', sortable: true, width: 180 },
{ prop: 'personnelRelationUnitName', label: '人事关系单位', sortable: true },
{ prop: 'unionRelationUnionName', label: '工会关系工会', sortable: true, width: 180 },
// { prop: 'specialStaffRemark', label: '多单位人员备注', sortable: true, checked: 0 }
],
unions: [],
units: [],
threeUnits: [],
formData: {
personnelRelationThreeUnitName: '',
personnelRelationUnionGroupName: '',
},
specialStaffTypeList: [],
users: [],
formRules: {
userId: [{ required: true, message: "请输入工号", trigger: "change" }],
specialStaffType: [{ required: true, message: "请选择人员类型", trigger: "change" }],
unionRelationUnionId: [{ required: true, message: "请选择工会关系所属工会", trigger: "change" }],
specialStaffRemark: [{ required: true, message: "请填写多单位人员备注", trigger: "change" }]
},
specialStaffDialog: false,
specialStaffTitle: '',
// HMC工会关系工会
unionRelationUnionOptions: []
}
},
methods: {
unionRelationUnionChange(val){
const unionInfo = this.unionRelationUnionOptions.find(v=> v.id === val)
this.formData.unionRelationUnionName = unionInfo.name
},
dropdownCommand(command) {
const { type, data } = command
if (type === 'view') {
this.openView(data.userId)
} else if (type === 'edit') {
this.openEdit(data.userId)
} else if (type === 'delete') {
this.doDelete(data)
}
},
doDelete(obj) {
this.$confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/staff/special/manage/removeSpecialStaff', {userId:obj.userId}).then(res => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
}
})
})
},
openEdit(userId) {
this.isView = false
this.formData = {}
this.getUserInfo(userId)
this.specialStaffDialog = true
this.specialStaffTitle = "修改人员"
},
openView(userId) {
this.isView = true
this.formData = {}
this.getUserInfo(userId)
this.specialStaffDialog = true
this.specialStaffTitle = "查看人员信息"
},
personnelAdd() {
this.isView = false
this.formData = {}
this.specialStaffDialog = true
this.specialStaffTitle = "新增人员"
},
getUserInfo(id) {
if (!id && !this.formData.userId) {
return
}
const url = !this.formData.userId
? "/platform/staff/special/manage/getSpecialStaffUserInfo"
: "/platform/staff/special/manage/getUserInfo"
const param = id ? id : this.formData.userId
this.$axios.post(url, { userId: param }).then((resp) => {
if (resp.code === 0) {
this.formData = resp.data
this.queryUser(this.formData.loginname, false)
}
})
},
changeType() {
const data = this.specialStaffTypeList.find((v) => v.code === this.formData.specialStaffType)
if (data && data.code === "MANY_UNIT") {
this.formData.isManyUnit = true
}
},
unionRelationUnitChange(v) {
const unit = this.units.find((item) => item.id === v)
if (unit) {
this.$set(this.formData, "unionRelationUnitId", unit.id)
this.$set(this.formData, "unionRelationUnitName", unit.name)
this.$set(this.formData, "unionRelationUnionId", unit.unionId)
this.$set(this.formData, "unionRelationUnionName", unit.unionName)
} else {
this.$set(this.formData, "unionRelationUnionId", null)
this.$set(this.formData, "unionRelationUnionName", null)
}
},
queryUser(keyWord, flag = true) {
if (!keyWord) {
return
}
this.$axios.post("/platform/staff/special/manage/queryUser", { keyWord, flag }).then((res) => {
this.users = res.data
})
},
doSubmit() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
this.$axios.post("/platform/staff/special/manage/addSpecialStaff", {
data: JSON.stringify(this.formData)
})
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.formData = {}
this.specialStaffDialog = false
this.pageData()
}
})
}
})
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
}
},
async initData() {
this.$businessTool.getDictOptions("SPECIAL_STAFF_TYPE").then((data) => {
this.specialStaffTypeList = data
})
this.unionRelationUnionOptions = await this.$businessTool.listUnion()
this.units = await this.$businessTool.listUnit()
},
},
async created() {
this.initData()
this.pageData()
this.unions = await this.$businessTool.listUnion()
},
});
</script>
<!--#
}
#-->
@@ -0,0 +1,342 @@
<!--#
layout("/layouts/platform.html"){
#-->
<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"
style="width: 100%">
</el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" clearable style="width: 100%"
@change="flushUnits">
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" v-model="pageForm.unitId"
style="width: 100%;"
clearable
filterable>
<el-option v-for="item in unitOptions" :label="item.name"
:value="item.id"
:key="item.id"></el-option>
</el-select>
</search-item>
<search-item label="进校时长">
<el-input placeholder="请输入进校时长" clearable v-model="pageForm.teachNum"
style="width: 100%"
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="办证年份">
<el-date-picker
format="yyyy"
value-format="yyyy"
v-model="pageForm.thirtyCertificateProcessingTime"
type="year"
placeholder="请选择荣誉证办理办证年份"
style="width: 100%">
</el-date-picker>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" style="width: 100%"
clearable
placeholder="教职工类别"
code="USER_STATE"></dict-select>
</search-item>
<search-item label="教职工类别">
<dict-select v-model="pageForm.personType" style="width: 100%"
clearable
placeholder="教职工类别"
code="USER_PERSON_TYPE"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="教职工管理">
<el-button size="small" @click="batchDelete" type="primary">
批量删除
</el-button>
<el-button size="small" @click="setThirtyTeach" type="primary">
一键设置
</el-button>
<el-button size="small" @click="openImport" type="primary">
导入
</el-button>
<el-button size="small" @click="doExport" type="primary">
导出
</el-button>
</table-tool>
<el-table ref="table" :data="tableData" style="width: 100%" row-key="id"
@sort-change="pageOrder"
v-loading="tableLoading" :size="tableSize" class="vi-table"
@selection-change="tableHandleSelectionChange">
<el-table-column type="selection" :reserve-selection="true"></el-table-column>
<el-table-column align="center" header-align="center" type="index"
:index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:width="column.width"
:key="column.prop"
:sortable="column.sortable"
>
<template v-if="column.prop==='member'" v-slot="{row}">
<span v-if="row.member==1" class="text-success ">
<i class="fa fa-circle ml5"></i>
</span>
<span v-else class="text-danger">
<i class="fa fa-circle ml5"></i>
</span>
</template>
<template v-else-if="column.prop==='thirtyCertificateProcessingTime'" v-slot="{row}">
<span v-if="row.isEditThirtyCertificateProcessingTime">
<el-date-picker
style="width: 100%;"
v-model="row.thirtyCertificateProcessingTime"
type="month"
placeholder="选择日期时间"
@change="rowThirtyCertificateProcessingTimeChange(row)"
value-format="yyyy-MM">
</el-date-picker>
</span>
<span v-else>
{{row.thirtyCertificateProcessingTime}}
</span>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="180px">
<template slot-scope="{row}">
<el-button size="mini" type="primary"
@click="row.isEditThirtyCertificateProcessingTime=1">编辑
</el-button>
<el-button size="mini" type="danger" @click="doDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<file-import ref="viewImport" temp_url="/platform/thirtyTeach/manage/downloadImportTemp"
post_url="/platform/thirtyTeach/manage/doImport" is_show_radio
@flush="pageData()"
></file-import>
</template>
</guava>
<el-diaLog title="一键设置" :visible.sync="setThirtyTeachVisible" :close-on-click-modal="false" width="50%">
<el-form label-width="120px">
<el-form-item label="设置年限">
<el-input placeholder="请输入要设置的年限" v-model="setThirtyTeachData.setNum" type="number"
style="width: 80%"></el-input>
</el-form-item>
<el-form-item label="更新模式">
<el-radio-group v-model="setThirtyTeachData.isFlag">
<el-radio-button label="true">清空更新</el-radio-button>
<el-radio-button label="false">追加</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
<div style="text-align: right">
<span>
<el-button @click="setThirtyTeachVisible = false">关 闭</el-button>
<el-button type="primary" @click="doSet">确定</el-button>
</span>
</div>
</el-diaLog>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
unionOptions: [],
unitOptions: [],
tableColumns: [
{prop: 'loginname', label: '工号', sortable: true},
{prop: 'username', label: '姓名', sortable: true},
{prop: 'sex', label: '性别'},
{prop: 'teachNum', label: '进校时长(年)', sortable: true},
{prop: 'personType', label: '教职工类别', sortable: true},
{prop: 'userState', label: '在职状态', sortable: true},
{prop: 'unionName', label: '所属工会', sortable: true},
{prop: 'unitName', label: '所属单位', sortable: true},
{prop: 'member', label: '是否会员', sortable: true},
{prop: 'mobile', label: '联系电话'},
{prop: 'thirtyCertificateProcessingTime', label: '《30年教龄荣誉证》办理年月', width: 200},
],
setThirtyTeachVisible: false,
setThirtyTeachData: {
setNum: 30,
isFlag: false
},
checkUsers: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
personType: '',
userState: ''
},
}
},
components: {
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime())
},
methods: {
rowThirtyCertificateProcessingTimeChange(row) {
row.isEditThirtyCertificateProcessingTime = false
this.$axios.post('/platform/thirtyTeach/manage/doEditThirtyCertificateProcessingTime', {
thirtyCertificateProcessingTime: row.thirtyCertificateProcessingTime,
id: row.id,
}).then(resp => {
if (resp.code === 0) {
this.doSearch()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
})
},
openEdit(row) {
},
openImport() {
this.$refs.guava.edit(() => {
this.$refs.viewImport.resetImportData()
})
},
doExport() {
const {searchKeyword, unionId, unitId, personType, userState} = this.pageForm
window.open('/platform/thirtyTeach/manage/doExport?searchKeyword=' + searchKeyword + '&unionId=' + unionId + '&unitId=' + unitId +
'&personType=' + personType + '&userState=' + userState)
},
doSet() {
if (!this.setThirtyTeachData.setNum) {
this.notifyWarning("请填写年限!!!")
return
}
this.$axios.post('/platform/thirtyTeach/manage/setThirtyTeach', {
setNum: this.setThirtyTeachData.setNum,
isFlag: this.setThirtyTeachData.isFlag,
}).then(resp => {
if (resp.code === 0) {
this.pageData()
this.setThirtyTeachVisible = false
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
})
},
tableHandleSelectionChange(val) {
this.checkUsers = val;
},
async batchDelete() {
if (!this.checkUsers.length) {
this.notifyWarning("请先勾选需要删除的数据!!!")
return
}
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const userIds = this.checkUsers.map(obj => obj.id);
this.$axios.post('/platform/thirtyTeach/manage/doBatchDelete', {
userIds: JSON.stringify(userIds)
}).then(resp => {
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
})
}
},
setThirtyTeach() {
this.setThirtyTeachData = {
setNum: 30,
isFlag: false
}
this.setThirtyTeachVisible = true
},
openView() {
},
async doDelete(userId) {
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
this.$axios.post('/platform/thirtyTeach/manage/doBatchDelete', {
userIds: JSON.stringify([userId])
}).then(resp => {
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
})
}
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.unitList = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.unitOptions = data
})
}
},
},
async created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,111 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会"
clearable style="width: 100%" @change="flushUnits">
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" v-model="pageForm.unitId"
style="width: 100%;"
clearable
filterable>
<el-option v-for="item in unitOptions" :label="item.name"
:value="item.id"
:key="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="教职工汇总">
<el-button size="small" @click="doExportSummary" type="primary">
导出汇总表
</el-button>
</table-tool>
<el-table ref="table" :data="tableData" style="width: 100%" row-key="id"
@sort-change="pageOrder" show-summary
v-loading="tableLoading" :size="tableSize" class="vi-table">
<el-table-column align="center" header-align="center" type="index"
:index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
</el-table-column>
</el-table>
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
unionId: '',
unitId: '',
},
tableColumns: [
{prop: 'name', label: '分工会名称', sortable: true},
{prop: 'userNum', label: '在职人数', sortable: true},
],
unionOptions: [],
unitOptions: [],
}
},
methods: {
doExportSummary(){
const {unionId, unitId} = this.pageForm
window.open(loc() + '/doExportSummary?unionId=' + unionId + '&unitId=' + unitId)
},
async pageData() {
const resp = await this.$axios.post(loc() + '/pageData', this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data
}
},
flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.unitList = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.unitOptions = data
})
}
},
},
async created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->