仓储物流 - 仓储发布需求,仓储资源分配,物流列表页面开发

This commit is contained in:
郭永超 2025-07-16 17:08:22 +08:00
parent 7fdf516d0a
commit 415b64bf2b
12 changed files with 746 additions and 541 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 KiB

View File

@ -2,7 +2,7 @@
<div class="ecommerce-left-menu-warp">
<div class="left-menu">
<div>
<img :src="getAssetsFile('images/logo3.png')?.href" style="width: 90%; height: 60px" />
<img :src="getAssetsFile('images/logo3.png')?.href" style="width: 90%" />
</div>
<view
v-for="(n, index) in leftMenu"

View File

@ -2,7 +2,7 @@
<div class="ecommerce-left-menu-warp">
<div class="left-menu">
<div>
<img :src="getAssetsFile('images/logo3.png')?.href" style="width: 90%; height: 60px" />
<img :src="getAssetsFile('images/logo3.png')?.href" style="width: 90%" />
</div>
<view
v-for="(n, index) in leftMenu"

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -3,12 +3,7 @@
<section>
<common>
<template #main>
<el-card shadow="none" style="border-radius: 14px">
<div class="max-w-7xl mx-auto p-4">
<img src="@/assets/images/warehouseLogistics/img19.png" fit="cover" class="storage-image" />
</div>
</el-card>
<!-- <el-card shadow="none" style="border-radius: 14px">
<el-card shadow="never" style="border-radius: 14px">
<div class="tabs tabs0">
<div class="tab cursor">
<div
@ -17,86 +12,72 @@
class="tab_list_li"
style="margin-left: 20px; margin-bottom: 10px"
:class="{ active: currentTab0 === index, tab_list_li0: currentTab0 === index }"
@click.stop="
currentTab0 = index;
currentTab1 = 0;
currentTab2 = 0;
"
>
{{ item }}
</div>
</div>
</div>
<div v-if="currentTab0 === 0" class="tabs">
<div class="tab cursor">
<div
v-for="(item, index) in tab1"
:key="index"
class="tab_list_li"
:class="{ active: currentTab1 === index }"
@click.stop="currentTab1 = index"
>
{{ item }}
</div>
<div style="display: flex">
<div style="flex: 1">
<el-form inline style="margin-left: -50px; margin-top: 10px">
<el-form-item>
<el-cascader
v-model="state.query.selectedAddress"
:options="addressOptions"
:props="cascaderProps"
placeholder="请选择省市区"
:size="formSize"
style="width: 300px"
/>
</el-form-item>
<el-form-item>
<el-input v-model="state.query.detailAddress" :size="formSize" placeholder="详细位置(如街道、门牌号等)" style="width: 300px" />
</el-form-item>
</el-form>
</div>
<div style="width: 150px; margin-top: 10px; text-align: right">
<el-button type="primary" size="large" style="width: 100px">查询</el-button>
</div>
</div>
<div v-if="currentTab0 === 1" class="tabs">
<div class="tab cursor">
<div
v-for="(item, index) in tab2"
:key="index"
class="tab_list_li"
:class="{ active: currentTab2 === index }"
@click.stop="currentTab2 = index"
>
{{ item }}
</el-card>
<div v-if="state.data == 0" class="warehouse-content-box no-data">暂无数据</div>
<div v-else style="padding-bottom: 20px">
<div v-for="(item, index) in state.data" :key="index" class="warehouse-content-box">
<div class="warehouse-content-box-left">
<img :src="item.imageUrl" fit="cover" draggable="false" />
</div>
<div class="warehouse-content-box-center">
<p class="center-title">
{{ item.title }}
</p>
<div class="center-text">
<div class="center-text-lable">车牌</div>
<div class="flex-1">{{ item.licensePlate }}</div>
<div class="center-text-lable">车长</div>
<div class="flex-1">{{ item.conductor }}</div>
</div>
<div class="center-text">
<div class="center-text-lable">车辆性质</div>
<div class="flex-1">{{ item.vehicleNature }}</div>
<div class="center-text-lable">车型</div>
<div class="flex-1">{{ item.vehicleModel }}</div>
</div>
<div class="center-text">
<div class="center-text-lable">最大载重</div>
<div class="flex-1">{{ item.maximumPayload }}</div>
<div class="center-text-lable">空闲时间</div>
<div class="flex-1">{{ item.freeTime }}</div>
</div>
</div>
</div>
<div v-if="currentTab0 === 1" class="tabs">
<div class="tab cursor">
<div
v-for="(item, index) in tab3"
:key="index"
class="tab_list_li"
:class="{ active: currentTab1 === index }"
@click.stop="currentTab1 = index"
>
{{ item }}
</div>
<div class="warehouse-content-box-right">
<p class="top-text">{{ item.price }}</p>
<el-button size="large" type="primary" class="right-button" @click="toLink(item)">预约</el-button>
</div>
</div>
</el-card> -->
<el-row :gutter="20" style="margin-top: 10px">
<el-col v-if="currentTab0 === 0" :span="24" style="margin-bottom: 100px !important">
<el-card class="storage-card" shadow="hover" body-style="padding: 0">
<div class="storage-content">
<div class="storage-content-top">
<img src="@/assets/images/warehouseLogistics/img11.png" fit="cover" class="storage-image storage-image1" @click="toLink" />
</div>
</div>
</el-card>
<el-card class="storage-card" shadow="hover" body-style="padding: 0">
<div class="storage-content">
<div class="storage-content-top">
<img src="@/assets/images/warehouseLogistics/img12.png" fit="cover" class="storage-image storage-image1" @click="toLink" />
</div>
</div>
</el-card>
</el-col>
<el-col v-else :span="24">
<el-card class="storage-card" shadow="hover" body-style="padding: 0">
<div class="storage-content">
<div class="storage-content-top">
<img src="@/assets/images/warehouseLogistics/img13.png" fit="cover" class="storage-image storage-image1" />
</div>
</div>
</el-card>
</el-col>
<div style="position: fixed; left: 50%; bottom: 7%">
<el-button style="padding: 10px 50px" size="large" type="primary" @click="shippingGoods">在线寄货</el-button>
</div>
<!-- <el-pagination
</div>
<!-- <el-pagination
:size="'large'"
:page-size="paginations.size"
:current-page="paginations.page"
@ -105,7 +86,6 @@
layout="prev, pager, next"
@current-change="currentChange"
/> -->
</el-row>
</template>
</common>
</section>
@ -120,74 +100,48 @@ import Common from '../components/common.vue';
import { useGetCommonData } from '@/store/modules/common.js';
import { storeToRefs } from 'pinia';
import { ElMessage } from 'element-plus';
import { getRegion } from '@/apis/common';
const store = useGetCommonData();
const { data } = storeToRefs(store);
const route = useRoute();
const router = useRouter();
const tab0 = reactive(['物流服务', '物流需求']);
const tab1 = reactive(['全部', '物流公司', '个人']);
const tab2 = reactive(['全部', '11米7', '13米', '13米7', '15米']);
const tab3 = reactive(['全部', '厢式', '平板', '高栏', '飞翼', '开顶']);
const tab0 = reactive(['选择位置']);
const currentTab0 = ref(0);
const currentTab1 = ref(0);
const currentTab2 = ref(0);
const currentTab3 = ref(0);
const formSize = 'large';
import img1 from './images/xiangshi.png';
import img2 from './images/gaolan.png';
const state = reactive({
menus: warehouseLogisticsRoutes[0].children,
query: {
current: {},
selectedAddress: [],
detailAddress: '',
},
data: [
{
imageUrl: '/storage1.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
location: '临沧市-耿马县',
price: '600.0',
rank: '1',
imageUrl: img1,
title: '长途大车',
licensePlate: '云AL6AB7',
conductor: '15m',
vehicleNature: '物流公司',
vehicleModel: '厢式',
maximumPayload: '1000吨',
freeTime: '2025.05.05',
price: '¥20元/吨/公里',
},
{
imageUrl: '/storage2.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心',
location: '临沧市-耿马县',
price: '600.0',
rank: '2',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
location: '临沧市-耿马县',
price: '600.0',
rank: '3',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
location: '临沧市-耿马县',
price: '600.0',
rank: '',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
location: '临沧市-耿马县',
price: '600.0',
rank: '',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
location: '临沧市-耿马县',
price: '600.0',
rank: '',
imageUrl: img2,
title: '长途大车',
licensePlate: '云AL5B15',
conductor: '13m',
vehicleNature: '个人',
vehicleModel: '高栏',
maximumPayload: '800吨',
freeTime: '2025.05.08',
price: '¥20元/吨/公里',
},
],
});
@ -200,13 +154,7 @@ const paginations = reactive({
const dialogFormVisible = ref(false);
const formLabelWidth = ref('120px');
onMounted(() => {
getWarehouseList('1');
});
const currentTab = ref(0);
const currentChange = (current) => {
paginations.page = current;
getWarehouseList(currentTab.value + 1);
@ -279,6 +227,30 @@ const priceConfirm = () => {
}
});
};
//
const cascaderProps = ref({
label: 'areaName', //
value: 'areaCode', //
children: 'areaChildVOS', //
emitPath: true,
expandTrigger: 'hover',
});
//
const addressOptions = ref([]);
const getArea = async () => {
const res = await getRegion();
if (res.code === 200) {
addressOptions.value = res.data;
} else {
ElMessage.error(res.message);
}
};
onMounted(() => {
// getWarehouseList('1');
getArea();
});
</script>
<style lang="scss" scoped>
.el-form-item--large {
@ -318,6 +290,7 @@ const priceConfirm = () => {
color: #000000;
font-size: 20px;
font-weight: 400;
transition: color 0.3s ease;
}
.tab_list_li:first-child {
margin-left: 20px;
@ -326,7 +299,19 @@ const priceConfirm = () => {
color: rgba(37, 191, 130, 1);
}
.tab_list_li0 {
border-bottom: 2px solid rgba(37, 191, 130, 1);
position: relative;
transition: color 0.3s ease;
}
.tab_list_li0::after {
content: '';
position: absolute;
left: 25%;
bottom: 0;
width: 50%;
height: 4px;
background: rgba(37, 191, 130, 1);
border-radius: 4px;
transition: all 0.3s ease;
}
}
.cursor {
@ -335,115 +320,83 @@ const priceConfirm = () => {
.active {
color: rgba(37, 191, 130, 1);
}
.storage-card {
.warehouse-content-box {
min-height: 150px;
margin-top: 20px;
padding: 20px;
border-radius: 14px;
background-color: #fff;
display: flex;
gap: 20px;
}
.no-data {
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 14px;
}
.warehouse-content-box-left {
height: 120px;
width: 120px;
border-radius: 14px;
position: relative;
overflow: hidden;
margin-bottom: 20px;
border: 0;
border-radius: 24px;
}
.storage-content {
@include flex-column;
gap: 16px;
&-top {
@include flex-row;
align-items: center;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-width: 100%;
min-height: 100%;
object-fit: cover;
}
}
.storage-price-left {
text-align: left;
}
.storage-image1 {
margin-right: 0;
width: 100%;
height: auto;
border-radius: 0;
object-fit: cover;
cursor: pointer;
}
.storage-info {
padding-right: 50px;
.warehouse-content-box-center {
flex: 1;
cursor: pointer;
text-align: left;
.center-title {
font-size: 22px;
font-weight: bold;
text-align: left;
margin-bottom: 10px;
}
.center-text {
font-size: 14px;
display: flex;
margin-bottom: 10px;
.center-text-lable {
color: #666;
width: 70px;
}
.flex-1 {
flex: 1;
}
.center-text-cont {
width: 120px;
}
}
.center-location {
font-size: 14px;
line-height: 20px;
.el-icon {
vertical-align: bottom;
}
}
}
.storage-title,
.storage-desc,
.storage-tags,
.storage-location {
overflow: hidden;
margin: 10px 0;
width: 100%;
}
.storage-title {
.warehouse-content-box-right {
width: 160px;
font-size: 20px;
font-weight: 700;
color: #000000;
@include ellipsis;
}
.storage-desc {
font-size: 16px;
color: #999999;
@include ellipsis;
i {
display: inline-block;
width: 20px;
height: 20px;
}
}
.storage-tags {
span {
margin-right: 10px;
}
}
.storage-location {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
color: #000000;
}
.storage-price {
display: flex;
align-items: center;
&-left {
flex: 1;
flex-direction: column;
align-items: flex-end;
justify-content: space-between;
.top-text {
font-size: 22px;
color: #25bf82;
font-weight: bold;
}
}
.price-label {
margin-right: 10px;
font-size: 16px;
color: #999999;
}
.price-amount {
font-size: 20px;
font-weight: 700;
color: #25bf82;
}
.contact-btn {
width: 152px;
height: 48px;
font-size: 20px;
border-radius: 8px;
background: #25bf82 !important;
:deep(.el-icon) {
margin-right: 10px;
}
}
.rank-badge {
position: absolute;
top: 0;
right: 20px;
width: 80px;
height: 80px;
}
.max-w-7xl {
max-width: 80rem;
background-color: #fff;
border-radius: 10px;
.storage-image {
.right-button {
width: 100%;
}
}

View File

@ -2,74 +2,86 @@
<section>
<common>
<template #main>
<el-card shadow="none" style="border-radius: 14px">
<el-card shadow="never" style="border-radius: 14px">
<div class="title">
<span @click="toBack(-2)">仓储</span>
<span class="mx-10"> > </span>
<span @click="toBack(-1)">申请仓储</span>
<span @click="toBack(-1)">发布需求</span>
<span class="mx-10"> > </span>
<span style="color: rgba(37, 191, 130, 1)">资源分配</span>
</div>
<div class="max-w-7xl mx-auto p-4">
<img src="@/assets/images/warehouseLogistics/img15.png" fit="cover" class="storage-image" />
<!-- <div class="flex items-center mb-8">
<div class="flex items-center mr-4">
<img :src="state.data.imgPath" fit="cover" class="rounded-lg shadow image-box" />
</div>
<div class="flex-1">
<h3 class="text-xl font-bold mb-2">{{ state.data.name }}</h3>
<div class="text-gray-600 mb-2">
<span>{{ state.data.parentTitle }}</span>
<img :src="getAssetsFile('images/warehouseLogistics/认证.png')" alt="" style="width: 20px; margin: 0 5px" />
<img :src="getAssetsFile('images/warehouseLogistics/优先级.png')" alt="" style="width: 20px" />
</div>
<div class="storage-tags">
<el-tag
v-for="(tags, indexT) in state.data.tag"
:key="indexT"
effect="plain"
round
style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82"
>
{{ tags }}
</el-tag>
</div>
<p class="mt-2 text-gray-700">联系人{{ state.data.contactName }}</p>
<p class="mt-2 text-gray-700">联系电话{{ state.data.contactPhone }}</p>
<p class="mt-2 text-gray-700">
<el-icon><Location /></el-icon> {{ state.data.address }}
</p>
</div>
<div class="text-gray-500 text-sm flex items-center" style="text-align: right">
<div>
<span style="color: #999999">报价</span>
<span class="ml-2 text-green-500 font-bold">
¥{{ state.data.price }}/{{
state.data.priceSpec === 1 ? 'm³' : state.data.priceSpec === 2 ? '间' : state.data.priceSpec === 3 ? '㎡' : ''
}}/{{ state.data.timeSpec === 1 ? '天' : state.data.timeSpec === 2 ? '月' : state.data.timeSpec === 3 ? '年' : '' }}
</span>
</div>
<div>
<el-button size="large" type="primary" @click="goDei">
<el-icon class="el-icon--right"><ChatLineRound /></el-icon>
留下信息
</el-button>
</div>
<div class="content-custom-title" style="margin-top: 20px">耿马县农业公司</div>
<div style="display: flex">
<div style="width: 60%">
<el-descriptions class="mb-20" :column="2">
<el-descriptions-item label="预约使用时间">2025.05.20</el-descriptions-item>
<el-descriptions-item label="位置">临沧市-耿马县</el-descriptions-item>
<el-descriptions-item label="货物类型">水果</el-descriptions-item>
<el-descriptions-item label="仓库用途">存储</el-descriptions-item>
<el-descriptions-item label="仓库类型">冷库</el-descriptions-item>
</el-descriptions>
</div>
<div style="flex: 1; text-align: right">
<el-button type="primary" size="large" style="width: 100px; margin-top: 20px">重新匹配</el-button>
</div>
</div>
</el-card>
<div class="storage-content">
<div class="content-custom-title">平台匹配仓储资源</div>
<div class="tabs">
<div class="tab cursor">
<div
v-for="(item, index) in tab1"
:key="index"
class="tab_list_li"
:class="{ active: currentTab1 === index }"
@click="handleTab1Click(item, index)"
>
{{ item }}
</div>
</div>
<div class="mt-6">
<h3 class="text-lg font-bold mb-4" style="margin-top: 30px">产品详细介绍</h3>
<div class="bg-white p-4 rounded-lg shadow-sm">
<p style="text-align: left" class="mb-4 text-gray-700" v-html="state.data.content ? state.data.content : '暂无介绍内容'"></p>
</div>
<el-row :gutter="20">
<el-col v-for="(item, index) in allData" :key="index" :span="8">
<div class="resource-item">
<div class="resource-item-img">
<img :src="item.imageUrl" fit="cover" draggable="false" class="storage-image" />
</div>
<p class="center-title">
<span class="highlight">{{ item.typeName }}</span>{{ item.title }}
</p>
<div>
<div class="resource-custom-tag">符合温湿度</div>
<div class="resource-custom-tag">24小时运营</div>
</div>
<div class="center-text">
<div class="center-text-lable">运营单位</div>
<div class="flex-1" :title="item.operationUnit">{{ item.operationUnit }}</div>
</div>
<div class="center-text">
<div class="center-text-lable">仓库位置</div>
<div class="flex-1" :title="item.location">{{ item.location }}</div>
</div>
<div class="center-text">
<div class="center-text-lable">仓库面积</div>
<div class="flex-1" :title="item.storageArea + '(可用' + item.usableArea + ')'">
{{ item.storageArea }}可用{{ item.usableArea }}
</div>
</div>
<div class="center-text" style="margin: 10px 0">
<div class="center-text-lable" style="color: 000; font-weight: bold">参考价格</div>
<div class="flex-1" style="font-size: 20px; color: #25bf82; font-weight: bold">{{ item.price }}</div>
</div>
<div style="display: flex">
<el-button type="primary" size="large" style="flex: 1; margin-top: 10px">立即预约</el-button>
<el-button size="large" plain style="flex: 1; margin-top: 10px">查看详情</el-button>
</div>
</div>
</div> -->
</div>
</el-card>
<el-card shadow="none" style="border-radius: 14px; margin-top: 20px">
<div class="max-w-7xl mx-auto p-4" style="padding: 0">
<img src="@/assets/images/warehouseLogistics/img16.png" fit="cover" class="storage-image" />
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
</common>
</section>
@ -84,28 +96,105 @@ import { warehouseDetail } from '@/apis/warehouseLogistics.js';
const route = useRoute();
const router = useRouter();
const state = reactive({
query: {},
data: {},
});
const tab1 = reactive(['全部', '距离最近仓储', '价格最便宜仓储']);
const currentTab1 = ref(0);
const handleTab1Click = (item, index) => {
currentTab1.value = index;
};
import img1 from './../images/普通仓储/1.jpg';
import img2 from './../images/普通仓储/2.jpg';
import img3 from './../images/恒温仓储/1.jpg';
import img4 from './../images/冷库/4.jpg';
import img5 from './../images/气调仓储/1.jpg';
const allData = ref([
{
imageUrl: img1,
typeId: 1,
typeName: '普通仓储',
title: '孟定边贸仓储中心',
operationUnit: '耿马宏泰物流有限公司,耿马宏泰物流有限公司 ',
pricingUnit: '元/㎡·月',
storageArea: '8,600㎡',
usableArea: '2,300㎡',
location: '孟定镇中缅大道8号',
price: '¥12元/㎡/月',
rank: '1',
},
{
imageUrl: img2,
typeId: 2,
typeName: '普通仓储',
title: '绿色食品园区集散仓',
operationUnit: '耿马县供销集团',
pricingUnit: '元/吨·天',
storageArea: '12,000㎡',
usableArea: '4,500㎡',
location: '绿色食品园区二期',
price: '¥1.5元/吨/月',
rank: '2',
},
{
imageUrl: img3,
typeId: 3,
typeName: '恒温仓储',
title: '蔗糖储备恒温库',
operationUnit: '耿马糖业有限公司',
pricingUnit: '元/托·月',
storageArea: '3,200㎡',
usableArea: '800㎡',
location: '耿马糖厂东侧',
price: '¥28元/托/月',
rank: '3',
},
{
imageUrl: img4,
typeId: 4,
typeName: '冷库',
title: '孟定果蔬冷链中心',
operationUnit: '临沧边境合作区管委会 ',
pricingUnit: '元/板·天',
storageArea: '5,000㎡',
usableArea: '1,200㎡',
location: '孟定海关监管区旁',
price: '¥2.8元/板/月',
rank: '4',
},
{
imageUrl: img5,
typeId: 5,
typeName: '气调仓储',
title: '高原蔬菜气调保鲜库',
operationUnit: '耿马高原农业合作社 ',
pricingUnit: '元/吨·月',
storageArea: '1,800㎡',
usableArea: '300㎡',
location: '勐撒镇蔬菜基地',
price: '¥45元/吨/月',
rank: '5',
},
]);
const toBack = (level) => {
router.go(level);
};
const param = ref({
id: '100',
});
const queryDetail = () => {
warehouseDetail(state.query.id).then((res) => {
warehouseDetail(param).then((res) => {
if (res.code === 200) {
state.data = res.data;
for (let i in state.data) {
state.data[i].tag = state.data[i].tags.split(',');
allData.value = res.data;
for (let i in allData.value) {
allData.value[i].tag = allData.value[i].tags.split(',');
}
}
});
};
onMounted(() => {
state.query.id = route.query.id;
param.value.id = route.query.id ?? '100';
// queryDetail();
});
</script>
@ -116,238 +205,134 @@ onMounted(() => {
font-weight: bold;
cursor: pointer;
}
/* 根据需要添加样式,这里仅提供基础样式 */
//
$primary-color: #25bf82; //
$text-dark: #25bf82; //
$text-regular: #606266; //
$border-color: #dcdfe6; //
//
:deep(.custom-inquiry-dialog) {
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
.el-dialog__header {
padding: 20px;
border-bottom: 1px solid #f2f6fc;
.el-dialog__title {
font-size: 18px;
color: $text-dark;
font-weight: 600;
}
}
.el-dialog__body {
padding: 20px 28px;
}
.el-form-item__label {
color: $text-regular;
font-size: 14px;
padding-bottom: 6px;
}
}
.info-section {
padding: 0px 50px;
margin-bottom: 24px;
.info-item {
margin-bottom: 12px;
.label {
color: $text-regular;
margin-right: 8px;
font-size: 20px;
}
.value {
color: $text-dark;
font-weight: 500;
font-size: 20px;
}
}
}
//
:deep(.el-input) {
.el-input__inner {
height: 40px;
line-height: 40px;
border-radius: 4px;
&:focus {
border-color: $primary-color;
}
}
.el-input__suffix {
color: $text-regular;
right: 12px;
}
}
//
:deep(.custom-select-dropdown) {
.el-select-dropdown__item {
color: $text-regular;
&.selected {
color: $primary-color;
}
}
}
//
.dialog-footer {
text-align: right;
.el-button {
padding: 10px 24px;
border-radius: 4px;
font-size: 14px;
}
.cancel-btn {
color: $text-regular;
&:hover {
color: $primary-color;
border-color: $primary-color;
}
}
.submit-btn {
color: #fff;
background: $primary-color;
&:hover {
background: mix($primary-color, #fff, 85%);
}
}
}
.bac {
background: rgba(37, 191, 130, 0.1);
border: 1px solid rgba(37, 191, 130, 0.5);
border-radius: 8px;
padding: 2px 5px;
}
.image-box {
width: 300px;
height: 300px;
}
.text-gray-500 {
height: 300px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: start !important;
font-size: 20px !important;
color: #000000 !important;
padding-top: 30px;
}
.text-gray-600 {
font-size: 20px;
color: #000000 !important;
}
.flex-1 {
width: 40%;
height: 300px;
flex-direction: column;
display: flex;
align-items: flex-start;
justify-content: space-evenly;
}
.max-w-7xl {
max-width: 80rem;
.storage-content {
padding: 20px 20px 0 20px;
margin-top: 20px;
border-radius: 14px;
background-color: #fff;
border-radius: 10px;
.storage-image {
width: 100%;
}
.content-custom-title {
font-size: 20px;
font-weight: bold;
text-align: left;
margin-bottom: 10px;
}
.tabs {
//height: 160px;
line-height: 50px;
display: flex;
flex-direction: column;
font-size: 18px;
align-items: flex-start;
justify-content: space-between;
// padding: 0 20px;
}
.tabs0 {
padding: 0;
}
.tab {
// height: 100px;
width: 850px;
display: flex;
align-items: center;
justify-content: flex-start;
overflow-x: auto;
overflow: auto; /* 启用滚动 */
white-space: nowrap; /* 强制单行显示 */
-ms-overflow-style: none; /* IE/Edge 兼容 */
scrollbar-width: none; /* 隐藏滚动条 */
.tab_list {
color: #999999;
font-size: 20px;
font-weight: 400;
}
.tab_list_li {
margin-left: 40px;
color: #666;
font-size: 18px;
font-weight: 400;
transition: color 0.3s ease;
}
.tab_list_li:first-child {
margin-left: 0px;
}
.tab_list_li.active {
color: #25bf82;
font-weight: bold;
}
}
.mx-auto {
margin-left: auto;
margin-right: auto;
.cursor {
cursor: pointer;
}
.p-4 {
padding: 1rem;
padding-bottom: 0;
}
.flex {
display: flex;
}
.items-center {
align-items: center;
}
.mb-4 {
margin-bottom: 1rem;
}
.mr-4 {
margin-right: 1rem;
}
.text-green-500 {
.active {
color: #25bf82;
font-weight: bold;
}
.text-lg {
font-size: 1.125rem;
.resource-item {
width: 100%;
min-height: 300px;
display: flex;
flex-direction: column;
margin-bottom: 20px;
text-align: left;
}
.font-bold {
font-weight: 700;
}
.rounded-lg {
border-radius: 0.5rem;
background-color: #f5f5f5;
}
.shadow {
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.text-xl {
font-size: 24px;
}
.text-gray-600 {
color: #757575;
}
.text-gray-700 {
color: #000000;
font-size: 18px;
}
.text-sm {
font-size: 0.875rem;
}
.space-x-2 {
gap: 0.5rem;
}
.bg-green-500 {
background-color: #4caf50;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.mt-4 {
margin-top: 1rem;
.resource-item-img {
width: 100%;
height: 250px;
border-radius: 14px;
position: relative;
overflow: hidden;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-width: 100%;
min-height: 100%;
object-fit: cover;
}
}
.center-title {
color: #666;
font-size: 18px;
font-weight: bold;
text-align: left;
margin-bottom: 10px;
.highlight {
color: #25bf82;
}
}
.resource-custom-tag {
display: inline-block;
margin-right: 10px;
margin-bottom: 10px;
padding: 4px 6px;
background: rgba(37, 191, 130, 0.1);
border: 1px solid rgba(37, 191, 130, 0.5);
border-radius: 8px;
font-size: 16px;
font-weight: bold;
color: #25bf82;
}
.center-text {
font-size: 16px;
display: flex;
margin-bottom: 10px;
.center-text-lable {
color: #666;
width: 86px;
line-height: 20px;
}
.flex-1 {
flex: 1;
line-height: 20px;
text-align: left;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
</style>

View File

@ -120,6 +120,119 @@
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
<div class="dialog-custom-title">分拣包装需要</div>
<el-form-item label="分拣包装服务" prop="sortingService" :label-width="'110'">
<el-radio-group v-model="formInline.sortingService">
<el-radio :value="1">需要</el-radio>
<el-radio :value="2">不需要</el-radio>
</el-radio-group>
</el-form-item>
<div v-show="formInline.sortingService === 1">
<el-form-item label="分拣类型" prop="sortingType">
<el-select v-model="formInline.sortingType" placeholder="请选择" :size="formSize" :style="{ width: unifiedWidth }">
<el-option v-for="item in sortingTypeList" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
<el-form-item label="分拣标准" prop="sortingStandards">
<el-select v-model="formInline.sortingStandards" placeholder="请选择" :size="formSize" :style="{ width: unifiedWidth }">
<el-option v-for="item in sortingStandardList" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
<el-form-item label="包装类型" prop="packagingType">
<el-select v-model="formInline.packagingType" placeholder="请选择" :size="formSize" :style="{ width: unifiedWidth }">
<el-option v-for="item in packagingTypesList" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
<el-form-item label="包装规格" prop="packagingSpecifications">
<el-input
v-model="formInline.packagingSpecifications"
:size="formSize"
clearable
placeholder="请输入包装规格"
:style="{ width: unifiedWidth }"
>
<template #append>Kg/</template>
</el-input>
</el-form-item>
<el-form-item label="日分拣包装量" prop="dailySortingVolume" :label-width="'110'">
<el-input
v-model="formInline.dailySortingVolume"
:size="formSize"
clearable
placeholder="请输入日分拣包装量"
:style="{ width: '270px' }"
>
<template #append>/</template>
</el-input>
</el-form-item>
<el-form-item label="其他需求" prop="otherRequirements">
<el-input
v-model="formInline.otherRequirements"
:size="formSize"
clearable
placeholder="请输入其他需求"
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
</div>
<div class="dialog-custom-title">附加服务</div>
<el-form-item label="服务项目">
<el-checkbox-group v-model="formInline.additionalServicesList">
<el-checkbox label="预冷处理" :value="1" />
<el-checkbox label="质量检测" :value="2" />
<el-checkbox label="贴标服务" :value="3" />
<el-checkbox label="条形码生成" :value="4" />
</el-checkbox-group>
</el-form-item>
<el-form-item label="其他服务" prop="otherServices">
<el-input
v-model="formInline.otherServices"
:size="formSize"
clearable
placeholder="请输入其他服务"
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
<div class="dialog-custom-title">企业信息</div>
<el-form-item label="企业名称" prop="enterpriseName">
<el-input
v-model="formInline.enterpriseName"
:size="formSize"
clearable
placeholder="请输入企业名称"
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
<el-form-item label="联系人" prop="contacts">
<el-input
v-model="formInline.contacts"
:size="formSize"
clearable
placeholder="请输入联系人"
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
<el-form-item label="联系电话" prop="contactNumber">
<el-input
v-model="formInline.contactNumber"
:size="formSize"
clearable
placeholder="请输入联系电话"
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
<el-form-item label="电子邮箱" prop="email">
<el-input
v-model="formInline.email"
:size="formSize"
clearable
placeholder="请输入电子邮箱"
:style="{ width: unifiedWidth }"
></el-input>
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button type="primary" size="large" style="width: 200px; margin-top: 20px" @click="application"> 提交 </el-button>
@ -146,7 +259,6 @@ const state = reactive({
data: {},
});
const dialogVisible = ref(false);
const unifiedWidth = '300px';
const formSize = 'large';
const formRef = ref(null);
@ -164,6 +276,22 @@ const formInline = reactive({
goodsWeight: '', //
temperature: '', //
detailedDescription: '', //
sortingService: 2, //
sortingType: '', //
sortingStandards: '', //
packagingType: '', //
packagingSpecifications: '', //
dailySortingVolume: '', //
otherRequirements: '', //
additionalServicesList: [], //
otherServices: '', //
enterpriseName: '', //
contacts: '', //
contactNumber: '', //
email: '', //
});
const resetForm = ref({ ...formInline });
const dialogRules = reactive({
@ -251,6 +379,117 @@ const dialogRules = reactive({
{ pattern: /^\d+(\.\d{1,2})?$/, message: '请输入有效数字(最多两位小数)', trigger: 'blur' },
],
detailedDescription: [{ required: true, message: '请输入详情描述', trigger: 'blur' }],
sortingType: [
{
required: true,
validator: (rule, value, callback) => {
if (formInline.sortingService === 1 && !value) {
callback(new Error('请选择分拣类型'));
} else {
callback();
}
},
trigger: 'change',
},
],
sortingStandards: [
{
required: true,
validator: (rule, value, callback) => {
if (formInline.sortingService === 1 && !value) {
callback(new Error('请选择分拣标准'));
} else {
callback();
}
},
trigger: 'change',
},
],
packagingType: [
{
required: true,
validator: (rule, value, callback) => {
if (formInline.sortingService === 1 && !value) {
callback(new Error('请选择包装类型'));
} else {
callback();
}
},
trigger: 'change',
},
],
packagingSpecifications: [
{
required: true,
validator: (rule, value, callback) => {
if (formInline.sortingService === 1 && !value) {
callback(new Error('请输入包装规格'));
} else if (formInline.sortingService === 1 && !/^\d+(\.\d{1,2})?$/.test(value)) {
callback(new Error('请输入有效数字(最多两位小数)'));
} else {
callback();
}
},
trigger: 'blur',
},
],
dailySortingVolume: [
{
required: true,
validator: (rule, value, callback) => {
if (formInline.sortingService === 1 && !value) {
callback(new Error('请输入日分拣量'));
} else if (formInline.sortingService === 1 && !/^\d+(\.\d{1,2})?$/.test(value)) {
callback(new Error('请输入有效数字(最多两位小数)'));
} else {
callback();
}
},
trigger: 'blur',
},
],
//
otherRequirements: [
{
required: true,
validator: (rule, value, callback) => {
if (formInline.sortingService === 1 && !value) {
callback(new Error('请输入其他需求'));
} else {
callback();
}
},
trigger: 'blur',
},
],
//
otherServices: [{ required: false, message: '请输入其他服务', trigger: 'blur' }],
//
enterpriseName: [
{ required: true, message: '请输入企业名称', trigger: 'blur' },
{ min: 2, max: 50, message: '长度在2到50个字符', trigger: 'blur' },
],
contacts: [
{ required: true, message: '请输入联系人', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在2到20个字符', trigger: 'blur' },
],
contactNumber: [
{ required: true, message: '请输入联系电话', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' },
],
email: [
{ required: true, message: '请输入电子邮箱', trigger: 'blur' },
{ type: 'email', message: '请输入有效的邮箱地址', trigger: ['blur', 'change'] },
],
});
//
const disableStartDate = (time) => {
@ -323,6 +562,28 @@ const goodsList = ref([
name: '冷藏货物',
},
]);
const sortingTypeList = ref([
{ id: 1, name: '分拣类型一' },
{ id: 2, name: '分拣类型二' },
]);
const sortingStandardList = ref([
{ id: 1, name: '分拣标准一' },
{ id: 2, name: '分拣标准二' },
]);
const packagingTypesList = ref([
{ id: 1, name: '包装类型一' },
{ id: 2, name: '包装类型二' },
]);
const sortingServiceChange = (val) => {
if (val === 2) {
formInline.sortingType = '';
formInline.sortingStandards = '';
formInline.packagingType = '';
formInline.packagingSpecifications = '';
formInline.dailySortingVolume = '';
formInline.otherRequirements = '';
}
};
//
const cascaderProps = ref({
@ -342,22 +603,28 @@ const getArea = async () => {
ElMessage.error(res.message);
}
};
const reservation = () => {
dialogVisible.value = true;
Object.assign(formInline, resetForm.value);
};
const onSubmit = async () => {
await formRef.value.validate();
ElMessage.success('提交成功');
console.log(formInline);
dialogVisible.value = false;
};
const toBack = (level) => {
router.go(level);
};
const application = () => {
const application = async () => {
// await formRef.value.validate();
// ElMessage.success('');
// console.log(formInline);
// if (formInline.sortingService === 2) {
// formInline.sortingType = '';
// formInline.sortingStandards = '';
// formInline.packagingType = '';
// formInline.packagingSpecifications = '';
// formInline.dailySortingVolume = '';
// formInline.otherRequirements = '';
// }
//
//
Object.assign(formInline, resetForm.value);
//
router.push({
name: 'warehouse-allocation',
});