Kaynağa Gözat

app 拍照功能实现 售后服务管理开发

8521520123jsy 1 yıl önce
ebeveyn
işleme
bcb28ac354
28 değiştirilmiş dosya ile 2835 ekleme ve 139 silme
  1. 10 0
      api/mainData/index.js
  2. 41 0
      api/salesServiceManagement/demandList/index.js
  3. 19 0
      api/wms/index.js
  4. 8 0
      enum/dict.js
  5. 41 10
      pages/index/index.vue
  6. 171 6
      pages/maintenance/check/components/CheckCard.vue
  7. 114 0
      pages/maintenance/check/components/PreviewPhoto.vue
  8. 43 25
      pages/maintenance/check/index.vue
  9. 10 4
      pages/maintenanceWorkorder/sparepart/sparepart.vue
  10. 95 2
      pages/maintenanceWorkorder/submitted_ministry/submitted_ministry.vue
  11. 183 66
      pages/repair/repair/index.vue
  12. 15 2
      pages/saleManage/businessOpportunity/index.vue
  13. 12 3
      pages/saleManage/components/selectContact.vue
  14. 20 11
      pages/saleManage/saleOrder/index.vue
  15. 323 0
      pages/salesServiceManagement/demandList/add.vue
  16. 229 0
      pages/salesServiceManagement/demandList/components/AfterSales.vue
  17. 279 0
      pages/salesServiceManagement/demandList/components/Invoice.vue
  18. 122 0
      pages/salesServiceManagement/demandList/components/contactAdd.vue
  19. 196 0
      pages/salesServiceManagement/demandList/components/contactList.vue
  20. 8 0
      pages/salesServiceManagement/demandList/components/demandInfor.vue
  21. 133 0
      pages/salesServiceManagement/demandList/components/faultAdd.vue
  22. 67 0
      pages/salesServiceManagement/demandList/components/invoice.scss
  23. 165 0
      pages/salesServiceManagement/demandList/components/itemSelect.vue
  24. 94 0
      pages/salesServiceManagement/demandList/components/screen.vue
  25. 294 0
      pages/salesServiceManagement/demandList/index.vue
  26. 125 1
      pages/tour_tally/check/components/CheckCard.vue
  27. 2 1
      pages/tour_tally/check/index.vue
  28. 16 8
      pages/tour_tally/order/order.vue

+ 10 - 0
api/mainData/index.js

@@ -81,6 +81,16 @@ export async function enterprisePage(params) {
 	}
 	return Promise.reject(new Error(res.message));
 }
+/**
+ * 获取系统参数
+ */
+export async function parameterGetByCode(data) {
+	const res = await postJ(Vue.prototype.apiUrl + `/sys/parameter/getByCode`, data);
+	if (res.code == 0) {
+		return res.data;
+	}
+	return Promise.reject(new Error(res.message));
+}
 // // 根据工艺路线编码获取工序
 // export async function getProcessByRoute (data) {
 //   const res = await request.post(

+ 41 - 0
api/salesServiceManagement/demandList/index.js

@@ -0,0 +1,41 @@
+import {
+	get,
+	put,
+	putJ,
+	postJ,
+	deleteApi
+} from "@/utils/request";
+import Vue from "vue";
+
+/**
+ * 获取售后需求列表数据
+ */
+export async function getTableList(params) {
+	const res = await get(Vue.prototype.apiUrl + `/eom/afterSalesDemand/page`, params);
+	if (res.code == 0) {
+		return res.data;
+	}
+	return Promise.reject(new Error(res.message));
+}
+
+/**
+ * 获取信息详情 仓库
+ */
+export async function getSendSaleOrderrecordDetailSplit(id) {
+	const data = await get(
+		Vue.prototype.apiUrl + `/eom/saleordersendrecord/getByIdSplit/${id}`, {}
+	);
+	if (data.code == 0) {
+		return data.data;
+	}
+	return Promise.reject(data.message);
+}
+
+//新增
+export async function saveSalesDemand(data) {
+	const res = await postJ(Vue.prototype.apiUrl + `/eom/afterSalesDemand/save`, data);
+	if (res.code == 0) {
+		return res.data;
+	}
+	return Promise.reject(new Error(res.message));
+}

+ 19 - 0
api/wms/index.js

@@ -0,0 +1,19 @@
+import {
+	get,
+	put,
+	putJ,
+	postJ
+} from "@/utils/request";
+import Vue from "vue";
+
+// 查询出入库详情
+//sourceBizNo
+export async function getInfoBySourceBizNoAll(sourceBizNo) {
+	const data = await get(
+		Vue.prototype.apiUrl + `/wms/outintwo/getInfoBySourceBizNoAll/${sourceBizNo}`, {}
+	);
+	if (data.code == 0) {
+		return data.data;
+	}
+	return Promise.reject(data.message);
+}

+ 8 - 0
enum/dict.js

@@ -4,3 +4,11 @@ export default {
   资产类型: 'ASSECTSTYPE',
   物品类型: 'classify'
 }
+
+//发货审核状态
+export const reviewStatusEnum = [
+  { value: 0, label: '未提交' },
+  { value: 1, label: '审核中' },
+  { value: 2, label: '已审核' },
+  { value: 3, label: '审核未通过' }
+];

+ 41 - 10
pages/index/index.vue

@@ -1,6 +1,7 @@
 <template>
 	<view>
-		<uni-nav-bar fixed="true" statusBar="true" title="工作台" right-icon="scan" @clickRight="HandlScanCode"></uni-nav-bar>
+		<uni-nav-bar fixed="true" statusBar="true" title="工作台" right-icon="scan"
+			@clickRight="HandlScanCode"></uni-nav-bar>
 		<view>
 			<CellTip title="协同办公" v-if="internalManagementList.length > 0"></CellTip>
 			<view class="nav">
@@ -17,7 +18,8 @@
 			<CellTip title="生产管理" v-if="productionList.length > 0"></CellTip>
 			<view class="nav">
 				<view class="nav-content">
-					<view class="nav-item" v-for="item in productionList" :key="item.link_url" @click="toNav(item.path)">
+					<view class="nav-item" v-for="item in productionList" :key="item.link_url"
+						@click="toNav(item.path)">
 						<span :class="'iconfont ' + item.icon"></span>
 						<label>{{ item.title }}</label>
 						<label>{{ item.num }}</label>
@@ -53,6 +55,18 @@
 				</view>
 			</view>
 		</view>
+		<view>
+			<CellTip title="售后服务管理"></CellTip>
+			<view class="nav">
+				<view class="nav-content">
+					<view class="nav-item" v-for="(item, index) in serviceList" @click="toNav(item.path)">
+						<span :class="'iconfont ' + item.icon"></span>
+						<i class="badge" v-if="item.badge">{{ item.badge }}</i>
+						<label>{{ item.name }}</label>
+					</view>
+				</view>
+			</view>
+		</view>
 		<view>
 			<CellTip title="仓储管理" v-if="warehousingList.length > 0"></CellTip>
 
@@ -113,7 +127,9 @@
 
 <script>
 	import CellTip from '@/components/CellTip.vue'
-	import { statistics } from '@/api/myTicket'
+	import {
+		statistics
+	} from '@/api/myTicket'
 	export default {
 		components: {
 			CellTip
@@ -404,7 +420,22 @@
 					// }
 				],
 				treeList: [],
-				saleManageList: []
+				saleManageList: [],
+				// 售后服务
+				serviceList: [{
+						name: '售后需求',
+						url: `/pages/salesServiceManagement/demandList/index`,
+						path: '/pages/salesServiceManagement/demandList/index',
+						icon: 'icon-gongdanguanli',
+						badge: 0
+					},
+					// {
+					// 	name: '发货确认单',
+					// 	url: `/pages/invoiceConfirm/index`,
+					// 	icon: 'icon-gongdanguanli',
+					// 	badge: 0
+					// }
+				]
 			}
 		},
 		created() {
@@ -459,12 +490,12 @@
 								item.name = item.name.replace('员工', '')
 								item.name = item.name.replace('管理员', '')
 							})
-						}else if (f.path == 'internalManagement') {
-							console.log(f,'f')
+						} else if (f.path == 'internalManagement') {
+							console.log(f, 'f')
 							this.internalManagementList = f.children
-							
+
 						}
-						
+
 					})
 				}
 			},
@@ -478,7 +509,7 @@
 			HandlScanCode() {
 				let _this = this
 				uni.scanCode({
-					success: function (res) {
+					success: function(res) {
 						_this.scantoRouter(res.result)
 					}
 				})
@@ -494,4 +525,4 @@
 
 <style lang="scss" scoped>
 	@import 'index.scss';
-</style>
+</style>

+ 171 - 6
pages/maintenance/check/components/CheckCard.vue

@@ -34,9 +34,11 @@
 					<div v-if="item.status == 0" style="color: green">正常</div>
 					<div v-else-if="item.status == -1" style="color: red">异常</div>
 				</view>
-				<textarea v-if="type !== 'view'" placeholder="请输入" v-model="item.result" @input="inputChange($event, item)" />
+				<textarea v-if="type !== 'view'" placeholder="请输入" v-model="item.result"
+					@input="inputChange($event, item)" />
 				<view class="result-text" v-else>{{ item.result }}</view>
 				<view class="radio-wrapper" v-if="type !== 'view'">
+
 					<!-- <div
 						v-for="(it, ind) in statusList"
 						:key="ind"
@@ -71,11 +73,30 @@
 				</view>
 			</view>
 		</view>
+		<!-- 新增拍照 *** -->
+		<view class="card-cell">
+			<text class="label">
+				<span class="mark"></span>
+			</text>
+			<view class="photo_info">
+				<view class="btn_box" v-if="type != 'view'">
+					<text class="photo_btn" @click="chooseImage">拍照</text>
+				</view>
+				<view class="photo_list">
+					<PreviewPhoto :type="type" @imagedelete="imagedelete" :imageList="photoList" />
+				<!-- 	<u-album :urls="photoList" :rowCount="3" @delete="handleDelete" :maxCount="9" :singleSize="180"
+						:multipleSize="180"></u-album> -->
+				</view>
+			</view>
+		</view>
+		<u-toast ref="uToast"></u-toast>
 	</view>
 </template>
 
 <script>
+	import PreviewPhoto from './PreviewPhoto.vue'
 	export default {
+		components:{ PreviewPhoto },
 		props: {
 			item: {
 				type: Object,
@@ -89,14 +110,27 @@
 		},
 		data() {
 			return {
-				statusList: [
-					{ label: '正常', status: 0 },
-					{ label: '异常', status: -1 }
+				statusList: [{
+						label: '正常',
+						status: 0
+					},
+					{
+						label: '异常',
+						status: -1
+					}
 				]
 			}
 		},
+		// *** 新增
+		computed: {
+			photoList() {
+				if (!this.item.photoList) return []
+				return this.item.photoList
+			}
+		},
 		methods: {
 			inputChange(obj, item) {
+				console.log(item, 'item --')
 				if (obj.target.value.length > 0) {
 					item.status = -1
 				} else {
@@ -105,40 +139,132 @@
 			},
 			changeStatus(item, it) {
 				item.status = it.status
-			}
+			},
+
+			// handleDelete(e, i) {
+			// 	console.log(e, 'eeeee');
+			// 	console.log(i, 'iiiiiiiiiiii')
+			// },
+			
+			// 图片删除
+			imagedelete(index){
+				this.item.photoList.splice(index,1);
+			},
+
+			// *** 新增拍照功能
+			chooseImage() {
+				const _this = this
+				if(_this.photoList.length >= 9){
+					_this.$refs.uToast.show({
+						type: "warning",
+						message: "最多上传9张照片",
+					})
+					return
+				}
+				uni.chooseImage({
+					count: 9, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['camera'], //从相册选择
+					success: function(res) {
+						uni.showLoading({
+							title: '加载中'
+						})
+
+						_this.uploadFile(res.tempFilePaths).then(res => {
+							res.forEach(item => {
+								let fileNames = item.storePath.split('/')
+								let url = _this.apiUrl +
+									'/main/file/getFile?objectName=' + item.storePath +
+									'&fullfilename=' + fileNames[fileNames.length -
+										1]
+								console.log(_this.item, 'url ---')
+								if (!_this.item.photoList || _this.item.photoList?.length ==
+									0) {
+									_this.$set(_this.item, 'photoList', [url])
+								} else {
+									// 不能存储超过 9 张
+									if(_this.item.photoList.length < 9){
+										_this.item.photoList.push(url);
+									}
+								}
+								// _this.imgs.push(url)
+							})
+							uni.hideLoading()
+
+						})
+					}
+				});
+			},
+			uploadFile(list) {
+				let PromiseAll = []
+				const apiUrl = this.apiUrl
+				const token = uni.getStorageSync("token"); //取存本地的token
+				list.forEach(item => {
+					PromiseAll.push(
+						new Promise((resolve, reject) => {
+							uni.uploadFile({
+								url: apiUrl + '/main/file/upload',
+								filePath: item,
+								name: 'multiPartFile',
+								header: {
+									authorization: token
+								},
+								success: (uploadFileRes) => {
+									let data = JSON.parse(uploadFileRes.data)
+									resolve(data.data)
+								}
+							});
+						}),
+					)
+				})
+				return Promise.all(PromiseAll)
+			},
 		}
 	}
 </script>
 
 <style lang="scss" scoped>
 	$border-color: #f2f2f2;
+
 	.kd-check-card {
 		font-size: 28rpx;
 		border: 1rpx solid $border-color;
+
 		.label {
 			display: inline-block;
 			width: 80rpx;
 			text-align: center;
 			border-right: 1px solid $border-color;
 			justify-content: center;
+			
+			.mark{
+				width: 80rpx;
+				height: 4rpx;
+				display: inline-block;
+			}
 		}
+
 		.title {
 			line-height: 72rpx;
 			font-weight: bold;
 			background-color: #f2f2f2;
 		}
+
 		.card-cell {
 			min-height: 72rpx;
 			display: flex;
 			align-items: stretch;
 			border: 1px solid $border-color;
+
 			text {
 				display: flex;
 				align-items: center;
 			}
 		}
+
 		.cell-content {
 			flex: 1;
+
 			.content-status {
 				width: 100%;
 				height: 50rpx;
@@ -147,27 +273,33 @@
 				border-bottom: 1rpx solid #f2f2f2;
 			}
 		}
+
 		.radio-wrapper {
 			padding: 10rpx 20rpx;
 			border-bottom: 1px solid $border-color;
 			margin-left: -8rpx;
 		}
+
 		/deep/uni-textarea {
 			width: 100%;
 			box-sizing: border-box;
 		}
+
 		.result-text {
 			min-height: 100rpx;
 			padding: 10rpx;
 		}
+
 		.cell-content {
 			padding-left: 8rpx;
 		}
+
 		.radio-wrapper {
 			display: flex;
 			align-items: center;
 			justify-content: space-around;
 		}
+
 		.wrapper-box {
 			width: 45%;
 			height: 80rpx;
@@ -177,5 +309,38 @@
 			color: #000;
 			border-radius: 15rpx;
 		}
+
+		.photo_info {
+			width: 100%;
+			padding: 6px 12rpx;
+			// display: flex;
+			// align-items: center;
+			
+			.btn_box{
+				width: 100%;
+			}
+
+			.photo_btn {
+				// margin-left: ;
+				background-color: #157a2c;
+				width: 140rpx;
+				height: 60rpx;
+				text-align: center;
+				line-height: 60rpx;
+				font-size: 24rpx;
+				color: #fff;
+				text-align: center;
+				border-radius: 8rpx;
+				margin-bottom: 12rpx;
+				display: inline-block;
+			}
+		}
+		
+		/deep/.u-album__row__wrapper {
+			uni-image {
+				width: 180rpx !important;
+				height: 180rpx !important;
+			}
+		}
 	}
-</style>
+</style>

+ 114 - 0
pages/maintenance/check/components/PreviewPhoto.vue

@@ -0,0 +1,114 @@
+<template>
+	<view class="container">
+		<!-- 图片列表 -->
+		<view class="image-list">
+			<view class="image-item" :style="{height:height || '180rpx'}" v-for="(item, index) in imageList"
+				:key="index">
+				<text class="imagedelete" @click="$emit('imagedelete',index)" v-if="type != 'view'">
+					x
+				</text>
+				<image :src="item" mode="aspectFill" lazy-load @click="previewImage(index)"></image>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				height: '180rpx'
+			};
+		},
+		watch: {
+
+		},
+		props: {
+			type: {
+				type: String,
+				default: 'edit'
+			},
+			imageList: {
+				type: Array,
+				default: () => []
+			}
+		},
+		mounted() {
+			this.getElementWidth();
+		},
+		methods: {
+			// 预览图片
+			previewImage(index) {
+				uni.previewImage({
+					current: index,
+					urls: this.imageList.map(item => item)
+				});
+			},
+			getElementWidth() {
+				// 创建查询实例
+				const query = uni.createSelectorQuery().in(this);
+
+				// 选择要查询的元素
+				query.select('.container')
+					.boundingClientRect(data => {
+						console.log(data.width,'data.width')
+						let height = Math.floor(((data.width - 20) * 31) / 50);
+						this.height = height > 160 ? height + 'rpx' : '180rpx'
+					})
+					.exec();
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.container {
+		padding: 10px;
+	}
+
+	.imagedelete {
+		position: absolute;
+		z-index: 20;
+		display: block;
+		right: 4rpx;
+		top: -2rpx;
+		text-align: center;
+		background: rgba(0, 0, 0, 0.5);
+		color: #fff;
+		border-radius: 50%;
+		font-size: 30rpx;
+		width: 44rpx;
+		height: 44rpx;
+		line-height: 40rpx;
+		text-align: center;
+	}
+
+	.image-list {
+		display: flex;
+		flex-wrap: wrap;
+
+		.image-item {
+			position: relative;
+			width: 31%;
+			margin-bottom: 10px;
+			margin-right: 3%;
+
+			image {
+				width: 100%;
+				height: 100%;
+				border-radius: 5px;
+			}
+
+			text {
+				display: block;
+				margin-top: 5px;
+				font-size: 14px;
+				text-align: center;
+			}
+		}
+
+		.image-item:nth-child(3n) {
+			margin-right: 0;
+		}
+	}
+</style>

+ 43 - 25
pages/maintenance/check/index.vue

@@ -18,14 +18,16 @@
 				<view class="btn primary" @click="handleSave">保存</view>
 			</view>
 		</view>
-		<u-modal :show.sync="visible" class="maintenance-order" :showCancelButton="true" @confirm="confirm" @cancel="cancel" :closeOnClickOverlay="true">
+		<u-modal :show.sync="visible" class="maintenance-order" :showCancelButton="true" @confirm="confirm"
+			@cancel="cancel" :closeOnClickOverlay="true">
 			<view class="" style="flex: 1">
 				<view class="title">备件使用登记</view>
 				<view class="register-content">
 					<view class="inner">
 						<view class="col" v-for="item in applyEquiPartList">
 							{{ item.name }}({{ item.code }}/{{ item.model }})
-							<u-number-box v-model="item.usedNum" :step="1" :min="item.min" :max="item.num"></u-number-box>
+							<u-number-box v-model="item.usedNum" :step="1" :min="item.min"
+								:max="item.num"></u-number-box>
 						</view>
 					</view>
 				</view>
@@ -33,24 +35,26 @@
 		</u-modal>
 
 		<uni-popup ref="inputDialog" type="dialog">
-			<uni-popup-dialog
-				ref="inputClose"
-				mode="input"
-				title="您当前已超出计划完成时间,请填写原因"
-				placeholder="请输入内容"
-				:before-close="true"
-				@close="handleClose"
-				@confirm="timeoutCauseConfirm"></uni-popup-dialog>
+			<uni-popup-dialog ref="inputClose" mode="input" title="您当前已超出计划完成时间,请填写原因" placeholder="请输入内容"
+				:before-close="true" @close="handleClose" @confirm="timeoutCauseConfirm"></uni-popup-dialog>
 		</uni-popup>
 	</view>
 </template>
 
 <script>
-	import { getDeviceInfo, mattersChecked } from '@/api/myTicket/index.js'
-	import { post, postJ } from '@/utils/api.js'
+	import {
+		getDeviceInfo,
+		mattersChecked
+	} from '@/api/myTicket/index.js'
+	import {
+		post,
+		postJ
+	} from '@/utils/api.js'
 	import CheckCard from './components/CheckCard.vue'
 	export default {
-		components: { CheckCard },
+		components: {
+			CheckCard
+		},
 		data() {
 			return {
 				registerObj: [],
@@ -128,7 +132,7 @@
 			// 	})
 			// },
 			handleSave() {
-				console.log(this.equipList)
+				console.log(this.equipList, '-------')
 				let isAllPass = true
 				isAllPass = this.equipList.every(item => item.status > -1)
 				let params = {
@@ -142,7 +146,9 @@
 							operationGuide: item.operationGuide,
 							result: item.result,
 							serialNum: item.serialNum,
-							status: item.status
+							status: item.status,
+							// 新增 拍照数据
+							photoList: item.photoList || []
 						}
 					})
 				}
@@ -205,14 +211,13 @@
 			},
 			_report(timeoutCause = '') {
 				post(
-					this.apiUrl + '/workOrder/reportWork',
-					{
-						workOrderId: this.workOrderId,
-						timeoutCause
-					},
-					true,
-					false
-				)
+						this.apiUrl + '/workOrder/reportWork', {
+							workOrderId: this.workOrderId,
+							timeoutCause
+						},
+						true,
+						false
+					)
 					.then(res => {
 						if (res?.success) {
 							let data = res.data
@@ -257,7 +262,9 @@
 			},
 
 			getList() {
-				getDeviceInfo({ id: this.id }).then(data => {
+				getDeviceInfo({
+					id: this.id
+				}).then(data => {
 					this.equiName = data.name
 					this.equiCode = data.code
 					this.equipList = data.workItems.map(item => {
@@ -294,17 +301,20 @@
 		display: flex;
 		flex-direction: column;
 		padding-bottom: 100rpx;
+
 		.title {
 			line-height: 80rpx;
 			display: flex;
 			justify-content: space-between;
 			padding: 0 30rpx;
 		}
+
 		.check-list {
 			flex: 1;
 			overflow: auto;
 			padding: 0 30rpx 100rpx;
 		}
+
 		.footer {
 			height: 100rpx;
 			display: flex;
@@ -314,12 +324,14 @@
 			border: 1rpx solid $j-primary-border-green;
 			background: #fff;
 			z-index: 100;
+
 			.btn {
 				display: flex;
 				flex: 1;
 				justify-content: center;
 				align-items: center;
 				border-radius: 0;
+
 				&.primary {
 					background-color: $j-primary-border-green;
 					color: #fff;
@@ -331,14 +343,17 @@
 			margin-bottom: 20rpx;
 		}
 	}
+
 	.nav-right {
 		position: relative;
+
 		.text-box {
 			white-space: nowrap;
 			padding: 4rpx;
 			border: 1rpx solid rgba(242, 242, 242, 1);
 		}
 	}
+
 	.maintenance-order {
 		/deep/ .u-modal__content {
 			padding: 0 !important;
@@ -350,17 +365,20 @@
 				height: 1.4em !important;
 			}
 		}
+
 		.title {
 			background-color: rgba(51, 51, 51, 1);
 			line-height: 60rpx;
 			text-align: center;
 			color: #fff;
 		}
+
 		.register-content {
 			padding: 20rpx;
 
 			.inner {
 				border: 1rpx solid rgba(242, 242, 242, 1);
+
 				.col {
 					font-size: 28rpx;
 					border-bottom: 1rpx solid rgba(242, 242, 242, 1);
@@ -371,4 +389,4 @@
 			}
 		}
 	}
-</style>
+</style>

+ 10 - 4
pages/maintenanceWorkorder/sparepart/sparepart.vue

@@ -43,12 +43,13 @@
 					{{ addForm.fixCode }}
 				</view>
 			</Cell> -->
-
+			<!-- addForm.receivingDeptName -->
 			<Cell cellType="more" title="领用部门">
 				<view class="cell-tip-right" slot="more">
 					{{ addForm.receivingDeptName }}
 				</view>
 			</Cell>
+			<!-- {{ addForm.recipientName }} -->
 			<Cell cellType="more" title="领用人">
 				<view class="cell-tip-right" slot="more">
 					{{ addForm.recipientName }}
@@ -242,7 +243,9 @@
 					usageTime: '', //使用时间 //详情信息
 					detailList: [],
 					deviceId: '',
-					executorDeptName: ''
+					executorDeptName: '',
+					receivingDeptName:'',
+					recipientName:""
 				},
 				tableList: [],
 				deviceList: [],
@@ -262,6 +265,7 @@
 		},
 		async onLoad(data) {
 			const obj = JSON.parse(data.data)
+			console.log(obj,'obj ----')
 			this.type = obj.pageType
 			this.getDept()
 			if (this.type == 'add') {
@@ -269,7 +273,8 @@
 				this.addForm.repairName = obj.planName;
 				this.addForm.repairId = obj.id;
 				this.deviceList = obj.deviceList;
-
+				this.addForm.receivingDeptName = obj.createGroupName;
+				this.addForm.recipientName = obj.executeUserName;
 				// if (!obj.sparePartsApplyList) {
 				// 	this.addForm.deviceName = obj.deviceName;
 				// 	this.addForm.fixCode = obj.fixCode;
@@ -355,10 +360,11 @@
 					})
 					return
 				}
+
 				uni.showLoading({
 					title: '加载中'
 				})
-
+				
 				this.addForm.detailList = this.tableList
 				this.addForm.deviceList = this.deviceList
 				applySpareParts(this.addForm)

+ 95 - 2
pages/maintenanceWorkorder/submitted_ministry/submitted_ministry.vue

@@ -31,6 +31,12 @@
 				<fileMain v-model="form.attachments"></fileMain>
 				<!-- <uni-file-picker :limit="4" v-model="FileImgList" fileMediatype="image" mode="grid" @select="handlImageSelect" @delete="handlImagDeletee" /> -->
 			</view>
+			<view class="sc-wrap" style="margin-top: 38rpx;">
+				<view class="photo_btn" @click="chooseImage">拍照</view>
+				<view class="photo_list">
+					<PreviewPhoto type="edit" @imagedelete="imagedelete" :imageList="form.photoList" />
+				</view>
+			</view>
 			<view class="bpbj" v-if="form.stockOutApplyPartList.length > 0">
 				<view class="title">备件使用登记</view>
 				<view class="detail-content">
@@ -46,10 +52,12 @@
 			<view class="item s1" @click="submit">提交</view>
 			<view class="item s2" @click="goBack">返回</view>
 		</view>
+		<u-toast ref="uToast"></u-toast>
 	</view>
 </template>
 
 <script>
+	import PreviewPhoto from '@/pages/maintenance/check/components/PreviewPhoto.vue'
 	import {
 		getWorkOrderDetail,
 		getDeviceList,
@@ -65,7 +73,8 @@
 	import fileMain from "@/pages/doc/index.vue"
 	export default {
 		components: {
-			fileMain
+			fileMain,
+			PreviewPhoto
 		},
 		data() {
 			return {
@@ -79,6 +88,8 @@
 					// 备品备件
 					stockOutApplyPartList: [],
 					attachments: [],
+					// 拍照列表
+					photoList: []
 				},
 				workOrderCode: '',
 				// 选择的图片
@@ -104,6 +115,74 @@
 					}
 				})
 			},
+			// 图片删除
+			imagedelete(index) {
+				this.form.photoList.splice(index, 1);
+			},
+			// *** 新增拍照功能
+			chooseImage() {
+				const _this = this
+				if (_this.form.photoList.length >= 9) {
+					_this.$refs.uToast.show({
+						type: "warning",
+						message: "最多上传9张照片",
+					})
+					return
+				}
+				uni.chooseImage({
+					count: 9, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['camera'], //从相册选择
+					success: function(res) {
+						uni.showLoading({
+							title: '加载中'
+						})
+
+						_this.uploadFile(res.tempFilePaths).then(res => {
+							res.forEach(item => {
+								let fileNames = item.storePath.split('/')
+								let url = _this.apiUrl +
+									'/main/file/getFile?objectName=' + item.storePath +
+									'&fullfilename=' + fileNames[fileNames.length -
+										1]
+
+								let photoList = _this.form.photoList;
+								// 不能存储超过 9 张
+								if (photoList.length < 9) {
+									_this.form.photoList.push(url);
+								}
+							})
+							uni.hideLoading()
+
+						})
+					}
+				});
+			},
+			uploadFile(list) {
+				let PromiseAll = []
+				const apiUrl = this.apiUrl
+				const token = uni.getStorageSync("token"); //取存本地的token
+				list.forEach(item => {
+					PromiseAll.push(
+						new Promise((resolve, reject) => {
+							uni.uploadFile({
+								url: apiUrl + '/main/file/upload',
+								filePath: item,
+								name: 'multiPartFile',
+								header: {
+									authorization: token
+								},
+								success: (uploadFileRes) => {
+									let data = JSON.parse(uploadFileRes.data)
+									resolve(data.data)
+								}
+							});
+						}),
+					)
+				})
+				return Promise.all(PromiseAll)
+			},
+
 			// 返回
 			goBack() {
 				uni.navigateBack({
@@ -165,7 +244,8 @@
 					id: this.worksheetInfo.id,
 					remark: this.form.repairReportExplain,
 					attachments: this.form.attachments,
-					workOrderImg: this.form.workOrderImg.join(',')
+					// workOrderImg: this.form.workOrderImg.join(',')
+					photoList: this.form.photoList
 				}).then(() => {
 					uni.showToast({
 						title: '报工成功',
@@ -233,6 +313,19 @@
 </script>
 
 <style lang="scss" scoped>
+	.photo_btn {
+		background-color: #157a2c;
+		width: 140rpx;
+		height: 60rpx;
+		line-height: 60rpx;
+		font-size: 24rpx;
+		color: #fff;
+		text-align: center;
+		border-radius: 8rpx;
+		margin-bottom: 12rpx;
+		display: inline-block;
+	}
+	
 	.fixed-top-bar {
 		display: flex;
 		background: #fff;

+ 183 - 66
pages/repair/repair/index.vue

@@ -1,6 +1,7 @@
 <template>
 	<view class="main">
-		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" right-icon="scan" title="申请报修" @clickLeft="goHome" @clickRight="HandlScanCode"></uni-nav-bar>
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" right-icon="scan" title="申请报修" @clickLeft="goHome"
+			@clickRight="HandlScanCode"></uni-nav-bar>
 		<view>
 			<!-- <CellTip title="基本信息" /> -->
 			<!-- <Cell cellType="more" title="选择设备">
@@ -65,13 +66,15 @@
 			<view class="item">
 				<view class="label">通知领导</view>
 				<view class="value-wrap" style="padding-left: 0">
-					<zxz-uni-data-select :localdata="userList" v-model="addForm.leaderUserId" @change="handleUserChange"></zxz-uni-data-select>
+					<zxz-uni-data-select :localdata="userList" v-model="addForm.leaderUserId"
+						@change="handleUserChange"></zxz-uni-data-select>
 				</view>
 			</view>
 			<view class="item">
 				<view class="label">期望完成时间</view>
 				<view class="value-wrap">
-					<uni-datetime-picker type="datetime" class="picker" v-model="addForm.expectedTime" @change="confirm">
+					<uni-datetime-picker type="datetime" class="picker" v-model="addForm.expectedTime"
+						@change="confirm">
 						{{ showTime }}
 					</uni-datetime-picker>
 				</view>
@@ -79,7 +82,14 @@
 		</view>
 		<view class="gzms-wrap">
 			<view class="title">故障描述</view>
-			<u--textarea v-model="addForm.remark" class="border" maxlength="500" placeholder="请输入内容" count></u--textarea>
+			<u--textarea v-model="addForm.remark" class="border" maxlength="500" placeholder="请输入内容"
+				count></u--textarea>
+		</view>
+		<view class="gzms-wrap">
+			<view class="photo_btn" @click="chooseImage">拍照</view>
+			<view class="photo_list">
+				<PreviewPhoto type="add" @imagedelete="imagedelete" :imageList="form.repairsImg" />
+			</view>
 		</view>
 		<!-- <view class="sc-wrap">
 			<view class="title">相关照片</view>
@@ -89,19 +99,34 @@
 		<view class="footer">
 			<text @click="submitAdd">报修</text>
 		</view>
-		<ba-tree-picker ref="treePicker" :multiple="false" @select-change="confirmDep" title="选择部门" :localdata="listData" valueKey="id" textKey="name" childrenKey="children" />
+		<ba-tree-picker ref="treePicker" :multiple="false" @select-change="confirmDep" title="选择部门"
+			:localdata="listData" valueKey="id" textKey="name" childrenKey="children" />
+		<u-toast ref="uToast"></u-toast>
 	</view>
 </template>
 
 <script>
+	import PreviewPhoto from '@/pages/maintenance/check/components/PreviewPhoto.vue'
 	import baTreePicker from '@/components/ba-tree-picker/ba-tree-picker.vue'
-	import { listOrganizations, getUserPage } from '@/api/myTicket/index.js'
+	import {
+		listOrganizations,
+		getUserPage
+	} from '@/api/myTicket/index.js'
 	import Assign from '@/components/Assign.vue'
-	import { getAssetInfo, save, getByFixCode } from '@/api/repair'
+	import {
+		getAssetInfo,
+		save,
+		getByFixCode
+	} from '@/api/repair'
 	import CellTip from '@/components/CellTip.vue'
 	import Cell from '@/components/Cell.vue'
-	import { postJ, get } from '@/utils/api.js'
-	import { getRuleNo } from '@/utils/utils.js'
+	import {
+		postJ,
+		get
+	} from '@/utils/api.js'
+	import {
+		getRuleNo
+	} from '@/utils/utils.js'
 	import selectUser from '../selectUser/index.vue'
 	import dayjs from 'dayjs'
 	export default {
@@ -110,7 +135,8 @@
 			Cell,
 			selectUser,
 			Assign,
-			baTreePicker
+			baTreePicker,
+			PreviewPhoto
 		},
 		data() {
 			return {
@@ -164,6 +190,74 @@
 					url: '/pages/index/index'
 				})
 			},
+			// *** 新增拍照
+			chooseImage() {
+				const _this = this
+				if (_this.form.repairsImg.length >= 9) {
+					_this.$refs.uToast.show({
+						type: "warning",
+						message: "最多上传9张照片",
+					})
+					return
+				}
+				uni.chooseImage({
+					count: 9, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['camera'], //从相册选择
+					success: function(res) {
+						uni.showLoading({
+							title: '加载中'
+						})
+
+						_this.uploadFile(res.tempFilePaths).then(res => {
+							res.forEach(item => {
+								let fileNames = item.storePath.split('/')
+								let url = _this.apiUrl +
+									'/main/file/getFile?objectName=' + item.storePath +
+									'&fullfilename=' + fileNames[fileNames.length -
+										1]
+								let repairsImg = _this.form.repairsImg;
+								// 不能存储超过 9 张
+								if (repairsImg.length < 9) {
+									_this.form.repairsImg.push(url);
+								}
+							})
+							uni.hideLoading()
+
+						})
+					}
+				});
+			},
+			uploadFile(list) {
+				let PromiseAll = []
+				const apiUrl = this.apiUrl
+				const token = uni.getStorageSync("token"); //取存本地的token
+				list.forEach(item => {
+					PromiseAll.push(
+						new Promise((resolve, reject) => {
+							uni.uploadFile({
+								url: apiUrl + '/main/file/upload',
+								filePath: item,
+								name: 'multiPartFile',
+								header: {
+									authorization: token
+								},
+								success: (uploadFileRes) => {
+									let data = JSON.parse(uploadFileRes.data)
+									resolve(data.data)
+								}
+							});
+						}),
+					)
+				})
+				return Promise.all(PromiseAll)
+			},
+			// 图片删除
+			imagedelete(index) {
+				this.form.repairsImg.splice(index, 1);
+			},
+
+			// ***
 			// 提交新增
 			submitAdd() {
 				if (!this.addForm.code) {
@@ -186,7 +280,8 @@
 					sourceType: 1,
 					leaderDeptId: this.addForm.leaderDeptId,
 					leaderUserId: this.addForm.leaderUserId,
-					leaderName: this.addForm.leaderName
+					leaderName: this.addForm.leaderName,
+					repairsImg: this.form.repairsImg,
 				}
 				save(params)
 					.then(res => {
@@ -217,7 +312,11 @@
 				this.getUser(data[0])
 			},
 			getUser(deptCode) {
-				getUserPage({ pageNum: 1, size: -1, groupId: deptCode }).then(data => {
+				getUserPage({
+					pageNum: 1,
+					size: -1,
+					groupId: deptCode
+				}).then(data => {
 					this.userList = data.list.map(item => {
 						item.text = item.name
 						item.value = item.id
@@ -242,7 +341,8 @@
 						...res,
 						leaderUserId: ''
 					}
-					this.addForm.equiLocation = this.addForm.deviceLocationName + '-' + this.addForm.deviceDetailAddress
+					this.addForm.equiLocation = this.addForm.deviceLocationName + '-' + this.addForm
+						.deviceDetailAddress
 				})
 			},
 			confirm(e) {
@@ -265,7 +365,8 @@
 				this.form.equiCode = data.assetCode
 				this.form.equiName = data.assetName
 				this.form.equiModel = data.information.modelType || ''
-				this.form.equiLocation = this.initDetailLocation(`${data.factoryName}/${data.workshopName}/${data.lineName}/${data.detailLocation}`)
+				this.form.equiLocation = this.initDetailLocation(
+					`${data.factoryName}/${data.workshopName}/${data.lineName}/${data.detailLocation}`)
 			},
 			// 设备位置
 			initDetailLocation(val) {
@@ -304,10 +405,10 @@
 						deptName: n.deptName
 					}
 				})
-				let repairsImg = param.repairsImg.map(n => {
-					return n.url
-				})
-				param.repairsImg = repairsImg.join(',')
+				// let repairsImg = param.repairsImg.map(n => {
+				// 	return n.url
+				// })
+				// param.repairsImg = repairsImg.join(',')
 				param.expectedTime = this.showTime
 				postJ(this.apiUrl + '/repair/info/saveOrEdit', param).then(res => {
 					if (res.success) {
@@ -324,50 +425,50 @@
 			},
 
 			// 选择图片
-			async handlImageSelect(e) {
-				let element = e.tempFiles[0]
-				let url = await this.uploadFiles(element.path)
-				console.log(url)
-				if (url) {
-					element.url = url
-					this.form.repairsImg.push(element)
-				}
-			},
+			// async handlImageSelect(e) {
+			// 	let element = e.tempFiles[0]
+			// 	let url = await this.uploadFiles(element.path)
+			// 	console.log(url)
+			// 	if (url) {
+			// 		element.url = url
+			// 		this.form.repairsImg.push(element)
+			// 	}
+			// },
 			// 图片删除
-			handlImagDeletee(e) {
-				let index = this.form.repairsImg.findIndex(n => {
-					return n.uuid == e.tempFile.uuid
-				})
-				if (index !== -1) {
-					this.form.repairsImg.splice(index, 1)
-				}
-			},
+			// handlImagDeletee(e) {
+			// 	let index = this.form.repairsImg.findIndex(n => {
+			// 		return n.uuid == e.tempFile.uuid
+			// 	})
+			// 	if (index !== -1) {
+			// 		this.form.repairsImg.splice(index, 1)
+			// 	}
+			// },
 			// 文件上传
-			uploadFiles(tempFilePaths) {
-				let that = this
-				return new Promise((resolve, reject) => {
-					uni.uploadFile({
-						url: this.apiUrl + '/data/doc/add', //后端用于处理图片并返回图片地址的接口
-						filePath: tempFilePaths,
-						name: 'file',
-						header: that.header,
-						formData: {
-							module: '申请报修'
-						},
-						success: res => {
-							let data = JSON.parse(res.data) //返回的是字符串,需要转成对象格式
-							resolve(data.data.accessUrl)
-						},
-						fail: err => {
-							reject(null)
-							uni.showToast({
-								title: '图片上传失败',
-								icon: 'none'
-							})
-						}
-					})
-				})
-			},
+			// uploadFiles(tempFilePaths) {
+			// 	let that = this
+			// 	return new Promise((resolve, reject) => {
+			// 		uni.uploadFile({
+			// 			url: this.apiUrl + '/data/doc/add', //后端用于处理图片并返回图片地址的接口
+			// 			filePath: tempFilePaths,
+			// 			name: 'file',
+			// 			header: that.header,
+			// 			formData: {
+			// 				module: '申请报修'
+			// 			},
+			// 			success: res => {
+			// 				let data = JSON.parse(res.data) //返回的是字符串,需要转成对象格式
+			// 				resolve(data.data.accessUrl)
+			// 			},
+			// 			fail: err => {
+			// 				reject(null)
+			// 				uni.showToast({
+			// 					title: '图片上传失败',
+			// 					icon: 'none'
+			// 				})
+			// 			}
+			// 		})
+			// 	})
+			// },
 			// 打开用户选择
 			handlselectUser() {
 				this.$refs.select_user.open()
@@ -399,10 +500,12 @@
 					'm+': this.getMinutes(),
 					's+': this.getSeconds()
 				}
-				if (/(y+)/.test(format)) format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
+				if (/(y+)/.test(format)) format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1
+					.length))
 				for (var i in args) {
 					var n = args[i]
-					if (new RegExp('(' + i + ')').test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ('00' + n).substr(('' + n).length))
+					if (new RegExp('(' + i + ')').test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 1 ?
+						n : ('00' + n).substr(('' + n).length))
 				}
 				return format
 			},
@@ -431,7 +534,8 @@
 								...res,
 								leaderUserId: ''
 							}
-							this.addForm.equiLocation = this.addForm.deviceLocationName + '-' + this.addForm.deviceDetailAddress
+							this.addForm.equiLocation = this.addForm.deviceLocationName + '-' + this
+								.addForm.deviceDetailAddress
 						})
 					}
 				})
@@ -488,6 +592,19 @@
 		font-size: 32rpx;
 	}
 
+	.photo_btn {
+		background-color: #157a2c;
+		width: 140rpx;
+		height: 60rpx;
+		line-height: 60rpx;
+		font-size: 24rpx;
+		color: #fff;
+		text-align: center;
+		border-radius: 8rpx;
+		margin-bottom: 12rpx;
+		display: inline-block;
+	}
+
 	.equiDetails {
 		.list {
 			border-bottom: none;
@@ -607,7 +724,7 @@
 			display: flex;
 			border: 1px solid #d7d7d7;
 
-			& + .item {
+			&+.item {
 				margin-top: 20rpx;
 			}
 
@@ -697,7 +814,7 @@
 				}
 			}
 
-			& + .jsr-item {
+			&+.jsr-item {
 				margin-left: 20rpx;
 			}
 		}
@@ -722,4 +839,4 @@
 	.border {
 		border: 1px solid #eee;
 	}
-</style>
+</style>

+ 15 - 2
pages/saleManage/businessOpportunity/index.vue

@@ -15,9 +15,16 @@
 			<image class="menu_icon" src="~@/static/pda/menu.svg"></image>
 
 		</view>
-		<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
+<!-- 		<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
 			<myCard @del="del(item)" :item="item" :index="index+1" :columns="columns" :btnList="btnList"></myCard>
 
+		</view> -->
+		<view class="wrapper">
+			<u-list @scrolltolower="scrolltolower" class="listContent">
+				<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
+					<myCard @del="del(item)" :item="item" :index="index+1" :columns="columns" :btnList="btnList"></myCard>
+				</view>
+			</u-list>
 		</view>
 		<view style='margin-top: 20vh;' v-if="tableList.length==0">
 			<u-empty iconSize='150' textSize='32' text='暂无数据'>
@@ -204,7 +211,13 @@
 					})
 					this.getList(this.where)
 				})
-			}
+			},
+			scrolltolower(){
+				if (this.isEnd) {
+					return
+				}
+				this.getList();
+			},
 		}
 	}
 </script>

+ 12 - 3
pages/saleManage/components/selectContact.vue

@@ -83,8 +83,8 @@
 				listData: [], //列表数据
 				classificationList: [], //分类数据
 				seletedAll: false, //全选状态,
-				isAll:''
-			
+				isAll:'',
+				isDemand:''
 			}
 		},
 		//选择的列表长度
@@ -96,8 +96,12 @@
 			},
 		
 		},
-		onLoad({ isAll }) {
+		onLoad({ isAll , type}) {
 			this.isAll = isAll //1多选 2单选
+			// *** 新增 需求进来的话 要增加查询条件
+			if(type == '需求'){
+				this.isDemand = '1'
+			}
 			this.getClassify()
 		},
 		onShow() {
@@ -130,6 +134,11 @@
 					name: this.searchVal,
 					categoryId: this.categoryLevelId
 				}
+				// 需求新增参数 *** 
+				if(this.isDemand == '1'){
+					params.type = '1'
+					params.status = '1'
+				}
 				contactPage(params).then(res => {
 					uni.hideLoading()
 					if (this.page == 1) {

+ 20 - 11
pages/saleManage/saleOrder/index.vue

@@ -2,24 +2,27 @@
 	<view class="mainBox">
 		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="订单" @clickLeft="back">
 		</uni-nav-bar>
-		
 		<view class="top-wrapper">
 			<uni-section>
 				<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="searchVal" placeholder="客户名称">
 				</uni-easyinput>
 			</uni-section>
-		
 			<button class="search_btn" @click="doSearch">搜索</button>
-		
 			<image class="menu_icon" src="~@/static/pda/menu.svg"></image>
-		
 		</view>
-		<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
+		<view class="wrapper">
+			<u-list @scrolltolower="scrolltolower" class="listContent">
+				<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
+					<myCard :item="item" :index="index+1" :btnList="btnList" :columns="columns" @del="del(item)">
+					</myCard>
+				</view>
+			</u-list>
+		</view>
+		<!-- 		<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
 			<myCard  :item="item" :index="index+1" :btnList="btnList" :columns="columns"
 				@del="del(item)"></myCard>
-
-		</view>
-<view style='margin-top: 20vh;' v-if="tableList.length==0">
+		</view> -->
+		<view style='margin-top: 20vh;' v-if="tableList.length==0">
 			<u-empty iconSize='150' textSize='32' text='暂无数据'>
 			</u-empty>
 		</view>
@@ -132,7 +135,7 @@
 				page: 1,
 				size: 10,
 				isEnd: false,
-				searchVal:''
+				searchVal: ''
 				//报价管理-审核枚举
 
 			}
@@ -164,7 +167,7 @@
 				let data = {
 					pageNum: this.page,
 					size: this.size,
-					partaName:this.searchVal
+					partaName: this.searchVal
 				}
 				getTableList(data).then(res => {
 					if (this.page === 1) {
@@ -194,7 +197,12 @@
 					url: '/pages/saleManage/saleOrder/add'
 				})
 			},
-
+			scrolltolower(){
+				if (this.isEnd) {
+					return
+				}
+				this.getList();
+			},
 		}
 	}
 </script>
@@ -212,6 +220,7 @@
 		align-items: center;
 		justify-content: center;
 	}
+
 	.top-wrapper {
 		background-color: #fff;
 		display: flex;

+ 323 - 0
pages/salesServiceManagement/demandList/add.vue

@@ -0,0 +1,323 @@
+<template>
+	<view class="">
+		<uni-nav-bar background-color="#157A2C" color="#fff" fixed="true" statusBar="true" left-icon="back" title="新增需求"
+			@clickLeft="back">
+		</uni-nav-bar>
+		<u-subsection :list="list" :current="current" @change="sectionChange"></u-subsection>
+		<u-cell-group v-show="current == 0">
+			<!-- 售后对象 -->
+			<u-cell title="需求编码" arrow-direction="down">
+				<view slot="value" style="display: flex;align-items: center;width: 100%;">
+					<u--input disabled style="flex:1" border="surround" v-model="form.code">
+					</u--input>
+				</view>
+			</u-cell>
+			<u-cell title="需求名称" arrow-direction="down">
+				<view slot="value" style="display: flex;align-items: center;width: 100%;">
+					<u--input style="flex:1" placeholder="请输入" border="surround" v-model="form.name">
+					</u--input>
+				</view>
+			</u-cell>
+			<u-cell title="客户名称" arrow-direction="down">
+				<view slot="value" style="display: flex;align-items: center;width: 100%;">
+					<u--input style="flex:1" placeholder="请选择" border="surround" @click.native="selectContactShow"
+						v-model="form.contactName">
+					</u--input>
+				</view>
+			</u-cell>
+			<u-cell title="发货单" arrow-direction="down">
+				<view slot="value" style="display: flex;align-items: center;width: 100%;">
+					<u--input style="flex:1" placeholder="请选择" border="surround" @click.native="invoiceDialogOpen"
+						v-model="form.orderCode">
+					</u--input>
+				</view>
+			</u-cell>
+			<u-cell title="报修地址" arrow-direction="down">
+				<view slot="value" style="display: flex;align-items: center;width: 100%;">
+					<u--input style="flex:1" placeholder="请输入" border="surround" v-model="form.contactAddress">
+					</u--input>
+				</view>
+			</u-cell>
+			<u-cell title="故障等级" arrow-direction="down">
+				<uni-data-picker v-model="form.faultLevel" slot="value" placeholder="请选择" :localdata="fault_level"
+					@change="sourceCodeOnchange">
+				</uni-data-picker>
+			</u-cell>
+			<u-cell title="期望解决时间" arrow-direction="down">
+				<uni-datetime-picker type="date" slot="value" v-model="form.expectedTime">
+				</uni-datetime-picker>
+			</u-cell>
+			<u-cell title="报修人" arrow-direction="down">
+				<view slot="value" style="display: flex;align-items: center;width: 100%;">
+					<u--input style="flex:1" placeholder="请输入" border="surround" v-model="form.repairName">
+					</u--input>
+				</view>
+			</u-cell>
+		</u-cell-group>
+		<AfterSales ref="salesRef" v-show="current == 1" :itemList="form.tableList" />
+		<!-- 联系人 -->
+		<ContactList ref="contactRef" v-show="current == 2" :itemList="form.contactInfoVOS" />
+		<view class="footerButton">
+			<u-button type="default" text="返回" @click="back"></u-button>
+			<u-button type="primary" @click="save" text="保存"></u-button>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import {
+		getByCode
+	} from '@/api/pda/common.js'
+	import {
+		contactDetail
+	} from '@/api/saleManage/contact/index.js'
+	import {
+		saveSalesDemand
+	} from '@/api/salesServiceManagement/demandList/index.js'
+	import AfterSales from './components/AfterSales.vue'
+	import ContactList from './components/contactList.vue'
+	export default {
+		components: {
+			AfterSales,
+			ContactList
+		},
+		data() {
+			return {
+				form: {
+					code: '',
+					name: '',
+					contactName: '',
+					repairName: '',
+					expectedTime: '',
+					faultLevel: '',
+					contactAddress: '',
+					orderCode: '',
+				},
+				list: ['基本信息', '售后对象', '联系人'],
+				current: 0,
+				fault_level: []
+			}
+		},
+		created() {
+			this.getByCode();
+			const userInfo = uni.getStorageSync('userInfo');
+			this.$set(this.form, 'repairName', userInfo.name);
+		},
+		onLoad(data) {
+			// 客户数据
+			uni.$off('setSelectList')
+			uni.$on('setSelectList', (data) => {
+				if (data && data.length > 0) {
+					let res = data[0]
+					console.log(res, 'res')
+					this.$set(this.form, 'contactId', res.id);
+					this.$set(this.form, 'contactName', res.name);
+					this.contactDetail(res.id);
+					// this.$forceUpdate();
+				}
+			})
+			// 售后对象数据
+			uni.$on('goosData', (data) => {
+				this.$set(this.form, 'orderCode', data.orderCode);
+				this.$set(this.form, 'orderId', data.orderId);
+				console.log(data, 'data');
+				let list = JSON.parse(JSON.stringify(data.tableList));
+				// 如果计量数量没有的话默认是 1
+				list.map(
+					(el) =>
+					(el.measureQuantity = el.measureQuantity ? el.measureQuantity : 1)
+				);
+				this.$set(this.form, 'tableList', list);
+			})
+		},
+		onUnload() {
+			uni.$off('setSelectList');
+			uni.$off('goosData');
+		},
+		mounted() {
+
+		},
+		methods: {
+			sectionChange(index) {
+				this.current = index;
+			},
+			selectContactShow() {
+				uni.navigateTo({
+					url: `/pages/saleManage/components/selectContact?isAll=2&type=需求`
+				})
+			},
+			//客户回调
+			async contactDetail(id, type) {
+				if (!id) {
+					this.contractInfo = {};
+					return;
+				}
+				let {
+					base,
+					other,
+					linkList
+				} = await contactDetail(id);
+				base.contactName = base.name;
+				let addressName = '';
+				if (other.addressName) {
+					addressName += other.addressName;
+				}
+				if (other.address) {
+					addressName += other.address;
+				}
+				// this.$set(this.form, 'contractInfo', base);
+				this.form.contactCode = base.code;
+				if (type != 'init') {
+					this.$set(this.form, 'contactAddress', addressName);
+					this.$set(
+						this.form,
+						'contactInfoVOS',
+						linkList.map((item) => {
+							item['contactName'] = item.linkName;
+							item['contactPhone'] = item.mobilePhone;
+							item['telephone'] = item.phone;
+							return item;
+						})
+					);
+					// 清空发货单的数据 *** 初次进来不清空
+					this.$set(this.form, 'orderCode', '');
+					this.$set(this.form, 'orderId', '');
+					this.$set(this.form, 'tableList', []);
+				}
+			},
+			sourceCodeOnchange(e) {
+				const value = e.detail.value;
+				this.form.faultLevel = value[0].value;
+				console.log(value, '赋值')
+				// this.form.sourceCode = value.map(item => item.value).toString()
+				// this.form.sourceName = value.map(item => item.text).toString()
+			},
+			invoiceDialogOpen() {
+				if (!this.form.contactId) {
+					this.$refs.uToast.show({
+						type: "warning",
+						message: "请先选择客户",
+					})
+					return;
+				}
+				uni.navigateTo({
+					url: '/pages/salesServiceManagement/demandList/components/Invoice?contactId=' + this.form
+						.contactId
+				})
+			},
+			async getByCode() {
+				const codeValue = await getByCode('fault_level');
+				let list = codeValue.map(item => {
+					const key = Object.keys(item)[0]
+					return {
+						value: key,
+						text: item[key]
+					}
+				})
+				this.fault_level = list;
+			},
+			save() {
+				let data = JSON.parse(JSON.stringify(this.form));
+				delete data.tableList;
+				delete data.code;
+				console.log(data, 'form ---')
+				try {
+					if (!data.name) {
+						this.$refs.uToast.show({
+							type: "warning",
+							message: "请输入需求名称",
+						})
+						return
+					}
+					if (!data.contactName) {
+						this.$refs.uToast.show({
+							type: "warning",
+							message: "请选择客户名称",
+						})
+						return
+					}
+					if (!data.orderCode) {
+						this.$refs.uToast.show({
+							type: "warning",
+							message: "请选择发货单",
+						})
+						return
+					}
+					if (!data.contactAddress) {
+						this.$refs.uToast.show({
+							type: "warning",
+							message: "请输入报修地址",
+						})
+						return
+					}
+					if (!data.faultLevel) {
+						this.$refs.uToast.show({
+							type: "warning",
+							message: "请选择故障等级",
+						})
+						return
+					}
+					// 联系人数据
+					let contactInfoVOS = this.$refs.contactRef.getTabData();
+					if (contactInfoVOS.length == 0) {
+						this.$refs.uToast.show({
+							type: "warning",
+							message: "至少需要存在一条联系人数据",
+						})
+						this.current = 2
+						return
+					}
+					data.contactInfoVOS = contactInfoVOS;
+					// 售后对象数据
+					let productDetail = this.$refs.salesRef.getTabData();
+					data.productDetail = productDetail;
+					uni.showLoading({
+						title: '加载中'
+					})
+					console.log(data, 'data');
+					saveSalesDemand(data).then((res) => {
+						uni.hideLoading()
+						this.back()
+					}).catch((e) => {
+						console.log(e,'报错了')
+						uni.hideLoading()
+					})
+				} catch (error) {
+					uni.hideLoading();
+					console.log(error, 'error');
+				}
+			}
+		},
+
+	}
+</script>
+
+<style lang="scss" scoped>
+	/deep/.u-subsection__item__text {
+		font-size: 28rpx !important;
+	}
+
+	/deep/.u-cell__body__content {
+		flex: none;
+		margin-right: 16rpx;
+	}
+
+	.footerButton {
+		width: 100%;
+		height: 84rpx;
+		display: flex;
+		position: fixed;
+		bottom: 0;
+		z-index: 10;
+
+		/deep/.u-button {
+			height: 100%;
+		}
+
+		>view {
+			flex: 1;
+
+		}
+	}
+</style>

+ 229 - 0
pages/salesServiceManagement/demandList/components/AfterSales.vue

@@ -0,0 +1,229 @@
+<template>
+	<view class="after_sales">
+		<view class="sales_info" v-if="tableList.length > 0">
+			<view>名称:{{ fieldRow('categoryName') }}</view>
+			<view>类型:{{ fieldRow('productCategoryName') }}</view>
+			<view>编码:{{ fieldRow('categoryCode') }}</view>
+			<view>发货条码:{{ fieldRow('barcodes') }}</view>
+			<view>发货时间:{{ fieldRow('shipmentDate') }}</view>
+			<view>质保有效期:{{ fieldRow('guaranteePeriodDeadline') }}</view>
+			<view>计量数量:{{ fieldRow('measureQuantity') }}</view>
+			<view class="action">
+				<text class="text">
+					操作:
+				</text>
+				<u-button @click="goProblem('add')" :plain="true" :hairline="true" size='mini' type="default"
+					text="添加故障"></u-button>
+				<u-button @click="del" :plain="true" :hairline="true" size='mini' type="default" class="delete"
+					text="删除"></u-button>
+			</view>
+		</view>
+		<view v-for="(item, index) in faultDetails" :key="index" style="position: relative;">
+			<myCard @edit="goProblem('edit',index,item)" @del="delProblem(index)" :item="item" :index="index+1"
+				:columns="columns" :btnList="btnList">
+			</myCard>
+		</view>
+	</view>
+
+</template>
+
+<script>
+	import myCard from '@/pages/saleManage/components/myCard.vue'
+	export default {
+		components: {
+			myCard
+		},
+		props: {
+			itemList: {
+				type: Array,
+				default: () => []
+			}
+		},
+		watch: {
+			itemList: {
+				handler(newVal) {
+					let list = JSON.parse(JSON.stringify(newVal));
+					list.map((el) => {
+						el.faultDetails = el.faultDetails ? el.faultDetails : []
+					})
+					this.tableList = list
+				},
+				deep: true,
+				immediate: true
+			}
+		},
+		computed: {
+			faultDetails() {
+				if (this.tableList.length > 0) {
+					return this.tableList[0].faultDetails
+				}
+				return []
+			},
+			fieldRow() {
+				return (field) => {
+					if (this.tableList.length == 0) return '';
+					return this.tableList[0][field]
+				}
+			}
+		},
+		data() {
+			return {
+				typeOptions: [{
+						text: '维修',
+						value: '1'
+					},
+					{
+						text: '保养',
+						value: '2'
+					},
+					{
+						text: '安装',
+						value: '3'
+					}
+				],
+				columns: [
+					[{
+						label: '故障类型:',
+						prop: 'type',
+						className: 'perce100',
+						formatter: (row) => {
+							const user = this.typeOptions.find(item => item.value === row.type);
+							return user.text
+						}
+					}],
+					[{
+						label: '故障现象:',
+						prop: 'faultPhenomenon',
+					}],
+					[{
+						label: '故障原因:',
+						prop: 'faultReason'
+					}],
+					[{
+						label: '维修过程:',
+						prop: 'maintenanceProcess',
+						className: 'perce100'
+					}],
+					[{
+						label: '操作:',
+						prop: 'action',
+						type: 'action',
+						className: 'perce100',
+					}],
+				],
+				btnList: [{
+						name: '编辑',
+						apiName: 'edit',
+						btnType: 'error',
+						type: '2',
+						pageUrl: '',
+					},
+					{
+						name: '删除',
+						apiName: 'del',
+						btnType: 'error',
+						type: '2',
+						pageUrl: '',
+
+					}
+				],
+				tableList: []
+			}
+		},
+		onLoad({}) {},
+		created() {
+			uni.$off('updateFaultList')
+			uni.$on('updateFaultList', ({
+				type,
+				data,
+				index
+			}) => {
+				if (type == 'add') {
+					this.tableList[0].faultDetails.push(data)
+				} else {
+					this.$set(this.tableList[0].faultDetails, index, data)
+				}
+				console.log(this.tableList, 'this.tableList ===')
+			})
+
+		},
+		methods: {
+			del() {
+				uni.showModal({
+					title: '确认删除',
+					content: '确定要删除这条售后对象吗?',
+					confirmText: '删除',
+					confirmColor: '#FF4D4F',
+					success: (res) => {
+						if (res.confirm) {
+							this.tableList = [];
+						} else if (res.cancel) {
+							// 用户点击了取消按钮
+							console.log('用户取消删除');
+						}
+					}
+				});
+			},
+			// 删除故障
+			delProblem(index) {
+				uni.showModal({
+					title: '确认删除',
+					content: '确定要删除这条故障吗?',
+					confirmText: '删除',
+					confirmColor: '#FF4D4F',
+					success: (res) => {
+						if (res.confirm) {
+							this.tableList[0].faultDetails.splice(index, 1);
+						} else if (res.cancel) {
+							// 用户点击了取消按钮
+							console.log('用户取消删除');
+						}
+					}
+				});
+			},
+			// 现在只针对做 一 对 多 的 故障数据
+			goProblem(type, index, obj) {
+				let data = obj ? JSON.stringify(obj) : '';
+				uni.navigateTo({
+					url: `/pages/salesServiceManagement/demandList/components/faultAdd?type=${type}&index=${index}&data=${data}`
+				})
+			},
+			addFault() {
+
+			},
+			getTabData() {
+				return this.tableList || []
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.sales_info {
+		padding: 8px 16px;
+		font-size: 13px;
+		font-style: normal;
+		font-weight: 400;
+		line-height: 22px;
+		word-wrap: break-word;
+		border-bottom: 6rpx solid #E1E1E1;
+
+		.action {
+			display: flex;
+			line-height: 22px;
+
+			.text {
+				margin-right: 12rpx;
+			}
+
+			/deep/ .u-button {
+				width: 100rpx;
+				font-size: 26rpx;
+				margin-left: 10rpx;
+				margin-right: 0rpx;
+				background: #157a2c;
+				color: #fff !important;
+			}
+		}
+	}
+</style>

+ 279 - 0
pages/salesServiceManagement/demandList/components/Invoice.vue

@@ -0,0 +1,279 @@
+<template>
+	<view class="mainBox">
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="发货单" @clickLeft="backAdd">
+			<!--右菜单-->
+		<!-- 	<template slot="right">
+				<u-button type="success" size="small" class="u-reset-button" @click="invoiceSelect"
+					text="选择发货单"></u-button>
+			</template> -->
+		</uni-nav-bar>
+		<!-- <u-subsection :list="list" :current="current" @change="sectionChange"></u-subsection> -->
+		<view class="top-wrapper">
+			<view class="nav_box rx-sc">
+				<view class="nav_item " :class="{active: current == 0}" @click="handNav(0)">
+					发货单</view>
+				<view class="nav_item" :class="{active: current == 1}" @click="handNav(1)">
+					物品明细</view>
+				<view class="menu_box" @click="handleSearch" v-show="current == 0">
+					<image class="menu_icon" src="~@/static/moreSearch.svg"></image>
+				</view>
+			</view>
+		</view>
+		<view class="wrapper">
+			<u-list v-show="current == 0" @scrolltolower="scrolltolower" class="listContent">
+				<checkbox-group v-for="(item, index) in dataList" :key="index" @change="e => selectVal(e, item, index)">
+					<label>
+						<view class="listBox">
+							<view class="listBox-sel">
+								<checkbox :value="item.id" color="#fff" :disabled="item.disabled"
+									:checked="item.checked" />
+							</view>
+							<view class="listBox-con">
+								<view class="listBox-top">
+									<view class="listBox-name">
+										{{ item.contactName }}
+									</view>
+
+								</view>
+								<view class="listBox-bottom">
+									<view>发货单编码:{{ item.docNo }}</view>
+									<view>销售订单编码:{{ item.orderNo }}</view>
+									<view class="half">是否回执:{{ item.replied == 1?'是':'否' }}</view>
+									<view class="half">状态:{{ orderStatus(item) }}</view>
+									<view>创建时间:{{ item.createTime }}</view>
+								</view>
+							</view>
+						</view>
+					</label>
+				</checkbox-group>
+				<u-empty class="noDate" style="margin-top: 20vh" v-if="!dataList.length"></u-empty>
+			</u-list>
+			<itemSelect @getDetails="getDetails" ref="itemRef" v-show="current == 1" />
+		</view>
+		<view class="footer">
+			<u-button type="success" size="small" class="u-reset-button" @click="jumpAdd">
+				<view class="selBtn">选择( {{ checkListLen }} )</view>
+			</u-button>
+		</view>
+		<screen ref="screen" @succeed="cabScreen"></screen>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import {
+		parameterGetByCode
+	} from '@/api/mainData/index.js';
+	import screen from './screen.vue'
+	import itemSelect from './itemSelect.vue'
+	import {
+		reviewStatusEnum
+	} from '@/enum/dict';
+	import {
+		saleordersendrecord
+	} from '@/api/saleManage/saleorder/index.js'
+	let [isEnd] = [false]
+	export default {
+		components: {
+			screen,
+			itemSelect
+		},
+		computed: {
+			orderStatus() {
+				return (row) => {
+					return reviewStatusEnum[row.reviewStatus].label;
+				};
+			},
+			checkListLen() {
+				return this.detailsData.id ? 1 : 0
+			},
+		},
+		data() {
+			return {
+				contactId: '',
+				current: 0,
+				page: 1,
+				size: 10,
+				dataList: [],
+				detailsData: {},
+			}
+		},
+		onLoad({
+			contactId
+		}) {
+			this.contactId = contactId;
+			this.getList();
+			// this.getClassify()
+		},
+		methods: {
+			//返回添加页
+			backAdd() {
+				uni.navigateBack()
+			},
+			invoiceSelect() {
+
+			},
+			handNav(index) {
+				this.current = index;
+			},
+			handleSearch() {
+				console.log(this.$refs.screen, 'ref');
+				this.$refs.screen.open();
+			},
+			cabScreen(params) {
+				console.log(params, 'params -')
+				this.page = 1;
+				this.getList(params);
+			},
+			async getList(data = {}) {
+				let params = {
+					pageNum: this.page,
+					reviewStatus: 2,
+					...data,
+					contactId: this.contactId
+				}
+				isEnd = false
+				const res = await saleordersendrecord(params)
+				if (params.pageNum === 1) {
+					this.dataList = []
+				}
+				this.dataList.push(...res.list)
+				isEnd = this.dataList.length >= res.count
+
+			},
+			//勾选
+			selectVal(e, val, index) {
+				this.$set(this.dataList[index], 'checked', !this.dataList[index].checked)
+				this.dataList.forEach((item, i) => {
+					if (item.id != val.id) {
+						this.$set(this.dataList[i], 'checked', false)
+					}
+				})
+
+				// 勾选完 查询物品明细
+				if (val.checked) {
+					this.$refs.itemRef.getData(this.dataList[index]);
+				} else {
+					this.$refs.itemRef.resetTable();
+				}
+				this.detailsData = {};
+			},
+			// 选择
+			jumpAdd() {
+				if (!this.detailsData.id) {
+					this.$refs.uToast.show({
+						type: "warning",
+						message: "请选择一条物品明细数据",
+					})
+					return;
+				}
+			  let obj =	this.dataList.filter(item => item.checked)[0];
+				let data = {
+					orderCode: obj.docNo,
+					orderId: obj.id,
+					tableList: [this.detailsData]
+				}
+				uni.$emit('goosData',data);
+				uni.navigateBack();
+			},
+
+			getDetails(data) {
+				this.detailsData = data;
+			},
+
+			scrolltolower() {
+				if (isEnd) return
+				this.page++
+				this.getList()
+			},
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import './invoice.scss';
+
+	/deep/.u-subsection__item__text {
+		font-size: 28rpx !important;
+	}
+
+	.u-reset-button {
+		position: absolute;
+		right: 10rpx;
+		top: 20rpx;
+		width: 160rpx;
+	}
+
+	.mainBox {
+		height: 100vh;
+		display: flex;
+		flex-direction: column;
+
+		.wrapper {
+			// flex: 1;
+			height: calc(100vh - 250rpx);
+			overflow: hidden;
+		}
+
+		//底部按钮
+		.footer {
+			height: 45px;
+			position: relative;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			bottom: 0;
+			width: 100%;
+			height: 50px;
+			border-top: 1px solid #eeecec;
+			background-color: #ffffff;
+			z-index: 999;
+
+			.bottom {
+				margin-left: 10rpx;
+			}
+
+			.u-reset-button {
+				position: absolute;
+				right: 10rpx;
+				top: 20rpx;
+				width: 150rpx;
+			}
+		}
+
+		.nav_box {
+			padding: 6rpx 32rpx;
+			position: relative;
+
+			.nav_item {
+				font-size: 28rpx;
+				font-weight: 400;
+				color: $theme-color;
+				background: #F0F8F2;
+				margin-right: 16rpx;
+				padding: 4rpx 16rpx;
+				border-radius: 8rpx;
+				border: 2rpx solid #ACD4B5;
+
+			}
+
+			.menu_box {
+				position: absolute;
+				right: 20rpx;
+				top: 10rpx;
+
+				.menu_icon {
+					width: 44rpx;
+					height: 44rpx;
+				}
+
+			}
+
+			.active {
+				background: $theme-color;
+				border: 2rpx solid $theme-color;
+				color: #FFF;
+			}
+		}
+	}
+</style>

+ 122 - 0
pages/salesServiceManagement/demandList/components/contactAdd.vue

@@ -0,0 +1,122 @@
+<template>
+	<view class="mainBox">
+		<uni-nav-bar background-color="#157A2C" color="#fff" fixed="true" statusBar="true" left-icon="back" title="联系人信息"
+			@clickLeft="back">
+		</uni-nav-bar>
+		<u-cell-group>
+			<u-cell title="姓名" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.contactName"></u--input>
+			</u-cell>
+			<u-cell title="手机" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.contactPhone"></u--input>
+			</u-cell>
+			<u-cell title="电话" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.telephone"></u--input>
+			</u-cell>
+			<u-cell title="微信号" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.wechat"></u--input>
+			</u-cell>
+			<u-cell title="邮箱" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.email"></u--input>
+			</u-cell>
+			<u-cell title="部门" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.deptName"></u--input>
+			</u-cell>
+			<u-cell title="职务" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.post"></u--input>
+			</u-cell>
+			<u-cell title="备注" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.remark"></u--input>
+			</u-cell>
+			<view class="footerButton">
+				<u-button type="default" text="返回" @click="back"></u-button>
+				<u-button type="primary" @click="save" text="保存"></u-button>
+			</view>
+		</u-cell-group>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		data() {
+			return {
+				form: {
+					contactName: '',
+					contactPhone: '',
+					telephone: '',
+					wechat: '',
+					email: '',
+					deptName: '',
+					post: '',
+					remark: '',
+				},
+				type: '',
+				infoIdx:'',
+			}
+		},
+
+		async onLoad(data) {
+			this.infoIdx = data.index;
+			this.type = data.type
+			if (data.data) {
+				this.form = JSON.parse(data.data)
+			}
+		},
+		methods: {
+			save() {
+				if (!this.form.contactName) {
+					this.$refs.uToast.show({
+						type: "warning",
+						message: "姓名不能为空",
+					})
+					return
+				}
+				uni.$emit('updateContactList', {
+				data: this.form,
+				type: this.type,
+				index:this.infoIdx
+				})
+				this.back()
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	/deep/.u-cell__body__content {
+		flex: none;
+		margin-right: 16rpx;
+	}
+
+	.mainBox {
+		padding-bottom: 84rpx;
+	}
+
+	.footerButton {
+		width: 100%;
+		height: 84rpx;
+		display: flex;
+		position: fixed;
+		bottom: 0;
+
+		/deep/.u-button {
+			height: 100%;
+		}
+
+		>view {
+			flex: 1;
+
+		}
+	}
+
+	// /deep/.u-button {
+	// 	height: 100%;
+	// }
+
+	/deep/.u-subsection__item__text {
+		font-size: 28rpx !important;
+	}
+</style>

+ 196 - 0
pages/salesServiceManagement/demandList/components/contactList.vue

@@ -0,0 +1,196 @@
+<template>
+	<view class="after_sales">
+		<view class="bth_oper">
+			<view class="btn add" @click="goContact('add')">添加</view>
+			<view class="btn del" @click="batchDelete">删除</view>
+			<text class="reserve">请至少保留一条联系人数据</text>
+		</view>
+		<u-list class="listContent">
+			<checkbox-group v-for="(item, index) in contactList" :key="index" @change="e => selectVal(e, item, index)">
+				<label>
+					<view class="listBox">
+						<view class="listBox-sel">
+							<checkbox :value="item.id" color="#fff" :disabled="item.disabled" :checked="item.checked" />
+						</view>
+						<view class="listBox-con">
+							<view class="listBox-bottom">
+								<view>姓名:{{ item.contactName }}</view>
+								<view>手机:{{ item.contactPhone }}</view>
+								<view>电话:{{ item.telephone }}</view>
+								<view>微信号:{{ item.wechat }}</view>
+								<view>邮箱:{{ item.email }}</view>
+								<view>部门:{{ item.deptName }}</view>
+								<view>职务:{{ item.post }}</view>
+								<view>备注:{{ item.remark }}</view>
+								<view class="action">
+									<text class="text">
+										操作:
+									</text>
+									<u-button @click="goContact('edit',index,item)" :plain="true" :hairline="true"
+										size='mini' type="default" text="编辑"></u-button>
+									<u-button @click="del" :plain="true" :hairline="true" size='mini' type="default"
+										class="delete" text="删除"></u-button>
+								</view>
+							</view>
+						</view>
+					</view>
+				</label>
+			</checkbox-group>
+			<u-empty class="noDate" style="margin-top: 20vh" v-if="!contactList.length"></u-empty>
+		</u-list>
+	</view>
+
+</template>
+
+<script>
+	import myCard from '@/pages/saleManage/components/myCard.vue'
+	export default {
+		components: {
+			myCard
+		},
+		props: {
+			itemList: {
+				type: Array,
+				default: () => []
+			}
+		},
+		watch: {
+			itemList: {
+				handler(newVal) {
+					let list = JSON.parse(JSON.stringify(newVal));
+					this.contactList = list
+				},
+				deep: true,
+				immediate: true
+			}
+		},
+		computed: {},
+		data() {
+			return {
+				contactList: []
+			}
+		},
+		onLoad({}) {},
+		created() {
+			uni.$off('updateContactList')
+			uni.$on('updateContactList', ({
+				type,
+				data,
+				index
+			}) => {
+				console.log(data, 'data');
+				if (type == 'add') {
+					this.contactList.push(data);
+				} else {
+					this.$set(this.contactList, index, data);
+				}
+
+			})
+
+		},
+		methods: {
+			// 勾选数据
+			selectVal(e, val, index) {
+				this.$set(this.contactList[index], 'checked', !this.contactList[index].checked)
+			},
+			// 删除联系人
+			del(index) {
+				uni.showModal({
+					title: '确认删除',
+					content: '确定要删除这条联系人数据吗?',
+					confirmText: '删除',
+					confirmColor: '#FF4D4F',
+					success: (res) => {
+						if (res.confirm) {
+							this.contactList.splice(index, 1);
+						} else if (res.cancel) {
+							// 用户点击了取消按钮
+							console.log('用户取消删除');
+						}
+					}
+				});
+			},
+			// 批量删除
+			batchDelete() {
+				uni.showModal({
+					title: '确认删除',
+					content: '确定要删除所选联系人数据吗?',
+					confirmText: '删除',
+					confirmColor: '#FF4D4F',
+					success: (res) => {
+						if (res.confirm) {
+							this.contactList = this.contactList.filter(item=> !item.checked);
+						} else if (res.cancel) {
+							// 用户点击了取消按钮
+							console.log('用户取消删除');
+						}
+					}
+				});
+			},
+			// 现在只针对做 一 对 多 的 故障数据
+			goContact(type, index, obj) {
+				let data = obj ? JSON.stringify(obj) : '';
+				uni.navigateTo({
+					url: `/pages/salesServiceManagement/demandList/components/contactAdd?type=${type}&index=${index}&data=${data}`
+				})
+			},
+			addFault() {
+
+			},
+			getTabData() {
+				return this.contactList || []
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import './invoice.scss';
+
+	.bth_oper {
+		display: flex;
+		align-items: center;
+		margin-top: 16rpx;
+		border-bottom: 1px solid #e5e5e5;
+		padding-bottom: 16rpx;
+
+		.btn {
+			width: 80rpx;
+			height: 48rpx;
+			line-height: 48rpx;
+			text-align: center;
+			background: #1890ff;
+			font-size: 26rpx;
+			color: #ffffff;
+			border-radius: 8rpx;
+		}
+
+		.del {
+			background: #ff4d4f;
+		}
+
+		.reserve {
+			color: #e6a23c;
+			font-size: 26rpx;
+			margin-left: 18rpx;
+		}
+	}
+
+	.action {
+		display: flex;
+		line-height: 22px;
+
+		.text {
+			margin-right: 12rpx;
+		}
+
+		/deep/ .u-button {
+			width: 100rpx;
+			font-size: 26rpx;
+			margin-left: 10rpx;
+			margin-right: 0rpx;
+			background: #157a2c;
+			color: #fff !important;
+		}
+	}
+</style>

+ 8 - 0
pages/salesServiceManagement/demandList/components/demandInfor.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 133 - 0
pages/salesServiceManagement/demandList/components/faultAdd.vue

@@ -0,0 +1,133 @@
+<template>
+	<view class="mainBox">
+		<uni-nav-bar background-color="#157A2C" color="#fff" fixed="true" statusBar="true" left-icon="back" title="故障信息"
+			@clickLeft="back">
+		</uni-nav-bar>
+		<u-cell-group>
+
+			<u-cell title="故障类型" arrow-direction="down">
+				<uni-data-picker v-model="form.type" slot="value" placeholder="请选择" :localdata="typeOptions"
+					@change="sourceCodeOnchange">
+				</uni-data-picker>
+			</u-cell>
+			<u-cell title="故障现象" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.faultPhenomenon"></u--input>
+			</u-cell>
+			<u-cell title="故障原因" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.faultReason"></u--input>
+			</u-cell>
+			<u-cell title="维修过程" arrow-direction="down">
+				<u--input slot="value" placeholder="请输入" border="surround" v-model="form.maintenanceProcess"></u--input>
+			</u-cell>
+
+			<view class="footerButton">
+				<u-button type="default" text="返回" @click="back"></u-button>
+				<u-button type="primary" @click="save" text="保存"></u-button>
+			</view>
+		</u-cell-group>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		data() {
+			return {
+				form: {
+					type: '',
+					faultPhenomenon: '',
+					faultReason: '',
+					maintenanceProcess: '',
+				},
+				type: '',
+				infoIdx:'',
+				typeOptions: [{
+						text: '维修',
+						value: '1'
+					},
+					{
+						text: '保养',
+						value: '2'
+					},
+					{
+						text: '安装',
+						value: '3'
+					}
+				],
+			}
+		},
+
+		async onLoad(data) {
+			this.infoIdx = data.index;
+			this.type = data.type
+			if (data.data) {
+				this.form = JSON.parse(data.data)
+			}
+		},
+		methods: {
+			save() {
+				if (!this.form.type) {
+					this.$refs.uToast.show({
+						type: "warning",
+						message: "故障类型不能为空",
+					})
+					return
+				}
+				if (!this.form.faultPhenomenon) {
+					this.$refs.uToast.show({
+						type: "warning",
+						message: "故障现象不能为空",
+					})
+					return
+				}
+				uni.$emit('updateFaultList', {
+				data: this.form,
+				type: this.type,
+				index:this.infoIdx
+				})
+				this.back()
+			},
+			sourceCodeOnchange(e){
+				console.log(e);
+			}
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	/deep/.u-cell__body__content {
+		flex: none;
+		margin-right: 16rpx;
+	}
+
+	.mainBox {
+		padding-bottom: 84rpx;
+	}
+
+	.footerButton {
+		width: 100%;
+		height: 84rpx;
+		display: flex;
+		position: fixed;
+		bottom: 0;
+
+		/deep/.u-button {
+			height: 100%;
+		}
+
+		>view {
+			flex: 1;
+
+		}
+	}
+
+	// /deep/.u-button {
+	// 	height: 100%;
+	// }
+
+	/deep/.u-subsection__item__text {
+		font-size: 28rpx !important;
+	}
+</style>

+ 67 - 0
pages/salesServiceManagement/demandList/components/invoice.scss

@@ -0,0 +1,67 @@
+	.listContent {
+		height: 100% !important;
+
+		.listBox {
+			display: flex;
+			// height: 180rpx;
+			padding: 20rpx 0;
+			border-bottom: 2rpx solid #e5e5e5;
+
+			.listBox-sel {
+				height: 90rpx;
+				width: 80rpx;
+				// line-height: 90rpx;
+				text-align: center;
+
+				checkbox {
+					transform: scale(1.2);
+				}
+			}
+
+			.listBox-con {
+				width: 100%;
+				// display: flex;
+				// flex-wrap: wrap;
+				// justify-content: space-between;
+				align-items: center;
+				padding: 0 18rpx 0 0;
+
+				.listBox-top {
+					width: 100%;
+					display: flex;
+					justify-content: space-between;
+					padding-bottom: 10rpx;
+
+					.listBox-name,
+					.listBox-code {
+						display: inline-block;
+						font-size: $uni-font-size-sm;
+						font-weight: bold;
+					}
+				}
+
+				.listBox-bottom {
+					width: 100%;
+					display: flex;
+					justify-content: space-between;
+					font-size: $uni-font-size-sm;
+					flex-wrap: wrap;
+
+					>view {
+						width: 100%;
+						overflow: hidden;
+						white-space: nowrap;
+						text-overflow: ellipsis;
+					}
+
+					.half {
+						width: 50%;
+					}
+				}
+			}
+		}
+
+		.noDate {
+			height: 100%;
+		}
+	}

+ 165 - 0
pages/salesServiceManagement/demandList/components/itemSelect.vue

@@ -0,0 +1,165 @@
+<template>
+	<u-list class="listContent">
+		<checkbox-group v-for="(item, index) in listData" :key="index" @change="e => selectVal(e, item, index)">
+			<label>
+				<view class="listBox">
+					<view class="listBox-sel">
+						<checkbox :value="item.id" color="#fff" :disabled="item.disabled" :checked="item.checked" />
+					</view>
+					<view class="listBox-con">
+						<view class="listBox-top">
+							<view class="listBox-name">
+								{{ item.categoryName }}
+							</view>
+
+						</view>
+						<view class="listBox-bottom">
+							<view>类型:{{ item.productCategoryName }}</view>
+							<view>编码:{{ item.categoryCode }}</view>
+							<view>牌号:{{ item.productBrand }}</view>
+							<view>型号:{{ item.categoryModel }}</view>
+							<view>规格:{{ item.packingSpecification }}</view>
+							<view>批次号:{{ item.batchNo }}</view>
+							<view>计量数量:{{ item.measureQuantity }}</view>
+							<view>单价(元):{{ item.singlePrice }}</view>
+							<view>发货条码/车架号:{{ item.barcodes }}</view>
+						</view>
+					</view>
+				</view>
+			</label>
+		</checkbox-group>
+		<u-empty class="noDate" style="margin-top: 20vh" v-if="!listData.length"></u-empty>
+	</u-list>
+</template>
+
+<script>
+	import {
+		saleordersendrecord
+	} from '@/api/saleManage/saleorder/index.js'
+	import {
+		parameterGetByCode
+	} from '@/api/mainData/index.js';
+	import {
+		getInfoBySourceBizNoAll
+	} from "@/api/wms/index.js"
+	import {
+		getSendSaleOrderrecordDetailSplit
+	} from "@/api/salesServiceManagement/demandList/index.js"
+	const dayjs = require('dayjs');
+	export default {
+		data() {
+			return {
+				listData: [],
+			}
+		},
+		onLoad({}) {},
+		methods: {
+			async getData(row) {
+				this.listData = [];
+				let params = {
+					code: 'after_sales_product_list_source'
+				};
+				const res = await parameterGetByCode(params);
+				if (res.value == '1') {
+					this.getInfo(row);
+				} else {
+					this._getInfo(row.docNo);
+				}
+			},
+			resetTable(){
+				this.listData = [];
+			},
+			async _getInfo(sourceBizNo) {
+				const dataArray = await getInfoBySourceBizNoAll(sourceBizNo);
+				let res = {};
+				if (dataArray && dataArray.length > 0) {
+					res = JSON.parse(JSON.stringify(dataArray[0]));
+					res['outInDetailList'] = [];
+					dataArray.forEach((item) => {
+						item.outInDetailList.forEach((val) => {
+							res['outInDetailList'].push(val);
+						});
+					});
+				}
+				this.init(res);
+			},
+			init(res) {
+				let productList = res?.outInDetailList?.map(
+					(productItem, productIndex) => {
+						return {
+							...productItem,
+							outInDetailRecordRequestList: productItem.outInDetailRecordRequestList.map((
+							packingItem) => {
+								return {
+									...packingItem,
+									categoryName: productItem.categoryName,
+									categoryCode: productItem.categoryCode,
+									categoryModel: productItem.categoryModel,
+									produceTime: packingItem.produceTime || null,
+									shipmentDate: res.createTime || null,
+									guaranteePeriodDeadline: this.getTime(res.createTime)[0],
+									warrantyStatus: this.getTime(res.createTime)[1]
+								};
+							})
+						};
+					}
+				);
+				// 获取包装维度数据
+				const arr = [];
+				for (const key in productList) {
+					for (const k in productList[key].outInDetailRecordRequestList) {
+						arr.push({
+							...productList[key].outInDetailRecordRequestList[k]
+						});
+					}
+				}
+				this.listData = arr;
+			},
+			async getInfo(row) {
+				const res = await getSendSaleOrderrecordDetailSplit(row.id);
+				let list = res.productList.map((el) => {
+					el.categoryCode = el.productCode;
+					el.categoryName = el.productName;
+					el.categoryModel = el.modelType;
+					el.measureQuantity = el.totalCount;
+					el.barcodes = el.carCode;
+					el.packingSpecification = el.specification;
+					el.shipmentDate = row.createTime || null;
+					(el.guaranteePeriodDeadline = this.getTime(row.createTime)[0]),
+					(el.warrantyStatus = this.getTime(row.createTime)[1]);
+					return el;
+				});
+				this.listData = list;
+			},
+			async selectVal(e, val, index) {
+				this.$set(this.listData[index], 'checked', !this.listData[index].checked)
+				this.listData.forEach((item, i) => {
+					if (item.id != val.id) {
+						this.$set(this.listData[i], 'checked', false)
+					}
+				})
+				let data = val.checked ? val : {};
+				this.$emit('getDetails', data);
+			},
+			getTime(createTime) {
+				let date = new Date(createTime);
+				date.setMonth(date.getMonth() + 13); // 月份加13月
+				let time = dayjs(date).format('YYYY-MM-DD HH:mm:ss');
+				let warrantyStatus =
+					new Date(time).getTime() > new Date().getTime() ? 0 : 1;
+				return [time, warrantyStatus];
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import './invoice.scss';
+
+	.u-reset-button {
+		position: absolute;
+		right: 10rpx;
+		top: 20rpx;
+		width: 160rpx;
+	}
+</style>

+ 94 - 0
pages/salesServiceManagement/demandList/components/screen.vue

@@ -0,0 +1,94 @@
+<template>
+	<view>
+		<u-popup :show="show" closeOnClickOverlay mode="top" @close="closePopup">
+			<view class="search_list">
+				<u-form labelPosition="left" :model="form" labelWidth="180" labelAlign="left" class="baseForm">
+					<u-form-item label="发货单编码:" class="item-form" borderBottom prop="assetType">
+						<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.docNo" placeholder="请输入">
+						</uni-easyinput>
+					</u-form-item>
+					<u-form-item label="销售订单编码:" class="item-form" borderBottom prop="assetType">
+						<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.orderNo"
+							placeholder="请输入">
+						</uni-easyinput>
+					</u-form-item>
+					<u-form-item label="客户名称:" class="item-form" borderBottom prop="assetType">
+						<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.contactName"
+							placeholder="请输入">
+						</uni-easyinput>
+					</u-form-item>
+					<!-- 					<u-form-item label="发货单编码:" class="item-form" borderBottom prop="assetType">
+						<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.keyWord"
+							placeholder="请输入">
+						</uni-easyinput>
+					</u-form-item> -->
+				</u-form>
+			</view>
+			<view class="operate_box rx-bc">
+				<u-button size="small" class="u-reset-button" @click="reset">
+					重置
+				</u-button>
+				<u-button type="success" size="small" class="u-reset-button" @click="submit">
+					确定
+				</u-button>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		props: [],
+		data() {
+			return {
+				form: {
+					docNo: "",
+					orderNo: "",
+					contactName: ""
+				},
+				show: false,
+			}
+		},
+		methods: {
+			open() {
+				this.show = true;
+			},
+			closePopup() {
+
+			},
+			reset() {
+				this.form = {
+					docNo: "",
+					orderNo: "",
+					contactName: ""
+				}
+				this.submit();
+			},
+			submit() {
+				this.$emit('succeed',this.form);
+				this.show = false;
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.search_list {
+		padding: 0 20rpx;
+	}
+	
+	.operate_box {
+		padding: 10rpx 32rpx;
+	
+		/deep/ .u-button {
+			width: 40%;
+		}
+	}
+	
+	.item-form{
+		/deep/ .u-form-item__body__left__content__label{
+			font-size: 28rpx;
+		}
+	}
+</style>

+ 294 - 0
pages/salesServiceManagement/demandList/index.vue

@@ -0,0 +1,294 @@
+<template>
+	<view class="mainBox">
+		<uni-nav-bar background-color="#157A2C" color="#fff" fixed="true" statusBar="true" left-icon="back" title="售后需求"
+			@clickLeft="back">
+		</uni-nav-bar>
+		<view class="top-wrapper">
+			<uni-section>
+				<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="searchVal" placeholder="名称">
+				</uni-easyinput>
+			</uni-section>
+			<button class="search_btn" @click="doSearch">搜索</button>
+			<image class="menu_icon" src="~@/static/pda/menu.svg"></image>
+		</view>
+		<view class="wrapper">
+			<u-list @scrolltolower="scrolltolower" class="listContent">
+				<view v-for="(item, index) in tableList" :key="index" style="position: relative;">
+					<myCard @del="del(item)" @edit="add('edit')" @details="add('view')" :item="item" :index="index+1" :columns="columns" :btnList="btnList">
+					</myCard>
+				</view>
+			</u-list>
+		</view>
+		<view style='margin-top: 20vh;' v-if="tableList.length==0">
+			<u-empty iconSize='150' textSize='32' text='暂无数据'>
+			</u-empty>
+		</view>
+		<view class="add" @click="add('add')">
+			<u-icon name="plus" color="#fff"></u-icon>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+
+	</view>
+</template>
+
+<script>
+	import {
+		deleteInformation
+	} from '@/api/saleManage/businessOpportunity/index.js'
+	import {
+		getTableList,
+	} from '@/api/salesServiceManagement/demandList/index.js'
+	import myCard from '@/pages/saleManage/components/myCard.vue'
+	export default {
+		components: {
+			myCard,
+		},
+
+		data() {
+			return {
+				tableList: [],
+				searchVal: '',
+				page: 1,
+				size: 10,
+				isEnd: false,
+				current: {},
+				btnList: [{
+						name: '详情',
+						apiName: 'details',
+						btnType: 'primary',
+						type: '1',
+						pageUrl: '/pages/saleManage/businessOpportunity/components/drawer',
+
+					}, {
+						name: '修改',
+						apiName: '',
+						btnType: 'primary',
+						type: '1',
+						pageUrl: '/pages/saleManage/businessOpportunity/add',
+						judge: [{
+							authorities: '',
+						}, {
+							key: 'demandStatus',
+							value: [0, 2, 3, 4, 5],
+
+						}],
+					},
+					{
+						name: '删除',
+						apiName: 'del',
+						btnType: 'error ',
+						type: '2',
+						pageUrl: '',
+						judge: [{
+							authorities: '',
+						}, {
+							key: 'demandStatus',
+							value: [0, 2, 3, 4, 5],
+						}],
+					}, {
+						name: '提交',
+						apiName: '',
+						btnType: 'primary',
+						type: '1',
+						pageUrl: '',
+						judge: [{
+							authorities: '',
+						}, {
+							key: 'demandStatus',
+							value: [0],
+						}],
+					},
+					{
+						name: '撤回',
+						apiName: '',
+						btnType: 'primary',
+						type: '1',
+						pageUrl: '',
+						judge: [{
+							authorities: '',
+						}, {
+							key: 'demandStatus',
+							value: [0],
+						}],
+					}
+				],
+				columns: [
+					[{
+						label: '名称:',
+						prop: 'name',
+						type: 'title',
+						className: 'perce100',
+					}],
+					[{
+						label: '编码:',
+						prop: 'code'
+					}, {
+						label: '客户编码:',
+						prop: 'contactCode'
+					}],
+					[{
+						label: '客户名称:',
+						prop: 'contactName'
+					}, {
+						label: '故障等级:',
+						prop: 'faultLevel'
+					}],
+					[{
+						label: '创建人:',
+						prop: 'createUserName'
+					}, {
+						label: '创建时间:',
+						prop: 'createTime',
+					}],
+					[{
+						label: '审核人:',
+						prop: 'approvalUserName'
+					}, {
+						label: '状态:',
+						prop: 'demandStatus',
+						formatter: (row) => {
+							let cellValue = row.demandStatus;
+							return cellValue == 0 ?
+								'待审核' :
+								cellValue == 2 ?
+								'已拒绝' :
+								cellValue == 1 ?
+								'已通过' :
+								cellValue == 3 ?
+								'已撤回' :
+								'';
+						}
+					}],
+					[{
+						label: '操作:',
+						prop: 'action',
+						type: 'action',
+						className: 'perce100',
+					}],
+
+				]
+			}
+		},
+		computed: {
+
+		},
+
+		onShow() {
+			this.isEnd = false
+			this.page = 1
+			this.getList()
+		},
+
+		methods: {
+			doSearch() {
+				this.isEnd = false
+				this.page = 1
+				this.getList()
+			},
+			//获取列表信息
+			getList() {
+				if (this.isEnd) {
+					return
+				}
+				uni.showLoading({
+					title: '加载中'
+				})
+
+				let data = {
+					pageNum: this.page,
+					size: this.size,
+					type: 1,
+					name: this.searchVal
+
+				}
+				getTableList(data).then(res => {
+					if (this.page === 1) {
+						this.tableList = res.list
+					} else {
+						this.tableList.push(...res.list)
+					}
+					this.page += 1
+					this.isEnd = this.tableList.length >= res.count
+					uni.hideLoading();
+				}).catch((e) => {
+					uni.hideLoading()
+				})
+			},
+			add(type) {
+				uni.navigateTo({
+					url: `/pages/salesServiceManagement/demandList/add?type=${type}`
+				})
+			},
+			scrolltolower() {
+				if (this.isEnd) {
+					return
+				}
+				this.getList();
+			},
+			del(item) {
+				deleteInformation([item.id]).then(res => {
+					this.isEnd = false
+					this.page = 1
+					this.$refs.uToast.show({
+						type: "success",
+						message: "操作成功",
+					})
+					this.getList(this.where)
+				})
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.add {
+		width: 96rpx;
+		height: 96rpx;
+		border-radius: 48rpx;
+		background: #3c9cff;
+		position: fixed;
+		bottom: 100rpx;
+		right: 24rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.top-wrapper {
+		background-color: #fff;
+		display: flex;
+		width: 750rpx;
+		height: 88rpx;
+		padding: 16rpx 32rpx;
+		align-items: center;
+		gap: 16rpx;
+
+		/deep/.uni-section {
+			margin-top: 0px;
+		}
+
+		/deep/.uni-section-header {
+			padding: 0px;
+
+		}
+
+		.search_btn {
+			width: 120rpx;
+			height: 70rpx;
+			line-height: 70rpx;
+			padding: 0 24rpx;
+			background: $theme-color;
+			font-size: 32rpx;
+			color: #fff;
+			margin: 0;
+			margin-left: 26rpx;
+		}
+
+		.menu_icon {
+			width: 44rpx;
+			height: 44rpx;
+			margin-left: 14rpx;
+		}
+	}
+</style>

+ 125 - 1
pages/tour_tally/check/components/CheckCard.vue

@@ -72,11 +72,28 @@
 				</view>
 			</view>
 		</view>
+		<!-- 新增拍照 *** -->
+		<view class="card-cell">
+			<text class="label">
+				<span class="mark"></span>
+			</text>
+			<view class="photo_info">
+				<view class="btn_box" v-if="type != 'view'">
+					<text class="photo_btn" @click="chooseImage">拍照</text>
+				</view>
+				<view class="photo_list">
+					<PreviewPhoto :type="type" @imagedelete="imagedelete" :imageList="photoList" />
+				</view>
+			</view>
+		</view>
+		<u-toast ref="uToast"></u-toast>
 	</view>
 </template>
 
 <script>
+	import PreviewPhoto from '@/pages/maintenance/check/components/PreviewPhoto.vue'
 	export default {
+		components:{ PreviewPhoto },
 		props: {
 			item: {
 				type: Object,
@@ -96,6 +113,13 @@
 				]
 			}
 		},
+		// *** 新增
+		computed: {
+			photoList() {
+				if (!this.item.photoList) return []
+				return this.item.photoList
+			}
+		},
 		methods: {
 			inputChange(obj, item) {
 				if (obj.target.value.length > 0) {
@@ -106,7 +130,80 @@
 			},
 			changeStatus(item, it) {
 				item.status = it.status
-			}
+			},
+			
+			// *** 新增拍照功能
+			chooseImage() {
+				const _this = this
+				if(_this.photoList.length >= 9){
+					_this.$refs.uToast.show({
+						type: "warning",
+						message: "最多上传9张照片",
+					})
+					return
+				}
+				uni.chooseImage({
+					count: 9, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['camera'], //从相册选择
+					success: function(res) {
+						uni.showLoading({
+							title: '加载中'
+						})
+			
+						_this.uploadFile(res.tempFilePaths).then(res => {
+							res.forEach(item => {
+								let fileNames = item.storePath.split('/')
+								let url = _this.apiUrl +
+									'/main/file/getFile?objectName=' + item.storePath +
+									'&fullfilename=' + fileNames[fileNames.length -
+										1]
+								console.log(_this.item, 'url ---')
+								if (!_this.item.photoList || _this.item.photoList?.length ==
+									0) {
+									_this.$set(_this.item, 'photoList', [url])
+								} else {
+									// 不能存储超过 9 张
+									if(_this.item.photoList.length < 9){
+										_this.item.photoList.push(url);
+									}
+								}
+								// _this.imgs.push(url)
+							})
+							uni.hideLoading()
+			
+						})
+					}
+				});
+			},
+			uploadFile(list) {
+				let PromiseAll = []
+				const apiUrl = this.apiUrl
+				const token = uni.getStorageSync("token"); //取存本地的token
+				list.forEach(item => {
+					PromiseAll.push(
+						new Promise((resolve, reject) => {
+							uni.uploadFile({
+								url: apiUrl + '/main/file/upload',
+								filePath: item,
+								name: 'multiPartFile',
+								header: {
+									authorization: token
+								},
+								success: (uploadFileRes) => {
+									let data = JSON.parse(uploadFileRes.data)
+									resolve(data.data)
+								}
+							});
+						}),
+					)
+				})
+				return Promise.all(PromiseAll)
+			},
+			// 图片删除
+			imagedelete(index){
+				this.item.photoList.splice(index,1);
+			},
 		}
 	}
 </script>
@@ -123,6 +220,11 @@
 			border-right: 1px solid $border-color;
 			justify-content: center;
 		}
+		.mark{
+			width: 80rpx;
+			height: 4rpx;
+			display: inline-block;
+		}
 		.title {
 			line-height: 72rpx;
 			font-weight: bold;
@@ -179,4 +281,26 @@
 			border-radius: 15rpx;
 		}
 	}
+	
+	.photo_info {
+		width: 100%;
+		padding: 6px 12rpx;
+		
+		.btn_box{
+			width: 100%;
+		}
+	
+		.photo_btn {
+			background-color: #157a2c;
+			width: 140rpx;
+			height: 60rpx;
+			line-height: 60rpx;
+			font-size: 24rpx;
+			color: #fff;
+			text-align: center;
+			border-radius: 8rpx;
+			margin-bottom: 12rpx;
+			display: inline-block !important;
+		}
+	}
 </style>

+ 2 - 1
pages/tour_tally/check/index.vue

@@ -114,7 +114,8 @@
 							operationGuide: item.operationGuide,
 							result: item.result,
 							serialNum: item.serialNum,
-							status: item.status
+							status: item.status,
+							photoList: item.photoList || []
 						}
 					})
 				}

+ 16 - 8
pages/tour_tally/order/order.vue

@@ -34,7 +34,7 @@
 		post,
 		postJ
 	} from '@/utils/api.js'
-	let [page, size, isEnd] = [1, 10, true]
+	let [page, size, isEnd] = [1, 10, false]
 	export default {
 		components: {
 			OrderTask
@@ -87,6 +87,7 @@
 					pageNum: 1,
 					size: 1
 				}).then(res => {
+					console.log(res,'res ===')
 					this.tabList[0].number = res.count
 				})
 				getWorkOrderList({
@@ -150,7 +151,8 @@
 			},
 			getFirstList: function() {
 				page = 1
-				isEnd = true
+				// isEnd = true
+				isEnd = false
 				this.getList()
 			},
 			getMoreLists: function() {
@@ -170,17 +172,23 @@
 				}
 				getWorkOrderList(params)
 					.then(res => {
-						this.tabList[this.pickTabIndex].list = res.list
-						isEnd = this.tabList[this.pickTabIndex].list >= res.count
-						uni.hideLoading()
+						// this.tabList[this.pickTabIndex].list = res.list
+						// isEnd = this.tabList[this.pickTabIndex].list >= res.count
+						if(page == 1){
+							this.tabList[this.pickTabIndex].list = res.list;
+						}else{
+							this.tabList[this.pickTabIndex].list.push(...res.list);
+						}
+						isEnd = this.tabList[this.pickTabIndex].list.length >= res.count;
+						uni.hideLoading();
 					})
 					.catch(() => {
-						uni.hideLoading()
+						uni.hideLoading();
 					})
 			},
 			changeChartsTab(index) {
-				this.pickTabIndex = index
-				this.getFirstList()
+				this.pickTabIndex = index;
+				this.getFirstList();
 			}
 		}
 	}