| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019 |
- <script setup lang="ts">
- import { computed, nextTick, onMounted, reactive, ref } 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 } 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 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 terminateForm = reactive({
- terminateDate: '',
- reason: '',
- depositHandling: '全额退还',
- deductAmount: 0,
- })
- 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 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 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
- 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
- }
- }
- 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>
- <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 v-model="rentalForm.rentalInfo.rentalTime" placeholder="请输入租期" />
- </el-form-item>
- <el-form-item label="租金" prop="rentalInfo.rentalRect">
- <el-input 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="请输入租期开始时间"
- />
- </el-form-item>
- <el-form-item label="租期" prop="contractDataA.tenantTime">
- <el-input v-model="rentalForm.contractDataA.tenantTime" placeholder="请输入租期" />
- </el-form-item>
- <el-form-item label="租期结束时间" prop="contractDataA.tenantTimeEnd">
- <el-date-picker
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- v-model="rentalForm.contractDataA.tenantTimeEnd"
- placeholder="请输入租期结束时间"
- />
- </el-form-item>
- <el-form-item label="每套租金" prop="contractDataA.tenantRent">
- <el-input
- v-model="rentalForm.contractDataA.tenantRent"
- placeholder="请输入每套租金"
- />
- </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
- 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
- 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
- v-model="rentalForm.contractDataB.dormAnnualRent"
- placeholder="请输入宿舍楼年租金(元)"
- />
- </el-form-item>
- <el-form-item label="总租金(元)" prop="contractDataB.totalAnnualRent">
- <el-input
- 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
- 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
- v-model="rentalForm.contractDataB.dormAnnualPropertyFee"
- placeholder="请输入宿舍楼年物业费(元)"
- />
- </el-form-item>
- <el-form-item label="年物业管理费(元)" prop="contractDataB.totalAnnualPropertyFee">
- <el-input
- v-model="rentalForm.contractDataB.totalAnnualPropertyFee"
- placeholder="请输入年物业管理费(元)"
- />
- </el-form-item>
- <el-form-item
- label="年租金和物业费用总计(元)"
- prop="contractDataB.annualTotalRentAndPropertyFee"
- >
- <el-input
- 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
- v-model="rentalForm.contractDataC.annualRentLower"
- placeholder="请输入年租金(小写)"
- />
- </el-form-item>
- <el-form-item label="年物业服务费(小写)" prop="contractDataC.annualPropertyFeeLower">
- <el-input
- 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>
- <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>
- </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>
|