pagereceivecenter.vue 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204
  1. <script>
  2. import filterQuery from "../order/components/orderCenter/filterQuery.vue";
  3. import commissionFilterQuery from "../order/components/commission/filterQuery.vue";
  4. import dayjs from "dayjs";
  5. // status 状态 1 发单(刚发出来) 2 接单(处理中) 3 收单(入库了) 4 未收(没有收到)
  6. export default {
  7. components: {
  8. filterQuery,
  9. commissionFilterQuery,
  10. },
  11. data() {
  12. return {
  13. orderList: [],
  14. page: {
  15. pageSize: 10,
  16. pageNum: 1,
  17. total: 0
  18. },
  19. tagModalVisible: false,
  20. tagList: [],
  21. currentTags: [],
  22. currentOrder: {},
  23. followUpModelShow: false,
  24. followUpNotes: '',
  25. countdown: 300,
  26. countdownIntervals: null,
  27. //筛选条件
  28. filterList: [
  29. { name: '全部列表', type: 1 },
  30. { name: '我的接发单', type: 2 },
  31. { name: '我的分成', type: 3 }
  32. ],
  33. statisticsSendStatus: [],//中间统计数据
  34. activeType: 1,//当前选择的筛选类型,顶部tab的类型
  35. activeStatus: '',//当前选择的状态,统计数据的类型
  36. currentFollowUp: [],//当前订单的跟进记录
  37. showMoreFollowUp: false,
  38. // 查询参数(默认当月)
  39. queryParams: {
  40. sendDateStart: dayjs().startOf('month').format("YYYY-MM-DD"),
  41. sendDateEnd: dayjs().format("YYYY-MM-DD"),
  42. type: '1',
  43. item: undefined,
  44. phone: undefined,
  45. deptId: undefined,
  46. state: undefined,
  47. status: undefined,
  48. allTagList: [],
  49. identification: undefined,
  50. createBy: undefined,
  51. pageNum: 1,
  52. pageSize: 10,
  53. },
  54. // 字典数据
  55. dicts: {
  56. crmFormStatusDict: [],
  57. crmFormCategoryDict: [],
  58. crmFormStateDict: [],
  59. crmFormTacticDict: [],
  60. },
  61. mapHeight: "0px",
  62. // 我的分成的查询参数
  63. commissionQueryParams: {
  64. receiptDateEnd: dayjs().format("YYYY-MM-DD"),
  65. receiptDateStart: dayjs().startOf('month').format("YYYY-MM-DD"),
  66. item: undefined,
  67. phone: undefined,
  68. receiptUserId: undefined,
  69. pageNum: 1,
  70. pageSize: 10,
  71. },
  72. }
  73. },
  74. computed: {
  75. // 根据当前选择的类型返回对应的查询参数
  76. currentQueryParams() {
  77. return this.activeType === 3 ? this.commissionQueryParams : this.queryParams;
  78. },
  79. },
  80. onLoad() {
  81. // 初始化字典数据
  82. this.$getDicts('crm_form_status').then(res => {
  83. this.dicts.crmFormStatusDict = res;
  84. });
  85. this.$getDicts('crm_form_category').then(res => {
  86. this.dicts.crmFormCategoryDict = res;
  87. });
  88. this.$getDicts('crm_form_state').then(res => {
  89. this.dicts.crmFormStateDict = res;
  90. });
  91. this.$getDicts('crm_form_tactic').then(res => {
  92. this.dicts.crmFormTacticDict = res;
  93. });
  94. // 设置 mapHeight
  95. uni.getSystemInfo({
  96. success: (e) => {
  97. const {
  98. windowHeight
  99. } = e;
  100. this.mapHeight = (windowHeight - 70) + 'px';
  101. }
  102. });
  103. //初始调用
  104. this.getOrderList();
  105. this.getStatisticsSendStatus();
  106. // 初始化获取全部标签
  107. this.getAllTags();
  108. this.countdownInterval()
  109. },
  110. onUnload() {
  111. clearInterval(this.countdownInterval);
  112. },
  113. // 下拉刷新
  114. async onPullDownRefresh() {
  115. try {
  116. // 重置页码和列表
  117. this.page.pageNum = 1;
  118. this.queryParams.pageNum = 1;
  119. this.commissionQueryParams.pageNum = 1;
  120. this.orderList = [];
  121. // 重新获取数据
  122. await this.getOrderList();
  123. // 重新获取统计数据
  124. await this.getStatisticsSendStatus();
  125. } catch (error) {
  126. console.error('下拉刷新失败:', error);
  127. } finally {
  128. // 停止下拉刷新动画
  129. uni.stopPullDownRefresh();
  130. }
  131. },
  132. // 滑动到底部加载更多
  133. onReachBottom() {
  134. if (this.orderList.length >= this.page.total) {
  135. //到底了,没有更多
  136. return;
  137. }
  138. const params = this.activeType === 3 ? this.commissionQueryParams : this.queryParams;
  139. params.pageNum++;
  140. this.page.pageNum++;
  141. this.getOrderList();
  142. },
  143. watch: {
  144. countdown: {
  145. handler(newVal, oldVal) {
  146. if (newVal <= 0) {
  147. this.orderList.forEach(order => {
  148. if (order.status == 1) {
  149. this.handleBtnClick('isBusy', order)
  150. }
  151. })
  152. clearInterval(this.countdownInterval);
  153. }
  154. },
  155. immediate: true
  156. }
  157. },
  158. methods: {
  159. countdownInterval() {
  160. this.countdownInterval = setInterval(() => {
  161. this.countdown--
  162. }, 1000);
  163. },
  164. //获取列表数据
  165. async getOrderList() {
  166. // 记录本次请求的筛选条件,用于避免“加载中切换 tab”导致旧请求覆盖新数据
  167. const requestType = this.activeType;
  168. const requestStatus = this.activeStatus;
  169. const requestPageNum = this.activeType === 3
  170. ? this.commissionQueryParams.pageNum
  171. : this.queryParams.pageNum;
  172. try {
  173. let result;
  174. // 如果是"我的分成",调用分成接口
  175. if (this.activeType === 3) {
  176. // 参考 myCommission.vue 的实现,需要传递 type: 2
  177. result = await uni.$u.api.selectCommissionList({
  178. pageSize: this.commissionQueryParams.pageSize,
  179. pageNum: this.commissionQueryParams.pageNum,
  180. }, {
  181. ...this.commissionQueryParams,
  182. type: '2'
  183. });
  184. console.log('分成列表', result);
  185. } else {
  186. // 否则调用订单列表接口
  187. // 合并查询参数和筛选参数
  188. const params = {
  189. ...this.queryParams,
  190. type: this.activeType,
  191. status: this.activeStatus || this.queryParams.status,
  192. };
  193. // 移除分页参数,因为已经在第一个参数中传递
  194. delete params.pageNum;
  195. delete params.pageSize;
  196. result = await uni.$u.api.selectClueOrderFormList({
  197. pageSize: this.queryParams.pageSize,
  198. pageNum: this.queryParams.pageNum,
  199. }, params);
  200. console.log('接单列表', result);
  201. // 把数组按照status的大小排序,从小到大
  202. result.rows.sort((a, b) => {
  203. return a.status - b.status;
  204. // return b.status - a.status;
  205. })
  206. }
  207. // 若用户在请求期间切换了类型或状态,丢弃本次结果,避免错误显示
  208. if (this.activeType !== requestType || (this.activeType !== 3 && this.activeStatus !== requestStatus)) {
  209. return;
  210. }
  211. const currentPageNum = this.activeType === 3
  212. ? this.commissionQueryParams.pageNum
  213. : this.queryParams.pageNum;
  214. if (currentPageNum !== requestPageNum) {
  215. return;
  216. }
  217. // 获取当前使用的查询参数
  218. const params = this.activeType === 3 ? this.commissionQueryParams : this.queryParams;
  219. // 如果是第一页(下拉刷新或初始加载),直接替换列表
  220. if (params.pageNum === 1) {
  221. this.orderList = result.rows;
  222. } else {
  223. // 否则追加数据(上拉加载更多)
  224. this.orderList.push(...result.rows);
  225. }
  226. this.page.total = result.total;
  227. this.page.pageNum = params.pageNum;
  228. this.page.pageSize = params.pageSize;
  229. } catch (error) {
  230. console.error('列表接口调用失败:', error);
  231. // 添加用户友好的错误提示
  232. const errorMsg = this.activeType === 3 ? '获取分成列表失败,请稍后重试' : '获取订单列表失败,请稍后重试';
  233. uni.$u.toast(errorMsg);
  234. }
  235. },
  236. //获取统计数据
  237. async getStatisticsSendStatus() {
  238. // 如果是"我的分成",不需要统计数据
  239. if (this.activeType === 3) {
  240. this.statisticsSendStatus = [];
  241. return;
  242. }
  243. // 传递完整的查询参数,包括筛选条件,参考 orderCenter.vue 的实现
  244. const params = {
  245. ...this.queryParams,
  246. type: this.activeType,
  247. };
  248. // 移除分页参数
  249. delete params.pageNum;
  250. delete params.pageSize;
  251. const { data } = await uni.$u.api.statisticsSendStatus(params);
  252. // console.log('统计数据是', data)
  253. this.statisticsSendStatus = data;
  254. },
  255. // 处理按钮点击事件
  256. async handleBtnClick(btnType, order) {
  257. if (btnType == 'acceptOrder') {
  258. //去接单
  259. console.log('去接单', order)
  260. //打开模态窗二次确认,确认后跳转接单form
  261. uni.showModal({
  262. title: '确认接单',
  263. content: `是否确认接单订单:${order.item}?`,
  264. success: async (res) => {
  265. if (res.confirm) {
  266. await uni.$u.api.oderForm({
  267. status: "2",
  268. id: order.id,
  269. });
  270. uni.navigateTo({
  271. url: `/pages/orderDetailRefactored/index?orderId=${order.id}&item=${order.item}&type=${this.type}&clueId=${order.clueId}`,
  272. })
  273. } else if (res.cancel) {
  274. // 用户点击了取消,不执行任何操作
  275. uni.$u.toast('已取消接单');
  276. }
  277. }
  278. })
  279. } else if (btnType == 'isBusy') {
  280. //在忙
  281. console.log('在忙', order)
  282. //当前订单移动到末尾
  283. this.orderList.push(this.orderList.splice(this.orderList.indexOf(order), 1)[0]);
  284. } else if (btnType == 'willFollow') {
  285. //待跟进
  286. console.log('待跟进', order)
  287. //打开模态窗
  288. this.followUpModelShow = true;
  289. this.currentOrder = order
  290. } else if (btnType == 'tag') {
  291. //打标签
  292. console.log('打标签', order)
  293. // 如果标签列表为空,重新获取一次
  294. if (!this.tagList || this.tagList.length === 0) {
  295. await this.getAllTags();
  296. }
  297. //打开模态窗
  298. this.tagModalVisible = true;
  299. // 确保 order.tags 存在且是数组
  300. if (order && order.tags && Array.isArray(order.tags) && order.tags.length > 0) {
  301. this.currentTags = order.tags.map(tag => tag && tag.id ? tag.id : null).filter(id => id !== null);
  302. } else {
  303. this.currentTags = [];
  304. }
  305. this.currentOrder = order
  306. } else if (btnType == 'share') {
  307. //一键分享
  308. console.log('一键分享', order)
  309. } else if (btnType == 'oneFollow') {
  310. //待跟进
  311. console.log('待跟进', order)
  312. this.followUpModelShow = true;
  313. this.currentOrder = order
  314. }
  315. },
  316. // 格式化金额
  317. formatAmount(amount) {
  318. if (!amount) return '-';
  319. return parseFloat(amount).toLocaleString();
  320. },
  321. // 格式化金额
  322. formatAmount(amount) {
  323. if (!amount) return '-';
  324. return parseFloat(amount).toLocaleString();
  325. },
  326. // 跳转订单详情
  327. toOrderDetail(order) {
  328. //点卡片看详情
  329. // if (order.status == '1' || order.status == '2') {
  330. uni.navigateTo({
  331. url: `/pages/orderDetailRefactored/index?orderId=${order.id}&item=${order.item}&type=${this.type}&clueId=${order.clueId}`,
  332. })
  333. // } else {
  334. // uni.$u.toast('当前订单无法查看详情');
  335. // return;
  336. // }
  337. },
  338. //获取全部标签
  339. async getAllTags() {
  340. try {
  341. const res = await uni.$u.api.getClueTagGroupVoList({ tagGroupApplication: '2' })
  342. console.log('全部标签', res)
  343. // 确保数据结构正确
  344. if (res && res.data && res.data.length > 0 && res.data[0].clueTagDataList) {
  345. this.tagList = res.data[0].clueTagDataList || [];
  346. } else {
  347. this.tagList = [];
  348. console.warn('标签数据格式不正确', res);
  349. }
  350. } catch (error) {
  351. console.error('获取标签列表失败:', error);
  352. this.tagList = [];
  353. uni.$u.toast('获取标签列表失败');
  354. }
  355. },
  356. cancelTag() {
  357. this.tagModalVisible = false;
  358. // 重置状态
  359. this.currentTags = [];
  360. this.currentOrder = {};
  361. },
  362. async confirmTag() {
  363. try {
  364. console.log('确认打标签', this.currentTags)
  365. // 确保 currentTags 是数组且不为空
  366. if (!Array.isArray(this.currentTags)) {
  367. this.currentTags = [];
  368. }
  369. // 过滤掉无效值
  370. const validTags = this.currentTags.filter(tag => tag !== null && tag !== undefined && tag !== '');
  371. const allTags = validTags.join(',');
  372. console.log('allTags', allTags)
  373. if (!this.currentOrder || !this.currentOrder.id) {
  374. uni.$u.toast('订单信息错误');
  375. return;
  376. }
  377. await uni.$u.api.updateTags({
  378. id: this.currentOrder.id,
  379. allTags: allTags,
  380. })
  381. this.tagModalVisible = false;
  382. uni.$u.toast('标签更新成功');
  383. //更新当前订单的标签
  384. if (this.currentOrder && Array.isArray(this.tagList)) {
  385. this.currentOrder.tags = this.tagList.filter(tag => tag && tag.id && validTags.includes(tag.id));
  386. }
  387. // 更新列表中的订单标签
  388. const orderIndex = this.orderList.findIndex(item =>
  389. item.id === this.currentOrder.id ||
  390. (item.receiptId && this.currentOrder.receiptId && item.receiptId === this.currentOrder.receiptId)
  391. );
  392. if (orderIndex !== -1 && this.currentOrder.tags) {
  393. this.$set(this.orderList, orderIndex, {
  394. ...this.orderList[orderIndex],
  395. tags: this.currentOrder.tags
  396. });
  397. }
  398. } catch (error) {
  399. console.error('更新标签失败:', error);
  400. uni.$u.toast('标签更新失败');
  401. }
  402. },
  403. // 确认跟进细节按钮点击事件
  404. async confirmFollowUp() {
  405. console.log('确认跟进细节:', this.followUpNotes);
  406. this.followUpModelShow = false;
  407. // 可以在这里添加提交跟进细节的逻辑
  408. // 未收的时候,提交一个跟进记录 待跟进_内容
  409. const res = await uni.$u.api.addOrderFollow({
  410. orderId: this.currentOrder.id,
  411. content: `待跟进_${this.followUpNotes}`,
  412. })
  413. if (res.code == 200) {
  414. uni.$u.toast('提交待跟进记录成功');
  415. }
  416. this.followUpNotes = '';
  417. },
  418. // 切换筛选条件
  419. async changeFilter(param) {
  420. this.activeType = param.type;
  421. // 切换筛选条件时,重置状态筛选
  422. this.activeStatus = '';
  423. this.queryParams.status = undefined;
  424. this.page.pageNum = 1;
  425. this.queryParams.pageNum = 1;
  426. this.commissionQueryParams.pageNum = 1;
  427. this.orderList = [];
  428. this.getOrderList();
  429. this.getStatisticsSendStatus()
  430. },
  431. // 处理关键词搜索
  432. handleKeyword() {
  433. const params = this.activeType === 3 ? this.commissionQueryParams : this.queryParams;
  434. params.pageNum = 1;
  435. this.page.pageNum = 1;
  436. this.orderList = [];
  437. this.getOrderList();
  438. // 搜索时也要更新统计数据
  439. this.getStatisticsSendStatus();
  440. },
  441. // 处理关键词清空
  442. handleKeywordClear() {
  443. const params = this.activeType === 3 ? this.commissionQueryParams : this.queryParams;
  444. params.phone = "";
  445. params.pageNum = 1;
  446. this.page.pageNum = 1;
  447. this.orderList = [];
  448. this.getOrderList();
  449. // 清空时也要更新统计数据
  450. this.getStatisticsSendStatus();
  451. },
  452. // 显示筛选弹窗
  453. handleshowFilter() {
  454. const refName = this.activeType === 3 ? 'commissionFilter' : 'filter';
  455. this.$refs[refName].show();
  456. },
  457. // 处理筛选查询
  458. handleFilterQuery() {
  459. const params = this.activeType === 3 ? this.commissionQueryParams : this.queryParams;
  460. params.pageNum = 1;
  461. this.page.pageNum = 1;
  462. this.orderList = [];
  463. this.getOrderList();
  464. // 筛选时也要更新统计数据
  465. this.getStatisticsSendStatus();
  466. },
  467. //切换统计数据的类型
  468. changeStatus(param) {
  469. if (param == this.activeStatus) {
  470. //如果当前点击的状态和当前选中的状态相同,则取消选中
  471. this.activeStatus = '';
  472. this.queryParams.status = undefined;
  473. this.queryParams.pageNum = 1;
  474. this.page.pageNum = 1;
  475. this.orderList = [];
  476. this.getOrderList();
  477. } else {
  478. //如果当前点击的状态和当前选中的状态不同,则切换选中状态
  479. this.activeStatus = param;
  480. this.queryParams.status = param;
  481. this.queryParams.pageNum = 1;
  482. this.page.pageNum = 1;
  483. this.orderList = [];
  484. this.getOrderList();
  485. }
  486. },
  487. //点击查看更多的跟进
  488. async handleShowMoreFollowUp() {
  489. //当前的order是
  490. console.log()
  491. const { data } = await uni.$u.api.getDuplicateOrderFollowListByClueId({
  492. clueId: this.currentOrder.clueId
  493. });
  494. console.log('这里是跟进', data)
  495. const allData = []
  496. for (const key in data) {
  497. allData.push(...data[key])
  498. }
  499. const filterData = allData.filter(item => {
  500. console.log('过滤', item)
  501. //过滤出来tem.content不包括联系师傅、师傅拍图技巧、到达客户面对面、未收评分、待跟进_
  502. return item.content.indexOf('联系师傅') == -1 && item.content.indexOf('师傅拍图技巧') == -1 && item.content.indexOf('到达客户面对面') == -1 && item.content.indexOf('未收评分') == -1 && item.content.indexOf('待跟进_') == -1
  503. })
  504. console.log('筛选后的跟进', filterData)
  505. this.currentFollowUp = filterData || [];
  506. this.showMoreFollowUp = true
  507. },
  508. // 电话号码脱敏函数
  509. desensitizePhone(phone) {
  510. if (!phone) return '-';
  511. const phoneStr = String(phone);
  512. if (phoneStr.length !== 11) return phoneStr;
  513. return phoneStr.substring(0, 3) + '****' + phoneStr.substring(7);
  514. }
  515. }
  516. }
  517. </script>
  518. <template>
  519. <view class="container">
  520. <u-navbar title="接单中心" :autoBack="true" :placeholder="true" v-hideNav></u-navbar>
  521. <!-- 筛选条件 -->
  522. <u-tabs :list="filterList" @click="changeFilter"></u-tabs>
  523. <!-- 查询参数区域 -->
  524. <view class="queryParams_wrap">
  525. <view class="search">
  526. <u--input clearable prefixIcon="search" v-model="currentQueryParams.phone" shape="circle" @blur="handleKeyword"
  527. @clear="handleKeywordClear" placeholder="请输入电话"></u--input>
  528. </view>
  529. <view class="query">
  530. <view style="margin-right: 10rpx;" @click="handleshowFilter">筛选</view>
  531. <u-icon name="arrow-down-fill" color="#aaa" size="10"></u-icon>
  532. </view>
  533. </view>
  534. <!-- 统计数据 -->
  535. <view v-if="activeType !== 3" class="send_status_wrap">
  536. <scroll-view scroll-x>
  537. <view class="statisticsContainer">
  538. <view v-for="item in statisticsSendStatus" :key="item.status" @click="changeStatus(item.status)"
  539. class="statisticsItem" :class="{ 'activeStatusClass': item.status == activeStatus }">
  540. <view>{{ item.statusName }}</view>
  541. <view>({{ item.count || 0 }})</view>
  542. </view>
  543. </view>
  544. </scroll-view>
  545. </view>
  546. <!-- 订单列表容器 -->
  547. <view class="order_list_wrap">
  548. <transition-group name="order-move" tag="div">
  549. <!-- 我的分成 - 使用专门的分成卡片 -->
  550. <view class="commission_item" v-for="item in orderList" :key="activeType === 3 ? item.id : (item.receiptId + item.id)" v-if="activeType === 3">
  551. <view class="commission_top">
  552. <view class="top_left">{{ item.receiptItem || '-' }}</view>
  553. <view class="top_right">
  554. <text class="account_type">{{ item.accountType === '1' ? '前端' : '后端' }}</text>
  555. </view>
  556. </view>
  557. <view class="commission_info">
  558. <view class="info_row">
  559. <view class="info_item">
  560. <text class="label">电话: </text>
  561. <text class="value">{{ desensitizePhone(item.phone) }}</text>
  562. </view>
  563. </view>
  564. <view class="info_row">
  565. <view class="info_item">
  566. <text class="label">收单时间: </text>
  567. <text class="value">{{ item.receiptDate || '-' }}</text>
  568. </view>
  569. </view>
  570. <view class="info_row">
  571. <view class="info_item">
  572. <text class="label">收单人: </text>
  573. <text class="value">{{ item.receiptNickName || '-' }}</text>
  574. </view>
  575. <view class="info_item">
  576. <text class="label">公司: </text>
  577. <text class="value">{{ item.orgName || '-' }}</text>
  578. </view>
  579. </view>
  580. <view class="info_row">
  581. <view class="info_item">
  582. <text class="label">分成所属人: </text>
  583. <text class="value">{{ item.userName || '-' }}</text>
  584. </view>
  585. <view class="info_item">
  586. <text class="label">分成比例: </text>
  587. <text class="value">{{ item.commissionRate || '-' }}%</text>
  588. </view>
  589. </view>
  590. </view>
  591. <view class="commission_amount">
  592. <view class="amount_item">
  593. <view class="amount_label">业绩</view>
  594. <view class="amount_value primary">{{ formatAmount(item.commissionAmount) }}</view>
  595. </view>
  596. <view class="amount_item">
  597. <view class="amount_label">毛业绩</view>
  598. <view class="amount_value">{{ formatAmount(item.grossAmount) }}</view>
  599. </view>
  600. </view>
  601. </view>
  602. <!-- 全部列表和我的接发单 - 使用订单卡片 -->
  603. <view class="orderCard" v-for="item in orderList"
  604. :key="activeType === 3 ? item.id : (item.receiptId + item.id)"
  605. v-if="activeType !== 3"
  606. @click.stop="toOrderDetail(item)">
  607. <view class="bandAndPrice">
  608. <view class="bandName">{{ item.itemBrand || '暂无品牌' }}</view>
  609. <view class="price">¥{{ item.priceRange || '?' }}</view>
  610. </view>
  611. <view class="mainLind">
  612. <view class="itemName">{{ item.item || '暂无项目' }}</view>
  613. <view class="mainLindInfo">
  614. <view class="infoItem">
  615. <view class="infoItemTitle">发单人:</view>
  616. <view>{{ item.createNickName || '未知' }}</view>
  617. </view>
  618. <view class="infoItem">
  619. <view class="infoItemTitle">机构:</view>
  620. <view>{{ item.orgName || '暂无机构' }}</view>
  621. </view>
  622. <view class="infoItem">
  623. <view class="infoItemTitle">电话:</view>
  624. <view>{{ desensitizePhone(item.phone) }}</view>
  625. </view>
  626. <view class="infoItem">
  627. <view class="infoItemTitle">接单人:</view>
  628. <view>{{ item.identificationName || '暂无所属人' }}</view>
  629. </view>
  630. <view class="infoItem">
  631. <view class="infoItemTitle">运营人:</view>
  632. <view>{{ item.clueOperationName || '暂无运营人' }}</view>
  633. </view>
  634. <view class="infoItem">
  635. <view class="infoItemTitle">发单日期:</view>
  636. <view>{{ item.sendDate || '暂无时间' }}</view>
  637. </view>
  638. </view>
  639. </view>
  640. <view class="tags">
  641. <view class="tag" v-for="(tag, index) in item.tags" :key="index"
  642. :style="{ backgroundColor: tag.color, opacity: 0.8 }">
  643. {{ tag.name }}
  644. </view>
  645. </view>
  646. <view class="Btns">
  647. <!-- status 状态 1 发单(刚发出来) 2 接单(处理中) 3 收单(入库了) 4 未收(没有收到) -->
  648. <view class="btnGroup" v-if="item && (item.status == '1')">
  649. <view class="card-button" @click.stop="handleBtnClick('acceptOrder', item)">立即接单</view>
  650. <view class="card-button isBusy" @click.stop="handleBtnClick('isBusy', item)">
  651. <view>在忙</view>
  652. <view v-if="countdown > 0">({{ countdown }} s)</view>
  653. </view>
  654. </view>
  655. <view class="btnGroup" v-if="item && (item.status == '2')">
  656. <view class="card-button willFollow" @click.stop="handleBtnClick('willFollow', item)">
  657. 待跟进
  658. </view>
  659. <view class="card-button isBusy" @click.stop="handleBtnClick('tag', item)">打标签</view>
  660. </view>
  661. <view class="btnGroup" v-if="item && (item.status == '4')">
  662. <view class="card-button oneFollow" @click.stop="handleBtnClick('oneFollow', item)">待跟进</view>
  663. </view>
  664. </view>
  665. </view>
  666. </transition-group>
  667. <view class="hasMore">
  668. {{ orderList.length >= page.total ? '没有更多了~' : '向下滑动加载更多~' }}
  669. </view>
  670. </view>
  671. <!-- 打标签模态窗 -->
  672. <u-modal showCancelButton :show="tagModalVisible" title="选择标签" @confirm="confirmTag" @cancel="cancelTag">
  673. <view class="slot-content">
  674. <u-checkbox-group class="tagCheckboxGroup" v-model="currentTags" placement="column">
  675. <u-checkbox
  676. v-for="(item, index) in tagList"
  677. :key="item && item.id ? item.id : index"
  678. :customStyle="{ marginBottom: '8px' }"
  679. :label="item && item.name ? item.name : '未知标签'"
  680. :name="item && item.id ? item.id : ''">
  681. </u-checkbox>
  682. </u-checkbox-group>
  683. <view v-if="tagList.length === 0" style="text-align: center; padding: 40rpx 0; color: #999;">
  684. 暂无可用标签
  685. </view>
  686. </view>
  687. </u-modal>
  688. <u-modal showCancelButton :show="followUpModelShow" :title="'填写跟进细节'" @confirm="confirmFollowUp"
  689. @cancel="followUpModelShow = false">
  690. <view class="modal-content">
  691. <u--textarea v-model="followUpNotes" placeholder="请输入情况" confirm-type="done"
  692. style="width: 400rpx;margin-bottom: 10rpx; "></u--textarea>
  693. <u-button type="primary" @click="handleShowMoreFollowUp">点击查看更多跟进</u-button>
  694. </view>
  695. </u-modal>
  696. <!-- 更多跟进 -->
  697. <u-modal :show="showMoreFollowUp" title="详细跟进记录" @confirm="showMoreFollowUp = false">
  698. <!-- <view class="followUpBox"> -->
  699. <scroll-view class="followUpBox" scroll-y>
  700. <view v-for="value in currentFollowUp" :key="value.id" class="followUpItem">
  701. <view class="followUpInfo">
  702. <view class="followUpNickname">
  703. 账号:{{ value.createNickname }}
  704. </view>
  705. <view class="followUpOrgName">{{ value.orgName }}</view>
  706. </view>
  707. <view class="followUpContent">{{ value.content }}</view>
  708. </view>
  709. </scroll-view>
  710. <!-- </view> -->
  711. </u-modal>
  712. <!-- 筛选组件 - 订单列表 -->
  713. <filter-query v-if="activeType !== 3" ref="filter" v-model="queryParams" @getList="handleFilterQuery" :mapHeight="mapHeight"
  714. :dicts="dicts"></filter-query>
  715. <!-- 筛选组件 - 我的分成 -->
  716. <commission-filter-query v-if="activeType === 3" ref="commissionFilter" v-model="commissionQueryParams" @getList="handleFilterQuery" :mapHeight="mapHeight"></commission-filter-query>
  717. </view>
  718. </template>
  719. <style scoped lang="scss">
  720. .container {
  721. box-sizing: border-box;
  722. min-height: 100vh;
  723. background-color: #f5f5f5;
  724. }
  725. .hasMore {
  726. text-align: center;
  727. padding: 20rpx 0;
  728. font-size: 24rpx;
  729. color: #999;
  730. }
  731. .queryParams_wrap {
  732. display: flex;
  733. background: #fff;
  734. padding: 14px 0;
  735. border-bottom: 1px solid #f0f0f0;
  736. .query,
  737. .search {
  738. display: flex;
  739. align-items: center;
  740. justify-content: center;
  741. font-size: 16px;
  742. font-weight: 700;
  743. color: #202020;
  744. }
  745. .query {
  746. flex: 1;
  747. cursor: pointer;
  748. }
  749. .search {
  750. flex: 2;
  751. padding-left: 20px;
  752. padding-right: 10px;
  753. }
  754. }
  755. .send_status_wrap {
  756. width: 690rpx;
  757. padding: 0 30rpx;
  758. margin-top: 20rpx;
  759. display: flex;
  760. .statisticsContainer {
  761. display: flex;
  762. align-items: center;
  763. flex-wrap: nowrap;
  764. white-space: nowrap;
  765. }
  766. }
  767. .order_list_wrap {
  768. padding: 10px 0;
  769. }
  770. /* 分成卡片样式 */
  771. .commission_item {
  772. background: #fff;
  773. border-radius: 20rpx;
  774. padding: 20rpx;
  775. margin: 20rpx 20rpx;
  776. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
  777. .commission_top {
  778. display: flex;
  779. justify-content: space-between;
  780. margin-bottom: 15rpx;
  781. .top_left {
  782. font-size: 36rpx;
  783. font-weight: bold;
  784. color: #202020;
  785. }
  786. .top_right {
  787. .account_type {
  788. background: #108cff;
  789. color: #fff;
  790. padding: 8rpx 16rpx;
  791. border-radius: 20rpx;
  792. font-size: 24rpx;
  793. }
  794. }
  795. }
  796. .commission_info {
  797. margin-bottom: 15rpx;
  798. .info_row {
  799. display: flex;
  800. margin-bottom: 16rpx;
  801. &:last-child {
  802. margin-bottom: 0;
  803. }
  804. .info_item {
  805. flex: 1;
  806. display: flex;
  807. align-items: center;
  808. font-size: 28rpx;
  809. .label {
  810. color: #9b9aa2;
  811. margin-right: 16rpx;
  812. min-width: 120rpx;
  813. }
  814. .value {
  815. color: #202020;
  816. }
  817. }
  818. }
  819. }
  820. .commission_amount {
  821. display: flex;
  822. justify-content: space-around;
  823. padding: 30rpx 0;
  824. border-top: 1rpx solid #f0f0f0;
  825. background: #f8f9fb;
  826. border-radius: 20rpx;
  827. .amount_item {
  828. text-align: center;
  829. .amount_label {
  830. font-size: 24rpx;
  831. color: #9b9aa2;
  832. margin-bottom: 10rpx;
  833. }
  834. .amount_value {
  835. font-size: 32rpx;
  836. font-weight: bold;
  837. color: #202020;
  838. &.primary {
  839. color: #108cff;
  840. }
  841. }
  842. }
  843. }
  844. }
  845. /* 订单卡片主容器 */
  846. .orderCard {
  847. box-sizing: border-box;
  848. width: 95%;
  849. background-color: #fff;
  850. margin: 20rpx auto;
  851. border-radius: 20rpx;
  852. padding: 20rpx;
  853. }
  854. /* 品牌和价格区域 */
  855. .orderCard .bandAndPrice {
  856. display: flex;
  857. justify-content: space-between;
  858. align-items: center;
  859. }
  860. /* 品牌名称 */
  861. .orderCard .bandAndPrice .bandName {
  862. font-size: 20rpx;
  863. font-weight: 700;
  864. border: 2px solid #2563EB;
  865. padding: 6rpx 12rpx;
  866. border-radius: 15rpx;
  867. background-color: #EFF6FF;
  868. color: #2563EB;
  869. }
  870. /* 价格 */
  871. .orderCard .bandAndPrice .price {
  872. font-size: 30rpx;
  873. font-weight: 700;
  874. }
  875. /* 主要内容行 */
  876. .orderCard .mainLind {
  877. margin-top: 10rpx;
  878. display: flex;
  879. justify-content: space-between;
  880. align-items: center;
  881. gap: 20rpx;
  882. flex-direction: column;
  883. }
  884. /* 主要内容行信息容器 */
  885. .orderCard .mainLind .mainLindInfo {
  886. display: grid;
  887. grid-template-columns: 1fr 1fr;
  888. flex-direction: column;
  889. gap: 10rpx;
  890. font-size: 24rpx;
  891. color: #6b7280;
  892. text-wrap: nowrap;
  893. width: 100%;
  894. .infoItem {
  895. display: flex;
  896. .infoItemTitle {
  897. font-weight: 700;
  898. }
  899. }
  900. }
  901. /* 商品名称 */
  902. .orderCard .mainLind .itemName {
  903. font-size: 30rpx;
  904. font-weight: 700;
  905. color: #374751;
  906. width: 100%;
  907. text-align: left;
  908. }
  909. /* 标签区域 */
  910. .orderCard .tags {
  911. display: flex;
  912. gap: 10rpx;
  913. }
  914. /* 单个标签 */
  915. .orderCard .tags .tag {
  916. font-size: 20rpx;
  917. font-weight: 700;
  918. padding: 6rpx 12rpx;
  919. border-radius: 15rpx;
  920. background-color: #EFF6FF;
  921. color: #fff;
  922. }
  923. /* 按钮区域 */
  924. .orderCard .Btns {
  925. margin-top: 10rpx;
  926. }
  927. /* 按钮组 */
  928. .orderCard .Btns .btnGroup {
  929. display: flex;
  930. justify-content: space-between;
  931. align-items: center;
  932. gap: 20rpx;
  933. }
  934. /* 卡片按钮基础样式 */
  935. .orderCard .Btns .btnGroup .card-button {
  936. font-size: 24rpx;
  937. font-weight: 700;
  938. border: 2rpx solid #2563EB;
  939. padding: 6rpx 12rpx;
  940. border-radius: 15rpx;
  941. background-color: #2563EB;
  942. color: #fff;
  943. width: 45%;
  944. text-align: center;
  945. cursor: pointer;
  946. height: 60rpx;
  947. line-height: 60rpx;
  948. display: flex;
  949. justify-content: center;
  950. align-items: center;
  951. }
  952. /* 忙碌状态按钮 */
  953. .orderCard .Btns .btnGroup .card-button.isBusy {
  954. background-color: #fff;
  955. color: #6B7280;
  956. border-color: #6B7280;
  957. }
  958. /* 待跟进状态按钮 */
  959. .orderCard .Btns .btnGroup .card-button.willFollow {
  960. background-color: #EFF6FF;
  961. color: #2563EB;
  962. }
  963. /* 单独跟进按钮 */
  964. .orderCard .Btns .btnGroup .card-button.oneFollow {
  965. width: 100%;
  966. background-color: #EFF6FF;
  967. color: #2563EB;
  968. }
  969. .followUpScroll {
  970. height: 600rpx;
  971. }
  972. /* 订单移动动画 */
  973. .order-move-enter-active,
  974. .order-move-leave-active {
  975. transition: all 0.5s ease;
  976. }
  977. .order-move-enter-from,
  978. .order-move-leave-to {
  979. opacity: 0;
  980. transform: translateY(30px);
  981. }
  982. .order-move-move {
  983. transition: transform 0.5s ease;
  984. }
  985. .cancelBtn {
  986. margin-top: 20rpx;
  987. }
  988. .tagCheckboxGroup {
  989. display: grid;
  990. grid-template-columns: repeat(2, 1fr);
  991. }
  992. .statisticsItem {
  993. font-size: 30rpx;
  994. display: inline-flex;
  995. align-items: center;
  996. background: #fff;
  997. margin-right: 30rpx;
  998. padding: 8rpx 16rpx;
  999. white-space: nowrap;
  1000. border-radius: 6rpx;
  1001. color: #333;
  1002. &.activeStatusClass {
  1003. color: #fff;
  1004. background: #4c8afe;
  1005. }
  1006. }
  1007. .activeStatusClass {
  1008. background-color: #2563EB;
  1009. color: #fff;
  1010. }
  1011. ::v-deep .u-tabs__wrapper__nav__line {
  1012. top: 7px;
  1013. }
  1014. .followUpItem {
  1015. background-color: #F7FBFE;
  1016. width: 540rpx;
  1017. margin: 20rpx;
  1018. padding: 20rpx;
  1019. box-sizing: border-box;
  1020. .followUpInfo {
  1021. display: flex;
  1022. justify-content: space-between;
  1023. align-items: center;
  1024. gap: 10rpx;
  1025. margin-bottom: 10rpx;
  1026. }
  1027. .followUpNickname {
  1028. font-size: 24rpx;
  1029. font-weight: 700;
  1030. color: #2563EB;
  1031. }
  1032. .followUpOrgName {
  1033. font-size: 24rpx;
  1034. font-weight: 700;
  1035. color: #6B7280;
  1036. }
  1037. .followUpContent {
  1038. font-size: 24rpx;
  1039. font-weight: 700;
  1040. color: #374751;
  1041. }
  1042. }
  1043. .followUpBox {
  1044. height: 600rpx;
  1045. }
  1046. .u-tabs{
  1047. background-color: #fff;
  1048. }
  1049. ::v-deep .u-navbar {
  1050. flex-shrink: 0;
  1051. }
  1052. </style>