feat(mobile-h5): wire select-only master data into business forms
Replace master-data CRUD pickers with CRM/PL selectors, require productId, drop auto vehicle create, and remove 基础资料 routes/menu. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
a8f59183df
commit
db06fea45a
9 files changed
+129
-725
No files matched your search
@@ -23,11 +23,6 @@ const simpleRoutes: any[] = [
|
||||
path: '/weighing',
|
||||
name: 'Weighing',
|
||||
meta: { title: '地磅单管理', icon: '', isHide: false }
|
||||
},
|
||||
{
|
||||
path: '/master-data',
|
||||
name: 'MasterData',
|
||||
meta: { title: '基础资料', icon: '', isHide: false }
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -88,48 +88,6 @@ const routes: RouteRecordRaw[] = [
|
||||
name: 'WeighingDetailEdit',
|
||||
component: () => import('@/views/weighing/detail.vue'),
|
||||
meta: { title: '地磅单详情' }
|
||||
},
|
||||
{
|
||||
path: '/master-data',
|
||||
name: 'MasterData',
|
||||
component: () => import('@/views/master-data/index.vue'),
|
||||
meta: { title: '基础资料' }
|
||||
},
|
||||
{
|
||||
path: '/master-data/company/detail',
|
||||
name: 'CompanyDetail',
|
||||
component: () => import('@/views/master-data/company-detail.vue'),
|
||||
meta: { title: '公司详情' }
|
||||
},
|
||||
{
|
||||
path: '/master-data/company/detail/:id',
|
||||
name: 'CompanyDetailEdit',
|
||||
component: () => import('@/views/master-data/company-detail.vue'),
|
||||
meta: { title: '公司详情' }
|
||||
},
|
||||
{
|
||||
path: '/master-data/cargo/detail',
|
||||
name: 'CargoDetail',
|
||||
component: () => import('@/views/master-data/cargo-detail.vue'),
|
||||
meta: { title: '货物详情' }
|
||||
},
|
||||
{
|
||||
path: '/master-data/cargo/detail/:id',
|
||||
name: 'CargoDetailEdit',
|
||||
component: () => import('@/views/master-data/cargo-detail.vue'),
|
||||
meta: { title: '货物详情' }
|
||||
},
|
||||
{
|
||||
path: '/master-data/vehicle/detail',
|
||||
name: 'VehicleDetail',
|
||||
component: () => import('@/views/master-data/vehicle-detail.vue'),
|
||||
meta: { title: '车牌号详情' }
|
||||
},
|
||||
{
|
||||
path: '/master-data/vehicle/detail/:id',
|
||||
name: 'VehicleDetailEdit',
|
||||
component: () => import('@/views/master-data/vehicle-detail.vue'),
|
||||
meta: { title: '车牌号详情' }
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -100,8 +100,7 @@ const menuList = computed(() => {
|
||||
return [
|
||||
{ path: '/plans', label: '计划管理', icon: '📋' },
|
||||
{ path: '/inventory', label: '出入库管理', icon: '📦' },
|
||||
{ path: '/weighing', label: '地磅单管理', icon: '⚖️' },
|
||||
{ path: '/master-data', label: '基础资料', icon: '📚' }
|
||||
{ path: '/weighing', label: '地磅单管理', icon: '⚖️' }
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div v-if="isView" class="form-input">
|
||||
{{ formData.partnerCompany || '--' }}
|
||||
</div>
|
||||
<div v-else class="form-input" @click="showCompanyPicker = true">
|
||||
<div v-else class="form-input" @click="showCustomerPicker = true">
|
||||
<span :class="{ placeholder: !formData.partnerCompany }">
|
||||
{{ formData.partnerCompany || '请选择往来单位' }}
|
||||
</span>
|
||||
@@ -49,11 +49,11 @@
|
||||
<div class="form-item">
|
||||
<div class="form-label">产品 <span class="required">*</span></div>
|
||||
<div v-if="isView" class="form-input">
|
||||
{{ formData.product || '--' }}
|
||||
{{ productDisplay || '--' }}
|
||||
</div>
|
||||
<div v-else class="form-input" @click="showCargoPicker = true">
|
||||
<span :class="{ placeholder: !formData.product }">
|
||||
{{ formData.product || '请选择产品' }}
|
||||
<div v-else class="form-input" @click="showProductPicker = true">
|
||||
<span :class="{ placeholder: !productDisplay }">
|
||||
{{ productDisplay || '请选择产品' }}
|
||||
</span>
|
||||
<van-icon name="arrow" class="arrow-icon" />
|
||||
</div>
|
||||
@@ -79,7 +79,7 @@
|
||||
</div>
|
||||
<div v-else class="form-input" @click="showVehiclePicker = true">
|
||||
<span :class="{ placeholder: !formData.vehicleNo }">
|
||||
{{ formData.vehicleNo || '请选择或输入车牌号' }}
|
||||
{{ formData.vehicleNo || '请选择车牌号' }}
|
||||
</span>
|
||||
<van-icon name="arrow" class="arrow-icon" />
|
||||
</div>
|
||||
@@ -125,175 +125,55 @@
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
<!-- 公司选择器 -->
|
||||
<van-popup v-model:show="showCompanyPicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="companySearchKeyword"
|
||||
placeholder="搜索往来单位名称"
|
||||
@search="handleCompanySearch"
|
||||
@clear="handleCompanySearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCompanyOptions"
|
||||
show-toolbar
|
||||
@confirm="onCompanyConfirm"
|
||||
@cancel="showCompanyPicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
<DbCustomerPicker v-model:show="showCustomerPicker" @select="onCustomerSelect" />
|
||||
<DbProductPicker v-model:show="showProductPicker" @select="onProductSelect" />
|
||||
<DbVehiclePicker v-model:show="showVehiclePicker" @select="onVehicleSelect" />
|
||||
|
||||
<!-- 货物选择器 -->
|
||||
<van-popup v-model:show="showCargoPicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="cargoSearchKeyword"
|
||||
placeholder="搜索产品名称"
|
||||
@search="handleCargoSearch"
|
||||
@clear="handleCargoSearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCargoOptions"
|
||||
show-toolbar
|
||||
@confirm="onCargoConfirm"
|
||||
@cancel="showCargoPicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<!-- 日期选择器 -->
|
||||
<van-calendar
|
||||
v-model:show="showDateCalendar"
|
||||
v-model="dateSelected"
|
||||
@confirm="onDateConfirm"
|
||||
/>
|
||||
|
||||
<!-- 车牌号选择器:支持搜索 + 手动输入 -->
|
||||
<van-popup v-model:show="showVehiclePicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="vehicle-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="vehicleSearchKeyword"
|
||||
placeholder="搜索车牌号"
|
||||
@search="handleVehicleSearch"
|
||||
@clear="handleVehicleSearch"
|
||||
@update:model-value="handleVehicleSearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<div class="vehicle-list">
|
||||
<van-cell
|
||||
v-for="item in filteredVehicleOptions"
|
||||
:key="item.vehicleNo"
|
||||
:title="item.vehicleNo"
|
||||
clickable
|
||||
@click="onVehicleSelect(item.vehicleNo)"
|
||||
/>
|
||||
<van-cell v-if="filteredVehicleOptions.length === 0 && !vehicleLoading" title="暂无匹配车牌号,可点击下方手动输入" />
|
||||
</div>
|
||||
<div class="manual-input-row">
|
||||
<van-button block plain type="primary" @click="showManualVehicleInput = true">
|
||||
手动输入新车牌号
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<!-- 手动输入车牌号弹层 -->
|
||||
<van-dialog
|
||||
v-model:show="showManualVehicleInput"
|
||||
title="输入车牌号"
|
||||
show-cancel-button
|
||||
@confirm="onManualVehicleConfirm"
|
||||
>
|
||||
<van-field
|
||||
v-model="manualVehicleNo"
|
||||
placeholder="请输入车牌号"
|
||||
clearable
|
||||
class="dialog-field"
|
||||
/>
|
||||
</van-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { showToast } from 'vant'
|
||||
import { inventoryApi, type InventoryRecord, type InventoryCreate } from '@/api/inventoryApi'
|
||||
import { companyApi, cargoApi, vehicleApi } from '@/api/masterDataApi'
|
||||
import type { CrmCustomerOption, CrmProductOption } from '@/api/crmOptionsApi'
|
||||
import DbCustomerPicker from '@/components/pickers/DbCustomerPicker.vue'
|
||||
import DbProductPicker from '@/components/pickers/DbProductPicker.vue'
|
||||
import DbVehiclePicker from '@/components/pickers/DbVehiclePicker.vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const isView = computed(() => route.query.mode === 'view')
|
||||
const isEdit = computed(() => route.query.mode === 'edit' || route.params.id)
|
||||
// 计划带入新增时计划号锁定,避免误改
|
||||
const isEdit = computed(() => route.query.mode === 'edit' || !!route.params.id)
|
||||
const isPlanNoReadonly = computed(() => !!route.query.planNo && !isEdit.value)
|
||||
// const isAdd = computed(() => !isView.value && !isEdit.value) // 未使用
|
||||
|
||||
const saving = ref(false)
|
||||
const editingRecord = ref<InventoryRecord | null>(null)
|
||||
const showCompanyPicker = ref(false)
|
||||
const showCargoPicker = ref(false)
|
||||
const showCustomerPicker = ref(false)
|
||||
const showProductPicker = ref(false)
|
||||
const showVehiclePicker = ref(false)
|
||||
const showManualVehicleInput = ref(false)
|
||||
const showDateCalendar = ref(false)
|
||||
const dateSelected = ref<Date | null>(null)
|
||||
const companyOptions = ref<{ text: string; value: string }[]>([])
|
||||
const vehicleOptions = ref<{ vehicleNo: string }[]>([])
|
||||
const vehicleSearchKeyword = ref('')
|
||||
const vehicleLoading = ref(false)
|
||||
const manualVehicleNo = ref('')
|
||||
const productDisplay = ref((route.query.product as string) || '')
|
||||
|
||||
// 公司搜索相关
|
||||
const companySearchKeyword = ref('')
|
||||
const allCompanyOptions = ref<{ text: string; value: string }[]>([])
|
||||
const filteredCompanyOptions = computed(() => {
|
||||
if (!companySearchKeyword.value) {
|
||||
return [allCompanyOptions.value]
|
||||
}
|
||||
const filtered = allCompanyOptions.value.filter(item =>
|
||||
item.text.toLowerCase().includes(companySearchKeyword.value.toLowerCase())
|
||||
)
|
||||
return [filtered]
|
||||
})
|
||||
|
||||
// 产品搜索相关
|
||||
const cargoSearchKeyword = ref('')
|
||||
const allCargoOptions = ref<{ text: string; value: string }[]>([])
|
||||
const filteredCargoOptions = computed(() => {
|
||||
if (!cargoSearchKeyword.value) return [allCargoOptions.value]
|
||||
const filtered = allCargoOptions.value.filter(item =>
|
||||
item.text.toLowerCase().includes(cargoSearchKeyword.value.toLowerCase())
|
||||
)
|
||||
return [filtered]
|
||||
})
|
||||
|
||||
const filteredVehicleOptions = computed(() => {
|
||||
if (!vehicleSearchKeyword.value) return vehicleOptions.value
|
||||
const kw = vehicleSearchKeyword.value.toLowerCase()
|
||||
return vehicleOptions.value.filter(item =>
|
||||
item.vehicleNo.toLowerCase().includes(kw)
|
||||
)
|
||||
})
|
||||
|
||||
// 如果是从计划管理跳转过来的(有planNo参数),日期为空;否则使用当前日期
|
||||
const initialDate = route.query.planNo ? '' : dayjs().format('YYYY-MM-DD')
|
||||
const purchasePlanIdFromRoute = route.query.purchasePlanId ? Number(route.query.purchasePlanId) : undefined
|
||||
const purchasePlanIdFromRoute = route.query.purchasePlanId
|
||||
? String(route.query.purchasePlanId)
|
||||
: undefined
|
||||
|
||||
const formData = reactive<InventoryCreate>({
|
||||
date: initialDate,
|
||||
partnerCompany: (route.query.customerName as string) || '',
|
||||
businessType: (route.query.businessType as '入库' | '出库') || '入库',
|
||||
product: (route.query.product as string) || '',
|
||||
productId: (route.query.productId as string) || '',
|
||||
quantity: 32,
|
||||
vehicleNo: '',
|
||||
planNo: (route.query.planNo as string) || '',
|
||||
@@ -301,91 +181,19 @@ const formData = reactive<InventoryCreate>({
|
||||
purchasePlanId: purchasePlanIdFromRoute
|
||||
})
|
||||
|
||||
// 初始化日期选择器的默认值(如果日期为空,使用当前日期作为选择器的默认值)
|
||||
dateSelected.value = route.query.planNo ? null : dayjs().toDate()
|
||||
|
||||
const loadCompanies = async () => {
|
||||
try {
|
||||
const companies = await companyApi.list()
|
||||
allCompanyOptions.value = companies.map(item => ({
|
||||
text: item.name,
|
||||
value: item.name
|
||||
}))
|
||||
companyOptions.value = allCompanyOptions.value
|
||||
} catch (error) {
|
||||
console.error('加载公司列表失败', error)
|
||||
}
|
||||
const onCustomerSelect = (item: CrmCustomerOption) => {
|
||||
formData.partnerCompany = item.customerName
|
||||
}
|
||||
|
||||
const handleCompanySearch = () => {
|
||||
// 触发计算属性更新
|
||||
const onProductSelect = (item: CrmProductOption) => {
|
||||
formData.productId = item.id
|
||||
productDisplay.value = item.productName
|
||||
}
|
||||
|
||||
const loadCargos = async () => {
|
||||
try {
|
||||
const cargos = await cargoApi.list()
|
||||
allCargoOptions.value = cargos.map(item => ({
|
||||
text: item.name,
|
||||
value: item.name
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载货物列表失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCargoSearch = () => {
|
||||
// 触发 computed 过滤
|
||||
}
|
||||
|
||||
const loadVehicles = async () => {
|
||||
vehicleLoading.value = true
|
||||
try {
|
||||
const list = await vehicleApi.list(vehicleSearchKeyword.value || undefined)
|
||||
vehicleOptions.value = list.map(item => ({ vehicleNo: item.vehicleNo }))
|
||||
} catch (error) {
|
||||
console.error('加载车牌号列表失败', error)
|
||||
} finally {
|
||||
vehicleLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleVehicleSearch = () => {
|
||||
loadVehicles()
|
||||
}
|
||||
|
||||
const onVehicleSelect = (vehicleNo: string) => {
|
||||
formData.vehicleNo = vehicleNo
|
||||
showVehiclePicker.value = false
|
||||
}
|
||||
|
||||
const onManualVehicleConfirm = () => {
|
||||
const v = (manualVehicleNo.value || '').trim()
|
||||
if (v) {
|
||||
formData.vehicleNo = v
|
||||
showVehiclePicker.value = false
|
||||
}
|
||||
showManualVehicleInput.value = false
|
||||
manualVehicleNo.value = ''
|
||||
}
|
||||
|
||||
// 保存前确保车牌号已写入车牌号表(新车牌则先创建)
|
||||
const ensureVehicleExists = async (vehicleNo: string) => {
|
||||
if (!vehicleNo?.trim()) return
|
||||
try {
|
||||
await vehicleApi.create({ vehicleNo: vehicleNo.trim(), remarks: null })
|
||||
} catch (err: any) {
|
||||
if (err.response?.status !== 409) throw err
|
||||
}
|
||||
}
|
||||
|
||||
const onCompanyConfirm = ({ selectedOptions }: any) => {
|
||||
formData.partnerCompany = selectedOptions[0].value
|
||||
showCompanyPicker.value = false
|
||||
}
|
||||
|
||||
const onCargoConfirm = ({ selectedOptions }: any) => {
|
||||
formData.product = selectedOptions[0].value
|
||||
showCargoPicker.value = false
|
||||
const onVehicleSelect = (licensePlate: string) => {
|
||||
formData.vehicleNo = licensePlate
|
||||
}
|
||||
|
||||
const onDateConfirm = (value: Date | Date[]) => {
|
||||
@@ -396,22 +204,22 @@ const onDateConfirm = (value: Date | Date[]) => {
|
||||
}
|
||||
|
||||
const loadData = async () => {
|
||||
if (isEdit.value && route.params.id) {
|
||||
if ((isEdit.value || isView.value) && route.params.id) {
|
||||
try {
|
||||
const record = await inventoryApi.get(Number(route.params.id))
|
||||
const record = await inventoryApi.get(String(route.params.id))
|
||||
editingRecord.value = record
|
||||
Object.assign(formData, {
|
||||
date: record.date,
|
||||
partnerCompany: record.partnerCompany,
|
||||
businessType: record.businessType,
|
||||
product: record.product,
|
||||
productId: record.productId || '',
|
||||
quantity: record.quantity,
|
||||
vehicleNo: record.vehicleNo || '',
|
||||
planNo: record.planNo || '',
|
||||
remarks: record.remarks || '',
|
||||
purchasePlanId: record.purchasePlanId
|
||||
})
|
||||
// 初始化日期选择器的值(用于编辑时回显)
|
||||
productDisplay.value = record.product || ''
|
||||
if (record.date) {
|
||||
dateSelected.value = dayjs(record.date).toDate()
|
||||
}
|
||||
@@ -423,16 +231,19 @@ const loadData = async () => {
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formData.date || !formData.partnerCompany || !formData.product || !formData.quantity || !formData.vehicleNo) {
|
||||
showToast({ type: 'fail', message: '请填写必填项' })
|
||||
if (
|
||||
!formData.date ||
|
||||
!formData.partnerCompany ||
|
||||
!formData.productId ||
|
||||
!formData.quantity ||
|
||||
!formData.vehicleNo
|
||||
) {
|
||||
showToast({ type: 'fail', message: '请填写必填项(含产品与车牌)' })
|
||||
return
|
||||
}
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
if (formData.vehicleNo?.trim()) {
|
||||
await ensureVehicleExists(formData.vehicleNo.trim())
|
||||
}
|
||||
if (editingRecord.value) {
|
||||
await inventoryApi.update(editingRecord.value.id, formData)
|
||||
showToast({ type: 'success', message: '更新成功' })
|
||||
@@ -440,7 +251,6 @@ const handleSubmit = async () => {
|
||||
await inventoryApi.create(formData)
|
||||
showToast({ type: 'success', message: '创建成功' })
|
||||
}
|
||||
// 根据来源跳转到对应页面(兼容 from=plan / from=plans)
|
||||
const from = route.query.from as string
|
||||
if (from === 'plan' || from === 'plans') {
|
||||
router.push('/plans')
|
||||
@@ -455,7 +265,6 @@ const handleSubmit = async () => {
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
// 根据来源跳转到对应页面(兼容 from=plan / from=plans)
|
||||
const from = route.query.from as string
|
||||
if (from === 'plan' || from === 'plans') {
|
||||
router.push('/plans')
|
||||
@@ -464,28 +273,7 @@ const handleBack = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 监听公司选择器弹窗,当打开时重置搜索关键词
|
||||
watch(showCompanyPicker, (newVal) => {
|
||||
if (newVal) {
|
||||
companySearchKeyword.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
watch(showCargoPicker, (newVal) => {
|
||||
if (newVal) {
|
||||
cargoSearchKeyword.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
watch(showVehiclePicker, (newVal) => {
|
||||
if (newVal) {
|
||||
vehicleSearchKeyword.value = ''
|
||||
loadVehicles()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadCompanies(), loadCargos()])
|
||||
if (isEdit.value || isView.value) {
|
||||
await loadData()
|
||||
}
|
||||
@@ -495,55 +283,6 @@ onMounted(async () => {
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/styles/detail-page.scss';
|
||||
|
||||
.company-picker-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #ebedf0;
|
||||
background: #fff;
|
||||
|
||||
:deep(.van-search) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.van-search__content) {
|
||||
background: #f7f8fa;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
:deep(.van-field__control) {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 不强制让 van-picker 占满剩余高度,使用 popup 的 max-height 控制总体高度 */
|
||||
|
||||
.vehicle-picker-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 70vh;
|
||||
}
|
||||
|
||||
.vehicle-picker-container .vehicle-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.vehicle-picker-container .manual-input-row {
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid #ebedf0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.dialog-field {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
/* 数量为默认值 32 时红色标识,提醒用户关注 */
|
||||
.quantity-default-red .form-label,
|
||||
.quantity-default-red .form-label .required {
|
||||
color: var(--van-danger-color, #ee0a24);
|
||||
@@ -553,4 +292,3 @@ onMounted(async () => {
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -510,7 +510,7 @@ const canDeleteRecord = (item: InventoryRecord) => {
|
||||
return dateStr >= today
|
||||
}
|
||||
|
||||
const handleDelete = (id: number) => {
|
||||
const handleDelete = (id: string) => {
|
||||
showDialog({
|
||||
title: '确认删除',
|
||||
message: '确定要删除这条记录吗?',
|
||||
@@ -540,13 +540,14 @@ const handleGenerateWeighing = (record: InventoryRecord) => {
|
||||
inboundOutboundId: record.id.toString(),
|
||||
vehicleNo: record.vehicleNo,
|
||||
cargoName: record.product,
|
||||
productId: record.productId || '',
|
||||
businessType: record.businessType,
|
||||
supplier: supplier,
|
||||
consignee: consignee,
|
||||
planNo: record.planNo || '',
|
||||
purchasePlanId: record.purchasePlanId?.toString() || '',
|
||||
batchNo: record.batchNo || '',
|
||||
quantity: record.quantity.toString(), // 传递数量(吨)
|
||||
quantity: record.quantity.toString(),
|
||||
from: 'inventory'
|
||||
}
|
||||
})
|
||||
@@ -555,7 +556,7 @@ const handleGenerateWeighing = (record: InventoryRecord) => {
|
||||
/**
|
||||
* 生成二维码图片地址:内容为出入库单 ID(与 H5 填写页一致)
|
||||
*/
|
||||
const getQrImageUrl = (inventoryId: number) =>
|
||||
const getQrImageUrl = (inventoryId: string) =>
|
||||
`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(String(inventoryId))}`
|
||||
|
||||
/** 打开磅单二维码弹窗,供用户截图保存(不依赖 HTTPS) */
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<div v-if="isView" class="form-input">
|
||||
{{ formData.customerName || '--' }}
|
||||
</div>
|
||||
<div v-else class="form-input" @click="showCompanyPicker = true">
|
||||
<div v-else class="form-input" @click="showCustomerPicker = true">
|
||||
<span :class="{ placeholder: !formData.customerName }">
|
||||
{{ formData.customerName || '请选择往来单位' }}
|
||||
</span>
|
||||
@@ -49,11 +49,11 @@
|
||||
<div class="form-item">
|
||||
<div class="form-label">产品 <span class="required">*</span></div>
|
||||
<div v-if="isView" class="form-input">
|
||||
{{ formData.product || '--' }}
|
||||
{{ productDisplay || '--' }}
|
||||
</div>
|
||||
<div v-else class="form-input" @click="showCargoPicker = true">
|
||||
<span :class="{ placeholder: !formData.product }">
|
||||
{{ formData.product || '请选择产品' }}
|
||||
<div v-else class="form-input" @click="showProductPicker = true">
|
||||
<span :class="{ placeholder: !productDisplay }">
|
||||
{{ productDisplay || '请选择产品' }}
|
||||
</span>
|
||||
<van-icon name="arrow" class="arrow-icon" />
|
||||
</div>
|
||||
@@ -125,56 +125,15 @@
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
<!-- 公司选择器 -->
|
||||
<van-popup v-model:show="showCompanyPicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="companySearchKeyword"
|
||||
placeholder="搜索往来单位名称"
|
||||
@search="handleCompanySearch"
|
||||
@clear="handleCompanySearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCompanyOptions"
|
||||
show-toolbar
|
||||
@confirm="onCompanyConfirm"
|
||||
@cancel="showCompanyPicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
<DbCustomerPicker v-model:show="showCustomerPicker" @select="onCustomerSelect" />
|
||||
<DbProductPicker v-model:show="showProductPicker" @select="onProductSelect" />
|
||||
|
||||
<!-- 货物选择器 -->
|
||||
<van-popup v-model:show="showCargoPicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="cargoSearchKeyword"
|
||||
placeholder="搜索产品名称"
|
||||
@search="handleCargoSearch"
|
||||
@clear="handleCargoSearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCargoOptions"
|
||||
show-toolbar
|
||||
@confirm="onCargoConfirm"
|
||||
@cancel="showCargoPicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<!-- 开始日期选择器 -->
|
||||
<van-calendar
|
||||
v-model:show="showStartDateCalendar"
|
||||
v-model="startDateSelected"
|
||||
@confirm="onStartDateConfirm"
|
||||
/>
|
||||
|
||||
<!-- 结束日期选择器 -->
|
||||
<van-calendar
|
||||
v-model:show="showEndDateCalendar"
|
||||
v-model="endDateSelected"
|
||||
@@ -184,52 +143,30 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { showToast } from 'vant'
|
||||
import { planApi, type Plan, type PlanCreate } from '@/api/plansApi'
|
||||
import { companyApi, cargoApi } from '@/api/masterDataApi'
|
||||
import type { CrmCustomerOption, CrmProductOption } from '@/api/crmOptionsApi'
|
||||
import DbCustomerPicker from '@/components/pickers/DbCustomerPicker.vue'
|
||||
import DbProductPicker from '@/components/pickers/DbProductPicker.vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const isView = computed(() => route.query.mode === 'view')
|
||||
const isEdit = computed(() => route.query.mode === 'edit' || route.params.id)
|
||||
// const isAdd = computed(() => !isView.value && !isEdit.value) // 未使用
|
||||
const isEdit = computed(() => route.query.mode === 'edit' || !!route.params.id)
|
||||
|
||||
const saving = ref(false)
|
||||
const editingPlan = ref<Plan | null>(null)
|
||||
const showCompanyPicker = ref(false)
|
||||
const showCargoPicker = ref(false)
|
||||
const showCustomerPicker = ref(false)
|
||||
const showProductPicker = ref(false)
|
||||
const showStartDateCalendar = ref(false)
|
||||
const showEndDateCalendar = ref(false)
|
||||
const startDateSelected = ref<Date | null>(null)
|
||||
const endDateSelected = ref<Date | null>(null)
|
||||
const companyOptions = ref<{ text: string; value: string }[]>([])
|
||||
const cargoOptions = ref<{ text: string; value: string }[]>([])
|
||||
|
||||
// 搜索相关 - 往来单位
|
||||
const companySearchKeyword = ref('')
|
||||
const allCompanyOptions = ref<{ text: string; value: string }[]>([])
|
||||
const filteredCompanyOptions = computed(() => {
|
||||
if (!companySearchKeyword.value) return [allCompanyOptions.value]
|
||||
const filtered = allCompanyOptions.value.filter(item =>
|
||||
item.text.toLowerCase().includes(companySearchKeyword.value.toLowerCase())
|
||||
)
|
||||
return [filtered]
|
||||
})
|
||||
|
||||
// 搜索相关 - 产品
|
||||
const cargoSearchKeyword = ref('')
|
||||
const allCargoOptions = ref<{ text: string; value: string }[]>([])
|
||||
const filteredCargoOptions = computed(() => {
|
||||
if (!cargoSearchKeyword.value) return [allCargoOptions.value]
|
||||
const filtered = allCargoOptions.value.filter(item =>
|
||||
item.text.toLowerCase().includes(cargoSearchKeyword.value.toLowerCase())
|
||||
)
|
||||
return [filtered]
|
||||
})
|
||||
const productDisplay = ref('')
|
||||
|
||||
const formData = reactive<PlanCreate>({
|
||||
planNo: '',
|
||||
@@ -237,57 +174,21 @@ const formData = reactive<PlanCreate>({
|
||||
startDate: dayjs().format('YYYY-MM-DD'),
|
||||
endDate: '',
|
||||
businessType: '入库',
|
||||
product: '',
|
||||
productId: '',
|
||||
plannedQuantity: 0,
|
||||
customerName: '',
|
||||
remarks: ''
|
||||
})
|
||||
|
||||
// 初始化日期选择器的默认值
|
||||
startDateSelected.value = dayjs().toDate()
|
||||
|
||||
const loadCompanies = async () => {
|
||||
try {
|
||||
const companies = await companyApi.list()
|
||||
allCompanyOptions.value = companies.map(item => ({
|
||||
text: item.name,
|
||||
value: item.name
|
||||
}))
|
||||
companyOptions.value = allCompanyOptions.value
|
||||
} catch (error) {
|
||||
console.error('加载公司列表失败', error)
|
||||
}
|
||||
const onCustomerSelect = (item: CrmCustomerOption) => {
|
||||
formData.customerName = item.customerName
|
||||
}
|
||||
|
||||
const loadCargos = async () => {
|
||||
try {
|
||||
const cargos = await cargoApi.list()
|
||||
allCargoOptions.value = cargos.map(item => ({
|
||||
text: item.name,
|
||||
value: item.name
|
||||
}))
|
||||
cargoOptions.value = allCargoOptions.value
|
||||
} catch (error) {
|
||||
console.error('加载货物列表失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
const onCompanyConfirm = ({ selectedOptions }: any) => {
|
||||
formData.customerName = selectedOptions[0].value
|
||||
showCompanyPicker.value = false
|
||||
}
|
||||
|
||||
const onCargoConfirm = ({ selectedOptions }: any) => {
|
||||
formData.product = selectedOptions[0].value
|
||||
showCargoPicker.value = false
|
||||
}
|
||||
|
||||
const handleCompanySearch = () => {
|
||||
// 触发 computed 过滤
|
||||
}
|
||||
|
||||
const handleCargoSearch = () => {
|
||||
// 触发 computed 过滤
|
||||
const onProductSelect = (item: CrmProductOption) => {
|
||||
formData.productId = item.id
|
||||
productDisplay.value = item.productName
|
||||
}
|
||||
|
||||
const onStartDateConfirm = (value: Date | Date[]) => {
|
||||
@@ -305,9 +206,9 @@ const onEndDateConfirm = (value: Date | Date[]) => {
|
||||
}
|
||||
|
||||
const loadData = async () => {
|
||||
if (isEdit.value && route.params.id) {
|
||||
if ((isEdit.value || isView.value) && route.params.id) {
|
||||
try {
|
||||
const plan = await planApi.get(Number(route.params.id))
|
||||
const plan = await planApi.get(String(route.params.id))
|
||||
editingPlan.value = plan
|
||||
Object.assign(formData, {
|
||||
planNo: plan.planNo || '',
|
||||
@@ -315,12 +216,12 @@ const loadData = async () => {
|
||||
startDate: plan.startDate || '',
|
||||
endDate: plan.endDate || '',
|
||||
businessType: plan.businessType,
|
||||
product: plan.product,
|
||||
productId: plan.productId || '',
|
||||
plannedQuantity: plan.plannedQuantity,
|
||||
customerName: plan.customerName || '',
|
||||
remarks: plan.remarks || ''
|
||||
})
|
||||
// 初始化日期选择器的值
|
||||
productDisplay.value = plan.product || ''
|
||||
if (plan.startDate) {
|
||||
startDateSelected.value = dayjs(plan.startDate).toDate()
|
||||
}
|
||||
@@ -335,8 +236,8 @@ const loadData = async () => {
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formData.product || !formData.plannedQuantity) {
|
||||
showToast({ type: 'fail', message: '请填写必填项' })
|
||||
if (!formData.productId || !formData.plannedQuantity) {
|
||||
showToast({ type: 'fail', message: '请填写必填项(含产品)' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -362,19 +263,10 @@ const handleBack = () => {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadCompanies(), loadCargos()])
|
||||
if (isEdit.value || isView.value) {
|
||||
await loadData()
|
||||
}
|
||||
})
|
||||
|
||||
// 打开弹窗时重置搜索关键词
|
||||
watch(showCompanyPicker, (val) => {
|
||||
if (val) companySearchKeyword.value = ''
|
||||
})
|
||||
watch(showCargoPicker, (val) => {
|
||||
if (val) cargoSearchKeyword.value = ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -469,7 +361,6 @@ watch(showCargoPicker, (val) => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.radio-wrapper {
|
||||
padding: 12px 0;
|
||||
}
|
||||
@@ -481,30 +372,4 @@ watch(showCargoPicker, (val) => {
|
||||
margin-top: 24px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.company-picker-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #ebedf0;
|
||||
background: #fff;
|
||||
|
||||
:deep(.van-search) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.van-search__content) {
|
||||
background: #f7f8fa;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
:deep(.van-field__control) {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -437,7 +437,7 @@ const handleViewRelated = async (record: Plan) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleDelete = (id: number) => {
|
||||
const handleDelete = (id: string) => {
|
||||
showDialog({
|
||||
title: '确认删除',
|
||||
message: '确定要删除这个计划吗?',
|
||||
@@ -455,17 +455,17 @@ const handleDelete = (id: number) => {
|
||||
|
||||
const handleGenerateInventory = (record: Plan) => {
|
||||
router.push({
|
||||
path: '/inventory',
|
||||
path: '/inventory/detail',
|
||||
query: {
|
||||
planNo: record.planNo || '',
|
||||
product: record.product || '',
|
||||
productId: record.productId || '',
|
||||
businessType: record.businessType || '',
|
||||
customerName: record.customerName || '',
|
||||
purchasePlanId: String(record.id),
|
||||
from: 'plan'
|
||||
}
|
||||
})
|
||||
showToast({ type: 'success', message: '已跳转到出入库页面' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -15,21 +15,22 @@
|
||||
<div v-if="isView" class="form-input">
|
||||
{{ formData.vehicleNo || '--' }}
|
||||
</div>
|
||||
<van-field
|
||||
v-else
|
||||
v-model="formData.vehicleNo"
|
||||
placeholder="请输入车牌号"
|
||||
/>
|
||||
<div v-else class="form-input" @click="showVehiclePicker = true">
|
||||
<span :class="{ placeholder: !formData.vehicleNo }">
|
||||
{{ formData.vehicleNo || '请选择车牌号' }}
|
||||
</span>
|
||||
<van-icon name="arrow" class="arrow-icon" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="form-label">货物名称 <span class="required">*</span></div>
|
||||
<div v-if="isView" class="form-input">
|
||||
{{ formData.cargoName || '--' }}
|
||||
{{ cargoDisplay || '--' }}
|
||||
</div>
|
||||
<div v-else class="form-input" @click="showCargoPicker = true">
|
||||
<span :class="{ placeholder: !formData.cargoName }">
|
||||
{{ formData.cargoName || '请选择货物名称' }}
|
||||
<span :class="{ placeholder: !cargoDisplay }">
|
||||
{{ cargoDisplay || '请选择货物名称' }}
|
||||
</span>
|
||||
<van-icon name="arrow" class="arrow-icon" />
|
||||
</div>
|
||||
@@ -188,68 +189,10 @@
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
<!-- 货物选择器 -->
|
||||
<van-popup v-model:show="showCargoPicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="cargoSearchKeyword"
|
||||
placeholder="搜索货物名称"
|
||||
@search="handleCargoSearch"
|
||||
@clear="handleCargoSearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCargoOptions"
|
||||
show-toolbar
|
||||
@confirm="onCargoConfirm"
|
||||
@cancel="showCargoPicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<!-- 供货单位选择器 -->
|
||||
<van-popup v-model:show="showSupplierPicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="companySearchKeyword"
|
||||
placeholder="搜索往来单位名称"
|
||||
@search="handleCompanySearch"
|
||||
@clear="handleCompanySearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCompanyOptions"
|
||||
show-toolbar
|
||||
@confirm="onSupplierConfirm"
|
||||
@cancel="showSupplierPicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<!-- 收货单位选择器 -->
|
||||
<van-popup v-model:show="showConsigneePicker" round position="bottom" :style="{ maxHeight: '70vh' }">
|
||||
<div class="company-picker-container">
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="companySearchKeyword"
|
||||
placeholder="搜索往来单位名称"
|
||||
@search="handleCompanySearch"
|
||||
@clear="handleCompanySearch"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
<van-picker
|
||||
:columns="filteredCompanyOptions"
|
||||
show-toolbar
|
||||
@confirm="onConsigneeConfirm"
|
||||
@cancel="showConsigneePicker = false"
|
||||
/>
|
||||
</div>
|
||||
</van-popup>
|
||||
<DbProductPicker v-model:show="showCargoPicker" @select="onProductSelect" />
|
||||
<DbCustomerPicker v-model:show="showSupplierPicker" @select="onSupplierSelect" />
|
||||
<DbCustomerPicker v-model:show="showConsigneePicker" @select="onConsigneeSelect" />
|
||||
<DbVehiclePicker v-model:show="showVehiclePicker" @select="onVehicleSelect" />
|
||||
|
||||
<!-- 毛重日期选择器 -->
|
||||
<van-calendar
|
||||
@@ -290,50 +233,31 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { showToast } from 'vant'
|
||||
import { weighingApi, type WeighingRecord, type WeighingCreate } from '@/api/weighingApi'
|
||||
import { companyApi, cargoApi } from '@/api/masterDataApi'
|
||||
import type { CrmCustomerOption, CrmProductOption } from '@/api/crmOptionsApi'
|
||||
import { inventoryApi } from '@/api/inventoryApi'
|
||||
import { planApi } from '@/api/plansApi'
|
||||
import DbCustomerPicker from '@/components/pickers/DbCustomerPicker.vue'
|
||||
import DbProductPicker from '@/components/pickers/DbProductPicker.vue'
|
||||
import DbVehiclePicker from '@/components/pickers/DbVehiclePicker.vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const isView = computed(() => route.query.mode === 'view')
|
||||
const isEdit = computed(() => route.query.mode === 'edit' || route.params.id)
|
||||
// const isAdd = computed(() => !isView.value && !isEdit.value) // 未使用
|
||||
const isEdit = computed(() => route.query.mode === 'edit' || !!route.params.id)
|
||||
|
||||
const saving = ref(false)
|
||||
const editingRecord = ref<WeighingRecord | null>(null)
|
||||
const showCargoPicker = ref(false)
|
||||
const showSupplierPicker = ref(false)
|
||||
const showConsigneePicker = ref(false)
|
||||
const companyOptions = ref<{ text: string; value: string }[]>([])
|
||||
const cargoOptions = ref<{ text: string; value: string }[]>([])
|
||||
|
||||
// 搜索相关
|
||||
const companySearchKeyword = ref('')
|
||||
const allCompanyOptions = ref<{ text: string; value: string }[]>([])
|
||||
const filteredCompanyOptions = computed(() => {
|
||||
if (!companySearchKeyword.value) return [allCompanyOptions.value]
|
||||
const filtered = allCompanyOptions.value.filter(item =>
|
||||
item.text.toLowerCase().includes(companySearchKeyword.value.toLowerCase())
|
||||
)
|
||||
return [filtered]
|
||||
})
|
||||
|
||||
const cargoSearchKeyword = ref('')
|
||||
const allCargoOptions = ref<{ text: string; value: string }[]>([])
|
||||
const filteredCargoOptions = computed(() => {
|
||||
if (!cargoSearchKeyword.value) return [allCargoOptions.value]
|
||||
const filtered = allCargoOptions.value.filter(item =>
|
||||
item.text.toLowerCase().includes(cargoSearchKeyword.value.toLowerCase())
|
||||
)
|
||||
return [filtered]
|
||||
})
|
||||
const showVehiclePicker = ref(false)
|
||||
const cargoDisplay = ref('')
|
||||
|
||||
// 毛重时间选择器相关状态
|
||||
const showGrossWeightDateCalendar = ref(false)
|
||||
@@ -368,7 +292,7 @@ const timeColumns = generateTimeColumns()
|
||||
|
||||
const formData = reactive<WeighingCreate>({
|
||||
vehicleNo: '',
|
||||
cargoName: '',
|
||||
productId: '',
|
||||
businessType: '入库',
|
||||
supplier: '',
|
||||
consignee: '',
|
||||
@@ -407,51 +331,46 @@ const initFromRoute = async () => {
|
||||
if (inboundOutboundId) {
|
||||
try {
|
||||
// 获取出入库单数据
|
||||
const inventory = await inventoryApi.get(Number(inboundOutboundId))
|
||||
|
||||
// 填充基础数据(优先使用路由参数,如果没有则使用出入库单数据)
|
||||
const inventory = await inventoryApi.get(String(inboundOutboundId))
|
||||
|
||||
formData.vehicleNo = (route.query.vehicleNo as string) || inventory.vehicleNo
|
||||
formData.cargoName = (route.query.cargoName as string) || inventory.product
|
||||
formData.productId = (route.query.productId as string) || inventory.productId || ''
|
||||
cargoDisplay.value = (route.query.cargoName as string) || inventory.product
|
||||
const businessType = (route.query.businessType as '入库' | '出库') || inventory.businessType
|
||||
formData.businessType = businessType
|
||||
|
||||
// 根据业务类型设置供货单位和收货单位
|
||||
// 入库单:供货单位 = 往来单位,收货单位 = 安庆市山峡化工有限公司
|
||||
// 出库单:供货单位 = 安庆市山峡化工有限公司,收货单位 = 往来单位
|
||||
|
||||
if (route.query.supplier) {
|
||||
formData.supplier = route.query.supplier as string
|
||||
} else {
|
||||
formData.supplier = businessType === '入库' ? inventory.partnerCompany : '安庆市山峡化工有限公司'
|
||||
}
|
||||
|
||||
|
||||
if (route.query.consignee) {
|
||||
formData.consignee = route.query.consignee as string
|
||||
} else {
|
||||
formData.consignee = businessType === '入库' ? '安庆市山峡化工有限公司' : inventory.partnerCompany
|
||||
}
|
||||
|
||||
|
||||
formData.planNo = (route.query.planNo as string) || inventory.planNo || ''
|
||||
// 填充出入库单号(优先使用路由参数,如果没有则使用出入库单数据)
|
||||
formData.batchNo = (route.query.batchNo as string) || inventory.batchNo || ''
|
||||
formData.inboundOutboundId = Number(inboundOutboundId)
|
||||
formData.inboundOutboundId = String(inboundOutboundId)
|
||||
formData.weighingPoint = '山峡化工'
|
||||
|
||||
// 本次量:优先使用路由参数中的quantity(吨),如果没有则使用出入库单的quantity(吨),然后转换为kg
|
||||
|
||||
const quantityInTons = route.query.quantity ? Number(route.query.quantity) : inventory.quantity
|
||||
formData.currentQuantity = quantityInTons * 1000
|
||||
|
||||
// 如果有计划ID,获取计划数据(优先使用路由参数)
|
||||
|
||||
const purchasePlanId = (route.query.purchasePlanId as string) || inventory.purchasePlanId?.toString()
|
||||
if (purchasePlanId) {
|
||||
// 先设置计划ID,确保即使获取计划数据失败也能保存计划ID
|
||||
formData.purchasePlanId = Number(purchasePlanId)
|
||||
formData.purchasePlanId = String(purchasePlanId)
|
||||
try {
|
||||
const plan = await planApi.get(Number(purchasePlanId))
|
||||
// 计划量就是计划的plannedQuantity(单位:吨),需要转换为kg
|
||||
const plan = await planApi.get(String(purchasePlanId))
|
||||
formData.plannedQuantity = plan.plannedQuantity * 1000
|
||||
if (!formData.productId && plan.productId) {
|
||||
formData.productId = plan.productId
|
||||
cargoDisplay.value = cargoDisplay.value || plan.product
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取计划数据失败', error)
|
||||
// 即使获取计划数据失败,计划ID也已经设置了
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -513,53 +432,21 @@ const calculateNetWeight = () => {
|
||||
netWeight.value // 触发计算
|
||||
}
|
||||
|
||||
const loadCompanies = async () => {
|
||||
try {
|
||||
const companies = await companyApi.list()
|
||||
allCompanyOptions.value = companies.map(item => ({
|
||||
text: item.name,
|
||||
value: item.name
|
||||
}))
|
||||
companyOptions.value = allCompanyOptions.value
|
||||
} catch (error) {
|
||||
console.error('加载公司列表失败', error)
|
||||
}
|
||||
const onProductSelect = (item: CrmProductOption) => {
|
||||
formData.productId = item.id
|
||||
cargoDisplay.value = item.productName
|
||||
}
|
||||
|
||||
const loadCargos = async () => {
|
||||
try {
|
||||
const cargos = await cargoApi.list()
|
||||
allCargoOptions.value = cargos.map(item => ({
|
||||
text: item.name,
|
||||
value: item.name
|
||||
}))
|
||||
cargoOptions.value = allCargoOptions.value
|
||||
} catch (error) {
|
||||
console.error('加载货物列表失败', error)
|
||||
}
|
||||
const onSupplierSelect = (item: CrmCustomerOption) => {
|
||||
formData.supplier = item.customerName
|
||||
}
|
||||
|
||||
const onCargoConfirm = ({ selectedOptions }: any) => {
|
||||
formData.cargoName = selectedOptions[0].value
|
||||
showCargoPicker.value = false
|
||||
const onConsigneeSelect = (item: CrmCustomerOption) => {
|
||||
formData.consignee = item.customerName
|
||||
}
|
||||
|
||||
const onSupplierConfirm = ({ selectedOptions }: any) => {
|
||||
formData.supplier = selectedOptions[0].value
|
||||
showSupplierPicker.value = false
|
||||
}
|
||||
|
||||
const onConsigneeConfirm = ({ selectedOptions }: any) => {
|
||||
formData.consignee = selectedOptions[0].value
|
||||
showConsigneePicker.value = false
|
||||
}
|
||||
|
||||
const handleCompanySearch = () => {
|
||||
// 触发 computed 过滤
|
||||
}
|
||||
|
||||
const handleCargoSearch = () => {
|
||||
// 触发 computed 过滤
|
||||
const onVehicleSelect = (licensePlate: string) => {
|
||||
formData.vehicleNo = licensePlate
|
||||
}
|
||||
|
||||
// 拆分日期时间字符串为日期和时间部分
|
||||
@@ -685,11 +572,11 @@ const onTareWeightTimeCancel = () => {
|
||||
const loadData = async () => {
|
||||
if (isEdit.value && route.params.id) {
|
||||
try {
|
||||
const record = await weighingApi.get(Number(route.params.id))
|
||||
const record = await weighingApi.get(String(route.params.id))
|
||||
editingRecord.value = record
|
||||
Object.assign(formData, {
|
||||
vehicleNo: record.vehicleNo,
|
||||
cargoName: record.cargoName,
|
||||
productId: record.productId || '',
|
||||
businessType: record.businessType,
|
||||
supplier: record.supplier,
|
||||
consignee: record.consignee,
|
||||
@@ -709,6 +596,7 @@ const loadData = async () => {
|
||||
executedQuantity: record.executedQuantity,
|
||||
batchNo: record.batchNo || ''
|
||||
})
|
||||
cargoDisplay.value = record.cargoName || ''
|
||||
|
||||
// 拆分并设置日期时间选择器的值(用于编辑时回显)
|
||||
if (record.grossWeightTime) {
|
||||
@@ -735,8 +623,8 @@ const loadData = async () => {
|
||||
const handleSubmit = async () => {
|
||||
// 只验证必填项:车牌号、货物名称、供货单位、收货单位
|
||||
// 毛重和皮重可以分步保存,不强制要求
|
||||
if (!formData.vehicleNo || !formData.cargoName || !formData.supplier || !formData.consignee) {
|
||||
showToast({ type: 'fail', message: '请填写必填项' })
|
||||
if (!formData.vehicleNo || !formData.productId || !formData.supplier || !formData.consignee) {
|
||||
showToast({ type: 'fail', message: '请填写必填项(含产品与车牌)' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -789,25 +677,12 @@ const handleBack = () => {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadCompanies(), loadCargos()])
|
||||
if (isEdit.value || isView.value) {
|
||||
await loadData()
|
||||
} else {
|
||||
// 如果是新增模式,且是从出入库管理跳转过来的,初始化数据
|
||||
await initFromRoute()
|
||||
}
|
||||
})
|
||||
|
||||
// 打开弹窗时重置搜索关键词
|
||||
watch(showCargoPicker, (val) => {
|
||||
if (val) cargoSearchKeyword.value = ''
|
||||
})
|
||||
watch(showSupplierPicker, (val) => {
|
||||
if (val) companySearchKeyword.value = ''
|
||||
})
|
||||
watch(showConsigneePicker, (val) => {
|
||||
if (val) companySearchKeyword.value = ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -822,32 +697,5 @@ watch(showConsigneePicker, (val) => {
|
||||
.text-danger {
|
||||
color: #ee0a24;
|
||||
}
|
||||
|
||||
.company-picker-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #ebedf0;
|
||||
background: #fff;
|
||||
|
||||
:deep(.van-search) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.van-search__content) {
|
||||
background: #f7f8fa;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
:deep(.van-field__control) {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 不强制让 van-picker 占满剩余高度,使用 popup 的 max-height 控制总体高度 */
|
||||
</style>
|
||||
|
||||
@@ -429,7 +429,7 @@ const isWeighingRecordToday = (item: WeighingRecord) => {
|
||||
return dateStr === dayjs().format('YYYY-MM-DD')
|
||||
}
|
||||
|
||||
const handleVoid = (id: number) => {
|
||||
const handleVoid = (id: string) => {
|
||||
showDialog({
|
||||
title: '确认作废',
|
||||
message: '确定要作废这条地磅单吗?',
|
||||
|
||||
Reference in new issue
Block a user