DescriptionForm.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <template>
  2. <el-form
  3. v-if="!isDetail"
  4. ref="descriptionFormRef"
  5. :model="formData"
  6. :rules="rules"
  7. label-width="120px"
  8. >
  9. <!--富文本编辑器组件-->
  10. <el-form-item label="商品详情" prop="description">
  11. <Editor v-model:modelValue="formData.description" />
  12. </el-form-item>
  13. </el-form>
  14. <Descriptions
  15. v-if="isDetail"
  16. :data="formData"
  17. :schema="allSchemas.detailSchema"
  18. class="descriptionFormDescriptions"
  19. >
  20. <!-- 展示 HTML 内容 -->
  21. <template #description="{ row }">
  22. <div v-dompurify-html="row.description" style="width: 600px"></div>
  23. </template>
  24. </Descriptions>
  25. </template>
  26. <script lang="ts" name="DescriptionForm" setup>
  27. import type { Spu } from '@/api/mall/product/spu'
  28. import { Editor } from '@/components/Editor'
  29. import { PropType } from 'vue'
  30. import { propTypes } from '@/utils/propTypes'
  31. import { copyValueToTarget } from '@/utils'
  32. import { descriptionSchema } from './spu.data'
  33. const { allSchemas } = useCrudSchemas(descriptionSchema)
  34. const message = useMessage() // 消息弹窗
  35. const props = defineProps({
  36. propFormData: {
  37. type: Object as PropType<Spu>,
  38. default: () => {}
  39. },
  40. activeName: propTypes.string.def(''),
  41. isDetail: propTypes.bool.def(false) // 是否作为详情组件
  42. })
  43. const descriptionFormRef = ref() // 表单Ref
  44. const formData = ref<Spu>({
  45. description: '' // 商品详情
  46. })
  47. // 表单规则
  48. const rules = reactive({
  49. description: [required]
  50. })
  51. /**
  52. * 富文本编辑器如果输入过再清空会有残留,需再重置一次
  53. */
  54. watch(
  55. () => formData.value.description,
  56. (newValue) => {
  57. if ('<p><br></p>' === newValue) {
  58. formData.value.description = ''
  59. }
  60. },
  61. {
  62. deep: true,
  63. immediate: true
  64. }
  65. )
  66. /**
  67. * 将传进来的值赋值给formData
  68. */
  69. watch(
  70. () => props.propFormData,
  71. (data) => {
  72. if (!data) return
  73. // fix:三个表单组件监听赋值必须使用 copyValueToTarget 使用 formData.value = data 会监听非常多次
  74. copyValueToTarget(formData.value, data)
  75. },
  76. {
  77. // fix: 去掉深度监听只有对象引用发生改变的时候才执行,解决改一动多的问题
  78. immediate: true
  79. }
  80. )
  81. /**
  82. * 表单校验
  83. */
  84. const emit = defineEmits(['update:activeName'])
  85. const validate = async () => {
  86. // 校验表单
  87. if (!descriptionFormRef) return
  88. return await unref(descriptionFormRef).validate((valid) => {
  89. if (!valid) {
  90. message.warning('商品详情为完善!!')
  91. emit('update:activeName', 'description')
  92. // 目的截断之后的校验
  93. throw new Error('商品详情为完善!!')
  94. } else {
  95. // 校验通过更新数据
  96. Object.assign(props.propFormData, formData.value)
  97. }
  98. })
  99. }
  100. defineExpose({ validate })
  101. </script>