FollowDialog.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <ElDialog
  3. v-model="dialogVisible"
  4. title="新增跟进记录"
  5. width="50%"
  6. align-center
  7. >
  8. <ElForm ref="formRef" :model="formData" :rules="rules" label-width="auto">
  9. <ElFormItem :label="selectLabelArr[0]" prop="first_id">
  10. <ElSelect v-model="formData.first_id">
  11. <ElOption
  12. v-for="item in selectList"
  13. :key="item.id"
  14. :value="item.id"
  15. :label="item.name"
  16. />
  17. </ElSelect>
  18. </ElFormItem>
  19. <ElFormItem :label="selectLabelArr[1]" prop="second_id">
  20. <ElSelect v-model="formData.second_id">
  21. <ElOption
  22. v-for="item in secondSelectList"
  23. :key="item.id"
  24. :value="item.id"
  25. :label="item.name"
  26. />
  27. </ElSelect>
  28. </ElFormItem>
  29. <ElFormItem label="微信聊天记录" prop="chat_imgs">
  30. <el-upload
  31. :file-list="fileList"
  32. name="follow"
  33. :action="uploadServer"
  34. list-type="picture-card"
  35. :limit="12"
  36. :on-preview="handlePictureCardPreview"
  37. :on-remove="handleRemove"
  38. :before-upload="beforeUpload"
  39. :on-success="handleSuccess"
  40. :headers="{Authorization: useUserStore().accessToken}"
  41. drag
  42. >
  43. <i class="el-icon-plus"></i>
  44. <el-icon><Plus /></el-icon>
  45. <template #tip>
  46. <div style="color:red">支持拖拽上传,限 jpg、png、jpeg 图片,最大{{maxFileSizeMB}}M,最多12张</div>
  47. </template>
  48. </el-upload>
  49. <!-- 图片预览 -->
  50. <el-image-viewer
  51. v-if="picDialogVisible"
  52. :url-list="[dialogImageUrl]"
  53. show-progress
  54. :initial-index="0"
  55. @close="picDialogVisible = false"
  56. />
  57. </ElFormItem>
  58. <ElFormItem label="跟进详情" prop="detail">
  59. <!-- 富文本编辑器 -->
  60. <ArtWangEditor class="el-top" v-model="formData.detail" height="250px"/>
  61. </ElFormItem>
  62. </ElForm>
  63. <template #footer>
  64. <div class="dialog-footer">
  65. <ElButton @click="dialogVisible = false">取消</ElButton>
  66. <ElButton type="primary" @click="handleSubmit">提交</ElButton>
  67. </div>
  68. </template>
  69. </ElDialog>
  70. </template>
  71. <script setup lang="ts">
  72. import {computed, ref} from 'vue'
  73. import { useUserStore } from '@/store/modules/user'
  74. import { Plus } from '@element-plus/icons-vue'
  75. import {ElMessage, ElMessageBox, UploadProps, UploadUserFile} from 'element-plus'
  76. import type { FormInstance, FormRules } from 'element-plus'
  77. import {commonApi} from "@/api/commonApi";
  78. interface Props {
  79. visible: boolean
  80. type:Api.FollowTye
  81. userData?: any
  82. first_id?: number
  83. second_id?: number
  84. selectList: Api.Common.SelectRelationInfo[]
  85. }
  86. interface Emits {
  87. (e: 'update:visible', value: boolean): void
  88. (e: 'submit'): void
  89. }
  90. const props = defineProps<Props>()
  91. const emit = defineEmits<Emits>()
  92. const uploadServer = computed(() => import.meta.env.VITE_API_URL + import.meta.env.VITE_UPLOAD_URL)
  93. const fileList = ref<UploadUserFile[]>([])
  94. const dialogImageUrl = ref('')
  95. const picDialogVisible = ref(false)
  96. // 对话框显示控制
  97. const dialogVisible = computed({
  98. get: () => props.visible,
  99. set: (value) => emit('update:visible', value)
  100. })
  101. const selectLabelArr = computed(() => {
  102. return {
  103. 'school' : ['校园(园区)', '校方关系人'],
  104. 'canteen' : ['校园(园区)', '食堂'],
  105. 'company' : ['餐饮公司', '餐饮公司方关系人'],
  106. }[props.type]
  107. })
  108. // 表单实例
  109. const formRef = ref<FormInstance>()
  110. let defalutValue = {
  111. first_id: null,
  112. second_id: null,
  113. chat_imgs: [],
  114. detail: '',
  115. type: props.type
  116. }
  117. // 表单数据
  118. const formData = reactive<Form.Follow>({...defalutValue})
  119. // 表单验证规则
  120. const rules: FormRules = {
  121. first_id: [
  122. { required: true, message: '请选择' + selectLabelArr.value[0], trigger: 'blur' },
  123. ],
  124. second_id: [
  125. { required: true, message: '请选择' + selectLabelArr.value[1], trigger: 'blur' },
  126. ],
  127. detail: [
  128. { required: true, message: '请填写详情', trigger: 'blur' },
  129. ],
  130. }
  131. const handleRemove: UploadProps['onRemove'] = (uploadFile) => {
  132. let upName = uploadFile.response ? uploadFile.response.data.name : uploadFile.name
  133. commonApi.delImg(upName)
  134. for (let i = 0; i < formData.chat_imgs.length; i++) {
  135. if (formData.chat_imgs[i] === upName) {
  136. formData.chat_imgs.splice(i, 1)
  137. break
  138. }
  139. }
  140. }
  141. const maxFileSizeMB = 3
  142. const beforeUpload: UploadProps['onChange'] = (uploadFile) => {
  143. if (uploadFile.size && uploadFile.size > 1024 * 1024 * maxFileSizeMB) {
  144. ElMessage.error('上传图片大小不能超过2M')
  145. return false
  146. }
  147. if (!uploadFile.type.startsWith('image/')) {
  148. ElMessage.error('只能上传图片文件')
  149. return false
  150. }
  151. return true
  152. }
  153. const handleSuccess = (response:any, uploadFile: UploadFile) => {
  154. if (response.code === 200) {
  155. formData.chat_imgs.push(response.data.name)
  156. ElMessage.success('上传成功!')
  157. } else {
  158. fileList.value = fileList.value.filter((file) => file.name !== uploadFile.name)
  159. ElMessage.error(response.msg)
  160. }
  161. }
  162. const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
  163. dialogImageUrl.value = uploadFile.url!
  164. picDialogVisible.value = true
  165. }
  166. const secondSelectList = computed(() => {
  167. if (formData.first_id) {
  168. let tmp = props.selectList.find(item => item.id === formData.first_id)
  169. if (tmp && tmp.children) {
  170. if (!tmp.children.find(item => item.id === formData.second_id)) {
  171. formData.second_id = null
  172. }
  173. return tmp.children
  174. }
  175. }
  176. formData.second_id = null
  177. return []
  178. })
  179. // 统一监听对话框状态变化
  180. watch(
  181. () => [props.visible, props.type, props.userData],
  182. ([visible]) => {
  183. if (visible) {
  184. formData.first_id = props.first_id || null
  185. formData.second_id = props.second_id || null
  186. }
  187. },
  188. { immediate: true }
  189. )
  190. // 提交表单
  191. const handleSubmit = async () => {
  192. if (!formRef.value) return
  193. await formRef.value.validate((valid) => {
  194. if (valid) {
  195. commonApi.follow(formData).then(() => {
  196. ElMessage.success('提交成功')
  197. Object.assign(formData, defalutValue)
  198. formData.chat_imgs = [];
  199. fileList.value = []
  200. console.log(`%c formData == `, 'background:#41b883 ; padding:1px; color:#fff', formData);
  201. dialogVisible.value = false
  202. emit('submit')
  203. })
  204. }
  205. })
  206. }
  207. </script>