ElectronicReportForm.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <template>
  2. <div class="electronic-report-form">
  3. <el-form
  4. ref="formRef"
  5. :model="formData"
  6. :rules="formRules"
  7. label-width="140px"
  8. :validate-on-rule-change="false"
  9. @validate="handleValidateChange"
  10. >
  11. <!-- 出具方式选择 -->
  12. <el-form-item label="出具方式:" prop="deliveryType">
  13. <el-checkbox-group v-model="formData.deliveryType" @change="handleDeliveryTypeChange">
  14. <el-checkbox label="miniprogram">小程序推送</el-checkbox>
  15. <el-checkbox label="email">邮箱推送</el-checkbox>
  16. </el-checkbox-group>
  17. </el-form-item>
  18. <!-- 小程序推送表单 -->
  19. <template v-if="formData.deliveryType.includes('miniprogram')">
  20. <el-form-item label="小程序推送对象:" prop="miniprogramTarget">
  21. <el-checkbox-group v-model="formData.miniprogramTarget">
  22. <el-checkbox label="main">主账号管理员</el-checkbox>
  23. <el-checkbox label="sub">子账号管理员</el-checkbox>
  24. </el-checkbox-group>
  25. </el-form-item>
  26. </template>
  27. <!-- 邮箱推送表单 -->
  28. <template v-if="formData.deliveryType.includes('email')">
  29. <el-form-item label="邮箱推送:" prop="emailAddress">
  30. <el-input
  31. v-model="formData.emailAddress"
  32. placeholder="请输入邮箱"
  33. class="!w-300px"
  34. />
  35. </el-form-item>
  36. </template>
  37. </el-form>
  38. </div>
  39. </template>
  40. <script setup lang="ts">
  41. import { ref, reactive, watch, computed } from 'vue'
  42. import type { FormInstance, FormRules } from 'element-plus'
  43. const props = defineProps<{
  44. modelValue: any
  45. isPartReport: boolean
  46. }>()
  47. const emit = defineEmits<{
  48. 'update:modelValue': [value: any]
  49. 'validate-change': [valid: boolean]
  50. }>()
  51. // 表单引用
  52. const formRef = ref<FormInstance>()
  53. // 表单数据
  54. const formData = reactive<any>({
  55. deliveryType: [],
  56. miniprogramTarget: [],
  57. emailAddress: ''
  58. })
  59. // 表单验证规则 - 只在提交时验证,不设置实时验证触发器
  60. const formRules = computed((): FormRules<any> => {
  61. const rules: FormRules<any> = {
  62. deliveryType: [
  63. {
  64. type: 'array',
  65. required: true,
  66. message: '请选择出具方式',
  67. validator: (rule, value, callback) => {
  68. if (!value || value.length === 0) {
  69. callback(new Error('请选择出具方式'))
  70. } else {
  71. callback()
  72. }
  73. }
  74. }
  75. ]
  76. }
  77. // 根据出具方式动态添加验证规则(不设置trigger,只在手动验证时触发)
  78. if (formData.deliveryType.includes('miniprogram')) {
  79. rules.miniprogramTarget = [
  80. {
  81. type: 'array',
  82. required: true,
  83. message: '请选择小程序推送对象',
  84. validator: (rule, value, callback) => {
  85. if (!value || value.length === 0) {
  86. callback(new Error('请选择小程序推送对象'))
  87. } else {
  88. callback()
  89. }
  90. }
  91. }
  92. ]
  93. }
  94. if (formData.deliveryType.includes('email')) {
  95. rules.emailAddress = [
  96. { required: true, message: '请输入邮箱地址' },
  97. {
  98. type: 'email',
  99. message: '请输入正确的邮箱地址'
  100. }
  101. ]
  102. }
  103. return rules
  104. })
  105. // 监听props变化
  106. watch(() => props.modelValue, (newValue) => {
  107. Object.assign(formData, newValue)
  108. }, { immediate: true, deep: true })
  109. // 监听formData变化,向外emit
  110. watch(formData, (newValue) => {
  111. emit('update:modelValue', { ...newValue })
  112. }, { deep: true })
  113. // 出具方式变化处理
  114. const handleDeliveryTypeChange = (value: string[]) => {
  115. // 清空相关字段
  116. if (!value.includes('miniprogram')) {
  117. formData.miniprogramTarget = []
  118. }
  119. if (!value.includes('email')) {
  120. formData.emailAddress = ''
  121. }
  122. // 清除验证错误
  123. formRef.value?.clearValidate()
  124. }
  125. // 表单验证状态变化
  126. const handleValidateChange = (prop: string, isValid: boolean, message: string) => {
  127. // 这里可以收集所有字段的验证状态
  128. // 为简化,我们在validate方法中统一处理
  129. }
  130. // 验证表单
  131. const validate = async (): Promise<boolean> => {
  132. if (!formRef.value) return false
  133. try {
  134. await formRef.value.validate()
  135. emit('validate-change', true)
  136. return true
  137. } catch (error) {
  138. emit('validate-change', false)
  139. return false
  140. }
  141. }
  142. // 重置表单
  143. const resetFields = () => {
  144. formRef.value?.resetFields()
  145. }
  146. // 清除验证
  147. const clearValidate = () => {
  148. formRef.value?.clearValidate()
  149. }
  150. // 暴露方法
  151. defineExpose({
  152. validate,
  153. resetFields,
  154. clearValidate
  155. })
  156. </script>
  157. <style lang="scss" scoped>
  158. .electronic-report-form {
  159. :deep(.el-form-item) {
  160. margin-bottom: 18px;
  161. }
  162. :deep(.el-radio-group) {
  163. .el-radio {
  164. margin-right: 24px;
  165. margin-bottom: 8px;
  166. }
  167. }
  168. :deep(.el-checkbox-group) {
  169. .el-checkbox {
  170. margin-right: 24px;
  171. margin-bottom: 8px;
  172. }
  173. }
  174. }
  175. </style>