BannerForm.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <Dialog v-model="dialogVisible" :title="dialogTitle">
  3. <el-form
  4. ref="formRef"
  5. v-loading="formLoading"
  6. :model="formData"
  7. :rules="formRules"
  8. label-width="100px"
  9. >
  10. <el-row>
  11. <el-col :span="24">
  12. <el-form-item label="标题" prop="title">
  13. <el-input v-model="formData.title" placeholder="请输入 Banner 标题" />
  14. </el-form-item>
  15. </el-col>
  16. <el-col :span="24">
  17. <el-form-item label="图片" prop="picUrl">
  18. <UploadImg v-model="formData.picUrl" />
  19. </el-form-item>
  20. </el-col>
  21. <el-col :span="24">
  22. <el-form-item label="跳转地址" prop="url">
  23. <el-input v-model="formData.url" placeholder="请输入跳转地址" />
  24. </el-form-item>
  25. </el-col>
  26. <el-col :span="24">
  27. <el-form-item label="排序" prop="sort">
  28. <el-input-number v-model="formData.sort" :min="0" clearable controls-position="right" />
  29. </el-form-item>
  30. </el-col>
  31. <el-col :span="24">
  32. <el-form-item label="状态" prop="status">
  33. <el-radio-group v-model="formData.status">
  34. <el-radio
  35. v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
  36. :key="dict.value"
  37. :label="dict.value"
  38. >
  39. {{ dict.label }}
  40. </el-radio>
  41. </el-radio-group>
  42. </el-form-item>
  43. </el-col>
  44. <el-col :span="24">
  45. <el-form-item label="位置" prop="position">
  46. <el-radio-group v-model="formData.position">
  47. <el-radio
  48. v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_BANNER_POSITION)"
  49. :key="dict.value"
  50. :label="dict.value"
  51. >
  52. {{ dict.label }}
  53. </el-radio>
  54. </el-radio-group>
  55. </el-form-item>
  56. </el-col>
  57. <el-col :span="24">
  58. <el-form-item label="描述" prop="memo">
  59. <el-input v-model="formData.memo" placeholder="请输入描述" type="textarea" />
  60. </el-form-item>
  61. </el-col>
  62. </el-row>
  63. </el-form>
  64. <template #footer>
  65. <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
  66. <el-button @click="dialogVisible = false">取 消</el-button>
  67. </template>
  68. </Dialog>
  69. </template>
  70. <script lang="ts" setup>
  71. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  72. import * as BannerApi from '@/api/mall/market/banner'
  73. const { t } = useI18n() // 国际化
  74. const message = useMessage() // 消息弹窗
  75. const dialogVisible = ref(false) // 弹窗的是否展示
  76. const dialogTitle = ref('') // 弹窗的标题
  77. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  78. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  79. const formData = ref({
  80. id: undefined,
  81. title: undefined,
  82. picUrl: undefined,
  83. status: 0,
  84. position: 1,
  85. url: undefined,
  86. sort: 0,
  87. memo: undefined
  88. })
  89. const formRules = reactive({
  90. title: [{ required: true, message: 'Banner 标题不能为空', trigger: 'blur' }],
  91. picUrl: [{ required: true, message: '图片 URL 不能为空', trigger: 'blur' }],
  92. status: [{ required: true, message: '活动状态不能为空', trigger: 'blur' }],
  93. position: [{ required: true, message: '位置不能为空', trigger: 'blur' }],
  94. sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
  95. url: [{ required: true, message: '跳转地址不能为空', trigger: 'blur' }]
  96. })
  97. const formRef = ref() // 表单 Ref
  98. /** 打开弹窗 */
  99. const open = async (type: string, id?: number) => {
  100. dialogVisible.value = true
  101. dialogTitle.value = t('action.' + type)
  102. formType.value = type
  103. resetForm()
  104. // 修改时,设置数据
  105. if (id) {
  106. formLoading.value = true
  107. try {
  108. formData.value = await BannerApi.getBanner(id)
  109. } finally {
  110. formLoading.value = false
  111. }
  112. }
  113. }
  114. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  115. /** 提交表单 */
  116. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  117. const submitForm = async () => {
  118. // 校验表单
  119. if (!formRef) return
  120. const valid = await formRef.value.validate()
  121. if (!valid) return
  122. // 提交请求
  123. formLoading.value = true
  124. try {
  125. const data = formData.value as unknown as BannerApi.BannerVO
  126. if (formType.value === 'create') {
  127. await BannerApi.createBanner(data)
  128. message.success(t('common.createSuccess'))
  129. } else {
  130. await BannerApi.updateBanner(data)
  131. message.success(t('common.updateSuccess'))
  132. }
  133. dialogVisible.value = false
  134. // 发送操作成功的事件
  135. emit('success')
  136. } finally {
  137. formLoading.value = false
  138. }
  139. }
  140. /** 重置表单 */
  141. const resetForm = () => {
  142. formData.value = {
  143. id: undefined,
  144. title: undefined,
  145. picUrl: undefined,
  146. status: 0,
  147. position: 1,
  148. url: undefined,
  149. sort: 0,
  150. memo: undefined
  151. }
  152. formRef.value?.resetFields()
  153. }
  154. </script>