EditCourse.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <a-form
  3. :model="form"
  4. :rules="rules"
  5. ref="formRef"
  6. :label-col="{ span: 5 }"
  7. :wrapper-col="{ span: 18 }"
  8. labelAlign="left"
  9. class="edit-course-form"
  10. >
  11. <a-form-item label="工单标题" name="title" required>
  12. <a-input v-model:value="form.title" placeholder="工单标题" />
  13. </a-form-item>
  14. <a-form-item label="关联客户" name="customer" required>
  15. <a-select v-model:value="form.customer" placeholder="选择客户">
  16. <a-select-option v-for="item in customerList" :key="item.value" :value="item.value">{{
  17. item.label
  18. }}</a-select-option>
  19. </a-select>
  20. </a-form-item>
  21. <a-form-item label="产品" name="product">
  22. <a-select v-model:value="form.product" placeholder="选择订单">
  23. <a-select-option v-for="item in productList" :key="item.value" :value="item.value">{{
  24. item.label
  25. }}</a-select-option>
  26. </a-select>
  27. </a-form-item>
  28. <a-form-item label="工单类型" name="type" required>
  29. <a-select v-model:value="form.type" placeholder="选择类型">
  30. <a-select-option v-for="item in typeList" :key="item.value" :value="item.value">{{
  31. item.label
  32. }}</a-select-option>
  33. </a-select>
  34. </a-form-item>
  35. <a-form-item label="情况说明" name="desc">
  36. <a-textarea v-model:value="form.desc" :maxlength="300" :rows="4" placeholder="请输入情况说明" show-count />
  37. </a-form-item>
  38. <a-form-item label="信息来源" name="source">
  39. <a-select v-model:value="form.source" placeholder="选择信息来源">
  40. <a-select-option v-for="item in sourceList" :key="item.value" :value="item.value">{{
  41. item.label
  42. }}</a-select-option>
  43. </a-select>
  44. </a-form-item>
  45. <a-form-item label="上传附件" name="attachments">
  46. <a-upload
  47. v-model:file-list="form.attachments"
  48. :before-upload="beforeUpload"
  49. :multiple="true"
  50. :list-type="picture - card"
  51. :show-upload-list="{ showPreviewIcon: false }"
  52. :custom-request="dummyRequest"
  53. :accept="'.jpg,.png'"
  54. >
  55. <a-button>上传文件</a-button>
  56. </a-upload>
  57. <div class="upload-tip">请上传jpg、png图片附件,最多可上传4张,单张大小不要超过8M。</div>
  58. </a-form-item>
  59. <a-form-item label="联系人" name="contact" required>
  60. <a-input v-model:value="form.contact" placeholder="联系人" />
  61. </a-form-item>
  62. <a-form-item label="联系电话" name="phone">
  63. <a-input v-model:value="form.phone" placeholder="联系电话" />
  64. </a-form-item>
  65. <a-form-item label="所属区域" name="region">
  66. <a-select v-model:value="form.region" placeholder="请选择">
  67. <a-select-option v-for="item in regionList" :key="item.value" :value="item.value">{{
  68. item.label
  69. }}</a-select-option>
  70. </a-select>
  71. </a-form-item>
  72. <a-form-item label="详细地址" name="address">
  73. <a-input v-model:value="form.address" placeholder="详细地址" />
  74. </a-form-item>
  75. <a-form-item style="text-align: right; margin-top: 32px">
  76. <a-button @click="emit('close')" style="margin-right: 16px">取消</a-button>
  77. <a-button type="primary" @click="onSubmit">保存</a-button>
  78. </a-form-item>
  79. </a-form>
  80. </template>
  81. <script setup>
  82. import { ref, watch } from 'vue'
  83. const props = defineProps({
  84. course: { type: Object, default: () => ({}) }
  85. })
  86. const emit = defineEmits(['close'])
  87. const formRef = ref()
  88. const form = ref({
  89. title: '',
  90. customer: '',
  91. product: '',
  92. type: '',
  93. desc: '',
  94. source: '',
  95. attachments: [],
  96. contact: '',
  97. phone: '',
  98. region: '',
  99. address: ''
  100. })
  101. // mock 下拉数据
  102. const customerList = [
  103. { label: '张三公司', value: 'zhangsan' },
  104. { label: '李四企业', value: 'lisi' }
  105. ]
  106. const productList = [
  107. { label: '订单A', value: 'a' },
  108. { label: '订单B', value: 'b' }
  109. ]
  110. const typeList = [
  111. { label: '售后', value: 'after' },
  112. { label: '投诉', value: 'complain' }
  113. ]
  114. const sourceList = [
  115. { label: '电话', value: 'phone' },
  116. { label: '微信', value: 'wechat' }
  117. ]
  118. const regionList = [
  119. { label: '浙江舟山', value: 'zhoushan' },
  120. { label: '杭州', value: 'hangzhou' }
  121. ]
  122. watch(
  123. () => props.course,
  124. (val) => {
  125. form.value = {
  126. ...form.value,
  127. ...val
  128. }
  129. },
  130. { deep: true, immediate: true }
  131. )
  132. // 校验规则
  133. const rules = {
  134. title: [{ required: true, message: '请输入工单标题' }],
  135. customer: [{ required: true, message: '请选择客户' }],
  136. type: [{ required: true, message: '请选择工单类型' }],
  137. contact: [{ required: true, message: '请输入联系人' }]
  138. }
  139. // 附件上传限制
  140. function beforeUpload(file, fileList) {
  141. const isImg = file.type === 'image/jpeg' || file.type === 'image/png'
  142. const isLt8M = file.size / 1024 / 1024 < 8
  143. if (!isImg) {
  144. window.$message?.error('只能上传jpg/png图片')
  145. return false
  146. }
  147. if (!isLt8M) {
  148. window.$message?.error('单张图片不能超过8M')
  149. return false
  150. }
  151. if (form.value.attachments.length + fileList.length > 4) {
  152. window.$message?.error('最多上传4张图片')
  153. return false
  154. }
  155. return true
  156. }
  157. // mock上传
  158. function dummyRequest({ onSuccess }) {
  159. setTimeout(() => {
  160. onSuccess && onSuccess()
  161. }, 500)
  162. }
  163. function onSubmit() {
  164. formRef.value.validate().then(() => {
  165. console.log('保存数据', form.value)
  166. emit('close')
  167. })
  168. }
  169. </script>
  170. <style lang="less" scoped>
  171. .edit-course-form {
  172. padding-top: 24px;
  173. .upload-tip {
  174. color: #888;
  175. font-size: 12px;
  176. margin-top: 4px;
  177. }
  178. }
  179. </style>