index.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. <template>
  2. <view class="oder_form_wrap">
  3. <u-navbar placeholder :autoBack="true" title="发单表单" @rightClick="handleNavSaveClick">
  4. <view class="u-nav-slot" slot="right">
  5. 保存
  6. </view>
  7. </u-navbar>
  8. <view class="form_wrap">
  9. <u--form labelPosition="left" labelWidth="100" :model="form" :rules="rules" ref="form" class="form_wrap"
  10. :errorType="'toast'">
  11. <u-form-item label="省市区" borderBottom>
  12. <pick-regions :defaultRegion="defaultRegion" @getRegion="handleGetRegion">
  13. <view class="region-picker">
  14. <template v-if="form.province">
  15. <u--input :value="form.province + '/' + form.city + '/' + form.area" placeholder="点击选择"
  16. readonly suffixIcon="arrow-right" suffixIconStyle="color : #c0c4cc"></u--input>
  17. </template>
  18. <template v-else>
  19. <u--input placeholder="点击选择" readonly suffixIcon="arrow-right"
  20. suffixIconStyle="color : #c0c4cc"></u--input>
  21. </template>
  22. </view>
  23. </pick-regions>
  24. </u-form-item>
  25. <u-form-item label="详细地址" prop="address" borderBottom>
  26. <u--textarea v-model="form.address" placeholder="请输入详细地址" count confirmType="done"></u--textarea>
  27. </u-form-item>
  28. <u-form-item label="上门时间" prop="visitTime" borderBottom>
  29. <date-time-picker v-model="form.visitTime" :value-format="'YYYY-MM-DD HH:mm:ss'" :type="'datetime'">
  30. </date-time-picker>
  31. </u-form-item>
  32. <u-form-item label="类型" prop="category" borderBottom>
  33. <ld-select :list="categoryDict" label-key="dictLabel" value-key="dictValue" placeholder="请选择类型"
  34. v-model="form.category" :border="false"></ld-select>
  35. <u-icon slot="right" name="arrow-right"></u-icon>
  36. </u-form-item>
  37. <u-form-item label="物品品牌" prop="brand" borderBottom>
  38. <ld-select
  39. :list="brandDict"
  40. label-key="dictLabel"
  41. value-key="dictValue"
  42. placeholder="请选择物品品牌"
  43. v-model="form.brand"
  44. :border="false"
  45. ></ld-select>
  46. <u-icon slot="right" name="arrow-right"></u-icon>
  47. </u-form-item>
  48. <u-form-item label="价格范围" prop="priceRange" borderBottom>
  49. <u--input v-model="form.priceRange" placeholder="请输入价格范围" border="none"></u--input>
  50. </u-form-item>
  51. <u-form-item label="战术选择" prop="tactic" borderBottom>
  52. <ld-select :list="tacticDict" label-key="dictLabel" value-key="dictValue" placeholder="请选择战术"
  53. v-model="form.tactic" :border="false"></ld-select>
  54. <u-icon slot="right" name="arrow-right"></u-icon>
  55. </u-form-item>
  56. <u-form-item label="补充说明" prop="remarks" borderBottom>
  57. <u--textarea v-model="form.remarks" placeholder="请输入补充说明" count confirmType="done"></u--textarea>
  58. </u-form-item>
  59. </u--form>
  60. </view>
  61. <!-- 文件上传区域 -->
  62. <view class="upload_area">
  63. <!-- 聊天记录附件 -->
  64. <order-file-upload title="聊天记录附件" orderFileType="1" :file-list="form.chatAttachmentList"
  65. @update:fileList="updateChatFiles"
  66. tip-text="上传聊天截图、录音等文件"></order-file-upload>
  67. <!-- 报价附件 -->
  68. <order-file-upload title="报价附件" orderFileType="2" :file-list="form.quoteAttachmentList"
  69. @update:fileList="updateQuoteFiles"
  70. tip-text="上传报价附件"></order-file-upload>
  71. <!-- 高清图附件 -->
  72. <order-file-upload title="高清图附件" orderFileType="3" :file-list="form.hdImageAttachmentList"
  73. @update:fileList="updateHdImageFiles"
  74. tip-text="上传物品高清图片"></order-file-upload>
  75. <!-- 其他附件 -->
  76. <order-file-upload title="其他附件" orderFileType="4" :file-list="form.otherAttachmentList"
  77. @update:fileList="updateOtherFiles"
  78. tip-text="上传其他相关文件"></order-file-upload>
  79. </view>
  80. </view>
  81. </template>
  82. <script>
  83. import orderFileUpload from '@/components/order-file-upload/order-file-upload.vue'
  84. import dateTimePicker from "@/components/dateTimePicker/dateTimePicker.vue"
  85. import ldSelect from "@/components/ld-select/ld-select.vue"
  86. export default {
  87. components: {
  88. orderFileUpload,
  89. dateTimePicker,
  90. ldSelect
  91. },
  92. data() {
  93. return {
  94. defaultRegion: ['广东省', '广州市', '番禺区'],
  95. categoryDict: [],
  96. tacticDict: [],
  97. brandDict: [],
  98. form: {
  99. clueId: '',
  100. sendDate: '',
  101. website: '',
  102. item: '',
  103. phone: '',
  104. address: '',
  105. visitTime: '',
  106. remarks: '',
  107. category: '',
  108. brand: '',
  109. priceRange: '',
  110. tactic: '',
  111. // 地区信息
  112. province: '',
  113. city: '',
  114. area: '',
  115. // 附件列表
  116. chatAttachmentList: [], // 聊天记录附件
  117. quoteAttachmentList: [], // 报价附件
  118. hdImageAttachmentList: [], // 高清图附件
  119. otherAttachmentList: [] // 其他附件
  120. },
  121. rules: {
  122. sendDate: {
  123. type: 'string',
  124. required: true,
  125. message: '请输入发单日期',
  126. trigger: ['blur', 'change']
  127. },
  128. website: {
  129. type: 'url',
  130. message: '请输入正确的网址格式',
  131. trigger: ['blur', 'change']
  132. },
  133. item: {
  134. type: 'string',
  135. required: true,
  136. message: '请输入物品描述',
  137. trigger: ['blur', 'change']
  138. },
  139. phone: {
  140. type: 'string',
  141. required: true,
  142. message: '请输入联系电话',
  143. trigger: ['blur', 'change']
  144. },
  145. address: {
  146. type: 'string',
  147. required: true,
  148. message: '请输入详细地址',
  149. trigger: ['blur', 'change']
  150. },
  151. visitTime: {
  152. type: 'string',
  153. required: true,
  154. message: '请输入上门时间',
  155. trigger: ['blur', 'change']
  156. },
  157. category: {
  158. type: 'string',
  159. required: true,
  160. message: '请选择类型',
  161. trigger: ['blur', 'change']
  162. },
  163. brand: {
  164. type: 'string',
  165. required: true,
  166. message: '请选择物品品牌',
  167. trigger: ['blur', 'change']
  168. },
  169. tactic: {
  170. type: 'string',
  171. required: true,
  172. message: '请选择战术',
  173. trigger: ['blur', 'change']
  174. }
  175. }
  176. }
  177. },
  178. methods: {
  179. // 获取地区选择
  180. handleGetRegion(region) {
  181. const [provinceData, cityData, areaData] = region;
  182. this.form.province = provinceData.name;
  183. this.form.city = cityData.name;
  184. this.form.area = areaData.name;
  185. // 只在详细地址为空时自动填充省市区
  186. if (!this.form.address || this.form.address.trim() === '') {
  187. this.form.address = this.form.province + this.form.city + this.form.area;
  188. }
  189. },
  190. // 更新各类附件
  191. updateChatFiles(fileList) {
  192. this.form.chatAttachmentList = fileList;
  193. },
  194. updateQuoteFiles(fileList) {
  195. this.form.quoteAttachmentList = fileList;
  196. },
  197. updateHdImageFiles(fileList) {
  198. this.form.hdImageAttachmentList = fileList;
  199. },
  200. updateOtherFiles(fileList) {
  201. this.form.otherAttachmentList = fileList;
  202. },
  203. // 文件变化处理
  204. handleFileChange(data) {
  205. console.log('文件上传变化:', data);
  206. },
  207. // 获取字典数据
  208. async getDicts() {
  209. try {
  210. const [categoryRes, tacticRes, brandRes] = await Promise.all([
  211. this.$getDicts('crm_form_category'),
  212. this.$getDicts('crm_form_tactic'),
  213. this.$getDicts('crm_form_brand')
  214. ]);
  215. this.categoryDict = categoryRes;
  216. this.tacticDict = tacticRes;
  217. this.brandDict = brandRes;
  218. } catch (error) {
  219. console.error('获取字典数据失败:', error);
  220. }
  221. },
  222. // 处理保存
  223. async handleNavSaveClick() {
  224. try {
  225. // 表单验证
  226. await this.$refs.form.validate();
  227. // 合并所有附件
  228. const allAttachments = [
  229. ...this.form.chatAttachmentList,
  230. ...this.form.quoteAttachmentList,
  231. ...this.form.hdImageAttachmentList,
  232. ...this.form.otherAttachmentList
  233. ];
  234. // 准备提交数据
  235. const submitData = {
  236. ...this.form,
  237. uploadList: allAttachments
  238. };
  239. // 调用保存接口
  240. await uni.$u.api.saveClueOrderForm(submitData);
  241. uni.$u.toast('发单记录添加成功');
  242. // 延迟返回
  243. setTimeout(() => {
  244. uni.navigateBack();
  245. }, 1500);
  246. } catch (error) {
  247. console.error('保存失败:', error);
  248. if (error.message) {
  249. uni.$u.toast(error.message);
  250. }
  251. }
  252. }
  253. },
  254. onLoad(option) {
  255. const clueId = option.clueId;
  256. this.form.clueId = clueId;
  257. this.getDicts();
  258. }
  259. }
  260. </script>
  261. <style lang="scss" scoped>
  262. .oder_form_wrap {
  263. background-color: #f5f5f5;
  264. min-height: 100vh;
  265. padding-bottom: 100rpx;
  266. padding-top: 10px;
  267. }
  268. .form_wrap {
  269. background-color: #fff;
  270. border-radius: 16rpx;
  271. overflow: hidden;
  272. }
  273. .upload_area {
  274. padding: 0 20rpx;
  275. margin: 20rpx 0;
  276. }
  277. .bottom_btn {
  278. position: fixed;
  279. bottom: 0;
  280. left: 0;
  281. right: 0;
  282. padding: 20rpx;
  283. background: #fff;
  284. box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1);
  285. }
  286. .region-picker {
  287. width: 100%;
  288. }
  289. ::v-deep .u-form-item__body {
  290. padding: 20rpx 40rpx;
  291. }
  292. ::v-deep .u-form-item {
  293. border-bottom: 1rpx solid #f5f5f5;
  294. }
  295. ::v-deep .u-form-item:last-child {
  296. border-bottom: none;
  297. }
  298. </style>