| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479 |
- <script setup lang="ts">
- import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
- import {
- ElButton,
- ElCard,
- ElCol,
- ElContainer,
- ElDatePicker,
- ElDialog,
- ElForm,
- ElFormItem,
- ElIcon,
- ElInput,
- ElInputNumber,
- ElMain,
- ElMessage,
- ElOption,
- ElRow,
- ElSelect,
- ElStep,
- ElSteps,
- ElTag,
- } from 'element-plus'
- import {
- ArrowLeft,
- BookText,
- Cpu,
- Eye,
- FileText,
- Home,
- MapPin,
- Plus,
- User,
- X,
- } from 'lucide-vue-next'
- import { useRoute, useRouter } from 'vue-router'
- import { clientGet, clientPost } from '@/utils/request.ts'
- // 导入docx-preview库
- import { renderAsync } from 'docx-preview'
- const router = useRouter()
- const route = useRoute()
- // 响应式数据
- const showRentalDialog = ref(false)
- const showTerminateDialog = ref(false)
- const showDocxPreviewDialog = ref(false) // 新增:DOCX预览对话框
- const docxPreviewLoading = ref(false) // 新增:DOCX加载状态
- const docxPreviewContainer = ref<HTMLElement>() // 新增:DOCX预览容器引用
- const currentStep = ref(0)
- const submitting = ref(false)
- const terminating = ref(false)
- const loading = ref(true)
- const MINIO_URL = import.meta.env.VITE_MINIO_BASE_URL
- const propertyInfo = ref({
- id: '',
- buildingNumber: '',
- priceRange: '',
- address: '',
- area: '',
- status: '', // 未租 或 已租
- floor: '',
- facilities: '',
- assetType: '', //公租房|厂房|创新创业基地
- })
- const receiptData = ref({})
- const basicInfo = ref({
- buildYear: '',
- orientation: '',
- houseType: '',
- })
- const assetFilter = reactive({
- category: '',
- })
- const assets = ref<DeviceInfo[]>([])
- const filteredAssets = computed(() => {
- return assets.value.filter((asset) => {
- const categoryMatch = !assetFilter.category || asset.deviceType === assetFilter.category
- return categoryMatch
- })
- })
- const tenantInfo = ref<TenantInfo | null>(null)
- const contractInfo = ref<ContractInfo | null>(null)
- interface ContractA {
- tenantName: string
- landlordName: string
- tenantTimeStart: string
- tenantTime: string
- tenantTimeEnd: string
- tenantRent: string
- tenantDeposit: string
- tenantDepositAmount: string
- }
- interface ContractB {
- purpose: string
- landlordName: string
- landlordUniCode: string
- landlordLegalRepresentative: string
- landlordDuty: string
- tenantName: string
- tenantUniCode: string
- tenantLegalRepresentative: string
- tenantDuty: string
- who: string
- whatTime: string
- title: string
- supportingRoomArea: string
- officeArea: string
- canteenArea: string
- totalLeasedArea: string
- dormTotalRooms: string
- dormSmallRooms: string
- dormLargeRooms: string
- deliveryDate: string
- productionProject: string
- leaseTermYears: string
- leaseStartDate: string
- leaseEndDate: string
- renewNoticeMonths: string
- factorySpecificFloor1: string
- rentPerSqmFloor1: string
- factorySpecificFloor2: string
- rentPerSqmFloor2: string
- factoryAnnualRent: string
- supportingRoomRentPerSqm: string
- supportingRoomAnnualRent: string
- dormSmallRoomRent: string
- dormLargeRoomRent: string
- dormAnnualRent: string
- totalAnnualRent: string
- propertyFeePerSqm: string
- factorySupportingPropertyFee: string
- dormSmallRoomPropertyFee: string
- dormLargeRoomPropertyFee: string
- dormAnnualPropertyFee: string
- totalAnnualPropertyFee: string
- annualTotalRentAndPropertyFee: string
- depositAmount: string
- }
- interface ContractC {
- lessorName: string
- lessorLegalRep: string
- lessorUniCode: string
- lesseeName: string
- lesseeLegalRep: string
- lesseeIdCode: string
- propertyLocation: string
- rentableArea: string
- usableArea: string
- sharedArea: string
- propertyUseNature: string
- storeName: string
- brand: string
- businessScope: string
- leaseTermMonths: string
- leaseStartDate: string
- leaseEndDate: string
- renovationStartDate: string
- renovationEndDate: string
- officialLeaseStartDate: string
- annualRentLower: string
- annualPropertyFeeLower: string
- depositAmount: string
- }
- const rentalForm = reactive<{
- houseId: string
- contractData: ContractA | ContractB | ContractC | null
- contractDataA: ContractA
- contractDataB: ContractB
- contractDataC: ContractC
- rentalInfo: {
- rentalName: string
- rentalPhone: string
- rentalIdCard: string
- rentalTimeStart: string
- rentalTime: string
- rentalRect: string
- }
- }>({
- houseId: route.query.houseId as string,
- contractData: null,
- rentalInfo: {
- rentalName: '',
- rentalPhone: '',
- rentalIdCard: '',
- rentalTimeStart: '',
- rentalTime: '',
- rentalRect: '',
- },
- contractDataA: {
- landlordName: '',
- tenantDeposit: '',
- tenantDepositAmount: '',
- tenantName: '',
- tenantRent: '',
- tenantTime: '',
- tenantTimeEnd: '',
- tenantTimeStart: '',
- },
- contractDataB: {
- annualTotalRentAndPropertyFee: '',
- canteenArea: '',
- deliveryDate: '',
- depositAmount: '',
- dormAnnualPropertyFee: '',
- dormAnnualRent: '',
- dormLargeRoomPropertyFee: '',
- dormLargeRoomRent: '',
- dormLargeRooms: '',
- dormSmallRoomPropertyFee: '',
- dormSmallRoomRent: '',
- dormSmallRooms: '',
- dormTotalRooms: '',
- factoryAnnualRent: '',
- factorySpecificFloor1: '',
- factorySpecificFloor2: '',
- factorySupportingPropertyFee: '',
- landlordDuty: '',
- landlordLegalRepresentative: '',
- landlordName: '',
- landlordUniCode: '',
- leaseEndDate: '',
- leaseStartDate: '',
- leaseTermYears: '',
- officeArea: '',
- productionProject: '',
- propertyFeePerSqm: '',
- purpose: '',
- renewNoticeMonths: '',
- rentPerSqmFloor1: '',
- rentPerSqmFloor2: '',
- supportingRoomAnnualRent: '',
- supportingRoomArea: '',
- supportingRoomRentPerSqm: '',
- tenantDuty: '',
- tenantLegalRepresentative: '',
- tenantName: '',
- tenantUniCode: '',
- title: '',
- totalAnnualPropertyFee: '',
- totalAnnualRent: '',
- totalLeasedArea: '',
- whatTime: '',
- who: '',
- },
- contractDataC: {
- annualPropertyFeeLower: '',
- annualRentLower: '',
- brand: '',
- businessScope: '',
- depositAmount: '',
- leaseEndDate: '',
- leaseStartDate: '',
- leaseTermMonths: '',
- lesseeIdCode: '',
- lesseeLegalRep: '',
- lesseeName: '',
- lessorLegalRep: '',
- lessorName: '',
- lessorUniCode: '',
- officialLeaseStartDate: '',
- propertyLocation: '',
- propertyUseNature: '',
- renovationEndDate: '',
- renovationStartDate: '',
- rentableArea: '',
- sharedArea: '',
- storeName: '',
- usableArea: '',
- },
- })
- const rentalRules = {
- // 租户信息验证规则
- 'rentalInfo.rentalName': [{ required: true, message: '请输入租户姓名', trigger: 'blur' }],
- 'rentalInfo.rentalPhone': [{ required: true, message: '请输入租户电话', trigger: 'blur' }],
- 'rentalInfo.rentalIdCard': [{ required: false, message: '请输入租户身份证号', trigger: 'blur' }],
- 'rentalInfo.rentalTimeStart': [
- { required: true, message: '请输入租期开始时间', trigger: 'blur' },
- ],
- 'rentalInfo.rentalTime': [{ required: true, message: '请输入租期', trigger: 'blur' }],
- 'rentalInfo.rentalRect': [{ required: true, message: '请输入租金', trigger: 'blur' }],
- // 公租房合同A验证规则
- 'contractDataA.tenantName': [{ required: true, message: '请输入租方', trigger: 'blur' }],
- 'contractDataA.landlordName': [{ required: true, message: '请输入房东', trigger: 'blur' }],
- 'contractDataA.tenantTimeStart': [
- { required: true, message: '请输入租期开始时间', trigger: 'blur' },
- ],
- 'contractDataA.tenantTime': [{ required: true, message: '请输入租期', trigger: 'blur' }],
- 'contractDataA.tenantTimeEnd': [
- { required: true, message: '请输入租期结束时间', trigger: 'blur' },
- ],
- 'contractDataA.tenantRent': [{ required: true, message: '请输入每套租金', trigger: 'blur' }],
- 'contractDataA.tenantDeposit': [{ required: true, message: '请输入每套物业费', trigger: 'blur' }],
- 'contractDataA.tenantDepositAmount': [{ required: true, message: '请输入押金', trigger: 'blur' }],
- // 厂房合同B验证规则 - 所有字段必填
- 'contractDataB.purpose': [{ required: true, message: '请输入用途', trigger: 'blur' }],
- 'contractDataB.landlordName': [{ required: true, message: '请输入房东', trigger: 'blur' }],
- 'contractDataB.landlordUniCode': [
- { required: true, message: '请输入法人统一社会信用代码', trigger: 'blur' },
- ],
- 'contractDataB.landlordLegalRepresentative': [
- { required: true, message: '请输入法定代表人', trigger: 'blur' },
- ],
- 'contractDataB.landlordDuty': [{ required: true, message: '请输入房东职务', trigger: 'blur' }],
- 'contractDataB.tenantName': [{ required: true, message: '请输入租方', trigger: 'blur' }],
- 'contractDataB.tenantUniCode': [
- { required: true, message: '请输入租方统一社会信用代码', trigger: 'blur' },
- ],
- 'contractDataB.tenantLegalRepresentative': [
- { required: true, message: '请输入法定代表人', trigger: 'blur' },
- ],
- 'contractDataB.tenantDuty': [{ required: true, message: '请输入租方职务', trigger: 'blur' }],
- 'contractDataB.who': [{ required: true, message: '请输入谁', trigger: 'blur' }],
- 'contractDataB.whatTime': [{ required: true, message: '请输入何时', trigger: 'blur' }],
- 'contractDataB.title': [{ required: true, message: '请输入标题', trigger: 'blur' }],
- 'contractDataB.supportingRoomArea': [
- { required: true, message: '请输入配套用房面积(㎡)', trigger: 'blur' },
- ],
- 'contractDataB.officeArea': [
- { required: true, message: '请输入办公室面积(㎡)', trigger: 'blur' },
- ],
- 'contractDataB.canteenArea': [
- { required: true, message: '请输入食堂面积(㎡)', trigger: 'blur' },
- ],
- 'contractDataB.totalLeasedArea': [
- { required: true, message: '请输入总面积(㎡)', trigger: 'blur' },
- ],
- 'contractDataB.dormTotalRooms': [
- { required: true, message: '请输入宿舍楼总间数', trigger: 'blur' },
- ],
- 'contractDataB.dormSmallRooms': [
- { required: true, message: '请输入宿舍小间数', trigger: 'blur' },
- ],
- 'contractDataB.dormLargeRooms': [
- { required: true, message: '请输入宿舍大间数', trigger: 'blur' },
- ],
- 'contractDataB.deliveryDate': [
- { required: true, message: '请输入标的交付日期', trigger: 'blur' },
- ],
- 'contractDataB.productionProject': [
- { required: true, message: '请输入生产项目名称', trigger: 'blur' },
- ],
- 'contractDataB.leaseTermYears': [
- { required: true, message: '请输入租赁期限(年)', trigger: 'blur' },
- ],
- 'contractDataB.leaseStartDate': [
- { required: true, message: '请输入租赁起始日', trigger: 'blur' },
- ],
- 'contractDataB.leaseEndDate': [{ required: true, message: '请输入租赁终止日', trigger: 'blur' }],
- 'contractDataB.renewNoticeMonths': [
- { required: true, message: '请输入续租提前通知月数', trigger: 'blur' },
- ],
- 'contractDataB.factorySpecificFloor1': [
- { required: true, message: '请输入标准化厂房某楼层', trigger: 'blur' },
- ],
- 'contractDataB.rentPerSqmFloor1': [
- { required: true, message: '请输入该楼层租金(元/㎡/月)', trigger: 'blur' },
- ],
- 'contractDataB.factorySpecificFloor2': [
- { required: true, message: '请输入标准化厂房另一楼层', trigger: 'blur' },
- ],
- 'contractDataB.rentPerSqmFloor2': [
- { required: true, message: '请输入该楼层租金(元/㎡/月)', trigger: 'blur' },
- ],
- 'contractDataB.factoryAnnualRent': [
- { required: true, message: '请输入厂房年租金(元)', trigger: 'blur' },
- ],
- 'contractDataB.supportingRoomRentPerSqm': [
- { required: true, message: '请输入配套用房租金(元/㎡/月)', trigger: 'blur' },
- ],
- 'contractDataB.supportingRoomAnnualRent': [
- { required: true, message: '请输入配套用房年租金(元)', trigger: 'blur' },
- ],
- 'contractDataB.dormSmallRoomRent': [
- { required: true, message: '请输入宿舍楼普通单间月租金(元)', trigger: 'blur' },
- ],
- 'contractDataB.dormLargeRoomRent': [
- { required: true, message: '请输入宿舍楼大单间月租金(元)', trigger: 'blur' },
- ],
- 'contractDataB.dormAnnualRent': [
- { required: true, message: '请输入宿舍楼年租金(元)', trigger: 'blur' },
- ],
- 'contractDataB.totalAnnualRent': [
- { required: true, message: '请输入总租金(元)', trigger: 'blur' },
- ],
- 'contractDataB.propertyFeePerSqm': [
- { required: true, message: '请输入标准化厂房和配套用房物业费(元/㎡/月)', trigger: 'blur' },
- ],
- 'contractDataB.factorySupportingPropertyFee': [
- { required: true, message: '请输入标准化厂房和配套用房年物业费(元)', trigger: 'blur' },
- ],
- 'contractDataB.dormSmallRoomPropertyFee': [
- { required: true, message: '请输入宿舍楼普通单间月物业费(元)', trigger: 'blur' },
- ],
- 'contractDataB.dormLargeRoomPropertyFee': [
- { required: true, message: '请输入宿舍楼大单间月物业费(元)', trigger: 'blur' },
- ],
- 'contractDataB.dormAnnualPropertyFee': [
- { required: true, message: '请输入宿舍楼年物业费(元)', trigger: 'blur' },
- ],
- 'contractDataB.totalAnnualPropertyFee': [
- { required: true, message: '请输入年物业管理费(元)', trigger: 'blur' },
- ],
- 'contractDataB.annualTotalRentAndPropertyFee': [
- { required: true, message: '请输入年租金和物业费用总计(元)', trigger: 'blur' },
- ],
- 'contractDataB.depositAmount': [
- { required: true, message: '请输入租赁押金金额(元)', trigger: 'blur' },
- ],
- // 创新创业基地合同C验证规则 - 所有字段必填
- 'contractDataC.lessorName': [
- { required: true, message: '请输入出租方(甲方)名称', trigger: 'blur' },
- ],
- 'contractDataC.lessorLegalRep': [
- { required: true, message: '请输入出租方法定代表人', trigger: 'blur' },
- ],
- 'contractDataC.lessorUniCode': [
- { required: true, message: '请输入出租方统一社会信用代码', trigger: 'blur' },
- ],
- 'contractDataC.lesseeName': [
- { required: true, message: '请输入承租方(乙方)名称', trigger: 'blur' },
- ],
- 'contractDataC.lesseeLegalRep': [
- { required: true, message: '请输入承租方法定代表人', trigger: 'blur' },
- ],
- 'contractDataC.lesseeIdCode': [
- { required: true, message: '请输入承租方统一社会信用代码/身份证号', trigger: 'blur' },
- ],
- 'contractDataC.propertyLocation': [
- { required: true, message: '请输入标的物坐落', trigger: 'blur' },
- ],
- 'contractDataC.rentableArea': [
- { required: true, message: '请输入计租面积(平方米)', trigger: 'blur' },
- ],
- 'contractDataC.usableArea': [
- { required: true, message: '请输入使用面积(平方米)', trigger: 'blur' },
- ],
- 'contractDataC.sharedArea': [
- { required: true, message: '请输入公摊面积(平方米)', trigger: 'blur' },
- ],
- 'contractDataC.propertyUseNature': [
- { required: true, message: '请输入标的物使用性质', trigger: 'blur' },
- ],
- 'contractDataC.storeName': [{ required: true, message: '请输入店铺名称', trigger: 'blur' }],
- 'contractDataC.brand': [{ required: true, message: '请输入商品/服务品牌', trigger: 'blur' }],
- 'contractDataC.businessScope': [{ required: true, message: '请输入经营范围', trigger: 'blur' }],
- 'contractDataC.leaseTermMonths': [
- { required: true, message: '请输入租赁期限(个月)', trigger: 'blur' },
- ],
- 'contractDataC.leaseStartDate': [
- { required: true, message: '请输入租赁起始日', trigger: 'blur' },
- ],
- 'contractDataC.leaseEndDate': [{ required: true, message: '请输入租赁终止日', trigger: 'blur' }],
- 'contractDataC.renovationStartDate': [
- { required: true, message: '请输入装修期起始日', trigger: 'blur' },
- ],
- 'contractDataC.renovationEndDate': [
- { required: true, message: '请输入装修期终止日', trigger: 'blur' },
- ],
- 'contractDataC.officialLeaseStartDate': [
- { required: true, message: '请输入正式起租时间', trigger: 'blur' },
- ],
- 'contractDataC.annualRentLower': [
- { required: true, message: '请输入年租金(小写)', trigger: 'blur' },
- ],
- 'contractDataC.annualPropertyFeeLower': [
- { required: true, message: '请输入年物业服务费(小写)', trigger: 'blur' },
- ],
- 'contractDataC.depositAmount': [
- { required: true, message: '请输入租赁保证金金额', trigger: 'blur' },
- ],
- }
- const rentalFormRef = ref()
- interface BaseResponse {
- code: number
- msg: string
- }
- interface HouseInfoVo {
- houseName: string | null
- address: string | null
- status: string | null
- rentRange: number | null
- tenantInfo: TenantInfo | null
- houseInfo: HouseInfo | null
- deviceInfo: DeviceInfo[] | null
- contractInfo: ContractInfo | null
- assetType: string | null
- }
- interface HouseInfoResponse extends BaseResponse {
- data: HouseInfoVo
- }
- interface AReceiptInfoResponse extends BaseResponse {
- data: PageType<AReceiptInfo>
- }
- interface TenantInfo {
- tenantName: string | null
- tenantNumber: string | null
- tenantIdCard: string | null
- tenantInDate: string | null
- tenantTime: string | null
- tenantRent: string | null
- }
- interface HouseInfo {
- area: string | null
- floor: string | null
- introduce: string | null
- houseType: string | null
- }
- interface DeviceInfo {
- deviceName: string | null
- deviceType: string | null
- deviceBrand: string | null
- deviceNumber: string | null
- devicePrice: string | null
- }
- interface ContractInfo {
- contractNumber: string | null
- contractDate: string | null
- contractTime: string | null
- contractExpirationDate: string | null
- contractDeposit: string | null
- contractStatus: string | null
- contractOriginalUrl: string | null
- }
- const deviceTypes = computed(() => {
- const types = new Set(assets.value.map((asset) => asset.deviceType).filter(Boolean))
- return Array.from(types)
- })
- // const openARViewing = () => {
- // ElMessage.info('正在启动AR看房功能...')
- // }
- const filterAssets = () => {
- // 筛选逻辑已通过计算属性实现
- }
- // 新增:预览DOCX文件的函数
- const previewDocx = async (url: string) => {
- url = MINIO_URL + url
- if (!url) {
- ElMessage.error('合同文件URL不存在')
- return
- }
- showDocxPreviewDialog.value = true
- docxPreviewLoading.value = true
- try {
- // 获取DOCX文件
- const response = await fetch(url)
- if (!response.ok) {
- throw new Error('无法获取合同文件')
- }
- const arrayBuffer = await response.arrayBuffer()
- // 等待DOM更新
- await nextTick()
- if (docxPreviewContainer.value) {
- // 清空容器
- docxPreviewContainer.value.innerHTML = ''
- // 渲染DOCX内容
- await renderAsync(arrayBuffer, docxPreviewContainer.value, undefined, {
- className: 'docx-wrapper',
- inWrapper: true,
- ignoreWidth: false,
- ignoreHeight: false,
- ignoreFonts: false,
- breakPages: true,
- ignoreLastRenderedPageBreak: true,
- experimental: false,
- trimXmlDeclaration: true,
- useBase64URL: false,
- renderHeaders: true,
- renderFooters: true,
- renderFootnotes: true,
- renderEndnotes: true,
- debug: false,
- })
- }
- } catch (error) {
- console.error('预览DOCX文件失败:', error)
- ElMessage.error('预览合同文件失败,请稍后重试')
- showDocxPreviewDialog.value = false
- } finally {
- docxPreviewLoading.value = false
- }
- }
- // 新增:关闭DOCX预览对话框
- const closeDocxPreview = () => {
- showDocxPreviewDialog.value = false
- if (docxPreviewContainer.value) {
- docxPreviewContainer.value.innerHTML = ''
- }
- }
- const getValidationFields = () => {
- const assetType = propertyInfo.value.assetType
- if (assetType === '公租房') {
- return [
- 'contractDataA.tenantName',
- 'contractDataA.landlordName',
- 'contractDataA.tenantTimeStart',
- 'contractDataA.tenantTime',
- 'contractDataA.tenantTimeEnd',
- 'contractDataA.tenantRent',
- 'contractDataA.tenantDeposit',
- 'contractDataA.tenantDepositAmount',
- ]
- } else if (assetType === '厂房') {
- return [
- 'contractDataB.purpose',
- 'contractDataB.landlordName',
- 'contractDataB.landlordUniCode',
- 'contractDataB.landlordLegalRepresentative',
- 'contractDataB.landlordDuty',
- 'contractDataB.tenantName',
- 'contractDataB.tenantUniCode',
- 'contractDataB.tenantLegalRepresentative',
- 'contractDataB.tenantDuty',
- 'contractDataB.who',
- 'contractDataB.whatTime',
- 'contractDataB.title',
- 'contractDataB.supportingRoomArea',
- 'contractDataB.officeArea',
- 'contractDataB.canteenArea',
- 'contractDataB.totalLeasedArea',
- 'contractDataB.dormTotalRooms',
- 'contractDataB.dormSmallRooms',
- 'contractDataB.dormLargeRooms',
- 'contractDataB.deliveryDate',
- 'contractDataB.productionProject',
- 'contractDataB.leaseTermYears',
- 'contractDataB.leaseStartDate',
- 'contractDataB.leaseEndDate',
- 'contractDataB.renewNoticeMonths',
- 'contractDataB.factorySpecificFloor1',
- 'contractDataB.rentPerSqmFloor1',
- 'contractDataB.factorySpecificFloor2',
- 'contractDataB.rentPerSqmFloor2',
- 'contractDataB.factoryAnnualRent',
- 'contractDataB.supportingRoomRentPerSqm',
- 'contractDataB.supportingRoomAnnualRent',
- 'contractDataB.dormSmallRoomRent',
- 'contractDataB.dormLargeRoomRent',
- 'contractDataB.dormAnnualRent',
- 'contractDataB.totalAnnualRent',
- 'contractDataB.propertyFeePerSqm',
- 'contractDataB.factorySupportingPropertyFee',
- 'contractDataB.dormSmallRoomPropertyFee',
- 'contractDataB.dormLargeRoomPropertyFee',
- 'contractDataB.dormAnnualPropertyFee',
- 'contractDataB.totalAnnualPropertyFee',
- 'contractDataB.annualTotalRentAndPropertyFee',
- 'contractDataB.depositAmount',
- ]
- } else if (assetType === '创新创业基地') {
- return [
- 'contractDataC.lessorName',
- 'contractDataC.lessorLegalRep',
- 'contractDataC.lessorUniCode',
- 'contractDataC.lesseeName',
- 'contractDataC.lesseeLegalRep',
- 'contractDataC.lesseeIdCode',
- 'contractDataC.propertyLocation',
- 'contractDataC.rentableArea',
- 'contractDataC.usableArea',
- 'contractDataC.sharedArea',
- 'contractDataC.propertyUseNature',
- 'contractDataC.storeName',
- 'contractDataC.brand',
- 'contractDataC.businessScope',
- 'contractDataC.leaseTermMonths',
- 'contractDataC.leaseStartDate',
- 'contractDataC.leaseEndDate',
- 'contractDataC.renovationStartDate',
- 'contractDataC.renovationEndDate',
- 'contractDataC.officialLeaseStartDate',
- 'contractDataC.annualRentLower',
- 'contractDataC.annualPropertyFeeLower',
- 'contractDataC.depositAmount',
- ]
- }
- return []
- }
- const nextStep = async () => {
- if (currentStep.value === 0) {
- try {
- await rentalFormRef.value.validateField([
- 'rentalInfo.rentalName',
- 'rentalInfo.rentalPhone',
- 'rentalInfo.rentalIdCard',
- 'rentalInfo.rentalTimeStart',
- 'rentalInfo.rentalTime',
- 'rentalInfo.rentalRect',
- ])
- currentStep.value++
- } catch (error) {
- console.log('第一步验证失败:', error)
- }
- } else if (currentStep.value === 1) {
- try {
- const fieldsToValidate = getValidationFields()
- await rentalFormRef.value.validateField(fieldsToValidate)
- currentStep.value++
- } catch (error) {
- console.log('第二步验证失败:', error)
- }
- }
- }
- const handleCloseRentalDialog = () => {
- showRentalDialog.value = false
- currentStep.value = 0
- Object.assign(rentalForm.rentalInfo, {
- rentalName: '',
- rentalPhone: '',
- rentalIdCard: '',
- rentalTimeStart: '',
- rentalTime: '',
- rentalRect: '',
- })
- Object.assign(rentalForm.contractDataA, {
- landlordName: '',
- tenantDeposit: '',
- tenantDepositAmount: '',
- tenantName: '',
- tenantRent: '',
- tenantTime: '',
- tenantTimeEnd: '',
- tenantTimeStart: '',
- })
- // 重置contractDataB的所有字段
- Object.assign(rentalForm.contractDataB, {
- annualTotalRentAndPropertyFee: '',
- canteenArea: '',
- deliveryDate: '',
- depositAmount: '',
- dormAnnualPropertyFee: '',
- dormAnnualRent: '',
- dormLargeRoomPropertyFee: '',
- dormLargeRoomRent: '',
- dormLargeRooms: '',
- dormSmallRoomPropertyFee: '',
- dormSmallRoomRent: '',
- dormSmallRooms: '',
- dormTotalRooms: '',
- factoryAnnualRent: '',
- factorySpecificFloor1: '',
- factorySpecificFloor2: '',
- factorySupportingPropertyFee: '',
- landlordDuty: '',
- landlordLegalRepresentative: '',
- landlordName: '',
- landlordUniCode: '',
- leaseEndDate: '',
- leaseStartDate: '',
- leaseTermYears: '',
- officeArea: '',
- productionProject: '',
- propertyFeePerSqm: '',
- purpose: '',
- renewNoticeMonths: '',
- rentPerSqmFloor1: '',
- rentPerSqmFloor2: '',
- supportingRoomAnnualRent: '',
- supportingRoomArea: '',
- supportingRoomRentPerSqm: '',
- tenantDuty: '',
- tenantLegalRepresentative: '',
- tenantName: '',
- tenantUniCode: '',
- title: '',
- totalAnnualPropertyFee: '',
- totalAnnualRent: '',
- totalLeasedArea: '',
- whatTime: '',
- who: '',
- })
- // 重置contractDataC的所有字段
- Object.assign(rentalForm.contractDataC, {
- annualPropertyFeeLower: '',
- annualRentLower: '',
- brand: '',
- businessScope: '',
- depositAmount: '',
- leaseEndDate: '',
- leaseStartDate: '',
- leaseTermMonths: '',
- lesseeIdCode: '',
- lesseeLegalRep: '',
- lesseeName: '',
- lessorLegalRep: '',
- lessorName: '',
- lessorUniCode: '',
- officialLeaseStartDate: '',
- propertyLocation: '',
- propertyUseNature: '',
- renovationEndDate: '',
- renovationStartDate: '',
- rentableArea: '',
- sharedArea: '',
- storeName: '',
- usableArea: '',
- })
- }
- const submitRental = async () => {
- submitting.value = true
- try {
- if (propertyInfo.value.assetType === '公租房') {
- rentalForm.contractData = rentalForm.contractDataA
- } else if (propertyInfo.value.assetType === '厂房') {
- rentalForm.contractData = rentalForm.contractDataB
- } else if (propertyInfo.value.assetType === '创新创业基地') {
- rentalForm.contractData = rentalForm.contractDataC
- }
- const res = await clientPost<typeof rentalForm, BaseResponse>(
- '/acontractInfo/signContract',
- rentalForm,
- )
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- return
- }
- ElMessage.success(res.msg)
- handleCloseRentalDialog()
- await getData()
- // 新增:签订合同成功后自动预览DOCX
- if (contractInfo.value?.contractOriginalUrl) {
- setTimeout(() => {
- previewDocx(contractInfo.value!.contractOriginalUrl!)
- }, 500) // 延迟500ms确保数据更新完成
- }
- } catch (error) {
- console.error(error)
- ElMessage.error('出租失败,请重试')
- } finally {
- submitting.value = false
- }
- }
- const confirmTerminate = async () => {
- terminating.value = true
- try {
- const res = await clientGet<
- {
- houseId: string
- },
- BaseResponse
- >('/acontractInfo/returnRent', {
- params: {
- houseId: propertyInfo.value.id,
- },
- })
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- return
- }
- ElMessage.success(res.msg)
- showTerminateDialog.value = false
- await getData()
- } catch (error) {
- console.error(error)
- ElMessage.error('退租失败,请重试')
- } finally {
- terminating.value = false
- }
- }
- const getReceiptData = async (contractNumber) => {
- loading.value = true
- try {
- const res = await clientGet<
- {
- receiptNumber: string
- payer: string
- paymentMethod: string
- contractNumber: string
- },
- AReceiptInfoResponse
- >('/AReceiptInfo//findByPageWithContract', {
- params: {
- pageNum: 1,
- pageSize: 10000,
- contractNumber: contractNumber,
- },
- })
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- return
- }
- receiptData.value = res.data.records || {}
- } catch (error) {
- console.error(error)
- ElMessage.error('获取数据失败')
- } finally {
- loading.value = false
- }
- }
- const getData = async () => {
- try {
- loading.value = true
- const res = await clientGet<
- {
- houseId: string
- },
- HouseInfoResponse
- >('/asimplifiedHouseInfo/getHouseDetailInfo', {
- params: {
- houseId: route.query.houseId as string,
- },
- })
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- return
- }
- const data = res.data
- // 新增:获取收据信息
- await getReceiptData(data.contractInfo?.contractNumber || '')
- console.log('接口返回数据:', data)
- propertyInfo.value = {
- id: route.query.houseId as string,
- buildingNumber: data.houseName || '',
- priceRange: data.rentRange ? `${data.rentRange}` : '',
- address: data.address || '',
- area: data.houseInfo?.area || '',
- status: data.status || '未租',
- floor: data.houseInfo?.floor || '',
- facilities: data.houseInfo?.introduce || '',
- assetType: data.assetType || '',
- }
- if (data.houseInfo) {
- basicInfo.value = {
- buildYear: '',
- orientation: '',
- houseType: data.houseInfo.houseType || '',
- }
- }
- if (data.deviceInfo && Array.isArray(data.deviceInfo)) {
- assets.value = data.deviceInfo.map((device) => ({
- deviceName: device.deviceName,
- deviceType: device.deviceType,
- deviceBrand: device.deviceBrand,
- deviceNumber: device.deviceNumber,
- devicePrice: device.devicePrice,
- }))
- } else {
- assets.value = []
- }
- if (data.status === '已租' && data.tenantInfo) {
- tenantInfo.value = {
- tenantName: data.tenantInfo.tenantName,
- tenantNumber: data.tenantInfo.tenantNumber,
- tenantIdCard: data.tenantInfo.tenantIdCard,
- tenantInDate: data.tenantInfo.tenantInDate,
- tenantTime: data.tenantInfo.tenantTime,
- tenantRent: data.tenantInfo.tenantRent,
- }
- } else {
- tenantInfo.value = null
- }
- if (data.status === '已租' && data.contractInfo) {
- contractInfo.value = {
- contractNumber: data.contractInfo.contractNumber,
- contractDate: data.contractInfo.contractDate,
- contractTime: data.contractInfo.contractTime,
- contractExpirationDate: data.contractInfo.contractExpirationDate,
- contractDeposit: data.contractInfo.contractDeposit,
- contractStatus: data.contractInfo.contractStatus,
- contractOriginalUrl: data.contractInfo.contractOriginalUrl,
- }
- } else {
- contractInfo.value = null
- }
- } catch (error) {
- console.error('获取房屋详情失败:', error)
- ElMessage.error('获取房屋详情失败')
- } finally {
- loading.value = false
- }
- }
- const calculateEndDate = computed(() => {
- if (!rentalForm.rentalInfo.rentalTimeStart || !rentalForm.rentalInfo.rentalTime) {
- return ''
- }
- const startDate = new Date(rentalForm.rentalInfo.rentalTimeStart)
- if (isNaN(startDate.getTime())) {
- return ''
- }
- // 创建结束日期副本
- const endDate = new Date(startDate)
- // 添加月数
- endDate.setMonth(endDate.getMonth() + parseInt(rentalForm.rentalInfo.rentalTime))
- // 减去一天,得到租期结束日期
- endDate.setDate(endDate.getDate() - 1)
- // 格式化为 YYYY-MM-DD
- const year = endDate.getFullYear()
- const month = String(endDate.getMonth() + 1).padStart(2, '0')
- const day = String(endDate.getDate()).padStart(2, '0')
- return `${year}-${month}-${day}`
- })
- watch(
- () => rentalForm.rentalInfo.rentalTimeStart,
- (newVal) => {
- if (newVal) {
- rentalForm.contractDataA.tenantTimeStart = newVal
- }
- },
- { immediate: true },
- )
- watch(
- () => rentalForm.rentalInfo.rentalTime,
- (newVal) => {
- if (newVal) {
- rentalForm.contractDataA.tenantTime = newVal
- // 同时更新结束时间
- updateContractEndDate()
- }
- },
- { immediate: true },
- )
- watch(
- () => rentalForm.rentalInfo.rentalRect,
- (newVal) => {
- if (newVal) {
- rentalForm.contractDataA.tenantRent = newVal
- }
- },
- { immediate: true },
- )
- // 添加一个方法来更新合同结束日期
- const updateContractEndDate = () => {
- if (rentalForm.contractDataA.tenantTimeStart && rentalForm.contractDataA.tenantTime) {
- const startDate = new Date(rentalForm.contractDataA.tenantTimeStart)
- if (!isNaN(startDate.getTime())) {
- const endDate = new Date(startDate)
- endDate.setMonth(
- endDate.getMonth() + parseInt(rentalForm.contractDataA.tenantTime.toString()),
- )
- endDate.setDate(endDate.getDate() - 1)
- rentalForm.contractDataA.tenantTimeEnd = formatDate(endDate)
- }
- }
- }
- // 添加日期格式化函数
- const formatDate = (date: Date): string => {
- const year = date.getFullYear()
- const month = String(date.getMonth() + 1).padStart(2, '0')
- const day = String(date.getDate()).padStart(2, '0')
- return `${year}-${month}-${day}`
- }
- // 监听合同开始时间和租期的变化,自动更新结束时间
- watch(
- [() => rentalForm.contractDataA.tenantTimeStart, () => rentalForm.contractDataA.tenantTime],
- () => {
- updateContractEndDate()
- },
- )
- onMounted(() => {
- getData()
- })
- </script>
- <template>
- <el-container class="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
- <el-main class="h-full" v-loading="loading">
- <!-- <div class="py-0 has-footer">-->
- <el-button type="primary" @click="router.back">
- <el-icon class="mr-1"><ArrowLeft /></el-icon>
- 返回
- </el-button>
- <!-- </div>-->
- <div
- class="bg-gradient-to-r from-blue-600 to-purple-700 text-white py-4 px-8 my-4 rounded-2xl"
- >
- <div class="w-full">
- <div class="flex items-center justify-between">
- <div>
- <h1 class="text-3xl font-extrabold mb-2 my-0">{{ propertyInfo.buildingNumber }}</h1>
- <p class="text-base opacity-90">
- <el-icon class="mr-2 text-blue-500"><MapPin /></el-icon>
- <span>{{ propertyInfo.address }}</span>
- </p>
- </div>
- <div class="text-right flex items-center gap-6">
- <div class="relative">
- <!-- <button-->
- <!-- @click="openARViewing"-->
- <!-- class="ar-viewing-btn group relative overflow-hidden bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 text-white px-6 py-3 rounded-2xl font-semibold text-sm shadow-2xl transform transition-all duration-300 hover:scale-105 hover:shadow-pink-500/25 active:scale-95"-->
- <!-- >-->
- <!-- <div-->
- <!-- class="absolute inset-0 bg-gradient-to-r from-pink-600 via-purple-600 to-indigo-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"-->
- <!-- ></div>-->
- <!-- <div class="relative flex items-center gap-2">-->
- <!-- <div class="w-5 h-5 relative">-->
- <!-- <div-->
- <!-- class="absolute inset-0 bg-white rounded-full opacity-20 animate-ping"-->
- <!-- ></div>-->
- <!-- <el-icon class="relative z-10"><Camera /></el-icon>-->
- <!-- </div>-->
- <!-- <span class="relative z-10">AR看房</span>-->
- <!-- </div>-->
- <!-- <div-->
- <!-- class="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -skew-x-12 -translate-x-full group-hover:translate-x-full transition-transform duration-1000"-->
- <!-- ></div>-->
- <!-- </button>-->
- <div
- class="absolute -inset-1 bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 rounded-2xl blur opacity-30 group-hover:opacity-50 transition-opacity duration-300 -z-10"
- ></div>
- </div>
- <div>
- <el-tag
- :type="propertyInfo.status === '未租' ? 'success' : 'warning'"
- size="large"
- class="mb-2"
- >
- {{ propertyInfo.status }}
- </el-tag>
- <div class="text-xl font-bold">{{ propertyInfo.priceRange }} 元/月</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="py-0">
- <div class="w-full">
- <el-card
- v-if="propertyInfo.status === '已租' && tenantInfo"
- class="mb-6 shadow-lg rounded-2xl border-0"
- >
- <template #header>
- <div class="flex items-center">
- <el-icon class="mr-2 text-blue-500"><User /></el-icon>
- <span class="text-lg font-semibold">租户信息</span>
- </div>
- </template>
- <el-row :gutter="24">
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">租户姓名</label>
- <div class="text-lg font-semibold text-gray-800">{{ tenantInfo.tenantName }}</div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">联系电话</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ tenantInfo.tenantNumber }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">身份证号</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ tenantInfo.tenantIdCard }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">入住时间</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ tenantInfo.tenantInDate }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">租期</label>
- <div class="text-lg font-semibold text-gray-800">{{ tenantInfo.tenantTime }}</div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">月租金</label>
- <div class="text-lg font-semibold text-blue-600">
- {{ tenantInfo.tenantRent }} 元
- </div>
- </div>
- </el-col>
- </el-row>
- </el-card>
- <el-card class="mb-6 shadow-lg rounded-2xl border-0">
- <template #header>
- <div class="flex items-center">
- <el-icon class="mr-2 text-green-500"><Home /></el-icon>
- <span class="text-lg font-semibold">房屋基本信息</span>
- </div>
- </template>
- <el-row :gutter="24">
- <el-col :xs="24" :sm="12" :md="6">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">建筑面积</label>
- <div class="text-lg font-semibold text-gray-800">{{ propertyInfo.area }} ㎡</div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="6" v-if="propertyInfo.floor">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">所在楼层</label>
- <div class="text-lg font-semibold text-gray-800">{{ propertyInfo.floor }}</div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="6">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">介绍</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ propertyInfo.facilities }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="6" v-if="basicInfo.houseType">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">房屋类型</label>
- <div class="text-lg font-semibold text-gray-800">{{ basicInfo.houseType }}</div>
- </div>
- </el-col>
- </el-row>
- </el-card>
- <el-card class="mb-6 shadow-lg rounded-2xl border-0">
- <template #header>
- <div class="flex items-center justify-between">
- <div class="flex items-center">
- <el-icon class="mr-2 text-purple-500"><Cpu /></el-icon>
- <span class="text-lg font-semibold">房屋设备资产</span>
- </div>
- <div class="flex items-center gap-4">
- <el-select
- v-model="assetFilter.category"
- placeholder="设备类型"
- size="small"
- style="width: 120px"
- @change="filterAssets"
- >
- <el-option label="全部" value=""></el-option>
- <el-option
- v-for="type in deviceTypes"
- :key="type"
- :label="type"
- :value="type"
- ></el-option>
- </el-select>
- </div>
- </div>
- </template>
- <el-row :gutter="16">
- <el-col
- :xs="24"
- :sm="12"
- :md="8"
- :lg="6"
- v-for="(asset, index) in filteredAssets"
- :key="index"
- class="mb-4"
- >
- <div
- class="border border-gray-200 rounded-lg px-4 py-2 hover:shadow-md transition-shadow bg-white"
- >
- <div class="mb-3">
- <span class="font-semibold text-gray-800 text-lg">{{ asset.deviceName }}</span>
- <p class="text-sm text-gray-500">{{ asset.deviceType }}</p>
- </div>
- <div class="text-sm text-gray-600 space-y-1">
- <p><strong>品牌:</strong>{{ asset.deviceBrand }}</p>
- <p><strong>型号:</strong>{{ asset.deviceNumber }}</p>
- <p>
- <strong>价值:</strong>
- <span class="text-green-600 font-semibold">{{ asset.devicePrice }} 元</span>
- </p>
- </div>
- </div>
- </el-col>
- </el-row>
- <div v-if="filteredAssets.length === 0" class="text-center py-8 text-gray-500">
- 暂无符合条件的设备资产
- </div>
- </el-card>
- <el-card
- v-if="propertyInfo.status === '已租' && contractInfo"
- class="mb-6 shadow-lg rounded-2xl border-0"
- >
- <template #header>
- <div class="flex items-center justify-between">
- <div class="flex items-center">
- <el-icon class="mr-2 text-purple-500"><FileText /></el-icon>
- <span class="text-lg font-semibold">合同信息</span>
- </div>
- <!-- 新增:预览合同按钮 -->
- <el-button
- v-if="contractInfo.contractOriginalUrl"
- type="primary"
- size="small"
- @click="previewDocx(contractInfo.contractOriginalUrl)"
- class="flex items-center gap-1"
- >
- <el-icon><Eye /></el-icon>
- 预览合同
- </el-button>
- </div>
- </template>
- <el-row :gutter="24">
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">合同编号</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ contractInfo.contractNumber }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">签约日期</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ contractInfo.contractDate }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">合同期限</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ contractInfo.contractTime }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">到期日期</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ contractInfo.contractExpirationDate }}
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">押金</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ contractInfo.contractDeposit }} 元
- </div>
- </div>
- </el-col>
- <el-col :xs="24" :sm="12" :md="8">
- <div class="mb-4">
- <label class="block text-sm font-medium text-gray-700 mb-1">合同状态</label>
- <div class="text-lg font-semibold text-gray-800">
- {{ contractInfo.contractStatus }}
- </div>
- </div>
- </el-col>
- </el-row>
- </el-card>
- <el-card
- v-if="propertyInfo.status === '已租' && tenantInfo"
- class="mb-6 shadow-lg rounded-2xl border-0"
- >
- <template #header>
- <div class="flex items-center">
- <el-icon class="mr-2 text-blue-500"><BookText /></el-icon>
- <span class="text-lg font-semibold">收据信息</span>
- </div>
- </template>
- <el-table :data="receiptData" v-loading="loading" stripe class="w-full">
- <el-table-column type="index" label="序号" min-width="80" />
- <el-table-column prop="startDate" label="开始时间" min-width="80" />
- <el-table-column prop="endDate" label="结束时间" min-width="80" />
- <el-table-column prop="receiptReason" label="收款事由" />
- </el-table>
- </el-card>
- <div class="flex justify-center gap-4">
- <el-button
- v-if="propertyInfo.status === '空闲'"
- type="primary"
- size="large"
- @click="showRentalDialog = true"
- class="px-8 py-3"
- >
- <el-icon class="mr-2"><Plus /></el-icon>
- 出租房屋
- </el-button>
- <el-button
- v-if="propertyInfo.status === '已租'"
- type="danger"
- size="large"
- @click="showTerminateDialog = true"
- class="px-8 py-3"
- >
- <el-icon class="mr-2"><X /></el-icon>
- 退租房屋
- </el-button>
- </div>
- </div>
- </div>
- </el-main>
- <!-- 新增:DOCX预览对话框 -->
- <el-dialog
- v-model="showDocxPreviewDialog"
- title="合同预览"
- width="70%"
- :before-close="closeDocxPreview"
- class="docx-preview-dialog"
- >
- <div
- v-loading="docxPreviewLoading"
- element-loading-text="正在加载合同文件..."
- class="docx-preview-wrapper"
- >
- <div ref="docxPreviewContainer" class="docx-container" v-show="!docxPreviewLoading"></div>
- </div>
- <template #footer>
- <div class="flex justify-end">
- <el-button @click="closeDocxPreview">关闭</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog
- v-model="showRentalDialog"
- title="房屋出租"
- width="800px"
- :before-close="handleCloseRentalDialog"
- >
- <el-form :model="rentalForm" :rules="rentalRules" ref="rentalFormRef" label-width="120px">
- <el-steps :active="currentStep" finish-status="success" class="mb-8">
- <el-step title="租户信息" />
- <el-step title="合同条款" />
- <el-step title="确认提交" />
- </el-steps>
- <div v-show="currentStep === 0">
- <el-form-item label="租户姓名" prop="rentalInfo.rentalName">
- <el-input v-model="rentalForm.rentalInfo.rentalName" placeholder="请输入租户姓名" />
- </el-form-item>
- <el-form-item label="联系电话" prop="rentalInfo.rentalPhone">
- <el-input v-model="rentalForm.rentalInfo.rentalPhone" placeholder="请输入联系电话" />
- </el-form-item>
- <el-form-item label="身份证号" prop="rentalInfo.rentalIdCard">
- <el-input v-model="rentalForm.rentalInfo.rentalIdCard" placeholder="请输入身份证号" />
- </el-form-item>
- <el-form-item label="租期开始时间" prop="rentalInfo.rentalTimeStart">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.rentalInfo.rentalTimeStart"
- placeholder="请输入租期开始时间"
- />
- </el-form-item>
- <el-form-item label="租期(月)" prop="rentalInfo.rentalTime">
- <el-input-number
- :max="500"
- :min="1"
- v-model="rentalForm.rentalInfo.rentalTime"
- placeholder="请输入租期"
- />
- </el-form-item>
- <!-- 展示一个不可编辑的根据上方计算出的租期结束时间-->
- <el-form-item label="租期结束时间" v-if="rentalForm.rentalInfo.rentalTimeStart">
- <el-input
- :value="calculateEndDate"
- placeholder="根据开始时间和租期自动计算"
- readonly
- disabled
- />
- </el-form-item>
- <el-form-item label="租金" prop="rentalInfo.rentalRect">
- <el-input-number
- :min="0"
- :max="1000000"
- v-model="rentalForm.rentalInfo.rentalRect"
- placeholder="请输入租金"
- />
- </el-form-item>
- </div>
- <div v-show="currentStep === 1">
- <div v-if="propertyInfo.assetType === '公租房'">
- <el-form-item label="租方" prop="contractDataA.tenantName">
- <el-input v-model="rentalForm.contractDataA.tenantName" placeholder="请输入租方" />
- </el-form-item>
- <el-form-item label="房东" prop="contractDataA.landlordName">
- <el-input v-model="rentalForm.contractDataA.landlordName" placeholder="请输入房东" />
- </el-form-item>
- <el-form-item label="租期开始时间" prop="contractDataA.tenantTimeStart">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.contractDataA.tenantTimeStart"
- placeholder="请输入租期开始时间"
- :disabled="currentStep > 0"
- />
- </el-form-item>
- <el-form-item label="租期(月)" prop="contractDataA.tenantTime">
- <el-input-number
- :max="500"
- :min="1"
- v-model="rentalForm.contractDataA.tenantTime"
- placeholder="请输入租期"
- :disabled="currentStep > 0"
- />
- </el-form-item>
- <el-form-item label="租期结束时间" prop="contractDataA.tenantTimeEnd">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- disabled
- v-model="rentalForm.contractDataA.tenantTimeEnd"
- placeholder="请输入租期结束时间"
- />
- </el-form-item>
- <el-form-item label="每套租金" prop="contractDataA.tenantRent">
- <el-input-number
- :min="0"
- :max="1000000"
- v-model="rentalForm.contractDataA.tenantRent"
- placeholder="请输入每套租金"
- :disabled="currentStep > 0"
- />
- </el-form-item>
- <el-form-item label="每套物业费" prop="contractDataA.tenantDeposit">
- <el-input
- v-model="rentalForm.contractDataA.tenantDeposit"
- placeholder="请输入每套物业费"
- />
- </el-form-item>
- <el-form-item label="押金" prop="contractDataA.tenantDepositAmount">
- <el-input-number
- v-model="rentalForm.contractDataA.tenantDepositAmount"
- placeholder="请输入押金"
- />
- </el-form-item>
- </div>
- <div v-if="propertyInfo.assetType === '厂房'">
- <el-form-item label="用途" prop="contractDataB.purpose">
- <el-input v-model="rentalForm.contractDataB.purpose" placeholder="请输入用途" />
- </el-form-item>
- <el-form-item label="房东" prop="contractDataB.landlordName">
- <el-input v-model="rentalForm.contractDataB.landlordName" placeholder="请输入房东" />
- </el-form-item>
- <el-form-item label="法人统一社会信用代码" prop="contractDataB.landlordUniCode">
- <el-input
- v-model="rentalForm.contractDataB.landlordUniCode"
- placeholder="请输入法人统一社会信用代码"
- />
- </el-form-item>
- <el-form-item label="法定代表人" prop="contractDataB.landlordLegalRepresentative">
- <el-input
- v-model="rentalForm.contractDataB.landlordLegalRepresentative"
- placeholder="请输入法定代表人"
- />
- </el-form-item>
- <el-form-item label="房东职务" prop="contractDataB.landlordDuty">
- <el-input
- v-model="rentalForm.contractDataB.landlordDuty"
- placeholder="请输入房东职务"
- />
- </el-form-item>
- <el-form-item label="租方" prop="contractDataB.tenantName">
- <el-input v-model="rentalForm.contractDataB.tenantName" placeholder="请输入租方" />
- </el-form-item>
- <el-form-item label="租方统一社会信用代码" prop="contractDataB.tenantUniCode">
- <el-input
- v-model="rentalForm.contractDataB.tenantUniCode"
- placeholder="请输入租方统一社会信用代码"
- />
- </el-form-item>
- <el-form-item label="法定代表人" prop="contractDataB.tenantLegalRepresentative">
- <el-input
- v-model="rentalForm.contractDataB.tenantLegalRepresentative"
- placeholder="请输入法定代表人"
- />
- </el-form-item>
- <el-form-item label="租方职务" prop="contractDataB.tenantDuty">
- <el-input
- v-model="rentalForm.contractDataB.tenantDuty"
- placeholder="请输入租方职务"
- />
- </el-form-item>
- <el-form-item label="谁" prop="contractDataB.who">
- <el-input v-model="rentalForm.contractDataB.who" placeholder="请输入谁" />
- </el-form-item>
- <el-form-item label="何时" prop="contractDataB.whatTime">
- <el-input v-model="rentalForm.contractDataB.whatTime" placeholder="请输入何时" />
- </el-form-item>
- <el-form-item label="标题" prop="contractDataB.title">
- <el-input v-model="rentalForm.contractDataB.title" placeholder="请输入标题" />
- </el-form-item>
- <el-form-item label="配套用房面积 (㎡) " prop="contractDataB.supportingRoomArea">
- <el-input
- v-model="rentalForm.contractDataB.supportingRoomArea"
- placeholder="请输入配套用房面积(㎡)"
- />
- </el-form-item>
- <el-form-item label="办公室面积(㎡)" prop="contractDataB.officeArea">
- <el-input
- v-model="rentalForm.contractDataB.officeArea"
- placeholder="请输入办公室面积(㎡)"
- />
- </el-form-item>
- <el-form-item label="食堂面积(㎡)" prop="contractDataB.canteenArea">
- <el-input
- v-model="rentalForm.contractDataB.canteenArea"
- placeholder="请输入食堂面积(㎡)"
- />
- </el-form-item>
- <el-form-item label="总面积(㎡)" prop="contractDataB.totalLeasedArea">
- <el-input
- v-model="rentalForm.contractDataB.totalLeasedArea"
- placeholder="请输入总面积(㎡)"
- />
- </el-form-item>
- <el-form-item label="宿舍楼总间数" prop="contractDataB.dormTotalRooms">
- <el-input
- v-model="rentalForm.contractDataB.dormTotalRooms"
- placeholder="请输入宿舍楼总间数"
- />
- </el-form-item>
- <el-form-item label="宿舍小间数" prop="contractDataB.dormSmallRooms">
- <el-input
- v-model="rentalForm.contractDataB.dormSmallRooms"
- placeholder="请输入宿舍小间数"
- />
- </el-form-item>
- <el-form-item label="宿舍大间数" prop="contractDataB.dormLargeRooms">
- <el-input
- v-model="rentalForm.contractDataB.dormLargeRooms"
- placeholder="请输入宿舍大间数"
- />
- </el-form-item>
- <el-form-item label="标的交付日期" prop="contractDataB.deliveryDate">
- <el-input
- v-model="rentalForm.contractDataB.deliveryDate"
- placeholder="请输入标的交付日期"
- />
- </el-form-item>
- <el-form-item label="生产项目名称" prop="contractDataB.productionProject">
- <el-input
- v-model="rentalForm.contractDataB.productionProject"
- placeholder="请输入生产项目名称"
- />
- </el-form-item>
- <el-form-item label="租赁期限(年)" prop="contractDataB.leaseTermYears">
- <el-input
- v-model="rentalForm.contractDataB.leaseTermYears"
- placeholder="请输入租赁期限(年)"
- />
- </el-form-item>
- <el-form-item label="租赁起始日" prop="contractDataB.leaseStartDate">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.contractDataB.leaseStartDate"
- placeholder="请输入租赁起始日"
- />
- </el-form-item>
- <el-form-item label="租赁终止日" prop="contractDataB.leaseEndDate">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.contractDataB.leaseEndDate"
- placeholder="请输入租赁终止日"
- />
- </el-form-item>
- <el-form-item label="续租提前通知月数" prop="contractDataB.renewNoticeMonths">
- <el-input
- v-model="rentalForm.contractDataB.renewNoticeMonths"
- placeholder="请输入续租提前通知月数"
- />
- </el-form-item>
- <el-form-item label="标准化厂房某楼层" prop="contractDataB.factorySpecificFloor1">
- <el-input
- v-model="rentalForm.contractDataB.factorySpecificFloor1"
- placeholder="请输入标准化厂房某楼层"
- />
- </el-form-item>
- <el-form-item label="该楼层租金(元/㎡/月)" prop="contractDataB.rentPerSqmFloor1">
- <el-input
- v-model="rentalForm.contractDataB.rentPerSqmFloor1"
- placeholder="请输入该楼层租金(元/㎡/月)"
- />
- </el-form-item>
- <el-form-item label="标准化厂房另一楼层" prop="contractDataB.factorySpecificFloor2">
- <el-input
- v-model="rentalForm.contractDataB.factorySpecificFloor2"
- placeholder="请输入标准化厂房另一楼层"
- />
- </el-form-item>
- <el-form-item label="该楼层租金(元/㎡/月)" prop="contractDataB.rentPerSqmFloor2">
- <el-input
- v-model="rentalForm.contractDataB.rentPerSqmFloor2"
- placeholder="请输入该楼层租金(元/㎡/月)"
- />
- </el-form-item>
- <el-form-item label="厂房年租金(元)" prop="contractDataB.factoryAnnualRent">
- <el-input-number
- v-model="rentalForm.contractDataB.factoryAnnualRent"
- placeholder="请输入厂房年租金(元)"
- />
- </el-form-item>
- <el-form-item
- label="配套用房租金(元/㎡/月)"
- prop="contractDataB.supportingRoomRentPerSqm"
- >
- <el-input
- v-model="rentalForm.contractDataB.supportingRoomRentPerSqm"
- placeholder="请输入配套用房租金(元/㎡/月)"
- />
- </el-form-item>
- <el-form-item
- label="配套用房年租金(元)"
- prop="contractDataB.supportingRoomAnnualRent"
- >
- <el-input-number
- v-model="rentalForm.contractDataB.supportingRoomAnnualRent"
- placeholder="请输入配套用房年租金(元)"
- />
- </el-form-item>
- <el-form-item label="宿舍楼普通单间月租金(元)" prop="contractDataB.dormSmallRoomRent">
- <el-input
- v-model="rentalForm.contractDataB.dormSmallRoomRent"
- placeholder="请输入宿舍楼普通单间月租金(元)"
- />
- </el-form-item>
- <el-form-item label="宿舍楼大单间月租金(元)" prop="contractDataB.dormLargeRoomRent">
- <el-input
- v-model="rentalForm.contractDataB.dormLargeRoomRent"
- placeholder="请输入宿舍楼大单间月租金(元)"
- />
- </el-form-item>
- <el-form-item label="宿舍楼年租金(元)" prop="contractDataB.dormAnnualRent">
- <el-input-number
- v-model="rentalForm.contractDataB.dormAnnualRent"
- placeholder="请输入宿舍楼年租金(元)"
- />
- </el-form-item>
- <el-form-item label="总租金(元)" prop="contractDataB.totalAnnualRent">
- <el-input-number
- v-model="rentalForm.contractDataB.totalAnnualRent"
- placeholder="请输入总租金(元)"
- />
- </el-form-item>
- <el-form-item
- label="标准化厂房和配套用房物业费(元/㎡/月)"
- prop="contractDataB.propertyFeePerSqm"
- >
- <el-input
- v-model="rentalForm.contractDataB.propertyFeePerSqm"
- placeholder="请输入标准化厂房和配套用房物业费(元/㎡/月)"
- />
- </el-form-item>
- <el-form-item
- label="标准化厂房和配套用房年物业费(元)"
- prop="contractDataB.factorySupportingPropertyFee"
- >
- <el-input-number
- v-model="rentalForm.contractDataB.factorySupportingPropertyFee"
- placeholder="请输入标准化厂房和配套用房年物业费(元)"
- />
- </el-form-item>
- <el-form-item
- label="宿舍楼普通单间月物业费(元)"
- prop="contractDataB.dormSmallRoomPropertyFee"
- >
- <el-input
- v-model="rentalForm.contractDataB.dormSmallRoomPropertyFee"
- placeholder="请输入宿舍楼普通单间月物业费(元)"
- />
- </el-form-item>
- <el-form-item
- label="宿舍楼大单间月物业费(元)"
- prop="contractDataB.dormLargeRoomPropertyFee"
- >
- <el-input
- v-model="rentalForm.contractDataB.dormLargeRoomPropertyFee"
- placeholder="请输入宿舍楼大单间月物业费(元)"
- />
- </el-form-item>
- <el-form-item label="宿舍楼年物业费(元)" prop="contractDataB.dormAnnualPropertyFee">
- <el-input-number
- v-model="rentalForm.contractDataB.dormAnnualPropertyFee"
- placeholder="请输入宿舍楼年物业费(元)"
- />
- </el-form-item>
- <el-form-item label="年物业管理费(元)" prop="contractDataB.totalAnnualPropertyFee">
- <el-input-number
- v-model="rentalForm.contractDataB.totalAnnualPropertyFee"
- placeholder="请输入年物业管理费(元)"
- />
- </el-form-item>
- <el-form-item
- label="年租金和物业费用总计(元)"
- prop="contractDataB.annualTotalRentAndPropertyFee"
- >
- <el-input-number
- v-model="rentalForm.contractDataB.annualTotalRentAndPropertyFee"
- placeholder="请输入年租金和物业费用总计(元)"
- />
- </el-form-item>
- <el-form-item label="租赁押金金额(元)" prop="contractDataB.depositAmount">
- <el-input-number
- v-model="rentalForm.contractDataB.depositAmount"
- placeholder="请输入租赁押金金额(元)"
- />
- </el-form-item>
- </div>
- <div v-if="propertyInfo.assetType === '创新创业基地'">
- <el-form-item label="出租方(甲方)名称" prop="contractDataC.lessorName">
- <el-input
- v-model="rentalForm.contractDataC.lessorName"
- placeholder="请输入出租方(甲方)名称"
- />
- </el-form-item>
- <el-form-item label="出租方法定代表人" prop="contractDataC.lessorLegalRep">
- <el-input
- v-model="rentalForm.contractDataC.lessorLegalRep"
- placeholder="请输入出租方法定代表人"
- />
- </el-form-item>
- <el-form-item label="出租方统一社会信用代码" prop="contractDataC.lessorUniCode">
- <el-input
- v-model="rentalForm.contractDataC.lessorUniCode"
- placeholder="请输入出租方统一社会信用代码"
- />
- </el-form-item>
- <el-form-item label="承租方(乙方)名称" prop="contractDataC.lesseeName">
- <el-input
- v-model="rentalForm.contractDataC.lesseeName"
- placeholder="请输入承租方(乙方)名称"
- />
- </el-form-item>
- <el-form-item label="承租方法定代表人" prop="contractDataC.lesseeLegalRep">
- <el-input
- v-model="rentalForm.contractDataC.lesseeLegalRep"
- placeholder="请输入承租方法定代表人"
- />
- </el-form-item>
- <el-form-item label="承租方统一社会信用代码/身份证号" prop="contractDataC.lesseeIdCode">
- <el-input
- v-model="rentalForm.contractDataC.lesseeIdCode"
- placeholder="请输入承租方统一社会信用代码/身份证号"
- />
- </el-form-item>
- <el-form-item label="标的物坐落" prop="contractDataC.propertyLocation">
- <el-input
- v-model="rentalForm.contractDataC.propertyLocation"
- placeholder="请输入标的物坐落"
- />
- </el-form-item>
- <el-form-item label="计租面积(平方米)" prop="contractDataC.rentableArea">
- <el-input
- v-model="rentalForm.contractDataC.rentableArea"
- placeholder="请输入计租面积(平方米)"
- />
- </el-form-item>
- <el-form-item label="使用面积(平方米)" prop="contractDataC.usableArea">
- <el-input
- v-model="rentalForm.contractDataC.usableArea"
- placeholder="请输入使用面积(平方米)"
- />
- </el-form-item>
- <el-form-item label="公摊面积(平方米)" prop="contractDataC.sharedArea">
- <el-input
- v-model="rentalForm.contractDataC.sharedArea"
- placeholder="请输入公摊面积(平方米)"
- />
- </el-form-item>
- <el-form-item label="标的物使用性质" prop="contractDataC.propertyUseNature">
- <el-input
- v-model="rentalForm.contractDataC.propertyUseNature"
- placeholder="请输入标的物使用性质"
- />
- </el-form-item>
- <el-form-item label="店铺名称" prop="contractDataC.storeName">
- <el-input v-model="rentalForm.contractDataC.storeName" placeholder="请输入店铺名称" />
- </el-form-item>
- <el-form-item label="商品/服务品牌" prop="contractDataC.brand">
- <el-input
- v-model="rentalForm.contractDataC.brand"
- placeholder="请输入商品/服务品牌"
- />
- </el-form-item>
- <el-form-item label="经营范围" prop="contractDataC.businessScope">
- <el-input
- v-model="rentalForm.contractDataC.businessScope"
- placeholder="请输入经营范围"
- />
- </el-form-item>
- <el-form-item label="租赁期限(个月)" prop="contractDataC.leaseTermMonths">
- <el-input
- v-model="rentalForm.contractDataC.leaseTermMonths"
- placeholder="请输入租赁期限(个月)"
- />
- </el-form-item>
- <el-form-item label="租赁起始日" prop="contractDataC.leaseStartDate">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.contractDataC.leaseStartDate"
- placeholder="请输入租赁起始日"
- />
- </el-form-item>
- <el-form-item label="租赁终止日" prop="contractDataC.leaseEndDate">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.contractDataC.leaseEndDate"
- placeholder="请输入租赁终止日"
- />
- </el-form-item>
- <el-form-item label="装修期起始日" prop="contractDataC.renovationStartDate">
- <el-input
- v-model="rentalForm.contractDataC.renovationStartDate"
- placeholder="请输入装修期起始日"
- />
- </el-form-item>
- <el-form-item label="装修期终止日" prop="contractDataC.renovationEndDate">
- <el-input
- v-model="rentalForm.contractDataC.renovationEndDate"
- placeholder="请输入装修期终止日"
- />
- </el-form-item>
- <el-form-item label="正式起租时间" prop="contractDataC.officialLeaseStartDate">
- <el-input
- v-model="rentalForm.contractDataC.officialLeaseStartDate"
- placeholder="请输入正式起租时间"
- />
- </el-form-item>
- <el-form-item label="年租金(小写)" prop="contractDataC.annualRentLower">
- <el-input-number
- v-model="rentalForm.contractDataC.annualRentLower"
- placeholder="请输入年租金(小写)"
- />
- </el-form-item>
- <el-form-item label="年物业服务费(小写)" prop="contractDataC.annualPropertyFeeLower">
- <el-input-number
- v-model="rentalForm.contractDataC.annualPropertyFeeLower"
- placeholder="请输入年物业服务费(小写)"
- />
- </el-form-item>
- <el-form-item label="租赁保证金金额" prop="contractDataC.depositAmount">
- <el-input-number
- v-model="rentalForm.contractDataC.depositAmount"
- placeholder="请输入租赁保证金金额"
- />
- </el-form-item>
- </div>
- </div>
- <div v-show="currentStep === 2">
- <div class="bg-gray-50 p-6 rounded-lg">
- <h3 class="text-lg font-semibold mb-4">请确认以下信息:</h3>
- <!-- 第一步:租户信息 -->
- <div class="mb-6">
- <h4 class="text-md font-semibold mb-3 text-blue-600">租户信息</h4>
- <el-row :gutter="24">
- <el-col :span="12">
- <p><strong>租户姓名:</strong>{{ rentalForm.rentalInfo.rentalName }}</p>
- <p><strong>联系电话:</strong>{{ rentalForm.rentalInfo.rentalPhone }}</p>
- <p><strong>身份证号:</strong>{{ rentalForm.rentalInfo.rentalIdCard }}</p>
- </el-col>
- <el-col :span="12">
- <p><strong>租金:</strong>{{ rentalForm.rentalInfo.rentalRect }} 元</p>
- <p><strong>租期:</strong>{{ rentalForm.rentalInfo.rentalTime }}</p>
- <p><strong>开始时间:</strong>{{ rentalForm.rentalInfo.rentalTimeStart }}</p>
- </el-col>
- </el-row>
- </div>
- <!-- 第二步:合同条款信息 -->
- <div class="mb-6">
- <h4 class="text-md font-semibold mb-3 text-green-600">合同条款信息</h4>
- <!-- 公租房合同信息 -->
- <div v-if="propertyInfo.assetType === '公租房'">
- <el-row :gutter="24">
- <el-col :span="12">
- <p><strong>租方:</strong>{{ rentalForm.contractDataA.tenantName }}</p>
- <p><strong>房东:</strong>{{ rentalForm.contractDataA.landlordName }}</p>
- <p>
- <strong>租期开始时间:</strong>{{ rentalForm.contractDataA.tenantTimeStart }}
- </p>
- <p><strong>租期:</strong>{{ rentalForm.contractDataA.tenantTime }}</p>
- </el-col>
- <el-col :span="12">
- <p>
- <strong>租期结束时间:</strong>{{ rentalForm.contractDataA.tenantTimeEnd }}
- </p>
- <p><strong>每套租金:</strong>{{ rentalForm.contractDataA.tenantRent }} 元</p>
- <p>
- <strong>每套物业费:</strong>{{ rentalForm.contractDataA.tenantDeposit }} 元
- </p>
- <p>
- <strong>押金:</strong>{{ rentalForm.contractDataA.tenantDepositAmount }} 元
- </p>
- </el-col>
- </el-row>
- </div>
- <!-- 厂房合同信息 -->
- <div v-if="propertyInfo.assetType === '厂房'">
- <el-row :gutter="24">
- <el-col :span="12">
- <p><strong>用途:</strong>{{ rentalForm.contractDataB.purpose }}</p>
- <p><strong>房东:</strong>{{ rentalForm.contractDataB.landlordName }}</p>
- <p>
- <strong>法人统一社会信用代码:</strong
- >{{ rentalForm.contractDataB.landlordUniCode }}
- </p>
- <p>
- <strong>法定代表人:</strong
- >{{ rentalForm.contractDataB.landlordLegalRepresentative }}
- </p>
- <p><strong>房东职务:</strong>{{ rentalForm.contractDataB.landlordDuty }}</p>
- <p><strong>租方:</strong>{{ rentalForm.contractDataB.tenantName }}</p>
- <p>
- <strong>租方统一社会信用代码:</strong
- >{{ rentalForm.contractDataB.tenantUniCode }}
- </p>
- <p>
- <strong>租方法定代表人:</strong
- >{{ rentalForm.contractDataB.tenantLegalRepresentative }}
- </p>
- <p><strong>租方职务:</strong>{{ rentalForm.contractDataB.tenantDuty }}</p>
- <p><strong>谁:</strong>{{ rentalForm.contractDataB.who }}</p>
- <p><strong>何时:</strong>{{ rentalForm.contractDataB.whatTime }}</p>
- <p><strong>标题:</strong>{{ rentalForm.contractDataB.title }}</p>
- <p>
- <strong>配套用房面积:</strong
- >{{ rentalForm.contractDataB.supportingRoomArea }} ㎡
- </p>
- <p><strong>办公室面积:</strong>{{ rentalForm.contractDataB.officeArea }} ㎡</p>
- <p><strong>食堂面积:</strong>{{ rentalForm.contractDataB.canteenArea }} ㎡</p>
- <p>
- <strong>总面积:</strong>{{ rentalForm.contractDataB.totalLeasedArea }} ㎡
- </p>
- <p>
- <strong>宿舍楼总间数:</strong>{{ rentalForm.contractDataB.dormTotalRooms }}
- </p>
- <p>
- <strong>宿舍小间数:</strong>{{ rentalForm.contractDataB.dormSmallRooms }}
- </p>
- <p>
- <strong>宿舍大间数:</strong>{{ rentalForm.contractDataB.dormLargeRooms }}
- </p>
- <p>
- <strong>标的交付日期:</strong>{{ rentalForm.contractDataB.deliveryDate }}
- </p>
- <p>
- <strong>生产项目名称:</strong
- >{{ rentalForm.contractDataB.productionProject }}
- </p>
- <p>
- <strong>租赁期限(年):</strong>{{ rentalForm.contractDataB.leaseTermYears }}
- </p>
- <p>
- <strong>租赁起始日:</strong>{{ rentalForm.contractDataB.leaseStartDate }}
- </p>
- <p><strong>租赁终止日:</strong>{{ rentalForm.contractDataB.leaseEndDate }}</p>
- </el-col>
- <el-col :span="12">
- <p>
- <strong>续租提前通知月数:</strong
- >{{ rentalForm.contractDataB.renewNoticeMonths }}
- </p>
- <p>
- <strong>标准化厂房某楼层:</strong
- >{{ rentalForm.contractDataB.factorySpecificFloor1 }}
- </p>
- <p>
- <strong>该楼层租金(元/㎡/月):</strong
- >{{ rentalForm.contractDataB.rentPerSqmFloor1 }}
- </p>
- <p>
- <strong>标准化厂房另一楼层:</strong
- >{{ rentalForm.contractDataB.factorySpecificFloor2 }}
- </p>
- <p>
- <strong>该楼层租金(元/㎡/月):</strong
- >{{ rentalForm.contractDataB.rentPerSqmFloor2 }}
- </p>
- <p>
- <strong>厂房年租金:</strong
- >{{ rentalForm.contractDataB.factoryAnnualRent }} 元
- </p>
- <p>
- <strong>配套用房租金(元/㎡/月):</strong
- >{{ rentalForm.contractDataB.supportingRoomRentPerSqm }}
- </p>
- <p>
- <strong>配套用房年租金:</strong
- >{{ rentalForm.contractDataB.supportingRoomAnnualRent }} 元
- </p>
- <p>
- <strong>宿舍楼普通单间月租金:</strong
- >{{ rentalForm.contractDataB.dormSmallRoomRent }} 元
- </p>
- <p>
- <strong>宿舍楼大单间月租金:</strong
- >{{ rentalForm.contractDataB.dormLargeRoomRent }} 元
- </p>
- <p>
- <strong>宿舍楼年租金:</strong
- >{{ rentalForm.contractDataB.dormAnnualRent }} 元
- </p>
- <p>
- <strong>总租金:</strong>{{ rentalForm.contractDataB.totalAnnualRent }} 元
- </p>
- <p>
- <strong>标准化厂房和配套用房物业费(元/㎡/月):</strong
- >{{ rentalForm.contractDataB.propertyFeePerSqm }}
- </p>
- <p>
- <strong>标准化厂房和配套用房年物业费:</strong
- >{{ rentalForm.contractDataB.factorySupportingPropertyFee }} 元
- </p>
- <p>
- <strong>宿舍楼普通单间月物业费:</strong
- >{{ rentalForm.contractDataB.dormSmallRoomPropertyFee }} 元
- </p>
- <p>
- <strong>宿舍楼大单间月物业费:</strong
- >{{ rentalForm.contractDataB.dormLargeRoomPropertyFee }} 元
- </p>
- <p>
- <strong>宿舍楼年物业费:</strong
- >{{ rentalForm.contractDataB.dormAnnualPropertyFee }} 元
- </p>
- <p>
- <strong>年物业管理费:</strong
- >{{ rentalForm.contractDataB.totalAnnualPropertyFee }} 元
- </p>
- <p>
- <strong>年租金和物业费用总计:</strong
- >{{ rentalForm.contractDataB.annualTotalRentAndPropertyFee }} 元
- </p>
- <p>
- <strong>租赁押金金额:</strong>{{ rentalForm.contractDataB.depositAmount }} 元
- </p>
- </el-col>
- </el-row>
- </div>
- <!-- 创新创业基地合同信息 -->
- <div v-if="propertyInfo.assetType === '创新创业基地'">
- <el-row :gutter="24">
- <el-col :span="12">
- <p>
- <strong>出租方(甲方)名称:</strong>{{ rentalForm.contractDataC.lessorName }}
- </p>
- <p>
- <strong>出租方法定代表人:</strong
- >{{ rentalForm.contractDataC.lessorLegalRep }}
- </p>
- <p>
- <strong>出租方统一社会信用代码:</strong
- >{{ rentalForm.contractDataC.lessorUniCode }}
- </p>
- <p>
- <strong>承租方(乙方)名称:</strong>{{ rentalForm.contractDataC.lesseeName }}
- </p>
- <p>
- <strong>承租方法定代表人:</strong
- >{{ rentalForm.contractDataC.lesseeLegalRep }}
- </p>
- <p>
- <strong>承租方统一社会信用代码/身份证号:</strong
- >{{ rentalForm.contractDataC.lesseeIdCode }}
- </p>
- <p>
- <strong>标的物坐落:</strong>{{ rentalForm.contractDataC.propertyLocation }}
- </p>
- <p>
- <strong>计租面积:</strong>{{ rentalForm.contractDataC.rentableArea }} 平方米
- </p>
- <p>
- <strong>使用面积:</strong>{{ rentalForm.contractDataC.usableArea }} 平方米
- </p>
- <p>
- <strong>公摊面积:</strong>{{ rentalForm.contractDataC.sharedArea }} 平方米
- </p>
- <p>
- <strong>标的物使用性质:</strong
- >{{ rentalForm.contractDataC.propertyUseNature }}
- </p>
- <p><strong>店铺名称:</strong>{{ rentalForm.contractDataC.storeName }}</p>
- </el-col>
- <el-col :span="12">
- <p><strong>商品/服务品牌:</strong>{{ rentalForm.contractDataC.brand }}</p>
- <p><strong>经营范围:</strong>{{ rentalForm.contractDataC.businessScope }}</p>
- <p>
- <strong>租赁期限:</strong>{{ rentalForm.contractDataC.leaseTermMonths }} 个月
- </p>
- <p>
- <strong>租赁起始日:</strong>{{ rentalForm.contractDataC.leaseStartDate }}
- </p>
- <p><strong>租赁终止日:</strong>{{ rentalForm.contractDataC.leaseEndDate }}</p>
- <p>
- <strong>装修期起始日:</strong
- >{{ rentalForm.contractDataC.renovationStartDate }}
- </p>
- <p>
- <strong>装修期终止日:</strong
- >{{ rentalForm.contractDataC.renovationEndDate }}
- </p>
- <p>
- <strong>正式起租时间:</strong
- >{{ rentalForm.contractDataC.officialLeaseStartDate }}
- </p>
- <p>
- <strong>年租金(小写):</strong
- >{{ rentalForm.contractDataC.annualRentLower }} 元
- </p>
- <p>
- <strong>年物业服务费(小写):</strong
- >{{ rentalForm.contractDataC.annualPropertyFeeLower }} 元
- </p>
- <p>
- <strong>租赁保证金金额:</strong
- >{{ rentalForm.contractDataC.depositAmount }} 元
- </p>
- </el-col>
- </el-row>
- </div>
- </div>
- </div>
- </div>
- </el-form>
- <template #footer>
- <div class="flex justify-between">
- <el-button v-if="currentStep > 0" @click="currentStep--">上一步</el-button>
- <div class="flex gap-2">
- <el-button @click="handleCloseRentalDialog">取消</el-button>
- <el-button v-if="currentStep < 2" type="primary" @click="nextStep">下一步</el-button>
- <el-button
- v-if="currentStep === 2"
- type="primary"
- @click="submitRental"
- :loading="submitting"
- >确认出租</el-button
- >
- </div>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="showTerminateDialog" title="退租确认" width="600px">
- <div class="mb-6" v-if="contractInfo">
- <h3 class="text-lg font-semibold mb-4">合同信息</h3>
- <div class="bg-gray-50 p-4 rounded-lg">
- <p><strong>合同编号:</strong>{{ contractInfo.contractNumber }}</p>
- <p><strong>租户姓名:</strong>{{ tenantInfo?.tenantName }}</p>
- <p><strong>租期:</strong>{{ contractInfo.contractTime }}</p>
- <p><strong>到期日期:</strong>{{ contractInfo.contractExpirationDate }}</p>
- <p><strong>押金:</strong>{{ contractInfo.contractDeposit }} 元</p>
- </div>
- </div>
- <template #footer>
- <div class="flex justify-end gap-2">
- <el-button @click="showTerminateDialog = false">取消</el-button>
- <el-button type="danger" @click="confirmTerminate" :loading="terminating">
- 确认退租
- </el-button>
- </div>
- </template>
- </el-dialog>
- </el-container>
- </template>
- <style scoped>
- .el-card {
- border: none;
- }
- .el-button {
- font-weight: 600;
- }
- .el-steps {
- margin-bottom: 2rem;
- }
- .ar-viewing-btn {
- position: relative;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- border: none;
- cursor: pointer;
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
- }
- .ar-viewing-btn:hover {
- transform: translateY(-2px) scale(1.05);
- box-shadow: 0 20px 40px rgba(102, 126, 234, 0.4);
- }
- .ar-viewing-btn:active {
- transform: translateY(0) scale(0.98);
- }
- .ar-viewing-btn::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: linear-gradient(135deg, #f093fb 0%, #f5576c 50%, #4facfe 100%);
- border-radius: inherit;
- opacity: 0;
- transition: opacity 0.3s ease;
- z-index: -1;
- }
- .ar-viewing-btn:hover::before {
- opacity: 1;
- }
- @keyframes gradient {
- 0% {
- background-position: 0% 50%;
- }
- 50% {
- background-position: 100% 50%;
- }
- 100% {
- background-position: 0% 50%;
- }
- }
- .bg-gradient-to-r {
- background-size: 200% 200%;
- animation: gradient 15s ease infinite;
- }
- @keyframes ping {
- 75%,
- 100% {
- transform: scale(2);
- opacity: 0;
- }
- }
- .animate-ping {
- animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
- }
- /* 新增:DOCX预览相关样式 */
- .docx-preview-dialog {
- --el-dialog-content-font-size: 14px;
- }
- .docx-preview-wrapper {
- min-height: 400px;
- max-height: 70vh;
- overflow-y: auto;
- border: 1px solid #e4e7ed;
- border-radius: 4px;
- background-color: #fff;
- }
- .docx-container {
- padding: 20px;
- font-family: 'Times New Roman', serif;
- line-height: 1.6;
- color: #333;
- }
- /* DOCX内容样式优化 */
- .docx-container :deep(.docx-wrapper) {
- max-width: 100%;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- padding: 40px;
- }
- .docx-container :deep(p) {
- margin: 0 0 12px 0;
- text-align: justify;
- }
- .docx-container :deep(table) {
- width: 100%;
- border-collapse: collapse;
- margin: 16px 0;
- }
- .docx-container :deep(table td),
- .docx-container :deep(table th) {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- .docx-container :deep(table th) {
- background-color: #f5f5f5;
- font-weight: bold;
- }
- .docx-container :deep(h1),
- .docx-container :deep(h2),
- .docx-container :deep(h3),
- .docx-container :deep(h4),
- .docx-container :deep(h5),
- .docx-container :deep(h6) {
- margin: 20px 0 12px 0;
- font-weight: bold;
- }
- .docx-container :deep(.page-break) {
- page-break-before: always;
- margin-top: 40px;
- padding-top: 40px;
- border-top: 1px dashed #ccc;
- }
- </style>
|