send-dialog.vue 9.18 KB
<template>
	<el-dialog title="创建送出记录" :visible.sync="visible" width="800px" :close-on-click-modal="false">
		<el-form ref="form" :model="{ items }" label-width="110px">
			<div
				v-for="(item, index) in items"
				:key="index"
				class="form-block"
			>
				<div class="form-block-header">
					<span class="form-block-title">记录 {{ index + 1 }}</span>
					<el-button
						v-if="items.length > 1"
						type="text"
						icon="el-icon-minus"
						@click="removeItem(index)"
					>
						删除
					</el-button>
				</div>
				<el-row :gutter="12">
					<el-col :span="12">
						<el-form-item :label="'门店'" :prop="`items.${index}.storeId`">
							<el-select v-model="item.storeId" placeholder="请选择门店" filterable style="width: 100%">
								<el-option
									v-for="s in storeList"
									:key="s.id"
									:label="s.fullName"
									:value="s.id"
								/>
							</el-select>
						</el-form-item>
					</el-col>
					<el-col :span="12">
						<el-form-item :label="'产品类型'" :prop="`items.${index}.productType`">
							<el-select
								v-model="item.productType"
								placeholder="请选择产品类型"
								clearable
								filterable
								style="width: 100%"
							>
								<el-option
									v-for="p in productTypeOptions"
									:key="p.Value"
									:label="p.Name"
									:value="p.Name"
								/>
							</el-select>
						</el-form-item>
					</el-col>
				</el-row>
				<el-row :gutter="12">
					<el-col :span="12">
						<el-form-item :label="'清洗商'" :prop="`items.${index}.laundrySupplierId`">
							<el-select
								v-model="item.laundrySupplierId"
								placeholder="请选择清洗商"
								filterable
								style="width: 100%"
								@change="val => handleSupplierChange(index, val)"
							>
								<el-option
									v-for="sp in filteredSupplierList(item.productType)"
									:key="sp.id"
									:label="sp.supplierName"
									:value="sp.id"
								/>
							</el-select>
						</el-form-item>
					</el-col>
					<el-col :span="12">
						<el-form-item label="清洗单价">
							<el-input v-model="item.laundryPrice" placeholder="自动填充" disabled />
						</el-form-item>
					</el-col>
				</el-row>
				<el-row :gutter="12">
					<el-col :span="12">
						<el-form-item :label="'送出数量'" :prop="`items.${index}.quantity`">
							<el-input-number v-model="item.quantity" :min="1" :precision="0" style="width: 100%" />
						</el-form-item>
					</el-col>
					<el-col :span="12">
						<el-form-item :label="'送出时间'" :prop="`items.${index}.sendTime`">
							<el-date-picker
								v-model="item.sendTime"
								type="datetime"
								value-format="yyyy-MM-dd HH:mm:ss"
								format="yyyy-MM-dd HH:mm:ss"
								placeholder="请选择送出时间"
								style="width: 100%"
							/>
						</el-form-item>
					</el-col>
				</el-row>
				<el-form-item label="备注">
					<el-input v-model="item.remark" type="textarea" :rows="2" placeholder="请输入备注" />
				</el-form-item>
				<el-divider v-if="index !== items.length - 1" />
			</div>
			<el-form-item>
				<el-button type="dashed" icon="el-icon-plus" @click="addItem">
					新增一条记录
				</el-button>
			</el-form-item>
		</el-form>
		<div slot="footer" class="dialog-footer">
			<el-button @click="visible = false">取消</el-button>
			<el-button type="primary" @click="submit" :loading="loading">
				{{ items.length > 1 ? `批量提交(${items.length} 条)` : '确定' }}
			</el-button>
		</div>
	</el-dialog>
</template>

<script>
import request from '@/utils/request'
import { getStoreSelector } from '@/api/extend/store'

export default {
	name: 'SendDialog',
	data() {
		return {
			visible: false,
			loading: false,
			items: [],
			storeList: [],
			supplierList: [],
			allSupplierList: [], // 保存所有清洗商列表
			productTypeOptions: [],
			defaultSendTime: ''
		}
	},
	computed: {
	},
	mounted() {
		this.initStoreList()
		this.initSupplierList()
		this.loadProductTypeOptions()
	},
	methods: {
		createEmptyItem() {
			return {
				storeId: '',
				productType: '',
				laundrySupplierId: '',
				laundryPrice: 0,
				quantity: 1,
				sendTime: this.defaultSendTime,
				remark: ''
			}
		},
		// 初始化
		init() {
			this.visible = true
			// 格式化当前时间为 yyyy-MM-dd HH:mm:ss
			const now = new Date()
			const year = now.getFullYear()
			const month = String(now.getMonth() + 1).padStart(2, '0')
			const day = String(now.getDate()).padStart(2, '0')
			const hours = String(now.getHours()).padStart(2, '0')
			const minutes = String(now.getMinutes()).padStart(2, '0')
			const seconds = String(now.getSeconds()).padStart(2, '0')
			this.defaultSendTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`

			this.items = [this.createEmptyItem()]
			this.$nextTick(() => {
				if (this.$refs.form) {
					this.$refs.form.clearValidate && this.$refs.form.clearValidate()
				}
			})
		},
		// 初始化门店列表
		initStoreList() {
			getStoreSelector().then(res => {
				if (res.code == 200 && res.data && res.data.list) {
					this.storeList = res.data.list
				}
			}).catch(() => {
				this.storeList = []
			})
		},
		// 初始化清洗商列表
		initSupplierList() {
			request({
				url: '/api/Extend/LqLaundrySupplier/GetList',
				method: 'GET',
				data: { currentPage: 1, pageSize: 1000, isEffective: 1 }
			}).then(res => {
				if (res.code == 200 && res.data && res.data.list) {
					this.allSupplierList = res.data.list
					this.supplierList = res.data.list
				}
			}).catch(() => {
				this.allSupplierList = []
				this.supplierList = []
			})
		},
		// 加载产品类型选项
		loadProductTypeOptions() {
			request({
				url: '/api/Extend/LqStoreConsumableInventory/consumable-product-type',
				method: 'GET'
			}).then(res => {
				if (res.code == 200 && res.data && Array.isArray(res.data)) {
					this.productTypeOptions = res.data
				} else {
					this.productTypeOptions = []
				}
			}).catch(() => {
				this.productTypeOptions = []
			})
		},
		// 门店变化
		handleStoreChange() {
			// 可以在这里添加逻辑
		},
		// 产品类型变化(当前实现中,不需要额外处理)
		handleProductTypeChange() {},
		// 按产品类型过滤清洗商
		filteredSupplierList(productType) {
			if (!productType) return this.allSupplierList
			return this.allSupplierList.filter(supplier => supplier.productType === productType)
		},
		// 清洗商变化
		handleSupplierChange(index, value) {
			const supplier = this.allSupplierList.find(item => item.id === value)
			if (supplier) {
				this.$set(this.items[index], 'laundryPrice', supplier.laundryPrice || 0)
			} else {
				this.$set(this.items[index], 'laundryPrice', 0)
			}
		},
		// 新增一条记录
		addItem() {
			this.items.push(this.createEmptyItem())
		},
		// 删除一条记录
		removeItem(index) {
			if (this.items.length === 1) return
			this.items.splice(index, 1)
		},
		// 前端校验
		validateItems() {
			if (!this.items.length) {
				this.$message.error('请至少填写一条记录')
				return false
			}
			for (let i = 0; i < this.items.length; i++) {
				const item = this.items[i]
				if (!item.storeId) {
					this.$message.error(`第 ${i + 1} 条:请选择门店`)
					return false
				}
				if (!item.productType) {
					this.$message.error(`第 ${i + 1} 条:请选择产品类型`)
					return false
				}
				if (!item.laundrySupplierId) {
					this.$message.error(`第 ${i + 1} 条:请选择清洗商`)
					return false
				}
				if (!item.quantity || item.quantity <= 0) {
					this.$message.error(`第 ${i + 1} 条:请输入有效的送出数量`)
					return false
				}
				// 产品类型与清洗商匹配校验
				const supplier = this.allSupplierList.find(x => x.id === item.laundrySupplierId)
				if (supplier && supplier.productType && supplier.productType !== item.productType) {
					this.$message.error(`第 ${i + 1} 条:清洗商【${supplier.supplierName}】不支持清洗产品类型【${item.productType}】`)
					return false
				}
			}
			return true
		},
		// 提交(支持单条或批量)
		async submit() {
			if (!this.validateItems()) return
			if (this.loading) return
			this.loading = true
			try {
				const payloadItems = this.items.map(x => ({
					storeId: x.storeId,
					productType: x.productType,
					laundrySupplierId: x.laundrySupplierId,
					quantity: x.quantity,
					sendTime: x.sendTime,
					remark: x.remark
				}))
				const res = await request({
					url: '/api/Extend/LqLaundryFlow/BatchSend',
					method: 'POST',
					data: { items: payloadItems }
				})
				if (res.code == 200) {
					this.$message.success(res.msg || res.message || '创建成功')
					this.visible = false
					this.$emit('refresh')
				} else {
					this.$message.error(res.msg || res.message || '创建失败')
				}
			} finally {
				this.loading = false
			}
		}
	},
	watch: {
		visible(val) {
			if (!val) {
				this.$refs.form && this.$refs.form.resetFields()
			}
		}
	}
}
</script>

<style lang="scss" scoped>
.dialog-footer {
	text-align: right;
}

.form-block {
	padding: 8px 0 0;
	max-height: 300px;
	overflow-y: scroll;
}

.form-block-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 4px;
}

.form-block-title {
	font-weight: 600;
	font-size: 13px;
	color: #606266;
}
</style>