index.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <view class="yd-page-container">
  3. <!-- 顶部导航栏 -->
  4. <wd-navbar
  5. :title="getTitle"
  6. left-arrow placeholder safe-area-inset-top fixed
  7. @click-left="handleBack"
  8. />
  9. <!-- 表单区域 -->
  10. <view>
  11. <wd-form ref="formRef" :model="formData" :rules="formRules">
  12. <wd-cell-group border>
  13. <wd-cell title="短信类型" title-width="200rpx" prop="type" center>
  14. <wd-picker
  15. v-model="formData.type"
  16. :columns="templateTypeOptions"
  17. placeholder="请选择短信类型"
  18. />
  19. </wd-cell>
  20. <wd-input
  21. v-model="formData.name"
  22. label="模板名称"
  23. label-width="200rpx"
  24. prop="name"
  25. clearable
  26. placeholder="请输入模板名称"
  27. />
  28. <wd-input
  29. v-model="formData.code"
  30. label="模板编码"
  31. label-width="200rpx"
  32. prop="code"
  33. clearable
  34. placeholder="请输入模板编码"
  35. />
  36. <wd-cell title="短信渠道" title-width="200rpx" prop="channelId" center>
  37. <wd-picker
  38. v-model="formData.channelId"
  39. :columns="channelOptions"
  40. placeholder="请选择短信渠道"
  41. />
  42. </wd-cell>
  43. <wd-cell title="开启状态" title-width="200rpx" prop="status" center>
  44. <wd-radio-group v-model="formData.status" shape="button">
  45. <wd-radio
  46. v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
  47. :key="dict.value"
  48. :value="dict.value"
  49. >
  50. {{ dict.label }}
  51. </wd-radio>
  52. </wd-radio-group>
  53. </wd-cell>
  54. <wd-textarea
  55. v-model="formData.content"
  56. label="模板内容"
  57. label-width="200rpx"
  58. prop="content"
  59. clearable
  60. placeholder="请输入模板内容"
  61. :rows="4"
  62. />
  63. <wd-input
  64. v-model="formData.apiTemplateId"
  65. label="API 模板编号"
  66. label-width="200rpx"
  67. prop="apiTemplateId"
  68. clearable
  69. placeholder="请输入短信 API 的模板编号"
  70. />
  71. <wd-textarea
  72. v-model="formData.remark"
  73. label="备注"
  74. label-width="200rpx"
  75. prop="remark"
  76. clearable
  77. placeholder="请输入备注"
  78. />
  79. </wd-cell-group>
  80. </wd-form>
  81. </view>
  82. <!-- 底部保存按钮 -->
  83. <view class="yd-detail-footer">
  84. <wd-button
  85. type="primary"
  86. block
  87. :loading="formLoading"
  88. @click="handleSubmit"
  89. >
  90. 保存
  91. </wd-button>
  92. </view>
  93. </view>
  94. </template>
  95. <script lang="ts" setup>
  96. import type { FormInstance } from 'wot-design-uni/components/wd-form/types'
  97. import type { SmsChannel } from '@/api/system/sms/channel'
  98. import type { SmsTemplate } from '@/api/system/sms/template'
  99. import { computed, onMounted, ref } from 'vue'
  100. import { useToast } from 'wot-design-uni'
  101. import { getSimpleSmsChannelList } from '@/api/system/sms/channel'
  102. import { createSmsTemplate, getSmsTemplate, updateSmsTemplate } from '@/api/system/sms/template'
  103. import { getIntDictOptions } from '@/hooks/useDict'
  104. import { navigateBackPlus } from '@/utils'
  105. import { CommonStatusEnum, DICT_TYPE } from '@/utils/constants'
  106. const props = defineProps<{
  107. id?: number | any
  108. }>()
  109. definePage({
  110. style: {
  111. navigationBarTitleText: '',
  112. navigationStyle: 'custom',
  113. },
  114. })
  115. const toast = useToast()
  116. const getTitle = computed(() => props.id ? '编辑短信模板' : '新增短信模板')
  117. const formLoading = ref(false)
  118. const formData = ref<SmsTemplate>({
  119. id: undefined,
  120. type: undefined,
  121. name: '',
  122. code: '',
  123. channelId: undefined,
  124. status: CommonStatusEnum.ENABLE,
  125. content: '',
  126. apiTemplateId: '',
  127. remark: '',
  128. })
  129. const formRules = {
  130. type: [{ required: true, message: '短信类型不能为空' }],
  131. name: [{ required: true, message: '模板名称不能为空' }],
  132. code: [{ required: true, message: '模板编码不能为空' }],
  133. channelId: [{ required: true, message: '短信渠道不能为空' }],
  134. status: [{ required: true, message: '开启状态不能为空' }],
  135. content: [{ required: true, message: '模板内容不能为空' }],
  136. apiTemplateId: [{ required: true, message: 'API 模板编号不能为空' }],
  137. }
  138. const formRef = ref<FormInstance>()
  139. /** 短信渠道列表 */
  140. const channelList = ref<SmsChannel[]>([])
  141. /** 短信类型选项 */
  142. const templateTypeOptions = computed(() => {
  143. return getIntDictOptions(DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE).map(item => ({
  144. value: item.value,
  145. label: item.label,
  146. }))
  147. })
  148. /** 短信渠道选项 */
  149. const channelOptions = computed(() => {
  150. return channelList.value.map(item => ({
  151. value: item.id,
  152. label: item.signature,
  153. }))
  154. })
  155. /** 返回上一页 */
  156. function handleBack() {
  157. navigateBackPlus('/pages-system/sms/index')
  158. }
  159. /** 加载短信渠道列表 */
  160. async function loadChannelList() {
  161. channelList.value = await getSimpleSmsChannelList()
  162. }
  163. /** 加载详情 */
  164. async function getDetail() {
  165. if (!props.id) {
  166. return
  167. }
  168. formData.value = await getSmsTemplate(props.id)
  169. }
  170. /** 提交表单 */
  171. async function handleSubmit() {
  172. const { valid } = await formRef.value.validate()
  173. if (!valid) {
  174. return
  175. }
  176. formLoading.value = true
  177. try {
  178. if (props.id) {
  179. await updateSmsTemplate(formData.value)
  180. toast.success('修改成功')
  181. } else {
  182. await createSmsTemplate(formData.value)
  183. toast.success('新增成功')
  184. }
  185. setTimeout(() => {
  186. handleBack()
  187. }, 500)
  188. } finally {
  189. formLoading.value = false
  190. }
  191. }
  192. /** 初始化 */
  193. onMounted(async () => {
  194. await loadChannelList()
  195. await getDetail()
  196. })
  197. </script>
  198. <style lang="scss" scoped>
  199. </style>