pagereceivecenter.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. <script>
  2. // import orderCard from "./compounts/orderCard.vue";
  3. // status 状态 1 发单(刚发出来) 2 接单(处理中) 3 收单(入库了) 4 未收(没有收到)
  4. export default {
  5. components: {
  6. // orderCard,
  7. },
  8. data() {
  9. return {
  10. orderList: [],
  11. page: {
  12. pageSize: 10,
  13. pageNum: 1,
  14. total: 0
  15. },
  16. tagModalVisible: false,
  17. tagList: [],
  18. currentTags: [],
  19. currentOrder: {},
  20. followUpModelShow: false,
  21. followUpNotes: '',
  22. countdown: 300,
  23. countdownIntervals: null,
  24. //筛选条件
  25. filterList: [
  26. { name: '全部列表', type: 1 },
  27. { name: '我的接发单', type: 2 }
  28. ],
  29. statisticsSendStatus: [],//中间统计数据
  30. activeType: 1,//当前选择的筛选类型,顶部tab的类型
  31. activeStatus: '',//当前选择的状态,统计数据的类型
  32. currentFollowUp: [],//当前订单的跟进记录
  33. showMoreFollowUp: false
  34. }
  35. },
  36. onLoad() {
  37. //初始调用
  38. this.getOrderList();
  39. this.getStatisticsSendStatus();
  40. this.countdownInterval()
  41. // uni.navigateTo({
  42. // url: `/pages/orderDetailNew/index?orderId=5464&item=测试发单&type=undefined&clueId=1973381744953516033`,
  43. // })
  44. },
  45. onUnload() {
  46. clearInterval(this.countdownInterval);
  47. },
  48. watch: {
  49. countdown: {
  50. handler(newVal, oldVal) {
  51. if (newVal <= 0) {
  52. this.orderList.forEach(order => {
  53. if (order.status == 1) {
  54. this.handleBtnClick('isBusy', order)
  55. }
  56. })
  57. clearInterval(this.countdownInterval);
  58. }
  59. },
  60. immediate: true
  61. }
  62. },
  63. methods: {
  64. countdownInterval() {
  65. this.countdownInterval = setInterval(() => {
  66. this.countdown--
  67. }, 1000);
  68. },
  69. //获取列表数据
  70. async getOrderList() {
  71. try {
  72. const result = await uni.$u.api.selectClueOrderFormList({
  73. pageSize: this.page.pageSize,
  74. pageNum: this.page.pageNum,
  75. }, {
  76. type: this.activeType,
  77. status: this.activeStatus,
  78. });
  79. console.log('接单列表', result);
  80. // 把数组按照status的大小排序,从小到大
  81. result.rows.sort((a, b) => {
  82. return a.status - b.status;
  83. // return b.status - a.status;
  84. })
  85. this.orderList.push(...result.rows);
  86. this.page.total = result.total;
  87. } catch (error) {
  88. console.error('接单列表接口调用失败:', error);
  89. // 添加用户友好的错误提示
  90. uni.$u.toast('获取订单列表失败,请稍后重试');
  91. }
  92. },
  93. //获取统计数据
  94. async getStatisticsSendStatus() {
  95. const { data } = await uni.$u.api.statisticsSendStatus({ type: this.activeType });
  96. // console.log('统计数据是', data)
  97. this.statisticsSendStatus = data;
  98. },
  99. // 处理按钮点击事件
  100. async handleBtnClick(btnType, order) {
  101. if (btnType == 'acceptOrder') {
  102. //去接单
  103. console.log('去接单', order)
  104. //打开模态窗二次确认,确认后跳转接单form
  105. uni.showModal({
  106. title: '确认接单',
  107. content: `是否确认接单订单:${order.item}?`,
  108. success: async (res) => {
  109. if (res.confirm) {
  110. await uni.$u.api.oderForm({
  111. status: "2",
  112. id: order.id,
  113. });
  114. uni.navigateTo({
  115. url: `/pages/orderDetailNew/index?orderId=${order.id}&item=${order.item}&type=${this.type}&clueId=${order.clueId}`,
  116. })
  117. } else if (res.cancel) {
  118. // 用户点击了取消,不执行任何操作
  119. uni.$u.toast('已取消接单');
  120. }
  121. }
  122. })
  123. } else if (btnType == 'isBusy') {
  124. //在忙
  125. console.log('在忙', order)
  126. //当前订单移动到末尾
  127. this.orderList.push(this.orderList.splice(this.orderList.indexOf(order), 1)[0]);
  128. } else if (btnType == 'willFollow') {
  129. //待跟进
  130. console.log('待跟进', order)
  131. //打开模态窗
  132. this.followUpModelShow = true;
  133. this.currentOrder = order
  134. } else if (btnType == 'tag') {
  135. //打标签
  136. console.log('打标签', order)
  137. //打开模态窗
  138. this.tagModalVisible = true;
  139. this.getAllTags();
  140. this.currentTags = order.tags.map(tag => tag.id);
  141. this.currentOrder = order
  142. } else if (btnType == 'share') {
  143. //一键分享
  144. console.log('一键分享', order)
  145. } else if (btnType == 'oneFollow') {
  146. //待跟进
  147. console.log('待跟进', order)
  148. this.followUpModelShow = true;
  149. this.currentOrder = order
  150. }
  151. },
  152. // 跳转订单详情
  153. toOrderDetail(order) {
  154. //点卡片看详情
  155. // if (order.status == '1' || order.status == '2') {
  156. uni.navigateTo({
  157. url: `/pages/orderDetailNew/index?orderId=${order.id}&item=${order.item}&type=${this.type}&clueId=${order.clueId}`,
  158. })
  159. // } else {
  160. // uni.$u.toast('当前订单无法查看详情');
  161. // return;
  162. // }
  163. },
  164. //滑动加载
  165. scrolltolower() {
  166. // console.log('到底了');
  167. if (this.orderList.length >= this.page.total) {
  168. //到底了,没有更多
  169. } else {
  170. this.page.pageNum++;
  171. this.getOrderList();
  172. }
  173. },
  174. //获取全部标签
  175. async getAllTags() {
  176. const res = await uni.$u.api.getClueTagGroupVoList({ tagGroupApplication: '2' })
  177. console.log('全部标签', res.data[0].clueTagDataList)
  178. this.tagList = res.data[0].clueTagDataList;
  179. },
  180. cancelTag() {
  181. this.tagModalVisible = false;
  182. },
  183. async confirmTag() {
  184. console.log('确认打标签', this.currentTags)
  185. // 这里可以添加打标签的逻辑
  186. const allTags = this.currentTags.map(tag => tag).join(',');
  187. console.log('allTags', allTags)
  188. await uni.$u.api.updateTags({
  189. id: this.currentOrder.id,
  190. allTags: allTags,
  191. })
  192. this.tagModalVisible = false;
  193. uni.$u.toast('标签更新成功');
  194. //更新当前订单的标签
  195. this.currentOrder.tags = this.tagList.filter(tag => this.currentTags.includes(tag.id));
  196. },
  197. // 确认跟进细节按钮点击事件
  198. async confirmFollowUp() {
  199. console.log('确认跟进细节:', this.followUpNotes);
  200. this.followUpModelShow = false;
  201. // 可以在这里添加提交跟进细节的逻辑
  202. // 未收的时候,提交一个跟进记录 待跟进_内容
  203. const res = await uni.$u.api.addOrderFollow({
  204. orderId: this.currentOrder.id,
  205. content: `待跟进_${this.followUpNotes}`,
  206. })
  207. if (res.code == 200) {
  208. uni.$u.toast('提交待跟进记录成功');
  209. }
  210. this.followUpNotes = '';
  211. },
  212. // 切换筛选条件
  213. async changeFilter(param) {
  214. this.activeType = param.type;
  215. this.page.pageNum = 1;
  216. this.orderList = [];
  217. this.getOrderList();
  218. this.getStatisticsSendStatus()
  219. },
  220. //切换统计数据的类型
  221. changeStatus(param) {
  222. if (param == this.activeStatus) {
  223. //如果当前点击的状态和当前选中的状态相同,则取消选中
  224. this.activeStatus = '';
  225. this.page.pageNum = 1;
  226. this.orderList = [];
  227. this.getOrderList();
  228. } else {
  229. //如果当前点击的状态和当前选中的状态不同,则切换选中状态
  230. this.activeStatus = param;
  231. this.page.pageNum = 1;
  232. this.orderList = [];
  233. this.getOrderList();
  234. }
  235. },
  236. //点击查看更多的跟进
  237. async handleShowMoreFollowUp() {
  238. //当前的order是
  239. console.log()
  240. const { data } = await uni.$u.api.getDuplicateOrderFollowListByClueId({
  241. clueId: this.currentOrder.clueId
  242. });
  243. console.log('这里是跟进', data)
  244. const allData = []
  245. for (const key in data) {
  246. allData.push(...data[key])
  247. }
  248. const filterData = allData.filter(item => {
  249. console.log('过滤', item)
  250. //过滤出来tem.content不包括联系师傅、师傅拍图技巧、到达客户面对面、未收评分、待跟进_
  251. return item.content.indexOf('联系师傅') == -1 && item.content.indexOf('师傅拍图技巧') == -1 && item.content.indexOf('到达客户面对面') == -1 && item.content.indexOf('未收评分') == -1 && item.content.indexOf('待跟进_') == -1
  252. })
  253. console.log('筛选后的跟进', filterData)
  254. this.currentFollowUp = filterData || [];
  255. this.showMoreFollowUp = true
  256. }
  257. }
  258. }
  259. </script>
  260. <template>
  261. <view class="container">
  262. <u-navbar title="接单中心" :autoBack="true" :placeholder="true" v-hideNav></u-navbar>
  263. <!-- 筛选条件 -->
  264. <u-tabs :list="filterList" @click="changeFilter"></u-tabs>
  265. <!-- 统计数据 -->
  266. <scroll-view scroll-x class="statusScrollView" style="width: 100%;">
  267. <view class="statisticsContainer">
  268. <view v-for="item in statisticsSendStatus" :key="item.status" @click="changeStatus(item.status)"
  269. class="statisticsItem" :class="{ 'activeStatusClass': item.status == activeStatus }">
  270. <view>{{ item.statusName }}</view>
  271. <view>({{ item.count || 0 }})</view>
  272. </view>
  273. </view>
  274. </scroll-view>
  275. <view class="scrollViewContainer">
  276. <scroll-view class="scrollView" scroll-y @scrolltolower="scrolltolower">
  277. <transition-group name="order-move" tag="div">
  278. <!-- <orderCard v-for="item in orderList" :key="item.receiptId + item.id" :order="item"
  279. @handleBtnClick="handleBtnClick">
  280. </orderCard> -->
  281. <view class="orderCard" v-for="item in orderList" :key="item.receiptId + item.id"
  282. @click.stop="toOrderDetail(item)">
  283. <view class="bandAndPrice">
  284. <view class="bandName">{{ item.itemBrand || '暂无品牌' }}</view>
  285. <view class="price">¥{{ item.priceRange || '?' }}</view>
  286. </view>
  287. <view class="mainLind">
  288. <!-- <view class="mainLindImg">
  289. <image :src="'/static/acceptOrder/orderCardPic.jpg'" v-if="item.src" />
  290. </view> -->
  291. <view class="itemName">{{ item.item || '暂无项目' }}</view>
  292. <view class="mainLindInfo">
  293. <view class="infoItem">
  294. <view class="infoItemTitle">发单人:</view>
  295. <view>{{ item.createNickName || '未知' }}</view>
  296. </view>
  297. <view class="infoItem">
  298. <view class="infoItemTitle">机构:</view>
  299. <view>{{ item.orgName || '暂无机构' }}</view>
  300. </view>
  301. <view class="infoItem">
  302. <view class="infoItemTitle">电话:</view>
  303. <view>{{ item.phone || '暂无电话' }}</view>
  304. </view>
  305. <view class="infoItem">
  306. <view class="infoItemTitle">接单人:</view>
  307. <view>{{ item.identificationName || '暂无所属人' }}</view>
  308. </view>
  309. <view class="infoItem">
  310. <view class="infoItemTitle">运营人:</view>
  311. <view>{{ item.clueOperationName || '暂无运营人' }}</view>
  312. </view>
  313. <view class="infoItem">
  314. <view class="infoItemTitle">发单日期:</view>
  315. <view>{{ item.sendDate || '暂无时间' }}</view>
  316. </view>
  317. </view>
  318. </view>
  319. <view class="tags">
  320. <view class="tag" v-for="(tag, index) in item.tags" :key="index"
  321. :style="{ backgroundColor: tag.color, opacity: 0.8 }">
  322. {{ tag.name }}</view>
  323. </view>
  324. <view class="Btns">
  325. <!-- status 状态 1 发单(刚发出来) 2 接单(处理中) 3 收单(入库了) 4 未收(没有收到) -->
  326. <view class="btnGroup" v-if="item && (item.status == '1')">
  327. <view class="card-button" @click.stop="handleBtnClick('acceptOrder', item)">立即接单</view>
  328. <view class=" card-button isBusy" @click.stop="handleBtnClick('isBusy', item)">
  329. <view>
  330. 在忙
  331. </view>
  332. <view v-if="countdown > 0">
  333. ({{ countdown }} s)
  334. </view>
  335. </view>
  336. </view>
  337. <view class="btnGroup" v-if="item && (item.status == '2')">
  338. <view class="card-button willFollow" @click.stop="handleBtnClick('willFollow', item)">
  339. 待跟进
  340. </view>
  341. <view class="card-button isBusy" @click.stop="handleBtnClick('tag', item)">打标签</view>
  342. </view>
  343. <!-- <view class="btnGroup" v-if="item && (item.status == '3')">
  344. <view class="card-button share" @click.stop="handleBtnClick('share', item)">一键分享</view>
  345. </view> -->
  346. <view class="btnGroup" v-if="item && (item.status == '4')">
  347. <view class="card-button oneFollow" @click.stop="handleBtnClick('oneFollow', item)">待跟进
  348. </view>
  349. </view>
  350. </view>
  351. </view>
  352. </transition-group>
  353. <view class="hasMore">
  354. {{ orderList.length >= page.total ? '没有更多了~' : '向下滑动加载更多~' }}
  355. </view>
  356. </scroll-view>
  357. </view>
  358. <!-- 打标签模态窗 -->
  359. <u-modal showCancelButton :show="tagModalVisible" title="选择标签" @confirm="confirmTag" @cancel="cancelTag">
  360. <view class="slot-content">
  361. <u-checkbox-group class="tagCheckboxGroup" v-model="currentTags" placement="column">
  362. <u-checkbox :customStyle="{ marginBottom: '8px' }" v-for="(item, index) in tagList" :key="item.id"
  363. :label="item.name" :name="item.id">
  364. </u-checkbox>
  365. </u-checkbox-group>
  366. </view>
  367. </u-modal>
  368. <u-modal showCancelButton :show="followUpModelShow" :title="'填写跟进细节'" @confirm="confirmFollowUp"
  369. @cancel="followUpModelShow = false">
  370. <view class="modal-content">
  371. <u--textarea v-model="followUpNotes" placeholder="请输入情况" confirm-type="done"
  372. style="width: 400rpx;margin-bottom: 10rpx; "></u--textarea>
  373. <u-button type="primary" @click="handleShowMoreFollowUp">点击查看更多跟进</u-button>
  374. </view>
  375. </u-modal>
  376. <!-- 更多跟进 -->
  377. <u-modal :show="showMoreFollowUp" title="详细跟进记录" @confirm="showMoreFollowUp = false">
  378. <!-- <view class="followUpBox"> -->
  379. <scroll-view class="followUpBox" scroll-y>
  380. <view v-for="value in currentFollowUp" :key="value.id" class="followUpItem">
  381. <view class="followUpInfo">
  382. <view class="followUpNickname">
  383. 账号:{{ value.createNickname }}
  384. </view>
  385. <view class="followUpOrgName">{{ value.orgName }}</view>
  386. </view>
  387. <view class="followUpContent">{{ value.content }}</view>
  388. </view>
  389. </scroll-view>
  390. <!-- </view> -->
  391. </u-modal>
  392. </view>
  393. </template>
  394. <style scoped lang="scss">
  395. .hasMore {
  396. text-align: center;
  397. padding: 20rpx 0;
  398. font-size: 24rpx;
  399. color: #999;
  400. }
  401. .scrollViewContainer {
  402. height: calc(100vh - 44px - 44px - 27px - 10rpx);
  403. }
  404. .followUpScroll {
  405. height: 600rpx;
  406. }
  407. .scrollView {
  408. height: 100%;
  409. }
  410. /* 订单移动动画 */
  411. .order-move-enter-active,
  412. .order-move-leave-active {
  413. transition: all 0.5s ease;
  414. }
  415. .order-move-enter-from,
  416. .order-move-leave-to {
  417. opacity: 0;
  418. transform: translateY(30px);
  419. }
  420. .order-move-move {
  421. transition: transform 0.5s ease;
  422. }
  423. /* 订单卡片主容器 */
  424. .orderCard {
  425. box-sizing: border-box;
  426. width: 95%;
  427. background-color: #fff;
  428. margin: 20rpx auto;
  429. border-radius: 20rpx;
  430. padding: 20rpx;
  431. }
  432. /* 品牌和价格区域 */
  433. .orderCard .bandAndPrice {
  434. display: flex;
  435. justify-content: space-between;
  436. align-items: center;
  437. }
  438. /* 品牌名称 */
  439. .orderCard .bandAndPrice .bandName {
  440. font-size: 20rpx;
  441. font-weight: 700;
  442. border: 2px solid #2563EB;
  443. padding: 6rpx 12rpx;
  444. border-radius: 15rpx;
  445. background-color: #EFF6FF;
  446. color: #2563EB;
  447. }
  448. /* 价格 */
  449. .orderCard .bandAndPrice .price {
  450. font-size: 30rpx;
  451. font-weight: 700;
  452. }
  453. /* 主要内容行 */
  454. .orderCard .mainLind {
  455. margin-top: 10rpx;
  456. display: flex;
  457. justify-content: space-between;
  458. align-items: center;
  459. gap: 20rpx;
  460. flex-direction: column;
  461. }
  462. /* 主要内容行图片容器 */
  463. .orderCard .mainLind .mainLindImg image {
  464. width: 150rpx;
  465. height: 150rpx;
  466. border-radius: 20rpx;
  467. }
  468. /* 主要内容行信息容器 */
  469. .orderCard .mainLind .mainLindInfo {
  470. display: grid;
  471. grid-template-columns: 1fr 1fr;
  472. flex-direction: column;
  473. gap: 10rpx;
  474. font-size: 24rpx;
  475. color: #6b7280;
  476. text-wrap: nowrap;
  477. .infoItem {
  478. display: flex;
  479. .infoItemTitle {
  480. font-weight: 700;
  481. }
  482. }
  483. }
  484. /* 商品名称 */
  485. .orderCard .mainLind .itemName {
  486. font-size: 30rpx;
  487. font-weight: 700;
  488. color: #374751;
  489. width: 100%;
  490. text-align: left;
  491. }
  492. /* 标签区域 */
  493. .orderCard .tags {
  494. display: flex;
  495. gap: 10rpx;
  496. }
  497. /* 单个标签 */
  498. .orderCard .tags .tag {
  499. font-size: 20rpx;
  500. font-weight: 700;
  501. padding: 6rpx 12rpx;
  502. border-radius: 15rpx;
  503. background-color: #EFF6FF;
  504. color: #fff;
  505. }
  506. /* 按钮区域 */
  507. .orderCard .Btns {
  508. margin-top: 10rpx;
  509. }
  510. /* 按钮组 */
  511. .orderCard .Btns .btnGroup {
  512. display: flex;
  513. justify-content: space-between;
  514. align-items: center;
  515. gap: 20rpx;
  516. }
  517. /* 卡片按钮基础样式 */
  518. .orderCard .Btns .btnGroup .card-button {
  519. font-size: 24rpx;
  520. font-weight: 700;
  521. border: 2rpx solid #2563EB;
  522. padding: 6rpx 12rpx;
  523. border-radius: 15rpx;
  524. background-color: #2563EB;
  525. color: #fff;
  526. width: 45%;
  527. text-align: center;
  528. cursor: pointer;
  529. height: 60rpx;
  530. line-height: 60rpx;
  531. }
  532. /* 忙碌状态按钮 */
  533. .orderCard .Btns .btnGroup .card-button.isBusy {
  534. background-color: #fff;
  535. color: #6B7280;
  536. border-color: #6B7280;
  537. display: flex;
  538. justify-content: center;
  539. }
  540. /* 待跟进状态按钮 */
  541. .orderCard .Btns .btnGroup .card-button.willFollow {
  542. background-color: #EFF6FF;
  543. color: #2563EB;
  544. }
  545. /* 分享按钮 */
  546. .orderCard .Btns .btnGroup .card-button.share {
  547. width: 100%;
  548. }
  549. /* 单独跟进按钮 */
  550. .orderCard .Btns .btnGroup .card-button.oneFollow {
  551. width: 100%;
  552. background-color: #EFF6FF;
  553. color: #2563EB;
  554. }
  555. .cancelBtn {
  556. margin-top: 20rpx;
  557. }
  558. .tagCheckboxGroup {
  559. display: grid;
  560. grid-template-columns: repeat(2, 1fr);
  561. }
  562. .statisticsContainer {
  563. display: flex;
  564. align-items: center;
  565. flex-wrap: nowrap;
  566. white-space: nowrap;
  567. padding: 0 0rpx;
  568. }
  569. .statisticsItem {
  570. display: flex;
  571. justify-content: center;
  572. align-items: center;
  573. background-color: #fff;
  574. padding: 10rpx 20rpx;
  575. border-radius: 15rpx;
  576. font-size: 24rpx;
  577. font-weight: 700;
  578. margin: 0 10rpx;
  579. white-space: nowrap;
  580. flex-shrink: 0;
  581. }
  582. .activeStatusClass {
  583. background-color: #2563EB;
  584. color: #fff;
  585. }
  586. ::v-deep .u-tabs__wrapper__nav__line {
  587. top: 7px;
  588. }
  589. .followUpItem {
  590. background-color: #F7FBFE;
  591. width: 540rpx;
  592. margin: 20rpx;
  593. padding: 20rpx;
  594. box-sizing: border-box;
  595. .followUpInfo {
  596. display: flex;
  597. justify-content: space-between;
  598. align-items: center;
  599. gap: 10rpx;
  600. margin-bottom: 10rpx;
  601. }
  602. .followUpNickname {
  603. font-size: 24rpx;
  604. font-weight: 700;
  605. color: #2563EB;
  606. }
  607. .followUpOrgName {
  608. font-size: 24rpx;
  609. font-weight: 700;
  610. color: #6B7280;
  611. }
  612. .followUpContent {
  613. font-size: 24rpx;
  614. font-weight: 700;
  615. color: #374751;
  616. }
  617. }
  618. .followUpBox {
  619. height: 600rpx;
  620. }
  621. </style>