This commit is contained in:
2025-12-17 20:10:08 +08:00
parent 6351aaba48
commit c35bea7cc7
23 changed files with 288 additions and 241 deletions
@@ -303,11 +303,11 @@
//设置用户信息
setUser(state, payload) {
state.user = payload
state.room = payload.loginname + ":${@auth.getSessionId()}"
}
},
actions: {}
})
$.get("/platform/sys/user/getLogonUser").then((res) => {
if (res.code === 0) {
window.sessionStorage.setItem("user", JSON.stringify(res.data))
@@ -122,7 +122,8 @@ layout("/layouts/platform.html"){
<el-descriptions-item label="活动预算费用" :span="2">
<el-form-item prop="budgets">
<el-table :data="formData.budgets" border max-height="500" size="mini" style="width: 95%" show-summary>
<el-table :data="formData.budgets" border max-height="500" size="mini" style="width: 95%"
show-summary>
<el-table-column label="序号" sortable type="index" width="100"></el-table-column>
<el-table-column label="费用项目名称" prop="name">
<template scope="{row,$index}">
@@ -342,8 +343,38 @@ layout("/layouts/platform.html"){
}
})
},
async init() {
async initActivityTypeList() {
this.activityDeclareReimbursementList = await this.$businessTool.getEnumOptions("ActivityDeclareReimbursement")
const activityDeclareReimbursementList = []
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
} else {
if (this.$auth.hasRoleOr(["SCHOOL_UNION_ACTIVITY_ADMIN"])) {
this.activityDeclareReimbursementList.map(v => {
if (["SCHOOL_UNION"].includes(v.name)) {
activityDeclareReimbursementList.push(v)
}
})
}
if (this.$auth.hasRoleOr(["BRANCH_UNION_WENTI_SPORTS", "UNION_REIMBURSEMENT_MANAGER"])) {
this.activityDeclareReimbursementList.map(v => {
if (["BRANCH_UNION"].includes(v.name)) {
activityDeclareReimbursementList.push(v)
}
})
}
if (this.$auth.hasRoleOr(["CLUB_PRESIDENT"])) {
this.activityDeclareReimbursementList.map(v => {
if (["CLUB"].includes(v.name)) {
activityDeclareReimbursementList.push(v)
}
})
}
this.activityDeclareReimbursementList = activityDeclareReimbursementList
}
},
async init() {
await this.initActivityTypeList()
if (this.bizId) {
this.findOne(this.bizId)
} else {
@@ -322,7 +322,8 @@ layout("/layouts/platform.html"){
planDate: [],
},
formRules: {
id: [{required: true, message: "必填", trigger: ['change', 'blur']}]
id: [{required: true, message: "必填", trigger: ['change', 'blur']}],
sign: [{required: true, message: "必填", trigger: ['change', 'blur']}]
},
activityOptions: [],
@@ -514,7 +515,7 @@ layout("/layouts/platform.html"){
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
} else {
if (this.$auth.hasRoleOr(["SCHOOL_REIMBURSEMENT_MANAGER","SCHOOL_REIMBURSEMENT_MANAGER"])) {
if (this.$auth.hasRoleOr(["SCHOOL_REIMBURSEMENT_MANAGER"])) {
this.budgetTypeOption.map(v => {
if (["ACTIVITY_BUDGET_TYPE_ONE"].includes(v.code)) {
budgetTypeCloseOption.push(v)
@@ -120,6 +120,10 @@ layout("/layouts/platform.html"){
: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>
@@ -111,9 +111,8 @@ layout("/layouts/platform.html"){
: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"
>
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</el-form-item>
</el-form>
@@ -125,9 +125,8 @@ layout("/layouts/platform.html"){
: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"
>
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</el-form-item>
</el-form>
@@ -166,7 +165,7 @@ layout("/layouts/platform.html"){
{prop: "actualMoney", label: "报销金额(元)"},
{prop: "declareUnitName", label: "申报单位/协会", sortable: true},
{prop: "applyTime", label: "申报时间", sortable: true},
{prop: "taskName", label: "当前节点"},
{prop: "curTaskName", label: "当前节点"},
{prop: "instanceState", label: "流程状态"}
],
activityDeclareReimbursementList: [],
@@ -193,6 +192,8 @@ layout("/layouts/platform.html"){
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
id: row.id,
actualMoney: row.actualMoney,
processTaskId: row.taskId,
taskName: row.curTaskName
}
@@ -208,11 +209,11 @@ layout("/layouts/platform.html"){
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
this.$axios.post("/platform/activityReimbursement/deputySchoolUnion/doReview", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}), id: this.formData.id
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
@@ -125,9 +125,8 @@ layout("/layouts/platform.html"){
: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"
>
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</el-form-item>
</el-form>
@@ -166,7 +165,7 @@ layout("/layouts/platform.html"){
{prop: "actualMoney", label: "报销金额(元)"},
{prop: "declareUnitName", label: "申报单位/协会", sortable: true},
{prop: "applyTime", label: "申报时间", sortable: true},
{prop: "taskName", label: "当前节点"},
{prop: "curTaskName", label: "当前节点"},
{prop: "instanceState", label: "流程状态"}
],
activityDeclareReimbursementList: [],
@@ -125,9 +125,8 @@ layout("/layouts/platform.html"){
: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"
>
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</el-form-item>
</el-form>
@@ -166,7 +165,7 @@ layout("/layouts/platform.html"){
{prop: "actualMoney", label: "报销金额(元)"},
{prop: "declareUnitName", label: "申报单位/协会", sortable: true},
{prop: "applyTime", label: "申报时间", sortable: true},
{prop: "taskName", label: "当前节点"},
{prop: "curTaskName", label: "当前节点"},
{prop: "instanceState", label: "流程状态"}
],
activityDeclareReimbursementList: [],
@@ -124,9 +124,8 @@ layout("/layouts/platform.html"){
: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"
>
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_userSign"></pc-signature>
</el-form-item>
</el-form>
@@ -165,7 +164,7 @@ layout("/layouts/platform.html"){
{prop: "actualMoney", label: "报销金额(元)"},
{prop: "declareUnitName", label: "申报单位/协会", sortable: true},
{prop: "applyTime", label: "申报时间", sortable: true},
{prop: "taskName", label: "当前节点"},
{prop: "curTaskName", label: "当前节点"},
{prop: "instanceState", label: "流程状态"}
],
activityDeclareReimbursementList: [],
@@ -1,167 +0,0 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="getChartData">
<search-item label="年度">
<el-date-picker
placeholder="请选择年度"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="主办单位">
<el-select v-model="pageForm.hostUnitId" clearable filterable
placeholder="请选择主办单位"
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.undertakeUnitId" clearable filterable
placeholder="请选择承办单位"
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>
</el-card>
<el-card shadow="never">
<table-tool label="活动统计">
<el-button @click="doExport" icon="el-icon-download" size="small" type="primary">
导出活动
</el-button>
</table-tool>
<div id="activityChart" style="width: 100%; height: 400px;"></div>
</el-card>
</template>
</guava>
</div>
<script>
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
undertakeUnitId: '',
hostUnitId: '',
year: new Date().getFullYear() + "",
},
activityChart: null,
activityCount: [
{
activityType: '家具家电',
count: 38,
},
{
activityType: '粮油副食',
count: 52,
},
{
activityType: '生鲜水果',
count: 61,
},
],
unitOptions: [],
clubOptions: [],
}
},
methods: {
doExport() {
window.open("/platform/activity/statistics/doExport?year=" + this.pageForm.year +
"&undertakeUnitId=" + this.pageForm.undertakeUnitId +
"&hostUnitId=" + this.pageForm.hostUnitId)
},
getChartData() {
this.$axios.post("/platform/activity/statistics/getChartData", {
year: this.pageForm.year,
undertakeUnitId: this.pageForm.undertakeUnitId,
hostUnitId: this.pageForm.hostUnitId
}).then(resp => {
if (resp.code === 0) {
this.activityCount = resp.data;
this.initChart()
}
})
},
initChart() {
if (this.activityChart) {
this.activityChart.destroy();
}
this.activityChart = new G2Plot.Column('activityChart', {
data: this.activityCount,
xField: 'activityTypeName',
yField: 'count',
label: {
position: 'middle',
style: {
fill: '#FFFFFF',
opacity: 0.6,
},
},
xAxis: {
label: {
autoHide: true,
autoRotate: false,
},
},
meta: {
activityTypeName: {alias: '活动类型'},
count: {alias: '数量'},
},
color: '#5B8FF9',
});
this.activityChart.render();
},
async getClubsByRole() {
const resp = await this.$axios.post("/platform/club/examine/apply/getClubsByRole")
return resp.data
},
},
async created() {
this.clubOptions = await this.getClubsByRole()
this.clubOptions.map((v) => {
v.name = v.clubName
})
const units = await this.$businessTool.listUnit()
this.unitOptions = this.clubOptions.concat(units)
this.getChartData()
},
mounted() {
},
})
</script>
<!--#
}
#-->
@@ -56,10 +56,10 @@ const ACTIVITY_BUDGET_INFO = {
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="审核金额">
<el-descriptions-item label="审核金额" v-if="task.ext.tf_totalBudgetMoney">
{{task.ext.tf_totalBudgetMoney}}
</el-descriptions-item>
<el-descriptions-item :span="2"></el-descriptions-item>
<el-descriptions-item :span="2" v-if="task.ext.tf_totalBudgetMoney"></el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
task.taskFormData.opinion
}}
@@ -212,7 +212,7 @@ layout("/layouts/platform.html"){
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
tf_totalBudgetMoney: 0,
tf_totalBudgetMoney: row.declareTotalBudgetMoney,
processTaskId: row.taskId,
taskName: row.curTaskName
}
@@ -143,6 +143,32 @@ const optionSelect = {
<div class="confirm-section-title">联系信息</div>
<el-form :model="contactForm" ref="contactForm" :rules="contactRules" label-width="80px">
<el-row :gutter="10">
<el-col :span="20">
<el-form-item v-if="projectInfo.provideMode == 3" prop="receiveAddress"
label="收货地址"
:rules="[{ required: true, message: '请选择收货地址', trigger: 'change' }]">
<el-select v-model="contactForm.receiveAddress" placeholder="请选择收货地址"
style="width: 100%" @change="onAddressChange">
<el-option v-for="item in addressOptions"
:key="item.id"
:label="item.province+ item.city+ item.county+ item.addressDetail"
:value="item.province + item.city + item.county + item.addressDetail">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button @click="openAddress" type="primary">添加地址</el-button>
</el-col>
<el-col :span="24">
<el-form-item prop="userName" label="收货人">
<el-input
v-model="contactForm.userName"
placeholder="请输入收货人"
clearable>
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item prop="mobile" label="联系电话">
<el-input
@@ -153,23 +179,11 @@ const optionSelect = {
</el-input>
</el-form-item>
</el-col>
<el-col :span="20">
<el-form-item v-if="projectInfo.provideMode == 3" prop="receiveAddress"
label="收货地址"
:rules="[{ required: true, message: '请选择收货地址', trigger: 'change' }]">
<el-select v-model="contactForm.receiveAddress" placeholder="请选择收货地址"
style="width: 100%">
<el-option v-for="item in addressOptions"
:key="item.id"
:label="'收货人:'+item.userName + ',联系电话:' + item.tel + ',收货地址:' + item.province+ item.city+ item.county+ item.addressDetail"
:value="'收货人:'+item.userName + ',联系电话:' + item.tel + ',收货地址:' + item.province+ item.city+ item.county+ item.addressDetail">
</el-option>
</el-select>
<el-col :span="24">
<el-form-item prop="sign" label="签字">
<pc-signature v-model="contactForm.userSign"></pc-signature>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button @click="openAddress" type="primary">添加地址</el-button>
</el-col>
</el-row>
@@ -249,10 +263,15 @@ const optionSelect = {
showOptionDetailDialog: false, // 选项详情弹窗
selectedOption: null, // 当前选中的选项
contactForm: {
mobile: "", // 联系电话,
receiveAddress: ""
mobile: "", // 联系电话
receiveAddress: "",
userName: "", // 收货人
userSign: ""
},
contactRules: {
userName: [
{required: true, message: "请输入收货人", trigger: "blur"}
],
mobile: [
{required: true, message: "请输入联系电话", trigger: "blur"},
{
@@ -341,6 +360,22 @@ const optionSelect = {
}
},
methods: {
// 地址选择变更处理
onAddressChange(value) {
if (value) {
const selectedAddress = this.addressOptions.find(item =>
(item.province + item.city + item.county + item.addressDetail) === value
);
if (selectedAddress) {
// 自动填充收货人和电话
this.contactForm.userName = selectedAddress.userName;
this.contactForm.mobile = selectedAddress.tel;
// const data = selectedAddress.province + selectedAddress.city + selectedAddress.county + selectedAddress.addressDetail
// debugger
// this.$set(this.contactForm, "receiveAddress", data)
}
}
},
openAddress() {
this.$refs.addressDialog.dialogVisible = true
this.$refs.addressDialog.formData = {userId: this.userId}
@@ -420,6 +455,8 @@ const optionSelect = {
if (this.projectInfo.provideMode === 3) {
if (this.userSelection.length > 0 && this.userSelection[0].receiveAddress) {
this.contactForm.receiveAddress = this.userSelection[0].receiveAddress
this.contactForm.userName = this.userSelection[0].userName;
this.contactForm.mobile = this.userSelection[0].mobile;
}
}
@@ -470,6 +507,7 @@ const optionSelect = {
selectOptionId: this.selectedRadioId,
selectNum: 1,
mobile: this.contactForm.mobile,
userName: this.contactForm.userName,
receiveAddress: this.contactForm.receiveAddress
}
]
@@ -481,6 +519,7 @@ const optionSelect = {
selectOptionId: option.id,
selectNum: option.selectNum,
mobile: this.contactForm.mobile,
userName: this.contactForm.userName,
receiveAddress: this.contactForm.receiveAddress
}))
}
@@ -53,12 +53,18 @@ layout("/layouts/platform_h5.html"){
<span v-else>暂无</span>
</template>
</van-cell>
<van-cell title="已报名总人数">
<!-- <van-cell title="已报名总人数">-->
<!-- <template #right-icon>-->
<!-- <span v-if="row.successUserApply>0&&row.applyType!==3">{{ row.successUserApply }}人</span>-->
<!-- <span v-else-if="JSON.parse(row.applyWay).length===2&&row.applyWay.includes(1)">{{row.totalApplyNum}}人</span>-->
<!-- <span v-else-if="row.totalApplyNum>0&&row.applyType===3">{{ row.totalApplyNum }}人</span>-->
<!-- <span v-else>0人</span>-->
<!-- </template>-->
<!-- </van-cell>-->
<van-cell title="暂保存人数">
<template #right-icon>
<span v-if="row.successUserApply>0&&row.applyType!==3">{{ row.successUserApply }}人</span>
<span v-else-if="JSON.parse(row.applyWay).length===2&&row.applyWay.includes(1)">{{row.totalApplyNum}}人</span>
<span v-else-if="row.totalApplyNum>0&&row.applyType===3">{{ row.totalApplyNum }}人</span>
<span v-else>0人</span>
<span v-if="row.apply_num_bc>0">已保存({{row.apply_num_bc}}</span>
<span v-else>暂无已保存人数</span>
</template>
</van-cell>
<van-cell title="已报名人员" v-if="JSON.parse(row.applyWay).length===1">
@@ -686,6 +686,27 @@ layout("/layouts/platform_h5.html"){
<div class="confirm-content-scroll">
<!-- 手机号输入 -->
<div class="mobile-input-section">
<!--收货地址-->
<van-field
v-if="projectInfo.provideMode == 3"
v-model="formData.receiveAddress"
label="收货地址"
rows="2"
type="textarea"
placeholder="请选择收货地址"
readonly
is-link
@click="showAddressSheet = true"
required
></van-field>
<van-field
v-model="formData.userName"
label="收货人"
placeholder="请输入收货人"
:error="userNameError"
@focus="userNameError = false"
required
></van-field>
<van-field
v-model="formData.mobile"
label="联系电话"
@@ -695,19 +716,6 @@ layout("/layouts/platform_h5.html"){
maxlength="11"
required
></van-field>
<!--收货地址-->
<van-field
v-if="projectInfo.provideMode == 3"
v-model="formData.receiveAddress"
label="收货地址"
rows="4"
type="textarea"
placeholder="请选择收货地址"
readonly
is-link
@click="showAddressSheet = true"
required
></van-field>
</div>
<!-- 选择内容 -->
@@ -813,10 +821,12 @@ layout("/layouts/platform_h5.html"){
showOptionDetailDialog: false, // 选项详情弹窗
selectedOption: null, // 当前选中的选项
mobileError: false, // 手机号错误标记
userNameError: false, // 收货人错误标记
formData: {
userSign: "", // 用户签名
mobile: "", // 手机号码
address: "" // 收货地址
address: "",// 收货地址
userName: "",//收货人
},
addressOptions: [],
@@ -941,14 +951,17 @@ layout("/layouts/platform_h5.html"){
// 如果有用户选择数据,从中获取手机号
if (this.userSelection && this.userSelection.length > 0 && this.userSelection[0].mobile) {
this.formData.mobile = this.userSelection[0].mobile
this.formData.userName = this.userSelection[0].userName
// 获取签名信息(如果有)
if (this.userSelection[0].userSign) {
this.formData.userSign = this.userSelection[0].userSign
}
} else if (this.$store.user && this.$store.user.mobile) {
} else if (this.$store.state.user && this.$store.state.user.mobile) {
// 如果没有选择过,使用store中的默认手机号
this.formData.mobile = this.$store.user.mobile
this.formData.mobile = this.$store.state.user.mobile
}else if (this.$store.state.user && this.$store.state.user.username){
this.formData.userName = this.$store.state.user.username
}
// 地址回显
@@ -995,6 +1008,11 @@ layout("/layouts/platform_h5.html"){
return
}
// 验证收货人
if (!this.validateUserName()) {
return;
}
// 验证手机号
if (!this.validateMobile()) {
return
@@ -1030,7 +1048,8 @@ layout("/layouts/platform_h5.html"){
{
selectOptionId: this.selectedRadioId,
selectNum: 1,
mobile: this.formData.mobile
mobile: this.formData.mobile,
userName: this.formData.userName
}
]
}
@@ -1040,7 +1059,8 @@ layout("/layouts/platform_h5.html"){
selections = this.selectedOptions.map((option) => ({
selectOptionId: option.id,
selectNum: option.selectNum,
mobile: this.formData.mobile
mobile: this.formData.mobile,
userName: this.formData.userName
}))
}
@@ -1101,6 +1121,16 @@ layout("/layouts/platform_h5.html"){
return true
},
// 验证收货人
validateUserName() {
if (!this.formData.userName) {
this.userNameError = true;
this.$toast.fail("请输入收货人姓名");
return false;
}
return true;
},
// 格式化时间范围
formatTimeRange(start, end) {
if (!start || !end) return "未设置"
@@ -1198,8 +1228,10 @@ layout("/layouts/platform_h5.html"){
// 选择收货地址
selectAddress(address) {
this.formData.receiveAddress =
"收货人:" + address.userName + ",联系电话:" + address.tel + ",收货地址:" + address.province + address.city + address.county + address.addressDetail
// "收货人:" + address.userName + ",联系电话:" + address.tel + ",收货地址:" +
this.formData.userName = address.userName
this.formData.mobile = address.tel
this.formData.receiveAddress = address.province + address.city + address.county + address.addressDetail
this.showAddressSheet = false
},