diff --git a/src/main/resources/views/platform/zhghh5/democratic/proposal/transact/write/index.html b/src/main/resources/views/platform/zhghh5/democratic/proposal/transact/write/index.html index c671b056..086c3f87 100644 --- a/src/main/resources/views/platform/zhghh5/democratic/proposal/transact/write/index.html +++ b/src/main/resources/views/platform/zhghh5/democratic/proposal/transact/write/index.html @@ -2,7 +2,251 @@ layout("/layouts/platform_h5.html"){ #--> -
-
- - - +
+
+
+
+

撰写提案

+
情系职工 · 真诚服务
+
+
+
+ +
+ +
+ +
+
提案撰写须知
+
请围绕学校改革发展、内部管理、职工需求等方面,一事一案,提出可行性建议。
+
+ +
+ + + +
+

一、基本信息

+ @@ -124,7 +414,7 @@ layout("/layouts/platform_h5.html"){ show-toolbar :columns="sessionOptions.map(item => ({text: item.fullName, value: item.id}))" @confirm="onSessionConfirm" - @cancel="showSessionPicker = false" + @cancel="setVisibleState('showSessionPicker', false)" > @@ -143,7 +433,7 @@ layout("/layouts/platform_h5.html"){ name="committeeName" label="所属委员会" placeholder="请选择所属委员会" - @click="showCommitteePicker = true" + @click="setVisibleState('showCommitteePicker', true)" :rules="[{ required: true, message: '请选择所属委员会' }]" > @@ -151,7 +441,7 @@ layout("/layouts/platform_h5.html"){ show-toolbar :columns="committeeOptions.map(item => ({text: item.name, value: item.id}))" @confirm="onCommitteeConfirm" - @cancel="showCommitteePicker = false" + @cancel="setVisibleState('showCommitteePicker', false)" > @@ -170,10 +460,13 @@ layout("/layouts/platform_h5.html"){ placeholder="请输入联系电话" :rules="[{ required: true, message: '请填写联系电话' }]" > + +
- - - + +
+

二、提案内容

+ @@ -201,7 +494,7 @@ layout("/layouts/platform_h5.html"){ show-toolbar :columns="sourceOptions.map(item => ({text: item.name, value: item.code}))" @confirm="onSourceConfirm" - @cancel="showSourcePicker = false" + @cancel="setVisibleState('showSourcePicker', false)" > @@ -212,97 +505,20 @@ layout("/layouts/platform_h5.html"){ name="typeName" label="提案类型" placeholder="请选择提案类型" - @click="showTypePicker = true" + @click="setVisibleState('showTypePicker', true)" :rules="[{ required: true, message: '请选择提案类型' }]" required > - - - - - - -
- -
- -
选择建议承办单位
- -
- - -
- -
- - -
- - - - - - - -
-
-
-
- - - @@ -310,17 +526,20 @@ layout("/layouts/platform_h5.html"){ v-model="formData.measures" label="建议措施" type="textarea" - rows="6" + rows="3" autosize - placeholder="请输入建议措施" + placeholder="请提出具体、可行的建议措施" :rules="[{ required: true, message: '请填写建议措施' }]" + class="proposal-textarea-field" required > + +
-
- - - + +
+

三、附件材料

+ - + +
- -
- 保存 - 提交 - 提交 -
-
+ + + + + + +
+
+ +
选择建议承办单位
+ +
+ +
+ +
+ +
+ + + + + + + +
+
+
+ +
+ + +
+ + 保存草稿 + + + 提交提案 + + + 重新提交 + +
@@ -383,6 +662,8 @@ layout("/layouts/platform_h5.html"){ noticeDialogVisible: false, isWriteTime: true, + formLoading: false, + loadingAction: '', // 建议承办单位 suggestUnitOptions: [], @@ -393,6 +674,16 @@ layout("/layouts/platform_h5.html"){ } }, methods: { + /** + * 更新页面弹层显示状态,避免在模板事件中直接为 Vue 数据赋值。 + * @param {String} stateName showSessionPicker、showSourcePicker 等弹层状态字段名。 + * @param {Boolean} visible true 表示打开,false 表示关闭。 + * @return {void} 无返回值,仅更新当前页面状态。 + */ + setVisibleState(stateName, visible) { + this.$set(this, stateName, visible); + }, + // 选择器确认事件 onSessionConfirm(value) { this.formData.sessionId = value.value; @@ -462,17 +753,20 @@ layout("/layouts/platform_h5.html"){ this.showCommitteePicker = false; }, - async onSave() { - // 表单验证 - try { - await this.$refs.formRef.validate(); - + // 保存草稿:校验当前表单后保存 ProposalInfo,接口成功时返回提案数据并回到我的提案。 + onSave() { + if (this.formLoading) { + return; + } + this.$refs.formRef.validate().then(() => { + this.formLoading = true; + this.loadingAction = 'save'; this.$toast.loading({ message: '保存中...', forbidClick: true, }); - this.$axios.post("/platform/proposal/write/save", {info: JSON.stringify(this.formData)}) + return this.$axios.post("/platform/proposal/write/save", {info: JSON.stringify(this.formData)}) .then((res) => { this.$toast.clear(); if (res.code === 0) { @@ -485,29 +779,46 @@ layout("/layouts/platform_h5.html"){ .catch(err => { this.$toast.clear(); this.$toast.fail('网络错误,请稍后重试'); + }) + .finally(() => { + this.formLoading = false; + this.loadingAction = ''; }); - } catch (error) { - // 表单验证失败 + }).catch((error) => { console.log('表单验证失败', error); - } + }); }, - // 提交 - async onSubmit() { - try { - await this.$refs.formRef.validate(); + /** + * 提交前补充业务校验。 + * @param {String} briefMessage 案由不足配置字数时展示的完整提示前缀。 + * @return {Boolean} true 表示可以继续提交,false 表示已经提示并终止提交。 + */ + validateBeforeSubmit(briefMessage) { + if (!this.formData.name || this.formData.name.trim().length < 1) { + this.$toast("请填写提案名称"); + return false; + } + const briefMinLength = Number(this.proposalConfig.briefMinLength || 0); + if ((this.formData.brief || '').length < briefMinLength) { + this.$toast(briefMessage + briefMinLength + "字"); + return false; + } + return true; + }, - if (!this.formData.name || this.formData.name.trim().length < 1) { - this.$toast("请填写提案名称"); + // 首次提交:info 为完整提案 JSON,成功后进入提案流程并返回我的提案。 + onSubmit() { + if (this.formLoading) { + return; + } + this.$refs.formRef.validate().then(() => { + if (!this.validateBeforeSubmit("案由最少为")) { return; } - - if (this.formData.brief.length < this.proposalConfig.briefMinLength) { - this.$toast("案由" + this.proposalConfig.briefMinLength + "字"); - return; - } - - this.$dialog.confirm({ + this.formLoading = true; + this.loadingAction = 'submit'; + return this.$dialog.confirm({ title: '提示', message: '您确定要提交吗?', }).then(() => { @@ -516,7 +827,7 @@ layout("/layouts/platform_h5.html"){ forbidClick: true, }); - this.$axios.post('/platform/proposal/write/submit', {info: JSON.stringify(this.formData)}) + return this.$axios.post('/platform/proposal/write/submit', {info: JSON.stringify(this.formData)}) .then(res => { this.$toast.clear(); if (res.code === 0) { @@ -532,29 +843,27 @@ layout("/layouts/platform_h5.html"){ }); }).catch(() => { // 取消提交 + }).finally(() => { + this.formLoading = false; + this.loadingAction = ''; }); - } catch (error) { - // 表单验证失败 + }).catch((error) => { console.log('表单验证失败', error); - } + }); }, - // 重新提交 - async onSubmitAgain() { - try { - await this.$refs.formRef.validate(); - - if (!this.formData.name || this.formData.name.trim().length < 1) { - this.$toast("请填写提案名称"); + // 重新提交:除完整提案 JSON 外携带 taskId,用于继续当前退回任务。 + onSubmitAgain() { + if (this.formLoading) { + return; + } + this.$refs.formRef.validate().then(() => { + if (!this.validateBeforeSubmit("提案内容和依据最少为")) { return; } - - if (this.formData.brief.length < this.proposalConfig.briefMinLength) { - this.$toast("提案内容和依据最少为" + this.proposalConfig.briefMinLength + "字"); - return; - } - - this.$dialog.confirm({ + this.formLoading = true; + this.loadingAction = 'submitAgain'; + return this.$dialog.confirm({ title: '提示', message: '您确定要提交吗?', }).then(() => { @@ -563,7 +872,7 @@ layout("/layouts/platform_h5.html"){ forbidClick: true, }); - this.$axios.post('/platform/proposal/write/submitAgain', { + return this.$axios.post('/platform/proposal/write/submitAgain', { info: JSON.stringify(this.formData), taskId: this.taskId }).then(res => { @@ -582,11 +891,13 @@ layout("/layouts/platform_h5.html"){ }); }).catch(() => { // 取消提交 + }).finally(() => { + this.formLoading = false; + this.loadingAction = ''; }); - } catch (error) { - // 表单验证失败 + }).catch((error) => { console.log('表单验证失败', error); - } + }); }, // 根据当前教代会届次获取允许撰写的提案类型 @@ -613,22 +924,20 @@ layout("/layouts/platform_h5.html"){ }); }, - //教代会change - async meetingChange(val) { - // 切换届次后清空旧值,并加载新届次允许选择的提案类型 + // 切换教代会后清空跨届次数据,并按类型、代表团、提案方式、撰写时间的顺序重新加载。 + meetingChange(val) { this.$set(this.formData, "typeId", null); this.$set(this.formData, "typeName", ""); this.typeOptions = []; - this.listProposalType(); - this.formData.delegationId = null; - this.formData.committeeId = null; - this.formData.delegationName = ''; - this.formData.committeeName = ''; - await this.listDelegation(); - await this.searchMineDelegation(); - await this.listSource(); - // 检查是否在撰写时间内 - this.checkWriteTime(); + this.$set(this.formData, "delegationId", null); + this.$set(this.formData, "committeeId", null); + this.$set(this.formData, "delegationName", ''); + this.$set(this.formData, "committeeName", ''); + return this.listProposalType() + .then(() => this.listDelegation()) + .then(() => this.searchMineDelegation()) + .then(() => this.listSource()) + .then(() => this.checkWriteTime()); }, // 获取代表团 @@ -642,7 +951,7 @@ layout("/layouts/platform_h5.html"){ // 建议承办单位 listSuggestUnit() { - this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => { + return this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => { if (res.code === 0) { this.suggestUnitOptions = res.data } @@ -651,26 +960,26 @@ layout("/layouts/platform_h5.html"){ // 查询开启的教代会 listOpenSession(isModify = false) { - this.$axios.post("/platform/proposal/common/listOpenSession").then(async (res) => { + return this.$axios.post("/platform/proposal/common/listOpenSession").then((res) => { if (res.code === 0) { this.sessionOptions = res.data; if (!isModify && this.sessionOptions && this.sessionOptions.length > 0) { this.$set(this.formData, "sessionId", this.sessionOptions[0].id); this.$set(this.formData, "sessionName", this.sessionOptions[0].fullName); - this.listProposalType(); - await this.listDelegation(); - await this.listSource(); - // 获取代表团 - await this.searchMineDelegation(); - // 检查是否在撰写时间内 - this.checkWriteTime(); - } else { - await this.listDelegation(); - await this.listSource(); - this.listProposalType().then(() => { - this.echoPicker(); - }); + return this.listProposalType() + .then(() => this.listDelegation()) + .then(() => this.listSource()) + .then(() => this.searchMineDelegation()) + .then(() => this.checkWriteTime()); } + // 没有开启的教代会时不继续请求依赖 sessionId 的接口。 + if (!this.formData.sessionId) { + return Promise.resolve(); + } + return this.listDelegation() + .then(() => this.listSource()) + .then(() => this.listProposalType()) + .then(() => this.echoPicker()); } }); }, @@ -700,7 +1009,7 @@ layout("/layouts/platform_h5.html"){ // 检查是否在撰写时间内 checkWriteTime() { - this.$axios.post("/platform/proposal/write/checkWriteTime", {sessionId: this.formData.sessionId}).then((res) => { + return this.$axios.post("/platform/proposal/write/checkWriteTime", {sessionId: this.formData.sessionId}).then((res) => { if (res.code === 0) { if (!res.data) { this.$toast("当前时间不在撰写时间段内"); @@ -735,7 +1044,7 @@ layout("/layouts/platform_h5.html"){ if (res.code === 0) { res.data.brief=removeHTMLTag(res.data.brief) res.data.measures=removeHTMLTag(res.data.measures) - this.formData = res.data; + this.$set(this, "formData", res.data); this.listOpenSession(true); } });