Zlpt_Portal/src/views/equip/detail.vue

906 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Navmenu></Navmenu>
<div class="equipDetail">
<div class="top">
<div class="showImg">
<showImg :url-list="pageData.pictures || []"></showImg>
</div>
<div class="baseInfo">
<div class="equipInfo">
<div class="left">
<div class="title">
<div class="name">{{ pageData.modelName }}{{ pageData.deviceName }}</div>
<div class="tag">
<div class="item">{{ pageData.maStatus == '16' ? '待租' : pageData.maStatus }}</div>
<div class="item otherItem" v-if="pageData.isAudit == 1">已审核</div>
</div>
</div>
<div class="viewNnum">浏览{{ pageData.searchNum || 1050 }}</div>
<div class="infoBox">
<div class="item" v-for="(v, i) in equipBaseInfoList" :key="i">
<div class="label">{{ v.label }}</div>
<div class="value">{{
v.key.split(',').map(key => {
return pageData[key] || v.default
}).join('')
}}
</div>
</div>
</div>
</div>
<div class="right">
<div class="Top">
<div class="price">
<span>{{ pageData.monthLeasePrice }}</span>
/月
</div>
<div class="collect" @click="collectChange">
<el-icon class="no" v-show="!isCollect">
<Star/>
</el-icon>
<el-icon class="yes" v-show="isCollect">
<StarFilled/>
</el-icon>
{{ isCollect ? '装备已收藏' : '收藏装备' }}
</div>
</div>
<div class="options">
<div class="item contact" @click="openPhone">联系商家</div>
<div class="item applyFor" @click="openLease">我要租</div>
</div>
</div>
</div>
<div class="businessInfo">
<img class="bgCar" src="@/assets/img/equipDetail/gouwu.png"/>
<div class="business">
<img
src="@/assets/img/bns-logo.png"
class="avatar"/>
<div class="fonts">
<div class="name">{{ pageData.companyName }}</div>
<div class="other">
<div class="item" v-for="(v, i) in businessList" :key="i">
<div class="label">{{ v.label }}</div>
<div class="value">{{ pageData[v.key] }}{{ v.unit }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="detail">
<div class="publicTitle">装备详情</div>
<div class="publicLine"></div>
<div class="list publicContent">
<div class="item" v-for="(v, i) in equipDetailKeyList" :key="i">
<div class="label">{{ v.label }}</div>
<div :class="v.fn ? 'fnValue' : 'value'" @click="handelDetailListClick(v.fn,pageData[v.arg])">{{
pageData[v.key]
}}
</div>
</div>
</div>
</div>
<div class="appearance">
<div class="publicTitle">装备外观</div>
<div class="publicLine"></div>
<div class="urlList publicContent">
<img :src="v" v-for="(v, i) in (pageData.pictures || [])" :key="i"/>
</div>
</div>
<div class="recommend">
<div class="publicTitle">
<div>为您推荐</div>
<div class="change" @click="gethotList">换一批</div>
</div>
<div class="content">
<equip-card class="item"
@on-click="goDetail"
v-for="(v, i) in hotList"
:key="i"
:url="v.picUrl"
:name="`${v.modelName}${v.deviceName}`"
:tags="[v.maStatus=='16' ? '待租' : v.maStatus,v.location]"
:company="v.companyName"
:price="v.monthLeasePrice"
timeUnit="月"
:id="v.maId"></equip-card>
</div>
</div>
<el-dialog
v-model="dialoglease"
title="填写租赁信息"
lock-scroll
class="dialoglease"
width="60%"
>
<el-config-provider :locale="zhCn">
<el-form
ref="ruleFormRef"
:model="ruleForm"
:rules="rules"
label-width="120px"
class="demo-ruleForm"
status-icon
>
<el-row>
<el-col :span="15">
<el-form-item label="设备进场地址" prop="address">
<el-cascader :props="addressCascader" v-model="ruleForm.address" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="15">
<el-form-item label="详细地址" prop="detailAddress">
<el-input placeholder="请输入地址" v-model="ruleForm.detailAddress"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="15">
<el-form-item label="进场时间" prop="entryTime">
<el-date-picker
v-model="ruleForm.entryTime"
value-format="YYYY-MM-DD"
type="date"
placeholder="请选择"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="15">
<el-form-item label="工期时长" prop="duration">
<el-input v-model="ruleForm.duration" type="number" placeholder="请输入工期时长">
<template #append>天</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="7">
<el-form-item label="是否需要机手" prop="machinist">
<el-radio-group v-model="ruleForm.machinist">
<el-radio-button :label="1" :disabled="!pageData.isOperator">
</el-radio-button>
<el-radio-button :label="0">
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发票类型" prop="invoiceType">
<el-radio-group v-model="ruleForm.invoiceType">
<el-radio-button label="">
不需要
</el-radio-button>
<el-radio-button :label="1">
增值税普票
</el-radio-button>
<el-radio-button :label="2">
增值税专票
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="15">
<el-form-item label="项目说明" prop="projectDescription">
<el-input placeholder="请填写项目说明" rows="5" type="textarea"
v-model="ruleForm.projectDescription"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-config-provider>
<equipDetailTable
:price="pageData.monthLeasePrice"
:name="`${pageData.modelName}${pageData.deviceName}`"
:company="pageData.companyName"
:url="pageData.picUrl"
:brand="pageData.brand"
:code="pageData.code"
:group="pageData.groupName"
:position="pageData.location"
:specifications="pageData.specification"
:type="pageData.typeName"
unit="月"
></equipDetailTable>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="submit">
提交
</el-button>
</span>
</template>
</el-dialog>
<el-dialog
v-model="dialogPhone"
title="服务电话"
width="30%"
>
<div style="font-size: 16px;font-weight: 600;">
{{ pageData.authPhone || '18815622887' }}
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="openPhone">
确认
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import ShowImg from './comoonents/showImg.vue'
import {reactive, ref} from 'vue'
import EquipCard from 'components/equipCard.vue'
import {getDetail,getHotList,equipCollect,apiSubmitLease,apiGetAddressList} from "@/http/api/equip"
import {useRoute, useRouter} from "vue-router";
import Navmenu from '@/components/Navmenu/index.vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import equipDetailTable from '@/components/equipDetailTable.vue'
import {ElMessage} from "element-plus";
const router = useRouter()
const route = useRoute()
const pageParams = route.params
//设备简略基本信息
const equipBaseInfoList = reactive([
{
label: '设备规格',
key: 'specification',
default:'起重量5吨'
},
{
label: '设备单位',
key: 'companyName',
default: '滁州公司'
},
{
label: '配备机手',
key: 'isOperatorCn'
},
{
label: '发布时间',
key: 'createTime'
},
{
label: '更新时间',
key: 'updateTime'
}
])
//商家标签信息
const businessList = reactive([
{
label: '入驻时间',
key: 'companyCreateTime',
unit: ''
},
{
label: '上架数量',
key: 'companyUpNum',
unit: '台'
}
])
//装备详情数据map
const equipDetailKeyList = reactive([
{
label: '装备编号',
key: 'code',
fn: '',
arg: ''
},
{
label: '装备类别',
key: 'typeName',
fn: '',
arg: ''
},
{
label: '装备组别',
key: 'groupName',
fn: '',
arg: ''
},
{
label: '装备名称',
key: 'deviceName',
fn: '',
arg: ''
},
{
label: '规格/操作重量',
key: 'specification',
fn: '',
arg: ''
},
{
label: '品牌',
key: 'brand',
fn: '',
arg: ''
},
{
label: '装备型号',
key: 'modelName',
fn: '',
arg: ''
},
{
label: '序列号码',
key: 'serialNumber',
fn: '',
arg: ''
},
{
label: '出场时间',
key: 'productionDate',
fn: '',
arg: ''
},
{
label: '工作时长',
key: 'workingHours',
fn: '',
arg: ''
},
{
label: '检验信息',
key: 'isExaminationPdf',
fn: 'openPdf',
arg: 'examinationPdf'
},
{
label: '保险信息',
key: 'isInsurancePdf',
fn: 'openPdf',
arg: 'insurancePdf'
}
])
//
const dialogPhone = ref(false)
//装备详情数据
const pageData = ref({})
//我要租 弹窗
const dialoglease = ref(false)
//装备收藏状态
const isCollect = ref(false)
//推荐列表
const hotList = ref([])
//我要租 表单数据
const ruleForm = ref({
address: [],//进场地址
detailAddress: '',//详细地址
entryTime: '',//进场时间
duration: '',//工期时长
machinist: 0,//是否需要机手
invoiceType: '',//发票类型
projectDescription: ''//项目说明
})
const rules = reactive({
address: [
{required: true, message: '请输入进场地址', trigger: 'blur'}
],
detailAddress: [
{required: true, message: '请输入详细地址', trigger: 'blur'}
],
entryTime: [
{required: true, message: '请选择进场时间', trigger: 'blur'}
],
duration: [
{required: true, message: '请输入工期时长', trigger: 'blur'}
],
machinist: [
{required: true, message: '请输入进场地址', trigger: 'blur'}
],
invoiceType: [
{required: true, message: '请输入进场地址', trigger: 'blur'}
],
projectDescription: [
{required: true, message: '请输入项目说明', trigger: 'blur'}
],
})
//打开我要租表单
const openLease = () => {
dialoglease.value = true
}
//切换收藏状态
const collectChange = async () => {
isCollect.value = !isCollect.value
const params = {
maId:pageData.value.maId,
isCollect:isCollect.value
}
const res = await equipCollect(params)
if(res.code == '200'){
ElMessage({
type:'success',
duration:1000,
message:`装备${isCollect.value ? '收藏' : '取消收藏'}成功`
})
}
}
//打开商家电话弹窗
const openPhone = () => {
dialogPhone.value = !dialogPhone.value
}
// 打开新标签页查看pdf
const openPdf = (name) => {
if(name){
window.open(name)
}
}
const that = {
openPdf
}
const addressCascader = {
lazy:true,
label:'name',
value:'id',
lazyLoad: async (node,resolve) =>{
const { level,data } = node
let nodes = []
if(level == 0){
const arr = await getAddressData()
nodes = arr
}else if(level == 1){
const arr = await getAddressData(data.code)
nodes = arr
}else if(level == 2){
const arr = await getAddressData(data.code)
nodes = arr.map((item) => ({
...item,
leaf:true
}))
}
resolve(nodes)
}
}
//获取地址列表
const getAddressData = async (code = '') => {
let params = {}
if(code){
params = { code }
}
const res = await apiGetAddressList(params)
return res.data || []
}
const handelDetailListClick = (fnName, arg) => {
if (fnName) {
that[fnName](arg)
}
}
//获取页面数据
const getData = async () => {
const res = await getDetail(pageParams.id)
res.data.isOperatorCn = res.data.isOperator ? '是' : '否'
res.data.isInsurancePdf = res.data.insurancePdf ? '点击查看' : '暂无'
res.data.isExaminationPdf = res.data.examinationPdf ? '点击查看' : '暂无'
isCollect.value = res.data.collectId ? true : false
pageData.value = res.data
}
//获取推荐列表
const gethotList = async () => {
const params = {
pageNum:1,
pageSize:3
}
const res = await getHotList(params)
hotList.value = res.rows
}
//获取详情数据
const goDetail = (val) => {
router.push({
path:`/equipDetail/${val.id}`
})
}
//提交申请
const submit = async() => {
console.log(pageData.value)
const params = {
addressId: ruleForm.value.address[2],
address: ruleForm.value.detailAddress,
realStartTime: ruleForm.value.entryTime,
duration: ruleForm.value.duration,
isMachinist: ruleForm.value.machinist,
invoiceType: ruleForm.value.invoiceType,
description: ruleForm.value.projectDescription,
maId:pageData.value.maId
}
const res = await apiSubmitLease(params)
if(res.code == '200'){
ElMessage({
message:'提交租赁申请成功',
type:'success',
duration:1500
})
}
dialoglease.value = false
}
const init = async () => {
await gethotList()
await getData()
}
init()
</script>
<style scoped lang="scss">
:deep(.dialoglease){
margin: 10px auto 0 !important;
min-width: 855px !important;
}
:deep(.el-form-item){
display: flex;
width: 100%;
.el-form-item__content {
flex: 1;
}
}
.equipDetail {
user-select: none;
margin-top: 20px;
.top {
display: flex;
margin-bottom: 50px;
.showImg {
width: 38%;
border-radius: 15px;
overflow: hidden;
margin-right: 30px;
}
.baseInfo {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.equipInfo {
display: flex;
.left {
margin-right: 5px;
.title {
display: flex;
align-items: center;
.name {
font-size: 24px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
color: #000000;
}
.tag {
display: flex;
align-items: center;
.item {
font-size: 13px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
color: #005af2;
margin-left: 15px;
padding: 2px 10px;
border: 1px solid #005af2;
border-radius: 4px;
}
.otherItem {
border-color: #ff6734;
color: #ff6734;
}
}
}
.viewNnum {
font-size: 13px;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
color: #bcbcbc;
margin-top: 10px;
}
.infoBox {
margin-top: 20px;
.item {
display: flex;
align-items: center;
margin-bottom: 18px;
.label {
font-size: 15px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
color: #8e8e8e;
margin-right: 15px;
}
.value {
font-size: 14px;
font-family: PingFangSC, PingFang SC;
color: #333333;
}
}
}
}
.right {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.collect {
user-select: none;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 14px;
color: #acacac;
cursor: pointer;
.no {
font-size: 16px;
}
.yes {
font-size: 20px;
color: #1b7eff;
}
}
.price {
font-size: 15px;
font-weight: 500;
font-family: PingFangSC, PingFang SC;
color: #ff4800;
text-align: right;
span {
font-size: 30px;
font-weight: 600;
}
}
.options {
display: flex;
justify-content: flex-end;
.item {
cursor: pointer;
width: 110px;
height: 40px;
line-height: 40px;
border-radius: 4px;
font-size: 18px;
font-weight: 600;
text-align: center;
}
.contact {
color: #ffffff;
background: #3cabff;
margin-right: 20px;
}
.applyFor {
border: 1px solid #3cabff;
color: #3cabff;
box-sizing: border-box;
line-height: 38px;
}
}
}
}
.businessInfo {
width: 100%;
height: 147px;
background: #f7f9fa;
border-radius: 15px;
position: relative;
box-sizing: border-box;
padding: 25px 15px;
.bgCar {
position: absolute;
top: 0;
right: 0;
height: 100%;
z-index: 0;
}
.business {
display: flex;
align-items: center;
.avatar {
width: 65px;
height: 65px;
border-radius: 100%;
margin-right: 10px;
}
.fonts {
.name {
font-size: 20px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
color: #333333;
margin-bottom: 12px;
}
.other {
display: flex;
.item {
font-size: 14px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
color: #333333;
display: flex;
margin-right: 15px;
.label {
}
.value {
}
}
}
}
}
}
}
}
.publicTitle {
font-size: 20px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
color: #333333;
display: flex;
align-items: center;
justify-content: space-between;
}
.publicLine {
width: 100%;
height: 12px;
border-bottom: 1px solid #e0e0e0;
position: relative;
&:before {
content: '';
height: 3px;
width: 40px;
background: #2282ff;
border-radius: 2px;
position: absolute;
bottom: -1px;
left: 20px;
}
}
.publicContent {
box-sizing: border-box;
padding: 40px 70px 10px;
}
.detail {
.list {
display: flex;
flex-wrap: wrap;
.item {
cursor: pointer;
width: calc(100% / 3);
font-size: 16px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
display: flex;
margin-bottom: 35px;
.label {
color: #8e8e8e;
}
.value {
color: #333333;
}
.fnValue {
color: #0087cd;
}
}
}
}
.appearance {
margin-bottom: 20px;
.urlList {
img {
width: 100%;
}
}
}
.recommend {
.change {
font-size: 14px;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
color: #9d9d9d;
cursor: pointer;
}
.content {
margin-top: 20px;
width: 100%;
display: flex;
.item {
width: calc((100% - 40px) / 3);
&:nth-child(3n - 1) {
margin: 0 20px;
}
}
}
}
}
</style>