教代会意见:

1、撰写建议-> 代表姓名label改成建议人,所属代表团label改为建议人所属代表团;新增字段记录人、所属讨论组,工作措施删掉
3、我的意见:列表意见人和代表团改为建议人和建议人所属代表团,记录员帮建议人录入建议,录入人和被录入人都可以看到
4、意见办理:校工会审核页面添加意见类别
5、流程还要修改:记录员提交后,流转到校工会和两办,校工会审核(修改类别和承办单位),两办只审阅不审核
This commit is contained in:
2026-04-21 09:12:02 +08:00
parent 377dbafc18
commit fe938025d1
13 changed files with 599 additions and 224 deletions
@@ -24,6 +24,7 @@ import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -108,7 +109,10 @@ public class OpinionMineController {
Cnd cnd = Cnd.NEW();
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.SCHOOL_UNION_PROPOSAL_ADMIN.name())) {
cnd.and("info.createUserId", "=", SecurityUtil.getUserId());
SqlExpressionGroup group = Cnd.NEW().where();
group.and("info.createUserId", "=", SecurityUtil.getUserId())
.or("info.suggestUserId", "=", SecurityUtil.getUserId());
cnd.and(group);
}
OpinionSearchParam.buildSearch(cnd, pageForm);
cnd.andEX("info.sessionId", "=", sessionId);
@@ -92,7 +92,8 @@ public class OpinionOfficeAuditController {
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("info.sessionId", "=", sessionId);
cnd.and("t.taskName", "=", "office");
// cnd.and("t.taskName", "=", "office");
cnd.and("t.taskName", "=", "schoolAudit");
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
if (approval) {
@@ -127,7 +127,8 @@ public class OpinionSchoolAuditController {
@ApiOperation("修改意见")
@SLog(tag = "意见管理系统-校工会审核", msg = "修改意见")
public Result edit(@Param("info") OpinionInfo opinionInfo) {
dao.update(opinionInfo);
// The school-union audit only edits opinion category here, so update the target field explicitly.
dao.update(OpinionInfo.class, org.nutz.dao.Chain.make("typeId", opinionInfo.getTypeId()), Cnd.where("id", "=", opinionInfo.getId()));
ProcessInstance instance = dao.fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", opinionInfo.getId()));
Dict dict = FlowUtil.variableToDict(instance.getVariable());
@@ -18,6 +18,7 @@ import com.budwk.app.zhgh.democratic.opinion.service.OpinionWriteService;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.service.ProposalWriteService;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.models.Teacher_congress_delegate;
import com.budwk.app.zhgh.democratic.teachercongress.discussiongroup.models.Teacher_congress_discussion_group;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.models.Teacher_congress_session;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -25,6 +26,9 @@ import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -125,8 +129,84 @@ public class OpinionWriteController {
@SaCheckPermission("opinion.write")
@ApiOperation("意见详情")
public Result detail(@Valid String id) {
OpinionInfo info = dao.fetch(OpinionInfo.class, id);
return Result.success(info);
// Join delegation name for edit echo because the page displays delegation as a readonly name field.
Sql sql = Sqls.create("""
SELECT
info.*,
tcd.name AS delegationName
FROM opinion_info info
LEFT JOIN teacher_congress_delegation tcd ON tcd.id = info.delegationId
$condition
""");
sql.setCondition(Cnd.where("info.id", "=", id));
sql.setCallback(Sqls.callback.record());
dao.execute(sql);
return Result.success(sql.getObject(Record.class));
}
@At
@SaCheckPermission("opinion.write")
public Result listDiscussionGroup(@Valid String sessionId, String recorderUserId, String recorderUserCode) {
// Only expose discussion groups managed by the current recorder to avoid cross-recorder selection.
Cnd cnd = Cnd.where("sessionId", "=", sessionId).and("delFlag", "=", false);
if (StrUtil.isNotBlank(recorderUserId)) {
cnd.and("recorderUserId", "=", recorderUserId);
}
if (StrUtil.isBlank(recorderUserId) && StrUtil.isNotBlank(recorderUserCode)) {
cnd.and("recorderUserCode", "=", recorderUserCode);
}
List<Teacher_congress_discussion_group> list = dao.query(
Teacher_congress_discussion_group.class,
cnd.asc("code")
);
return Result.success(list);
}
@At
@SaCheckPermission("opinion.write")
public Result discussionGroupDetail(@Valid String id) {
Sql sql = Sqls.create("""
SELECT
tcdg.id,
tcdg.code,
tcdg.name,
tcdg.sessionId,
tcdg.recorderUserId,
tcdg.recorderUserCode,
tcdg.recorderUserName,
vu.mobile AS recorderUserMobile
FROM teacher_congress_discussion_group tcdg
LEFT JOIN vw_user vu ON vu.id = tcdg.recorderUserId
$condition
""");
sql.setCondition(Cnd.where("tcdg.id", "=", id).and("tcdg.delFlag", "=", false));
sql.setCallback(Sqls.callback.record());
dao.execute(sql);
return Result.success(sql.getObject(Record.class));
}
@At
@SaCheckPermission("opinion.write")
public Result searchSuggestUserDelegation(@Valid String sessionId, @Valid String userId) {
Sql sql = Sqls.create("""
SELECT
tcd.id,
tcd.name,
tcd.code
FROM vw_user vu
LEFT JOIN teacher_congress_delegation_unit tcdu ON tcdu.unitId = vu.unitId AND tcdu.sessionId = @sessionId
LEFT JOIN teacher_congress_delegation tcd ON tcd.id = tcdu.delegationId
WHERE vu.id = @userId
AND tcd.id IS NOT NULL
AND tcd.delFlag = 0
ORDER BY CAST(tcd.code AS UNSIGNED), tcd.code ASC
LIMIT 1
""");
sql.setParam("sessionId", sessionId);
sql.setParam("userId", userId);
sql.setCallback(Sqls.callback.record());
dao.execute(sql);
return Result.success(sql.getObject(Record.class));
}
@At
@@ -32,7 +32,7 @@ public class OpinionOfficeSuffixInterceptor implements FlowInterceptor {
Dao dao = ServiceContext.find(Dao.class);
String opinionId = execution.getProcessInstance().getBusinessNo();
String officeResult = execution.getArgs().getStr(FlowConst.TASK_FORM_DATA_PREFIX + "officeResult");
String officeResult = execution.getArgs().getStr(FlowConst.TASK_FORM_DATA_PREFIX + "schoolResult");
if (StrUtil.isNotBlank(officeResult) && "YES".equals(officeResult)) {
// 删除原来的记录
@@ -75,6 +75,29 @@ public class OpinionInfo extends BaseModel {
@ColDefine(type = ColType.VARCHAR, width = 32)
private String delegationId;
@Column
@Comment("建议人ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String suggestUserId;
@Column
@Comment("建议人name")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String suggestUserName;
@Column
@Comment("建议人code")
@ColDefine(type = ColType.VARCHAR, width = 120)
private String suggestUserLoginName;
@Column
@Comment("建议人所属代表团ID")
private String suggestUserDelegationId;
@Column
@Comment("建议人所属代表团名称")
private String suggestUserDelegationName;
@Column
@Comment("单位")
@ColDefine(type = ColType.VARCHAR, width = 100)
@@ -32,6 +32,9 @@ public class OpinionWriteServiceImpl extends BaseServiceImpl<OpinionInfo> implem
@Override
public String generateOpinionCode(String sessionId, String delegationId) {
Teacher_congress_delegation delegation = dao().fetch(Teacher_congress_delegation.class, delegationId);
if (delegation == null) {
return "";
}
Sql sql = Sqls.fetchString("""
SELECT
@@ -5,6 +5,7 @@ const OPINION_INFO = {
<div class="opinion-info">
<div class="process-title">
意见基础信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<h3 style="text-align: center;font-weight: 600" class="pt10 pb10">
{{ viewData.name }}
@@ -97,6 +98,7 @@ const OPINION_INFO = {
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
dicts: ["PROCESS_TASK_SUBMIT_TYPE", "PROPOSAL_FEEDBACK", "PROPOSAL_REPLY_IMPLEMENT"],
@@ -136,7 +138,10 @@ const OPINION_INFO = {
}
})
},
// 查看流程图
openChart(){
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
}
},
style:
/*language=CSS*/
@@ -85,10 +85,10 @@ layout("/layouts/platform.html"){
tableColumns: [
{label: "意见编号", prop: "code"},
{label: "意见名称", prop: "name", width: "200px"},
{label: "意见人", prop: "createUserName"},
{label: "建议人", prop: "createUserName"},
{label: "意见类别", prop: "typeName"},
{label: "届次", prop: "sessionName"},
{label: "代表团", prop: "delegationName"},
{label: "建议人所属代表团", prop: "delegationName"},
{label: "当前节点", prop: "curTaskName"},
{label: "流程状态", prop: "instanceState"}
]
@@ -49,10 +49,10 @@ layout("/layouts/platform.html"){
<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>
<!-- <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>
@@ -74,6 +74,17 @@ layout("/layouts/platform.html"){
<el-radio label="NO" border>不通过</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="意见类别" prop="typeId"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-select v-model="formData.typeId" clearable filterable style="width: 100%" placeholder="请选择意见类别">
<el-option
v-for="item in typeOptions"
:label="item.name"
:value="item.id"
:key="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label="主办单位"
:rules="[{required:true, message:'必填',trigger:['change','blur']}]"
@@ -159,6 +170,7 @@ layout("/layouts/platform.html"){
sessionOptions: [],
delegationOptions: [],
underTakeOptions: [],
typeOptions: [],
row: {},
}
@@ -181,8 +193,10 @@ layout("/layouts/platform.html"){
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
id: row.id,
processTaskId: row.taskId,
taskName: row.curTaskName,
typeId: row.typeId,
tf_masterUnitId: null,
tf_slaveUnitIds: [],
tf_schoolResult: 'YES',
@@ -201,21 +215,35 @@ layout("/layouts/platform.html"){
type: "warning"
}).then(() => {
const loading = createLoading('提交中')
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val,
tf_masterUnitName: this.formData.tf_masterUnitId ? this.underTakeOptions.find(v => v.id === this.formData.tf_masterUnitId)?.name : null,
tf_slaveUnitNames: this.formData.tf_slaveUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name),
tf_slaveUnitNameStr: this.formData.tf_slaveUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name).join(','),
// The school-union audit can modify opinion type, so persist typeId before completing the workflow task.
this.$axios.post("/platform/opinion/schoolAudit/edit", {
info: JSON.stringify({
id: this.formData.id,
typeId: this.formData.typeId
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}).then((editRes) => {
if (editRes.code !== 0) {
loading.close()
return
}
}).finally(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val,
tf_masterUnitName: this.formData.tf_masterUnitId ? this.underTakeOptions.find(v => v.id === this.formData.tf_masterUnitId)?.name : null,
tf_slaveUnitNames: this.formData.tf_slaveUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name),
tf_slaveUnitNameStr: this.formData.tf_slaveUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name).join(','),
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
loading.close()
})
}).catch(() => {
loading.close()
})
})
@@ -263,12 +291,20 @@ layout("/layouts/platform.html"){
this.underTakeOptions = res.data
}
})
},
listOpinionType() {
this.$axios.post("/platform/opinion/common/listOpinionType").then((res) => {
if (res.code === 0) {
this.typeOptions = res.data || []
}
})
}
},
created() {
this.pageData()
this.listOpenSession()
this.listUnderTake()
this.listOpinionType()
}
})
</script>
@@ -4,54 +4,51 @@ const BASIC_FORM = {
template: `
<el-form :model="formData" :rules="formRules" label-width="120px" ref="addForm">
<el-row :gutter="20" type="flex">
<el-col :span="12">
<el-form-item label="记录人" prop="createUserId">
<el-input :value="recorderDisplay" readonly disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="代表姓名" prop="createUserId">
<user-select
:disabled="school || !$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN','TEACHER_CONGRESS_DELEGATION_CONTACT'])"
ref="userSelectRef"
v-model="formData.createUserId"
<el-form-item label="所属讨论组" prop="delegationId">
<el-select
v-model="formData.delegationId"
clearable
filterable
placeholder="请选择所属讨论组"
style="width: 100%"
api="/platform/teacherCongress/common/listDelegate"
option_label="userName"
option_value="userId"
:api_params="{sessionId:formData.sessionId,delegationId:formData.delegationId}"
:option_label_func="(item)=>{return item.userName + ' - ' + item.loginName}"
@change="userChange"
@change="discussionGroupChange"
>
<el-option
v-for="item in discussionGroupOptions"
:key="item.id"
:label="discussionGroupLabel(item)"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="12">
<el-form-item label="建议人" prop="suggestUserId" style="width: 98%">
<user-select
ref="suggestUserSelectRef"
v-model="formData.suggestUserId"
style="width: 100%"
api="/platform/teacherCongress/discussionGroup/recorderOptions"
api_input_key_name="keyword"
:option_list="suggestUserOptions"
option_value="id"
:option_label_func="(item)=> item.username + ' - ' + item.loginname"
@change="suggestUserChange"
></user-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="意见时间" prop="createTime">
<el-input readonly v-model="formData.createTime" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="12">
<el-form-item label="所属教代会" prop="sessionId">
<el-select
:disabled="school"
@change="meetingChange"
clearable
filterable
placeholder="请选择所属教代会"
v-model="formData.sessionId"
style="width: 100%"
>
<el-option :key="item.id" :label="item.fullName" :value="item.id"
v-for="item in sessionOptions"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属代表团" prop="delegationId">
<el-select clearable filterable placeholder="请选择所属代表团" v-model="formData.delegationId"
style="width: 100%" disabled>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in delegationOptions"></el-option>
</el-select>
<el-form-item label="建议人所属代表团" prop="suggestUserDelegationName" ref="suggestUserDelegationNameRef">
<el-input v-model="formData.suggestUserDelegationName" readonly disabled ></el-input>
</el-form-item>
</el-col>
</el-row>
@@ -70,25 +67,59 @@ const BASIC_FORM = {
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="12">
<el-form-item label="意见名称" prop="name">
<el-input maxlength="100" placeholder="请输入意见名称" v-model="formData.name"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="12">
<el-form-item label="所属教代会" prop="sessionId">
<el-select
clearable
filterable
placeholder="请选择所属教代会"
v-model="formData.sessionId"
style="width: 100%"
@change="meetingChange"
>
<el-option
v-for="item in sessionOptions"
:key="item.id"
:label="item.fullName"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</el-col> <el-col :span="12">
<el-form-item label="意见类别" prop="typeId">
<el-select v-model="formData.typeId" style="width: 100%" placeholder="请选择意见类别">
<el-option :key="item.code" :label="item.name" :value="item.id"
v-for="item in typeOptions"></el-option>
<el-option
v-for="item in typeOptions"
:key="item.code"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="12">
<el-form-item label="意见名称" prop="name">
<el-input maxlength="100" placeholder="请输入意见名称" v-model="formData.name"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="意见时间" prop="createTime">
<el-input readonly v-model="formData.createTime" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="建议承办单位" prop="suggestUnits">
<el-select v-model="formData.suggestUnits" multiple filterable style="width: 100%" placeholder="请选择建议承办单位">
<el-option :key="item.id" :label="item.name" :value="item.name"
v-for="item in suggestUnitOptions"></el-option>
<el-option
v-for="item in suggestUnitOptions"
:key="item.id"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
@@ -96,24 +127,9 @@ const BASIC_FORM = {
<text-editor v-model="formData.brief" key="brief" placeholder="请输入意见和建议"></text-editor>
</el-form-item>
<el-form-item label="工作措施" prop="measures">
<text-editor v-model="formData.measures" key="measures"
placeholder="请输入工作措施"></text-editor>
</el-form-item>
<!--<el-form-item label="附件上传" prop="files">
<file-upload
:value.sync="formData.files"
:upload_number="5"
upload_result_category="array"
upload_mode="drag"
complete_result
></file-upload>
</el-form-item>-->
<!--<el-form-item label="电子签名" prop="signature">
<pc-signature v-model="formData.signature"></pc-signature>
</el-form-item>-->
<!-- <el-form-item label="工作措施" prop="measures">-->
<!-- <text-editor v-model="formData.measures" key="measures" placeholder="请输入工作措施"></text-editor>-->
<!-- </el-form-item>-->
</el-form>
`,
props: {
@@ -125,30 +141,46 @@ const BASIC_FORM = {
},
data() {
return {
bizId: '',
taskId: '',
bizId: "",
taskId: "",
formData: {},
sessionOptions: [],
delegationOptions: [],
discussionGroupOptions: [],
suggestUserOptions: [],
typeOptions: [],
formRules: {
createUserId: [{required: true, message: "请选择意见人", trigger: ["blur", "change"]}],
createTime: [{required: true, message: "请输入意见时间", trigger: ["blur", "change"]}],
name: [{required: true, message: "请输入意见名称", trigger: ["blur", "change"]}],
delegationId: [{required: true, message: "请选择所属代表团", trigger: ["blur", "change"]}],
sessionId: [{required: true, message: "请选择所属教代会", trigger: ["blur", "change"]}],
typeId: [{required: true, message: "请选择意见类别", trigger: ["blur", "change"]}],
suggestUnits: [{required: true, message: "请选择建议承办单位", trigger: ["blur", "change"]}],
brief: [{required: true, message: "请输入意见和建议", trigger: ["blur", "change"]}],
measures: [{required: true, message: "请输入工作措施", trigger: ["blur", "change"]}],
unitName: [{required: true, message: "请输入单位", trigger: ["blur", "change"]}],
mobile: [{required: true, message: "请输入联系方式", trigger: ["blur", "change"]}],
signature: [{required: false, message: "请扫描二维码进行签字", trigger: ["blur", "change"]}]
},
// 建议承办单位
suggestUnitOptions: [],
tempUserId: '',
formRules: {
delegationId: [{ required: true, message: "请选择所属讨论组", trigger: ["blur", "change"] }],
createUserId: [{ required: true, message: "请选择所属讨论组后自动带出记录人", trigger: ["blur", "change"] }],
createTime: [{ required: true, message: "请输入意见时间", trigger: ["blur", "change"] }],
sessionId: [{ required: true, message: "请选择所属教代会", trigger: ["blur", "change"] }],
suggestUserId: [{ required: true, message: "请选择建议人", trigger: ["blur", "change"] }],
suggestUserDelegationName: [{ required: true, message: "请先选择建议人并自动带出所属代表团", trigger: ["blur", "change"] }],
name: [{ required: true, message: "请输入意见名称", trigger: ["blur", "change"] }],
typeId: [{ required: true, message: "请选择意见类别", trigger: ["blur", "change"] }],
suggestUnits: [{ required: true, message: "请选择建议承办单位", trigger: ["blur", "change"] }],
brief: [{ required: true, message: "请输入意见和建议", trigger: ["blur", "change"] }],
measures: [{ required: true, message: "请输入工作措施", trigger: ["blur", "change"] }],
unitName: [{ required: true, message: "请先选择建议人自动带出单位", trigger: ["blur", "change"] }],
mobile: [{ required: true, message: "请输入联系电话", trigger: ["blur", "change"] }]
}
}
},
computed: {
recorderDisplay() {
if (!this.formData.createUserName) {
return ""
}
return this.formData.createUserLoginName
? this.formData.createUserName + " - " + this.formData.createUserLoginName
: this.formData.createUserName
},
discussionGroupName() {
const group = this.discussionGroupOptions.find((item) => item.id === this.formData.delegationId)
if (!group) {
return this.formData.discussionGroupName || ""
}
return group.name || ""
}
},
methods: {
@@ -158,7 +190,6 @@ const BASIC_FORM = {
await this.init()
this.listSuggestUnit()
this.listOpinionType()
this.echoRepresentativeName()
},
async edit() {
const valid = await this.$refs["addForm"].validate()
@@ -167,31 +198,22 @@ const BASIC_FORM = {
this.$message.warning("请输入意见名称")
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading('正在提交中')
this.$axios.post('/platform/opinion/schoolAudit/edit', { info: JSON.stringify(this.formData) }).then(res => {
const loading = createLoading("正在提交中")
this.$axios.post("/platform/opinion/schoolAudit/edit", { info: JSON.stringify(this.buildSubmitFormData()) }).then((res) => {
loading.close()
if (res.code === 0) {
this.$message.success("提交成功")
this.$emit('edit')
this.$emit("edit")
}
})
})
}
},
userChange(val) {
const user = this.$refs.userSelectRef.options.find(item => item.userId === val)
this.searchDelegation()
this.$set(this.formData, "createUserName", user?.userName)
this.$set(this.formData, "createUserLoginName", user?.loginName)
this.$set(this.formData, "mobile", user?.mobile)
this.$set(this.formData, "unitName", user.unitName)
},
async onSave() {
const valid = await this.$refs["addForm"].validate()
if (valid) {
@@ -199,17 +221,15 @@ const BASIC_FORM = {
this.$message.warning("请输入意见名称")
return
}
this.$axios.post("/platform/opinion/write/save", {info: JSON.stringify(this.formData)}).then((res) => {
this.$axios.post("/platform/opinion/write/save", { info: JSON.stringify(this.buildSubmitFormData()) }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.formData = res.data
commonUtil.pjaxPush('/platform/opinion/mine')
this.formData = this.normalizeDetailFormData(res.data)
commonUtil.pjaxPush("/platform/opinion/mine")
}
})
}
},
// 提交
async onSubmit() {
const valid = await this.$refs["addForm"].validate()
if (valid) {
@@ -217,24 +237,22 @@ const BASIC_FORM = {
this.$message.warning("请输入意见名称")
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = createLoading('正在提交中')
this.$axios.post('/platform/opinion/write/submit', {info: JSON.stringify(this.formData)}).then(res => {
const loading = createLoading("正在提交中")
this.$axios.post("/platform/opinion/write/submit", { info: JSON.stringify(this.buildSubmitFormData()) }).then((res) => {
loading.close()
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/opinion/mine')
commonUtil.pjaxPush("/platform/opinion/mine")
}
})
})
}
},
// 重新提交
async onSubmitAgain() {
const valid = await this.$refs["addForm"].validate()
if (valid) {
@@ -242,25 +260,23 @@ const BASIC_FORM = {
this.$message.warning("请输入意见名称")
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/opinion/write/submitAgain', {
info: JSON.stringify(this.formData),
this.$axios.post("/platform/opinion/write/submitAgain", {
info: JSON.stringify(this.buildSubmitFormData()),
taskId: GetQueryString("taskId")
}).then(res => {
}).then((res) => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/opinion/mine')
commonUtil.pjaxPush("/platform/opinion/mine")
}
})
})
}
},
// 获取意见类别
listOpinionType() {
this.$axios.post("/platform/opinion/common/listOpinionType").then((res) => {
if (res.code === 0) {
@@ -268,14 +284,6 @@ const BASIC_FORM = {
}
})
},
//教代会change
async meetingChange(val) {
this.formData.delegationId = null
this.formData.committeeId = null
this.listDelegation()
this.searchDelegation()
},
// 建议承办单位
listSuggestUnit() {
this.$axios.post("/platform/opinion/common/listUnderTake").then((res) => {
if (res.code === 0) {
@@ -283,92 +291,281 @@ const BASIC_FORM = {
}
})
},
// 获取代表团
listDelegation() {
return this.$axios.post("/platform/opinion/common/listDelegation", {sessionId: this.formData.sessionId}).then((res) => {
listSession(includeClosed) {
const url = includeClosed ? "/platform/opinion/common/listSession" : "/platform/opinion/common/listOpenSession"
return this.$axios.post(url).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
this.sessionOptions = res.data || []
}
})
},
// 查询开启的教代会
listOpenSession(isModify = false) {
this.$axios.post("/platform/opinion/common/listOpenSession").then(async (res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (!isModify && this.sessionOptions) {
this.$set(this.formData, "sessionId", this.sessionOptions[0].id)
// 获取代表团
await this.searchDelegation()
}
await this.listDelegation()
}
})
getCurrentUser() {
// Reuse the current user in store and avoid adding another current-user API.
const user = this.$store && this.$store.state ? this.$store.state.user : {}
return {
id: user && user.id ? user.id : "",
username: user && user.username ? user.username : "",
loginname: user && user.loginname ? user.loginname : "",
birthday: user && user.birthday ? user.birthday : ""
}
},
//查询代表的代表团
searchDelegation() {
return this.$axios.post("/platform/opinion/write/searchDelegation", {
fillCurrentRecorder() {
// Keep recorder aligned with the current logged-in archive user on page init and session switch.
const currentUser = this.getCurrentUser()
this.formData.createUserId = currentUser.id
this.formData.createUserName = currentUser.username
this.formData.createUserLoginName = currentUser.loginname
},
normalizeDetailFormData(data) {
// Convert persisted model fields back into the current page layout fields during detail echo.
// The detail API may return lower-case keys, so echo must support both camelCase and lower-case names.
const detail = data || {}
const getValue = (camelKey, lowerKey) => {
if (detail[camelKey] !== undefined && detail[camelKey] !== null) {
return detail[camelKey]
}
if (detail[lowerKey] !== undefined && detail[lowerKey] !== null) {
return detail[lowerKey]
}
return ""
}
const suggestUnits = getValue("suggestUnits", "suggestunits")
let suggestUnitList = []
if (Array.isArray(suggestUnits)) {
suggestUnitList = suggestUnits
} else if (suggestUnits) {
try {
suggestUnitList = JSON.parse(suggestUnits)
} catch (e) {
suggestUnitList = []
}
}
return {
id: getValue("id", "id"),
code: getValue("code", "code"),
name: getValue("name", "name"),
typeId: getValue("typeId", "typeid"),
sessionId: getValue("sessionId", "sessionid"),
createTime: getValue("createTime", "createtime"),
mobile: getValue("mobile", "mobile"),
unitName: getValue("unitName", "unitname"),
brief: getValue("brief", "brief"),
measures: getValue("measures", "measures"),
files: getValue("files", "files"),
signId: getValue("signId", "signid"),
publicity: getValue("publicity", "publicity"),
excellent: getValue("excellent", "excellent"),
suggestUnits: suggestUnitList,
createUserId: getValue("suggestUserId", "suggestuserid"),
createUserName: getValue("suggestUserName", "suggestusername"),
createUserLoginName: getValue("suggestUserLoginName", "suggestuserloginname"),
delegationId: getValue("suggestUserDelegationId", "suggestuserdelegationid"),
suggestUserId: getValue("createUserId", "createuserid"),
suggestUserName: getValue("createUserName", "createusername"),
suggestUserLoginName: getValue("createUserLoginName", "createuserloginname"),
suggestUserDelegationId: getValue("delegationId", "delegationid"),
suggestUserDelegationName: getValue("delegationName", "delegationname"),
delegationName: getValue("delegationName", "delegationname"),
discussionGroupName: getValue("suggestUserDelegationName", "suggestuserdelegationname")
}
},
buildSubmitFormData() {
// Swap layout fields back to the original model fields before save and submit.
const formData = { ...this.formData }
const discussionGroupName = this.discussionGroupName
return {
...formData,
createUserId: formData.suggestUserId || "",
createUserName: formData.suggestUserName || "",
createUserLoginName: formData.suggestUserLoginName || "",
delegationId: formData.suggestUserDelegationId || "",
suggestUserId: formData.createUserId || "",
suggestUserName: formData.createUserName || "",
suggestUserLoginName: formData.createUserLoginName || "",
suggestUserDelegationId: formData.delegationId || "",
suggestUserDelegationName: discussionGroupName || ""
}
},
listDiscussionGroup() {
if (!this.formData.sessionId) {
this.discussionGroupOptions = []
return Promise.resolve()
}
const currentUser = this.getCurrentUser()
return this.$axios.post("/platform/opinion/write/listDiscussionGroup", {
sessionId: this.formData.sessionId,
userId: this.formData.createUserId
recorderUserId: currentUser.id,
recorderUserCode: currentUser.loginname
}).then((res) => {
if (res.code === 0) {
this.$set(this.formData, "delegationId", res.data)
this.discussionGroupOptions = res.data || []
}
})
},
async meetingChange() {
this.formData.delegationId = ""
this.fillCurrentRecorder()
this.clearSuggestDelegation()
await this.listDiscussionGroup()
// When the current recorder manages multiple groups, default to the first returned group.
if (this.discussionGroupOptions.length) {
this.formData.delegationId = this.discussionGroupOptions[0].id
await this.discussionGroupChange(this.formData.delegationId)
}
if (this.formData.suggestUserId) {
await this.loadSuggestUserDelegation()
}
},
clearRecorder() {
this.formData.createUserId = ""
this.formData.createUserName = ""
this.formData.createUserLoginName = ""
},
clearSuggestDelegation() {
this.formData.suggestUserDelegationId = ""
this.formData.suggestUserDelegationName = ""
this.formData.delegationName = ""
},
discussionGroupChange(groupId) {
if (!groupId) {
this.fillCurrentRecorder()
this.formData.discussionGroupName = ""
return Promise.resolve()
}
return this.$axios.post("/platform/opinion/write/discussionGroupDetail", { id: groupId }).then((res) => {
const selectedGroup = this.discussionGroupOptions.find((item) => item.id === groupId) || {}
const group = res.code === 0 && res.data ? res.data : selectedGroup
this.formData.createUserId = group.recorderUserId || selectedGroup.recorderUserId || ""
this.formData.createUserName = group.recorderUserName || selectedGroup.recorderUserName || ""
this.formData.createUserLoginName = group.recorderUserCode || selectedGroup.recorderUserCode || ""
this.formData.discussionGroupName = group.name || selectedGroup.name || ""
this.$nextTick(() => {
this.$refs.addForm && this.$refs.addForm.clearValidate(["createUserId"])
})
})
},
discussionGroupLabel(item) {
if (!item) {
return ""
}
return item.code ? item.name + "" + item.code + "" : item.name
},
suggestUserChange(userId) {
const componentOptions = this.$refs.suggestUserSelectRef && this.$refs.suggestUserSelectRef.options ? this.$refs.suggestUserSelectRef.options : []
this.suggestUserOptions = this.mergeOptions(this.suggestUserOptions, componentOptions, "id")
const user = this.suggestUserOptions.find((item) => item.id === userId)
this.formData.suggestUserId = user ? user.id : ""
this.formData.suggestUserName = user ? user.username : ""
this.formData.suggestUserLoginName = user ? user.loginname : ""
this.formData.mobile = user ? user.mobile || "" : ""
this.formData.unitName = user ? user.unitName || "" : ""
if (!userId) {
this.clearSuggestDelegation()
return
}
this.loadSuggestUserDelegation()
},
loadSuggestUserDelegation() {
if (!this.formData.sessionId || !this.formData.suggestUserId) {
this.clearSuggestDelegation()
return Promise.resolve()
}
return this.$axios.post("/platform/opinion/write/searchSuggestUserDelegation", {
sessionId: this.formData.sessionId,
userId: this.formData.suggestUserId
}).then((res) => {
const data = res.code === 0 ? res.data : null
this.formData.suggestUserDelegationId = data && data.id ? data.id : ""
this.formData.suggestUserDelegationName = data && data.name ? data.name : ""
this.formData.delegationName = data && data.name ? data.name : ""
})
},
mergeOptions(current, incoming, key) {
const map = new Map()
;(incoming || []).concat(current || []).forEach((item) => {
if (item && item[key] && !map.has(item[key])) {
map.set(item[key], item)
}
})
return Array.from(map.values())
},
applySuggestUserDelegationLabelStyle() {
// Find the label from the form-item ref directly so the style survives outer layout changes.
this.$nextTick(() => {
const formItemRef = this.$refs.suggestUserDelegationNameRef
const formItemEl = formItemRef && formItemRef.$el ? formItemRef.$el : null
const labelEl = formItemEl ? formItemEl.querySelector(".el-form-item__label") : null
if (!labelEl) {
return
}
labelEl.style.width = "120px"
labelEl.style.whiteSpace = "nowrap"
labelEl.style.transform = "translateX(-13px)"
})
},
async init() {
// 清空显示值
this.$set(this.formData, "createUserId", '');
if (this.bizId) {
const res = await this.$axios.post("/platform/opinion/write/detail", {id: this.bizId})
const res = await this.$axios.post("/platform/opinion/write/detail", { id: this.bizId })
if (res.code === 0) {
this.formData = res.data
this.tempUserId = this.formData.createUserId;
this.listOpenSession(true)
this.formData = {
suggestUnits: [],
...this.normalizeDetailFormData(res.data)
}
await this.listSession(true)
await this.listDiscussionGroup()
if (this.discussionGroupOptions.length && !this.discussionGroupOptions.find((item) => item.id === this.formData.delegationId)) {
this.formData.delegationId = this.discussionGroupOptions[0].id
}
if (this.formData.suggestUserId) {
this.suggestUserOptions = [{
id: this.formData.suggestUserId,
username: this.formData.suggestUserName,
loginname: this.formData.suggestUserLoginName,
mobile: this.formData.mobile,
unitName: this.formData.unitName
}]
if (!this.formData.suggestUserDelegationName) {
await this.loadSuggestUserDelegation()
}
}
if (this.formData.delegationId) {
await this.discussionGroupChange(this.formData.delegationId)
}
}
} else {
this.listOpenSession(false)
// 临时存储用户ID
this.tempUserId = this.$store.state.user.id;
this.$set(this.formData, "createUserName", this.$store.state.user.username)
this.$set(this.formData, "createUserLoginName", this.$store.state.user.loginname)
this.$set(this.formData, "createTime", this.$moment().format("YYYY-MM-DD"))
this.$set(this.formData, "mobile", this.$store.state.user.mobile)
this.$set(this.formData, "unitName", this.$store.state.user.unit?.name)
}
},
// 回显代表姓名
echoRepresentativeName() {
const checkRefAndSet = () => {
if (this.$refs.userSelectRef) {
// 1. 设置options
this.$refs.userSelectRef.options = [{
userId: this.tempUserId || this.$store.state.user.id,
userName: this.formData.createUserName || this.$store.state.user.username,
loginName: this.formData.createUserLoginName || this.$store.state.user.loginname
}];
// 2. 延迟赋值,确保options已生效
this.$nextTick(() => {
this.$set(this.formData, "createUserId", this.tempUserId || this.$store.state.user.id);
});
} else {
setTimeout(checkRefAndSet, 50);
this.formData = {
sessionId: "",
delegationId: "",
createUserId: "",
createUserName: "",
createUserLoginName: "",
suggestUserId: "",
suggestUserName: "",
suggestUserLoginName: "",
suggestUserDelegationId: "",
suggestUserDelegationName: "",
delegationName: "",
discussionGroupName: "",
createTime: this.$moment().format("YYYY-MM-DD"),
mobile: "",
unitName: "",
suggestUnits: []
}
};
this.$nextTick(() => {
checkRefAndSet();
});
},
this.fillCurrentRecorder()
await this.listSession(false)
if (this.sessionOptions.length) {
this.formData.sessionId = this.sessionOptions[0].id
await this.listDiscussionGroup()
if (this.discussionGroupOptions.length) {
this.formData.delegationId = this.discussionGroupOptions[0].id
await this.discussionGroupChange(this.formData.delegationId)
}
}
}
}
},
mounted() {
this.$emit('ready')
this.$emit("ready")
this.applySuggestUserDelegationLabelStyle()
},
style:
/*language=CSS*/
`
`
}
@@ -2,7 +2,13 @@
layout("/layouts/platform.html"){
#-->
<style></style>
<style>
.el-form-item__label {
width: 120px;
white-space: nowrap;
transform: translateX(-13px);
}
</style>
<div id="app" v-cloak>
@@ -16,6 +22,14 @@ layout("/layouts/platform.html"){
<el-button type="primary" @click="$refs.formRef?.onSubmit()" v-if="!taskId">提交</el-button>
<el-button type="primary" @click="$refs.formRef?.onSubmitAgain()" v-else>提交</el-button>
</template>
<el-dialog title="温馨提示" :visible.sync="noticeDialogVisible" v-model="noticeDialogVisible">
<div style="max-height: 50vh; overflow-y: auto; white-space: pre-line; ">
{{friendlyReminderText}}
</div>
<div slot="footer">
<el-button type="primary" @click="noticeDialogVisible = false">我已知晓</el-button>
</div>
</el-dialog>
</custom-card>
</div>
@@ -32,15 +46,26 @@ layout("/layouts/platform.html"){
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
friendlyReminderText: '',
noticeDialogVisible: false
}
},
methods: {
onReady() {
this.$refs.formRef.ready(this.bizId, this.taskId)
}
},
async getConfigKeyObj() {
const resp = await this.$axios.post("/open/common/getConfigKeyObj", { key: "WriteOpinion" })
if(resp.data?.note){
this.noticeDialogVisible = true;
this.friendlyReminderText = resp.data?.note;
} else {
return "暂无配置提示内容";
}
},
},
async created() {
this.getConfigKeyObj();
},
})
</script>