Yannay месяцев назад: 2
Родитель
Сommit
bf720349f8

+ 17 - 0
pages.json

@@ -216,6 +216,14 @@
216 216
 			}
217 217
 		},
218 218
 		{
219
+			"path": "pages/orderDetailNew/index",
220
+			"style": {
221
+				"navigationBarTitleText": "",
222
+				"enablePullDownRefresh": true,
223
+				"navigationStyle": "custom"
224
+			}
225
+		},
226
+		{
219 227
 			"path": "pages/receiptForm/index",
220 228
 			"style": {
221 229
 				"navigationBarTitleText": "",
@@ -232,6 +240,15 @@
232 240
 				"navigationBarBackgroundColor": "#108cff",
233 241
 				"navigationStyle": "custom"
234 242
 			}
243
+		},
244
+		{
245
+			"path": "pages/acceptOrderOrder/index",
246
+			"style": {
247
+				"navigationBarTitleText": "接单中心",
248
+				"enablePullDownRefresh": false,
249
+				"navigationBarBackgroundColor": "#108cff",
250
+				"navigationStyle": "custom"
251
+			}
235 252
 		}
236 253
 	],
237 254
 	"globalStyle": {

+ 232 - 0
pages/acceptOrderOrder/compounts/orderCard.vue

@@ -0,0 +1,232 @@
1
+<template>
2
+    <view class="order-card" :class="{ 'order-card-overTime': order.isDelay }" @click.stop="handleClick(order)">
3
+        <view class="order-card-header">
4
+            <view class="order-card-header-left">
5
+                <view class="order-card-header-left-band" v-for="value in order.tags" :key="value.id"
6
+                    :style="{ backgroundColor: value.color }">
7
+                    {{ value.name }}
8
+                </view>
9
+                <view class="order-card-header-left-band" v-if="order.tags.length == 0" style="backgroundColor: #999;">
10
+                    暂无标签
11
+                </view>
12
+            </view>
13
+            <view class="order-card-header-right">
14
+                <view class="order-card-header-right-price">
15
+                    ¥{{ order.priceRange ? order.priceRange : '暂无价格' }}
16
+                </view>
17
+            </view>
18
+        </view>
19
+        <view class="order-card-content">
20
+            <view class="order-card-content-left">
21
+                <image :src="order.image ? order.image : '/static/acceptOrder/orderCardPic.jpg'" mode="scaleToFill" />
22
+            </view>
23
+            <view class="order-card-content-right">
24
+                <view>{{ order.item }}</view>
25
+                <view>发单人:{{ order.createNickName }}</view>
26
+                <view>{{ order.sendDate }}</view>
27
+            </view>
28
+        </view>
29
+
30
+        <view class="order-card-bottom">
31
+            <u-row justify="between" v-if="order.status == '1' || order.status == null">
32
+                <u-col span="5.5">
33
+                    <view @click.stop="handleAcceptOrder(order)">
34
+                        <u-button type="primary" size="medium">立即接单</u-button>
35
+                    </view>
36
+                </u-col>
37
+                <u-col span="5.5">
38
+                    <view @click.stop="handleBusy(order)">
39
+                        <u-button type="primary" size="medium">在忙</u-button>
40
+
41
+                    </view>
42
+                </u-col>
43
+            </u-row>
44
+            <u-row justify="between" v-if="order.status == '2'">
45
+                <u-col span="5.5">
46
+                    <view @click.stop="handleWillFollow(order)">
47
+                        <u-button type="primary" size="medium">待跟进</u-button>
48
+
49
+                    </view>
50
+                </u-col>
51
+                <u-col span="5.5">
52
+                    <view @click.stop="handleTag(order)">
53
+
54
+                        <u-button type="primary" size="medium">打标签</u-button>
55
+                    </view>
56
+                </u-col>
57
+            </u-row>
58
+            <u-row justify="between" v-if="order.status == '3'">
59
+                <u-col span="12">
60
+                    <view @click.stop="handleShare(order)">
61
+                        <u-button type="primary" size="medium">一键分享</u-button>
62
+                    </view>
63
+                </u-col>
64
+            </u-row>
65
+        </view>
66
+    </view>
67
+</template>
68
+
69
+<script>
70
+export default {
71
+    props: {
72
+        order: {
73
+            type: Object,
74
+            default: () => ({})
75
+        }
76
+    },
77
+    computed: {
78
+        statue() {
79
+            switch (this.order.status) {
80
+                case 'pending':
81
+                    return '待接单';
82
+                case 'received':
83
+                    return '已接单';
84
+                case 'rejected':
85
+                    return '已拒绝';
86
+            }
87
+        }
88
+    },
89
+    methods: {
90
+        handleAcceptOrder(order) {
91
+            console.log('立即接单',order);
92
+             this.$emit('handleCardClick', order);
93
+        },
94
+        handleWillFollow(order) {
95
+            console.log('待跟进', order);
96
+        },
97
+        handleBusy(order) {
98
+            console.log('在忙', order);
99
+        },
100
+        handleTag(order) {
101
+            console.log('打标签', order);
102
+        },
103
+        handleShare(order) {
104
+            console.log('一键分享', order);
105
+        },
106
+        handleClick(order) {
107
+            console.log('点击了订单', order);
108
+            this.$emit('handleCardClick', order);
109
+        }
110
+    }
111
+}
112
+</script>
113
+
114
+<style scoped>
115
+/* 样式部分无修改,保持原样 */
116
+.order-card {
117
+    box-sizing: border-box;
118
+    margin: 20rpx;
119
+    padding: 16rpx;
120
+    border-radius: 20rpx;
121
+    background-color: #fff;
122
+    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
123
+    border: 1px solid #000;
124
+    border-color: rgb(254 226 226 / var(--tw-border-opacity, 1));
125
+}
126
+
127
+.order-card-overTime {
128
+    background-color: rgba(254, 242, 242, 1);
129
+}
130
+
131
+.order-card-header {
132
+    display: flex;
133
+    justify-content: space-between;
134
+    align-items: center;
135
+}
136
+
137
+.order-card-header-left {
138
+    display: flex;
139
+}
140
+
141
+.order-card-header-left>view {
142
+    height: 30rpx;
143
+    line-height: 30rpx;
144
+    padding: 0 12rpx;
145
+    border-radius: 10rpx;
146
+    font-size: 20rpx;
147
+    font-weight: 700;
148
+    padding: 5rpx 12rpx;
149
+    margin-right: 10rpx;
150
+}
151
+
152
+.order-card-header-left-band {
153
+    --tw-text-opacity: 1;
154
+    --tw-border-opacity: 1;
155
+    --tw-bg-opacity: 1;
156
+    color: #fff;
157
+    background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
158
+    border: 1px solid #000;
159
+    border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
160
+}
161
+
162
+.order-card-header-left-status {
163
+    --tw-text-opacity: 1;
164
+    --tw-bg-opacity: 1;
165
+    color: rgb(255 107 107 / var(--tw-text-opacity, 1));
166
+    background-color: rgb(255 241 241 / var(--tw-bg-opacity, 1));
167
+    border: 1px solid #000;
168
+    border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
169
+}
170
+
171
+.order-card-header-left-timeout {
172
+    --tw-text-opacity: 1;
173
+    --tw-bg-opacity: 1;
174
+    color: rgb(255 107 107 / var(--tw-text-opacity, 1));
175
+    background-color: rgb(255 241 241 / var(--tw-bg-opacity, 1));
176
+    border: 1px solid #000;
177
+    border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
178
+}
179
+
180
+.order-card-header-left-phone {
181
+    --tw-text-opacity: 1;
182
+    --tw-bg-opacity: 1;
183
+    color: rgb(255 107 107 / var(--tw-text-opacity, 1));
184
+    background-color: rgb(255 241 241 / var(--tw-bg-opacity, 1));
185
+    border: 1px solid #000;
186
+    border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
187
+}
188
+
189
+.order-card-header-right-price {
190
+    font-weight: 800;
191
+    font-size: 1.5rem;
192
+}
193
+
194
+.order-card-content {
195
+    display: flex;
196
+    align-items: center;
197
+    margin-top: 20rpx;
198
+}
199
+
200
+.order-card-content image {
201
+    width: 150rpx;
202
+    height: 150rpx;
203
+    margin-right: 20rpx;
204
+    border-radius: 20rpx;
205
+}
206
+
207
+.order-card-content .order-card-content-right {
208
+    flex: 1;
209
+    font-size: 24rpx;
210
+    display: flex;
211
+    flex-direction: column;
212
+    gap: 10rpx;
213
+    font-size: 24rpx;
214
+    font-weight: 700;
215
+}
216
+
217
+.order-card-content .order-card-content-right>view:nth-child(1) {
218
+    font-size: 35rpx;
219
+    margin-bottom: 10rpx;
220
+}
221
+
222
+.order-card-bottom {
223
+    margin-top: 20rpx;
224
+}
225
+
226
+.order-card-bottom .u-button {
227
+    height: 70rpx;
228
+    border-radius: 20rpx;
229
+    font-size: 24rpx;
230
+    font-weight: 700;
231
+}
232
+</style>

+ 88 - 0
pages/acceptOrderOrder/index.vue

@@ -0,0 +1,88 @@
1
+<template>
2
+	<view class="container">
3
+		<u-navbar title="接单中心" :autoBack="true" :placeholder="true" v-hideNav></u-navbar>
4
+
5
+		<scroll-view class="scroll_wrap" scroll-y @scrolltolower="scrolltolower">
6
+			<order-card v-for="order in ordersList" :key="order.id" :order="order" @handleCardClick="handleCardClick"></order-card>
7
+			<view class="hasMore">
8
+				{{ ordersList.length >= page.total ? '没有更多了~' : '向下滑动加载更多~' }}
9
+			</view>
10
+		</scroll-view>
11
+	</view>
12
+</template>
13
+<script>
14
+import orderCard from "./compounts/orderCard.vue";
15
+
16
+
17
+
18
+export default {
19
+	components: {
20
+		orderCard
21
+	},
22
+	data() {
23
+		return {
24
+			ordersList: [],
25
+			page: {
26
+				pageSize: 10,
27
+				pageNum: 1,
28
+				total: 0
29
+			}
30
+		};
31
+	},
32
+	methods: {
33
+		async getOrderList() {
34
+
35
+			const { rows,total } = await uni.$u.api.selectClueOrderFormList({
36
+				pageSize: this.page.pageSize,
37
+				pageNum: this.page.pageNum,
38
+			}
39
+			);
40
+			console.log('接单列表', rows);
41
+			this.ordersList.push(...rows);
42
+			this.page.total=total;
43
+		},
44
+		scrolltolower() {
45
+			if(this.ordersList.length>=this.page.total){
46
+				return uni.$u.toast('没有更多了');
47
+			}
48
+			this.page.pageNum++;
49
+			this.getOrderList();
50
+		},
51
+		reset() {
52
+			this.ordersList = [];
53
+			this.page.pageNum = 1;
54
+		},
55
+		handleCardClick(order) {
56
+			console.log('点击了订单', order);
57
+			//跳转
58
+			// uni.navigateTo({
59
+			// 		url: `/pages/orderDetail/index?orderId=${order.id}&item=${order.item}&type=${this.type}&clueId=${order.clueId}`,
60
+			// 	})
61
+
62
+			//跳转新的页面
63
+			uni.navigateTo({
64
+				url: `/pages/orderDetailNew/index?orderId=${order.id}&item=${order.item}&type=${this.type}&clueId=${order.clueId}`,
65
+			})
66
+		},
67
+
68
+	},
69
+	onLoad() {
70
+		this.getOrderList();
71
+	}
72
+}
73
+
74
+
75
+
76
+</script>
77
+
78
+<style scoped>
79
+	.scroll_wrap {
80
+		height: calc( 100vh - 44px );
81
+	}
82
+	.hasMore {
83
+		text-align: center;
84
+		padding: 20rpx 0;
85
+		font-size: 24rpx;
86
+		color: #999;
87
+	}
88
+</style>

+ 192 - 91
pages/clue/post/index.vue

@@ -1,16 +1,17 @@
1 1
 <template>
2 2
 	<view class="post_item">
3 3
 		<view class="post_top">
4
-			<view class="top_left">{{item.name}}</view>
5
-			<view class="top_right">{{item.assignStateCode === '1' ? "已分配" : "未分配"}}</view>
4
+			<view class="top_left">{{ item.name }}</view>
5
+			<view class="top_right">{{ item.assignStateCode === '1' ? "已分配" : "未分配" }}</view>
6 6
 		</view>
7 7
 		<view class="post_info">
8 8
 			<view class="telPhone">
9 9
 				<view class="phone">
10 10
 					<text>电话: </text>
11
-					<show-real-text :real="item.telephone" :type='type' :style="{ color : item.repetitionOperationName ? 'red' : 'black' }"></show-real-text>
11
+					<show-real-text :real="item.telephone" :type='type'
12
+						:style="{ color: item.repetitionOperationName ? 'red' : 'black' }"></show-real-text>
12 13
 					<template v-if="item.telAddr">
13
-						({{item.telAddr}})
14
+						({{ item.telAddr }})
14 15
 					</template>
15 16
 					<text v-if="item.repetitionOperationName">( 撞 : {{ item.repetitionOperationName }})</text>
16 17
 				</view>
@@ -19,132 +20,232 @@
19 20
 			<view class="telPhone" v-if="item.weixin">
20 21
 				<text>微信: </text>
21 22
 				<view class="phone">
22
-					<text :style="{ color : item.repetitionOperWeixinName ? 'red' : 'black' }">{{item.weixin}}</text>
23
+					<text :style="{ color: item.repetitionOperWeixinName ? 'red' : 'black' }">{{ item.weixin }}</text>
23 24
 					<text v-if="item.repetitionOperWeixinName">( 撞 : {{ item.repetitionOperWeixinName }})</text>
24 25
 				</view>
25 26
 			</view>
26 27
 			<view class="info">
27 28
 				<view class="createTime">{{ item.createTime }}</view>
28
-				<view >{{ item.appName }}</view>
29
+				<view>{{ item.appName }}</view>
29 30
 			</view>
30 31
 			<view class="info">
31
-				<view class="owner" style="margin-right: 20px;">所属人 {{ item.clueOwnerName ? item.clueOwnerName : "-" }}</view>
32
-				<view class="operation">运营人 {{ item.clueOperationName ?  item.clueOperationName : "-" }}</view>
32
+				<view class="owner" style="margin-right: 20px;">所属人 {{ item.clueOwnerName ? item.clueOwnerName : "-" }}
33
+				</view>
34
+				<view class="operation">运营人 {{ item.clueOperationName ? item.clueOperationName : "-" }}</view>
33 35
 			</view>
34 36
 		</view>
35 37
 		<view class="clue_state_wrap">
36 38
 			<view class="clue_state">
37
-				<view class="state_wrap"><view class="label">线索阶段:</view>{{crm_clue_phase(item.clueState)}}</view>
39
+				<view class="state_wrap">
40
+					<view class="label">线索阶段:</view>{{ crm_clue_phase(item.clueState) }}
41
+				</view>
38 42
 				<view class="clueTag">
39 43
 					<view class="label">线索标签:</view>
40
-					<u-tag :text="tag.name" plain plainFill borderColor="#fff" size="mini" v-for="(tag) in item.clueTags" :key="tag.id" style="margin-right: 10px;" :bgColor="tag.color" color="#fff"></u-tag>
44
+					<u-tag :text="tag.name" plain plainFill borderColor="#fff" size="mini"
45
+						v-for="(tag) in item.clueTags" :key="tag.id" style="margin-right: 10px;" :bgColor="tag.color"
46
+						color="#fff"></u-tag>
41 47
 				</view>
42 48
 			</view>
43 49
 		</view>
50
+		<view class="sendOrder" @click.stop="handleSendOrder(item)">
51
+			<image src='/static/publicClue/littlePlane.png' mode="aspectFit" class="sendOrder_img"></image>
52
+			<view>发单</view>
53
+		</view>
44 54
 	</view>
45 55
 </template>
46 56
 
47 57
 <script>
48
-	import {
49
-		selectDictLabel
50
-	} from "@/utils/util";
51
-	export default {
52
-		props: {
53
-			item: {
54
-				type: Object,
55
-				required: true
56
-			},
57
-			dicts : {
58
-				type : Object,
59
-				required : true
60
-			},
61
-			type : {
62
-				type : String | Number,
63
-				required : true
64
-			},
58
+import {
59
+	selectDictLabel
60
+} from "@/utils/util";
61
+export default {
62
+	props: {
63
+		item: {
64
+			type: Object,
65
+			required: true
65 66
 		},
66
-		data() {
67
-			return {
68
-				caseStatusDicts : [],
69
-			}
67
+		dicts: {
68
+			type: Object,
69
+			required: true
70 70
 		},
71
-		methods: {
72
-			// 字典翻译
73
-			crm_clue_phase(caseStatus){
74
-				return selectDictLabel(this.dicts.caseStatusDicts,caseStatus);
75
-			},
76
-			handleCopy(item){
77
-				uni.setClipboardData({
78
-					data: item.telephone,
79
-					success: function () {
80
-						uni.$u.toast("复制成功");
71
+		type: {
72
+			type: String | Number,
73
+			required: true
74
+		},
75
+	},
76
+	data() {
77
+		return {
78
+			caseStatusDicts: [],
79
+		}
80
+	},
81
+	methods: {
82
+		// 字典翻译
83
+		crm_clue_phase(caseStatus) {
84
+			return selectDictLabel(this.dicts.caseStatusDicts, caseStatus);
85
+		},
86
+		handleCopy(item) {
87
+			uni.setClipboardData({
88
+				data: item.telephone,
89
+				success: function () {
90
+					uni.$u.toast("复制成功");
91
+				}
92
+			});
93
+		},
94
+		// 主页面的发单
95
+		async handleSendOrder(item) {
96
+			console.log(item);
97
+			const {
98
+				data: count
99
+			} = await uni.$u.api.getClueSendFormCountByClueId({
100
+				clueId: item.id
101
+			});
102
+			console.log(count);
103
+			if (count > 0) {
104
+				uni.showModal({
105
+					title: '该线索已发单是否再次发单?',
106
+					success: (res) => {
107
+						if (res.confirm) {
108
+							this.toOrderForm(item)
109
+						}
81 110
 					}
82 111
 				});
83
-			},
112
+			} else {
113
+				this.toOrderForm(item)
114
+			}
84 115
 		},
85
-	}
116
+		toOrderForm(item) {
117
+			console.log(item);
118
+			const {
119
+				id,
120
+				ownLatestDynamicTime,
121
+				createTime,
122
+				clueOwnerId
123
+			} = item;
124
+			if (this.$store.state.user.userInfo.userId === clueOwnerId) {
125
+				uni.navigateTo({
126
+					url: `/pages/orderForm/index?clueId=${id}`
127
+				})
128
+			} else {
129
+				// 确定用于判断的目标时间(ownLatestDynamicTime,为null则用createTime)
130
+				const date = ownLatestDynamicTime || createTime
131
+
132
+				const twoDaysLater = new Date(date)
133
+				twoDaysLater.setDate(twoDaysLater.getDate() + 2) // 日期加2天
134
+
135
+				// 是否大于当前时间 小于可以发单
136
+				let isOrderForm = false
137
+				if (twoDaysLater) {
138
+					isOrderForm = twoDaysLater.getTime() <= new Date().getTime()
139
+				}
140
+				if (isOrderForm) {
141
+					uni.navigateTo({
142
+						url: `/pages/orderForm/index?clueId=${id}`
143
+					})
144
+				} else {
145
+					uni.$u.toast('非所属人需两天内无跟进记录才可发单')
146
+				}
147
+			}
148
+		},
149
+	},
150
+}
86 151
 </script>
87 152
 
88 153
 <style lang="scss" scoped>
89
-	.post_item {
90
-		background: #fff;
91
-		border-radius: 20px;
92
-		padding: 20px;
93
-		margin-bottom: 20px;
94
-		.post_top {
95
-			display: flex;
96
-			justify-content: space-between;
97
-			margin-bottom: 10px;
98
-			.top_left {
99
-				font-size: 18px;
100
-			}
154
+.post_item {
155
+	background: #fff;
156
+	border-radius: 20px;
157
+	padding: 20px;
158
+	margin-bottom: 20px;
159
+	position: relative;
101 160
 
102
-			.top_right {
103
-				color: #87bf66;
104
-			}
161
+	.post_top {
162
+		display: flex;
163
+		justify-content: space-between;
164
+		margin-bottom: 10px;
165
+
166
+		.top_left {
167
+			font-size: 18px;
105 168
 		}
106 169
 
107
-		.post_info {
108
-			font-size: 14px;
109
-			.telPhone {
110
-				display: flex;
111
-				margin-bottom: 6px;
112
-				.copy_btn {
113
-					color: #4fa5fe;
114
-					margin-left: 10px;
115
-				}
116
-			}
170
+		.top_right {
171
+			color: #87bf66;
172
+		}
173
+	}
117 174
 
118
-			.info {
119
-				display: flex;
120
-				margin-bottom: 10px;
121
-				.createTime {
122
-					margin-right: 10px;
123
-				}
175
+	.post_info {
176
+		font-size: 14px;
124 177
 
125
-				.copy_btn {
126
-					display: flex;
127
-					flex-wrap: wrap;
128
-				}
178
+		.telPhone {
179
+			display: flex;
180
+			margin-bottom: 6px;
181
+
182
+			.copy_btn {
183
+				color: #4fa5fe;
184
+				margin-left: 10px;
129 185
 			}
130 186
 		}
131 187
 
132
-		.clue_state_wrap {
133
-			font-size: 14px;
134
-			background: #f8f9fb;
135
-			padding: 10px;
136
-			color: #9b9aa2;
137
-			overflow: hidden;
138
-			.state_wrap{
139
-				display: flex;
140
-				margin-bottom: 10px;
141
-			}
142
-			.label{
143
-				flex: 0 0 66px;
188
+		.info {
189
+			display: flex;
190
+			margin-bottom: 10px;
191
+
192
+			.createTime {
193
+				margin-right: 10px;
144 194
 			}
145
-			.clueTag {
195
+
196
+			.copy_btn {
146 197
 				display: flex;
198
+				flex-wrap: wrap;
147 199
 			}
148 200
 		}
149 201
 	}
202
+
203
+	.clue_state_wrap {
204
+		font-size: 14px;
205
+		background: #f8f9fb;
206
+		padding: 10px;
207
+		color: #9b9aa2;
208
+		overflow: hidden;
209
+
210
+		.state_wrap {
211
+			display: flex;
212
+			margin-bottom: 10px;
213
+		}
214
+
215
+		.label {
216
+			flex: 0 0 66px;
217
+		}
218
+
219
+		.clueTag {
220
+			display: flex;
221
+		}
222
+	}
223
+
224
+
225
+	.sendOrder {
226
+		width: 50px;
227
+		height: 50px;
228
+		background-color: rgb(36, 98, 234);
229
+		color: #fff;
230
+		border-radius: 50%;
231
+		display: flex;
232
+		flex-direction: column;
233
+		justify-content: center;
234
+		align-items: center;
235
+
236
+		font-size: 10px;
237
+		font-weight: 700;
238
+		font-family: "uicon";
239
+
240
+		position: absolute;
241
+		right: 20px;
242
+		bottom: 115px;
243
+
244
+
245
+		.sendOrder_img {
246
+			width: 20px;
247
+			height: 20px;
248
+		}
249
+	}
250
+}
150 251
 </style>

+ 19 - 12
pages/login/index.vue

@@ -144,19 +144,26 @@
144 144
 					}
145 145
 					this.$store.dispatch("user/login", this.form).then(async (userId) => {
146 146
 						// #ifdef H5
147
-						if(this.firstLoginState){
148
-							// 有state要绑定一下用户
149
-						  	await uni.$u.api.firstLogin({ userId , firstLoginState : this.firstLoginState });
147
+						uni.switchTab({
148
+							url: `/pages/person/index`,
149
+							success: () => {
150
+								this.$store.dispatch("app/register");
151
+								uni.$u.toast("登录成功");
152
+							}
153
+						})
154
+						// if(this.firstLoginState){
155
+						// 	// 有state要绑定一下用户
156
+						//   	await uni.$u.api.firstLogin({ userId , firstLoginState : this.firstLoginState });
150 157
 							
151
-							uni.reLaunch({
152
-								url:"/pages/bindSuccess/index",
153
-								success: () => {
154
-									uni.$u.toast("绑定成功");
155
-								}
156
-							});
157
-						}else{
158
-							uni.$u.toast("授权失败,无法绑定");
159
-						}
158
+						// 	uni.reLaunch({
159
+						// 		url:"/pages/bindSuccess/index",
160
+						// 		success: () => {
161
+						// 			uni.$u.toast("绑定成功");
162
+						// 		}
163
+						// 	});
164
+						// }else{
165
+						// 	uni.$u.toast("授权失败,无法绑定");
166
+						// }
160 167
 						// #endif
161 168
 						
162 169
 						// #ifdef  APP-PLUS

+ 202 - 0
pages/orderDetailNew/components/common.scss

@@ -0,0 +1,202 @@
1
+// 公共SCSS变量定义
2
+$colors: (
3
+    primary: #108cff,
4
+    primary-light: rgba(16, 140, 255, 0.08),
5
+    bg: #f9fafb,
6
+    card: #ffffff,
7
+    border: #f5f5f5,
8
+    text-primary: #1f2937,
9
+    text-secondary: #374151,
10
+    shadow: rgba(0, 0, 0, 0.05)
11
+);
12
+
13
+$sizes: (
14
+    radius: 16rpx,
15
+    padding: 32rpx,
16
+    padding-sm: 28rpx,
17
+    margin-sm: 18rpx,
18
+    margin-xs: 16rpx,
19
+    icon-padding: 14rpx,
20
+    font-title: 34rpx,
21
+    font-content: 32rpx,
22
+    line-height: 56rpx,
23
+    checkbox-size: 32rpx
24
+);
25
+
26
+// 字体优化
27
+$font: (
28
+    family: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif',
29
+    smoothing: antialiased
30
+);
31
+
32
+// 字体大小变量
33
+$font-sizes: (
34
+    title: 38rpx,
35
+    content: 34rpx,
36
+    sub-content: 30rpx,
37
+    small: 26rpx,
38
+    tiny: 24rpx
39
+);
40
+
41
+// 字体权重变量
42
+$font-weights: (
43
+    bold: 700,
44
+    semi-bold: 600,
45
+    medium: 500,
46
+    regular: 450,
47
+    light: 400
48
+);
49
+
50
+// 行高变量
51
+$line-heights: (
52
+    large: 56rpx,
53
+    medium: 48rpx,
54
+    small: 40rpx
55
+);
56
+
57
+// 字间距变量
58
+$letter-spacings: (
59
+    large: 1rpx,
60
+    medium: 0.8rpx,
61
+    small: 0.5rpx
62
+);
63
+
64
+// 文本颜色变量
65
+$text-colors: (
66
+    primary: map-get($colors, text-primary),
67
+    secondary: map-get($colors, text-secondary),
68
+    tertiary: #666666,
69
+    placeholder: #999999
70
+);
71
+
72
+// 公共混合宏
73
+@mixin flex-center {
74
+    display: flex;
75
+    align-items: center;
76
+}
77
+
78
+@mixin shadow($level: 1) {
79
+    $shadow-levels: (
80
+        1: 0 2rpx 12rpx map-get($colors, shadow),
81
+        2: 0 4rpx 20rpx map-get($colors, shadow),
82
+        3: 0 8rpx 30rpx map-get($colors, shadow)
83
+    );
84
+box-shadow: map-get($shadow-levels, $level);
85
+transition: box-shadow 0.3s ease;
86
+}
87
+
88
+@mixin card {
89
+    width: 100%;
90
+    margin: 0;
91
+    background-color: map-get($colors, card);
92
+    border-radius: map-get($sizes, radius);
93
+    @include shadow;
94
+}
95
+
96
+// 字体样式混合宏
97
+@mixin font-styles(
98
+    $size: content,
99
+    $weight: regular,
100
+    $color: primary,
101
+    $line-height: medium,
102
+    $letter-spacing: medium
103
+) {
104
+    font-size: map-get($font-sizes, $size);
105
+    font-weight: map-get($font-weights, $weight);
106
+    color: map-get($text-colors, $color);
107
+    line-height: map-get($line-heights, $line-height);
108
+    letter-spacing: map-get($letter-spacings, $letter-spacing);
109
+    font-family: map-get($font, family);
110
+}
111
+
112
+// 公共页面容器样式
113
+.page-container {
114
+    box-sizing: border-box;
115
+    padding: 0;
116
+    background-color: map-get($colors, bg);
117
+    font-family: map-get($font, family);
118
+    -webkit-font-smoothing: map-get($font, smoothing);
119
+    font-smoothing: map-get($font, smoothing);
120
+}
121
+
122
+// 公共字体样式
123
+// 页面主标题
124
+.page-title {
125
+    @include font-styles($size: title, $weight: bold, $color: primary);
126
+}
127
+
128
+// 卡片标题
129
+.card-title {
130
+    @include font-styles($size: title, $weight: bold, $color: primary);
131
+    border-bottom: 1rpx solid map-get($colors, border);
132
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
133
+    margin: 0;
134
+}
135
+
136
+// 地址标题
137
+.address-title {
138
+    @include font-styles($size: title, $weight: bold, $color: primary);
139
+    flex: 1;
140
+}
141
+
142
+// 主要内容文字
143
+.content-text {
144
+    @include font-styles;
145
+}
146
+
147
+// 辅助文字
148
+.auxiliary-text {
149
+    @include font-styles($size: small, $weight: regular, $color: tertiary, $line-height: small, $letter-spacing: small);
150
+}
151
+
152
+// 复选框/单选框文字
153
+.form-item-text {
154
+    @include font-styles;
155
+    vertical-align: middle;
156
+}
157
+
158
+// 空状态文字
159
+.empty-text {
160
+    @include font-styles;
161
+    text-align: center;
162
+}
163
+
164
+// 标签文字
165
+.label-text {
166
+    @include font-styles($size: tiny, $weight: regular, $color: tertiary);
167
+}
168
+
169
+// 值文字
170
+.value-text {
171
+    @include font-styles($size: small, $weight: regular, $color: secondary);
172
+}
173
+
174
+// 公共卡片样式
175
+.card_wrap {
176
+    @include card;
177
+    margin-bottom: 20rpx;
178
+
179
+    &:hover {
180
+        @include shadow(2);
181
+    }
182
+}
183
+
184
+// 公共地址标题样式
185
+.address-header {
186
+    @include flex-center;
187
+    margin-bottom: map-get($sizes, margin-sm);
188
+    padding-bottom: map-get($sizes, margin-sm);
189
+    border-bottom: 1rpx solid map-get($colors, border);
190
+
191
+    .location-icon {
192
+        margin-right: map-get($sizes, margin-xs);
193
+        background-color: map-get($colors, primary-light);
194
+        padding: map-get($sizes, icon-padding);
195
+        border-radius: 50%;
196
+        flex-shrink: 0;
197
+    }
198
+
199
+    .address-title {
200
+        margin-left: 16rpx;
201
+    }
202
+}

+ 102 - 0
pages/orderDetailNew/components/orderDetailNewView.vue

@@ -0,0 +1,102 @@
1
+<template>
2
+    <view class="orderDetailNewView">
3
+
4
+        <view class="page-item" v-show="activeIndex === 0">
5
+            <pageOne @handleNextClick="handleNextClick" />
6
+        </view>
7
+        <view class="page-item" v-show="activeIndex === 1">
8
+            <pageTwo @handleNextClick="handleNextClick" />
9
+        </view>
10
+        <view class="page-item" v-show="activeIndex === 2">
11
+            <pageThree @handleNextClick="handleNextClick" :detailImages="allFroms.formTwo.detailImages || []" />
12
+        </view>
13
+        <view class="page-item" v-show="activeIndex === 3">
14
+            <pageFour @handleNextClick="handleNextClick" />
15
+        </view>
16
+
17
+        <ul class="page">
18
+            <li v-for="(tab, index) in tabs" :key="index" :class="{ 'active': activeIndex === index }"
19
+                @click="activeIndex = index">{{ tab }}</li>
20
+        </ul>
21
+    </view>
22
+</template>
23
+
24
+<script>
25
+import pageOne from './pageOne.vue'
26
+import pageTwo from './pageTwo.vue'
27
+import pageThree from './pageThree.vue'
28
+import pageFour from './pageFour.vue'
29
+export default {
30
+    components: {
31
+        pageOne,
32
+        pageTwo,
33
+        pageThree,
34
+        pageFour
35
+    },
36
+    data() {
37
+        return {
38
+            activeIndex: 0,
39
+            tabs: ['一', '二', '三', '四'],
40
+            allFroms: {
41
+                formOne: {},
42
+                formTwo: {},
43
+                formThree: {},
44
+                formFour: {},
45
+            }
46
+        }
47
+    },
48
+    name: 'OrderDetailNewView',
49
+    methods: {
50
+        handleNextClick({ nowPage, form }) {
51
+            this.activeIndex++
52
+            this.allFroms[nowPage] = form
53
+            console.log("1111", this.allFroms[nowPage])
54
+        }
55
+
56
+    }
57
+}
58
+
59
+
60
+</script>
61
+
62
+<style scoped>
63
+.orderDetailNewView {
64
+    padding: 20rpx;
65
+}
66
+
67
+.page {
68
+    position: fixed;
69
+    right: 20rpx;
70
+    top: 40%;
71
+    display: flex;
72
+    flex-direction: column;
73
+    align-items: center;
74
+    justify-content: center;
75
+    list-style: none;
76
+    color: #000;
77
+    font-size: 20rpx;
78
+    font-weight: 800;
79
+
80
+    li {
81
+        opacity: 0.7;
82
+        display: flex;
83
+        align-items: center;
84
+        justify-content: center;
85
+        background-color: #fff;
86
+        border-radius: 50%;
87
+        width: 70rpx;
88
+        height: 70rpx;
89
+        line-height: 80rpx;
90
+        text-align: center;
91
+        margin-bottom: 10rpx;
92
+        transition: all 0.3s ease-in-out;
93
+        font-weight: 800;
94
+    }
95
+
96
+    li.active {
97
+        color: #fff;
98
+        opacity: 1;
99
+        background-color: rgb(37 99 235 / 1);
100
+    }
101
+}
102
+</style>

+ 5 - 0
pages/orderDetailNew/components/pageFour.vue

@@ -0,0 +1,5 @@
1
+<template>
2
+    <view>
3
+        4
4
+    </view>
5
+</template>

+ 337 - 0
pages/orderDetailNew/components/pageOne.vue

@@ -0,0 +1,337 @@
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"
9
+                    style="border-radius: 20rpx;border-color: #007AFF;color: #007AFF;">复制全部图片</u-button>
10
+            </u-col>
11
+        </u-row>
12
+
13
+        <!-- 实物图卡片 -->
14
+        <view class="card_wrap">
15
+            <view class="card-title">实物图</view>
16
+            <view class="image-upload-container">
17
+                <view class="image-list">
18
+                    <view class="image-item" v-for="(item, index) in form.truePic" :key="'truePic-' + index">
19
+                        <pic-comp :src="item"></pic-comp>
20
+                        <view class="delete-btn" @click="deleteImage('truePic', index)">×</view>
21
+                    </view>
22
+                    <view class="upload-btn" @click="uploadImage('truePic')">
23
+                        <u-icon name="plus" size="40" color="#999"></u-icon>
24
+                    </view>
25
+                </view>
26
+            </view>
27
+        </view>
28
+
29
+        <!-- 聊天记录卡片 -->
30
+        <view class="card_wrap">
31
+            <view class="card-title">聊天记录</view>
32
+            <view class="image-upload-container">
33
+                <view class="image-list">
34
+                    <view class="image-item" v-for="(item, index) in form.chatRecords" :key="'chatRecords-' + index">
35
+                        <pic-comp :src="item"></pic-comp>
36
+                        <view class="delete-btn" @click="deleteImage('chatRecords', index)">×</view>
37
+                    </view>
38
+                    <view class="upload-btn" @click="uploadImage('chatRecords')">
39
+                        <u-icon name="plus" size="40" color="#999"></u-icon>
40
+                    </view>
41
+                </view>
42
+            </view>
43
+        </view>
44
+
45
+        <!-- 基本信息卡片 -->
46
+        <view class="info-card">
47
+            <view class="info-card-title">基本信息</view>
48
+            <u-row class="info-row">
49
+                <u-col span="6">
50
+                    <view class="info-label">发单人</view>
51
+                    <view class="info-value">张三</view>
52
+                </u-col>
53
+                <u-col span="6">
54
+                    <view class="info-label">型号</view>
55
+                    <view class="info-value">iPhone 15 Pro</view>
56
+                </u-col>
57
+            </u-row>
58
+            <u-row class="info-row">
59
+                <u-col span="6">
60
+                    <view class="info-label">上门时间</view>
61
+                    <view class="info-value">2025-12-20 14:30</view>
62
+                </u-col>
63
+                <u-col span="6">
64
+                    <view class="info-label">地址</view>
65
+                    <view class="info-value">北京市朝阳区建国路88号</view>
66
+                </u-col>
67
+            </u-row>
68
+        </view>
69
+
70
+        <!-- 联系方式卡片 -->
71
+        <view class="connect">
72
+            <view class="connect-card phone-card" @click="handlePhoneClick">
73
+                <u-icon name="phone" size="40" color="#07C160" style="margin-bottom: 10rpx;"></u-icon>
74
+                <view class="connect-title">电话</view>
75
+                <!-- 小红点 -->
76
+                <view v-if="phone" class="red-dot"></view>
77
+            </view>
78
+            <view class="connect-card wechat-card" @click="handleWechatClick">
79
+                <u-icon name="chat" size="40" color="#07C160" style="margin-bottom: 10rpx;"></u-icon>
80
+                <view class="connect-title">微信</view>
81
+                <!-- 小红点 -->
82
+                <view v-if="wechat" class="red-dot"></view>
83
+            </view>
84
+        </view>
85
+
86
+        <u-button @click="handleNextClick" type="primary" size="middle" style="border-radius: 20rpx;">下一步</u-button>
87
+
88
+    </view>
89
+</template>
90
+<script>
91
+import picComp from './picComp.vue'
92
+
93
+export default {
94
+    components: {
95
+        picComp
96
+    },
97
+    data() {
98
+        return {
99
+            form: {
100
+                truePic: [],
101
+                chatRecords: [],
102
+            },
103
+            phone: '13800138000',
104
+            wechat: 'wechat123456',
105
+            // 控制小红点显示的变量
106
+        }
107
+    },
108
+    methods: {
109
+        // 上传图片
110
+        uploadImage(type) {
111
+            uni.chooseImage({
112
+                count: 9 - this.form[type].length, // 最多选择9张
113
+                sizeType: ['compressed'], // 压缩图片
114
+                sourceType: ['album', 'camera'], // 从相册选择或拍照
115
+                success: (res) => {
116
+                    const tempFilePaths = res.tempFilePaths
117
+                    // 将图片路径添加到对应的数组中
118
+                    this.form[type] = [...this.form[type], ...tempFilePaths]
119
+                    // 这里可以添加上传到服务器的逻辑
120
+                    // this.uploadToServer(tempFilePaths, type)
121
+                },
122
+                fail: (err) => {
123
+                    console.error('选择图片失败:', err)
124
+                }
125
+            })
126
+        },
127
+        // 删除图片
128
+        deleteImage(type, index) {
129
+            uni.showModal({
130
+                title: '提示',
131
+                content: '确定要删除这张图片吗?',
132
+                success: (res) => {
133
+                    if (res.confirm) {
134
+                        this.form[type].splice(index, 1)
135
+                    }
136
+                }
137
+            })
138
+        },
139
+        // 上传到服务器(示例)
140
+        uploadToServer(filePaths, type) {
141
+            filePaths.forEach((filePath, index) => {
142
+                uni.uploadFile({
143
+                    url: 'your-upload-api-url', // 替换为实际的上传接口
144
+                    filePath: filePath,
145
+                    name: 'file',
146
+                    formData: {
147
+                        type: type
148
+                    },
149
+                    success: (uploadRes) => {
150
+                        const data = JSON.parse(uploadRes.data)
151
+                        // 上传成功后,将临时路径替换为服务器返回的路径
152
+                        const tempIndex = this.form[type].indexOf(filePath)
153
+                        if (tempIndex !== -1) {
154
+                            this.form[type][tempIndex] = data.url // 假设服务器返回data.url
155
+                        }
156
+                    },
157
+                    fail: (err) => {
158
+                        console.error('上传图片失败:', err)
159
+                    }
160
+                })
161
+            })
162
+        },
163
+        // 电话卡片点击事件
164
+        handlePhoneClick() {
165
+            console.log('电话卡片被点击', '电话号码:', this.phone)
166
+            // 这里可以添加拨打电话的逻辑,例如调用uni.makePhoneCall
167
+        },
168
+        // 微信卡片点击事件
169
+        handleWechatClick() {
170
+            console.log('微信卡片被点击', '微信号:', this.wechat)
171
+            // 这里可以添加打开微信的逻辑
172
+        },
173
+        // 下一步
174
+        handleNextClick() {
175
+            // 校验表单
176
+            if (!this.form.truePic.length) {
177
+                uni.showToast({
178
+                    title: '请上传实物图',
179
+                    icon: 'none'
180
+                })
181
+                return
182
+            }
183
+            if (!this.form.chatRecords.length) {
184
+                uni.showToast({
185
+                    title: '请上传聊天记录',
186
+                    icon: 'none'
187
+                })
188
+                return
189
+            }
190
+            this.$emit('handleNextClick', {
191
+                nowPage: 'formOne',
192
+                form: this.form,
193
+            })
194
+        }
195
+    }
196
+}
197
+</script>
198
+<style scoped lang="scss">
199
+// 导入公共样式
200
+@import './common.scss';
201
+
202
+// 主样式
203
+.page-itemOne {
204
+    @extend .page-container;
205
+}
206
+
207
+.page-itemOne-title {
208
+    @include font-styles($size: title, $weight: bold, $color: primary);
209
+}
210
+
211
+.page-itemOne-form {
212
+    @include font-styles($size: tiny, $weight: semi-bold, $color: secondary);
213
+    text-wrap: nowrap;
214
+}
215
+
216
+.image-upload-container {
217
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
218
+}
219
+
220
+.image-list {
221
+    display: flex;
222
+    flex-wrap: wrap;
223
+    gap: 20rpx;
224
+}
225
+
226
+.image-item {
227
+    position: relative;
228
+    width: 200rpx;
229
+    height: 200rpx;
230
+    box-sizing: border-box;
231
+}
232
+
233
+.delete-btn {
234
+    position: absolute;
235
+    top: -10rpx;
236
+    right: -10rpx;
237
+    width: 40rpx;
238
+    height: 40rpx;
239
+    background-color: #ff4d4f;
240
+    color: #fff;
241
+    border-radius: 50%;
242
+    display: flex;
243
+    align-items: center;
244
+    justify-content: center;
245
+    @include font-styles($size: tiny, $weight: bold);
246
+    z-index: 10;
247
+}
248
+
249
+.upload-btn {
250
+    width: 200rpx;
251
+    height: 200rpx;
252
+    border: 8rpx dashed #ddd;
253
+    border-radius: 30rpx;
254
+    display: flex;
255
+    align-items: center;
256
+    justify-content: center;
257
+    background-color: #f9f9f9;
258
+    box-sizing: border-box;
259
+}
260
+
261
+/* 基本信息卡片样式 */
262
+.info-card {
263
+    @include card;
264
+    margin-top: 20rpx;
265
+    margin-bottom: 20rpx;
266
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
267
+
268
+    &:hover {
269
+        @include shadow(2);
270
+    }
271
+}
272
+
273
+.info-card-title {
274
+    @include font-styles($size: title, $weight: bold, $color: primary);
275
+    margin-bottom: 25rpx;
276
+    padding-bottom: 15rpx;
277
+    border-bottom: 1rpx solid map-get($colors, border);
278
+}
279
+
280
+.info-row {
281
+    margin-bottom: 20rpx;
282
+}
283
+
284
+.info-label {
285
+    @include font-styles($size: tiny, $weight: regular, $color: tertiary);
286
+    margin-bottom: 8rpx;
287
+}
288
+
289
+.info-value {
290
+    @include font-styles($size: small, $weight: regular, $color: secondary, $line-height: small);
291
+    word-break: break-all;
292
+}
293
+
294
+/* 联系方式卡片样式 */
295
+.connect {
296
+    display: flex;
297
+    justify-content: space-between;
298
+    margin: 20rpx 0;
299
+    gap: 20rpx;
300
+}
301
+
302
+.connect-card {
303
+    flex: 1;
304
+    @include card;
305
+    padding: 30rpx;
306
+    display: flex;
307
+    flex-direction: column;
308
+    align-items: center;
309
+    box-sizing: border-box;
310
+    position: relative;
311
+
312
+    &:hover {
313
+        @include shadow(2);
314
+    }
315
+}
316
+
317
+.connect-title {
318
+    @include font-styles($size: tiny, $weight: regular, $color: tertiary);
319
+    margin-bottom: 8rpx;
320
+}
321
+
322
+.connect-value {
323
+    @include font-styles($size: small, $weight: medium, $color: secondary);
324
+}
325
+
326
+/* 小红点样式 */
327
+.red-dot {
328
+    position: absolute;
329
+    top: 15rpx;
330
+    right: 15rpx;
331
+    width: 16rpx;
332
+    height: 16rpx;
333
+    background-color: #ff4d4f;
334
+    border-radius: 50%;
335
+    box-shadow: 0 0 4rpx rgba(255, 77, 79, 0.3);
336
+}
337
+</style>

+ 202 - 0
pages/orderDetailNew/components/pageThree.vue

@@ -0,0 +1,202 @@
1
+<template>
2
+    <view class="page-container">
3
+        <view class="card_wrap">
4
+            <view class="detail-image-section">
5
+                <view class="address-header">
6
+                    <text class="address-title">高清细节图</text>
7
+                </view>
8
+                <view class="detail-image-content">
9
+                    <view v-if="detailImages.length > 0" class="detail-image-list">
10
+                        <view class="detail-image-item" v-for="(item, index) in detailImages" :key="'detail-' + index">
11
+                            <pic-comp :src="item"></pic-comp>
12
+                        </view>
13
+                    </view>
14
+                    <view v-else class="no-images">暂无高清细节图</view>
15
+                </view>
16
+            </view>
17
+        </view>
18
+
19
+        <!-- 支付信息录入卡片 -->
20
+        <view class="info-card">
21
+            <view class="info-card-title">支付信息</view>
22
+            <!-- 开户人和银行名称同一行 -->
23
+            <u-row class="info-row" justify="space-between">
24
+                <u-col span="5.8">
25
+                    <view class="info-label">开户人</view>
26
+                    <u-input v-model="paymentInfo.accountHolder" placeholder="请输入开户人姓名" class="info-input" />
27
+                </u-col>
28
+                <u-col span="5.8">
29
+                    <view class="info-label">银行名称</view>
30
+                    <u-input v-model="paymentInfo.bankName" placeholder="请输入银行名称" class="info-input" />
31
+                </u-col>
32
+            </u-row>
33
+            <!-- 银行账号单独一行 -->
34
+            <u-row class="info-row">
35
+                <u-col span="12">
36
+                    <view class="info-label">银行账号</view>
37
+                    <u-input v-model="paymentInfo.bankAccount" placeholder="请输入银行账号" class="info-input" />
38
+                </u-col>
39
+            </u-row>
40
+            <!-- 身份证号单独一行 -->
41
+            <u-row class="info-row">
42
+                <u-col span="12">
43
+                    <view class="info-label">身份证号</view>
44
+                    <u-input v-model="paymentInfo.idNumber" placeholder="请输入身份证号" class="info-input" />
45
+                </u-col>
46
+            </u-row>
47
+        </view>
48
+    </view>
49
+</template>
50
+
51
+<script>
52
+import picComp from './picComp.vue'
53
+
54
+export default {
55
+    components: {
56
+        picComp
57
+    },
58
+    props: {
59
+        detailImages: {
60
+            type: Array,
61
+            default: () => []
62
+        }
63
+    },
64
+    data() {
65
+        return {
66
+            // 支付信息
67
+            paymentInfo: {
68
+                accountHolder: '', // 开户人
69
+                bankName: '', // 银行名称
70
+                bankAccount: '', // 银行账号
71
+                idNumber: '' // 身份证号
72
+            }
73
+        };
74
+    },
75
+    methods: {
76
+        // 下一步按钮点击事件
77
+        handleNextClick() {
78
+            this.$emit('handleNextClick', {
79
+                nowPage: 'formThree',
80
+                form: {
81
+                    detailImages: this.detailImages,
82
+                    paymentInfo: this.paymentInfo
83
+                }
84
+            });
85
+        }
86
+    }
87
+}
88
+</script>
89
+
90
+<style lang="scss" scoped>
91
+// 导入公共样式
92
+@import './common.scss';
93
+
94
+// 主样式
95
+.page-container {
96
+    box-sizing: border-box;
97
+    padding: 0;
98
+    background-color: map-get($colors, bg);
99
+    font-family: map-get($font, family);
100
+    -webkit-font-smoothing: map-get($font, smoothing);
101
+    font-smoothing: map-get($font, smoothing);
102
+}
103
+
104
+.card_wrap {
105
+    @include card;
106
+    margin-bottom: 20rpx;
107
+
108
+    &:hover {
109
+        @include shadow(2);
110
+    }
111
+}
112
+
113
+.detail-image-section {
114
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
115
+}
116
+
117
+.detail-image-content {
118
+
119
+    .detail-image-list {
120
+        display: flex;
121
+        flex-wrap: wrap;
122
+        gap: 24rpx;
123
+    }
124
+
125
+    .detail-image-item {
126
+        width: calc((100% - 24rpx * 2) / 3);
127
+        aspect-ratio: 1 / 1;
128
+        border-radius: 12rpx;
129
+        overflow: hidden;
130
+        box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
131
+        background-color: #f9f9f9;
132
+        transition: all 0.3s ease;
133
+
134
+        &:hover {
135
+            transform: translateY(-2rpx);
136
+            box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
137
+        }
138
+    }
139
+
140
+    .no-images {
141
+        @include font-styles($size: content, $weight: regular, $color: tertiary);
142
+        text-align: center;
143
+        padding: 80rpx 0;
144
+        background-color: #f9f9f9;
145
+        border-radius: 12rpx;
146
+    }
147
+}
148
+
149
+/* 支付信息卡片样式 */
150
+.info-card {
151
+    @include card;
152
+    margin-top: 20rpx;
153
+    margin-bottom: 20rpx;
154
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
155
+    box-sizing: border-box;
156
+
157
+    &:hover {
158
+        @include shadow(2);
159
+    }
160
+
161
+    .u-col {
162
+        padding: 0;
163
+        box-sizing: border-box;
164
+    }
165
+
166
+    .u-col:first-child {
167
+        padding-right: 15rpx;
168
+    }
169
+
170
+    .u-col:last-child {
171
+        padding-left: 15rpx;
172
+    }
173
+}
174
+
175
+.info-card-title {
176
+    @include font-styles($size: title, $weight: bold, $color: primary);
177
+    margin-bottom: 25rpx;
178
+    padding-bottom: 15rpx;
179
+    border-bottom: 1rpx solid map-get($colors, border);
180
+}
181
+
182
+.info-row {
183
+    margin-bottom: 20rpx;
184
+    box-sizing: border-box;
185
+    padding: 0;
186
+}
187
+
188
+.info-label {
189
+    @include font-styles($size: tiny, $weight: regular, $color: tertiary);
190
+    margin-bottom: 8rpx;
191
+    display: block;
192
+}
193
+
194
+.info-input {
195
+    border-radius: 8rpx;
196
+    border: 1rpx solid #e5e7eb;
197
+    padding: 12rpx 16rpx;
198
+    width: 100%;
199
+    box-sizing: border-box;
200
+    @include font-styles($size: small, $weight: regular, $color: secondary);
201
+}
202
+</style>

+ 835 - 0
pages/orderDetailNew/components/pageTwo.vue

@@ -0,0 +1,835 @@
1
+<template>
2
+    <view class="page-container">
3
+        <view class="card_wrap">
4
+            <view class="address-section">
5
+                <view class="address-header">
6
+                    <u-icon name="map" size="36rpx" color="#108cff" class="location-icon"></u-icon>
7
+                    <text class="address-title">上门地址</text>
8
+                </view>
9
+                <view class="address-content">
10
+                    <text class="address-text">北京市朝阳区建国路88号SOHO现代城A座2301室</text>
11
+                </view>
12
+            </view>
13
+        </view>
14
+
15
+        <view class="card_wrap checklist-card">
16
+            <view class="checklist-section">
17
+                <u-checkbox-group v-model="selectedCheckbox" placement="column">
18
+                    <view class="checklist-item">
19
+                        <view class="checkbox-text-container">
20
+                            <u-checkbox name="contact师傅" size="40rpx" color="#108cff" />
21
+                            <text class="checklist-text">联系师傅</text>
22
+                        </view>
23
+                        <u-input v-if="selectedCheckbox.includes('contact师傅')" v-model="formData.contactPhone"
24
+                            placeholder="请输入师傅手机号" size="default" class="checklist-input" />
25
+                    </view>
26
+                    <view class="checklist-item">
27
+                        <view class="checkbox-text-container">
28
+                            <u-checkbox name="photo技巧" size="40rpx" color="#108cff" />
29
+                            <text class="checklist-text">师傅拍图技巧</text>
30
+                        </view>
31
+                        <u-input v-if="selectedCheckbox.includes('photo技巧')" v-model="formData.photoTips"
32
+                            type="textarea" placeholder="请输入拍图技巧" rows="3" class="checklist-textarea" />
33
+                        <!-- 上传图片按钮 -->
34
+                        <view v-if="selectedCheckbox.includes('photo技巧')" class="upload-btn-container">
35
+                            <div class="upload-btn" @click="chooseImage('photoTips')">
36
+                                <u-icon name="camera" size="32rpx" color="#108cff"></u-icon>
37
+                                <text class="upload-btn-text">上传图片</text>
38
+                            </div>
39
+                        </view>
40
+                        <!-- 图片显示区域 -->
41
+                        <view v-if="selectedCheckbox.includes('photo技巧') && photoTipsImages.length > 0"
42
+                            class="image-list">
43
+                            <view v-for="(image, index) in photoTipsImages" :key="index" class="image-item"
44
+                                @click="previewImageHandler(image, 'photoTips')">
45
+                                <image :src="image" mode="aspectFill" class="image-thumb"></image>
46
+                            </view>
47
+                        </view>
48
+                    </view>
49
+                    <view class="checklist-item">
50
+                        <view class="checkbox-text-container">
51
+                            <u-checkbox name="face2face" size="40rpx" color="#108cff" />
52
+                            <text class="checklist-text">到达客户面对面</text>
53
+                        </view>
54
+                        <u-input v-if="selectedCheckbox.includes('face2face')" v-model="formData.face2faceNotes"
55
+                            type="textarea" placeholder="请输入备注信息" rows="3" class="checklist-textarea" />
56
+                        <!-- 上传图片按钮 -->
57
+                        <view v-if="selectedCheckbox.includes('face2face')" class="upload-btn-container">
58
+                            <div class="upload-btn" @click="chooseImage('face2face')">
59
+                                <u-icon name="camera" size="32rpx" color="#108cff"></u-icon>
60
+                                <text class="upload-btn-text">上传图片</text>
61
+                            </div>
62
+                        </view>
63
+                        <!-- 图片显示区域 -->
64
+                        <view v-if="selectedCheckbox.includes('face2face') && face2faceImages.length > 0"
65
+                            class="image-list">
66
+                            <view v-for="(image, index) in face2faceImages" :key="index" class="image-item"
67
+                                @click="previewImageHandler(image, 'face2face')">
68
+                                <image :src="image" mode="aspectFill" class="image-thumb"></image>
69
+                            </view>
70
+                        </view>
71
+                    </view>
72
+                </u-checkbox-group>
73
+            </view>
74
+        </view>
75
+
76
+        <!-- 新添加的数字选择器卡片 -->
77
+        <view class="card_wrap price-card">
78
+            <view class="price-section">
79
+                <view class="price-picker-container">
80
+                    <!-- 上方快速操作按钮 -->
81
+                    <view class="quick-actions top-actions">
82
+                        <div class="quick-btn increase" @click="quickChangePrice(100)">+100</div>
83
+                        <div class="quick-btn increase" @click="quickChangePrice(1000)">+1000</div>
84
+                    </view>
85
+
86
+                    <!-- 数字选择器 -->
87
+                    <view class="number-box-container">
88
+                        <view class="price-input-box">
89
+                            <text class="price-label">核准价¥</text>
90
+                            <input type="number" v-model="approvedPrice" class="price-input" placeholder="0" min="0"
91
+                                @input="onPriceInput" />
92
+                        </view>
93
+                    </view>
94
+
95
+                    <!-- 下方快速操作按钮 -->
96
+                    <view class="quick-actions bottom-actions">
97
+                        <div class="quick-btn decrease" @click="quickChangePrice(-100)">-100</div>
98
+                        <div class="quick-btn decrease" @click="quickChangePrice(-1000)">-1000</div>
99
+                    </view>
100
+                </view>
101
+            </view>
102
+        </view>
103
+
104
+        <!-- 新添加的高清细节图上传卡片 -->
105
+        <view class="card_wrap detail-image-card">
106
+            <view class="detail-image-section">
107
+                <div class="detail-image-header">
108
+                    <div class="detail-image-title">上传高清细节图(支持多选)</div>
109
+                    <div class="copy-btn" @click="copyAllDetailImages">
110
+                        <text>一键复制</text>
111
+                    </div>
112
+                </div>
113
+                <div class="detail-image-upload-container">
114
+                    <view class="detail-image-list">
115
+                        <view class="detail-image-item" v-for="(item, index) in detailImages" :key="'detail-' + index">
116
+                            <pic-comp :src="item"></pic-comp>
117
+                            <view class="detail-delete-btn" @click="deleteDetailImage(index)">×</view>
118
+                        </view>
119
+                        <view class="detail-upload-btn" @click="uploadDetailImage">
120
+                            <u-icon name="plus" size="40rpx" color="#999"></u-icon>
121
+                        </view>
122
+                    </view>
123
+                </div>
124
+            </view>
125
+        </view>
126
+
127
+        <u-button @click="handleNextClick" type="primary" size="middle" style="border-radius: 20rpx;">下一步</u-button>
128
+    </view>
129
+</template>
130
+
131
+<script>
132
+import picComp from './picComp.vue'
133
+
134
+export default {
135
+    components: {
136
+        picComp
137
+    },
138
+    data() {
139
+        return {
140
+            selectedCheckbox: [],
141
+            formData: {
142
+                contactPhone: '',
143
+                photoTips: '',
144
+                face2faceNotes: ''
145
+            },
146
+            // 图片相关数据
147
+            photoTipsImages: [], // 师傅技巧图片数组
148
+            face2faceImages: [], // 到达客户面对面图片数组
149
+            // 全屏预览相关
150
+            previewImage: '', // 当前预览的图片
151
+            showPreview: false, // 是否显示全屏预览
152
+            // 核准价格相关
153
+            approvedPrice: 0, // 核准价格初始值
154
+            // 高清细节图相关
155
+            detailImages: [] // 高清细节图数组
156
+        };
157
+    },
158
+    methods: {
159
+        // 选择图片方法
160
+        chooseImage(type) {
161
+            uni.chooseImage({
162
+                count: 9, // 最多选择9张图片
163
+                sizeType: ['original', 'compressed'], // 原图或压缩图
164
+                sourceType: ['album', 'camera'], // 从相册或相机选择
165
+                success: (res) => {
166
+                    const tempFilePaths = res.tempFilePaths;
167
+                    // 根据类型将图片添加到对应的数组
168
+                    if (type === 'photoTips') {
169
+                        this.photoTipsImages = [...this.photoTipsImages, ...tempFilePaths];
170
+                    } else if (type === 'face2face') {
171
+                        this.face2faceImages = [...this.face2faceImages, ...tempFilePaths];
172
+                    }
173
+                },
174
+                fail: (err) => {
175
+                    console.error('选择图片失败:', err);
176
+                    uni.showToast({
177
+                        title: '选择图片失败',
178
+                        icon: 'none'
179
+                    });
180
+                }
181
+            });
182
+        },
183
+        // 图片预览方法
184
+        previewImageHandler(image, type) {
185
+            let currentIndex = 0;
186
+            let imageList = [];
187
+
188
+            // 根据类型获取对应的图片数组
189
+            if (type === 'photoTips') {
190
+                imageList = this.photoTipsImages;
191
+                currentIndex = imageList.indexOf(image);
192
+            } else if (type === 'face2face') {
193
+                imageList = this.face2faceImages;
194
+                currentIndex = imageList.indexOf(image);
195
+            }
196
+
197
+            // 使用uni-app的图片预览API
198
+            uni.previewImage({
199
+                current: currentIndex, // 当前预览图片的索引
200
+                urls: imageList, // 需要预览的图片链接列表
201
+                loop: true, // 是否可循环预览
202
+                longPressActions: {
203
+                    itemList: ['保存图片'],
204
+                    success: function (data) {
205
+                        // 保存图片到相册
206
+                        uni.saveImageToPhotosAlbum({
207
+                            filePath: imageList[data.tapIndex],
208
+                            success: function () {
209
+                                uni.showToast({
210
+                                    title: '保存成功',
211
+                                    icon: 'success'
212
+                                });
213
+                            },
214
+                            fail: function (err) {
215
+                                console.error('保存图片失败:', err);
216
+                                uni.showToast({
217
+                                    title: '保存失败',
218
+                                    icon: 'none'
219
+                                });
220
+                            }
221
+                        });
222
+                    }
223
+                }
224
+            });
225
+        },
226
+
227
+        // 价格输入回调
228
+        onPriceInput(e) {
229
+            // 确保价格是数字且不小于0
230
+            let value = Number(e.detail.value);
231
+            if (isNaN(value)) value = 0;
232
+            value = Math.max(0, value);
233
+            this.approvedPrice = value;
234
+        },
235
+
236
+        // 快速调整价格
237
+        quickChangePrice(amount) {
238
+            let newPrice = this.approvedPrice + amount;
239
+            // 确保价格不小于0
240
+            newPrice = Math.max(0, newPrice);
241
+            this.approvedPrice = newPrice;
242
+        },
243
+
244
+        // 上传高清细节图
245
+        uploadDetailImage() {
246
+            uni.chooseImage({
247
+                count: 9 - this.detailImages.length, // 最多选择9张
248
+                sizeType: ['compressed'], // 压缩图片
249
+                sourceType: ['album', 'camera'], // 从相册选择或拍照
250
+                success: (res) => {
251
+                    const tempFilePaths = res.tempFilePaths;
252
+                    // 将图片路径添加到数组中
253
+                    this.detailImages = [...this.detailImages, ...tempFilePaths];
254
+                },
255
+                fail: (err) => {
256
+                    console.error('选择图片失败:', err);
257
+                    uni.showToast({
258
+                        title: '选择图片失败',
259
+                        icon: 'none'
260
+                    });
261
+                }
262
+            });
263
+        },
264
+
265
+        // 删除高清细节图
266
+        deleteDetailImage(index) {
267
+            uni.showModal({
268
+                title: '提示',
269
+                content: '确定要删除这张图片吗?',
270
+                success: (res) => {
271
+                    if (res.confirm) {
272
+                        this.detailImages.splice(index, 1);
273
+                    }
274
+                }
275
+            });
276
+        },
277
+
278
+        // 复制所有高清细节图链接
279
+        copyAllDetailImages() {
280
+            if (this.detailImages.length === 0) {
281
+                uni.showToast({
282
+                    title: '暂无图片可复制',
283
+                    icon: 'none'
284
+                });
285
+                return;
286
+            }
287
+
288
+            const imageUrls = this.detailImages.join('\n');
289
+            uni.setClipboardData({
290
+                data: imageUrls,
291
+                success: () => {
292
+                    uni.showToast({
293
+                        title: '复制成功',
294
+                        icon: 'success'
295
+                    });
296
+                },
297
+                fail: () => {
298
+                    uni.showToast({
299
+                        title: '复制失败',
300
+                        icon: 'none'
301
+                    });
302
+                }
303
+            });
304
+        },
305
+
306
+        // 下一步按钮点击事件
307
+        handleNextClick() {
308
+            // 创建一个只包含被勾选checkbox对应数据的对象
309
+            const result = {};
310
+
311
+            // 检查联系师傅
312
+            if (this.selectedCheckbox.includes('contact师傅')) {
313
+                result.contactPhone = this.formData.contactPhone;
314
+            }
315
+
316
+            // 检查师傅拍图技巧
317
+            if (this.selectedCheckbox.includes('photo技巧')) {
318
+                result.photoTips = this.formData.photoTips;
319
+                result.photoTipsImages = this.photoTipsImages;
320
+            }
321
+
322
+            // 检查到达客户面对面
323
+            if (this.selectedCheckbox.includes('face2face')) {
324
+                result.face2faceNotes = this.formData.face2faceNotes;
325
+                result.face2faceImages = this.face2faceImages;
326
+            }
327
+
328
+            // 添加其他非checkbox控制的字段
329
+            result.approvedPrice = this.approvedPrice;
330
+            result.detailImages = this.detailImages;
331
+            // result.selectedCheckbox = this.selectedCheckbox;
332
+
333
+            // 打印结果对象
334
+            // console.log('当前界面的选中值:', result);
335
+
336
+            this.$emit('handleNextClick', {
337
+                nowPage: 'formTwo',
338
+                form: result,
339
+            })
340
+        }
341
+    }
342
+};
343
+</script>
344
+
345
+<style scoped lang="scss">
346
+// 导入公共样式
347
+@import './common.scss';
348
+
349
+// 主样式
350
+.page-container {
351
+    box-sizing: border-box;
352
+    padding: 0;
353
+    background-color: map-get($colors, bg);
354
+    font-family: map-get($font, family);
355
+    -webkit-font-smoothing: map-get($font, smoothing);
356
+    font-smoothing: map-get($font, smoothing);
357
+}
358
+
359
+.card_wrap {
360
+    @include card;
361
+    margin-bottom: 20rpx;
362
+
363
+    &:hover {
364
+        @include shadow(2);
365
+    }
366
+
367
+    &.checklist-card,
368
+    &.price-card,
369
+    &.detail-image-card {
370
+        margin-top: 20rpx;
371
+    }
372
+}
373
+
374
+.address-section {
375
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
376
+}
377
+
378
+.address-header {
379
+    @include flex-center;
380
+    margin-bottom: map-get($sizes, margin-sm);
381
+    padding-bottom: map-get($sizes, margin-sm);
382
+    border-bottom: 1rpx solid map-get($colors, border);
383
+
384
+    .location-icon {
385
+        margin-right: map-get($sizes, margin-xs);
386
+        background-color: map-get($colors, primary-light);
387
+        padding: map-get($sizes, icon-padding);
388
+        border-radius: 50%;
389
+        flex-shrink: 0;
390
+    }
391
+
392
+    .address-title {
393
+        margin-left: 16rpx;
394
+    }
395
+}
396
+
397
+.address-content {
398
+    .address-text {
399
+        @include font-styles;
400
+    }
401
+}
402
+
403
+// 复选框卡片样式
404
+.checklist-card {
405
+    margin-top: 20rpx;
406
+}
407
+
408
+.checklist-section {
409
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
410
+    display: block;
411
+    /* 明确设置为块级元素,避免任何flex影响 */
412
+}
413
+
414
+.checklist-item {
415
+    display: block;
416
+    /* 明确设置为块级元素,确保垂直排列 */
417
+    width: 100%;
418
+    /* 确保占满整个宽度 */
419
+    padding: 16rpx 0;
420
+    border-bottom: 1rpx solid map-get($colors, border);
421
+    margin-bottom: 0;
422
+    /* 移除任何可能的margin影响 */
423
+
424
+    &:first-child {
425
+        padding-top: 0;
426
+    }
427
+
428
+    &:last-child {
429
+        padding-bottom: 0;
430
+        border-bottom: none;
431
+    }
432
+
433
+    // 复选框和文本的容器
434
+    .checkbox-text-container {
435
+        @include flex-center;
436
+        display: flex;
437
+        align-items: center;
438
+    }
439
+}
440
+
441
+// u-checkbox样式调整
442
+u-checkbox {
443
+    margin-right: 16rpx;
444
+    flex-shrink: 0;
445
+    vertical-align: middle;
446
+}
447
+
448
+// 隐藏原生checkbox样式
449
+.checkbox {
450
+    display: none;
451
+}
452
+
453
+.checklist-text {
454
+    @include font-styles;
455
+    vertical-align: middle;
456
+}
457
+
458
+// 输入框样式
459
+.checklist-input,
460
+.checklist-textarea {
461
+    margin-top: 12rpx;
462
+    margin-left: 56rpx; // 与复选框对齐
463
+    width: calc(100% - 72rpx); // 减去左边距和额外的16rpx边距,确保不超出边界
464
+    max-width: calc(100% - 72rpx); // 确保最大宽度也不超出
465
+    box-sizing: border-box; // 确保padding和border不影响总宽度
466
+    border-radius: 8rpx;
467
+    border: 1rpx solid #e5e7eb;
468
+    padding: 12rpx 16rpx;
469
+    font-size: 28rpx;
470
+    background-color: #f9fafb;
471
+    transition: all 0.2s ease;
472
+
473
+    &:focus {
474
+        border-color: map-get($colors, primary);
475
+        background-color: #ffffff;
476
+        box-shadow: 0 0 0 2rpx rgba(16, 140, 255, 0.1);
477
+    }
478
+}
479
+
480
+.checklist-textarea {
481
+    min-height: 160rpx;
482
+    resize: vertical;
483
+    vertical-align: top;
484
+    padding-top: 16rpx;
485
+    padding-bottom: 16rpx;
486
+}
487
+
488
+// 解决textarea文本和placeholder居中问题
489
+// 直接穿透u-input组件的所有层级
490
+:deep(.checklist-textarea) {
491
+    & .u-input__textarea {
492
+        display: block !important;
493
+        height: auto !important;
494
+        min-height: 160rpx !important;
495
+        padding: 16rpx !important;
496
+        text-align: left !important;
497
+    }
498
+
499
+    & .u-input__textarea textarea {
500
+        display: block !important;
501
+        width: 100% !important;
502
+        height: auto !important;
503
+        min-height: 128rpx !important;
504
+        padding: 0 !important;
505
+        margin: 0 !important;
506
+        text-align: left !important;
507
+        vertical-align: top !important;
508
+        line-height: 1.5 !important;
509
+        resize: vertical !important;
510
+    }
511
+
512
+    // 确保输入的文本顶部对齐
513
+    & .u-input__textarea textarea:focus {
514
+        text-align: left !important;
515
+        vertical-align: top !important;
516
+    }
517
+
518
+    // 针对不同浏览器的placeholder样式
519
+    & .u-input__textarea textarea::-webkit-input-placeholder {
520
+        text-align: left !important;
521
+        vertical-align: top !important;
522
+        line-height: 1.5 !important;
523
+    }
524
+
525
+    & .u-input__textarea textarea::-moz-placeholder {
526
+        text-align: left !important;
527
+        vertical-align: top !important;
528
+        line-height: 1.5 !important;
529
+    }
530
+
531
+    & .u-input__textarea textarea:-ms-input-placeholder {
532
+        text-align: left !important;
533
+        vertical-align: top !important;
534
+        line-height: 1.5 !important;
535
+    }
536
+
537
+    & .u-input__textarea textarea::placeholder {
538
+        text-align: left !important;
539
+        vertical-align: top !important;
540
+        line-height: 1.5 !important;
541
+    }
542
+}
543
+
544
+// 上传按钮容器样式
545
+.upload-btn-container {
546
+    margin-top: 16rpx;
547
+    margin-left: 56rpx;
548
+    display: inline-block;
549
+}
550
+
551
+// 上传按钮样式
552
+.upload-btn {
553
+    display: flex;
554
+    align-items: center;
555
+    justify-content: center;
556
+    gap: 12rpx;
557
+    font-size: 30rpx;
558
+    padding: 20rpx 40rpx;
559
+    border-radius: 8rpx;
560
+    background-color: map-get($colors, bg);
561
+    border: 2rpx dashed map-get($colors, primary);
562
+    color: map-get($colors, primary);
563
+    transition: all 0.3s ease;
564
+    cursor: pointer;
565
+    min-width: 200rpx;
566
+    box-sizing: border-box;
567
+
568
+    &:hover {
569
+        background-color: map-get($colors, primary-light);
570
+        border-color: darken(map-get($colors, primary), 10%);
571
+        transform: translateY(-2rpx);
572
+        box-shadow: 0 4rpx 16rpx rgba(16, 140, 255, 0.15);
573
+    }
574
+
575
+    &:active {
576
+        transform: translateY(0);
577
+    }
578
+}
579
+
580
+.upload-btn-text {
581
+    color: map-get($colors, primary);
582
+    @include font-styles($size: small, $weight: medium);
583
+}
584
+
585
+// 图片列表样式
586
+.image-list {
587
+    margin-top: 16rpx;
588
+    margin-left: 56rpx;
589
+    display: flex;
590
+    flex-wrap: wrap;
591
+    gap: 16rpx;
592
+    padding-bottom: 8rpx;
593
+}
594
+
595
+// 图片项样式
596
+.image-item {
597
+    width: 120rpx;
598
+    height: 120rpx;
599
+    border-radius: 8rpx;
600
+    overflow: hidden;
601
+    background-color: map-get($colors, bg);
602
+    @include shadow(1);
603
+    transition: all 0.3s ease;
604
+    cursor: pointer;
605
+    position: relative;
606
+
607
+    &:hover {
608
+        @include shadow(2);
609
+        transform: translateY(-2rpx);
610
+    }
611
+}
612
+
613
+// 图片缩略图样式
614
+.image-thumb {
615
+    width: 100%;
616
+    height: 100%;
617
+    object-fit: cover;
618
+}
619
+
620
+// 价格卡片样式
621
+.price-card {
622
+    margin-top: 20rpx;
623
+}
624
+
625
+.price-section {
626
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
627
+}
628
+
629
+.detail-image-card {
630
+    margin-top: 20rpx;
631
+}
632
+
633
+.detail-image-section {
634
+    padding: map-get($sizes, padding-sm) map-get($sizes, padding);
635
+}
636
+
637
+.detail-image-header {
638
+    display: flex;
639
+    justify-content: space-between;
640
+    align-items: center;
641
+    margin-bottom: map-get($sizes, margin-sm);
642
+    padding-bottom: map-get($sizes, margin-sm);
643
+    border-bottom: 1rpx solid map-get($colors, border);
644
+}
645
+
646
+.detail-image-title {
647
+    @include font-styles($size: content, $weight: bold, $color: primary);
648
+}
649
+
650
+.copy-btn {
651
+    border-radius: 20rpx;
652
+    border: 1rpx solid #007AFF;
653
+    background-color: transparent;
654
+    color: #007AFF;
655
+    @include font-styles($size: small, $weight: regular);
656
+    padding: 0 24rpx;
657
+    height: 64rpx;
658
+    line-height: 64rpx;
659
+    display: flex;
660
+    align-items: center;
661
+    gap: 8rpx;
662
+    cursor: pointer;
663
+    user-select: none;
664
+    transition: all 0.3s ease;
665
+
666
+    &:hover {
667
+        background-color: rgba(0, 122, 255, 0.05);
668
+    }
669
+
670
+    &:active {
671
+        transform: scale(0.98);
672
+    }
673
+}
674
+
675
+.detail-image-upload-container {
676
+    margin-top: 20rpx;
677
+}
678
+
679
+.detail-image-list {
680
+    display: flex;
681
+    flex-wrap: wrap;
682
+    gap: 20rpx;
683
+}
684
+
685
+.detail-image-item {
686
+    position: relative;
687
+    width: 200rpx;
688
+    height: 200rpx;
689
+    box-sizing: border-box;
690
+}
691
+
692
+.detail-delete-btn {
693
+    position: absolute;
694
+    top: -10rpx;
695
+    right: -10rpx;
696
+    width: 40rpx;
697
+    height: 40rpx;
698
+    background-color: #ff4d4f;
699
+    color: #fff;
700
+    border-radius: 50%;
701
+    display: flex;
702
+    align-items: center;
703
+    justify-content: center;
704
+    @include font-styles($size: small, $weight: bold);
705
+    z-index: 10;
706
+}
707
+
708
+.detail-upload-btn {
709
+    width: 200rpx;
710
+    height: 200rpx;
711
+    border: 8rpx dashed #ddd;
712
+    border-radius: 30rpx;
713
+    display: flex;
714
+    align-items: center;
715
+    justify-content: center;
716
+    background-color: #f9f9f9;
717
+    box-sizing: border-box;
718
+}
719
+
720
+.price-picker-container {
721
+    display: flex;
722
+    flex-direction: column;
723
+    align-items: center;
724
+    padding: 20rpx 0;
725
+}
726
+
727
+// 快速操作按钮样式
728
+.quick-actions {
729
+    display: flex;
730
+    justify-content: center;
731
+    gap: 16rpx;
732
+    margin: 16rpx 0;
733
+    width: 100%;
734
+    max-width: 800rpx;
735
+}
736
+
737
+.quick-btn {
738
+    flex: 1;
739
+    border-radius: 12rpx;
740
+    font-size: 36rpx;
741
+    padding: 32rpx 0;
742
+    min-width: 0;
743
+    text-align: center;
744
+    color: #ffffff;
745
+    font-weight: 600;
746
+    transition: all 0.3s ease;
747
+    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
748
+    cursor: pointer;
749
+}
750
+
751
+.quick-btn.increase {
752
+    background-color: #e6f7ed;
753
+    color: #00b42a;
754
+}
755
+
756
+.quick-btn.decrease {
757
+    background-color: #fff1f0;
758
+    color: #f53f3f;
759
+}
760
+
761
+.quick-btn:hover {
762
+    opacity: 0.9;
763
+    transform: translateY(-2rpx);
764
+    box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.15);
765
+}
766
+
767
+// 数字选择器容器
768
+.number-box-container {
769
+    display: flex;
770
+    align-items: center;
771
+    gap: 16rpx;
772
+    margin: 20rpx 0;
773
+    width: 100%;
774
+    justify-content: center;
775
+    white-space: nowrap;
776
+}
777
+
778
+// 价格输入框盒子
779
+.price-input-box {
780
+    flex: 1;
781
+    max-width: 800rpx;
782
+    background-color: #f5f7fa;
783
+    border: 2rpx solid #e5e7eb;
784
+    border-radius: 12rpx;
785
+    padding: 20rpx 24rpx;
786
+    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
787
+    display: flex;
788
+    align-items: center;
789
+    justify-content: space-between;
790
+    white-space: nowrap;
791
+    min-width: 300rpx;
792
+}
793
+
794
+// 价格标签样式
795
+.price-label {
796
+    font-size: 36rpx;
797
+    color: map-get($colors, text-primary);
798
+    font-weight: 700;
799
+    min-width: 120rpx;
800
+    flex-shrink: 0;
801
+    margin-right: 16rpx;
802
+    letter-spacing: 1rpx;
803
+    font-family: map-get($font, family);
804
+}
805
+
806
+// 价格输入框样式
807
+.price-input {
808
+    width: 100%;
809
+    height: auto;
810
+    border: none;
811
+    outline: none;
812
+    background-color: transparent;
813
+    text-align: right;
814
+    font-size: 48rpx;
815
+    font-weight: 600;
816
+    color: map-get($colors, text-primary);
817
+    padding: 0 10rpx;
818
+    box-sizing: border-box;
819
+    -webkit-appearance: none;
820
+    -moz-appearance: textfield;
821
+    /* 使用等宽字体显示带斜线的0 */
822
+    font-family: Consolas, 'Courier New', monospace, -apple-system, BlinkMacSystemFont;
823
+}
824
+
825
+// 移除数字输入框的上下箭头
826
+.price-input::-webkit-inner-spin-button,
827
+.price-input::-webkit-outer-spin-button {
828
+    -webkit-appearance: none;
829
+    margin: 0;
830
+}
831
+
832
+.price-input:focus {
833
+    background-color: transparent;
834
+}
835
+</style>

+ 38 - 0
pages/orderDetailNew/components/picComp.vue

@@ -0,0 +1,38 @@
1
+<template>
2
+    <view class="pic-comp-container">
3
+        <image class="picComp" :src="src" mode="aspectFill" @click="click"></image>
4
+    </view>
5
+</template>
6
+<script>
7
+export default {
8
+    props: {
9
+        src: {
10
+            type: String,
11
+            default: ''
12
+        }
13
+    },
14
+    methods: {
15
+        click() {
16
+            uni.previewImage({
17
+                urls: [this.src],
18
+                current: this.src
19
+            })
20
+        }
21
+    }
22
+}
23
+</script>
24
+<style scoped>
25
+.pic-comp-container {
26
+    width: 100%;
27
+    height: 100%;
28
+    box-sizing: border-box;
29
+    overflow: hidden;
30
+    border-radius: 30rpx;
31
+}
32
+
33
+.picComp {
34
+    width: 100% !important;
35
+    height: 100% !important;
36
+    object-fit: cover;
37
+}
38
+</style>

+ 94 - 0
pages/orderDetailNew/index.vue

@@ -0,0 +1,94 @@
1
+<template>
2
+    <view>
3
+        <!-- 正确使用 u-navbar 的具名插槽 -->
4
+        <u-navbar :autoBack="true" :placeholder="true" v-hideNav>
5
+            <template v-slot:center>
6
+                <view class="slot-wrap">
7
+                    <text @click="handleBrandClick" class="brand">Hermes</text>
8
+                    <text class="divider">|</text>
9
+                    <text @click="handleModelClick" class="model">Birkin 30</text>
10
+                    <text class="divider">|</text>
11
+                    <text @click="handlePriceClick" class="price">¥125,000</text>
12
+                </view>
13
+            </template>
14
+            <template v-slot:right>
15
+                <view class="slot-right">
16
+                    <image src="/static/icons/plus.png" mode="scaleToFill" />
17
+                    <text>加一单</text>
18
+                </view>
19
+            </template>
20
+        </u-navbar>
21
+
22
+        <orderDetailNewView />
23
+
24
+    </view>
25
+</template>
26
+
27
+<script>
28
+import orderDetailNewView from './components/orderDetailNewView.vue'
29
+export default {
30
+    name: 'CustomNavbar',
31
+    components: {
32
+        orderDetailNewView
33
+    },
34
+    methods: {
35
+        handleBrandClick() {
36
+            console.log('点击了品牌')
37
+        },
38
+        handleModelClick() {
39
+            console.log('点击了型号')
40
+        },
41
+        handlePriceClick() {
42
+            console.log('点击了价格')
43
+        }
44
+    }
45
+}
46
+</script>
47
+
48
+<style scoped>
49
+.slot-wrap {
50
+    display: flex;
51
+    align-items: center;
52
+    background-color: #fff;
53
+    border-radius: 40rpx;
54
+    padding: 10rpx 20rpx;
55
+    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
56
+}
57
+
58
+.brand {
59
+    font-weight: bold;
60
+    color: #333;
61
+    font-size: 28rpx;
62
+}
63
+
64
+.divider {
65
+    margin: 0 15rpx;
66
+    color: #ddd;
67
+    font-size: 28rpx;
68
+}
69
+
70
+.model {
71
+    color: #666;
72
+    font-size: 26rpx;
73
+}
74
+
75
+.price {
76
+    color: blueviolet;
77
+    font-weight: bold;
78
+    font-size: 28rpx;
79
+}
80
+
81
+.slot-right {
82
+    display: flex;
83
+    flex-direction: column;
84
+    align-items: center;
85
+    justify-content: center;
86
+    font-size: 20rpx;
87
+    color: blueviolet;
88
+
89
+    image {
90
+        width: 30rpx;
91
+        height: 30rpx;
92
+    }
93
+}
94
+</style>

+ 430 - 280
pages/orderForm/index.vue

@@ -1,15 +1,49 @@
1 1
 <template>
2 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>
3
+		<u-navbar placeholder :autoBack="true" title="发单表单">
4
+
7 5
 		</u-navbar>
8 6
 
9 7
 		<view class="form_wrap">
10
-			<u--form labelPosition="left" labelWidth="100" :model="form" :rules="rules" ref="form" class="form_wrap"
8
+			<u--form labelPosition="top" labelWidth="100" :model="form" :rules="rules" ref="form" class="form_wrap"
11 9
 				:errorType="'toast'">
12
-				<u-form-item label="省市区" borderBottom>
10
+				<u-form-item label="物品品牌" prop="brand">
11
+					<ld-select :list="brandDict" label-key="dictLabel" value-key="dictValue" placeholder="请选择物品品牌"
12
+						v-model="form.brand" :border="false"></ld-select>
13
+					<u-icon slot="right" name="arrow-right"></u-icon>
14
+				</u-form-item>
15
+
16
+				<u-row justify="space-between">
17
+					<u-form-item label="型号" prop="model">
18
+						<u-col span="6">
19
+							<u--input v-model="form.model" placeholder="请输入型号" border="none"></u--input>
20
+
21
+						</u-col>
22
+					</u-form-item>
23
+
24
+					<u-form-item label="实价" prop="price">
25
+						<u-col span="6">
26
+							<u--input v-model="form.price" placeholder="请输入实价" border="none"></u--input>
27
+						</u-col>
28
+					</u-form-item>
29
+				</u-row>
30
+
31
+				<u-row justify="space-between">
32
+					<u-form-item label="客户电话" prop="phone">
33
+						<u-col span="6">
34
+							<u--input v-model="form.phone" placeholder="请输入客户电话" border="none"></u--input>
35
+
36
+						</u-col>
37
+					</u-form-item>
38
+
39
+					<u-form-item label="客户微信" prop="wechat">
40
+						<u-col span="6">
41
+							<u--input v-model="form.wechat" placeholder="请输入客户微信" border="none"></u--input>
42
+						</u-col>
43
+					</u-form-item>
44
+				</u-row>
45
+
46
+				<u-form-item label="省市区">
13 47
 					<pick-regions :defaultRegion="defaultRegion" @getRegion="handleGetRegion">
14 48
 						<view class="region-picker">
15 49
 							<template v-if="form.province">
@@ -24,39 +58,38 @@
24 58
 					</pick-regions>
25 59
 				</u-form-item>
26 60
 
27
-				<u-form-item label="详细地址" prop="address" borderBottom>
61
+				<u-form-item label="详细地址" prop="address" class='form_card'>
28 62
 					<u--textarea v-model="form.address" placeholder="请输入详细地址" count confirmType="done"></u--textarea>
29 63
 				</u-form-item>
30 64
 
31
-				<u-form-item label="上门时间" prop="visitTime" borderBottom>
65
+				<u-form-item label="上门时间" prop="visitTime">
32 66
 					<date-time-picker v-model="form.visitTime" :value-format="'YYYY-MM-DD HH:mm:ss'" :type="'datetime'">
33 67
 					</date-time-picker>
34 68
 				</u-form-item>
35 69
 
36
-				<u-form-item label="类型" prop="category" borderBottom>
70
+				<u-form-item label="类型" prop="category">
37 71
 					<ld-select :list="categoryDict" label-key="dictLabel" value-key="dictValue" placeholder="请选择类型"
38 72
 						v-model="form.category" :border="false"></ld-select>
39 73
 					<u-icon slot="right" name="arrow-right"></u-icon>
40 74
 				</u-form-item>
41 75
 
42
-				<u-form-item label="物品品牌" prop="brand" borderBottom>
43
-					<ld-select :list="brandDict" label-key="dictLabel" value-key="dictValue" placeholder="请选择物品品牌"
44
-						v-model="form.brand" :border="false"></ld-select>
45
-					<u-icon slot="right" name="arrow-right"></u-icon>
46
-				</u-form-item>
47 76
 
48
-				<u-form-item label="价格范围" prop="priceRange" borderBottom>
77
+
78
+				<u-form-item label="价格范围" prop="priceRange">
49 79
 					<u--input v-model="form.priceRange" placeholder="请输入价格范围" border="none"></u--input>
50 80
 				</u-form-item>
51 81
 
52
-				<u-form-item label="战术选择" prop="tactic" borderBottom>
53
-					<ld-select :list="tacticDict" label-key="dictLabel" value-key="dictValue" placeholder="请选择战术"
54
-						v-model="form.tactic" :border="false"></ld-select>
55
-					<u-icon slot="right" name="arrow-right"></u-icon>
82
+				<u-form-item label="战术选择" prop="tactic">
83
+					<view class="tactic-buttons">
84
+						<view v-for="item in tacticDict" :key="item.dictValue" class="tactic-button"
85
+							:class="{ 'active': form.tactic === item.dictValue }" @click="form.tactic = item.dictValue">
86
+							{{ item.dictLabel }}
87
+						</view>
88
+					</view>
56 89
 				</u-form-item>
57 90
 
58
-				<u-form-item label="补充说明" prop="remarks" borderBottom>
59
-					<u--textarea v-model="form.remarks" placeholder="请输入补充说明" count confirmType="done"></u--textarea>
91
+				<u-form-item label="备注消息" prop="remarks">
92
+					<u--textarea v-model="form.remarks" placeholder="请输入备注消息" count confirmType="done"></u--textarea>
60 93
 				</u-form-item>
61 94
 
62 95
 			</u--form>
@@ -81,289 +114,406 @@
81 114
 				@update:fileList="updateOtherFiles" tip-text="上传其他相关文件"></order-file-upload>
82 115
 		</view>
83 116
 
117
+		<u-button @click="handleNavSaveClick" type="primary">提交订单</u-button>
118
+
84 119
 	</view>
85 120
 </template>
86 121
 
87 122
 <script>
88
-	import orderFileUpload from '@/components/order-file-upload/order-file-upload.vue'
89
-	import dateTimePicker from "@/components/dateTimePicker/dateTimePicker.vue"
90
-	import ldSelect from "@/components/ld-select/ld-select.vue"
91
-	export default {
92
-		components: {
93
-			orderFileUpload,
94
-			dateTimePicker,
95
-			ldSelect
96
-		},
97
-		data() {
98
-			return {
99
-				defaultRegion: ['广东省', '广州市', '番禺区'],
100
-				categoryDict: [],
101
-				tacticDict: [],
102
-				brandDict: [],
103
-				
104
-				sendFormId : undefined,
105
-
106
-				form: {
107
-					clueId: '',
108
-					sendDate: '',
109
-					website: '',
110
-					item: '',
111
-					phone: '',
112
-					address: '',
113
-					visitTime: '',
114
-					remarks: '',
115
-					category: '',
116
-					brand: '',
117
-					priceRange: '',
118
-					tactic: '',
119
-					// 地区信息
120
-					province: '',
121
-					city: '',
122
-					area: '',
123
-					// 附件列表
124
-					chatAttachmentList: [], // 聊天记录附件
125
-					quoteAttachmentList: [], // 报价附件
126
-					hdImageAttachmentList: [], // 高清图附件
127
-					otherAttachmentList: [] // 其他附件
128
-				},
123
+import orderFileUpload from '@/components/order-file-upload/order-file-upload.vue'
124
+import dateTimePicker from "@/components/dateTimePicker/dateTimePicker.vue"
125
+import ldSelect from "@/components/ld-select/ld-select.vue"
126
+export default {
127
+	components: {
128
+		orderFileUpload,
129
+		dateTimePicker,
130
+		ldSelect
131
+	},
132
+	data() {
133
+		return {
134
+			defaultRegion: ['广东省', '广州市', '番禺区'],
135
+			categoryDict: [],
136
+			tacticDict: [],
137
+			brandDict: [],
138
+
139
+			sendFormId: undefined,
140
+
141
+			form: {
142
+				clueId: '',
143
+				sendDate: '',
144
+				website: '',
145
+				item: '',
146
+				phone: '',
147
+				wechat: '',
148
+				address: '',
149
+				visitTime: '',
150
+				remarks: '',
151
+				category: '',
152
+				brand: '',
153
+				model: '',
154
+				price: '',
155
+				priceRange: '',
156
+				tactic: '',
157
+				// 地区信息
158
+				province: '',
159
+				city: '',
160
+				area: '',
161
+				// 附件列表
162
+				chatAttachmentList: [], // 聊天记录附件
163
+				quoteAttachmentList: [], // 报价附件
164
+				hdImageAttachmentList: [], // 高清图附件
165
+				otherAttachmentList: [] // 其他附件
166
+			},
129 167
 
130
-				rules: {
131
-					sendDate: {
132
-						type: 'string',
133
-						required: true,
134
-						message: '请输入发单日期',
135
-						trigger: ['blur', 'change']
136
-					},
137
-					website: {
138
-						type: 'url',
139
-						message: '请输入正确的网址格式',
140
-						trigger: ['blur', 'change']
141
-					},
142
-					item: {
143
-						type: 'string',
144
-						required: true,
145
-						message: '请输入物品描述',
146
-						trigger: ['blur', 'change']
147
-					},
148
-					phone: {
149
-						type: 'string',
150
-						required: true,
151
-						message: '请输入联系电话',
152
-						trigger: ['blur', 'change']
153
-					},
154
-					address: {
155
-						type: 'string',
156
-						required: true,
157
-						message: '请输入详细地址',
158
-						trigger: ['blur', 'change']
159
-					},
160
-					visitTime: {
161
-						type: 'string',
162
-						required: true,
163
-						message: '请输入上门时间',
164
-						trigger: ['blur', 'change']
165
-					},
166
-					category: {
167
-						type: 'string',
168
-						required: true,
169
-						message: '请选择类型',
170
-						trigger: ['blur', 'change']
171
-					},
172
-					brand: {
173
-						type: 'string',
174
-						required: true,
175
-						message: '请选择物品品牌',
176
-						trigger: ['blur', 'change']
177
-					},
178
-					tactic: {
179
-						type: 'string',
180
-						required: true,
181
-						message: '请选择战术',
182
-						trigger: ['blur', 'change']
183
-					}
168
+			rules: {
169
+				sendDate: {
170
+					type: 'string',
171
+					required: true,
172
+					message: '请输入发单日期',
173
+					trigger: ['blur', 'change']
174
+				},
175
+				model: {
176
+					type: 'string',
177
+					required: true,
178
+					message: '请输入型号',
179
+					trigger: ['blur', 'change']
180
+				},
181
+				price: {
182
+					type: 'string',
183
+					required: true,
184
+					message: '请输入实价',
185
+					trigger: ['blur', 'change']
186
+				},
187
+				website: {
188
+					type: 'url',
189
+					message: '请输入正确的网址格式',
190
+					trigger: ['blur', 'change']
191
+				},
192
+				item: {
193
+					type: 'string',
194
+					required: true,
195
+					message: '请输入物品描述',
196
+					trigger: ['blur', 'change']
197
+				},
198
+				wechat: {
199
+					type: 'string',
200
+					required: true,
201
+					message: '请输入客户微信',
202
+					trigger: ['blur', 'change']
203
+				},
204
+				phone: {
205
+					type: 'string',
206
+					required: true,
207
+					message: '请输入联系电话',
208
+					trigger: ['blur', 'change']
209
+				},
210
+				address: {
211
+					type: 'string',
212
+					required: true,
213
+					message: '请输入详细地址',
214
+					trigger: ['blur', 'change']
215
+				},
216
+				visitTime: {
217
+					type: 'string',
218
+					required: true,
219
+					message: '请输入上门时间',
220
+					trigger: ['blur', 'change']
221
+				},
222
+				category: {
223
+					type: 'string',
224
+					required: true,
225
+					message: '请选择类型',
226
+					trigger: ['blur', 'change']
227
+				},
228
+				brand: {
229
+					type: 'string',
230
+					required: true,
231
+					message: '请选择物品品牌',
232
+					trigger: ['blur', 'change']
233
+				},
234
+				tactic: {
235
+					type: 'string',
236
+					required: true,
237
+					message: '请选择战术',
238
+					trigger: ['blur', 'change']
184 239
 				}
185 240
 			}
186
-		},
187
-
188
-		methods: {
189
-			// 加载表单数据
190
-			async loadFormData(sendFormId) {
191
-				try {
192
-					const res = await uni.$u.api.getClueSendFormVoByOrderId({
193
-						id: sendFormId
194
-					});
195
-					if (res.code === 200) {
196
-						this.form = res.data;
197
-					}
198
-				} catch (error) {
199
-					console.error('加载表单数据失败:', error);
200
-					uni.$u.toast('加载表单数据失败');
241
+		}
242
+	},
243
+
244
+	methods: {
245
+		// 加载表单数据
246
+		async loadFormData(sendFormId) {
247
+			try {
248
+				const res = await uni.$u.api.getClueSendFormVoByOrderId({
249
+					id: sendFormId
250
+				});
251
+				if (res.code === 200) {
252
+					this.form = res.data;
201 253
 				}
202
-			},
254
+			} catch (error) {
255
+				console.error('加载表单数据失败:', error);
256
+				uni.$u.toast('加载表单数据失败');
257
+			}
258
+		},
203 259
 
204
-			// 获取地区选择
205
-			handleGetRegion(region) {
206
-				const [provinceData, cityData, areaData] = region;
207
-				this.form.province = provinceData.name;
208
-				this.form.city = cityData.name;
209
-				this.form.area = areaData.name;
210
-				// 只在详细地址为空时自动填充省市区
211
-				if (!this.form.address || this.form.address.trim() === '') {
212
-					this.form.address = this.form.province + this.form.city + this.form.area;
213
-				}
214
-			},
260
+		// 获取地区选择
261
+		handleGetRegion(region) {
262
+			const [provinceData, cityData, areaData] = region;
263
+			this.form.province = provinceData.name;
264
+			this.form.city = cityData.name;
265
+			this.form.area = areaData.name;
266
+			// 只在详细地址为空时自动填充省市区
267
+			if (!this.form.address || this.form.address.trim() === '') {
268
+				this.form.address = this.form.province + this.form.city + this.form.area;
269
+			}
270
+		},
215 271
 
216
-			// 更新各类附件
217
-			updateChatFiles(fileList) {
218
-				this.form.chatAttachmentList = fileList;
219
-			},
272
+		// 更新各类附件
273
+		updateChatFiles(fileList) {
274
+			this.form.chatAttachmentList = fileList;
275
+		},
220 276
 
221
-			updateQuoteFiles(fileList) {
222
-				this.form.quoteAttachmentList = fileList;
223
-			},
277
+		updateQuoteFiles(fileList) {
278
+			this.form.quoteAttachmentList = fileList;
279
+		},
224 280
 
225
-			updateHdImageFiles(fileList) {
226
-				this.form.hdImageAttachmentList = fileList;
227
-			},
281
+		updateHdImageFiles(fileList) {
282
+			this.form.hdImageAttachmentList = fileList;
283
+		},
228 284
 
229
-			updateOtherFiles(fileList) {
230
-				this.form.otherAttachmentList = fileList;
231
-			},
285
+		updateOtherFiles(fileList) {
286
+			this.form.otherAttachmentList = fileList;
287
+		},
232 288
 
233
-			// 文件变化处理
234
-			handleFileChange(data) {
235
-				console.log('文件上传变化:', data);
236
-			},
237
-			// 获取字典数据
238
-			async getDicts() {
239
-				try {
240
-					const [categoryRes, tacticRes, brandRes] = await Promise.all([
241
-						this.$getDicts('crm_form_category'),
242
-						this.$getDicts('crm_form_tactic'),
243
-						this.$getDicts('crm_form_brand')
244
-					]);
245
-
246
-					this.categoryDict = categoryRes;
247
-					this.tacticDict = tacticRes;
248
-					this.brandDict = brandRes;
249
-				} catch (error) {
250
-					console.error('获取字典数据失败:', error);
251
-				}
252
-			},
289
+		// 文件变化处理
290
+		handleFileChange(data) {
291
+			console.log('文件上传变化:', data);
292
+		},
293
+		// 获取字典数据
294
+		async getDicts() {
295
+			try {
296
+				const [categoryRes, tacticRes, brandRes] = await Promise.all([
297
+					this.$getDicts('crm_form_category'),
298
+					this.$getDicts('crm_form_tactic'),
299
+					this.$getDicts('crm_form_brand')
300
+				]);
301
+
302
+				this.categoryDict = categoryRes;
303
+				this.tacticDict = tacticRes;
304
+				this.brandDict = brandRes;
305
+			} catch (error) {
306
+				console.error('获取字典数据失败:', error);
307
+			}
308
+		},
253 309
 
254
-			// 处理保存
255
-			async handleNavSaveClick() {
256
-				try {
257
-					// 表单验证
258
-					await this.$refs.form.validate();
259
-
260
-					if (this.form.id) {
261
-						const updatedForm = {
262
-							id: this.form.id,
263
-							item: this.form.item,
264
-							phone: this.form.phone,
265
-							authenticateUserId: this.form.authenticateUserId,
266
-							category: this.form.category,
267
-							brand: this.form.brand,
268
-							idCard: this.form.idCard,
269
-							customName: this.form.customName,
270
-							bankCardNumber: this.form.bankCardNumber,
271
-							bankName: this.form.bankName,
272
-							paymentMethod: this.form.paymentMethod,
273
-							visitTime: this.form.visitTime,
274
-							remarks: this.form.remarks,
275
-							priceRange: this.form.priceRange,
276
-							tactic: this.form.tactic
277
-						}
278
-						await uni.$u.api.updateClueOrderForm(updatedForm);
279
-						uni.$emit('updateSendFormSuccess');
280
-						uni.$u.toast('发单记录更新成功');
281
-					} else {
282
-						// 合并所有附件
283
-						const allAttachments = [
284
-							...this.form.chatAttachmentList,
285
-							...this.form.quoteAttachmentList,
286
-							...this.form.hdImageAttachmentList,
287
-							...this.form.otherAttachmentList
288
-						];
289
-						
290
-						// 准备提交数据
291
-						const submitData = {
292
-							...this.form,
293
-							uploadList: allAttachments
294
-						};
295
-						await uni.$u.api.saveClueOrderForm(submitData);
296
-						uni.$u.toast('发单记录添加成功');
310
+		// 处理保存
311
+		async handleNavSaveClick() {
312
+			try {
313
+				// 表单验证
314
+				await this.$refs.form.validate();
315
+
316
+				if (this.form.id) {
317
+					const updatedForm = {
318
+						clueId: this.form.clueId,
319
+						model: this.form.model,
320
+						price: this.form.price,
321
+						wechat: this.form.wechat,
322
+						id: this.form.id,
323
+						item: this.form.item,
324
+						phone: this.form.phone,
325
+						authenticateUserId: this.form.authenticateUserId,
326
+						category: this.form.category,
327
+						brand: this.form.brand,
328
+						idCard: this.form.idCard,
329
+						customName: this.form.customName,
330
+						bankCardNumber: this.form.bankCardNumber,
331
+						bankName: this.form.bankName,
332
+						paymentMethod: this.form.paymentMethod,
333
+						visitTime: this.form.visitTime,
334
+						remarks: this.form.remarks,
335
+						priceRange: this.form.priceRange,
336
+						tactic: this.form.tactic
297 337
 					}
338
+					await uni.$u.api.updateClueOrderForm(updatedForm);
339
+					uni.$emit('updateSendFormSuccess');
340
+					uni.$u.toast('发单记录更新成功');
341
+				} else {
342
+					// 合并所有附件
343
+					const allAttachments = [
344
+						...this.form.chatAttachmentList,
345
+						...this.form.quoteAttachmentList,
346
+						...this.form.hdImageAttachmentList,
347
+						...this.form.otherAttachmentList
348
+					];
349
+
350
+					// 准备提交数据
351
+					const submitData = {
352
+						...this.form,
353
+						uploadList: allAttachments
354
+					};
355
+					await uni.$u.api.saveClueOrderForm(submitData);
356
+					uni.$u.toast('发单记录添加成功');
357
+				}
298 358
 
299
-					// 延迟返回
300
-					setTimeout(() => {
301
-						uni.navigateBack();
302
-					}, 1500);
359
+				// 延迟返回
360
+				setTimeout(() => {
361
+					uni.navigateBack();
362
+				}, 1500);
303 363
 
304
-				} catch (error) {
305
-					console.error('保存失败:', error);
306
-					if (error.message) {
307
-						uni.$u.toast(error.message);
308
-					}
364
+			} catch (error) {
365
+				console.error('保存失败:', error);
366
+				if (error.message) {
367
+					uni.$u.toast(error.message);
309 368
 				}
310 369
 			}
311
-		},
312
-
313
-		onLoad(option) {
314
-			const clueId = option.clueId;
315
-			this.sendFormId = option.sendFormId;
316
-			this.form.clueId = clueId;
317
-			this.getDicts();
318
-			if (option.sendFormId) {
319
-				this.loadFormData(option.sendFormId);
320
-			}
370
+		}
371
+	},
372
+
373
+	onLoad(option) {
374
+		console.log('option', option);
375
+		const clueId = option.clueId;
376
+		this.sendFormId = option.sendFormId;
377
+		this.form.clueId = clueId;
378
+		this.getDicts();
379
+		if (option.sendFormId) {
380
+			this.loadFormData(option.sendFormId);
321 381
 		}
322 382
 	}
383
+}
323 384
 </script>
324 385
 
325 386
 <style lang="scss" scoped>
326
-	.oder_form_wrap {
327
-		background-color: #f5f5f5;
328
-		min-height: 100vh;
329
-		padding-bottom: 100rpx;
330
-		padding-top: 10px;
331
-	}
332
-
333
-	.form_wrap {
334
-		background-color: #fff;
335
-		border-radius: 16rpx;
336
-		overflow: hidden;
337
-	}
338
-
339
-	.upload_area {
340
-		padding: 0 20rpx;
341
-		margin: 20rpx 0;
342
-	}
387
+.oder_form_wrap {
388
+	background-color: #f5f5f5;
389
+	min-height: 100vh;
390
+	padding-bottom: 100rpx;
391
+	padding-top: 10px;
392
+	padding-left: 20rpx;
393
+	padding-right: 20rpx;
394
+}
395
+
396
+.form_wrap {
397
+	/* 移除整体背景和边框,让每个form-item成为独立卡片 */
398
+}
399
+
400
+.upload_area {
401
+	padding: 0 0rpx;
402
+	margin: 20rpx 0;
403
+}
404
+
405
+.bottom_btn {
406
+	position: fixed;
407
+	bottom: 0;
408
+	left: 0;
409
+	right: 0;
410
+	padding: 20rpx;
411
+	background: #fff;
412
+	box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1);
413
+}
414
+
415
+.region-picker {
416
+	width: 100%;
417
+}
418
+
419
+::v-deep .u-form-item {
420
+	/* 移除底部边框 */
421
+	border-bottom: none;
422
+	/* 添加卡片样式 */
423
+	// background-color: #fff;
424
+	border-radius: 16rpx;
425
+	/* 添加阴影效果 */
426
+	/* 添加外边距 */
427
+	margin-bottom: 20rpx;
428
+	/* 添加内边距 */
429
+	padding: 20rpx;
430
+	/* 确保内容不会溢出 */
431
+	overflow: hidden;
432
+}
433
+
434
+.form_card {
435
+	background-color: #fff;
436
+	box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
437
+
438
+}
439
+
440
+::v-deep .u-form-item__body {
441
+	padding: 10rpx 0rpx;
442
+}
443
+
444
+
445
+::v-deep .u-form-item__body__left__content__label {
446
+	color: rgb(107 114 128 / 1) !important;
447
+	font-size: 0.75rem;
448
+	line-height: 1rem;
449
+	font-weight: 700;
450
+}
451
+
452
+
453
+.u-button {
454
+	border-radius: 40rpx;
455
+	background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));
456
+	--tw-text-opacity: 1;
457
+	color: rgb(255 255 255 / var(--tw-text-opacity, 1));
458
+	font-weight: 700;
459
+	font-size: 1rem;
460
+	line-height: 1.5rem;
461
+	height: 100rpx;
462
+}
463
+
464
+.tactic-buttons {
465
+	display: flex;
466
+	justify-content: space-between;
467
+	margin-top: 10rpx;
468
+	width: 100%;
469
+}
470
+
471
+.tactic-button {
472
+	position: relative;
473
+	border-width: 3rpx;
474
+	border-style: solid;
475
+	border-color: #e5e7eb;
476
+	width: 30%;
477
+	height: 80rpx;
478
+	line-height: 80rpx;
479
+	text-align: center;
480
+	border-radius: 30rpx;
481
+	background-color: #f5f5f5;
482
+	color: rgb(107 114 128 / 1);
483
+	font-size: 28rpx;
484
+	transition: all 0.3s ease;
485
+	font-weight: 700;
486
+}
487
+
488
+.tactic-button.active {
489
+	border-color: rgb(29 78 216 / 1);
490
+	color: rgb(29 78 216 / 1);
491
+}
492
+
493
+.tactic-button::after {
494
+	content: '';
495
+
496
+	position: absolute;
497
+	border-width: 5rpx;
498
+	border-style: solid;
499
+	border-color: #ffffff;
500
+	top: 4%;
501
+	right: -12%;
502
+	transform: translate(-50%, -50%);
503
+	width: 25rpx;
504
+	height: 25rpx;
505
+	border-radius: 50%;
506
+	background-color: rgb(29 78 216 / 1);
507
+	opacity: 0;
508
+	transition: all 0.3s ease;
509
+}
510
+
511
+.tactic-button.active::after {
512
+	opacity: 1;
513
+}
514
+
515
+.u-textarea{
516
+	background-color: #f5f5f5;
517
+}
343 518
 
344
-	.bottom_btn {
345
-		position: fixed;
346
-		bottom: 0;
347
-		left: 0;
348
-		right: 0;
349
-		padding: 20rpx;
350
-		background: #fff;
351
-		box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1);
352
-	}
353
-
354
-	.region-picker {
355
-		width: 100%;
356
-	}
357
-
358
-	::v-deep .u-form-item__body {
359
-		padding: 20rpx 40rpx;
360
-	}
361
-
362
-	::v-deep .u-form-item {
363
-		border-bottom: 1rpx solid #f5f5f5;
364
-	}
365
-
366
-	::v-deep .u-form-item:last-child {
367
-		border-bottom: none;
368
-	}
369 519
 </style>

+ 9 - 3
pages/person/index.vue

@@ -14,7 +14,7 @@
14 14
 			<view class="header_wrap">
15 15
 				<view class="header_top_wrap">
16 16
 					<view class="header_info_left">
17
-						<u-avatar :src="$avatar(userInfo.avatar)" size="100rpx"></u-avatar>
17
+						<u-avatar @click="handleAvatarClick" :src="$avatar(userInfo.avatar)" size="100rpx"></u-avatar>
18 18
 						<view class="info_wrap">
19 19
 							<view class="info_top">
20 20
 								<text class="follow_name">{{userInfo.userName}}</text>
@@ -40,9 +40,9 @@
40 40
 							<image src="@/static/parson/icon-myMessage.png" mode=""></image>
41 41
 							<text>我的消息</text>
42 42
 						</navigator>
43
-						<navigator url='/pages/profile/index' open-type="navigate" class="menu_item" hover-class="none">
43
+						<navigator url='/pages/acceptOrderOrder/index' open-type="navigate" class="menu_item" hover-class="none">
44 44
 							<image src="@/static/parson/icon-mycase.png" mode=""></image>
45
-							<text>个人资料</text>
45
+							<text>接单中心</text>
46 46
 						</navigator>
47 47
 						<navigator url='/pages/privateClue/index' open-type="switchTab" class="menu_item" hover-class="none">
48 48
 							<image src="@/static/parson/clue.png" mode=""></image>
@@ -195,6 +195,12 @@
195 195
 					});
196 196
 				}
197 197
 			},
198
+			handleAvatarClick(){
199
+				//跳转个人资料
200
+				uni.navigateTo({
201
+					url: "/pages/profile/index"
202
+				})
203
+			}
198 204
 		},
199 205
 		mounted() {
200 206
 			if (this.navbarInitTop == 0) {

BIN
static/acceptOrder/orderCardPic.jpg


BIN
static/icons/plus.png


BIN
static/publicClue/littlePlane.png


+ 5 - 2
store/modules/user.js

@@ -28,13 +28,16 @@ export default {
28 28
 		netConfig: {
29 29
 			// http://59.42.9.166:9520/proxy
30 30
 			// http://10.0.7.100:9500
31
-			ip : "https://crm.nanjingshiyu.com/prod-api", // ip
31
+			// ip : "https://crm.nanjingshiyu.com/prod-api", // ip
32
+			ip : "https://crmtest.nanjingshiyu.com/prod-api", // 测试环境ip
33
+			// ip : "/api", // 测试环境ip
34
+			// ip : "http://47.113.184.101", // 测试环境ip
32 35
 			// ip: "http://172.16.7.200", // ip
33 36
 			// port: "9500", // 端口
34 37
 			isCallOff : "2", // 开关
35 38
 			folder: "", // 文件夹
36 39
 			webRtcIp : "", // 呼叫中心的ip
37
-			webRtcPort : "", // 呼叫中心的端口
40
+			webRtcPort : "", // 呼叫中心的端口s
38 41
 		},
39 42
 		systemList: [],
40 43