commit
This commit is contained in:
+492
-183
@@ -2,7 +2,251 @@
|
|||||||
layout("/layouts/platform_h5.html"){
|
layout("/layouts/platform_h5.html"){
|
||||||
#-->
|
#-->
|
||||||
|
|
||||||
<style>
|
<style id="style-proposal-write-h5">
|
||||||
|
.proposal-write-page {
|
||||||
|
--proposal-primary: #1677ee;
|
||||||
|
--proposal-text: #263548;
|
||||||
|
--proposal-muted: #8995a5;
|
||||||
|
min-height: 100%;
|
||||||
|
padding-bottom: calc(84px + env(safe-area-inset-bottom));
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #f3f7fc;
|
||||||
|
color: var(--proposal-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-hero {
|
||||||
|
position: relative;
|
||||||
|
height: 116px;
|
||||||
|
padding: 18px 18px 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #edf5ff;
|
||||||
|
background-image: url("/assets/mobile/img/home/v4/hero-campus.png");
|
||||||
|
background-position: 66% 46%;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-hero::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(242, 247, 255, 0.76);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-hero__content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-hero__title {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--proposal-primary);
|
||||||
|
font-size: 23px;
|
||||||
|
line-height: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-hero__subtitle {
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #718096;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-main {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
margin-top: -43px;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-notice {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
min-height: 62px;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
padding: 12px 11px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid #dfeafb;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: rgba(246, 250, 255, 0.97);
|
||||||
|
box-shadow: 0 3px 10px rgba(53, 98, 154, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-notice__icon {
|
||||||
|
flex: none;
|
||||||
|
margin: 1px 9px 0 0;
|
||||||
|
color: var(--proposal-primary);
|
||||||
|
font-size: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-notice__body {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-notice__title {
|
||||||
|
color: #3673bd;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-notice__text {
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #8a97a8;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-notice__link {
|
||||||
|
align-self: center;
|
||||||
|
flex: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 8px;
|
||||||
|
padding: 4px 0;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--proposal-primary);
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card {
|
||||||
|
margin-bottom: 11px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #e9eff7;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 3px 11px rgba(51, 87, 126, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card__title {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 12px 14px 8px 21px;
|
||||||
|
color: #354255;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card__title::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
bottom: 11px;
|
||||||
|
left: 12px;
|
||||||
|
width: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: var(--proposal-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-cell-group {
|
||||||
|
margin: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-cell {
|
||||||
|
min-height: 44px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-cell:not(:last-child)::after {
|
||||||
|
right: 14px;
|
||||||
|
left: 14px;
|
||||||
|
border-color: #eef2f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-field__label {
|
||||||
|
width: 84px;
|
||||||
|
color: #596779;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-field__value,
|
||||||
|
.proposal-card .van-field__control {
|
||||||
|
color: #4f5d70;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-field__control::placeholder {
|
||||||
|
color: #b1bac6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-field__word-limit {
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #b5bdc8;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-card .van-cell--required::before {
|
||||||
|
left: 6px;
|
||||||
|
color: #f06464;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-textarea-field {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-textarea-field .van-field__label {
|
||||||
|
padding-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-textarea-field .van-field__control {
|
||||||
|
min-height: 66px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-actions {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 100;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 9px;
|
||||||
|
padding: 10px 18px calc(10px + env(safe-area-inset-bottom));
|
||||||
|
border-top: 1px solid #edf1f6;
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
box-shadow: 0 -4px 14px rgba(50, 78, 112, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-actions .van-button {
|
||||||
|
height: 40px;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-actions .van-button:first-child {
|
||||||
|
flex: 1;
|
||||||
|
color: var(--proposal-primary);
|
||||||
|
border-color: var(--proposal-primary);
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-actions .van-button:last-child {
|
||||||
|
flex: 1.08;
|
||||||
|
border-color: var(--proposal-primary);
|
||||||
|
background: var(--proposal-primary);
|
||||||
|
box-shadow: 0 4px 10px rgba(22, 119, 238, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-actions .van-icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
vertical-align: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
.suggestion-unit-picker {
|
.suggestion-unit-picker {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -85,16 +329,62 @@ layout("/layouts/platform_h5.html"){
|
|||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
text-indent: 2em; /* 中文首行缩进更规范 */
|
text-indent: 2em; /* 中文首行缩进更规范 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
.proposal-hero__content,
|
||||||
|
.proposal-main {
|
||||||
|
max-width: 520px;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-main {
|
||||||
|
margin-top: -43px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposal-actions {
|
||||||
|
right: 50%;
|
||||||
|
left: auto;
|
||||||
|
width: 520px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transform: translateX(50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="app" v-cloak>
|
<div id="app" v-cloak>
|
||||||
<van-nav-bar title="撰写提案" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed z-index="999"
|
<van-nav-bar title="撰写提案" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed z-index="999"
|
||||||
class="custom-nav"></van-nav-bar>
|
class="custom-nav"></van-nav-bar>
|
||||||
|
|
||||||
<div class="form-container">
|
<div class="proposal-write-page">
|
||||||
<van-form ref="formRef">
|
<header class="proposal-hero">
|
||||||
<!-- 基本信息 -->
|
<div class="proposal-hero__content">
|
||||||
<van-cell-group title="基本信息">
|
<div>
|
||||||
|
<h1 class="proposal-hero__title">撰写提案</h1>
|
||||||
|
<div class="proposal-hero__subtitle">情系职工 · 真诚服务</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="proposal-main">
|
||||||
|
<!-- 撰写须知保留原配置内容,通过轻量提示卡片进入详情。 -->
|
||||||
|
<div class="proposal-notice">
|
||||||
|
<van-icon class="proposal-notice__icon" name="info-o"></van-icon>
|
||||||
|
<div class="proposal-notice__body">
|
||||||
|
<div class="proposal-notice__title">提案撰写须知</div>
|
||||||
|
<div class="proposal-notice__text">请围绕学校改革发展、内部管理、职工需求等方面,一事一案,提出可行性建议。</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="proposal-notice__link" @click="setVisibleState('noticeDialogVisible', true)">
|
||||||
|
查看详情
|
||||||
|
<van-icon name="arrow"></van-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<van-form ref="formRef">
|
||||||
|
<!-- 基本信息:保留当前教代会、代表身份及联系方式等业务字段。 -->
|
||||||
|
<section class="proposal-card">
|
||||||
|
<h2 class="proposal-card__title">一、基本信息</h2>
|
||||||
|
<van-cell-group :border="false">
|
||||||
<van-field
|
<van-field
|
||||||
v-model="formData.createUserName"
|
v-model="formData.createUserName"
|
||||||
label="代表姓名"
|
label="代表姓名"
|
||||||
@@ -116,7 +406,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
name="sessionName"
|
name="sessionName"
|
||||||
label="所属教代会"
|
label="所属教代会"
|
||||||
placeholder="请选择所属教代会"
|
placeholder="请选择所属教代会"
|
||||||
@click="showSessionPicker = true"
|
@click="setVisibleState('showSessionPicker', true)"
|
||||||
:rules="[{ required: true, message: '请选择所属教代会' }]"
|
:rules="[{ required: true, message: '请选择所属教代会' }]"
|
||||||
></van-field>
|
></van-field>
|
||||||
<van-popup v-model="showSessionPicker" position="bottom">
|
<van-popup v-model="showSessionPicker" position="bottom">
|
||||||
@@ -124,7 +414,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
show-toolbar
|
show-toolbar
|
||||||
:columns="sessionOptions.map(item => ({text: item.fullName, value: item.id}))"
|
:columns="sessionOptions.map(item => ({text: item.fullName, value: item.id}))"
|
||||||
@confirm="onSessionConfirm"
|
@confirm="onSessionConfirm"
|
||||||
@cancel="showSessionPicker = false"
|
@cancel="setVisibleState('showSessionPicker', false)"
|
||||||
></van-picker>
|
></van-picker>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
@@ -143,7 +433,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
name="committeeName"
|
name="committeeName"
|
||||||
label="所属委员会"
|
label="所属委员会"
|
||||||
placeholder="请选择所属委员会"
|
placeholder="请选择所属委员会"
|
||||||
@click="showCommitteePicker = true"
|
@click="setVisibleState('showCommitteePicker', true)"
|
||||||
:rules="[{ required: true, message: '请选择所属委员会' }]"
|
:rules="[{ required: true, message: '请选择所属委员会' }]"
|
||||||
></van-field>
|
></van-field>
|
||||||
<van-popup v-model="showCommitteePicker" position="bottom">
|
<van-popup v-model="showCommitteePicker" position="bottom">
|
||||||
@@ -151,7 +441,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
show-toolbar
|
show-toolbar
|
||||||
:columns="committeeOptions.map(item => ({text: item.name, value: item.id}))"
|
:columns="committeeOptions.map(item => ({text: item.name, value: item.id}))"
|
||||||
@confirm="onCommitteeConfirm"
|
@confirm="onCommitteeConfirm"
|
||||||
@cancel="showCommitteePicker = false"
|
@cancel="setVisibleState('showCommitteePicker', false)"
|
||||||
></van-picker>
|
></van-picker>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
@@ -170,10 +460,13 @@ layout("/layouts/platform_h5.html"){
|
|||||||
placeholder="请输入联系电话"
|
placeholder="请输入联系电话"
|
||||||
:rules="[{ required: true, message: '请填写联系电话' }]"
|
:rules="[{ required: true, message: '请填写联系电话' }]"
|
||||||
></van-field>
|
></van-field>
|
||||||
|
</van-cell-group>
|
||||||
|
</section>
|
||||||
|
|
||||||
</van-cell-group>
|
<!-- 提案内容:字段和校验继续以现有接口及实体定义为准。 -->
|
||||||
|
<section class="proposal-card">
|
||||||
<van-cell-group title="提案信息" class="form-group">
|
<h2 class="proposal-card__title">二、提案内容</h2>
|
||||||
|
<van-cell-group :border="false">
|
||||||
<van-field
|
<van-field
|
||||||
v-model="formData.name"
|
v-model="formData.name"
|
||||||
name="name"
|
name="name"
|
||||||
@@ -192,7 +485,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
name="提案方式"
|
name="提案方式"
|
||||||
label="提案方式"
|
label="提案方式"
|
||||||
placeholder="请选择提案方式"
|
placeholder="请选择提案方式"
|
||||||
@click="showSourcePicker = true"
|
@click="setVisibleState('showSourcePicker', true)"
|
||||||
:rules="[{ required: true, message: '请选择提案方式' }]"
|
:rules="[{ required: true, message: '请选择提案方式' }]"
|
||||||
required
|
required
|
||||||
></van-field>
|
></van-field>
|
||||||
@@ -201,7 +494,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
show-toolbar
|
show-toolbar
|
||||||
:columns="sourceOptions.map(item => ({text: item.name, value: item.code}))"
|
:columns="sourceOptions.map(item => ({text: item.name, value: item.code}))"
|
||||||
@confirm="onSourceConfirm"
|
@confirm="onSourceConfirm"
|
||||||
@cancel="showSourcePicker = false"
|
@cancel="setVisibleState('showSourcePicker', false)"
|
||||||
></van-picker>
|
></van-picker>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
@@ -212,97 +505,20 @@ layout("/layouts/platform_h5.html"){
|
|||||||
name="typeName"
|
name="typeName"
|
||||||
label="提案类型"
|
label="提案类型"
|
||||||
placeholder="请选择提案类型"
|
placeholder="请选择提案类型"
|
||||||
@click="showTypePicker = true"
|
@click="setVisibleState('showTypePicker', true)"
|
||||||
:rules="[{ required: true, message: '请选择提案类型' }]"
|
:rules="[{ required: true, message: '请选择提案类型' }]"
|
||||||
required
|
required
|
||||||
></van-field>
|
></van-field>
|
||||||
<van-popup v-model="showTypePicker" position="bottom">
|
|
||||||
<van-picker
|
|
||||||
show-toolbar
|
|
||||||
:columns="typeOptions.map(item => ({text: item.name, value: item.id}))"
|
|
||||||
@confirm="onTypeConfirm"
|
|
||||||
@cancel="showTypePicker = false"
|
|
||||||
></van-picker>
|
|
||||||
</van-popup>
|
|
||||||
|
|
||||||
<!-- <van-field
|
|
||||||
:value="formData.suggestUnits.length > 0 ? formData.suggestUnits.join(', ') : ''"
|
|
||||||
is-link
|
|
||||||
readonly
|
|
||||||
name="suggestUnits"
|
|
||||||
label="建议承办单位"
|
|
||||||
placeholder="请选择建议承办单位"
|
|
||||||
@click="showSuggestionUnitPicker = true"
|
|
||||||
:rules="[{ required: true, message: '请选择建议承办单位' }]"
|
|
||||||
required
|
|
||||||
></van-field>-->
|
|
||||||
<van-popup v-model="showSuggestionUnitPicker" position="bottom" :style="{ height: '70%' }">
|
|
||||||
<div class="suggestion-unit-picker">
|
|
||||||
<!-- 头部工具栏 -->
|
|
||||||
<div class="picker-toolbar">
|
|
||||||
<button class="picker-cancel" @click="onSuggestionUnitCancel">取消</button>
|
|
||||||
<div class="picker-title">选择建议承办单位</div>
|
|
||||||
<button class="picker-confirm" @click="onSuggestionUnitConfirm">确认</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 搜索框 -->
|
|
||||||
<div class="search-container">
|
|
||||||
<van-search
|
|
||||||
v-model="suggestionUnitSearchText"
|
|
||||||
placeholder="搜索承办单位"
|
|
||||||
@input="onSuggestionUnitSearch"
|
|
||||||
></van-search>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 选项列表 -->
|
|
||||||
<div class="options-container">
|
|
||||||
<van-checkbox-group v-model="selectedSuggestionUnits">
|
|
||||||
<van-cell-group>
|
|
||||||
<van-cell
|
|
||||||
v-for="item in filteredSuggestionUnits"
|
|
||||||
:key="item.id"
|
|
||||||
clickable
|
|
||||||
@click="toggleSuggestionUnit(item)"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<div class="option-item">
|
|
||||||
<van-checkbox
|
|
||||||
:name="item.name"
|
|
||||||
:checked="selectedSuggestionUnits.includes(item.name)"
|
|
||||||
@click.stop
|
|
||||||
/>
|
|
||||||
<span class="option-text">{{ item.name }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</van-cell>
|
|
||||||
</van-cell-group>
|
|
||||||
</van-checkbox-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</van-popup>
|
|
||||||
</van-cell-group>
|
|
||||||
|
|
||||||
<van-cell-group title="提案内容" class="form-group">
|
|
||||||
<!--<van-field
|
|
||||||
v-model="formData.researchFindings"
|
|
||||||
name="researchFindings"
|
|
||||||
label="调研情况"
|
|
||||||
type="textarea"
|
|
||||||
rows="4"
|
|
||||||
autosize
|
|
||||||
placeholder="请输入调研情况"
|
|
||||||
:rules="[{ required: true, message: '请填写调研情况' }]"
|
|
||||||
required
|
|
||||||
></van-field>-->
|
|
||||||
|
|
||||||
<van-field
|
<van-field
|
||||||
v-model="formData.brief"
|
v-model="formData.brief"
|
||||||
label="提案案由"
|
label="提案案由"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
rows="6"
|
rows="3"
|
||||||
autosize
|
autosize
|
||||||
placeholder="请输入案由"
|
placeholder="请简要说明需要解决的问题和背景"
|
||||||
:rules="[{ required: true, message: '请填写案由' }]"
|
:rules="[{ required: true, message: '请填写案由' }]"
|
||||||
|
class="proposal-textarea-field"
|
||||||
required
|
required
|
||||||
></van-field>
|
></van-field>
|
||||||
|
|
||||||
@@ -310,17 +526,20 @@ layout("/layouts/platform_h5.html"){
|
|||||||
v-model="formData.measures"
|
v-model="formData.measures"
|
||||||
label="建议措施"
|
label="建议措施"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
rows="6"
|
rows="3"
|
||||||
autosize
|
autosize
|
||||||
placeholder="请输入建议措施"
|
placeholder="请提出具体、可行的建议措施"
|
||||||
:rules="[{ required: true, message: '请填写建议措施' }]"
|
:rules="[{ required: true, message: '请填写建议措施' }]"
|
||||||
|
class="proposal-textarea-field"
|
||||||
required
|
required
|
||||||
></van-field>
|
></van-field>
|
||||||
|
</van-cell-group>
|
||||||
|
</section>
|
||||||
|
|
||||||
</van-cell-group>
|
<!-- 附件材料仅使用卡片分组,上传控件保持项目原有样式和结果结构。 -->
|
||||||
|
<section class="proposal-card">
|
||||||
<!-- 附件上传 -->
|
<h2 class="proposal-card__title">三、附件材料</h2>
|
||||||
<van-cell-group title="附件上传" class="form-group">
|
<van-cell-group :border="false">
|
||||||
<van-field label="附件" name="files" class="direction-column-field">
|
<van-field label="附件" name="files" class="direction-column-field">
|
||||||
<h5-file-upload
|
<h5-file-upload
|
||||||
slot="input"
|
slot="input"
|
||||||
@@ -332,15 +551,75 @@ layout("/layouts/platform_h5.html"){
|
|||||||
complete_result
|
complete_result
|
||||||
></h5-file-upload>
|
></h5-file-upload>
|
||||||
</van-field>
|
</van-field>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- 按钮区域 -->
|
<!-- 各选择器沿用原始数据源与回显逻辑。 -->
|
||||||
<div class="form-actions" v-if="isWriteTime">
|
<van-popup v-model="showTypePicker" position="bottom">
|
||||||
<van-button plain type="info" @click="onSave">保存</van-button>
|
<van-picker
|
||||||
<van-button type="primary" @click="onSubmit" v-if="!taskId">提交</van-button>
|
show-toolbar
|
||||||
<van-button type="primary" @click="onSubmitAgain" v-else>提交</van-button>
|
:columns="typeOptions.map(item => ({text: item.name, value: item.id}))"
|
||||||
</div>
|
@confirm="onTypeConfirm"
|
||||||
</van-form>
|
@cancel="setVisibleState('showTypePicker', false)"
|
||||||
|
></van-picker>
|
||||||
|
</van-popup>
|
||||||
|
|
||||||
|
<van-popup v-model="showSuggestionUnitPicker" position="bottom" :style="{ height: '70%' }">
|
||||||
|
<div class="suggestion-unit-picker">
|
||||||
|
<div class="picker-toolbar">
|
||||||
|
<button type="button" class="picker-cancel" @click="onSuggestionUnitCancel">取消</button>
|
||||||
|
<div class="picker-title">选择建议承办单位</div>
|
||||||
|
<button type="button" class="picker-confirm" @click="onSuggestionUnitConfirm">确认</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-container">
|
||||||
|
<van-search
|
||||||
|
v-model="suggestionUnitSearchText"
|
||||||
|
placeholder="搜索承办单位"
|
||||||
|
@input="onSuggestionUnitSearch"
|
||||||
|
></van-search>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="options-container">
|
||||||
|
<van-checkbox-group v-model="selectedSuggestionUnits">
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell
|
||||||
|
v-for="item in filteredSuggestionUnits"
|
||||||
|
:key="item.id"
|
||||||
|
clickable
|
||||||
|
@click="toggleSuggestionUnit(item)"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<div class="option-item">
|
||||||
|
<van-checkbox
|
||||||
|
:name="item.name"
|
||||||
|
:checked="selectedSuggestionUnits.includes(item.name)"
|
||||||
|
@click.stop
|
||||||
|
></van-checkbox>
|
||||||
|
<span class="option-text">{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
</van-checkbox-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-popup>
|
||||||
|
</van-form>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- 保存、首次提交和重新提交继续共用原业务入口。 -->
|
||||||
|
<div class="proposal-actions" v-if="isWriteTime">
|
||||||
|
<van-button plain type="info" :loading="formLoading && loadingAction === 'save'" :disabled="formLoading" @click="onSave">
|
||||||
|
<van-icon name="records"></van-icon>保存草稿
|
||||||
|
</van-button>
|
||||||
|
<van-button type="primary" :loading="formLoading && loadingAction === 'submit'" :disabled="formLoading" @click="onSubmit" v-if="!taskId">
|
||||||
|
<van-icon name="guide-o"></van-icon>提交提案
|
||||||
|
</van-button>
|
||||||
|
<van-button type="primary" :loading="formLoading && loadingAction === 'submitAgain'" :disabled="formLoading" @click="onSubmitAgain" v-else>
|
||||||
|
<van-icon name="guide-o"></van-icon>重新提交
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 提案撰写须知弹窗 -->
|
<!-- 提案撰写须知弹窗 -->
|
||||||
@@ -383,6 +662,8 @@ layout("/layouts/platform_h5.html"){
|
|||||||
noticeDialogVisible: false,
|
noticeDialogVisible: false,
|
||||||
|
|
||||||
isWriteTime: true,
|
isWriteTime: true,
|
||||||
|
formLoading: false,
|
||||||
|
loadingAction: '',
|
||||||
|
|
||||||
// 建议承办单位
|
// 建议承办单位
|
||||||
suggestUnitOptions: [],
|
suggestUnitOptions: [],
|
||||||
@@ -393,6 +674,16 @@ layout("/layouts/platform_h5.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
/**
|
||||||
|
* 更新页面弹层显示状态,避免在模板事件中直接为 Vue 数据赋值。
|
||||||
|
* @param {String} stateName showSessionPicker、showSourcePicker 等弹层状态字段名。
|
||||||
|
* @param {Boolean} visible true 表示打开,false 表示关闭。
|
||||||
|
* @return {void} 无返回值,仅更新当前页面状态。
|
||||||
|
*/
|
||||||
|
setVisibleState(stateName, visible) {
|
||||||
|
this.$set(this, stateName, visible);
|
||||||
|
},
|
||||||
|
|
||||||
// 选择器确认事件
|
// 选择器确认事件
|
||||||
onSessionConfirm(value) {
|
onSessionConfirm(value) {
|
||||||
this.formData.sessionId = value.value;
|
this.formData.sessionId = value.value;
|
||||||
@@ -462,17 +753,20 @@ layout("/layouts/platform_h5.html"){
|
|||||||
this.showCommitteePicker = false;
|
this.showCommitteePicker = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
async onSave() {
|
// 保存草稿:校验当前表单后保存 ProposalInfo,接口成功时返回提案数据并回到我的提案。
|
||||||
// 表单验证
|
onSave() {
|
||||||
try {
|
if (this.formLoading) {
|
||||||
await this.$refs.formRef.validate();
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.formRef.validate().then(() => {
|
||||||
|
this.formLoading = true;
|
||||||
|
this.loadingAction = 'save';
|
||||||
this.$toast.loading({
|
this.$toast.loading({
|
||||||
message: '保存中...',
|
message: '保存中...',
|
||||||
forbidClick: true,
|
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) => {
|
.then((res) => {
|
||||||
this.$toast.clear();
|
this.$toast.clear();
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -485,29 +779,46 @@ layout("/layouts/platform_h5.html"){
|
|||||||
.catch(err => {
|
.catch(err => {
|
||||||
this.$toast.clear();
|
this.$toast.clear();
|
||||||
this.$toast.fail('网络错误,请稍后重试');
|
this.$toast.fail('网络错误,请稍后重试');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.formLoading = false;
|
||||||
|
this.loadingAction = '';
|
||||||
});
|
});
|
||||||
} catch (error) {
|
}).catch((error) => {
|
||||||
// 表单验证失败
|
|
||||||
console.log('表单验证失败', error);
|
console.log('表单验证失败', error);
|
||||||
}
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 提交
|
/**
|
||||||
async onSubmit() {
|
* 提交前补充业务校验。
|
||||||
try {
|
* @param {String} briefMessage 案由不足配置字数时展示的完整提示前缀。
|
||||||
await this.$refs.formRef.validate();
|
* @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) {
|
// 首次提交:info 为完整提案 JSON,成功后进入提案流程并返回我的提案。
|
||||||
this.$toast("请填写提案名称");
|
onSubmit() {
|
||||||
|
if (this.formLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.formRef.validate().then(() => {
|
||||||
|
if (!this.validateBeforeSubmit("案由最少为")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.formLoading = true;
|
||||||
if (this.formData.brief.length < this.proposalConfig.briefMinLength) {
|
this.loadingAction = 'submit';
|
||||||
this.$toast("案由" + this.proposalConfig.briefMinLength + "字");
|
return this.$dialog.confirm({
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$dialog.confirm({
|
|
||||||
title: '提示',
|
title: '提示',
|
||||||
message: '您确定要提交吗?',
|
message: '您确定要提交吗?',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -516,7 +827,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
forbidClick: true,
|
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 => {
|
.then(res => {
|
||||||
this.$toast.clear();
|
this.$toast.clear();
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -532,29 +843,27 @@ layout("/layouts/platform_h5.html"){
|
|||||||
});
|
});
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// 取消提交
|
// 取消提交
|
||||||
|
}).finally(() => {
|
||||||
|
this.formLoading = false;
|
||||||
|
this.loadingAction = '';
|
||||||
});
|
});
|
||||||
} catch (error) {
|
}).catch((error) => {
|
||||||
// 表单验证失败
|
|
||||||
console.log('表单验证失败', error);
|
console.log('表单验证失败', error);
|
||||||
}
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 重新提交
|
// 重新提交:除完整提案 JSON 外携带 taskId,用于继续当前退回任务。
|
||||||
async onSubmitAgain() {
|
onSubmitAgain() {
|
||||||
try {
|
if (this.formLoading) {
|
||||||
await this.$refs.formRef.validate();
|
return;
|
||||||
|
}
|
||||||
if (!this.formData.name || this.formData.name.trim().length < 1) {
|
this.$refs.formRef.validate().then(() => {
|
||||||
this.$toast("请填写提案名称");
|
if (!this.validateBeforeSubmit("提案内容和依据最少为")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.formLoading = true;
|
||||||
if (this.formData.brief.length < this.proposalConfig.briefMinLength) {
|
this.loadingAction = 'submitAgain';
|
||||||
this.$toast("提案内容和依据最少为" + this.proposalConfig.briefMinLength + "字");
|
return this.$dialog.confirm({
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$dialog.confirm({
|
|
||||||
title: '提示',
|
title: '提示',
|
||||||
message: '您确定要提交吗?',
|
message: '您确定要提交吗?',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -563,7 +872,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
forbidClick: true,
|
forbidClick: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$axios.post('/platform/proposal/write/submitAgain', {
|
return this.$axios.post('/platform/proposal/write/submitAgain', {
|
||||||
info: JSON.stringify(this.formData),
|
info: JSON.stringify(this.formData),
|
||||||
taskId: this.taskId
|
taskId: this.taskId
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
@@ -582,11 +891,13 @@ layout("/layouts/platform_h5.html"){
|
|||||||
});
|
});
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// 取消提交
|
// 取消提交
|
||||||
|
}).finally(() => {
|
||||||
|
this.formLoading = false;
|
||||||
|
this.loadingAction = '';
|
||||||
});
|
});
|
||||||
} catch (error) {
|
}).catch((error) => {
|
||||||
// 表单验证失败
|
|
||||||
console.log('表单验证失败', 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, "typeId", null);
|
||||||
this.$set(this.formData, "typeName", "");
|
this.$set(this.formData, "typeName", "");
|
||||||
this.typeOptions = [];
|
this.typeOptions = [];
|
||||||
this.listProposalType();
|
this.$set(this.formData, "delegationId", null);
|
||||||
this.formData.delegationId = null;
|
this.$set(this.formData, "committeeId", null);
|
||||||
this.formData.committeeId = null;
|
this.$set(this.formData, "delegationName", '');
|
||||||
this.formData.delegationName = '';
|
this.$set(this.formData, "committeeName", '');
|
||||||
this.formData.committeeName = '';
|
return this.listProposalType()
|
||||||
await this.listDelegation();
|
.then(() => this.listDelegation())
|
||||||
await this.searchMineDelegation();
|
.then(() => this.searchMineDelegation())
|
||||||
await this.listSource();
|
.then(() => this.listSource())
|
||||||
// 检查是否在撰写时间内
|
.then(() => this.checkWriteTime());
|
||||||
this.checkWriteTime();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取代表团
|
// 获取代表团
|
||||||
@@ -642,7 +951,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
|
|
||||||
// 建议承办单位
|
// 建议承办单位
|
||||||
listSuggestUnit() {
|
listSuggestUnit() {
|
||||||
this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => {
|
return this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.suggestUnitOptions = res.data
|
this.suggestUnitOptions = res.data
|
||||||
}
|
}
|
||||||
@@ -651,26 +960,26 @@ layout("/layouts/platform_h5.html"){
|
|||||||
|
|
||||||
// 查询开启的教代会
|
// 查询开启的教代会
|
||||||
listOpenSession(isModify = false) {
|
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) {
|
if (res.code === 0) {
|
||||||
this.sessionOptions = res.data;
|
this.sessionOptions = res.data;
|
||||||
if (!isModify && this.sessionOptions && this.sessionOptions.length > 0) {
|
if (!isModify && this.sessionOptions && this.sessionOptions.length > 0) {
|
||||||
this.$set(this.formData, "sessionId", this.sessionOptions[0].id);
|
this.$set(this.formData, "sessionId", this.sessionOptions[0].id);
|
||||||
this.$set(this.formData, "sessionName", this.sessionOptions[0].fullName);
|
this.$set(this.formData, "sessionName", this.sessionOptions[0].fullName);
|
||||||
this.listProposalType();
|
return this.listProposalType()
|
||||||
await this.listDelegation();
|
.then(() => this.listDelegation())
|
||||||
await this.listSource();
|
.then(() => this.listSource())
|
||||||
// 获取代表团
|
.then(() => this.searchMineDelegation())
|
||||||
await this.searchMineDelegation();
|
.then(() => this.checkWriteTime());
|
||||||
// 检查是否在撰写时间内
|
|
||||||
this.checkWriteTime();
|
|
||||||
} else {
|
|
||||||
await this.listDelegation();
|
|
||||||
await this.listSource();
|
|
||||||
this.listProposalType().then(() => {
|
|
||||||
this.echoPicker();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// 没有开启的教代会时不继续请求依赖 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() {
|
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.code === 0) {
|
||||||
if (!res.data) {
|
if (!res.data) {
|
||||||
this.$toast("当前时间不在撰写时间段内");
|
this.$toast("当前时间不在撰写时间段内");
|
||||||
@@ -735,7 +1044,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
res.data.brief=removeHTMLTag(res.data.brief)
|
res.data.brief=removeHTMLTag(res.data.brief)
|
||||||
res.data.measures=removeHTMLTag(res.data.measures)
|
res.data.measures=removeHTMLTag(res.data.measures)
|
||||||
this.formData = res.data;
|
this.$set(this, "formData", res.data);
|
||||||
this.listOpenSession(true);
|
this.listOpenSession(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user