Ver código fonte

feat: 销售发货审批

liujt 2 meses atrás
pai
commit
55d9fca629

+ 12 - 1
api/warehouseManagement/index.js

@@ -1,4 +1,4 @@
-import { postJ, post, get } from '@/utils/request'
+import { postJ, post, get, putJ } from '@/utils/request'
 import Vue from 'vue'
 
 // 获取仓库列表
@@ -201,6 +201,17 @@ export async function outStorage(data) {
 	return Promise.reject(new Error(res.message))
 }
 
+/**
+ * 更新发货单信息
+ */
+export async function updateSendInformation(data) {
+  const res = await putJ(Vue.prototype.apiUrl + `/eom/saleordersendrecord/update`, data);
+  if(res.code == 0) {
+	return res.data;
+  }
+  return Promise.reject(new Error(res.message))
+}
+
 // 提交流程(出库)
 export async function submitInsideTwo(data) {
 	const res = await postJ(Vue.prototype.apiUrl + `/bpm/outApprove/submitInsideTwo`, data)

+ 24 - 3
api/wt/index.js

@@ -333,9 +333,21 @@ export async function getSaleOrderSendRecordDetailAPI(id) {
   }
   return Promise.reject(new Error(res.message));
 }
-//
-//
-//
+
+/**
+ * 获取发货信息详情(替代料)
+ */
+export async function getByIdOnlyReplaceAPI(id) {
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/saleordersendrecord/getByIdOnlyReplace/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
 
 //
 //获取仓库信息
@@ -695,3 +707,12 @@ export async function getStorageDetail(id) {
   }
   return Promise.reject(new Error(res.message));
 }
+
+// 动态表头
+export async function fieldModel(params) {
+    const res = await get(Vue.prototype.apiUrl + `/main/fieldmodel/list`, params, true);
+    if (res.code == 0) {
+      return res.data;
+    }
+    return Promise.reject(new Error(res.message));
+}

+ 8 - 0
pages.json

@@ -93,6 +93,14 @@
 				"navigationBarTextStyle": "white"
 			}
 		},
+		{
+			"path": "pages/home/wt/components/salesDelivery/selectEnterType",
+			"style": {
+				"navigationBarTitleText": "选择入库类别",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "white"
+			}
+		},
 
 		{
 			"path": "pages/home/wt/components/processTask",

+ 679 - 0
pages/home/wt/components/salesDelivery/selectEnterType.vue

@@ -0,0 +1,679 @@
+<template>
+	<view class="mainBox">
+		<view class="main">
+			<uni-nav-bar fixed="true" statusBar="true" left-icon="back" :title="`选择${warehousingName}`"
+				@clickLeft="backAdd">
+				<!--右菜单-->
+				<template slot="right">
+					<u-button type="success" size="small" class="u-reset-button" @click="$refs.treePicker._show()"
+						text="选择分类"></u-button>
+				</template>
+			</uni-nav-bar>
+			<view class="top-wrapper">
+				<uni-section>
+					<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="searchVal" placeholder="请输入编码/名称">
+					</uni-easyinput>
+				</uni-section>
+				<view style="display: flex;">
+					<button class="search_btn" @click="doSearch">搜索</button>
+					<view class="more_search">
+						<image src="~@/static/moreSearch.svg" mode="" @click="searchVisible = true"></image>
+					</view>
+				</view>
+			</view>
+			<view class="wrapper">
+				<u-list @scrolltolower="scrolltolower" class="listContent">
+					<checkbox-group v-for="(item, index) in listData" :key="index"
+						@change.stop="e => selectVal(e, item, index)">
+						<label>
+							<view class="listBox">
+								<view class="listBox-sel">
+									<checkbox :value="item.code" color="#fff" :disabled="item.disabled"
+										:checked="item.checked" />
+								</view>
+								<view class="listBox-con">
+									<view style="display: flex;">
+										<view class="listBox-top" style="justify-content: left;">
+											<view class="round">{{Number(index)+1}}</view>
+											<view class="listBox-name">
+												{{ item.categoryName }}
+											</view>
+										</view>
+										<view class="listBox-top">
+											<view class="listBox-code">
+												{{ item.categoryCode }}
+											</view>
+										</view>
+									</view>
+									<view class="listBox-bottom">
+										<!-- <view v-for="(itm, index) in tableHeader" :key="index">{{ itm.label }}:{{ item[itm.prop] }}</view> -->
+										<view>牌号:{{ item.brandNum }}</view>
+										<view>型号:{{ item.modelType }}</view>
+										<view>规格:{{ item.specification }}</view>
+										<view v-if="dimension != 1">批次号:{{ item.batchNo }}</view>
+										<view class="input_view" v-if="dimension != 3">
+											出库数量:
+											<u--input type="number" placeholder="请输入" border="surround"
+												v-model="item.outboundNum"
+												@change="filterOutboundNum($event, item, index)"></u--input>
+										</view>
+										<view>计量数量:{{ item.measureQuantity }}({{ item.measureUnit }})</view>
+										<view class="w100" v-if="dimension == 3">包装编码:{{ item.packageNo }}</view>
+										<view v-if="dimension == 3">
+											包装数量:{{ item.packingQuantity }}({{ item.packingUnit }})</view>
+										<view>重量:{{ item.weight }}({{ item.weightUnit }})</view>
+										<view v-if="dimension == 3">发货条码:{{ item.barcodes }}</view>
+										<view v-if="dimension == 3">物料代号:{{ item.materielDesignation }}</view>
+										<view v-if="dimension == 3">客户代号:{{ item.clientCode }}</view>
+										<view v-if="dimension == 3">刻码:{{ item.engrave }}</view>
+										<view v-if="dimension == 3">仓库:{{ item.warehouseName }}</view>
+									</view>
+								</view>
+							</view>
+						</label>
+					</checkbox-group>
+					<u-empty class="noDate" style="margin-top: 20vh" v-if="!listData.length"></u-empty>
+				</u-list>
+			</view>
+
+			<view class="footer">
+				<view class="bottom">
+					<checkbox v-if="!seletedAll" color="#fff" :checked="seletedAll" @tap="_seletedAll">全选</checkbox>
+					<checkbox class="select-all" color="#fff" v-else :checked="seletedAll" @tap="_seletedAll">取消全选
+					</checkbox>
+				</view>
+				<u-button type="success" size="small" class="u-reset-button" :disabled="!checkListLen" @click="jumpAdd">
+					<view class="selBtn">选择( {{ checkListLen }} )</view>
+				</u-button>
+			</view>
+		</view>
+		<!-- 搜索组件 -->
+		<u-popup :show="searchVisible" mode="top" @close="searchVisible = false" @open="openSearch">
+			<!-- <view class="search-container">
+				<view class="title">筛选</view>
+				<uni-forms ref="customForm" :modelValue="popupInfo" label-position="top">
+					<uni-forms-item label="列表维度" name="categoryCode">
+						<uni-data-select v-model="popupInfo.dimension" :localdata="dimensionOptions"></uni-data-select>
+					</uni-forms-item>
+					<uni-forms-item label="仓库" name="sourceBizNo">
+						<uni-data-select v-model="popupInfo.warehouseId"
+							:localdata="warehouseListOption"></uni-data-select>
+					</uni-forms-item>
+				</uni-forms>
+				<view class="footer">
+					<view class="btn reset" @click="handleReset">重置</view>
+					<view class="btn search" @click="handleSearch">搜索</view>
+				</view>
+			</view> -->
+			<view class="search_list">
+				<u-form labelPosition="left" :model="popupInfo" labelWidth="180" labelAlign="left" class="baseForm">
+					<u-form-item label="列表维度:" class="required-form" borderBottom prop="assetType">
+						<zxz-uni-data-select :localdata="dimensionOptions" v-model="popupInfo.dimension"
+							dataValue='value' dataKey="text" filterable format='{text}'></zxz-uni-data-select>
+					</u-form-item>
+					<u-form-item label="仓库:" class="required-form" borderBottom prop="warehouseId">
+						<zxz-uni-data-select :localdata="warehouseListOption" v-model="popupInfo.warehouseId"
+							dataValue='value' dataKey="text" filterable format='{text}'></zxz-uni-data-select>
+					</u-form-item>
+				</u-form>
+			</view>
+			<view class="operate_box rx-bc">
+				<u-button size="small" class="u-reset-button" @click="handleReset">
+					重置
+				</u-button>
+				<u-button type="success" size="small" class="u-reset-button" @click="handleSearch">
+					确定
+				</u-button>
+			</view>
+		</u-popup>
+		<ba-tree-picker ref="treePicker" key="verify" :multiple="false" @select-change="confirm" title="选择分类"
+			:localdata="classificationList" valueKey="id" textKey="name" childrenKey="child" />
+	</view>
+</template>
+
+<script>
+	import {
+		getTreeByIds,
+		getPackingList,
+		getWarehouseList,
+		getProductList,
+		getBatchList,
+		getHierarchyList,
+		getHierarchyFifo
+	} from '@/api/warehouseManagement'
+	import {
+		warehousingType,
+		tableContentData
+	} from '@/pages/warehouse/enum.js'
+	import baTreePicker from '@/components/ba-tree-picker/ba-tree-picker.vue'
+	import {
+		tableHeader
+	} from '@/pages/warehouse/common'
+	import UList from '@/uni_modules/uview-ui/components/u-list/u-list.vue'
+	export default {
+		components: {
+			baTreePicker
+		},
+
+		data() {
+			return {
+				popupInfo: {
+					dimension: 1,
+					warehouseId: ''
+				},
+				dimension: 1,
+				warehouseId: '',
+				searchVisible: false,
+				warehouseListOption: [],
+				dimensionOptions: [{
+						value: 1,
+						text: '物品维度'
+					},
+					{
+						value: 2,
+						text: '批次维度'
+					},
+					{
+						value: 3,
+						text: '包装维度'
+					}
+				],
+				page: 1,
+				size: 20,
+				isEnd: true,
+				searchVal: '',
+				pickTabIndex: 1,
+				popupShow: false, //右侧搜索窗
+				typeIndex: 1,
+				listData: [], //列表数据
+				classificationList: [], //分类数据
+				seletedAll: false, //全选状态
+				bizScene: '',
+				warehousingName: '',
+				warehousingType: ''
+			}
+		},
+		//选择的列表长度
+		computed: {
+			tableHeader() {
+				return tableHeader(+this.warehousingType)
+			},
+			checkListLen() {
+				console.log(
+					'this.listData.filter(el => el.checked)---',
+					this.listData.filter(el => el.checked)
+				)
+				return this.listData.filter(el => el.checked).length
+			},
+			curTab() {
+				return warehousingType.find(i => i.id == this.warehousingType) || {}
+			}
+		},
+		onLoad({
+			assetType
+		}) {
+			this.assetType = assetType
+			this.categoryLevelId = assetType
+			console.log('assetType---', assetType)
+			console.log('assetType---', uni.getStorageSync('productList'))
+		},
+		//触底刷新
+		// onReachBottom: function () {
+		// 	if (this.isEnd) {
+		// 		return
+		// 	}
+		// 	// 显示加载图标
+		// 	uni.showLoading({
+		// 		title: '数据加载中'
+		// 	})
+		// 	//获取更多数据
+		// 	this.page++
+		// 	this.getList()
+		// },
+		onShow() {
+			this.getClassify()
+			this.getwarehouseOptions()
+		},
+		methods: {
+			openSearch() {
+				this.popupInfo = {
+					dimension: this.dimension,
+					warehouseId: this.warehouseId
+				}
+			},
+			filterOutboundNum(value, row, index) {
+				if (value <= 0) {
+					this.$set(this.listData[index], 'outboundNum', 1)
+				}
+				if (value > row.measureQuantity) {
+					this.$set(this.listData[index], 'outboundNum', row.measureQuantity)
+				}
+			},
+			//获取仓库
+			getwarehouseOptions() {
+				getWarehouseList().then(res => {
+					this.warehouseListOption = res.data.map(item => {
+						return {
+							value: item.id,
+							text: item.name
+						}
+					})
+				})
+			},
+			handleReset() {
+				this.popupInfo = {
+					dimension: 3,
+					warehouseId: ''
+				}
+				this.dimension = 3
+				this.warehouseId = ''
+				this.listData = []
+				this.getList()
+			},
+			handleSearch() {
+				this.dimension = this.popupInfo.dimension
+				this.warehouseId = this.popupInfo.warehouseId
+				this.getList()
+			},
+			scrolltolower() {
+				if (this.isEnd) {
+					return
+				}
+				// 显示加载图标
+				uni.showLoading({
+					title: '数据加载中'
+				})
+				//获取更多数据
+				this.page++
+				this.getList()
+			},
+			//列表数据
+			async getList() {
+				this.searchVisible = false
+				this.isEnd = false
+				this._getClassifyList()
+			},
+			async _getClassifyList() {
+				uni.showLoading({
+					title: '数据加载中'
+				})
+				let res = null
+				const params = {
+					pageNum: this.page,
+					size: this.size,
+					searchKey: this.searchVal,
+					warehouseId: this.popupInfo.warehouseId,
+					categoryLevelId: this.categoryLevelId
+				}
+				if (this.popupInfo.dimension == 1) {
+					// 物品维度
+					res = await getProductList(params)
+				} else if (this.popupInfo.dimension == 2) {
+					// 批次维度
+					res = await getBatchList(params)
+					for (let i = 0; i < res.list.length; i++) {
+						res.list[i].outboundNum = res.list[i].measureQuantity;
+					}
+				} else {
+					// 包装维度
+					res = await getPackingList(params)
+					for (let i = 0; i < res.list.length; i++) {
+						res.list[i].outboundNum = res.list[i].packingQuantity;
+					}
+				}
+				uni.hideLoading()
+				if (this.page == 1) {
+					this.listData = []
+				}
+				this.listData = this.listData.concat(res.list)
+				this.isEnd = this.listData.length >= res.count
+				this.updateProductOutboundNums(this.listData)
+			},
+		updateProductOutboundNums(list) {
+			const productLists = uni.getStorageSync('productList')
+			console.log(productLists, 'productLists');
+
+			if (this.dimension == 1) {
+			//物品层
+			for (let i = 0; i < list.length; i++) {
+				const item = list[i];
+				const matchedProduct = productLists.find((product) => {
+					const isMatch = product.categoryId === item.categoryId;
+					return isMatch;
+				});
+
+				if (matchedProduct) {
+					this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
+					this.$set(item, 'disabled', true); // 禁用勾选框
+				}
+				// const isSelection = this.selectionList.find(
+				// 	(product) => product.categoryId === item.categoryId
+				// );
+				// if (isSelection) {
+				// 	this.$set(item, 'outboundNum', isSelection.outboundNum);
+				// }
+			}
+			} else {
+				for (let i = 0; i < list.length; i++) {
+					const item = list[i];
+					const matchedProduct = productLists.find((product) => {
+						const isMatch = product.id === item.id;
+						return isMatch;
+					});
+
+					if (matchedProduct) {
+						this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
+						this.$set(item, 'disabled', true); // 禁用勾选框
+					}
+					// const isSelection = this.selectionList.find(
+					// 	(product) => product.id === item.id
+					// );
+					// if (isSelection) {
+					// 	this.$set(item, 'outboundNum', isSelection.outboundNum);
+					// }
+				}
+			}
+		},
+			confirm([id]) {
+				console.log('id----------', id)
+				this.categoryLevelId = id
+				this.page = 1
+				this.getList()
+			},
+			async getClassify() {
+				getTreeByIds({
+					ids: this.assetType
+				}).then(res => {
+					console.log('res--------', res)
+					this.classificationList = res
+					this.page = 1
+					this.getList()
+				})
+			},
+			doSearch() {
+				this.page = 1
+				this.getList()
+			},
+			//勾选
+			selectVal(e, val, index) {
+				this.$set(this.listData[index], 'checked', !this.listData[index].checked)
+				// this.listData[index].checked = !this.listData[index].checked
+				this.seletedAll = !this.listData.some(item => !item.checked)
+			},
+			//全选按钮
+			_seletedAll() {
+				if (!this.seletedAll) {
+					this.seletedAll = true
+					this.listData.map(item => {
+						this.$set(item, 'checked', true)
+					})
+				} else {
+					this.seletedAll = false
+					//this.checkListLen = 0;
+					this.listData.map(item => {
+						this.$set(item, 'checked', false)
+					})
+				}
+			},
+			//跳转回添加页面
+			async jumpAdd() {
+				let selectionList = this.listData.filter(item => item.checked)
+		
+				if (this.dimension == 1) {
+					let boolen = selectionList.every(item => item.outboundNum > 0)
+					if (!boolen) {
+						uni.showToast({
+							icon: 'none',
+							title: '请输入出库数量',
+							duration: 2000
+						})
+						return
+					}
+				}
+
+				let data = null;
+				if (this.dimension == 3) {
+					data = await getHierarchyList({
+						ids: selectionList.map(item => item.id).join(','),
+						type: this.dimension
+					});
+				} else if (this.dimension == 2) {
+					data = await getHierarchyFifo({
+						type: this.dimension,
+						ids: selectionList.map(item => item.id).join(','),
+						builders: selectionList.map((item) => {
+							return {
+								categoryId: item.categoryId,
+								num: item.outboundNum,
+								id: item.id
+							};
+						})
+					});
+				} else if (this.dimension == 1) {
+					data = await getHierarchyFifo({
+						type: this.dimension,
+						builders: selectionList.map((item) => {
+						return {
+							categoryId: item.categoryId,
+							num: item.outboundNum
+						};
+						})
+					});
+				}
+				console.log('data-------------------', data)
+				uni.$emit('setSelectList', data, this.dimension)
+				uni.navigateBack()
+			},
+			//返回添加页
+			backAdd() {
+				uni.navigateBack()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.mainBox {
+		height: 100vh;
+
+		.main {
+			height: 100%;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.top-wrapper {
+			display: flex;
+			height: 88rpx;
+			align-items: center;
+			justify-content: space-between;
+			padding: 20rpx;
+
+			/deep/.uni-section {
+				margin-top: 0px;
+			}
+
+			/deep/.uni-section-header {
+				padding: 0px;
+
+			}
+
+			.search_btn {
+				width: 120rpx;
+				height: 70rpx;
+				line-height: 70rpx;
+				background: $theme-color;
+				font-size: 28rpx;
+				color: #fff;
+			}
+
+			.menu_icon {
+				width: 44rpx;
+				height: 44rpx;
+				margin-left: 14rpx;
+			}
+
+			.more_search {
+				display: flex;
+				align-items: center;
+				height: 70rpx;
+				line-height: 70rpx;
+
+			}
+
+			/deep/.u-input {
+				border: 1rpx solid #ccc;
+
+				.u-input__content__field-wrapper__field {
+					height: 40rpx !important;
+				}
+			}
+
+			image {
+				width: 52rpx;
+				height: 52rpx;
+				margin-left: 10rpx;
+			}
+
+		}
+
+		.wrapper {
+			flex: 1;
+			overflow: hidden;
+		}
+
+		.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;
+
+					.round {
+						width: 40rpx;
+						height: 40rpx;
+						line-height: 40rpx;
+						border-radius: 50%;
+						background: $theme-color;
+						color: #fff;
+						text-align: center;
+						font-size: 20rpx;
+					}
+
+					.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: 50%;
+							overflow: hidden;
+							white-space: nowrap;
+							text-overflow: ellipsis;
+						}
+
+						.input_view {
+							display: flex;
+							align-items: center;
+							justify-content: center;
+
+							.u-input {
+								height: 36rpx;
+								padding: 0 !important;
+								margin-right: 10rpx;
+								border: 1px solid #ddd;
+							}
+						}
+
+						.w100 {
+							width: 100%;
+						}
+					}
+				}
+			}
+
+			.noDate {
+				height: 100%;
+			}
+		}
+
+		//底部按钮
+		.footer {
+			height: 90rpx;
+			position: relative;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			bottom: 0;
+			width: 100%;
+			height: 100rpx;
+			border-top: 1rpx solid #eeecec;
+			background-color: #ffffff;
+			z-index: 999;
+
+			.bottom {
+				margin-left: 10rpx;
+			}
+
+			.u-reset-button {
+				position: absolute;
+				right: 10rpx;
+				top: 20rpx;
+				width: 150rpx;
+			}
+		}
+
+		.search_list {
+			min-height: 100rpx;
+
+			/deep/ .baseForm {
+				padding: 0 20rpx;
+			}
+		}
+
+		.operate_box {
+			padding: 10rpx 32rpx;
+
+			/deep/ .u-button {
+				width: 40%;
+			}
+		}
+	}
+</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 989 - 18
pages/home/wt/components/salesDelivery/taskForm.vue


+ 155 - 30
pages/home/wt/components/salesDelivery/taskSubmit.vue

@@ -7,13 +7,24 @@
 					v-model="form.reason"></u--textarea>
 			</u-form-item>
 		</u--form>
-		<view>
+		<!-- <view>
 			<u-button style="width: 100%;margin-bottom: 10rpx;" icon="edit-pen" :loading='loading' type="success"
 				text="通过" @click="handleAudit(1)">
 			</u-button>
 			<u-button style="width: 100%;" :loading='loading' type="error" icon="close" text="驳回"
 				@click="handleAudit(0)" v-if="!['starter'].includes(taskDefinitionKey)"></u-button>
+		</view> -->
+		<view class="btnList">
+			<u-button v-if="passBtnDisabled" style="width: 45%;margin-bottom: 10rpx;" :loading='loading' type="success" text="通过" @click="handleAudit(1)">
+			</u-button>
+			<u-button v-if="acceptBtnDisabled" style="width: 45%;margin-bottom: 10rpx;" :loading='loading' type="success" text="申请出库" @click="storemanApprove">
+			</u-button>
+			<u-button style="width: 45%;" :loading='loading' type="error" text="驳回" @click="rejectTask(0)"></u-button>
 		</view>
+		<!-- <view class="btnConcel">
+			<u-button @click="showAction = true">更多</u-button>
+		</view> -->
+		<!-- <u-action-sheet :actions="actionList" :closeOnClickOverlay="true" :closeOnClickAction="true" title="更多操作" :show="showAction" @close="showAction = false" @select="selectActionClick"></u-action-sheet> -->
 
 	</view>
 </template>
@@ -21,8 +32,12 @@
 <script>
 	import {
 		approveTaskWithVariables,
-		getWarehouseListByIdsAPI
+		getWarehouseListByIdsAPI,
+		getSaleOrderSendRecordDetailAPI,
+		getOutInBySourceBizNo,
+		rejectTask
 	} from '@/api/wt/index.js'
+	import { outStorage, updateSendInformation } from '@/api/warehouseManagement/index.js'
 	export default {
 		name: 'taskSubmit',
 		props: {
@@ -43,6 +58,7 @@
 		data() {
 			return {
 				loading: false,
+				outInData: { verifyStatus: 0 },
 				form: {
 					technicianId: '',
 					reason: '',
@@ -55,48 +71,150 @@
 						trigger: 'blur'
 					}
 				},
-				tabOptions: [{
-					key: 'deptLeaderApprove',
-					permissionType: 'view',
-					name: '部门主管审批',
-				}],
 			}
 		},
-		mounted() {
-			this.$refs.uForm.setRules(this.rules)
+		computed: {
+			acceptBtnDisabled() {
+				console.log('acceptBtnDisabled check:', this.taskDefinitionKey, this.outInData.verifyStatus);
+				return ['storemanApprove'].includes(this.taskDefinitionKey) && [0, 3].includes(this.outInData.verifyStatus);
+			},
+			passBtnDisabled() {
+				console.log('passBtnDisabled check:', this.taskDefinitionKey, this.outInData.verifyStatus);
+				return this.taskDefinitionKey != 'storemanApprove' || (this.taskDefinitionKey == 'storemanApprove' && this.outInData.verifyStatus == 2)
+			}
+		},
+		async mounted() {
+			this.$nextTick(() => {
+				this.$refs.uForm?.setRules(this.rules)
+			})
+			if (this.taskDefinitionKey == 'storemanApprove') {
+				let data = await getSaleOrderSendRecordDetailAPI(this.businessId);
+				try {
+					console.log(data, '1111111111');
+					data = await getOutInBySourceBizNo(data.docNo);
+					console.log('data--------------', data);
+					if (JSON.stringify(data) != '{}') {
+						this.outInData = data;
+					}
+					console.log(this.outInData, '============');
+				} catch (error) {
+					console.log(22222222, '22222222222');
+					this.outInData.verifyStatus = 0;
+				}
+			}
 		},
 		methods: {
+			async storemanApprove() {
+				let res = await this.getTableValue();
+				let storageData = res.returnStorageData;
+				console.log('storageData~~~', storageData);
+				// return
+				// 出库来源isSkip 0-正常  1-外部(外部跳过内部审核流程)
+				storageData.isSkip = 1;
+				try {
+					this.loading = true;
+					await outStorage(storageData);
+					approveTaskWithVariables({
+						id: this.taskId,
+						reason: this.form.reason,
+						variables: {
+							pass: true
+						}
+					}).then((res) => {
+						if (res.code != '-1') {
+							this.$emit('handleAudit', {
+								status: 1,
+								title: '出库'
+							});
+						}
+						this.loading = false;
+					});
+				} catch (error) {
+					this.loading = false;
+					console.error('保存失败:', error);
+				}
+			},
+
+			rejectTask(status) {
+				let variables = {
+					pass: !!status
+				};
+				rejectTask({
+					id: this.taskId,
+					reason: this.form.reason,
+					variables
+				}).then((res) => {
+					if (res.data.code != '-1') {
+						this.$emit('handleAudit', {
+						status,
+						title: status === 0 ? '驳回' : ''
+						});
+					}
+				});
+			},
+
 			async handleAudit(status) {
-				if (!!status) await this.$refs.uForm.validate()
-				let storemanIds = []
+				let storemanIds = '';
+				//发起人补充
+				if (
+					this.taskDefinitionKey === 'starter' ||
+					this.taskDefinitionKey === 'salesmanUploadReceipt'
+				) {
+					let arr = await this.getTableValue();
+					console.log('arr--------', arr);
+					if (!arr) {
+						return;
+					}
+					if (
+						this.taskDefinitionKey === 'salesmanUploadReceipt' &&
+						arr.replied === 0
+					) {
+						uni.$u.toast('回执附件不能为空');
+						return;
+					}
+					// console.log(arr)
+					// return
+					let data = await updateSendInformation(arr);
+					if (data.code != '0') {
+						return;
+					}
+				}
+
 				if (this.taskDefinitionKey === 'deptLeaderApprove') {
-					let form = await this.getTableValue();
-					let ids = form.productList.map((item) => item.warehouseId);
+					let arr = await this.getTableValue();
+					let ids = arr.form.productList.map((item) => item.warehouseId);
 					let data = await getWarehouseListByIdsAPI(ids || []);
-					storemanIds = data.map((item) => item.ownerId) || [];
+					storemanIds = data.map((item) => item.ownerId);
 				}
-				if (!storemanIds.length) return uni.$u.toast('未配置仓管人员,请检查')
 				this.loading = true
-				await this._approveTaskWithVariables(status, Array.from(new Set(storemanIds)).toString());
+				this._approveTaskWithVariables(
+					status,
+					storemanIds.length > 0
+						? Array.from(new Set(storemanIds)).toString()
+						: ''
+				);
 			},
-			async _approveTaskWithVariables(status,storemanIds='') {
+			async _approveTaskWithVariables(status, storemanIds) {
 				let variables = {
-					pass: !!status,
-					storemanIds
+					pass: !!status
 				};
-				let res = await approveTaskWithVariables({
+				if (storemanIds) {
+					variables['storemanIds'] = storemanIds;
+				}
+				let API = !!status ? approveTaskWithVariables : rejectTask;
+				API({
 					id: this.taskId,
 					reason: this.form.reason,
 					variables
-				})
-
-				if (res.code != '-1') {
-					this.$emit('handleAudit', {
-						status,
-						title: status === 0 ? '驳回' : ''
-					});
-				}
-				this.loading = false
+				}).then((res) => {
+					if (res.data.code != '-1') {
+						this.$emit('handleAudit', {
+							status,
+							title: status === 0 ? '驳回' : ''
+						});
+					}
+					this.loading = false
+				});
 			},
 
 			getTableValue() {
@@ -110,5 +228,12 @@
 	}
 </script>
 
-<style>
+<style scoped>
+.btnList {
+	display: flex;
+
+}
+.btnConcel {
+	margin-top: 20rpx;
+	}
 </style>

+ 186 - 0
pages/home/wt/components/salesOrderInvoice/processTask.vue

@@ -0,0 +1,186 @@
+<template>
+	<view class="havedone-container">
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" :title="uniNavBarTitle"
+		 background-color="#157A2C" color="#fff"
+			@clickLeft="back"></uni-nav-bar>
+			<!-- <iframe src="http://aiot.zoomwin.com.cn:51001/test/a.html" style="width: 200px;height: 600px" frameborder="0"></iframe> -->
+		<view v-if="processInstance.processDefinition">
+			<taskForm id='async-biz-form-component' :taskId="listData.taskId" :businessId="listData.businessId" :id="listData.id"
+				:taskDefinitionKey="listData.taskDefinitionKey"
+				 ref="bziRef"></taskForm>
+				 
+		</view>
+		<view v-for="(item, index) in runningTasks" :key="index">
+			<div v-if="processInstance.processDefinition">
+				<taskSubmit id='async-sub-form-component' :taskId="listData.taskId" :businessId="listData.businessId" :id="listData.id"
+					:taskDefinitionKey="listData.taskDefinitionKey" @handleAudit="handleAudit"
+					@getTableValue="getTableValue" @handleUpdateAssignee="handleUpdateAssignee(item)"
+					@handleBackList="handleBackList(item)" ref="subForm">
+				</taskSubmit>
+			</div>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import {
+		getProcessInstance,
+		getTaskListByProcessInstanceId
+	} from '@/api/wt/index.js'
+import Vue from 'vue'
+import taskForm from './taskForm.vue'
+import taskSubmit from './taskSubmit.vue'
+
+	export default {
+		name: 'processTask',
+		components:{ taskForm,taskSubmit },
+		data() {
+			return {
+				uniNavBarTitle: '',
+				processInstanceLoading: false,
+				listData: {},
+				processInstance: {},
+				runningTasks: [],
+				auditForms: [],
+				activeComp: null,
+			}
+		},
+
+		onLoad(option) {
+			this.listData = option
+			this.getDetail()
+			 this.activeComp = 'tab1'
+		},
+		methods: {
+			/** 获得流程实例 */
+		async	getDetail() {
+				// 获得流程实例相关
+				this.processInstanceLoading = true;
+				getProcessInstance({
+					id: this.listData.id
+				}).then(async (response) => {
+					if (!response) {
+						this.$message.error('查询不到流程信息!');
+						return;
+					}
+					// 设置流程信息 
+						this.processInstance = response;
+					this.uniNavBarTitle =`${ response.name } 【${ response.startUser?.nickname}】`
+						
+			
+					// //将业务表单,注册为动态组件
+					// Vue.component('async-biz-form-component', (resolve) => {
+					// 	require(['pages/home' + this.listData.miniHandleRouter], resolve);
+					// });
+					// Vue.component('async-sub-form-component', (resolve) => {
+					// 	require(['pages/home' + this.listData.miniViewRouter], resolve);
+					// });
+					
+				
+					this.processInstanceLoading = false;
+				});
+
+				this.runningTasks = [];
+				this.auditForms = [];
+				getTaskListByProcessInstanceId({
+					processInstanceId: this.listData.id
+				}).then((response) => {
+					console.log(response, 'response');
+					// 审批记录
+					this.tasks = [];
+					// 移除已取消的审批
+					response.forEach((task) => {
+						if (task.result !== 4) {
+							this.tasks.push(task);
+						}
+					});
+					// 排序,将未完成的排在前面,已完成的排在后面;
+					this.tasks.sort((a, b) => {
+						// 有已完成的情况,按照完成时间倒序
+						if (a.endTime && b.endTime) {
+							return b.endTime - a.endTime;
+						} else if (a.endTime) {
+							return 1;
+						} else if (b.endTime) {
+							return -1;
+							// 都是未完成,按照创建时间倒序
+						} else {
+							return b.createTime - a.createTime;
+						}
+					});
+
+					// 需要审核的记录
+					let userInfo = wx.getStorageSync("userInfo");
+					this.tasks.forEach((task) => {
+						if (task.result !== 1 && task.result !== 6) {
+							// 只有待处理才需要
+							return;
+						}
+						if (!task.assigneeUser || task.assigneeUser.id !== userInfo.userId) {
+							// 自己不是处理人
+							return;
+						}
+						if (task.taskDefinitionKey !== this.listData.taskDefinitionKey) {
+							// 不是当前流程的
+							return;
+						}
+						this.runningTasks.push({
+							...task
+						});
+						console.log(this.runningTasks, ' this.runningTasks');
+						this.auditForms.push({
+							reason: ''
+						});
+					});
+				});
+			},
+
+
+			/** 处理审批通过和不通过的操作 */
+			handleAudit(data) {
+				let text = data.status === 1 ? '通过' : '不通过';
+				this.$refs.uToast.show({
+					type: 'success',
+					message: `审批${data.title || text}成功!`,
+					iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+				})
+				// 获得最新详情
+				setTimeout(() => {
+				
+					uni.navigateBack()
+				}, 1000)
+
+
+				// const index = this.runningTasks.indexOf(task);
+				// this.$refs['form' + index][0].validate((valid) => {
+				//   if (!valid) {
+				//     return;
+				//   }
+				//   const data = {
+				//     id: task.id,
+				//     reason: this.auditForms[index].reason
+				//   };
+				//   if (pass) {
+				//     approveTask(data).then((response) => {
+				//       this.$message.success('审批通过成功!');
+				//       this.handleClose(); // 获得最新详情
+				//     });
+				//   } else {
+				//     rejectTask(data).then((response) => {
+				//       this.$message.success('审批不通过成功!');
+				//       this.handleClose(); // 获得最新详情
+				//     });
+				//   }
+				// });
+			},
+			getTableValue(fn) {
+				fn(this.$refs.bziRef.getTableValue());
+			}
+		}
+
+	}
+</script>
+
+<style>
+</style>

+ 250 - 0
pages/home/wt/components/salesOrderInvoice/taskForm.vue

@@ -0,0 +1,250 @@
+<template>
+	<view class="">
+		<u-sticky offset-top="50">
+			<u-subsection fontSize='25' mode='subsection' :list="list" :current="curNow" @change="sectionChange"
+				activeColor='#157A2C'></u-subsection>
+		</u-sticky>
+
+		<view v-show='curNow===0'>
+			<u--form style="margin: 0 20px;" labelPosition="left" :model="form" ref="uForm" labelWidth='140rpx'>
+				<u-form-item label="订单编号" prop="orderNo" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.orderNo"></u--input>
+				</u-form-item>
+				<u-form-item label="合同名称" prop="contractName" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.contractName"></u--input>
+				</u-form-item>
+				<u-form-item label="合同编号" prop="contractNumber" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.contractNumber"></u--input>
+				</u-form-item>
+				<u-form-item label="项目名称" prop="projectName" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.projectName"></u--input>
+				</u-form-item>
+				<u-form-item label="优惠总金额" prop="payAmount" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.payAmount"></u--input>
+				</u-form-item>
+
+				<u-form-item label="订单总金额" prop="totalAmount" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.totalAmount"></u--input>
+				</u-form-item>
+				<u-form-item label="附件" prop="orderFiles" borderBottom>
+					<fileMain v-model="form.orderFiles" type="view"></fileMain>
+				</u-form-item>
+			</u--form>
+
+		</view>
+		<view v-show='curNow===1'>
+			<u--form style="margin: 0 20px;" labelPosition="left" :model="form" ref="uForm" labelWidth='140rpx'>
+				<u-form-item label="客户名称" prop="partaName" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaName"></u--input>
+				</u-form-item>
+				<u-form-item label="客户信用代码" prop="partaUnifiedSocialCreditCode" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaUnifiedSocialCreditCode"></u--input>
+				</u-form-item>
+				<u-form-item label="客户联系人" prop="partaLinkName" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaLinkName"></u--input>
+				</u-form-item>
+				<u-form-item label="客户电话" prop="partaTel" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaTel"></u--input>
+				</u-form-item>
+				<u-form-item label="客户传真" prop="partaFax" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaFax"></u--input>
+				</u-form-item>
+				<u-form-item label="客户Email" prop="partaEmail" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaEmail"></u--input>
+				</u-form-item>
+				<u-form-item label="客户地址" prop="partaAddress" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partaAddress"></u--input>
+				</u-form-item>
+
+
+				<u-form-item label="售出方名称" prop="partbName" borderBottom>
+					<u--input style="width: 100%;" disabled :value='`${form.partbName}`'></u--input>
+				</u-form-item>
+				<u-form-item label="售出方信用代码" prop="partbUnifiedSocialCreditCode" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partbUnifiedSocialCreditCode"></u--input>
+				</u-form-item>
+				<u-form-item label="售出方联系人" prop="partbLinkName" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partbLinkName"></u--input>
+				</u-form-item>
+				<u-form-item label="售出方电话" prop="partbTel" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partbTel"></u--input>
+				</u-form-item>
+				<u-form-item label="售出方传真" prop="partbFax" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partbFax"></u--input>
+				</u-form-item>
+				<u-form-item label="售出方Email" prop="partbEmail" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partbEmail"></u--input>
+				</u-form-item>
+				<u-form-item label="售出方地址" prop="partbAddress" borderBottom>
+					<u--input style="width: 100%;" disabled v-model="form.partbAddress"></u--input>
+				</u-form-item>
+			</u--form>
+		</view>
+		<view v-show='curNow===2'>
+			<u-sticky offset-top="100">
+				<u-tag
+					:text="`总计: ${form.totalAmount&&form.totalAmount} 优惠总金额: ${form.payAmount&&form.payAmount}`"
+					size="large" type="success"></u-tag>
+			</u-sticky>
+			<view v-for="(item,index) in form['productList']" :key="index">
+				<u--form style="margin: 0 20px;" labelPosition="left" :model="form" ref="uForm" labelWidth='140rpx'>
+					<u-row v-for="(key,index1) in tableField" :key="index1">
+						<u-col :span="12">
+							<u-form-item :label="key.label" prop="categoryName" borderBottom>
+								<u--input style="width: 100%;" :title='item[key.field]' disabled
+									v-model="item[key.field]"></u--input>
+							</u-form-item>
+						</u-col>
+
+					</u-row>
+				</u--form>
+				<u-gap height="40" bgColor="#f0f0f0"></u-gap>
+			</view>
+
+		</view>
+		<view v-show='curNow===3'>
+			<view v-for="(item,index) in form['receiptPaymentList']" :key="index">
+				<u--form style="margin: 0 20px;" labelPosition="left" :model="form" ref="uForm" labelWidth='140rpx'>
+					<u-row v-for="(key,index1) in feeTableField" :key="index1">
+						<u-col :span="12">
+							<u-form-item :label="key.label" prop="categoryName" borderBottom>
+								<u--input style="width: 100%;" :title='item[key.field]' disabled
+									v-model="item[key.field]"></u--input>
+							</u-form-item>
+						</u-col>
+
+					</u-row>
+				</u--form>
+				<u-gap height="40" bgColor="#f0f0f0"></u-gap>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		getSaleOrderDetailAPI
+	} from '@/api/wt/index.js'
+	import fileMain from "@/pages/doc/index.vue"
+	import {transactionMethodsOp,shippingModeOp,shippingModePurchaseOp, pricingWayList, levelList, quoteTypeOp} from '@/enum/dict.js'
+	export default {
+		components: {
+			fileMain
+		},
+		props: {
+			businessId: {
+				default: ''
+			},
+			taskDefinitionKey: {
+				default: ''
+			},
+		},
+		computed: {
+			shippingModeOptions() {
+				return this.form.type == 2 ? shippingModePurchaseOp : shippingModeOp;
+			},
+			feeTableField() {
+				return [{
+						label: '期数',
+						field: 'issueNumber',
+					}, 
+					{
+						label: '款项类型',
+						field: 'typeName',
+					},
+					{
+						label: '款项名称',
+						field: 'moneyName',
+					},
+					{
+						label: '比例(%)',
+						field: 'ratio',
+					},
+					{
+						label: this.form.type == 2 ? '计划付款金额(元)' : '计划收款金额(元)',
+						field: 'price',
+					},
+					{
+						label: this.form.type == 2 ? '计划付款日期' : '计划收款日期',
+						field: 'deadLine',
+					},
+					{
+						label: '说明',
+						field: 'remark',
+					}
+				]
+			},
+		},
+		data() {
+			return {
+				form: {},
+				tableField: [{
+						label: '类型',
+						field: 'productCategoryName',
+					}, {
+						label: '名称',
+						field: 'productName',
+					},
+					{
+						label: '编码',
+						field: 'productCode',
+					},
+					{
+						field: 'specification',
+						label: '规格',
+
+					},
+					{
+						field: 'brandNo',
+						label: '牌号',
+
+					},
+					{
+						label: '客户代号',
+						field: 'customerMark',
+					},
+					{
+						label: '单价',
+						field: 'singlePrice',
+					},
+					{
+						label: '折让单价',
+						field: 'discountSinglePrice',
+					},
+					{
+						label: '数量',
+						field: 'totalCount',
+					},
+					{
+						label: '合计',
+						field: 'totalPrice',
+					},
+					{
+						label: '折让合计金额',
+						field: 'discountTotalPrice',
+					},
+				],
+				list: ['订单信息', '基本信息', '产品清单', '收款计划'],
+				curNow: 0
+			}
+		},
+		async mounted() {
+			await this.getDetailData(this.businessId);
+		},
+		methods: {
+			sectionChange(index) {
+				this.curNow = index;
+			},
+			async getDetailData(id) {
+				const data = await getSaleOrderDetailAPI(id);
+				this.form = data;
+			}
+		}
+	}
+</script>
+
+<style scoped>
+.btnConcel {
+		margin-top: 20rpx;
+	}
+</style>

+ 165 - 0
pages/home/wt/components/salesOrderInvoice/taskSubmit.vue

@@ -0,0 +1,165 @@
+<template>
+	<view class="">
+		<u--form style="margin: 0 20px;" labelPosition="left" :model="form" :rules="rules" ref="uForm"
+			labelWidth='140rpx'>
+			<u-form-item label="审批建议" prop="reason" required>
+				<u--textarea style="width: 100%;" height='120' border='surround' placeholder="请输入审批建议"
+					v-model="form.reason"></u--textarea>
+			</u-form-item>
+		</u--form>
+		<view class="btnList">
+			<u-button style="width: 45%;margin-bottom: 10rpx;" :loading='loading' type="success" text="通过"
+				@click="handleAudit(1)">
+			</u-button>
+			<u-button style="width: 45%;" :loading='loading' type="error" text="驳回" @click="rejectTask(0)"></u-button>
+		</view>
+		<view class="btnConcel">
+			<u-button @click="showAction = true">更多</u-button>
+		</view>
+		<u-action-sheet :actions="actionList" :closeOnClickOverlay="true" :closeOnClickAction="true" title="更多操作" :show="showAction" @close="showAction = false" @select="selectActionClick"></u-action-sheet>
+	</view>
+</template>
+
+<script>
+	import {
+		approveTaskWithVariables,
+		rejectTask,
+		cancelTask
+	} from '@/api/wt/index.js'
+	export default {
+		name: 'taskSubmit',
+		props: {
+			businessId: {
+				default: ''
+			},
+			taskId: {
+				default: ''
+			},
+			id: {
+				default: ''
+			},
+			taskDefinitionKey: {
+				default: ''
+			}
+		},
+
+		data() {
+			return {
+				showAction: false,
+				loading: false,
+				actionList: [{
+					name: '作废',
+					fontSize: '28',
+					color: '#ffaa7f'
+				}],
+				form: {
+					technicianId: '',
+					reason: '',
+				},
+				rules: {
+					reason: {
+						type: 'string',
+						required: true,
+						message: '请输入审批建议',
+						trigger: 'blur'
+					}
+				}
+			}
+		},
+		mounted() {
+			this.$refs.uForm.setRules(this.rules)
+		},
+		methods: {
+			selectActionClick(item) {
+				console.log('selectActionClick', item)
+				if (item.name == '作废') {
+					uni.showModal({
+						title: '提示',
+						content: '是否确认作废?',
+						success: (res) => {
+							if (res.confirm) {
+								this.loading = true
+								cancelTask({
+									taskId: this.taskId,
+									id: this.id,
+									reason: this.form.reason,
+									businessId: this.businessId,
+								}).then(() => {
+									if (res.code != '-1') {
+										this.loading = false
+										this.$emit('handleAudit', {
+											title: '作废'
+										});
+									}
+								}).catch(() => {
+									this.loading = false
+									this.$message.error("流程作废失败");
+								});
+							} else if (res.cancel) {
+								console.log('用户点击取消');
+							}
+						}
+					});
+				}
+			},
+			async handleAudit(status) {
+				if (!!status) await this.$refs.uForm.validate()
+				this.loading = true
+				await this._approveTaskWithVariables(status);
+			},
+			async _approveTaskWithVariables(status) {
+				let variables = {
+					pass: !!status
+				};
+				let res = await approveTaskWithVariables({
+					id: this.taskId,
+					reason: this.form.reason,
+					variables
+				})
+
+				if (res.code != '-1') {
+					this.$emit('handleAudit', {
+						status,
+						title: status === 0 ? '驳回' : ''
+					});
+				}
+				this.loading = false
+			},
+			async rejectTask(status) {
+				let variables = {
+					pass: !!status
+				};
+				let res = await rejectTask({
+					id: this.taskId,
+					reason: this.form.reason,
+					variables
+				})
+
+				if (res.code != '-1') {
+					this.$emit('handleAudit', {
+						status,
+						title: status === 0 ? '驳回' : ''
+					});
+				}
+				this.loading = false
+			},
+			getTableValue() {
+				return new Promise((resolve, reject) => {
+					this.$emit('getTableValue', async (data) => {
+						resolve(await data);
+					});
+				});
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.btnList {
+		display: flex;
+
+	}
+	.btnConcel {
+		margin-top: 20rpx;
+	}
+</style>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff