Browse Source

新增,修改有权限的可以修改和pc端一样的字段

Yannay 1 month ago
parent
commit
125dad3b68
1 changed files with 353 additions and 199 deletions
  1. 353 199
      pages/clueDetail/tabs/clueInfo/index.vue

+ 353 - 199
pages/clueDetail/tabs/clueInfo/index.vue

@@ -8,35 +8,99 @@
8 8
 				</view>
9 9
 				<view class="caseInfo_main_wrap">
10 10
 					<template v-if="params.type === '1'">
11
-						<view class="Info_item" v-for="(item,index) in caseInfoColumn" :key="item.prop">
12
-							<text class="label">{{item.label}}</text>
11
+						<view class="Info_item" v-for="(item, index) in caseInfoColumn" :key="item.prop">
12
+							<text class="label">{{ item.label }}</text>
13 13
 							<show-real-text :real="clueDetail.telephone" :type='params.type'
14
-								v-if="item.prop === 'telephone'"></show-real-text>
14
+								v-if="item.prop === 'telephone' && !hasEditPermission"></show-real-text>
15
+							<view class="phone_display value"
16
+								v-else-if="item.prop === 'telephone' && hasEditPermission && !phoneEditing"
17
+								@click="phoneEditing = true">{{ clueDetail.dsPhone || '点击编辑' }}</view>
18
+							<view class="input_wrap"
19
+								v-else-if="item.prop === 'telephone' && hasEditPermission && phoneEditing">
20
+								<input v-model="clueDetail.telephone" :focus="phoneEditing"
21
+									style="text-align: right; padding-right: 10px;" @blur="onPhoneBlur" />
22
+							</view>
23
+							<view class="input_wrap" v-else-if="item.type === 'date'">
24
+								<picker mode="date"
25
+									:value="clueDetail[item.prop] ? clueDetail[item.prop].slice(0, 10) : ''"
26
+									:disabled="!hasEditPermission" @change="onDateChange">
27
+									<view class="picker_value">{{ clueDetail[item.prop] ? clueDetail[item.prop].slice(0,
28
+										10) : '请选择日期' }}</view>
29
+								</picker>
30
+							</view>
31
+							<view class="input_wrap corporate_select" v-else-if="item.prop === 'genderTypeCode'">
32
+								<view class="corporate_select_inner">
33
+									<ld-select v-if="hasEditPermission" :list="sysUserSexDict" label-key="dictLabel"
34
+										value-key="dictValue" placeholder="请选择" v-model="clueDetail.genderTypeCode"
35
+										:border="false" @change="updateClueMainInfo" />
36
+									<text v-else class="value">{{ genderTypeCodeLabel }}</text>
37
+								</view>
38
+							</view>
39
+							<view class="input_wrap corporate_select" v-else-if="item.prop === 'corporateStatus'">
40
+								<view class="corporate_select_inner">
41
+									<ld-select v-if="hasEditPermission" :list="crmCorporateStatusDict"
42
+										label-key="dictLabel" value-key="dictValue" placeholder="请选择"
43
+										v-model="clueDetail.corporateStatus" :border="false"
44
+										@change="updateClueMainInfo" />
45
+									<text v-else class="value">{{ corporateStatusLabel }}</text>
46
+								</view>
47
+							</view>
15 48
 							<view class="input_wrap" v-else-if="item.input">
16
-								<input v-model="clueDetail[item.prop]" 
17
-									:disabled="!hasEditPermission"
18
-									style="text-align: right; padding-right: 10px;"
19
-									@blur="updateClueMainInfo" />
49
+								<input v-model="clueDetail[item.prop]" :disabled="!hasEditPermission"
50
+									style="text-align: right; padding-right: 10px;" @blur="updateClueMainInfo" />
20 51
 							</view>
21 52
 							<text v-else-if="item.color" class="value highlight" :style="handleStyle(item.color)">
22
-								{{clueDetail[item.prop]}}
53
+								{{ clueDetail[item.prop] }}
23 54
 							</text>
24
-							<text v-else class="value">{{clueDetail[item.prop]}}</text>
55
+							<text v-else class="value">{{ clueDetail[item.prop] }}</text>
25 56
 						</view>
26 57
 					</template>
27 58
 					<template v-if="params.type === '2'">
28
-						<view class="Info_item" v-for="(item,index) in caseInfoColumn" :key="item.prop">
29
-							<text class="label">{{item.label}}</text>
30
-							<view class="input_wrap" v-if="item.input">
31
-								<input v-model="clueDetail[item.prop]" 
32
-									:disabled="!hasEditPermission"
33
-									style="text-align: right; padding-right: 10px;"
34
-									@blur="updateClueMainInfo" />
59
+						<view class="Info_item" v-for="(item, index) in caseInfoColumn" :key="item.prop">
60
+							<text class="label">{{ item.label }}</text>
61
+							<view class="phone_display value"
62
+								v-if="item.prop === 'telephone' && hasEditPermission && !phoneEditing"
63
+								@click="phoneEditing = true">{{ clueDetail.dsPhone || '点击编辑' }}</view>
64
+							<view class="input_wrap"
65
+								v-else-if="item.prop === 'telephone' && hasEditPermission && phoneEditing">
66
+								<input v-model="clueDetail.telephone" :focus="phoneEditing"
67
+									style="text-align: right; padding-right: 10px;" @blur="onPhoneBlur" />
68
+							</view>
69
+							<text v-else-if="item.prop === 'telephone'" class="value">{{ clueDetail.dsPhone ||
70
+								clueDetail.telephone }}</text>
71
+							<view class="input_wrap" v-else-if="item.type === 'date'">
72
+								<picker mode="date"
73
+									:value="clueDetail[item.prop] ? clueDetail[item.prop].slice(0, 10) : ''"
74
+									:disabled="!hasEditPermission" @change="onDateChange">
75
+									<view class="picker_value">{{ clueDetail[item.prop] ? clueDetail[item.prop].slice(0,
76
+										10) : '请选择日期' }}</view>
77
+								</picker>
78
+							</view>
79
+							<view class="input_wrap corporate_select" v-else-if="item.prop === 'genderTypeCode'">
80
+								<view class="corporate_select_inner">
81
+									<ld-select v-if="hasEditPermission" :list="sysUserSexDict" label-key="dictLabel"
82
+										value-key="dictValue" placeholder="请选择" v-model="clueDetail.genderTypeCode"
83
+										:border="false" @change="updateClueMainInfo" />
84
+									<text v-else class="value">{{ genderTypeCodeLabel }}</text>
85
+								</view>
86
+							</view>
87
+							<view class="input_wrap corporate_select" v-else-if="item.prop === 'corporateStatus'">
88
+								<view class="corporate_select_inner">
89
+									<ld-select v-if="hasEditPermission" :list="crmCorporateStatusDict"
90
+										label-key="dictLabel" value-key="dictValue" placeholder="请选择"
91
+										v-model="clueDetail.corporateStatus" :border="false"
92
+										@change="updateClueMainInfo" />
93
+									<text v-else class="value">{{ corporateStatusLabel }}</text>
94
+								</view>
95
+							</view>
96
+							<view class="input_wrap" v-else-if="item.input">
97
+								<input v-model="clueDetail[item.prop]" :disabled="!hasEditPermission"
98
+									style="text-align: right; padding-right: 10px;" @blur="updateClueMainInfo" />
35 99
 							</view>
36 100
 							<text v-else-if="item.color" class="value highlight" :style="handleStyle(item.color)">
37
-								{{clueDetail[item.prop]}}
101
+								{{ clueDetail[item.prop] }}
38 102
 							</text>
39
-							<text v-else class="value">{{clueDetail[item.prop]}}</text>
103
+							<text v-else class="value">{{ clueDetail[item.prop] }}</text>
40 104
 						</view>
41 105
 					</template>
42 106
 					<template v-if="parsedRemarkDict && Object.keys(parsedRemarkDict).length > 0">
@@ -52,223 +116,313 @@
52 116
 </template>
53 117
 
54 118
 <script>
55
-	import {
56
-		cloneDeep,
57
-		isEqual
58
-	} from 'lodash';
59
-	import { checkPermi } from '@/utils/permission';
119
+import {
120
+	cloneDeep,
121
+	isEqual
122
+} from 'lodash';
123
+import { checkPermi } from '@/utils/permission';
124
+import ldSelect from '@/components/ld-select/ld-select.vue';
60 125
 
61
-	const caseInfoColumn = [{
62
-			prop: 'name',
63
-			label: '姓名',
64
-			input: true
65
-		},
66
-		{
67
-			prop: 'telephone',
68
-			label: '电话',
69
-			input: true
70
-		},
71
-		{
72
-			prop: 'genderTypeCode',
73
-			label: '性别',
74
-		},
75
-		{
76
-			prop: 'age',
77
-			label: '年龄',
78
-		},
79
-		{
80
-			prop: 'weixin',
81
-			label: '微信',
82
-			input: true
83
-		},
84
-		{
85
-			prop: 'corporateStatus',
86
-			label: '企业号状态',
87
-		},
88
-		{
89
-			prop: 'userDouyinId',
90
-			label: '抖音号',
91
-		},
92
-		{
93
-			prop: 'autoAddress',
94
-			label: '自动定位城市',
126
+const caseInfoColumn = [{
127
+	prop: 'name',
128
+	label: '姓名',
129
+	input: true
130
+},
131
+{
132
+	prop: 'telephone',
133
+	label: '电话',
134
+	input: true
135
+},
136
+{
137
+	prop: 'genderTypeCode',
138
+	label: '性别',
139
+	type: 'select',
140
+	dictType: 'sys_user_sex'
141
+},
142
+{
143
+	prop: 'age',
144
+	label: '年龄',
145
+	input: true
146
+},
147
+{
148
+	prop: 'weixin',
149
+	label: '微信',
150
+	input: true
151
+},
152
+{
153
+	prop: 'corporateStatus',
154
+	label: '企业号状态',
155
+	type: 'select',
156
+	dictType: 'crm_corporate_status'
157
+},
158
+{
159
+	prop: 'userDouyinId',
160
+	label: '抖音号',
161
+},
162
+{
163
+	prop: 'autoAddress',
164
+	label: '自动定位城市',
165
+},
166
+{
167
+	prop: 'telAddr',
168
+	label: '手机号归属地',
169
+},
170
+{
171
+	prop: 'createTime',
172
+	label: '线索创建时间',
173
+},
174
+{
175
+	prop: 'updateTime',
176
+	label: '最新修改时间',
177
+},
178
+{
179
+	prop: 'address',
180
+	label: '详细地址',
181
+	input: true
182
+},
183
+{
184
+	prop: 'remark',
185
+	label: '备注',
186
+	input: true
187
+},
188
+{
189
+	prop: 'qq',
190
+	label: 'QQ号',
191
+	input: true
192
+},
193
+{
194
+	prop: 'email',
195
+	label: '邮箱',
196
+	input: true
197
+},
198
+{
199
+	prop: 'date',
200
+	label: '日期',
201
+	type: 'date'
202
+},
203
+{
204
+	prop: 'manualAddressCode',
205
+	label: '手动填写地域',
206
+	input: true
207
+}
208
+]
209
+export default {
210
+	components: { ldSelect },
211
+	props: {
212
+		clueId: {
213
+			required: true
95 214
 		},
96
-		{
97
-			prop: 'telAddr',
98
-			label: '手机号归属地',
215
+		params: {
216
+			type: Object,
217
+			required: true
99 218
 		},
100
-		{
101
-			prop: 'createTime',
102
-			label: '线索创建时间',
219
+		clueDetailVo: {
220
+			type: Object,
221
+			required: true
103 222
 		},
104
-		{
105
-			prop: 'updateTime',
106
-			label: '最新修改时间',
107
-		},
108
-		{
109
-			prop: 'address',
110
-			label: '详细地址',
111
-		},
112
-		{
113
-			prop: 'remark',
114
-			label: '备注',
115
-		},
116
-		{
117
-			prop: 'qq',
118
-			label: 'QQ号',
223
+	},
224
+	computed: {
225
+		parsedRemarkDict() {
226
+			try {
227
+				const remarkDict = this.clueDetailVo.remarkDict
228
+				if (!remarkDict) {
229
+					return null
230
+				}
231
+				if (typeof remarkDict === 'string') {
232
+					const parsed = JSON.parse(remarkDict)
233
+					return typeof parsed === 'object' && parsed !== null ? parsed : null
234
+				}
235
+				return typeof remarkDict === 'object' && remarkDict !== null ? remarkDict : null
236
+			} catch (error) {
237
+				console.error('解析remarkDict失败:', error)
238
+				return null
239
+			}
119 240
 		},
120
-		{
121
-			prop: 'email',
122
-			label: '邮箱',
241
+		corporateStatusLabel() {
242
+			if (!this.clueDetail.corporateStatus || !this.crmCorporateStatusDict.length) return this.clueDetail.corporateStatus || ''
243
+			const item = this.crmCorporateStatusDict.find(d => d.dictValue === this.clueDetail.corporateStatus)
244
+			return item ? item.dictLabel : this.clueDetail.corporateStatus
123 245
 		},
124
-		{
125
-			prop: 'date',
126
-			label: '日期',
246
+		genderTypeCodeLabel() {
247
+			if (!this.clueDetail.genderTypeCode || !this.sysUserSexDict.length) return this.clueDetail.genderTypeCode || ''
248
+			const item = this.sysUserSexDict.find(d => d.dictValue === this.clueDetail.genderTypeCode)
249
+			return item ? item.dictLabel : this.clueDetail.genderTypeCode
127 250
 		},
128
-		{
129
-			prop: 'manualAddressCode',
130
-			label: '手动填写地域',
251
+		hasEditPermission() {
252
+			if (this.params?.type === '2') return true;
253
+			if (this.params?.type === '1') return checkPermi(['crm:PublicClue:detail:edit']);
254
+			return false;
131 255
 		}
132
-	]
133
-	export default {
134
-		props: {
135
-			clueId: {
136
-				required: true
137
-			},
138
-			params: {
139
-				type: Object,
140
-				required: true
141
-			},
142
-			clueDetailVo : {
143
-				type : Object,
144
-				required : true
145
-			},
146
-		},
147
-		computed : {
148
-			parsedRemarkDict() {
149
-			      try {
150
-			        const remarkDict = this.clueDetailVo.remarkDict
151
-			        if (!remarkDict) {
152
-			          return null
153
-			        }
154
-			        if (typeof remarkDict === 'string') {
155
-			          const parsed = JSON.parse(remarkDict)
156
-			          return typeof parsed === 'object' && parsed !== null ? parsed : null
157
-			        }
158
-			        return typeof remarkDict === 'object' && remarkDict !== null ? remarkDict : null
159
-			      } catch (error) {
160
-			        console.error('解析remarkDict失败:', error)
161
-			        return null
162
-			      }
163
-			    },
164
-			hasEditPermission() {
165
-				if (this.params?.type === '2') return true;
166
-				if (this.params?.type === '1') return checkPermi(['crm:PublicClue:detail:edit']);
167
-				return false;
256
+	},
257
+	methods: {
258
+		onDateChange(e) {
259
+			const val = e.detail && e.detail.value;
260
+			if (val) {
261
+				this.$set(this.clueDetail, 'date', val);
262
+				this.updateClueMainInfo();
168 263
 			}
169 264
 		},
170
-		methods: {
171
-			async updateClueMainInfo() {
172
-				if (!this.clueDetail.name) {
173
-					uni.$u.toast("姓名不能为空");
174
-					return;
175
-				}
176
-				if (!isEqual(this.cloneClueDetail, this.clueDetail)) {
177
-					await uni.$u.api.updateClueMainInfo(this.clueDetail);
178
-					uni.$u.toast("修改成功");
179
-					this.getData();
180
-				}
181
-			},
182
-			async getData() {
183
-				const {
184
-					data
185
-				} = await uni.$u.api.getClueMainInfoById({
186
-					id: this.clueId
187
-				});
188
-				this.clueDetail = data;
189
-				this.cloneClueDetail = cloneDeep(data);
265
+		async updateClueMainInfo() {
266
+			if (!this.clueDetail.name) {
267
+				uni.$u.toast("姓名不能为空");
268
+				return;
269
+			}
270
+			if (!isEqual(this.cloneClueDetail, this.clueDetail)) {
271
+				await uni.$u.api.updateClueMainInfo(this.clueDetail);
272
+				uni.$u.toast("修改成功");
273
+				this.getData();
190 274
 			}
191 275
 		},
192
-		created() {
193
-			this.getData();
194
-		},
195
-		data() {
196
-			return {
197
-				cloneClueDetail: {},
198
-				clueDetail: {},
199
-
200
-				caseInfoColumn,
276
+		async getData() {
277
+			const {
278
+				data
279
+			} = await uni.$u.api.getClueMainInfoById({
280
+				id: this.clueId
281
+			});
282
+			if (data.telephone && data.telephone.length >= 7) {
283
+				const phone = data.telephone.substring(3, data.telephone.length - 4);
284
+				data.dsPhone = data.telephone.replace(phone, '****');
285
+			} else {
286
+				data.dsPhone = data.telephone || '';
201 287
 			}
288
+			this.phoneEditing = false;
289
+			this.clueDetail = data;
290
+			this.cloneClueDetail = cloneDeep(data);
291
+		},
292
+		onPhoneBlur() {
293
+			this.phoneEditing = false;
294
+			this.updateClueMainInfo();
295
+		}
296
+	},
297
+	data() {
298
+		return {
299
+			cloneClueDetail: {},
300
+			clueDetail: {},
301
+			phoneEditing: false,
302
+			crmCorporateStatusDict: [],
303
+			sysUserSexDict: [],
304
+			caseInfoColumn,
202 305
 		}
306
+	},
307
+	created() {
308
+		this.getData();
309
+		this.$getDicts('crm_corporate_status').then(res => {
310
+			this.crmCorporateStatusDict = res || [];
311
+		});
312
+		this.$getDicts('sys_user_sex').then(res => {
313
+			this.sysUserSexDict = res || [];
314
+		});
203 315
 	}
316
+}
204 317
 </script>
205 318
 
206 319
 <style lang="scss" scoped>
207
-	.caseInfo_wrap {
208
-		min-height: 400px;
320
+.caseInfo_wrap {
321
+	min-height: 400px;
209 322
 
210
-		.caseInfo_title {
323
+	.caseInfo_title {
324
+		display: flex;
325
+		align-items: center;
326
+		height: 80rpx;
327
+		background: #f4f4f6;
328
+		padding-left: 40rpx;
329
+
330
+		image {
331
+			width: 24rpx;
332
+			height: 24rpx;
333
+			margin-right: 10rpx;
334
+		}
335
+
336
+		.info_text {
337
+			font-size: 24rpx;
338
+			color: #202020;
339
+		}
340
+
341
+		.tabs_wrap {
211 342
 			display: flex;
212
-			align-items: center;
213
-			height: 80rpx;
214
-			background: #f4f4f6;
215
-			padding-left: 40rpx;
216 343
 
217
-			image {
218
-				width: 24rpx;
219
-				height: 24rpx;
220
-				margin-right: 10rpx;
344
+			.tab_item {
345
+				margin-left: 30rpx;
221 346
 			}
347
+		}
348
+	}
222 349
 
223
-			.info_text {
224
-				font-size: 24rpx;
225
-				color: #202020;
350
+	.caseInfo_main_wrap {
351
+		.caseCards_list_wrap {
352
+			background: #ebf6ff;
353
+			margin-bottom: 10rpx;
354
+			margin-left: 10rpx;
355
+			margin-right: 10rpx;
356
+		}
357
+
358
+		.Info_item {
359
+			padding: 18rpx 40rpx;
360
+			display: flex;
361
+			justify-content: space-between;
362
+
363
+			.label {
364
+				color: #999999;
365
+				font-size: 26rpx;
226 366
 			}
227 367
 
228
-			.tabs_wrap {
229
-				display: flex;
368
+			.input_wrap {
369
+				border-bottom: 1px solid #ddd;
370
+			}
230 371
 
231
-				.tab_item {
232
-					margin-left: 30rpx;
233
-				}
372
+			.picker_value {
373
+				text-align: right;
374
+				padding-right: 10px;
375
+				font-size: 26rpx;
376
+				color: #202020;
234 377
 			}
235
-		}
236 378
 
237
-		.caseInfo_main_wrap {
238
-			.caseCards_list_wrap {
239
-				background: #ebf6ff;
240
-				margin-bottom: 10rpx;
241
-				margin-left: 10rpx;
242
-				margin-right: 10rpx;
379
+			.phone_display {
380
+				text-align: right;
381
+				font-size: 26rpx;
382
+				color: #202020;
243 383
 			}
244 384
 
245
-			.Info_item {
246
-				padding: 18rpx 40rpx;
385
+			.corporate_select {
386
+				flex: 1;
247 387
 				display: flex;
248
-				justify-content: space-between;
388
+				justify-content: flex-end;
389
+				min-width: 0;
390
+				border-bottom: none;
391
+			}
249 392
 
250
-				.label {
251
-					color: #999999;
252
-					font-size: 26rpx;
253
-				}
393
+			.corporate_select_inner {
394
+				display: inline-block;
395
+				border-bottom: 1px solid #ddd;
396
+				min-width: 120rpx;
397
+			}
254 398
 
255
-				.input_wrap {
256
-					border-bottom: 1px solid #ddd;
257
-				}
399
+			.corporate_select .value {
400
+				text-align: right;
401
+			}
258 402
 
259
-				.value {
260
-					font-size: 26rpx;
261
-					color: #202020;
262
-					border-radius: 100rpx;
263
-				}
403
+			::v-deep .corporate_select .main,
404
+			::v-deep .corporate_select .ldSelectInput {
405
+				justify-content: flex-end;
406
+				text-align: right;
407
+			}
264 408
 
265
-				.highlight {
266
-					font-size: 22rpx;
267
-					font-weight: 900;
268
-					padding: 6rpx 20rpx;
269
-				}
409
+			::v-deep .corporate_select input {
410
+				text-align: right !important;
411
+			}
412
+
413
+			.value {
414
+				font-size: 26rpx;
415
+				color: #202020;
416
+				border-radius: 100rpx;
270 417
 			}
271
-		}
272 418
 
419
+			.highlight {
420
+				font-size: 22rpx;
421
+				font-weight: 900;
422
+				padding: 6rpx 20rpx;
423
+			}
424
+		}
273 425
 	}
426
+
427
+}
274 428
 </style>