chenyidong il y a 3 mois
Parent
commit
e2ac40bbac

+ 1 - 1
components/show-emtry/show-emtry.vue

@@ -27,7 +27,7 @@
27
 
27
 
28
 <style lang="scss" scoped>
28
 <style lang="scss" scoped>
29
 	.emtry_wrap{
29
 	.emtry_wrap{
30
-		width: 750rpx;
30
+		width: 100%;
31
 		display: flex;
31
 		display: flex;
32
 		flex-direction: column;
32
 		flex-direction: column;
33
 		align-items: center;
33
 		align-items: center;

+ 5 - 3
pages.json

@@ -202,7 +202,9 @@
202
 		{
202
 		{
203
 			"path": "pages/order/index",
203
 			"path": "pages/order/index",
204
 			"style": {
204
 			"style": {
205
-				"navigationBarTitleText": "接单中心"
205
+				"navigationBarTitleText": "接单中心",
206
+				"enablePullDownRefresh": true,
207
+				"navigationStyle": "custom"
206
 			}
208
 			}
207
 		}
209
 		}
208
 	],
210
 	],
@@ -238,8 +240,8 @@
238
 		}, {
240
 		}, {
239
 			"text": "接单中心",
241
 			"text": "接单中心",
240
 			"pagePath": "pages/order/index",
242
 			"pagePath": "pages/order/index",
241
-			"iconPath": "static/tabs/private.png",
242
-			"selectedIconPath": "static/tabs/private1.png"
243
+			"iconPath": "static/tabs/order.png",
244
+			"selectedIconPath": "static/tabs/order1.png"
243
 		},{
245
 		},{
244
 			"text": "我的",
246
 			"text": "我的",
245
 			"pagePath": "pages/person/index",
247
 			"pagePath": "pages/person/index",

+ 249 - 0
pages/order/components/myCommission.vue

@@ -0,0 +1,249 @@
1
+<template>
2
+	<view class="my_commission_wrap">
3
+		<!-- 统计信息 -->
4
+		<view class="commission_item" v-for="item in listData" :key="item.id">
5
+			<view class="commission_top">
6
+				<view class="top_left">{{item.item}}</view>
7
+				<view class="top_right">
8
+					<text class="account_type">{{ item.accountType === '1' ? '前端' : '后端' }}</text>
9
+				</view>
10
+			</view>
11
+			<view class="commission_info">
12
+				<view class="info_row">
13
+					<view class="info_item">
14
+						<text class="label">电话: </text>
15
+						<show-real-text :real="item.phone" :type='type'></show-real-text>
16
+					</view>
17
+				</view>
18
+				<view class="info_row">
19
+					<view class="info_item">
20
+						<text class="label">收单时间: </text>
21
+						<text class="value">{{item.receiptDate || '-'}}</text>
22
+					</view>
23
+				</view>
24
+				<view class="info_row">
25
+					<view class="info_item">
26
+						<text class="label">收单人: </text>
27
+						<text class="value">{{item.receiptNickName || '-'}}</text>
28
+					</view>
29
+					<view class="info_item">
30
+						<text class="label">公司: </text>
31
+						<text class="value">{{item.orgName || '-'}}</text>
32
+					</view>
33
+				</view>
34
+				<view class="info_row">
35
+					<view class="info_item">
36
+						<text class="label">分成所属人: </text>
37
+						<text class="value">{{item.userName || '-'}}</text>
38
+					</view>
39
+					<view class="info_item">
40
+						<text class="label">分成比例: </text>
41
+						<text class="value">{{item.commissionRate || '-'}}%</text>
42
+					</view>
43
+				</view>
44
+			</view>
45
+			<view class="commission_amount">
46
+				<view class="amount_item">
47
+					<view class="amount_label">业绩</view>
48
+					<view class="amount_value primary">{{formatAmount(item.commissionAmount)}}</view>
49
+				</view>
50
+				<view class="amount_item">
51
+					<view class="amount_label">毛业绩</view>
52
+					<view class="amount_value">{{formatAmount(item.grossAmount)}}</view>
53
+				</view>
54
+			</view>
55
+		</view>
56
+
57
+		<!-- 加载更多 -->
58
+		<u-loadmore :status="loadStatus" v-if="listData.length > 0" />
59
+		<!-- 空状态 -->
60
+		<show-emtry v-if="listData.length === 0"></show-emtry>
61
+	</view>
62
+</template>
63
+
64
+<script>
65
+	import pullUpRefresh from "@/utils/pullUpRefresh";
66
+	export default {
67
+		mixins: [pullUpRefresh],
68
+		props: {
69
+			type: {
70
+				type: String,
71
+				default: '2'
72
+			},
73
+			showStats: {
74
+				type: Boolean,
75
+				default: true
76
+			}
77
+		},
78
+		data() {
79
+			return {
80
+				queryParams: {
81
+					pageNum: 1,
82
+					pageSize: 10,
83
+				},
84
+			}
85
+		},
86
+		methods: {
87
+			formatAmount(amount) {
88
+				if (!amount) return '-';
89
+				return parseFloat(amount).toLocaleString();
90
+			},
91
+			async getList() {
92
+				const {
93
+					pageNum,
94
+					pageSize,
95
+				} = this.queryParams;
96
+				this.queryParams.type = this.type;
97
+				// 调用分成接口
98
+				const {
99
+					rows,
100
+					total
101
+				} = await uni.$u.api.selectCommissionList({
102
+					pageSize,
103
+					pageNum,
104
+				}, this.queryParams);
105
+				return rows;
106
+			},
107
+			handleOnReachBottom() {
108
+				this.handleReachBottom();
109
+			}
110
+		},
111
+		mounted() {
112
+			this.resetData();
113
+		}
114
+	}
115
+</script>
116
+
117
+<style lang="scss" scoped>
118
+	.my_commission_wrap {
119
+		padding: 20px;
120
+	}
121
+
122
+	.stats_info_wrap {
123
+		margin-bottom: 30px;
124
+	}
125
+
126
+	.stats_info_top {
127
+		display: flex;
128
+		margin-bottom: 20px;
129
+
130
+		.info_item {
131
+			box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
132
+			width: 23%;
133
+			margin-right: 2.6%;
134
+			height: 120px;
135
+			padding: 15px;
136
+			background: #fff;
137
+			border-radius: 15px;
138
+
139
+			&:last-child {
140
+				margin-right: 0;
141
+			}
142
+
143
+			.info_title {
144
+				font-size: 14px;
145
+				color: #6b7280;
146
+				margin-bottom: 15px;
147
+			}
148
+
149
+			.info_value {
150
+				font-size: 24px;
151
+				font-weight: bold;
152
+				color: #202020;
153
+			}
154
+		}
155
+	}
156
+
157
+	.commission_item {
158
+		background: #fff;
159
+		border-radius: 20px;
160
+		padding: 20px;
161
+		margin-bottom: 20px;
162
+		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
163
+
164
+		.commission_top {
165
+			display: flex;
166
+			justify-content: space-between;
167
+			margin-bottom: 15px;
168
+
169
+			.top_left {
170
+				font-size: 18px;
171
+				font-weight: bold;
172
+				color: #202020;
173
+			}
174
+
175
+			.top_right {
176
+				.account_type {
177
+					background: #108cff;
178
+					color: #fff;
179
+					padding: 4px 8px;
180
+					border-radius: 10px;
181
+					font-size: 12px;
182
+				}
183
+			}
184
+		}
185
+
186
+		.commission_info {
187
+			margin-bottom: 15px;
188
+
189
+			.info_row {
190
+				display: flex;
191
+				margin-bottom: 8px;
192
+
193
+				&:last-child {
194
+					margin-bottom: 0;
195
+				}
196
+
197
+				.info_item {
198
+					flex: 1;
199
+					display: flex;
200
+					align-items: center;
201
+					font-size: 14px;
202
+
203
+					.label {
204
+						color: #9b9aa2;
205
+						margin-right: 8px;
206
+						min-width: 60px;
207
+					}
208
+
209
+					.value {
210
+						color: #202020;
211
+					}
212
+				}
213
+			}
214
+		}
215
+
216
+		.commission_amount {
217
+			display: flex;
218
+			justify-content: space-around;
219
+			padding: 15px 0;
220
+			border-top: 1px solid #f0f0f0;
221
+			background: #f8f9fb;
222
+			border-radius: 10px;
223
+
224
+			.amount_item {
225
+				text-align: center;
226
+
227
+				.amount_label {
228
+					font-size: 12px;
229
+					color: #9b9aa2;
230
+					margin-bottom: 5px;
231
+				}
232
+
233
+				.amount_value {
234
+					font-size: 16px;
235
+					font-weight: bold;
236
+					color: #202020;
237
+
238
+					&.primary {
239
+						color: #108cff;
240
+					}
241
+				}
242
+			}
243
+		}
244
+	}
245
+
246
+	.empty_wrap {
247
+		margin-top: 100px;
248
+	}
249
+</style>

+ 235 - 0
pages/order/components/orderCenter.vue

@@ -0,0 +1,235 @@
1
+<template>
2
+	<view class="order_center_wrap">
3
+		<view class="order_item" v-for="item in listData" :key="item.id" @click="handleToDetail(item)">
4
+			<view class="order_top">
5
+				<view class="top_left">{{item.item}}</view>
6
+				<view class="top_right">
7
+					<text :class="getStatusClass(item.status)">{{getStatusText(item.status)}}</text>
8
+				</view>
9
+			</view>
10
+			<view class="order_info">
11
+				<view class="telPhone">
12
+					<view class="phone">
13
+						<text>电话: </text>
14
+						<show-real-text :real="item.phone" :type='type'
15
+							:style="{ color : item.repetitionOperationName ? 'red' : 'black' }"></show-real-text>
16
+					</view>
17
+					<view class="copy_btn" @click.stop="handleCopy(item)" v-if="type != '1'">复制</view>
18
+				</view>
19
+				<view class="info">
20
+					<view class="createUser" style="margin-right: 20px;">发单人:
21
+						{{ item.createNickName ? item.createNickName : "-" }}</view>
22
+					<view class="orgName">机构: {{ item.orgName ? item.orgName : "-" }}</view>
23
+				</view>
24
+				<view class="info">
25
+					<view class="sendDate" style="margin-right: 20px;">发单日期: {{ item.sendDate ? item.sendDate : "-" }}
26
+					</view>
27
+				</view>
28
+				<view class="info">
29
+					<view class="owner">所属人 {{ item.clueOwnerName ? item.clueOwnerName : "-" }}</view>
30
+					<view class="operation" style="margin-right: 20px;">运营人
31
+						{{ item.clueOperationName ? item.clueOperationName : "-" }}</view>
32
+				</view>
33
+			</view>
34
+			<view class="clue_state_wrap">
35
+				<view class="clue_state">
36
+					<view class="state_wrap">
37
+						<view class="label">阶段:</view>{{crm_form_state(item.state)}}
38
+					</view>
39
+					<view class="clueTag">
40
+						<view class="label">标签:</view>
41
+						<u-tag :text="tag.name" plain plainFill borderColor="#fff" size="mini"
42
+							v-for="(tag) in item.tags" :key="tag.id" style="margin-right: 10px;"
43
+							:bgColor="tag.color" color="#fff"></u-tag>
44
+					</view>
45
+				</view>
46
+			</view>
47
+		</view>
48
+
49
+		<!-- 加载更多 -->
50
+		<u-loadmore :status="loadStatus" v-if="listData.length > 0" />
51
+		<!-- 空状态 -->
52
+		<show-emtry v-if="listData.length === 0"></show-emtry>
53
+	</view>
54
+</template>
55
+
56
+<script>
57
+	import pullUpRefresh from "@/utils/pullUpRefresh";
58
+	import { selectDictLabel } from "@/utils/util";
59
+	export default {
60
+		mixins: [pullUpRefresh],
61
+		props: {
62
+			type: {
63
+				type: String,
64
+				default: '2'
65
+			},
66
+			dicts: {
67
+				type: Object,
68
+				required: true
69
+			}
70
+		},
71
+		data() {
72
+			return {
73
+				// 可以添加特定于接单中心的参数
74
+				queryParams: {
75
+					pageNum: 1,
76
+					pageSize: 10,
77
+				},
78
+			}
79
+		},
80
+		methods: {
81
+			// 字典翻译
82
+			crm_form_state(state) {
83
+				return selectDictLabel(this.dicts.crmFormStateDicts, state);
84
+			},
85
+			getStatusText(status) {
86
+				const statusMap = {
87
+					'1': '发单',
88
+					'2': '接单',
89
+					'3': '收单',
90
+					'4': '未收'
91
+				};
92
+				return statusMap[status] || status;
93
+			},
94
+			getStatusClass(status) {
95
+				const classMap = {
96
+					'1': 'status_pending',
97
+					'2': 'status_received',
98
+					'3': 'status_confirmed',
99
+					'4': 'status_rejected'
100
+				};
101
+				return classMap[status] || 'status_default';
102
+			},
103
+			handleCopy(item) {
104
+				uni.setClipboardData({
105
+					data: item.phone,
106
+					success: function() {
107
+						uni.$u.toast("复制成功");
108
+					}
109
+				});
110
+			},
111
+			handleToDetail(item) {
112
+				// 跳转到详情页面
113
+				uni.navigateTo({
114
+					url: `/pages/orderDetail/index?id=${item.id}`
115
+				});
116
+			},
117
+			async getList() {
118
+				const {
119
+					pageNum,
120
+					pageSize,
121
+				} = this.queryParams;
122
+				this.queryParams.type = this.type;
123
+				// 调用接单中心的接口
124
+				const {
125
+					rows,
126
+					total
127
+				} = await uni.$u.api.selectClueOrderFormList({
128
+						pageSize,
129
+						pageNum
130
+					},
131
+					this.queryParams
132
+				);
133
+				return rows;
134
+			},
135
+			handleOnReachBottom() {
136
+				this.handleReachBottom();
137
+			}
138
+		},
139
+		mounted() {
140
+			this.resetData();
141
+		}
142
+	}
143
+</script>
144
+
145
+<style lang="scss" scoped>
146
+	.order_center_wrap {
147
+		padding: 20px;
148
+		box-sizing: border-box;
149
+		min-height: 100vh;
150
+	}
151
+
152
+	.order_item {
153
+		background: #fff;
154
+		border-radius: 20px;
155
+		padding: 20px;
156
+		margin-bottom: 20px;
157
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
158
+
159
+		.order_top {
160
+			display: flex;
161
+			justify-content: space-between;
162
+			margin-bottom: 15px;
163
+
164
+			.top_left {
165
+				font-size: 18px;
166
+				font-weight: bold;
167
+				color: #202020;
168
+			}
169
+
170
+			.top_right {
171
+				.status_pending {
172
+					color: #e65d6f;
173
+				}
174
+
175
+				.status_received {
176
+					color: #ff9900;
177
+				}
178
+
179
+				.status_confirmed {
180
+					color: #67c23a;
181
+				}
182
+
183
+				.status_rejected {
184
+					color: #909399;
185
+				}
186
+			}
187
+		}
188
+
189
+		.order_info {
190
+			font-size: 14px;
191
+			color: #666;
192
+
193
+			.telPhone {
194
+				display: flex;
195
+				margin-bottom: 10px;
196
+
197
+				.copy_btn {
198
+					color: #4fa5fe;
199
+					margin-left: 10px;
200
+				}
201
+			}
202
+
203
+			.info {
204
+				display: flex;
205
+				margin-bottom: 8px;
206
+
207
+				view {
208
+					flex: 1;
209
+				}
210
+			}
211
+		}
212
+	}
213
+
214
+	.empty_wrap {
215
+		margin-top: 100px;
216
+	}
217
+	
218
+	.clue_state_wrap {
219
+		font-size: 14px;
220
+		background: #f8f9fb;
221
+		padding: 10px;
222
+		color: #9b9aa2;
223
+		overflow: hidden;
224
+		.state_wrap{
225
+			display: flex;
226
+			margin-bottom: 10px;
227
+		}
228
+		.label{
229
+			flex: 0 0 40px !important;
230
+		}
231
+		.clueTag {
232
+			display: flex;
233
+		}
234
+	}
235
+</style>

+ 86 - 6
pages/order/index.vue

@@ -1,22 +1,102 @@
1
 <template>
1
 <template>
2
-	<view>
3
-		
2
+	<view class="order_wrap">
3
+		<u-navbar title="接单中心" :autoBack="true" :placeholder="true" v-hideNav></u-navbar>
4
+		<yui-tabs :tabs="tabs" v-model="activeIndex" :lineWidth="'120rpx'" :isLazyRender="true" color="#108cff"
5
+			titleActiveColor="#108cff" :swipeable="true" :swiper="false" :ellipsis="false" :scroll-threshold="3"
6
+			:sticky="true" :sticky-threshold="0" :offset-top="offsetTop" :z-index="99">
7
+			<template #orderCenter>
8
+				<orderCenter ref="orderCenter" type="1" :dicts="dicts"></orderCenter>
9
+			</template>
10
+			<template #myOrder>
11
+				<orderCenter ref="myOrder" type="2" :dicts="dicts"></orderCenter>
12
+			</template>
13
+			<template #myCommission>
14
+				<myCommission ref="myCommission" type="2" :showStats="true"></myCommission>
15
+			</template>
16
+		</yui-tabs>
4
 	</view>
17
 	</view>
5
 </template>
18
 </template>
6
 
19
 
7
 <script>
20
 <script>
21
+	import orderCenter from "./components/orderCenter";
22
+	import myCommission from "./components/myCommission";
23
+
8
 	export default {
24
 	export default {
25
+		components: {
26
+			orderCenter,
27
+			myCommission
28
+		},
29
+		onPullDownRefresh() {
30
+			uni.stopPullDownRefresh();
31
+			this.$refs[this.activeTel].resetData();
32
+		},
33
+		onReachBottom() {
34
+			this.$refs[this.activeTel].handleOnReachBottom();
35
+		},
36
+		computed: {
37
+			activeTel() {
38
+				return this.tabs.find(v => v.activeIndex === this.activeIndex).slot;
39
+			},
40
+		},
9
 		data() {
41
 		data() {
10
 			return {
42
 			return {
11
-				
43
+				activeIndex: 0,
44
+				offsetTop: 0,
45
+				tabs: [{
46
+						label: '接单中心',
47
+						slot: 'orderCenter',
48
+						activeIndex: 0,
49
+					}, {
50
+						label: '我的接发单',
51
+						slot: 'myOrder',
52
+						activeIndex: 1,
53
+					},
54
+					{
55
+						label: '我的分成',
56
+						slot: 'myCommission',
57
+						activeIndex: 2,
58
+					}
59
+				],
60
+				dicts : {
61
+					crmFormStateDicts : [],
62
+				}
12
 			}
63
 			}
13
 		},
64
 		},
65
+		mounted() {
66
+			// 页面初始化后的逻辑
67
+			uni.getSystemInfo({
68
+				success: (e) => {
69
+					let offsetTop = 0
70
+					// #ifdef H5
71
+					offsetTop = 43
72
+					// #endif
73
+					this.offsetTop = offsetTop;
74
+				}
75
+			});
76
+			this.$getDicts('crm_follow_status').then(res => {
77
+				this.dicts.crmFormStateDicts = res;
78
+			});
79
+		},
14
 		methods: {
80
 		methods: {
15
-			
16
-		}
81
+			// tab切换事件处理
82
+			handleTabChange(index) {
83
+				this.activeIndex = index;
84
+			}
85
+		},
86
+		// 页面滚动触发事件
87
+		onPageScroll(e) {
88
+			//页面滚动事件
89
+			uni.$emit('onPageScroll', e)
90
+		},
17
 	}
91
 	}
18
 </script>
92
 </script>
19
 
93
 
20
-<style>
94
+<style lang="scss" scoped>
95
+	::v-deep .yui-tabs__content {
96
+		background-color: transparent;
21
 
97
 
98
+		.yui-tabs__track {
99
+			background-color: transparent;
100
+		}
101
+	}
22
 </style>
102
 </style>

BIN
static/tabs/order.png


BIN
static/tabs/order1.png


+ 12 - 1
utils/api.js

@@ -75,12 +75,23 @@ const install = (Vue, vm) => {
75
 		deleteClueFile : (data)=> http.delete(store.state.user.path + '/clueFile/deleteClueFile',data),
75
 		deleteClueFile : (data)=> http.delete(store.state.user.path + '/clueFile/deleteClueFile',data),
76
 		getCallClueFileByClueId : (params)=> http.get(store.state.user.path + '/clueFile/getCallClueFileByClueId',{params, custom : { noAuth: true }}),
76
 		getCallClueFileByClueId : (params)=> http.get(store.state.user.path + '/clueFile/getCallClueFileByClueId',{params, custom : { noAuth: true }}),
77
 		getClueSendFormCountByClueId : (params = {},config = {})=>http.get(store.state.user.path + '/clueSendForm/getClueSendFormCountByClueId',{ params }),
77
 		getClueSendFormCountByClueId : (params = {},config = {})=>http.get(store.state.user.path + '/clueSendForm/getClueSendFormCountByClueId',{ params }),
78
-		saveClueOrderForm:(data,config={})=>http.post(store.state.user.path + '/clueSendForm/saveClueOrderForm',data),
78
+		// 订单相关接口
79
+		selectClueOrderFormList:(params={},data={})=>http.post(store.state.user.path + '/clueSendForm/list?' + qs.stringify(params),data),
80
+		oderForm:(data={})=>http.post(store.state.user.path + '/clueSendForm/oderForm',data),
81
+		updateTags:(data={})=>http.post(store.state.user.path + '/clueSendForm/updateTags',data),
82
+		addOrderFollow:(data={})=>http.post(store.state.user.path + '/orderFollow/addOrderFollow',data),
83
+		getOrderFollowListByOrderId:(params={})=>http.get(store.state.user.path + '/orderFollow/getOrderFollowListByOrderId',{params}),
84
+		deleteOrder:(data={})=>http.post(store.state.user.path + '/clueSendForm/deleteOrder',data),
85
+		updateOrderState:(data={})=>http.post(store.state.user.path + '/clueSendForm/updateOrderState',data),
86
+		updateClueOrderForm:(data={})=>http.post(store.state.user.path + '/clueSendForm/updateClueOrderForm',data),
87
+		
79
 		getOrderFollowListByClueId:(params = {},config = {})=>http.get(store.state.user.path + '/orderFollow/getOrderFollowListByClueId',{ params }),
88
 		getOrderFollowListByClueId:(params = {},config = {})=>http.get(store.state.user.path + '/orderFollow/getOrderFollowListByClueId',{ params }),
80
 		getDuplicateOrderFollowListByClueId:(params = {},config = {})=>http.get(store.state.user.path + '/orderFollow/getDuplicateOrderFollowListByClueId',{ params }),
89
 		getDuplicateOrderFollowListByClueId:(params = {},config = {})=>http.get(store.state.user.path + '/orderFollow/getDuplicateOrderFollowListByClueId',{ params }),
81
 		deleteOrderFollow:(data,config={})=>http.post(store.state.user.path + '/orderFollow/deleteOrderFollow',data),
90
 		deleteOrderFollow:(data,config={})=>http.post(store.state.user.path + '/orderFollow/deleteOrderFollow',data),
82
 		getOrderFollowList:(params = {},config = {})=>http.get(store.state.user.path + '/orderFollow/getOrderFollowList',{ params }),
91
 		getOrderFollowList:(params = {},config = {})=>http.get(store.state.user.path + '/orderFollow/getOrderFollowList',{ params }),
83
 		getDuplicateClueFollowByClueId:(params = {},config = {})=>http.get(store.state.user.path + '/clueFollow/getDuplicateClueFollowByClueId',{ params }),
92
 		getDuplicateClueFollowByClueId:(params = {},config = {})=>http.get(store.state.user.path + '/clueFollow/getDuplicateClueFollowByClueId',{ params }),
93
+		
94
+		selectCommissionList:(params={},data={})=>http.post(store.state.user.path + '/clueCommissionForm/list?' + qs.stringify(params),data),
84
 	}
95
 	}
85
 }
96
 }
86
 
97