pageOne.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <template>
  2. <view class="page-itemOne">
  3. <u-row justify="space-between" customStyle="margin-bottom: 10px">
  4. <u-col span="3">
  5. <div class="page-itemOne-title">图片资料</div>
  6. </u-col>
  7. <u-col span="3.5">
  8. <u-button size="small" @click="copyAllImages"
  9. style="border-radius: 20rpx;border-color: #007AFF;color: #007AFF;">复制全部图片</u-button>
  10. </u-col>
  11. </u-row>
  12. <!-- 实物图卡片 -->
  13. <view class="card_wrap">
  14. <view class="card-title">实物图</view>
  15. <view class="image-upload-container">
  16. <view class="image-list">
  17. <view class="image-item" v-for="(item, index) in trueUploadList" :key="'truePic-' + index">
  18. <pic-comp :src="item.fileUrl"></pic-comp>
  19. <view class="delete-btn" @click="deleteImage('truePic', item)">×</view>
  20. </view>
  21. <view class="upload-btn" @click="uploadImage('truePic')">
  22. <u-icon name="plus" size="40" color="#999"></u-icon>
  23. </view>
  24. </view>
  25. </view>
  26. </view>
  27. <!-- 聊天记录卡片 -->
  28. <view class="card_wrap">
  29. <view class="card-title">聊天记录</view>
  30. <view class="image-upload-container">
  31. <view class="image-list">
  32. <view class="image-item" v-for="(item, index) in chatRecordsUploadList"
  33. :key="'chatRecords-' + index">
  34. <pic-comp :src="item.fileUrl"></pic-comp>
  35. <view class="delete-btn" @click="deleteImage('chatRecords', item)">×</view>
  36. </view>
  37. <view class="upload-btn" @click="uploadImage('chatRecords')">
  38. <u-icon name="plus" size="40" color="#999"></u-icon>
  39. </view>
  40. </view>
  41. </view>
  42. </view>
  43. <!-- 基本信息卡片 -->
  44. <view class="info-card">
  45. <view class="info-card-title">基本信息</view>
  46. <u-row class="info-row">
  47. <u-col span="6">
  48. <view class="info-label">发单人</view>
  49. <view class="info-value">{{ orderDetail.createNickName || '未填写' }}</view>
  50. </u-col>
  51. <u-col span="6">
  52. <view class="info-label">型号</view>
  53. <view class="info-value">{{ orderDetail.model || '未填写' }}</view>
  54. </u-col>
  55. </u-row>
  56. <u-row class="info-row">
  57. <u-col span="6">
  58. <view class="info-label">上门时间</view>
  59. <view class="info-value">{{ orderDetail.visitTime || '未填写' }}</view>
  60. </u-col>
  61. <u-col span="6">
  62. <view class="info-label">地址</view>
  63. <view class="info-value">{{ orderDetail.address || '未填写' }}</view>
  64. </u-col>
  65. </u-row>
  66. </view>
  67. <!-- 联系方式卡片 -->
  68. <view class="connect">
  69. <view class="connect-card phone-card" @click="handlePhoneClick">
  70. <u-icon name="phone" size="40" color="#07C160" style="margin-bottom: 10rpx;"></u-icon>
  71. <view class="connect-title">电话</view>
  72. <!-- 小红点 -->
  73. <view v-if="orderDetail.phone" class="red-dot"></view>
  74. </view>
  75. <view class="connect-card wechat-card" @click="handleWechatClick">
  76. <u-icon name="chat" size="40" color="#07C160" style="margin-bottom: 10rpx;"></u-icon>
  77. <view class="connect-title">微信</view>
  78. <!-- 小红点 -->
  79. <view v-if="orderDetail.wechat" class="red-dot"></view>
  80. </view>
  81. </view>
  82. <u-button @click="handleNextClick" type="primary" size="middle" style="border-radius: 20rpx;">下一步</u-button>
  83. </view>
  84. </template>
  85. <script>
  86. import picComp from './picComp.vue'
  87. export default {
  88. props: {
  89. orderDetail: {
  90. type: Object,
  91. default: () => { },
  92. },
  93. orderId: {
  94. type: String,
  95. default: '',
  96. }
  97. },
  98. components: {
  99. picComp
  100. },
  101. data() {
  102. return {
  103. //展示的图片列表
  104. trueUploadList: [],
  105. chatRecordsUploadList: [],
  106. // 待绑定的图片列表
  107. bindList: [],
  108. }
  109. },
  110. watch: {
  111. // 监听 props 变化,触发请求
  112. orderDetail: {
  113. handler(newVal) {
  114. if (newVal) { // 确保 props 有值再执行
  115. this.getList('2', '1');
  116. this.getList('2', '2');
  117. }
  118. }
  119. }
  120. },
  121. methods: {
  122. // 选择图片
  123. uploadImage(type) {
  124. uni.chooseImage({
  125. count: 9, // 最多选择9张
  126. sizeType: ['compressed'], // 压缩图片
  127. sourceType: ['album', 'camera'], // 从相册选择或拍照
  128. success: (res) => {
  129. const tempFilePaths = res.tempFilePaths
  130. console.log('上传的图片路径:11', tempFilePaths)
  131. this.uploadToServer(tempFilePaths, type)
  132. },
  133. fail: (err) => {
  134. console.error('选择图片失败:', err)
  135. }
  136. })
  137. },
  138. // 删除图片
  139. deleteImage(type, item) {
  140. uni.showModal({
  141. title: '提示',
  142. content: '确定要删除这张图片吗?',
  143. success: (res) => {
  144. if (res.confirm) {
  145. // 调接口删除
  146. console.log('现在要删除的文件文件是:', type, item.fileUrl, item.id)
  147. this.deleteImg(item.id)
  148. this.getList('2', '1');
  149. this.getList('2', '2');
  150. }
  151. }
  152. })
  153. },
  154. // 删除图片
  155. async deleteImg(id) {
  156. try {
  157. await uni.$u.api.deleteClueFile([id])
  158. uni.showToast({
  159. title: '删除成功',
  160. icon: 'success',
  161. duration: 2000
  162. })
  163. } catch (error) {
  164. uni.showToast({
  165. title: '删除失败',
  166. icon: 'error',
  167. duration: 2000
  168. })
  169. }
  170. },
  171. // 上传到服务
  172. async uploadToServer(filePaths, type) {
  173. // 实际的上传逻辑
  174. try {
  175. //实物图的话就是2,聊天记录的话就是1
  176. let p = type == 'truePic' ? '2' : type == 'chatRecords' ? '1' : ''
  177. console.log('当前上传的图片类型是', p)
  178. const res = await Promise.all(filePaths.map(filePath => this.uploadFile(filePath, p)));
  179. // 绑定
  180. this.bindOrder(type, p);
  181. // 实物图的话传2
  182. if (type == 'truePic') {
  183. // this.bindOrder('2', '2');
  184. this.getList('2', '2');
  185. }
  186. // 实物图的话聊天记录的话传1
  187. if (type == 'chatRecords') {
  188. // 实物图的话聊天记录的话传1
  189. // this.bindOrder('2', '1');
  190. this.getList('2', '1');
  191. }
  192. } catch (error) {
  193. console.error('上传失败:', error);
  194. uni.$u.toast('上传失败');
  195. }
  196. },
  197. //绑定订单
  198. async bindOrder(type, orderFileType) {
  199. const res = await uni.$u.api.saveClueFile({
  200. clueId: this.orderDetail.clueId,//线索id
  201. list: this.bindList,
  202. sourceId: this.orderId,//订单id,sendformid
  203. type: type,
  204. orderFileType: orderFileType
  205. });
  206. uni.$u.toast("上传成功");
  207. uni.hideLoading();
  208. // 清空待绑定的图片列表
  209. this.bindList = [];
  210. },
  211. // 上传文件
  212. async uploadFile(fileUrl, orderFileType) {
  213. try {
  214. uni.showLoading({
  215. title: '上传中...',
  216. mask: true
  217. });
  218. console.log(111, fileUrl)
  219. // 调用统一的上传接口
  220. const { data } = await uni.$u.api.uploadFile(fileUrl);
  221. const fileObj = {
  222. fileSize: data.fileSize,
  223. fileSuffix: data.fileSuffix,
  224. fileName: data.name,
  225. fileUrl: data.url,
  226. orderFileType: orderFileType
  227. };
  228. if (orderFileType == '2') {
  229. // this.trueUploadList.push(fileObj);
  230. } else if (orderFileType == '1') {
  231. // this.chatRecordsUploadList.push(fileObj);
  232. }
  233. this.bindList.push(fileObj);
  234. } catch (error) {
  235. uni.hideLoading();
  236. console.error('文件上传失败:', error);
  237. uni.$u.toast('上传失败,请重试');
  238. }
  239. },
  240. // 电话卡片点击事件
  241. handlePhoneClick() {
  242. console.log('电话卡片被点击', '电话号码:', this.orderDetail.phone)
  243. if (this.orderDetail.phone) {
  244. //拨打电话
  245. uni.makePhoneCall({
  246. phoneNumber: this.orderDetail.phone,
  247. success: () => {
  248. this.$store.commit("call/SET_FORM", {
  249. clueId: this.orderDetail.clueId,
  250. type: "3",
  251. callee: this.orderDetail.phone,
  252. });
  253. },
  254. });
  255. } else {
  256. uni.showToast({
  257. title: '该订单暂时没有电话号码',
  258. icon: 'none'
  259. })
  260. }
  261. },
  262. // 微信卡片点击事件
  263. handleWechatClick() {
  264. console.log('微信卡片被点击', '微信号:', this.orderDetail.wechat)
  265. if (this.orderDetail.wechat) {
  266. //复制微信号
  267. uni.setClipboardData({
  268. data: this.orderDetail.wechat,
  269. success: () => {
  270. uni.showToast({
  271. title: '微信号已复制',
  272. icon: 'none'
  273. })
  274. }
  275. })
  276. } else {
  277. uni.showToast({
  278. title: '该订单暂时没有微信号',
  279. icon: 'none'
  280. })
  281. }
  282. },
  283. // 下一步
  284. handleNextClick() {
  285. // 校验表单
  286. if (!this.form.truePic.length) {
  287. uni.showToast({
  288. title: '请上传实物图',
  289. icon: 'none'
  290. })
  291. return
  292. }
  293. if (!this.form.chatRecords.length) {
  294. uni.showToast({
  295. title: '请上传聊天记录',
  296. icon: 'none'
  297. })
  298. return
  299. }
  300. this.$emit('handleNextClick', {
  301. nowPage: 'formOne',
  302. form: this.form,
  303. })
  304. },
  305. // 获取文件列表
  306. async getList(type, orderFileType) {
  307. console.log('获取文件列表', type, orderFileType)
  308. try {
  309. const params = {
  310. clueId: this.orderDetail.clueId,
  311. sourceId: this.orderId,
  312. type,
  313. orderFileType,
  314. isDuplicate: '1',//先传1
  315. pageNum: 1,
  316. pageSize: 1000 // 设置一个较大的值以获取所有数据
  317. }
  318. const response = await uni.$u.api.selectClueFileByDto(params)
  319. if (orderFileType == '1') {
  320. this.trueUploadList = response.rows || []
  321. } else if (orderFileType == '2') {
  322. this.chatRecordsUploadList = response.rows || []
  323. }
  324. } catch (error) {
  325. uni.$u.toast(`获取列表失败:${error.message}`)
  326. this.trueUploadList = []
  327. this.chatRecordsUploadList = []
  328. }
  329. },
  330. //一键复制
  331. copyAllImages() {
  332. // 合并所有图片
  333. const allImages = [...this.trueUploadList, ...this.chatRecordsUploadList];
  334. //取出所有图的url
  335. const allUrls = allImages.map(item => item.fileUrl);
  336. console.log('所有图片:', allUrls)
  337. console.log('合并后的图片列表:', allUrls)
  338. if (allUrls.length > 0) {
  339. // 复制到剪贴板
  340. uni.setClipboardData({
  341. data: JSON.stringify(allUrls),
  342. success: () => {
  343. uni.showToast({
  344. title: '所有图片已复制',
  345. icon: 'none'
  346. })
  347. }
  348. })
  349. } else {
  350. uni.showToast({
  351. title: '没有图片可复制',
  352. icon: 'none'
  353. })
  354. }
  355. },
  356. },
  357. }
  358. </script>
  359. <style scoped lang="scss">
  360. // 导入公共样式
  361. @import './common.scss';
  362. // 主样式
  363. .page-itemOne {
  364. @extend .page-container;
  365. }
  366. .page-itemOne-title {
  367. @include font-styles($size: title, $weight: bold, $color: primary);
  368. }
  369. .page-itemOne-form {
  370. @include font-styles($size: tiny, $weight: semi-bold, $color: secondary);
  371. text-wrap: nowrap;
  372. }
  373. .image-upload-container {
  374. padding: map-get($sizes, padding-sm) map-get($sizes, padding);
  375. }
  376. .image-list {
  377. display: flex;
  378. flex-wrap: wrap;
  379. gap: 20rpx;
  380. }
  381. .image-item {
  382. position: relative;
  383. width: 200rpx;
  384. height: 200rpx;
  385. box-sizing: border-box;
  386. }
  387. .delete-btn {
  388. position: absolute;
  389. top: -10rpx;
  390. right: -10rpx;
  391. width: 40rpx;
  392. height: 40rpx;
  393. background-color: #ff4d4f;
  394. color: #fff;
  395. border-radius: 50%;
  396. display: flex;
  397. align-items: center;
  398. justify-content: center;
  399. @include font-styles($size: tiny, $weight: bold);
  400. z-index: 10;
  401. }
  402. .upload-btn {
  403. width: 200rpx;
  404. height: 200rpx;
  405. border: 8rpx dashed #ddd;
  406. border-radius: 30rpx;
  407. display: flex;
  408. align-items: center;
  409. justify-content: center;
  410. background-color: #f9f9f9;
  411. box-sizing: border-box;
  412. }
  413. /* 基本信息卡片样式 */
  414. .info-card {
  415. @include card;
  416. margin-top: 20rpx;
  417. margin-bottom: 20rpx;
  418. padding: map-get($sizes, padding-sm) map-get($sizes, padding);
  419. &:hover {
  420. @include shadow(2);
  421. }
  422. }
  423. .info-card-title {
  424. @include font-styles($size: title, $weight: bold, $color: primary);
  425. margin-bottom: 25rpx;
  426. padding-bottom: 15rpx;
  427. border-bottom: 1rpx solid map-get($colors, border);
  428. }
  429. .info-row {
  430. margin-bottom: 20rpx;
  431. }
  432. .info-label {
  433. @include font-styles($size: tiny, $weight: regular, $color: tertiary);
  434. margin-bottom: 8rpx;
  435. }
  436. .info-value {
  437. @include font-styles($size: small, $weight: regular, $color: secondary, $line-height: small);
  438. word-break: break-all;
  439. }
  440. /* 联系方式卡片样式 */
  441. .connect {
  442. display: flex;
  443. justify-content: space-between;
  444. margin: 20rpx 0;
  445. gap: 20rpx;
  446. }
  447. .connect-card {
  448. flex: 1;
  449. @include card;
  450. padding: 30rpx;
  451. display: flex;
  452. flex-direction: column;
  453. align-items: center;
  454. box-sizing: border-box;
  455. position: relative;
  456. &:hover {
  457. @include shadow(2);
  458. }
  459. }
  460. .connect-title {
  461. @include font-styles($size: tiny, $weight: regular, $color: tertiary);
  462. margin-bottom: 8rpx;
  463. }
  464. .connect-value {
  465. @include font-styles($size: small, $weight: medium, $color: secondary);
  466. }
  467. /* 小红点样式 */
  468. .red-dot {
  469. position: absolute;
  470. top: 15rpx;
  471. right: 15rpx;
  472. width: 25rpx;
  473. height: 25rpx;
  474. background-color: #ff4d4f;
  475. border-radius: 50%;
  476. box-shadow: 0 0 4rpx rgba(255, 77, 79, 0.3);
  477. }
  478. </style>