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,386 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.dashboard-container {
width: 100%;
margin: 0 auto;
}
.stat-cards {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.stat-card-content {
display: flex;
align-items: center;
}
.icon-wrapper {
width: 48px;
height: 48px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16px;
}
.stat-info .label {
color: #909399;
font-size: 14px;
margin-bottom: 4px;
}
.stat-info .value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.stat-info .trend {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
.up {
color: #67c23a;
}
.down {
color: #f56c6c;
}
.filter-card {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.charts-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-bottom: 20px;
}
.chart-card {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #ebeef5;
}
.chart-title {
font-size: 16px;
font-weight: bold;
color: #303133;
}
.chart {
height: 320px;
}
</style>
<div id="app" v-cloak>
<div class="dashboard-container">
<!-- 统计卡片 -->
<div class="stat-cards">
<div class="stat-card" v-for="(item, index) in statCards" :key="index">
<div class="stat-card-content">
<div class="icon-wrapper" :style="{ backgroundColor: item.bgColor }">
<i :class="item.icon" style="font-size: 24px; color: #1867b0"></i>
</div>
<div class="stat-info">
<div class="label">{{ item.label }}</div>
<div class="value">{{ item.value }}</div>
<div class="trend" v-if="item.trend">
较上月{{item.trend >= 0 ? '增加' : '减少'}}
<span :class="item.trend >= 0 ? 'up' : 'down'">
{{ Math.abs(item.trend) }}
<i :class="item.trend >= 0 ? 'el-icon-top' : 'el-icon-bottom'"></i>
</span>
</div>
</div>
</div>
</div>
</div>
<!-- 筛选条件 -->
<div class="filter-card">
<el-form :inline="true" :model="pageForm" size="small">
<el-form-item label="时间范围">
<el-date-picker
v-model="pageForm.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
></el-date-picker>
</el-form-item>
<el-form-item label="分工会">
<el-select :clearable="true" v-model="pageForm.department" placeholder="请选择分工会">
<el-option v-for="item in departments" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="doSearch">查询</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
</div>
<!-- 图表区域 -->
<div class="charts-container">
<div class="chart-card">
<div class="chart-header">
<span class="chart-title">投稿趋势分析</span>
<el-radio-group v-model="trendType" size="small" @change="initTrendChart">
<el-radio-button label="week"></el-radio-button>
<el-radio-button label="month"></el-radio-button>
<el-radio-button label="year"></el-radio-button>
</el-radio-group>
</div>
<div id="trendChart" class="chart"></div>
</div>
<div class="chart-card">
<div class="chart-header">
<span class="chart-title">分工会投稿分布</span>
<el-tooltip content="数据更新时间:2024-02-24" placement="top">
<i class="el-icon-info"></i>
</el-tooltip>
</div>
<div id="pieChart" class="chart"></div>
</div>
</div>
<!-- 排行榜 -->
<!-- <el-card class="ranking-card">-->
<!-- <div slot="header">-->
<!-- <span>投稿排行榜</span>-->
<!-- <el-tabs v-model="rankingTab" @tab-click="handleRankingTabChange">-->
<!-- <el-tab-pane label="投稿人排行" name="person"></el-tab-pane>-->
<!-- <el-tab-pane label="分工会排行" name="department"></el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </div>-->
<!-- <el-table :data="rankingData" style="width: 100%" :max-height="400" stripe>-->
<!-- <el-table-column type="index" width="50" label="排名"></el-table-column>-->
<!-- <el-table-column-->
<!-- :prop="rankingTab === 'person' ? 'name' : 'department'"-->
<!-- :label="rankingTab === 'person' ? '姓名' : '分工会'"-->
<!-- ></el-table-column>-->
<!-- <el-table-column prop="count" label="投稿数量" sortable></el-table-column>-->
<!-- <el-table-column prop="rate" label="环比增长" width="150">-->
<!-- <template slot-scope="scope">-->
<!-- <span :class="scope.row.rate >= 0 ? 'up' : 'down'">-->
<!-- {{ scope.row.rate }}%-->
<!-- <i :class="scope.row.rate >= 0 ? 'el-icon-top' : 'el-icon-bottom'"></i>-->
<!-- </span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<!-- </el-card>-->
</div>
</div>
<script nonce="${cspNonce!}">
let trendChart,
distributionChart = null
new Vue({
el: "#app",
data() {
return {
statCards: [],
pageForm: {
dateRange: "",
department: ""
},
departments: [],
clubOptions: [],
trendType: "month",
rankingTab: "person",
rankingData: [],
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.setMonth(start.getMonth() - 1)
picker.$emit("pick", [start, end])
}
}
]
}
}
},
methods: {
doSearch() {},
resetSearch() {},
initTrendChart() {
// 趋势图数据
this.$axios
.post("/platform/article/analysis/trend", {
type: this.trendType,
startDate: this.pageForm.dateRange[0],
endDate: this.pageForm.dateRange[1]
})
.then((res) => {
if (res.code === 0) {
const trendData = res.data
// 初始化趋势图
trendChart && trendChart.destroy()
trendChart = new G2Plot.Line("trendChart", {
data: trendData,
padding: "auto",
xField: "date",
yField: "count",
smooth: true,
color: "#1867b0",
point: {
size: 5,
shape: "diamond",
style: {
fill: "white",
stroke: "#1867b0",
lineWidth: 2
}
}
})
trendChart.render()
// // 饼图数据
// const pieData = [
// { type: "文学院", value: 30 },
// { type: "理学院", value: 25 },
// { type: "工学院", value: 35 },
// { type: "医学院", value: 20 },
// { type: "经管学院", value: 28 }
// ]
//
// // 初始化饼图
// const pie = new G2Plot.Pie("pieChart", {
// data: pieData,
// angleField: "value",
// colorField: "type",
// radius: 0.8,
// label: {
// type: "outer",
// content: "{name} {percentage}"
// }
// })
// pie.render()
}
})
},
initDistributionChart() {
this.$axios
.post("/platform/article/analysis/distribution", {
startDate: this.pageForm.dateRange[0],
endDate: this.pageForm.dateRange[1]
})
.then((res) => {
if (res.code === 0) {
// 初始化饼图
distributionChart && distributionChart.destroy()
distributionChart = new G2Plot.Pie("pieChart", {
data: res.data,
angleField: "value",
colorField: "type",
radius: 0.8,
label: {
type: "outer",
content: "{name} {percentage}"
}
})
distributionChart.render()
}
})
},
loadRankingData() {
this.rankingData =
this.rankingTab === "person"
? [
{ name: "张三", count: 56, rate: 12.5 },
{ name: "李四", count: 48, rate: -5.2 },
{ name: "王五", count: 45, rate: 8.3 }
]
: [
{ department: "文学院", count: 156, rate: 15.2 },
{ department: "理学院", count: 142, rate: -2.1 },
{ department: "工学院", count: 138, rate: 5.6 }
]
},
resetFilter() {
this.filterForm = {
dateRange: "",
department: ""
}
},
handleRankingTabChange() {
this.loadRankingData()
},
updateTrendChart() {
this.initTrendChart()
},
overview() {
this.$axios.post("/platform/article/analysis/overview").then((res) => {
if (res.code === 0) {
this.statCards = res.data
}
})
}
},
mounted() {
this.initTrendChart()
this.initDistributionChart()
this.loadRankingData()
this.overview()
},
created() {
this.$businessTool.listClub().then((res) => (this.clubOptions = res))
this.$businessTool.listUnit().then((res) => (this.departments = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,170 @@
<!--#
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
:clearable="true"
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="年度"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<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>
<article-info ref="articleInfoRef">
<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>
</article-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"article-info": ARTICLE_INFO
},
data() {
return {
pageForm: {
approval: false
},
showApprovalForm: false,
}
},
methods: {
// 查看
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.articleInfoRef.onOpen(row)
})
},
// 审核
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.articleInfoRef.onOpen(row)
})
},
// 提交
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
// 撤回
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,170 @@
<!--#
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
:clearable="true"
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="年度"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<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>
<article-info ref="articleInfoRef">
<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>
</article-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"article-info": ARTICLE_INFO
},
data() {
return {
pageForm: {
approval: false
},
showApprovalForm: false,
}
},
methods: {
// 查看
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.articleInfoRef.onOpen(row)
})
},
// 审核
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.articleInfoRef.onOpen(row)
})
},
// 提交
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
// 撤回
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,103 @@
const ARTICLE_INFO = {
template: /*language=HTML*/ `
<div class="">
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border>
<el-descriptions-item label="投稿人姓名">{{ viewData.userName }}</el-descriptions-item>
<el-descriptions-item label="投稿人工号">{{ viewData.loginName }}</el-descriptions-item>
<el-descriptions-item label="投稿人单位">{{ viewData.unitName }}</el-descriptions-item>
<el-descriptions-item label="投稿人工会">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="投稿人联系方式">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="稿件修改人联系方式">{{ viewData.mobile2 }}</el-descriptions-item>
<el-descriptions-item label="投稿标题" :span="2">{{ viewData.title }}</el-descriptions-item>
<el-descriptions-item label="投稿说明" :span="2">
<span style="white-space: pre-line">{{ viewData.excerpt }}</span>
</el-descriptions-item>
<el-descriptions-item label="稿件" :span="2">
<file-preview :files="viewData.files" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
}}({{task.ext.initiatorAccount}})
</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName
}}({{task.taskFormData.loginName}})
</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
task.taskFormData.opinion }}
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
store,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
visible: false,
viewData: {},
doneTasks: [],
row: null
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
this.getDoneTasks()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/article/common/info', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
// 查看流程图
openChart(){
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId,this.row.instanceId)
}
}
}
@@ -0,0 +1,170 @@
<!--#
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
:clearable="true"
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="年度"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<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>
<article-info ref="articleInfoRef">
<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>
</article-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"article-info": ARTICLE_INFO
},
data() {
return {
pageForm: {
approval: false
},
showApprovalForm: false,
}
},
methods: {
// 查看
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.articleInfoRef.onOpen(row)
})
},
// 审核
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.articleInfoRef.onOpen(row)
})
},
// 提交
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
// 撤回
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,204 @@
<!--#
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 v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable 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 v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable style="width: 100%">
<el-option v-for="item in unitOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="投稿来源:">
<el-select v-model="pageForm.origin" placeholder="请选择投稿来源" filterable clearable style="width: 100%">
<el-option v-for="item in dict.type.ARTICLE_ORIGIN" :key="item.code" :label="item.label" :value="item.code"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="clubName" label="投稿人协会"></el-table-column>
<el-table-column prop="origin" label="投稿来源">
<template slot-scope="{row}">{{dict.type.ARTICLE_ORIGIN.find(v=>v.code===row.origin)?.label}}
</template>
</el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName"
show-overflow-tooltip></el-table-column>
<el-table-column label="操作" fixed="right">
<template slot-scope="{row}">
<el-button @click="onOpen(row.id)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.processInstanceTaskStatus==='ACTIVE'" @click="openApproval(row)"
size="mini" type="primary">
审核
</el-button>
<el-button
v-if="row.processInstanceTaskStatus==='COMPLETE' && !row.nextTaskIsComplete"
@click="openRevoke(row.processInstanceTaskId)"
size="mini"
type="danger"
>
撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #public>
<info ref="infoRef"></info>
<div v-if="showApprovalForm">
<div class="process-title">{{formData.processInstanceNodeName}}</div>
<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>
<el-row type="flex" justify="end">
<el-button plain @click="$refs.guava.index()">取消</el-button>
<el-button type="danger" @click="doApproval('BACK_TO_START')">退回到投稿人</el-button>
<el-button type="danger" @click="doApproval('BACK_TO_UNION')"
v-if="currentRow.origin === 'ARTICLE_ORIGIN_UNION'">退回到分工会
</el-button>
<el-button type="danger" @click="doApproval('BACK_TO_CLUB')"
v-if="currentRow.origin === 'ARTICLE_ORIGIN_CLUB'">退回到协会
</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/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
dicts: ["ARTICLE_ORIGIN"],
components: {info},
data() {
return {
pageForm: {
approval: false
},
showApprovalForm: false,
currentRow: {}
}
},
methods: {
onOpen(id) {
this.showApprovalForm = false
this.$refs.guava.public(() => {
this.$refs.infoRef.onOpen(id)
})
},
openApproval(row) {
this.$refs.guava.public(() => {
this.currentRow = row
this.$refs.infoRef.onOpen(row.id)
this.formData = row.approvalParam
this.showApprovalForm = true
})
},
// 动态审核
doApproval(result) {
this.formData.bpmTaskApprovalType = "DYNAMIC"
if (result === 'BACK_TO_START') {
this.$confirm('请确认投稿人重新提交后是否需要重新走审批流程?', '提示', {
distinguishCancelAndClose: true,
confirmButtonText: '需要',
cancelButtonText: '不需要',
type: 'warning'
}).then(() => {
this.submitApproval(result, true);
}).catch((action) => {
if (action === 'cancel') {
this.submitApproval(result, false);
}
})
} else {
this.submitApproval(result, false);
}
},
submitApproval(result, processAgain) {
this.$refs.approvalFormRef.validate((valid) => {
if (valid) {
this.$axios
.post("/platform/article/firstExamine/approval", {
approval: JSON.stringify(this.formData),
result: result,
processAgain: processAgain
})
.then((res) => {
if (res.code === 0) {
this.$refs.guava.index();
this.$message.success(res.msg);
this.doSearch();
}
});
}
});
},
openRevoke(taskId) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/platform/article/firstExamine/revoke", {taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,122 @@
<!--#
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 v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="请输入标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onOpen(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>
<article-info ref="infoRef"></article-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"article-info": ARTICLE_INFO
},
data() {
return {}
},
methods: {
// 查看
onOpen(id) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(id)
})
},
// 编辑
onEdit(row) {
commonUtil.pjaxPush('/platform/article/write?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
},
// 撤回
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
// 删除
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/article/mine/delete", {id: id}).then((res) => {
if (res.code === 0) {
this.doSearch()
this.$message.success(res.msg)
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,105 @@
<!--#
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 v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度" style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable 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 v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable style="width: 100%">
<el-option v-for="item in unitOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属协会:">
<el-select v-model="pageForm.clubId" placeholder="请选择所属协会" filterable clearable style="width: 100%">
<el-option v-for="item in clubOptions" :key="item.id" :label="item.clubName" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="投稿来源:">
<el-select v-model="pageForm.origin" placeholder="请选择投稿来源" filterable clearable style="width: 100%">
<el-option v-for="item in dict.type.ARTICLE_ORIGIN" :key="item.code" :label="item.label" :value="item.code"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="clubName" label="投稿人协会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="origin" label="投稿来源">
<template slot-scope="{row}">{{dict.type.ARTICLE_ORIGIN.find(v=>v.code===row.origin)?.label}}</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="100px">
<template slot-scope="{row}">
<el-button @click="onOpen(row)" size="mini" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #public>
<article-info ref="articleInfoRef"></article-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
const vue = new Vue({
el: "#app",
store,
mixins: [initTableMixins],
dicts: ["ARTICLE_ORIGIN"],
components: {
"article-info": ARTICLE_INFO
},
data() {
return {
pageForm: {
approval: false
},
unionOptions: [],
unitOptions: [],
clubOptions: []
}
},
methods: {
onOpen(row) {
this.$refs.guava.public(() => {
this.$refs.articleInfoRef.onOpen(row)
})
}
},
created() {
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.$businessTool.listCLubByRole().then((res) => (this.clubOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,48 @@
<div id="article_school_union_approval_form">
<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: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: "#article_school_union_approval_form",
data() {
return {
taskId: GetQueryString("taskId"),
formData: {
approval: "",
approvalOpinion: ""
}
}
},
methods: {
handleTaskAction(val) {
console.log(val)
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify(val)
}).then(res => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage({
type: "task-complete"
}, "*")
}
})
},
handleCancel(val) {
console.log(val)
}
}
})
</script>
@@ -0,0 +1,170 @@
<!--#
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
:clearable="true"
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="年度"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<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>
<article-info ref="articleInfoRef">
<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>
</article-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"article-info": ARTICLE_INFO
},
data() {
return {
pageForm: {
approval: false
},
showApprovalForm: false,
}
},
methods: {
// 查看
openView(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = false
this.$refs.articleInfoRef.onOpen(row)
})
},
// 审核
openAudit(row) {
this.$refs.guava.edit(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.articleInfoRef.onOpen(row)
})
},
// 提交
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
// 撤回
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,208 @@
<!--#
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="150px" label-suffix="">
<el-form-item prop="origin" label="投稿来源">
<el-radio-group v-model="formData.origin" size="small">
<el-radio border v-for="item in origins" :label="item.code" :key="item.code">{{item.name}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="userName" label="投稿人姓名">
<el-input disabled v-model="formData.userName"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="loginName" label="投稿人工号">
<el-input disabled v-model="formData.loginName"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item prop="unitName" label="投稿人单位">
<el-input disabled v-model="formData.unitName" placeholder="请输入单位"></el-input>
</el-form-item>
<el-form-item prop="unionName" label="投稿人工会">
<el-input disabled v-model="formData.unionName"></el-input>
</el-form-item>
<el-form-item prop="mobile" label="投稿人联系方式">
<el-input v-model="formData.mobile" placeholder="请输入投稿人联系方式"></el-input>
</el-form-item>
<el-form-item prop="mobile2" label="修改人联系方式">
<el-input v-model="formData.mobile2" placeholder="请输入稿件修改联系人方式"></el-input>
</el-form-item>
<el-form-item prop="clubId" label="投稿人协会" v-if="formData.origin === 'ARTICLE_ORIGIN_CLUB'">
<el-select v-model="formData.clubId" placeholder="请选择" style="width: 100%">
<el-option v-for="item in permission?.clubs" :key="item.id" :label="item.clubName"
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="title" label="投稿标题">
<el-input v-model="formData.title" maxlength="100" show-word-limit placeholder="请输入标题"></el-input>
</el-form-item>
<el-form-item prop="excerpt" label="投稿说明">
<el-input v-model="formData.excerpt" type="textarea" maxlength="500" show-word-limit
placeholder="请输入投稿说明"></el-input>
</el-form-item>
<el-form-item prop="files" label="稿件">
<file-upload
:value.sync="formData.files"
:upload_number="5"
upload_result_category="array"
complete_result
upload_mode="drag"
></file-upload>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<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="onSubmitAgain" v-else>提交</el-button>
</el-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
dicts: ["ARTICLE_ORIGIN"],
computed: {
origins() {
if (this.dict?.type?.ARTICLE_ORIGIN && this.permission && this.permission.roles) {
return this.dict.type.ARTICLE_ORIGIN.filter((item) => this.permission && this.permission.roles.includes(item.code))
}
return []
}
},
store,
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formData: {},
formRules: {
title: [{required: true, message: "必填", trigger: ["change", "blur"]}],
excerpt: [{required: true, message: "必填", trigger: ["change", "blur"]}],
clubId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
files: [{required: false, message: "必填", trigger: ["change", "blur"]}],
origin: [{required: true, message: "必填", trigger: ["change", "blur"]}],
mobile: [{required: true, message: "必填", trigger: ["change", "blur"]}],
mobile2: [{required: true, message: "必填", trigger: ["change", "blur"]}]
},
permission: {}
}
},
methods: {
// 保存
onSave() {
this.$refs.formRef.validateField(["title"], (errMsg) => {
if (errMsg) {
this.$message.warning("请填写标题")
return
}
this.$axios.post("/platform/article/write/save", {article: JSON.stringify(this.formData)}).then((res) => {
if (res.code === 0) {
this.$message.success("保存成功")
//this.$store.dispatch("pjaxRoute", "/platform/article/mine")
commonUtil.pjaxPush("/platform/article/mine")
}
})
})
},
// 提交
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
if(this.formData.clubId) {
const club = this.permission?.clubs.find(o => o.id === this.formData.clubId)
this.$set(this.formData, 'clubName', club.clubName)
}
this.$axios.post("/platform/article/write/submit", {
article: JSON.stringify(this.formData),
taskId: this.taskId,
instanceId: this.instanceId
}).then((res) => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush("/platform/article/mine")
}
})
}
})
},
// 重新提交
onSubmitAgain() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
if(this.formData.clubId) {
const club = this.permission?.clubs.find(o => o.id === this.formData.clubId)
this.$set(this.formData, 'clubName', club.clubName)
}
this.$axios.post('/platform/article/write/submitAgain', {
article: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/article/mine')
}
})
})
},
checkPermission() {
this.$axios.post("/platform/article/write/checkPermission").then((res) => {
if (res.code === 0) {
this.permission = res.data
}
})
},
init() {
if (this.bizId) {
this.$axios.post("/platform/article/write/get", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
} else {
const {username, loginname, id, unit, union, mobile} = this.$store.state.user
this.formData = {
userName: username,
loginName: loginname,
userId: id,
unitId: unit?.id,
unitName: unit?.name,
unionId: union?.id,
unionName: union?.name,
mobile: mobile,
mobile2: mobile
}
}
}
},
created() {
this.init()
this.checkPermission()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,161 @@
<!--#
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>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="资产类型列表">
<el-button @click="openAdd" 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"
>
</el-table-column>
<el-table-column label="操作" width="200">
<template scope="{row}">
<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>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
<el-dialog
title=""
:visible.sync="dialogVisible"
width="40%"
:close-on-click-modal="false">
<el-form :model="formData" :rules="rules" ref="ruleForm" label-width="120px">
<el-form-item label="编号" prop="categoryCode">
<el-input v-model="formData.categoryCode" maxlength="30" placeholder="编码"></el-input>
</el-form-item>
<el-form-item label="名称" prop="categoryName">
<el-input v-model="formData.categoryName" maxlength="30" placeholder="内容"></el-input>
</el-form-item>
<el-form-item label="折旧年限(年)" prop="depreciationYear">
<el-input v-model="formData.depreciationYear" maxlength="30" placeholder="折旧年限(年)"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">关 闭</el-button>
<el-button type="primary" @click="doSubmit">提 交</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{prop: 'categoryCode', label: '编号'},
{prop: 'categoryName', label: '名称'},
{prop: 'depreciationYear', label: '折旧年限(年)'},
],
dialogVisible: false,
rules: {
categoryCode: [{required: true, message: '请输入编号', trigger: ['change', 'blur']}],
categoryName: [{required: true, message: '请输入名称', trigger: ['change', 'blur']}],
depreciationYear: [{required: true, message: '请输入折旧年限', trigger: ['change', 'blur']}],
},
}
},
methods: {
openEdit(row) {
this.formData = {}
this.formData = clone(row)
this.dialogVisible = true
},
openAdd() {
this.formData = {}
if (this.$refs['ruleForm']) {
this.$refs['ruleForm'].resetFields()
}
this.dialogVisible = true
},
async doDelete(id) {
const confirm = await this.$confirm('确定删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await this.$axios.post(loc() + '/doDelete', {id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyError(resp.msg)
}
}
},
async doSubmit() {
const valid = await this.$refs['ruleForm'].validate()
if (valid) {
const resp = await this.$axios.post(loc() + "/doSubmit", this.formData)
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
this.dialogVisible = false
} else {
this.notifyError(resp.msg)
}
}
},
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,349 @@
let ASSSET_FORM = {
/*language=HTML*/
template: `
<div>
<el-form :model="formData" :rules="ruleForm" label-width="120px" ref="AddForm">
<el-descriptions :column="3" border class="table_fixed">
<el-descriptions-item label="资产编号">
<el-form-item prop="assetNumber" label-width="0">
<el-input placeholder="不填为系统自动生成或自己编写"
v-model="formData.assetNumber" maxlength="100"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产名称">
<el-form-item prop="assetName" label-width="0">
<el-input placeholder="请填写资产名称"
v-model="formData.assetName" maxlength="100"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产类别">
<el-form-item prop="assetCategoryId" label-width="0">
<el-select @change="assetCategoryIdChange" clearable placeholder="请选择资产类别"
style="width: 100%" v-model="formData.assetCategoryId">
<el-option :label="item.categoryName+''+item.depreciationYear+'年)'"
:value="item.id"
v-for="item in assetCategoryOption"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产规格型号">
<el-form-item prop="assetSpecs" label-width="0">
<el-input placeholder="请填写资产规格型号"
v-model="formData.assetSpecs" maxlength="100"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="供应商名称">
<el-form-item prop="assetSupplierName" label-width="0">
<el-input placeholder="请填写供应商名称"
v-model="formData.assetSupplierName" maxlength="100"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="采购方式">
<el-form-item prop="assetFundingSubjectName" label-width="0">
<el-select clearable placeholder="请选择采购方式"
style="width: 100%"
v-model="formData.assetFundingSubjectName">
<el-option label="网购" value="网购"></el-option>
<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="assetPurposeName" label-width="0">
<el-select clearable placeholder="请选择用途"
style="width: 100%"
v-model="formData.assetPurposeName">
<el-option label="职工之家建设" value="职工之家建设"></el-option>
<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="assetUnitPrice" label-width="0">
<el-input-number :precision="2" placeholder="单价" style="width: 100%"
v-model="formData.assetUnitPrice">
</el-input-number>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="数量">
<el-form-item prop="assetQuantity" label-width="0">
<el-input-number :precision="0" placeholder="数量" style="width: 100%"
v-model="formData.assetQuantity" :max="999999">
</el-input-number>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产类型">
<el-form-item prop="assetTypeCode" label-width="0">
<el-radio-group @change="assetTypeCodeChange" v-model="formData.assetTypeCode">
<el-radio :label="1" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
校工会资产
</el-radio>
<el-radio :label="2">分工会资产</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="开始使用日期">
<el-form-item prop="assetUsedDate" label-width="0">
<el-date-picker @change="assetUsedDateChange" placeholder="开始使用日期"
style="width: 100%" v-model="formData.assetUsedDate"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="预计报废时间">
<el-form-item prop="assetRetiredAssetsDate" label-width="0">
<el-date-picker placeholder="预计报废时间"
disabled style="width: 100%" v-model="formData.assetRetiredAssetsDate"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="责任人">
<el-form-item prop="assetUseUserId" label-width="0">
<el-select :remote-method="searchAssetUseUser"
@change="assetUseUserIdChange"
clearable
filterable
placeholder="可输入姓名或者工号查询"
remote
style="width: 100%"
v-model="formData.assetUseUserId">
<el-option :label="item.username+'-'+item.loginname"
:value="item.id"
v-for="item in assetUseUserOption"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="使用/管理部门">
<template v-if="formData.assetTypeCode===1">
<el-form-item prop="assetUseUnionName" label-width="0">
<el-input :value="formData.assetUseUnionName" disabled
></el-input>
</el-form-item>
</template>
<template v-else>
<el-form-item prop="assetUseUnionId" label-width="0">
<el-select
@change="assetUseUnionIdChange"
clearable
filterable
placeholder="请选择使用/管理部门"
style="width: 100%"
v-model="formData.assetUseUnionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unionList"></el-option>
</el-select>
</el-form-item>
</template>
</el-descriptions-item>
<el-descriptions-item label="存放地点">
<el-form-item prop="assetStorageLocation" label-width="0">
<el-input placeholder="请输入存放地点" v-model="formData.assetStorageLocation"
maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="使用状况">
<el-form-item prop="assetUsageStateName" label-width="0">
<dict-select v-model="formData.assetUsageStateName" placeholder="请选择使用状况"
code="ASSET_USAGE_STATE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item span="2">
</el-descriptions-item>
<el-descriptions-item label="备注" span="3">
<el-form-item prop="assetNotes" label-width="0">
<el-input placeholder="请输入备注" v-model="formData.assetNotes"
maxlength="150" type="textarea" :rows="3"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="发票/购买信息" span="3">
<el-form-item prop="assetInvoiceFiles" label-width="0">
<file-upload
:value.sync="formData.assetInvoiceFiles"
upload_mode="drag"
accept=".jpg,.jpeg,.png,.pdf"
:upload_number="20"
upload_result_category="array"
complete_result
></file-upload>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产图片" span="3">
<el-form-item prop="assetFiles" label-width="0">
<file-upload
:value.sync="formData.assetFiles"
upload_mode="drag"
accept=".jpg,.jpeg,.png,.pdf"
:upload_number="20"
upload_result_category="array"
complete_result
></file-upload>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<div style="float: right;margin: 20px 0">
<el-button @click="doSubmit" type="primary">提 交
</el-button>
</div>
</div>
`,
store,
mixins: [initTableMixins],
data() {
return {
ruleForm: {
assetName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetCategoryId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetSpecs: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetSupplierName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetFundingSubjectName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetPurposeName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetUnitPrice: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetQuantity: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetTypeCode: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetUsedDate: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetRetiredAssetsDate: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetUseUserId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetUseUnionId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetStorageLocation: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetUsageStateName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetInvoiceFiles: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetFiles: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
unions: [],
assetCategoryOption: [],
assetUseUserOption: [],
unionList: [],
}
},
methods: {
open() {
},
async findOne(id) {
const res = await this.$axios.post("/platform/asset/manage/findOne", {id})
this.formData = res.data
},
async openEdit(id) {
await this.findOne(id)
this.searchAssetUseUser(this.formData.assetUseUserId)
},
assetUseUnionIdChange(val) {
const union = this.unions.find(v => v.id === val)
if (union) {
this.$set(this.formData, "assetUseUnionName", union.name)
} else {
this.$set(this.formData, "assetUseUnionName", null)
}
},
// 切换资产类型把使用/管理部门清空
assetTypeCodeChange(val) {
if (val === 1) {
this.$set(this.formData, "assetUseUnionName", "校工会")
} else {
this.$set(this.formData, "assetUseUnionName", null)
this.$set(this.formData, "assetUseUnionId", null)
}
},
// 点击责任人
assetUseUserIdChange(val) {
const {
unionname,
unionid
} = this.assetUseUserOption.find(v => v.id === val)
this.formData.assetUseUnionId = unionid
if (this.formData.assetTypeCode === 1) {
this.formData.assetUseUnionName = "校工会"
} else {
this.formData.assetUseUnionName = unionname
}
},
// 点击开始使用日期🧄预计报废时间
assetUsedDateChange(val) {
if (!this.formData.assetCategoryId) {
this.$message.warning('请选择资产所属类别');
this.$set(this.formData, "assetUsedDate", null)
return
}
const assetCategoryOption = clone(this.assetCategoryOption)
const data = assetCategoryOption.find(v => v.id === this.formData.assetCategoryId)
const depreciationDate = this.$moment(val).add(data.depreciationYear, 'y').format('YYYY-MM-DD')
this.$set(this.formData, "assetRetiredAssetsDate", depreciationDate)
},
assetCategoryIdChange() {
if (this.formData.assetUsedDate) {
this.assetUsedDateChange(this.formData.assetUsedDate)
} else {
this.$set(this.formData, "assetUsedDate", null);
}
},
// 查询责任人
searchAssetUseUser(val) {
$.get("/platform/asset/manage/searchAssetUseUser", {query: val}).then(resp => {
if (resp.code === 0) {
this.assetUseUserOption = resp.data
}
})
},
// 查询资产类别
queryCategory() {
this.$axios.post("/platform/asset/category/queryCategory").then(resp => {
if (resp.code === 0) {
this.assetCategoryOption = resp.data
}
})
},
doSubmit() {
this.$refs["AddForm"].validate((valid) => {
if (valid) {
let formData = clone(this.formData)
if (formData.assetInvoiceFiles) {
formData.assetInvoiceFiles = JSON.stringify(formData.assetInvoiceFiles)
}
if (formData.assetFiles) {
formData.assetFiles = JSON.stringify(formData.assetFiles)
}
this.$axios.post("/platform/asset/manage/" + (formData.id ? "doEdit" : "doAdd"), formData).then(resp => {
if (resp.code === 0) {
this.formData = {}
this.$refs.AddForm.resetFields()
this.$emit("save_success")
this.$message.success(resp.msg);
} else {
this.$message.warning(resp.msg);
}
})
}
})
}
},
async created() {
this.queryCategory()
this.$businessTool.listUnion().then((data) => {
this.unionList = data
})
},
style: /*language=CSS*/ `
.table_fixed .el-form-item {
margin-bottom: 0px !important;
}
`
}
@@ -0,0 +1,164 @@
let ASSSET_INFO = {
/*language=HTML*/
template: `
<div>
<el-tabs tab-position="top" v-model="activeName">
<el-tab-pane label="资产基本信息" name="1">
<el-descriptions :column="3" border style="margin-top: 10px;">
<el-descriptions-item label="资产编号">
{{viewData.assetNumber}}
</el-descriptions-item>
<el-descriptions-item label="资产名称">
{{viewData.assetName}}
</el-descriptions-item>
<el-descriptions-item label="资产类别">
{{viewData.assetCategoryName}}{{viewData.assetDepreciationYear}}年)
</el-descriptions-item>
<el-descriptions-item label="资产规格型号">
{{viewData.assetSpecs}}
</el-descriptions-item>
<el-descriptions-item label="供应商名称">
{{viewData.assetSupplierName}}
</el-descriptions-item>
<el-descriptions-item label="采购方式">
{{viewData.assetFundingSubjectName}}
</el-descriptions-item>
<el-descriptions-item label="用途">
{{viewData.assetPurposeName}}
</el-descriptions-item>
<el-descriptions-item label="单价(元)">
{{viewData.assetUnitPrice}}
</el-descriptions-item>
<el-descriptions-item label="数量(台/件)">
{{viewData.assetQuantity}}
</el-descriptions-item>
<el-descriptions-item label="资产类型">
{{viewData.assetTypeCode===1?'校工会资产':'分工会资产'}}
</el-descriptions-item>
<el-descriptions-item label="开始使用日期">
{{$moment(viewData.assetUsedDate).format('YYYY-MM-DD')}}
</el-descriptions-item>
<el-descriptions-item label="预计报废时间">
{{$moment(viewData.assetRetiredAssetsDate).format('YYYY-MM-DD')}}
</el-descriptions-item>
<el-descriptions-item label="责任人">
{{viewData.assetUseUserName}}
</el-descriptions-item>
<el-descriptions-item label="使用/管理部门">
{{viewData.assetUseUnionName}}
</el-descriptions-item>
<el-descriptions-item label="存放地点">
{{viewData.assetStorageLocation}}
</el-descriptions-item>
<el-descriptions-item label="使用状况">
{{viewData.assetUsageStateName}}
</el-descriptions-item>
<el-descriptions-item span="2">
</el-descriptions-item>
<el-descriptions-item label="备注" span="3">
<div style="white-space: pre">{{viewData.assetNotes}}</div>
</el-descriptions-item>
<el-descriptions-item label="发票/购买信息" span="3">
<file-preview :files="viewData.assetInvoiceFiles" complete_result></file-preview>
</el-descriptions-item>
<el-descriptions-item label="资产图片" span="3">
<file-preview :files="viewData.assetFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="盘点信息" name="2"
v-if="viewData.assetStocktakingList
&& viewData.assetStocktakingList.length>0">
<el-table :data="viewData.assetStocktakingList"
:size="tableSize"
ref="table"
row-key="id"
style="width: 100%"
>
<el-table-column
label="原责任人" prop="oldAssetUseUserName">
</el-table-column>
<el-table-column
label="原使用/管理部门" prop="oldAssetUseUnionName">
</el-table-column>
<el-table-column
label="原存放地点" prop="oldAssetStorageLocation">
</el-table-column>
<el-table-column
label="原使用状况" prop="oldAssetUsageStateName">
</el-table-column>
<el-table-column
label="操作时间" prop="createdAt">
<template v-slot="{row}">
{{$moment(row.createdAt).format('YYYY-MM-DD HH:mm:ss')}}
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template v-slot="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<el-dialog
title="盘点信息查询"
:visible.sync="dialogVisible"
:append-to-body="true"
width="50%">
<el-descriptions :column="2" border style="margin-top: 10px;">
<el-descriptions-item label="旧责任人">
{{tableStocktakingData.oldAssetUseUserName}}
</el-descriptions-item>
<el-descriptions-item label="旧使用/管理部门">
{{tableStocktakingData.oldAssetUseUnionName}}
</el-descriptions-item>
<el-descriptions-item label="旧存放地点">
{{tableStocktakingData.oldAssetStorageLocation}}
</el-descriptions-item>
<el-descriptions-item label="旧使用状况">
{{tableStocktakingData.oldAssetUsageStateName}}
</el-descriptions-item>
<el-descriptions-item label="盘点时间">
{{$moment(tableStocktakingData.createdAt).format('YYYY-MM-DD HH:mm:ss')}}
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="旧备注" :span="2">
{{tableStocktakingData.oldAssetNotes}}
</el-descriptions-item>
<el-descriptions-item label="旧资产图片" :span="2">
<file-preview :files="tableStocktakingData.oldAssetFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">关 闭</el-button>
</span>
</el-dialog>
</div>
`, store,
mixins: [initTableMixins],
data() {
return {
viewData: {},
tableStocktakingData: {},
activeName: "1",
dialogVisible:false
}
},
methods: {
openView(row){
this.tableStocktakingData=row
this.dialogVisible=true
},
open(id) {
this.$axios.post("/platform/asset/manage/fondOneAsset", {id}).then(res => {
this.viewData = res.data
})
}
}
}
@@ -0,0 +1,146 @@
let ASSSET_STOCKTAKING_FORM = {
/*language=HTML*/
template: `
<div>
<el-form :model="formData" :rules="ruleForm" label-width="120px" ref="AddForm">
<el-descriptions :column="3" border class="table_fixed">
<el-descriptions-item label="资产编号">
<el-form-item prop="assetNumber" label-width="0">
<el-input disabled v-model="formData.assetNumber"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产名称">
<el-form-item prop="assetName" label-width="0">
<el-input disabled v-model="formData.assetName"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="开始使用日期">
<el-form-item prop="assetUsedDate" label-width="0">
<el-date-picker disabled style="width: 100%"
v-model="formData.assetUsedDate"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="责任人">
<el-form-item prop="assetUseUserId" label-width="0">
<el-select :remote-method="searchAssetUseUser"
clearable
filterable
placeholder="可输入姓名或者工号查询"
remote
style="width: 100%"
v-model="formData.assetUseUserId">
<el-option :label="item.username+'-'+item.loginname"
:value="item.id"
:key="item.id"
v-for="item in assetUseUserOption"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="存放地点">
<el-form-item prop="assetStorageLocation" label-width="0">
<el-input placeholder="请输入存放地点" v-model="formData.assetStorageLocation"
maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="使用状况">
<el-form-item prop="assetUsageStateName" label-width="0">
<dict-select v-model="formData.assetUsageStateName" placeholder="请选择使用状况"
code="ASSET_USAGE_STATE"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="备注" span="3">
<el-form-item prop="assetNotes" label-width="0">
<el-input placeholder="请输入备注" v-model="formData.assetNotes"
maxlength="150" type="textarea" :rows="3"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产图片" span="3">
<el-form-item prop="assetFiles" label-width="0">
<file-upload
:value.sync="formData.assetFiles"
upload_mode="drag"
accept=".jpg,.jpeg,.png,.pdf"
:upload_number="20"
upload_result_category="array"
complete_result
></file-upload>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<div style="float: right;margin: 20px 0">
<el-button @click="doSubmit" type="primary">提 交
</el-button>
</div>
</div>
`,
store,
mixins: [initTableMixins],
data() {
return {
ruleForm: {
assetUseUserId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetStorageLocation: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetUsageStateName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
assetFiles: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
assetUseUserOption: [],
assetInfo: {}
}
},
methods: {
open(row) {
this.assetInfo = row
this.$set(this.formData, "assetId", row.id)
this.$set(this.formData, "assetStocktakingPlanId", row.assetStocktakingPlanId)
this.$set(this.formData, "assetNumber", row.assetNumber)
this.$set(this.formData, "assetName", row.assetName)
this.$set(this.formData, "assetUsedDate", row.assetUsedDate)
this.$set(this.formData, "assetStorageLocation", row.assetStorageLocation)
},
doSubmit(){
this.$refs["AddForm"].validate((valid) => {
if (valid) {
let formData = clone(this.formData)
if (formData.assetFiles) {
formData.assetFiles = JSON.stringify(formData.assetFiles)
}
this.$axios.post("/platform/asset/stocktaking/doSubmit", formData).then(resp => {
if (resp.code === 0) {
this.formData = {}
this.$refs.AddForm.resetFields()
this.$emit("save_success")
this.$message.success(resp.msg);
} else {
this.$message.warning(resp.msg);
}
})
}
})
},
// 查询责任人
searchAssetUseUser(val) {
$.get("/platform/asset/manage/searchAssetUseUser", {query: val}).then(resp => {
if (resp.code === 0) {
this.assetUseUserOption = resp.data
}
})
},
},
async created() {
},
style: /*language=CSS*/ `
.table_fixed .el-form-item {
margin-bottom: 0px !important;
}
`
}
@@ -0,0 +1,202 @@
<!--#
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%"
v-model="pageForm.assetTypeCode" @change="doSearch">
<el-option label="校工会资产" :value="1"></el-option>
<el-option label="分工会资产" :value="2"></el-option>
</el-select>
</search-item>
<search-item label="资产类别">
<el-select clearable filterable placeholder="请选择资产类别" style="width: 100%"
v-model="pageForm.assetCategoryId" @change="doSearch">
<el-option :key="item.id"
:label="item.categoryName"
:value="item.id"
v-for="item in assetCategoryOption"></el-option>
</el-select>
</search-item>
<search-item label="使用状况">
<dict-select v-model="pageForm.assetUsageStateName" placeholder="请选择使用状况"
@change="doSearch"
code="ASSET_USAGE_STATE"></dict-select>
</search-item>
<search-item label="使用/管理部门" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<el-select
@change="doSearch"
clearable
filterable
placeholder="请选择使用/管理部门"
style="width: 100%"
v-model="pageForm.assetUseUnionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unionList"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="资产列表">
<el-button @click="doDepreciation" size="small" type="primary">
折旧
</el-button>
<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 v-slot="{row}" v-if="column.prop=='assetTypeCode'">
{{row.assetTypeCode===1?'校工会资产':'分工会资产'}}
</template>
<template v-slot="{row}" v-else-if="column.prop=='assetRetiredAssetsDate'">
{{$moment(row.assetRetiredAssetsDate).format('YYYY-MM-DD')}}
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template v-slot="{row}">
<el-button @click="openView(row.id)" 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 #view>
<asset-info ref="assetInfo"></asset-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/assetInfo.js"){}#-->
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{prop: 'assetNumber', label: '资产编号'},
{prop: 'assetName', label: '资产名称'},
{prop: 'categoryName', label: '类别名称'},
{prop: 'assetStorageLocation', label: '存放地点'},
{prop: 'assetUseUserName', label: '责任人'},
{prop: 'assetAllMoney', label: '原值(元)'},
{prop: 'assetSurplusMoney', label: '净值'},
{prop: 'assetDepreciationMoney', label: '累计折旧(元)'},
{prop: 'assetUsageMonth', label: '预计使用月份'},
{prop: 'assetRetiredAssetsDate', label: '折旧到期日期'},
],
assetCategoryOption: [],
unionList: [],
}
},
components: {
"asset-info": ASSSET_INFO,
},
methods: {
doExport(){
this.$downLoad("/platform/asset/depreciation/doExport", this.pageForm)
},
doDepreciation(){
this.$confirm("此操作将给所有资产折旧, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/asset/depreciation/doDepreciation")
if (resp.code === 0) {
this.doSearch()
this.$message({
type: "success",
message: resp.msg
})
} else {
this.$message.error(resp.msg)
}
})
},
openView(id) {
this.$refs.guava.view(() => {
this.$refs.assetInfo.open(id)
})
},
doDelete(id) {
this.$confirm("此操作将永久删除折旧信息, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/asset/depreciation/doDelete", {id})
if (resp.code === 0) {
this.doSearch()
this.$message({
type: "success",
message: resp.msg
})
} else {
this.$message.error(resp.msg)
}
})
},
// 查询资产类别
queryCategory() {
this.$axios.post("/platform/asset/category/queryCategory").then(resp => {
if (resp.code === 0) {
this.assetCategoryOption = resp.data
}
})
},
},
async created() {
this.queryCategory()
this.$businessTool.listUnion().then((data) => {
this.unionList = data
})
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,205 @@
<!--#
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%"
v-model="pageForm.assetTypeCode" @change="doSearch">
<el-option label="校工会资产" :value="1"></el-option>
<el-option label="分工会资产" :value="2"></el-option>
</el-select>
</search-item>
<search-item label="资产类别">
<el-select clearable filterable placeholder="请选择资产类别" style="width: 100%"
v-model="pageForm.assetCategoryId" @change="doSearch">
<el-option :key="item.id"
:label="item.categoryName"
:value="item.id"
v-for="item in assetCategoryOption"></el-option>
</el-select>
</search-item>
<search-item label="使用状况">
<dict-select v-model="pageForm.assetUsageStateName" placeholder="请选择使用状况"
@change="doSearch"
code="ASSET_USAGE_STATE"></dict-select>
</search-item>
<search-item label="使用/管理部门" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<el-select
@change="doSearch"
clearable
filterable
placeholder="请选择使用/管理部门"
style="width: 100%"
v-model="pageForm.assetUseUnionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unionList"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="资产列表">
<el-button @click="openAdd" size="small" type="primary">
新增资产
</el-button>
<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 v-slot="{row}" v-if="column.prop=='assetTypeCode'">
{{row.assetTypeCode===1?'校工会资产':'分工会资产'}}
</template>
<template v-slot="{row}" v-else-if="column.prop=='assetRetiredAssetsDate'">
{{$moment(row.assetRetiredAssetsDate).format('YYYY-MM-DD')}}
</template>
</el-table-column>
<el-table-column label="操作" width="300">
<template v-slot="{row}">
<el-button @click="openView(row.id)" size="mini" type="primary">查看
</el-button>
<el-button @click="openEdit(row.id)" size="mini" type="primary">编辑
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除
</el-button>
<!-- <el-button @click="doExportInit(row.id)" size="mini" type="primary">导出信息表
</el-button>-->
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<asset-info ref="assetInfo"></asset-info>
</template>
<template #edit>
<asset-form ref="assetForm" @save_success="saveSuccess"></asset-form>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/assetForm.js"){}#-->
<!--#include("../common/assetInfo.js"){}#-->
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{prop: 'assetNumber', label: '资产编号'},
{prop: 'assetName', label: '资产名称'},
{prop: 'categoryName', label: '类别名称'},
{prop: 'assetStorageLocation', label: '存放地点'},
{prop: 'assetUseUserName', label: '责任人'},
{prop: 'assetRetiredAssetsDate', label: '折旧到期日期'},
{prop: 'assetUsageStateName', label: '使用状况'},
],
assetCategoryOption: [],
unionList: []
}
},
components: {
"asset-form": ASSSET_FORM,
"asset-info": ASSSET_INFO,
},
methods: {
doExport(){
this.$downLoad("/platform/asset/manage/doExport", this.pageForm)
},
saveSuccess() {
this.doSearch()
this.$refs.guava.index()
},
openView(id) {
this.$refs.guava.view(() => {
this.$refs.assetInfo.open(id)
})
},
openEdit(id) {
this.$refs.guava.edit(() => {
this.$refs.assetForm.openEdit(id)
})
},
openAdd() {
this.$refs.guava.edit(() => {
this.$refs.assetForm.open()
})
},
doDelete(id) {
this.$confirm("此操作将永久删除资产和折旧信息, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/asset/manage/doDelete", {id})
if (resp.code === 0) {
this.doSearch()
this.$message({
type: "success",
message: resp.msg
})
} else {
this.$message.error(resp.msg)
}
})
},
// 查询资产类别
queryCategory() {
this.$axios.post("/platform/asset/category/queryCategory").then(resp => {
if (resp.code === 0) {
this.assetCategoryOption = resp.data
}
})
},
},
async created() {
this.queryCategory()
this.$businessTool.listUnion().then((data) => {
this.unionList = data
})
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,241 @@
<!--#
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 placeholder="请选择盘点时间段" style="width: 100%"
v-model="pageForm.assetStocktakingPlanId" @change="doSearch">
<el-option :label="p.name" :value="p.id" :key="p.id"
v-for="p in stocktakingPlanOption"></el-option>
</el-select>
</search-item>
<search-item label="资产类型">
<el-select clearable filterable placeholder="请选择资产类型" style="width: 100%"
v-model="pageForm.assetTypeCode" @change="doSearch">
<el-option label="校工会资产" :value="1"></el-option>
<el-option label="分工会资产" :value="2"></el-option>
</el-select>
</search-item>
<search-item label="资产类别">
<el-select clearable filterable placeholder="请选择资产类别" style="width: 100%"
v-model="pageForm.assetCategoryId" @change="doSearch">
<el-option :key="item.id"
:label="item.categoryName"
:value="item.id"
v-for="item in assetCategoryOption"></el-option>
</el-select>
</search-item>
<search-item label="使用状况">
<dict-select v-model="pageForm.assetUsageStateName" placeholder="请选择使用状况"
@change="doSearch"
code="ASSET_USAGE_STATE"></dict-select>
</search-item>
<search-item label="使用/管理部门" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<el-select
@change="doSearch"
clearable
filterable
placeholder="请选择使用/管理部门"
style="width: 100%"
v-model="pageForm.assetUseUnionId"
>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unionList"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="资产列表">
<el-radio-group v-model="pageForm.isStocktaking" size="mini" @change="doSearch">
<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>
</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"
>
<template v-slot="{row}" v-if="column.prop=='assetTypeCode'">
{{row.assetTypeCode===1?'校工会资产':'分工会资产'}}
</template>
<template v-slot="{row}" v-else-if="column.prop=='assetRetiredAssetsDate'">
{{$moment(row.assetRetiredAssetsDate).format('YYYY-MM-DD')}}
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template v-slot="{row}">
<el-button @click="openView(row.id)" size="mini" type="primary">查看
</el-button>
<el-button @click="openStocktaking(row)" size="mini" type="primary"
v-if="!row.isStocktaking"
:disabled="stocktakingPlanOption.length==0
||!pageForm.assetStocktakingPlanId
||!stocktakingPlanOption.find(p=>p.id===pageForm.assetStocktakingPlanId).isShow">
开始盘点
</el-button>
<el-button
:disabled="stocktakingPlanOption.length==0
||!pageForm.assetStocktakingPlanId
||!stocktakingPlanOption.find(p=>p.id===pageForm.assetStocktakingPlanId).isShow"
@click="doDelete(row.id)"
size="mini"
type="danger" v-if="row.isStocktaking">
删除盘点
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<asset-info ref="assetInfo"></asset-info>
</template>
<template #edit>
<asset-stocktaking-form ref="assetStocktakingForm" @save_success="saveSuccess"></asset-stocktaking-form>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/assetStocktakingForm.js"){}#-->
<!--#include("../common/assetInfo.js"){}#-->
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{prop: 'assetNumber', label: '资产编号'},
{prop: 'assetName', label: '资产名称'},
{prop: 'categoryName', label: '类别名称'},
{prop: 'assetTypeCode', label: '资产类型'},
{prop: 'assetStorageLocation', label: '存放地点'},
{prop: 'assetUseUserName', label: '责任人'},
{prop: 'assetRetiredAssetsDate', label: '折旧到期日期'},
{prop: 'assetUsageStateName', label: '使用状况'},
],
assetCategoryOption: [],
stocktakingPlanOption: [],
unionList: [],
pageForm: {
isStocktaking: false
}
}
},
components: {
"asset-stocktaking-form": ASSSET_STOCKTAKING_FORM,
"asset-info": ASSSET_INFO,
},
methods: {
saveSuccess() {
this.doSearch()
this.$refs.guava.index()
},
openView(id) {
this.$refs.guava.view(() => {
this.$refs.assetInfo.open(id)
})
},
openStocktaking(row) {
this.$refs.guava.edit(() => {
row.assetStocktakingPlanId = this.pageForm.assetStocktakingPlanId
this.$refs.assetStocktakingForm.open(row)
})
},
doDelete(id) {
this.$confirm("此操作将永久删除资产和折旧信息, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/asset/stocktaking/doDelete", {
id: id,
assetStocktakingPlanId: this.pageForm.assetStocktakingPlanId
})
if (resp.code === 0) {
this.doSearch()
this.$message({
type: "success",
message: resp.msg
})
} else {
this.$message.error(resp.msg)
}
})
},
// 查询资产类别
queryCategory() {
this.$axios.post("/platform/asset/category/queryCategory").then(resp => {
if (resp.code === 0) {
this.assetCategoryOption = resp.data
}
})
},
// 按年度查询资产盘点计划
async queryStocktakingPlan() {
const resp = await this.$axios.post("/platform/asset/stocktakingPlan/queryStocktakingPlan")
if (resp.code === 0) {
resp.data.forEach(v => {
const startDate = this.$moment(v.startDate).format('YYYY-MM-DD')
const endDate = this.$moment(v.endDate).format('YYYY-MM-DD')
v.name = startDate + "至" + endDate + "" + v.year + ""
v.isShow = (this.$moment().format('YYYY-MM-DD hh:mm:ss') > v.startDate && this.$moment().format('YYYY-MM-DD hh:mm:ss') < v.endDate)
})
this.stocktakingPlanOption = resp.data
if (this.stocktakingPlanOption && this.stocktakingPlanOption.length > 0) {
this.$set(this.pageForm, "assetStocktakingPlanId", this.stocktakingPlanOption[0].id)
} else {
this.$set(this.pageForm, "assetStocktakingPlanId", null)
}
}
},
},
async created() {
this.queryCategory()
await this.queryStocktakingPlan()
this.$businessTool.listUnion().then((data) => {
this.unionList = data
})
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,212 @@
<!--#
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 placeholder="按年度查询" type="year" 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-button @click="openAdd" 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"
>
</el-table-column>
<el-table-column label="操作" width="300">
<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>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
<el-dialog
:close-on-click-modal="false"
:title="title"
:visible.sync="dialogVisible"
width="40%">
<el-form :model="formData" :rules="formRules" label-width="100px" ref="addForm">
<el-form-item label="年度" prop="year">
<el-date-picker
:disabled="isView"
placeholder="选择年度"
style="width: 100%"
type="year"
v-model="formData.year"
value-format="yyyy">
</el-date-picker>
</el-form-item>
<el-form-item label="计划时间" prop="planDate">
<el-date-picker
:disabled="isView"
end-placeholder="结束日期"
start-placeholder="开始日期"
style="width: 100%"
type="datetimerange"
v-model="formData.planDate"
value-format="yyyy-MM-dd HH:mm:ss">
</el-date-picker>
</el-form-item>
<el-form-item label="说明" prop="note">
<el-input
:disabled="isView"
:rows="3"
placeholder="请输入说明"
type="textarea"
v-model="formData.note">
</el-input>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer" v-if="!isView">
<el-button @click="dialogVisible = false">关 闭</el-button>
<el-button @click="doSubmit" type="primary">提 交</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{prop: 'year', label: '年度', width: '200'},
{prop: 'startDate', label: '开始时间', width: '200'},
{prop: 'endDate', label: '结束时间', width: '200'},
{prop: 'note', label: '备注'},
],
isView: false,
title: "",
dialogVisible: false,
formRules: {
year: [{required: true, message: '必选', trigger: ['blur', 'change']}],
planDate: [{
required: true,
message: '必选',
trigger: ['blur', 'change']
}],
},
}
},
components: {},
methods: {
doSubmit() {
this.$refs["addForm"].validate(async (valid) => {
if (valid) {
const formData = clone(this.formData)
formData.startDate = formData.planDate[0]
formData.endDate = formData.planDate[1]
const resp = await this.$axios.post('/platform/asset/stocktakingPlan/doSubmit', formData)
if (resp.code === 0) {
this.doSearch()
this.notifySuccess(resp.msg)
} else {
this.notifyError(resp.msg)
}
this.dialogVisible = false
}
})
},
openAdd() {
this.isView = false
this.title = "新增计划"
this.formData = {
year: this.$moment().format('YYYY') + "",
planDate: [],
note: null
}
this.dialogVisible = true
},
openView(row) {
this.isView = true
this.title = "查看计划"
this.formData = {
year: row.year,
planDate: [row.startDate, row.endDate],
note: row.note
}
this.dialogVisible = true
},
openEdit(row) {
this.isView = false
this.title = "编辑计划"
this.formData = {
id: row.id,
year: row.year,
planDate: [row.startDate, row.endDate],
note: row.note
}
this.dialogVisible = true
},
doDelete(id) {
this.$confirm("此操作将永久删除盘点计划, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/asset/stocktakingPlan/doDelete", {id})
if (resp.code === 0) {
this.doSearch()
this.$message({
type: "success",
message: resp.msg
})
} else {
this.$message.error(resp.msg)
}
})
},
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
@@ -0,0 +1,135 @@
<!--#
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" class="mt10">
<table-tool label="数据列表">
<el-button type="primary" size="small" icon="el-icon-plus" @click="onOpen">新增</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="名称" prop="name" sortable></el-table-column>
<el-table-column label="模板内容" prop="template" width="400px"></el-table-column>
<el-table-column label="定时任务" prop="cron" width="150px"></el-table-column>
<el-table-column label="是否启用" prop="enabled" sortable width="150px">
<template scope="{row}">
<el-tag :type="row.enabled ? 'success' : 'danger'" size="mini">{{row.enabled ? '是' : '否'}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="onEdit(row)">修改</el-button>
<el-button size="mini" type="danger" @click="onDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" :close-on-click-modal="false" width="60%">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="名称"></el-input>
</el-form-item>
<el-form-item label="模板内容" prop="template">
<el-input v-model="formData.template" placeholder="模板内容" type="textarea" rows="5"></el-input>
</el-form-item>
<el-form-item label="定时任务" prop="cron">
{{formData.cron}}
<el-select v-model="formData.cron" placeholder="请选择定时任务或者输入cron表达式" allow-create filterable>
<el-option label="早上8点" value="0 0 8 * * ?"></el-option>
<el-option label="早上9点" value="0 0 9 * * ?"></el-option>
<el-option label="早上10点" value="0 0 10 * * ?"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否启用" prop="enabled">
<el-switch v-model="formData.enabled"></el-switch>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
dialogVisible: false,
formRules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
template: [{ required: true, message: "请输入模板内容", trigger: "blur" }],
cron: [{ required: true, message: "请选择定时任务或者输入cron表达式", trigger: "blur" }],
enabled: [{ required: true, message: "请选择是否启用", trigger: "blur" }]
}
}
},
methods: {
onOpen() {
this.dialogVisible = true
this.$nextTick(() => {
this.formData = {}
this.$refs.formRef.resetFields()
})
},
onEdit(row) {
this.dialogVisible = true
this.$nextTick(() => {
this.formData = { ...row }
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios.post("/platform/birthdayWishes/plan/" + (this.formData.id ? "update" : "insert"), this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogVisible = false
this.doSearch()
} else {
this.$message.error(res.msg)
}
})
}
})
},
onDelete(id) {
this.$confirm("确定删除吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post("/platform/birthdayWishes/plan/delete", { 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,157 @@
<!--#
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" class="mt10">
<table-tool label="数据列表">
<el-button type="primary" size="small" icon="el-icon-plus" @click="onOpen">新增</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="名称" prop="name" sortable></el-table-column>
<el-table-column label="年份" prop="year" sortable width="150px"></el-table-column>
<el-table-column label="开始时间" prop="startTime" sortable width="300px"></el-table-column>
<el-table-column label="结束时间" prop="endTime" sortable width="300px"></el-table-column>
<el-table-column label="是否启用" prop="enabled" sortable width="150px">
<template scope="{row}">
<el-tag :type="row.enabled ? 'success' : 'danger'" size="mini">{{row.enabled ? '是' : '否'}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="onEdit(row)">修改</el-button>
<el-button size="mini" type="danger" @click="onDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" :close-on-click-modal="false" width="60%">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="考核年份" prop="year">
<el-date-picker v-model="formData.year" type="year" value-format="yyyy" placeholder="考核年份" style="width: 100%"></el-date-picker>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="名称"></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
v-model="formData.startTime"
style="width: 100%"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="开始时间"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
v-model="formData.endTime"
style="width: 100%"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="结束时间"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="通知内容" prop="content">
<text-editor v-model="formData.content"></text-editor>
</el-form-item>
<el-form-item label="是否启用" prop="enabled">
<el-switch v-model="formData.enabled"></el-switch>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
dialogVisible: false,
formRules: {
name: [{ required: true, message: "名称不能为空", trigger: ["blur", "change"] }],
content: [{ required: true, message: "通知内容不能为空", trigger: ["blur", "change"] }],
year: [{ required: true, message: "考核年份不能为空", trigger: ["blur", "change"] }],
startTime: [{ required: true, message: "开始时间不能为空", trigger: ["blur", "change"] }],
endTime: [{ required: true, message: "结束时间不能为空", trigger: ["blur", "change"] }],
enabled: [{ required: true, message: "是否启用不能为空", trigger: ["blur", "change"] }]
}
}
},
methods: {
onOpen() {
this.dialogVisible = true
this.$nextTick(() => {
this.formData = {}
this.$refs.formRef.resetFields()
})
},
onEdit(row) {
this.dialogVisible = true
this.$nextTick(() => {
this.formData = { ...row }
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios.post("/platform/buildHome/act/save", this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogVisible = false
this.doSearch()
} else {
this.$message.error(res.msg)
}
})
}
})
},
onDelete(id) {
this.$confirm("确定删除吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post("/platform/buildHome/act/delete/" + 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,60 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-tabs__header {
background: #fff;
}
.el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
border-bottom: none;
}
</style>
<div id="app" v-cloak>
<el-tabs v-model="activeTab" @tab-click="tabChange" type="card">
<el-tab-pane name="unionOfficer">
<span slot="label">
<i class="el-icon-school"></i>
分工会干部
</span>
<union-officer ref="unionOfficerRef"></union-officer>
</el-tab-pane>
<el-tab-pane name="unionGroup">
<span slot="label">
<i class="el-icon-school"></i>
工会小组
</span>
<union-group ref="unionGroupRef"></union-group>
</el-tab-pane>
</el-tabs>
</div>
<script nonce="${cspNonce!}">
<!--#include('unionOfficer.js'){}#-->
<!--#include('unionGroup.js'){}#-->
new Vue({
el: "#app",
components: {
"union-officer": unionOfficer,
"union-group": unionGroup
},
data() {
return {
activeTab: "unionOfficer"
}
},
methods: {
tabChange(val) {
this.$nextTick(() => {
this.$refs[this.activeTab + "Ref"].doSearch()
})
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,157 @@
const unionGroup = {
template: /*language=HTML*/ `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="可输入名称查询"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
></el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-plus" style="margin-left: auto"
@click="openAdd">
新增
</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border>
<el-table-column type="index" width="50" label="序号"></el-table-column>
<el-table-column prop="code" label="小组编码"></el-table-column>
<el-table-column prop="name" label="小组名称"></el-table-column>
<el-table-column prop="leaderUserName" label="组长姓名"></el-table-column>
<el-table-column prop="leaderMobile" label="组长电话"></el-table-column>
<el-table-column label="操作" width="200px">
<template slot-scope="{row}">
<el-button type="primary" size="mini" @click="onEdit(row)">
编辑
</el-button>
<el-button type="danger" size="mini" @click="onDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogFormVisible" width="600px"
:close-on-click-modal="false">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="小组编码" prop="code">
<el-input v-model="formData.code" placeholder="小组编码" maxlength="10"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="小组名称" prop="name">
<el-input v-model="formData.name" placeholder="小组名称" maxlength="100"></el-input>
</el-form-item>
<el-form-item label="小组长" prop="leader">
<el-select
v-model="formData.leader"
filterable
remote
reserve-keyword
placeholder="请输入姓名查询"
:remote-method="getUserOptions"
style="width: 100%">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.username+'('+item.unitName+')'"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
data() {
return {
pageForm: {},
formData: {},
rules: {
code: [{ required: true, message: "请输入小组编码", trigger: "blur" }],
name: [{ required: true, message: "请输入小组名称", trigger: "blur" }],
leader: [{ required: true, message: "请选择小组长", trigger: "change" }]
},
userOptions: []
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
this.$refs.formRef.clearValidate()
})
},
onEdit(row) {
this.formData = { ...row }
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs.formRef.clearValidate()
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
const { id } = this.formData
const url = "/platform/buildHome/agency" + (id ? "/updateGroup" : "/insertGroup")
$.post(url, this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogFormVisible = false
this.doSearch()
}
})
}
})
},
onDelete(id) {
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
$.post("/platform/buildHome/agency/deleteGroup/" + id).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
pageData() {
$.get("/platform/buildHome/agency/groupPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
getUserOptions(keyword) {
$.get("/platform/buildHome/agency/listUser", { keyword }).then((res) => {
if (res.code === 0) {
this.userOptions = res.data
}
})
}
}
}
@@ -0,0 +1,123 @@
const unionOfficer = {
template: /*language=HTML*/ `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="请输入内容"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
>
<el-select v-model="pageForm.searchName" slot="prepend" size="small" placeholder="查询类型"
style="width: 120px">
<el-option label="角色" value="roleName"></el-option>
<el-option label="姓名" value="username"></el-option>
<el-option label="工号" value="loginname"></el-option>
</el-select>
</el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-plus" style="margin-left: auto"
@click="openAdd">添加
</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border size="small">
<el-table-column prop="username" label="姓名"></el-table-column>
<el-table-column prop="loginname" label="工号"></el-table-column>
<el-table-column prop="roleName" label="角色"></el-table-column>
<el-table-column label="操作" width="100px">
<template scope="scope">
<el-button size="mini" type="danger" icon="el-icon-delete"
:disabled="scope.row.roleCode === 'BRANCH_UNION_CHAIRMAN'"
@click="doDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
<el-form :model="formData" ref="form" size="small" label-width="80px">
<el-form-item prop="roleCode" label="角色">
<dict-select v-model="formData.roleCode" code="BRANCH_UNION_ROLES"></dict-select>
</el-form-item>
<el-form-item prop="userId" label="人员">
<user-select
v-model="formData.userId"
api="/platform/buildHome/agency/listUserSelect"
:option_label_func="
(item) => {
return item.username + item.loginname + '(' + item.unitName + ')'
}
"
></user-select>
</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>
</div>
`,
store,
mixins: [initTableMixins],
computed: {
userId() {
return this.$store.state.user.id
}
},
data() {
return {
pageForm: {
searchName: "username"
},
dialogFormVisible: false,
formData: {}
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
})
},
doSubmit() {
$.post("/platform/buildHome/agency/insertOfficer", this.formData).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
},
doDelete({ userId, roleCode }) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
$.post("/platform/buildHome/agency/deleteOfficer", { userId, roleCode }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
pageData() {
console.log(this.$store.state.user.id)
$.get("/platform/buildHome/agency/officerPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data
}
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,113 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker type="year" value-format="yyyy" v-model="pageForm.year"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="数据列表">
<el-button type="primary" size="small" icon="el-icon-plus" @click="$refs.kpiFormRef.onOpen()">新增
</el-button>
<!-- <el-button type="primary" size="small" icon="el-icon-download" @click="">导出汇总表</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
v-for="column in tableColumns"
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
:width="column.width"
:min-width="column.width"
header-align="center"
show-overflow-tooltip
>
<template v-if="column.prop === 'enabled'" scope="{row}">
<el-tag :type="row.enabled ? 'success' : 'danger'" size="mini">{{ row.enabled ? "是" : "否" }}
</el-tag>
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="$refs.kpiFormRef.onOpen(row.id)">修改</el-button>
<el-button size="mini" type="danger" @click="onDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<kpi-form ref="kpiFormRef" @refresh="doSearch"></kpi-form>
</div>
<script nonce="${cspNonce!}">
<!--#include('kpiForm.js'){}#-->
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"kpi-form": kpiForm
},
data() {
return {
formData: {
name: "",
year: "",
time: "",
categoryList: []
},
rules: {
name: [{ required: true, message: "请输入考核名称", trigger: ["blur", "change"] }],
year: [{ required: true, message: "请输入考核年度", trigger: ["blur", "change"] }],
time: [{ required: true, message: "请选择考核时间", trigger: ["blur", "change"] }]
},
tableColumns: [
{ label: "考核名称", prop: "name", sortable: true },
{ label: "考核年度", prop: "year", sortable: true, width: "200px" },
{ label: "开始时间", prop: "startTime", sortable: true, width: "200px" },
{ label: "结束时间", prop: "endTime", sortable: true, width: "200px" },
{ label: "是否开启", prop: "enabled", sortable: true, width: "200px" }
]
}
},
methods: {
onDelete(id) {
this.$confirm("确定要删除吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/buildHome/kpi/plan/delete", { id }).then((res) => {
if (res.code === 0) {
this.$message.success("删除成功")
this.doSearch()
} else {
this.$message.error(res.msg)
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,507 @@
const kpiForm = {
template: /*language=HTML*/ `
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="visible" :close-on-click-modal="false"
width="75%">
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px">
<div class="process-title">基础信息</div>
<el-form-item label="考核名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入考核名称"></el-input>
</el-form-item>
<el-row :gutter="20" type="flex">
<el-form-item label="考核年度" prop="year">
<el-date-picker v-model="formData.year" type="year" placeholder="选择年"
value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker v-model="formData.startTime" type="date" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker v-model="formData.endTime" type="date" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"></el-date-picker>
</el-form-item>
</el-row>
<el-form-item label="是否开启" prop="enable">
<el-switch v-model="formData.enable" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
<div class="process-title">考核内容</div>
<div class="kpi-plus">
<el-row type="flex" justify="space-between" class="mb20">
<el-button type="primary" icon="el-icon-plus" size="small" @click="showAddCategoryDialog">新增考核项目
</el-button>
</el-row>
<div>
<table>
<thead class="bg-gray-50">
<tr>
<th style="width: 10%">序号</th>
<th style="width: 10%">考核项目名称</th>
<th style="width: 50%">考核内容详情</th>
<th style="width: 10%">单项分</th>
<th style="width: 10%">分值</th>
<th style="width: 10%">操作</th>
</tr>
</thead>
<tbody ref="categoryList" style="height: 50vh;overflow-y: auto;display: table;width: 100%">
<template v-for="(category,categoryIndex) in formData.categoryList">
<tr v-for="(item,itemIndex) in category.items"
:class="{'category-split':itemIndex+1===category.items.length}">
<td v-if="itemIndex===0" :rowspan="category.items.length" class="text-center" style="width: 10%">
<div>{{categoryIndex+1}}</div>
</td>
<td v-if="itemIndex===0" :rowspan="category.items.length" style="width: 10%">
<span v-if="category?.$edit_status?.name === false">
{{category.name}}
</span>
<el-input v-model="category.name" v-else
@blur="$set(category['$edit_status'],'name',false)"></el-input>
<div class="td-extra" v-if="category?.$edit_status?.name === false">
<i class="fa fa-pencil edit" aria-hidden="true"
@click="$set(category['$edit_status'],'name',true)"></i>
<i class="fa fa-times delete" aria-hidden="true"
@click="onDeleteCategory(categoryIndex)"></i>
<i class="fa fa-plus" aria-hidden="true"
@click="addNewItem(categoryIndex)"></i>
</div>
</td>
<td class="item-content" style="width: 50%">
<span v-if="item?.$edit_status?.content === false">
{{item.content}}
</span>
<el-input v-else v-model="item.content" type="textarea" :rows="2"
@blur="$set(item['$edit_status'],'content',false)"></el-input>
<div class="td-extra" v-if="item?.$edit_status?.content === false">
<i class="fa fa-pencil edit" aria-hidden="true"
@click="$set(item['$edit_status'],'content',true)"></i>
<i class="fa fa-times delete" aria-hidden="true"
@click="onDeleteItem(categoryIndex,itemIndex)"></i>
</div>
</td>
<td style="width: 10%">
<span v-if="item?.$edit_status?.score === false">
{{item.score}}
</span>
<el-input-number v-else v-model="item.score" :min="1"
@blur="$set(item['$edit_status'],'score',false)"></el-input-number>
<div class="td-extra" v-if="item?.$edit_status?.score === false">
<i class="fa fa-pencil edit" aria-hidden="true"
@click="$set(item['$edit_status'],'score',true)"></i>
</div>
</td>
<td v-if="itemIndex===0" :rowspan="category.items.length" style="width: 10%">
{{category.items.reduce((sum, item) => sum + (item.score || 0), 0)}}
</td>
<td style="width: 10%">
<div class="td-extra" style="opacity: 1!important;">
<i class="fa fa-times delete" aria-hidden="true"
@click="onDeleteItem(categoryIndex,itemIndex)"></i>
</div>
</td>
</tr>
</template>
<tr>
<td>
<span style="font-weight: bold">
合计
</span>
</td>
<td></td>
<td></td>
<td></td>
<td :colspan="2">
<span style="font-weight: bold">
{{formData.categoryList.flatMap(v=>v.items).map(v=>v.score || 0).reduce((sum, v) => sum + v, 0)}}
</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="process-title">评比等级</div>
<div>
<el-row type="flex" justify="space-between" class="mb20">
<el-button type="primary" icon="el-icon-plus" size="small"
@click="formData.scoreLevels.push({})">新增评比等级
</el-button>
</el-row>
<table class="score-levels-table">
<thead class="bg-gray-50" style="display: table;width: 100%">
<tr>
<th style="width: 30%;">最小分数</th>
<th style="width: 30%;">最大分数</th>
<th style="width: 30%;">评比等级</th>
<th>操作</th>
</tr>
</thead>
<tbody ref="scoreLevels" style="display: table;width: 100%">
<tr v-for="(scoreLevel,scoreLevelIndex) in formData.scoreLevels">
<td>
<el-input-number v-model="scoreLevel.min" :min="1"
placeholder="请输入分数"></el-input-number>
</td>
<td>
<el-input-number v-model="scoreLevel.max" :min="1"
placeholder="请输入分数"></el-input-number>
</td>
<td>
<el-input v-model="scoreLevel.level" max="20" show-word-limit
placeholder="请输入评比等级"></el-input>
</td>
<td>
<div class="td-extra" style="opacity: 1!important;">
<i class="fa fa-times delete" aria-hidden="true"
@click="formData.scoreLevels.splice(scoreLevelIndex, 1)"></i>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<el-dialog title="新增考核项目" :visible.sync="dialogVisible" width="50%" append-to-body>
<el-form :model="newCategory" label-width="120px">
<el-form-item label="考核项目名称">
<el-input v-model="newCategory.name"></el-input>
</el-form-item>
<el-form-item label="考核项目代码">
<el-input v-model="newCategory.code"></el-input>
</el-form-item>
<el-form-item label="排序">
<el-input-number v-model="newCategory.sortOrder" :min="1"></el-input-number>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addCategory">确 定</el-button>
</span>
</el-dialog>
</div>
</el-form>
<span slot="footer">
<el-button @click="visible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
title: "新增",
visible: false,
dialogVisible: false,
formData: {
categoryList: [],
scoreLevels:[]
},
formRules: {
name: [{ required: true, message: "请输入考核名称", trigger: ["change", "blur"] }],
code: [{ required: true, message: "请输入考核代码", trigger: ["change", "blur"] }],
year: [{ required: true, message: "请输入考核年份", trigger: ["change", "blur"] }],
startTime: [{ required: true, message: "请输入考核时间", trigger: ["change", "blur"] }],
endTime: [{ required: true, message: "请输入考核时间", trigger: ["change", "blur"] }]
},
newCategory: {
name: "",
code: "",
sortOrder: 1,
items: []
}
}
},
methods: {
onOpen(id = null) {
this.visible = true
if (id) {
$.post("/platform/buildHome/kpi/plan/get", { id }).then((res) => {
if (res.code === 0) {
res.data.year = res.data.year.toString()
this.formData = res.data
this.initStatus()
} else {
this.$message.error(res.msg)
}
})
} else {
this.formData = {
categoryList: [],
scoreLevels:[]
}
}
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
//至少要有一个考核项目
if (!this.formData.categoryList || this.formData.categoryList.length === 0) {
this.$message.error("请至少添加一个考核项目")
return
}
//每个考核项目至少要有一个考核内容
for (let category of this.formData.categoryList) {
if (category.items.length === 0) {
this.$message.error("请至少添加一个考核内容")
return
}
}
//每个考核内容至少要有分数
const hasNoneScore = this.formData.categoryList.flatMap((v) => v.items).some((v) => !v.score)
if (hasNoneScore) {
this.$message.error("考核内容需要设置分数")
return
}
//要设置评比等级
if (!this.formData.scoreLevels || this.formData.scoreLevels.length === 0) {
this.$message.error("请至少添加一项评比等级")
return
}
//每条评比等级中必须填写完整
for (let scoreLevel of this.formData.scoreLevels) {
if (!scoreLevel.min || !scoreLevel.max || !scoreLevel.level) {
this.$message.error("评比等级需要设置完整")
return
}
}
//每条评比等级中的min max 不能重叠
for (let i = 0; i < this.formData.scoreLevels.length; i++) {
for (let j = i + 1; j < this.formData.scoreLevels.length; j++) {
if (
this.formData.scoreLevels[i].min <= this.formData.scoreLevels[j].max &&
this.formData.scoreLevels[i].max >= this.formData.scoreLevels[j].min
) {
this.$message.error("评比等级中的分数不能重叠")
return
}
}
}
this.$axios
.post("/platform/buildHome/kpi/plan/save", {
plan: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success("保存成功")
this.visible = false
this.$emit("refresh", null)
} else {
this.$message.error(res.msg)
}
})
}
})
},
initStatus() {
this.formData.categoryList.forEach((category) => {
this.$set(category, "$edit_status", {
name: false // 初始化 name 的编辑状态
})
if (category.items && Array.isArray(category.items)) {
category.items.forEach((item) => {
this.$set(item, "$edit_status", {
content: false, // 控制 item.content 的编辑状态
score: false // 控制 item.score 的编辑状态
})
})
}
})
},
showAddCategoryDialog() {
this.dialogVisible = true
this.newCategory = {
name: "",
code: "",
sortOrder: this.formData.categoryList.length + 1,
items: [{}]
}
},
addCategory() {
if (!this.newCategory.name || !this.newCategory.code) {
this.$message.warning("请填写完整信息")
return
}
const cateGoryId = Date.now()
const category = {
id: cateGoryId,
name: this.newCategory.name,
code: this.newCategory.code,
sortOrder: this.newCategory.sortOrder,
items: [
{
categoryId: cateGoryId,
content: null,
score: 1,
sortOrder: 1,
$edit_status: {
content: true,
score: false
}
}
],
$edit_status: { name: false }
}
this.formData.categoryList.push(category)
this.dialogVisible = false
this.$message.success("添加成功")
},
addNewItem(categoryIndex) {
const category = this.formData.categoryList[categoryIndex]
const newItem = {
id: Date.now(),
categoryId: category.id,
content: "",
score: 1,
sortOrder: category.items.length + 1,
$edit_status: {
content: true,
score: false
}
}
category.items.push(newItem)
},
// 删除考核项目
onDeleteCategory(cateGoryIndex) {
this.$confirm("确认删除该考核项目吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.formData.categoryList.splice(cateGoryIndex, 1)
this.$message.success("删除成功")
})
.catch(() => {})
},
// 删除考核内容
onDeleteItem(cateGoryIndex, itemIndex) {
this.$confirm("确认删除该考核内容吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.formData.categoryList[cateGoryIndex].items.splice(itemIndex, 1)
this.$message.success("删除成功")
})
.catch(() => {})
}
},
style: /*language=CSS*/ `
.kpi-plus {
}
.kpi-plus table {
width: 100%;
border-collapse: collapse;
position: relative;
}
.kpi-plus table thead {
background: #fafafa;
display: table;
table-layout: fixed;
width: calc(100% - 1em);
}
.kpi-plus table tbody {
display: block;
}
.kpi-plus thead th,
.kpi-plus tbody td {
width: auto;
min-width: 100px;
box-sizing: border-box;
}
.kpi-plus table thead th {
color: rgb(107 114 128);
background: #fafafa;
font-weight: 600;
padding: 14px 20px;
line-height: 20px;
}
.kpi-plus table tr:last-child {
position: sticky;
bottom: 0;
background-color: white;
}
.kpi-plus table tbody tr td {
padding: 14px 20px;
color: rgb(17 24 39);
line-height: 20px;
text-align: center;
cursor: pointer;
}
.kpi-plus table tbody tr td:hover {
background: rgb(249 250 251);
}
.kpi-plus table tbody tr td:hover .td-extra {
opacity: 1;
display: block;
}
.kpi-plus table tbody td.item-content {
border-bottom: 1px solid rgb(229 231 235);
text-align: left;
}
.kpi-plus table tbody .category-split td {
border-bottom: 1px solid rgb(33 40 53) !important;
}
.kpi-plus table tbody tr td[rowspan] {
border-bottom: 1px solid rgb(33 40 53);
}
.kpi-plus .score-levels-table .el-input-number{
width: unset!important;
}
.td-extra {
/*display: none;*/
/*opacity: 0;*/
transition: opacity 0.3s ease;
}
.td-extra .edit {
color: #0a84ff;
}
.td-extra .edit:hover {
color: #1375d8;
transform: scale(1.2);
}
.td-extra .delete {
color: #ff3b30;
}
.td-extra .delete:hover {
color: #ec2216;
transform: scale(1.2);
}
`
}
@@ -0,0 +1,78 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search>
<search-item label="考核名称">
<el-select v-model="pageForm.planId">
<el-option v-for="item in planOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="填写考核评议自评">
<el-button size="small" type="primary" @click="exportDocx">导出自评表</el-button>
</table-tool>
<kpi-write :plan-id="pageForm.planId" @refresh="doSearch" @export="exportDocx"></kpi-write>
</el-card>
</div>
<script nonce="${cspNonce!}">
<!--#include('kpiWrite.js'){}#-->
new Vue({
el: "#app",
components: { "kpi-write": kpiWrite },
data() {
return {
planOptions: [],
plan: {},
pageForm: {
planId: null
}
}
},
methods: {
listPlan() {
this.$axios.post("/platform/buildHome/kpi/write/listPlan").then((res) => {
if (res.code === 0) {
this.planOptions = res.data
if (this.planOptions.length > 0) {
this.pageForm.planId = this.planOptions[0].id
}
}
})
},
getPlan() {
this.$axios
.post("/platform/buildHome/kpi/write/getPlan", {
id: this.pageForm.planId
})
.then((res) => {
if (res.code === 0) {
this.plan = res.data
}
})
},
doSearch() {
this.getPlan()
},
exportDocx() {
this.$downLoad("/platform/buildHome/kpi/write/exportDocx", {
id: this.pageForm.planId
})
}
},
created() {
this.listPlan()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,281 @@
const kpiWrite = {
template: /*language=HTML*/ `
<div class="kpi-plus">
<div>
<table>
<thead class="bg-gray-50">
<tr>
<th style="width: 10%">序号</th>
<th style="width: 10%">考核项目名称</th>
<th style="width: 50%">考核内容详情</th>
<th style="width: 10%">单项分</th>
<th style="width: 10%">分值</th>
<th style="width: 10%">自评分</th>
</tr>
</thead>
<tbody ref="categoryList">
<template v-for="(category,categoryIndex) in formData.categoryList">
<tr v-for="(item,itemIndex) in category.items"
:class="{'category-split':itemIndex+1===category.items.length}">
<td v-if="itemIndex===0" :rowspan="category.items.length" class="text-center" style="width: 10%">
<div>{{categoryIndex+1}}</div>
</td>
<td v-if="itemIndex===0" :rowspan="category.items.length" style="width: 10%">
{{category.name}}
</td>
<td class="item-content" style="width: 50%">
{{item.content}}
</td>
<td style="width: 10%">
{{item.score}}
</td>
<td v-if="itemIndex===0" :rowspan="category.items.length" style="width: 10%">
{{category.items.reduce((sum, item) => sum + (item.score || 0), 0)}}
</td>
<td style="width: 10%">
<el-input-number v-model="item.selfScore"
:max="item.score"
:min="0"
:precision="0"
></el-input-number>
</td>
</tr>
</template>
<tr>
<td>
<span style="font-weight: bold">
合计
</span>
</td>
<td></td>
<td></td>
<td></td>
<td>
<span style="font-weight: bold">
{{formData.categoryList.flatMap(v=>v.items).map(v=>v.score || 0).reduce((sum, v) => sum + v, 0)}}
</span>
</td>
<td>
<span style="font-weight: bold">
{{formData.categoryList.flatMap(v=>v.items).map(v=>v.selfScore || 0).reduce((sum, v) => sum + v, 0)}}
</span>
</td>
</tr>
</tbody>
</table>
</div>
<el-row type="flex" justify="end" class="mt10">
<el-button @click="onExport">导出自评表</el-button>
<el-button type="primary" @click="onSave">保存</el-button>
</el-row>
</div>
`,
data() {
return {
formData: {
categoryList: []
},
formRules: {
name: [{ required: true, message: "请输入考核名称", trigger: ["change", "blur"] }],
code: [{ required: true, message: "请输入考核代码", trigger: ["change", "blur"] }],
year: [{ required: true, message: "请输入考核年份", trigger: ["change", "blur"] }],
time: [{ required: true, message: "请输入考核时间", trigger: ["change", "blur"] }]
},
write: []
}
},
props: {
planId: {
type: String,
default: ""
}
},
watch: {
planId: {
handler(val) {
if (val) {
this.getPlan()
}
},
immediate: true
}
},
methods: {
// 获取考核指标
async getPlan() {
const { code, data, msg } = await this.$axios.post("/platform/buildHome/kpi/write/getPlan", {
id: this.planId
})
if (code === 0) {
this.formData = data
await this.getWrite()
} else {
this.$message.error(msg)
}
},
// 获取填写记录
async getWrite() {
const { code, data, msg } = await this.$axios.post("/platform/buildHome/kpi/write/getWrite", {
id: this.planId
})
if (code === 0) {
this.write = data
this.assignScore()
} else {
this.$message.error(msg)
}
},
// 赋值分数
assignScore() {
this.formData.categoryList.forEach((category, categoryIndex) => {
category.items.forEach((item, itemIndex) => {
const write = this.write.find((write) => write.categoryId === category.id && write.itemId === item.id)
if (write) {
item.selfScore = write.selfScore
}
})
})
},
onSave() {
const list = []
this.formData.categoryList.forEach((category, categoryIndex) => {
category.items.forEach((item, itemIndex) => {
list.push({
planId: this.planId,
categoryId: category.id,
itemId: item.id,
selfScore: item.selfScore
})
})
})
this.$confirm("保存后可继续填写,确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then((res) => {
this.$axios
.post("/platform/buildHome/kpi/write/save", {
write: JSON.stringify(list),
planId: this.planId
})
.then((res) => {
if (res.code === 0) {
this.$message.success("保存成功")
this.$emit("refresh", null)
} else {
this.$message.error(res.msg)
}
})
})
},
onExport() {
this.$emit("export", null)
}
},
style: /*language=CSS*/ `
.kpi-plus {
}
.kpi-plus table {
width: 100%;
border-collapse: collapse;
position: relative;
}
.kpi-plus table thead {
background: #fafafa;
display: table;
table-layout: fixed;
width: calc(100% - 1em);
}
.kpi-plus table tbody {
display: block;
}
.kpi-plus table thead th,
.kpi-plus table tbody td {
width: auto;
min-width: 100px;
box-sizing: border-box;
}
.kpi-plus table thead th {
color: rgb(107 114 128);
background: #fafafa;
font-weight: 600;
padding: 14px 20px;
line-height: 20px;
}
.kpi-plus table tr:last-child {
position: sticky;
bottom: 0;
background-color: white;
}
.kpi-plus table tbody tr td {
padding: 14px 20px;
color: rgb(17 24 39);
line-height: 20px;
text-align: center;
cursor: pointer;
}
.kpi-plus table tbody tr td:hover {
background: rgb(249 250 251);
}
.kpi-plus table tbody tr td:hover .td-extra {
opacity: 1;
display: block;
}
.kpi-plus table tbody td.item-content {
border-bottom: 1px solid rgb(229 231 235);
text-align: left;
}
.kpi-plus table tbody .category-split td {
border-bottom: 1px solid rgb(33 40 53) !important;
}
.kpi-plus table tbody tr td[rowspan] {
border-bottom: 1px solid rgb(33 40 53);
}
.td-extra {
/*display: none;*/
/*opacity: 0;*/
transition: opacity 0.3s ease;
}
.td-extra .edit {
color: #0a84ff;
}
.td-extra .edit:hover {
color: #1375d8;
transform: scale(1.2);
}
.td-extra .delete {
color: #ff3b30;
}
.td-extra .delete:hover {
color: #ec2216;
transform: scale(1.2);
}
.kpi-plus table tbody tr td .el-input-number{
width: unset!important;
}
`
}
@@ -0,0 +1,84 @@
const form = {
template: /*language=HTML*/ `
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" :close-on-click-modal="false">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="单位" prop="unitName">
<el-input v-model="formData.unitName" placeholder="请输入单位" maxlength="100"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="地点" prop="address">
<el-input v-model="formData.address" placeholder="请输入地点" maxlength="100"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="面积" prop="area">
<el-input v-model="formData.area" placeholder="请输入面积" maxlength="10"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="设施" prop="facility">
<el-input v-model="formData.facility" type="textarea" :rows="5" placeholder="请输入设施"
maxlength="1000" show-word-limit></el-input>
</el-form-item>
<el-form-item label="开放时间" prop="openTime">
<el-input v-model="formData.openTime" placeholder="请输入开放时间"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</div>
</el-dialog>
`,
data() {
return {
dialogVisible: false,
formData: {},
rules: {
unitName: [{ required: true, message: "请输入单位", trigger: "blur" }],
address: [{ required: true, message: "请输入地点", trigger: "blur" }],
area: [{ required: true, message: "请输入面积", trigger: "blur" }],
facility: [{ required: true, message: "请输入设施", trigger: "blur" }],
openTime: [{ required: true, message: "请输入开放时间", trigger: "blur" }]
}
}
},
methods: {
onOpen(id) {
if (id) {
this.dialogVisible = true
this.resetForm()
$.post("/platform/buildHome/littleHouse/detail/" + id).then((resp) => {
if (resp.code === 0) {
this.formData = resp.data
}
})
} else {
this.dialogVisible = true
this.formData = {}
this.$nextTick(() => {
this.$refs.formRef.clearValidate()
})
}
},
resetForm() {
this.$nextTick(() => {
if (this.$refs.formRef) {
this.$refs.formRef.resetFields()
this.$refs.formRef.clearValidate()
}
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
$.post("/platform/buildHome/littleHouse/save", this.formData).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$emit("refresh")
this.dialogVisible = false
}
})
}
})
}
}
}
@@ -0,0 +1,78 @@
<!--#
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" class="mt10">
<table-tool label="数据列表">
<el-button type="primary" size="small" icon="el-icon-plus" @click="$refs.littleHouseFormRef.onOpen()">新增</el-button>
<el-button type="primary" size="small" icon="el-icon-download" @click="onExport">导出汇总表</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="单位" prop="unitName" sortable width="200px"></el-table-column>
<el-table-column label="活动场所基本情况">
<el-table-column label="地点" prop="address" sortable width="200px"></el-table-column>
<el-table-column label="面积" prop="area" sortable width="200px"></el-table-column>
<el-table-column label="设施" prop="facility" sortable></el-table-column>
<el-table-column label="开放时间" prop="openTime" sortable width="200px"></el-table-column>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="$refs.littleHouseFormRef.onOpen(row.id)">修改</el-button>
<el-button size="mini" type="danger" @click="onDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<little-house-form ref="littleHouseFormRef" @refresh="doSearch"></little-house-form>
</div>
<script nonce="${cspNonce!}">
<!--#include("form.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: { "little-house-form": form },
data() {
return {}
},
methods: {
onDelete(id) {
this.$confirm("确定删除吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
$.post("/platform/buildHome/littleHouse/delete/" + id).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
onExport() {
this.$downLoad("/platform/buildHome/littleHouse/exportXlsx")
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,366 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.container {
}
.alert {
padding: 15px;
background-color: #e8f4ff;
border-left: 4px solid var(--color-primary);
margin-bottom: 25px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
font-size: 15px;
animation: fadeIn 0.6s ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.alert i {
color: var(--color-primary);
margin-right: 8px;
}
.record-book {
background-color: white;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
overflow: hidden;
position: relative;
animation: slideUp 0.8s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.book-header {
background: linear-gradient(120deg, var(--color-primary), var(--color-primary-8));
color: white;
padding: 30px;
text-align: center;
position: relative;
overflow: hidden;
}
.book-header::before {
content: "";
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 70%);
pointer-events: none;
}
.header-title {
font-size: 36px;
font-weight: bold;
letter-spacing: 5px;
margin-bottom: 10px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
color: inherit;
}
.header-subtitle {
font-size: 18px;
letter-spacing: 2px;
opacity: 0.9;
}
.book-content {
padding: 30px 40px;
}
.section {
margin-bottom: 30px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 20px;
}
.section:last-child {
border-bottom: none;
margin-bottom: 0;
}
.section-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 20px;
color: var(--color-primary);
position: relative;
padding-left: 15px;
}
.section-title::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 5px;
height: 18px;
background-color: #1867b0;
border-radius: 3px;
}
.form-row {
display: flex;
flex-wrap: wrap;
margin-bottom: 15px;
gap: 20px;
}
.form-group {
flex: 1;
min-width: 200px;
}
.form-label {
display: block;
margin-bottom: 8px;
color: #555;
font-size: 15px;
}
.form-control {
width: 100%;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 15px;
transition: all 0.3s;
background-color: #f9fafc;
box-sizing: border-box;
}
.form-control:focus {
border-color: #1867b0;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
background-color: #fff;
outline: none;
}
.form-control:hover {
border-color: #1867b0;
}
.committee-members {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 15px;
}
.bottom-info {
margin-top: 30px;
display: flex;
justify-content: space-between;
gap: 20px;
}
.bottom-group {
flex: 1;
}
.notes {
font-size: 14px;
color: #888;
margin-top: 20px;
padding-top: 20px;
border-top: 1px dashed #ddd;
}
@media (max-width: 768px) {
.book-header {
padding: 20px;
}
.header-title {
font-size: 28px;
}
.book-content {
padding: 20px;
}
}
</style>
<div id="app" class="container" v-cloak>
<div class="alert">
<i class="fa fa-info-circle"></i>
提示:在机构信息页面维护后本页面会自动读取数据。
</div>
<div class="record-book">
<div class="book-header">
<h1 class="header-title">建家工作记录册</h1>
<div class="header-subtitle">工会组织基本信息</div>
</div>
<div class="book-content">
<div class="section">
<h2 class="section-title">分工会基本情况</h2>
<div class="form-row">
<div class="form-group">
<label class="form-label">分工会名称</label>
<input type="text" class="form-control" v-model="formData.unionName" readonly placeholder="请输入分工会名称" />
</div>
<!-- <div class="form-group">-->
<!-- <label class="form-label">填写时间</label>-->
<!-- <input type="date" class="form-control" v-model="formData.time" />-->
<!-- </div>-->
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">会员总数</label>
<input type="number" class="form-control" v-model="formData.memberNum" placeholder="请输入会员总数" />
</div>
<div class="form-group">
<label class="form-label">女教职工人数</label>
<input type="number" class="form-control" v-model="formData.femaleTeacherNum" placeholder="请输入女教职工人数" />
</div>
<div class="form-group">
<label class="form-label">工会小组数</label>
<input type="number" class="form-control" v-model="formData.unionGroupNum" placeholder="请输入工会小组数" />
</div>
</div>
</div>
<div class="section">
<h2 class="section-title">工会主要负责人</h2>
<div class="form-row">
<div class="form-group">
<label class="form-label">工会主席</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_CHAIRMAN" placeholder="请输入工会主席姓名" />
</div>
<div class="form-group">
<label class="form-label">副主席</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_VICE_CHAIRMAN" placeholder="请输入副主席姓名" />
</div>
</div>
</div>
<div class="section">
<h2 class="section-title">工会委员会成员</h2>
<div class="committee-members">
<div class="form-group" style="grid-column: 1 / -1">
<label class="form-label">工会委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">组织委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_ZUZHI_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">宣传委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_XUANCHUAN_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">女工委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_NVGONG_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">青年委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_QINGNIAN_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">文体委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_WENTI_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">生活委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_SHENGGHUO_WY" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label class="form-label">调解委员</label>
<input type="text" class="form-control" v-model="formData.BRANCH_UNION_TIAOJIE_WY" placeholder="请输入姓名" />
</div>
</div>
</div>
<div class="section">
<h2 class="section-title">工会小组</h2>
<div class="form-group">
<label class="form-label">工会小组长</label>
<input type="text" class="form-control" v-model="formData.groupLeaderNames" placeholder="请输入工会小组长姓名" />
</div>
</div>
<div class="section">
<h2 class="section-title">自评结果</h2>
<div class="form-row">
<div class="form-group">
<label class="form-label">自评分数</label>
<input type="number" class="form-control" v-model="formData.score" placeholder="请输入自评分数" />
</div>
<div class="form-group">
<label class="form-label">申报等级</label>
<input class="form-control" v-model="formData.level" readonly placeholder="自动根据自评分数计算" />
</div>
</div>
</div>
<div class="notes">
<i class="fas fa-pencil-alt"></i>
备注:本记录册是工会组织重要的基础资料,请认真填写并妥善保管。
</div>
<div class="export-container" style="text-align: center; margin-top: 30px">
<el-button icon="el-icon-download" type="primary" @click="exportDocx">导出记录册</el-button>
</div>
</div>
</div>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
data() {
return {
formData: {}
}
},
methods: {
initInfo() {
this.$axios.post("/platform/buildHome/logBook/info").then((res) => {
if (res.code === 0) {
this.formData = res.data
console.log(res.data)
} else {
this.$message.error(res.msg)
}
})
},
exportDocx() {
this.$downLoad("/platform/buildHome/logBook/exportDocx", this.formData)
}
},
created() {
this.initInfo()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,60 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<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" align="center" header-align="center" label="序号" type="index" width="80px"></el-table-column>
<el-table-column label="名称" prop="name" sortable></el-table-column>
<el-table-column label="年份" prop="year" sortable width="100px"></el-table-column>
<el-table-column label="开始时间" prop="startTime" sortable width="200px"></el-table-column>
<el-table-column label="结束时间" prop="endTime" sortable width="200px"></el-table-column>
<el-table-column label="填写状态" prop="materialId" width="100px">
<template scope="{row}">
<el-tag :type="row.materialId ? 'success' : 'danger'" size="mini">{{row.materialId ? '已填写' : '未填写'}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="$refs.materialInfoRef.onOpen(row.id,row.unionId)" v-if="row.materialId !== null">查看</el-button>
<el-button size="mini" type="primary" @click="$refs.materialWriteRef.onOpen(row.id)" v-if="row.materialId === null">
填写
</el-button>
<el-button size="mini" type="primary" @click="$refs.materialWriteRef.onOpen(row.id)" v-if="row.materialId !== null">
编辑
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<material-write ref="materialWriteRef"></material-write>
<material-info ref="materialInfoRef"></material-info>
</div>
<script nonce="${cspNonce!}">
<!--#include("write.js"){}#-->
<!--#include("./query/info.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"material-write": write,
"material-info": info
},
data() {
return {}
},
methods: {},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,85 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="评比事项">
<el-select v-model="pageForm.actId" placeholder="考核活动" clearable>
<el-option v-for="item in actOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="数据列表">
<el-button size="small" type="primary" icon="el-icon-download" @click="exportZip">导出汇总表</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="分工会名称" prop="unionName" sortable></el-table-column>
<el-table-column label="分工会编码" prop="unionCode" sortable></el-table-column>
<el-table-column label="填写状态" prop="isWrite">
<template scope="{row}">
<el-tag :type="row.isWrite ? 'success' : 'danger'" size="mini">{{row.isWrite ? '已填写' : '未填写'}}</el-tag>
</template>
</el-table-column>
<!-- <el-table-column label="建家记录册" prop="logBookFiles">-->
<!-- <template scope="{row}">{{row.logBookFiles}}</template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="自评表" prop="selfEvaluationFiles"></el-table-column>-->
<!-- <el-table-column label="小家汇总" prop="summaryFiles"></el-table-column>-->
<!-- <el-table-column label="年度工作总结和工作大事记录" prop="annualWorkSummaryFiles"></el-table-column>-->
<el-table-column label="操作" fixed="right" width="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="$refs.infoRef.onOpen(pageForm.actId,row.id)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<info ref="infoRef"></info>
</div>
<script nonce="${cspNonce!}">
<!--#include("info.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: { info },
data() {
return {
actOptions: [],
pageForm: {
actId: null
}
}
},
methods: {
listAct() {
this.$axios.get("/platform/buildHome/material/query/listAct").then((res) => {
if (res.code === 0) {
this.actOptions = res.data
if (this.actOptions.length > 0) {
this.$set(this.pageForm, "actId", this.actOptions[0].id)
this.doSearch()
}
}
})
},
exportZip(){
this.$downLoad('/platform/buildHome/material/query/exportZip', this.pageForm)
}
},
created() {
this.listAct()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,98 @@
const info = {
template: /*language=HTML*/ `
<el-dialog title="查看详情" :visible.sync="visible" width="50%">
<div class="upload-list">
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-book"></i>
建家记录册
</div>
<file-preview :files="viewData.logBookFiles" complete_result></file-preview>
</div>
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-bookmark"></i>
自评表
</div>
<file-preview :files="viewData.selfEvaluationFiles" complete_result></file-preview>
</div>
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-bar-chart"></i>
职工小家建设情况汇总
</div>
<file-preview :files="viewData.summaryFiles" complete_result></file-preview>
</div>
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-book"></i>
年度工作总结和工作大事记
</div>
<file-preview :files="viewData.annualWorkSummaryFiles" complete_result></file-preview>
</div>
</div>
</el-dialog>
`,
data() {
return {
viewData: {},
visible: false
}
},
methods: {
onOpen(actId, unionId) {
this.visible = true
this.$axios
.post("/platform/buildHome/material/query/infoByUnionId", {
actId,
unionId
})
.then((res) => {
if (res.code === 0) {
if(res.data){
this.viewData = res.data
}else{
this.viewData = {}
}
} else {
this.$message.error(res.msg)
}
})
}
},
style: /*language=CSS*/ `
.upload-list {
margin-bottom: 30px;
}
.upload-item {
border: 1px solid #eee;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
transition: all 0.3s;
}
.upload-item:hover {
border-color: #1867b0;
box-shadow: 0 2px 12px rgba(24, 103, 176, 0.1);
}
.upload-item-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
color: #000000;
display: flex;
align-items: center;
gap: 8px;
}
.upload-item-title i {
color: #1867b0;
}
`
}
@@ -0,0 +1,271 @@
const write = {
template: /*language=HTML*/ `
<el-dialog :title="dialogTitle" :visible.sync="visible" width="70%">
<div class="time-warning" v-if="activity && !isWithinTimeRange">
当前时间不在提交时间范围内,无法提交材料。提交时间:
{{ activity.startTime }} 至 {{ activity.endTime }}
</div>
<div class="upload-list">
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-book"></i>
建家记录册
</div>
<div class="upload-hint">
请到
<a href="/platform/buildHome/logBook" target="_blank">记录册填写页面</a>
,导出签字盖章后上传扫描件
</div>
<file-upload
:value.sync="formData.logBookFiles"
:upload_number="1"
upload_result_category="array"
complete_result
upload_text="选择文件"
upload_button_size="medium"
:disabled="!isWithinTimeRange"
></file-upload>
</div>
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-bookmark"></i>
自评表
</div>
<div class="upload-hint">
请到
<a href="/platform/buildHome/kpi/write" target="_blank">自评填写页面</a>
,填写完导出后签字盖章后上传扫描件
</div>
<file-upload
:value.sync="formData.selfEvaluationFiles"
:upload_number="1"
upload_result_category="array"
complete_result
upload_text="选择文件"
upload_button_size="medium"
:disabled="!isWithinTimeRange"
></file-upload>
</div>
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-bar-chart"></i>
职工小家建设情况汇总
</div>
<div class="upload-hint">
请到
<a href="/platform/buildHome/littleHouse" target="_blank">小家建设页面</a>
,填写完导出后签字盖章后上传扫描件
</div>
<file-upload
:value.sync="formData.summaryFiles"
:upload_number="1"
upload_result_category="array"
complete_result
upload_text="选择文件"
upload_button_size="medium"
:disabled="!isWithinTimeRange"
></file-upload>
</div>
<div class="upload-item">
<div class="upload-item-title">
<i class="fa fa-book"></i>
年度工作总结和工作大事记
</div>
<div class="upload-hint">请上传年度工作总结和工作大事记电子版</div>
<file-upload
:value.sync="formData.annualWorkSummaryFiles"
:upload_number="5"
upload_result_category="array"
complete_result
upload_text="选择文件"
upload_button_size="medium"
:disabled="!isWithinTimeRange"
></file-upload>
</div>
</div>
<div class="notice-box">
<i class="fa fa-exclamation-triangle"></i>
<strong>重要提示:</strong>
建家记录册、教职工之家建设考核评议自评表需由党委主要负责人签字盖章后扫描件上传
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="visible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit" :disabled="!isWithinTimeRange">提交评比材料</el-button>
</div>
</el-dialog>
`,
data() {
return {
visible: false,
dialogTitle: "评比材料提交",
activity: null,
actId: null,
formData: {
logBookFiles: [],
selfEvaluationFiles: [],
summaryFiles: [],
annualWorkSummaryFiles: []
}
}
},
computed: {
// 是否在活动时间范围内
isWithinTimeRange() {
if (!this.activity) return false
const now = new Date().getTime()
const startTime = new Date(this.activity.startTime).getTime()
const endTime = new Date(this.activity.endTime).getTime()
return now >= startTime && now <= endTime
}
},
methods: {
onOpen(id) {
this.visible = true
this.actId = id
this.$axios.post("/platform/buildHome/material/act", { actId: id }).then((res) => {
if (res.code === 0) {
this.activity = res.data
} else {
this.$message.error(res.msg)
}
})
this.$axios.post("/platform/buildHome/material/info", { actId: id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
} else {
this.$message.error(res.msg)
}
})
},
onSubmit() {
if (!this.isWithinTimeRange) {
this.$message.error("当前时间不在活动时间范围内,无法提交材料")
return
}
if (this.formData.logBookFiles.length === 0) {
this.$message.warning("请上传建家记录册")
return false
}
if (this.formData.selfEvaluationFiles.length === 0) {
this.$message.warning("请上传自评表")
return false
}
if (this.formData.summaryFiles.length === 0) {
this.$message.warning("请上传职工小家建设情况汇总")
return false
}
this.$axios
.post("/platform/buildHome/material/submit", { material: JSON.stringify(this.formData) })
.then((res) => {
if (res.code === 0) {
this.$message.success("提交成功")
this.visible = false
this.$emit("refresh")
} else {
this.$message.error(res.msg || "提交失败")
}
})
.catch((err) => {
console.error(err)
this.$message.error("提交失败")
})
}
},
style: /*language=CSS*/ `
.time-warning {
background-color: #fff1f0;
border: 1px solid #ffccc7;
border-left: 4px solid #ff4d4f;
padding: 12px 15px;
border-radius: 4px;
margin: 15px 0;
color: #cf1322;
}
.upload-list {
margin-bottom: 30px;
}
.upload-item {
border: 1px solid #eee;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
transition: all 0.3s;
}
.upload-item:hover {
border-color: #1867b0;
box-shadow: 0 2px 12px rgba(24, 103, 176, 0.1);
}
.upload-item-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
color: #000000;
display: flex;
align-items: center;
gap: 8px;
}
.upload-item-title i {
color: #1867b0;
}
.upload-hint {
background-color: #f0f7ff;
padding: 12px 15px;
border-radius: 4px;
font-size: 14px;
color: #555;
margin-bottom: 15px;
border-left: 3px solid #4189d6;
}
.upload-hint a {
color: #1867b0;
text-decoration: none;
font-weight: bold;
}
.upload-hint a:hover {
text-decoration: underline;
}
.notice-box {
background-color: #fff8e6;
border: 1px solid #ffe7a3;
border-left: 4px solid #ffbf00;
padding: 15px;
border-radius: 4px;
margin: 20px 0;
}
.notice-box i {
color: #ffbf00;
margin-right: 8px;
}
.dialog-footer .el-button--primary:disabled {
background: #cccccc;
border-color: #cccccc;
cursor: not-allowed;
}
`
}
@@ -0,0 +1,512 @@
const formEdit = {
template: /*language=HTML*/ `
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible="visible" width="70%" :close-on-click-modal="false" :before-close="handleClose">
<el-steps :active="activeStep" finish-status="success" simple>
<el-step title="基础信息"></el-step>
<el-step title="名额设置"></el-step>
</el-steps>
<!-- Step 1: 基础信息 -->
<div v-show="activeStep === 0">
<el-form :model="formData" ref="form" :rules="formRules" label-width="120px" class="form-container">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="活动名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入活动名称" maxlength="50"
show-word-limit>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="activityGroupId" label="可报名人员范围">
<div style="display: flex; justify-content: space-between">
<div style="width: 99%">
<el-select prop="groupId" placeholder="参加人员范围"
v-model="formData.activityGroupId"
style="width: 99%;"
clearable
filterable>
<el-option v-for="item in activityGroupList"
:label="item.groupName"
:value="item.groupId"
:key="item.groupId"
></el-option>
</el-select>
</div>
<div>
<el-button
@click="$refs.drawerUserScope.userScopeDialog = true"
type="primary">设置
</el-button>
</div>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="报名开始时间" prop="signUpStartTime">
<el-date-picker v-model="formData.signUpStartTime" type="datetime"
placeholder="请选择报名开始时间"
value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报名结束时间" prop="signUpEndTime">
<el-date-picker v-model="formData.signUpEndTime" type="datetime"
placeholder="请选择报名结束时间"
value-format="yyyy-MM-dd HH:mm:ss" 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="活动开始时间" 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-col>
<el-col :span="12">
<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-col>
</el-row>
<el-form-item label="通知内容" prop="notice">
<text-editor v-model="formData.notice"></text-editor>
</el-form-item>
</el-form>
</div>
<!-- Step 2: 名额设置 -->
<div v-show="activeStep === 1">
<el-form :model="formData" ref="quotaForm" :rules="formRules" label-width="120px"
class="form-container">
<el-form-item label="名额分配" prop="quotas">
<div class="quota-summary" v-if="formData.quotas.length > 0">
<span>总名额:<span class="quota-count"
style="margin-right: 0;">{{ totalQuota }}</span></span>
<span>已设置:<span class="quota-count" style="margin-right: 0;">{{ allocatedQuota }}</span> / {{ formData.quotas.length }}</span>
<span>未设置:<span class="quota-count quota-unset">{{ formData.quotas.length - allocatedQuota }}</span></span>
</div>
<el-table :data="formData.quotas"
border
style="width: 100%"
max-height="450px"
>
<el-table-column label="序号" width="80" align="center" type="index"></el-table-column>
<el-table-column label="工会名称" prop="name"></el-table-column>
<el-table-column label="名额数量" width="200" align="center">
<template slot-scope="scope">
<el-input-number v-model="scope.row.num" :min="0" :controls="false"
placeholder="请输入名额数量"
style="width: 100%"
@change="handleQuotaChange(scope.row)">
</el-input-number>
</template>
</el-table-column>
</el-table>
<div class="quota-actions">
<el-button type="primary" size="mini" @click="setAllQuotas">批量设置名额</el-button>
<el-button size="mini" @click="clearAllQuotas">清除全部名额</el-button>
</div>
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button @click="prevStep" v-if="activeStep > 0">
<i class="el-icon-arrow-left"></i> 上一步
</el-button>
<el-button type="primary" @click="nextStep" v-if="activeStep < 1">
下一步 <i class="el-icon-arrow-right"></i>
</el-button>
<el-button type="primary" @click="submitForm" :loading="submitting" v-if="activeStep === 1">
{{ submitting ? '提交中...' : '确定' }}
</el-button>
</div>
<drawer-user-scope
@group_change="getActivityGroup"
ref="drawerUserScope"
:group_id.sync="formData.activityGroupId"
></drawer-user-scope>
</el-dialog>
`,
components: {
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue")
},
data() {
// 日期验证器
const validateDateRange = (rule, value, callback) => {
const { signUpStartTime, signUpEndTime, startTime, endTime } = this.formData
if (rule.field === "signUpEndTime" && signUpStartTime && signUpEndTime) {
if (new Date(signUpEndTime) <= new Date(signUpStartTime)) {
callback(new Error("报名结束时间必须晚于报名开始时间"))
return
}
}
if (rule.field === "startTime" && signUpEndTime && startTime) {
if (new Date(startTime) <= new Date(signUpEndTime)) {
callback(new Error("活动开始时间必须晚于报名结束时间"))
return
}
}
if (rule.field === "endTime" && startTime && endTime) {
if (new Date(endTime) <= new Date(startTime)) {
callback(new Error("活动结束时间必须晚于活动开始时间"))
return
}
}
callback()
}
return {
visible: false,
activeStep: 0,
submitting: false,
activityGroupList: [],
formData: {
quotas: []
},
batchQuotaDialogVisible: false,
batchQuotaValue: 0,
formRules: {
name: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{ min: 1, max: 50, message: "长度在 1 到 50 个字符", trigger: "blur" }
],
signUpStartTime: [{ required: false, message: "请选择报名开始时间", trigger: "blur" }],
signUpEndTime: [
{ required: false, message: "请选择报名结束时间", trigger: "blur" },
{ validator: validateDateRange, trigger: "blur" }
],
startTime: [
{ required: false, message: "请选择活动开始时间", trigger: "blur" },
{ validator: validateDateRange, trigger: "blur" }
],
endTime: [
{ required: false, message: "请选择活动结束时间", trigger: "blur" },
{ validator: validateDateRange, trigger: "blur" }
],
notice: [{ required: true, message: "请输入通知内容", trigger: "blur" }],
quotas: [{ required: true, type: "array", message: "请设置名额分配", trigger: "change" }]
},
unionOptions: []
}
},
computed: {
// 计算总名额
totalQuota() {
return this.formData.quotas.reduce((sum, quota) => {
// 只计算已明确设置了数值的项
if (quota.num !== null && quota.num !== undefined) {
return sum + parseInt(quota.num || 0)
}
return sum
}, 0)
},
// 已分配名额数量(不包括未设置的)
allocatedQuota() {
return this.formData.quotas.filter((q) => q.num !== null && q.num !== undefined).length
}
},
methods: {
async getActivityGroup() {
const { data } = await $.get("/platform/activity/basic/scope/getActivityUserScopeGroup")
this.activityGroupList = data
},
// 处理关闭弹窗
handleClose() {
this.visible = false;
},
// 检查名额是否未设置
isQuotaUnset(value) {
return value === null || value === undefined
},
// 处理名额变更
handleQuotaChange(row) {
// 确保值转换为数字或null
if (row.num === "" || row.num === undefined) {
row.num = null
} else {
row.num = parseInt(row.num)
}
this.validateQuotas()
},
// 批量设置名额
setAllQuotas() {
this.$prompt("请输入要批量设置的名额数量", "批量设置", {
confirmButtonText: "确定",
cancelButtonText: "取消",
inputType: "number",
inputValidator: (value) => {
if (value === "") return "名额不能为空"
if (parseInt(value) < 0) return "名额不能为负数"
return true
}
})
.then(({ value }) => {
const num = parseInt(value)
this.formData.quotas.forEach((q) => {
q.num = num
})
this.validateQuotas()
this.$message.success("已将所有工会名额设置为" + num)
})
.catch(() => {})
},
// 清除所有名额
clearAllQuotas() {
this.$confirm("确定要清除所有名额设置吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.formData.quotas.forEach((q) => {
q.num = undefined
})
this.validateQuotas()
this.$message.success("已清除所有名额设置")
})
.catch(() => {})
},
// 打开表单
onOpen(id) {
this.visible = true
this.activeStep = 0
this.formData = {
quotas: []
}
if (id) {
// 如果是编辑模式,加载数据
this.$axios.post("/platform/cadreTraining/activity/get", { id: id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
} else {
this.$businessTool.listUnion().then((res) => {
this.unionOptions = res
this.formData.quotas = res.map((item) => ({
id: item.id,
name: item.name,
code: item.code,
num: undefined // 默认名额为null(未设置)
}))
})
}
},
// 上一步
prevStep() {
if (this.activeStep > 0) {
this.activeStep--
}
},
// 下一步
nextStep() {
const formRefs = [this.$refs.form, this.$refs.quotaForm]
const currentForm = formRefs[this.activeStep]
currentForm.validate((valid) => {
if (valid) {
if (this.activeStep < 1) {
this.activeStep++
}
} else {
this.$message.warning("请完成必填项")
}
})
},
// 验证名额
validateQuotas() {
this.$refs.quotaForm && this.$refs.quotaForm.validateField("quotas")
},
// 提交表单
submitForm() {
// 验证所有表单
Promise.all([
new Promise((resolve) => this.$refs.form.validate((valid) => resolve(valid))),
new Promise((resolve) => this.$refs.quotaForm.validate((valid) => resolve(valid)))
]).then((results) => {
if (results.every((valid) => valid)) {
const invalidQuota = this.formData.quotas.some((q) => {
// 只检查已设置了值的,未设置的不检查
if (q.num !== null && q.num !== undefined) {
return q.num < 0 || !Number.isInteger(parseInt(q.num))
}
return false
})
if (invalidQuota) {
this.$message.error("请填写有效的名额数量(非负整数)")
return
}
// 检查是否所有名额都未设置
if (this.allocatedQuota === 0) {
this.$confirm("当前所有工会名额均未设置,是否继续提交?", "提示", {
confirmButtonText: "继续提交",
cancelButtonText: "返回修改",
type: "warning"
})
.then(() => {
this.doSubmit()
})
.catch(() => {})
return
}
this.doSubmit()
} else {
// 切换到第一个验证失败的步骤
if (!results[0]) this.activeStep = 0
else if (!results[1]) this.activeStep = 1
}
})
},
// 执行提交操作
doSubmit() {
this.submitting = true
this.$axios
.post("/platform/cadreTraining/activity/" + (this.formData.id ? "update" : "insert"), { cadreTrainingAct: JSON.stringify(this.formData) })
.then((res) => {
if (res.code === 0) {
this.visible = false
this.$message.success(res.msg)
this.$emit("refresh")
}
})
.finally(() => {
this.submitting = false
})
}
},
async created() {
await this.getActivityGroup()
},
style: /*language=CSS*/ `
.form-container {
padding: 0 50px;
margin-top: 20px;
margin-bottom: 20px;
}
.batch-container {
background-color: #fff;
border-radius: 4px;
width: 100%;
}
.empty-batch {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 0;
background-color: #fafafa;
border: 1px dashed #d9d9d9;
border-radius: 4px;
}
.empty-icon {
font-size: 48px;
color: #909399;
margin-bottom: 15px;
}
.empty-text {
color: #909399;
font-size: 16px;
margin-bottom: 15px;
}
.empty-action {
margin-top: 5px;
}
.no-data {
text-align: center;
color: #909399;
padding: 20px 0;
}
.quota-summary {
display: flex;
margin-bottom: 15px;
background: #f8f8f8;
padding: 10px 15px;
border-radius: 4px;
}
.quota-summary span {
margin-right: 20px;
color: #606266;
}
.quota-count {
font-weight: bold;
color: #409EFF;
padding: 0 5px;
}
.quota-unset {
color: #E6A23C;
}
.quota-status {
font-size: 12px;
margin-top: 5px;
text-align: center;
}
.quota-unset-tip {
color: #E6A23C;
}
.quota-zero-tip {
color: #F56C6C;
}
.quota-set-tip {
color: #67C23A;
}
.quota-actions {
margin-top: 15px;
text-align: right;
}
/* 按钮样式优化 */
.el-button [class*="el-icon-"] + span {
margin-left: 5px;
}
`
}
@@ -0,0 +1,84 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="请选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></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="mini" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
</table-tool>
<el-table :data="tableData">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="name" label="名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="signUpStartTime" label="报名开始时间"></el-table-column>
<el-table-column prop="signUpEndTime" label="报名结束时间"></el-table-column>
<el-table-column prop="startTime" label="开始时间"></el-table-column>
<el-table-column prop="endTime" label="结束时间"></el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
<el-button size="mini" type="danger" @click="onDelete(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",
mixins: [initTableMixins],
components: {
"form-edit": formEdit
},
data() {
return {}
},
methods: {
openAdd() {
this.$refs.formEditRef.onOpen()
},
openEdit(row) {
this.$refs.formEditRef.onOpen(row.id)
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const { code, msg } = await this.$axios.post("/platform/cadreTraining/activity/delete", { id: id })
if (code === 0) {
this.$message.success(msg)
this.doSearch()
}
})
.catch(() => {})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,176 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
v-model="pageForm.year"
type="year"
:clearable="false"
value-format="yyyy"
placeholder="请选择年度"
style="width: 100%"
@change="getActivityByYear">
</el-date-picker>
</search-item>
<search-item label="活动名称">
<el-select v-model="pageForm.activityId" placeholder="请选择活动名称" clearable style="width: 100%" @change="doSearch">
<el-option v-for="item in activityList"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch"></el-input>
</search-item>
<search-item label="性别">
<el-select v-model="pageForm.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="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择所属单位" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button @click="onExport" icon="el-icon-s-promotion" type="primary" size="small">导出</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="name" label="活动名称"></el-table-column>
<el-table-column prop="applyTime" label="报名时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="$auth.hasRole('SYSADMIN')" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<cadre-training-info ref="cadreTrainingInfoRef"></cadre-training-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
//分页数据
mixins: [initTableMixins],
components: {
"cadre-training-info": cadreTrainingInfo,
},
data() {
return {
pageDataUrl: "/platform/cadreTraining/collect/pageData",
unionOptions: [],
unitOptions: [],
userOptions: [],
activityList: [],
currentYear: new Date().getFullYear(),
pageForm: {
year: new Date().getFullYear() + "",
activityId: "",
userName: "",
sex: "",
unionId: "",
unitId: ""
}
}
},
methods: {
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.cadreTrainingInfoRef.onOpen(row)
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/cadreTraining/collect/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
onExport() {
this.$downLoad('/platform/cadreTraining/collect/onExport', this.pageForm)
},
// 根据年度获取活动列表
async getActivityByYear() {
const res = await this.$axios.post("/platform/cadreTraining/collect/getActivityList", {
year: this.pageForm.year
});
if (res.code === 0) {
this.activityList = res.data;
// 默认选中最新的活动(第一个)
if (res.data && res.data.length > 0) {
this.pageData()
} else {
this.pageForm.activityId = ""; // 数据为空时设为空字符串
}
}
}
},
async created() {
// 获取当前年度的活动列表
await this.getActivityByYear();
// 获取工会和单位列表
this.$businessTool.listUnion().then((res) => (this.unionOptions = res));
this.$businessTool.listUnit().then((res) => (this.unitOptions = res));
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,114 @@
const cadreTrainingInfo = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
报名信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<table-tool label="活动信息"></table-tool>
<el-descriptions :column="2" border class="flow-task-form">
<el-descriptions-item label="活动名称" :span="2">{{viewData.name}}</el-descriptions-item>
<el-descriptions-item label="报名开始时间">{{viewData.signUpStartTime}}</el-descriptions-item>
<el-descriptions-item label="报名结束时间">{{viewData.signUpEndTime}}</el-descriptions-item>
<el-descriptions-item label="活动开始时间">{{viewData.startTime}}</el-descriptions-item>
<el-descriptions-item label="活动结束时间" >{{viewData.endTime}}</el-descriptions-item>
<el-descriptions-item label="活动内容" > <div v-html="viewData.notice"></div></el-descriptions-item>
</el-descriptions>
<table-tool label="人员信息"></table-tool>
<el-descriptions :column="2" border class="flow-task-form">
<el-descriptions-item label="姓名">{{viewData.userName}}</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.sex}}</el-descriptions-item>
<el-descriptions-item label="手机号">{{viewData.mobile}}</el-descriptions-item>
<el-descriptions-item label="备注">{{viewData.remark}}</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
}}({{task.ext.initiatorAccount}})
</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName
}}({{task.taskFormData.loginName}})
</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" :span="3" v-if="!task.ext.isFirstTaskNode">{{
task.taskFormData.opinion }}
</el-descriptions-item>
<el-descriptions-item label="签字" :span="3" v-if="!task.ext.isFirstTaskNode">
<el-image :src="task.ext.tf_userSign"
v-if="task.ext.tf_userSign"
class="signature-image"></el-image>
<span v-else>暂无</span>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
store,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
visible: false,
viewData: {},
doneTasks: [],
row: null
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
this.getDoneTasks()
},
// 获取申请信息
getInfo() {
this.viewData = { ...this.row };
// this.$axios.post('/platform/cadreTraining/activity/get', {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,115 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></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></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="name" label="活动名称"></el-table-column>
<el-table-column prop="applyTime" label="报名时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.instanceState != 20" @click="onCancelSignUp(row)" size="mini" type="danger">取消报名</el-button>
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<cadre-training-info ref="cadreTrainingInfoRef"></cadre-training-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('/platform/zhgh/dayofficework/cadreTraining/common/info.js'){}#-->
new Vue({
el: "#app",
store,
//分页数据
mixins: [initTableMixins],
components: {
"cadre-training-info": cadreTrainingInfo,
},
data() {
return {
pageDataUrl: "/platform/cadreTraining/mine/pageData",
unionOptions: [],
unitOptions: [],
userOptions: [],
}
},
methods: {
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.cadreTrainingInfoRef.onOpen(row)
})
},
// 取消报名(原撤回功能)
onCancelSignUp(row) {
this.$confirm("您确定要取消报名吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
try {
// 执行撤回操作
if (row.startTaskId) {
const revokeRes = await this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId});
if (revokeRes.code !== 0) {
this.$message.error(revokeRes.msg || "撤回失败");
return;
}
}
// 执行删除操作
const deleteRes = await this.$axios.post("/platform/cadreTraining/mine/delete", {id: row.id});
if (deleteRes.code === 0) {
this.$message.success("取消报名成功");
this.pageData();
} else {
this.$message.error(deleteRes.msg || "取消报名失败");
}
} catch (error) {
this.$message.error("操作失败");
}
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,247 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="请选择年度"
style="width: 100%"
@change="getActivityByYear">
</el-date-picker>
</search-item>
<search-item label="活动名称">
<el-select v-model="pageForm.activityId" placeholder="请选择活动名称" clearable style="width: 100%" @change="doSearch">
<el-option v-for="item in activityList"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch"></el-input>
</search-item>
<search-item label="性别">
<el-select v-model="pageForm.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="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择所属单位" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="name" label="活动名称"></el-table-column>
<el-table-column prop="applyTime" label="报名时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskState === 10" @click="openAudit(row)" size="mini" type="primary">审核
</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<cadre-training-info ref="cadreTrainingInfoRef">
<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-item label="电子签名" prop="tf_userSign" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</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>
</cadre-training-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
//分页数据
mixins: [initTableMixins],
components: {
"cadre-training-info": cadreTrainingInfo
},
data() {
return {
pageDataUrl: "/platform/cadreTraining/schoolAudit/pageData",
pageForm: {
approval: false,
year: new Date().getFullYear() + "", // 添加年份默认值
activityId: "", // 添加活动ID
userName: "",
sex: "",
unionId: "",
unitId: ""
},
formData: {},
showApprovalForm: false,
unionOptions: [],
unitOptions: [],
userOptions: [],
activityList: [] // 添加活动列表
}
},
methods: {
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.cadreTrainingInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.view(()=>{
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.cadreTrainingInfoRef.onOpen(row)
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
// 根据年度获取活动列表
async getActivityByYear() {
if (!this.pageForm.year) {
this.activityList = [];
this.pageForm.activityId = "";
return;
}
try {
const res = await this.$axios.post("/platform/cadreTraining/collect/getActivityList", {
year: parseInt(this.pageForm.year)
});
if (res.code === 0) {
this.activityList = res.data;
// 如果当前选中的活动不在新列表中,清空选择
if (this.pageForm.activityId && !res.data.some(item => item.id === this.pageForm.activityId)) {
this.pageForm.activityId = "";
}
this.doSearch();
}
} catch (error) {
console.error("获取活动列表失败:", error);
this.activityList = [];
this.pageForm.activityId = "";
}
},
// 添加搜索方法
doSearch() {
this.pageData();
}
},
created() {
// 初始化获取活动列表
this.getActivityByYear();
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
//单位查询
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,147 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="请选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></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 label="活动列表">
<el-radio-group v-model="pageForm.isEnrolled" @change="doSearch" size="mini" class="ml10">
<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">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="name" label="名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="signUpStartTime" label="报名开始时间">
<template slot-scope="{row}">{{ formatDate(row.signUpStartTime) }}</template>
</el-table-column>
<el-table-column prop="signUpEndTime" label="报名结束时间">
<template slot-scope="{row}">{{ formatDate(row.signUpEndTime) }}</template>
</el-table-column>
<el-table-column prop="startTime" label="开始时间">
<template slot-scope="{row}">{{ formatDate(row.startTime) }}</template>
</el-table-column>
<el-table-column prop="endTime" label="结束时间">
<template slot-scope="{row}">{{ formatDate(row.endTime) }}</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="{row}">
<el-tag :type="getStatusType(row)" size="mini">{{ getStatusText(row) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<template slot-scope="{row}">
<el-button
size="mini"
type="primary"
@click="openSign(row)"
v-if="getStatusText(row) === '报名中'">
报名
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<sign-form ref="signFormRef" @refresh="doSearch"></sign-form>
</div>
<script nonce="${cspNonce!}">
<!--#include("signForm.js"){}#-->
<!--#include('/platform/zhgh/dayofficework/cadreTraining/common/info.js'){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"cadre-training-info": cadreTrainingInfo,
"sign-form": signForm
},
data() {
return {
pageForm: {
isEnrolled: false,
year: new Date().getFullYear().toString(),
searchKeyword: ""
},
now: new Date().getTime()
}
},
methods: {
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.cadreTrainingInfoRef.onOpen(row)
})
},
doSearch() {
this.now = new Date().getTime()
this.pageData()
},
openSign(row) {
this.$refs.signFormRef.onOpen(row)
},
viewDetail(row) {},
// 格式化时间
formatDate(dateStr) {
if (!dateStr) return "-"
return dateStr.substring(0, 16).replace("T", " ")
},
// 获取活动状态
getStatusText(row) {
const now = this.now
const signUpStartTime = row.signUpStartTime ? new Date(row.signUpStartTime).getTime() : 0
const signUpEndTime = row.signUpEndTime ? new Date(row.signUpEndTime).getTime() : 0
const startTime = row.startTime ? new Date(row.startTime).getTime() : 0
const endTime = row.endTime ? new Date(row.endTime).getTime() : 0
if (now < signUpStartTime) {
return "未开始"
} else if (now >= signUpStartTime && now <= signUpEndTime) {
return "报名中"
} else if (now > signUpEndTime && now < startTime) {
return "报名结束"
} else if (now >= startTime && now <= endTime) {
return "活动中"
} else {
return "已结束"
}
},
// 获取状态标签类型
getStatusType(row) {
const status = this.getStatusText(row)
switch (status) {
case "未开始":
return "info"
case "报名中":
return "success"
case "报名结束":
return "warning"
case "活动中":
return "primary"
case "已结束":
return ""
default:
return ""
}
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,291 @@
const signForm = {
template: /*language=HTML*/ `
<el-dialog title="活动报名" :visible.sync="dialogVisible" width="70%" @open="handleDialogOpen">
<div class="process-title">
<snaker-start slot="header" define_key="GBPX" label="活动报名"></snaker-start>
</div>
<el-descriptions :column="2" border class="margin-top" style="margin: 10px" title="">
<el-descriptions-item label="活动名称">
<span class="item-center"> {{ viewData.name }}</span>
</el-descriptions-item>
<el-descriptions-item label="分工会名额">
{{ quota }}人 / 剩余: {{ remainingQuota }}人
</el-descriptions-item>
<el-descriptions-item label="报名开始时间">
{{ viewData.signUpStartTime }}
</el-descriptions-item>
<el-descriptions-item label="报名结束时间">
{{ viewData.signUpEndTime }}
</el-descriptions-item>
<el-descriptions-item label="开始时间">
{{ viewData.startTime }}
</el-descriptions-item>
<el-descriptions-item label="结束时间">
{{ viewData.endTime }}
</el-descriptions-item>
<el-descriptions-item label="活动内容" span="2">
<div v-html="viewData.notice"></div>
</el-descriptions-item>
</el-descriptions>
<!-- 个人报名信息 -->
<div class="process-title">选择报名人员</div>
<el-select
v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_ADMIN')"
v-model="searchTeammateUserId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="queryTeammate">
<el-option
v-for="item in teammateOptions"
:key="item.userId"
:label="item.userName + '(' + item.loginName + ')'"
:value="item.userId">
</el-option>
</el-select>
<el-button
v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_ADMIN')"
class="ml5" type="primary" icon="el-icon-plus"
@click="addTeamUser">添加
</el-button>
<el-table :data="teamUsers" class="mt10">
<el-table-column label="序号" type="index" width="60px"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unionName" label="分工会"></el-table-column>
<el-table-column prop="unitName" label="单位"></el-table-column>
<el-table-column prop="mobile" label="手机号"></el-table-column>
<el-table-column prop="remark" label="备注">
<template slot-scope="scope">
<el-input v-model="scope.row.remark" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="100px">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="removeTeamUser(scope.$index)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-row type="flex" justify="end" class="mt20">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="onConfirm" :loading="submitLoading"
:disabled="teamUsers.length === 0 ">确认报名
</el-button>
</el-row>
</el-dialog>
`,
store,
data() {
return {
//搜索框
searchTeammateUserId: null,
teammateOptions: [],
dialogVisible: false,
viewData: {},
id: null,
//表格用户(实际上只包含当前用户)
teamUsers: [],
quota: 0, // 报名名额限制
signedUsers: [], // 已报名人员列表
submitLoading: false, // 提交按钮加载状态
isSignUp: false // 是否已报名
}
},
computed: {
remainingQuota() {
// 如果 quota 为 null 或 undefined,显示"不限"
if (this.quota == null || this.quota === 0) return "不限"
// 如果 quota 为具体数值(包括0),则计算剩余名额
const remaining = Math.max(0, this.quota - this.signedUsers.length)
return remaining
},
},
methods: {
onOpen(row) {
this.row = row
this.dialogVisible = true
this.id = row.id;
},
handleDialogOpen() {
this.getActivityInfo()
this.getQuota(this.id)
this.loadUserData()
},
//查询队友信息
queryTeammate(val) {
if (val) {
this.$axios.post("/platform/cadreTraining/branchUnionSignUp/queryTeammate", {
keyword: val,
tissueId: this.id,
}).then((res) => {
if (res.code === 0) {
res.data.map(v => v.applyUserId = this.$store.state.user.id)
this.teammateOptions = res.data
}
})
}
},
//添加队友
addTeamUser() {
if (!this.searchTeammateUserId) {
this.$message.error("请先选择后再添加")
return
}
if (this.teamUsers.some((v) => v.userId === this.searchTeammateUserId)) {
this.$message.error("请勿重复添加")
return
}
if (this.quota > 0 && (this.signedUsers.length + this.teamUsers.length) >= this.quota) {
this.$message.error("已达到报名人数上限")
return
}
this.teamUsers.push(this.teammateOptions.find((v) => v.userId === this.searchTeammateUserId))
this.searchTeammateUserId = null
},
//移除队友
removeTeamUser(index) {
this.teamUsers.splice(index, 1)
},
// 加载用户数据
async loadUserData() {
try {
// 获取已报名人员
const signedResponse = await this.$axios.post("/platform/cadreTraining/branchUnionSignUp/listSignUser", { activityId: this.id })
if (signedResponse.code === 0) {
this.signedUsers = Array.isArray(signedResponse.data) ? signedResponse.data : []
// 检查当前用户是否已报名
const currentUser = this.signedUsers.find(user => user.userId === this.$store.state.user.id)
this.isSignUp = !!currentUser
// 显示当前用户信息
if (currentUser) {
this.teamUsers = this.signedUsers;
} else {
// 如果当前用户未报名,显示当前用户信息用于报名
this.teamUsers = [{
userId: this.$store.state.user.id,
userName: this.$store.state.user.username,
loginName: this.$store.state.user.loginname,
unitId: this.$store.state.user?.unit?.id,
unitName: this.$store.state.user?.unit?.name,
unionId: this.$store.state.user?.union?.id,
unionName: this.$store.state.user?.union?.name,
sex: this.$store.state.user.sex,
mobile: this.$store.state.user.mobile,
remark: ''
}]
}
}
} catch (error) {
this.$message.error("获取用户数据失败")
}
},
// 获取名额限制
async getQuota(id) {
try {
const { code, data } = await this.$axios.post("/platform/cadreTraining/branchUnionSignUp/quota", { activityId: id })
if (code === 0) {
this.quota = data
}
} catch (error) {
this.$message.error("获取名额限制失败")
}
},
//活动信息
getActivityInfo() {
this.$axios.post("/platform/cadreTraining/activity/get", {id: this.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
//提交报名
async onConfirm() {
// 检查是否已报名(仅当当前用户已报名时)
if (this.isSignUp && this.teamUsers.some(user => user.userId === this.$store.state.user.id)) {
this.$message.warning("您已报名该活动!")
return
}
// 检查是否有报名人员
if (this.teamUsers.length === 0) {
this.$message.warning("请至少添加一名报名人员!")
return
}
// 检查名额是否足够
if (this.quota > 0 && (this.signedUsers.length + this.teamUsers.length) > this.quota) {
// 添加空值检查
const remaining = this.quota ? this.quota - this.signedUsers.length : 0;
this.$message.warning('报名人数超过限额!当前还可报名' + remaining + '人');
return;
}
try {
this.submitLoading = true;
this.$confirm('您确定要为' + this.teamUsers.length + '人报名吗?', "提示", { confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
try {
// 构造报名数据数组
const signUpDataArray = this.teamUsers.map(user => {
return {
cadreTrainingActId: this.id,
userId: user.userId,
userName: user.userName,
loginName: user.loginName,
unitId: user.unitId,
unitName: user.unitName,
unionId: user.unionId,
unionName: user.unionName,
sex: user.sex,
mobile: user.mobile,
remark: user.remark || ''
}
})
const { code, msg } = await this.$axios.post('/platform/cadreTraining/branchUnionSignUp/submit', {
data: JSON.stringify(signUpDataArray)
})
if (code === 0) {
this.$message.success("报名成功")
// 更新状态
this.isSignUp = true
this.dialogVisible = false
this.$emit("refresh", null)
} else {
this.$message.error(msg || "报名失败")
}
} catch (error) {
this.$message.error("操作失败")
} finally {
this.submitLoading = false;
}
}).catch(() => {
this.submitLoading = false;
})
} catch (error) {
this.$message.error("操作失败")
this.submitLoading = false;
}
}
}
}
@@ -0,0 +1,495 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-collapse-item__arrow {
visibility: hidden;
}
.top_block {
width: 100%;
padding: 30px 80px;
}
.tr {
text-align: right;
box-sizing: border-box;
}
.tl {
text-align: left;
box-sizing: border-box;
}
.top_title {
font-size: 14px;
color: #808492;
}
.fs18 {
font-size: 18px;
}
.fs26 {
font-size: 26px;
}
.fs20 {
font-size: 20px;
}
.title {
font-size: 18px;
height: 36px;
line-height: 36px;
}
.none-data {
min-height: 300px;
background: url("/none.png") no-repeat center center;
background-size: 360px 260px;
}
.none-data-title {
position: absolute;
display: block;
width: 100%;
text-align: center;
bottom: 20%;
left: 0;
color: rgb(160, 160, 160);
}
.item-title {
color: rgb(160, 160, 160);
}
.item-content {
color: rgb(100, 100, 100);
}
.mb20 {
margin-bottom: 20px;
}
.item-type {
width: 100%;
height: 100%;
text-align: center;
height: 100px;
line-height: 100px;
}
.el-collapse, .el-collapse-item__header, .el-collapse-item__wrap {
border: none;
}
.el-collapse-item__content {
padding-bottom: 0;
}
.status {
text-align: center;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
height: 90px;
width: 100%;
}
.status-icon {
width: 60px;
height: 60px;
}
.status-name {
height: 30px;
line-height: 30px;
font-size: 12px;
color: rgb(180, 180, 180);
}
.chartTitle {
font-size: 14px;
color: #808492;
margin: 20px 0;
}
</style>
<div id="app" v-cloak>
<div class="p10">
<el-card shadow="never">
<el-row style="border-bottom: 10px solid rgb(240,240,240);padding: 20px;">
<template>
<span style="font-weight: bold">查找用户:</span>
<el-select
style="width: 300px"
v-model="userid"
filterable
remote
reserve-keyword
placeholder="请输入姓名或工号进行查询"
:remote-method="remoteMethod"
:loading="search_user_loading" @change="userChange">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.username+''+item.loginname+''"
:value="item.id">
</el-option>
</el-select>
</template>
<div class="pull-right offscreen-right mt5">
<div class="btn-group tool-button mt5">
<span style="font-weight: bold">{{user.sex?user.sex:''}}{{user.unitName?' / '+user.unitName:''}} {{user.unionName?' / '+user.unionName:''}}</span>
</div>
</div>
</el-row>
<div class="top_block" style="border-bottom: 10px solid rgb(240,240,240);" v-loading="top_block_loading">
<el-row style="height: 40px">
<el-col :offset="4" class="tr" :span="3">
<span class="top_title">职工慰问申请数</span>
</el-col>
<el-col :span="4" class="tr">
<span class="top_title">困难帮扶申请数</span>
</el-col>
<el-col :span="4" class="tr">
<span class="top_title">子女入学登记数</span>
</el-col>
<el-col :span="4" class="tr">
<span class="top_title">撰写提案数</span>
</el-col>
<!--<el-col :span="3" class="tr">
<span class="top_title">&lt;!&ndash;参与活动数&ndash;&gt;</span>
</el-col>-->
<el-col :span="3" class="tr">
<span class="top_title">经费报销次数</span>
</el-col>
</el-row>
<el-row style="height: 60px;line-height: 60px">
<el-col class="tl" :span="4">
<span class="top_title">今年</span>
</el-col>
<el-col class="tr" :span="4">
<span class="fs26"
style="color: #409EFF;">{{numData.now_year.zgww?numData.now_year.zgww:0}}</span>
</el-col>
<el-col class="tr" :span="4">
<span class="fs26"
style="color: #409EFF;">{{numData.now_year.knbf?numData.now_year.knbf:0}}</span>
</el-col>
<el-col class="tr" :span="4">
<span class="fs26"
style="color: #409EFF;">{{numData.now_year.znrx?numData.now_year.znrx:0}}</span>
</el-col>
<el-col class="tr" :span="3">
<span class="fs26" style="color: #409EFF;">{{numData.now_year.ta?numData.now_year.ta:0}}</span>
</el-col>
<!--<el-col class="tr" :span="3">
<span class="fs26" style="color: #409EFF;">&lt;!&ndash;{{numData.now_year.hd?numData.now_year.hd:0}}&ndash;&gt;</span>
</el-col>-->
<el-col class="tr" :span="3">
<span class="fs26"
style="color: #409EFF;">{{numData.now_year.jfbx?numData.now_year.jfbx:0}}</span>
</el-col>
</el-row>
<el-row style="height: 40px;line-height: 40px">
<el-col class="tl" :span="4">
<span class="top_title">全部</span>
</el-col>
<el-col class="tr" :span="4">
<span class="fs18">{{numData.all.zgww?numData.all.zgww:0}}</span>
</el-col>
<el-col class="tr" :span="4">
<span class="fs18">{{numData.all.knbf?numData.all.knbf:0}}</span>
</el-col>
<el-col class="tr" :span="4">
<span class="fs18">{{numData.all.znrx?numData.all.znrx:0}}</span>
</el-col>
<el-col class="tr" :span="3">
<span class="fs18">{{numData.all.ta?numData.all.ta:0}}</span>
</el-col>
<!-- <el-col class="tr" :span="3">
<span class="fs18">&lt;!&ndash;{{numData.all.hd?numData.all.hd:0}}&ndash;&gt;</span>
</el-col>-->
<el-col class="tr" :span="3">
<span class="fs18">{{numData.all.jfbx?numData.all.jfbx:0}}</span>
</el-col>
</el-row>
</div>
<el-row style="height: 500px;border-bottom: 10px solid rgb(240,240,240);padding: 20px 30px;padding-top: 10px;"
v-loading="chart_one_loading">
<div style="position: absolute;top: 25px;right: 40px;z-index: 999">
<el-date-picker
class="year"
style="width: 120px;"
size="mini"
v-model="numYear.startYear"
type="year" :clearable="false"
value-format="yyyy"
placeholder="选择年">
</el-date-picker>
-
<el-date-picker
class="year"
style="width: 120px;"
size="mini"
v-model="numYear.endYear"
type="year" :clearable="false"
value-format="yyyy"
placeholder="选择年">
</el-date-picker>
</div>
<div class="chartTitle">职工动态曲线</div>
<div id="chart_one" style="width: 100%;height:85%;margin-top: 40px"></div>
</el-row>
<el-card class="box-card">
<div slot="header" class="clearfix" style="position: relative">
<span class="title">职工动态时间线</span>
<el-select v-model="type" @change="timeLine" placeholder="请选择" style="float: right; padding: 0;">
<el-option v-for="(v,k) in typeObj" :key="k" :label="v.name" :value="k"></el-option>
</el-select>
<div style="float: right; padding: 0;margin-right: 10px">
<el-date-picker
@change="timeLine"
v-model="dateRange"
type="daterange"
value-format="yyyy-MM-dd"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</div>
</div>
<div class="text item" v-loading="timeline_loading">
<el-timeline v-if="list.length">
<el-timeline-item v-for="item in list" :color="typeObj[item.type]['color']"
:timestamp="item.time"
placement="top">
<el-card shadow="hover">
<el-collapse>
<el-collapse-item name="1">
<template slot="title">
<div :style="'color:'+ typeObj[item.type].color">
<i :class="typeObj[item.type].icon"></i>&nbsp;&nbsp;&nbsp;{{typeObj[item.type].name}}
</div>
</template>
</el-collapse-item>
</el-collapse>
</el-card>
</el-timeline-item>
</el-timeline>
<el-row v-else class="none-data">
<span class="none-data-title">暂无数据</span>
</el-row>
</div>
</el-card>
</el-card>
</div>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
data: () => {
return {
dateRange: [],
type: 'all',
chart_one_loading: false,
top_block_loading: false,
search_user_loading: false,
timeline_loading: false,
userid: '',
yearnum: 10,
typeObj: {
all: {
name: '全部',
color: ''
},
zgww: {
name: '职工慰问',
color: '#5B8FF9',
icon: 'fa fa-bed'
},
knbf: {
name: '困难帮扶',
color: '#5AD8A6',
icon: 'fa fa-handshake-o'
},
znrx: {
name: '子女入学',
color: '#F6BD16',
icon: 'fa fa-graduation-cap'
},
ta: {
name: '撰写提案',
color: "#E8684A",
icon: 'fa fa-lightbulb-o'
},
xhd: {
name: '校工会活动',
color: "#6DC8EC",
icon: 'el-icon-basketball'
},
fhhd: {
name: '分工会活动',
color: "#6DC8EC",
icon: 'el-icon-basketball'
},
sthd: {
name: '社团活动',
color: "#6DC8EC",
icon: 'el-icon-basketball'
},
yybx: {
name: '经费报销',
color: "#9270CA",
icon: 'fa fa-money'
},
},
numData: {
now_year: {},
all: {},
},
userOptions: [],
user: {},
list: [],
desc: true,
numYear: {
startYear: new Date().getFullYear() - 9 + '',
endYear: new Date().getFullYear() + '',
},
}
},
methods: {
timeLine() {
this.timeline_loading = true
$.post("/platform/careData/staff/timeLine", {
userid: this.userid,
type: this.type,
desc: this.desc,
startTime: this.dateRange && this.dateRange.length ? this.dateRange[0] : '',
endTime: this.dateRange && this.dateRange.length ? this.dateRange[1] : '',
}, (res) => {
if (res.code == 0) {
let {data} = res
this.list = data
}
this.timeline_loading = false
}, "json");
},
userChange(id) {
this.queryAll()
this.user = this.userOptions.find(v => v.id == id)
},
queryAll() {
this.getNumByYear()
this.getYearNumAndAllNum()
this.timeLine()
},
remoteMethod(str) {
this.search_user_loading = true
$.get("/platform/careData/staff/queryUser", {
key: str,
}, (res) => {
if (res.code == 0) {
let {list} = res.data
this.userOptions = list
}
this.search_user_loading = false
}, "json");
},
getNumByYear() {
this.chart_one_loading = true
let container = document.getElementById('chart_one');
container.innerHTML = ''
let plot
if (this.userid) {
this.$axios.post("/platform/careData/staff/getNumByYear", {
userid: this.userid,
yearnum: this.yearnum,
startYear: this.numYear.startYear,
endYear: this.numYear.endYear,
}).then(res=>{
if (res.code === 0) {
let {data} = res
plot = new G2Plot.Line(container, {
data,
xField: 'year',
yField: 'value',
seriesField: 'type',
legend: {
position: 'top',
},
smooth: true,
animation: {
appear: {
animation: 'path-in',
duration: 5000,
},
},
});
plot.render();
this.chart_one_loading = false
}
})
} else {
let data = []
let year = new Date().getFullYear()
for (let i = year - this.yearnum + 1; i <= year; i++) {
for (let k in this.typeObj) {
data.push({
type: this.typeObj[k]['name'],
value: 0,
year: i
})
}
}
plot = new G2Plot.StackArea(container, {data, ...config,});
plot.render();
this.chart_one_loading = false
}
},
getYearNumAndAllNum() {
this.top_block_loading = true
this.$axios.post('/platform/careData/staff/getYearNumAndAllNum', {userid: this.userid,}).then(res => {
if (res.code === 0) {
this.numData = res.data
this.top_block_loading = false
}
})
},
},
created() {
this.$axios.post('/platform/careData/staff/initUser').then(res => {
if (res.code === 0) {
this.userOptions = [res.data]
this.userid = this.userOptions[0].id
this.userChange(this.userOptions[0].id)
}
})
},
mounted() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,462 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.top_block {
width: 100%;
padding: 20px 80px;
border-bottom: 10px solid rgb(240, 240, 240);
}
.tr {
text-align: right;
}
.tl {
text-align: left;
}
.top_title {
font-size: 14px;
color: #808492;
height: 30px;
line-height: 30px;
margin-bottom: 5px;
}
.fs18 {
font-size: 18px;
}
.fs26 {
font-size: 26px;
}
.fs20 {
font-size: 20px;
}
.title {
font-size: 18px;
height: 36px;
line-height: 36px;
}
.none-data {
min-height: 300px;
background: url("/none.png") no-repeat center center;
background-size: 360px 260px;
}
.none-data-title {
position: absolute;
display: block;
width: 100%;
text-align: center;
bottom: 20%;
left: 0;
color: rgb(160, 160, 160);
}
.item-title {
color: rgb(160, 160, 160);
}
.item-content {
color: rgb(100, 100, 100);
}
.mb20 {
margin-bottom: 20px;
}
.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);
}
.year input {
text-align: center;
}
.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">
<el-row :gutter="60">
<el-col :span="8" style="position: relative">
<div class="top_title">会员数</div>
<div class="top_num">{{numData.hy_num?numData.hy_num:'0'}}</div>
<div class="cut-off-line"></div>
</el-col>
<el-col :span="8" style="position: relative">
<div class="top_title">分工会数</div>
<div class="top_num">{{numData.fgh_num?numData.fgh_num:'0'}}</div>
<div class="cut-off-line"></div>
</el-col>
<el-col :span="8" style="position: relative">
<div class="top_title">社团数</div>
<div class="top_num">{{numData.st_num?numData.st_num:'0'}}</div>
<div class="cut-off-line"></div>
</el-col>
</el-row>
</div>
<el-row style="padding: 30px 0;">
<el-col :span="12" style="border-right: 1px solid rgb(230,230,230);padding: 0 20px;position: relative">
<div class="chartTitle">会员性别占比</div>
<div id="memberSexChart" style="width: 100%;height: 280px;"></div>
</el-col>
<el-col :span="12" style="border-right: 1px solid rgb(230,230,230);padding: 0 20px;position: relative">
<div class="chartTitle">年度经费</div>
<div id="activityBudgetColumn" style="width: 100%;height: 280px;"></div>
</el-col>
</el-row>
<el-row style="padding: 30px 0;">
<el-col :span="24" style="border-right: 1px solid rgb(230,230,230);padding: 0 20px;position: relative">
<div class="chartTitle">困难帮扶申请趋势</div>
<div id="difficultHelpNumLine" style="width: 100%;height: 280px;"></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: 40px;z-index: 999">
<el-date-picker
class="year"
style="width: 120px;"
size="mini"
v-model="allUnionYear"
type="year" :clearable="false"
value-format="yyyy" @change="allUnionActivityAndJf"
placeholder="选择年">
</el-date-picker>
</div>
<el-col :span="24" style="padding: 0 20px"
v-loading="all_union_loading">
<div class="chartTitle" style="margin-bottom: 50px">{{allUnionYear}}年工会报销费用及活动情况
<el-tooltip class="item" effect="dark" :content="'点击切换为' + unionTip " placement="top">
<el-button type="text" icon="el-icon-sort" @click="doUnionSwitch"></el-button>
</el-tooltip>
</div>
<div id="allUnionChart" style="width: 100%;height: 300px;"></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: 40px;z-index: 999">
<el-date-picker
class="year"
style="width: 120px;"
size="mini"
v-model="allClubYear"
type="year" :clearable="false"
value-format="yyyy" @change="allClubActivityAndJf"
placeholder="选择年">
</el-date-picker>
</div>
<el-col :span="24" style="padding: 0 20px"
v-loading="all_club_loading">
<div class="chartTitle" style="margin-bottom: 50px">{{allClubYear}}年社团报销费用及活动情况
<el-tooltip class="item" effect="dark" :content="'点击切换为' + clubTip " placement="top">
<el-button type="text" icon="el-icon-sort" @click="doClubSwitch"></el-button>
</el-tooltip>
</div>
<div id="allClubChart" style="width: 100%;height: 300px;"></div>
</el-col>
</el-row>
</el-card>
</div>
</div>
<script nonce="${cspNonce!}">
let memberSexChart, activityBudgetColumn, difficultHelpNumLine = null
new Vue({
el: "#app",
data() {
return {
numData: {},
all_club_loading: false,
clubTip:'协会活动数',
allClubYear: moment().format('YYYY'),
isClubJf:true,
all_union_loading: false,
unionTip:'分工会活动数',
allUnionYear: moment().format('YYYY'),
isUnionJf:true,
}
},
methods: {
getNumData() {
this.$axios.post("/platform/caredata/union/getNumData").then(resp => {
if (resp.code === 0) {
this.numData = resp.data
}
})
},
// 会员性别统计图
memberSexNum() {
this.$axios.post("/platform/caredata/union/getHyNumBySex").then(resp => {
if (resp.code === 0) {
// 初始化饼图
memberSexChart && memberSexChart.destroy()
memberSexChart = new G2Plot.Pie("memberSexChart", {
data: resp.data,
angleField: "value",
colorField: "name",
radius: 0.8,
label: {
type: "性别",
content: "{name}"
}
})
memberSexChart.render()
}
})
},
//年度经费统计
activityBudget() {
this.$axios.post(loc() + "/getActivityBudget", this.pageForm).then((res) => {
if (res.code === 0) {
if (activityBudgetColumn) {
activityBudgetColumn.changeData(res.data)
return
}
activityBudgetColumn = new G2Plot.Column("activityBudgetColumn", {
data: res.data,
xField: "year",
yField: "value",
seriesField: "type",
isGroup: true,
columnStyle: {
radius: [20, 20, 0, 0],
},
})
activityBudgetColumn.render()
}
})
},
//困难帮扶申请趋势
getDifficultHelpNum() {
this.$axios.post(loc() + "/getDifficultHelpNum", this.pageForm).then((res) => {
if (res.code === 0) {
if (difficultHelpNumLine) {
difficultHelpNumLine.changeData(res.data)
return
}
difficultHelpNumLine = new G2Plot.Line("difficultHelpNumLine", {
data: res.data,
xField: 'year',
yField: 'value',
meta: {
year: {
alias: '年份',
},
value: {
alias: '数量',
}
},
point: {
size: 5,
shape: 'diamond',
style: {
fill: 'white',
stroke: '#5B8FF9',
lineWidth: 2,
},
},
tooltip: {showMarkers: false},
state: {
active: {
style: {
shadowBlur: 4,
stroke: '#000',
fill: 'red',
},
},
},
interactions: [{type: 'marker-active'}],
})
difficultHelpNumLine.render()
}
})
},
//社团报销费用及活动情况
async doClubSwitch(){
this.isClubJf = !this.isClubJf
this.clubTip = this.isClubJf ? '协会活动数' : '协会经费详情'
await this.allClubActivityAndJf();
},
async allClubActivityAndJf(){
this.all_club_loading = true
const resp = await this.$axios.post("/platform/activityReimbursement/board/allClubActivityAndMoney",{
year:this.allClubYear,
isClubMoney:this.isClubJf
})
if (resp.code === 0) {
let {data} = resp
document.getElementById("allClubChart").innerHTML = ''
const config = {
isStack: true,
"legend": {
"position": "top-right",
"flipPage": false
},
autoFit: true,
title: {
visible: true,
text: this.allClubYear + '年工会经费及活动详情',
},
description: {
visible: true,
text: '单位(元)',
},
xField: 'clubName',
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: {
clubName: {
alias: '协会',
},
money: {
alias: this.isClubJf?'金额':'活动数',
}
},
connectedArea: {
visible: true,
triggerOn: false,
},
}
const plot = new G2Plot.Column(document.getElementById("allClubChart"), {
data,
...config,
});
plot.render();
}
this.all_club_loading = false
},
//部门报销费用和活动情况
async doUnionSwitch(){
this.isUnionJf = !this.isUnionJf
this.unionTip = this.isUnionJf ? '分工会活动数' : '分工会经费详情'
await this.allUnionActivityAndJf();
},
async allUnionActivityAndJf() {
this.all_union_loading = true
const resp = await this.$axios.post("/platform/activityReimbursement/board/allUnionActivityAndMoney",{
year:this.allUnionYear,
isUnionMoney:this.isUnionJf
})
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: this.allUnionYear + '年工会经费及活动详情',
},
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: this.isUnionJf?'金额':'活动数',
}
},
connectedArea: {
visible: true,
triggerOn: false,
},
}
const plot = new G2Plot.Column(document.getElementById("allUnionChart"), {
data,
...config,
});
plot.render();
}
this.all_union_loading = false
},
},
created() {
this.getNumData()
this.memberSexNum()
this.activityBudget()
this.getDifficultHelpNum()
this.allClubActivityAndJf()
this.allUnionActivityAndJf()
},
mounted() {
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,129 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
placeholder="请选择年度"
type="year"
@change="doSearch"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="项目名称:">
<el-select v-model="pageForm.projectId" placeholder="请选择项目名称" filterable clearable
@change="doSearch" style="width: 100%">
<el-option
v-for="item in projectList"
:key="item.code"
:label="item.name"
:value="item.code">
</el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
@change="doSearch" style="width: 100%">
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="登记台账"></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'buyCount'">
<el-link @click="onView(row)" type="primary" :underline="false">{{ row.buyCount }}</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template v-slot="{ 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>
<template #view>
<user-info ref="userInfoRef"></user-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/userInfo.js'){}#-->
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"user-info": userInfo,
},
data() {
return {
tableColumns: [
{label: '年度', prop: 'year'},
{label: '项目', prop: 'projectName'},
{label: '工会', prop: 'unionName'},
{label: '登记人', prop: 'userName'},
{label: '购买人数', prop: 'buyCount'},
],
projectList: [],
unionList: [],
}
},
methods: {
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
}
})
},
onView(row) {
this.$refs.guava.view(() => {
this.$refs.userInfoRef.initData(row)
})
},
async getBuyClothesProject() {
const {data} = await this.$axios.post('/platform/clothing/apply/getBuyClothesProject')
return data
},
},
async created() {
this.unionList = await this.$businessTool.listUnion()
this.projectList = await this.getBuyClothesProject()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,184 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
disabled
placeholder="请选择年度"
type="year"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="项目名称">
<el-select v-model="pageForm.projectId" placeholder="请选择项目名称" filterable
@change="doSearch" style="width: 100%">
<el-option
v-for="item in projectList"
:key="item.code"
:label="item.name"
:value="item.code">
</el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
@change="doSearch" style="width: 100%">
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="近两年内">
<el-radio-group @change="(val) => doSearch()" v-model="pageForm.isBuy">
<el-radio-button :label="true">已购买</el-radio-button>
<el-radio-button :label="false">未购买</el-radio-button>
</el-radio-group>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"></el-input>
</search-item>
<search-item label="性别">
<el-select @change="doSearch" filterable clearable v-model="pageForm.sex"
placeholder="请选择性别" style="width: 100%">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="人员列表">
<el-button v-if="!pageForm.isBuy" type="primary" size="small" @click="doHandler">
<i class="ti-plus"></i>
提交名单
</el-button>
<el-button v-else type="danger" size="small" @click="doHandler">
<i class="el-icon-close"></i>
移除名单
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize"
ref="multipleTable" @selection-change="handleSelectionChange"
:row-key="(val) => val.id">
<el-table-column :reserve-selection="true" type="selection" width="55"></el-table-column>
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
},
data() {
return {
pageForm: {
year: this.$moment().format('YYYY'),
isBuy: false,
searchName: 'u.username'
},
tableColumns: [
{ prop: "userName", label: "姓名" },
{ prop: "loginName", label: "工号" },
{ prop: "sex", label: "性别" },
{ prop: "unitName", label: "单位" },
{ prop: "unionName", label: "工会" },
{ prop: "mobile", label: "联系方式" },
],
projectList: [],
unionList: [],
multipleSelection: []
}
},
methods: {
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
async getBuyClothesProject() {
const {data} = await this.$axios.post('/platform/clothing/apply/getBuyClothesProject')
return data
},
async doHandler() {
if(!this.pageForm.projectId) {
this.$message.warning('请选择项目')
return
}
if(this.multipleSelection.length === 0) {
this.$message.warning('请先选择人员')
return
}
const confirm = await this.$confirm('您选择了' + this.multipleSelection.length + '人, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === "confirm") {
const resp = await this.$axios.post('/platform/clothing/apply/doHandler', {
ids: JSON.stringify(this.multipleSelection),
projectId: this.pageForm.projectId,
year: this.pageForm.year,
isBuy: this.pageForm.isBuy,
})
if(resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.multipleSelection = []
this.$refs.multipleTable.clearSelection()
} else {
this.$message.warning(resp.msg)
}
}
},
handleSelectionChange(val) {
this.multipleSelection = val.length > 0 ? val.map(o => o.id) : []
},
},
async created() {
this.unionList = await this.$businessTool.listUnion()
this.projectList = await this.getBuyClothesProject()
if (this.projectList && this.projectList.length > 0) {
this.pageForm.projectId = this.projectList[0].code
}
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,69 @@
const userInfo = {
template: /*language=HTML*/ `
<div>
<div class="left-span-label">购买服装人员名单</div>
<el-table :data="tableData">
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns">
</el-table-column>
<el-table-column label="操作" width="100">
<template v-slot="{ row }">
<el-button @click="deleteBuyUser(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
`,
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{label: '姓名', prop: 'buyUserName'},
{label: '工号', prop: 'buyUserLoginName'},
{label: '性别', prop: 'sex'},
{label: '单位', prop: 'buyUserUnitName'},
{label: '所属工会', prop: 'buyUserUnionName'},
{label: '联系方式', prop: 'mobile'},
],
}
},
methods: {
initData(row) {
this.$axios.post('/platform/clothing/record/findBuyClothesUser', {
projectId: row.projectId,
userId: row.userId,
year: row.year,
}).then((resp) => {
if (resp.code === 0) {
this.tableData = clone(resp.data)
}
}).catch(() => {})
},
deleteBuyUser(row) {
this.$confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const resp = await this.$axios.post('/platform/clothing/record/deleteBuyUser', {id: row.id})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.warning(resp.msg)
}
}).catch(() => {})
},
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,158 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
placeholder="请选择年度"
type="year"
@change="doSearch"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="项目名称:">
<el-select v-model="pageForm.projectId" placeholder="请选择项目名称" filterable clearable
@change="doSearch" style="width: 100%">
<el-option
v-for="item in projectList"
:key="item.code"
:label="item.name"
:value="item.code">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="登记记录">
<el-button v-if="!pageForm.isBuy" type="primary" size="small" @click="openAdd">
<i class="ti-plus"></i>
服装登记
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'buyCount'">
<el-link @click="onView(row)" type="primary" :underline="false">{{ row.buyCount }}</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="300">
<template v-slot="{ row }">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="onExport(row)" size="mini" type="primary">导出</el-button>
<el-button @click="onDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<user-info ref="userInfoRef"></user-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/userInfo.js'){}#-->
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"user-info": userInfo,
},
data() {
return {
tableColumns: [
{label: '年度', prop: 'year'},
{label: '项目', prop: 'projectName'},
{label: '工会', prop: 'unionName'},
{label: '登记人', prop: 'userName'},
{label: '购买人数', prop: 'buyCount'},
],
projectList: [],
}
},
methods: {
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
}
})
},
onView(row) {
this.$refs.guava.view(() => {
this.$refs.userInfoRef.initData(row)
})
},
openAdd() {
commonUtil.pjaxPush('/platform/clothing/apply')
},
onDelete(row) {
this.$confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const resp = await this.$axios.post(loc() + '/doDelete', {
projectId: row.projectId,
year: row.year,
userId: row.userId,
})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.warning(resp.msg)
}
}).catch(() => {})
},
onExport(row) {
const params = {
year: row.year,
projectId: row.projectId,
userId: row.userId,
}
this.$downLoad("/platform/clothing/record/doExport", params)
},
async getBuyClothesProject() {
const {data} = await this.$axios.post('/platform/clothing/apply/getBuyClothesProject')
return data
},
},
async created() {
this.projectList = await this.getBuyClothesProject()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,67 @@
const basicForm = {
template: /*language=HTML*/ `
<el-dialog :visible.sync="visible" :title="formData.id ? '编辑' : '新增'">
<el-form :model="formData" :rules="rules" ref="formRef" label-width="80px">
<el-form-item label="课程标题" prop="title">
<el-input v-model="formData.title" placeholder="请输入课程标题"></el-input>
</el-form-item>
<el-form-item label="课程描述" prop="description">
<el-input type="textarea" v-model="formData.description" placeholder="请输入课程描述"
:rows="4"></el-input>
</el-form-item>
<el-form-item label="封面地址">
<file-upload
:value.sync="formData.cover"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item label="课程分类" prop="category">
<dict-select v-model="formData.category" code="TRAIN_EDU_COURSE_TYPE" style="width: 100%"></dict-select>
</el-form-item>
<el-form-item label="是否启用">
<el-switch v-model="formData.disabled" :active-value="false" :inactive-value="true"></el-switch>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="onSave">确定</el-button>
</div>
</el-dialog>
`,
data() {
return {
visible: false,
formData: {},
rules: {
title: [{required: true, message: '请输入课程标题', trigger: 'blur'}],
description: [{required: true, message: '请输入课程描述', trigger: 'blur'}],
category: [{required: true, message: '请选择课程分类', trigger: 'change'}]
}
}
},
methods: {
onOpen(row = null) {
this.visible = true
this.formData = {...row}
},
onSave() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$axios.post('/platform/edu/courses/' + (this.formData.id ? 'update' : 'insert'), this.formData).then(res => {
if (res.code === 0) {
this.visible = false
this.$message.success(res.msg)
this.$emit('refresh', null)
}
})
}
})
}
}
}
@@ -0,0 +1,425 @@
const contentForm = {
template: /*language=HTML*/ `
<el-dialog :visible.sync="visible" width="70%" title="章节视频管理" top="50px" class="edu_content_dialog">
<div v-if="selectedCourse">
<div class="section-header">
<div>
<h2 style="margin: 0; color: #303133;">{{ selectedCourse.title }} - 内容管理</h2>
<p style="margin: 5px 0 0; color: #909399;">管理课程章节和视频</p>
</div>
<div>
<el-button type="primary" icon="el-icon-plus" size="small" @click="onOpenChapter()">
添加章节
</el-button>
</div>
</div>
<div style="padding: 0 20px 20px;">
<div class="stats-card">
<!-- <el-row :gutter="20">-->
<!-- <el-col :span="8">-->
<!-- <h3 style="margin: 0;">{{ currentChapters.length }}</h3>-->
<!-- <p style="margin: 5px 0 0;">章节数量</p>-->
<!-- </el-col>-->
<!-- <el-col :span="8">-->
<!-- <h3 style="margin: 0;">{{ getTotalVideos() }}</h3>-->
<!-- <p style="margin: 5px 0 0;">视频数量</p>-->
<!-- </el-col>-->
<!-- <el-col :span="8">-->
<!-- <h3 style="margin: 0;">{{ formatDuration(getTotalDuration()) }}</h3>-->
<!-- <p style="margin: 5px 0 0;">总时长</p>-->
<!-- </el-col>-->
<!-- </el-row>-->
</div>
<div v-if="currentChapters.length === 0" style="text-align: center; padding: 50px; color: #909399;">
<i class="el-icon-folder-opened"
style="font-size: 64px; display: block; margin-bottom: 20px;"></i>
<p>暂无章节,请添加章节开始管理内容</p>
</div>
<div v-for="chapter in currentChapters" :key="chapter.id" class="chapter-card">
<div class="chapter-header">
<div>
<h3 style="margin: 0; color: #303133;">{{ chapter.title }}</h3>
<p style="margin: 5px 0 0; color: #909399;">
{{ chapter?.videos.length || 0 }} 个视频
</p>
</div>
<div>
<el-button size="small" type="primary" @click="onOpenVideo(chapter.id)">
添加视频
</el-button>
<el-button size="small" @click="onOpenChapter(chapter)">
编辑章节
</el-button>
<el-button size="small" type="danger" @click="deleteChapter(chapter.id)">
删除章节
</el-button>
</div>
</div>
<div class="chapter-content">
<div v-if="chapter?.videos.length === 0"
style="text-align: center; color: #909399; padding: 30px;">
<i class="el-icon-video-camera"
style="font-size: 32px; display: block; margin-bottom: 10px;"></i>
<p>暂无视频,点击"添加视频"开始添加内容</p>
</div>
<div v-for="video in chapter?.videos" :key="video.id" class="video-item">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="flex: 1;">
<h4 style="margin: 0 0 5px; color: #303133;">{{ video.title }}</h4>
<p style="margin: 0; color: #909399; font-size: 14px;">
<i class="el-icon-time"></i> {{ formatDuration(video.duration) }}
<span style="margin-left: 15px;">
<i class="el-icon-link"></i> {{ video.url }}
</span>
</p>
</div>
<div>
<el-button size="mini" @click="playVideo(video)">播放</el-button>
<el-button size="mini" @click="onOpenVideo(video.chapterId,video)">编辑
</el-button>
<el-button size="mini" type="danger" @click="deleteVideo(video.id)">删除
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else style="text-align: center; padding: 100px; color: #909399;">
<i class="el-icon-warning" style="font-size: 64px; display: block; margin-bottom: 20px;"></i>
<p>请先选择一个课程进行内容管理</p>
</div>
<!-- 章节弹窗 -->
<el-dialog :title="chapterForm.id ? '编辑章节' : '添加章节'" :visible.sync="chapterDialogVisible"
append-to-body
width="500px">
<el-form :model="chapterForm" :rules="chapterRules" ref="chapterFormRef" label-width="80px">
<el-form-item label="章节标题" prop="title">
<el-input v-model="chapterForm.title" placeholder="请输入章节标题"></el-input>
</el-form-item>
<el-form-item label="排序码" prop="sortCode">
<el-input-number v-model="chapterForm.sortCode" :min="1" style="width: 100%;"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="chapterDialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveChapter">确定</el-button>
</div>
</el-dialog>
<!-- 视频弹窗 -->
<el-dialog :title="videoForm.id ? '编辑视频' : '添加视频'" :visible.sync="videoDialogVisible" width="600px"
append-to-body>
<el-form :model="videoForm" :rules="videoRules" ref="videoFormRef" label-width="80px">
<el-form-item label="视频标题" prop="title">
<el-input v-model="videoForm.title" placeholder="请输入视频标题"></el-input>
</el-form-item>
<el-form-item label="视频地址" prop="url">
<!-- <el-input v-model="videoForm.url" placeholder="请输入视频地址"></el-input>-->
<file-upload
:value.sync="videoForm.url"
:upload_number="1"
upload_mode="file"
upload_result_category="interval"
upload_result_type="url"
accept="video/*"
></file-upload>
</el-form-item>
<!-- <el-form-item label="视频时长" prop="duration">-->
<!-- <el-input-number v-model="videoForm.duration" :min="1" placeholder="秒"-->
<!-- style="width: 100%;"></el-input-number>-->
<!-- <div class="duration-display">{{ formatDuration(videoForm.duration || 0) }}</div>-->
<!-- </el-form-item>-->
<el-form-item label="排序码" prop="sortCode">
<el-input-number v-model="videoForm.sortCode" :min="1" style="width: 100%;"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="videoDialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveVideo">确定</el-button>
</div>
</el-dialog>
<!-- 弹窗:视频播放器 -->
<el-dialog title="视频播放" :visible.sync="videoPlayDialogVisible" @close="handleVideoPlayDialogClose" append-to-body>
<div style="text-align: center;">
<video
ref="videoPlayer"
class="video-player"
:src="currentVideoSrc"
controls
autoplay
style="width:100%;max-width: 100%; height: auto;"
>
您的浏览器不支持视频标签。
</video>
</div>
</el-dialog>
</el-dialog>
`,
data() {
return {
visible: false,
selectedCourse: null,
// 弹窗显示状态
chapterDialogVisible: false,
videoDialogVisible: false,
// 表单数据
chapterForm: {},
videoForm: {},
// 表单验证规则
chapterRules: {
title: [{required: true, message: '请输入章节标题', trigger: 'blur'}],
sortCode: [{required: true, message: '请输入排序码', trigger: 'blur'}]
},
videoRules: {
title: [{required: true, message: '请输入视频标题', trigger: 'blur'}],
url: [{required: true, message: '请输入视频地址', trigger: 'blur'}],
duration: [{required: true, message: '请输入视频时长', trigger: 'blur'}],
sortCode: [{required: true, message: '请输入排序码', trigger: 'blur'}]
},
// 数据
chapters: [],
videos: [],
// 视频播放
videoPlayDialogVisible: false,
currentVideoSrc: null
}
},
computed: {
currentChapters() {
if (!this.selectedCourse) return [];
return this.chapters.filter(chapter => chapter.courseId === this.selectedCourse.id)
.sort((a, b) => a.sortCode - b.sortCode);
}
},
methods: {
onOpen(selectedCourse) {
this.visible = true
this.selectedCourse = selectedCourse
this.listChapter()
},
// 查询章节
listChapter() {
this.$axios.post('/platform/edu/chapters/list', {courseId: this.selectedCourse.id}).then(res => {
if (res.code === 0) {
this.chapters = res.data
}
})
},
// 新增/编辑章节
onOpenChapter(chapter = null) {
this.chapterForm = chapter ? {...chapter} : {
id: '',
courseId: this.selectedCourse.id,
title: '',
sortCode: this.currentChapters.length + 1
};
this.chapterDialogVisible = true;
this.$nextTick(() => {
this.$refs.chapterFormRef && this.$refs.chapterFormRef.clearValidate();
});
},
// 删除章节
deleteChapter(id) {
this.$confirm('此操作将永久删除该章节及其所有视频,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/edu/chapters/delete', {id}).then(res => {
this.$message.success('删除成功')
this.listChapter()
})
});
},
// 保存章节
saveChapter() {
this.$refs.chapterFormRef.validate(valid => {
if (valid) {
this.$axios.post('/platform/edu/chapters/' + (this.chapterForm.id ? 'update' : 'insert'), this.chapterForm).then(res => {
if (res.code === 0) {
this.chapterDialogVisible = false
this.$message.success(res.msg)
this.listChapter()
}
})
}
})
},
// 新增/编辑视频
onOpenVideo(chapterId, video = null) {
const chapter = this.chapters.find(chapter => chapter.id === chapterId)
this.videoForm = video ? {...video} : {
id: '',
chapterId: chapterId,
title: '',
url: '',
duration: 0,
sortCode: chapter ? chapter.videos.length + 1 : 1
};
this.videoDialogVisible = true;
this.$nextTick(() => {
this.$refs.videoFormRef && this.$refs.videoFormRef.clearValidate();
});
},
// 保存视频
saveVideo() {
this.$refs.videoFormRef.validate(valid => {
if (valid) {
this.$axios.post('/platform/edu/video/' + (this.videoForm.id ? 'update' : 'insert'), this.videoForm).then(res => {
if (res.code === 0) {
this.videoDialogVisible = false
this.$message.success(res.msg)
this.listChapter()
}
})
}
});
},
// 删除视频
deleteVideo(id) {
this.$confirm('确定删除此视频吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/edu/video/delete', {id: id}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.listChapter()
}
})
});
},
// 播放视频
playVideo(video) {
this.currentVideoSrc = video.url;
this.videoPlayDialogVisible = true;
// 确保 dialog 打开后视频能正确加载并播放(异步)
this.$nextTick(() => {
const videoEl = this.$refs.videoPlayer;
videoEl.load(); // 重新加载视频源
videoEl.play().catch(err => {
console.warn('自动播放失败,需用户点击播放按钮:', err);
});
});
},
// 关闭视频播放对话框
handleVideoPlayDialogClose(){
const videoEl = this.$refs.videoPlayer;
if (videoEl) {
videoEl.pause();
videoEl.currentTime = 0;
}
// 清空 src 避免音频仍在播放(某些浏览器)
this.currentVideoSrc = '';
},
formatDuration(seconds) {
if (!seconds) return '0分0秒';
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = seconds % 60;
if (hours > 0) {
return hours + '小时' + minutes + '分' + remainingSeconds + '秒'
} else {
return minutes + '分' + remainingSeconds + '秒'
}
}
},
style: /*language=CSS*/ `
/deep/ .edu_content_dialog .el-dialog__body {
height: calc(100vh - 155px);
overflow-y: auto;
}
/deep/ .section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 20px 20px 0;
}
/deep/ .video-item {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
transition: all 0.3s;
}
/deep/ .video-item:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
/deep/ .chapter-card {
border: 1px solid #e4e7ed;
border-radius: 8px;
margin-bottom: 20px;
overflow: hidden;
}
/deep/ .chapter-header {
background: #f5f7fa;
padding: 15px 20px;
border-bottom: 1px solid #e4e7ed;
display: flex;
justify-content: space-between;
align-items: center;
}
/deep/ .chapter-content {
padding: 20px;
}
/deep/ .stats-card {
color: white;
padding: 20px;
border-radius: 8px;
text-align: center;
margin-bottom: 20px;
}
/deep/ .course-cover {
width: 100px;
height: 60px;
object-fit: cover;
border-radius: 4px;
}
/deep/ .duration-display {
color: #909399;
font-size: 12px;
}
`
}
@@ -0,0 +1,102 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.course-cover{
width: 100px;
height: auto;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" icon="el-icon-plus" @click="$refs.basicFormRef.onOpen()">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="cover" label="课程封面" width="150">
<template slot-scope="scope">
<img v-if="scope.row.cover" :src="scope.row.cover" class="course-cover">
</template>
</el-table-column>
<el-table-column prop="title" label="课程标题" min-width="150"></el-table-column>
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip></el-table-column>
<el-table-column prop="category" label="分类" width="120">
<template slot-scope="scope">
<el-tag size="small">{{ scope.row.category }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="disabled" label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.disabled ? 'danger' : 'success'" size="small">
{{ scope.row.disabled ? '已禁用' : '启用中' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="300" align="center" fixed="right">
<template slot-scope="scope">
<el-button size="mini" @click="manageCourse(scope.row)" type="primary">
管理内容
</el-button>
<el-button size="mini" @click="$refs.basicFormRef.onOpen(scope.row)" type="primary">
编辑
</el-button>
<el-button size="mini" @click="onDelete(scope.row.id)" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<basic-form ref="basicFormRef" @refresh="pageData"></basic-form>
<content-form ref="contentFormRef"></content-form>
</div>
<script nonce="${cspNonce!}">
<!--#include('basicForm.js'){}#-->
<!--#include('contentForm.js'){}#-->
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
components: {
'basic-form': basicForm,
'content-form': contentForm
},
data() {
return {}
},
methods: {
manageCourse(row) {
this.$refs.contentFormRef.onOpen(row)
},
onDelete(id) {
this.$confirm('此操作将永久删除该课程及其所有章节和视频,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/edu/courses/delete', {id}).then(res => {
this.$message.success('删除成功')
this.pageData()
})
}).catch(() => {
})
}
},
created() {
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,79 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="课程">
<el-select v-model="pageForm.courseId" placeholder="请选择课程" clearable>
<el-option v-for="item in coursesOptions" :key="item.id" :value="item.id"
:label="item.title"></el-option>
</el-select>
</search-item>
<search-item label="开始时间">
<el-date-picker v-model="pageForm.startDate" type="date" placeholder="请选择开始时间"
format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable>
</el-date-picker>
</search-item>
<search-item label="结束时间">
<el-date-picker v-model="pageForm.endDate" type="date" placeholder="请选择结束时间"
format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable>
</el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<el-table :data="tableData">
<el-table-column label="序号" width="80" type="index" :index="indexMethod"></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="unitName"></el-table-column>
<el-table-column label="分工会" prop="unionName"></el-table-column>
<el-table-column label="学习时长(秒)" prop="totalWatchTime"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableData: [],
coursesOptions: []
}
},
methods: {
pageData() {
this.$axios.post('/platform/edu/personRank/ranking', this.pageForm).then(res => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
listCourses() {
this.$axios.post('/platform/edu/personRank/courses').then(res => {
if (res.code === 0) {
this.coursesOptions = res.data
}
})
}
},
created() {
this.listCourses()
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,77 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="课程">
<el-select v-model="pageForm.courseId" placeholder="请选择课程" clearable>
<el-option v-for="item in coursesOptions" :key="item.id" :value="item.id"
:label="item.title"></el-option>
</el-select>
</search-item>
<search-item label="开始时间">
<el-date-picker v-model="pageForm.startDate" type="date" placeholder="请选择开始时间"
format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable>
</el-date-picker>
</search-item>
<search-item label="结束时间">
<el-date-picker v-model="pageForm.endDate" type="date" placeholder="请选择结束时间"
format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable>
</el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<el-table :data="tableData">
<el-table-column label="序号" width="80" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="分工会名称" prop="unionName"></el-table-column>
<el-table-column label="分工会编码" prop="unionCode"></el-table-column>
<el-table-column label="参与人数" prop="participantCount"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
tableData: [],
coursesOptions: []
}
},
methods: {
pageData() {
this.$axios.post('/platform/edu/unionRank/ranking', this.pageForm).then(res => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
listCourses() {
this.$axios.post('/platform/edu/unionRank/courses').then(res => {
if (res.code === 0) {
this.coursesOptions = res.data
}
})
}
},
created() {
this.listCourses()
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,372 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<snaker-start slot="header" label="子女入学登记" define_key="ZNRXDJ"></snaker-start>
<el-form :model="formData" ref="formRef" class="flow-task-form">
<el-descriptions :column="2" border>
<el-descriptions-item label="登记类型" :span="2">
<el-form-item prop="registrationType"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-radio-group v-model="formData.registrationType">
<el-radio border :label="i.registrationType" :key="i.registrationType"
v-for="i in registrationTypeOption">
{{i.registrationTypeName}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="监护人(教工)姓名">
{{formData.userName}}
</el-descriptions-item>
<el-descriptions-item label="工号">
{{formData.loginName}}
</el-descriptions-item>
<el-descriptions-item label="手机号码">
<el-form-item prop="mobile"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-input v-model="formData.mobile" placeholder="请输入手机号码"
maxlength="20"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所在单位">
{{formData.unitName}}
</el-descriptions-item>
<el-descriptions-item label="监护人与学生关系">
<el-form-item prop="childRelationship"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select clearable placeholder="请选择监护人与学生关系"
style="width: 100%;"
v-model="formData.childRelationship">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="子女姓名">
<el-form-item prop="childrenName"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<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="sex"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select clearable placeholder="请选择性别"
style="width: 100%;"
v-model="formData.sex">
<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="childrenIdCard"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<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"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<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="childrenCurrentSchool"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<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="childrenPlanSchool"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select clearable placeholder="请选择拟报就读学校"
style="width: 100%;"
v-model="formData.childrenPlanSchool">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="子女户口所在地">
<el-form-item prop="childrenHuKouAddress"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-input v-model="formData.childrenHuKouAddress" placeholder="请输入子女户口所在地"
maxlength="30"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="备注">
<el-form-item prop="note"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-input v-model="formData.note" placeholder="请填写户籍所在地派出所"
maxlength="50"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="户口簿照片" :span="2">
<el-form-item prop="huKouFiles"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<file-upload :upload_number="10" :value.sync="formData.huKouFiles"
upload_result_type="url"
upload_text="请上传户口首页、户主页、父母和子女页"
complete_result upload_mode="drag"
upload_result_category="array"></file-upload>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="子女出生证照片" :span="2">
<el-form-item prop="birthCertificateFiles">
<file-upload :upload_number="10" :value.sync="formData.birthCertificateFiles"
upload_result_type="url"
complete_result upload_mode="drag"
upload_result_category="array"></file-upload>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" plain @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit" v-if="!taskId">提交</el-button>
<el-button type="primary" @click="onFinishTask" v-else>提交</el-button>
</el-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
dicts: ["ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP", "ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"],
mixins: [initTableMixins],
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
registrationTypeOption: [],
childRelationshipOption: [],
}
},
methods: {
getEnrollmentRegistrationPlan() {
this.$axios.post("/platform/enrollmentRegistration/apply/getEnrollmentRegistrationPlan").then(res => {
if (res.code === 0) {
this.registrationTypeOption = res.data
}
})
},
validateBirthday() {
if (!this.formData.registrationType) {
return "请选择登记类型"
}
if (!this.formData.childrenBirthday) {
return "请选择子女出生年月"
}
const childrenBirthday = new Date(this.formData.childrenBirthday);
if (isNaN(childrenBirthday.getTime())) {
return "出生日期格式无效";
}
const registrationType = this.registrationTypeOption.find(item => item.registrationType === this.formData.registrationType)
if (registrationType.greaterThanBirthday) {
const greaterThanBirthday = new Date(registrationType.greaterThanBirthday);
if (isNaN(greaterThanBirthday.getTime())) {
return "限制日期格式无效";
}
if (childrenBirthday < greaterThanBirthday) {
return "出生日期不能小于" + registrationType.greaterThanBirthday;
}
}
if (registrationType.lessThanBirthday) {
const lessThanBirthday = new Date(registrationType.lessThanBirthday);
if (isNaN(lessThanBirthday.getTime())) {
return "限制日期格式无效";
}
if (childrenBirthday > lessThanBirthday) {
return "出生日期不能大于" + registrationType.lessThanBirthday;
}
}
return null; // 表示通过
},
// 保存
onSave() {
const msg = this.validateBirthday()
if (msg) {
this.$message.warning(msg)
return
}
this.getIsRepeatByIdCard().then(flag => {
if (flag) {
} else {
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/enrollmentRegistration/apply/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success("保存成功")
commonUtil.pjaxPush('/platform/enrollmentRegistration/applyList/index')
}
})
})
}
})
},
// 提交
onSubmit() {
const msg = this.validateBirthday()
if (msg) {
this.$message.warning(msg)
return
}
this.$refs.formRef.validate((valid) => {
if (valid) {
this.getIsRepeatByIdCard().then(flag => {
if (flag) {
} else {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/enrollmentRegistration/apply/submit', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/enrollmentRegistration/applyList/index')
}
})
})
}
})
}
})
},
onFinishTask() {
const msg = this.validateBirthday()
if (msg) {
this.$message.warning(msg)
return
}
this.$refs.formRef.validate((valid) => {
if (valid) {
this.getIsRepeatByIdCard().then(flag => {
if (flag) {
} else {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/enrollmentRegistration/apply/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/enrollmentRegistration/applyList/index')
}
})
})
}
})
}
})
},
async getIsRepeatByIdCard() {
if (!this.formData.childrenIdCard) {
this.$message.error("请填写子女身份证号码")
return
}
const res = await this.$axios.post('/platform/enrollmentRegistration/apply/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
}
}
},
async findOne(id) {
const resp = await $.get('/platform/enrollmentRegistration/apply/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,
}
}
}
},
async created() {
this.init()
this.getEnrollmentRegistrationPlan()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,136 @@
<!--#
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>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="childrenName" label="子女姓名"></el-table-column>
<el-table-column prop="userName" label="教职工姓名"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="mobile" label="手机号码"></el-table-column>
<el-table-column prop="registrationType" label="登记类型">
<template v-slot="{row}">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_TYPE"
:value="row.registrationType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="applyTime" label="填报时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template v-slot="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作"
width="300px">
<template scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">
查看
</el-button>
<el-button @click="openEdit(row)" size="mini" type="primary"
v-if="row.taskKey === 'startTask' || !row.instanceId">
编辑
</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger"
v-if="row.taskKey === 'startTask' || !row.instanceId">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<enrollment-registration-info ref="enrollmentRegistrationInfo">
</enrollment-registration-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["ENROLLMENT_REGISTRATION_TYPE", "ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP", "ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"],
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/enrollmentRegistration/applyList/pageData",
pageForm: {
year: moment().format("YYYY"),
}
}
},
components: {
"enrollment-registration-info": ENROLLMENT_REGISTRATION_INFO
},
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.enrollmentRegistrationInfo.onOpen(row)
})
},
openEdit(row) {
commonUtil.pjaxPush('/platform/enrollmentRegistration/apply/index?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/enrollmentRegistration/applyList/doDelete", {id: id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
}
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,136 @@
const ENROLLMENT_REGISTRATION_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.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
<el-descriptions-item label="手机号码">{{viewData.mobile}}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{viewData.unitName}}</el-descriptions-item>
<el-descriptions-item label="监护人与学生关系">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP"
:value="viewData.childRelationship"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="登记类型">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_TYPE"
:value="viewData.registrationType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="子女姓名">
{{viewData.childrenName}}
</el-descriptions-item>
<el-descriptions-item label="性别">
{{viewData.sex}}
</el-descriptions-item>
<el-descriptions-item label="身份证号">
{{viewData.childrenIdCard}}
</el-descriptions-item>
<el-descriptions-item label="子女出生日期" >
{{viewData.childrenBirthday}}
</el-descriptions-item>
<el-descriptions-item label="现就读学校">
{{viewData.childrenCurrentSchool}}
</el-descriptions-item>
<el-descriptions-item label="拟报就读学校">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"
:value="viewData.childrenPlanSchool"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="子女户口所在地">
{{viewData.childrenHuKouAddress}}
</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">
{{viewData.note}}
</el-descriptions-item>
<el-descriptions-item :span="3" label="户口簿照片">
<file-preview :files="viewData.huKouFiles" complete_result></file-preview>
</el-descriptions-item>
<el-descriptions-item :span="3" label="子女出生证照片">
<file-preview :files="viewData.birthCertificateFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<template v-for="(task,index) 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="办理意见" v-if="!task.ext.isFirstTaskNode" :span="3">
{{
task.taskFormData.opinion
}}
</el-descriptions-item>
<el-descriptions-item label="签字" v-if="!task.ext.isFirstTaskNode" :span="3">
<el-image :src="task.ext.tf_userSign" fit="cover" style="height: 60px"
v-if="task.ext.tf_userSign"></el-image>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
dicts: ["ENROLLMENT_REGISTRATION_TYPE", "ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP", "ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"],
data() {
return {
viewData: {},
doneTasks: [],
row: null
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.getInfo()
this.getDoneTasks()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/enrollmentRegistration/apply/findOne', {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,200 @@
<!--#
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="申报列表">
<el-button @click="openAdd" size="small" class="ml10" type="primary">
创建计划
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="year" label="年度"></el-table-column>
<el-table-column prop="startTime" label="开始时间"></el-table-column>
<el-table-column prop="endTime" label="结束时间"></el-table-column>
<el-table-column prop="registrationType" label="登记类型">
<template v-slot="{row}">
<dict-tag :options="registrationTypeOption"
:value="row.registrationType"></dict-tag>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作"
width="300px">
<template scope="{row}">
<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>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog :visible.sync="dialogVisible" title="创建计划" width="40%">
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="170px">
<el-row :gutter="10">
<el-col :span="12">
<el-form-item
prop="year" label="年度"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-date-picker
placeholder="年度"
style="width: 100%"
type="year"
v-model="formData.year"
value-format="yyyy">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="登记类型" prop="registrationType"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select placeholder="请选择登记类型"
style="width: 100%;"
v-model="formData.registrationType">
<el-option
:key="item.code"
:label="item.name"
:value="item.code"
v-for="item in registrationTypeOption">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
prop="startTime" label="开始时间"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-date-picker
placeholder="开始时间"
style="width: 100%"
type="datetime"
v-model="formData.startTime"
value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
prop="endTime" label="结束时间"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-date-picker
placeholder="结束时间"
style="width: 100%"
type="datetime"
v-model="formData.endTime"
value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
prop="greaterThanBirthday" label="大于某个出生日期能填">
<el-date-picker
placeholder="大于某个出生日期能选"
style="width: 100%"
type="date"
v-model="formData.greaterThanBirthday"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
prop="lessThanBirthday" label="小于某个出生日期能填">
<el-date-picker
placeholder="小于某个出生日期能填"
style="width: 100%"
type="date"
v-model="formData.lessThanBirthday"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" plain @click="dialogVisible=false">关闭</el-button>
<el-button type="primary" @click="onSubmit">提交</el-button>
</el-row>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/enrollmentRegistration/plan/pageData",
pageForm: {
year: moment().format("YYYY")
},
dialogVisible: false,
registrationTypeOption: [],
}
},
methods: {
onSubmit() {
this.$refs.formRef.validate(async valid => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/enrollmentRegistration/plan/onSubmit", {data: JSON.stringify(this.formData)}).then((res) => {
if (res.code === 0) {
this.$message.success("保存成功")
this.doSearch()
this.dialogVisible = false
}
})
})
}
})
},
openEdit(row) {
const data = clone(row)
this.formData = data
this.dialogVisible = true
},
openAdd() {
this.formData = {
year: moment().format("YYYY")
}
this.dialogVisible = true
}
},
async created() {
this.registrationTypeOption = await this.$businessTool.getDictOptions("ENROLLMENT_REGISTRATION_TYPE")
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,216 @@
<!--#
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-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="登记类型">
<el-select clearable placeholder="登记类型"
style="width: 100%;"
v-model="pageForm.registrationType">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.ENROLLMENT_REGISTRATION_TYPE"></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-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="childrenName" label="子女姓名"></el-table-column>
<el-table-column prop="userName" label="教职工姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="mobile" label="手机号码"></el-table-column>
<el-table-column prop="registrationType" label="登记类型">
<template v-slot="{row}">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_TYPE"
:value="row.registrationType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="applyTime" label="填报时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template v-slot="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作"
width="300px">
<template 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>
<enrollment-registration-info ref="enrollmentRegistrationInfo">
<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>
<!--
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"-->
<el-form-item label="签字" prop="tf_userSign"
>
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</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>
</enrollment-registration-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["ENROLLMENT_REGISTRATION_TYPE", "ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP", "ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"],
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/enrollmentRegistration/schoolAudit/pageData",
pageForm: {
year: moment().format("YYYY"),
searchName: "info.userName",
approval: false
},
showApprovalForm: false,
unionOptions: [],
unitOptions: []
}
},
components: {
"enrollment-registration-info": ENROLLMENT_REGISTRATION_INFO
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.enrollmentRegistrationInfo.onOpen(row)
})
},
handleTaskAction(val) {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.enrollmentRegistrationInfo.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)
}
},
},
async created() {
this.unionOptions = await this.$businessTool.listUnion()
this.unitOptions = await this.$businessTool.listUnit()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,161 @@
<!--#
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-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="登记类型">
<el-select clearable placeholder="登记类型"
style="width: 100%;"
v-model="pageForm.registrationType">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.ENROLLMENT_REGISTRATION_TYPE"></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>
<el-button @click="doExportZip" size="mini" type="primary">导出附件zip
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="childrenName" label="子女姓名"></el-table-column>
<el-table-column prop="userName" label="教职工姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="mobile" label="手机号码"></el-table-column>
<el-table-column prop="registrationType" label="登记类型">
<template v-slot="{row}">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_TYPE"
:value="row.registrationType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="applyTime" label="填报时间"></el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作"
width="300px">
<template scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="doDelete(row)" size="mini" type="danger"
v-if="$auth.hasRoleOr(['SYSADMIN'])">删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<enrollment-registration-info ref="enrollmentRegistrationInfo">
</enrollment-registration-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["ENROLLMENT_REGISTRATION_TYPE", "ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP", "ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"],
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/enrollmentRegistration/summary/pageData",
pageForm: {
year: moment().format("YYYY"),
searchName: "info.userName",
approval: false
},
showApprovalForm: false,
unionOptions: [],
unitOptions: []
}
},
components: {
"enrollment-registration-info": ENROLLMENT_REGISTRATION_INFO
},
methods: {
doDelete(row) {
this.$confirm("确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/enrollmentRegistration/summary/doDelete", {id: row.id}).then((resp) => {
if (resp.code === 0) {
this.$message.success("删除成功")
this.doSearch()
}
})
})
},
doExportExcel() {
this.$downLoad("/platform/enrollmentRegistration/summary/doExportExcel", {
data: JSON.stringify(this.pageForm)
})
},
doExportZip() {
this.$downLoad("/platform/enrollmentRegistration/summary/doExportZip", {
data: JSON.stringify(this.pageForm)
})
},
openView(row) {
this.$refs.guava.view(() => {
this.showApprovalForm = false
this.$refs.enrollmentRegistrationInfo.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)
}
},
},
async created() {
this.unionOptions = await this.$businessTool.listUnion()
this.unitOptions = await this.$businessTool.listUnit()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,189 @@
<!--#
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-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="登记类型">
<el-select clearable placeholder="登记类型"
style="width: 100%;"
v-model="pageForm.registrationType">
<el-option :label="item.name" :value="item.code"
v-for="item in dict.type.ENROLLMENT_REGISTRATION_TYPE"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="申请列表">
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="childrenName" label="子女姓名"></el-table-column>
<el-table-column prop="userName" label="教职工姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="mobile" label="手机号码"></el-table-column>
<el-table-column prop="registrationType" label="登记类型">
<template v-slot="{row}">
<dict-tag :options="dict.type.ENROLLMENT_REGISTRATION_TYPE"
:value="row.registrationType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="applyTime" label="填报时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template v-slot="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作"
width="300px">
<template 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>
<enrollment-registration-info ref="enrollmentRegistrationInfo">
<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-item label="签字" prop="tf_userSign"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</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>
</enrollment-registration-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["ENROLLMENT_REGISTRATION_TYPE", "ENROLLMENT_REGISTRATION_CHILD_RELATIONSHIP", "ENROLLMENT_REGISTRATION_CHILDREN_PLAN_SCHOOL"],
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/enrollmentRegistration/unionAudit/pageData",
pageForm: {
year: moment().format("YYYY"),
searchName: "info.userName",
approval:false
},
showApprovalForm: false
}
},
components: {
"enrollment-registration-info": ENROLLMENT_REGISTRATION_INFO
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.enrollmentRegistrationInfo.onOpen(row)
})
},
handleTaskAction(val) {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.enrollmentRegistrationInfo.onOpen(row)
})
},
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,312 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="请选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></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="mini" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
</table-tool>
<el-table :data="tableData">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="name" label="名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="startTime" label="开始时间"></el-table-column>
<el-table-column prop="endTime" label="结束时间"></el-table-column>
<el-table-column prop="enable" label="是否开启">
<template slot-scope="{row}">
<i v-if="row.enable" class="fa fa-circle text-success"></i>
<i v-else class="fa fa-circle text-danger"></i>
</template>
</el-table-column>
<el-table-column prop="honorName" label="类型"></el-table-column>
<el-table-column prop="honorTypeName" label="荣誉类型"></el-table-column>
<el-table-column label="操作" width="200px" fixed="right">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</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>
<el-dialog :title="formData.id?'编辑' : '新增'" :visible.sync="dialogVisible" width="70%" top="50px">
<el-steps :active="stepActive" finish-status="success" simple>
<el-step description="" title="活动信息"></el-step>
<el-step description="" title="名额信息"></el-step>
</el-steps>
<el-form class="mt10" :model="formData" ref="formRef" :rules="formRules" label-width="120px">
<template v-if="stepActive === 0">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="name" label="评优评先名称">
<el-input v-model="formData.name" placeholder="请输入评优评先名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="honor">
<el-cascader
style="width: 100%"
:show-all-levels="false"
:props="{ emitPath: false, label: 'name', value: 'id' }"
v-model="formData.honor"
clearable
filterable
@change="honorChange"
:options="honorOptions"
></el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="year" label="年份">
<el-date-picker
v-model="formData.year"
type="year"
value-format="yyyy"
placeholder="选择年份"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col v-if="selectHonor.origin?.code === 'H1100'" :span="12">
<el-form-item prop="activityGroupId" label="参加人员范围">
<el-select clearable filterable placeholder="请选择参加人员范围" style="width: 99%" v-model="formData.activityGroupId">
<el-option
:label="item.groupName"
:value="item.groupId"
v-for="item in activityGroupList"
:key="item.groupId"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
type="datetime"
v-model="formData.startTime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择开始时间"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
type="datetime"
v-model="formData.endTime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择结束时间"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否启用" prop="enable">
<el-radio-group v-model="formData.enable" size="small">
<el-radio-button :label="true"></el-radio-button>
<el-radio-button :label="false"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="通知" prop="notice">
<text-editor v-model="formData.notice"></text-editor>
</el-form-item>
</el-col>
</el-row>
</template>
<template v-if="stepActive === 1">
<el-form-item v-if="selectHonor.origin?.code === 'H1100'" label="名额分配" prop="quotaAllocations">
<el-table :data="formData.quotaAllocations" border size="mini" max-height="600">
<el-table-column label="分工会编码" prop="code" show-overflow-tooltip></el-table-column>
<el-table-column label="分工会名称" prop="name" show-overflow-tooltip></el-table-column>
<el-table-column label="分配人数" prop="allocationNum">
<template slot-scope="{row}">
<el-input-number
v-model="row.allocationNum"
:min="0"
:step="1"
:pecision="0"
placeholder="请输入分配人数"
></el-input-number>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item v-if="selectHonor.origin?.code === 'H1200'" label="评选名额" prop="directions">
<el-input type="textarea" v-model="formData.directions" rows="4" maxlength="500" placeholder="请输入评选名额的说明"></el-input>
</el-form-item>
</template>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" v-if="stepActive === 0" @click="nextStep">下一步</el-button>
<el-button type="primary" v-if="stepActive === 1" @click="stepActive = 0">上一步</el-button>
<!--<el-button type="primary" @click="doSave">保存</el-button>-->
<el-button type="primary" v-if="stepActive === 1" @click="doSubmit">提交</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
activityGroupList: [],
stepActive: 0,
honorOptions: [],
formRules: {
year: [{ required: true, message: "请选择年份", trigger: "blur" }],
name: [{ required: true, message: "请输入评优评先名称", trigger: "blur" }],
honor: [{ required: true, message: "请选择类型", trigger: "blur" }],
startTime: [{ required: true, message: "请选择开始时间", trigger: "blur" }],
endTime: [{ required: true, message: "请选择结束时间", trigger: "blur" }],
notice: [{ required: true, message: "请输入通知", trigger: "blur" }],
activityGroupId: [{ required: true, message: "请输入通知", trigger: "blur" }],
enable: [{ required: true, message: "请选择是否启用", trigger: "blur" }]
},
dialogVisible: false,
quotaAllocations: [],
formData: {
name: "",
year: new Date().getFullYear().toString(),
startTime: null,
endTime: null,
notice: null,
quotaAllocations: null,
activityGroupId: "",
enable: true
},
selectHonor: {}
}
},
methods: {
nextStep() {
this.$refs.formRef.validate(async (valid) => {
if (valid) {
this.stepActive = 1
} else {
this.$message.warning("存在未填的必填项")
}
})
},
honorChange(val) {
const secondList = this.honorOptions.map((item) => item.children).flat()
const honor = secondList.find((o) => o.id === val)
if (honor){
this.selectHonor = this.honorOptions.find((o) => o.id === honor.parentId)
this.$set(this.formData, "honorTypeId", this.selectHonor.id)
this.$set(this.formData, "honorId", honor.id)
}
},
doSave() {},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios
.post("/platform/evaluate/activity/" + (this.formData.id ? "update" : "insert"), { data: JSON.stringify(this.formData) })
.then((res) => {
if (res.code === 0) {
this.dialogVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
}
})
},
openAdd() {
this.stepActive = 0
this.dialogVisible = true
this.formData={
name: "",
year: new Date().getFullYear().toString(),
startTime: null,
endTime: null,
notice: null,
quotaAllocations: null,
activityGroupId: "",
enable: true
}
this.$nextTick(() => {
this.$refs.formRef.resetFields()
this.$refs.formRef.clearValidate()
})
this.$axios.post("/platform/evaluate/activity/initQuotaAllocations").then((res) => {
if (res.code === 0) {
this.$set(this.formData, "quotaAllocations", res.data)
}
})
},
openEdit(row) {
this.stepActive = 0
if (typeof row.quotaAllocations == "string") {
row.quotaAllocations = JSON.parse(row.quotaAllocations)
}
this.formData = { ...row, year: row.year.toString(), honor: row.honorId }
this.honorChange(row.honorId)
this.dialogVisible = true
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/evaluate/activity/delete", { id: id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
listHonorType() {
this.$axios.post("/platform/evaluate/activity/honorType").then((res) => {
if (res.code === 0) {
this.honorOptions = res.data
}
})
},
initQuotaAllocations() {
this.$axios.post("/platform/evaluate/activity/initQuotaAllocations").then((res) => {
if (res.code === 0) {
this.quotaAllocations = res.data
}
})
},
async getActivityGroup() {
const { data } = await $.get("/platform/activity/basic/scope/getActivityUserScopeGroup")
this.activityGroupList = data
}
},
created() {
this.$set(this.pageForm, "year", new Date().getFullYear().toString())
this.listHonorType()
this.getActivityGroup()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,291 @@
const apply_component = {
template: /*language=HTML*/ `
<el-card shadow="never">
<snaker-start slot="header" label="荣誉申报" define_key="PYPX"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="120px">
<template v-if="formData.honorTypeName == '个人荣誉'">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="userName" label="姓名">
<el-input :value="formData.userName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="loginName" label="工号">
<el-input :value="formData.loginName" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="birthday" label="出生日期">
<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-col>
<el-col :span="12">
<el-form-item prop="mobile" label="联系方式" >
<el-input v-model="formData.mobile" placeholder="联系方式"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="sex" label="性别" >
<el-input v-model="formData.sex" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="民族" prop="nation">
<dict-select style="width: 100%" placeholder="请选择民族" v-model="formData.nation"
code="USER_NATION"></dict-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="education" label="学历">
<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 prop="political" label="政治面貌">
<dict-select
style="width: 100%"
placeholder="请选择政治面貌"
v-model="formData.political"
code="USER_POLITICAL"
></dict-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="technicalTitle" label="技术职称">
<el-input v-model="formData.technicalTitle" placeholder="填写技术职称"
max="50"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="governmentPosition" label="党政职务">
<el-input v-model="formData.governmentPosition" placeholder="填写党政职务"
max="50"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="unitName" label="所属单位">
<el-input :value="formData.unitName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="unionName" label="所属分工会">
<el-input :value="formData.unionName" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
</template>
<template v-else>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item prop="unionName" label="申报工会">
<el-input :value="formData.unionName" placeholder="请输入申报工会"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工会主席" prop="unionLeader">
<el-input placeholder="请填写工会主席" v-model="formData.unionLeader"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="会员人数" prop="memberNumber">
<el-input-number v-model="formData.memberNumber" :min="0"
placeholder="请填写会员人数"
:max="2000" style="width: 100%"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="mobile" label="联系方式" >
<el-input v-model="formData.mobile" placeholder="联系方式"></el-input>
</el-form-item>
</el-col>
</el-row>
</template>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="曾获何种奖励" prop="historyHonor">
<el-input v-model="formData.historyHonor" type="textarea" rows="8" maxlength="5000"
show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="简要事迹(主要成绩)" prop="briefDeeds">
<el-input v-model="formData.briefDeeds" type="textarea" rows="8" maxlength="5000"
show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="附件" prop="files">
<file-upload :value.sync="formData.files" upload_result_category="array" :upload_number="5"
complete_result></file-upload>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row type="flex" justify="end" style="margin-top: 20px;">
<el-button type="primary" plain @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit" v-if="!taskId" class="ml15">提交</el-button>
<el-button type="primary" @click="onFinishTask" class="ml15" v-else>提交</el-button>
</el-row>
</el-card>
`,
store,
data() {
return {
taskId: "",
formData: {},
formRules: {
loginName: [{required: true, message: "必填", trigger: ["change", "blur"]}],
userName: [{required: true, message: "必填", trigger: ["change", "blur"]}],
unitName: [{required: true, message: "必填", trigger: ["change", "blur"]}],
unionName: [{required: true, message: "必填", trigger: ["change", "blur"]}],
birthday: [{required: true, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: true, message: "必填", trigger: ["change", "blur"]}],
mobile: [{required: true, message: "必填", trigger: ["change", "blur"]}],
nation: [{required: true, message: "必填", trigger: ["change", "blur"]}],
political: [{required: true, message: "必填", trigger: ["change", "blur"]}],
education: [{required: true, message: "必填", trigger: ["change", "blur"]}],
technicalTitle: [{required: true, message: "必填", trigger: ["change", "blur"]}],
governmentPosition: [{required: true, message: "必填", trigger: ["change", "blur"]}],
briefDeeds: [{required: true, message: "必填", trigger: ["change", "blur"]}],
historyHonor: [{required: true, message: "必填", trigger: ["change", "blur"]}],
unionLeader: [{required: true, message: "必填", trigger: ["change", "blur"]}],
memberNumber: [{required: true, message: "必填", trigger: ["change", "blur"]}],
}
}
},
methods: {
onOpenEdit(row) {
this.taskId = row.taskId
this.$axios.post("/platform/evaluate/apply/info", {id: row.id}).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.$set(this.formData, "honorTypeName", row.honorTypeName)
}
})
},
onOpen(activity) {
this.initForm()
this.$set(this.formData, "evaluateId", activity.id)
this.$set(this.formData, "honorTypeId", activity.honorTypeId)
this.$set(this.formData, "honorTypeName", activity.honorTypeName)
this.$set(this.formData, "honorId", activity.honorId)
if (activity.honorTypeName.includes('集体')) {
this.getCollectiveInfo()
}
},
getCollectiveInfo() {
this.$axios.post("/platform/honor/basic/settings/getUnionInfo", {id: this.$store.state.user.union.id}).then((res) => {
if (res.code === 0) {
this.formData.memberNumber = res.data.memberNumber
this.formData.unionLeader = res.data.username
this.formData.unionName = this.$store.state.user.union.name
}
})
},
// 保存
onSave() {
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success("保存成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
}
}
})
})
},
onSubmit() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/submit', {
data: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
}
}
})
})
},
onFinishTask() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/submitAgain', {
data: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
}
}
})
})
},
initForm() {
const user = this.$store.state.user
this.$set(this.formData, "userName", user.username)
this.$set(this.formData, "loginName", user.loginname)
this.$set(this.formData, "unitId", user.unit ? user.unit.id : null)
this.$set(this.formData, "unitName", user.unit ? user.unit.name : null)
this.$set(this.formData, "unionId", user.union ? user.union.id : null)
this.$set(this.formData, "unionName", user.union ? user.union.name : null)
this.$set(this.formData, "sex", user.sex)
this.$set(this.formData, "mobile", user.mobile)
this.$set(this.formData, "birthday", user.birthday)
this.$set(this.formData, "nation", user.nation)
this.$set(this.formData, "political", user.political)
this.$set(this.formData, "education", user.education)
this.$set(this.formData, "technicalTitle", user.technicalTitle)
this.$set(this.formData, "governmentPosition", user.governmentPosition)
}
}
}
@@ -0,0 +1,90 @@
<!--#
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 v-model="pageForm.year" type="year" value-format="yyyy" placeholder="选择年度"
style="width: 100%"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<template slot="tool"></template>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="year" label="年份"></el-table-column>
<el-table-column prop="name" label="名称"></el-table-column>
<el-table-column prop="startTime" label="开始时间"></el-table-column>
<el-table-column prop="endTime" label="结束时间"></el-table-column>
<el-table-column prop="honorName" label="类型"></el-table-column>
<el-table-column prop="honorTypeName" label="荣誉类型"></el-table-column>
<el-table-column label="操作" width="200px">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openApply(row)">申请</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</template>
<template #edit>
<apply_form ref="applyFormRef" @refresh=""></apply_form>
</template>
<template #view>
<info ref="infoRef"></info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('apply.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
apply_form: apply_component
},
data() {
return {
}
},
methods: {
openApply(row) {
if(this.$moment().isAfter(this.$moment(row.endTime))) {
this.$message.warning('申请时间已截止')
return
}
$.post("/platform/evaluate/apply/valid", {id: row.id}).then((res) => {
if (res.code === 0) {
const {msg, data} = res
if (!data) {
this.$message.warning(msg)
return
}
//可以申请
this.$refs.guava.edit(()=>{
this.$refs.applyFormRef.onOpen(row)
})
}
})
}
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,195 @@
<!--#
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 v-model="pageForm.year" type="year" value-format="yyyy"
placeholder="选择年度" @change="listEvaluate"></el-date-picker>
</search-item>
<search-item label="事项">
<el-select v-model="pageForm.evaluateId" placeholder="请选择评优评先事项" filterable clearable
style="width: 100%">
<el-option v-for="item in evaluateList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入姓名或工号"
v-model="pageForm.searchKeyword">
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="evaluateName" label="名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="mobile" label="联系方式"></el-table-column>
<el-table-column prop="applyDateTime" label="申请时间"></el-table-column>
<el-table-column prop="honorName" label="类型" show-overflow-tooltip></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template v-slot="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="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>
<!--:rules="[{required:true,message:'必填',trigger:['change','blur']}]"-->
<el-form-item label="签字" prop="tf_userSign"
>
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</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"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
info
},
data() {
return {
pageForm: {
year: new Date().getFullYear() + "",
searchName: "info.userName",
approval:false
},
unionList: [],
unitList: [],
evaluateList: [],
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.infoRef.onOpen(row)
this.showApprovalForm = false
})
},
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.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
listEvaluate() {
this.$set(this.pageForm, "evaluateId","")
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", {year: this.pageForm.year}).then(resp => {
if (resp.code===0){
this.evaluateList = resp.data
if (resp.data.length > 0) {
// this.$set(this.pageForm, "evaluateId", resp.data[0].id)
}
this.pageData()
}
})
},
},
async created() {
this.listEvaluate()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,125 @@
const info = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="3" border>
<template v-if="!this.viewData.memberNumber">
<el-descriptions-item label="姓名">{{viewData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
<el-descriptions-item label="性别">{{viewData.sex}}</el-descriptions-item>
<el-descriptions-item label="出生年月">{{viewData.birthday}}</el-descriptions-item>
<el-descriptions-item label="民族">{{viewData.nation}}</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.technicalTitle}}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{viewData.governmentPosition}}</el-descriptions-item>
</template>
<el-descriptions-item label="工会" :span="1.5">{{viewData.unionName}}</el-descriptions-item>
<el-descriptions-item label="单位" :span="1.5">{{viewData.unitName}}</el-descriptions-item>
<template v-if="this.viewData.memberNumber">
<el-descriptions-item label="工会主席" :span="1.5">{{viewData.unionLeader}}</el-descriptions-item>
<el-descriptions-item label="会员人数" :span="1.5">{{viewData.memberNumber}}</el-descriptions-item>
</template>
<el-descriptions-item label="曾获何种荣誉称号" :span="3">
<div style="white-space: pre-line">
{{viewData.historyHonor}}
</div>
</el-descriptions-item>
<el-descriptions-item label="简要事迹(主要成绩)" :span="3">
<div style="white-space: pre-line">{{viewData.briefDeeds}}</div>
</el-descriptions-item>
<el-descriptions-item label="附件">
<file-preview :files="viewData.files" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<template v-for="(task,index) 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="办理意见" v-if="!task.ext.isFirstTaskNode" :span="3">
{{
task.taskFormData.opinion
}}
</el-descriptions-item>
<el-descriptions-item label="签字" v-if="!task.ext.isFirstTaskNode" :span="3">
<el-image :src="task.ext.tf_userSign" fit="cover" style="height: 60px"
v-if="task.ext.tf_userSign"></el-image>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
viewData: {},
row: {},
doneTasks: []
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.getInfo()
this.getDoneTasks()
},
// 获取申请信息
getInfo() {
this.$axios.post("/platform/evaluate/common/info", {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
// 查看流程图
openChart() {
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
}
}
}
@@ -0,0 +1,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 v-model="pageForm.year" type="year" placeholder="选择年度"
value-format="yyyy"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="evaluateName" label="事项名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="applyDateTime" label="申请时间"></el-table-column>
<el-table-column prop="honorName" label="类型" show-overflow-tooltip></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template v-slot="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">
查看
</el-button>
<el-button @click="openEdit(row)" size="mini" type="primary"
v-if="row.taskKey === 'startTask' || !row.instanceId">
编辑
</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger"
v-if="row.taskKey === 'startTask' || !row.instanceId">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #public>
<info ref="infoRef"></info>
</template>
<template #edit>
<apply_form ref="applyFormRef" @refresh="refresh"></apply_form>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
<!--#include("../apply/apply.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
apply_form: apply_component,
info
},
data() {
return {}
},
methods: {
refresh() {
this.$refs.guava.index()
this.pageData()
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
doDelete(id) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/evaluate/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
openView(row) {
this.$refs.guava.public(() => {
this.$refs.infoRef.onOpen(row)
this.showApprovalForm = false
})
},
openEdit(row) {
this.$refs.guava.edit(() => {
this.$refs.applyFormRef.onOpenEdit(row)
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,204 @@
<!--#
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 v-model="pageForm.year" type="year" value-format="yyyy" placeholder="选择年度"@change="listEvaluate"></el-date-picker>
</search-item>
<search-item label="事项">
<el-select v-model="pageForm.evaluateId" placeholder="请选择评优评先事项" filterable clearable
style="width: 100%">
<el-option v-for="item in evaluateList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入姓名或工号"
v-model="pageForm.searchKeyword">
</el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable style="width: 100%">
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable style="width: 100%">
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="evaluateName" label="事项名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="mobile" label="联系方式"></el-table-column>
<el-table-column prop="honorName" label="类型" show-overflow-tooltip></el-table-column>
<el-table-column prop="applyDateTime" label="申请时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template v-slot="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="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>
<!--:rules="[{required:true,message:'必填',trigger:['change','blur']}]"-->
<el-form-item label="签字" prop="tf_userSign"
>
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</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"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
info
},
data() {
return {
pageForm: {
year: new Date().getFullYear() + "",
searchName: "info.userName",
approval:false
},
unionList: [],
unitList: [],
evaluateList: [],
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.infoRef.onOpen(row)
this.showApprovalForm = false
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.$refs.infoRef.onOpen(row)
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.showApprovalForm = true
})
},
handleTaskAction(val) {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
})},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
listEvaluate() {
this.$set(this.pageForm, "evaluateId","")
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", {year: this.pageForm.year}).then(resp => {
if (resp.code===0){
this.evaluateList = resp.data
if (resp.data.length > 0) {
this.$set(this.pageForm, "evaluateId", resp.data[0].id)
}
this.pageData()
}
})
},
},
async created() {
this.unitList = await this.$businessTool.listUnit()
this.unionList = await this.$businessTool.listUnion()
this.listEvaluate()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,146 @@
<!--#
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
placeholder="选择年度"
type="year"
style="width: 100%"
v-model="pageForm.year"
value-format="yyyy"
@change="listEvaluate()"
></el-date-picker>
</search-item>
<search-item label="事项">
<el-select v-model="pageForm.evaluateId" placeholder="请选择评优评先事项" filterable clearable
style="width: 100%">
<el-option v-for="item in evaluateList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入姓名或工号"
v-model="pageForm.searchKeyword">
</el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
style="width: 100%">
<el-option v-for="item in unionList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable
style="width: 100%">
<el-option v-for="item in unitList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="mini" type="primary" @click="exportExcel">一键导出excel表</el-button>
<!--<el-button size="mini" type="primary" @click="">一键导出登记表</el-button>-->
</table-tool>
<el-table :data="tableData">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="evaluateName" label="事项名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="申请人姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="mobile" label="联系方式"></el-table-column>
<el-table-column prop="applyDateTime" label="申请时间"></el-table-column>
<el-table-column prop="honorName" label="类型" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="300px" fixed="right">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
<el-button size="mini" type="danger" @click="doDelete(row)"
v-if="$auth.hasRoleOr(['SYSADMIN'])">
删除
</el-button>
<!--<el-button size="mini" type="primary" @click="">导出登记表</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"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
info
},
data() {
return {
pageForm: {
year: new Date().getFullYear() + "",
searchName: "info.userName"
},
unionList: [],
unitList: [],
evaluateList: [],
}
},
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
exportExcel() {
this.$downLoad(loc() + "/exportExcel", this.pageForm)
},
async doDelete(row) {
const confirm = await this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post("/platform/evaluate/summary/delete", {id: row.id})
this.$message.success(resp.msg)
this.doSearch()
}
},
listEvaluate() {
this.$set(this.pageForm, "evaluateId","")
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", {year: this.pageForm.year}).then(resp => {
if (resp.code===0){
this.evaluateList = resp.data
if (resp.data.length > 0) {
this.$set(this.pageForm, "evaluateId", resp.data[0].id)
}
this.pageData()
}
})
},
},
async created() {
this.unitList = await this.$businessTool.listUnit()
this.unionList = await this.$businessTool.listUnion()
this.listEvaluate()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,306 @@
<!--#
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">
<el-descriptions :column="3" border>
<el-descriptions-item label="职工姓名">
<el-form-item prop="userId">
<el-select :remote-method="queryUsers"
@change="userChange"
clearable
filterable
remote
placeholder="输入工号或者姓名查找"
style="width: 100%"
v-model="selectedUserId">
<el-option :key="o.id"
:label="o.username+'('+o.loginname+')'"
:value="o.id"
v-for="o in userList"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工号">
<el-form-item prop="loginName">
<el-input v-model="formData.loginName" readonly size="small" placeholder="请输入职工姓名后自动填充"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-form-item prop="sex">
<el-input v-model="formData.sex" readonly size="small" placeholder="请输入职工姓名后自动填充"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="出生年月">
<el-form-item prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="yyyy-MM-dd"
placeholder="请输入职工姓名后自动填充"
style="width: 100%">
</el-date-picker>
<!-- <el-input :value="formatDate(formData.birthday)" readonly size="small" placeholder="请输入职工姓名后自动填充"></el-input>-->
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工会">
<el-form-item prop="unionName">
<el-input v-model="formData.unionName" readonly size="small" placeholder="请输入职工姓名后自动填充"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="单位">
<el-form-item prop="unitName">
<el-input v-model="formData.unitName" readonly size="small" placeholder="请输入职工姓名后自动填充"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="初始额度">
<el-form-item prop="initMoney">
<el-input v-model="formData.initMoney" readonly size="small" placeholder="请输入职工姓名后自动填充"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="剩余额度" :span="2">
<el-form-item prop="money">
<el-input v-model="formData.money" readonly size="small" placeholder="请输入剩余额度"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="健身卡使用情况记录" :span="3">
<el-form-item prop="usages">
<el-table :data="formData.usages" border size="small">
<el-table-column label="使用时间" prop="useTime" >
<template slot-scope="{row}">
<el-date-picker
v-model="row.useTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择使用时间"
style="width: 100%">
</el-date-picker>
</template>
</el-table-column>
<el-table-column label="使用地点" prop="place">
<template slot-scope="{row}">
<el-input v-model="row.place" maxlength="100"
placeholder="请输入使用地点"></el-input>
</template>
</el-table-column>
<el-table-column label="使用项目" prop="project">
<template slot-scope="{row}">
<el-input v-model="row.project" maxlength="100" placeholder="请输入使用项目"></el-input>
</template>
</el-table-column>
<el-table-column label="花费额度" prop="useMoney" >
<template slot-scope="{row}">
<el-input v-model="row.useMoney" maxlength="10" placeholder="请输入花费额度"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot="header">
<el-button type="primary" size="mini" @click="addUsage">添加</el-button>
</template>
<template slot-scope="scope">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
@click="removeUsage(scope.$index)">
</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" @click="onSave">提交</el-button>
</el-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
dicts: [],
data() {
return {
bizId: GetQueryString("bizId"),
formData: {
usages: []
},
userList: [],
selectedUserId: '',
formRules: {
userId: [{ required: true, message: '请选择职工', trigger: 'change' }],
userName: [{ required: true, message: '职工姓名不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生年月不能为空', trigger: 'blur' }],
unionName: [{ required: true, message: '工会单位不能为空', trigger: 'blur' }],
unitName: [{ required: true, message: '单位不能为空', trigger: 'blur' }],
initMoney: [{ required: true, message: '初始额度不能为空', trigger: 'blur' }],
},
}
},
watch: {
// 监听formData.usages的变化,实时计算剩余额度
'formData.usages': {
handler(newVal) {
this.calculateRemainingMoney();
},
deep: true
}
},
methods: {
// 添加使用记录方法
addUsage() {
if (!this.formData.usages) {
this.$set(this.formData, 'usages', []);
}
this.formData.usages.push({
useTime: '',
place: '',
project: '',
useMoney: ''
});
},
// 删除使用记录方法
removeUsage(index) {
if (this.formData.usages && this.formData.usages.length > 0) {
this.formData.usages.splice(index, 1);
}
},
// 计算剩余额度
calculateRemainingMoney() {
if (this.formData.initMoney) {
const totalUsed = this.formData.usages.reduce((sum, usage) => {
const useMoney = parseFloat(usage.useMoney) || 0;
return sum + useMoney;
}, 0);
this.$set(this.formData, 'money', this.formData.initMoney - totalUsed);
}
},
// 检查额度是否足够
checkBalance() {
if (this.formData.money < 0) {
this.$message.error('余额不足!');
return false;
}
return true;
},
// 查询用户
queryUsers(key) {
if (!key) return;
this.$axios.get("/platform/exerciseCard/apply/queryUsers", {
params: { key }
}).then(res => {
if (res.code === 0) {
this.userList = res.data;
}
});
},
// 用户选择变化
userChange(userId) {
const user = this.userList.find(item => item.id === userId);
this.selectedUserId = userId;
if (user) {
this.$set(this.formData, 'userId', user.id);
this.$set(this.formData, 'userName', user.username);
this.$set(this.formData, 'loginName', user.loginname);
this.$set(this.formData, 'sex', user.sex);
this.$set(this.formData, 'unitId', user.unitId);
this.$set(this.formData, 'unitName', user.unitName);
this.$set(this.formData, 'unionId', user.unionId);
this.$set(this.formData, 'unionName', user.unionName);
this.$set(this.formData, 'birthday', user.birthday);
this.$set(this.formData, 'initMoney', 300);
this.$set(this.formData, 'money', 300);
} else {
// 清空表单数据
this.$set(this.formData, 'userId', null);
this.$set(this.formData, 'userName', null);
this.$set(this.formData, 'loginName', null);
this.$set(this.formData, 'sex', null);
this.$set(this.formData, 'unitId', null);
this.$set(this.formData, 'unitName', null);
this.$set(this.formData, 'unionId', null);
this.$set(this.formData, 'unionName', null);
this.$set(this.formData, 'birthday', null);
this.$set(this.formData, 'initMoney', null);
this.$set(this.formData, 'money', null);
}
},
// 保存
onSave() {
if (!this.checkBalance()) {
return;
}
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/exerciseCard/apply/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush('/platform/exerciseCard/mine/index')
}
})
})
},
// 提交验证
validateBeforeSubmit() {
return new Promise((resolve) => {
this.$refs.formRef.validate((valid) => {
if (valid) {
resolve(true);
} else {
this.$message.error('请完善表单信息并勾选申报理由');
resolve(false);
}
});
});
},
async findOne(id) {
const resp = await $.get('/platform/exerciseCard/apply/findOne', {id})
if (resp.code === 0) {
return resp.data
}
},
init() {
if (this.bizId) {
this.findOne(this.bizId).then(async data => {
this.formData = data || {}
// 设置选中的用户ID
if (data && data.userId) {
this.selectedUserId = data.userId;
if (data.loginName) {
this.queryUsers(data.loginName);
}
}
})
} else {
}
}
},
created() {
this.init();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,59 @@
const EXERCISECARD_INFO = {
template: /*language=HTML*/ `
<div>
<table-tool label="人员信息"></table-tool>
<el-descriptions :column="3" border class="flow-task-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="出生年月">{{$moment(viewData.birthday).format('YYYY-MM-DD')}}</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.initMoney}}</el-descriptions-item>
<el-descriptions-item label="当前额度" :span="2">{{viewData.money}}</el-descriptions-item>
<el-descriptions-item label="健身卡使用情况记录" :span="3">
<el-table :data="viewData.usages" border size="small">
<el-table-column label="使用时间" prop="useTime"></el-table-column>
<el-table-column label="使用地点" prop="place"></el-table-column>
<el-table-column label="使用项目" prop="project"></el-table-column>
<el-table-column label="花费额度" prop="useMoney"></el-table-column>
</el-table>
</el-descriptions-item>
</el-descriptions>
<slot></slot>
</div>
`,
store,
data() {
return {
visible: false,
viewData: {
usages: [] // 初始化使用记录数组
},
doneTasks: [],
row: null
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/exerciseCard/apply/findOne', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data || {}
// 确保usages字段存在
if (!this.viewData.usages) {
this.$set(this.viewData, 'usages', [])
}
}
})
},
}
}
@@ -0,0 +1,109 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择"
style="width: 100%"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="initMoney" label="初始额度"></el-table-column>
<el-table-column prop="money" label="剩余额度"></el-table-column>
<el-table-column prop="applyTime" label="录入时间"></el-table-column>
<el-table-column label="操作" fixed="right" width="350px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button v-if="$auth.hasRole('SYSADMIN')" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
<el-button @click="doExportApply(row)" size="mini" type="primary" >证明模板导出</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<exercise-card-info ref="exerciseCardInfoRef"></exercise-card-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
//分页数据
mixins: [initTableMixins],
components: {
"exercise-card-info": EXERCISECARD_INFO
},
data() {
return {
pageDataUrl: "/platform/exerciseCard/mine/pageData",
unionOptions: [],
unitOptions: [],
userOptions: [],
importDialog: false,
checkedFields: []
}
},
components: {
"exercise-card-info": EXERCISECARD_INFO,
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime())
},
methods: {
// 导出示例
doExportApply(row){
this.$downLoad('/platform/exerciseCard/mine/doExportApply?id=' + row.id)
},
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.exerciseCardInfoRef.onOpen(row)
})
},
onEdit(row) {
commonUtil.pjaxPush('/platform/exerciseCard/apply/index', { bizId: row.id})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/exerciseCard/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,154 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</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="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择所属单位" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" icon="el-icon-upload2" @click="openImport">导入人员</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="initMoney" label="初始额度"></el-table-column>
<el-table-column prop="money" label="剩余额度"></el-table-column>
<el-table-column prop="applyTime" label="录入时间"></el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button v-if="$auth.hasRole('SYSADMIN')" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog title="人员导入" :visible.sync="importDialog" width="50%" :close-on-click-modal="false" :close-on-press-escape="false">
<file-import
ref="viewImport"
temp_url="/platform/exerciseCard/query/downloadTemplate"
post_url="/platform/exerciseCard/query/importData"
@flush="successImport"
></file-import>
</el-dialog>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<exercise-card-info ref="exerciseCardInfoRef"></exercise-card-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
//分页数据
mixins: [initTableMixins],
components: {
"exercise-card-info": EXERCISECARD_INFO
},
data() {
return {
pageDataUrl: "/platform/exerciseCard/query/pageData",
unionOptions: [],
unitOptions: [],
userOptions: [],
importDialog: false,
checkedFields: []
}
},
components: {
"exercise-card-info": EXERCISECARD_INFO,
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime())
},
methods: {
openImport() {
this.importDialog = true
},
successImport() {
this.importDialog = false
this.pageData()
},
onView(row) {
this.$refs.guava.view(()=>{
this.$refs.exerciseCardInfoRef.onOpen(row)
})
},
onEdit(row) {
commonUtil.pjaxPush('/platform/exerciseCard/apply/index', { bizId: row.id})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/exerciseCard/query/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
},
created() {
this.pageData()
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
//单位查询
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,422 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.dashboard-container{
height: calc(100vh - 64px - 20px);
display: flex;
flex-direction: column;
}
.stat-dashboard {
padding: 20px 0;
}
.stat-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin: 0 auto;
}
.stat-card {
background: #ffffff;
padding: 24px;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 16px;
position: relative;
overflow: hidden;
}
.stat-card:hover {
transform: translateY(-4px);
}
.stat-icon {
width: 60px;
height: 60px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
flex-shrink: 0;
}
.stat-content {
flex: 1;
}
.stat-number {
font-size: 32px;
font-weight: bold;
line-height: 1;
margin-bottom: 4px;
}
.stat-label {
font-size: 14px;
opacity: 0.9;
font-weight: 500;
}
@media (max-width: 768px) {
.stat-grid {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
padding: 0 15px;
}
.stat-card {
padding: 20px;
}
.stat-number {
font-size: 28px;
}
.stat-icon {
width: 50px;
height: 50px;
font-size: 20px;
}
}
@media (max-width: 480px) {
.stat-grid {
grid-template-columns: 1fr;
padding: 0;
}
.stat-card {
padding: 16px;
}
.stat-number {
font-size: 24px;
}
}
.content-section {
display: flex;
gap: 20px;
flex: 1;
}
.left-section {
flex: 1;
min-width: 0;
}
.right-section {
flex: 1;
display: flex;
flex-direction: column;
gap: 20px;
min-width: 0;
}
.section-card, .chart-card {
background: white;
padding: 20px;
border: 1px solid #f0f0f0;
height: 100%;
display: flex;
flex-direction: column;
}
.chart-card {
flex: 1;
min-height: 0;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 2px solid #f0f0f0;
}
.chart-container {
flex: 1;
/*min-height: 200px;*/
}
/* 响应式布局 */
@media (max-width: 1024px) {
.content-section {
flex-direction: column;
height: auto;
}
.left-section, .right-section {
flex: none;
}
.section-card {
height: 400px;
}
.chart-card {
height: 300px;
}
}
@media (max-width: 768px) {
.content-section {
gap: 15px;
margin-top: 15px;
}
.section-card, .chart-card {
padding: 15px;
border-radius: 8px;
}
.section-title {
font-size: 14px;
margin-bottom: 12px;
}
.chart-container {
min-height: 180px;
}
}
</style>
<div id="app" v-cloak>
<div class="dashboard-container">
<!-- 统计数据展示区域 -->
<div class="stat-dashboard">
<div class="stat-grid">
<div class="stat-card">
<div class="stat-icon medical-icon">
<i class="fa fa-heartbeat"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statCount.subsidyCount || 0 }}</div>
<div class="stat-label">医疗补助数</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon new-member-icon">
<i class="fa fa-user-plus"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statCount.newCount || 0 }}</div>
<div class="stat-label">本年新增会员数</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon total-member-icon">
<i class="fa fa-users"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statCount.count || 0 }}</div>
<div class="stat-label">基金会员总数</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon money-icon">
<i class="fa fa-yen"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ (statCount.totalSubsidyCost || 0).toLocaleString() }}</div>
<div class="stat-label">医疗补助总金额</div>
</div>
</div>
</div>
</div>
<!-- 下方内容区域 -->
<div class="content-section">
<!-- 左侧表格区域 -->
<div class="left-section">
<div class="section-card">
<div class="section-title">各分工会会员数量</div>
<el-table :data="unionCount" style="width: 100%" height="100%">
<el-table-column prop="name" label="分工会名称" min-width="200"></el-table-column>
<el-table-column prop="count" label="会员数量" width="120" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.count > 0 ? 'success' : 'info'">
{{ scope.row.count }}
</el-tag>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 右侧图表区域 -->
<div class="right-section">
<!-- 右上:在职状态图表 -->
<div class="chart-card">
<div class="section-title">在职状态分布</div>
<div id="userStateChart" class="chart-container"></div>
</div>
<!-- 右下:人员类型柱状图 -->
<div class="chart-card">
<div class="section-title">人员类型统计</div>
<div id="personTypeChart" class="chart-container"></div>
</div>
</div>
</div>
</div>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return {
statCount: {
// 医疗补助数
"subsidyCount": 12,
// 新增会员数
"newCount": 3,
//基金会员总数
"count": 3,
// 医疗补助金额
"totalSubsidyCost": 146401
},
unionCount: [],
userStateCount: [],
personTypeCount: [],
userStateChart: null,
personTypeChart: null
}
},
methods: {
// 统计数量
getStatCount() {
this.$axios.post('/platform/fund/dashBoard/statCount').then(res => {
if (res.code === 0) {
this.statCount = res.data
}
})
},
// 各分工会基金会员数
getStatUnionCount() {
this.$axios.post('/platform/fund/dashBoard/statUnionCount').then(res => {
if (res.code === 0) {
this.unionCount = res.data
}
})
},
// 各在职状态基金会员数
getUserStateCount() {
this.$axios.post('/platform/fund/dashBoard/userStateCount').then(res => {
if (res.code === 0) {
this.userStateCount = res.data
this.renderUserStateChart()
}
})
},
// 各人员类型基金会员数
getPersonTypeCount() {
this.$axios.post('/platform/fund/dashBoard/personTypeCount').then(res => {
if (res.code === 0) {
this.personTypeCount = res.data
this.renderPersonTypeChart()
}
})
},
// 渲染在职状态饼图
renderUserStateChart() {
if (this.userStateChart) {
this.userStateChart.destroy()
}
const data = []
if (this.userStateCount && this.userStateCount.length > 0) {
const stateData = this.userStateCount[0]
if (stateData.onDutyCount > 0) {
data.push({ type: '在职', value: stateData.onDutyCount })
}
if (stateData.retireCount > 0) {
data.push({ type: '退休', value: stateData.retireCount })
}
}
this.userStateChart = new G2Plot.Pie('userStateChart', {
data: data,
angleField: 'value',
colorField: 'type',
radius: 0.8,
label: {
type: 'outer',
content: '{name} {percentage}'
},
interactions: [{ type: 'element-active' }],
color: ['#5B8FF9', '#5AD8A6']
})
this.userStateChart.render()
},
// 渲染人员类型柱状图
renderPersonTypeChart() {
if (this.personTypeChart) {
this.personTypeChart.destroy()
}
this.personTypeChart = new G2Plot.Column('personTypeChart', {
data: this.personTypeCount,
xField: 'personType',
yField: 'userCount',
label: {
position: 'middle',
style: {
fill: '#FFFFFF',
opacity: 0.6,
},
},
xAxis: {
label: {
autoHide: true,
autoRotate: false,
},
},
meta: {
personType: {
alias: '人员类型',
},
userCount: {
alias: '人数',
},
},
color: '#5B8FF9'
})
this.personTypeChart.render()
}
},
created() {
this.getStatCount()
this.getStatUnionCount()
this.getUserStateCount()
this.getPersonTypeCount()
},
mounted() {
// 初始化图表
this.$nextTick(() => {
this.renderUserStateChart()
this.renderPersonTypeChart()
})
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,185 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits"
style="width: 100%" placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择所属单位" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<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>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" type="primary" @click="batchJoin">批量设置</el-button>
<el-button size="small" type="primary" @click="showImportDialog = true">批量导入</el-button>
</table-tool>
<el-table :data="tableData" ref="tableRef" row-key="id" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="selection" fixed="left"></el-table-column>
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<excel-import
ref="excelImportRef"
url="/platform/fundMember/batchJoin/batchImport"
template_url="/platform/fundMember/batchJoin/downloadTemplate"
:visible.sync="showImportDialog"
title="导入基金会员数据"
width="700px"
@import-success="doSearch"
:extra_params="{}"
></excel-import>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
tableColumns: [
{ label: "工号", prop: "loginname" },
{ label: "姓名", prop: "username" },
{ label: "性别", prop: "sex" },
{ label: "出生年月", prop: "birthday" },
{ label: "在职状态", prop: "userState", sortable: true },
{ label: "教职工类别", prop: "personType", sortable: true },
{ label: '编制类别', prop: 'preparedBy', sortable: true },
{ label: "所属工会", prop: "unionName" },
{ label: "所属单位", prop: "unitName" },
],
unionOptions: [],
unitOptions: [],
pageForm: {
approval: false,
searchKeyword: '',
unionId: '',
unitId: '',
userStates: [],
personTypes: [],
preparedBys: [],
},
formData: {},
showImportDialog: false
}
},
methods: {
batchJoin() {
const selection = this.$refs.tableRef.selection
if (selection.length === 0) {
this.$message.error("请选择要批量加入的人员")
return
}
this.$confirm("您确定要将勾选的用户批量加入基金会员吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/fundMember/batchJoin/confirm', {
loginNames: JSON.stringify(selection.map(item => item.loginname))
}).then(res => {
if (res.code === 0) {
this.$message.success("批量加入成功")
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
})
}
},
pageData() {
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('/platform/fundMember/batchJoin/pageData', pageForm)
.then(res => {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
})
}
},
created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
const role = this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN")
this.$businessTool.listUnit(role ? null : this.$store.state.user.union.id).then((res) => (this.unitOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,164 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="isJoin" label="申请类型">
<template slot-scope="{row}">
<el-tag v-if="row.isJoin" size="small">加入</el-tag>
<el-tag v-else size="small" type="danger">退出</el-tag>
</template>
</el-table-column>
<el-table-column prop="submitTime" label="申请时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="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>
<fund-member-info ref="fundMemberInfoRef">
<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>
</fund-member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
pageForm: {
approval: false
},
formData: {},
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,122 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="变更类型">
<el-select v-model="pageForm.isJoin" style="width: 100%">
<el-option label="全部" :value="null"></el-option>
<el-option label="加入" :value="true"></el-option>
<el-option label="退出" :value="false"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool :columns.sync="tableColumns">
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'isJoin'" scope="{row}">
<el-tag v-if="row.isJoin" size="small">加入</el-tag>
<el-tag v-else size="small" type="danger">退出</el-tag>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
tableColumns: [
{label: "工号", prop: "loginName"},
{label: "姓名", prop: "userName"},
{label: "性别", prop: "sex"},
{label: "出生年月", prop: "birthday"},
{label: "参加工作日期", prop: "joinWorkTime"},
{label: "退休日期", prop: "retireTime"},
{label: "所属工会", prop: "unionName"},
{label: "变更类型", prop: "isJoin"},
{label: "变更来源", prop: "changeOrigin"},
{label: "变更时间", prop: "changeTime"}
],
unionOptions: [],
pageForm: {
approval: false,
isJoin: null
},
formData: {},
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
exportExcel() {
if (!this.pageForm.year) {
this.$message.error('请选择年度再导出')
return
}
this.$downLoad('/platform/fundMember/query/exportExcel', {
year: this.pageForm.year,
unionId: this.pageForm.unionId
})
}
},
created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,110 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
tableColumns: [
{label: "年度", prop: "year"},
{label: "工号", prop: "loginName"},
{label: "姓名", prop: "userName"},
{label: "性别", prop: "sex"},
{label: "出生年月", prop: "birthday"},
{label: "在职状态", prop: "userState"},
{label: "所属工会", prop: "unionName"},
{label: "加入时间", prop: "joinTime"},
],
unionOptions: [],
pageForm: {
approval: false
},
formData: {},
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
exportExcel() {
if (!this.pageForm.year) {
this.$message.error('请选择年度再导出')
return
}
this.$downLoad('/platform/fundMember/query/exportExcel', {
year: this.pageForm.year,
unionId: this.pageForm.unionId
})
}
},
created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,102 @@
const fundMemberInfo = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border>
<el-descriptions-item label="姓名">{{viewData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
<el-descriptions-item label="性别">{{viewData.sex}}</el-descriptions-item>
<el-descriptions-item label="出生年月">{{viewData.birthday}}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{viewData.idCard}}</el-descriptions-item>
<el-descriptions-item label="参加工作时间">{{viewData.joinWorkTime}}</el-descriptions-item>
<el-descriptions-item label="退休时间">{{viewData.retireTime}}</el-descriptions-item>
<el-descriptions-item label="家庭住址">{{viewData.address}}</el-descriptions-item>
<el-descriptions-item label="手机电话">{{viewData.mobile}}</el-descriptions-item>
<el-descriptions-item label="住宅号码">{{viewData.homePhone}}</el-descriptions-item>
<el-descriptions-item label="照片">
<img :src="viewData.avatar" alt="" style="width: 120px;height: 150px" v-if="viewData.avatar">
</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
}}({{task.ext.initiatorAccount}})
</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName
}}({{task.taskFormData.loginName}})
</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
task.taskFormData.opinion }}
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
store,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data(){
return{
visible: false,
viewData: {},
doneTasks: [],
row: null
}
},
methods:{
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
this.getDoneTasks()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/fundMember/common/info', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
// 查看流程图
openChart() {
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
}
}
}
@@ -0,0 +1,122 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"
style="width: 100%"></el-date-picker>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="isJoin" label="申请类型">
<template slot-scope="{row}">
<el-tag v-if="row.isJoin" size="small">加入</el-tag>
<el-tag v-else size="small" type="danger">退出</el-tag>
</template>
</el-table-column>
<el-table-column prop="submitTime" label="申请时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="exportDocx(row.id)" 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>
<!-- v-if="row.taskKey === 'startTask' || !row.instanceId"-->
<el-button @click="onDelete(row.id)"
size="mini" type="danger">删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<fund-member-info ref="fundMemberInfoRef"></fund-member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
onEdit(row) {
commonUtil.pjaxPush('/platform/fundMember/write?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/fundMember/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
exportDocx(id){
this.$downLoad("/platform/fundMember/common/exportDocx", {id})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,221 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<!-- <search-item label="年度">-->
<!-- <el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"-->
<!-- style="width: 100%"></el-date-picker>-->
<!-- </search-item>-->
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits"
style="width: 100%" placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" @change="doSearch" style="width: 100%"
placeholder="请选择所属单位" clearable>
<el-option v-for="item in unitOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<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>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" type="primary" @click="backup">备份会员名单</el-button>
<el-button size="small" type="primary" @click="exportExcel">导出登记汇总表</el-button>
<el-button size="small" type="primary" @click="exportNewMemberExcel">导出本年新会员名单</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
<template v-else-if="column.prop === 'isJoin'" scope="{row}">
<el-tag v-if="row.isJoin" size="small">加入</el-tag>
<el-tag v-else size="small" type="danger">退出</el-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 @click="onQuit(row)" size="mini" type="danger">退会</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<fund-member-info ref="fundMemberInfoRef"></fund-member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
tableColumns: [
{ label: "工号", prop: "loginName" },
{ label: "姓名", prop: "userName" },
{ label: "性别", prop: "sex" },
{ label: "出生年月", prop: "birthday" },
{ label: "在职状态", prop: "userState", sortable: true },
{ label: "教职工类别", prop: "personType", sortable: true },
{ label: '编制类别', prop: 'preparedBy', sortable: true },
{ label: "所属工会", prop: "unionName" },
{ label: "所属单位", prop: "unitName" },
{ label: "加入时间", prop: "joinTime" },
],
unionOptions: [],
unitOptions: [],
pageForm: {
approval: false
},
formData: {},
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
// 退会
onQuit(row) {
this.$confirm('您确定要将' + row.userName + '退会吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/fundMember/query/quit', {
loginName: row.loginName
}).then((res) => {
if (res.code === 0) {
this.$message.success('退会成功')
this.pageData()
}
})
})
},
// 备份会员
backup() {
// 此处需要选择年份
this.$prompt('请输入备份会员至哪个年度', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[0-9]{4}$/,
inputErrorMessage: '请输入4位数的年份'
}).then(({value}) => {
this.$axios.post('/platform/fundMember/query/backup', {
year: value
}).then((res) => {
if (res.code === 0) {
this.$message.success('备份成功')
}
})
})
},
// 导出登记汇总表
exportExcel() {
if (!this.pageForm.year) {
this.$message.error('请选择年度再导出')
return
}
this.$downLoad('/platform/fundMember/query/exportExcel', {
year: this.pageForm.year,
unionId: this.pageForm.unionId
})
},
// 导出本年新会员名单
exportNewMemberExcel(){
this.$downLoad('/platform/fundMember/query/exportNewMemberExcel')
},
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() {
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('/platform/fundMember/query/pageData', pageForm)
.then(res => {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
})
}
},
created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,178 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="工号/姓名">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入工号或者姓名查询"
clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="isJoin" label="申请类型">
<template slot-scope="{row}">
<el-tag v-if="row.isJoin" size="small">加入</el-tag>
<el-tag v-else size="small" type="danger">退出</el-tag>
</template>
</el-table-column>
<el-table-column prop="submitTime" label="申请时间"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="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>
<fund-member-info ref="fundMemberInfoRef">
<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>
</fund-member-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
pageForm: {
approval: false
},
formData: {},
showApprovalForm: false,
unionOptions: []
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
},
created() {
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,261 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<snaker-start slot="header" label="基金会员入会申请" define_key="FUND_MEMBER"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名" prop="userName">
<el-input v-model="formData.userName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工号" prop="loginName">
<el-input v-model="formData.loginName" placeholder="请输入工号" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="出生年月" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择出生年月"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="sex" size="small">
<el-radio-group v-model="formData.sex">
<el-radio label="男" border></el-radio>
<el-radio label="女" border></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="身份证号码" prop="idCard">
<el-input v-model="formData.idCard" placeholder="请输入身份证号码"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="家庭住址" prop="address">
<el-input v-model="formData.address" placeholder="请输入家庭住址"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="参加工作时间" prop="joinWorkTime">
<el-date-picker
v-model="formData.joinWorkTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择参加工作时间"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="退休时间" prop="retireTime">
<el-date-picker
v-model="formData.retireTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择退休时间"
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="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" maxlength="11"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="住宅号码" prop="homePhone">
<el-input v-model="formData.homePhone" placeholder="请输入住宅电话" maxlength="20"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="照 片">
<file-upload
style="--upload-width: 150px;--upload-height:176px"
:value.sync="formData.avatar"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<!-- <el-form-item>-->
<!-- <el-checkbox v-model="isAgree">-->
<!-- 本人自愿申请参加南昌大学教职工医疗互助“爱心”基金会,同意并遵守《南昌大学教职工医疗互助“爱心”基金管理办法》的相关规定。-->
<!-- </el-checkbox>-->
<!-- </el-form-item>-->
</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"),
formData: {},
formRules: {
userName: [{required: true, message: '请输入姓名', trigger: 'blur'}],
loginName: [{required: true, message: '请输入工资号', trigger: 'blur'}],
birthday: [{required: true, message: '请选择出生年月', trigger: 'blur'}],
sex: [{required: true, message: '请选择性别', trigger: 'blur'}],
idCard: [{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]|3[0-1])\d{3}[Xx\d]$/,
message: '请输入正确的身份证号码',
trigger: 'blur'
}
],
address: [{required: true, message: '请输入家庭住址', trigger: 'blur'}],
joinWorkTime: [{required: true, message: '请选择参加工作时间', trigger: 'blur'}],
retireTime: [{required: false, message: '请选择退休时间', trigger: 'blur'}],
mobile: [{required: true, message: '请输入手机号码', trigger: 'blur'},
{
pattern: /^1[3456789]\d{9}$/,
message: '请输入正确的手机号码',
trigger: 'blur'
}],
homePhone: [
/*{required: true, message: '请输入住宅号码', trigger: 'blur'},
{
pattern: /^(0\d{2,3}-?)?\d{7,8}$/,
message: '请输入正确的住宅号码',
trigger: 'blur'
}*/
],
avatar: [{required: false, message: '请上传照片', trigger: 'blur'}]
},
isAgree: false
}
},
methods: {
// 保存
// onSave() {
// this.$confirm("您确定保存吗?", "提示", {
// confirmButtonText: "确定",
// cancelButtonText: "取消",
// type: "warning"
// }).then(() => {
// this.$axios.post('/platform/suggestionBox/write/save', {data: JSON.stringify(this.formData)}).then(res => {
// if (res.code === 0) {
// this.$message.success("保存成功")
// commonUtil.pjaxPush('/platform/suggestionBox/mine')
// }
// })
// })
// },
// 提交
onSubmit() {
this.$refs.formRef.validate(valid => {
if (!valid) return
// if (!this.isAgree) {
// this.$message.error("请先阅读并同意《南昌大学教职工医疗互助“爱心”基金管理办法》")
// return
// }
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/fundMember/write/submit', {
data: JSON.stringify(this.formData)
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/fundMember/mine')
}
})
})
})
},
onFinishTask() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/fundMember/write/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/fundMember/mine')
}
})
})
},
// 初始化
init() {
if (this.bizId) {
this.$axios.post("/platform/fundMember/write/info", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
} else {
const {username, loginname, sex, birthday, mobile, union, userState, idCard} = this.$store.state.user
this.formData = {
userName: username,
loginName: loginname,
sex: sex,
birthday: birthday,
mobile: mobile,
unionId: union?.id,
unionName: union?.name,
userState: userState,
idCard: idCard
}
}
},
},
created() {
this.init()
if(!this.bizId){
this.$axios.post('/platform/fundMember/write/validateApply')
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,550 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.analysis-page {
background: #f6f6f6;
min-height: calc(100vh - 64px);
padding: 20px;
}
.stats-row {
margin-bottom: 20px;
}
.stat-card {
text-align: center;
padding: 30px 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
transition: transform 0.3s ease;
cursor: pointer;
height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
}
.stat-card:hover {
transform: translateY(-5px);
}
.stat-card.card-blue {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.stat-card.card-green {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.stat-card.card-orange {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.stat-card.card-purple {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
.stat-number {
font-size: 36px;
font-weight: bold;
margin-bottom: 8px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.stat-label {
font-size: 16px;
opacity: 0.9;
font-weight: 500;
}
.chart-card {
margin-bottom: 20px;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.chart-title {
font-size: 18px;
font-weight: 600;
color: #303133;
}
.growth-tag {
font-size: 12px;
padding: 4px 8px;
border-radius: 4px;
font-weight: bold;
}
.chart-container {
height: 350px;
width: 100%;
}
.comparison-table {
margin-top: 20px;
}
.el-table .growth-cell {
font-weight: bold;
}
.growth-positive {
color: #67c23a;
}
.growth-negative {
color: #f56c6c;
}
.growth-zero {
color: #909399;
}
/* 响应式设计 */
@media (max-width: 768px) {
.analysis-page {
padding: 10px;
}
.stat-card {
padding: 20px 15px;
height: 100px;
}
.stat-number {
font-size: 28px;
}
.stat-label {
font-size: 14px;
}
.chart-container {
height: 280px;
}
.chart-header {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
}
@media (max-width: 480px) {
.stat-card {
padding: 15px 10px;
height: 90px;
}
.stat-number {
font-size: 24px;
}
.stat-label {
font-size: 12px;
}
.chart-container {
height: 250px;
}
}
/* 加载状态样式 */
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
}
.loading-text {
margin-left: 10px;
color: #606266;
font-size: 14px;
}
/* 错误状态样式 */
.error-container {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
color: #f56c6c;
}
.error-text {
margin-left: 10px;
font-size: 14px;
}
</style>
<div id="app" v-cloak>
<div class="analysis-page">
<!-- 加载状态 -->
<div v-if="loading" class="loading-container">
<i class="el-icon-loading"></i>
<span class="loading-text">数据加载中...</span>
</div>
<!-- 错误状态 -->
<div v-else-if="error" class="error-container">
<i class="el-icon-warning"></i>
<span class="error-text">{{ error }}</span>
</div>
<!-- 主要内容 -->
<div v-else>
<!-- 统计卡片 -->
<el-row :gutter="20" class="stats-row">
<el-col :xs="24" :sm="12" :md="6">
<div class="stat-card card-blue">
<div class="stat-number">{{ totalStats.totalPeople | number }}</div>
<div class="stat-label">总补助人数</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6">
<div class="stat-card card-green">
<div class="stat-number">{{ (totalStats.totalAmount / 10000) | currency }}</div>
<div class="stat-label">总补助金额(万元)</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6">
<div class="stat-card card-orange">
<div class="stat-number">{{ totalStats.avgAmount | currency }}</div>
<div class="stat-label">平均补助金额(元)</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6">
<div class="stat-card card-purple">
<div class="stat-number">{{ totalStats.yearCount }}</div>
<div class="stat-label">统计年度数</div>
</div>
</el-col>
</el-row>
<!-- 图表区域 -->
<el-row :gutter="20">
<el-col :xs="24" :lg="12">
<el-card class="chart-card" shadow="hover">
<div class="chart-header">
<span class="chart-title">年度补助人数趋势</span>
<el-tag v-if="growthRates.people !== null"
:type="getGrowthTagType(growthRates.people)"
class="growth-tag">
{{ growthRates.people > 0 ? '+' : '' }}{{ growthRates.people }}%
</el-tag>
</div>
<div ref="peopleChart" class="chart-container"></div>
</el-card>
</el-col>
<el-col :xs="24" :lg="12">
<el-card class="chart-card" shadow="hover">
<div class="chart-header">
<span class="chart-title">年度补助金额趋势</span>
<el-tag v-if="growthRates.amount !== null"
:type="getGrowthTagType(growthRates.amount)"
class="growth-tag">
{{ growthRates.amount > 0 ? '+' : '' }}{{ growthRates.amount }}%
</el-tag>
</div>
<div ref="amountChart" class="chart-container"></div>
</el-card>
</el-col>
</el-row>
<!-- 对比表格 -->
<el-card class="comparison-table" shadow="hover">
<div slot="header">
<span class="chart-title">年度对比分析</span>
</div>
<el-table :data="yearlyComparison" stripe style="width: 100%">
<el-table-column prop="year" label="年度" width="100" align="center"></el-table-column>
<el-table-column prop="people" label="补助人数" align="center">
<template slot-scope="scope">
{{ scope.row.people | number }}
</template>
</el-table-column>
<el-table-column label="人数增长率" align="center" width="120">
<template slot-scope="scope">
<span v-if="scope.row.peopleGrowthRate !== null"
:class="['growth-cell', getGrowthClass(scope.row.peopleGrowthRate)]">
{{ scope.row.peopleGrowthRate > 0 ? '+' : '' }}{{ scope.row.peopleGrowthRate }}%
</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="补助金额(万元)" align="center">
<template slot-scope="scope">
{{ (scope.row.amount / 10000) | currency }}
</template>
</el-table-column>
<el-table-column label="金额增长率" align="center" width="120">
<template slot-scope="scope">
<span v-if="scope.row.amountGrowthRate !== null"
:class="['growth-cell', getGrowthClass(scope.row.amountGrowthRate)]">
{{ scope.row.amountGrowthRate > 0 ? '+' : '' }}{{ scope.row.amountGrowthRate }}%
</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="人均补助(元)" align="center">
<template slot-scope="scope">
{{ scope.row.avgAmount | currency }}
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</div>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return {
loading: true,
error: null,
yearlyData: [],
totalStats: {
totalPeople: 0,
totalAmount: 0,
avgAmount: 0,
yearCount: 0
},
growthRates: {
people: null,
amount: null
},
peopleChart: null,
amountChart: null
}
},
computed: {
yearlyComparison() {
return this.yearlyData.map((item, index) => {
const prevItem = index > 0 ? this.yearlyData[index - 1] : null;
return {
year: item.year,
people: item.people,
amount: item.amount,
avgAmount: item.people > 0 ? Math.round(item.amount / item.people) : 0,
peopleGrowthRate: prevItem ?
Math.round(((item.people - prevItem.people) / prevItem.people) * 100) : null,
amountGrowthRate: prevItem ?
Math.round(((item.amount - prevItem.amount) / prevItem.amount) * 100) : null
};
});
}
},
filters: {
number(value) {
if (!value && value !== 0) return '0';
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
},
currency(value) {
if (!value && value !== 0) return '0.00';
return parseFloat(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
},
mounted() {
this.loadData();
},
methods: {
async loadData() {
try {
this.loading = true;
this.error = null;
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000));
// 模拟数据
this.yearlyData = [
{ year: 2020, people: 1250, amount: 3750000 },
{ year: 2021, people: 1380, amount: 4140000 },
{ year: 2022, people: 1520, amount: 4560000 },
{ year: 2023, people: 1680, amount: 5040000 },
{ year: 2024, people: 1850, amount: 5550000 }
];
this.calculateTotalStats();
this.calculateGrowthRates();
// 等待DOM更新后渲染图表
this.$nextTick(() => {
this.renderCharts();
});
} catch (error) {
this.error = '数据加载失败:' + error.message;
} finally {
this.loading = false;
}
},
calculateTotalStats() {
this.totalStats.totalPeople = this.yearlyData.reduce((sum, item) => sum + item.people, 0);
this.totalStats.totalAmount = this.yearlyData.reduce((sum, item) => sum + item.amount, 0);
this.totalStats.avgAmount = this.totalStats.totalPeople > 0 ?
Math.round(this.totalStats.totalAmount / this.totalStats.totalPeople) : 0;
this.totalStats.yearCount = this.yearlyData.length;
},
calculateGrowthRates() {
if (this.yearlyData.length >= 2) {
const firstYear = this.yearlyData[0];
const lastYear = this.yearlyData[this.yearlyData.length - 1];
this.growthRates.people = Math.round(
((lastYear.people - firstYear.people) / firstYear.people) * 100
);
this.growthRates.amount = Math.round(
((lastYear.amount - firstYear.amount) / firstYear.amount) * 100
);
}
},
renderCharts() {
// 确保DOM元素存在后再渲染图表
if (this.$refs.peopleChart && this.$refs.amountChart) {
this.renderPeopleChart();
this.renderAmountChart();
}
},
renderPeopleChart() {
// 销毁已存在的图表
if (this.peopleChart) {
this.peopleChart.destroy();
}
const data = this.yearlyData.map(item => ({
year: item.year.toString(),
value: item.people
}));
this.peopleChart = new G2Plot.Line(this.$refs.peopleChart, {
data,
xField: 'year',
yField: 'value',
point: {
size: 5,
shape: 'diamond',
style: {
fill: 'white',
stroke: '#5B8FF9',
lineWidth: 2,
},
},
tooltip: {
showMarkers: false,
formatter: (datum) => {
return { name: '补助人数', value: datum.value + ' 人' };
},
},
color: '#5B8FF9',
lineStyle: {
lineWidth: 3,
},
smooth: true,
animation: {
appear: {
animation: 'path-in',
duration: 1000,
},
},
});
this.peopleChart.render();
},
renderAmountChart() {
// 销毁已存在的图表
if (this.amountChart) {
this.amountChart.destroy();
}
const data = this.yearlyData.map(item => ({
year: item.year.toString(),
value: item.amount / 10000 // 转换为万元
}));
this.amountChart = new G2Plot.Line(this.$refs.amountChart, {
data,
xField: 'year',
yField: 'value',
point: {
size: 5,
shape: 'diamond',
style: {
fill: 'white',
stroke: '#5AD8A6',
lineWidth: 2,
},
},
tooltip: {
showMarkers: false,
formatter: (datum) => {
return { name: '补助金额', value: datum.value + ' 万元' };
},
},
color: '#5AD8A6',
lineStyle: {
lineWidth: 3,
},
smooth: true,
animation: {
appear: {
animation: 'path-in',
duration: 1000,
},
},
});
this.amountChart.render();
},
getGrowthTagType(rate) {
if (rate > 0) return 'success';
if (rate < 0) return 'danger';
return 'info';
},
getGrowthClass(rate) {
if (rate > 0) return 'growth-positive';
if (rate < 0) return 'growth-negative';
return 'growth-zero';
}
},
beforeDestroy() {
if (this.peopleChart) {
this.peopleChart.destroy();
}
if (this.amountChart) {
this.amountChart.destroy();
}
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,166 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="请选择年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" type="primary" @click="showImportDialog = true">导入补助数据</el-button>
<el-button size="small" type="primary" @click="exportExcel">导出补助公示表</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%" show-summary
:summary-method="getSummaries">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<!-- <el-table-column label="操作" fixed="right" width="200px">-->
<!-- <template slot-scope="{row}">-->
<!-- <el-button @click="openView(row)" size="mini" type="primary">查看</el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table>
</el-card>
<template #view>
</template>
</guava>
<excel-import
ref="excelImportRef"
url="/platform/fundSubsidy/query/importExcel"
template_url="/platform/fundSubsidy/query/downloadTemplate"
:visible.sync="showImportDialog"
title="导入数据"
width="700px"
@import-success="doSearch"
:extra_params="{}"
></excel-import>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {},
data() {
return {
tableColumns: [
{label: "工号", prop: "loginName"},
{label: "姓名", prop: "userName"},
{label: "门诊费用", prop: "outpatientCost"},
{label: "住院费用", prop: "hospitalCost"},
{label: "合计", prop: "totalCost"},
{label: "不予补助金额", prop: "noSubsidyCost"},
{label: "门诊医保已报金额", prop: "outpatientMedicalInsuranceReportedCost"},
{label: "住院医保已报金额", prop: "hospitalMedicalInsuranceReportedCost"},
{label: "自费金额", prop: "selfCost"},
{label: "补助金额", prop: "subsidyCost"},
],
unionOptions: [],
pageForm: {},
showImportDialog: false
}
},
methods: {
pageData() {
this.tableLoading = true
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
this.tableLoading = false
if (res.code === 0) {
this.tableData = res.data
}
})
},
getSummaries(param) {
const {columns, data} = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计';
}else if (index === 1) {
sums[index] = '';
}else if(index === columns.length - 1){
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] += ' 元';
} else {
sums[index] = 'N/A';
}
}
});
return sums;
},
openView(row) {
this.$refs.guava.edit(() => {
})
},
exportExcel() {
if (!this.pageForm.year) {
this.$message.error('请选择年度再导出')
return
}
this.$downLoad('/platform/fundSubsidy/query/exportExcel', {
year: this.pageForm.year,
unionId: this.pageForm.unionId
})
}
},
created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,100 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.card-shadow {
border-radius: 20px;
width: 40%;
margin: 0 auto;
transform: translateY(130px);
}
</style>
<div id="app" v-cloak>
<el-card shadow="never" class="card-shadow">
<template #header>
<h3 style="color: var(--color-primary)">量化考核全局配置</h3>
</template>
<el-form :model="formData" :rules="formRules" label-width="200px" ref="formRef" label-position="top" size="small">
<el-form-item label="线上成绩占比" prop="onLine">
<el-input :min="0" :max="100" v-model="formData.onLine" type="number">
<template slot="append">%</template>
</el-input>
</el-form-item>
<el-form-item label="线下成绩占比" prop="offLine">
<el-input :min="0" :max="100" v-model="formData.offLine" type="number">
<template slot="append">%</template>
</el-input>
</el-form-item>
<el-form-item label="是否需要分工会自评" prop="selfAssessment">
<el-radio-group v-model="formData.selfAssessment">
<el-radio-button :label="true">需要</el-radio-button>
<el-radio-button :label="false">不需要</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="是否显示单项分" prop="displaySingleItem">
<el-radio-group v-model="formData.displaySingleItem">
<el-radio-button :label="true">显示</el-radio-button>
<el-radio-button :label="false">不显示</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button type="primary" @click="submit">保存</el-button>
</el-row>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
data() {
return {
unitOptions: [],
formData: {
onLine: 0,
offline: 0,
selfAssessment: true,
displaySingleItem: true
},
formRules: {
onLine: [{ required: true, message: "请输入线上成绩占比", trigger: ["blur"] }],
offline: [{ required: true, message: "请输入线下成绩占比", trigger: ["blur"] }],
selfAssessment: [{ required: true, message: "请选择是否需要分工会自评", trigger: ["blur"] }],
displaySingleItem: [{ required: true, message: "请选择是否显示单项分", trigger: ["blur"] }]
}
}
},
methods: {
init() {
this.$axios.post(loc() + "/fetch").then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
},
submit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios
.post(loc() + "/submit", this.formData)
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.init()
} else {
this.$message.error(res.msg)
}
})
}
})
},
},
created() {
this.init()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,195 @@
<!--#
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 v-model="pageForm.annual" type="annual" value-format="yyyy" placeholder="请选择"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="考核名称">
<el-select v-model="pageForm.khid"
@change="doSearch"
style="width: 100%"
placeholder="请选择考核">
<el-option
v-for="item in kh"
:key="item.id"
:label="item.assessment"
:value="item.id">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="得分列表">
<el-button @click="onExport" icon="el-icon-download" size="small" type="primary">导出</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="record_id"
v-loading="tabLoading">
<el-table-column align="center" header-align="center" label="序号" width="100px">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column label="年度" prop="annual" header-align="center"
align="center">
</el-table-column>
<el-table-column label="分工会名称" prop="unionname" header-align="center"
show-overflow-tooltip
align="center" sortable></el-table-column>
<el-table-column label="线上得分" prop="xgh_score" header-align="center"
show-overflow-tooltip
align="center" sortable></el-table-column>
<el-table-column :label="'线上最终得分' + (examConfig.onLine ? '' + examConfig.onLine + '%' : '')" prop="onLineFinalScore" header-align="center"
show-overflow-tooltip
align="center" sortable></el-table-column>
<el-table-column label="线下得分" prop="offLineScore" header-align="center"
show-overflow-tooltip
align="center" sortable>
<template scope="scope">
<div v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')">
<div v-if="rowDataEdit && rowDataIndex==scope.$index">
<el-input placeholder="请输入线下得分"
autofocus
size="mini"
:ref="'input'+scope.row.record_id"
v-model="scope.row.offLineScore" @blur="openEdit(scope.row)"></el-input>
</div>
<div v-else title="点击编辑" @click="doRowDataEditMobile(scope.row,scope.$index)">
{{scope.row.offLineScore}}
<i class="el-icon-edit" style="color: #0a84ff"></i>
</div>
</div>
<div v-else>
{{scope.row.offLineScore}}
</div>
</template>
</el-table-column>
<el-table-column :label="'线下最终得分' + (examConfig.offLine ? '' + examConfig.offLine + '%' : '')" prop="offLineFinalScore" header-align="center"
show-overflow-tooltip
align="center" sortable></el-table-column>
<el-table-column label="最终考核得分" prop="totalScore" header-align="center"
show-overflow-tooltip
align="center" sortable></el-table-column>
<el-table-column label="排名" prop="sort" header-align="center"
show-overflow-tooltip
align="center" sortable></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
tabLoading: false,
tableData: [],
kh: [],
pageForm: {
khid: "",
annual: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
},
pickerOptions: {
disabledDate(time) {
return (
time.getFullYear() > new Date().getFullYear()
);
}
},
examConfig: {},
rowDataEdit: false,
rowDataIndex: null,
}
},
methods: {
onExport() {
this.$downLoad('/platform/ghkh/khph/downloadList', this.pageForm)
},
async openEdit(row) {
this.rowDataEdit = !this.rowDataEdit
const res = await $.post(loc() + "/doEditScore", {id: row.record_id, score: row.offLineScore, khId: this.pageForm.khid})
if(res.code === 0) {
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
this.doSearch()
},
async getKh() {
const res = await this.$axios.post("/platform/ghkh/khph/getKh", {"annual": this.pageForm.annual})
if (res.code === 0) {
if (res.data.length !== 0) {
this.kh = res.data
this.pageForm.khid = this.kh[0].id
} else {
this.kh = []
this.pageForm.khid = ""
}
}
},
doRowDataEditMobile(row, index) {
this.tableData.map(v => {
if (row.record_id === v.record_id) {
this.rowDataIndex = index
this.rowDataEdit = !this.rowDataEdit;
this.$nextTick(() => {
const ref = 'input' + row.record_id
console.log(this.$refs[ref])
this.$refs[ref][0].focus();
})
}
})
},
async khSearch() {
await this.getKh()
this.pageData();
},
pageData() {
this.$axios.post(base + "/platform/ghkh/khph/pageData", this.pageForm).then(res => {
this.tabLoading = false
if (res.code === 0) {
this.tableData = res.data.list;
this.pageForm.totalCount = res.data.totalCount;
} else {
this.$message({
message: res.msg,
type: 'error'
});
}
}).catch(error => {
this.tabLoading = false
});
this.tabLoading = true
},
fetchConfig() {
this.$axios.post("/platform/exam/config/fetch").then((res) => {
if (res.code === 0) {
this.examConfig = res.data
}
})
},
},
async created() {
this.fetchConfig()
this.pageForm.annual = new Date().getFullYear() + ""
await this.getKh()
this.pageData();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,261 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
#app {
overflow-y: unset !important;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="khSearch"
:picker-options="pickerOptions"
v-model="pageForm.annual"
type="year"
value-format="yyyy"
placeholder="请选择年度"
style="width: 100%">
</el-date-picker>
</search-item>
<search-item label="考核名称">
<el-input
v-model="pageForm.assessment"
placeholder="请输入考核名称查询"
clearable
style="width: 100%">
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="考核指标"></table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id" v-loading="tabLoading">
<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"
:width="column.width"
header-align="center"
show-overflow-tooltip>
<template scope="{row}" v-if="column.prop=='startTime'">
<span>{{row.startDateTime}} - {{row.endDateTime}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='disabled'">
<el-switch
v-model="row.disabled"
active-color="#13ce66"
inactive-color="#ff4949"
@change="(val) => toggleEnable(val, row.id)">
</el-switch>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" fixed="right" width="250px">
<template scope="scope">
<el-button size="mini" type="primary" @click="openView(scope.row.id)">查看</el-button>
<el-button size="mini" type="primary" @click="openEdit(scope.row.id)">编辑</el-button>
<el-button size="mini" type="danger" @click="doDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit_func>
<el-button type="primary" @click="doEdit('save')">暂存</el-button>
<el-button type="primary" @click="doEdit('submit')">提交</el-button>
</template>
<template #edit_footer>
<el-button type="primary" @click="doEdit('save')">暂存</el-button>
<el-button type="primary" @click="doEdit('submit')">提交</el-button>
</template>
<template #edit>
<kh-zb :form_data="formData" @change="v=>{this.formData=v}"></kh-zb>
</template>
<template #view>
<kh-zb :form_data="viewData" :is_view="true"></kh-zb>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
tableColumns: [
{ prop: 'annual', label: '年度' },
{ prop: 'assessment', label: '考核名称' },
{ prop: 'startTime', label: '填报时间', width: 300 },
{ prop: 'createTime', label: '创建时间' },
{ prop: 'createUserName', label: '创建人' },
{ prop: 'disabled', label: '是否开启' },
],
tabLoading: false,
loading: true,
activeName: '1',
tableData: [],
formData: {},
viewData: {
nrs: [{
bzs: [{}]
}],
},
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
},
pickerOptions: {
disabledDate(time) {
return (
time.getFullYear() > new Date().getFullYear()
);
}
},
pageDataUrl: "/platform/ghkh/khzb/pageData"
}
},
components: {
'kh-zb': httpVueLoader('/components/module/kh/KhZb.vue?v=' + new Date().getTime())
},
methods: {
toggleEnable(enable, id) {
this.$axios.post("/platform/ghkh/khzb/toggleEnable", {id, enable}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg);
} else {
this.$message.error(res.msg);
const row = this.tableData.find(item => item.id === id);
if (row) {
row.disabled = !enable;
}
}
})
},
async getKh() {
this.$axios.post("/platform/ghkh/khph/getKh", {"annual": this.pageForm.annual}).then(res => {
if (res.code === 0) {
if (res.data.length != 0) {
this.kh = res.data
this.pageForm.khid = this.kh[0].id
} else {
this.kh = []
this.pageForm.khid = ""
}
}
})
},
async khSearch() {
await this.getKh()
},
async openEdit(id) {
this.$axios.post('/platform/ghkh/khzb/edit', {id}).then(res => {
if (res.code === 0) {
this.formData = res.data;
this.$refs.guava.edit();
}
})
},
doEdit(type) {
let flag = true
if (!this.formData.annual) {
this.$message({message: "年度不能为空", type: 'error'})
return
}
if (!this.formData.assessment) {
this.$message({message: "考核名称不能为空", type: 'error'})
return
}
if(type === 'submit') {
this.formData.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (!nr.content) {
this.$message({message: "考核内容不能为空", type: 'error'})
flag = false
throw Error()
} else if (!bz.inspection) {
this.$message({message: "考核标准不能为空", type: 'error'})
flag = false;
throw Error()
}
})
})
}
if(this.formData.appealTimeRange && this.formData.appealTimeRange.length > 0) {
this.$set(this.formData, 'startApplyTime', this.formData.appealTimeRange[0])
this.$set(this.formData, 'endApplyTime', this.formData.appealTimeRange[1])
}
if(this.formData.fillTimeRange && this.formData.fillTimeRange.length > 0) {
this.$set(this.formData, 'startDateTime', this.formData.fillTimeRange[0])
this.$set(this.formData, 'endDateTime', this.formData.fillTimeRange[1])
}
if (flag) {
this.$axios.post(base + "/platform/ghkh/khzb/doEdit", {kh_zb: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message({
message: res.msg,
type: 'success'
});
}
this.$refs.guava.index()
this.pageData()
})
}
},
doDelete(id) {
this.$confirm('您确定要删除吗!', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: (a, b) => {
if ("confirm" == a) {//确认后再执行
this.$axios.post("/platform/ghkh/khzb/delete", {id: id}).then(res => {
if (res.code === 0) {
this.$message({
message: res.msg,
type: 'success'
});
this.pageData();
}
})
}
}
});
},
openView(id) {
this.loading = true;
this.$axios.post('/platform/ghkh/khzb/edit', {id}).then(res => {
if (res.code === 0) {
this.viewData = res.data;
this.$refs.guava.view(); // 数据设置完成后再调用view方法
}
this.loading = false;
}).catch(error => {
this.loading = false;
});
}
},
async created() {
this.pageData();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,349 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<div class="btn-group tool-button mt5">
<el-date-picker
@change="khSearch"
:picker-options="pickerOptions"
v-model="pageForm.annual"
type="year"
value-format="yyyy"
placeholder="选择年度">
</el-date-picker>
</div>
<div class="btn-group tool-button mt5">
<el-select placeholder="所属工会" v-model="pageForm.unionId" style="width: 100%;"
clearable="true"
@change="flushUnits" @clear="flushUnits"
v-if="${@shiro.hasRole('sysadmin')||@shiro.hasRole('A06')||@shiro.hasRole('H03')}"
filterable="true">
<el-option v-for="item in unions" :label="item.unionname" :value="item.id"></el-option>
</el-select>
</div>
<div class="btn-group tool-button mt5">
<el-button type="primary" icon="el-icon-search" @click="doSearch"></el-button>
</div>
</el-card>
<el-card shadow="never" class="mt20">
<el-table :data="tableData" style="width: 100%" row-key="id"
v-loading="tabLoading">
<el-table-column align="center" header-align="center" label="序号" width="100px">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column label="年度" prop="annual" header-align="center" width="300px" sortable
align="center">
<template scope="scope">
{{scope.row.annual}}
</template>
</el-table-column>
<el-table-column label="考核名称" prop="assessment" header-align="center" show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="基层工会名称" prop="unionname" header-align="center" show-overflow-tooltip
align="center">
<template scope="{row}">
({{row.unioncode}}){{row.unionname}}
</template>
</el-table-column>
<el-table-column label="标准总分" prop="bzf" header-align="center" show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="自评得分" prop="zp_score" header-align="center" show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="总部工会得分" prop="xgh_score" header-align="center" show-overflow-tooltip
align="center"></el-table-column>
<el-table-column align="center" header-align="center" label="操作" fixed="right" width="250px">
<template scope="scope">
<el-button size="mini" type="primary" @click="openView(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<el-form :model="formData" ref="form" label-width="100px"
style="height: calc(100vh - 50px);overflow-y: scroll;padding: 10px 15px">
<vi-title title="指标信息"></vi-title>
<el-row gutter="20">
<el-col :span="8">
<el-form-item prop="annual" label="年&emsp;&emsp;度">
<el-date-picker
readonly
v-model="formData.annual"
type="year"
value-format="yyyy"
placeholder="选择年度">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="flatname" label="分工会名称">
<el-input maxlength="30" value="" readonly v-model="formData.flatname"
placeholder="请填写分工会名称"
type="text"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="assessment" label="考核名称">
<el-input maxlength="30" readonly v-model="formData.assessment" placeholder="请填写考核名称"
type="text"></el-input>
</el-form-item>
</el-col>
</el-row>
<vi-title title="考核内容"></vi-title>
<el-form-item label="" label-width="0" v-for="nr,idx in formData.nrs">
<el-row type="flex" align="middle" justify="space-between">
<el-input v-model="nr.content" readonly maxlength="30" style="width: 50%"
placeholder="请填写考核内容">
<template slot="prepend"><span>{{ idx + 1 }}</span></template>
</el-input>
</el-row>
<el-row style="margin-top: 20px">
<el-table :data="nr.bzs" style="width: 100%" border show-summary
:summary-method="getSummaries">
<el-table-column align="center" header-align="center" label="序号" type="index">
</el-table-column>
<el-table-column label="考核标准" disabled prop="inspection" header-align="center"
align="center">
<template scope="{row}">
<el-input v-model="row.inspection"
readonly placeholder="请填写考核标准"></el-input>
</template>
</el-table-column>
<el-table-column label="标准分" prop="score" header-align="center" align="center"
width="150px">
<template scope="{row}">
<el-input v-model.number="row.score" readonly maxlength="4"
placeholder="请填写标准分"></el-input>
</template>
</el-table-column>
<el-table-column label="自评得分" prop="zpf" header-align="center" align="center"
width="150px">
<template scope="{row}">
<el-input v-if="row.zpf" v-model.number="row.zpf" maxlength="4"
readonly placeholder="请填写自评分"></el-input>
<el-input v-else value="暂无" maxlength="4"
readonly></el-input>
</template>
</el-table-column>
<el-table-column label="总部工会评分" prop="schools" header-align="center" align="center"
width="150px">
<template scope="{row}">
<el-input v-model.number="row.schools" readonly maxlength="4"
placeholder="请填写评分"></el-input>
</template>
</el-table-column>
<el-table-column label="加、减原因" prop="addition" header-align="center" align="center"
width="250px">
<template scope="{row}">
<el-input v-model.number="row.addition" readonly maxlength="50"
placeholder="请填写加、减原因"></el-input>
</template>
</el-table-column>
<el-table-column label="有关佐证材料" header-align="center" align="center"
width="250px">
<template scope="{row}">
<el-button type="primary" :disabled="!row.isEvidence" plain
@click="doView(nr.content,row.inspection,row)">
查看佐证材料
</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form-item>
</el-form>
</template>
</guava>
<el-drawer
:visible.sync="dialog"
direction="rtl" size="40%"
custom-class="demo-drawer"
ref="drawer">
<div class="demo-drawer__content" style="padding: 0 15px">
<upload-materials :data="data" :is_view="true"></upload-materials>
</div>
</el-drawer>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
unions: [],
units: [],
data: {},
row: {},
dialog: false,
loading: false,
formData: {},
tabLoading: false,
tableData: [],
pageForm: {
annual: moment().format('YYYY'),
pageNumber: 1,
pageSize: 10,
totalCount: 0,
},
pickerOptions: {
disabledDate(time) {
return (
time.getFullYear() > new Date().getFullYear()
);
}
},
}
},
components: {
'upload-materials': httpVueLoader('/components/module/kh/UploadMaterials.vue')
},
methods: {
async getKh() {
this.$axios.post("/platform/ghkh/khph/getKh", {"annual": this.pageForm.annual}).then(res => {
if (res.code === 0) {
if (res.data.length != 0) {
this.kh = res.data
this.pageForm.khid = this.kh[0].id
} else {
this.kh = []
this.pageForm.khid = ""
}
}
})
},
async khSearch() {
await this.getKh()
},
openView(row) {
this.$axios.post(base + "/platform/ghkh/lssjcx/getData", {zb_id: row.zb_id, union_id: row.union_id}).then(res => {
if (res.code === 0) {
res.data.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (bz.zp) {
bz.zpf = bz.zp.zpf
}
if (bz.sh) {
bz.addition = bz.sh.addition
bz.schools = bz.sh.schools
}
})
})
res.data.union_id = row.union_id
res.data.flatname = row.unionname
this.formData = res.data
this.$refs.guava.edit()
}
})
},
doView(nr, bz, row) {
this.dialog = true
this.data = {nr, bz, ...row.zp}
},
getSummaries(param) {
const {columns, data} = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '小计';
return;
} else if (index === 5) {
sums[index] = '';
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
if (sums[2]) {
sums[2] = sums[2]
}
if (sums[3]) {
sums[3] = sums[3]
}
if (sums[4]) {
sums[4] = sums[4]
}
} else {
sums[index] = '';
}
});
return sums;
},
pageData() {
this.tabLoading = true
this.$axios.post(base + "/platform/ghkh/lssjcx/pageData", this.pageForm).then(res => {
this.tabLoading = false
if (res.code == 0) {
this.tableData = res.data.list;
this.pageForm.totalCount = res.data.totalCount;
} else {
this.$message({
message: res.msg,
type: 'error'
});
}
}).catch(error => {
this.tabLoading = false
});
},
async flushUnits() {
this.$set(this.pageForm, "unitId", "")
if ("${@shiro.hasRole('sysadmin')||@shiro.hasRole('A06')||@shiro.hasRole('H03')}" === 'true') {
this.units = await getUnits(this.pageForm.unionId)
} else {
this.units = await getUnits("${@shiro.getPrincipalProperty('unit').getUnionid()}")
}
},
},
async created() {
this.pageData();
this.unions = await getUnions()
this.flushUnits()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,494 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-table .warning-row {
background: #CCE5FF;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.annual" type="annual" value-format="yyyy" placeholder="请选择"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionid" @change="doSearch" style="width: 100%"
placeholder="请选择所属工会" clearable>
<el-option v-for="item in unionOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool>
<el-radio-group v-model="pageForm.isAudit" size="small" @change="doSearch">
<el-radio-button :label="1">全部</el-radio-button>
<el-radio-button :label="2">已审核</el-radio-button>
<el-radio-button :label="3">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id"
@sort-change="pageOrder"
v-loading="tabLoading">
<el-table-column align="center" header-align="center" label="序号"
width="100px">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column label="年度" prop="annual" header-align="center"
sortable
align="center">
<template scope="scope">
{{scope.row.annual}}
</template>
</el-table-column>
<el-table-column label="基层工会名称" prop="unionname" header-align="center"
show-overflow-tooltip
align="center">
<template scope="{row}">
({{row.unioncode}}){{row.unionname}}
</template>
</el-table-column>
<el-table-column label="考核名称" prop="assessment" header-align="center"
show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="标准分" prop="bzf" sortable header-align="center"
show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="自评得分" sortable prop="zp_score" header-align="center"
show-overflow-tooltip v-if="examConfig.selfAssessment === true"
align="center"></el-table-column>
<el-table-column label="您的评分" sortable prop="self_score"
header-align="center"
show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="校工会评分" sortable prop="xgh_score"
header-align="center"
show-overflow-tooltip
align="center"></el-table-column>
<el-table-column label="状态" prop="name" header-align="center"
align="center">
<template scope="scope">
<span class="text-warning" v-if="scope.row.state==2">待评分</span>
<span class="text-success"
v-else-if="scope.row.state==3">校工会已审核</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
fixed="right" width="160px">
<template scope="scope">
<el-button size="mini" :disabled="scope.row.state==3" type="primary"
@click="openShGh(scope.row)">评分
</el-button>
<el-button size="mini" type="primary" :disabled="scope.row.state==3"
@click="doSubmit(scope.row)">提交
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit_func>
<el-button type="primary" @click="doEdit('save')">暂存</el-button>
<el-button type="primary" @click="doEdit('submit')">提交</el-button>
</template>
<template #edit_footer>
<el-button type="primary" @click="doEdit('save')">暂存</el-button>
<el-button type="primary" @click="doEdit('submit')">提交</el-button>
</template>
<template #edit>
<el-form :model="formData" ref="form" label-width="100px" :rules="formRules">
<table-tool label="指标信息"></table-tool>
<el-descriptions :column="3" border>
<el-descriptions-item label="年度">{{ formData.annual }}</el-descriptions-item>
<el-descriptions-item label="考核名称">{{ formData.assessment }}</el-descriptions-item>
<el-descriptions-item label="分工会名称">{{ formData.flatname }}</el-descriptions-item>
</el-descriptions>
<table-tool label="考核内容" class="mt10"></table-tool>
<el-form-item label="" label-width="0" v-for="nr,idx in formData.nrs" v-if="nr?.auditUser === $store.state.user.loginname">
<template>
<el-row type="flex" align="middle" justify="space-between">
<el-input v-model="nr.content" readonly maxlength="30" placeholder="请填写考核内容">
<template slot="prepend"><span>{{ idx + 1 }}</span></template>
</el-input>
</el-row>
<el-row style="margin-top: 20px">
<el-table :data="nr.bzs" style="width: 100%" border show-summary size="small" :summary-method="getSummaries"
:row-class-name="tableRowClassName">
<el-table-column align="center" header-align="center" label="序号"
type="index" width="60">
</el-table-column>
<el-table-column label="考核标准" disabled prop="inspection"
header-align="center" align="center">
<template scope="{row}">
<el-input v-model="row.inspection"
readonly placeholder="请填写考核标准"></el-input>
</template>
</el-table-column>
<el-table-column label="标准分" prop="score" header-align="center"
align="center">
<template scope="{row}">
<el-input v-model.number="row.score" readonly maxlength="4"
placeholder="请填写标准分"></el-input>
</template>
</el-table-column>
<el-table-column label="自评得分" prop="zpf" header-align="center"
align="center" v-if="examConfig.selfAssessment === true">
<template scope="{row}">
<el-input v-if="row.zpf" v-model.number="row.zpf"
maxlength="4"
readonly placeholder="请填写自评分"></el-input>
<el-input v-else value="暂无" maxlength="4"
readonly></el-input>
</template>
</el-table-column>
<el-table-column label="校工会评分" prop="schools" header-align="center"
align="center">
<template scope="{row}">
<el-input v-model="row.schools" maxlength="4"
placeholder="请填写评分" type="number"></el-input>
</template>
</el-table-column>
<el-table-column label="加、减原因" prop="addition" header-align="center"
align="center">
<template scope="{row}">
<el-input v-model="row.addition" maxlength="50"
placeholder="请填写加、减原因"></el-input>
</template>
</el-table-column>
<el-table-column label="佐证材料数量" header-align="center" align="center" width="100" prop="fileCount">
<template scope="scope">
<span v-if="scope.row.zp?.files?.length > 0" class="text-success" style="font-weight: bolder; font-size: 16px">
{{ scope.row.zp?.files?.length || 0 }}</span>
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column label="佐证材料" header-align="center" align="center" prop="files">
<template scope="{row, $index}">
<el-button type="primary" plain size="small"
@click="doView(nr.content,row.inspection,row, $index, idx)">
查看佐证材料
</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</template>
</el-form-item>
</el-form>
</template>
</guava>
<el-drawer
title="佐证材料"
:visible.sync="dialog"
direction="rtl" size="40%"
custom-class="demo-drawer"
ref="drawer">
<div class="demo-drawer__content" style="padding: 0 15px">
<upload-materials :data="data" :is_view="true">
<template #extra>
<table-tool label="校工会评分"></table-tool>
<el-form-item prop="score" label="评分标准">
<el-input disabled v-model="viewRow.score" type="text"></el-input>
</el-form-item>
<el-form-item prop="schools" label="校工会评分">
<el-input v-model="viewRow.schools" type="text" placeholder="请输入校工会评分"
type="number"></el-input>
</el-form-item>
</template>
</upload-materials>
<div class="demo-drawer__footer" style="float: right">
<el-popover
placement="top"
width="160"
v-model="visible">
<p>您确定要返回吗?返回将不能保存!</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="visible = false">取消</el-button>
<el-button type="primary" size="mini" @click="cancelForm">确定</el-button>
</div>
<el-button slot="reference">返 回</el-button>
</el-popover>
<el-button type="primary" @click="addForm">确 定</el-button>
</div>
</div>
</el-drawer>
</div>
<script nonce="${cspNonce!}">
window.vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
visible: false,
unions: [],
unionOptions: [],
ghPageForm: {},
v: 'index',
tabLoading: false,
tableData: [],
showGh: true,
formData: {},
dialog: false,
loading: false,
pageForm: {
annual: moment().format('YYYY'),
isAudit: 3,
pageNumber: 1,
pageSize: 10,
totalCount: 0,
year: new Date().getFullYear() + ""
},
formRules: {
schools: [{required: true, message: '请填写分数', trigger: ['blur', 'change']}],
addition: [{required: true, message: '请填写原因', trigger: ['blur', 'change']}],
},
data: {},
row: {},
pickerOptions: {
disabledDate(time) {
return (
time.getFullYear() > new Date().getFullYear()
);
}
},
examConfig: {},
viewRow: {},
index: "",
idx: "",
}
},
components: {
'upload-materials': httpVueLoader('/components/module/kh/UploadMaterials.vue')
},
methods: {
tableRowClassName({row, rowIndex}) {
if(row.zp?.updateStatus === true) {
return 'warning-row';
}
return '';
},
addForm() {
this.formData.nrs[this.idx].bzs[this.index].zp = this.data
this.dialog = false
},
cancelForm() {
this.visible = false
this.loading = false;
this.dialog = false;
},
async getKh() {
this.$axios.post("/platform/ghkh/khph/getKh", {"annual": this.pageForm.annual}).then(res => {
if (res.code === 0) {
if (res.data.length != 0) {
this.kh = res.data
this.pageForm.khid = this.kh[0].id
} else {
this.kh = []
this.pageForm.khid = ""
}
}
})
},
async khSearch() {
await this.getKh()
},
doEdit(type) {
let arr = []
this.formData.nrs.forEach(n => {
let zp
n.bzs.forEach(b => {
zp = {
"zb_id": this.formData.id,
"nr_id": n.id,
"bz_id": b.id,
"flatid": this.formData.union_id,
"schools": b.schools,
"addition": b.addition
}
arr.push(zp)
})
})
const loading = this.$loading({
lock: true,
text: '数据提交中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.$axios.post(base + "/platform/ghkh/xghsh/marking", {
pf: JSON.stringify(arr),
type: type
}).then(res => {
if (res.code == 0) {
this.$refs.guava.index()
this.pageData()
this.$message.success(res.msg)
} else {
this.$message({
message: "请给总部工会评分",
type: 'error'
});
}
loading.close()
}).catch(error => {
loading.close()
})
},
doSubmit(row) {
this.$confirm('提交后不可修改,您确定要提交吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(()=>{
this.$axios
.post("/platform/ghkh/xghsh/submit", {id: row.record_id})
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.error(resp.msg)
}
})
})
},
doView(nr, bz, row, index, idx) {
this.dialog = true
this.viewRow = row
this.data = {nr, bz, ...row.zp, remark: row.remark}
this.index = index
this.idx = idx
},
getSummaries(param) {
const {columns, data} = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '小计';
return;
} else if (['inspection', 'addition', 'files'].includes(column.property)) {
sums[index] = '';
return;
} else if (column.property === 'fileCount') {
const zpfs = data.map(v => v.zp?.files?.length || 0)
sums[index] = zpfs.reduce((a, b) => {
return a + b;
}) + ' 个'
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] += ' 分';
} else {
sums[index] = '';
}
});
return sums;
},
openShGh(row) {
this.$axios.post(base + "/platform/ghkh/xghsh/getData", {
zb_id: row.zb_id,
union_id: row.union_id
}).then(res => {
if (res.code === 0) {
res.data.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (bz.zp) {
bz.zpf = bz.zp.zpf
}
})
})
res.data.union_id = row.union_id
res.data.flatname = row.unionname
this.formData = res.data
}
})
this.$refs.guava.edit()
},
pageData() {
this.tabLoading = true
this.$axios.post(base + "/platform/ghkh/xghsh/pageData", this.pageForm).then(res => {
this.tabLoading = false
if (res.code == 0) {
this.tableData = res.data.list;
this.pageForm.totalCount = res.data.totalCount;
} else {
this.$message({
message: res.msg,
type: 'error'
});
}
}).catch(error => {
this.tabLoading = false
});
},
fetchConfig() {
this.$axios.post("/platform/exam/config/fetch").then((res) => {
if (res.code === 0) {
this.examConfig = res.data
}
})
},
},
async created() {
this.fetchConfig()
this.pageData();
//工会查询
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,101 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-card__header {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<template #header>
<div>
<h3 style="color: #1867b0">新建考核指标</h3>
</div>
<div>
<el-button type="primary" @click="doAdd('save')">暂存</el-button>
<el-button type="primary" @click="doAdd('submit')">提交</el-button>
</div>
</template>
<template>
<kh-zb :form_data="formData" @change="v=>{this.formData=v}"></kh-zb>
<el-row type="flex" justify="end">
<el-button type="primary" @click="doAdd('save')">暂存</el-button>
<el-button type="primary" @click="doAdd('submit')">提交</el-button>
</el-row>
</template>
</el-card>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
data() {
return {
v: 'index',
formData: {},
}
},
components: {
'kh-zb': httpVueLoader('/components/module/kh/KhZb.vue?v=' + moment(new Date()).unix()),
},
methods: {
doAdd(type) {
let flag = true
if (!this.formData.annual) {
this.$message({message: "年度不能为空", type: 'error'})
return
}
if (!this.formData.assessment) {
this.$message({message: "考核名称不能为空", type: 'error'})
return
}
if(type === 'submit') {
this.formData.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (!nr.content) {
this.$message({message: "考核内容不能为空", type: 'error'})
flag = false
throw Error()
} else if (!bz.inspection) {
this.$message({message: "考核标准不能为空", type: 'error'})
flag = false;
throw Error()
}
})
})
}
if (this.formData.fillTimeRange && this.formData.fillTimeRange.length === 2) {
this.formData.startDateTime = this.formData.fillTimeRange[0];
this.formData.endDateTime = this.formData.fillTimeRange[1];
}
if (this.formData.appealTimeRange && this.formData.appealTimeRange.length === 2) {
this.formData.startApplyTime = this.formData.appealTimeRange[0];
this.formData.endApplyTime = this.formData.appealTimeRange[1];
}
if (flag) {
this.$axios.post(base + "/platform/ghkh/Xjkhzb/doAdd", {kh_zb: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush('/platform/ghkh/khzb')
} else {
this.$message({message: res.msg, type: 'error'})
}
})
}
}
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,840 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-table .warning-row {
background: #CCE5FF;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="khSearch"
:picker-options="pickerOptions"
v-model="pageForm.annual"
type="year"
value-format="yyyy"
placeholder="选择年度"
style="width: 100%">
</el-date-picker>
</search-item>
<search-item label="考核名称">
<el-input
v-model="pageForm.assessment"
placeholder="根据考核名称关键字查询"
clearable
style="width: 100%">
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="考核信息"></table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id" v-loading="tabLoading">
<el-table-column align="center" header-align="center" label="序号" width="100px">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column label="年度" prop="annual" header-align="center" width="300px" sortable align="center">
</el-table-column>
<el-table-column label="考核名称" prop="assessment" header-align="center" show-overflow-tooltip align="center"></el-table-column>
<el-table-column label="填报时间" width="300px" header-align="center" show-overflow-tooltip align="center">
<template scope="scope">
<span>{{scope.row.startDateTime}} - {{scope.row.endDateTime}}</span>
</template>
</el-table-column>
<el-table-column label="状态" prop="name" header-align="center" align="center">
<template scope="scope">
<span class="text-info" v-if="!scope.row.state">未填报</span>
<span class="text-success" v-if="scope.row.state==1">填报中</span>
<span class="text-warning" v-if="scope.row.state==2">待评分</span>
<span class="text-success" v-if="scope.row.state==3">校工会已审核</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" fixed="right" width="250px">
<template scope="scope">
<el-button size="mini" type="primary" v-if="scope.row.state" @click="openView(scope.row)">查看
</el-button>
<el-button size="mini" type="primary" @click="openAdd(scope.row)" v-if="!scope.row.state">
填报
</el-button>
<el-button size="mini" type="primary" @click="openEdit(scope.row)" v-else>
修改
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit_func>
<el-button type="primary" @click="doSaveOrSubmit('save')">暂存</el-button>
<el-button type="primary" @click="doSaveOrSubmit('submit')">提交</el-button>
</template>
<template #edit_footer>
<el-button type="primary" @click="doSaveOrSubmit('save')">暂存</el-button>
<el-button type="primary" @click="doSaveOrSubmit('submit')">提交</el-button>
</template>
<template #edit>
<el-form :model="formData" ref="form" label-width="100px">
<table-tool label="联系信息"></table-tool>
<el-descriptions :column="3" border>
<el-descriptions-item label="填报人">{{ $store.state.user.username }}</el-descriptions-item>
<el-descriptions-item label="联系方式">{{ $store.state.user.mobile }}</el-descriptions-item>
<el-descriptions-item label="填报时间">{{ formData.fillTime }}</el-descriptions-item>
</el-descriptions>
<table-tool label="指标信息" class="mt10"></table-tool>
<el-descriptions :column="3" border>
<el-descriptions-item label="年度">{{ formData.annual }}</el-descriptions-item>
<el-descriptions-item label="考核名称">{{ formData.assessment }}</el-descriptions-item>
<el-descriptions-item label="分工会名称">{{ $store.state.user.union.name }}</el-descriptions-item>
</el-descriptions>
<table-tool label="考核内容" class="mt10"></table-tool>
<el-form-item label="" label-width="0" v-for="nr,idx in formData.nrs" :key="nr.id">
<el-row type="flex" align="middle" justify="space-between">
<el-input v-model="nr.content" readonly maxlength="30" style="width: 50%">
<template slot="prepend"><span>{{ idx + 1 }}</span></template>
</el-input>
</el-row>
<el-row style="margin-top: 20px">
<el-table :data="nr.bzs" style="width: 100%" border show-summary size="small" :summary-method="getSummaries">
<el-table-column align="center" header-align="center" label="序号" type="index"
width="100px">
</el-table-column>
<el-table-column label="考核标准" disabled prop="inspection" header-align="center"
align="center">
<template scope="{row}">
<el-input v-model="row.inspection"
readonly></el-input>
</template>
</el-table-column>
<el-table-column label="单项分" prop="single_score" header-align="center" align="center"
v-if="examConfig.displaySingleItem === true" width="250px">
<template scope="{row}">
<el-input v-model.number="row.single_score" readonly maxlength="4"></el-input>
</template>
</el-table-column>
<el-table-column label="标准分" prop="score" header-align="center" align="center"
width="250px">
<template scope="{row}">
<el-input v-model.number="row.score" readonly maxlength="4"></el-input>
</template>
</el-table-column>
<el-table-column label="自评得分" prop="zp.zpf" header-align="center" align="center"
v-if="examConfig.selfAssessment === true" width="250px">
<template slot-scope="{row}">
<el-input v-model.number="row.zp.zpf" maxlength="4"
@input="(val)=>{onInputZpf(val,row)}"
placeholder="请填写自评分">
<template #append v-if="row.bz_relation_id">
<el-button @click="calcScore(row)" icon="el-icon-paperclip"></el-button>
</template>
</el-input>
</template>
</el-table-column>
<el-table-column label="佐证材料数量" header-align="center" align="center" width="100" prop="fileCount">
<template scope="scope">
<span v-if="scope.row.zp?.files?.length > 0" class="text-success" style="font-weight: bolder; font-size: 16px">
{{ scope.row.zp?.files?.length || 0 }}</span>
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column label="佐证材料" header-align="center" align="center" width="250px" prop="files">
<template scope="props">
<el-button v-if="!props.row.isEvidence" plain size="small" type="info">此项无需佐证材料</el-button>
<el-button :type="props.row.zp?.files?.length > 0 ? 'success' : 'primary'"
plain
:disabled="!props.row.isEvidence" size="small"
v-else
@click="upload(nr.content, props.row.inspection, props.row, props.$index,idx)">
上传佐证材料
</el-button>
</template>
</el-table-column>
<el-table-column label="是否申诉" header-align="center" align="center" prop="updateStatus" width="150"
v-if="$moment().isAfter($moment(formData.startApplyTime)) && $moment().isBefore($moment(formData.endApplyTime))">
<template scope="{row}">
<el-radio-group v-model="row.zp.updateStatus" size="small">
<el-radio-button :label="true">申诉</el-radio-button>
<el-radio-button :label="false">不申诉</el-radio-button>
</el-radio-group>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form-item>
</el-form>
</template>
<template #view>
<el-form :model="formData" ref="form" label-width="100px">
<table-tool label="指标信息"></table-tool>
<el-descriptions :column="3" border>
<el-descriptions-item label="年度">{{ formData.annual }}</el-descriptions-item>
<el-descriptions-item label="考核名称">{{ formData.assessment }}</el-descriptions-item>
<el-descriptions-item label="分工会名称">{{ $store.state.user.union.name }}</el-descriptions-item>
</el-descriptions>
<table-tool label="考核内容" class="mt10"></table-tool>
<el-form-item label="" label-width="0" v-for="nr,idx in formData.nrs" :key="nr.id">
<el-row type="flex" align="middle" justify="space-between">
<el-input v-model="nr.content" readonly maxlength="30" style="width: 50%"
placeholder="请填写考核内容">
<template slot="prepend"><span>{{ idx + 1 }}</span></template>
</el-input>
</el-row>
<el-row style="margin-top: 20px">
<el-table :data="nr.bzs" style="width: 100%" border show-summary size="small" :summary-method="getSummaries"
:row-class-name="tableRowClassName">
<el-table-column align="center" header-align="center" label="序号" type="index" width="80">
</el-table-column>
<el-table-column label="考核标准" disabled prop="inspection" header-align="center"
align="center">
<template scope="{row}">
<el-input v-model="row.inspection"
readonly placeholder="请填写考核标准"></el-input>
</template>
</el-table-column>
<el-table-column label="单项分" prop="single_score" header-align="center" align="center"
v-if="examConfig.displaySingleItem === true" width="120px">
<template scope="{row}">
<el-input v-model.number="row.single_score" readonly maxlength="4"></el-input>
</template>
</el-table-column>
<el-table-column label="标准分" prop="score" header-align="center" align="center"
width="120px">
<template scope="{row}">
<el-input v-model.number="row.score" readonly maxlength="4"
placeholder="请填写标准分"></el-input>
</template>
</el-table-column>
<el-table-column label="自评得分" prop="zpf" header-align="center" align="center"
width="120px" v-if="examConfig.selfAssessment === true">
<template scope="{row}">
<el-input v-if="row.zpf" v-model.number="row.zpf" maxlength="4"
readonly placeholder="请填写自评分"></el-input>
<el-input v-else value="暂无" maxlength="4"
readonly></el-input>
</template>
</el-table-column>
<el-table-column label="校工会评分" prop="schools" header-align="center"
align="center" width="120px">
<template scope="{row}">
{{ row.schools || '暂无评分' }}
</template>
</el-table-column>
<el-table-column label="加、减原因" prop="addition" header-align="center"
align="center" show-overflow-tooltip width="200">
<template scope="{row}">
{{ row.addition || '暂无原因' }}
</template>
</el-table-column>
<el-table-column label="佐证材料数量" header-align="center" align="center" width="100" prop="fileCount">
<template scope="scope">
<span v-if="scope.row.zp?.files?.length > 0" class="text-success" style="font-weight: bolder; font-size: 16px">
{{ scope.row.zp?.files?.length || 0 }}</span>
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column label="佐证材料" header-align="center" align="center"
width="200px" prop="files">
<template scope="{row}">
<el-button v-if="!row.isEvidence" plain size="small" type="info">此项无需佐证材料</el-button>
<el-button :type="row.zp?.files?.length > 0 ? 'success' : 'primary'"
plain
:disabled="!row.isEvidence" size="small"
v-else
@click="viewUpload(nr.content,row.inspection,row)">
查看佐证材料
</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form-item>
</el-form>
</template>
</guava>
<el-drawer
title="佐证材料"
:visible.sync="dialog"
:show-close="false"
direction="rtl" size="40%"
custom-class="demo-drawer" :before-close="()=>{addForm()}"
ref="drawer">
<div class="demo-drawer__content" style="padding: 0 15px">
<upload-materials :data="data"></upload-materials>
<div class="demo-drawer__footer" style="float: right">
<el-popover
placement="top"
width="160"
v-model="visible">
<p>您确定要返回吗?返回将不能保存!</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="visible = false">取消</el-button>
<el-button type="primary" size="mini" @click="cancelForm">确定</el-button>
</div>
<el-button slot="reference">返 回</el-button>
</el-popover>
<el-button type="primary" @click="addForm">确 定</el-button>
</div>
</div>
</el-drawer>
<el-drawer
title="佐证材料"
:visible.sync="dialog_view"
direction="rtl" size="40%"
custom-class="demo-drawer"
ref="drawer">
<div class="demo-drawer__content" style="padding: 0 15px">
<upload-materials :data="data" :is_view="true"></upload-materials>
</div>
</el-drawer>
<calcscore-table :relation_year="relationYear"
:show_modal.sync="calcSoreTableModal"
@get_table_data="autoFillScore">
</calcscore-table>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
visible: false,
fileList: [],
v: 'index',
tableData: [],
formData: {},
dialog: false,
dialog_view: false,
loading: false,
pageForm: {
annual: moment().format('YYYY'),
pageNumber: 1,
pageSize: 10,
totalCount: 0,
},
data: {bz: '', clnrs: null, nr: '', remark: ''},
row: {},
index: "",
idx: "",
addFormData: [],
pickerOptions: {
disabledDate(time) {
return (
time.getFullYear() > new Date().getFullYear()
);
}
},
relationYear: {},
calcSoreTableModal: false,
current_bz_id: '',
examConfig: {},
}
},
filters: {
none2str(val) {
return val ? val : '暂无'
}
},
components: {
'upload-materials': httpVueLoader('/components/module/kh/UploadMaterials.vue?v=' + new Date().getTime()),
'calcscore-table': httpVueLoader('/components/module/kh/CalcScoreTab.vue?ver=' + Math.random()),
},
methods: {
tableRowClassName({row, rowIndex}) {
if(row.zp?.updateStatus === true) {
return 'warning-row';
}
return '';
},
goBack() {
this.pageData()
this.$refs.guava.index()
},
//计算得分
async calcScore(row) {
this.current_bz_id = row.id
this.calcSoreTableModal = true
this.relationYear = {year: this.formData.annual, bz_relation_id: row.bz_relation_id}
},
autoFillScore(scoreTable) {
this.formData.nrs.some(nr => {
nr.bzs.some(v => {
if (v.id === this.current_bz_id) {
this.$set(v, 'clnr', this.renderScoreTable(v.bz_relation_id, scoreTable))
if (scoreTable.length * v.single_score > Number(v.score) && !v.beyond_highestscore) {
this.$message.warning('自评得分不能超过标准分!')
this.$set(v.zp, 'zpf', v.score)
return true
}
if (this.relationYear.bz_relation_id === "Performance") {
let single_score = 0
scoreTable.map(v => {
single_score += v.integral
})
this.$set(v.zp, 'zpf', single_score)
}else if(['proposal','ConandDif'].includes(this.relationYear.bz_relation_id)){
let single_score = 0
if(Number(v.single_score)!==0&&scoreTable.length!==0){
single_score=Number(v.single_score)*scoreTable.length
}
this.$set(v.zp, 'zpf', single_score)
} else {
this.$set(v.zp, 'zpf', scoreTable.length * v.single_score)
}
return true
}
})
})
},
//自定义材料说明
renderScoreTable(relation_id, score_data) {
if (score_data) {
let res = ''
switch (relation_id) {
case 'proposal':
score_data.map((v, i) => {
res += (i + 1) + ' .提案人:' + v.username + ',提案名称:' + v.proposalName + ';\n'
})
return res
case 'secteameet':
score_data.map((v, i) => {
res += (i + 1) + ' .申请人:' + v.username + ',会议名称:' + v.meeting_name + ';\n'
})
return res
case 'ConandDif':
score_data.map((v, i) => {
res += (i + 1) + ' .被慰问/补助人:' + v.be_username + ',慰问/补助类型:' + v.typename + ';\n'
})
return res
case 'Performance':
score_data.map((v, i) => {
res += (i + 1) + ' .在:' + v.activityName + '届运动会中,' + v.eventName + '项目获得了地' + v.ranking + '名;\n'
})
return res
default:
return ''
}
}
return ''
},
onInputZpf(v, row) {
if (Number(v) > Number(row.score) && !row.beyond_highestscore) {
row.zp.zpf = Number(row.score)
this.$message.warning('自评得分不能超过标准分!')
}
},
async doSaveOrSubmit(v) {
const params = []
let valid = true
let msg = ''
for (let i = 0; i < this.formData.nrs.length; i++) {
const n = this.formData.nrs[i]
for (let j = 0; j < n.bzs.length; j++) {
const b = n.bzs[j]
params.push({
"zb_id": this.formData.id,
"nr_id": n.id,
"bz_id": b.id,
"clnr": b.zp?.clnr,
"zpf": b.zp?.zpf,
"files": b.zp?.files,
"id": b.zp?.id ? b.zp?.id : null,
"updateStatus": b.zp?.updateStatus
})
if(v === 'submit' && valid === true) {
if(b.isEvidence === true && !b.zp?.files) {
msg = '考核内容第' + (i + 1) + '项,考核标准第' + (j + 1) + '项,佐证材料为空,是否继续提交?'
valid = false
}
}
}
}
if (v === 'submit' && valid === false) {
this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.submit(params, v)
}).catch(() => {})
} else {
this.submit(params, v)
}
},
submit(params, v) {
const loading = this.$loading({
lock: true,
text: '数据提交中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.$axios.post(base + "/platform/ghkh/zp/doHandler", {
zp: JSON.stringify(params),
handletype: v
}).then(res => {
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
loading.close()
this.$refs.guava.index()
/*if (v === 'submit') {
this.$refs.guava.index()
return
}
this.$axios.post(base + '/platform/ghkh/zp/openView', {id: this.formData.id}).then(resa => {
this.$nextTick(() => {
this.formData = resa.data
})
})*/
}).catch(error => {
loading.close()
})
},
async getKh() {
this.$axios.post("/platform/ghkh/khph/getKh", {"annual": this.pageForm.annual}).then(res => {
if (res.code === 0) {
if (res.data.length != 0) {
this.kh = res.data
this.pageForm.khid = this.kh[0].id
} else {
this.kh = []
this.pageForm.khid = ""
}
}
})
},
async khSearch() {
await this.getKh()
},
viewUpload(nr, bz, row) {
this.data = {nr, bz, clnr: row.clnr, ...row.zp, remark: row.remark}
this.dialog_view = true
},
upload(nr, bz, row, index, idx) {
this.dialog = true
if (row.zp) {
this.data = {nr, bz, clnr: row.clnr, ...row.zp, remark: row.remark}
} else {
this.data = {nr, bz, clnr: row.clnr, ...row.zp, remark: row.remark}
}
this.row = row
this.index = index
this.idx = idx
},
addForm() {
this.$set(this.formData.nrs[this.idx].bzs[this.index], 'zp', this.data)
this.dialog = false
this.$forceUpdate()
},
cancelForm() {
this.visible = false
this.loading = false;
this.dialog = false;
},
getSummaries(param) {
const {columns, data} = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '小计';
return;
} else if (['inspection', 'files', 'addition'].includes(column.property)) {
sums[index] = '';
return;
} else if (column.property === 'zp.zpf' && this.examConfig.selfAssessment === true) {
const zpfs = data.map(v => v.zp?.zpf || 0)
sums[index] = zpfs.reduce((a, b) => {
return a + b;
}) + ' 分'
return;
} else if (column.property === 'fileCount') {
const zpfs = data.map(v => v.zp?.files?.length || 0)
sums[index] = zpfs.reduce((a, b) => {
return a + b;
}) + ' 个'
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] += ' 分';
} else {
sums[index] = null;
}
});
return sums;
},
pageData() {
this.tabLoading = true
this.$axios.post(base + "/platform/ghkh/zp/pageData", this.pageForm).then(res => {
this.tabLoading = false
if (res.code == 0) {
this.tableData = res.data.list;
this.pageForm.totalCount = res.data.totalCount;
} else {
this.$message({
message: res.msg,
type: 'error'
});
}
}).catch(error => {
this.tabLoading = false
});
},
async openAdd(row) {
if(this.$moment().isBefore(this.$moment(row.startDateTime))) {
this.$message.error("该考核未开始")
return
}
if(this.$moment().isAfter(this.$moment(row.endDateTime))) {
this.$message.error("该考核已结束")
return
}
this.$axios.post(base + "/platform/ghkh/khzb/getZb", {id: row.id}).then(data => {
if (data.code === 0) {
data.data.nrs.forEach(v => {
v.bzs.forEach(x => {
if (!x.zp) {
x.zp = {zpf: 0}
}
})
})
this.formData = data.data
this.formData.userName = this.$store.state.user.username
this.formData.mobile = this.$store.state.user.mobile
this.formData.unionName = this.$store.state.user.union.name
this.formData.fillTime = this.$moment().format('YYYY-MM-DD HH:mm:ss')
this.$refs.guava.edit()
}
})
},
async openEdit(row) {
// 考核还未开始
if(this.$moment().isBefore(this.$moment(row.startDateTime))) {
this.$message.error("该考核未开始")
return
}
// 考核还没结束
if(this.$moment().isBefore(this.$moment(row.endDateTime))) {
if(row.state === 2 || row.state === 3) {
this.$message.error("当前时间未在申诉期内,不能修改")
return
}
} else if(this.$moment().isAfter(this.$moment(row.endDateTime)) && this.$moment().isBefore(this.$moment(row.startApplyTime))) {
if(row.state === 2 || row.state === 3) {
this.$message.error("当前时间未在申诉期内,不能修改")
return
}
} else {
if(this.$moment().isBefore(this.$moment(row.startApplyTime))) {
this.$message.error("该考核申诉期未开始")
return
}
}
if(this.$moment().isAfter(this.$moment(row.endApplyTime))) {
this.$message.error("该考核申诉期已结束")
return
}
this.$axios.post(base + '/platform/ghkh/zp/openView', {id: row.id}).then(resa => {
if (resa.code === 0) {
this.formData = resa.data
this.$refs.guava.edit()
}
})
},
async doAdd() {
this.addFormData = []
this.formData.nrs.forEach(n => {
let zp = {}
n.bzs.forEach(b => {
if (b.zp) {
zp = {
"zb_id": this.formData.id,
"nr_id": n.id,
"bz_id": b.id,
"clnr": b.zp.clnr,
"zpf": b.zpf,
"files": b.zp.files,
"updateStatus": b.zp?.updateStatus
}
} else {
zp = {"zb_id": this.formData.id, "nr_id": n.id, "bz_id": b.id, "zpf": b.zpf}
}
this.addFormData.push(zp)
})
})
const loading = this.$loading({
lock: true,
text: '数据提交中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const res = await $.post(base + "/platform/ghkh/zp/doAdd", {zp: JSON.stringify(this.addFormData)})
if (res.code === 0) {
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
loading.close()
const resa = await this.$axios.post(base + '/platform/ghkh/zp/openView', {id: this.formData.id})
await this.$nextTick()
this.formData = resa.data
},
doEdit() {
this.formData.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (bz.zp) {
bz.zp = {
...bz.zp, "zpf": bz.zpf,
}
}
})
})
const loading = this.$loading({
lock: true,
text: '数据提交中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.$axios.post(base + "/platform/ghkh/zp/doEdit", {zb: JSON.stringify(this.formData)}).then(data => {
if (data.code == 0) {
this.pageData()
this.$message.success(data.msg)
} else {
this.$message({
message: data.msg,
type: 'error'
});
}
loading.close()
}).catch(error => {
loading.close()
})
},
subXgh() {
this.formData.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (bz.zp) {
bz.zp = {
"bz": bz.zp.bz,
"files": bz.zp.files,
"clnr": bz.zp.clnr,
"zb_id": this.formData.id,
"nr_id": nr.id,
"bz_id": bz.id,
"zpf": bz.zpf
}
} else {
bz.zp = {"zb_id": this.formData.id, "nr_id": nr.id, "bz_id": bz.id, "zpf": bz.zpf}
}
})
})
const loading = this.$loading({
lock: true,
text: '数据提交中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.$axios.post(base + "/platform/ghkh/zp/subXgh", {zb: JSON.stringify(this.formData)}).then(data => {
if (data.code == 0) {
this.$refs.guava.index()
this.pageData()
this.$message.success(data.msg)
} else {
this.$message({
message: data.msg,
type: 'error'
});
}
loading.close()
}).catch(error => {
loading.close()
})
},
openView(row) {
this.$axios.post(base + "/platform/ghkh/zp/openView", {id: row.id}).then(res => {
if (res.code === 0) {
res.data.nrs.forEach(nr => {
nr.bzs.forEach(bz => {
if (bz.zp) {
bz.zpf = bz.zp.zpf
bz.clnr = bz.zp.clnr
}
})
})
this.formData = res.data;
}
this.$refs.guava.view()
})
},
fetchConfig() {
this.$axios.post("/platform/exam/config/fetch").then((res) => {
if (res.code === 0) {
this.examConfig = res.data
}
})
},
},
async created() {
this.fetchConfig()
this.pageData();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,165 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="院区名称">
<el-input style="width: 350px;" @keyup.enter.native="doSearch"
clearable placeholder="请输入院区名称" v-model="pageForm.campusName"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="体检项目" :app="this">
<el-button type="primary" size="small" @click="openAdd"> 新增院区</el-button>
</table-tool>
<el-table :data="tableData">
<el-table-column align="center" header-align="center" label="序号" type="index" width="100">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="院区编码"
prop="campusCode"></el-table-column>
<el-table-column align="center" header-align="center" label="院区名称"
prop="campusName"></el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="200">
<template scope="{row}">
<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>
<el-row class="el-pagination-container">
<el-pagination
@current-change="pageNumberChange"
:current-page="pageForm.pageNumber"
layout="total, prev, pager, next, jumper"
:total="pageForm.totalCount">
</el-pagination>
</el-row>
</el-card>
</guava>
<el-dialog title="新增院区" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="30%">
<el-form :model="formData" ref="addForm" :rules="rules">
<el-form-item prop="campusCode" label="院区编码">
<el-input v-model="formData.campusCode" placeholder="请输入院区编码" clearable></el-input>
</el-form-item>
<el-form-item prop="campusName" label="院区名称">
<el-input v-model="formData.campusName" placeholder="请输入院区名称" clearable></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="编辑院区" :visible.sync="editDialogVisible" :close-on-click-modal="false" width="30%">
<el-form :model="formData" ref="editForm" :rules="rules">
<el-form-item prop="campusCode" label="院区编码">
<el-input v-model="formData.campusCode" placeholder="请输入院区编码" clearable></el-input>
</el-form-item>
<el-form-item prop="campusName" label="院区名称">
<el-input v-model="formData.campusName" placeholder="请输入院区名称" clearable></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
addDialogVisible: false,
editDialogVisible: false,
formData: {},
rules: {
campusName: [{required: true, message: '请输入院区名称', trigger: ['change', 'blur']}],
campusCode: [{required: true, message: '请输入院区编码', trigger: ['change', 'blur']}]
},
tableData: []
}
},
methods: {
openAdd() {
this.formData = {}
this.addDialogVisible = true
if (this.$refs["addForm"])
this.$refs["addForm"].resetFields()
},
doAdd() {
this.$refs['addForm'].validate(valid => {
if (valid) {
$.post('/platform/healthCheckup/campus/doAdd', this.formData).then(res => {
if (res.code === 0) {
this.addDialogVisible = false
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
}
})
},
openEdit(obj) {
this.formData = JSON.parse(JSON.stringify(obj))
this.editDialogVisible = true
},
doEdit() {
this.$refs['editForm'].validate(valid => {
if (valid) {
$.post('/platform/healthCheckup/campus/doEdit', this.formData).then(res => {
if (res.code === 0) {
this.editDialogVisible = false
this.pageData()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
}
})
},
doDelete(id) {
this.$confirm('此操作将删除院区,确认删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
$.post('/platform/healthCheckup/campus/doDelete', {id: id}).then(res => {
if (res.code === 0) {
this.doSearch()
this.$message.success(res.msg)
}
})
}).catch(() => {
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,158 @@
const CONDITION_STRUCTURE_DIALOG = {
template: /*language=HTML*/ `
<el-dialog
:close-on-click-modal="false"
:visible.sync="dialogVisible"
title="高级查询构造器"
width="50%"
>
<div class="process-title">过滤条件匹配</div>
<el-row :gutter="20">
<el-col :span="20">
<el-select v-model="formData.method" placeholder="请选择匹配方式" style="width: 100%">
<el-option label="AND(所有条件都要求匹配)" value="AND"></el-option>
<el-option label="OR(条件中的任意一个匹配)" value="OR"></el-option>
</el-select>
</el-col>
<el-col :span="4">
<el-button type="primary" icon="el-icon-plus" @click="formData.conditions.push({})">添加条件
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" v-for="(cnd,idx) in formData.conditions" :key="idx" style="margin-top: 20px">
<el-col :span="2">
<el-tag>条件{{idx+1}}</el-tag>
</el-col>
<el-col :span="8">
<el-select v-model="cnd.field" placeholder="请选择字段" style="width: 100%"
@change="(v)=>fieldChange(v,cnd)">
<el-option
v-for="item in fields"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
<el-select v-model="cnd.operational" placeholder="请选择" style="width: 100%">
<el-option
v-for="item in operationalOption"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="8">
<el-date-picker
v-if="cnd.fieldObj&&cnd.fieldObj.type=='date'"
v-model="cnd.value"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择日期" style="width: 100%">
</el-date-picker>
<el-select v-else-if="cnd.fieldObj&&cnd.fieldObj.type=='select'" v-model="cnd.value"
placeholder="请选择值"
filterable
style="width: 100%"
clearable>
<el-option
v-for="item in cnd.fieldObj.options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-input v-else v-model="cnd.value" clearable placeholder="请输入值"
style="width: 100%"></el-input>
</el-col>
<el-col :span="2">
<el-button type="danger" icon="el-icon-minus" @click="formData.conditions.splice(idx, 1)">
</el-button>
</el-col>
</el-row>
<span slot="footer">
<el-button @click="dialogVisible = false">关 闭</el-button>
<el-button type="primary" @click="doSubmit">确 认</el-button>
</span>
</el-dialog>
`,
data() {
return {
dialogVisible: false,
formData: {
method: "",
conditions: []
},
fields: [
{
"label": "性别",
"value": "sex",
"type": "select",
"options": [{"value": "男", "label": "男"}, {"value": "女", "label": "女"}]
},
{
"label": "出生日期",
"value": "birthday",
"type": "date",
},
{
"label": "婚姻状况",
"value": "marriage",
"type": "select",
"options": [{"value": "未婚", "label": "未婚"}, {"value": "已婚", "label": "已婚"}]
}
],
operationalOption: [
{"label": "等于(=)", "value": "="},
{"label": "不等于(!=)", "value": "!="},
{"label": "小于(<)", "value": "<"},
{"label": "小于等于(<=)", "value": "<="},
{"label": "大于(>)", "value": ">"},
{"label": "大于等于(>=)", "value": ">="},
]
}
},
methods: {
async onOpen(formData) {
console.log(formData)
if (formData) {
this.formData = formData
}else{
this.formData = {
method: "",
conditions: []
}
}
this.dialogVisible = true
this.$forceUpdate()
},
fieldChange(val, cnd) {
this.$set(cnd, "fieldObj", this.fields.find(v => v.value === val))
this.$set(cnd, "value", null)
this.$forceUpdate()
},
doSubmit() {
if (!this.formData.method) {
this.$message.error("请选择匹配方式")
return
}
if (this.formData.conditions.length === 0) {
this.$message.error("请添加条件")
return
}
if (this.formData.conditions.some(v => !v.field || !v.operational || !v.value)) {
this.$message.error("请填写完整条件")
return
}
this.$emit("confirm", this.formData)
this.dialogVisible = false
}
}
}
@@ -0,0 +1,336 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" class="platform" v-cloak>
<guava ref="guava" padding="0 5%">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
:clearable="true"
@change="yearChange"
placeholder="选择年"
type="year"
style="width: 100%;"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="体检项目">
<el-select @change="doSearch();getHealthCheckupSubject();"
style="width: 100%;"
v-model="pageForm.projectId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in projectOptions"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<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"
:key="item.id"
: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"
:key="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="体检项目">
<el-button type="primary" size="small" @click="openImport">导入名单
</el-button>
<el-button :disabled="!pageForm.projectId" type="primary" size="small"
@click="doAudit(true)">确认名单
</el-button>
<!-- 取消确认 -->
<el-button :disabled="!pageForm.projectId" type="danger" size="small"
@click="doAudit(false)">取消确认
</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id"
@sort-change="pageOrder" :size="tableSize"
v-loading="tableLoading" ref="table" 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
:sortable="column.sortable"
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width" min-width="100px">
<template v-if="column.prop=='optionName'" v-slot="{row}">
{{row.optionName?row.optionName:''}}
</template>
<template v-else-if="column.prop=='isAudit'" v-slot="{row}">
<el-tag type="success" v-if="row.isAudit">已确认</el-tag>
<el-tag type="info" v-else>未确认</el-tag>
</template>
<template v-else-if="column.prop=='userSign'" v-slot="{row}">
<el-image v-if="row.userSign"
:src="row.userSign"
fit="cover" style="height: 60px"></el-image>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
fixed="right">
<template slot-scope="{row}">
<el-button @click="openEditHealthCheckup(row)" size="mini"
:disabled="row.isAudit" type="primary">
编辑
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
<el-dialog title="修改套餐" :visible.sync="exportHealthCheckupDialog" width="50%"
:close-on-click-modal="false">
<el-form :model="editHealthCheckupData" label-width="120px" ref="editHealthCheckupForm">
<el-form-item label="姓名">
<el-input :value="editHealthCheckupData.userName"></el-input>
</el-form-item>
<el-form-item label="工号">
<el-input :value="editHealthCheckupData.loginName"></el-input>
</el-form-item>
<el-form-item label="套餐"
prop="subjectId"
:rules="[{required:true,message:'请选择',trigger:['change','blur']}]">
<el-select v-model="editHealthCheckupData.subjectId" style="width: 100%">
<el-option v-for="item in projectSubjectOptions" :key="item.id" :value="item.id"
:label="item.optionName"></el-option>
</el-select>
</el-form-item>
<el-form-item label="备注"
prop="bz">
<el-input v-model="editHealthCheckupData.bz" type="textarea" rows="5"
placeholder="请输入备注"></el-input>
</el-form-item>
<!-- <el-form-item label="院区"
prop="campus"
:rules="[{required:true,message:'请选择',trigger:['change','blur']}]">
<el-select v-model="editHealthCheckupData.campus" style="width: 100%">
<el-option v-for="item in campusOptions" :key="item.id" :value="item.id"
:label="item.campusName"></el-option>
</el-select>
</el-form-item>-->
</el-form>
<el-row type="flex" justify="end">
<el-button @click="exportHealthCheckupDialog=false" type="primary" plain>取消</el-button>
<el-button @click="doEditHealthCheckupData" type="primary" v-loading="loading">确定
</el-button>
</el-row>
</el-dialog>
<excel-import
ref="excelImportRef"
url="/platform/healthCheckup/list/mange/healthImport"
template_url="/platform/healthCheckup/list/mange/downloadTem"
:visible.sync="importVisible"
title="导入名单数据"
width="700px"
:extra_params="{healthProjectId:pageForm.projectId}"
></excel-import>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
pageForm: {
year: moment().format('YYYY'),
},
unions: [],
units: [],
projectOptions: [],
projectSubjectOptions: [],
tableColumns: [
{prop: 'loginName', label: '工号'},
{prop: 'userName', label: '姓名'},
{prop: 'sex', label: '性别', sortable: true},
{prop: 'unionName', label: '所属工会', sortable: true},
{prop: 'unitName', label: '所属单位', sortable: true},
{prop: 'optionName', label: '所选套餐'},
{prop: 'selectTime', label: '选择时间', width: "160px"},
{prop: 'receiveAddress', label: '邮寄地址', width: "160px"},
{prop: 'isAudit', label: '是否确认'},
{prop: 'auditTime', label: '确认时间'},
{prop: 'bz', label: '备注',width: "200px"},
],
exportHealthCheckupDialog: false,
editHealthCheckupData: {},
loading: false,
//导入名单
importVisible: false,
campusOptions: [],
}
},
components: {
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime())
},
methods: {
async doAudit(flag) {
// flag true,确认 false,取消
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"]) && !this.pageForm.unionId) {
this.notifyWarning("请选择需要提交的分工会")
return
}
if (this.pageForm.totalCount === 0) {
this.notifyWarning("当前分工会没有名单,暂不需要提交")
return
}
const confirm = await this.$confirm(flag ? '您确定名单都已核实,准确无误?' : '您确定取消确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === "confirm") {
const resp = await $.post("/platform/healthCheckup/list/mange/doAuditUser", {
projectId: this.pageForm.projectId,
unionId: this.pageForm.unionId,
flag: flag
})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyError(resp.msg)
}
}
},
doEditHealthCheckupData() {
this.$refs['editHealthCheckupForm'].validate(async valid => {
if (valid) {
this.loading = true
const resp = await $.post(loc() + "/doEditHealthCheckupData", this.editHealthCheckupData)
this.exportHealthCheckupDialog = false
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyWarning(resp.msg)
}
this.loading = false
}
})
},
async openEditHealthCheckup(row) {
this.editHealthCheckupData = {
userName: row.userName,
loginName: row.loginName,
subjectId: row.subjectId,
campus: row.campus,
projectId: this.pageForm.projectId,
userId: row.id
}
this.exportHealthCheckupDialog = true
},
async yearChange() {
const resp = await $.get("/platform/healthCheckup/project/mange/getHealthCheckupProject", {year: this.pageForm.year})
if (resp.code === 0) {
this.projectOptions = resp.data
if (resp.data && resp.data.length > 0) {
this.$set(this.pageForm, "projectId", resp.data[0].id)
} else {
this.$set(this.pageForm, "projectId", null)
}
await this.getHealthCheckupSubject()
} else {
this.notifyError(resp.msg)
}
},
async getHealthCheckupSubject() {
const resp = await $.get("/platform/healthCheckup/project/mange/findOne", {id: this.pageForm.projectId})
if (resp.code === 0) {
this.projectSubjectOptions = resp.data.healthCheckupProjectSubjects
} else {
this.notifyError(resp.msg)
}
},
async queryCampus() {
const resp = await $.get("/platform/healthCheckup/campus/queryCampus")
if (resp.code === 0) {
this.campusOptions = resp.data
} else {
this.notifyError(resp.msg)
}
},
async flushUnits() {
this.$set(this.pageForm, "unitId", "")
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
} else {
this.units = await this.$businessTool.listUnit()
}
},
openImport() {
// importUser
this.importVisible = true;
},
successImport() {
this.importLoading = false
this.doSearch()
},
},
async created() {
this.unions = await this.$businessTool.listUnion()
this.flushUnits()
await this.yearChange()
this.pageData()
await this.queryCampus()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,703 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" class="platform" v-cloak>
<guava ref="guava" padding="0 5%">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年&emsp;&emsp;度">
<el-date-picker
v-model="pageForm.year"
type="year"
style="width: 100%"
value-format="yyyy"
placeholder="请选择年度">
</el-date-picker>
</search-item>
<search-item label="项目名称">
<el-input placeholder="请输入项目名称" clearable v-model="pageForm.name"
@keyup.enter.native="doSearch" style="width:100%"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="体检项目" :app="this">
<el-button type="primary" size="small"
@click="openAdd">新建体检项目
</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id"
@sort-change="pageOrder" :size="tableSize"
v-loading="tableLoading" ref="table" 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
:sortable="column.sortable"
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width" min-width="100px">
<template v-if="column.prop=='choiceTime'" v-slot="{row}">
{{row.choiceTimeStart}}-{{row.choiceTimeEnd}}
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作" width="100px">
<template slot-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:'code',data:row}">
二维码
</el-dropdown-item>
<el-dropdown-item
v-if="( row.isWithinChoiceTime || row.canCreated ) && row.isHasUserList===0"
:command="{type:'created',data:row}">
生成名单
</el-dropdown-item>
<el-dropdown-item
v-if="( row.isWithinChoiceTime || row.canCreated ) && row.isHasUserList>0"
:command="{type:'renew',data:row}">
更新名单
</el-dropdown-item>
<el-dropdown-item
v-if="( row.isWithinChoiceTime || row.canCreated ) && row.isHasUserList>0"
:command="{type:'reset',data:row}">
重置名单
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',data:row}">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',data:row}">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<el-form :model="formData" ref="form" :rules="formRules" label-width="120px"
v-loading="formLoading">
<table-tool label="体检项目信息"></table-tool>
<el-form-item prop="name" label="项目名称">
<el-input v-model="formData.name" placeholder="项目名称" maxlength="100"></el-input>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item prop="choiceTime" label="选择时间">
<el-date-picker
style="width: 80%"
v-model="formData.choiceTime"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="activityGroupId" label="可报名人员范围">
<permission-group :value.sync="formData.activityGroupId"></permission-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item prop="healthCheckupType" label="体检对象类型">
<el-radio-group v-model="formData.healthCheckupType">
<el-radio-button label="jzg">教职工</el-radio-button>
<el-radio-button label="js">家属</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="体检套餐" prop="healthCheckupProjectSubjects">
<el-card shadow="hover" v-for="(item,index) in formData.healthCheckupProjectSubjects"
:key="index">
<el-row :gutter="20">
<el-col :span="4">
医院名称:
<el-input v-model="item.optionName"></el-input>
</el-col>
<el-col :span="4">
排序:
<el-input v-model="item.optionSort"></el-input>
</el-col>
<!--<el-col :span="4">
封面图<file-upload :upload_number="1" :value.sync="item.imgUrl"
accept=".jpg,.jpeg,.png"
class="imgUrl"
upload_result_type="url"
complete_result upload_mode="file"></file-upload>
</el-col>-->
<el-col :span="4">
编辑说明:
<div>
<el-button type="primary" size="small"
@click="openDescRichText(item.description,index)">编辑说明
</el-button>
</div>
</el-col>
<el-col :span="2">
操作:
<div>
<el-button type="danger" size="small"
:disabled="formData.healthCheckupProjectSubjects.length===1"
@click="deleteSubject(item,index)">删除
</el-button>
</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
医院方提供材料:
<div>
<file-upload :value.sync="item.files"
upload_mode="file"
:upload_number="10" upload_result_category="array"
accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png"
complete_result></file-upload>
</div>
</el-col>
</el-row>
<div class="s-options-list" style="margin-top: 10px;">
<el-table :data="item.subjectMoneys" border size="small">
<el-table-column label="名称">
<template slot-scope="{row}">
<el-input v-model="row.subjectMoneyName" autosize
class="text-input"
data-type="option"
></el-input>
</template>
</el-table-column>
<el-table-column label="套餐金额">
<template slot-scope="{row}">
<el-input v-model="row.money" autosize
class="text-input"
data-type="option"
></el-input>
</template>
</el-table-column>
<el-table-column label="结算金额">
<template slot-scope="{row}">
<el-input v-model="row.settlementMoney" autosize
class="text-input"
data-type="option"
></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="200px">
<template slot-scope="{row,$index}" slot="header">
<el-button size="mini" type="primary"
@click="item.subjectMoneys.push({
money:'',
settlementMoney:'',
subjectMoneyName:'',
marriage:'',
})">添加
</el-button>
</template>
<template slot-scope="{row,$index}">
<div class="option-delete">
<el-button size="mini" type="primary"
@click="openCnd(row,$index,index)">设置可选条件
</el-button>
<el-button size="mini" type="danger"
@click="deleteRow(row,$index,index)">删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
<div class="s-operation">
<el-button size="small" type="primary"
@click="formData.healthCheckupProjectSubjects.push({optionNameId:'',
optionName:'套餐'+(formData.healthCheckupProjectSubjects.length+1),
optionSort:formData.healthCheckupProjectSubjects.length+1,
imgUrl:null,
subjectMoneys:[]})">
添加医院
</el-button>
</div>
</el-form-item>
<el-form-item label="项目封面" prop="cover">
<file-upload :upload_number="1" :value.sync="formData.cover"
accept=".jpg,.jpeg,.png"
class="imgUrl"
upload_result_type="url"
complete_result upload_mode="image"></file-upload>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div style="display: flex;justify-content: flex-end">
<el-button @click="doAdd" type="primary">
提交
</el-button>
</div>
</template>
<template #view>
<el-descriptions :column="3" border class="table_fixed">
<el-descriptions-item :span="3" label="项目名称">
{{viewData.name}}
</el-descriptions-item>
<el-descriptions-item :span="3" label="选择时间">
{{viewData.choiceTimeStart}}-{{viewData.choiceTimeEnd}}
</el-descriptions-item>
<el-descriptions-item :span="3" label="可报名人员范围">
{{viewData.activityGroupName}}
</el-descriptions-item>
<el-descriptions-item :span="3" label="体检对象类型">
{{viewData.healthCheckupType==='jzg'?'教职工':'家属'}}
</el-descriptions-item>
<template v-for="i in viewData.healthCheckupProjectSubjects">
<el-descriptions-item label="套餐名称">
{{i.optionName}}
</el-descriptions-item>
<el-descriptions-item label="套餐说明">
<el-link type="primary"
@click="openViewDescRichText(i.description)">
点击查看说明
</el-link>
</el-descriptions-item>
<el-descriptions-item label="套餐图片">
<file-preview :files="i.imgUrl" v-if="i.imgUrl"></file-preview>
<div v-else>暂无</div>
</el-descriptions-item>
</template>
</el-descriptions>
</template>
</guava>
<drawer-user-scope
@group_change="getActivityGroup"
ref="drawerUserScope"
:group_id.sync="formData.activityGroupId"
></drawer-user-scope>
<el-dialog
title="活动二维码"
:visible.sync="codeDialogVisible"
:close-on-click-modal="false"
width="30%">
<div style=" display: flex;justify-content: center;">
<qrcode :options="{ width: 400 }" :value="activityUrl"></qrcode>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="codeDialogVisible = false" type="primary">关 闭</el-button>
</span>
</el-dialog>
<el-dialog
:close-on-click-modal="false"
:visible.sync="richTextDialog"
:title="(subjectIndex!==null&&subjectIndex>=0)?'编辑说明':'查看说明'"
:append-to-body="true"
width="60%">
<template>
<text-editor v-model="description" v-if="subjectIndex!==null&&subjectIndex>=0"></text-editor>
<div v-else v-html="description"></div>
</template>
<span slot="footer" class="dialog-footer">
<template v-if="subjectIndex!==null&&subjectIndex>=0">
<el-button @click="richTextDialog = false">关 闭</el-button>
<el-button type="primary" @click="getRichText">确 定</el-button>
</template>
<template v-else>
<el-button @click="richTextDialog = false" type="primary">关 闭</el-button>
</template>
</span>
</el-dialog>
<el-dialog
:close-on-click-modal="false"
:visible.sync="subjectMoneyDialog"
title="套餐"
width="50%"
>
</el-dialog>
<condition-structure-dialog ref="conditionStructureDialog" @confirm="addCondition"></condition-structure-dialog>
<el-dialog :visible.sync="conditionStructureDialogVisible" title="条件构造器">
<condition-group :group="conditionGroup" :field_options="fieldOptions"
@remove="removeRootGroup"></condition-group>
<div slot="footer">
<el-button @click="conditionStructureDialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmCnd">确定</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/ConditionStructure.js"){}#-->
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
showSubmit: true,
conditions: {
method: "",
conditions: [{}],
},
viewData: {},
subjectIndex: null,
richTextDialog: false,
activityGroupList: [],
pageForm: {
year: moment().format('YYYY')
},
formData: {
healthCheckupProjectSubjects: []
},
tableColumns: [
{prop: 'year', label: '年度'},
{prop: 'name', label: '项目名称'},
{prop: 'choiceTime', label: '选择时间'},
],
formRules: {
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
choiceTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
activityGroupId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
// cover: [{required: true, message: '必填', trigger: ['blur', 'change']}],
healthCheckupType: [{required: true, message: '必填', trigger: ['blur', 'change']}],
healthCheckupProjectSubjects: [{
required: true,
message: '必填',
trigger: ['blur', 'change']
}],
},
deleteRowIds: [],
description: "",
codeDialogVisible: false,
activityUrl: '',
rowData: {},
subjectRowData: {},
subjectMoneyDialog: false,
subjectMoneyIndex: null,
hospitalIndex: null,
deleteSubjectIds: {},
// 条件构造器相关
conditionStructureDialogVisible: false,
// 可选字段列表
fieldOptions: [
{label: "姓名", value: "username"},
{label: "工号", value: "loginname"},
{label: "性别", value: "sex"},
{label: "年龄", value: "age"},
{label: "婚姻状况", value: "marriage"},
{label: "在职状态", value: "userState"},
{label: "编制类别", value: "preparedBy"},
{label: "教职工类别", value: "personType"},
],
conditionGroup: {
logic: "AND",
conditions: [],
groups: []
}
}
},
components: {
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue"),
"condition-structure-dialog": CONDITION_STRUCTURE_DIALOG
},
methods: {
removeRootGroup() {
// 重置根条件组
this.updateFromData.conditionGroup = {
logic: "AND",
conditions: [],
groups: []
}
},
dropdownCommand(command) {
const {type, data} = command
if (type === 'view') {
this.openView(data)
} else if (type === 'created') {
this.createUserList(data)
} else if (type === 'renew') {
this.renewUserList(data)
} else if (type === 'reset') {
this.resetUserList(data)
} else if (type === 'edit') {
this.openEdit(data)
} else if (type === 'delete') {
this.doDelete(data.id)
} else if (type === 'code') {
this.openCode(data.id)
}
},
openAddSubjectMoney(row, index) {
row.index = index
this.subjectRowData = row
this.subjectMoneyDialog = true
},
addCondition(val) {
this.$set(this.formData.healthCheckupProjectSubjects[this.subjectMoneyIndex].subjectMoneys[this.rowData.index], 'matchCnd', val)
},
openCnd(row, subjectIndex, hospitalIndex) {
this.rowData = row
this.subjectMoneyIndex = subjectIndex
this.hospitalIndex = hospitalIndex
this.conditionStructureDialogVisible = true
if (row.matchCnd) {
this.conditionGroup = row.matchCnd
} else {
this.conditionGroup = {
logic: "AND",
conditions: [],
groups: []
}
}
// this.$refs.conditionStructureDialog.onOpen(row.matchCnd ? row.matchCnd : null)
},
// 条件构造器确认
confirmCnd() {
this.conditionStructureDialogVisible = false
this.$set(this.formData.healthCheckupProjectSubjects[this.hospitalIndex].subjectMoneys[this.subjectMoneyIndex], 'matchCnd', this.conditionGroup)
},
async createUserList(row) {
const msg = '您确定要生成【' + row.name + '】体检名单吗?(该名单生成是按照创建时选择的可报名人员范围来生成)'
const confirm = await this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if ('confirm' !== confirm) return
const loading = this.$loading({
lock: true,
text: '数据更新中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const resp = await this.$axios.post(loc() + '/createUserList', row)
if (resp.code === 0) {
setTimeout(() => {
loading.close()
this.$message.success('操作成功')
this.pageData()
}, 1000)
} else {
this.$message.warning(resp.msg)
}
},
async renewUserList(row) {
const msg = '您确定要更新【' + row.name + '】的体检名单吗?(如可报名人员范围发生变化会删除已选择的人员信息)'
const confirm = await this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if ('confirm' !== confirm) return
const loading = this.$loading({
lock: true,
text: '数据更新中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const resp = await this.$axios.post(loc() + '/renewUserList', row)
loading.close()
if (resp.code === 0) {
this.$message.success('操作成功')
this.pageData()
} else {
this.$message.warning(resp.msg)
}
},
async resetUserList(row) {
const msg = '您确定要重置【' + row.name + '】的体检名单吗?(该操作会将所有已选择的人员清空后,在进行生成)'
const confirm = await this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if ('confirm' !== confirm) return
const loading = this.$loading({
lock: true,
text: '数据更新中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const resp = await this.$axios.post(loc() + '/resetUserList', row)
loading.close()
if (resp.code === 0) {
this.$message.success('操作成功')
this.pageData()
} else {
this.$message.warning(resp.msg)
}
},
openCode(id) {
this.activityUrl = location.origin + "/platform/healthCheckup/project/mange"
this.codeDialogVisible = true
},
deleteSubject(row, index) {
this.formData.healthCheckupProjectSubjects.splice(index, 1)
if (row.id) this.deleteSubjectIds.push(row.id)
},
deleteRow(row, index, subjectMoneyIndex) {
this.formData.healthCheckupProjectSubjects[subjectMoneyIndex].subjectMoneys.splice(index, 1)
if (row.id) this.deleteRowIds.push(row.id)
},
async doDelete(id) {
const confirm = await this.$confirm('确定要删除该项目吗?', '提示', {type: 'warning'})
if (confirm) {
const resp = await this.$axios.post(loc() + "/doDelete", {id})
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
},
async openEdit(row) {
this.formData = await this.findOne(row.id)
this.$refs.guava.edit()
},
async openView(row) {
this.viewData = await this.findOne(row.id)
this.$refs.guava.view()
},
async findOne(id) {
const resp = await this.$axios.post(loc() + "/findOne", {id: id})
if (resp.code === 0) {
resp.data.choiceTime = [resp.data.choiceTimeStart, resp.data.choiceTimeEnd]
return resp.data
} else {
this.notifyError("查询失败")
}
},
async doAdd() {
const formValid = await this.$refs["form"].validate()
if (formValid) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const formData = clone(this.formData)
formData.choiceTimeStart = formData.choiceTime[0]
formData.choiceTimeEnd = formData.choiceTime[1]
formData.healthCheckupProjectSubjects = JSON.stringify(this.formData.healthCheckupProjectSubjects)
formData.activityGroupName = this.activityGroupList.find(v => v.groupId === this.formData.activityGroupId).groupName
formData.deleteRowIds = JSON.stringify(this.deleteRowIds)
formData.deleteSubjectIds = JSON.stringify(this.deleteSubjectIds)
const resp = await this.$axios.post("/platform/healthCheckup/project/mange/doAdd", formData)
loading.close()
if (resp.code === 0) {
this.pageData()
this.$refs.guava.index()
this.deleteRowIds = []
this.deleteSubjectIds = []
} else {
this.notifyWarning(resp.msg)
}
}
},
openAdd() {
this.formData = {
name: null,
activityGroupId: null,
choiceTime: null,
healthCheckupProjectSubjects: [
{
optionName: '套餐1',
optionNameId: '',
optionSort: '1',
imgUrl: '',
subjectMoneys: []
}
]
}
if (this.$refs.form) this.$refs.form.resetFields();
this.$refs.guava.edit()
},
openDescRichText(richText, sIdx) {
this.subjectIndex = sIdx
this.description = richText
this.richTextDialog = true
},
openViewDescRichText(richText) {
this.subjectIndex = null
this.description = richText
this.richTextDialog = true
},
getRichText() {
this.formData.healthCheckupProjectSubjects[this.subjectIndex].description = this.description
this.richTextDialog = false
},
async getActivityGroup() {
const {data} = await this.$axios.post('/platform/activity/basic/scope/getActivityUserScopeGroup')
this.activityGroupList = data
},
},
async created() {
this.getActivityGroup()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,512 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div class="platform" id="app" v-cloak>
<guava padding="0 5%" ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
clearable
@change="yearChange"
placeholder="选择年"
style="width: 100%;"
type="year"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="体检项目">
<el-select @change="getHealthCheckupSubject();"
style="width: 100%;"
v-model="pageForm.projectId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in projectOptions"></el-option>
</el-select>
</search-item>
<search-item label="所属工会" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<el-select placeholder="请选择所属工会" v-model="pageForm.unionId"
style="width: 100%;"
:clearable="clearable"
@change="flushUnits" @clear="flushUnits"
filterable>
<el-option v-for="item in unions" :label="item.name"
:value="item.id" :key="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" :key="item.id"></el-option>
</el-select>
</search-item>-->
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="工会列表">
<template
v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN', 'BRANCH_UNION_CHAIRMAN'])">
<template v-if="projectInfo.healthCheckupType==='jzg'">
<el-button :disabled="!pageForm.projectId"
@click="exportReceiveDetail(true)"
icon="el-icon-printer"
size="small"
type="primary">导出教职工已选名单
</el-button>
<el-button :disabled="!pageForm.projectId"
@click="exportReceiveDetail(false)"
icon="el-icon-printer"
size="small"
type="primary"
v-if="projectInfo.healthCheckupType==='jzg'">导出教职工未选名单
</el-button>
<!-- <el-button @click="selectOptionByAdmin"
icon="el-icon-printer"
size="small"
type="primary"
v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">管理员代选择
</el-button>-->
<el-button @click="selectOptionByLastYear"
icon="el-icon-printer"
size="small"
type="primary"
v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">一键选择去年数据
</el-button>
<el-button @click="msgNotSelect"
icon="el-icon-printer"
size="small"
type="primary"
v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">给未选发送消息
</el-button>
</template>
<el-button :disabled="!pageForm.projectId"
@click="exportUserCompanion()"
icon="el-icon-printer"
size="small"
type="primary"
v-if="projectInfo.healthCheckupType==='js'">导出家属名单
</el-button>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize" :summary-method="getSummaries"
@sort-change="pageOrder" class="vi-table"
ref="table" row-key="id" show-summary
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"
:key="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 v-slot="{row}" v-if="column.prop==='unselectedTeacherSum'">
<el-link @click="openUnclaimed(row.id)" type="primary">
{{row.unselectedTeacherSum}}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" header-align="center"
label="操作" prop="userOnline"
width="200px">
<template slot-scope="{row}">
<el-button @click="openView(row.id)" size="mini"
type="primary"
v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN', 'BRANCH_UNION_CHAIRMAN'])">
查看已选人员
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</template>
<template #view>
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-option">
<el-input clearable placeholder="请输入内容"
v-model="pageFormUnion.searchKeyword">
<el-select @keyup.enter.native="doUnionSearch" placeholder="查询类型"
slot="prepend"
style="width: 80px;"
v-model="pageFormUnion.searchName">
<el-option label="姓名" value="u.username"></el-option>
<el-option label="工号" value="u.loginname"></el-option>
</el-select>
</el-input>
</div>
</div>
<div class="search-query">
<el-button @click="doUnionSearch" icon="el-icon-search" type="primary">搜索
</el-button>
</div>
</div>
</el-card>
<el-card class="mt10" shadow="never">
<div v-if="pageFormUnion.isSelected=='0'">
<table-tool label="已选人员"></table-tool>
</div>
<div v-else>
<table-tool label="未选人员"></table-tool>
</div>
<el-table :data="receive_tableData" :size="tableSize" class="vi-table"
height="100%"
row-key="id" style="width: 100%;height: 700px" v-loading="tableLoading">
<el-table-column type="index" width="50"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
show-overflow-tooltip
v-for="column in receive_tableColumns"
:key="column.prop"
>
</el-table-column>
</el-table>
</el-card>
<el-row class="el-pagination-container" style="margin-bottom: 0px">
<el-pagination
:current-page="pageFormUnion.pageNumber"
:page-size="pageFormUnion.pageSize"
:page-sizes="[5,10, 20, 30, 50]"
:total="pageFormUnion.totalCount"
@current-change="pageNumberChange"
@size-change="pageSizeChange"
layout="total, sizes, prev, pager, next">
</el-pagination>
</el-row>
</template>
</guava>
<el-dialog :visible.sync="selectByAdminDialogVisible" title="管理员代选体检项目"
width="35%">
<el-form label-position="right" label-width="120px">
<el-form-item label="体检项目">
<el-select style="width: 100%" v-model="noSelectOptionId">
<el-option :key="item.id" :label="item.optionName" :value="item.id"
v-for="item in projectSubjectOptions"></el-option>
</el-select>
</el-form-item>
<el-form-item
label="院区"
prop="campus">
<el-select style="width: 100%" v-model="campus">
<el-option :key="item.id" :label="item.campusName" :value="item.id"
v-for="item in campusOptions"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-row justify="end" type="flex">
<el-button @click="selectByAdminDialogVisible=false">取消</el-button>
<el-button @click="doSelectByAdmin" type="primary" :loading="loading">提交</el-button>
</el-row>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
pageForm: {
year: moment().format('YYYY'),
},
pageFormUnion: {
pageNumber: 1,
pageSize: 10,
totalCount: null,
searchName: 'u.username',
//0:已选人员页面 1:未选人员页面
isSelected: '',
},
units: [],
unions: [],
projectOptions: [],
receive_tableColumns: [],
receive_tableData: [],
clearable: false,
tableColumns: [
{prop: 'unionName', label: '所属工会'},
{prop: 'sumCount', label: '本次体检人数'},
],
projectInfo: {},
selectByAdminDialogVisible: false,
projectSubjectOptions: [],
campusOptions: [],
noSelectOptionId: null,
campus: null,
loading: false,
}
},
methods: {
async msgNotSelect() {
const confirm = await this.$confirm('请确定未选择的教职工发送提醒短信?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === "confirm") {
this.tableLoading = true
const resp = await $.get(loc() + '/msgNotSelect', {
projectId: this.pageForm.projectId
})
if (resp.code === 0) {
setTimeout(() => {
this.doSearch()
this.tableLoading = false
this.notifySuccess(resp.msg)
}, 2000)
} else {
this.notifyWarning(resp.msg)
}
}
},
async doSelectByAdmin() {
if (!this.noSelectOptionId || !this.campus) {
this.notifyWarning('请选择套餐/院区')
return
}
const {optionName} = this.projectSubjectOptions.find(v => v.id === this.noSelectOptionId)
const confirm = await this.$confirm('请确定是否把【' + optionName + '】套餐赋给未选择的教职工?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === "confirm") {
this.loading = true
const resp = await $.get(loc() + '/doSelectByAdmin', {
optionId: this.noSelectOptionId,
campus: this.campus,
projectId: this.pageForm.projectId
})
if (resp.code === 0) {
setTimeout(() => {
this.doSearch()
this.loading = false
this.selectByAdminDialogVisible = false
this.notifySuccess(resp.msg)
}, 2000)
} else {
this.notifyWarning(resp.msg)
}
}
},
async selectOptionByLastYear() {
const confirm = await this.$confirm('请确定是否把没有选择的教职工统一选择去年的数据?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === "confirm") {
const resp = await this.$axios.post(loc() + '/selectOptionByLastYear', {
projectId: this.pageForm.projectId
})
if (resp.code === 0) {
this.doSearch()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
},
selectOptionByAdmin() {
this.noSelectOptionId = null
this.selectByAdminDialogVisible = true
},
async yearChange() {
const resp = await this.$axios.post("/platform/healthCheckup/project/mange/getHealthCheckupProject", {year: this.pageForm.year})
if (resp.code === 0) {
this.projectOptions = resp.data
if (resp.data && resp.data.length > 0) {
this.$set(this.pageForm, "projectId", resp.data[0].id)
} else {
this.$set(this.pageForm, "projectId", null)
}
await this.getHealthCheckupSubject()
} else {
this.notifyError(resp.msg)
}
},
async getHealthCheckupSubject() {
this.projectSubjectOptions = []
const resp = await this.$axios.post("/platform/healthCheckup/project/mange/findOne", {id: this.pageForm.projectId})
if (resp.code === 0) {
if (resp.data) {
this.projectInfo = resp.data
this.projectSubjectOptions = resp.data.healthCheckupProjectSubjects
}
} else {
this.notifyError(resp.msg)
}
this.doSearch()
},
async queryCampus() {
const resp = await this.$axios.post("/platform/healthCheckup/campus/queryCampus")
if (resp.code === 0) {
this.campusOptions = resp.data
} else {
this.notifyError(resp.msg)
}
},
async pageData() {
this.tableColumns = []
const loading = this.$loading({
lock: true,
text: '努力加载中。。。',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.tableColumns.push(
{prop: 'unionName', label: '所属工会'},
{prop: 'sumCount', label: '本次体检人数'}
)
if (this.projectSubjectOptions && this.projectSubjectOptions.length > 0) {
this.projectSubjectOptions.forEach(v => {
this.tableColumns.push({prop: v.optionName, label: v.optionName})
})
}
this.tableColumns.push(
{prop: "totalCount", label: "选取人数"},
{prop: "unselectedTeacherSum", label: "未选人数"}
)
if (!this.pageForm.projectId) {
this.tableData = []
}
const resp = await this.$axios.post(loc() + '/pageData', this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data.tableList
}
loading.close()
},
pageNumberChange(val) {
this.pageFormUnion.pageNumber = val;
this.pageUnionData();
},
pageSizeChange(val) {
this.pageFormUnion.pageSize = val;
this.pageUnionData();
},
async flushUnits() {
this.$set(this.pageForm, "unitId", "")
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
} else {
this.units = await this.$businessTool.listUnit()
}
},
async init() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.unions = await this.$businessTool.listUnion()
this.clearable = true
} else {
this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id)
this.$set(this.pageForm, "unionId", this.unions[0].id)
}
await this.yearChange()
await this.queryCampus()
},
//查看未选择人数
async openUnclaimed(unionId) {
this.pageFormUnion.isSelected = '1'
this.pageFormUnion.unionId = unionId
this.pageFormUnion.projectId = this.pageForm.projectId
await this.pageUnionData();
},
//查看已选人员
async openView(unionId) {
this.pageFormUnion.isSelected = '0'
this.pageFormUnion.unionId = unionId
this.pageFormUnion.projectId = this.pageForm.projectId
await this.pageUnionData();
},
async pageUnionData() {
const resp = await this.$axios.post(loc() + '/receivePageData', this.pageFormUnion)
if (resp.code === 0) {
this.$refs.guava.view()
this.receive_tableColumns = resp.data.label
this.receive_tableData = resp.data.list.list
this.pageFormUnion.totalCount = resp.data.list.totalCount
}
},
doUnionSearch() {
this.pageFormUnion.pageNumber = 1
this.pageUnionData();
},
//按分工会导出已选名单
exportReceiveDetail(flag) {
const {year, projectId, unionId} = this.pageForm
window.open(loc() + '/exportReceiveDetail?year=' + year + '&projectId=' + projectId + '&unionId=' + (unionId ? unionId : '') + '&flag=' + flag)
},
//导出家属信息
exportUserCompanion() {
const {year, projectId, unionId} = this.pageForm
window.open(loc() + '/exportUserCompanion?year=' + year + '&projectId=' + projectId + '&unionId=' + (unionId ? unionId : ''))
},
getSummaries(param) {
const {columns, data} = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '总计';
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return Math.floor((prev + curr) * 100) / 100;
} else {
return prev;
}
}, 0);
sums[index] += ' 人';
} else {
sums[index] = null;
}
});
return sums;
}
},
async created() {
this.init()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,630 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-select {
width: 100%;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<div class="btn-group tool-button">
<div class="block">
<el-date-picker
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="年度">
</el-date-picker>
</div>
</div>
<div class="btn-group tool-button">
<el-select v-model="pageForm.honorLevel" placeholder="请选择级别" style="width: 100%"
@change="doSearch"
clearable>
<el-option v-for="o in honorLevelList"
:key="o.id"
:label="o.name"
:value="o.id"
></el-option>
</el-select>
</div>
<div class="btn-group tool-button mt5">
<el-radio-group v-model="pageForm.honorType" @change="doSearch">
<el-radio-button v-for="v in honorTypeList" :label="v.id">{{v.name}}</el-radio-button>
</el-radio-group>
</div>
<div class="btn-group tool-button">
<el-button type="primary" @click="doSearch" icon="el-icon-search"></el-button>
</div>
<div class="pull-right offscreen-right">
<el-button size="medium" type="primary" @click="applyHonor">申请荣誉</el-button>
</div>
</el-card>
<honor-apply-table :loading="tableLoading" :page="pageForm" :data="tableData"
ref="hat"
@order="pageOrder">
<template #vi-title>
<vi-title title="申请列表"></vi-title>
</template>
<template #column>
<el-table-column align="center" header-align="center" label="操作" fixed="right" width="150px">
<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:'edit',data:row}"
:disabled="(row.honorType=='101'&&row.stateId>1500)||(row.honorType=='102'&&row.stateId>1600)">
编辑
</el-dropdown-item>
<!--#if(@shiro.hasRole('sysadmin')){#-->
<el-dropdown-item :command="{type:'delete',data:row}"
:loading="row.delLoading">
删除
</el-dropdown-item>
<!--#}else{#-->
<el-dropdown-item :command="{type:'delete',data:row}"
:disabled="(row.honorType=='101'&&row.stateId>1500)||(row.honorType=='102'&&row.stateId>1600)"
:loading="row.delLoading">
删除
</el-dropdown-item>
<!--#}#-->
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</template>
<template #pagination>
<!--#include("/layouts/pagination.html"){}#-->
</template>
</honor-apply-table>
</template>
<template #edit>
<template #header>
<el-row type="flex" justify="space-between">
<h3>{{isEdit?'修改数据':'添加数据'}}</h3>
</el-row>
</template>
<el-form :model="formData" label-width="120px" ref="form">
<el-row type="flex" :gutter="20">
<el-col :span="24">
<el-form-item label="荣誉类型" prop="honorType">
<el-select v-model="formData.honorType" @change="honorTypeChange" :disabled="isEdit">
<el-option v-for="o in honorTypeList"
:key="o.id"
:label="o.name"
:value="o.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-collapse v-model="collapse">
<el-collapse-item title="" name="basic">
<template slot="title">
<div class="text-primary" style="width: 100%">
基础信息
</div>
</template>
<template v-if="formData.honorType===HonorApi.honor_single_id">
<el-row type="flex" :gutter="20">
<el-col :span="24" prop="userId">
<el-form-item prop="userId" label="获奖人员">
<el-select
style="width: 100%"
v-model="formData.userId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入姓名或工号查找"
:remote-method="userRemoteMethod"
:loading="userLoading"
@change="userChange"
:disabled="isEdit">
<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-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="性别" prop="userSex">
<el-radio-group v-model="formData.userSex" :disabled="isEdit">
<el-radio-button label="男"></el-radio-button>
<el-radio-button label="女"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="在职状态" prop="jobStatus">
<el-input v-model="formData.jobStatus"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="担任工会职务" prop="post">
<el-input v-model="formData.post"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="职称" prop="title">
<el-input v-model="formData.title"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="生日" prop="birthday">
<el-date-picker
style="width: 100%"
v-model="formData.birthday"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="政治面貌" prop="political">
<el-input v-model="formData.political"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="民族" prop="nation">
<el-select placeholder="民族" style="width: 100%" filterable
v-model="formData.nation">
<el-option v-for="nation in nationOptions" :key="nation" :value="nation"
:label="nation"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="加入工会时间" prop="joinTime">
<el-date-picker
style="width: 100%"
v-model="formData.joinTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="所属单位" prop="unitId">
<el-select placeholder="所属单位" v-model="formData.unitId" clearable
style="width: 100%;"
clearable="true"
filterable="true"
:disabled="isEdit">
<el-option v-for="item in units"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属工会" prop="unionId">
<el-select placeholder="所属工会" v-model="formData.unionId" clearable
style="width: 100%;"
clearable="true"
filterable="true"
:disabled="isEdit">
<el-option v-for="item in unions"
:label="item.unionname"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
<template v-else>
<el-row type="flex">
<el-col :span="12">
<!--<el-form-item label="获奖单位" prop="unitName">
<el-select placeholder="获奖单位" v-model="formData.unitName"
style="width: 100%;"
clearable="true"
filterable
allow-create
:disabled="isEdit">
<el-option v-for="item in units"
:label="item.name"
:value="item.name"></el-option>
</el-select>
</el-form-item>-->
<el-form-item label="申报分工会" prop="unionId">
<el-select placeholder="请选择申报分工会" v-model="formData.unionId"
style="width: 100%;"
clearable="true"
filterable
@change="unionSelectChange"
:disabled="isEdit">
<el-option v-for="item in unions"
:label="item.unionname"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<!--<el-form-item label="所属工会" prop="unionId">
<el-select placeholder="所属工会" v-model="formData.unionId"
style="width: 100%;"
clearable="true"
filterable="true"
:disabled="isEdit">
<el-option v-for="item in unions"
:label="item.unionname"
:value="item.id"></el-option>
</el-select>
</el-form-item>-->
<el-form-item label="工会主席" prop="unionLeader">
<el-input v-model="formData.unionLeader"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex">
<!--<el-col :span="8">
<el-form-item label="单位负责人" prop="unitLeader">
<el-input v-model="formData.unitLeader"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="单位人数" prop="unitPeopleNum">
<el-input-number v-model="formData.unitPeopleNum" :min="0"
:max="2000" style="width: 100%"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="女职工人员" prop="unitFemalePeopleNum">
<el-input-number
v-model.number="formData.unitFemalePeopleNum" :min="0"
:max="2000" style="width: 100%"></el-input-number>
</el-form-item>
</el-col>-->
<el-col :span="12">
<el-form-item label="会员人数" prop="memberNumber">
<el-input-number v-model="formData.memberNumber" :min="0"
:max="2000" style="width: 100%"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工会小组数" prop="unionGroupNumber">
<el-input-number v-model="formData.unionGroupNumber" :min="0"
:max="2000" style="width: 100%"></el-input-number>
</el-form-item>
</el-col>
</el-row>
</template>
<el-row type="flex" :gutter="20">
<el-col :span="24">
<el-form-item label="曾受何种奖励" prop="award">
<el-input v-model="formData.award" type="textarea" rows="4"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="24">
<el-form-item label="主要事迹" prop="Deeds">
<el-input v-model="formData.Deeds" type="textarea" rows="4"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-collapse-item>
<el-collapse-item title="获奖信息" name="prize">
<template slot="title">
<div class="text-primary" style="width: 100%">
获奖信息
</div>
</template>
<template>
<!-- <el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="奖项" prop="prize">
<el-select v-model="formData.prize">
<el-option v-for="o in honorPrizeList"
:key="o.id"
:label="o.name"
:value="o.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="奖项说明" prop="prizeDesc">
<el-input v-model="formData.prizeDesc" maxlength="100"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item label="级别">
<el-select v-model="formData.honorLevel" placeholder="">
<el-option v-for="o in honorLevelList"
:key="o.id"
:label="o.name"
:value="o.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
-->
</el-row>
<el-col :span="24">
<el-form-item label="附件" prop="files">
<file-upload card :files.sync="formData.files" :max-size="50 * 1024 * 1024"></file-upload>
</el-form-item>
</el-col>
</template>
</el-collapse-item>
</el-collapse>
</el-form>
<el-row class="m20 text-right">
<el-button type="primary" @click="doSubmit">提交</el-button>
</el-row>
</template>
<template #view>
<honor-info ref="info"></honor-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
units: [],
unions: [],
nationOptions: nation,
honorTypeList: [],
honorLevelList: [],
honorAwardList: [],
honorPrizeList: [],
collapse: ['basic', 'prize'],
userLoading: false,
userOptions: [],
isEdit: false,
pageForm: {
year: new Date().getFullYear() + "",
honorType: '',
honorLevel: ''
},
firstInPage: true,
}
},
components: {
'file-upload': httpVueLoader('/components/plugins/FileUpload.vue'),
'honor-apply-table': httpVueLoader('/components/honor/honorApplyTable.vue'),
'honor-info': httpVueLoader('/components/honor/honorInfo.vue'),
},
methods: {
unionSelectChange(val) {
},
dropdownCommand(command) {
const {type, data} = command
if (type == 'view') {
this.openView(data)
} else if (type == 'edit') {
this.openEdit(data)
} else if (type == 'delete') {
this.doDelete(data)
}
},
openView(data) {
this.$refs.info.getInfo(data.id)
this.$refs.guava.view()
},
doDelete(row) {
this.$confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" == a) {//确认后再执行
this.$set(row, "delLoading", true)
const resp = await $.post(loc() + '/doDelete', {id: row.id})
if (resp.code === 0) {
this.pageData()
this.$message.success(resp.msg)
}else{
this.$message.error(resp.msg)
}
this.$set(row, "delLoading", false)
}
}
});
},
openEdit(data) {
this.isEdit = true
this.findData(data)
this.$refs.guava.edit()
},
applyHonor() {
this.initData()
this.isEdit = false
this.$refs.guava.edit()
if (this.$refs['form']) {
this.$refs['form'].resetFields()
}
},
async userChange() {
const user = await queryUserById(this.formData.userId)
this.setFormData(user)
},
setFormData(user) {
this.$set(this.formData, "userSex", user[0].sex)
this.$set(this.formData, "userName", user[0].username)
this.$set(this.formData, "unitId", user[0].unitid)
this.$set(this.formData, "unionId", user[0].unionid)
this.$set(this.formData, "birthday", user[0].birthday)
this.$set(this.formData, "title", user[0].jobTitle)
//this.$set(this.formData, "post", user[0].position)
this.$set(this.formData, "unionName", user[0].unionname)
this.$set(this.formData, "unitName", user[0].unitname)
this.$set(this.formData, "jobStatus", user[0].userState)
this.$set(this.formData, "political", user[0].political)
},
async userRemoteMethod(query) {
if (query) {
this.userLoading = true
const arr = await searchUser(query)
this.userOptions = arr
this.userLoading = false
}
},
async initData() {
this.honorTypeList = await HonorApi.getHonorType()
if (this.honorTypeList) {
this.$set(this.pageForm,"honorType",this.honorTypeList[0].id)
this.formData = {
honorType: this.honorTypeList[0].id
}
this.honorPrizeList = await HonorApi.getHonorPrize(this.formData.honorType)
}
this.honorLevelList = await HonorApi.getHonorLevel()
this.honorAwardList = await HonorApi.getHonorAwardType()
this.units = await getUnits(null)
this.unions = await getUnions(null)
if (this.formData.honorType === HonorApi.honor_single_id) {
await this.userRemoteMethod("${@shiro.getPrincipalProperty('loginname')}")
this.$set(this.formData, "userId", this.userOptions[0].id)
await this.userChange()
}
},
async honorTypeChange(val) {
this.$set(this.formData, "prize", null)
this.honorPrizeList = await HonorApi.getHonorPrize(val)
if (this.formData.honorType === HonorApi.honor_single_id) {
await this.userRemoteMethod("${@shiro.getPrincipalProperty('loginname')}")
this.$set(this.formData, "userId", this.userOptions[0].id)
await this.userChange()
} else {
}
},
async doSubmit() {
this.formData.files = JSON.stringify(this.formData.files)
const resp = await $.post(loc() + '/doSubmit', this.formData)
if(resp.code===0){
this.$notify.success({title: '成功', message: resp.msg});
this.pageData()
this.$refs.guava.index()
}else{
this.$notify.error({title: '失败', message: resp.msg});
}
},
async findData(data) {
this.formData = {}
const data1 = clone(data)
this.honorPrizeList = await HonorApi.getHonorPrize(data.honorType)
this.formData = data1
if (this.formData.userId && this.formData.userId !== '') {
const user = await queryUserById(this.formData.userId)
this.setFormData(user)
} else {
this.$set(this.formData, 'userName', this.formData.userName)
}
this.$set(this.formData, "prize", data.prize)
this.$set(this.formData, "honorLevel", data.honorLevel)
this.$set(this.formData, "political", data.political)
this.$set(this.formData, "post", data.post)
this.$set(this.formData, "title", data.title)
this.$set(this.formData, "unionId", data1.unionId)
this.$set(this.formData, "unionLeader", data1.unionLeader)
if (data.files && data.files.length > 0) this.$set(this.formData, "files", JSON.parse(data.files))
}
},
watch: {
"formData.prize"(newVal) {
if (this.firstInPage === false && newVal) {
this.$set(this.formData, "honorLevel", this.honorPrizeList.find(v => v.id === newVal).level)
this.firstInPage = false
}
},
"formData.unitName"(newVal) {
const isExist = this.units.some(v => v.name == newVal)
if(this.formData.honorType === HonorApi.honor_single_id) {
if (isExist) {
const unionId = this.units.find(v => v.name == newVal).unionid
this.$set(this.formData, "unionId", unionId ? unionId : "")
} else {
this.$set(this.formData, "unionId", "")
}
}
},
"formData.unionId"(newVal) {
if(this.formData.honorType === HonorApi.honor_list_id) {
if(this.firstInPage === false) {
const un = this.unions.find(o => o.id === newVal)
this.formData.unionLeader = un ? un.leadername : ''
this.formData.unionName = un ? un.unionname : ''
} else {
this.firstInPage = false
}
}
}
},
async created() {
await this.initData()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,261 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<el-row :gutter="10" style="height: calc(100vh - 126px)" type="flex">
<el-col :span="5">
<el-card body-style="{ height: '100%' }" shadow="never" style="height: 100%">
<div style="max-height: calc(100vh - 170px); overflow-y: auto">
<el-tree
:data="treeData"
:default-expanded-keys="['1']"
:expand-on-click-node="false"
:filter-node-method="filterNode"
:props="{
children: 'child',
label: 'name'
}"
@node-click="nodeClick"
highlight-current
node-key="id"
ref="treeRef"
>
<template slot-scope="{ node, data }">
<span class="el-tree-node__label">
<i class="el-icon-folder-opened" v-if="node.level===1"></i>
<i class="el-icon-folder" v-else></i>
{{node.label}}
</span>
</template>
</el-tree>
</div>
</el-card>
</el-col>
<el-col :span="19">
<el-card shadow="never" style="height: 100%">
<table-tool>
<el-button @click="openAddBasicType" size="small" type="primary">
<i class="el-icon-plus"></i>
新建基础类型
</el-button>
</table-tool>
<el-table :data="tableData" :height="tableHeight" border ref="table" size="medium">
<el-table-column label="序号" sortable type="index" width="50px"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="代码" prop="code"></el-table-column>
<el-table-column label="等级" prop="level"
sortable
v-if="honorTypeList.map(h=>h.id).includes(chooseNode.id)">
<template slot-scope="{row}">
{{row.level?honorLevelList.find(v=>v.id === row.level).name:''}}
</template>
</el-table-column>
<el-table-column label="操作" width="200px">
<template slot-scope="{row}">
<el-button @click="openEditType(row)" size="mini" type="primary">
编辑
</el-button>
<el-button @click="doDelete(row)" size="mini" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
<el-dialog :close-on-click-modal="false" :visible.sync="basicTypeDialogVisible" title="基础类型"
width="40%">
<el-form :model="formData" :rules="rules" label-width="80" ref="basicForm">
<el-row gutter="30">
<el-form-item label="上级名称" prop="parentName" v-if="submitType==='add'">
<el-input disabled maxlength="100" type="text"
v-model="formData.parentName"></el-input>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input maxlength="100" placeholder="请输入基础类型名称" type="text"
v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="代码" prop="code">
<el-input maxlength="100" placeholder="请输入基础类型名称" type="text"
v-model="formData.code"></el-input>
</el-form-item>
<el-form-item label="荣誉等级" prop="level"
v-if="honorTypeList.map(h=>h.id).includes(chooseNode.id)">
<el-radio-group v-model="formData.level">
<el-radio-button :key="o.id" :label="o.id"
v-for="o in honorLevelList">{{o.name}}
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-row>
</el-form>
<div class="el-dialog__footer">
<el-button @click="doSubmit" type="primary">提交
</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
defaultExpandedKeys: ["1"],
basicTypeDialogVisible: false,
filterText: "",
treeData: [],
defaultProps: {
children: "child",
label: "name"
},
chooseNode: {},
formData: {},
rules: {
name: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
code: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
},
submitType: "add",
tableData: [],
honorLevelList: [],
honorTypeList: [],
tableHeight: null
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
}
},
components: {
"tree-layout": httpVueLoader("/components/plugins/TreeLayout.vue")
},
methods: {
filterNode(value, data, node) {
if (!value) return true
return data.name.indexOf(value) !== -1
},
openEditType(row) {
this.formData = {
id: row.id,
name: row.name,
code: row.code,
level: row.level
}
this.basicTypeDialogVisible = true
this.submitType = "edit"
},
doDelete({ id }) {
this.$confirm("确定要删除该机构吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: (a) => {
if ("confirm" === a) {
this.$axios.post(loc() + "/doDelete", { id: id }).then(res => {
if (res.code === 0) {
this.$notify.success({ title: "成功", message: res.msg })
this.getTree(false)
} else {
this.$notify.error({ title: "失败", message: res.msg })
}
})
}
}
})
},
getTree(changeNode = false) {
this.$axios.post("/platform/honor/basic/settings/getTree").then(res => {
if (res.code === 0) {
this.treeData = res.data
if (changeNode) {
this.chooseNode = res.data[0]
}
this.getData()
} else {
this.$notify.error({ message: res.msg, title: "失败" })
}
})
},
openAddBasicType() {
this.basicTypeDialogVisible = true
this.formData = {
parentId: this.chooseNode.id,
parentName: this.chooseNode.name,
name: "",
code: "",
level: this.honorTypeList.map(h => h.id).includes(this.chooseNode.id) ? this.honorLevelList[0].id : null
}
this.submitType = "add"
},
doSubmit() {
this.$refs["basicForm"].validate(async (valid) => {
if (valid) {
this.$axios.post("/platform/honor/basic/settings/doSubmit", this.formData).then(res => {
if (res.code === 0) {
this.$message.success("操作成功")
this.basicTypeDialogVisible = false
this.getTree(false)
} else {
this.$message.warning("操作失败")
}
})
}
})
},
nodeClick(data) {
this.chooseNode = data
this.getData()
},
getData() {
this.$axios.post("/platform/honor/basic/settings/getData", { parentId: this.chooseNode.id }).then(res => {
if (res.code === 0) {
this.tableData = res.data
}
})
},
getHonorType() {
this.$axios.post("/platform/honor/basic/settings/getHonorType").then(res => {
if (res.code === 0) {
this.honorTypeList = res.data
}
})
},
getHonorLevel() {
this.$axios.post("/platform/honor/basic/settings/getHonorLevel").then(res => {
if (res.code === 0) {
this.honorLevelList = res.data
}
})
}
},
async mounted() {
await this.getTree(true)
this.getHonorType()
this.getHonorLevel()
this.$nextTick(() => {
this.tableHeight = window.innerHeight - this.$refs.table.$el.children[2].getBoundingClientRect().top-200
window.onresize = () => {
this.tableHeight = window.innerHeight - this.$refs.table.$el.children[2].getBoundingClientRect().top-200
}
})
}
})
</script>
<!--#
}
#-->

Some files were not shown because too many files have changed in this diff Show More