| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486 |
- <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,
- Cpu,
- Eye,
- FileText,
- Home,
- MapPin,
- Plus,
- User,
- X,
- BookText,
- Download
- } 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: true, 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">
- <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>
|